• Publicity: Public Only All

head-procs.tcl

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.

Location:
packages/acs-templating/tcl/head-procs.tcl
Created:
2007-05-18
Author:
Lee Denison <lee@xarg.co.uk>

Procedures in this file

Detailed information

template::add_body_handler (public)

 template::add_body_handler -event event -script script \
    [ -identifier identifier ]

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:

  • onload
  • onunload
  • onclick
  • ondblclick
  • onmousedown
  • onmouseup
  • onmouseover
  • onmousemove
  • onmouseout
  • onkeypress
  • onkeydown
  • onkeyup

Switches:
-event
(required)
the event during which the supplied script should be executed
-script
(required)
the JavaScript code to execute
-identifier
(defaults to "anonymous") (optional)
a name, if supplied, used to ensure this JavaScript code is only added to the handler once

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::add_body_handler template::add_body_handler test_templates_and_scripts->template::add_body_handler Class ::xo::lti::LTI Class ::xo::lti::LTI (public) Class ::xo::lti::LTI->template::add_body_handler packages/acs-templating/www/scripts/xinha/attach-file.tcl packages/acs-templating/ www/scripts/xinha/attach-file.tcl packages/acs-templating/www/scripts/xinha/attach-file.tcl->template::add_body_handler packages/acs-templating/www/scripts/xinha/attach-image.tcl packages/acs-templating/ www/scripts/xinha/attach-image.tcl packages/acs-templating/www/scripts/xinha/attach-image.tcl->template::add_body_handler packages/calendar/www/cal-item-new.tcl packages/calendar/ www/cal-item-new.tcl packages/calendar/www/cal-item-new.tcl->template::add_body_handler packages/forums/lib/message/row2.tcl packages/forums/ lib/message/row2.tcl packages/forums/lib/message/row2.tcl->template::add_body_handler

Testcases:
templates_and_scripts

template::add_body_script (public)

 template::add_body_script [ -async ] [ -charset charset ] \
    [ -crossorigin crossorigin ] [ -defer ] [ -integrity integrity ] \
    [ -script script ] [ -src src ] [ -type type ]

Add a script to the start of the body section of the document to be returned to the users client. You must supply either src or script.

Switches:
-async
(boolean) (optional)
whether execution of the script should be executed asynchronously as soon as it is available
-charset
(optional)
the charset attribute of the script tag, i.e. the character set of the script if it differs from the main document
-crossorigin
(optional)
Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used
-defer
(boolean) (optional)
whether execution of the script should be deferred until after the page has been loaded
-integrity
(optional)
provide hash values for W3C Subresource Integrity recommendation
-script
(optional)
the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src
-src
(optional)
the src attribute of the script tag, i.e. the source url of the script
-type
(defaults to "text/javascript") (optional)
the type attribute of the script tag, e.g. 'text/javascript'

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::add_body_script template::add_body_script test_templates_and_scripts->template::add_body_script test_xowiki_test_cases xowiki_test_cases (test xowiki) test_xowiki_test_cases->template::add_body_script security::csp::require security::csp::require (public) template::add_body_script->security::csp::require template::head::require_csp template::head::require_csp (private) template::add_body_script->template::head::require_csp Class ::xowf::test_item::Answer_manager Class ::xowf::test_item::Answer_manager (public) Class ::xowf::test_item::Answer_manager->template::add_body_script Class ::xowf::test_item::Question_manager Class ::xowf::test_item::Question_manager (public) Class ::xowf::test_item::Question_manager->template::add_body_script Class ::xowiki::formfield::FormField Class ::xowiki::formfield::FormField (public) Class ::xowiki::formfield::FormField->template::add_body_script Class ::xowiki::includelet::personal-notification-messages Class ::xowiki::includelet::personal-notification-messages (public) Class ::xowiki::includelet::personal-notification-messages->template::add_body_script ad_html_text_convert ad_html_text_convert (public) ad_html_text_convert->template::add_body_script

Testcases:
templates_and_scripts, xowiki_test_cases

template::add_confirm_handler (public)

 template::add_confirm_handler [ -event event ] [ -message message ] \
    [ -CSSclass CSSclass ] [ -id id ] [ -selector selector ] \
    [ -formfield formfield ]

Register an event handler for confirmation dialogs for elements either with a specified ID, CSS class, a formfield targeted by form id and field name or a CSS selector.

Switches:
-event
(defaults to "click") (optional)
register confirm handler for this type of event
-message
(defaults to "Are you sure?") (optional)
Message to be displayed in the confirmation dialog. If the message looks like a message key (starting and ending with a hash sign) it is treated as a message key
-CSSclass
(defaults to "acs-confirm") (optional)
register confirm handler for this CSS class
-id
(optional)
register confirm handler for this HTML ID
-selector
(optional)
register confirm handler for elements identified by this CSS selector. When a CSS selector contains double and single quotes, we won't add any of those around the selector automatically. Instead, the user must specify them explicitly, for instance like this: ... -selector {'[name="o\'hara"]'}. If the selector does not contain any single or double quotes, we can let the user omit them, as for the case of a simple tag name selector: ... -selector "li". Quotes can also be omitted if the selector contains only one kind of them, like ... -selector {[data-property='value']} or ... -selector {[data-property="value"]}
-formfield
(optional)
register confirm handler for this formfield, specified in a list of two elements in the form { form_id field_name }
Author:
Gustaf Neumann

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::add_confirm_handler template::add_confirm_handler test_templates_and_scripts->template::add_confirm_handler _ _ (public) template::add_confirm_handler->_ Class ::Generic::List Class ::Generic::List (public) Class ::Generic::List->template::add_confirm_handler packages/acs-admin/www/auth/authority.tcl packages/acs-admin/ www/auth/authority.tcl packages/acs-admin/www/auth/authority.tcl->template::add_confirm_handler packages/acs-admin/www/auth/index.tcl packages/acs-admin/ www/auth/index.tcl packages/acs-admin/www/auth/index.tcl->template::add_confirm_handler packages/acs-automated-testing/www/server.tcl packages/acs-automated-testing/ www/server.tcl packages/acs-automated-testing/www/server.tcl->template::add_confirm_handler packages/acs-lang/www/admin/index.tcl packages/acs-lang/ www/admin/index.tcl packages/acs-lang/www/admin/index.tcl->template::add_confirm_handler

Testcases:
templates_and_scripts

template::add_event_listener (public)

 template::add_event_listener [ -event event ] [ -CSSclass CSSclass ] \
    [ -id id ] [ -formfield formfield ] [ -selector selector ] \
    [ -usecapture ] [ -preventdefault ] -script script

Register an event handler for elements. The affected elements can be specified in different ways, which will be checked in the following order of precedence: id, formfield, selector and CSSclass. Normally one needs to provide only one kind of specification.

Switches:
-event
(defaults to "click") (optional)
register handler for this type of event
-CSSclass
(defaults to "acs-listen") (optional)
register handler for this CSS class
-id
(optional)
register handler for this HTML ID
-formfield
(optional)
register handler for this formfield, specified in a list of two elements in the form { form_id field_name }
-selector
(optional)
register handler for elements identified by this CSS selector. When a CSS selector contains double and single quotes, we won't add any of those around the selector automatically. Instead, the user must specify them explicitly, for instance like this: ... -selector {'[name="o\'hara"]'}. If the selector does not contain any single or double quotes, we can let the user omit them, as for the case of a simple tag name selector: ... -selector "li". Quotes can also be omitted if the selector contains only one kind of them, like ... -selector {[data-property='value']} or ... -selector {[data-property="value"]}
-usecapture
(boolean) (defaults to "false") (optional)
indicating whether event will be dispatched to the registered listener before being dispatched to any EventTarget beneath it in the DOM tree.
-preventdefault
(boolean) (defaults to "true") (optional)
this option can the used prevent default click handling
-script
(required)
Author:
Gustaf Neumann

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::add_event_listener template::add_event_listener test_templates_and_scripts->template::add_event_listener template::add_body_script template::add_body_script (public) template::add_event_listener->template::add_body_script Class ::xo::Table::BootstrapTableRenderer::AnchorField Class ::xo::Table::BootstrapTableRenderer::AnchorField (public) Class ::xo::Table::BootstrapTableRenderer::AnchorField->template::add_event_listener Class ::xowf::test_item::Answer_manager Class ::xowf::test_item::Answer_manager (public) Class ::xowf::test_item::Answer_manager->template::add_event_listener Class ::xowiki::formfield::candidate_box_select Class ::xowiki::formfield::candidate_box_select (public) Class ::xowiki::formfield::candidate_box_select->template::add_event_listener Class ::xowiki::formfield::range Class ::xowiki::formfield::range (public) Class ::xowiki::formfield::range->template::add_event_listener Class ::xowiki::includelet::bookmarklet-button Class ::xowiki::includelet::bookmarklet-button (public) Class ::xowiki::includelet::bookmarklet-button->template::add_event_listener

Testcases:
templates_and_scripts

template::add_footer (public)

 template::add_footer [ -direction direction ] [ -src src ] \
    [ -params params ] [ -html html ]

Add a footer include to the end of the document body. This function is used by site wide services to add functionality to the end of a page. Examples include the developer support toolbar, acs-lang translation interface and the acs-templating WYSIWYG editor textarea place holder. If you are not implementing a site wide service, you should not be using this function to add content to your page. You must supply either src or html.

Switches:
-direction
(defaults to "outer") (optional)
whether the footer should be added as the outer most page content or the inner most
-src
(optional)
the path to the include
-params
(optional)
a list of name, value pairs to pass as parameter to the include
-html
(optional)
literal html to include in the page. This parameter will be ignored if a values has been supplied for src.
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 Class ::xo::lti::LTI Class ::xo::lti::LTI (public) template::add_footer template::add_footer Class ::xo::lti::LTI->template::add_footer packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::add_footer xo::lti::LTI instproc form_render xo::lti::LTI instproc form_render (public) xo::lti::LTI instproc form_render->template::add_footer

Testcases:
No testcase defined.

template::add_header (public)

 template::add_header [ -direction direction ] [ -src src ] \
    [ -params params ] [ -html html ]

Add a header include to the beginning of the document body. This function is used by site wide services to add functionality to the beginning of a page. Examples include the developer support toolbar, acs-lang translation interface and the acs-templating WYSIWYG editor textarea place holder. If you are not implementing a site wide service, you should not be using this function to add content to your page. You must supply either src or html.

Switches:
-direction
(defaults to "outer") (optional)
whether the header should be added as the outer most page content or the inner most
-src
(optional)
the path to the include
-params
(optional)
a list of name, value pairs to pass as parameter to the include
-html
(optional)
literal html to include in the page. This parameter will be ignored if a values has been supplied for src.
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl template::add_header template::add_header packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::add_header

Testcases:
No testcase defined.

template::add_refresh_on_history_handler (public)

 template::add_refresh_on_history_handler

Register an event handler which will trigger a complete page refresh when we land on this page by accessing the browser's history (back and forward buttons). This is useful e.g. for those pages where some push interaction is happening and retrieving the page from the browser history would display it in an inconsistent state.

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::add_refresh_on_history_handler template::add_refresh_on_history_handler test_templates_and_scripts->template::add_refresh_on_history_handler template::add_body_script template::add_body_script (public) template::add_refresh_on_history_handler->template::add_body_script xo::ChatClass instproc login xo::ChatClass instproc login (public) xo::ChatClass instproc login->template::add_refresh_on_history_handler

Testcases:
templates_and_scripts

template::add_script (public)

 template::add_script [ -async ] [ -charset charset ] \
    [ -crossorigin crossorigin ] [ -defer ] [ -integrity integrity ] \
    [ -order order ] [ -script script ] [ -section section ] \
    [ -src src ] [ -type type ]
Switches:
-async
(boolean) (optional)
whether execution of the script should be executed asynchronously as soon as it is available
-charset
(optional)
the charset attribute of the script tag, i.e. the character set of the script if it differs from the main document
-crossorigin
(optional)
Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used
-defer
(boolean) (optional)
whether execution of the script should be deferred until after the page has been loaded
-integrity
(optional)
provide hash values for W3C Subresource Integrity recommendation
-order
(defaults to "0") (optional)
specify inclusion order
-script
(optional)
the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src
-section
(defaults to "head") (optional)
section, where script is added ("head" or "body")
-src
(optional)
the src attribute of the script tag, i.e. the source url of the script
-type
(defaults to "text/javascript") (optional)
the type attribute of the script tag, e.g. 'text/javascript'

Partial Call Graph (max 5 caller/called nodes):
%3 Class ::xowiki::formfield::FormField Class ::xowiki::formfield::FormField (public) template::add_script template::add_script Class ::xowiki::formfield::FormField->template::add_script Class ::xowiki::formfield::numeric Class ::xowiki::formfield::numeric (public) Class ::xowiki::formfield::numeric->template::add_script packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::add_script richtext::ckeditor4::initialize_widget richtext::ckeditor4::initialize_widget (public) richtext::ckeditor4::initialize_widget->template::add_script richtext::ckeditor5::initialize_widget richtext::ckeditor5::initialize_widget (public) richtext::ckeditor5::initialize_widget->template::add_script template::add_body_script template::add_body_script (public) template::add_script->template::add_body_script template::head::add_script template::head::add_script (public) template::add_script->template::head::add_script

Testcases:
No testcase defined.

template::collect_body_scripts (public)

 template::collect_body_scripts

Collect the body scripts via an easy to call function, hiding the template used for the implementation.

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::collect_body_scripts template::collect_body_scripts test_templates_and_scripts->template::collect_body_scripts template::adp_include template::adp_include (public) template::collect_body_scripts->template::adp_include Class ::xowf::test_item::Answer_manager Class ::xowf::test_item::Answer_manager (public) Class ::xowf::test_item::Answer_manager->template::collect_body_scripts xowf::test_item::Answer_manager instproc render_print_button xowf::test_item::Answer_manager instproc render_print_button (protected) xowf::test_item::Answer_manager instproc render_print_button->template::collect_body_scripts

Testcases:
templates_and_scripts

template::get_body_event_handlers (public)

 template::get_body_event_handlers

Get body event handlers specified with template::add_body_handler. The proc clears the global variable ::template::body_handlers after having processed its content.

Partial Call Graph (max 5 caller/called nodes):
%3 test_templates_and_scripts templates_and_scripts (test acs-templating) template::get_body_event_handlers template::get_body_event_handlers test_templates_and_scripts->template::get_body_event_handlers template::add_body_script template::add_body_script (public) template::get_body_event_handlers->template::add_body_script template::register_double_click_handler template::register_double_click_handler (private) template::get_body_event_handlers->template::register_double_click_handler packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::get_body_event_handlers packages/acs-templating/lib/body_scripts.tcl packages/acs-templating/ lib/body_scripts.tcl packages/acs-templating/lib/body_scripts.tcl->template::get_body_event_handlers

Testcases:
templates_and_scripts

template::get_footer_html (public)

 template::get_footer_html

Get footers as a chunk of html suitable for insertion into blank-master.adp Called only from blank-master.tcl

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl template::get_footer_html template::get_footer_html packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::get_footer_html template::adp_include template::adp_include (public) template::get_footer_html->template::adp_include template::themed_template template::themed_template (public) template::get_footer_html->template::themed_template

Testcases:
No testcase defined.

template::get_header_html (public)

 template::get_header_html

Get headers as a chunk of html suitable for insertion into blank-master.adp Called only from blank-master.tcl

Partial Call Graph (max 5 caller/called nodes):
%3 packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl template::get_header_html template::get_header_html packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::get_header_html template::adp_include template::adp_include (public) template::get_header_html->template::adp_include

Testcases:
No testcase defined.

template::head::add_css (public)

 template::head::add_css [ -alternate ] [ -crossorigin crossorigin ] \
    -href href [ -integrity integrity ] [ -lang lang ] \
    [ -media media ] [ -order order ] [ -title title ]

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.

Switches:
-alternate
(boolean) (optional)
sets the rel attribute of the link tag defining to 'alternate stylesheet' if set, sets it to 'stylesheet' otherwise
-crossorigin
(optional)
Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used
-href
(required)
the href attribute of the link tag, e.g. the target stylesheet
-integrity
(optional)
provide hash values for W3C Subresource Integrity recommendation
-lang
(optional)
the lang attribute of the link tag specifying the language of its attributes if they differ from the document language
-media
(defaults to "all") (optional)
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, e.g. 'screen,print,braille'
-order
(defaults to "0") (optional)
-title
(optional)
the title attribute of the link tag describing the target of this link
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_xowiki_test_cases xowiki_test_cases (test xowiki) template::head::add_css template::head::add_css test_xowiki_test_cases->template::head::add_css template::head::add_link template::head::add_link (public) template::head::add_css->template::head::add_link Class ::xowiki::formfield::FormField Class ::xowiki::formfield::FormField (public) Class ::xowiki::formfield::FormField->template::head::add_css ad_html_text_convert ad_html_text_convert (public) ad_html_text_convert->template::head::add_css cookieconsent::add_to_page cookieconsent::add_to_page (public) cookieconsent::add_to_page->template::head::add_css packages/acs-admin/www/users/merge.tcl packages/acs-admin/ www/users/merge.tcl packages/acs-admin/www/users/merge.tcl->template::head::add_css packages/acs-automated-testing/www/admin/index.tcl packages/acs-automated-testing/ www/admin/index.tcl packages/acs-automated-testing/www/admin/index.tcl->template::head::add_css

Testcases:
xowiki_test_cases

template::head::add_javascript (public)

 template::head::add_javascript [ -async ] [ -charset charset ] \
    [ -crossorigin crossorigin ] [ -defer ] [ -integrity integrity ] \
    [ -order order ] [ -script script ] [ -src 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.

Switches:
-async
(boolean) (optional)
whether execution of the script should be executed asynchronously as soon as it is available
-charset
(optional)
the charset attribute of the script tag, i.e. the character set of the script if it differs from the main document
-crossorigin
(optional)
Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used
-defer
(boolean) (optional)
whether execution of the script should be deferred until after the page has been loaded
-integrity
(optional)
provide hash values for W3C Subresource Integrity recommendation
-order
(defaults to "0") (optional)
specify inclusion order
-script
(optional)
the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src
-src
(optional)
the src attribute of the script tag, i.e. the source url of the script
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 ad_html_text_convert ad_html_text_convert (public) template::head::add_javascript template::head::add_javascript ad_html_text_convert->template::head::add_javascript boomerang::initialize_widget boomerang::initialize_widget (public) boomerang::initialize_widget->template::head::add_javascript cookieconsent::add_to_page cookieconsent::add_to_page (public) cookieconsent::add_to_page->template::head::add_javascript packages/acs-templating/www/scripts/xinha/attach-file.tcl packages/acs-templating/ www/scripts/xinha/attach-file.tcl packages/acs-templating/www/scripts/xinha/attach-file.tcl->template::head::add_javascript packages/acs-templating/www/scripts/xinha/attach-image.tcl packages/acs-templating/ www/scripts/xinha/attach-image.tcl packages/acs-templating/www/scripts/xinha/attach-image.tcl->template::head::add_javascript template::head::add_script template::head::add_script (public) template::head::add_javascript->template::head::add_script

Testcases:
No testcase defined.

template::head::add_link (public)

 template::head::add_link [ -crossorigin crossorigin ] -href href \
    [ -integrity integrity ] [ -lang lang ] [ -media media ] \
    [ -order order ] -rel rel [ -title title ] [ -type 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.

Switches:
-crossorigin
(optional)
Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used
-href
(required)
the href attribute of the link tag, e.g. the target document of the link
-integrity
(optional)
provide hash values for W3C Subresource Integrity recommendation
-lang
(optional)
the lang attribute of the link tag specifying the language of its attributes if they differ from the document language
-media
(optional)
the media attribute of the link tag describing which display media this link is relevant to. This may be a comma
-order
(defaults to "0") (optional)
specify inclusion order
-rel
(required)
the rel attribute of the link tag defining the relationship of the linked document to the current one, e.g. 'stylesheet'
-title
(optional)
the title attribute of the link tag describing the target of this link
-type
(optional)
the type attribute of the link tag, e.g. 'text/css' separated list of values, e.g. 'screen,print,braille'
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 Class ::xowf::test_item::Question_manager Class ::xowf::test_item::Question_manager (public) template::head::add_link template::head::add_link Class ::xowf::test_item::Question_manager->template::head::add_link template::head::add_css template::head::add_css (public) template::head::add_css->template::head::add_link xowf::test_item::Question_manager instproc question_statistics_block xowf::test_item::Question_manager instproc question_statistics_block (public) xowf::test_item::Question_manager instproc question_statistics_block->template::head::add_link

Testcases:
No testcase defined.

template::head::add_meta (public)

 template::head::add_meta [ -http_equiv http_equiv ] [ -name name ] \
    [ -scheme scheme ] [ -content content ] [ -lang 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.

Switches:
-http_equiv
(optional)
the http-equiv attribute of the meta tag, i.e. the HTTP header which this metadata is equivalent to e.g. 'content-type'
-name
(optional)
the name attribute of the meta tag, i.e. the metadata identifier
-scheme
(optional)
the scheme attribute of the meta tag defining which metadata scheme should be used to interpret the metadata, e.g. 'DC' for Dublin Core (http://dublincore.org/)
-content
(optional)
the content attribute of the meta tag, i.e. the metadata value
-lang
(optional)
the lang attribute of the meta tag specifying the language of its attributes if they differ from the document language

Partial Call Graph (max 5 caller/called nodes):
%3 test_xowiki_test_cases xowiki_test_cases (test xowiki) template::head::add_meta template::head::add_meta test_xowiki_test_cases->template::head::add_meta packages/acs-bootstrap-installer/installer/www/blank-master.tcl packages/acs-bootstrap-installer/ installer/www/blank-master.tcl packages/acs-bootstrap-installer/installer/www/blank-master.tcl->template::head::add_meta packages/acs-subsite/www/admin/plain-master.tcl packages/acs-subsite/ www/admin/plain-master.tcl packages/acs-subsite/www/admin/plain-master.tcl->template::head::add_meta packages/acs-subsite/www/plain-master.tcl packages/acs-subsite/ www/plain-master.tcl packages/acs-subsite/www/plain-master.tcl->template::head::add_meta packages/acs-subsite/www/register/index.tcl packages/acs-subsite/ www/register/index.tcl packages/acs-subsite/www/register/index.tcl->template::head::add_meta packages/acs-subsite/www/shared/plain-master.tcl packages/acs-subsite/ www/shared/plain-master.tcl packages/acs-subsite/www/shared/plain-master.tcl->template::head::add_meta

Testcases:
xowiki_test_cases

template::head::add_script (public)

 template::head::add_script [ -async ] [ -charset charset ] \
    [ -crossorigin crossorigin ] [ -defer ] [ -integrity integrity ] \
    [ -order order ] [ -script script ] [ -src src ] [ -type type ]

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.

Switches:
-async
(boolean) (optional)
whether execution of the script should be executed asynchronously as soon as it is available
-charset
(optional)
the charset attribute of the script tag, i.e. the character set of the script if it differs from the main document
-crossorigin
(optional)
Enumerated attribute to indicate whether CORS (Cross-Origin Resource Sharing) should be used
-defer
(boolean) (optional)
whether execution of the script should be deferred until after the page has been loaded
-integrity
(optional)
provide hash values for W3C Subresource Integrity recommendation
-order
(defaults to "0") (optional)
specify inclusion order
-script
(optional)
the inline script for the body of the script tag. This parameter will be ignored if a value has been supplied for src
-src
(optional)
the src attribute of the script tag, i.e. the source url of the script
-type
(defaults to "text/javascript") (optional)
the type attribute of the script tag, e.g. 'text/javascript'

Partial Call Graph (max 5 caller/called nodes):
%3 packages/forums/www/message-view.tcl packages/forums/ www/message-view.tcl template::head::add_script template::head::add_script packages/forums/www/message-view.tcl->template::head::add_script packages/forums/www/moderate/message-delete.tcl packages/forums/ www/moderate/message-delete.tcl packages/forums/www/moderate/message-delete.tcl->template::head::add_script template::add_script template::add_script (public) template::add_script->template::head::add_script template::head::add_javascript template::head::add_javascript (public) template::head::add_javascript->template::head::add_script xo::Page proc header_stuff xo::Page proc header_stuff xo::Page proc header_stuff->template::head::add_script security::csp::require security::csp::require (public) template::head::add_script->security::csp::require template::head::require_csp template::head::require_csp (private) template::head::add_script->template::head::require_csp

Testcases:
No testcase defined.

template::head::add_style (public)

 template::head::add_style -style style [ -title title ] [ -lang lang ] \
    [ -media media ] [ -type type ]

Add an embedded css style declaration

Switches:
-style
(required)
CSS content to be included in the style tag
-title
(optional)
the title attribute of the link tag describing the target of this link
-lang
(optional)
the lang attribute of the link tag specifying the language of its attributes if they differ from the document language
-media
(optional)
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, e.g. 'screen,print,braille'
-type
(defaults to "text/css") (optional)
the type attribute of the link tag, e.g. 'text/css'
Author:
Dave Bauer <dave@thedesignexperience.org>
Created:
2007-11-30

Partial Call Graph (max 5 caller/called nodes):
%3 ad_html_text_convert ad_html_text_convert (public) template::head::add_style template::head::add_style ad_html_text_convert->template::head::add_style apidoc::tclcode_to_html apidoc::tclcode_to_html (public) apidoc::tclcode_to_html->template::head::add_style packages/acs-api-browser/www/proc-view.tcl packages/acs-api-browser/ www/proc-view.tcl packages/acs-api-browser/www/proc-view.tcl->template::head::add_style packages/acs-developer-support/www/shell.tcl packages/acs-developer-support/ www/shell.tcl packages/acs-developer-support/www/shell.tcl->template::head::add_style packages/acs-templating/www/scripts/xinha/attach-file.tcl packages/acs-templating/ www/scripts/xinha/attach-file.tcl packages/acs-templating/www/scripts/xinha/attach-file.tcl->template::head::add_style _ _ (public) template::head::add_style->_

Testcases:
No testcase defined.

template::head::can_resolve_urn (public)

 template::head::can_resolve_urn resource

Return a boolean value indicating, whether we can resolve the URN.

Parameters:
resource

Partial Call Graph (max 5 caller/called nodes):
%3 test_urn_api urn_api (test acs-templating) template::head::can_resolve_urn template::head::can_resolve_urn test_urn_api->template::head::can_resolve_urn Class ::xowf::test_item::Answer_manager Class ::xowf::test_item::Answer_manager (public) Class ::xowf::test_item::Answer_manager->template::head::can_resolve_urn packages/acs-templating/www/sitewide-admin/index.tcl packages/acs-templating/ www/sitewide-admin/index.tcl packages/acs-templating/www/sitewide-admin/index.tcl->template::head::can_resolve_urn packages/xotcl-request-monitor/www/index.tcl packages/xotcl-request-monitor/ www/index.tcl packages/xotcl-request-monitor/www/index.tcl->template::head::can_resolve_urn packages/xotcl-request-monitor/www/long-calls.tcl packages/xotcl-request-monitor/ www/long-calls.tcl packages/xotcl-request-monitor/www/long-calls.tcl->template::head::can_resolve_urn xowf::test_item::Answer_manager instproc grading_table xowf::test_item::Answer_manager instproc grading_table (public) xowf::test_item::Answer_manager instproc grading_table->template::head::can_resolve_urn

Testcases:
urn_api

template::head::flush_link (public)

 template::head::flush_link -href href -rel rel

Flush a link tag, which was previously set in the head section via template::head::add_link

Switches:
-href
(required)
the href attribute of the link tag, e.g. the target document of the link. A glob pattern similar link in "string match" can be provided.
-rel
(required)
the rel attribute of the link tag defining the relationship of the linked document to the current one, e.g. 'stylesheet'
Author:
Gustaf Neumann
Created:
2018-03-09
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_head_includes head_includes (test acs-templating) template::head::flush_link template::head::flush_link test_head_includes->template::head::flush_link template::head::flush_included template::head::flush_included (private) template::head::flush_link->template::head::flush_included template::head::prepare_multirows template::head::prepare_multirows (private) template::head::prepare_multirows->template::head::flush_link

Testcases:
head_includes

template::head::flush_script (public)

 template::head::flush_script -src src

Flush a script tag, which was previously set in the head section via template::add_script. One can delete multiple entries by providing a glob pattern.

Switches:
-src
(required)
src attribute of the script tag, i.e. the source url of the script. A glob pattern similar link in "string match" can be provided.
Author:
Gustaf Neumann
Created:
2018-03-09
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_head_includes head_includes (test acs-templating) template::head::flush_script template::head::flush_script test_head_includes->template::head::flush_script template::head::flush_included template::head::flush_included (private) template::head::flush_script->template::head::flush_included

Testcases:
head_includes

template::head::includes (public)

 template::head::includes -container container -parts parts

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.

Switches:
-container
(required)
compound resource
-parts
(required)
list of resources, which are included in a compound resource (container).
Author:
Gustaf Neumann
Created:
2018-03-09
See Also:

Partial Call Graph (max 5 caller/called nodes):
%3 test_head_includes head_includes (test acs-templating) template::head::includes template::head::includes test_head_includes->template::head::includes packages/openacs-bootstrap3-theme/tcl/resource-init.tcl packages/openacs-bootstrap3-theme/ tcl/resource-init.tcl packages/openacs-bootstrap3-theme/tcl/resource-init.tcl->template::head::includes

Testcases:
head_includes

template::register_urn (public)

 template::register_urn -urn urn -resource resource \
    [ -csp_list csp_list ]

Register a URN for a resource. These URNs provide a single place for e.g. updating references to external resources when switching between a CDN and a local resource, or when a resource should be updated. We could consider a dns-prefetch for CDN requests. When the url-check is performed at register time, the performance for processing the url can be neglected.

Switches:
-urn
(required)
-resource
(required)
-csp_list
(optional)

Partial Call Graph (max 5 caller/called nodes):
%3 test_urn_api urn_api (test acs-templating) template::register_urn template::register_urn test_urn_api->template::register_urn highcharts::register_urns highcharts::register_urns (private) highcharts::register_urns->template::register_urn packages/bootstrap-icons/tcl/resource-init.tcl packages/bootstrap-icons/ tcl/resource-init.tcl packages/bootstrap-icons/tcl/resource-init.tcl->template::register_urn packages/fa-icons/tcl/resource-init.tcl packages/fa-icons/ tcl/resource-init.tcl packages/fa-icons/tcl/resource-init.tcl->template::register_urn packages/openacs-bootstrap3-theme/tcl/resource-init.tcl packages/openacs-bootstrap3-theme/ tcl/resource-init.tcl packages/openacs-bootstrap3-theme/tcl/resource-init.tcl->template::register_urn packages/openacs-bootstrap5-theme/tcl/resource-init.tcl packages/openacs-bootstrap5-theme/ tcl/resource-init.tcl packages/openacs-bootstrap5-theme/tcl/resource-init.tcl->template::register_urn

Testcases:
urn_api

template::set_css_property (public)

 template::set_css_property [ -class class ] \
    [ -querySelector querySelector ] -property property -value value

Set the specified CSS property in the DOM tree of the browser for elements for the specified class or query selector. This function should be used sparely in special situations, where CSS modification other approaches might be too complex.

Switches:
-class
(optional)
CSS class for which properties is set
-querySelector
(optional)
CSS querySelector via the javascript function querySelectorAll
-property
(required)
CSS property
-value
(required)
value for the CSS property

Partial Call Graph (max 5 caller/called nodes):
%3 template::add_script template::add_script (public) template::set_css_property template::set_css_property template::set_css_property->template::add_script

Testcases:
No testcase defined.
[ hide source ] | [ make this the default ]

Content File Source

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 data structures 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.
} {
    #ns_log notice "----- template::reset_request_vars [ad_conn url]"
    array unset ::template::head::scripts
    array unset ::template::head::links
    array unset ::template::head::metas
    array unset ::template::body_handlers

    set ::template::body_scripts {}
    set ::template::headers {}
    set ::template::footers {}
}

d_proc -public template::register_urn {
    -urn:required
    -resource:required
    {-csp_list ""}
} {

    Register a URN for a resource. These URNs provide a single place
    for e.g. updating references to external resources when switching
    between a CDN and a local resource, or when a resource should be
    updated.

    We could consider a dns-prefetch for CDN requests. When the
    url-check is performed at register time, the performance for
    processing the url can be neglected.

} {
    set key ::template::head::urn($urn)
    if {[info exists $key]} {
        set old_resource [set $key]
        #
        # Prefer local URLs over non-local ones (starting with http*:)
        #
        if {[string match //* $old_resource] || [string match http* $old_resource]} {
            ns_log notice "overwrite URN: $urn <$old_resource> with <$resource>"
            set $key $resource
            set ::template::head::urn_csp($urn$csp_list
        } else {
            ns_log notice "keep old URN: $urn <$old_resource> instead of <$resource>"
        }
    } else {
        set $key $resource
        set ::template::head::urn_csp($urn$csp_list
        ns_log notice "add URN: $urn <$resource>"
    }
}


d_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, i.e. 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 deferred until after
                   the page has been loaded
    @param integrity provide hash values for W3C Subresource Integrity recommendation
    @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, i.e. the source url of the
                   script
    @param type    the type attribute of the script tag, e.g. '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
    }
}

d_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 <strong>must</strong> 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, i.e. 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 deferred until after
                   the page has been loaded
    @param integrity provide hash values for W3C Subresource Integrity recommendation
    @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, i.e. the source url of the
                   script
    @param type    the type attribute of the script tag, e.g. 'text/javascript'

} {
    if {$defer_p} {
        set defer defer
    } else {
        set defer ""
    }

    if {$async_p} {
        set async async
    } else {
        set async ""
    }

    #
    # Replace potential URN in src with resolved value
    #
    set key ::template::head::urn($src)
    if {[info exists $key]} {
        template::head::require_csp $::template::head::urn_csp($src)
        set src [set $key]
    } elseif {[string match urn:* $src]} {
        ns_log error "URN <$src> could not be resolved"
    }

    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'
        #security::csp::require script-src 'strict-dynamic'

        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]
    }
}

d_proc -public template::head::flush_script {
    {-src:required}
} {

    Flush a script tag, which was previously set in the head section
    via template::add_script.  One can delete multiple entries by
    providing a glob pattern.

    @author Gustaf Neumann
    @creation-date 2018-03-09

    @param src     src attribute of the script tag, i.e. 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
}


d_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, e.g. 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, e.g. '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, e.g. 'text/css'
                   separated list of values, e.g. 'screen,print,braille'

    @see ::template::head::flush_link
} {
    set ::template::head::links($rel,$href) [list $rel $href $type $media $title $lang $order $crossorigin $integrity]
}

d_proc -public template::head::flush_link {
    {-href:required}
    {-rel:required}
} {
    Flush 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, e.g. 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, e.g. 'stylesheet'
    @see ::template::head::add_link
} {
    array unset ::template::head::links $rel,$href
    flush_included $href
}

d_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
    }
}

d_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 resource uri resource
    @see ::template::head::includes
} {
    return [info exists ::template::head::included($resource)]
}

d_proc -private template::head::included_in {
    resource
} {

    Return the containiner resource, containing the provided resource

    @author Gustaf Neumann
    @creation-date 2020-02-01

    @param resource uri resource
    @see ::template::head::includes
} {
    set key ::template::head::included($resource)
    return [expr {[info exists $key] ? [set $key] : ""}]
}

d_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)
        }
    }
}



d_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
    <strong>must</strong> supply either name or http_equiv.

    @param http_equiv the http-equiv attribute of the meta tag, i.e. the
                      HTTP header which this metadata is equivalent to
                      e.g. 'content-type'
    @param name       the name attribute of the meta tag, i.e. the metadata
                      identifier
    @param scheme     the scheme attribute of the meta tag defining which
                      metadata scheme should be used to interpret the metadata,
                      e.g. 'DC' for Dublin Core (http://dublincore.org/)
    @param content    the content attribute of the meta tag, i.e. 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 \
    ]
}

d_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, e.g. '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, e.g. '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
}

d_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, i.e. 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 deferred until after
                   the page has been loaded
    @param integrity provide hash values for W3C Subresource Integrity recommendation
    @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, i.e. 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
}

d_proc -public template::head::add_css {
    {-alternate:boolean}
    {-crossorigin ""}
    {-href:required}
    {-integrity ""}
    {-lang ""}
    {-media "all"}
    {-order "0"}
    {-title ""}
} {
    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, e.g. 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, e.g. '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
    @param crossorigin  Enumerated attribute to indicate whether CORS
                     (Cross-Origin Resource Sharing) should be used
    @param integrity provide hash values for W3C Subresource Integrity recommendation

    @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 \
        -crossorigin $crossorigin \
        -integrity $integrity \
}

d_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.

    <p>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.</p>

    <p><code>event</code> may be one of:</p>
    <ul>
      <li>onload</li>
      <li>onunload</li>
      <li>onclick</li>
      <li>ondblclick</li>
      <li>onmousedown</li>
      <li>onmouseup</li>
      <li>onmouseover</li>
      <li>onmousemove</li>
      <li>onmouseout</li>
      <li>onkeypress</li>
      <li>onkeydown</li>
      <li>onkeyup</li>
    </ul>

    @param event      the event during which the supplied script should be
                      executed
    @param script     the JavaScript code to execute
    @param identifier a name, if supplied, used to ensure this JavaScript code
                      is only added to the handler once
} {
    variable ::template::body_handlers

    if {$identifier eq "anonymous"} {
        lappend body_handlers($event,anonymous) $script
    } else {
        # Even a one event handler needs to be added in a list
        # since all handlers, anonymous and specific are treated as a
        # list in blank-master.tcl
        set body_handlers($event,$identifier) [list $script]
    }
}

d_proc -public template::add_body_script {
    {-async:boolean}
    {-charset ""}
    {-crossorigin ""}
    {-defer:boolean}
    {-integrity ""}
    {-script ""}
    {-src ""}
    {-type "text/javascript"}
} {
    Add a script to the start of the body section of the document to be returned
    to the users client. You <strong>must</strong> 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, i.e. 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 deferred until after
                   the page has been loaded
    @param integrity provide hash values for W3C Subresource Integrity recommendation
    @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, i.e. the source url of the
                   script
    @param type    the type attribute of the script tag, e.g. 'text/javascript'
} {

    if {$defer_p} {
        set defer defer
    } else {
        set defer ""
    }
    if {$async_p} {
        set async async
    } else {
        set async ""
    }

    if {$src eq "" && $script eq ""} {
        error "You must supply either -src or -script."
    }

    if {$script ne ""} {
        #
        # We have an inline 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'
    } else {
        #
        # Replace potential URN in src with resolved value
        #
        set key ::template::head::urn($src)
        if {[info exists $key]} {
            template::head::require_csp $::template::head::urn_csp($src)
            set src [set $key]
        } elseif {[string match urn:* $src]} {
            ns_log error "URN <$src> could not be resolved"
        }
    }

    lappend ::template::body_scripts $type $src $charset $defer $async $script $crossorigin $integrity
}


d_proc -public template::add_header {
    {-direction "outer"}
    {-src ""}
    {-params ""}
    {-html ""}
} {
    Add a header include to the beginning of the document body.  This function
    is used by site wide services to add functionality to the beginning of a
    page.  Examples include the developer support toolbar, acs-lang translation
    interface and the acs-templating WYSIWYG editor textarea place holder.  If
    you are not implementing a site wide service, you should not be using this
    function to add content to your page.  You must supply either src or html.

    @param direction whether the header should be added as the outer most
                     page content or the inner most
    @param src       the path to the include
    @param params    a list of name, value pairs to pass as parameter to the
                     include
    @param html      literal html to include in the page.  This parameter will
                     be ignored if a values has been supplied for src.

    @see template::add_footer
} {
    variable ::template::headers

    if {$src eq ""} {
        if {$html eq ""} {
            error "You must supply either -src or -html."
        }
        set values [list literal $html ""]
    } else {
        set values [list include $src $params]
    }

    if {[info exists headers]} {
      switch -- $direction {
        outer {set headers [linsert $headers 0 $values]}
        inner {lappend headers $values}
        default {error "unknown direction $direction"}
      }
    } else {
      set headers [list $values]
    }
}

d_proc -public template::add_footer {
    {-direction "outer"}
    {-src ""}
    {-params ""}
    {-html ""}
} {
    Add a footer include to the end of the document body.  This function
    is used by site wide services to add functionality to the end of a
    page.  Examples include the developer support toolbar, acs-lang translation
    interface and the acs-templating WYSIWYG editor textarea place holder.  If
    you are not implementing a site wide service, you should not be using this
    function to add content to your page.  You must supply either src or html.

    @param direction whether the footer should be added as the outer most
                     page content or the inner most
    @param src       the path to the include
    @param params    a list of name, value pairs to pass as parameter to the
                     include
    @param html      literal html to include in the page.  This parameter will
                     be ignored if a values has been supplied for src.

    @see template::add_header
} {
    variable ::template::footers

    if {$src eq ""} {
        if {$html eq ""} {
            error "You must supply either -src or -html."
        }
        set values [list literal $html ""]
    } else {
        set values [list include $src $params]
    }

    if {[info exists footers]} {
      switch -- $direction {
        outer {lappend footers $values}
        inner {set footers [linsert $footers 0 $values]}
        default {error "unknown direction $direction"}
      }
    } else {
      set footers [list $values]
    }
}

d_proc -private template::head::resolve_urn {
    resource
} {
    Replace potential URN in provided resource name with resolved
    value
} {
    set key ::template::head::urn($resource)
    if {[info exists $key]} {
        template::head::require_csp $::template::head::urn_csp($resource)
        set resource [set $key]
    }
    return $resource
}

d_proc template::head::can_resolve_urn {
    resource
} {
    Return a boolean value indicating, whether we can resolve the URN.
} {
    return [info exists ::template::head::urn($resource)]
}

d_proc -private template::head::require_csp {
    csp_list
} {
    Require the CSP directives as defined for URNs.

    @param csp_list flat list of pairs consisting of directives and values.
} {
    foreach {directive value} $csp_list {
        security::csp::require $directive $value
    }
}

ad_proc -private template::head::prepare_multirows {} {
    Generate multirows for meta, css, scripts
    Called only from blank-master.tcl
} {

    # Generate the <meta> tag multirow
    variable ::template::head::metas
    template::multirow create meta name content http_equiv scheme lang
    if {[array exists metas]} {
        foreach name [array names metas] {
            foreach {http_equiv name scheme content lang} $metas($name) {
                template::multirow append meta \
                    $name \
                    $content \
                    $http_equiv \
                    $scheme \
                    $lang
            }
        }
        unset metas
    }

    # Generate the <link> tag multirow
    variable ::template::head::links

    #
    # Filter out included links, such we have to do this only once.
    #
    foreach name [array names links] {
        lassign [split $name ,] rel href
        set container [::template::head::included_in $href]
        if {$container ne ""} {
            set container [template::head::resolve_urn $container]
            if {[array names links *,$container] ne ""} {
                template::head::flush_link -href $href -rel $rel
            }
        }
    }

    template::multirow create link rel type href title lang media order crossorigin integrity
    if {[array exists links]} {
        # first non alternate stylesheet
        foreach name [array names links] {
            foreach {rel href type media title lang order crossorigin integrity} $links($name) {
                if {$rel ne "alternate stylesheet"} {
                    template::multirow append link \
                        $rel \
                        $type \
                        [resolve_urn $href] \
                        $title \
                        $lang \
                        $media \
                        $order \
                        $crossorigin $integrity
                    set links($name""
                }
            }
        }
        # order the stylesheets before adding alternate ones
        template::multirow sort link order
        # now alternate stylesheet
        foreach name [array names links] {
            foreach {rel href type media title lang order crossorigin integrity} $links($name) {
                if {$links($name) ne ""} {
                    template::multirow append link \
                        $rel \
                        $type \
                        [resolve_urn $href] \
                        $title \
                        $lang \
                        $media \
                        $order \
                        $crossorigin $integrity
                    set links($name""
                }
            }
        }
        array unset links
    }

    # Generate the <style /> tag multirow
    variable ::template::head::styles
    template::multirow create ___style type title lang media style
    if {[array exists styles]} {
        foreach name [array names styles] {
            foreach {type media title lang style} $styles($name) {
                template::multirow append ___style \
                    $type \
                    $title \
                    $lang \
                    $media \
                    $style
            }
        }
        array unset styles
    }

    # Generate the head <script /> tag multirow
    variable ::template::head::scripts

    template::multirow create headscript type src charset defer async content order crossorigin integrity
    if {[array exists scripts]} {

        foreach name [array names scripts] {

            set container [::template::head::included_in $name]
            if {$container ne ""} {
                set container [template::head::resolve_urn $container]
                if {[array names scripts $container] ne ""} {
                    continue
                }
            }

            foreach {type src charset defer async content order crossorigin integrity} $scripts($name) {
                #ns_log notice "ADD order $order src $src"
                template::multirow append headscript \
                    $type \
                    [resolve_urn $src] \
                    $charset \
                    $defer \
                    $async \
                    $content \
                    $order \
                    $crossorigin $integrity
            }
        }
        template::multirow sort headscript order
        array unset scripts
    }
    template::prepare_body_script_multirow
}

ad_proc -private template::prepare_body_script_multirow {} {
    Generate multirows body_scripts.  Called from
    template::head::prepare_multirows and from steaming output
    handler.
} {
    # Generate the body <script /> tag multirow
    variable ::template::body_scripts
    template::multirow create body_script type src charset defer async content crossorigin integrity
    if {[info exists body_scripts]} {
        foreach {type src charset defer async content crossorigin integrity} $body_scripts {
            template::multirow append body_script \
                $type \
                $src \
                $charset \
                $defer \
                $async \
                $content \
                $crossorigin $integrity
        }
        unset body_scripts
    }
}

d_proc template::get_header_html {
} {
    Get headers as a chunk of html suitable for insertion into blank-master.adp
    Called only from blank-master.tcl
} {
    # Generate the body headers
    variable ::template::headers
    set header ""
    if {[info exists headers]} {
        foreach header_list $headers {
            lassign $header_list type src params
            if {$type eq "literal"} {
                append header $src
            } else {
                append header [template::adp_include $src $params]
            }
        }
        unset headers
    }
    return $header
}

d_proc template::get_footer_html {
} {
    Get footers as a chunk of html suitable for insertion into blank-master.adp
    Called only from blank-master.tcl
} {
    # Generate the body footers
    variable ::template::footers
    set footer ""

    if {[info exists footers]} {
        foreach footer_list $footers {
            lassign $footer_list type src params
            if {$type eq "literal"} {
                append footer $src
            } else {
                set themed_template [template::themed_template $src]
                append footer [template::adp_include $themed_template $params]
            }
        }
        unset footers
    }
    return $footer
}

ad_proc -private template::register_double_click_handler {} {
} {
    set default_timeout [parameter::get_from_package_key \
                             -package_key acs-templating \
                             -parameter DefaultPreventDoubleClickTimeoutMs \
                             -default 2000]
    if {$default_timeout == 0} {
        return
    }
    template::add_body_script -script [subst -nobackslashes -nocommands [ns_trim {
        function oacs_reenable_double_click_handler(target) {
            if ( target.dataset.oacsClicked == 'true') {
                target.dataset.oacsClicked = false;
                target.disabled = false;
                target.classList.remove("disabled");
                console.log("re-enable click handler");
            }
        };
        for (e of document.getElementsByClassName('prevent-double-click')) {
            if (!e.dataset.oacsDoubleClickHandlerRegistered) {
                e.addEventListener('click', function(event) {
                    let target = event.target || event.srcElement;
                    if ( target.dataset.oacsClicked == 'true') {
                        event.stopPropagation();
                        event.preventDefault();
                        console.log("blocked double-click");
                        return false;
                    } else {
                        target.dataset.oacsClicked = true;
                        target.classList.add("disabled");
                        let timeout = target.dataset.oacsTimeout || $default_timeout;
                        console.log('reactivate in ' + timeout);
                        setTimeout(function() {oacs_reenable_double_click_handler(target);}, timeout);
                        setTimeout(function() {target.disabled = true;});
                        return true;
                    }
                }, true);
                // In case the page has changed before the button was re-enabled
                // and the user uses the brower's back button, we have to establish
                // a clickable state.
                e.addEventListener('focus', function(event) {
                    oacs_reenable_double_click_handler(event.target || event.srcElement);
                });
                e.dataset.oacsDoubleClickHandlerRegistered = true;
            }
        };
    }]]
}

d_proc template::get_body_event_handlers {
} {

    Get body event handlers specified with template::add_body_handler.
    The proc clears the global variable ::template::body_handlers
    after having processed its content.

} {
    template::register_double_click_handler

    #
    # Concatenate the JavaScript event handlers for the body tag
    #
    variable ::template::body_handlers
    set event_handlers ""

    if {[array exists body_handlers]} {

        #
        # Collect all entries for one event type (e.g. "onload")
        #
        foreach name [array names body_handlers] {
            set event [lindex [split $name ","] 0]
            foreach js $body_handlers($name) {
                lappend body_handlers($event"[string trimright $js {; }];"
            }
            unset body_handlers($name)
        }

        #
        # Turn events into calls for event listener and add these via
        # add_body_script.
        #
        set js ""
        foreach {event script} [array get body_handlers] {
            #
            # Remove the "on" prefix if provided. E.g. "onload" is
            # mapped to the "load" event on "window" (UIevent). It
            # would as well be possible to map to DOM events (on
            # "document")
            # (https://developer.mozilla.org/en-US/docs/Web/Events)
            #
            regsub ^on $event "" event
            append js [ns_trim -delimiter | [subst {
                | window.addEventListener('$event', function () {
                |     [join $script { }]
                | }, false);
                |}]]
        }
        if {$js ne ""} {
            template::add_body_script -script $js
        }

        unset body_handlers
    }

    return $event_handlers
}

d_proc template::add_confirm_handler {
    {-event click}
    {-message "#acs-templating.Are_you_sure#"}
    {-CSSclass "acs-confirm"}
    {-id}
    {-selector}
    {-formfield}
} {
    Register an event handler for confirmation dialogs for elements
    either with a specified ID, CSS class, a formfield targeted by
    form id and field name or a CSS selector.

    @param event     register confirm handler for this type of event
    @param id        register confirm handler for this HTML ID
    @param CSSclass  register confirm handler for this CSS class
    @param formfield register confirm handler for this formfield, specified
                     in a list of two elements in the form
                     <code>{ form_id field_name }</code>
    @param selector register confirm handler for elements identified
                    by this CSS selector. When a CSS selector contains
                    double and single quotes, we won't add any of
                    those around the selector automatically. Instead,
                    the user must specify them explicitly, for instance
                    like this: ... -selector {'[name="o\'hara"]'}. If
                    the selector does not contain any single or double
                    quotes, we can let the user omit them, as for the
                    case of a simple tag name selector: ... -selector
                    "li". Quotes can also be omitted if the selector
                    contains only one kind of them, like ... -selector
                    {[data-property='value']} or ... -selector
                    {[data-property="value"]}
    @param message  Message to be displayed in the confirmation dialog.
                    If the message looks like a message key
                    (starting and ending with a hash sign)
                    it is treated as a message key
    @author  Gustaf Neumann
} {
    if {[regexp {^#(.*)*#$} $message . key]} {
        set message [_ $key]
    }
    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
    } elseif {[info exists selector]} {
        lappend cmd -selector $selector
    } else {
        lappend cmd -CSSclass $CSSclass
    }

    {*}$cmd
}

ad_proc template::add_refresh_on_history_handler {} {
    Register an event handler which will trigger a complete page
    refresh when we land on this page by accessing the browser's
    history (back and forward buttons).

    This is useful e.g. for those pages where some push interaction is
    happening and retrieving the page from the browser history would
    display it in an inconsistent state.
} {
    # courtesy of: vasleo@gmail.com from Stack Overflow
    template::add_body_script -script {
        window.addEventListener( "pageshow", function ( event ) {
            var historyTraversal = event.persisted ||
            ( typeof window.performance != "undefined" &&
              window.performance.navigation.type === 2 );
            if ( historyTraversal ) {
                window.location.reload();
            }
        });
    }
}

d_proc template::set_css_property {
    -class
    -querySelector
    -property:required
    -value:required
} {
    Set the specified CSS property in the DOM tree of the browser for
    elements for the specified class or query selector. This function
    should be used sparely in special situations, where CSS
    modification other approaches might be too complex.

    @param class CSS class for which properties is set
    @param querySelector CSS querySelector via the javascript function querySelectorAll
    @param property CSS property
    @param value value for the CSS property
} {
    if {[info exists class]} {
        set selector [subst {document.getElementsByClassName("$class")}]
    } elseif {[info exists querySelector]} {
        set selector [subst {document.querySelectorAll("$querySelector")}]
    } else {
        error "either 'class' or 'querySelector' must be specified"
    }
    template::add_script -section body -script [subst -nocommands {
        window.addEventListener('DOMContentLoaded', (event) => {
            var els = $selector;
            for(var i = 0; i < els.length; i++) { els[i].style.$property = "$value"; }
        });
    }]
}

d_proc template::add_event_listener {
    {-event click}
    {-CSSclass "acs-listen"}
    {-id}
    {-formfield}
    {-selector}
    {-usecapture:boolean false}
    {-preventdefault:boolean true}
    {-script:required}
} {
    Register an event handler for elements. The affected elements can
    be specified in different ways, which will be checked in the
    following order of precedence: id, formfield, selector and
    CSSclass. Normally one needs to provide only one kind of
    specification.

    @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
                     <code>{ form_id field_name }</code>
    @param selector register handler for elements identified by this
                    CSS selector. When a CSS selector contains double
                    and single quotes, we won't add any of those
                    around the selector automatically. Instead, the
                    user must specify them explicitly, for instance
                    like this: ... -selector {'[name="o\'hara"]'}. If
                    the selector does not contain any single or double
                    quotes, we can let the user omit them, as for the
                    case of a simple tag name selector: ... -selector
                    "li". Quotes can also be omitted if the selector
                    contains only one kind of them, like ... -selector
                    {[data-property='value']} or ... -selector
                    {[data-property="value"]}
    @param usecapture indicating whether event will be dispatched to the
                      registered listener before being dispatched to any
                      EventTarget beneath it in the DOM tree.
    @param preventdefault this option can the used prevent default click handling

    @author  Gustaf Neumann
} {
    set prevent [expr {$preventdefault_p ? "event.preventDefault();" : ""}]
    if {!$preventdefault_p && [regexp {^\s*([a-zA-Z0-9_]+)[\(]event[\)];\s*} $script . fn]} {
        #
        # In the most simple case, there is no need for a wrapper function.
        #
        set script [subst {e.addEventListener('$event', $fn$usecapture_p);}]
    } else {
        set script [ns_trim -delimiter | [subst {
           | e.addEventListener('$event', function (event) {$prevent$script}, $usecapture_p);
        }]]
    }
    if {[info exists id]} {
        set script [ns_trim -delimiter | [subst {
            | var e = document.getElementById('$id');
            | if (e !== null) {$script}
            |}]]
    } elseif {[info exists formfield]} {
        lassign $formfield id name
        set script [ns_trim -delimiter | [subst {
            | var e = document.getElementById('$id').elements.namedItem('$name');
            | if (e !== null) {$script}
            |}]]
    } elseif {[info exists selector]} {
        #
        # Find if either single or double quotes are absent from the
        # selector and we can use them around it safely.
        #
        foreach q {' \"} {
            if {[string first $q $selector] < 0} {
                set selector ${q}${selector}${q}
                break
            }
        }
        set script [ns_trim -delimiter | [subst {
            | for (e of document.querySelectorAll($selector)) {
            |   $script
            |}}]]
    } else {
        #
        # In case, no "id" is provided, use the "CSSclass"
        #
        set script [ns_trim -delimiter | [subst {
            | for (e of document.getElementsByClassName('$CSSclass')) {
            |   $script
            |}}]]
    }

    template::add_body_script -script $script
}

ad_proc template::collect_body_scripts {} {
    Collect the body scripts via an easy to call function, hiding the
    template used for the implementation.
} {
    return [template::adp_include /packages/acs-templating/lib/body_scripts {}]
}

# Local variables:
#    mode: tcl
#    tcl-indent-level: 4
#    indent-tabs-mode: nil
# End: