Mercurial > hg > isophonics-drupal-site
diff core/modules/quickedit/js/quickedit.js @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/quickedit/js/quickedit.js Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,374 @@ +/** +* DO NOT EDIT THIS FILE. +* See the following change record for more information, +* https://www.drupal.org/node/2815083 +* @preserve +**/ + +(function ($, _, Backbone, Drupal, drupalSettings, JSON, storage) { + var options = $.extend(drupalSettings.quickedit, { + strings: { + quickEdit: Drupal.t('Quick edit') + } + }); + + var fieldsMetadataQueue = []; + + var fieldsAvailableQueue = []; + + var contextualLinksQueue = []; + + var entityInstancesTracker = {}; + + Drupal.behaviors.quickedit = { + attach: function attach(context) { + $('body').once('quickedit-init').each(initQuickEdit); + + var $fields = $(context).find('[data-quickedit-field-id]').once('quickedit'); + if ($fields.length === 0) { + return; + } + + $(context).find('[data-quickedit-entity-id]').once('quickedit').each(function (index, entityElement) { + processEntity(entityElement); + }); + + $fields.each(function (index, fieldElement) { + processField(fieldElement); + }); + + contextualLinksQueue = _.filter(contextualLinksQueue, function (contextualLink) { + return !initializeEntityContextualLink(contextualLink); + }); + + fetchMissingMetadata(function (fieldElementsWithFreshMetadata) { + _.each(fieldElementsWithFreshMetadata, processField); + + contextualLinksQueue = _.filter(contextualLinksQueue, function (contextualLink) { + return !initializeEntityContextualLink(contextualLink); + }); + }); + }, + detach: function detach(context, settings, trigger) { + if (trigger === 'unload') { + deleteContainedModelsAndQueues($(context)); + } + } + }; + + Drupal.quickedit = { + app: null, + + collections: { + entities: null, + + fields: null + }, + + editors: {}, + + metadata: { + has: function has(fieldID) { + return storage.getItem(this._prefixFieldID(fieldID)) !== null; + }, + add: function add(fieldID, metadata) { + storage.setItem(this._prefixFieldID(fieldID), JSON.stringify(metadata)); + }, + get: function get(fieldID, key) { + var metadata = JSON.parse(storage.getItem(this._prefixFieldID(fieldID))); + return typeof key === 'undefined' ? metadata : metadata[key]; + }, + _prefixFieldID: function _prefixFieldID(fieldID) { + return 'Drupal.quickedit.metadata.' + fieldID; + }, + _unprefixFieldID: function _unprefixFieldID(fieldID) { + return fieldID.substring(26); + }, + intersection: function intersection(fieldIDs) { + var prefixedFieldIDs = _.map(fieldIDs, this._prefixFieldID); + var intersection = _.intersection(prefixedFieldIDs, _.keys(sessionStorage)); + return _.map(intersection, this._unprefixFieldID); + } + } + }; + + var permissionsHashKey = Drupal.quickedit.metadata._prefixFieldID('permissionsHash'); + var permissionsHashValue = storage.getItem(permissionsHashKey); + var permissionsHash = drupalSettings.user.permissionsHash; + if (permissionsHashValue !== permissionsHash) { + if (typeof permissionsHash === 'string') { + _.chain(storage).keys().each(function (key) { + if (key.substring(0, 26) === 'Drupal.quickedit.metadata.') { + storage.removeItem(key); + } + }); + } + storage.setItem(permissionsHashKey, permissionsHash); + } + + $(document).on('drupalContextualLinkAdded', function (event, data) { + if (data.$region.is('[data-quickedit-entity-id]')) { + if (!data.$region.is('[data-quickedit-entity-instance-id]')) { + data.$region.once('quickedit'); + processEntity(data.$region.get(0)); + } + var contextualLink = { + entityID: data.$region.attr('data-quickedit-entity-id'), + entityInstanceID: data.$region.attr('data-quickedit-entity-instance-id'), + el: data.$el[0], + region: data.$region[0] + }; + + if (!initializeEntityContextualLink(contextualLink)) { + contextualLinksQueue.push(contextualLink); + } + } + }); + + function extractEntityID(fieldID) { + return fieldID.split('/').slice(0, 2).join('/'); + } + + function initQuickEdit(bodyElement) { + Drupal.quickedit.collections.entities = new Drupal.quickedit.EntityCollection(); + Drupal.quickedit.collections.fields = new Drupal.quickedit.FieldCollection(); + + Drupal.quickedit.app = new Drupal.quickedit.AppView({ + el: bodyElement, + model: new Drupal.quickedit.AppModel(), + entitiesCollection: Drupal.quickedit.collections.entities, + fieldsCollection: Drupal.quickedit.collections.fields + }); + } + + function processEntity(entityElement) { + var entityID = entityElement.getAttribute('data-quickedit-entity-id'); + if (!entityInstancesTracker.hasOwnProperty(entityID)) { + entityInstancesTracker[entityID] = 0; + } else { + entityInstancesTracker[entityID]++; + } + + var entityInstanceID = entityInstancesTracker[entityID]; + entityElement.setAttribute('data-quickedit-entity-instance-id', entityInstanceID); + } + + function processField(fieldElement) { + var metadata = Drupal.quickedit.metadata; + var fieldID = fieldElement.getAttribute('data-quickedit-field-id'); + var entityID = extractEntityID(fieldID); + + var entityElementSelector = '[data-quickedit-entity-id="' + entityID + '"]'; + var $entityElement = $(entityElementSelector); + + if (!$entityElement.length) { + throw 'Quick Edit could not associate the rendered entity field markup (with [data-quickedit-field-id="' + fieldID + '"]) with the corresponding rendered entity markup: no parent DOM node found with [data-quickedit-entity-id="' + entityID + '"]. This is typically caused by the theme\'s template for this entity type forgetting to print the attributes.'; + } + var entityElement = $(fieldElement).closest($entityElement); + + if (entityElement.length === 0) { + var $lowestCommonParent = $entityElement.parents().has(fieldElement).first(); + entityElement = $lowestCommonParent.find($entityElement); + } + var entityInstanceID = entityElement.get(0).getAttribute('data-quickedit-entity-instance-id'); + + if (!metadata.has(fieldID)) { + fieldsMetadataQueue.push({ + el: fieldElement, + fieldID: fieldID, + entityID: entityID, + entityInstanceID: entityInstanceID + }); + return; + } + + if (metadata.get(fieldID, 'access') !== true) { + return; + } + + if (Drupal.quickedit.collections.entities.findWhere({ entityID: entityID, entityInstanceID: entityInstanceID })) { + initializeField(fieldElement, fieldID, entityID, entityInstanceID); + } else { + fieldsAvailableQueue.push({ el: fieldElement, fieldID: fieldID, entityID: entityID, entityInstanceID: entityInstanceID }); + } + } + + function initializeField(fieldElement, fieldID, entityID, entityInstanceID) { + var entity = Drupal.quickedit.collections.entities.findWhere({ + entityID: entityID, + entityInstanceID: entityInstanceID + }); + + $(fieldElement).addClass('quickedit-field'); + + var field = new Drupal.quickedit.FieldModel({ + el: fieldElement, + fieldID: fieldID, + id: fieldID + '[' + entity.get('entityInstanceID') + ']', + entity: entity, + metadata: Drupal.quickedit.metadata.get(fieldID), + acceptStateChange: _.bind(Drupal.quickedit.app.acceptEditorStateChange, Drupal.quickedit.app) + }); + + Drupal.quickedit.collections.fields.add(field); + } + + function fetchMissingMetadata(callback) { + if (fieldsMetadataQueue.length) { + var fieldIDs = _.pluck(fieldsMetadataQueue, 'fieldID'); + var fieldElementsWithoutMetadata = _.pluck(fieldsMetadataQueue, 'el'); + var entityIDs = _.uniq(_.pluck(fieldsMetadataQueue, 'entityID'), true); + + entityIDs = _.difference(entityIDs, Drupal.quickedit.metadata.intersection(entityIDs)); + fieldsMetadataQueue = []; + + $.ajax({ + url: Drupal.url('quickedit/metadata'), + type: 'POST', + data: { + 'fields[]': fieldIDs, + 'entities[]': entityIDs + }, + dataType: 'json', + success: function success(results) { + _.each(results, function (fieldMetadata, fieldID) { + Drupal.quickedit.metadata.add(fieldID, fieldMetadata); + }); + + callback(fieldElementsWithoutMetadata); + } + }); + } + } + + function loadMissingEditors(callback) { + var loadedEditors = _.keys(Drupal.quickedit.editors); + var missingEditors = []; + Drupal.quickedit.collections.fields.each(function (fieldModel) { + var metadata = Drupal.quickedit.metadata.get(fieldModel.get('fieldID')); + if (metadata.access && _.indexOf(loadedEditors, metadata.editor) === -1) { + missingEditors.push(metadata.editor); + + Drupal.quickedit.editors[metadata.editor] = false; + } + }); + missingEditors = _.uniq(missingEditors); + if (missingEditors.length === 0) { + callback(); + return; + } + + var loadEditorsAjax = Drupal.ajax({ + url: Drupal.url('quickedit/attachments'), + submit: { 'editors[]': missingEditors } + }); + + var realInsert = Drupal.AjaxCommands.prototype.insert; + loadEditorsAjax.commands.insert = function (ajax, response, status) { + _.defer(callback); + realInsert(ajax, response, status); + }; + + loadEditorsAjax.execute(); + } + + function initializeEntityContextualLink(contextualLink) { + var metadata = Drupal.quickedit.metadata; + + function hasFieldWithPermission(fieldIDs) { + for (var i = 0; i < fieldIDs.length; i++) { + var fieldID = fieldIDs[i]; + if (metadata.get(fieldID, 'access') === true) { + return true; + } + } + return false; + } + + function allMetadataExists(fieldIDs) { + return fieldIDs.length === metadata.intersection(fieldIDs).length; + } + + var fields = _.where(fieldsAvailableQueue, { + entityID: contextualLink.entityID, + entityInstanceID: contextualLink.entityInstanceID + }); + var fieldIDs = _.pluck(fields, 'fieldID'); + + if (fieldIDs.length === 0) { + return false; + } else if (hasFieldWithPermission(fieldIDs)) { + var entityModel = new Drupal.quickedit.EntityModel({ + el: contextualLink.region, + entityID: contextualLink.entityID, + entityInstanceID: contextualLink.entityInstanceID, + id: contextualLink.entityID + '[' + contextualLink.entityInstanceID + ']', + label: Drupal.quickedit.metadata.get(contextualLink.entityID, 'label') + }); + Drupal.quickedit.collections.entities.add(entityModel); + + var entityDecorationView = new Drupal.quickedit.EntityDecorationView({ + el: contextualLink.region, + model: entityModel + }); + entityModel.set('entityDecorationView', entityDecorationView); + + _.each(fields, function (field) { + initializeField(field.el, field.fieldID, contextualLink.entityID, contextualLink.entityInstanceID); + }); + fieldsAvailableQueue = _.difference(fieldsAvailableQueue, fields); + + var initContextualLink = _.once(function () { + var $links = $(contextualLink.el).find('.contextual-links'); + var contextualLinkView = new Drupal.quickedit.ContextualLinkView($.extend({ + el: $('<li class="quickedit"><a href="" role="button" aria-pressed="false"></a></li>').prependTo($links), + model: entityModel, + appModel: Drupal.quickedit.app.model + }, options)); + entityModel.set('contextualLinkView', contextualLinkView); + }); + + loadMissingEditors(initContextualLink); + + return true; + } else if (allMetadataExists(fieldIDs)) { + return true; + } + + return false; + } + + function deleteContainedModelsAndQueues($context) { + $context.find('[data-quickedit-entity-id]').addBack('[data-quickedit-entity-id]').each(function (index, entityElement) { + var entityModel = Drupal.quickedit.collections.entities.findWhere({ el: entityElement }); + if (entityModel) { + var contextualLinkView = entityModel.get('contextualLinkView'); + contextualLinkView.undelegateEvents(); + contextualLinkView.remove(); + + entityModel.get('entityDecorationView').remove(); + + entityModel.destroy(); + } + + function hasOtherRegion(contextualLink) { + return contextualLink.region !== entityElement; + } + + contextualLinksQueue = _.filter(contextualLinksQueue, hasOtherRegion); + }); + + $context.find('[data-quickedit-field-id]').addBack('[data-quickedit-field-id]').each(function (index, fieldElement) { + Drupal.quickedit.collections.fields.chain().filter(function (fieldModel) { + return fieldModel.get('el') === fieldElement; + }).invoke('destroy'); + + function hasOtherFieldElement(field) { + return field.el !== fieldElement; + } + + fieldsMetadataQueue = _.filter(fieldsMetadataQueue, hasOtherFieldElement); + fieldsAvailableQueue = _.filter(fieldsAvailableQueue, hasOtherFieldElement); + }); + } +})(jQuery, _, Backbone, Drupal, drupalSettings, window.JSON, window.sessionStorage); \ No newline at end of file