updated linkit contrib module to last beta version
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Title attribute functions.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, document) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var fieldName = '[name="attributes[title]"]';
|
||||
|
||||
/**
|
||||
* Automatically populate the title attribute.
|
||||
*/
|
||||
$(document).bind('linkit.autocomplete.select', function (triggerEvent, event, ui) {
|
||||
if (ui.item.hasOwnProperty('title')) {
|
||||
$('form.linkit-editor-dialog-form').find(fieldName).val(ui.item.title);
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, Drupal, document);
|
||||
@@ -3,7 +3,7 @@
|
||||
* Linkit Autocomplete based on jQuery UI.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, _, document) {
|
||||
(function ($, Drupal, _) {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
* JQuery UI autocomplete source callback.
|
||||
*
|
||||
* @param {object} request
|
||||
* The request object.
|
||||
* @param {function} response
|
||||
* The function to call with the response.
|
||||
*/
|
||||
function sourceData(request, response) {
|
||||
var elementId = this.element.attr('id');
|
||||
@@ -22,21 +24,15 @@
|
||||
autocomplete.cache[elementId] = {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {object} suggestions
|
||||
*/
|
||||
function showSuggestions(suggestions) {
|
||||
response(suggestions.matches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the data object into an array and update autocomplete results.
|
||||
*
|
||||
* @param {object} data
|
||||
* The data sent back from the server.
|
||||
*/
|
||||
function sourceCallbackHandler(data) {
|
||||
autocomplete.cache[elementId][term] = data;
|
||||
showSuggestions(data);
|
||||
autocomplete.cache[elementId][term] = data.suggestions;
|
||||
response(data.suggestions);
|
||||
}
|
||||
|
||||
// Get the desired term and construct the autocomplete URL for it.
|
||||
@@ -44,27 +40,48 @@
|
||||
|
||||
// Check if the term is already cached.
|
||||
if (autocomplete.cache[elementId].hasOwnProperty(term)) {
|
||||
showSuggestions(autocomplete.cache[elementId][term]);
|
||||
response(autocomplete.cache[elementId][term]);
|
||||
}
|
||||
else {
|
||||
var options = $.extend({success: sourceCallbackHandler, data: {q: term}}, autocomplete.ajax);
|
||||
var options = $.extend({
|
||||
success: sourceCallbackHandler,
|
||||
data: {q: term}
|
||||
}, autocomplete.ajax);
|
||||
$.ajax(this.element.attr('data-autocomplete-path'), options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an autocomplete select event.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* @param {object} ui
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
* Handles an autocomplete select event.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* The event triggered.
|
||||
* @param {object} ui
|
||||
* The jQuery UI settings object.
|
||||
*
|
||||
* @return {boolean}
|
||||
* False to prevent further handlers.
|
||||
*/
|
||||
function selectHandler(event, ui) {
|
||||
if (ui.item.hasOwnProperty('path')) {
|
||||
event.target.value = ui.item.path;
|
||||
var $form = $(event.target).closest('form');
|
||||
if (!ui.item.path) {
|
||||
throw 'Missing path param.' + JSON.stringify(ui.item);
|
||||
}
|
||||
$(document).trigger('linkit.autocomplete.select', [event, ui]);
|
||||
|
||||
$('input[name="href_dirty_check"]', $form).val(ui.item.path);
|
||||
|
||||
if (ui.item.entity_type_id || ui.item.entity_uuid || ui.item.substitution_id) {
|
||||
if (!ui.item.entity_type_id || !ui.item.entity_uuid || !ui.item.substitution_id) {
|
||||
throw 'Missing path param.' + JSON.stringify(ui.item);
|
||||
}
|
||||
|
||||
$('input[name="attributes[data-entity-type]"]', $form).val(ui.item.entity_type_id);
|
||||
$('input[name="attributes[data-entity-uuid]"]', $form).val(ui.item.entity_uuid);
|
||||
$('input[name="attributes[data-entity-substitution]"]', $form).val(ui.item.substitution_id);
|
||||
}
|
||||
|
||||
event.target.value = ui.item.path;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -74,18 +91,20 @@
|
||||
* @param {object} ul
|
||||
* The <ul> element that the newly created <li> element must be appended to.
|
||||
* @param {object} item
|
||||
* The list item to append.
|
||||
*
|
||||
* @return {object}
|
||||
* jQuery collection of the ul element.
|
||||
*/
|
||||
function renderItem(ul, item) {
|
||||
var $line = $('<li>').addClass('linkit-result');
|
||||
$line.append($('<span>').html(item.title).addClass('linkit-result--title'));
|
||||
var $line = $('<li>').addClass('linkit-result-line');
|
||||
var $wrapper = $('<div>').addClass('linkit-result-line-wrapper');
|
||||
$wrapper.append($('<span>').html(item.label).addClass('linkit-result-line--title'));
|
||||
|
||||
if (item.description !== null) {
|
||||
$line.append($('<span>').html(item.description).addClass('linkit-result--description'));
|
||||
if (item.hasOwnProperty('description')) {
|
||||
$wrapper.append($('<span>').html(item.description).addClass('linkit-result-line--description'));
|
||||
}
|
||||
|
||||
return $line.appendTo(ul);
|
||||
return $line.append($wrapper).appendTo(ul);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,7 +124,7 @@
|
||||
|
||||
$.each(grouped_items, function (group, items) {
|
||||
if (group.length) {
|
||||
ul.append('<li class="linkit-result--group">' + group + '</li>');
|
||||
ul.append('<li class="linkit-result-line--group ui-menu-divider">' + group + '</li>');
|
||||
}
|
||||
|
||||
$.each(items, function (index, item) {
|
||||
@@ -114,20 +133,35 @@
|
||||
});
|
||||
}
|
||||
|
||||
function focusHandler() {
|
||||
return false;
|
||||
}
|
||||
|
||||
function searchHandler(event) {
|
||||
var options = autocomplete.options;
|
||||
|
||||
return !options.isComposing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the autocomplete behavior to all required fields.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches the autocomplete behaviors.
|
||||
* @prop {Drupal~behaviorDetach} detach
|
||||
* Detaches the autocomplete behaviors.
|
||||
*/
|
||||
Drupal.behaviors.linkit_autocomplete = {
|
||||
attach: function (context) {
|
||||
// Act on textfields with the "form-autocomplete" class.
|
||||
// Act on textfields with the "form-linkit-autocomplete" class.
|
||||
var $autocomplete = $(context).find('input.form-linkit-autocomplete').once('linkit-autocomplete');
|
||||
if ($autocomplete.length) {
|
||||
$.widget('custom.autocomplete', $.ui.autocomplete, {
|
||||
_create: function () {
|
||||
this._super();
|
||||
this.widget().menu('option', 'items', '> :not(.linkit-result--group)');
|
||||
this.widget().menu('option', 'items', '> :not(.linkit-result-line--group)');
|
||||
},
|
||||
_renderMenu: autocomplete.options.renderMenu,
|
||||
_renderItem: autocomplete.options.renderItem
|
||||
@@ -136,6 +170,17 @@
|
||||
// Use jQuery UI Autocomplete on the textfield.
|
||||
$autocomplete.autocomplete(autocomplete.options);
|
||||
$autocomplete.autocomplete('widget').addClass('linkit-ui-autocomplete');
|
||||
|
||||
$autocomplete.click(function () {
|
||||
$autocomplete.autocomplete('search', $autocomplete.val());
|
||||
});
|
||||
|
||||
$autocomplete.on('compositionstart.autocomplete', function () {
|
||||
autocomplete.options.isComposing = true;
|
||||
});
|
||||
$autocomplete.on('compositionend.autocomplete', function () {
|
||||
autocomplete.options.isComposing = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
detach: function (context, settings, trigger) {
|
||||
@@ -154,14 +199,17 @@
|
||||
cache: {},
|
||||
options: {
|
||||
source: sourceData,
|
||||
focus: focusHandler,
|
||||
search: searchHandler,
|
||||
select: selectHandler,
|
||||
renderItem: renderItem,
|
||||
renderMenu: renderMenu,
|
||||
select: selectHandler,
|
||||
minLength: 1
|
||||
minLength: 1,
|
||||
isComposing: false
|
||||
},
|
||||
ajax: {
|
||||
dataType: 'json'
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery, Drupal, _, document);
|
||||
})(jQuery, Drupal, _);
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @file
|
||||
* Send events to add or remove a tags to the filter_html allowed tags.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, document) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* When enabling the linkit filter, also add linkit rules to filter_html.
|
||||
*
|
||||
* @type {Drupal~behavior}
|
||||
*
|
||||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Attaches linkitFilterHtml behavior.
|
||||
*/
|
||||
Drupal.behaviors.linkitFilterHtml = {
|
||||
attach: function (context) {
|
||||
var selector = '[data-drupal-selector="edit-filters-linkit-status"]';
|
||||
var feature = editorFeature();
|
||||
$(context).find(selector).once('filters-linkit-status').each(function () {
|
||||
$(this).on('click', function () {
|
||||
var eventName = $(this).is(':checked') ? 'drupalEditorFeatureAdded' : 'drupalEditorFeatureRemoved';
|
||||
$(document).trigger(eventName, feature);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a editor feature.
|
||||
*
|
||||
* @return {Drupal.EditorFeature}
|
||||
* A editor feature with linkit specific tags and attributes.
|
||||
*/
|
||||
function editorFeature() {
|
||||
var linkitFeature = new Drupal.EditorFeature('linkit');
|
||||
var rule = new Drupal.EditorFeatureHTMLRule();
|
||||
// Tags.
|
||||
rule.required.tags = ['a'];
|
||||
rule.allowed.tags = ['a'];
|
||||
// Attributes.
|
||||
rule.required.attributes = ['data-entity-substitution', 'data-entity-type', 'data-entity-uuid', 'title'];
|
||||
rule.allowed.attributes = ['data-entity-substitution', 'data-entity-type', 'data-entity-uuid', 'title'];
|
||||
|
||||
linkitFeature.addHTMLRule(rule);
|
||||
return linkitFeature;
|
||||
}
|
||||
|
||||
})(jQuery, Drupal, document);
|
||||
@@ -1,52 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* IMCE integration for Linkit.
|
||||
*/
|
||||
|
||||
(function ($, Drupal, drupalSettings) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @namespace
|
||||
*
|
||||
* Need to be in the global namespace, otherwise the IMCE window will not show
|
||||
* the 'select' button in the toolbar.
|
||||
*/
|
||||
var linkitImce = window.linkitImce = {};
|
||||
|
||||
/**
|
||||
* Drupal behavior to handle imce linkit integration.
|
||||
*/
|
||||
Drupal.behaviors.linkitImce = {
|
||||
attach: function (context, settings) {
|
||||
var $link = $(context).find('.linkit-imce-open').once('linkit-imce-open');
|
||||
if ($link.length) {
|
||||
$link.bind('click', function (event) {
|
||||
event.preventDefault();
|
||||
window.open($(this).attr('href'), '', 'width=760,height=560,resizable=1');
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handler for imce sendto operation.
|
||||
*/
|
||||
linkitImce.sendto = function (file, win) {
|
||||
var imce = win.imce;
|
||||
var items = imce.getSelection();
|
||||
|
||||
if (imce.countSelection() > 1) {
|
||||
imce.setMessage(Drupal.t('You can only select one file.'));
|
||||
return;
|
||||
}
|
||||
var path = imce.getConf('root_url') + '/' + imce.getItemPath(items[0]);
|
||||
$('[data-drupal-selector="edit-attributes-href"]').val(path);
|
||||
win.close();
|
||||
};
|
||||
|
||||
|
||||
})(jQuery, Drupal, drupalSettings);
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 539 B |
@@ -1,223 +0,0 @@
|
||||
/**
|
||||
* @file
|
||||
* Linkit plugin.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
|
||||
(function ($, Drupal, drupalSettings, CKEDITOR) {
|
||||
|
||||
'use strict';
|
||||
|
||||
// Alter the dialog settings to make a bigger dialog.
|
||||
// $(window).on('dialog:beforecreate', function (event, dialog, $element, settings) {
|
||||
// settings.dialogClass = settings.dialogClass.replace('ui-dialog--narrow', '');
|
||||
// settings.width = 700;
|
||||
// });
|
||||
|
||||
CKEDITOR.plugins.add('linkit', {
|
||||
init: function (editor) {
|
||||
// Add the commands for link and unlink.
|
||||
editor.addCommand('linkit', {
|
||||
allowedContent: new CKEDITOR.style({
|
||||
element: 'a',
|
||||
attributes: {
|
||||
'!href': '',
|
||||
// @TODO: Read these dynamically from the profile.
|
||||
'accesskey': '',
|
||||
'id': '',
|
||||
'rel': '',
|
||||
'target': '',
|
||||
'title': ''
|
||||
}
|
||||
}),
|
||||
requiredContent: new CKEDITOR.style({
|
||||
element: 'a',
|
||||
attributes: {
|
||||
href: ''
|
||||
}
|
||||
}),
|
||||
modes: {wysiwyg: 1},
|
||||
canUndo: true,
|
||||
exec: function (editor) {
|
||||
var linkElement = getSelectedLink(editor);
|
||||
var linkDOMElement = null;
|
||||
|
||||
// Set existing values based on selected element.
|
||||
var existingValues = {};
|
||||
if (linkElement && linkElement.$) {
|
||||
linkDOMElement = linkElement.$;
|
||||
|
||||
// Populate an array with the link's current attributes.
|
||||
var attribute = null;
|
||||
var attributeName;
|
||||
for (var attrIndex = 0; attrIndex < linkDOMElement.attributes.length; attrIndex++) {
|
||||
attribute = linkDOMElement.attributes.item(attrIndex);
|
||||
attributeName = attribute.nodeName.toLowerCase();
|
||||
// Don't consider data-cke-saved- attributes; they're just there
|
||||
// to work around browser quirks.
|
||||
if (attributeName.substring(0, 15) === 'data-cke-saved-') {
|
||||
continue;
|
||||
}
|
||||
// Store the value for this attribute, unless there's a
|
||||
// data-cke-saved- alternative for it, which will contain the
|
||||
// quirk-free, original value.
|
||||
existingValues[attributeName] = linkElement.data('cke-saved-' + attributeName) || attribute.nodeValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare a save callback to be used upon saving the dialog.
|
||||
var saveCallback = function (returnValues) {
|
||||
editor.fire('saveSnapshot');
|
||||
|
||||
// Create a new link element if needed.
|
||||
if (!linkElement && returnValues.attributes.href) {
|
||||
var selection = editor.getSelection();
|
||||
var range = selection.getRanges(1)[0];
|
||||
|
||||
// Use link URL as text with a collapsed cursor.
|
||||
if (range.collapsed) {
|
||||
// Shorten mailto URLs to just the email address.
|
||||
var text = new CKEDITOR.dom.text(returnValues.attributes.href.replace(/^mailto:/, ''), editor.document);
|
||||
range.insertNode(text);
|
||||
range.selectNodeContents(text);
|
||||
}
|
||||
|
||||
// Create the new link by applying a style to the new text.
|
||||
var style = new CKEDITOR.style({element: 'a', attributes: returnValues.attributes});
|
||||
style.type = CKEDITOR.STYLE_INLINE;
|
||||
style.applyToRange(range);
|
||||
range.select();
|
||||
|
||||
// Set the link so individual properties may be set below.
|
||||
linkElement = getSelectedLink(editor);
|
||||
}
|
||||
// Update the link properties.
|
||||
else if (linkElement) {
|
||||
for (var attrName in returnValues.attributes) {
|
||||
if (returnValues.attributes.hasOwnProperty(attrName)) {
|
||||
// Update the property if a value is specified.
|
||||
if (returnValues.attributes[attrName].length > 0) {
|
||||
var value = returnValues.attributes[attrName];
|
||||
linkElement.data('cke-saved-' + attrName, value);
|
||||
linkElement.setAttribute(attrName, value);
|
||||
}
|
||||
// Delete the property if set to an empty string.
|
||||
else {
|
||||
linkElement.removeAttribute(attrName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save snapshot for undo support.
|
||||
editor.fire('saveSnapshot');
|
||||
};
|
||||
// Drupal.t() will not work inside CKEditor plugins because CKEditor
|
||||
// loads the JavaScript file instead of Drupal. Pull translated
|
||||
// strings from the plugin settings that are translated server-side.
|
||||
var dialogSettings = {
|
||||
title: linkElement ? editor.config.linkit_dialogTitleAdd : editor.config.linkit_dialogTitleEdit,
|
||||
dialogClass: 'editor-linkit-dialog'
|
||||
};
|
||||
|
||||
// Open the dialog for the edit form.
|
||||
Drupal.ckeditor.openDialog(editor, Drupal.url('linkit/dialog/linkit/' + editor.config.drupal.format), existingValues, saveCallback, dialogSettings);
|
||||
}
|
||||
});
|
||||
|
||||
// CTRL + L.
|
||||
editor.setKeystroke(CKEDITOR.CTRL + 76, 'linkit');
|
||||
|
||||
// Add buttons.
|
||||
if (editor.ui.addButton) {
|
||||
editor.ui.addButton('Linkit', {
|
||||
label: Drupal.t('Link'),
|
||||
command: 'linkit',
|
||||
icon: this.path + '/linkit.png'
|
||||
});
|
||||
}
|
||||
|
||||
editor.on('doubleclick', function (evt) {
|
||||
var element = getSelectedLink(editor) || evt.data.element;
|
||||
|
||||
if (!element.isReadOnly()) {
|
||||
if (element.is('a')) {
|
||||
editor.getSelection().selectElement(element);
|
||||
editor.getCommand('linkit').exec();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If the "menu" plugin is loaded, register the menu items.
|
||||
if (editor.addMenuItems) {
|
||||
editor.addMenuItems({
|
||||
linkit: {
|
||||
label: Drupal.t('Edit Link'),
|
||||
command: 'linkit',
|
||||
group: 'link',
|
||||
order: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If the "contextmenu" plugin is loaded, register the listeners.
|
||||
if (editor.contextMenu) {
|
||||
editor.contextMenu.addListener(function (element, selection) {
|
||||
if (!element || element.isReadOnly()) {
|
||||
return null;
|
||||
}
|
||||
var anchor = getSelectedLink(editor);
|
||||
if (!anchor) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var menu = {};
|
||||
if (anchor.getAttribute('href') && anchor.getChildCount()) {
|
||||
menu = {
|
||||
linkit: CKEDITOR.TRISTATE_OFF
|
||||
};
|
||||
}
|
||||
return menu;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the surrounding link element of current selection.
|
||||
*
|
||||
* The following selection will all return the link element.
|
||||
*
|
||||
* @example
|
||||
* <a href="#">li^nk</a>
|
||||
* <a href="#">[link]</a>
|
||||
* text[<a href="#">link]</a>
|
||||
* <a href="#">li[nk</a>]
|
||||
* [<b><a href="#">li]nk</a></b>]
|
||||
* [<a href="#"><b>li]nk</b></a>
|
||||
*
|
||||
* @param {CKEDITOR.editor} editor
|
||||
* The CKEditor editor object
|
||||
*
|
||||
* @return {?HTMLElement}
|
||||
* The selected link element, or null.
|
||||
*
|
||||
*/
|
||||
function getSelectedLink(editor) {
|
||||
var selection = editor.getSelection();
|
||||
var selectedElement = selection.getSelectedElement();
|
||||
if (selectedElement && selectedElement.is('a')) {
|
||||
return selectedElement;
|
||||
}
|
||||
|
||||
var range = selection.getRanges(true)[0];
|
||||
|
||||
if (range) {
|
||||
range.shrink(CKEDITOR.SHRINK_TEXT);
|
||||
return editor.elementPath(range.getCommonAncestor()).contains('a', 1);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
})(jQuery, Drupal, drupalSettings, CKEDITOR);
|
||||
Reference in New Issue
Block a user