updated linkit contrib module to last beta version

This commit is contained in:
2018-04-17 14:53:21 +02:00
parent c0fbcb7706
commit 76ff40f8bb
136 changed files with 5138 additions and 3860 deletions
@@ -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);