1/** 2 * Page behaviours 3 * 4 * This class adds various behaviours to the rendered page 5 */ 6dw_page = { 7 /** 8 * initialize page behaviours 9 */ 10 init: function(){ 11 dw_page.sectionHighlight(); 12 jQuery('a.fn_top').mouseover(dw_page.footnoteDisplay); 13 dw_page.makeToggle('#dw__toc h3','#dw__toc > div'); 14 }, 15 16 /** 17 * Highlight the section when hovering over the appropriate section edit button 18 * 19 * @author Andreas Gohr <andi@splitbrain.org> 20 */ 21 sectionHighlight: function() { 22 jQuery('form.btn_secedit') 23 .mouseover(function(){ 24 var $tgt = jQuery(this).parent(), 25 nr = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/)[2], 26 $highlight = jQuery(), // holder for elements in the section to be highlighted 27 $highlightWrap = jQuery('<div class="section_highlight"></div>'); // section highlight wrapper 28 29 // Walk the dom tree in reverse to find the sibling which is or contains the section edit marker 30 while($tgt.length > 0 && !($tgt.hasClass('sectionedit' + nr) || $tgt.find('.sectionedit' + nr).length)) { 31 $tgt = $tgt.prev(); 32 $highlight = $highlight.add($tgt); 33 } 34 // insert the section highlight wrapper before the last element added to $highlight 35 $highlight.filter(':last').before($highlightWrap); 36 // and move the elements to be highlighted inside the section highlight wrapper 37 $highlight.detach().appendTo($highlightWrap); 38 }) 39 .mouseout(function(){ 40 // find the section highlight wrapper... 41 var $highlightWrap = jQuery('.section_highlight'); 42 // ...move its children in front of it (as siblings)... 43 $highlightWrap.before($highlightWrap.children().detach()); 44 // ...and remove the section highlight wrapper 45 $highlightWrap.detach(); 46 }); 47 }, 48 49 /** 50 * Create/get a insitu popup used by the footnotes 51 * 52 * @param target - the DOM element at which the popup should be aligned at 53 * @param popup_id - the ID of the (new) DOM popup 54 * @return the Popup jQuery object 55 */ 56 insituPopup: function(target, popup_id) { 57 // get or create the popup div 58 var $fndiv = jQuery('#' + popup_id); 59 60 // popup doesn't exist, yet -> create it 61 if($fndiv.length === 0){ 62 $fndiv = jQuery(document.createElement('div')) 63 .attr('id', popup_id) 64 .addClass('insitu-footnote JSpopup') 65 .mouseleave(function () {jQuery(this).hide();}); 66 jQuery('.dokuwiki:first').append($fndiv); 67 } 68 69 // position() does not support hidden elements 70 $fndiv.show().position({ 71 my: 'left top', 72 at: 'left center', 73 of: target 74 }).hide(); 75 76 return $fndiv; 77 }, 78 79 /** 80 * Display an insitu footnote popup 81 * 82 * @author Andreas Gohr <andi@splitbrain.org> 83 * @author Chris Smith <chris@jalakai.co.uk> 84 */ 85 footnoteDisplay: function () { 86 var content = jQuery(jQuery(this).attr('href')) // Footnote text anchor 87 .closest('div.fn').html(); 88 89 if (content === null){ 90 return; 91 } 92 93 // strip the leading content anchors and their comma separators 94 content = content.replace(/((^|\s*,\s*)<sup>.*?<\/sup>)+\s*/gi, ''); 95 96 // prefix ids on any elements with "insitu__" to ensure they remain unique 97 content = content.replace(/\bid=(['"])([^"']+)\1/gi,'id="insitu__$2'); 98 99 // now put the content into the wrapper 100 dw_page.insituPopup(this, 'insitu__fn').html(content).show(); 101 }, 102 103 /** 104 * Makes an element foldable by clicking its handle 105 * 106 * This is used for the TOC toggling, but can be used for other elements 107 * as well. A state indicator is inserted into the handle and can be styled 108 * by CSS. 109 * 110 * @param selector handle What should be clicked to toggle 111 * @param selector content This element will be toggled 112 */ 113 makeToggle: function(handle, content, state){ 114 var $handle, $content, $clicky, $child, setClicky; 115 $handle = jQuery(handle); 116 if(!$handle.length) return; 117 $content = jQuery(content); 118 if(!$content.length) return; 119 120 // we animate the children 121 $child = $content.children(); 122 123 // class/display toggling 124 setClicky = function(hiding){ 125 if(hiding){ 126 $clicky.html('<span>+</span>'); 127 $handle.addClass('closed'); 128 $handle.removeClass('open'); 129 }else{ 130 $clicky.html('<span>−</span>'); 131 $handle.addClass('open'); 132 $handle.removeClass('closed'); 133 } 134 }; 135 136 $handle[0].setState = function(state){ 137 var hidden; 138 if(!state) state = 1; 139 140 // Assert that content instantly takes the whole space 141 $content.css('min-height', $content.height()).show(); 142 143 // stop any running animation 144 $child.stop(true, true); 145 146 // was a state given or do we toggle? 147 if(state === -1) { 148 hidden = false; 149 } else if(state === 1) { 150 hidden = true; 151 } else { 152 hidden = $child.is(':hidden'); 153 } 154 155 // update the state 156 setClicky(!hidden); 157 158 // Start animation and assure that $toc is hidden/visible 159 $child.dw_toggle(hidden, function () { 160 $content.toggle(hidden); 161 $content.css('min-height',''); // remove min-height again 162 }); 163 }; 164 165 // the state indicator 166 $clicky = jQuery(document.createElement('strong')); 167 168 // click function 169 $handle.css('cursor','pointer') 170 .click($handle[0].setState) 171 .prepend($clicky); 172 173 // initial state 174 $handle[0].setState(state); 175 } 176}; 177 178jQuery(dw_page.init); 179