[ Index ]

PHP Cross Reference of DokuWiki

title

Body

[close]

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

   1  /**
   2   * The Link Wizard
   3   *
   4   * @author Andreas Gohr <gohr@cosmocode.de>
   5   * @author Pierre Spring <pierre.spring@caillou.ch>
   6   */
   7  var dw_linkwiz = {
   8      $wiz: null,
   9      $entry: null,
  10      result: null,
  11      timer: null,
  12      textArea: null,
  13      selected: null,
  14      selection: null,
  15  
  16      /**
  17       * Initialize the dw_linkwizard by creating the needed HTML
  18       * and attaching the eventhandlers
  19       */
  20      init: function($editor){
  21          // position relative to the text area
  22          var pos = $editor.position();
  23  
  24          // create HTML Structure
  25          if(dw_linkwiz.$wiz)
  26              return;
  27          dw_linkwiz.$wiz = jQuery(document.createElement('div'))
  28                 .dialog({
  29                     autoOpen: false,
  30                     draggable: true,
  31                     title: LANG.linkwiz,
  32                     resizable: false
  33                 })
  34                 .html(
  35                      '<div>'+LANG.linkto+' <input type="text" class="edit" id="link__wiz_entry" autocomplete="off" /></div>'+
  36                      '<div id="link__wiz_result"></div>'
  37                      )
  38                 .parent()
  39                 .attr('id','link__wiz')
  40                 .css({
  41                      'position':    'absolute',
  42                      'top':         (pos.top+20)+'px',
  43                      'left':        (pos.left+80)+'px'
  44                     })
  45                 .hide()
  46                 .appendTo('.dokuwiki:first');
  47  
  48          dw_linkwiz.textArea = $editor[0];
  49          dw_linkwiz.result = jQuery('#link__wiz_result')[0];
  50  
  51          // scrollview correction on arrow up/down gets easier
  52          jQuery(dw_linkwiz.result).css('position', 'relative');
  53  
  54          dw_linkwiz.$entry = jQuery('#link__wiz_entry');
  55          if(JSINFO.namespace){
  56              dw_linkwiz.$entry.val(JSINFO.namespace+':');
  57          }
  58  
  59          // attach event handlers
  60          jQuery('#link__wiz .ui-dialog-titlebar-close').click(dw_linkwiz.hide);
  61          dw_linkwiz.$entry.keyup(dw_linkwiz.onEntry);
  62          jQuery(dw_linkwiz.result).on('click', 'a', dw_linkwiz.onResultClick);
  63      },
  64  
  65      /**
  66       * handle all keyup events in the entry field
  67       */
  68      onEntry: function(e){
  69          if(e.keyCode == 37 || e.keyCode == 39){ //left/right
  70              return true; //ignore
  71          }
  72          if(e.keyCode == 27){ //Escape
  73              dw_linkwiz.hide();
  74              e.preventDefault();
  75              e.stopPropagation();
  76              return false;
  77          }
  78          if(e.keyCode == 38){ //Up
  79              dw_linkwiz.select(dw_linkwiz.selected -1);
  80              e.preventDefault();
  81              e.stopPropagation();
  82              return false;
  83          }
  84          if(e.keyCode == 40){ //Down
  85              dw_linkwiz.select(dw_linkwiz.selected +1);
  86              e.preventDefault();
  87              e.stopPropagation();
  88              return false;
  89          }
  90          if(e.keyCode == 13){ //Enter
  91              if(dw_linkwiz.selected > -1){
  92                  var $obj = dw_linkwiz.$getResult(dw_linkwiz.selected);
  93                  if($obj.length > 0){
  94                      dw_linkwiz.resultClick($obj.find('a')[0]);
  95                  }
  96              }else if(dw_linkwiz.$entry.val()){
  97                  dw_linkwiz.insertLink(dw_linkwiz.$entry.val());
  98              }
  99  
 100              e.preventDefault();
 101              e.stopPropagation();
 102              return false;
 103          }
 104          dw_linkwiz.autocomplete();
 105      },
 106  
 107      /**
 108       * Get one of the results by index
 109       *
 110       * @param   num int result div to return
 111       * @returns DOMObject or null
 112       */
 113      getResult: function(num){
 114          DEPRECATED('use dw_linkwiz.$getResult()[0] instead');
 115          return dw_linkwiz.$getResult()[0] || null;
 116      },
 117  
 118      /**
 119       * Get one of the results by index
 120       *
 121       * @param   num int result div to return
 122       * @returns jQuery object
 123       */
 124      $getResult: function(num) {
 125          return jQuery(dw_linkwiz.result).find('div').eq(num);
 126      },
 127  
 128      /**
 129       * Select the given result
 130       */
 131      select: function(num){
 132          if(num < 0){
 133              dw_linkwiz.deselect();
 134              return;
 135          }
 136  
 137          var $obj = dw_linkwiz.$getResult(num);
 138          if ($obj.length === 0) {
 139              return;
 140          }
 141  
 142          dw_linkwiz.deselect();
 143          $obj.addClass('selected');
 144  
 145          // make sure the item is viewable in the scroll view
 146  
 147          //getting child position within the parent
 148          var childPos = $obj.position().top;
 149          //getting difference between the childs top and parents viewable area
 150          var yDiff = childPos + $obj.outerHeight() - jQuery(dw_linkwiz.result).innerHeight();
 151  
 152          if (childPos < 0) {
 153              //if childPos is above viewable area (that's why it goes negative)
 154              jQuery(dw_linkwiz.result)[0].scrollTop += childPos;
 155          } else if(yDiff > 0) {
 156              // if difference between childs top and parents viewable area is
 157              // greater than the height of a childDiv
 158              jQuery(dw_linkwiz.result)[0].scrollTop += yDiff;
 159          }
 160  
 161          dw_linkwiz.selected = num;
 162      },
 163  
 164      /**
 165       * deselect a result if any is selected
 166       */
 167      deselect: function(){
 168          if(dw_linkwiz.selected > -1){
 169              dw_linkwiz.$getResult(dw_linkwiz.selected).removeClass('selected');
 170          }
 171          dw_linkwiz.selected = -1;
 172      },
 173  
 174      /**
 175       * Handle clicks in the result set an dispatch them to
 176       * resultClick()
 177       */
 178      onResultClick: function(e){
 179          if(!jQuery(this).is('a')) {
 180              return;
 181          }
 182          e.stopPropagation();
 183          e.preventDefault();
 184          dw_linkwiz.resultClick(this);
 185          return false;
 186      },
 187  
 188      /**
 189       * Handles the "click" on a given result anchor
 190       */
 191      resultClick: function(a){
 192          dw_linkwiz.$entry.val(a.title);
 193          if(a.title == '' || a.title.substr(a.title.length-1) == ':'){
 194              dw_linkwiz.autocomplete_exec();
 195          }else{
 196              if (jQuery(a.nextSibling).is('span')) {
 197                  dw_linkwiz.insertLink(a.nextSibling.innerHTML);
 198              }else{
 199                  dw_linkwiz.insertLink('');
 200              }
 201          }
 202      },
 203  
 204      /**
 205       * Insert the id currently in the entry box to the textarea,
 206       * replacing the current selection or at the cursor position.
 207       * When no selection is available the given title will be used
 208       * as link title instead
 209       */
 210      insertLink: function(title){
 211          var link = dw_linkwiz.$entry.val(),
 212              sel, stxt;
 213          if(!link) {
 214              return;
 215          }
 216  
 217          sel = DWgetSelection(dw_linkwiz.textArea);
 218          if(sel.start == 0 && sel.end == 0) {
 219              sel = dw_linkwiz.selection;
 220          }
 221  
 222          stxt = sel.getText();
 223  
 224          // don't include trailing space in selection
 225          if(stxt.charAt(stxt.length - 1) == ' '){
 226              sel.end--;
 227              stxt = sel.getText();
 228          }
 229  
 230          if(!stxt && !DOKU_UHC) {
 231              stxt=title;
 232          }
 233  
 234          // prepend colon inside namespaces for non namespace pages
 235          if(dw_linkwiz.textArea.form.id.value.indexOf(':') != -1 &&
 236             link.indexOf(':') == -1){
 237             link = ':' + link;
 238          }
 239  
 240          var so = link.length;
 241          var eo = 0;
 242          if(dw_linkwiz.val){
 243              if(dw_linkwiz.val.open) {
 244                  so += dw_linkwiz.val.open.length;
 245                  link = dw_linkwiz.val.open+link;
 246              }
 247              link += '|';
 248              so += 1;
 249              if(stxt) {
 250                  link += stxt;
 251              }
 252              if(dw_linkwiz.val.close) {
 253                  link += dw_linkwiz.val.close;
 254                  eo = dw_linkwiz.val.close.length;
 255              }
 256          }
 257  
 258          pasteText(sel,link,{startofs: so, endofs: eo});
 259          dw_linkwiz.hide();
 260  
 261          // reset the entry to the parent namespace
 262          var externallinkpattern = new RegExp('^((f|ht)tps?:)?//', 'i'),
 263              entry_value;
 264          if (externallinkpattern.test(dw_linkwiz.$entry.val())) {
 265              if (JSINFO.namespace) {
 266                  entry_value = JSINFO.namespace + ':';
 267              } else {
 268                  entry_value = ''; //reset whole external links
 269              }
 270          } else {
 271              entry_value = dw_linkwiz.$entry.val().replace(/[^:]*$/, '')
 272          }
 273          dw_linkwiz.$entry.val(entry_value);
 274      },
 275  
 276      /**
 277       * Start the page/namespace lookup timer
 278       *
 279       * Calls autocomplete_exec when the timer runs out
 280       */
 281      autocomplete: function(){
 282          if(dw_linkwiz.timer !== null){
 283              window.clearTimeout(dw_linkwiz.timer);
 284              dw_linkwiz.timer = null;
 285          }
 286  
 287          dw_linkwiz.timer = window.setTimeout(dw_linkwiz.autocomplete_exec,350);
 288      },
 289  
 290      /**
 291       * Executes the AJAX call for the page/namespace lookup
 292       */
 293      autocomplete_exec: function(){
 294          var $res = jQuery(dw_linkwiz.result);
 295          dw_linkwiz.deselect();
 296          $res.html('<img src="'+DOKU_BASE+'lib/images/throbber.gif" alt="" width="16" height="16" />')
 297              .load(
 298              DOKU_BASE + 'lib/exe/ajax.php',
 299              {
 300                  call: 'linkwiz',
 301                  q: dw_linkwiz.$entry.val()
 302              }
 303          );
 304      },
 305  
 306      /**
 307       * Show the link wizard
 308       */
 309      show: function(){
 310          dw_linkwiz.selection  = DWgetSelection(dw_linkwiz.textArea);
 311          dw_linkwiz.$wiz.show();
 312          dw_linkwiz.$entry.focus();
 313          dw_linkwiz.autocomplete();
 314  
 315          // Move the cursor to the end of the input
 316          var temp = dw_linkwiz.$entry.val();
 317          dw_linkwiz.$entry.val('');
 318          dw_linkwiz.$entry.val(temp);
 319      },
 320  
 321      /**
 322       * Hide the link wizard
 323       */
 324      hide: function(){
 325          dw_linkwiz.$wiz.hide();
 326          dw_linkwiz.textArea.focus();
 327      },
 328  
 329      /**
 330       * Toggle the link wizard
 331       */
 332      toggle: function(){
 333          if(dw_linkwiz.$wiz.css('display') == 'none'){
 334              dw_linkwiz.show();
 335          }else{
 336              dw_linkwiz.hide();
 337          }
 338      }
 339  };