diff --git a/modules/media_wysiwyg/images/wysiwyg-media.gif b/modules/media_wysiwyg/images/wysiwyg-media.gif deleted file mode 100644 index 495e71d37e1cc541b8de361bd2811818931af1be..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 139 zcmZ?wbhEHb6k!lySi}GV4Gj$k4jef6@caM&|G@$vLh&aHCp!ZxgARxTQp>;`5V7md zKZ8>otM-0tblmY?_Ci96YsVS3x_fPU2egVmu3quxRo~{A{`p+mlbINq7{h%Nv{&?< jT++aq@M(cZ%G6tHGWG{4=}7B_o2Z^iIh(gzn86wV2FWxI diff --git a/modules/media_wysiwyg/media_wysiwyg.ckeditor.inc b/modules/media_wysiwyg/media_wysiwyg.ckeditor.inc new file mode 100644 index 0000000..3434d1d --- /dev/null +++ b/modules/media_wysiwyg/media_wysiwyg.ckeditor.inc @@ -0,0 +1,16 @@ + variable_get('media_wysiwyg_wysiwyg_title', t('Media browser')), 'vendor url' => 'http://drupal.org/project/media', - 'icon path' => drupal_get_path('module', 'media_wysiwyg') . '/images', - 'icon file' => 'wysiwyg-media.gif', + 'icon path' => drupal_get_path('module', 'media_wysiwyg') . '/wysiwyg_plugins/media_ckeditor/images', + 'icon file' => 'icon.gif', 'icon title' => variable_get('media_wysiwyg_wysiwyg_icon_title', t('Add media')), // @todo: move this to the plugin directory for the wysiwyg plugin. 'js path' => drupal_get_path('module', 'media_wysiwyg') . '/js', diff --git a/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/images/icon.gif b/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/images/icon.gif new file mode 100644 index 0000000000000000000000000000000000000000..bf9b501c3dd5a10dcbc33ce2491afe1ea55fb737 GIT binary patch literal 126 zcmZ?wbhEHb6krfwSj52a|NsAk55FHcaG;@~fdR|~l0cyNlZBC;ft5iA!~v;gV0Mn! zb;sM_)DNZ&KjMOxwKKS-(.*?)/gi, ''); + } else { + wysiwygHTML = '' + wysiwygHTML + ''; + } + + var editorElement = CKEDITOR.dom.element.createFromHtml(wysiwygHTML); + ckeditorInstance.insertElement(editorElement); + + // Initialize widget on our html if possible. + if (parseFloat(CKEDITOR.version) >= 4.3 && typeof(CKEDITOR.plugins.registered.widget) != 'undefined') { + ckeditorInstance.widgets.initOn( editorElement, 'mediabox' ); + } + }, + + /** + * Forces custom attributes into the class field of the specified image. + * + * Due to a bug in some versions of Firefox + * (http://forums.mozillazine.org/viewtopic.php?f=9&t=1991855), the + * custom attributes used to share information about the image are + * being stripped as the image markup is set into the rich text + * editor. Here we encode these attributes into the class field so + * the data survives. + * + * @param imgElement + * The image + * @fid + * The file id. + * @param view_mode + * The view mode. + * @param additional + * Additional attributes to add to the image. + */ + forceAttributesIntoClass: function (imgElement, fid, view_mode, additional) { + var wysiwyg = imgElement.attr('wysiwyg'); + if (wysiwyg) { + imgElement.addClass('attr__wysiwyg__' + wysiwyg); + } + var format = imgElement.attr('format'); + if (format) { + imgElement.addClass('attr__format__' + format); + } + var typeOf = imgElement.attr('typeof'); + if (typeOf) { + imgElement.addClass('attr__typeof__' + typeOf); + } + if (fid) { + imgElement.addClass('img__fid__' + fid); + } + if (view_mode) { + imgElement.addClass('img__view_mode__' + view_mode); + } + if (additional) { + for (var name in additional) { + if (additional.hasOwnProperty(name)) { + switch (name) { + case 'field_file_image_alt_text[und][0][value]': + imgElement.attr('alt', additional[name]); + break; + case 'field_file_image_title_text[und][0][value]': + imgElement.attr('title', additional[name]); + break; + default: + imgElement.addClass('attr__' + name + '__' + additional[name]); + break; + } + } + } + } + }, + + /** + * Retrieves encoded attributes from the specified class string. + * + * @param classString + * A string containing the value of the class attribute. + * @return + * An array containing the attribute names as keys, and an object + * with the name, value, and attribute type (either 'attr' or + * 'img', depending on whether it is an image attribute or should + * be it the attributes section) + */ + getAttributesFromClass: function (classString) { + var actualClasses = []; + var otherAttributes = []; + var classes = classString.split(' '); + var regexp = new RegExp('^(attr|img)__([^\S]*)__([^\S]*)$'); + for (var index = 0; index < classes.length; index++) { + var matches = classes[index].match(regexp); + if (matches && matches.length === 4) { + otherAttributes[matches[2]] = { + name: matches[2], + value: matches[3], + type: matches[1] + }; + } + else { + actualClasses.push(classes[index]); + } + } + if (actualClasses.length > 0) { + otherAttributes['class'] = { + name: 'class', + value: actualClasses.join(' '), + type: 'attr' + }; + } + return otherAttributes; + }, + + sortAttributes: function (a, b) { + var nameA = a.name.toLowerCase(); + var nameB = b.name.toLowerCase(); + if (nameA < nameB) { + return -1; + } + if (nameA > nameB) { + return 1; + } + return 0; + } + }; + +})(jQuery); diff --git a/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/plugin.js b/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/plugin.js new file mode 100644 index 0000000..635ef44 --- /dev/null +++ b/modules/media_wysiwyg/wysiwyg_plugins/media_ckeditor/plugin.js @@ -0,0 +1,216 @@ +/* +Copyright (c) 2003-2013, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +/** + * @file Plugin for inserting images from Drupal media module + * + * @TODO Remove all the legecy media wrapper once it's sure nobody uses that + * anymore. + */ +( function() { + var mediaPluginDefinition = { + icons: 'media', + requires: ['button'], + // Check if this instance has widget support. All the default distributions + // of the editor have the widget plugin disabled by default. + hasWidgetSupport: typeof(CKEDITOR.plugins.registered.widget) != 'undefined', + mediaLegacyWrappers: false, + + // Wrap Drupal plugin in a proxy plugin. + init: function(editor){ + editor.addCommand( 'media', + { + exec: function (editor) { + var data = { + format: 'html', + node: null, + content: '' + }; + var selection = editor.getSelection(); + + if (selection) { + data.node = selection.getSelectedElement(); + if (data.node) { + data.node = data.node.$; + } + if (selection.getType() == CKEDITOR.SELECTION_TEXT) { + if (CKEDITOR.env.ie) { + data.content = selection.getNative().createRange().text; + } + + else { + data.content = selection.getNative().toString(); + } + } + else if (data.node) { + // content is supposed to contain the "outerHTML". + data.content = data.node.parentNode.innerHTML; + } + } + Drupal.settings.ckeditor.plugins['media'].invoke(data, Drupal.settings.ckeditor.plugins['media'], editor.name); + } + }); + + editor.ui.addButton( 'Media', + { + label: 'Add media', + command: 'media', + icon: this.path + 'images/icon.gif' + }); + + var ckeditorversion = parseFloat(CKEDITOR.version); + + // Because the media comment wrapper don't work well for CKEditor we + // replace them by using a custom mediawrapper element. + // Instead having + // + // We wrap the placeholder with + // + // That way we can deal better with selections - see selectionChange. + CKEDITOR.dtd['mediawrapper'] = CKEDITOR.dtd; + CKEDITOR.dtd.$blockLimit['mediawrapper'] = 1; + CKEDITOR.dtd.$inline['mediawrapper'] = 1; + CKEDITOR.dtd.$nonEditable['mediawrapper'] = 1; + if (ckeditorversion >= 4.1) { + // Register allowed tag for advanced filtering. + editor.filter.allow( 'mediawrapper[!data]', 'MediaWrapper' ); + // Don't remove the data-file_info attribute added by media! + editor.filter.allow( '*[!data-file_info]', 'MediaWrapper' ); + // Objects should be selected as a whole in the editor. + CKEDITOR.dtd.$object['mediawrapper'] = 1; + } + function prepareDataForWysiwygMode(data) { + data = Drupal.media.filter.replaceTokenWithPlaceholder(data); + // Legacy media wrapper. + mediaPluginDefinition.mediaLegacyWrappers = (data.indexOf("(.*?)/gi, '$2'); + return data; + } + function prepareDataForSourceMode(data) { + var replacement = '$2'; + // Legacy wrapper + if (mediaPluginDefinition.mediaLegacyWrappers) { + replacement = '$2'; + } + data = data.replace(/(.*?)<\/mediawrapper>/gi, replacement); + data = Drupal.media.filter.replacePlaceholderWithToken(data); + return data; + } + + // Ensure the tokens are replaced by placeholders while editing. + // Check for widget support. + if (mediaPluginDefinition.hasWidgetSupport) { + editor.widgets.add( 'mediabox', + { + button: 'Create a mediabox', + template: '', + editables: {}, + allowedContent: '*', + upcast: function( element ) { + if (element.name != 'mediawrapper') { + // Ensure media tokens are converted to media placeholdes. + element.setHtml(prepareDataForWysiwygMode(element.getHtml())); + } + return element.name == 'mediawrapper'; + }, + + downcast: function( widgetElement ) { + var token = prepareDataForSourceMode(widgetElement.getOuterHtml()); + return new CKEDITOR.htmlParser.text(token); + return element.name == 'mediawrapper'; + } + }); + } + else if (ckeditorversion >= 4) { + // CKEditor >=4.0 + editor.on('setData', function( event ) { + event.data.dataValue = prepareDataForWysiwygMode(event.data.dataValue); + }); + } + else { + // CKEditor >=3.6 behaviour. + editor.on( 'beforeSetMode', function( event, data ) { + event.removeListener(); + var wysiwyg = editor._.modes[ 'wysiwyg' ]; + var source = editor._.modes[ 'source' ]; + wysiwyg.loadData = CKEDITOR.tools.override( wysiwyg.loadData, function( org ) + { + return function( data ) { + return ( org.call( this, prepareDataForWysiwygMode(data)) ); + }; + } ); + source.loadData = CKEDITOR.tools.override( source.loadData, function( org ) + { + return function( data ) { + return ( org.call( this, prepareDataForSourceMode(data) ) ); + }; + } ); + }); + } + + // Provide alternative to the widget functionality introduced in 4.3. + if (!mediaPluginDefinition.hasWidgetSupport) { + // Ensure tokens instead the html element is saved. + editor.on('getData', function( event ) { + event.data.dataValue = prepareDataForSourceMode(event.data.dataValue); + }); + + // Ensure our enclosing wrappers are always included in the selection. + editor.on('selectionChange', function( event ) { + var ranges = editor.getSelection().getRanges().createIterator(); + var newRanges = []; + var currRange; + while(currRange = ranges.getNextRange()) { + var commonAncestor = currRange.getCommonAncestor(false); + if (commonAncestor && typeof(commonAncestor.getName) != 'undefined' && commonAncestor.getName() == 'mediawrapper') { + var range = new CKEDITOR.dom.range( editor.document ); + if (currRange.collapsed === true) { + // Don't allow selection within the wrapper element. + if (currRange.startOffset == 0) { + // While v3 plays nice with setting start and end to avoid + // editing within the media wrapper element, v4 ignores that. + // Thus we try to move the cursor further away. + if (parseInt(CKEDITOR.version) > 3) { + range.setStart(commonAncestor.getPrevious()); + range.setEnd(commonAncestor.getPrevious()); + } + else { + range.setStartBefore(commonAncestor); + } + } + else { + // While v3 plays nice with setting start and end to avoid + // editing within the media wrapper element, v4 ignores that. + // Thus we try to move the cursor further away. + if (parseInt(CKEDITOR.version) > 3) { + range.setStart(commonAncestor.getNext(), 1); + range.setEnd(commonAncestor.getNext(), 1); + } + else { + range.setStartAfter(commonAncestor); + } + } + } + else { + // Always select the whole wrapper element. + range.setStartBefore(commonAncestor); + range.setEndAfter(commonAncestor); + } + newRanges.push(range); + } + } + if (newRanges.length) { + editor.getSelection().selectRanges(newRanges); + } + }); + } + } + }; + // Add dependency to widget plugin if possible. + if (parseFloat(CKEDITOR.version) >= 4.3 && mediaPluginDefinition.hasWidgetSupport) { + mediaPluginDefinition.requires.push('widget'); + } + CKEDITOR.plugins.add( 'media', mediaPluginDefinition); +} )();