Chris@0: /** Chris@0: * DO NOT EDIT THIS FILE. Chris@0: * See the following change record for more information, Chris@0: * https://www.drupal.org/node/2815083 Chris@0: * @preserve Chris@0: **/ Chris@0: Chris@0: (function ($, Drupal, Backbone, CKEDITOR, _) { Chris@0: Drupal.ckeditor.ControllerView = Backbone.View.extend({ Chris@0: events: {}, Chris@0: Chris@0: initialize: function initialize() { Chris@0: this.getCKEditorFeatures(this.model.get('hiddenEditorConfig'), this.disableFeaturesDisallowedByFilters.bind(this)); Chris@0: Chris@0: this.model.listenTo(this.model, 'change:activeEditorConfig', this.model.sync); Chris@0: this.listenTo(this.model, 'change:isDirty', this.parseEditorDOM); Chris@0: }, Chris@0: parseEditorDOM: function parseEditorDOM(model, isDirty, options) { Chris@0: if (isDirty) { Chris@0: var currentConfig = this.model.get('activeEditorConfig'); Chris@0: Chris@0: var rows = []; Chris@0: this.$el.find('.ckeditor-active-toolbar-configuration').children('.ckeditor-row').each(function () { Chris@0: var groups = []; Chris@0: Chris@0: $(this).find('.ckeditor-toolbar-group').each(function () { Chris@0: var $group = $(this); Chris@0: var $buttons = $group.find('.ckeditor-button'); Chris@0: if ($buttons.length) { Chris@0: var group = { Chris@0: name: $group.attr('data-drupal-ckeditor-toolbar-group-name'), Chris@0: items: [] Chris@0: }; Chris@0: $group.find('.ckeditor-button, .ckeditor-multiple-button').each(function () { Chris@0: group.items.push($(this).attr('data-drupal-ckeditor-button-name')); Chris@0: }); Chris@0: groups.push(group); Chris@0: } Chris@0: }); Chris@0: if (groups.length) { Chris@0: rows.push(groups); Chris@0: } Chris@0: }); Chris@0: this.model.set('activeEditorConfig', rows); Chris@0: Chris@0: this.model.set('isDirty', false); Chris@0: Chris@0: if (options.broadcast !== false) { Chris@0: var prev = this.getButtonList(currentConfig); Chris@0: var next = this.getButtonList(rows); Chris@0: if (prev.length !== next.length) { Chris@0: this.$el.find('.ckeditor-toolbar-active').trigger('CKEditorToolbarChanged', [prev.length < next.length ? 'added' : 'removed', _.difference(_.union(prev, next), _.intersection(prev, next))[0]]); Chris@0: } Chris@0: } Chris@0: } Chris@0: }, Chris@0: getCKEditorFeatures: function getCKEditorFeatures(CKEditorConfig, callback) { Chris@0: var getProperties = function getProperties(CKEPropertiesList) { Chris@0: return _.isObject(CKEPropertiesList) ? _.keys(CKEPropertiesList) : []; Chris@0: }; Chris@0: Chris@0: var convertCKERulesToEditorFeature = function convertCKERulesToEditorFeature(feature, CKEFeatureRules) { Chris@0: for (var i = 0; i < CKEFeatureRules.length; i++) { Chris@0: var CKERule = CKEFeatureRules[i]; Chris@0: var rule = new Drupal.EditorFeatureHTMLRule(); Chris@0: Chris@0: var tags = getProperties(CKERule.elements); Chris@0: rule.required.tags = CKERule.propertiesOnly ? [] : tags; Chris@0: rule.allowed.tags = tags; Chris@0: Chris@0: rule.required.attributes = getProperties(CKERule.requiredAttributes); Chris@0: rule.allowed.attributes = getProperties(CKERule.attributes); Chris@0: Chris@0: rule.required.styles = getProperties(CKERule.requiredStyles); Chris@0: rule.allowed.styles = getProperties(CKERule.styles); Chris@0: Chris@0: rule.required.classes = getProperties(CKERule.requiredClasses); Chris@0: rule.allowed.classes = getProperties(CKERule.classes); Chris@0: Chris@0: rule.raw = CKERule; Chris@0: Chris@0: feature.addHTMLRule(rule); Chris@0: } Chris@0: }; Chris@0: Chris@0: var hiddenCKEditorID = 'ckeditor-hidden'; Chris@0: if (CKEDITOR.instances[hiddenCKEditorID]) { Chris@0: CKEDITOR.instances[hiddenCKEditorID].destroy(true); Chris@0: } Chris@0: Chris@0: var hiddenEditorConfig = this.model.get('hiddenEditorConfig'); Chris@0: if (hiddenEditorConfig.drupalExternalPlugins) { Chris@0: var externalPlugins = hiddenEditorConfig.drupalExternalPlugins; Chris@14: Object.keys(externalPlugins || {}).forEach(function (pluginName) { Chris@14: CKEDITOR.plugins.addExternal(pluginName, externalPlugins[pluginName], ''); Chris@14: }); Chris@0: } Chris@0: CKEDITOR.inline($('#' + hiddenCKEditorID).get(0), CKEditorConfig); Chris@0: Chris@0: CKEDITOR.once('instanceReady', function (e) { Chris@0: if (e.editor.name === hiddenCKEditorID) { Chris@0: var CKEFeatureRulesMap = {}; Chris@0: var rules = e.editor.filter.allowedContent; Chris@0: var rule = void 0; Chris@0: var name = void 0; Chris@0: for (var i = 0; i < rules.length; i++) { Chris@0: rule = rules[i]; Chris@0: name = rule.featureName || ':('; Chris@0: if (!CKEFeatureRulesMap[name]) { Chris@0: CKEFeatureRulesMap[name] = []; Chris@0: } Chris@0: CKEFeatureRulesMap[name].push(rule); Chris@0: } Chris@0: Chris@0: var features = {}; Chris@0: var buttonsToFeatures = {}; Chris@14: Object.keys(CKEFeatureRulesMap).forEach(function (featureName) { Chris@14: var feature = new Drupal.EditorFeature(featureName); Chris@14: convertCKERulesToEditorFeature(feature, CKEFeatureRulesMap[featureName]); Chris@14: features[featureName] = feature; Chris@14: var command = e.editor.getCommand(featureName); Chris@14: if (command) { Chris@14: buttonsToFeatures[command.uiItems[0].name] = featureName; Chris@0: } Chris@14: }); Chris@0: Chris@0: callback(features, buttonsToFeatures); Chris@0: } Chris@0: }); Chris@0: }, Chris@0: getFeatureForButton: function getFeatureForButton(button) { Chris@0: if (button === '-') { Chris@0: return false; Chris@0: } Chris@0: Chris@0: var featureName = this.model.get('buttonsToFeatures')[button.toLowerCase()]; Chris@0: Chris@0: if (!featureName) { Chris@0: featureName = button.toLowerCase(); Chris@0: } Chris@0: var featuresMetadata = this.model.get('featuresMetadata'); Chris@0: if (!featuresMetadata[featureName]) { Chris@0: featuresMetadata[featureName] = new Drupal.EditorFeature(featureName); Chris@0: this.model.set('featuresMetadata', featuresMetadata); Chris@0: } Chris@0: return featuresMetadata[featureName]; Chris@0: }, Chris@0: disableFeaturesDisallowedByFilters: function disableFeaturesDisallowedByFilters(features, buttonsToFeatures) { Chris@0: this.model.set('featuresMetadata', features); Chris@0: Chris@0: this.model.set('buttonsToFeatures', buttonsToFeatures); Chris@0: Chris@0: this.broadcastConfigurationChanges(this.$el); Chris@0: Chris@0: var existingButtons = []; Chris@0: Chris@0: var buttonGroups = _.flatten(this.model.get('activeEditorConfig')); Chris@0: for (var i = 0; i < buttonGroups.length; i++) { Chris@0: var buttons = buttonGroups[i].items; Chris@0: for (var k = 0; k < buttons.length; k++) { Chris@0: existingButtons.push(buttons[k]); Chris@0: } Chris@0: } Chris@0: Chris@0: existingButtons = _.unique(existingButtons); Chris@0: Chris@0: for (var n = 0; n < existingButtons.length; n++) { Chris@0: var button = existingButtons[n]; Chris@0: var feature = this.getFeatureForButton(button); Chris@0: Chris@0: if (feature === false) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: if (Drupal.editorConfiguration.featureIsAllowedByFilters(feature)) { Chris@0: this.$el.find('.ckeditor-toolbar-active').trigger('CKEditorToolbarChanged', ['added', existingButtons[n]]); Chris@0: } else { Chris@0: $('.ckeditor-toolbar-active li[data-drupal-ckeditor-button-name="' + button + '"]').detach().appendTo('.ckeditor-toolbar-disabled > .ckeditor-toolbar-available > ul'); Chris@0: Chris@0: this.model.set({ isDirty: true }, { broadcast: false }); Chris@0: } Chris@0: } Chris@0: }, Chris@0: broadcastConfigurationChanges: function broadcastConfigurationChanges($ckeditorToolbar) { Chris@0: var view = this; Chris@0: var hiddenEditorConfig = this.model.get('hiddenEditorConfig'); Chris@0: var getFeatureForButton = this.getFeatureForButton.bind(this); Chris@0: var getCKEditorFeatures = this.getCKEditorFeatures.bind(this); Chris@0: $ckeditorToolbar.find('.ckeditor-toolbar-active').on('CKEditorToolbarChanged.ckeditorAdmin', function (event, action, button) { Chris@0: var feature = getFeatureForButton(button); Chris@0: Chris@0: if (feature === false) { Chris@0: return; Chris@0: } Chris@0: Chris@0: var configEvent = action === 'added' ? 'addedFeature' : 'removedFeature'; Chris@0: Drupal.editorConfiguration[configEvent](feature); Chris@0: }).on('CKEditorPluginSettingsChanged.ckeditorAdmin', function (event, settingsChanges) { Chris@14: Object.keys(settingsChanges || {}).forEach(function (key) { Chris@14: hiddenEditorConfig[key] = settingsChanges[key]; Chris@14: }); Chris@0: Chris@0: getCKEditorFeatures(hiddenEditorConfig, function (features) { Chris@0: var featuresMetadata = view.model.get('featuresMetadata'); Chris@14: Object.keys(features || {}).forEach(function (name) { Chris@14: var feature = features[name]; Chris@14: if (featuresMetadata.hasOwnProperty(name) && !_.isEqual(featuresMetadata[name], feature)) { Chris@14: Drupal.editorConfiguration.modifiedFeature(feature); Chris@0: } Chris@14: }); Chris@0: Chris@0: view.model.set('featuresMetadata', features); Chris@0: }); Chris@0: }); Chris@0: }, Chris@0: getButtonList: function getButtonList(config) { Chris@0: var buttons = []; Chris@0: Chris@0: config = _.flatten(config); Chris@0: Chris@0: config.forEach(function (group) { Chris@0: group.items.forEach(function (button) { Chris@0: buttons.push(button); Chris@0: }); Chris@0: }); Chris@0: Chris@0: return _.without(buttons, '-'); Chris@0: } Chris@0: }); Chris@0: })(jQuery, Drupal, Backbone, CKEDITOR, _);