4 * This class adds various behaviours to the rendered page
8 * initialize page behaviours
11 dw_page.sectionHighlight();
12 dw_page.currentIDHighlight();
13 jQuery('a.fn_top').on('mouseover', dw_page.footnoteDisplay);
14 dw_page.makeToggle('#dw__toc h3','#dw__toc > div');
18 * Highlight the section when hovering over the appropriate section edit button
20 * @author Andreas Gohr <andi@splitbrain.org>
22 sectionHighlight: function() {
23 jQuery('form.btn_secedit')
25 * wrap the editable section in a div
28 let $tgt = jQuery(this).parent();
29 const match = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/);
32 let $highlight = jQuery(); // holder for elements in the section to be highlighted
33 const $highlightWrap = jQuery('<div class="section_highlight_wrapper"></div>');
35 // the edit button should be part of the highlight
36 $highlight = $highlight.add($tgt);
38 // Walk the dom tree in reverse to find the sibling which is or contains the section edit marker
39 while ($tgt.length > 0 && !($tgt.hasClass('sectionedit' + nr) || $tgt.find('.sectionedit' + nr).length)) {
41 $highlight = $highlight.add($tgt);
43 // wrap the elements to be highlighted in the section highlight wrapper
44 $highlight.wrapAll($highlightWrap);
47 * highlight the section
49 .on('mouseover', function () {
50 jQuery(this).parents('.section_highlight_wrapper').addClass('section_highlight');
55 .on('mouseout', function () {
56 jQuery(this).parents('.section_highlight_wrapper').removeClass('section_highlight');
62 * Highlight internal link pointing to current page
64 * @author Henry Pan <dokuwiki@phy25.com>
66 currentIDHighlight: function(){
67 jQuery('a.wikilink1, a.wikilink2').filter('[data-wiki-id="'+JSINFO.id+'"]').wrap('<span class="curid"></span>');
71 * Create/get a insitu popup used by the footnotes
73 * @param target - the DOM element at which the popup should be aligned at
74 * @param popup_id - the ID of the (new) DOM popup
75 * @return the Popup jQuery object
77 insituPopup: function(target, popup_id) {
78 // get or create the popup div
79 var $fndiv = jQuery('#' + popup_id);
81 // popup doesn't exist, yet -> create it
82 if($fndiv.length === 0){
83 $fndiv = jQuery(document.createElement('div'))
85 .addClass('insitu-footnote JSpopup')
86 .attr('aria-hidden', 'true')
87 .on('mouseleave', function () {jQuery(this).hide().attr('aria-hidden', 'true');})
88 .attr('role', 'tooltip');
89 jQuery('.dokuwiki:first').append($fndiv);
92 // position() does not support hidden elements
93 $fndiv.show().position({
103 * Display an insitu footnote popup
105 * @author Andreas Gohr <andi@splitbrain.org>
106 * @author Chris Smith <chris@jalakai.co.uk>
107 * @author Anika Henke <anika@selfthinker.org>
109 footnoteDisplay: function () {
110 var $content = jQuery(jQuery(this).attr('href')) // Footnote text anchor
111 .parent().siblings('.content').clone();
113 if (!$content.length) {
117 // prefix ids on any elements with "insitu__" to ensure they remain unique
118 jQuery('[id]', $content).each(function(){
119 var id = jQuery(this).attr('id');
120 jQuery(this).attr('id', 'insitu__' + id);
123 var content = $content.html().trim();
124 // now put the content into the wrapper
125 dw_page.insituPopup(this, 'insitu__fn').html(content)
126 .show().attr('aria-hidden', 'false');
130 * Makes an element foldable by clicking its handle
132 * This is used for the TOC toggling, but can be used for other elements
133 * as well. A state indicator is inserted into the handle and can be styled
136 * To properly reserve space for the expanded element, the sliding animation is
137 * done on the children of the content. To make that look good and to make sure aria
138 * attributes are assigned correctly, it's recommended to make sure that the content
139 * element contains a single child element only.
141 * @param {selector} handle What should be clicked to toggle
142 * @param {selector} content This element will be toggled
143 * @param {int} state initial state (-1 = open, 1 = closed)
145 makeToggle: function(handle, content, state){
146 var $handle, $content, $clicky, $child, setClicky;
147 $handle = jQuery(handle);
148 if(!$handle.length) return;
149 $content = jQuery(content);
150 if(!$content.length) return;
152 // we animate the children
153 $child = $content.children();
155 // class/display toggling
156 setClicky = function(hiding){
158 $clicky.html('<span>+</span>');
159 $handle.addClass('closed');
160 $handle.removeClass('open');
162 $clicky.html('<span>−</span>');
163 $handle.addClass('open');
164 $handle.removeClass('closed');
168 $handle[0].setState = function(state){
170 if(!state) state = 1;
172 // Assert that content instantly takes the whole space
173 $content.css('min-height', $content.height()).show();
175 // stop any running animation
176 $child.stop(true, true);
178 // was a state given or do we toggle?
181 } else if(state === 1) {
184 hidden = $child.is(':hidden');
190 // Start animation and assure that $toc is hidden/visible
191 $child.dw_toggle(hidden, function () {
192 $content.toggle(hidden);
193 $content.attr('aria-expanded', hidden);
194 $content.css('min-height',''); // remove min-height again
198 // the state indicator
199 $clicky = jQuery(document.createElement('strong'));
202 $handle.css('cursor','pointer')
203 .on('click', $handle[0].setState)
207 $handle[0].setState(state);
211 jQuery(dw_page.init);