277 lines
9.2 KiB
JavaScript
277 lines
9.2 KiB
JavaScript
(function() {
|
|
|
|
CKEDITOR.plugins.add('pwlink', {
|
|
|
|
requires: 'dialog,fakeobjects',
|
|
|
|
init: function(editor) {
|
|
|
|
var allowed = 'a[!href,target,name,title,rel]';
|
|
var required = 'a[href]';
|
|
|
|
var classOptions = ProcessWire.config.InputfieldCKEditor.pwlink.classOptions;
|
|
if(classOptions.length) allowed += "(" + classOptions + ")";
|
|
|
|
/*
|
|
if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'advanced' ) )
|
|
allowed = allowed.replace( ']', ',accesskey,charset,dir,id,lang,name,rel,tabindex,title,type]{*}(*)' );
|
|
|
|
if ( CKEDITOR.dialog.isTabEnabled( editor, 'link', 'target' ) )
|
|
allowed = allowed.replace( ']', ',target,onclick]' );
|
|
*/
|
|
|
|
// Add the link and unlink buttons.
|
|
editor.addCommand('pwlink', {
|
|
allowedContent: allowed,
|
|
requiredContent: required,
|
|
exec: loadIframeLinkPicker
|
|
});
|
|
|
|
editor.addCommand('anchor', new CKEDITOR.dialogCommand( 'anchor', {
|
|
allowedContent: 'a[!name,id]',
|
|
requiredContent: 'a[name]'
|
|
}));
|
|
|
|
editor.addCommand('unlink', new CKEDITOR.unlinkCommand());
|
|
editor.addCommand('removeAnchor', new CKEDITOR.removeAnchorCommand());
|
|
|
|
editor.setKeystroke( CKEDITOR.CTRL + 76 /*L*/, 'pwlink' );
|
|
|
|
if ( editor.ui.addButton ) {
|
|
editor.ui.addButton( 'PWLink', {
|
|
label: editor.lang.link.toolbar,
|
|
command: 'pwlink',
|
|
toolbar: 'links,10',
|
|
hidpi: true,
|
|
icon: (CKEDITOR.env.hidpi ? this.path + 'images/hidpi/pwlink.png' : this.path + 'images/pwlink.png')
|
|
});
|
|
editor.ui.addButton( 'Unlink', {
|
|
label: editor.lang.link.unlink,
|
|
command: 'unlink',
|
|
toolbar: 'links,20'
|
|
});
|
|
editor.ui.addButton( 'Anchor', {
|
|
label: editor.lang.link.anchor.toolbar,
|
|
command: 'anchor',
|
|
toolbar: 'links,30'
|
|
});
|
|
}
|
|
|
|
// On double click we execute the command (= we open modal)
|
|
editor.on( 'doubleclick', function( evt ) {
|
|
var element = CKEDITOR.plugins.link.getSelectedLink( editor ) || evt.data.element;
|
|
if ( element.is( 'a' ) && !element.getAttribute('name') && !element.isReadOnly() ) {
|
|
var $a = jQuery(element.$);
|
|
if($a.children('img').length == 0) {
|
|
evt.cancel(); // prevent CKE's link dialog
|
|
editor.commands.pwlink.exec();
|
|
}
|
|
}
|
|
});
|
|
|
|
// prevent CKE's default "Edit Link" from showing in context menu
|
|
editor.on('instanceReady', function(ck) {
|
|
ck.editor.removeMenuItem('link');
|
|
});
|
|
|
|
// add context menu item
|
|
if (editor.contextMenu) {
|
|
editor.addMenuItem('pwlinkitem', {
|
|
label: ProcessWire.config.InputfieldCKEditor.pwlink.edit,
|
|
command: 'pwlink',
|
|
group: 'link',
|
|
icon: (CKEDITOR.env.hidpi ? this.path + 'images/hidpi/pwlink.png' : this.path + 'images/pwlink.png')
|
|
});
|
|
editor.contextMenu.addListener(function(element) {
|
|
if ( !element || element.isReadOnly() ) return null;
|
|
var anchor = CKEDITOR.plugins.link.tryRestoreFakeAnchor( editor, element );
|
|
var menu = {};
|
|
if ( !anchor && !( anchor = CKEDITOR.plugins.link.getSelectedLink( editor ) ) ) return null;
|
|
if ( anchor.getAttribute( 'href' ) && anchor.getChildCount() ) menu = { pwlinkitem: CKEDITOR.TRISTATE_OFF };
|
|
return menu;
|
|
});
|
|
}
|
|
}
|
|
}); // ckeditor.plugins.add
|
|
|
|
function loadIframeLinkPicker(editor) {
|
|
|
|
var $in = jQuery("#Inputfield_id");
|
|
var pageID;
|
|
if($in.length) {
|
|
//if($in.hasClass('PageFrontEdit')) {
|
|
// var pageID = jQuery("#" + editor.name).closest('.pw-edit').attr('data-page');
|
|
//} else {
|
|
pageID = $in.val();
|
|
//}
|
|
} else {
|
|
pageID = jQuery("#" + editor.name).closest('.Inputfield').attr('data-pid');
|
|
}
|
|
|
|
// language support
|
|
var $textarea = jQuery('#' + editor.name); // get textarea of this instance
|
|
var selection = editor.getSelection(true);
|
|
var node = selection.getStartElement();
|
|
var nodeName = node.getName(); // will typically be 'a', 'img' or 'p'
|
|
var selectionText = selection.getSelectedText();
|
|
var selectionHtml = editor.getSelectedHtml(true); // true=return string
|
|
var $existingLink = null;
|
|
var anchors = CKEDITOR.plugins.link.getEditorAnchors(editor);
|
|
var inlineNodeNames = '/em/strong/i/b/u/s/span/small/abbr/cite/figcaption/';
|
|
|
|
if(nodeName != 'a' && nodeName != 'img') {
|
|
var parentNodes = node.getParents();
|
|
for(var n = 0; n < parentNodes.length; n++) {
|
|
var parentNode = parentNodes[n];
|
|
var parentNodeName = parentNode.getName();
|
|
if(parentNodeName === 'a') {
|
|
// if there is a parent <a> element then expand selection to include all of it
|
|
// this prevents double click on the <em> part of <a href='./'>foo <em>bar</em> baz</a> from
|
|
// just including the 'bar' as the link text
|
|
node = parentNode;
|
|
break;
|
|
} else if(inlineNodeNames.indexOf('/' + parentNodeName + '/') > -1 && node.getText() === selectionText) {
|
|
// include certain wrapping inline elements for formatting in the selection text
|
|
node = parentNode;
|
|
selection.selectElement(node);
|
|
}
|
|
}
|
|
}
|
|
|
|
nodeName = node.getName(); // in case it changed above
|
|
|
|
if(nodeName == 'a') {
|
|
// existing link
|
|
$existingLink = jQuery(node.$);
|
|
selectionText = node.getText();
|
|
selectionHtml = node.getHtml();
|
|
selection.selectElement(node);
|
|
} else if(nodeName == 'td' || nodeName == 'th' || nodeName == 'tr') {
|
|
var firstChar = selectionText.substring(0,1);
|
|
if(firstChar == "\n" || firstChar == "\r") {
|
|
ProcessWire.alert('Your selection includes part of the table. Please try selecting the text again.');
|
|
return;
|
|
}
|
|
} else if(nodeName == 'img') {
|
|
// linked image
|
|
var $img = jQuery(node.$);
|
|
$existingLink = $img.parent('a');
|
|
selectionText = node.$.outerHTML;
|
|
selectionHtml = selectionText;
|
|
|
|
} else if (selectionText.length < 1) {
|
|
// If not on top of link and there is no text selected - just return (don't load iframe at all)
|
|
return;
|
|
} else {
|
|
// new link
|
|
}
|
|
|
|
// build the modal URL
|
|
var modalUrl = ProcessWire.config.urls.admin + 'page/link/?id=' + pageID + '&modal=1';
|
|
var $langWrapper = $textarea.closest('.LanguageSupport');
|
|
|
|
if($langWrapper.length) {
|
|
// multi-language field
|
|
modalUrl += "&lang=" + $langWrapper.data("language");
|
|
} else {
|
|
// multi-language field in Table
|
|
$langWrapper = $textarea.parents('.InputfieldTable_langTabs').find('li.ui-state-active a')
|
|
if($langWrapper.length && typeof $langWrapper.data('lang') != "undefined") {
|
|
modalUrl += "&lang=" + $langWrapper.data('lang');
|
|
} else if(jQuery('#pw-edit-lang').length) {
|
|
modalUrl += "&lang=" + jQuery('#pw-edit-lang').val(); // front-end editor
|
|
}
|
|
}
|
|
|
|
if($existingLink != null) {
|
|
var attrs = ['href', 'title', 'class', 'rel', 'target'];
|
|
for(var n = 0; n < attrs.length; n++) {
|
|
var val = $existingLink.attr(attrs[n]);
|
|
if(val && val.length) modalUrl += "&" + attrs[n] + "=" + encodeURIComponent(val);
|
|
}
|
|
}
|
|
|
|
// add any anchors to the modal URL
|
|
if(anchors.length > 0) {
|
|
for(var n = 0; n < anchors.length; n++) {
|
|
modalUrl += '&anchors[]=' + encodeURIComponent(anchors[n].id);
|
|
}
|
|
}
|
|
|
|
// set link text
|
|
var linkText = ($existingLink && $existingLink.text().length) ? $existingLink.text() : selectionText;
|
|
|
|
if(nodeName !== 'img' && linkText.length) {
|
|
modalUrl += '&text=' + encodeURIComponent(linkText);
|
|
}
|
|
|
|
// labels
|
|
var insertLinkLabel = ProcessWire.config.InputfieldCKEditor.pwlink.label;
|
|
var cancelLabel = ProcessWire.config.InputfieldCKEditor.pwlink.cancel;
|
|
var $iframe; // set after modalSettings down
|
|
|
|
// action when insert link button is clicked
|
|
function clickInsert() {
|
|
|
|
var $i = $iframe.contents();
|
|
var $a = jQuery(jQuery("#link_markup", $i).text());
|
|
if($a.attr('href') && $a.attr('href').length) {
|
|
if($a.text() === selectionText || !$a.text().length) {
|
|
// if input text has not changed from original, then use the original HTML rather than the text
|
|
$a.html(selectionHtml);
|
|
}
|
|
var html = jQuery("<div />").append($a).html();
|
|
var el = CKEDITOR.dom.element.createFromHtml(html);
|
|
editor.insertElement(el); // was: editor.insertHtml(html);
|
|
}
|
|
|
|
$iframe.dialog("close");
|
|
}
|
|
|
|
// settings for modal window
|
|
var modalSettings = {
|
|
title: "<i class='fa fa-link'></i> " + insertLinkLabel,
|
|
open: function() {
|
|
if(jQuery(".cke_maximized").length > 0) {
|
|
// the following is required when CKE is maximized to make sure dialog is on top of it
|
|
jQuery('.ui-dialog').css('z-index', 9999);
|
|
jQuery('.ui-widget-overlay').css('z-index', 9998);
|
|
}
|
|
},
|
|
buttons: [ {
|
|
'class': "pw_link_submit_insert",
|
|
'html': "<i class='fa fa-link'></i> " + insertLinkLabel,
|
|
'click': clickInsert
|
|
}, {
|
|
'html': "<i class='fa fa-times-circle'></i> " + cancelLabel,
|
|
'click': function() { $iframe.dialog("close"); },
|
|
'class': 'ui-priority-secondary'
|
|
}
|
|
]
|
|
};
|
|
|
|
// create modal window
|
|
var $iframe = pwModalWindow(modalUrl, modalSettings, 'medium');
|
|
|
|
// modal window load event
|
|
$iframe.on('load', function() {
|
|
|
|
var $i = $iframe.contents();
|
|
$i.find("#ProcessPageEditLinkForm").data('iframe', $iframe);
|
|
|
|
// capture enter key in main URL text input
|
|
jQuery("#link_page_url_input", $i).keydown(function(event) {
|
|
var $this = jQuery(this);
|
|
var val = $this.val().trim();
|
|
if (event.keyCode == 13) {
|
|
event.preventDefault();
|
|
if(val.length > 0) clickInsert();
|
|
return false;
|
|
}
|
|
});
|
|
|
|
}); // load
|
|
|
|
} // function loadIframeLinkPicker(editor) {
|
|
|
|
})();
|