/** * Umbraco Link Plugin, based on the original link plugin by MoxieCode * swapped out the dialog implementation with our own dialog service * and support for passing in localLinks */ /*global tinymce:true */ tinymce.PluginManager.add('umbracolink', function(editor) { function createLinkList(callback) { return function() { var linkList = editor.settings.link_list; if (typeof(linkList) == "string") { tinymce.util.XHR.send({ url: linkList, success: function(text) { callback(tinymce.util.JSON.parse(text)); } }); } else { callback(linkList); } }; } function showDialog(linkList) { var data = {}, selection = editor.selection, dom = editor.dom, selectedElm, anchorElm, initialText; var win, linkListCtrl, relListCtrl, targetListCtrl; function linkListChangeHandler(e) { var textCtrl = win.find('#text'); if (!textCtrl.value() || (e.lastControl && textCtrl.value() == e.lastControl.text())) { textCtrl.value(e.control.text()); } win.find('#href').value(e.control.value()); } function buildLinkList() { var linkListItems = [{text: 'None', value: ''}]; tinymce.each(linkList, function(link) { linkListItems.push({ text: link.text || link.title, value: link.value || link.url, menu: link.menu }); }); return linkListItems; } function buildRelList(relValue) { var relListItems = [{text: 'None', value: ''}]; tinymce.each(editor.settings.rel_list, function(rel) { relListItems.push({ text: rel.text || rel.title, value: rel.value, selected: relValue === rel.value }); }); return relListItems; } function buildTargetList(targetValue) { var targetListItems = [{text: 'None', value: ''}]; if (!editor.settings.target_list) { targetListItems.push({text: 'New window', value: '_blank'}); } tinymce.each(editor.settings.target_list, function(target) { targetListItems.push({ text: target.text || target.title, value: target.value, selected: targetValue === target.value }); }); return targetListItems; } function buildAnchorListControl(url) { var anchorList = []; tinymce.each(editor.dom.select('a:not([href])'), function(anchor) { var id = anchor.name || anchor.id; if (id) { anchorList.push({ text: id, value: '#' + id, selected: url.indexOf('#' + id) != -1 }); } }); if (anchorList.length) { anchorList.unshift({text: 'None', value: ''}); return { name: 'anchor', type: 'listbox', label: 'Anchors', values: anchorList, onselect: linkListChangeHandler }; } } function updateText() { if (!initialText && data.text.length === 0) { this.parent().parent().find('#text')[0].value(this.value()); } } selectedElm = selection.getNode(); anchorElm = dom.getParent(selectedElm, 'a[href]'); data.text = initialText = anchorElm ? (anchorElm.innerText || anchorElm.textContent) : selection.getContent({format: 'text'}); data.href = anchorElm ? dom.getAttrib(anchorElm, 'href') : ''; data.target = anchorElm ? dom.getAttrib(anchorElm, 'target') : ''; data.rel = anchorElm ? dom.getAttrib(anchorElm, 'rel') : ''; if (selectedElm.nodeName == "IMG") { data.text = initialText = " "; } if (linkList) { linkListCtrl = { type: 'listbox', label: 'Link list', values: buildLinkList(), onselect: linkListChangeHandler }; } if (editor.settings.target_list !== false) { targetListCtrl = { name: 'target', type: 'listbox', label: 'Target', values: buildTargetList(data.target) }; } if (editor.settings.rel_list) { relListCtrl = { name: 'rel', type: 'listbox', label: 'Rel', values: buildRelList(data.rel) }; } var injector = angular.element(document.getElementById("umbracoMainPageBody")).injector(); var dialogService = injector.get("dialogService"); var currentTarget = undefined; //if we already have a link selected, we want to pass that data over to the dialog if(anchorElm){ var anchor = $(anchorElm); currentTarget = { name: anchor.attr("title"), url: anchor.attr("href"), target: anchor.attr("target") }; //locallink detection, we do this here, to avoid poluting the dialogservice //so the dialog service can just expect to get a node-like structure if(currentTarget.url.indexOf("localLink:") > 0){ currentTarget.id = currentTarget.url.substring(currentTarget.url.indexOf(":")+1,currentTarget.url.length-1); } } dialogService.linkPicker({ currentTarget: currentTarget, callback: function (data) { if (data) { var href = data.url; function insertLink() { if (anchorElm) { dom.setAttribs(anchorElm, { href: href, title: data.name, target: data.target ? data.target : null, rel: data.rel ? data.rel : null, 'data-id': data.id ? data.id : null }); selection.select(anchorElm); editor.execCommand('mceEndTyping'); } else { editor.execCommand('mceInsertLink', false, { href: href, title: data.name, target: data.target ? data.target : null, rel: data.rel ? data.rel : null, 'data-id': data.id ? data.id : null }); } } if (!href) { editor.execCommand('unlink'); return; } //if we have an id, it must be a locallink:id, aslong as the isMedia flag is not set if(data.id && (angular.isUndefined(data.isMedia) || !data.isMedia)){ href = "/{localLink:" + data.id + "}"; insertLink(); return; } // Is email and not //user@domain.com if (href.indexOf('@') > 0 && href.indexOf('//') == -1 && href.indexOf('mailto:') == -1) { href = 'mailto:' + href; insertLink(); return; } // Is www. prefixed if (/^\s*www\./i.test(href)) { href = 'http://' + href; insertLink(); return; } insertLink(); } } }); } editor.addButton('link', { icon: 'link', tooltip: 'Insert/edit link', shortcut: 'Ctrl+K', onclick: createLinkList(showDialog), stateSelector: 'a[href]' }); editor.addButton('unlink', { icon: 'unlink', tooltip: 'Remove link', cmd: 'unlink', stateSelector: 'a[href]' }); editor.addShortcut('Ctrl+K', '', createLinkList(showDialog)); this.showDialog = showDialog; editor.addMenuItem('link', { icon: 'link', text: 'Insert link', shortcut: 'Ctrl+K', onclick: createLinkList(showDialog), stateSelector: 'a[href]', context: 'insert', prependToContext: true }); });