[ 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              sectok: $dwform.find('input[name=sectok]').val()
 215          }
 216      );
 217  }
 218  
 219  /**
 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
 223   *
 224   * Sets focus to the editbox as well
 225   */
 226  jQuery(function () {
 227      var $editform = jQuery('#dw__editform');
 228      if ($editform.length == 0) {
 229          return;
 230      }
 231  
 232      var $edit_text = jQuery('#wiki__text');
 233      if ($edit_text.length > 0) {
 234          if($edit_text.attr('readOnly')) {
 235              return;
 236          }
 237  
 238          // set focus and place cursor at the start
 239          var sel = DWgetSelection($edit_text[0]);
 240          sel.start = 0;
 241          sel.end   = 0;
 242          DWsetSelection(sel);
 243          $edit_text.trigger('focus');
 244  
 245          doku_edit_text_content = $edit_text.val();
 246      }
 247  
 248      var changeHandler = function() {
 249          doku_hasTextBeenModified();
 250  
 251          doku_summaryCheck();
 252      };
 253  
 254      $editform.change(changeHandler);
 255      $editform.keydown(changeHandler);
 256  
 257      window.onbeforeunload = function(){
 258          if(window.textChanged) {
 259              return LANG.notsavedyet;
 260          }
 261      };
 262      window.onunload = deleteDraft;
 263  
 264      // reset change memory var on submit
 265      jQuery('#edbtn__save').on('click',
 266          function() {
 267              window.onbeforeunload = '';
 268              textChanged = false;
 269          }
 270      );
 271      jQuery('#edbtn__preview').on('click',
 272          function() {
 273              window.onbeforeunload = '';
 274              textChanged = false;
 275              window.keepDraft = true; // needed to keep draft on page unload
 276          }
 277      );
 278  
 279      var $summary = jQuery('#edit__summary');
 280      $summary.on('change keyup', doku_summaryCheck);
 281  
 282      if (textChanged) doku_summaryCheck();
 283  });
 284  
 285  /**
 286   * Updates textChanged variable if content of the editor has been modified
 287   */
 288  function doku_hasTextBeenModified() {
 289      if (!textChanged) {
 290          var $edit_text = jQuery('#wiki__text');
 291  
 292          if ($edit_text.length > 0) {
 293              textChanged = doku_edit_text_content != $edit_text.val();
 294          } else {
 295              textChanged = true;
 296          }
 297      }
 298  }
 299  
 300  /**
 301   * Checks if a summary was entered - if not the style is changed
 302   *
 303   * @author Andreas Gohr <andi@splitbrain.org>
 304   */
 305  function doku_summaryCheck(){
 306      var $sum = jQuery('#edit__summary'),
 307          missing = $sum.val() === '';
 308      $sum.toggleClass('missing', missing).toggleClass('edit', !missing);
 309  }