[ XREF Home ] [ Index ]

PHP Cross Reference of WordPress Trunk

Provided by Yoast

title

Body

[close]

/wp-includes/js/tinymce/plugins/wplink/js/ -> wplink.dev.js (source)

   1  var wpLink;
   2  
   3  (function($){
   4      var inputs = {}, rivers = {}, ed, River, Query;
   5  
   6      wpLink = {
   7          timeToTriggerRiver: 150,
   8          minRiverAJAXDuration: 200,
   9          riverBottomThreshold: 5,
  10          keySensitivity: 100,
  11          lastSearch: '',
  12          textarea: function() { return edCanvas; },
  13  
  14          init : function() {
  15              inputs.dialog = $('#wp-link');
  16              inputs.submit = $('#wp-link-submit');
  17              // URL
  18              inputs.url = $('#url-field');
  19              // Secondary options
  20              inputs.title = $('#link-title-field');
  21              // Advanced Options
  22              inputs.openInNewTab = $('#link-target-checkbox');
  23              inputs.search = $('#search-field');
  24              // Build Rivers
  25              rivers.search = new River( $('#search-results') );
  26              rivers.recent = new River( $('#most-recent-results') );
  27              rivers.elements = $('.query-results', inputs.dialog);
  28  
  29              // Bind event handlers
  30              inputs.dialog.keydown( wpLink.keydown );
  31              inputs.dialog.keyup( wpLink.keyup );
  32              inputs.submit.click( function(e){
  33                  wpLink.update();
  34                  e.preventDefault();
  35              });
  36              $('#wp-link-cancel').click( wpLink.close );
  37              $('#internal-toggle').click( wpLink.toggleInternalLinking );
  38  
  39              rivers.elements.bind('river-select', wpLink.updateFields );
  40  
  41              inputs.search.keyup( wpLink.searchInternalLinks );
  42  
  43              inputs.dialog.bind('wpdialogrefresh', wpLink.refresh);
  44              inputs.dialog.bind('wpdialogbeforeopen', wpLink.beforeOpen);
  45              inputs.dialog.bind('wpdialogclose', wpLink.onClose);
  46          },
  47  
  48          beforeOpen : function() {
  49              wpLink.range = null;
  50  
  51              if ( ! wpLink.isMCE() && document.selection ) {
  52                  wpLink.textarea().focus();
  53                  wpLink.range = document.selection.createRange();
  54              }
  55          },
  56  
  57          open : function() {
  58              // Initialize the dialog if necessary (html mode).
  59              if ( ! inputs.dialog.data('wpdialog') ) {
  60                  inputs.dialog.wpdialog({
  61                      title: wpLinkL10n.title,
  62                      width: 480,
  63                      height: 'auto',
  64                      modal: true,
  65                      dialogClass: 'wp-dialog',
  66                      zIndex: 300000
  67                  });
  68              }
  69  
  70              inputs.dialog.wpdialog('open');
  71          },
  72  
  73          isMCE : function() {
  74              return tinyMCEPopup && ( ed = tinyMCEPopup.editor ) && ! ed.isHidden();
  75          },
  76  
  77          refresh : function() {
  78              // Refresh rivers (clear links, check visibility)
  79              rivers.search.refresh();
  80              rivers.recent.refresh();
  81  
  82              if ( wpLink.isMCE() )
  83                  wpLink.mceRefresh();
  84              else
  85                  wpLink.setDefaultValues();
  86  
  87              // Focus the URL field and highlight its contents.
  88              //     If this is moved above the selection changes,
  89              //     IE will show a flashing cursor over the dialog.
  90              inputs.url.focus()[0].select();
  91              // Load the most recent results if this is the first time opening the panel.
  92              if ( ! rivers.recent.ul.children().length )
  93                  rivers.recent.ajax();
  94          },
  95  
  96          mceRefresh : function() {
  97              var e;
  98              ed = tinyMCEPopup.editor;
  99  
 100              tinyMCEPopup.restoreSelection();
 101  
 102              // If link exists, select proper values.
 103              if ( e = ed.dom.getParent(ed.selection.getNode(), 'A') ) {
 104                  // Set URL and description.
 105                  inputs.url.val( e.href );
 106                  inputs.title.val( ed.dom.getAttrib(e, 'title') );
 107                  // Set open in new tab.
 108                  if ( "_blank" == ed.dom.getAttrib(e, 'target') )
 109                      inputs.openInNewTab.prop('checked', true);
 110                  // Update save prompt.
 111                  inputs.submit.val( wpLinkL10n.update );
 112  
 113              // If there's no link, set the default values.
 114              } else {
 115                  wpLink.setDefaultValues();
 116              }
 117  
 118              tinyMCEPopup.storeSelection();
 119          },
 120  
 121          close : function() {
 122              if ( wpLink.isMCE() )
 123                  tinyMCEPopup.close();
 124              else
 125                  inputs.dialog.wpdialog('close');
 126          },
 127  
 128          onClose: function() {
 129              if ( ! wpLink.isMCE() ) {
 130                  wpLink.textarea().focus();
 131                  if ( wpLink.range ) {
 132                      wpLink.range.moveToBookmark( wpLink.range.getBookmark() );
 133                      wpLink.range.select();
 134                  }
 135              }
 136          },
 137  
 138          getAttrs : function() {
 139              return {
 140                  href : inputs.url.val(),
 141                  title : inputs.title.val(),
 142                  target : inputs.openInNewTab.prop('checked') ? '_blank' : ''
 143              };
 144          },
 145  
 146          update : function() {
 147              if ( wpLink.isMCE() )
 148                  wpLink.mceUpdate();
 149              else
 150                  wpLink.htmlUpdate();
 151          },
 152  
 153          htmlUpdate : function() {
 154              var attrs, html, start, end, cursor,
 155                  textarea = wpLink.textarea();
 156  
 157              if ( ! textarea )
 158                  return;
 159  
 160              attrs = wpLink.getAttrs();
 161  
 162              // If there's no href, return.
 163              if ( ! attrs.href || attrs.href == 'http://' )
 164                  return;
 165  
 166              // Build HTML
 167              html = '<a href="' + attrs.href + '"';
 168  
 169              if ( attrs.title )
 170                  html += ' title="' + attrs.title + '"';
 171              if ( attrs.target )
 172                  html += ' target="' + attrs.target + '"';
 173  
 174              html += '>';
 175  
 176              // Insert HTML
 177              // W3C
 178              if ( typeof textarea.selectionStart !== 'undefined' ) {
 179                  start       = textarea.selectionStart;
 180                  end         = textarea.selectionEnd;
 181                  selection   = textarea.value.substring( start, end );
 182                  html        = html + selection + '</a>';
 183                  cursor      = start + html.length;
 184  
 185                  // If no next is selected, place the cursor inside the closing tag.
 186                  if ( start == end )
 187                      cursor -= '</a>'.length;
 188  
 189                  textarea.value = textarea.value.substring( 0, start )
 190                                 + html
 191                                 + textarea.value.substring( end, textarea.value.length );
 192  
 193                  // Update cursor position
 194                  textarea.selectionStart = textarea.selectionEnd = cursor;
 195  
 196              // IE
 197              // Note: If no text is selected, IE will not place the cursor
 198              //       inside the closing tag.
 199              } else if ( document.selection && wpLink.range ) {
 200                  textarea.focus();
 201                  wpLink.range.text = html + wpLink.range.text + '</a>';
 202                  wpLink.range.moveToBookmark( wpLink.range.getBookmark() );
 203                  wpLink.range.select();
 204  
 205                  wpLink.range = null;
 206              }
 207  
 208              wpLink.close();
 209              textarea.focus();
 210          },
 211  
 212          mceUpdate : function() {
 213              var ed = tinyMCEPopup.editor,
 214                  attrs = wpLink.getAttrs(),
 215                  e, b;
 216  
 217              tinyMCEPopup.restoreSelection();
 218              e = ed.dom.getParent(ed.selection.getNode(), 'A');
 219  
 220              // If the values are empty, unlink and return
 221              if ( ! attrs.href || attrs.href == 'http://' ) {
 222                  if ( e ) {
 223                      tinyMCEPopup.execCommand("mceBeginUndoLevel");
 224                      b = ed.selection.getBookmark();
 225                      ed.dom.remove(e, 1);
 226                      ed.selection.moveToBookmark(b);
 227                      tinyMCEPopup.execCommand("mceEndUndoLevel");
 228                      wpLink.close();
 229                  }
 230                  return;
 231              }
 232  
 233              tinyMCEPopup.execCommand("mceBeginUndoLevel");
 234  
 235              if (e == null) {
 236                  ed.getDoc().execCommand("unlink", false, null);
 237                  tinyMCEPopup.execCommand("CreateLink", false, "#mce_temp_url#", {skip_undo : 1});
 238  
 239                  tinymce.each(ed.dom.select("a"), function(n) {
 240                      if (ed.dom.getAttrib(n, 'href') == '#mce_temp_url#') {
 241                          e = n;
 242                          ed.dom.setAttribs(e, attrs);
 243                      }
 244                  });
 245  
 246                  // Sometimes WebKit lets a user create a link where
 247                  // they shouldn't be able to. In this case, CreateLink
 248                  // injects "#mce_temp_url#" into their content. Fix it.
 249                  if ( $(e).text() == '#mce_temp_url#' ) {
 250                      ed.dom.remove(e);
 251                      e = null;
 252                  }
 253              } else {
 254                  ed.dom.setAttribs(e, attrs);
 255              }
 256  
 257              // Don't move caret if selection was image
 258              if ( e && (e.childNodes.length != 1 || e.firstChild.nodeName != 'IMG') ) {
 259                  ed.focus();
 260                  ed.selection.select(e);
 261                  ed.selection.collapse(0);
 262                  tinyMCEPopup.storeSelection();
 263              }
 264  
 265              tinyMCEPopup.execCommand("mceEndUndoLevel");
 266              wpLink.close();
 267          },
 268  
 269          updateFields : function( e, li, originalEvent ) {
 270              inputs.url.val( li.children('.item-permalink').val() );
 271              inputs.title.val( li.hasClass('no-title') ? '' : li.children('.item-title').text() );
 272              if ( originalEvent && originalEvent.type == "click" )
 273                  inputs.url.focus();
 274          },
 275          setDefaultValues : function() {
 276              // Set URL and description to defaults.
 277              // Leave the new tab setting as-is.
 278              inputs.url.val('http://');
 279              inputs.title.val('');
 280  
 281              // Update save prompt.
 282              inputs.submit.val( wpLinkL10n.save );
 283          },
 284  
 285          searchInternalLinks : function() {
 286              var t = $(this), waiting,
 287                  search = t.val();
 288  
 289              if ( search.length > 2 ) {
 290                  rivers.recent.hide();
 291                  rivers.search.show();
 292  
 293                  // Don't search if the keypress didn't change the title.
 294                  if ( wpLink.lastSearch == search )
 295                      return;
 296  
 297                  wpLink.lastSearch = search;
 298                  waiting = t.siblings('img.waiting').show();
 299  
 300                  rivers.search.change( search );
 301                  rivers.search.ajax( function(){ waiting.hide(); });
 302              } else {
 303                  rivers.search.hide();
 304                  rivers.recent.show();
 305              }
 306          },
 307  
 308          next : function() {
 309              rivers.search.next();
 310              rivers.recent.next();
 311          },
 312          prev : function() {
 313              rivers.search.prev();
 314              rivers.recent.prev();
 315          },
 316  
 317          keydown : function( event ) {
 318              var fn, key = $.ui.keyCode;
 319  
 320              switch( event.which ) {
 321                  case key.UP:
 322                      fn = 'prev';
 323                  case key.DOWN:
 324                      fn = fn || 'next';
 325                      clearInterval( wpLink.keyInterval );
 326                      wpLink[ fn ]();
 327                      wpLink.keyInterval = setInterval( wpLink[ fn ], wpLink.keySensitivity );
 328                      break;
 329                  default:
 330                      return;
 331              }
 332              event.preventDefault();
 333          },
 334          keyup: function( event ) {
 335              var key = $.ui.keyCode;
 336  
 337              switch( event.which ) {
 338                  case key.ESCAPE:
 339                      event.stopImmediatePropagation();
 340                      if ( ! $(document).triggerHandler( 'wp_CloseOnEscape', [{ event: event, what: 'wplink', cb: wpLink.close }] ) )
 341                          wpLink.close();
 342  
 343                      return false;
 344                      break;
 345                  case key.UP:
 346                  case key.DOWN:
 347                      clearInterval( wpLink.keyInterval );
 348                      break;
 349                  default:
 350                      return;
 351              }
 352              event.preventDefault();
 353          },
 354  
 355          delayedCallback : function( func, delay ) {
 356              var timeoutTriggered, funcTriggered, funcArgs, funcContext;
 357  
 358              if ( ! delay )
 359                  return func;
 360  
 361              setTimeout( function() {
 362                  if ( funcTriggered )
 363                      return func.apply( funcContext, funcArgs );
 364                  // Otherwise, wait.
 365                  timeoutTriggered = true;
 366              }, delay);
 367  
 368              return function() {
 369                  if ( timeoutTriggered )
 370                      return func.apply( this, arguments );
 371                  // Otherwise, wait.
 372                  funcArgs = arguments;
 373                  funcContext = this;
 374                  funcTriggered = true;
 375              };
 376          },
 377  
 378          toggleInternalLinking : function( event ) {
 379              var panel = $('#search-panel'),
 380                  widget = inputs.dialog.wpdialog('widget'),
 381                  // We're about to toggle visibility; it's currently the opposite
 382                  visible = !panel.is(':visible'),
 383                  win = $(window);
 384  
 385              $(this).toggleClass('toggle-arrow-active', visible);
 386  
 387              inputs.dialog.height('auto');
 388              panel.slideToggle( 300, function() {
 389                  setUserSetting('wplink', visible ? '1' : '0');
 390                  inputs[ visible ? 'search' : 'url' ].focus();
 391  
 392                  // Move the box if the box is now expanded, was opened in a collapsed state,
 393                  // and if it needs to be moved. (Judged by bottom not being positive or
 394                  // bottom being smaller than top.)
 395                  var scroll = win.scrollTop(),
 396                      top = widget.offset().top,
 397                      bottom = top + widget.outerHeight(),
 398                      diff = bottom - win.height();
 399  
 400                  if ( diff > scroll ) {
 401                      widget.animate({'top': diff < top ?  top - diff : scroll }, 200);
 402                  }
 403              });
 404              event.preventDefault();
 405          }
 406      }
 407  
 408      River = function( element, search ) {
 409          var self = this;
 410          this.element = element;
 411          this.ul = element.children('ul');
 412          this.waiting = element.find('.river-waiting');
 413  
 414          this.change( search );
 415          this.refresh();
 416  
 417          element.scroll( function(){ self.maybeLoad(); });
 418          element.delegate('li', 'click', function(e){ self.select( $(this), e ); });
 419      };
 420  
 421      $.extend( River.prototype, {
 422          refresh: function() {
 423              this.deselect();
 424              this.visible = this.element.is(':visible');
 425          },
 426          show: function() {
 427              if ( ! this.visible ) {
 428                  this.deselect();
 429                  this.element.show();
 430                  this.visible = true;
 431              }
 432          },
 433          hide: function() {
 434              this.element.hide();
 435              this.visible = false;
 436          },
 437          // Selects a list item and triggers the river-select event.
 438          select: function( li, event ) {
 439              var liHeight, elHeight, liTop, elTop;
 440  
 441              if ( li.hasClass('unselectable') || li == this.selected )
 442                  return;
 443  
 444              this.deselect();
 445              this.selected = li.addClass('selected');
 446              // Make sure the element is visible
 447              liHeight = li.outerHeight();
 448              elHeight = this.element.height();
 449              liTop = li.position().top;
 450              elTop = this.element.scrollTop();
 451  
 452              if ( liTop < 0 ) // Make first visible element
 453                  this.element.scrollTop( elTop + liTop );
 454              else if ( liTop + liHeight > elHeight ) // Make last visible element
 455                  this.element.scrollTop( elTop + liTop - elHeight + liHeight );
 456  
 457              // Trigger the river-select event
 458              this.element.trigger('river-select', [ li, event, this ]);
 459          },
 460          deselect: function() {
 461              if ( this.selected )
 462                  this.selected.removeClass('selected');
 463              this.selected = false;
 464          },
 465          prev: function() {
 466              if ( ! this.visible )
 467                  return;
 468  
 469              var to;
 470              if ( this.selected ) {
 471                  to = this.selected.prev('li');
 472                  if ( to.length )
 473                      this.select( to );
 474              }
 475          },
 476          next: function() {
 477              if ( ! this.visible )
 478                  return;
 479  
 480              var to = this.selected ? this.selected.next('li') : $('li:not(.unselectable):first', this.element);
 481              if ( to.length )
 482                  this.select( to );
 483          },
 484          ajax: function( callback ) {
 485              var self = this,
 486                  delay = this.query.page == 1 ? 0 : wpLink.minRiverAJAXDuration,
 487                  response = wpLink.delayedCallback( function( results, params ) {
 488                      self.process( results, params );
 489                      if ( callback )
 490                          callback( results, params );
 491                  }, delay );
 492  
 493              this.query.ajax( response );
 494          },
 495          change: function( search ) {
 496              if ( this.query && this._search == search )
 497                  return;
 498  
 499              this._search = search;
 500              this.query = new Query( search );
 501              this.element.scrollTop(0);
 502          },
 503          process: function( results, params ) {
 504              var list = '', alt = true, classes = '',
 505                  firstPage = params.page == 1;
 506  
 507              if ( !results ) {
 508                  if ( firstPage ) {
 509                      list += '<li class="unselectable"><span class="item-title"><em>'
 510                      + wpLinkL10n.noMatchesFound
 511                      + '</em></span></li>';
 512                  }
 513              } else {
 514                  $.each( results, function() {
 515                      classes = alt ? 'alternate' : '';
 516                      classes += this['title'] ? '' : ' no-title';
 517                      list += classes ? '<li class="' + classes + '">' : '<li>';
 518                      list += '<input type="hidden" class="item-permalink" value="' + this['permalink'] + '" />';
 519                      list += '<span class="item-title">';
 520                      list += this['title'] ? this['title'] : wpLinkL10n.noTitle;
 521                      list += '</span><span class="item-info">' + this['info'] + '</span></li>';
 522                      alt = ! alt;
 523                  });
 524              }
 525  
 526              this.ul[ firstPage ? 'html' : 'append' ]( list );
 527          },
 528          maybeLoad: function() {
 529              var self = this,
 530                  el = this.element,
 531                  bottom = el.scrollTop() + el.height();
 532  
 533              if ( ! this.query.ready() || bottom < this.ul.height() - wpLink.riverBottomThreshold )
 534                  return;
 535  
 536              setTimeout(function() {
 537                  var newTop = el.scrollTop(),
 538                      newBottom = newTop + el.height();
 539  
 540                  if ( ! self.query.ready() || newBottom < self.ul.height() - wpLink.riverBottomThreshold )
 541                      return;
 542  
 543                  self.waiting.show();
 544                  el.scrollTop( newTop + self.waiting.outerHeight() );
 545  
 546                  self.ajax( function() { self.waiting.hide(); });
 547              }, wpLink.timeToTriggerRiver );
 548          }
 549      });
 550  
 551      Query = function( search ) {
 552          this.page = 1;
 553          this.allLoaded = false;
 554          this.querying = false;
 555          this.search = search;
 556      };
 557  
 558      $.extend( Query.prototype, {
 559          ready: function() {
 560              return !( this.querying || this.allLoaded );
 561          },
 562          ajax: function( callback ) {
 563              var self = this,
 564                  query = {
 565                      action : 'wp-link-ajax',
 566                      page : this.page,
 567                      '_ajax_linking_nonce' : $('#_ajax_linking_nonce').val()
 568                  };
 569  
 570              if ( this.search )
 571                  query.search = this.search;
 572  
 573              this.querying = true;
 574  
 575              $.post( ajaxurl, query, function(r) {
 576                  self.page++;
 577                  self.querying = false;
 578                  self.allLoaded = !r;
 579                  callback( r, query );
 580              }, "json" );
 581          }
 582      });
 583  
 584      $(document).ready( wpLink.init );
 585  })(jQuery);


Generated: Wed Jun 1 08:30:02 2011 Cross-referenced by PHPXref 0.7
Provided by Yoast and awesome WordPress Hosting