[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

/lib/scripts/ -> edit.js (source)

   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   * Called for each entry of toolbar definition array (built by inc/toolbar.php and extended via js)
  11   *
  12   * Style the buttons through the toolbutton class
  13   *
  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
  19   *
  20   * @author Andreas Gohr <andi@splitbrain.org>
  21   * @author Michal Rezler <m.rezler@centrum.cz>
  22   */
  23  function createToolButton(icon,label,key,id,classname){
  24      var $btn = jQuery(document.createElement('button')),
  25          $ico = jQuery(document.createElement('img'));
  26  
  27      // prepare the basic button stuff
  28      $btn.addClass('toolbutton');
  29      if(classname){
  30          $btn.addClass(classname);
  31      }
  32  
  33      $btn.attr('title', label).attr('aria-controls', 'wiki__text');
  34      if(key){
  35          $btn.attr('title', label + ' ['+key.toUpperCase()+']')
  36              .attr('accessKey', key);
  37      }
  38  
  39      // set IDs if given
  40      if(id){
  41          $btn.attr('id', id);
  42          $ico.attr('id', id+'_ico');
  43      }
  44  
  45      // create the icon and add it to the button
  46      if(icon.substr(0,1) !== '/'){
  47          icon = DOKU_BASE + 'lib/images/toolbar/' + icon;
  48      }
  49      $ico.attr('src', icon);
  50      $ico.attr('alt', '');
  51      $ico.attr('width', 16);
  52      $ico.attr('height', 16);
  53      $btn.append($ico);
  54  
  55      // we have to return a DOM object (for compatibility reasons)
  56      return $btn[0];
  57  }
  58  
  59  /**
  60   * Creates a picker window for inserting text
  61   *
  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.
  66   *
  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>
  72   */
  73  function createPicker(id,props,edid){
  74      // create the wrapping div
  75      var $picker = jQuery(document.createElement('div'));
  76  
  77      $picker.addClass('picker a11y');
  78      if(props['class']){
  79          $picker.addClass(props['class']);
  80      }
  81  
  82      $picker.attr('id', id).css('position', 'absolute');
  83  
  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))
  89              .appendTo($picker);
  90          return $btn;
  91      }
  92  
  93      jQuery.each(props.list, function (key, item) {
  94          if (!props.list.hasOwnProperty(key)) {
  95              return;
  96          }
  97  
  98          if(isNaN(key)){
  99              // associative array -> treat as text => image pairs
 100              if (item.substr(0,1) !== '/') {
 101                  item = DOKU_BASE+'lib/images/'+props.icobase+'/'+item;
 102              }
 103              jQuery(document.createElement('img'))
 104                  .attr('src', item)
 105                  .attr('alt', '')
 106                  .appendTo($makebutton(key));
 107          }else if (typeof item == 'string'){
 108              // a list of text -> treat as text picker
 109              $makebutton(item).text(item);
 110          }else{
 111              // a list of lists -> treat it as subtoolbar
 112              initToolbar($picker,edid,props.list);
 113              return false; // all buttons handled already
 114          }
 115  
 116      });
 117      jQuery('body').append($picker);
 118  
 119      // we have to return a DOM object (for compatibility reasons)
 120      return $picker[0];
 121  }
 122  
 123  /**
 124   * Called by picker buttons to insert Text and close the picker again
 125   *
 126   * @author Andreas Gohr <andi@splitbrain.org>
 127   */
 128  function pickerInsert(text,edid){
 129      insertAtCarret(edid,text);
 130      pickerClose();
 131  }
 132  
 133  /**
 134   * Add button action for signature button
 135   *
 136   * @param  {jQuery} $btn   Button element to add the action to
 137   * @param  {Array}  props  Associative array of button properties
 138   * @param  {string} edid   ID of the editor textarea
 139   * @return {string} picker id for aria-controls attribute
 140   * @author Gabriel Birke <birke@d-scribe.de>
 141   */
 142  function addBtnActionSignature($btn, props, edid) {
 143      if(typeof SIG != 'undefined' && SIG != ''){
 144          $btn.on('click', function (e) {
 145              insertAtCarret(edid,SIG);
 146              e.preventDefault();
 147          });
 148          return edid;
 149      }
 150      return '';
 151  }
 152  
 153  /**
 154   * Determine the current section level while editing
 155   *
 156   * @param {string} textboxId   ID of the text field
 157   *
 158   * @author Andreas Gohr <gohr@cosmocode.de>
 159   */
 160  function currentHeadlineLevel(textboxId){
 161      var field = jQuery('#' + textboxId)[0],
 162          s = false,
 163          opts = [field.value.substr(0,DWgetSelection(field).start)];
 164      if (field.form && field.form.prefix) {
 165          // we need to look in prefix context
 166          opts.push(field.form.prefix.value);
 167      }
 168  
 169      jQuery.each(opts, function (_, opt) {
 170          // Check whether there is a headline in the given string
 171          var str = "\n" + opt,
 172              lasthl = str.lastIndexOf("\n==");
 173          if (lasthl !== -1) {
 174              s = str.substr(lasthl+1,6);
 175              return false;
 176          }
 177      });
 178      if (s === false) {
 179          return 0;
 180      }
 181      return 7 - s.match(/^={2,6}/)[0].length;
 182  }
 183  
 184  
 185  /**
 186   * global var used for not saved yet warning
 187   */
 188  window.textChanged = false;
 189  
 190  /**
 191   * global var which stores original editor content
 192   */
 193  window.doku_edit_text_content = '';
 194  /**
 195   * Delete the draft before leaving the page
 196   */
 197  function deleteDraft() {
 198      if (is_opera || window.keepDraft) {
 199          return;
 200      }
 201  
 202      var $dwform = jQuery('#dw__editform');
 203  
 204      if($dwform.length === 0) {
 205          return;
 206      }
 207  
 208      // remove a possibly saved draft using ajax
 209      jQuery.post(DOKU_BASE + 'lib/exe/ajax.php',
 210          {
 211              call: 'draftdel',
 212              id: $dwform.find('input[name=id]').val()
 213          }
 214      );
 215  }
 216  
 217  /**
 218   * Activate "not saved" dialog, add draft deletion to page unload,
 219   * add handlers to monitor changes
 220   * Note: textChanged could be set by e.g. html_edit() as well
 221   *
 222   * Sets focus to the editbox as well
 223   */
 224  jQuery(function () {
 225      var $editform = jQuery('#dw__editform');
 226      if ($editform.length == 0) {
 227          return;
 228      }
 229  
 230      var $edit_text = jQuery('#wiki__text');
 231      if ($edit_text.length > 0) {
 232          if($edit_text.attr('readOnly')) {
 233              return;
 234          }
 235  
 236          // set focus and place cursor at the start
 237          var sel = DWgetSelection($edit_text[0]);
 238          sel.start = 0;
 239          sel.end   = 0;
 240          DWsetSelection(sel);
 241          $edit_text.focus();
 242  
 243          doku_edit_text_content = $edit_text.val();
 244      }
 245  
 246      var changeHandler = function() {
 247          doku_hasTextBeenModified();
 248  
 249          doku_summaryCheck();
 250      };
 251  
 252      $editform.change(changeHandler);
 253      $editform.keydown(changeHandler);
 254  
 255      window.onbeforeunload = function(){
 256          if(window.textChanged) {
 257              return LANG.notsavedyet;
 258          }
 259      };
 260      window.onunload = deleteDraft;
 261  
 262      // reset change memory var on submit
 263      jQuery('#edbtn__save').click(
 264          function() {
 265              window.onbeforeunload = '';
 266              textChanged = false;
 267          }
 268      );
 269      jQuery('#edbtn__preview').click(
 270          function() {
 271              window.onbeforeunload = '';
 272              textChanged = false;
 273              window.keepDraft = true; // needed to keep draft on page unload
 274          }
 275      );
 276  
 277      var $summary = jQuery('#edit__summary');
 278      $summary.change(doku_summaryCheck);
 279      $summary.keyup(doku_summaryCheck);
 280  
 281      if (textChanged) doku_summaryCheck();
 282  });
 283  
 284  /**
 285   * Updates textChanged variable if content of the editor has been modified
 286   */
 287  function doku_hasTextBeenModified() {
 288      if (!textChanged) {
 289          var $edit_text = jQuery('#wiki__text');
 290  
 291          if ($edit_text.length > 0) {
 292              textChanged = doku_edit_text_content != $edit_text.val();
 293          } else {
 294              textChanged = true;
 295          }
 296      }
 297  }
 298  
 299  /**
 300   * Checks if a summary was entered - if not the style is changed
 301   *
 302   * @author Andreas Gohr <andi@splitbrain.org>
 303   */
 304  function doku_summaryCheck(){
 305      var $sum = jQuery('#edit__summary'),
 306          missing = $sum.val() === '';
 307      $sum.toggleClass('missing', missing).toggleClass('edit', !missing);
 308  }