+++ /dev/null
-/**
- * @file
- * Paragraphs drag and drop handling and integration with the Sortable library.
- */
-
-(function ($, Drupal) {
-
- 'use strict';
-
- /**
- * jQuery plugin for Sortable
- *
- * Registers Sortable under a custom name to prevent a collision with jQuery
- * UI.
- *
- * @param {Object|String} options
- * @param {..*} [args]
- * @returns {jQuery|*}
- */
- $.fn.paragraphsSortable = function (options) {
- var retVal,
- args = arguments;
-
- this.each(function () {
- var $el = $(this),
- sortable = $el.data('sortable');
-
- if (!sortable && (options instanceof Object || !options)) {
- sortable = new Sortable(this, options);
- $el.data('sortable', sortable);
- }
-
- if (sortable) {
- if (options === 'widget') {
- return sortable;
- }
- else if (options === 'destroy') {
- sortable.destroy();
- $el.removeData('sortable');
- }
- else if (typeof sortable[options] === 'function') {
- retVal = sortable[options].apply(sortable, [].slice.call(args, 1));
- }
- else if (options in sortable.options) {
- retVal = sortable.option.apply(sortable, args);
- }
- }
- });
-
- return (retVal === void 0) ? this : retVal;
- };
-
-
- Drupal.behaviors.paragraphsDraggable = {
- attach: function (context) {
-
- // Initialize drag and drop.
- $('ul.paragraphs-dragdrop', context).each(function (i, item) {
- $(item).paragraphsSortable({
- group: "paragraphs",
- sort: true,
- handle: ".tabledrag-handle",
- onMove: isAllowed,
- onEnd: handleReorder
- });
- });
-
- /**
- * Callback to update weight and path information.
- *
- * @param evt
- * The Sortable event.
- */
- function handleReorder(evt) {
- var $item = $(evt.item);
- var $parent = $item.closest('.paragraphs-dragdrop');
- var $children = $parent.children('li');
- var $srcParent = $(evt.to);
- var $srcChildren = $srcParent.children('li');
-
- // Update both the source and target children.
- updateWeightsAndPath($srcChildren);
- updateWeightsAndPath($children);
- }
-
-
- /**
- * Update weight and recursively update path of the provided paragraphs.
- *
- * @param $items
- * Drag and drop items.
- */
- function updateWeightsAndPath($items) {
- $items.each(function (index, value) {
-
- // Update the weight in the weight of the current element, avoid
- // matching child weights by selecting the first.
- var $currentItem = $(value);
- var $weight = $currentItem.find('.paragraphs-dragdrop__weight:first');
- $weight.val(index);
-
- // Update the path of the current element and then update all nested
- // elements.
- updatePaths($currentItem, $currentItem.parent());
- $currentItem.find('> div > ul').each(function () {
- updateNestedPath(this, index, $currentItem);
- });
- })
- }
-
- /**
- * Update the path field based on the parent.
- *
- * @param $item
- * A list item.
- * @param $parent
- * The parent of the list item.
- */
- function updatePaths($item, $parent) {
- // Select the first path field which is the one from the current
- // element.
- var $pathField = $item.find('.paragraphs-dragdrop__path:first');
- var newPath = $parent.attr('data-paragraphs-dragdrop-path');
- $pathField.val(newPath);
- }
-
- /**
- * Update nested paragraphs for a field/list.
- *
- * @param childList
- * The paragraph field/list, parent of the children to be updated.
- * @param parentIndex
- * The index of the parent list item.
- * @param $parentListItem
- * The parent list item.
- */
- function updateNestedPath(childList, parentIndex, $parentListItem) {
-
- var sortablePath = childList.getAttribute('data-paragraphs-dragdrop-path');
- var newParent = $parentListItem.parent().attr('data-paragraphs-dragdrop-path');
-
- // Update the data attribute of the list based on the parent index and
- // list item.
- sortablePath = newParent + "][" + parentIndex + sortablePath.substr(sortablePath.lastIndexOf("]"));
- childList.setAttribute('data-paragraphs-dragdrop-path', sortablePath);
-
- // Now update the children.
- $(childList).children().each(function (childIndex) {
- var $childListItem = $(this);
- updatePaths($childListItem, $(childList), childIndex);
- $(this).find('> div > ul').each(function () {
- var nestedChildList = this;
- updateNestedPath(nestedChildList, childIndex, $childListItem);
- });
- });
- }
-
-
- /**
- * Callback to check if a paragraph item can be dropped into a position.
- *
- * @param evt
- * The Sortable event.
- * @param originalEvent
- * The original Sortable event.
- *
- * @returns {boolean|*}
- * True if the type is allowed and there is enough room.
- */
- function isAllowed(evt, originalEvent) {
- var dragee = evt.dragged;
- var target = evt.to;
- var drageeType = dragee.dataset.paragraphsDragdropBundle;
- var allowedTypes = target.dataset.paragraphsDragdropAllowedTypes;
- var hasSameContainer = evt.to === evt.from;
- return hasSameContainer || (contains(drageeType, allowedTypes) && hasRoom(target));
- }
-
- /**
- * Checks if the target has room.
- *
- * @param target
- * The target list/paragraph field.
- *
- * @returns {boolean}
- * True if the field is unlimited or limit is not reached yet.
- */
- function hasRoom(target) {
-
- var cardinality = target.dataset.paragraphsDragdropCardinality;
- var occupants = target.childNodes.length;
- var isLimited = parseInt(cardinality, 10) !== -1;
- var hasRoom = cardinality > occupants;
-
- return hasRoom || !isLimited;
- }
-
- /**
- * Checks if the paragraph type is allowed in the target type list.
- *
- * @param candidate
- * The paragraph type.
- * @param set
- * Comma separated list of target types.
- *
- * @returns {boolean}
- * TRUE if the target type is allowed.
- */
- function contains(candidate, set) {
- set = set.split(',');
- var l = set.length;
-
- for(var i = 0; i < l; i++) {
- if(set[i] === candidate) {
- return true;
- }
- }
- return false;
- }
-
- // Fix for an iOS 10 bug. Binding empty event handler on the touchmove
- // event.
- window.addEventListener('touchmove', function () {
- })
- }
- }
-
-})(jQuery, Drupal);