[ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 (function () { 2 var link = (function (domGlobals) { 3 'use strict'; 4 5 var global = tinymce.util.Tools.resolve('tinymce.PluginManager'); 6 7 var global$1 = tinymce.util.Tools.resolve('tinymce.util.VK'); 8 9 var assumeExternalTargets = function (editorSettings) { 10 return typeof editorSettings.link_assume_external_targets === 'boolean' ? editorSettings.link_assume_external_targets : false; 11 }; 12 var hasContextToolbar = function (editorSettings) { 13 return typeof editorSettings.link_context_toolbar === 'boolean' ? editorSettings.link_context_toolbar : false; 14 }; 15 var getLinkList = function (editorSettings) { 16 return editorSettings.link_list; 17 }; 18 var hasDefaultLinkTarget = function (editorSettings) { 19 return typeof editorSettings.default_link_target === 'string'; 20 }; 21 var getDefaultLinkTarget = function (editorSettings) { 22 return editorSettings.default_link_target; 23 }; 24 var getTargetList = function (editorSettings) { 25 return editorSettings.target_list; 26 }; 27 var setTargetList = function (editor, list) { 28 editor.settings.target_list = list; 29 }; 30 var shouldShowTargetList = function (editorSettings) { 31 return getTargetList(editorSettings) !== false; 32 }; 33 var getRelList = function (editorSettings) { 34 return editorSettings.rel_list; 35 }; 36 var hasRelList = function (editorSettings) { 37 return getRelList(editorSettings) !== undefined; 38 }; 39 var getLinkClassList = function (editorSettings) { 40 return editorSettings.link_class_list; 41 }; 42 var hasLinkClassList = function (editorSettings) { 43 return getLinkClassList(editorSettings) !== undefined; 44 }; 45 var shouldShowLinkTitle = function (editorSettings) { 46 return editorSettings.link_title !== false; 47 }; 48 var allowUnsafeLinkTarget = function (editorSettings) { 49 return typeof editorSettings.allow_unsafe_link_target === 'boolean' ? editorSettings.allow_unsafe_link_target : false; 50 }; 51 var Settings = { 52 assumeExternalTargets: assumeExternalTargets, 53 hasContextToolbar: hasContextToolbar, 54 getLinkList: getLinkList, 55 hasDefaultLinkTarget: hasDefaultLinkTarget, 56 getDefaultLinkTarget: getDefaultLinkTarget, 57 getTargetList: getTargetList, 58 setTargetList: setTargetList, 59 shouldShowTargetList: shouldShowTargetList, 60 getRelList: getRelList, 61 hasRelList: hasRelList, 62 getLinkClassList: getLinkClassList, 63 hasLinkClassList: hasLinkClassList, 64 shouldShowLinkTitle: shouldShowLinkTitle, 65 allowUnsafeLinkTarget: allowUnsafeLinkTarget 66 }; 67 68 var global$2 = tinymce.util.Tools.resolve('tinymce.dom.DOMUtils'); 69 70 var global$3 = tinymce.util.Tools.resolve('tinymce.Env'); 71 72 var appendClickRemove = function (link, evt) { 73 domGlobals.document.body.appendChild(link); 74 link.dispatchEvent(evt); 75 domGlobals.document.body.removeChild(link); 76 }; 77 var open = function (url) { 78 if (!global$3.ie || global$3.ie > 10) { 79 var link = domGlobals.document.createElement('a'); 80 link.target = '_blank'; 81 link.href = url; 82 link.rel = 'noreferrer noopener'; 83 var evt = domGlobals.document.createEvent('MouseEvents'); 84 evt.initMouseEvent('click', true, true, domGlobals.window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); 85 appendClickRemove(link, evt); 86 } else { 87 var win = domGlobals.window.open('', '_blank'); 88 if (win) { 89 win.opener = null; 90 var doc = win.document; 91 doc.open(); 92 doc.write('<meta http-equiv="refresh" content="0; url=' + global$2.DOM.encode(url) + '">'); 93 doc.close(); 94 } 95 } 96 }; 97 var OpenUrl = { open: open }; 98 99 var global$4 = tinymce.util.Tools.resolve('tinymce.util.Tools'); 100 101 var toggleTargetRules = function (rel, isUnsafe) { 102 var rules = ['noopener']; 103 var newRel = rel ? rel.split(/\s+/) : []; 104 var toString = function (rel) { 105 return global$4.trim(rel.sort().join(' ')); 106 }; 107 var addTargetRules = function (rel) { 108 rel = removeTargetRules(rel); 109 return rel.length ? rel.concat(rules) : rules; 110 }; 111 var removeTargetRules = function (rel) { 112 return rel.filter(function (val) { 113 return global$4.inArray(rules, val) === -1; 114 }); 115 }; 116 newRel = isUnsafe ? addTargetRules(newRel) : removeTargetRules(newRel); 117 return newRel.length ? toString(newRel) : null; 118 }; 119 var trimCaretContainers = function (text) { 120 return text.replace(/\uFEFF/g, ''); 121 }; 122 var getAnchorElement = function (editor, selectedElm) { 123 selectedElm = selectedElm || editor.selection.getNode(); 124 if (isImageFigure(selectedElm)) { 125 return editor.dom.select('a[href]', selectedElm)[0]; 126 } else { 127 return editor.dom.getParent(selectedElm, 'a[href]'); 128 } 129 }; 130 var getAnchorText = function (selection, anchorElm) { 131 var text = anchorElm ? anchorElm.innerText || anchorElm.textContent : selection.getContent({ format: 'text' }); 132 return trimCaretContainers(text); 133 }; 134 var isLink = function (elm) { 135 return elm && elm.nodeName === 'A' && elm.href; 136 }; 137 var hasLinks = function (elements) { 138 return global$4.grep(elements, isLink).length > 0; 139 }; 140 var isOnlyTextSelected = function (html) { 141 if (/</.test(html) && (!/^<a [^>]+>[^<]+<\/a>$/.test(html) || html.indexOf('href=') === -1)) { 142 return false; 143 } 144 return true; 145 }; 146 var isImageFigure = function (node) { 147 return node && node.nodeName === 'FIGURE' && /\bimage\b/i.test(node.className); 148 }; 149 var link = function (editor, attachState) { 150 return function (data) { 151 editor.undoManager.transact(function () { 152 var selectedElm = editor.selection.getNode(); 153 var anchorElm = getAnchorElement(editor, selectedElm); 154 var linkAttrs = { 155 href: data.href, 156 target: data.target ? data.target : null, 157 rel: data.rel ? data.rel : null, 158 class: data.class ? data.class : null, 159 title: data.title ? data.title : null 160 }; 161 if (!Settings.hasRelList(editor.settings) && Settings.allowUnsafeLinkTarget(editor.settings) === false) { 162 linkAttrs.rel = toggleTargetRules(linkAttrs.rel, linkAttrs.target === '_blank'); 163 } 164 if (data.href === attachState.href) { 165 attachState.attach(); 166 attachState = {}; 167 } 168 if (anchorElm) { 169 editor.focus(); 170 if (data.hasOwnProperty('text')) { 171 if ('innerText' in anchorElm) { 172 anchorElm.innerText = data.text; 173 } else { 174 anchorElm.textContent = data.text; 175 } 176 } 177 editor.dom.setAttribs(anchorElm, linkAttrs); 178 editor.selection.select(anchorElm); 179 editor.undoManager.add(); 180 } else { 181 if (isImageFigure(selectedElm)) { 182 linkImageFigure(editor, selectedElm, linkAttrs); 183 } else if (data.hasOwnProperty('text')) { 184 editor.insertContent(editor.dom.createHTML('a', linkAttrs, editor.dom.encode(data.text))); 185 } else { 186 editor.execCommand('mceInsertLink', false, linkAttrs); 187 } 188 } 189 }); 190 }; 191 }; 192 var unlink = function (editor) { 193 return function () { 194 editor.undoManager.transact(function () { 195 var node = editor.selection.getNode(); 196 if (isImageFigure(node)) { 197 unlinkImageFigure(editor, node); 198 } else { 199 editor.execCommand('unlink'); 200 } 201 }); 202 }; 203 }; 204 var unlinkImageFigure = function (editor, fig) { 205 var a, img; 206 img = editor.dom.select('img', fig)[0]; 207 if (img) { 208 a = editor.dom.getParents(img, 'a[href]', fig)[0]; 209 if (a) { 210 a.parentNode.insertBefore(img, a); 211 editor.dom.remove(a); 212 } 213 } 214 }; 215 var linkImageFigure = function (editor, fig, attrs) { 216 var a, img; 217 img = editor.dom.select('img', fig)[0]; 218 if (img) { 219 a = editor.dom.create('a', attrs); 220 img.parentNode.insertBefore(a, img); 221 a.appendChild(img); 222 } 223 }; 224 var Utils = { 225 link: link, 226 unlink: unlink, 227 isLink: isLink, 228 hasLinks: hasLinks, 229 isOnlyTextSelected: isOnlyTextSelected, 230 getAnchorElement: getAnchorElement, 231 getAnchorText: getAnchorText, 232 toggleTargetRules: toggleTargetRules 233 }; 234 235 var global$5 = tinymce.util.Tools.resolve('tinymce.util.Delay'); 236 237 var global$6 = tinymce.util.Tools.resolve('tinymce.util.XHR'); 238 239 var attachState = {}; 240 var createLinkList = function (editor, callback) { 241 var linkList = Settings.getLinkList(editor.settings); 242 if (typeof linkList === 'string') { 243 global$6.send({ 244 url: linkList, 245 success: function (text) { 246 callback(editor, JSON.parse(text)); 247 } 248 }); 249 } else if (typeof linkList === 'function') { 250 linkList(function (list) { 251 callback(editor, list); 252 }); 253 } else { 254 callback(editor, linkList); 255 } 256 }; 257 var buildListItems = function (inputList, itemCallback, startItems) { 258 var appendItems = function (values, output) { 259 output = output || []; 260 global$4.each(values, function (item) { 261 var menuItem = { text: item.text || item.title }; 262 if (item.menu) { 263 menuItem.menu = appendItems(item.menu); 264 } else { 265 menuItem.value = item.value; 266 if (itemCallback) { 267 itemCallback(menuItem); 268 } 269 } 270 output.push(menuItem); 271 }); 272 return output; 273 }; 274 return appendItems(inputList, startItems || []); 275 }; 276 var delayedConfirm = function (editor, message, callback) { 277 var rng = editor.selection.getRng(); 278 global$5.setEditorTimeout(editor, function () { 279 editor.windowManager.confirm(message, function (state) { 280 editor.selection.setRng(rng); 281 callback(state); 282 }); 283 }); 284 }; 285 var showDialog = function (editor, linkList) { 286 var data = {}; 287 var selection = editor.selection; 288 var dom = editor.dom; 289 var anchorElm, initialText; 290 var win, onlyText, textListCtrl, linkListCtrl, relListCtrl, targetListCtrl, classListCtrl, linkTitleCtrl, value; 291 var linkListChangeHandler = function (e) { 292 var textCtrl = win.find('#text'); 293 if (!textCtrl.value() || e.lastControl && textCtrl.value() === e.lastControl.text()) { 294 textCtrl.value(e.control.text()); 295 } 296 win.find('#href').value(e.control.value()); 297 }; 298 var buildAnchorListControl = function (url) { 299 var anchorList = []; 300 global$4.each(editor.dom.select('a:not([href])'), function (anchor) { 301 var id = anchor.name || anchor.id; 302 if (id) { 303 anchorList.push({ 304 text: id, 305 value: '#' + id, 306 selected: url.indexOf('#' + id) !== -1 307 }); 308 } 309 }); 310 if (anchorList.length) { 311 anchorList.unshift({ 312 text: 'None', 313 value: '' 314 }); 315 return { 316 name: 'anchor', 317 type: 'listbox', 318 label: 'Anchors', 319 values: anchorList, 320 onselect: linkListChangeHandler 321 }; 322 } 323 }; 324 var updateText = function () { 325 if (!initialText && onlyText && !data.text) { 326 this.parent().parent().find('#text')[0].value(this.value()); 327 } 328 }; 329 var urlChange = function (e) { 330 var meta = e.meta || {}; 331 if (linkListCtrl) { 332 linkListCtrl.value(editor.convertURL(this.value(), 'href')); 333 } 334 global$4.each(e.meta, function (value, key) { 335 var inp = win.find('#' + key); 336 if (key === 'text') { 337 if (initialText.length === 0) { 338 inp.value(value); 339 data.text = value; 340 } 341 } else { 342 inp.value(value); 343 } 344 }); 345 if (meta.attach) { 346 attachState = { 347 href: this.value(), 348 attach: meta.attach 349 }; 350 } 351 if (!meta.text) { 352 updateText.call(this); 353 } 354 }; 355 var onBeforeCall = function (e) { 356 e.meta = win.toJSON(); 357 }; 358 onlyText = Utils.isOnlyTextSelected(selection.getContent()); 359 anchorElm = Utils.getAnchorElement(editor); 360 data.text = initialText = Utils.getAnchorText(editor.selection, anchorElm); 361 data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; 362 if (anchorElm) { 363 data.target = dom.getAttrib(anchorElm, 'target'); 364 } else if (Settings.hasDefaultLinkTarget(editor.settings)) { 365 data.target = Settings.getDefaultLinkTarget(editor.settings); 366 } 367 if (value = dom.getAttrib(anchorElm, 'rel')) { 368 data.rel = value; 369 } 370 if (value = dom.getAttrib(anchorElm, 'class')) { 371 data.class = value; 372 } 373 if (value = dom.getAttrib(anchorElm, 'title')) { 374 data.title = value; 375 } 376 if (onlyText) { 377 textListCtrl = { 378 name: 'text', 379 type: 'textbox', 380 size: 40, 381 label: 'Text to display', 382 onchange: function () { 383 data.text = this.value(); 384 } 385 }; 386 } 387 if (linkList) { 388 linkListCtrl = { 389 type: 'listbox', 390 label: 'Link list', 391 values: buildListItems(linkList, function (item) { 392 item.value = editor.convertURL(item.value || item.url, 'href'); 393 }, [{ 394 text: 'None', 395 value: '' 396 }]), 397 onselect: linkListChangeHandler, 398 value: editor.convertURL(data.href, 'href'), 399 onPostRender: function () { 400 linkListCtrl = this; 401 } 402 }; 403 } 404 if (Settings.shouldShowTargetList(editor.settings)) { 405 if (Settings.getTargetList(editor.settings) === undefined) { 406 Settings.setTargetList(editor, [ 407 { 408 text: 'None', 409 value: '' 410 }, 411 { 412 text: 'New window', 413 value: '_blank' 414 } 415 ]); 416 } 417 targetListCtrl = { 418 name: 'target', 419 type: 'listbox', 420 label: 'Target', 421 values: buildListItems(Settings.getTargetList(editor.settings)) 422 }; 423 } 424 if (Settings.hasRelList(editor.settings)) { 425 relListCtrl = { 426 name: 'rel', 427 type: 'listbox', 428 label: 'Rel', 429 values: buildListItems(Settings.getRelList(editor.settings), function (item) { 430 if (Settings.allowUnsafeLinkTarget(editor.settings) === false) { 431 item.value = Utils.toggleTargetRules(item.value, data.target === '_blank'); 432 } 433 }) 434 }; 435 } 436 if (Settings.hasLinkClassList(editor.settings)) { 437 classListCtrl = { 438 name: 'class', 439 type: 'listbox', 440 label: 'Class', 441 values: buildListItems(Settings.getLinkClassList(editor.settings), function (item) { 442 if (item.value) { 443 item.textStyle = function () { 444 return editor.formatter.getCssText({ 445 inline: 'a', 446 classes: [item.value] 447 }); 448 }; 449 } 450 }) 451 }; 452 } 453 if (Settings.shouldShowLinkTitle(editor.settings)) { 454 linkTitleCtrl = { 455 name: 'title', 456 type: 'textbox', 457 label: 'Title', 458 value: data.title 459 }; 460 } 461 win = editor.windowManager.open({ 462 title: 'Insert link', 463 data: data, 464 body: [ 465 { 466 name: 'href', 467 type: 'filepicker', 468 filetype: 'file', 469 size: 40, 470 autofocus: true, 471 label: 'Url', 472 onchange: urlChange, 473 onkeyup: updateText, 474 onpaste: updateText, 475 onbeforecall: onBeforeCall 476 }, 477 textListCtrl, 478 linkTitleCtrl, 479 buildAnchorListControl(data.href), 480 linkListCtrl, 481 relListCtrl, 482 targetListCtrl, 483 classListCtrl 484 ], 485 onSubmit: function (e) { 486 var assumeExternalTargets = Settings.assumeExternalTargets(editor.settings); 487 var insertLink = Utils.link(editor, attachState); 488 var removeLink = Utils.unlink(editor); 489 var resultData = global$4.extend({}, data, e.data); 490 var href = resultData.href; 491 if (!href) { 492 removeLink(); 493 return; 494 } 495 if (!onlyText || resultData.text === initialText) { 496 delete resultData.text; 497 } 498 if (href.indexOf('@') > 0 && href.indexOf('//') === -1 && href.indexOf('mailto:') === -1) { 499 delayedConfirm(editor, 'The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?', function (state) { 500 if (state) { 501 resultData.href = 'mailto:' + href; 502 } 503 insertLink(resultData); 504 }); 505 return; 506 } 507 if (assumeExternalTargets === true && !/^\w+:/i.test(href) || assumeExternalTargets === false && /^\s*www[\.|\d\.]/i.test(href)) { 508 delayedConfirm(editor, 'The URL you entered seems to be an external link. Do you want to add the required http:// prefix?', function (state) { 509 if (state) { 510 resultData.href = 'http://' + href; 511 } 512 insertLink(resultData); 513 }); 514 return; 515 } 516 insertLink(resultData); 517 } 518 }); 519 }; 520 var open$1 = function (editor) { 521 createLinkList(editor, showDialog); 522 }; 523 var Dialog = { open: open$1 }; 524 525 var getLink = function (editor, elm) { 526 return editor.dom.getParent(elm, 'a[href]'); 527 }; 528 var getSelectedLink = function (editor) { 529 return getLink(editor, editor.selection.getStart()); 530 }; 531 var getHref = function (elm) { 532 var href = elm.getAttribute('data-mce-href'); 533 return href ? href : elm.getAttribute('href'); 534 }; 535 var isContextMenuVisible = function (editor) { 536 var contextmenu = editor.plugins.contextmenu; 537 return contextmenu ? contextmenu.isContextMenuVisible() : false; 538 }; 539 var hasOnlyAltModifier = function (e) { 540 return e.altKey === true && e.shiftKey === false && e.ctrlKey === false && e.metaKey === false; 541 }; 542 var gotoLink = function (editor, a) { 543 if (a) { 544 var href = getHref(a); 545 if (/^#/.test(href)) { 546 var targetEl = editor.$(href); 547 if (targetEl.length) { 548 editor.selection.scrollIntoView(targetEl[0], true); 549 } 550 } else { 551 OpenUrl.open(a.href); 552 } 553 } 554 }; 555 var openDialog = function (editor) { 556 return function () { 557 Dialog.open(editor); 558 }; 559 }; 560 var gotoSelectedLink = function (editor) { 561 return function () { 562 gotoLink(editor, getSelectedLink(editor)); 563 }; 564 }; 565 var leftClickedOnAHref = function (editor) { 566 return function (elm) { 567 var sel, rng, node; 568 if (Settings.hasContextToolbar(editor.settings) && !isContextMenuVisible(editor) && Utils.isLink(elm)) { 569 sel = editor.selection; 570 rng = sel.getRng(); 571 node = rng.startContainer; 572 if (node.nodeType === 3 && sel.isCollapsed() && rng.startOffset > 0 && rng.startOffset < node.data.length) { 573 return true; 574 } 575 } 576 return false; 577 }; 578 }; 579 var setupGotoLinks = function (editor) { 580 editor.on('click', function (e) { 581 var link = getLink(editor, e.target); 582 if (link && global$1.metaKeyPressed(e)) { 583 e.preventDefault(); 584 gotoLink(editor, link); 585 } 586 }); 587 editor.on('keydown', function (e) { 588 var link = getSelectedLink(editor); 589 if (link && e.keyCode === 13 && hasOnlyAltModifier(e)) { 590 e.preventDefault(); 591 gotoLink(editor, link); 592 } 593 }); 594 }; 595 var toggleActiveState = function (editor) { 596 return function () { 597 var self = this; 598 editor.on('nodechange', function (e) { 599 self.active(!editor.readonly && !!Utils.getAnchorElement(editor, e.element)); 600 }); 601 }; 602 }; 603 var toggleViewLinkState = function (editor) { 604 return function () { 605 var self = this; 606 var toggleVisibility = function (e) { 607 if (Utils.hasLinks(e.parents)) { 608 self.show(); 609 } else { 610 self.hide(); 611 } 612 }; 613 if (!Utils.hasLinks(editor.dom.getParents(editor.selection.getStart()))) { 614 self.hide(); 615 } 616 editor.on('nodechange', toggleVisibility); 617 self.on('remove', function () { 618 editor.off('nodechange', toggleVisibility); 619 }); 620 }; 621 }; 622 var Actions = { 623 openDialog: openDialog, 624 gotoSelectedLink: gotoSelectedLink, 625 leftClickedOnAHref: leftClickedOnAHref, 626 setupGotoLinks: setupGotoLinks, 627 toggleActiveState: toggleActiveState, 628 toggleViewLinkState: toggleViewLinkState 629 }; 630 631 var register = function (editor) { 632 editor.addCommand('mceLink', Actions.openDialog(editor)); 633 }; 634 var Commands = { register: register }; 635 636 var setup = function (editor) { 637 editor.addShortcut('Meta+K', '', Actions.openDialog(editor)); 638 }; 639 var Keyboard = { setup: setup }; 640 641 var setupButtons = function (editor) { 642 editor.addButton('link', { 643 active: false, 644 icon: 'link', 645 tooltip: 'Insert/edit link', 646 onclick: Actions.openDialog(editor), 647 onpostrender: Actions.toggleActiveState(editor) 648 }); 649 editor.addButton('unlink', { 650 active: false, 651 icon: 'unlink', 652 tooltip: 'Remove link', 653 onclick: Utils.unlink(editor), 654 onpostrender: Actions.toggleActiveState(editor) 655 }); 656 if (editor.addContextToolbar) { 657 editor.addButton('openlink', { 658 icon: 'newtab', 659 tooltip: 'Open link', 660 onclick: Actions.gotoSelectedLink(editor) 661 }); 662 } 663 }; 664 var setupMenuItems = function (editor) { 665 editor.addMenuItem('openlink', { 666 text: 'Open link', 667 icon: 'newtab', 668 onclick: Actions.gotoSelectedLink(editor), 669 onPostRender: Actions.toggleViewLinkState(editor), 670 prependToContext: true 671 }); 672 editor.addMenuItem('link', { 673 icon: 'link', 674 text: 'Link', 675 shortcut: 'Meta+K', 676 onclick: Actions.openDialog(editor), 677 stateSelector: 'a[href]', 678 context: 'insert', 679 prependToContext: true 680 }); 681 editor.addMenuItem('unlink', { 682 icon: 'unlink', 683 text: 'Remove link', 684 onclick: Utils.unlink(editor), 685 stateSelector: 'a[href]' 686 }); 687 }; 688 var setupContextToolbars = function (editor) { 689 if (editor.addContextToolbar) { 690 editor.addContextToolbar(Actions.leftClickedOnAHref(editor), 'openlink | link unlink'); 691 } 692 }; 693 var Controls = { 694 setupButtons: setupButtons, 695 setupMenuItems: setupMenuItems, 696 setupContextToolbars: setupContextToolbars 697 }; 698 699 global.add('link', function (editor) { 700 Controls.setupButtons(editor); 701 Controls.setupMenuItems(editor); 702 Controls.setupContextToolbars(editor); 703 Actions.setupGotoLinks(editor); 704 Commands.register(editor); 705 Keyboard.setup(editor); 706 }); 707 function Plugin () { 708 } 709 710 return Plugin; 711 712 }(window)); 713 })();
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated : Wed Dec 25 08:20:01 2024 | Cross-referenced by PHPXref |