ad_library { The template::head::* api manipulates the head section of the document that will be returned to the users client. Packages should use this api to add package specific javascripts, CSS, link tags and meta tags to the HTML document. @author Lee Denison (lee@xarg.co.uk) @creation-date 2007-05-18 } namespace eval template {} namespace eval template::head {} ad_proc -private template::reset_request_vars {} { Resets all global datastructures used to manage the head section of the returned document. This should be called at the beginning of any request handled by the templating system. } { array unset ::template::head::scripts array unset ::template::head::links array unset ::template::head::metas array unset ::template::body_handlers array unset ::template::body_scripts set ::template::headers [list] set ::template::footers [list] } ad_proc -public template::add_script { {-async:boolean} {-charset ""} {-crossorigin ""} {-defer:boolean} {-integrity ""} {-order "0"} {-script ""} {-section "head"} {-src ""} {-type "text/javascript"} } { @param async whether execution of the script should be executed asynchronously as soon as it is available @param charset the charset attribute of the script tag, ie. the character set of the script if it differs from the main document @param crossorigin Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used @param defer whether execution of the script should be defered until after the page has been loaded @param integrity provide hash values for W3C Subresource Integrity recommentation @param order specify inclusion order @param script the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src @param section section, where script is added ("head" or "body") @param src the src attribute of the script tag, ie. the source url of the script @param type the type attribute of the script tag, eg. 'text/javascript' } { if {$section eq "head"} { # # A head script # ::template::head::add_script -type $type -defer=$defer_p -async=$async_p \ -src $src -charset $charset -script $script -order $order \ -crossorigin $crossorigin -integrity $integrity } else { # # A body script. The order is ignored. # ::template::add_body_script -type $type -defer=$defer_p -async=$async_p \ -src $src -charset $charset -script $script \ -crossorigin $crossorigin -integrity $integrity } } ad_proc -public template::head::add_script { {-async:boolean} {-charset ""} {-crossorigin ""} {-defer:boolean} {-integrity ""} {-order "0"} {-script ""} {-src ""} {-type "text/javascript"} } { Add a script to the head section of the document to be returned to the users client. A script library in an external file may only be included once; subsequent calls to add_script will replace the existing entry. Anonymous script blocks will be added without checking for duplicates; the caller must ensure that anonymous script blocks are not inadvertently added multiple times. You must supply either src or script. @param async whether execution of the script should be executed asynchronously as soon as it is available @param charset the charset attribute of the script tag, ie. the character set of the script if it differs from the main document @param crossorigin Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used @param defer whether execution of the script should be defered until after the page has been loaded @param integrity provide hash values for W3C Subresource Integrity recommentation @param order specify inclusion order @param script the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src @param src the src attribute of the script tag, ie. the source url of the script @param type the type attribute of the script tag, eg. 'text/javascript' } { if {$defer_p} { set defer defer } else { set defer "" } if {$async_p} { set async async } else { set async "" } if {$src eq ""} { if {$script eq ""} { error "You must supply either -src or -script." } # # For the time being, not all browsers support # nonces. According to the specs the added 'unsafe-inline', # is ignored on browsers supporting nonces. # # We could restrict setting of unsafe-inline to certain # browsers by checking the user agent. # security::csp::require script-src 'unsafe-inline' lappend ::template::head::scripts(anonymous) $type "" $charset $defer $async $script $order $crossorigin $integrity } else { set ::template::head::scripts($src) [list $type $src $charset $defer $async "" $order $crossorigin $integrity] } } ad_proc -public template::head::flush_script { {-src:required} } { Flush a a script tag, which was previously set in the head section via template::add_script. One can provide a wild @author Gustaf Neumann @creation-date 2018-03-09 @param src src attribute of the script tag, ie. the source url of the script. A glob pattern similar link in "string match" can be provided. @see ::template::head::add_script } { array unset ::template::head::scripts $src flush_included $src } ad_proc -public template::head::add_link { {-crossorigin ""} {-href:required} {-integrity ""} {-lang ""} {-media ""} {-order "0"} {-rel:required} {-title ""} {-type ""} } { Add a link tag to the head section of the document to be returned to the users client. A given target document may only be added once for a specified relation; subsequent calls to add_link will replace the existing entry. @param crossorigin Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used @param href the href attribute of the link tag, eg. the target document of the link @param integrity provide hash values for W3C Subresource Integrity recommendation @param lang the lang attribute of the link tag specifying the language of its attributes if they differ from the document language @param media the media attribute of the link tag describing which display media this link is relevant to. This may be a comma @param order specify inclusion order @param rel the rel attribute of the link tag defining the relationship of the linked document to the current one, eg. 'stylesheet' @param title the title attribute of the link tag describing the target of this link @param type the type attribute of the link tag, eg. 'text/css' separated list of values, eg. 'screen,print,braille' @see ::template::head::flush_link } { set ::template::head::links($rel,$href) [list $rel $href $type $media $title $lang $order $crossorigin $integrity] } ad_proc -public template::head::flush_link { {-href:required} {-rel:required} } { Flush a a link tag, which was previously set in the head section via template::head::add_link @author Gustaf Neumann @creation-date 2018-03-09 @param href the href attribute of the link tag, eg. the target document of the link. A glob pattern similar link in "string match" can be provided. @param rel the rel attribute of the link tag defining the relationship of the linked document to the current one, eg. 'stylesheet' @see ::template::head::add_link } { array unset ::template::head::links $rel,$href flush_included $href } ad_proc -public template::head::includes { {-container:required} {-parts:required} } { Define, that a compound resource (container) contains multiple parts. Container and parts are typically urls, which are referred to by a "href" attribute or by link or a "src" attribute of a script. @author Gustaf Neumann @creation-date 2018-03-09 @param container compound resource @param parts list of resources, which are included in a compound resource (container). @see ::template::head::add_link @see ::template::head::add_script @see ::template::head::included_p } { set ::template::head::includes($container) $parts foreach p $parts { set ::template::head::included($p) $container } } ad_proc -private template::head::included_p { resource } { Check, if the provided resource is included by some other resource. @author Gustaf Neumann @creation-date 2018-03-09 @param uri resource @see ::template::head::includes } { return [info exists ::template::head::included($resource)] } ad_proc -private template::head::flush_included { resource } { Flush a part relations ships of a compound resource @author Gustaf Neumann @creation-date 2018-03-09 @param resource compound resource @see ::template::head::add_link } { ns_log notice "flush_included <$resource> includes: [array get ::template::head::includes $resource]" foreach {container parts} [array get ::template::head::includes $resource] { unset ::template::head::includes($container) foreach p $parts { unset ::template::head::included($p) } } } ad_proc -public template::head::add_meta { {-http_equiv ""} {-name ""} {-scheme ""} {-content ""} {-lang ""} } { Add a meta tag to the head section of the document to be returned to the users client. A meta tag with a given name or http-equiv may only be added once; subsequent calls to add_meta will replace the existing entry. You must supply either name or http_equiv. @param http_equiv the http-equiv attribute of the meta tag, ie. the HTTP header which this metadata is equivalent to eg. 'content-type' @param name the name attribute of the meta tag, ie. the metadata identifier @param scheme the scheme attribute of the meta tag defining which metadata scheme should be used to interpret the metadata, eg. 'DC' for Dublin Core (http://dublincore.org/) @param content the content attribute of the meta tag, ie the metadata value @param lang the lang attribute of the meta tag specifying the language of its attributes if they differ from the document language } { variable ::template::head::metas if {$http_equiv eq "" && $name eq ""} { error "You must supply either -http_equiv or -name." } set metas($http_equiv,$name) [list \ $http_equiv \ $name \ $scheme \ $content \ $lang \ ] } ad_proc -public template::head::add_style { {-style:required} {-title ""} {-lang ""} {-media ""} {-type "text/css"} } { Add an embedded css style declaration @author Dave Bauer (dave@thedesignexperience.org) @creation-date 2007-11-30 @param style CSS content to be included in the style tag @param type the type attribute of the link tag, eg. 'text/css' @param media the media attribute of the link tag describing which display media this link is relevant to. This may be a comma separated list of values, eg. 'screen,print,braille' @param title the title attribute of the link tag describing the target of this link @param lang the lang attribute of the link tag specifying the language of its attributes if they differ from the document language } { variable ::template::head::styles if {[info exists styles(anonymous)]} { # # Add this combination only once # foreach {_type _media _title _lang _style} $styles(anonymous) { if {$type eq $_type && $_media eq $media && $_title eq $title && $_lang eq $lang && $_style eq $style } { return } } } lappend styles(anonymous) $type $media $title $lang $style } ad_proc -public template::head::add_javascript { {-async:boolean} {-charset ""} {-crossorigin ""} {-defer:boolean} {-integrity ""} {-order "0"} {-script ""} {-src ""} } { Add a script of type 'text/javascript' to the head section of the document to be returned to the users client. This function is a wrapper around template::head::add_script. You must supply either src or script. @param async whether execution of the script should be executed asynchronously as soon as it is available @param charset the charset attribute of the script tag, ie. the character set of the script if it differs from the main document @param crossorigin Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used @param defer whether execution of the script should be defered until after the page has been loaded @param integrity provide hash values for W3C Subresource Integrity recommentation @param order specify inclusion order @param script the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src @param src the src attribute of the script tag, ie. the source url of the script @see template::head::add_script } { template::head::add_script \ -defer=$defer_p -async=$async_p \ -type text/javascript \ -src $src \ -charset $charset \ -script $script \ -order $order \ -crossorigin $crossorigin -integrity $integrity } ad_proc -public template::head::add_css { {-alternate:boolean} {-href:required} {-media "all"} {-title ""} {-lang ""} {-order "0"} } { Add a link tag with relation type 'stylesheet' or 'alternate stylesheet', and type 'text/css' to the head section of the document to be returned to the users client. A given target stylesheet may only be added once; subsequent calls to add_css will replace the existing entry. This function is a wrapper around template::head::add_link. @param href the href attribute of the link tag, eg. the target stylesheet @param alternate sets the rel attribute of the link tag defining to 'alternate stylesheet' if set, sets it to 'stylesheet' otherwise @param media the media attribute of the link tag describing which display media this link is relevant to. This may be a comma separated list of values, eg. 'screen,print,braille' @param title the title attribute of the link tag describing the target of this link @param lang the lang attribute of the link tag specifying the language of its attributes if they differ from the document language @see template::head::add_link } { if {$alternate_p} { set rel "alternate stylesheet" } else { set rel "stylesheet" } template::head::add_link -rel $rel \ -type text/css \ -href $href \ -media $media \ -title $title \ -lang $lang \ -order $order } ad_proc -public template::add_body_handler { {-event:required} {-script:required} {-identifier anonymous} } { Adds javascript code to an event handler in the body tag. Several javascript code blocks may be assigned to each handler by subsequent calls to template::add_body_handler.
If your script may only be added once you may supply an identifier. Subsequent calls to template::add_body_handler with the same identifier will replace your script rather than appending to it.
event
may be one of:
{ form_id field_name }
@param message Message to be displayed in the confirmation dialog
@author Gustaf Neumann
} {
set script [subst {
if (!confirm('$message')) {
event.preventDefault();
}
}]
set cmd [list template::add_event_listener \
-event $event -script $script -preventdefault=false]
if {[info exists id]} {
lappend cmd -id $id
} elseif {[info exists formfield]} {
lappend cmd -formfield $formfield
} else {
lappend cmd -CSSclass $CSSclass
}
{*}$cmd
}
ad_proc template::add_event_listener {
{-event click}
{-CSSclass "acs-listen"}
{-id}
{-formfield}
{-usecapture:boolean false}
{-preventdefault:boolean true}
{-script:required}
} {
Register an event handler for elements either with a specified ID,
CSS class, or for a formfield targeted by form id and field name.
@param event register handler for this type of event
@param id register handler for this HTML ID
@param CSSclass register handler for this CSS class
@param formfield register handler for this formfield, specified
in a list of two elements in the form
{ form_id field_name }
@author Gustaf Neumann
} {
set prevent [expr {$preventdefault_p ? "event.preventDefault();" : ""}]
set script [subst {
e.addEventListener('$event', function (event) {$prevent$script}, $usecapture_p);
}]
if {[info exists id]} {
set script [subst {
var e = document.getElementById('$id');
if (e !== null) {$script}
}]
} elseif {[info exists formfield]} {
lassign $formfield id name
set script [subst {
var e = document.getElementById('$id').elements.namedItem('$name');
if (e !== null) {$script}
}]
} else {
#
# In case, no id is provided, use the "CSSclass"
#
set script [subst {
var elems = document.getElementsByClassName('$CSSclass');
for (var i = 0, l = elems.length; i < l; i++) {
var e = elems\[i\];
$script
}
}]
}
template::add_body_script -script $script
}
# Local variables:
# mode: tcl
# tcl-indent-level: 4
# indent-tabs-mode: nil
# End: