Ultimate Nofollow - Version 1.4.2

Version Description

  • Fixes compatability issue with WordPress 3.9
Download this release

Release Info

Developer bitacre
Plugin Icon wp plugin Ultimate Nofollow
Version 1.4.2
Comparing to
See all releases

Code changes from version 1.4.1 to 1.4.2

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