Language patch pt-br for login.txt
[dokuwiki.git] / lib / scripts / page.js
blobda7faa471a4e9bc77f7fa55f68855725133c4e84
1 /**
2  * Page behaviours
3  *
4  * This class adds various behaviours to the rendered page
5  */
6 dw_page = {
7     /**
8      * initialize page behaviours
9      */
10     init: function(){
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');
15     },
17     /**
18      * Highlight the section when hovering over the appropriate section edit button
19      *
20      * @author Andreas Gohr <andi@splitbrain.org>
21      */
22     sectionHighlight: function() {
23         jQuery('form.btn_secedit')
24             /*
25              * wrap the editable section in a div
26              */
27             .each(function () {
28                 let $tgt = jQuery(this).parent();
29                 const match = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/);
30                 if(!match) return;
31                 const nr = match[2];
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)) {
40                     $tgt = $tgt.prev();
41                     $highlight = $highlight.add($tgt);
42                 }
43                 // wrap the elements to be highlighted in the section highlight wrapper
44                 $highlight.wrapAll($highlightWrap);
45             })
46             /*
47              * highlight the section
48              */
49             .on('mouseover', function () {
50                 jQuery(this).parents('.section_highlight_wrapper').addClass('section_highlight');
51             })
52             /*
53              * remove highlight
54              */
55             .on('mouseout', function () {
56                 jQuery(this).parents('.section_highlight_wrapper').removeClass('section_highlight');
57             });
58     },
61     /**
62      * Highlight internal link pointing to current page
63      *
64      * @author Henry Pan <dokuwiki@phy25.com>
65      */
66     currentIDHighlight: function(){
67         jQuery('a.wikilink1, a.wikilink2').filter('[data-wiki-id="'+JSINFO.id+'"]').wrap('<span class="curid"></span>');
68     },
70     /**
71      * Create/get a insitu popup used by the footnotes
72      *
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
76      */
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'))
84                 .attr('id', popup_id)
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);
90         }
92         // position() does not support hidden elements
93         $fndiv.show().position({
94             my: 'left top',
95             at: 'left center',
96             of: target
97         }).hide();
99         return $fndiv;
100     },
102     /**
103      * Display an insitu footnote popup
104      *
105      * @author Andreas Gohr <andi@splitbrain.org>
106      * @author Chris Smith <chris@jalakai.co.uk>
107      * @author Anika Henke <anika@selfthinker.org>
108      */
109     footnoteDisplay: function () {
110         var $content = jQuery(jQuery(this).attr('href')) // Footnote text anchor
111                       .parent().siblings('.content').clone();
113         if (!$content.length) {
114             return;
115         }
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);
121         });
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');
127     },
129     /**
130      * Makes an element foldable by clicking its handle
131      *
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
134      * by CSS.
135      *
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.
140      *
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)
144      */
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){
157             if(hiding){
158                 $clicky.html('<span>+</span>');
159                 $handle.addClass('closed');
160                 $handle.removeClass('open');
161             }else{
162                 $clicky.html('<span>−</span>');
163                 $handle.addClass('open');
164                 $handle.removeClass('closed');
165             }
166         };
168         $handle[0].setState = function(state){
169             var hidden;
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?
179             if(state === -1) {
180                 hidden = false;
181             } else if(state === 1) {
182                 hidden = true;
183             } else {
184                 hidden = $child.is(':hidden');
185             }
187             // update the state
188             setClicky(!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
195             }, true);
196         };
198         // the state indicator
199         $clicky = jQuery(document.createElement('strong'));
201         // click function
202         $handle.css('cursor','pointer')
203                .on('click', $handle[0].setState)
204                .prepend($clicky);
206         // initial state
207         $handle[0].setState(state);
208     }
211 jQuery(dw_page.init);