[ 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                  .css('height', '16')
 107                  .appendTo($makebutton(key));
 108          }else if (typeof item == 'string'){
 109              // a list of text -> treat as text picker
 110              $makebutton(item).text(item);
 111          }else{
 112              // a list of lists -> treat it as subtoolbar
 113              initToolbar($picker,edid,props.list);
 114              return false; // all buttons handled already
 115          }
 116  
 117      });
 118      jQuery('body').append($picker);
 119  
 120      // we have to return a DOM object (for compatibility reasons)
 121      return $picker[0];
 122  }
 123  
 124  /**
 125   * Called by picker buttons to insert Text and close the picker again
 126   *
 127   * @author Andreas Gohr <andi@splitbrain.org>
 128   */
 129  function pickerInsert(text,edid){
 130      insertAtCarret(edid,text);
 131      pickerClose();
 132  }
 133  
 134  /**
 135   * Add button action for signature button
 136   *
 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>
 142   */
 143  function addBtnActionSignature($btn, props, edid) {
 144      if(typeof SIG != 'undefined' && SIG != ''){
 145          $btn.on('click', function (e) {
 146              insertAtCarret(edid,SIG);
 147              e.preventDefault();
 148          });
 149          return edid;
 150      }
 151      return '';
 152  }
 153  
 154  /**
 155   * Determine the current section level while editing
 156   *
 157   * @param {string} textboxId   ID of the text field
 158   *
 159   * @author Andreas Gohr <gohr@cosmocode.de>
 160   */
 161  function currentHeadlineLevel(textboxId){
 162      var field = jQuery('#' + textboxId)[0],
 163          s = false,
 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);
 168      }
 169  
 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==");
 174          if (lasthl !== -1) {
 175              s = str.substr(lasthl+1,6);
 176              return false;
 177          }
 178      });
 179      if (s === false) {
 180          return 0;
 181      }
 182      return 7 - s.match(/^={2,6}/)[0].length;
 183  }
 184  
 185  
 186  /**
 187   * global var used for not saved yet warning
 188   */
 189  window.textChanged = false;
 190  
 191  /**
 192   * global var which stores original editor content
 193   */
 194  window.doku_edit_text_content = '';
 195  /**
 196   * Delete the draft before leaving the page
 197   */
 198  function deleteDraft() {
 199      if (is_opera || window.keepDraft) {
 200          return;
 201      }
 202  
 203      var $dwform = jQuery('#dw__editform');
 204  
 205      if($dwform.length === 0) {
 206          return;
 207      }
 208  
 209      // remove a possibly saved draft using ajax
 210      jQuery.post(DOKU_BASE + 'lib/exe/ajax.php',
 211          {
 212              call: 'draftdel',
 213              id: $dwform.find('input[name=id]').val()
 214          }
 215      );
 216  }
 217  
 218  /**
 219   * Activate "not saved" dialog, add draft deletion to page unload,
 220   * add handlers to monitor changes
 221   * Note: textChanged could be set by e.g. html_edit() as well
 222   *
 223   * Sets focus to the editbox as well
 224   */
 225  jQuery(function () {
 226      var $editform = jQuery('#dw__editform');
 227      if ($editform.length == 0) {
 228          return;
 229      }
 230  
 231      var $edit_text = jQuery('#wiki__text');
 232      if ($edit_text.length > 0) {
 233          if($edit_text.attr('readOnly')) {
 234              return;
 235          }
 236  
 237          // set focus and place cursor at the start
 238          var sel = DWgetSelection($edit_text[0]);
 239          sel.start = 0;
 240          sel.end   = 0;
 241          DWsetSelection(sel);
 242          $edit_text.trigger('focus');
 243  
 244          doku_edit_text_content = $edit_text.val();
 245      }
 246  
 247      var changeHandler = function() {
 248          doku_hasTextBeenModified();
 249  
 250          doku_summaryCheck();
 251      };
 252  
 253      $editform.change(changeHandler);
 254      $editform.keydown(changeHandler);
 255  
 256      window.onbeforeunload = function(){
 257          if(window.textChanged) {
 258              return LANG.notsavedyet;
 259          }
 260      };
 261      window.onunload = deleteDraft;
 262  
 263      // reset change memory var on submit
 264      jQuery('#edbtn__save').on('click',
 265          function() {
 266              window.onbeforeunload = '';
 267              textChanged = false;
 268          }
 269      );
 270      jQuery('#edbtn__preview').on('click',
 271          function() {
 272              window.onbeforeunload = '';
 273              textChanged = false;
 274              window.keepDraft = true; // needed to keep draft on page unload
 275          }
 276      );
 277  
 278      var $summary = jQuery('#edit__summary');
 279      $summary.on('change 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  }