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