Ticket #41590: 41590.patch
| File 41590.patch, 88.2 KB (added by , 8 years ago) |
|---|
-
wp-includes/js/tinymce/plugins/link/plugin.js
1 (function () { 2 3 var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)} 4 5 // Used when there is no 'main' module. 6 // The name is probably (hopefully) unique so minification removes for releases. 7 var register_3795 = function (id) { 8 var module = dem(id); 9 var fragments = id.split('.'); 10 var target = Function('return this;')(); 11 for (var i = 0; i < fragments.length - 1; ++i) { 12 if (target[fragments[i]] === undefined) 13 target[fragments[i]] = {}; 14 target = target[fragments[i]]; 15 } 16 target[fragments[fragments.length - 1]] = module; 17 }; 18 19 var instantiate = function (id) { 20 var actual = defs[id]; 21 var dependencies = actual.deps; 22 var definition = actual.defn; 23 var len = dependencies.length; 24 var instances = new Array(len); 25 for (var i = 0; i < len; ++i) 26 instances[i] = dem(dependencies[i]); 27 var defResult = definition.apply(null, instances); 28 if (defResult === undefined) 29 throw 'module [' + id + '] returned undefined'; 30 actual.instance = defResult; 31 }; 32 33 var def = function (id, dependencies, definition) { 34 if (typeof id !== 'string') 35 throw 'module id must be a string'; 36 else if (dependencies === undefined) 37 throw 'no dependencies for ' + id; 38 else if (definition === undefined) 39 throw 'no definition function for ' + id; 40 defs[id] = { 41 deps: dependencies, 42 defn: definition, 43 instance: undefined 44 }; 45 }; 46 47 var dem = function (id) { 48 var actual = defs[id]; 49 if (actual === undefined) 50 throw 'module [' + id + '] was undefined'; 51 else if (actual.instance === undefined) 52 instantiate(id); 53 return actual.instance; 54 }; 55 56 var req = function (ids, callback) { 57 var len = ids.length; 58 var instances = new Array(len); 59 for (var i = 0; i < len; ++i) 60 instances.push(dem(ids[i])); 61 callback.apply(null, callback); 62 }; 63 64 var ephox = {}; 65 66 ephox.bolt = { 67 module: { 68 api: { 69 define: def, 70 require: req, 71 demand: dem 72 } 73 } 74 }; 75 76 var define = def; 77 var require = req; 78 var demand = dem; 79 // this helps with minificiation when using a lot of global references 80 var defineGlobal = function (id, ref) { 81 define(id, [], function () { return ref; }); 82 }; 83 /*jsc 84 ["tinymce.plugins.link.Plugin","tinymce.core.PluginManager","tinymce.plugins.link.core.Actions","tinymce.plugins.link.ui.Controls","global!tinymce.util.Tools.resolve","tinymce.core.util.VK","tinymce.plugins.link.ui.Dialog","tinymce.plugins.link.core.OpenUrl","tinymce.plugins.link.core.Utils","tinymce.plugins.link.core.Settings","tinymce.core.util.Delay","tinymce.core.util.Tools","tinymce.core.util.XHR","global!RegExp","tinymce.core.dom.DOMUtils","tinymce.core.Env"] 85 jsc*/ 86 defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve); 87 /** 88 * ResolveGlobal.js 89 * 90 * Released under LGPL License. 91 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 92 * 93 * License: http://www.tinymce.com/license 94 * Contributing: http://www.tinymce.com/contributing 95 */ 96 97 define( 98 'tinymce.core.PluginManager', 99 [ 100 'global!tinymce.util.Tools.resolve' 101 ], 102 function (resolve) { 103 return resolve('tinymce.PluginManager'); 104 } 105 ); 106 107 /** 108 * ResolveGlobal.js 109 * 110 * Released under LGPL License. 111 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 112 * 113 * License: http://www.tinymce.com/license 114 * Contributing: http://www.tinymce.com/contributing 115 */ 116 117 define( 118 'tinymce.core.util.VK', 119 [ 120 'global!tinymce.util.Tools.resolve' 121 ], 122 function (resolve) { 123 return resolve('tinymce.util.VK'); 124 } 125 ); 126 127 /** 128 * ResolveGlobal.js 129 * 130 * Released under LGPL License. 131 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 132 * 133 * License: http://www.tinymce.com/license 134 * Contributing: http://www.tinymce.com/contributing 135 */ 136 137 define( 138 'tinymce.core.util.Delay', 139 [ 140 'global!tinymce.util.Tools.resolve' 141 ], 142 function (resolve) { 143 return resolve('tinymce.util.Delay'); 144 } 145 ); 146 147 /** 148 * ResolveGlobal.js 149 * 150 * Released under LGPL License. 151 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 152 * 153 * License: http://www.tinymce.com/license 154 * Contributing: http://www.tinymce.com/contributing 155 */ 156 157 define( 158 'tinymce.core.util.Tools', 159 [ 160 'global!tinymce.util.Tools.resolve' 161 ], 162 function (resolve) { 163 return resolve('tinymce.util.Tools'); 164 } 165 ); 166 167 /** 168 * ResolveGlobal.js 169 * 170 * Released under LGPL License. 171 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 172 * 173 * License: http://www.tinymce.com/license 174 * Contributing: http://www.tinymce.com/contributing 175 */ 176 177 define( 178 'tinymce.core.util.XHR', 179 [ 180 'global!tinymce.util.Tools.resolve' 181 ], 182 function (resolve) { 183 return resolve('tinymce.util.XHR'); 184 } 185 ); 186 187 define( 188 'tinymce.plugins.link.core.Settings', 189 [ 190 191 ], 192 function () { 193 var assumeExternalTargets = function (editorSettings) { 194 return typeof editorSettings.link_assume_external_targets === 'boolean' ? editorSettings.link_assume_external_targets : false; 195 }; 196 197 var hasContextToolbar = function (editorSettings) { 198 return typeof editorSettings.link_context_toolbar === 'boolean' ? editorSettings.link_context_toolbar : false; 199 }; 200 201 var getLinkList = function (editorSettings) { 202 return editorSettings.link_list; 203 }; 204 205 var hasDefaultLinkTarget = function (editorSettings) { 206 return typeof editorSettings.default_link_target === 'string'; 207 }; 208 209 var getDefaultLinkTarget = function (editorSettings) { 210 return editorSettings.default_link_target; 211 }; 212 213 var getTargetList = function (editorSettings) { 214 return editorSettings.target_list; 215 }; 216 217 var setTargetList = function (editor, list) { 218 editor.settings.target_list = list; 219 }; 220 221 var shouldShowTargetList = function (editorSettings) { 222 return getTargetList(editorSettings) !== false; 223 }; 224 225 var getRelList = function (editorSettings) { 226 return editorSettings.rel_list; 227 }; 228 229 var hasRelList = function (editorSettings) { 230 return getRelList(editorSettings) !== undefined; 231 }; 232 233 var getLinkClassList = function (editorSettings) { 234 return editorSettings.link_class_list; 235 }; 236 237 var hasLinkClassList = function (editorSettings) { 238 return getLinkClassList(editorSettings) !== undefined; 239 }; 240 241 var shouldShowLinkTitle = function (editorSettings) { 242 return editorSettings.link_title !== false; 243 }; 244 245 var allowUnsafeLinkTarget = function (editorSettings) { 246 return typeof editorSettings.allow_unsafe_link_target === 'boolean' ? editorSettings.allow_unsafe_link_target : false; 247 }; 248 249 return { 250 assumeExternalTargets: assumeExternalTargets, 251 hasContextToolbar: hasContextToolbar, 252 getLinkList: getLinkList, 253 hasDefaultLinkTarget: hasDefaultLinkTarget, 254 getDefaultLinkTarget: getDefaultLinkTarget, 255 getTargetList: getTargetList, 256 setTargetList: setTargetList, 257 shouldShowTargetList: shouldShowTargetList, 258 getRelList: getRelList, 259 hasRelList: hasRelList, 260 getLinkClassList: getLinkClassList, 261 hasLinkClassList: hasLinkClassList, 262 shouldShowLinkTitle: shouldShowLinkTitle, 263 allowUnsafeLinkTarget: allowUnsafeLinkTarget 264 }; 265 } 266 ); 267 268 defineGlobal("global!RegExp", RegExp); 269 /** 270 * Utils.js 271 * 272 * Released under LGPL License. 273 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 274 * 275 * License: http://www.tinymce.com/license 276 * Contributing: http://www.tinymce.com/contributing 277 */ 278 279 define( 280 'tinymce.plugins.link.core.Utils', 281 [ 282 'tinymce.core.util.Tools', 283 'tinymce.plugins.link.core.Settings', 284 'global!RegExp' 285 ], 286 function (Tools, Settings, RegExp) { 287 288 var toggleTargetRules = function (rel, isUnsafe) { 289 var rules = ['noopener']; 290 var newRel = rel ? rel.split(/\s+/) : []; 291 292 var toString = function (rel) { 293 return Tools.trim(rel.sort().join(' ')); 294 }; 295 296 var addTargetRules = function (rel) { 297 rel = removeTargetRules(rel); 298 return rel.length ? rel.concat(rules) : rules; 299 }; 300 301 var removeTargetRules = function (rel) { 302 return rel.filter(function (val) { 303 return Tools.inArray(rules, val) === -1; 304 }); 305 }; 306 307 newRel = isUnsafe ? addTargetRules(newRel) : removeTargetRules(newRel); 308 return newRel.length ? toString(newRel) : null; 309 }; 310 311 312 var trimCaretContainers = function (text) { 313 return text.replace(/\uFEFF/g, ''); 314 }; 315 316 317 var getAnchorElement = function (editor, selectedElm) { 318 selectedElm = selectedElm || editor.selection.getStart(); 319 if (isImageFigure(selectedElm)) { 320 // for an image conained in a figure we look for a link inside the selected element 321 return editor.dom.select('a[href]', selectedElm)[0]; 322 } else { 323 return editor.dom.getParent(selectedElm, 'a[href]'); 324 } 325 }; 326 327 328 var getAnchorText = function (selection, anchorElm) { 329 var text = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({ format: 'text' }); 330 return trimCaretContainers(text); 331 }; 332 333 334 var isLink = function (elm) { 335 return elm && elm.nodeName === 'A' && elm.href; 336 }; 337 338 var hasLinks = function (elements) { 339 return Tools.grep(elements, isLink).length > 0; 340 }; 341 342 343 var isOnlyTextSelected = function (html) { 344 // Partial html and not a fully selected anchor element 345 if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') == -1)) { 346 return false; 347 } 348 349 return true; 350 }; 351 352 353 var isImageFigure = function (node) { 354 return node && node.nodeName === 'FIGURE' && /\bimage\b/i.test(node.className); 355 }; 356 357 358 var link = function (editor, attachState) { 359 return function (data) { 360 editor.undoManager.transact(function () { 361 var selectedElm = editor.selection.getNode(); 362 var anchorElm = getAnchorElement(editor, selectedElm); 363 364 var linkAttrs = { 365 href: data.href, 366 target: data.target ? data.target : null, 367 rel: data.rel ? data.rel : null, 368 "class": data["class"] ? data["class"] : null, 369 title: data.title ? data.title : null 370 }; 371 372 if (!Settings.hasRelList(editor.settings) && Settings.allowUnsafeLinkTarget(editor.settings) === false) { 373 linkAttrs.rel = toggleTargetRules(linkAttrs.rel, linkAttrs.target == '_blank'); 374 } 375 376 if (data.href === attachState.href) { 377 attachState.attach(); 378 attachState = {}; 379 } 380 381 if (anchorElm) { 382 editor.focus(); 383 384 if (data.hasOwnProperty('text')) { 385 if ("innerText" in anchorElm) { 386 anchorElm.innerText = data.text; 387 } else { 388 anchorElm.textContent = data.text; 389 } 390 } 391 392 editor.dom.setAttribs(anchorElm, linkAttrs); 393 394 editor.selection.select(anchorElm); 395 editor.undoManager.add(); 396 } else { 397 if (isImageFigure(selectedElm)) { 398 linkImageFigure(editor, selectedElm, linkAttrs); 399 } else if (data.hasOwnProperty('text')) { 400 editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(data.text))); 401 } else { 402 editor.execCommand('mceInsertLink', false, linkAttrs); 403 } 404 } 405 }); 406 }; 407 }; 408 409 410 var unlink = function (editor) { 411 return function () { 412 editor.undoManager.transact(function () { 413 var node = editor.selection.getNode(); 414 if (isImageFigure(node)) { 415 unlinkImageFigure(editor, node); 416 } else { 417 editor.execCommand('unlink'); 418 } 419 }); 420 }; 421 }; 422 423 424 var unlinkImageFigure = function (editor, fig) { 425 var a, img; 426 img = editor.dom.select('img', fig)[0]; 427 if (img) { 428 a = editor.dom.getParents(img, 'a[href]', fig)[0]; 429 if (a) { 430 a.parentNode.insertBefore(img, a); 431 editor.dom.remove(a); 432 } 433 } 434 }; 435 436 437 var linkImageFigure = function (editor, fig, attrs) { 438 var a, img; 439 img = editor.dom.select('img', fig)[0]; 440 if (img) { 441 a = editor.dom.create('a', attrs); 442 img.parentNode.insertBefore(a, img); 443 a.appendChild(img); 444 } 445 }; 446 447 return { 448 link: link, 449 unlink: unlink, 450 isLink: isLink, 451 hasLinks: hasLinks, 452 isOnlyTextSelected: isOnlyTextSelected, 453 getAnchorElement: getAnchorElement, 454 getAnchorText: getAnchorText, 455 toggleTargetRules: toggleTargetRules 456 }; 457 } 458 ); 459 /** 460 * Dialog.js 461 * 462 * Released under LGPL License. 463 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 464 * 465 * License: http://www.tinymce.com/license 466 * Contributing: http://www.tinymce.com/contributing 467 */ 468 469 define( 470 'tinymce.plugins.link.ui.Dialog', 471 [ 472 'tinymce.core.util.Delay', 473 'tinymce.core.util.Tools', 474 'tinymce.core.util.XHR', 475 'tinymce.plugins.link.core.Utils', 476 'tinymce.plugins.link.core.Settings' 477 ], 478 function (Delay, Tools, XHR, Utils, Settings) { 479 var attachState = {}; 480 481 var createLinkList = function (editor, callback) { 482 var linkList = Settings.getLinkList(editor.settings); 483 484 if (typeof linkList == "string") { 485 XHR.send({ 486 url: linkList, 487 success: function (text) { 488 callback(editor, JSON.parse(text)); 489 } 490 }); 491 } else if (typeof linkList == "function") { 492 linkList(function (list) { 493 callback(editor, list); 494 }); 495 } else { 496 callback(editor, linkList); 497 } 498 }; 499 500 var buildListItems = function (inputList, itemCallback, startItems) { 501 var appendItems = function (values, output) { 502 output = output || []; 503 504 Tools.each(values, function (item) { 505 var menuItem = { text: item.text || item.title }; 506 507 if (item.menu) { 508 menuItem.menu = appendItems(item.menu); 509 } else { 510 menuItem.value = item.value; 511 512 if (itemCallback) { 513 itemCallback(menuItem); 514 } 515 } 516 517 output.push(menuItem); 518 }); 519 520 return output; 521 }; 522 523 return appendItems(inputList, startItems || []); 524 }; 525 526 // Delay confirm since onSubmit will move focus 527 var delayedConfirm = function (editor, message, callback) { 528 var rng = editor.selection.getRng(); 529 530 Delay.setEditorTimeout(editor, function () { 531 editor.windowManager.confirm(message, function (state) { 532 editor.selection.setRng(rng); 533 callback(state); 534 }); 535 }); 536 }; 537 538 var showDialog = function (editor, linkList) { 539 var data = {}, selection = editor.selection, dom = editor.dom, anchorElm, initialText; 540 var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value; 541 542 var linkListChangeHandler = function (e) { 543 var textCtrl = win.find('#text'); 544 545 if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) { 546 textCtrl.value(e.control.text()); 547 } 548 549 win.find('#href').value(e.control.value()); 550 }; 551 552 var buildAnchorListControl = function (url) { 553 var anchorList = []; 554 555 Tools.each(editor.dom.select('a:not([href])'), function (anchor) { 556 var id = anchor.name || anchor.id; 557 558 if (id) { 559 anchorList.push({ 560 text: id, 561 value: '#' + id, 562 selected: url.indexOf('#' + id) != -1 563 }); 564 } 565 }); 566 567 if (anchorList.length) { 568 anchorList.unshift({ text: 'None', value: '' }); 569 570 return { 571 name: 'anchor', 572 type: 'listbox', 573 label: 'Anchors', 574 values: anchorList, 575 onselect: linkListChangeHandler 576 }; 577 } 578 }; 579 580 var updateText = function () { 581 if (!initialText && onlyText && !data.text) { 582 this.parent().parent().find('#text')[0].value(this.value()); 583 } 584 }; 585 586 var urlChange = function (e) { 587 var meta = e.meta || {}; 588 589 if (linkListCtrl) { 590 linkListCtrl.value(editor.convertURL(this.value(), 'href')); 591 } 592 593 Tools.each(e.meta, function (value, key) { 594 var inp = win.find('#' + key); 595 596 if (key === 'text') { 597 if (initialText.length === 0) { 598 inp.value(value); 599 data.text = value; 600 } 601 } else { 602 inp.value(value); 603 } 604 }); 605 606 if (meta.attach) { 607 attachState = { 608 href: this.value(), 609 attach: meta.attach 610 }; 611 } 612 613 if (!meta.text) { 614 updateText.call(this); 615 } 616 }; 617 618 var onBeforeCall = function (e) { 619 e.meta = win.toJSON(); 620 }; 621 622 onlyText = Utils.isOnlyTextSelected(selection.getContent()); 623 anchorElm = Utils.getAnchorElement(editor); 624 625 data.text = initialText = Utils.getAnchorText(editor.selection, anchorElm); 626 data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; 627 628 if (anchorElm) { 629 data.target = dom.getAttrib(anchorElm, 'target'); 630 } else if (Settings.hasDefaultLinkTarget(editor.settings)) { 631 data.target = Settings.getDefaultLinkTarget(editor.settings); 632 } 633 634 if ((value = dom.getAttrib(anchorElm, 'rel'))) { 635 data.rel = value; 636 } 637 638 if ((value = dom.getAttrib(anchorElm, 'class'))) { 639 data['class'] = value; 640 } 641 642 if ((value = dom.getAttrib(anchorElm, 'title'))) { 643 data.title = value; 644 } 645 646 if (onlyText) { 647 textListCtrl = { 648 name: 'text', 649 type: 'textbox', 650 size: 40, 651 label: 'Text to display', 652 onchange: function () { 653 data.text = this.value(); 654 } 655 }; 656 } 657 658 if (linkList) { 659 linkListCtrl = { 660 type: 'listbox', 661 label: 'Link list', 662 values: buildListItems( 663 linkList, 664 function (item) { 665 item.value = editor.convertURL(item.value || item.url, 'href'); 666 }, 667 [{ text: 'None', value: '' }] 668 ), 669 onselect: linkListChangeHandler, 670 value: editor.convertURL(data.href, 'href'), 671 onPostRender: function () { 672 /*eslint consistent-this:0*/ 673 linkListCtrl = this; 674 } 675 }; 676 } 677 678 if (Settings.shouldShowTargetList(editor.settings)) { 679 if (Settings.getTargetList(editor.settings) === undefined) { 680 Settings.setTargetList(editor, [ 681 { text: 'None', value: '' }, 682 { text: 'New window', value: '_blank' } 683 ]); 684 } 685 686 targetListCtrl = { 687 name: 'target', 688 type: 'listbox', 689 label: 'Target', 690 values: buildListItems(Settings.getTargetList(editor.settings)) 691 }; 692 } 693 694 if (Settings.hasRelList(editor.settings)) { 695 relListCtrl = { 696 name: 'rel', 697 type: 'listbox', 698 label: 'Rel', 699 values: buildListItems( 700 Settings.getRelList(editor.settings), 701 function (item) { 702 if (Settings.allowUnsafeLinkTarget(editor.settings) === false) { 703 item.value = Utils.toggleTargetRules(item.value, data.target === '_blank'); 704 } 705 } 706 ) 707 }; 708 } 709 710 if (Settings.hasLinkClassList(editor.settings)) { 711 classListCtrl = { 712 name: 'class', 713 type: 'listbox', 714 label: 'Class', 715 values: buildListItems( 716 Settings.getLinkClassList(editor.settings), 717 function (item) { 718 if (item.value) { 719 item.textStyle = function () { 720 return editor.formatter.getCssText({ inline: 'a', classes: [item.value] }); 721 }; 722 } 723 } 724 ) 725 }; 726 } 727 728 if (Settings.shouldShowLinkTitle(editor.settings)) { 729 linkTitleCtrl = { 730 name: 'title', 731 type: 'textbox', 732 label: 'Title', 733 value: data.title 734 }; 735 } 736 737 win = editor.windowManager.open({ 738 title: 'Insert link', 739 data: data, 740 body: [ 741 { 742 name: 'href', 743 type: 'filepicker', 744 filetype: 'file', 745 size: 40, 746 autofocus: true, 747 label: 'Url', 748 onchange: urlChange, 749 onkeyup: updateText, 750 onbeforecall: onBeforeCall 751 }, 752 textListCtrl, 753 linkTitleCtrl, 754 buildAnchorListControl(data.href), 755 linkListCtrl, 756 relListCtrl, 757 targetListCtrl, 758 classListCtrl 759 ], 760 onSubmit: function (e) { 761 var assumeExternalTargets = Settings.assumeExternalTargets(editor.settings); 762 var insertLink = Utils.link(editor, attachState); 763 var removeLink = Utils.unlink(editor); 764 765 var resultData = Tools.extend({}, data, e.data); 766 /*eslint dot-notation: 0*/ 767 var href = resultData.href; 768 769 if (!href) { 770 removeLink(); 771 return; 772 } 773 774 if (!onlyText || resultData.text === initialText) { 775 delete resultData.text; 776 } 777 778 // Is email and not //user@domain.com 779 if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) { 780 delayedConfirm( 781 editor, 782 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', 783 function (state) { 784 if (state) { 785 resultData.href = 'mailto:' + href; 786 } 787 insertLink(resultData); 788 } 789 ); 790 return; 791 } 792 793 // Is not protocol prefixed 794 if ((assumeExternalTargets === true && !/^\w+:/i.test(href)) || 795 (assumeExternalTargets === false && /^\s*www[\.|\d\.]/i.test(href))) { 796 delayedConfirm( 797 editor, 798 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?', 799 function (state) { 800 if (state) { 801 resultData.href = 'http://' + href; 802 } 803 insertLink(resultData); 804 } 805 ); 806 return; 807 } 808 809 insertLink(resultData); 810 } 811 }); 812 }; 813 814 var open = function (editor) { 815 createLinkList(editor, showDialog); 816 }; 817 818 return { 819 open: open 820 }; 821 } 822 ); 823 /** 824 * ResolveGlobal.js 825 * 826 * Released under LGPL License. 827 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 828 * 829 * License: http://www.tinymce.com/license 830 * Contributing: http://www.tinymce.com/contributing 831 */ 832 833 define( 834 'tinymce.core.dom.DOMUtils', 835 [ 836 'global!tinymce.util.Tools.resolve' 837 ], 838 function (resolve) { 839 return resolve('tinymce.dom.DOMUtils'); 840 } 841 ); 842 843 /** 844 * ResolveGlobal.js 845 * 846 * Released under LGPL License. 847 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 848 * 849 * License: http://www.tinymce.com/license 850 * Contributing: http://www.tinymce.com/contributing 851 */ 852 853 define( 854 'tinymce.core.Env', 855 [ 856 'global!tinymce.util.Tools.resolve' 857 ], 858 function (resolve) { 859 return resolve('tinymce.Env'); 860 } 861 ); 862 863 /** 864 * OpenUrl.js 865 * 866 * Released under LGPL License. 867 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 868 * 869 * License: http://www.tinymce.com/license 870 * Contributing: http://www.tinymce.com/contributing 871 */ 872 873 define( 874 'tinymce.plugins.link.core.OpenUrl', 875 [ 876 'tinymce.core.dom.DOMUtils', 877 'tinymce.core.Env' 878 ], 879 function (DOMUtils, Env) { 880 var appendClickRemove = function (link, evt) { 881 document.body.appendChild(link); 882 link.dispatchEvent(evt); 883 document.body.removeChild(link); 884 }; 885 886 var open = function (url) { 887 // Chrome and Webkit has implemented noopener and works correctly with/without popup blocker 888 // Firefox has it implemented noopener but when the popup blocker is activated it doesn't work 889 // Edge has only implemented noreferrer and it seems to remove opener as well 890 // Older IE versions pre IE 11 falls back to a window.open approach 891 if (!Env.ie || Env.ie > 10) { 892 var link = document.createElement('a'); 893 link.target = '_blank'; 894 link.href = url; 895 link.rel = 'noreferrer noopener'; 896 897 var evt = document.createEvent('MouseEvents'); 898 evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 899 900 appendClickRemove(link, evt); 901 } else { 902 var win = window.open('', '_blank'); 903 if (win) { 904 win.opener = null; 905 var doc = win.document; 906 doc.open(); 907 doc.write('<meta http-equiv="refresh" content="0; url=' + DOMUtils.DOM.encode(url) + '">'); 908 doc.close(); 909 } 910 } 911 }; 912 913 return { 914 open: open 915 }; 916 } 917 ); 918 /** 919 * Actions.js 920 * 921 * Released under LGPL License. 922 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 923 * 924 * License: http://www.tinymce.com/license 925 * Contributing: http://www.tinymce.com/contributing 926 */ 927 928 define( 929 'tinymce.plugins.link.core.Actions', 930 [ 931 'tinymce.core.util.VK', 932 'tinymce.plugins.link.ui.Dialog', 933 'tinymce.plugins.link.core.OpenUrl', 934 'tinymce.plugins.link.core.Utils', 935 'tinymce.plugins.link.core.Settings' 936 ], 937 function (VK, Dialog, OpenUrl, Utils, Settings) { 938 var getLink = function (editor, elm) { 939 return editor.dom.getParent(elm, 'a[href]'); 940 }; 941 942 var getSelectedLink = function (editor) { 943 return getLink(editor, editor.selection.getStart()); 944 }; 945 946 var getHref = function (elm) { 947 // Returns the real href value not the resolved a.href value 948 var href = elm.getAttribute('data-mce-href'); 949 return href ? href : elm.getAttribute('href'); 950 }; 951 952 var isContextMenuVisible = function (editor) { 953 var contextmenu = editor.plugins.contextmenu; 954 return contextmenu ? contextmenu.isContextMenuVisible() : false; 955 }; 956 957 var hasOnlyAltModifier = function (e) { 958 return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false; 959 }; 960 961 var gotoLink = function (editor, a) { 962 if (a) { 963 var href = getHref(a); 964 if (/^#/.test(href)) { 965 var targetEl = editor.$(href); 966 if (targetEl.length) { 967 editor.selection.scrollIntoView(targetEl[0], true); 968 } 969 } else { 970 OpenUrl.open(a.href); 971 } 972 } 973 }; 974 975 var openDialog = function (editor) { 976 return function () { 977 Dialog.open(editor); 978 }; 979 }; 980 981 var gotoSelectedLink = function (editor) { 982 return function () { 983 gotoLink(editor, getSelectedLink(editor)); 984 }; 985 }; 986 987 var leftClickedOnAHref = function (editor) { 988 return function (elm) { 989 var sel, rng, node; 990 if (Settings.hasContextToolbar(editor.settings) && !isContextMenuVisible(editor) && Utils.isLink(elm)) { 991 sel = editor.selection; 992 rng = sel.getRng(); 993 node = rng.startContainer; 994 // ignore cursor positions at the beginning/end (to make context toolbar less noisy) 995 if (node.nodeType == 3 && sel.isCollapsed() && rng.startOffset > 0 && rng.startOffset < node.data.length) { 996 return true; 997 } 998 } 999 return false; 1000 }; 1001 }; 1002 1003 var setupGotoLinks = function (editor) { 1004 editor.on('click', function (e) { 1005 var link = getLink(editor, e.target); 1006 if (link && VK.metaKeyPressed(e)) { 1007 e.preventDefault(); 1008 gotoLink(editor, link); 1009 } 1010 }); 1011 1012 editor.on('keydown', function (e) { 1013 var link = getSelectedLink(editor); 1014 if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) { 1015 e.preventDefault(); 1016 gotoLink(editor, link); 1017 } 1018 }); 1019 }; 1020 1021 var toggleActiveState = function (editor) { 1022 return function () { 1023 var self = this; 1024 editor.on('nodechange', function (e) { 1025 self.active(!editor.readonly && !!Utils.getAnchorElement(editor, e.element)); 1026 }); 1027 }; 1028 }; 1029 1030 var toggleViewLinkState = function (editor) { 1031 return function () { 1032 var self = this; 1033 1034 var toggleVisibility = function (e) { 1035 if (Utils.hasLinks(e.parents)) { 1036 self.show(); 1037 } else { 1038 self.hide(); 1039 } 1040 }; 1041 1042 if (!Utils.hasLinks(editor.dom.getParents(editor.selection.getStart()))) { 1043 self.hide(); 1044 } 1045 1046 editor.on('nodechange', toggleVisibility); 1047 1048 self.on('remove', function () { 1049 editor.off('nodechange', toggleVisibility); 1050 }); 1051 }; 1052 }; 1053 1054 return { 1055 openDialog: openDialog, 1056 gotoSelectedLink: gotoSelectedLink, 1057 leftClickedOnAHref: leftClickedOnAHref, 1058 setupGotoLinks: setupGotoLinks, 1059 toggleActiveState: toggleActiveState, 1060 toggleViewLinkState: toggleViewLinkState 1061 }; 1062 } 1063 ); 1064 /** 1065 * Controls.js 1066 * 1067 * Released under LGPL License. 1068 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 1069 * 1070 * License: http://www.tinymce.com/license 1071 * Contributing: http://www.tinymce.com/contributing 1072 */ 1073 1074 define( 1075 'tinymce.plugins.link.ui.Controls', 1076 [ 1077 'tinymce.plugins.link.core.Actions', 1078 'tinymce.plugins.link.core.Utils' 1079 ], 1080 function (Actions, Utils) { 1081 1082 var setupButtons = function (editor) { 1083 editor.addButton('link', { 1084 icon: 'link', 1085 tooltip: 'Insert/edit link', 1086 shortcut: 'Meta+K', 1087 onclick: Actions.openDialog(editor), 1088 onpostrender: Actions.toggleActiveState(editor) 1089 }); 1090 1091 editor.addButton('unlink', { 1092 icon: 'unlink', 1093 tooltip: 'Remove link', 1094 onclick: Utils.unlink(editor), 1095 onpostrender: Actions.toggleActiveState(editor) 1096 }); 1097 1098 if (editor.addContextToolbar) { 1099 editor.addButton('openlink', { 1100 icon: 'newtab', 1101 tooltip: 'Open link', 1102 onclick: Actions.gotoSelectedLink(editor) 1103 }); 1104 } 1105 }; 1106 1107 var setupMenuItems = function (editor) { 1108 editor.addMenuItem('openlink', { 1109 text: 'Open link', 1110 icon: 'newtab', 1111 onclick: Actions.gotoSelectedLink(editor), 1112 onPostRender: Actions.toggleViewLinkState(editor), 1113 prependToContext: true 1114 }); 1115 1116 editor.addMenuItem('link', { 1117 icon: 'link', 1118 text: 'Link', 1119 shortcut: 'Meta+K', 1120 onclick: Actions.openDialog(editor), 1121 stateSelector: 'a[href]', 1122 context: 'insert', 1123 prependToContext: true 1124 }); 1125 }; 1126 1127 var setupContextToolbars = function (editor) { 1128 if (editor.addContextToolbar) { 1129 editor.addContextToolbar( 1130 Actions.leftClickedOnAHref(editor), 1131 'openlink | link unlink' 1132 ); 1133 } 1134 }; 1135 1136 return { 1137 setupButtons: setupButtons, 1138 setupMenuItems: setupMenuItems, 1139 setupContextToolbars: setupContextToolbars 1140 }; 1141 } 1142 ); 1143 /** 1144 * Plugin.js 1145 * 1146 * Released under LGPL License. 1147 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 1148 * 1149 * License: http://www.tinymce.com/license 1150 * Contributing: http://www.tinymce.com/contributing 1151 */ 1152 1153 define( 1154 'tinymce.plugins.link.Plugin', 1155 [ 1156 'tinymce.core.PluginManager', 1157 'tinymce.plugins.link.core.Actions', 1158 'tinymce.plugins.link.ui.Controls' 1159 ], 1160 function (PluginManager, Actions, Controls) { 1161 PluginManager.add('link', function (editor) { 1162 Controls.setupButtons(editor); 1163 Controls.setupMenuItems(editor); 1164 Controls.setupContextToolbars(editor); 1165 Actions.setupGotoLinks(editor); 1166 editor.addShortcut('Meta+K', '', Actions.openDialog(editor)); 1167 editor.addCommand('mceLink', Actions.openDialog(editor)); 1168 }); 1169 1170 return function () { }; 1171 } 1172 ); 1173 dem('tinymce.plugins.link.Plugin')(); 1174 })(); -
wp-includes/js/tinymce/plugins/link/plugin.min.js
1 !function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("4",tinymce.util.Tools.resolve),g("1",["4"],function(a){return a("tinymce.PluginManager")}),g("5",["4"],function(a){return a("tinymce.util.VK")}),g("a",["4"],function(a){return a("tinymce.util.Delay")}),g("b",["4"],function(a){return a("tinymce.util.Tools")}),g("c",["4"],function(a){return a("tinymce.util.XHR")}),g("9",[],function(){var a=function(a){return"boolean"==typeof a.link_assume_external_targets&&a.link_assume_external_targets},b=function(a){return"boolean"==typeof a.link_context_toolbar&&a.link_context_toolbar},c=function(a){return a.link_list},d=function(a){return"string"==typeof a.default_link_target},e=function(a){return a.default_link_target},f=function(a){return a.target_list},g=function(a,b){a.settings.target_list=b},h=function(a){return f(a)!==!1},i=function(a){return a.rel_list},j=function(a){return void 0!==i(a)},k=function(a){return a.link_class_list},l=function(a){return void 0!==k(a)},m=function(a){return a.link_title!==!1},n=function(a){return"boolean"==typeof a.allow_unsafe_link_target&&a.allow_unsafe_link_target};return{assumeExternalTargets:a,hasContextToolbar:b,getLinkList:c,hasDefaultLinkTarget:d,getDefaultLinkTarget:e,getTargetList:f,setTargetList:g,shouldShowTargetList:h,getRelList:i,hasRelList:j,getLinkClassList:k,hasLinkClassList:l,shouldShowLinkTitle:m,allowUnsafeLinkTarget:n}}),h("d",RegExp),g("8",["b","9","d"],function(a,b,c){var d=function(b,c){var d=["noopener"],e=b?b.split(/\s+/):[],f=function(b){return a.trim(b.sort().join(" "))},g=function(a){return a=h(a),a.length?a.concat(d):d},h=function(b){return b.filter(function(b){return a.inArray(d,b)===-1})};return e=c?g(e):h(e),e.length?f(e):null},e=function(a){return a.replace(/\uFEFF/g,"")},f=function(a,b){return b=b||a.selection.getStart(),k(b)?a.dom.select("a[href]",b)[0]:a.dom.getParent(b,"a[href]")},g=function(a,b){var c=b?b.innerText||b.textContent:a.getContent({format:"text"});return e(c)},h=function(a){return a&&"A"===a.nodeName&&a.href},i=function(b){return a.grep(b,h).length>0},j=function(a){return!(/</.test(a)&&(!/^<a [^>]+>[^<]+<\/a>$/.test(a)||a.indexOf("href=")==-1))},k=function(a){return a&&"FIGURE"===a.nodeName&&/\bimage\b/i.test(a.className)},l=function(a,c){return function(e){a.undoManager.transact(function(){var g=a.selection.getNode(),h=f(a,g),i={href:e.href,target:e.target?e.target:null,rel:e.rel?e.rel:null,"class":e["class"]?e["class"]:null,title:e.title?e.title:null};b.hasRelList(a.settings)||b.allowUnsafeLinkTarget(a.settings)!==!1||(i.rel=d(i.rel,"_blank"==i.target)),e.href===c.href&&(c.attach(),c={}),h?(a.focus(),e.hasOwnProperty("text")&&("innerText"in h?h.innerText=e.text:h.textContent=e.text),a.dom.setAttribs(h,i),a.selection.select(h),a.undoManager.add()):k(g)?o(a,g,i):e.hasOwnProperty("text")?a.insertContent(a.dom.createHTML("a",i,a.dom.encode(e.text))):a.execCommand("mceInsertLink",!1,i)})}},m=function(a){return function(){a.undoManager.transact(function(){var b=a.selection.getNode();k(b)?n(a,b):a.execCommand("unlink")})}},n=function(a,b){var c,d;d=a.dom.select("img",b)[0],d&&(c=a.dom.getParents(d,"a[href]",b)[0],c&&(c.parentNode.insertBefore(d,c),a.dom.remove(c)))},o=function(a,b,c){var d,e;e=a.dom.select("img",b)[0],e&&(d=a.dom.create("a",c),e.parentNode.insertBefore(d,e),d.appendChild(e))};return{link:l,unlink:m,isLink:h,hasLinks:i,isOnlyTextSelected:j,getAnchorElement:f,getAnchorText:g,toggleTargetRules:d}}),g("6",["a","b","c","8","9"],function(a,b,c,d,e){var f={},g=function(a,b){var d=e.getLinkList(a.settings);"string"==typeof d?c.send({url:d,success:function(c){b(a,JSON.parse(c))}}):"function"==typeof d?d(function(c){b(a,c)}):b(a,d)},h=function(a,c,d){var e=function(a,d){return d=d||[],b.each(a,function(a){var b={text:a.text||a.title};a.menu?b.menu=e(a.menu):(b.value=a.value,c&&c(b)),d.push(b)}),d};return e(a,d||[])},i=function(b,c,d){var e=b.selection.getRng();a.setEditorTimeout(b,function(){b.windowManager.confirm(c,function(a){b.selection.setRng(e),d(a)})})},j=function(a,c){var g,j,k,l,m,n,o,p,q,r,s,t={},u=a.selection,v=a.dom,w=function(a){var b=k.find("#text");(!b.value()||a.lastControl&&b.value()==a.lastControl.text())&&b.value(a.control.text()),k.find("#href").value(a.control.value())},x=function(c){var d=[];if(b.each(a.dom.select("a:not([href])"),function(a){var b=a.name||a.id;b&&d.push({text:b,value:"#"+b,selected:c.indexOf("#"+b)!=-1})}),d.length)return d.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:d,onselect:w}},y=function(){j||!l||t.text||this.parent().parent().find("#text")[0].value(this.value())},z=function(c){var d=c.meta||{};n&&n.value(a.convertURL(this.value(),"href")),b.each(c.meta,function(a,b){var c=k.find("#"+b);"text"===b?0===j.length&&(c.value(a),t.text=a):c.value(a)}),d.attach&&(f={href:this.value(),attach:d.attach}),d.text||y.call(this)},A=function(a){a.meta=k.toJSON()};l=d.isOnlyTextSelected(u.getContent()),g=d.getAnchorElement(a),t.text=j=d.getAnchorText(a.selection,g),t.href=g?v.getAttrib(g,"href"):"",g?t.target=v.getAttrib(g,"target"):e.hasDefaultLinkTarget(a.settings)&&(t.target=e.getDefaultLinkTarget(a.settings)),(s=v.getAttrib(g,"rel"))&&(t.rel=s),(s=v.getAttrib(g,"class"))&&(t["class"]=s),(s=v.getAttrib(g,"title"))&&(t.title=s),l&&(m={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){t.text=this.value()}}),c&&(n={type:"listbox",label:"Link list",values:h(c,function(b){b.value=a.convertURL(b.value||b.url,"href")},[{text:"None",value:""}]),onselect:w,value:a.convertURL(t.href,"href"),onPostRender:function(){n=this}}),e.shouldShowTargetList(a.settings)&&(void 0===e.getTargetList(a.settings)&&e.setTargetList(a,[{text:"None",value:""},{text:"New window",value:"_blank"}]),p={name:"target",type:"listbox",label:"Target",values:h(e.getTargetList(a.settings))}),e.hasRelList(a.settings)&&(o={name:"rel",type:"listbox",label:"Rel",values:h(e.getRelList(a.settings),function(b){e.allowUnsafeLinkTarget(a.settings)===!1&&(b.value=d.toggleTargetRules(b.value,"_blank"===t.target))})}),e.hasLinkClassList(a.settings)&&(q={name:"class",type:"listbox",label:"Class",values:h(e.getLinkClassList(a.settings),function(b){b.value&&(b.textStyle=function(){return a.formatter.getCssText({inline:"a",classes:[b.value]})})})}),e.shouldShowLinkTitle(a.settings)&&(r={name:"title",type:"textbox",label:"Title",value:t.title}),k=a.windowManager.open({title:"Insert link",data:t,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:z,onkeyup:y,onbeforecall:A},m,r,x(t.href),n,o,p,q],onSubmit:function(c){var g=e.assumeExternalTargets(a.settings),h=d.link(a,f),k=d.unlink(a),m=b.extend({},t,c.data),n=m.href;return n?(l&&m.text!==j||delete m.text,n.indexOf("@")>0&&n.indexOf("//")==-1&&n.indexOf("mailto:")==-1?void i(a,"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(a){a&&(m.href="mailto:"+n),h(m)}):g===!0&&!/^\w+:/i.test(n)||g===!1&&/^\s*www[\.|\d\.]/i.test(n)?void i(a,"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(a){a&&(m.href="http://"+n),h(m)}):void h(m)):void k()}})},k=function(a){g(a,j)};return{open:k}}),g("e",["4"],function(a){return a("tinymce.dom.DOMUtils")}),g("f",["4"],function(a){return a("tinymce.Env")}),g("7",["e","f"],function(a,b){var c=function(a,b){document.body.appendChild(a),a.dispatchEvent(b),document.body.removeChild(a)},d=function(d){if(!b.ie||b.ie>10){var e=document.createElement("a");e.target="_blank",e.href=d,e.rel="noreferrer noopener";var f=document.createEvent("MouseEvents");f.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),c(e,f)}else{var g=window.open("","_blank");if(g){g.opener=null;var h=g.document;h.open(),h.write('<meta http-equiv="refresh" content="0; url='+a.DOM.encode(d)+'">'),h.close()}}};return{open:d}}),g("2",["5","6","7","8","9"],function(a,b,c,d,e){var f=function(a,b){return a.dom.getParent(b,"a[href]")},g=function(a){return f(a,a.selection.getStart())},h=function(a){var b=a.getAttribute("data-mce-href");return b?b:a.getAttribute("href")},i=function(a){var b=a.plugins.contextmenu;return!!b&&b.isContextMenuVisible()},j=function(a){return a.altKey===!0&&a.shiftKey===!1&&a.ctrlKey===!1&&a.metaKey===!1},k=function(a,b){if(b){var d=h(b);if(/^#/.test(d)){var e=a.$(d);e.length&&a.selection.scrollIntoView(e[0],!0)}else c.open(b.href)}},l=function(a){return function(){b.open(a)}},m=function(a){return function(){k(a,g(a))}},n=function(a){return function(b){var c,f,g;return!!(e.hasContextToolbar(a.settings)&&!i(a)&&d.isLink(b)&&(c=a.selection,f=c.getRng(),g=f.startContainer,3==g.nodeType&&c.isCollapsed()&&f.startOffset>0&&f.startOffset<g.data.length))}},o=function(b){b.on("click",function(c){var d=f(b,c.target);d&&a.metaKeyPressed(c)&&(c.preventDefault(),k(b,d))}),b.on("keydown",function(a){var c=g(b);c&&13===a.keyCode&&j(a)&&(a.preventDefault(),k(b,c))})},p=function(a){return function(){var b=this;a.on("nodechange",function(c){b.active(!a.readonly&&!!d.getAnchorElement(a,c.element))})}},q=function(a){return function(){var b=this,c=function(a){d.hasLinks(a.parents)?b.show():b.hide()};d.hasLinks(a.dom.getParents(a.selection.getStart()))||b.hide(),a.on("nodechange",c),b.on("remove",function(){a.off("nodechange",c)})}};return{openDialog:l,gotoSelectedLink:m,leftClickedOnAHref:n,setupGotoLinks:o,toggleActiveState:p,toggleViewLinkState:q}}),g("3",["2","8"],function(a,b){var c=function(c){c.addButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Meta+K",onclick:a.openDialog(c),onpostrender:a.toggleActiveState(c)}),c.addButton("unlink",{icon:"unlink",tooltip:"Remove link",onclick:b.unlink(c),onpostrender:a.toggleActiveState(c)}),c.addContextToolbar&&c.addButton("openlink",{icon:"newtab",tooltip:"Open link",onclick:a.gotoSelectedLink(c)})},d=function(b){b.addMenuItem("openlink",{text:"Open link",icon:"newtab",onclick:a.gotoSelectedLink(b),onPostRender:a.toggleViewLinkState(b),prependToContext:!0}),b.addMenuItem("link",{icon:"link",text:"Link",shortcut:"Meta+K",onclick:a.openDialog(b),stateSelector:"a[href]",context:"insert",prependToContext:!0})},e=function(b){b.addContextToolbar&&b.addContextToolbar(a.leftClickedOnAHref(b),"openlink | link unlink")};return{setupButtons:c,setupMenuItems:d,setupContextToolbars:e}}),g("0",["1","2","3"],function(a,b,c){return a.add("link",function(a){c.setupButtons(a),c.setupMenuItems(a),c.setupContextToolbars(a),b.setupGotoLinks(a),a.addShortcut("Meta+K","",b.openDialog(a)),a.addCommand("mceLink",b.openDialog(a))}),function(){}}),d("0")()}(); 2 No newline at end of file -
wp-includes/js/tinymce/plugins/link/plugin.js
1 (function () { 2 3 var defs = {}; // id -> {dependencies, definition, instance (possibly undefined)} 4 5 // Used when there is no 'main' module. 6 // The name is probably (hopefully) unique so minification removes for releases. 7 var register_3795 = function (id) { 8 var module = dem(id); 9 var fragments = id.split('.'); 10 var target = Function('return this;')(); 11 for (var i = 0; i < fragments.length - 1; ++i) { 12 if (target[fragments[i]] === undefined) 13 target[fragments[i]] = {}; 14 target = target[fragments[i]]; 15 } 16 target[fragments[fragments.length - 1]] = module; 17 }; 18 19 var instantiate = function (id) { 20 var actual = defs[id]; 21 var dependencies = actual.deps; 22 var definition = actual.defn; 23 var len = dependencies.length; 24 var instances = new Array(len); 25 for (var i = 0; i < len; ++i) 26 instances[i] = dem(dependencies[i]); 27 var defResult = definition.apply(null, instances); 28 if (defResult === undefined) 29 throw 'module [' + id + '] returned undefined'; 30 actual.instance = defResult; 31 }; 32 33 var def = function (id, dependencies, definition) { 34 if (typeof id !== 'string') 35 throw 'module id must be a string'; 36 else if (dependencies === undefined) 37 throw 'no dependencies for ' + id; 38 else if (definition === undefined) 39 throw 'no definition function for ' + id; 40 defs[id] = { 41 deps: dependencies, 42 defn: definition, 43 instance: undefined 44 }; 45 }; 46 47 var dem = function (id) { 48 var actual = defs[id]; 49 if (actual === undefined) 50 throw 'module [' + id + '] was undefined'; 51 else if (actual.instance === undefined) 52 instantiate(id); 53 return actual.instance; 54 }; 55 56 var req = function (ids, callback) { 57 var len = ids.length; 58 var instances = new Array(len); 59 for (var i = 0; i < len; ++i) 60 instances.push(dem(ids[i])); 61 callback.apply(null, callback); 62 }; 63 64 var ephox = {}; 65 66 ephox.bolt = { 67 module: { 68 api: { 69 define: def, 70 require: req, 71 demand: dem 72 } 73 } 74 }; 75 76 var define = def; 77 var require = req; 78 var demand = dem; 79 // this helps with minificiation when using a lot of global references 80 var defineGlobal = function (id, ref) { 81 define(id, [], function () { return ref; }); 82 }; 83 /*jsc 84 ["tinymce.plugins.link.Plugin","tinymce.core.PluginManager","tinymce.plugins.link.core.Actions","tinymce.plugins.link.ui.Controls","global!tinymce.util.Tools.resolve","tinymce.core.util.VK","tinymce.plugins.link.ui.Dialog","tinymce.plugins.link.core.OpenUrl","tinymce.plugins.link.core.Utils","tinymce.plugins.link.core.Settings","tinymce.core.util.Delay","tinymce.core.util.Tools","tinymce.core.util.XHR","global!RegExp","tinymce.core.dom.DOMUtils","tinymce.core.Env"] 85 jsc*/ 86 defineGlobal("global!tinymce.util.Tools.resolve", tinymce.util.Tools.resolve); 87 /** 88 * ResolveGlobal.js 89 * 90 * Released under LGPL License. 91 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 92 * 93 * License: http://www.tinymce.com/license 94 * Contributing: http://www.tinymce.com/contributing 95 */ 96 97 define( 98 'tinymce.core.PluginManager', 99 [ 100 'global!tinymce.util.Tools.resolve' 101 ], 102 function (resolve) { 103 return resolve('tinymce.PluginManager'); 104 } 105 ); 106 107 /** 108 * ResolveGlobal.js 109 * 110 * Released under LGPL License. 111 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 112 * 113 * License: http://www.tinymce.com/license 114 * Contributing: http://www.tinymce.com/contributing 115 */ 116 117 define( 118 'tinymce.core.util.VK', 119 [ 120 'global!tinymce.util.Tools.resolve' 121 ], 122 function (resolve) { 123 return resolve('tinymce.util.VK'); 124 } 125 ); 126 127 /** 128 * ResolveGlobal.js 129 * 130 * Released under LGPL License. 131 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 132 * 133 * License: http://www.tinymce.com/license 134 * Contributing: http://www.tinymce.com/contributing 135 */ 136 137 define( 138 'tinymce.core.util.Delay', 139 [ 140 'global!tinymce.util.Tools.resolve' 141 ], 142 function (resolve) { 143 return resolve('tinymce.util.Delay'); 144 } 145 ); 146 147 /** 148 * ResolveGlobal.js 149 * 150 * Released under LGPL License. 151 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 152 * 153 * License: http://www.tinymce.com/license 154 * Contributing: http://www.tinymce.com/contributing 155 */ 156 157 define( 158 'tinymce.core.util.Tools', 159 [ 160 'global!tinymce.util.Tools.resolve' 161 ], 162 function (resolve) { 163 return resolve('tinymce.util.Tools'); 164 } 165 ); 166 167 /** 168 * ResolveGlobal.js 169 * 170 * Released under LGPL License. 171 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 172 * 173 * License: http://www.tinymce.com/license 174 * Contributing: http://www.tinymce.com/contributing 175 */ 176 177 define( 178 'tinymce.core.util.XHR', 179 [ 180 'global!tinymce.util.Tools.resolve' 181 ], 182 function (resolve) { 183 return resolve('tinymce.util.XHR'); 184 } 185 ); 186 187 define( 188 'tinymce.plugins.link.core.Settings', 189 [ 190 191 ], 192 function () { 193 var assumeExternalTargets = function (editorSettings) { 194 return typeof editorSettings.link_assume_external_targets === 'boolean' ? editorSettings.link_assume_external_targets : false; 195 }; 196 197 var hasContextToolbar = function (editorSettings) { 198 return typeof editorSettings.link_context_toolbar === 'boolean' ? editorSettings.link_context_toolbar : false; 199 }; 200 201 var getLinkList = function (editorSettings) { 202 return editorSettings.link_list; 203 }; 204 205 var hasDefaultLinkTarget = function (editorSettings) { 206 return typeof editorSettings.default_link_target === 'string'; 207 }; 208 209 var getDefaultLinkTarget = function (editorSettings) { 210 return editorSettings.default_link_target; 211 }; 212 213 var getTargetList = function (editorSettings) { 214 return editorSettings.target_list; 215 }; 216 217 var setTargetList = function (editor, list) { 218 editor.settings.target_list = list; 219 }; 220 221 var shouldShowTargetList = function (editorSettings) { 222 return getTargetList(editorSettings) !== false; 223 }; 224 225 var getRelList = function (editorSettings) { 226 return editorSettings.rel_list; 227 }; 228 229 var hasRelList = function (editorSettings) { 230 return getRelList(editorSettings) !== undefined; 231 }; 232 233 var getLinkClassList = function (editorSettings) { 234 return editorSettings.link_class_list; 235 }; 236 237 var hasLinkClassList = function (editorSettings) { 238 return getLinkClassList(editorSettings) !== undefined; 239 }; 240 241 var shouldShowLinkTitle = function (editorSettings) { 242 return editorSettings.link_title !== false; 243 }; 244 245 var allowUnsafeLinkTarget = function (editorSettings) { 246 return typeof editorSettings.allow_unsafe_link_target === 'boolean' ? editorSettings.allow_unsafe_link_target : false; 247 }; 248 249 return { 250 assumeExternalTargets: assumeExternalTargets, 251 hasContextToolbar: hasContextToolbar, 252 getLinkList: getLinkList, 253 hasDefaultLinkTarget: hasDefaultLinkTarget, 254 getDefaultLinkTarget: getDefaultLinkTarget, 255 getTargetList: getTargetList, 256 setTargetList: setTargetList, 257 shouldShowTargetList: shouldShowTargetList, 258 getRelList: getRelList, 259 hasRelList: hasRelList, 260 getLinkClassList: getLinkClassList, 261 hasLinkClassList: hasLinkClassList, 262 shouldShowLinkTitle: shouldShowLinkTitle, 263 allowUnsafeLinkTarget: allowUnsafeLinkTarget 264 }; 265 } 266 ); 267 268 defineGlobal("global!RegExp", RegExp); 269 /** 270 * Utils.js 271 * 272 * Released under LGPL License. 273 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 274 * 275 * License: http://www.tinymce.com/license 276 * Contributing: http://www.tinymce.com/contributing 277 */ 278 279 define( 280 'tinymce.plugins.link.core.Utils', 281 [ 282 'tinymce.core.util.Tools', 283 'tinymce.plugins.link.core.Settings', 284 'global!RegExp' 285 ], 286 function (Tools, Settings, RegExp) { 287 288 var toggleTargetRules = function (rel, isUnsafe) { 289 var rules = ['noopener']; 290 var newRel = rel ? rel.split(/\s+/) : []; 291 292 var toString = function (rel) { 293 return Tools.trim(rel.sort().join(' ')); 294 }; 295 296 var addTargetRules = function (rel) { 297 rel = removeTargetRules(rel); 298 return rel.length ? rel.concat(rules) : rules; 299 }; 300 301 var removeTargetRules = function (rel) { 302 return rel.filter(function (val) { 303 return Tools.inArray(rules, val) === -1; 304 }); 305 }; 306 307 newRel = isUnsafe ? addTargetRules(newRel) : removeTargetRules(newRel); 308 return newRel.length ? toString(newRel) : null; 309 }; 310 311 312 var trimCaretContainers = function (text) { 313 return text.replace(/\uFEFF/g, ''); 314 }; 315 316 317 var getAnchorElement = function (editor, selectedElm) { 318 selectedElm = selectedElm || editor.selection.getStart(); 319 if (isImageFigure(selectedElm)) { 320 // for an image conained in a figure we look for a link inside the selected element 321 return editor.dom.select('a[href]', selectedElm)[0]; 322 } else { 323 return editor.dom.getParent(selectedElm, 'a[href]'); 324 } 325 }; 326 327 328 var getAnchorText = function (selection, anchorElm) { 329 var text = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({ format: 'text' }); 330 return trimCaretContainers(text); 331 }; 332 333 334 var isLink = function (elm) { 335 return elm && elm.nodeName === 'A' && elm.href; 336 }; 337 338 var hasLinks = function (elements) { 339 return Tools.grep(elements, isLink).length > 0; 340 }; 341 342 343 var isOnlyTextSelected = function (html) { 344 // Partial html and not a fully selected anchor element 345 if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') == -1)) { 346 return false; 347 } 348 349 return true; 350 }; 351 352 353 var isImageFigure = function (node) { 354 return node && node.nodeName === 'FIGURE' && /\bimage\b/i.test(node.className); 355 }; 356 357 358 var link = function (editor, attachState) { 359 return function (data) { 360 editor.undoManager.transact(function () { 361 var selectedElm = editor.selection.getNode(); 362 var anchorElm = getAnchorElement(editor, selectedElm); 363 364 var linkAttrs = { 365 href: data.href, 366 target: data.target ? data.target : null, 367 rel: data.rel ? data.rel : null, 368 "class": data["class"] ? data["class"] : null, 369 title: data.title ? data.title : null 370 }; 371 372 if (!Settings.hasRelList(editor.settings) && Settings.allowUnsafeLinkTarget(editor.settings) === false) { 373 linkAttrs.rel = toggleTargetRules(linkAttrs.rel, linkAttrs.target == '_blank'); 374 } 375 376 if (data.href === attachState.href) { 377 attachState.attach(); 378 attachState = {}; 379 } 380 381 if (anchorElm) { 382 editor.focus(); 383 384 if (data.hasOwnProperty('text')) { 385 if ("innerText" in anchorElm) { 386 anchorElm.innerText = data.text; 387 } else { 388 anchorElm.textContent = data.text; 389 } 390 } 391 392 editor.dom.setAttribs(anchorElm, linkAttrs); 393 394 editor.selection.select(anchorElm); 395 editor.undoManager.add(); 396 } else { 397 if (isImageFigure(selectedElm)) { 398 linkImageFigure(editor, selectedElm, linkAttrs); 399 } else if (data.hasOwnProperty('text')) { 400 editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(data.text))); 401 } else { 402 editor.execCommand('mceInsertLink', false, linkAttrs); 403 } 404 } 405 }); 406 }; 407 }; 408 409 410 var unlink = function (editor) { 411 return function () { 412 editor.undoManager.transact(function () { 413 var node = editor.selection.getNode(); 414 if (isImageFigure(node)) { 415 unlinkImageFigure(editor, node); 416 } else { 417 editor.execCommand('unlink'); 418 } 419 }); 420 }; 421 }; 422 423 424 var unlinkImageFigure = function (editor, fig) { 425 var a, img; 426 img = editor.dom.select('img', fig)[0]; 427 if (img) { 428 a = editor.dom.getParents(img, 'a[href]', fig)[0]; 429 if (a) { 430 a.parentNode.insertBefore(img, a); 431 editor.dom.remove(a); 432 } 433 } 434 }; 435 436 437 var linkImageFigure = function (editor, fig, attrs) { 438 var a, img; 439 img = editor.dom.select('img', fig)[0]; 440 if (img) { 441 a = editor.dom.create('a', attrs); 442 img.parentNode.insertBefore(a, img); 443 a.appendChild(img); 444 } 445 }; 446 447 return { 448 link: link, 449 unlink: unlink, 450 isLink: isLink, 451 hasLinks: hasLinks, 452 isOnlyTextSelected: isOnlyTextSelected, 453 getAnchorElement: getAnchorElement, 454 getAnchorText: getAnchorText, 455 toggleTargetRules: toggleTargetRules 456 }; 457 } 458 ); 459 /** 460 * Dialog.js 461 * 462 * Released under LGPL License. 463 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 464 * 465 * License: http://www.tinymce.com/license 466 * Contributing: http://www.tinymce.com/contributing 467 */ 468 469 define( 470 'tinymce.plugins.link.ui.Dialog', 471 [ 472 'tinymce.core.util.Delay', 473 'tinymce.core.util.Tools', 474 'tinymce.core.util.XHR', 475 'tinymce.plugins.link.core.Utils', 476 'tinymce.plugins.link.core.Settings' 477 ], 478 function (Delay, Tools, XHR, Utils, Settings) { 479 var attachState = {}; 480 481 var createLinkList = function (editor, callback) { 482 var linkList = Settings.getLinkList(editor.settings); 483 484 if (typeof linkList == "string") { 485 XHR.send({ 486 url: linkList, 487 success: function (text) { 488 callback(editor, JSON.parse(text)); 489 } 490 }); 491 } else if (typeof linkList == "function") { 492 linkList(function (list) { 493 callback(editor, list); 494 }); 495 } else { 496 callback(editor, linkList); 497 } 498 }; 499 500 var buildListItems = function (inputList, itemCallback, startItems) { 501 var appendItems = function (values, output) { 502 output = output || []; 503 504 Tools.each(values, function (item) { 505 var menuItem = { text: item.text || item.title }; 506 507 if (item.menu) { 508 menuItem.menu = appendItems(item.menu); 509 } else { 510 menuItem.value = item.value; 511 512 if (itemCallback) { 513 itemCallback(menuItem); 514 } 515 } 516 517 output.push(menuItem); 518 }); 519 520 return output; 521 }; 522 523 return appendItems(inputList, startItems || []); 524 }; 525 526 // Delay confirm since onSubmit will move focus 527 var delayedConfirm = function (editor, message, callback) { 528 var rng = editor.selection.getRng(); 529 530 Delay.setEditorTimeout(editor, function () { 531 editor.windowManager.confirm(message, function (state) { 532 editor.selection.setRng(rng); 533 callback(state); 534 }); 535 }); 536 }; 537 538 var showDialog = function (editor, linkList) { 539 var data = {}, selection = editor.selection, dom = editor.dom, anchorElm, initialText; 540 var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value; 541 542 var linkListChangeHandler = function (e) { 543 var textCtrl = win.find('#text'); 544 545 if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) { 546 textCtrl.value(e.control.text()); 547 } 548 549 win.find('#href').value(e.control.value()); 550 }; 551 552 var buildAnchorListControl = function (url) { 553 var anchorList = []; 554 555 Tools.each(editor.dom.select('a:not([href])'), function (anchor) { 556 var id = anchor.name || anchor.id; 557 558 if (id) { 559 anchorList.push({ 560 text: id, 561 value: '#' + id, 562 selected: url.indexOf('#' + id) != -1 563 }); 564 } 565 }); 566 567 if (anchorList.length) { 568 anchorList.unshift({ text: 'None', value: '' }); 569 570 return { 571 name: 'anchor', 572 type: 'listbox', 573 label: 'Anchors', 574 values: anchorList, 575 onselect: linkListChangeHandler 576 }; 577 } 578 }; 579 580 var updateText = function () { 581 if (!initialText && onlyText && !data.text) { 582 this.parent().parent().find('#text')[0].value(this.value()); 583 } 584 }; 585 586 var urlChange = function (e) { 587 var meta = e.meta || {}; 588 589 if (linkListCtrl) { 590 linkListCtrl.value(editor.convertURL(this.value(), 'href')); 591 } 592 593 Tools.each(e.meta, function (value, key) { 594 var inp = win.find('#' + key); 595 596 if (key === 'text') { 597 if (initialText.length === 0) { 598 inp.value(value); 599 data.text = value; 600 } 601 } else { 602 inp.value(value); 603 } 604 }); 605 606 if (meta.attach) { 607 attachState = { 608 href: this.value(), 609 attach: meta.attach 610 }; 611 } 612 613 if (!meta.text) { 614 updateText.call(this); 615 } 616 }; 617 618 var onBeforeCall = function (e) { 619 e.meta = win.toJSON(); 620 }; 621 622 onlyText = Utils.isOnlyTextSelected(selection.getContent()); 623 anchorElm = Utils.getAnchorElement(editor); 624 625 data.text = initialText = Utils.getAnchorText(editor.selection, anchorElm); 626 data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; 627 628 if (anchorElm) { 629 data.target = dom.getAttrib(anchorElm, 'target'); 630 } else if (Settings.hasDefaultLinkTarget(editor.settings)) { 631 data.target = Settings.getDefaultLinkTarget(editor.settings); 632 } 633 634 if ((value = dom.getAttrib(anchorElm, 'rel'))) { 635 data.rel = value; 636 } 637 638 if ((value = dom.getAttrib(anchorElm, 'class'))) { 639 data['class'] = value; 640 } 641 642 if ((value = dom.getAttrib(anchorElm, 'title'))) { 643 data.title = value; 644 } 645 646 if (onlyText) { 647 textListCtrl = { 648 name: 'text', 649 type: 'textbox', 650 size: 40, 651 label: 'Text to display', 652 onchange: function () { 653 data.text = this.value(); 654 } 655 }; 656 } 657 658 if (linkList) { 659 linkListCtrl = { 660 type: 'listbox', 661 label: 'Link list', 662 values: buildListItems( 663 linkList, 664 function (item) { 665 item.value = editor.convertURL(item.value || item.url, 'href'); 666 }, 667 [{ text: 'None', value: '' }] 668 ), 669 onselect: linkListChangeHandler, 670 value: editor.convertURL(data.href, 'href'), 671 onPostRender: function () { 672 /*eslint consistent-this:0*/ 673 linkListCtrl = this; 674 } 675 }; 676 } 677 678 if (Settings.shouldShowTargetList(editor.settings)) { 679 if (Settings.getTargetList(editor.settings) === undefined) { 680 Settings.setTargetList(editor, [ 681 { text: 'None', value: '' }, 682 { text: 'New window', value: '_blank' } 683 ]); 684 } 685 686 targetListCtrl = { 687 name: 'target', 688 type: 'listbox', 689 label: 'Target', 690 values: buildListItems(Settings.getTargetList(editor.settings)) 691 }; 692 } 693 694 if (Settings.hasRelList(editor.settings)) { 695 relListCtrl = { 696 name: 'rel', 697 type: 'listbox', 698 label: 'Rel', 699 values: buildListItems( 700 Settings.getRelList(editor.settings), 701 function (item) { 702 if (Settings.allowUnsafeLinkTarget(editor.settings) === false) { 703 item.value = Utils.toggleTargetRules(item.value, data.target === '_blank'); 704 } 705 } 706 ) 707 }; 708 } 709 710 if (Settings.hasLinkClassList(editor.settings)) { 711 classListCtrl = { 712 name: 'class', 713 type: 'listbox', 714 label: 'Class', 715 values: buildListItems( 716 Settings.getLinkClassList(editor.settings), 717 function (item) { 718 if (item.value) { 719 item.textStyle = function () { 720 return editor.formatter.getCssText({ inline: 'a', classes: [item.value] }); 721 }; 722 } 723 } 724 ) 725 }; 726 } 727 728 if (Settings.shouldShowLinkTitle(editor.settings)) { 729 linkTitleCtrl = { 730 name: 'title', 731 type: 'textbox', 732 label: 'Title', 733 value: data.title 734 }; 735 } 736 737 win = editor.windowManager.open({ 738 title: 'Insert link', 739 data: data, 740 body: [ 741 { 742 name: 'href', 743 type: 'filepicker', 744 filetype: 'file', 745 size: 40, 746 autofocus: true, 747 label: 'Url', 748 onchange: urlChange, 749 onkeyup: updateText, 750 onbeforecall: onBeforeCall 751 }, 752 textListCtrl, 753 linkTitleCtrl, 754 buildAnchorListControl(data.href), 755 linkListCtrl, 756 relListCtrl, 757 targetListCtrl, 758 classListCtrl 759 ], 760 onSubmit: function (e) { 761 var assumeExternalTargets = Settings.assumeExternalTargets(editor.settings); 762 var insertLink = Utils.link(editor, attachState); 763 var removeLink = Utils.unlink(editor); 764 765 var resultData = Tools.extend({}, data, e.data); 766 /*eslint dot-notation: 0*/ 767 var href = resultData.href; 768 769 if (!href) { 770 removeLink(); 771 return; 772 } 773 774 if (!onlyText || resultData.text === initialText) { 775 delete resultData.text; 776 } 777 778 // Is email and not //user@domain.com 779 if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) { 780 delayedConfirm( 781 editor, 782 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', 783 function (state) { 784 if (state) { 785 resultData.href = 'mailto:' + href; 786 } 787 insertLink(resultData); 788 } 789 ); 790 return; 791 } 792 793 // Is not protocol prefixed 794 if ((assumeExternalTargets === true && !/^\w+:/i.test(href)) || 795 (assumeExternalTargets === false && /^\s*www[\.|\d\.]/i.test(href))) { 796 delayedConfirm( 797 editor, 798 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?', 799 function (state) { 800 if (state) { 801 resultData.href = 'http://' + href; 802 } 803 insertLink(resultData); 804 } 805 ); 806 return; 807 } 808 809 insertLink(resultData); 810 } 811 }); 812 }; 813 814 var open = function (editor) { 815 createLinkList(editor, showDialog); 816 }; 817 818 return { 819 open: open 820 }; 821 } 822 ); 823 /** 824 * ResolveGlobal.js 825 * 826 * Released under LGPL License. 827 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 828 * 829 * License: http://www.tinymce.com/license 830 * Contributing: http://www.tinymce.com/contributing 831 */ 832 833 define( 834 'tinymce.core.dom.DOMUtils', 835 [ 836 'global!tinymce.util.Tools.resolve' 837 ], 838 function (resolve) { 839 return resolve('tinymce.dom.DOMUtils'); 840 } 841 ); 842 843 /** 844 * ResolveGlobal.js 845 * 846 * Released under LGPL License. 847 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 848 * 849 * License: http://www.tinymce.com/license 850 * Contributing: http://www.tinymce.com/contributing 851 */ 852 853 define( 854 'tinymce.core.Env', 855 [ 856 'global!tinymce.util.Tools.resolve' 857 ], 858 function (resolve) { 859 return resolve('tinymce.Env'); 860 } 861 ); 862 863 /** 864 * OpenUrl.js 865 * 866 * Released under LGPL License. 867 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 868 * 869 * License: http://www.tinymce.com/license 870 * Contributing: http://www.tinymce.com/contributing 871 */ 872 873 define( 874 'tinymce.plugins.link.core.OpenUrl', 875 [ 876 'tinymce.core.dom.DOMUtils', 877 'tinymce.core.Env' 878 ], 879 function (DOMUtils, Env) { 880 var appendClickRemove = function (link, evt) { 881 document.body.appendChild(link); 882 link.dispatchEvent(evt); 883 document.body.removeChild(link); 884 }; 885 886 var open = function (url) { 887 // Chrome and Webkit has implemented noopener and works correctly with/without popup blocker 888 // Firefox has it implemented noopener but when the popup blocker is activated it doesn't work 889 // Edge has only implemented noreferrer and it seems to remove opener as well 890 // Older IE versions pre IE 11 falls back to a window.open approach 891 if (!Env.ie || Env.ie > 10) { 892 var link = document.createElement('a'); 893 link.target = '_blank'; 894 link.href = url; 895 link.rel = 'noreferrer noopener'; 896 897 var evt = document.createEvent('MouseEvents'); 898 evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 899 900 appendClickRemove(link, evt); 901 } else { 902 var win = window.open('', '_blank'); 903 if (win) { 904 win.opener = null; 905 var doc = win.document; 906 doc.open(); 907 doc.write('<meta http-equiv="refresh" content="0; url=' + DOMUtils.DOM.encode(url) + '">'); 908 doc.close(); 909 } 910 } 911 }; 912 913 return { 914 open: open 915 }; 916 } 917 ); 918 /** 919 * Actions.js 920 * 921 * Released under LGPL License. 922 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 923 * 924 * License: http://www.tinymce.com/license 925 * Contributing: http://www.tinymce.com/contributing 926 */ 927 928 define( 929 'tinymce.plugins.link.core.Actions', 930 [ 931 'tinymce.core.util.VK', 932 'tinymce.plugins.link.ui.Dialog', 933 'tinymce.plugins.link.core.OpenUrl', 934 'tinymce.plugins.link.core.Utils', 935 'tinymce.plugins.link.core.Settings' 936 ], 937 function (VK, Dialog, OpenUrl, Utils, Settings) { 938 var getLink = function (editor, elm) { 939 return editor.dom.getParent(elm, 'a[href]'); 940 }; 941 942 var getSelectedLink = function (editor) { 943 return getLink(editor, editor.selection.getStart()); 944 }; 945 946 var getHref = function (elm) { 947 // Returns the real href value not the resolved a.href value 948 var href = elm.getAttribute('data-mce-href'); 949 return href ? href : elm.getAttribute('href'); 950 }; 951 952 var isContextMenuVisible = function (editor) { 953 var contextmenu = editor.plugins.contextmenu; 954 return contextmenu ? contextmenu.isContextMenuVisible() : false; 955 }; 956 957 var hasOnlyAltModifier = function (e) { 958 return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false; 959 }; 960 961 var gotoLink = function (editor, a) { 962 if (a) { 963 var href = getHref(a); 964 if (/^#/.test(href)) { 965 var targetEl = editor.$(href); 966 if (targetEl.length) { 967 editor.selection.scrollIntoView(targetEl[0], true); 968 } 969 } else { 970 OpenUrl.open(a.href); 971 } 972 } 973 }; 974 975 var openDialog = function (editor) { 976 return function () { 977 Dialog.open(editor); 978 }; 979 }; 980 981 var gotoSelectedLink = function (editor) { 982 return function () { 983 gotoLink(editor, getSelectedLink(editor)); 984 }; 985 }; 986 987 var leftClickedOnAHref = function (editor) { 988 return function (elm) { 989 var sel, rng, node; 990 if (Settings.hasContextToolbar(editor.settings) && !isContextMenuVisible(editor) && Utils.isLink(elm)) { 991 sel = editor.selection; 992 rng = sel.getRng(); 993 node = rng.startContainer; 994 // ignore cursor positions at the beginning/end (to make context toolbar less noisy) 995 if (node.nodeType == 3 && sel.isCollapsed() && rng.startOffset > 0 && rng.startOffset < node.data.length) { 996 return true; 997 } 998 } 999 return false; 1000 }; 1001 }; 1002 1003 var setupGotoLinks = function (editor) { 1004 editor.on('click', function (e) { 1005 var link = getLink(editor, e.target); 1006 if (link && VK.metaKeyPressed(e)) { 1007 e.preventDefault(); 1008 gotoLink(editor, link); 1009 } 1010 }); 1011 1012 editor.on('keydown', function (e) { 1013 var link = getSelectedLink(editor); 1014 if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) { 1015 e.preventDefault(); 1016 gotoLink(editor, link); 1017 } 1018 }); 1019 }; 1020 1021 var toggleActiveState = function (editor) { 1022 return function () { 1023 var self = this; 1024 editor.on('nodechange', function (e) { 1025 self.active(!editor.readonly && !!Utils.getAnchorElement(editor, e.element)); 1026 }); 1027 }; 1028 }; 1029 1030 var toggleViewLinkState = function (editor) { 1031 return function () { 1032 var self = this; 1033 1034 var toggleVisibility = function (e) { 1035 if (Utils.hasLinks(e.parents)) { 1036 self.show(); 1037 } else { 1038 self.hide(); 1039 } 1040 }; 1041 1042 if (!Utils.hasLinks(editor.dom.getParents(editor.selection.getStart()))) { 1043 self.hide(); 1044 } 1045 1046 editor.on('nodechange', toggleVisibility); 1047 1048 self.on('remove', function () { 1049 editor.off('nodechange', toggleVisibility); 1050 }); 1051 }; 1052 }; 1053 1054 return { 1055 openDialog: openDialog, 1056 gotoSelectedLink: gotoSelectedLink, 1057 leftClickedOnAHref: leftClickedOnAHref, 1058 setupGotoLinks: setupGotoLinks, 1059 toggleActiveState: toggleActiveState, 1060 toggleViewLinkState: toggleViewLinkState 1061 }; 1062 } 1063 ); 1064 /** 1065 * Controls.js 1066 * 1067 * Released under LGPL License. 1068 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 1069 * 1070 * License: http://www.tinymce.com/license 1071 * Contributing: http://www.tinymce.com/contributing 1072 */ 1073 1074 define( 1075 'tinymce.plugins.link.ui.Controls', 1076 [ 1077 'tinymce.plugins.link.core.Actions', 1078 'tinymce.plugins.link.core.Utils' 1079 ], 1080 function (Actions, Utils) { 1081 1082 var setupButtons = function (editor) { 1083 editor.addButton('link', { 1084 icon: 'link', 1085 tooltip: 'Insert/edit link', 1086 shortcut: 'Meta+K', 1087 onclick: Actions.openDialog(editor), 1088 onpostrender: Actions.toggleActiveState(editor) 1089 }); 1090 1091 editor.addButton('unlink', { 1092 icon: 'unlink', 1093 tooltip: 'Remove link', 1094 onclick: Utils.unlink(editor), 1095 onpostrender: Actions.toggleActiveState(editor) 1096 }); 1097 1098 if (editor.addContextToolbar) { 1099 editor.addButton('openlink', { 1100 icon: 'newtab', 1101 tooltip: 'Open link', 1102 onclick: Actions.gotoSelectedLink(editor) 1103 }); 1104 } 1105 }; 1106 1107 var setupMenuItems = function (editor) { 1108 editor.addMenuItem('openlink', { 1109 text: 'Open link', 1110 icon: 'newtab', 1111 onclick: Actions.gotoSelectedLink(editor), 1112 onPostRender: Actions.toggleViewLinkState(editor), 1113 prependToContext: true 1114 }); 1115 1116 editor.addMenuItem('link', { 1117 icon: 'link', 1118 text: 'Link', 1119 shortcut: 'Meta+K', 1120 onclick: Actions.openDialog(editor), 1121 stateSelector: 'a[href]', 1122 context: 'insert', 1123 prependToContext: true 1124 }); 1125 }; 1126 1127 var setupContextToolbars = function (editor) { 1128 if (editor.addContextToolbar) { 1129 editor.addContextToolbar( 1130 Actions.leftClickedOnAHref(editor), 1131 'openlink | link unlink' 1132 ); 1133 } 1134 }; 1135 1136 return { 1137 setupButtons: setupButtons, 1138 setupMenuItems: setupMenuItems, 1139 setupContextToolbars: setupContextToolbars 1140 }; 1141 } 1142 ); 1143 /** 1144 * Plugin.js 1145 * 1146 * Released under LGPL License. 1147 * Copyright (c) 1999-2017 Ephox Corp. All rights reserved 1148 * 1149 * License: http://www.tinymce.com/license 1150 * Contributing: http://www.tinymce.com/contributing 1151 */ 1152 1153 define( 1154 'tinymce.plugins.link.Plugin', 1155 [ 1156 'tinymce.core.PluginManager', 1157 'tinymce.plugins.link.core.Actions', 1158 'tinymce.plugins.link.ui.Controls' 1159 ], 1160 function (PluginManager, Actions, Controls) { 1161 PluginManager.add('link', function (editor) { 1162 Controls.setupButtons(editor); 1163 Controls.setupMenuItems(editor); 1164 Controls.setupContextToolbars(editor); 1165 Actions.setupGotoLinks(editor); 1166 editor.addShortcut('Meta+K', '', Actions.openDialog(editor)); 1167 editor.addCommand('mceLink', Actions.openDialog(editor)); 1168 }); 1169 1170 return function () { }; 1171 } 1172 ); 1173 dem('tinymce.plugins.link.Plugin')(); 1174 })(); -
wp-includes/js/tinymce/plugins/link/plugin.min.js
1 !function(){var a={},b=function(b){for(var c=a[b],e=c.deps,f=c.defn,g=e.length,h=new Array(g),i=0;i<g;++i)h[i]=d(e[i]);var j=f.apply(null,h);if(void 0===j)throw"module ["+b+"] returned undefined";c.instance=j},c=function(b,c,d){if("string"!=typeof b)throw"module id must be a string";if(void 0===c)throw"no dependencies for "+b;if(void 0===d)throw"no definition function for "+b;a[b]={deps:c,defn:d,instance:void 0}},d=function(c){var d=a[c];if(void 0===d)throw"module ["+c+"] was undefined";return void 0===d.instance&&b(c),d.instance},e=function(a,b){for(var c=a.length,e=new Array(c),f=0;f<c;++f)e.push(d(a[f]));b.apply(null,b)},f={};f.bolt={module:{api:{define:c,require:e,demand:d}}};var g=c,h=function(a,b){g(a,[],function(){return b})};h("4",tinymce.util.Tools.resolve),g("1",["4"],function(a){return a("tinymce.PluginManager")}),g("5",["4"],function(a){return a("tinymce.util.VK")}),g("a",["4"],function(a){return a("tinymce.util.Delay")}),g("b",["4"],function(a){return a("tinymce.util.Tools")}),g("c",["4"],function(a){return a("tinymce.util.XHR")}),g("9",[],function(){var a=function(a){return"boolean"==typeof a.link_assume_external_targets&&a.link_assume_external_targets},b=function(a){return"boolean"==typeof a.link_context_toolbar&&a.link_context_toolbar},c=function(a){return a.link_list},d=function(a){return"string"==typeof a.default_link_target},e=function(a){return a.default_link_target},f=function(a){return a.target_list},g=function(a,b){a.settings.target_list=b},h=function(a){return f(a)!==!1},i=function(a){return a.rel_list},j=function(a){return void 0!==i(a)},k=function(a){return a.link_class_list},l=function(a){return void 0!==k(a)},m=function(a){return a.link_title!==!1},n=function(a){return"boolean"==typeof a.allow_unsafe_link_target&&a.allow_unsafe_link_target};return{assumeExternalTargets:a,hasContextToolbar:b,getLinkList:c,hasDefaultLinkTarget:d,getDefaultLinkTarget:e,getTargetList:f,setTargetList:g,shouldShowTargetList:h,getRelList:i,hasRelList:j,getLinkClassList:k,hasLinkClassList:l,shouldShowLinkTitle:m,allowUnsafeLinkTarget:n}}),h("d",RegExp),g("8",["b","9","d"],function(a,b,c){var d=function(b,c){var d=["noopener"],e=b?b.split(/\s+/):[],f=function(b){return a.trim(b.sort().join(" "))},g=function(a){return a=h(a),a.length?a.concat(d):d},h=function(b){return b.filter(function(b){return a.inArray(d,b)===-1})};return e=c?g(e):h(e),e.length?f(e):null},e=function(a){return a.replace(/\uFEFF/g,"")},f=function(a,b){return b=b||a.selection.getStart(),k(b)?a.dom.select("a[href]",b)[0]:a.dom.getParent(b,"a[href]")},g=function(a,b){var c=b?b.innerText||b.textContent:a.getContent({format:"text"});return e(c)},h=function(a){return a&&"A"===a.nodeName&&a.href},i=function(b){return a.grep(b,h).length>0},j=function(a){return!(/</.test(a)&&(!/^<a [^>]+>[^<]+<\/a>$/.test(a)||a.indexOf("href=")==-1))},k=function(a){return a&&"FIGURE"===a.nodeName&&/\bimage\b/i.test(a.className)},l=function(a,c){return function(e){a.undoManager.transact(function(){var g=a.selection.getNode(),h=f(a,g),i={href:e.href,target:e.target?e.target:null,rel:e.rel?e.rel:null,"class":e["class"]?e["class"]:null,title:e.title?e.title:null};b.hasRelList(a.settings)||b.allowUnsafeLinkTarget(a.settings)!==!1||(i.rel=d(i.rel,"_blank"==i.target)),e.href===c.href&&(c.attach(),c={}),h?(a.focus(),e.hasOwnProperty("text")&&("innerText"in h?h.innerText=e.text:h.textContent=e.text),a.dom.setAttribs(h,i),a.selection.select(h),a.undoManager.add()):k(g)?o(a,g,i):e.hasOwnProperty("text")?a.insertContent(a.dom.createHTML("a",i,a.dom.encode(e.text))):a.execCommand("mceInsertLink",!1,i)})}},m=function(a){return function(){a.undoManager.transact(function(){var b=a.selection.getNode();k(b)?n(a,b):a.execCommand("unlink")})}},n=function(a,b){var c,d;d=a.dom.select("img",b)[0],d&&(c=a.dom.getParents(d,"a[href]",b)[0],c&&(c.parentNode.insertBefore(d,c),a.dom.remove(c)))},o=function(a,b,c){var d,e;e=a.dom.select("img",b)[0],e&&(d=a.dom.create("a",c),e.parentNode.insertBefore(d,e),d.appendChild(e))};return{link:l,unlink:m,isLink:h,hasLinks:i,isOnlyTextSelected:j,getAnchorElement:f,getAnchorText:g,toggleTargetRules:d}}),g("6",["a","b","c","8","9"],function(a,b,c,d,e){var f={},g=function(a,b){var d=e.getLinkList(a.settings);"string"==typeof d?c.send({url:d,success:function(c){b(a,JSON.parse(c))}}):"function"==typeof d?d(function(c){b(a,c)}):b(a,d)},h=function(a,c,d){var e=function(a,d){return d=d||[],b.each(a,function(a){var b={text:a.text||a.title};a.menu?b.menu=e(a.menu):(b.value=a.value,c&&c(b)),d.push(b)}),d};return e(a,d||[])},i=function(b,c,d){var e=b.selection.getRng();a.setEditorTimeout(b,function(){b.windowManager.confirm(c,function(a){b.selection.setRng(e),d(a)})})},j=function(a,c){var g,j,k,l,m,n,o,p,q,r,s,t={},u=a.selection,v=a.dom,w=function(a){var b=k.find("#text");(!b.value()||a.lastControl&&b.value()==a.lastControl.text())&&b.value(a.control.text()),k.find("#href").value(a.control.value())},x=function(c){var d=[];if(b.each(a.dom.select("a:not([href])"),function(a){var b=a.name||a.id;b&&d.push({text:b,value:"#"+b,selected:c.indexOf("#"+b)!=-1})}),d.length)return d.unshift({text:"None",value:""}),{name:"anchor",type:"listbox",label:"Anchors",values:d,onselect:w}},y=function(){j||!l||t.text||this.parent().parent().find("#text")[0].value(this.value())},z=function(c){var d=c.meta||{};n&&n.value(a.convertURL(this.value(),"href")),b.each(c.meta,function(a,b){var c=k.find("#"+b);"text"===b?0===j.length&&(c.value(a),t.text=a):c.value(a)}),d.attach&&(f={href:this.value(),attach:d.attach}),d.text||y.call(this)},A=function(a){a.meta=k.toJSON()};l=d.isOnlyTextSelected(u.getContent()),g=d.getAnchorElement(a),t.text=j=d.getAnchorText(a.selection,g),t.href=g?v.getAttrib(g,"href"):"",g?t.target=v.getAttrib(g,"target"):e.hasDefaultLinkTarget(a.settings)&&(t.target=e.getDefaultLinkTarget(a.settings)),(s=v.getAttrib(g,"rel"))&&(t.rel=s),(s=v.getAttrib(g,"class"))&&(t["class"]=s),(s=v.getAttrib(g,"title"))&&(t.title=s),l&&(m={name:"text",type:"textbox",size:40,label:"Text to display",onchange:function(){t.text=this.value()}}),c&&(n={type:"listbox",label:"Link list",values:h(c,function(b){b.value=a.convertURL(b.value||b.url,"href")},[{text:"None",value:""}]),onselect:w,value:a.convertURL(t.href,"href"),onPostRender:function(){n=this}}),e.shouldShowTargetList(a.settings)&&(void 0===e.getTargetList(a.settings)&&e.setTargetList(a,[{text:"None",value:""},{text:"New window",value:"_blank"}]),p={name:"target",type:"listbox",label:"Target",values:h(e.getTargetList(a.settings))}),e.hasRelList(a.settings)&&(o={name:"rel",type:"listbox",label:"Rel",values:h(e.getRelList(a.settings),function(b){e.allowUnsafeLinkTarget(a.settings)===!1&&(b.value=d.toggleTargetRules(b.value,"_blank"===t.target))})}),e.hasLinkClassList(a.settings)&&(q={name:"class",type:"listbox",label:"Class",values:h(e.getLinkClassList(a.settings),function(b){b.value&&(b.textStyle=function(){return a.formatter.getCssText({inline:"a",classes:[b.value]})})})}),e.shouldShowLinkTitle(a.settings)&&(r={name:"title",type:"textbox",label:"Title",value:t.title}),k=a.windowManager.open({title:"Insert link",data:t,body:[{name:"href",type:"filepicker",filetype:"file",size:40,autofocus:!0,label:"Url",onchange:z,onkeyup:y,onbeforecall:A},m,r,x(t.href),n,o,p,q],onSubmit:function(c){var g=e.assumeExternalTargets(a.settings),h=d.link(a,f),k=d.unlink(a),m=b.extend({},t,c.data),n=m.href;return n?(l&&m.text!==j||delete m.text,n.indexOf("@")>0&&n.indexOf("//")==-1&&n.indexOf("mailto:")==-1?void i(a,"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",function(a){a&&(m.href="mailto:"+n),h(m)}):g===!0&&!/^\w+:/i.test(n)||g===!1&&/^\s*www[\.|\d\.]/i.test(n)?void i(a,"The URL you entered seems to be an external link. Do you want to add the required http:// prefix?",function(a){a&&(m.href="http://"+n),h(m)}):void h(m)):void k()}})},k=function(a){g(a,j)};return{open:k}}),g("e",["4"],function(a){return a("tinymce.dom.DOMUtils")}),g("f",["4"],function(a){return a("tinymce.Env")}),g("7",["e","f"],function(a,b){var c=function(a,b){document.body.appendChild(a),a.dispatchEvent(b),document.body.removeChild(a)},d=function(d){if(!b.ie||b.ie>10){var e=document.createElement("a");e.target="_blank",e.href=d,e.rel="noreferrer noopener";var f=document.createEvent("MouseEvents");f.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),c(e,f)}else{var g=window.open("","_blank");if(g){g.opener=null;var h=g.document;h.open(),h.write('<meta http-equiv="refresh" content="0; url='+a.DOM.encode(d)+'">'),h.close()}}};return{open:d}}),g("2",["5","6","7","8","9"],function(a,b,c,d,e){var f=function(a,b){return a.dom.getParent(b,"a[href]")},g=function(a){return f(a,a.selection.getStart())},h=function(a){var b=a.getAttribute("data-mce-href");return b?b:a.getAttribute("href")},i=function(a){var b=a.plugins.contextmenu;return!!b&&b.isContextMenuVisible()},j=function(a){return a.altKey===!0&&a.shiftKey===!1&&a.ctrlKey===!1&&a.metaKey===!1},k=function(a,b){if(b){var d=h(b);if(/^#/.test(d)){var e=a.$(d);e.length&&a.selection.scrollIntoView(e[0],!0)}else c.open(b.href)}},l=function(a){return function(){b.open(a)}},m=function(a){return function(){k(a,g(a))}},n=function(a){return function(b){var c,f,g;return!!(e.hasContextToolbar(a.settings)&&!i(a)&&d.isLink(b)&&(c=a.selection,f=c.getRng(),g=f.startContainer,3==g.nodeType&&c.isCollapsed()&&f.startOffset>0&&f.startOffset<g.data.length))}},o=function(b){b.on("click",function(c){var d=f(b,c.target);d&&a.metaKeyPressed(c)&&(c.preventDefault(),k(b,d))}),b.on("keydown",function(a){var c=g(b);c&&13===a.keyCode&&j(a)&&(a.preventDefault(),k(b,c))})},p=function(a){return function(){var b=this;a.on("nodechange",function(c){b.active(!a.readonly&&!!d.getAnchorElement(a,c.element))})}},q=function(a){return function(){var b=this,c=function(a){d.hasLinks(a.parents)?b.show():b.hide()};d.hasLinks(a.dom.getParents(a.selection.getStart()))||b.hide(),a.on("nodechange",c),b.on("remove",function(){a.off("nodechange",c)})}};return{openDialog:l,gotoSelectedLink:m,leftClickedOnAHref:n,setupGotoLinks:o,toggleActiveState:p,toggleViewLinkState:q}}),g("3",["2","8"],function(a,b){var c=function(c){c.addButton("link",{icon:"link",tooltip:"Insert/edit link",shortcut:"Meta+K",onclick:a.openDialog(c),onpostrender:a.toggleActiveState(c)}),c.addButton("unlink",{icon:"unlink",tooltip:"Remove link",onclick:b.unlink(c),onpostrender:a.toggleActiveState(c)}),c.addContextToolbar&&c.addButton("openlink",{icon:"newtab",tooltip:"Open link",onclick:a.gotoSelectedLink(c)})},d=function(b){b.addMenuItem("openlink",{text:"Open link",icon:"newtab",onclick:a.gotoSelectedLink(b),onPostRender:a.toggleViewLinkState(b),prependToContext:!0}),b.addMenuItem("link",{icon:"link",text:"Link",shortcut:"Meta+K",onclick:a.openDialog(b),stateSelector:"a[href]",context:"insert",prependToContext:!0})},e=function(b){b.addContextToolbar&&b.addContextToolbar(a.leftClickedOnAHref(b),"openlink | link unlink")};return{setupButtons:c,setupMenuItems:d,setupContextToolbars:e}}),g("0",["1","2","3"],function(a,b,c){return a.add("link",function(a){c.setupButtons(a),c.setupMenuItems(a),c.setupContextToolbars(a),b.setupGotoLinks(a),a.addShortcut("Meta+K","",b.openDialog(a)),a.addCommand("mceLink",b.openDialog(a))}),function(){}}),d("0")()}(); 2 No newline at end of file