diff --git a/includes/media.filter.inc b/includes/media.filter.inc index 0f0a254..0164de7 100644 --- a/includes/media.filter.inc +++ b/includes/media.filter.inc @@ -131,28 +131,29 @@ function media_token_to_markup($match, $wysiwyg = FALSE) { $attribute_whitelist = media_variable_get('wysiwyg_allowed_attributes'); $settings['attributes'] = array_intersect_key($attributes, array_flip($attribute_whitelist)); - // Many media formatters will want to apply width and height independently - // of the style attribute or the corresponding HTML attributes, so pull - // these two out into top-level settings. Different WYSIWYG editors have - // different behavior with respect to whether they store user-specified - // dimensions in the HTML attributes or the style attribute, so check both. - // Per http://www.w3.org/TR/html5/the-map-element.html#attr-dim-width, the - // HTML attributes are merely hints: CSS takes precedence. - if (isset($settings['attributes']['style'])) { - $css_properties = media_parse_css_declarations($settings['attributes']['style']); - foreach (array('width', 'height') as $dimension) { - if (isset($css_properties[$dimension]) && substr($css_properties[$dimension], -2) == 'px') { - $settings[$dimension] = substr($css_properties[$dimension], 0, -2); - } - elseif (isset($settings['attributes'][$dimension])) { - $settings[$dimension] = $settings['attributes'][$dimension]; + if (!empty($tag_info['attributes']) && is_array($tag_info['attributes'])) { + $attribute_whitelist = media_variable_get('wysiwyg_allowed_attributes'); + $settings['attributes'] = array_intersect_key($tag_info['attributes'], array_flip($attribute_whitelist)); + + // Many media formatters will want to apply width and height independently + // of the style attribute or the corresponding HTML attributes, so pull + // these two out into top-level settings. Different WYSIWYG editors have + // different behavior with respect to whether they store user-specified + // dimensions in the HTML attributes or the style attribute, so check both. + // Per http://www.w3.org/TR/html5/the-map-element.html#attr-dim-width, the + // HTML attributes are merely hints: CSS takes precedence. + if (isset($settings['attributes']['style'])) { + $css_properties = media_parse_css_declarations($settings['attributes']['style']); + foreach (array('width', 'height') as $dimension) { + if (isset($css_properties[$dimension]) && substr($css_properties[$dimension], -2) == 'px') { + $settings[$dimension] = substr($css_properties[$dimension], 0, -2); + } + elseif (isset($settings['attributes'][$dimension])) { + $settings[$dimension] = $settings['attributes'][$dimension]; + } } } } - - if ($wysiwyg) { - $settings['wysiwyg'] = $wysiwyg; - } } catch (Exception $e) { watchdog('media', 'Unable to render media from %tag. Error: %error', array('%tag' => $tag, '%error' => $e->getMessage())); @@ -160,7 +161,20 @@ function media_token_to_markup($match, $wysiwyg = FALSE) { } if ($wysiwyg) { + $settings['wysiwyg'] = $wysiwyg; + // If sending markup to a WYSIWYG, we need to pass the file infomation so + // that a inline macro can be generated when the WYSIWYG is detached. + // The WYSIWYG plugin is expecting this information in the format of a + // urlencoded JSON string stored in the data-file_info attribute of the + // element. $element = media_get_file_without_label($file, $tag_info['view_mode'], $settings); + $data = drupal_json_encode(array( + 'type' => 'media', + 'fid' => $file->fid, + 'view_mode' => $tag_info['view_mode'], + )); + $element['#attributes']['data-file_info'] = urlencode($data); + $element['#attributes']['class'][] = 'media-element'; } else { // Display the field elements. diff --git a/js/wysiwyg-media.js b/js/wysiwyg-media.js index bbcaac0..152e469 100644 --- a/js/wysiwyg-media.js +++ b/js/wysiwyg-media.js @@ -8,153 +8,89 @@ Drupal.media = Drupal.media || {}; -// Define the behavior. +/** + * Register the plugin with WYSIWYG. + */ Drupal.wysiwyg.plugins.media = { /** - * Initializes the tag map. + * Determine whether a DOM element belongs to this plugin. + * + * @param node + * A DOM element */ - initializeTagMap: function () { - if (typeof Drupal.settings.tagmap == 'undefined') { - Drupal.settings.tagmap = { }; - } + isNode: function(node) { + return $(node).is('img.media-element'); }, /** * Execute the button. - * @TODO: Debug calls from this are never called. What's its function? + * + * @param data + * An object containing data about the current selection: + * - format: 'html' when the passed data is HTML content, 'text' when the + * passed data is plain-text content. + * - node: When 'format' is 'html', the focused DOM element in the editor. + * - content: The textual representation of the focused/selected editor + * content. + * @param settings + * The plugin settings, as provided in the plugin's PHP include file. + * @param instanceId + * The ID of the current editor instance. */ invoke: function (data, settings, instanceId) { if (data.format == 'html') { - Drupal.media.popups.mediaBrowser(function (mediaFiles) { - Drupal.wysiwyg.plugins.media.mediaBrowserOnSelect(mediaFiles, instanceId); - }, settings['global']); - } - }, - - /** - * Respond to the mediaBrowser's onSelect event. - * @TODO: Debug calls from this are never called. What's its function? - */ - mediaBrowserOnSelect: function (mediaFiles, instanceId) { - var mediaFile = mediaFiles[0]; - var options = {}; - Drupal.media.popups.mediaStyleSelector(mediaFile, function (formattedMedia) { - Drupal.wysiwyg.plugins.media.insertMediaFile(mediaFile, formattedMedia.type, formattedMedia.html, formattedMedia.options, Drupal.wysiwyg.instances[instanceId]); - }, options); - - return; - }, - - insertMediaFile: function (mediaFile, viewMode, formattedMedia, options, wysiwygInstance) { - - this.initializeTagMap(); - // @TODO: the folks @ ckeditor have told us that there is no way - // to reliably add wrapper divs via normal HTML. - // There is some method of adding a "fake element" - // But until then, we're just going to embed to img. - // This is pretty hacked for now. - // - var imgElement = $(this.stripDivs(formattedMedia)); - this.addImageAttributes(imgElement, mediaFile.fid, viewMode, options); - - var toInsert = this.outerHTML(imgElement); - // Create an inline tag - var inlineTag = Drupal.wysiwyg.plugins.media.createTag(imgElement); - // Add it to the tag map in case the user switches input formats - Drupal.settings.tagmap[inlineTag] = toInsert; - wysiwygInstance.insert(toInsert); - }, - - /** - * Gets the HTML content of an element - * - * @param jQuery element - */ - outerHTML: function (element) { - return $('
').append( element.eq(0).clone() ).html(); - }, - - addImageAttributes: function (imgElement, fid, view_mode, additional) { - // imgElement.attr('fid', fid); - // imgElement.attr('view_mode', view_mode); - // Class so we can find this image later. - imgElement.addClass('media-image'); - this.forceAttributesIntoClass(imgElement, fid, view_mode, additional); - if (additional) { - for (k in additional) { - if (additional.hasOwnProperty(k)) { - if (k === 'attr') { - imgElement.attr(k, additional[k]); - } - } + var insert = new InsertMedia(instanceId); + if (this.isNode(data.node)) { + // Change the view mode for already-inserted media. + var media_file = extract_file_info($(data.node)); + insert.onSelect([media_file]); + } + else { + // Insert new media. + insert.prompt(settings.global); } } }, /** - * Due to problems handling wrapping divs in ckeditor, this is needed. - * - * Going forward, if we don't care about supporting other editors - * we can use the fakeobjects plugin to ckeditor to provide cleaner - * transparency between what Drupal will output
- * instead of just , for now though, we're going to remove all the stuff surrounding the images. - * - * @param String formattedMedia - * Element containing the image - * - * @return HTML of tag inside formattedMedia - */ - stripDivs: function (formattedMedia) { - // Check to see if the image tag has divs to strip - var stripped = null; - if ($(formattedMedia).is('img')) { - stripped = this.outerHTML($(formattedMedia)); - } else { - stripped = this.outerHTML($('img', $(formattedMedia))); - } - // This will fail if we pass the img tag without anything wrapping it, like we do when re-enabling WYSIWYG - return stripped; - }, - - /** * Attach function, called when a rich text editor loads. * This finds all [[tags]] and replaces them with the html * that needs to show in the editor. * + * This finds all JSON macros and replaces them with the HTML placeholder + * that will show in the editor. */ attach: function (content, settings, instanceId) { - var matches = content.match(/\[\[.*?\]\]/g); - this.initializeTagMap(); - var tagmap = Drupal.settings.tagmap; + ensure_tagmap(); + + var tagmap = Drupal.settings.tagmap, + matches = content.match(/\[\[.*?\]\]/g), + media_definition; + if (matches) { - var inlineTag = ""; - for (i = 0; i < matches.length; i++) { - inlineTag = matches[i]; - if (tagmap[inlineTag]) { - // This probably needs some work... - // We need to somehow get the fid propogated here. - // We really want to - var tagContent = tagmap[inlineTag]; - var mediaMarkup = this.stripDivs(tagContent); // THis is
.. - - var _tag = inlineTag; - _tag = _tag.replace('[[',''); - _tag = _tag.replace(']]',''); + for (var index in matches) { + var macro = matches[index]; + + if (tagmap[macro]) { + var media_json = macro.replace('[[', '').replace(']]', ''); + + // Make sure that the media JSON is valid. try { - mediaObj = JSON.parse(_tag); + media_definition = JSON.parse(media_json); } - catch(err) { - mediaObj = null; + catch (err) { + media_definition = null; } - if(mediaObj) { - var imgElement = $(mediaMarkup); - this.addImageAttributes(imgElement, mediaObj.fid, mediaObj.view_mode); - var toInsert = this.outerHTML(imgElement); - content = content.replace(inlineTag, toInsert); + if (media_definition) { + // Apply attributes. + var element = create_element(tagmap[macro], media_definition); + var markup = outerHTML(element); + + content = content.replace(macro, markup); } } else { - debug.debug("Could not find content for " + inlineTag); + debug.debug("Could not find content for " + macro); } } } @@ -165,221 +101,186 @@ Drupal.wysiwyg.plugins.media = { * Detach function, called when a rich text editor detaches */ detach: function (content, settings, instanceId) { - // Replace all Media placeholder images with the appropriate inline json - // string. Using a regular expression instead of jQuery manipulation to - // prevent