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