editor.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. * The DokuWiki editor features
  3. *
  4. * These are the advanced features of the editor. It does NOT contain any
  5. * code for the toolbar buttons and it functions. See toolbar.js for that.
  6. */
  7. var dw_editor = {
  8. /**
  9. * initialize the default editor functionality
  10. *
  11. * All other functions can also be called separately for non-default
  12. * textareas
  13. */
  14. init: function(){
  15. var $editor = jQuery('#wiki__text');
  16. if($editor.length === 0) {
  17. return;
  18. }
  19. dw_editor.initSizeCtl('#size__ctl',$editor);
  20. if($editor.attr('readOnly')) {
  21. return;
  22. }
  23. $editor.keydown(dw_editor.keyHandler);
  24. },
  25. /**
  26. * Add the edit window size and wrap controls
  27. *
  28. * Initial values are read from cookie if it exists
  29. *
  30. * @param selector ctlarea the div to place the controls
  31. * @param selector editor the textarea to control
  32. */
  33. initSizeCtl: function(ctlarea,editor){
  34. var $ctl = jQuery(ctlarea),
  35. $textarea = jQuery(editor);
  36. if($ctl.length === 0 || $textarea.length === 0) {
  37. return;
  38. }
  39. $textarea.css('height', DokuCookie.getValue('sizeCtl') || '300px');
  40. var wrp = DokuCookie.getValue('wrapCtl');
  41. if(wrp){
  42. dw_editor.setWrap($textarea[0], wrp);
  43. } // else use default value
  44. jQuery.each([
  45. ['larger', function(){dw_editor.sizeCtl(editor,100);}],
  46. ['smaller', function(){dw_editor.sizeCtl(editor,-100);}],
  47. ['wrap', function(){dw_editor.toggleWrap(editor);}]
  48. ], function (_, img) {
  49. jQuery(document.createElement('img'))
  50. .attr('src', DOKU_BASE+'lib/images/' + img[0] + '.gif')
  51. .attr('alt', '')
  52. .on('click', img[1])
  53. .appendTo($ctl);
  54. });
  55. },
  56. /**
  57. * This sets the vertical size of the editbox and adjusts the cookie
  58. *
  59. * @param selector editor the textarea to control
  60. * @param int val the relative value to resize in pixel
  61. */
  62. sizeCtl: function(editor,val){
  63. var $textarea = jQuery(editor),
  64. height = parseInt($textarea.css('height')) + val;
  65. $textarea.css('height', height+'px');
  66. DokuCookie.setValue('sizeCtl',$textarea.css('height'));
  67. },
  68. /**
  69. * Toggle the wrapping mode of the editor textarea and adjusts the
  70. * cookie
  71. *
  72. * @param selector editor the textarea to control
  73. */
  74. toggleWrap: function(editor){
  75. var $textarea = jQuery(editor),
  76. wrap = $textarea.attr('wrap');
  77. dw_editor.setWrap($textarea[0],
  78. (wrap && wrap.toLowerCase() == 'off') ? 'soft' : 'off');
  79. DokuCookie.setValue('wrapCtl',$textarea.attr('wrap'));
  80. },
  81. /**
  82. * Set the wrapping mode of a textarea
  83. *
  84. * @author Fluffy Convict <fluffyconvict@hotmail.com>
  85. * @author <shutdown@flashmail.com>
  86. * @link http://news.hping.org/comp.lang.javascript.archive/12265.html
  87. * @link https://bugzilla.mozilla.org/show_bug.cgi?id=41464
  88. * @param DomObject textarea
  89. * @param string wrapAttrValue
  90. */
  91. setWrap: function(textarea, wrapAttrValue){
  92. textarea.setAttribute('wrap', wrapAttrValue);
  93. // Fix display for mozilla
  94. var parNod = textarea.parentNode;
  95. var nxtSib = textarea.nextSibling;
  96. parNod.removeChild(textarea);
  97. parNod.insertBefore(textarea, nxtSib);
  98. },
  99. /**
  100. * Make intended formattings easier to handle
  101. *
  102. * Listens to all key inputs and handle indentions
  103. * of lists and code blocks
  104. *
  105. * Currently handles space, backspace, enter and
  106. * ctrl-enter presses
  107. *
  108. * @author Andreas Gohr <andi@splitbrain.org>
  109. * @fixme handle tabs
  110. * @param event e - the key press event object
  111. */
  112. keyHandler: function(e){
  113. if(jQuery.inArray(e.keyCode,[8, 10, 13, 32]) === -1) {
  114. return;
  115. }
  116. var selection = DWgetSelection(this);
  117. if(selection.getLength() > 0) {
  118. return; //there was text selected, keep standard behavior
  119. }
  120. var search = "\n"+this.value.substr(0,selection.start);
  121. var linestart = Math.max(search.lastIndexOf("\n"),
  122. search.lastIndexOf("\r")); //IE workaround
  123. search = search.substr(linestart);
  124. if((e.keyCode == 13 || e.keyCode == 10) && e.ctrlKey) { // Ctrl-Enter (With Chrome workaround)
  125. // Submit current edit
  126. jQuery('#edbtn__save').trigger('click');
  127. e.preventDefault(); // prevent enter key
  128. return false;
  129. }else if(e.keyCode == 13){ // Enter
  130. // keep current indention for lists and code
  131. var match = search.match(/(\n +([\*-] ?)?)/);
  132. if(match){
  133. var scroll = this.scrollHeight;
  134. var match2 = search.match(/^\n +[\*-]\s*$/);
  135. // Cancel list if the last item is empty (i. e. two times enter)
  136. if (match2 && this.value.substr(selection.start).match(/^($|\r?\n)/)) {
  137. this.value = this.value.substr(0, linestart) + "\n" +
  138. this.value.substr(selection.start);
  139. selection.start = linestart + 1;
  140. selection.end = linestart + 1;
  141. DWsetSelection(selection);
  142. } else {
  143. insertAtCarret(this.id,match[1]);
  144. }
  145. this.scrollTop += (this.scrollHeight - scroll);
  146. e.preventDefault(); // prevent enter key
  147. return false;
  148. }
  149. }else if(e.keyCode == 8){ // Backspace
  150. // unindent lists
  151. var match = search.match(/(\n +)([*-] ?)$/);
  152. if(match){
  153. var spaces = match[1].length-1;
  154. if(spaces > 3){ // unindent one level
  155. this.value = this.value.substr(0,linestart)+
  156. this.value.substr(linestart+2);
  157. selection.start = selection.start - 2;
  158. selection.end = selection.start;
  159. }else{ // delete list point
  160. this.value = this.value.substr(0,linestart)+
  161. this.value.substr(selection.start);
  162. selection.start = linestart;
  163. selection.end = linestart;
  164. }
  165. DWsetSelection(selection);
  166. e.preventDefault(); // prevent backspace
  167. return false;
  168. }
  169. }else if(e.keyCode == 32){ // Space
  170. // intend list item
  171. var match = search.match(/(\n +)([*-] )$/);
  172. if(match){
  173. this.value = this.value.substr(0,linestart)+' '+
  174. this.value.substr(linestart);
  175. selection.start = selection.start + 2;
  176. selection.end = selection.start;
  177. DWsetSelection(selection);
  178. e.preventDefault(); // prevent space
  179. return false;
  180. }
  181. }
  182. }
  183. };
  184. jQuery(dw_editor.init);