added linkit contrib module

This commit is contained in:
Bachir Soussi Chiadmi
2017-11-27 00:05:29 +01:00
parent 6a9608f0c7
commit f7646c417a
87 changed files with 7018 additions and 0 deletions
@@ -0,0 +1,21 @@
/**
* @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);
@@ -0,0 +1,167 @@
/**
* @file
* Linkit Autocomplete based on jQuery UI.
*/
(function ($, Drupal, _, document) {
'use strict';
var autocomplete;
/**
* JQuery UI autocomplete source callback.
*
* @param {object} request
* @param {function} response
*/
function sourceData(request, response) {
var elementId = this.element.attr('id');
if (!(elementId in autocomplete.cache)) {
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
*/
function sourceCallbackHandler(data) {
autocomplete.cache[elementId][term] = data;
showSuggestions(data);
}
// Get the desired term and construct the autocomplete URL for it.
var term = request.term;
// Check if the term is already cached.
if (autocomplete.cache[elementId].hasOwnProperty(term)) {
showSuggestions(autocomplete.cache[elementId][term]);
}
else {
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}
*/
function selectHandler(event, ui) {
if (ui.item.hasOwnProperty('path')) {
event.target.value = ui.item.path;
}
$(document).trigger('linkit.autocomplete.select', [event, ui]);
return false;
}
/**
* Override jQuery UI _renderItem function to output HTML by default.
*
* @param {object} ul
* The <ul> element that the newly created <li> element must be appended to.
* @param {object} item
*
* @return {object}
*/
function renderItem(ul, item) {
var $line = $('<li>').addClass('linkit-result');
$line.append($('<span>').html(item.title).addClass('linkit-result--title'));
if (item.description !== null) {
$line.append($('<span>').html(item.description).addClass('linkit-result--description'));
}
return $line.appendTo(ul);
}
/**
* Override jQuery UI _renderMenu function to handle groups.
*
* @param {object} ul
* An empty <ul> element to use as the widget's menu.
* @param {array} items
* An Array of items that match the user typed term.
*/
function renderMenu(ul, items) {
var self = this.element.autocomplete('instance');
var grouped_items = _.groupBy(items, function (item) {
return item.hasOwnProperty('group') ? item.group : '';
});
$.each(grouped_items, function (group, items) {
if (group.length) {
ul.append('<li class="linkit-result--group">' + group + '</li>');
}
$.each(items, function (index, item) {
self._renderItemData(ul, item);
});
});
}
/**
* Attaches the autocomplete behavior to all required fields.
*
* @type {Drupal~behavior}
*/
Drupal.behaviors.linkit_autocomplete = {
attach: function (context) {
// Act on textfields with the "form-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)');
},
_renderMenu: autocomplete.options.renderMenu,
_renderItem: autocomplete.options.renderItem
});
// Use jQuery UI Autocomplete on the textfield.
$autocomplete.autocomplete(autocomplete.options);
$autocomplete.autocomplete('widget').addClass('linkit-ui-autocomplete');
}
},
detach: function (context, settings, trigger) {
if (trigger === 'unload') {
$(context).find('input.form-linkit-autocomplete')
.removeOnce('linkit-autocomplete')
.autocomplete('destroy');
}
}
};
/**
* Autocomplete object implementation.
*/
autocomplete = {
cache: {},
options: {
source: sourceData,
renderItem: renderItem,
renderMenu: renderMenu,
select: selectHandler,
minLength: 1
},
ajax: {
dataType: 'json'
}
};
})(jQuery, Drupal, _, document);
@@ -0,0 +1,52 @@
/**
* @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);
@@ -0,0 +1,15 @@
/**
* @file
* Some basic behaviors and utility functions for Linkit.
*/
(function ($, Drupal, drupalSettings) {
'use strict';
/**
* @namespace
*/
Drupal.linkit = {};
})(jQuery, Drupal, drupalSettings);
Binary file not shown.

After

Width:  |  Height:  |  Size: 539 B

@@ -0,0 +1,223 @@
/**
* @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);