2 * Functions for text editing (toolbar stuff)
4 * @todo most of the stuff in here should be revamped and then moved to toolbar.js
5 * @author Andreas Gohr <andi@splitbrain.org>
9 * Creates a toolbar button through the DOM
10 * Called for each entry of toolbar definition array (built by inc/toolbar.php and extended via js)
12 * Style the buttons through the toolbutton class
14 * @param {string} icon image filename, relative to folder lib/images/toolbar/
15 * @param {string} label title of button, show on mouseover
16 * @param {string} key hint in title of button for access key
17 * @param {string} id id of button, and '<id>_ico' of icon
18 * @param {string} classname for styling buttons
20 * @author Andreas Gohr <andi@splitbrain.org>
21 * @author Michal Rezler <m.rezler@centrum.cz>
23 function createToolButton(icon,label,key,id,classname){
24 var $btn = jQuery(document.createElement('button')),
25 $ico = jQuery(document.createElement('img'));
27 // prepare the basic button stuff
28 $btn.addClass('toolbutton');
30 $btn.addClass(classname);
33 $btn.attr('title', label).attr('aria-controls', 'wiki__text');
35 $btn.attr('title', label + ' ['+key.toUpperCase()+']')
36 .attr('accessKey', key);
42 $ico.attr('id', id+'_ico');
45 // create the icon and add it to the button
46 if(icon.substr(0,1) !== '/'){
47 icon = DOKU_BASE + 'lib/images/toolbar/' + icon;
49 $ico.attr('src', icon);
51 $ico.attr('width', 16);
52 $ico.attr('height', 16);
55 // we have to return a DOM object (for compatibility reasons)
60 * Creates a picker window for inserting text
62 * The given list can be an associative array with text,icon pairs
63 * or a simple list of text. Style the picker window through the picker
64 * class or the picker buttons with the pickerbutton class. Picker
65 * windows are appended to the body and created invisible.
67 * @param {string} id the ID to assign to the picker
68 * @param {Array} props the properties for the picker
69 * @param {string} edid the ID of the textarea
70 * @return DOMobject the created picker
71 * @author Andreas Gohr <andi@splitbrain.org>
73 function createPicker(id,props,edid){
74 // create the wrapping div
75 var $picker = jQuery(document.createElement('div'));
77 $picker.addClass('picker a11y');
79 $picker.addClass(props['class']);
82 $picker.attr('id', id).css('position', 'absolute');
84 function $makebutton(title) {
85 var $btn = jQuery(document.createElement('button'))
86 .addClass('pickerbutton').attr('title', title)
87 .attr('aria-controls', edid)
88 .on('click', bind(pickerInsert, title, edid))
93 jQuery.each(props.list, function (key, item) {
94 if (!props.list.hasOwnProperty(key)) {
99 // associative array -> treat as text => image pairs
100 if (item.substr(0,1) !== '/') {
101 item = DOKU_BASE+'lib/images/'+props.icobase+'/'+item;
103 jQuery(document.createElement('img'))
107 .appendTo($makebutton(key));
108 }else if (typeof item == 'string'){
109 // a list of text -> treat as text picker
110 $makebutton(item).text(item);
112 // a list of lists -> treat it as subtoolbar
113 initToolbar($picker,edid,props.list);
114 return false; // all buttons handled already
118 jQuery('body').append($picker);
120 // we have to return a DOM object (for compatibility reasons)
125 * Called by picker buttons to insert Text and close the picker again
127 * @author Andreas Gohr <andi@splitbrain.org>
129 function pickerInsert(text,edid){
130 insertAtCarret(edid,text);
135 * Add button action for signature button
137 * @param {jQuery} $btn Button element to add the action to
138 * @param {Array} props Associative array of button properties
139 * @param {string} edid ID of the editor textarea
140 * @return {string} picker id for aria-controls attribute
141 * @author Gabriel Birke <birke@d-scribe.de>
143 function addBtnActionSignature($btn, props, edid) {
144 if(typeof SIG != 'undefined' && SIG != ''){
145 $btn.on('click', function (e) {
146 insertAtCarret(edid,SIG);
155 * Determine the current section level while editing
157 * @param {string} textboxId ID of the text field
159 * @author Andreas Gohr <gohr@cosmocode.de>
161 function currentHeadlineLevel(textboxId){
162 var field = jQuery('#' + textboxId)[0],
164 opts = [field.value.substr(0,DWgetSelection(field).start)];
165 if (field.form && field.form.prefix) {
166 // we need to look in prefix context
167 opts.push(field.form.prefix.value);
170 jQuery.each(opts, function (_, opt) {
171 // Check whether there is a headline in the given string
172 var str = "\n" + opt,
173 lasthl = str.lastIndexOf("\n==");
175 s = str.substr(lasthl+1,6);
182 return 7 - s.match(/^={2,6}/)[0].length;
187 * global var used for not saved yet warning
189 window.textChanged = false;
192 * global var which stores original editor content
194 window.doku_edit_text_content = '';
196 * Delete the draft before leaving the page
198 function deleteDraft() {
199 if (is_opera || window.keepDraft) {
203 var $dwform = jQuery('#dw__editform');
205 if($dwform.length === 0) {
209 // remove a possibly saved draft using ajax
210 jQuery.post(DOKU_BASE + 'lib/exe/ajax.php',
213 id: $dwform.find('input[name=id]').val(),
214 sectok: $dwform.find('input[name=sectok]').val()
220 * Activate "not saved" dialog, add draft deletion to page unload,
221 * add handlers to monitor changes
222 * Note: textChanged could be set by e.g. html_edit() as well
224 * Sets focus to the editbox as well
227 var $editform = jQuery('#dw__editform');
228 if ($editform.length == 0) {
232 var $edit_text = jQuery('#wiki__text');
233 if ($edit_text.length > 0) {
234 if($edit_text.attr('readOnly')) {
238 // set focus and place cursor at the start
239 var sel = DWgetSelection($edit_text[0]);
243 $edit_text.trigger('focus');
245 doku_edit_text_content = $edit_text.val();
248 var changeHandler = function() {
249 doku_hasTextBeenModified();
254 $editform.change(changeHandler);
255 $editform.keydown(changeHandler);
257 window.onbeforeunload = function(){
258 if(window.textChanged) {
259 return LANG.notsavedyet;
262 window.onunload = deleteDraft;
264 // reset change memory var on submit
265 jQuery('#edbtn__save').on('click',
267 window.onbeforeunload = '';
271 jQuery('#edbtn__preview').on('click',
273 window.onbeforeunload = '';
275 window.keepDraft = true; // needed to keep draft on page unload
279 var $summary = jQuery('#edit__summary');
280 $summary.on('change keyup', doku_summaryCheck);
282 if (textChanged) doku_summaryCheck();
286 * Updates textChanged variable if content of the editor has been modified
288 function doku_hasTextBeenModified() {
290 var $edit_text = jQuery('#wiki__text');
292 if ($edit_text.length > 0) {
293 textChanged = doku_edit_text_content != $edit_text.val();
301 * Checks if a summary was entered - if not the style is changed
303 * @author Andreas Gohr <andi@splitbrain.org>
305 function doku_summaryCheck(){
306 var $sum = jQuery('#edit__summary'),
307 missing = $sum.val() === '';
308 $sum.toggleClass('missing', missing).toggleClass('edit', !missing);