1/** 2 * Functions for text editing (toolbar stuff) 3 * 4 * @todo most of the stuff in here should be revamped and then moved to toolbar.js 5 * @author Andreas Gohr <andi@splitbrain.org> 6 */ 7 8/** 9 * Creates a toolbar button through the DOM 10 * 11 * Style the buttons through the toolbutton class 12 * 13 * @author Andreas Gohr <andi@splitbrain.org> 14 * @author Michal Rezler <m.rezler@centrum.cz> 15 */ 16function createToolButton(icon,label,key,id,classname){ 17 var $btn = jQuery(document.createElement('button')), 18 $ico = jQuery(document.createElement('img')); 19 20 // prepare the basic button stuff 21 $btn.addClass('toolbutton'); 22 if(classname){ 23 $btn.addClass(classname); 24 } 25 26 $btn.attr('title', label); 27 if(key){ 28 $btn.attr('title', label + ' ['+key.toUpperCase()+']') 29 .attr('accessKey', key); 30 } 31 32 // set IDs if given 33 if(id){ 34 $btn.attr('id', id); 35 $ico.attr('id', id+'_ico'); 36 } 37 38 // create the icon and add it to the button 39 if(icon.substr(0,1) !== '/'){ 40 icon = DOKU_BASE + 'lib/images/toolbar/' + icon; 41 } 42 $ico.attr('src', icon); 43 $btn.append($ico); 44 45 // we have to return a DOM object (for compatibility reasons) 46 return $btn[0]; 47} 48 49/** 50 * Creates a picker window for inserting text 51 * 52 * The given list can be an associative array with text,icon pairs 53 * or a simple list of text. Style the picker window through the picker 54 * class or the picker buttons with the pickerbutton class. Picker 55 * windows are appended to the body and created invisible. 56 * 57 * @param string id the ID to assign to the picker 58 * @param array props the properties for the picker 59 * @param string edid the ID of the textarea 60 * @rteurn DOMobject the created picker 61 * @author Andreas Gohr <andi@splitbrain.org> 62 */ 63function createPicker(id,props,edid){ 64 // create the wrapping div 65 var $picker = jQuery(document.createElement('div')); 66 67 $picker.addClass('picker a11y'); 68 if(props['class']){ 69 $picker.addClass(props['class']); 70 } 71 72 $picker.attr('id', id).css('position', 'absolute'); 73 74 function $makebutton(title) { 75 var $btn = jQuery(document.createElement('button')) 76 .addClass('pickerbutton').attr('title', title) 77 .bind('click', bind(pickerInsert, title, edid)) 78 .appendTo($picker); 79 return $btn; 80 } 81 82 jQuery.each(props.list, function (key, item) { 83 if (!props.list.hasOwnProperty(key)) { 84 return; 85 } 86 87 if(isNaN(key)){ 88 // associative array -> treat as text => image pairs 89 if (item.substr(0,1) !== '/') { 90 item = DOKU_BASE+'lib/images/'+props.icobase+'/'+item; 91 } 92 jQuery(document.createElement('img')) 93 .attr('src', item) 94 .appendTo($makebutton(key)); 95 }else if (typeof item == 'string'){ 96 // a list of text -> treat as text picker 97 $makebutton(item).text(item); 98 }else{ 99 // a list of lists -> treat it as subtoolbar 100 initToolbar($picker,edid,props.list); 101 return false; // all buttons handled already 102 } 103 104 }); 105 jQuery('body').append($picker); 106 107 // we have to return a DOM object (for compatibility reasons) 108 return $picker[0]; 109} 110 111/** 112 * Called by picker buttons to insert Text and close the picker again 113 * 114 * @author Andreas Gohr <andi@splitbrain.org> 115 */ 116function pickerInsert(text,edid){ 117 insertAtCarret(edid,text); 118 pickerClose(); 119} 120 121/** 122 * Add button action for signature button 123 * 124 * @param DOMElement btn Button element to add the action to 125 * @param array props Associative array of button properties 126 * @param string edid ID of the editor textarea 127 * @return boolean If button should be appended 128 * @author Gabriel Birke <birke@d-scribe.de> 129 */ 130function addBtnActionSignature($btn, props, edid) { 131 if(typeof SIG != 'undefined' && SIG != ''){ 132 $btn.bind('click', bind(insertAtCarret,edid,SIG)); 133 return true; 134 } 135 return false; 136} 137 138/** 139 * Determine the current section level while editing 140 * 141 * @author Andreas Gohr <gohr@cosmocode.de> 142 */ 143function currentHeadlineLevel(textboxId){ 144 var field = jQuery('#' + textboxId)[0], 145 s = false, 146 opts = [field.value.substr(0,getSelection(field).start)]; 147 if (field.form.prefix) { 148 // we need to look in prefix context 149 opts.push(field.form.prefix.value); 150 } 151 152 jQuery.each(opts, function (_, opt) { 153 // Check whether there is a headline in the given string 154 var str = "\n" + opt, 155 lasthl = str.lastIndexOf("\n=="); 156 if (lasthl !== -1) { 157 s = str.substr(lasthl+1,6); 158 return false; 159 } 160 }); 161 if (s === false) { 162 return 0; 163 } 164 return 7 - s.match(/^={2,6}/)[0].length; 165} 166 167 168/** 169 * global var used for not saved yet warning 170 */ 171window.textChanged = false; 172 173/** 174 * Delete the draft before leaving the page 175 */ 176function deleteDraft() { 177 if (is_opera || window.keepDraft) { 178 return; 179 } 180 181 var $dwform = jQuery('#dw__editform'); 182 183 if($dwform.length === 0) { 184 return; 185 } 186 187 // remove a possibly saved draft using ajax 188 jQuery.post(DOKU_BASE + 'lib/exe/ajax.php', 189 { 190 call: 'draftdel', 191 id: $dwform.find('input[name=id]').val() 192 } 193 ); 194} 195 196/** 197 * Activate "not saved" dialog, add draft deletion to page unload, 198 * add handlers to monitor changes 199 * 200 * Sets focus to the editbox as well 201 */ 202jQuery(function () { 203 var $editform = jQuery('#dw__editform'); 204 if ($editform.length == 0) { 205 return; 206 } 207 208 var $edit_text = jQuery('#wiki__text'); 209 if ($edit_text.length > 0) { 210 if($edit_text.attr('readOnly')) { 211 return; 212 } 213 214 // set focus and place cursor at the start 215 var sel = getSelection($edit_text[0]); 216 sel.start = 0; 217 sel.end = 0; 218 setSelection(sel); 219 $edit_text.focus(); 220 } 221 222 var checkfunc = function() { 223 textChanged = true; //global var 224 summaryCheck(); 225 }; 226 227 $editform.change(checkfunc); 228 $editform.keydown(checkfunc); 229 230 window.onbeforeunload = function(){ 231 if(window.textChanged) { 232 return LANG.notsavedyet; 233 } 234 }; 235 window.onunload = deleteDraft; 236 237 // reset change memory var on submit 238 jQuery('#edbtn__save').click( 239 function() { 240 window.onbeforeunload = ''; 241 textChanged = false; 242 } 243 ); 244 jQuery('#edbtn__preview').click( 245 function() { 246 window.onbeforeunload = ''; 247 textChanged = false; 248 window.keepDraft = true; // needed to keep draft on page unload 249 } 250 ); 251 252 var $summary = jQuery('#edit__summary'); 253 $summary.change(summaryCheck); 254 $summary.keyup(summaryCheck); 255 256 if (textChanged) summaryCheck(); 257}); 258 259/** 260 * Checks if a summary was entered - if not the style is changed 261 * 262 * @author Andreas Gohr <andi@splitbrain.org> 263 */ 264function summaryCheck(){ 265 var $sum = jQuery('#edit__summary'), 266 missing = $sum.val() === ''; 267 $sum.toggleClass('missing', missing).toggleClass('edit', !missing); 268} 269