Problem/Motivation

There have recently been two different approaches to solving media alignment in Media module. One solution was to use the alignment buttons in the wysiwyg editor, solved in #2018075: Media inline filter: Delegate "float" to outer element. The second solution added an alignment option within the media browser selector in #2842391: better support for float media left and float media right. These two adds two conflicting css classes to the media container element, so it's very much possible to have html that says:

<div class="media … media-float-left media-wysiwyg-align-right">
  …
</div>

There was also an issue that addressed this, and was set as fixed without fixing the addressed problem: #2913361: Media inline filter float classes are inconsistent.

Suggested resolution

Unify and have these solutions work on the same macros and code, and have a common, merged class name for alignment. Keep both solutions for alignment, but make them talk the same language.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

kaare created an issue. See original summary.

joseph.olstad’s picture

Hmm, I didn't notice this.
what is your configuration? are you using wysiwyg with tinymce/ckeditor library or media_ckeditor with ckeditor module?

can you reproduce this on the media_dev distribution?

Screenshot of media_dev in action

kaare’s picture

My config is wysiwyg.module + ckeditor. The behavior is the same in the media_dev distribution (simplytest.me). Steps to reproduce this behavior:

  • Enable text alignment in e.g. full_html wysiwyg profile (admin/config/content/wysiwyg/profile/full_html).
  • Edit a node with full_html as text format, insert media and select Right alignment in media browser settings.
  • In the wysiwyg editor, click on the inserted media and click on the Align Left icon in the wysiwyg toolbar.
  • Save.

Two different classes now compete about the proper alignment. Using the media_dev distro on simplytest.me, I've looked into the generated macros in the four different configurations:

  1. No alignment
  2. Aligned right only in media browser
  3. Aligned left only in wysiwyg editor
  4. Aligned both right in media browser and left in wysiwyg editor

The media macro in these cases are as following (irrelevant keys/attributes removed)

No alignment

[[{
  "fields":{
    "alignment":""
  },
  "field_deltas":{
    "4":{
      "alignment":""
    }
  },
  "attributes":{
    "class":"media-element file-teaser",
    "data-delta":"4"

  }
}]]

Aligned right in media browser

[[{
  "fid":"5",
  "fields":{
    "alignment":"right"
  },
  "field_deltas":{
    "6":{
      "alignment":"right"
    },
    "7":{
      "alignment":"right"
    }
  },
  "attributes":{
    "class":"media-element file-teaser media-wysiwyg-align-right",
    "data-delta":"7"
  }
}]]

Aligned left in wysiwyg editor

[[{
  "fields":{
    "alignment":""
  },
  "field_deltas": {
    "4":{
      "alignment":""
    },
    "5":{
      "alignment":""
    }
  },
  "attributes":{
    "style":"float: left;",
    "class":"media-element file-teaser",
    "data-delta":"5"
  }
}]]

Aligned both right in media browser and left in wysiwyg editor

[[{
  "fields":{
    "alignment":"right"
  },
  "field_deltas":{
    "6":{
      "alignment":"right"
    }
  },
  "attributes":{
    "style":"float: left;",
    "class":"media-element file-teaser media-wysiwyg-align-right",
    "data-delta":"6"
  }
}]]
kaare’s picture

Two different solutions, two different classes and two independent attributes in the media macro for determining alignment. They compete directly against each other and really must be united. I suspect the solution in #2842391: better support for float media left and float media right is the right way forward, i.e. the code for handling alignment through wysiwyg buttons must adhere to this code. Using inline styling for alignment is really limiting (even though I think it's only set in the macro, and manipulated to css classes in js, correct me if I'm wrong).

These two approaches should work against the same macro attribute and set the same class. If I set the alignment in media browser, I should be able to alter it in the wysiwyg editor.

kaare’s picture

I'm looking into this now and need to dump my brain about the way forward:

The goal is to position media elements only with classes and use the same class names both from media browser alignment and wysiwyg alignment. I.e. no translation of inline floats to classes during content filtering (macro expansion). #2018075: Media inline filter: Delegate "float" to outer element added this approach and is in its entirety solved server side in PHP. It's a quick and "dirty" approach and the simplest solution to solve this issue is to rename the css classes introduced here to media-wysiwyg-align-(left|right|center). It's still a bad solution. The only 'stored' data about media alignment is by inline styles set by the wysiwyg editor.

A better approach is to manipulate the media macro directly, either in JS upon aligning or server side during content save. If done upon aligning we need a different solution for each wysiwyg editor through plugins. E.g. ckeditor needs an override or additional behavior for its core justify plugin. If this is solved server side we can utilize the code added in #2018075: Media inline filter: Delegate "float" to outer element and attach the proper css classes to the macro prior to content save. The saved macro should then be stripped for all inline floats.

For this issue to be complete/solved we will also need to be backwards compatible with the 7.x-2.x branch. That means either:

  • Add an update that converts media macros stored in databases to have uniform alignment code.
  • Keep the two conflicting css definitions, but mark one of the obsolete. This requires less work and may be an acceptable solution as Drupal 7 and media-7.x hopefully is declining in usage.
joseph.olstad’s picture

Can you turn these ideas into a patch? Either option fine
Would be nice

kaare’s picture

Component: Code » Media WYSIWYG
Status: Active » Needs review
FileSize
9.11 KB

Unfinished initial attempt. This adds a CKEditor plugin that take on the alignment commands/buttons and adds proper alignment classes to the media placeholder in the wysiwyg editor. It updates the Drupal.settings.mediaDataMap entries with proper alignment so you can set the alignment using the wysiwyg align buttons, open the media browser and have its setting properly reflected here.

The plugin integration is only made for the wysiwyg.module + ckeditor integration using the media_dev distribution during development. It's a separate plugin that have to be enabled for the selected wysiwyg profile in admin/config/content/wysiwyg/profile.

TODO

  • Integrate it as part of the media wysiwyg plugin, not as a separate plugin, or have the plugin always loaded with the media wysiwyg plugin.
  • Find a better home for the editor-specific code/plugins. media_wysiwyg/native_plugins/ckeditor/media_align sounds wrong. How about media_wysiwyg/editors/ckeditor/PLUGIN/ or media_wysiwyg/js/ckeditor/PLUGIN/?
  • Remove any signs of <… style="float:left"> or <… align="left"> handling, i.e. basically revert #2018075: Media inline filter: Delegate "float" to outer element
  • Rephrase and update the help text related to the media_wysiwyg_alignment setting.
  • Add update function that converts existing macros from using inline style to using alignment from settings.
  • Stabilize and agree upon new wysiwyg alignment API in media_wysiwyg/js/wysiwyg-media.js.
  • Add ckeditor integration to the Media CKEditor project. (Create separate issue over there).
kaare’s picture

Discussion/Questions

  • Is using only CSS classes for alignment the true way forward? Are there any situations where this isn't the right thing to do? Should we have an option for what scheme to use for alignment, i.e. inline style based or based on css classes? I vote yes towards having css class only alignment.
  • The media wysiwyg alignment setting currently reflect the above scenario with css alignment as an option overall. Should this be limited to only allow alignment of media within the media browser, i.e. a UI setting? If UI setting only, the css files for actual alignment needs to be permanently added in order to have the One True Way of aligment using css classes.
  • The media macro is a mess. It contains a lot of overlapping settings and contains both file info about the inserted media and the base file. The entire field_deltas branch is superfluous and could easily be rebuilt by setting what delta the inserted element has. This point really is a separate issue, but I included it here as it is an observation / follow up of this issue.
joseph.olstad’s picture

Q) Is using only CSS classes for alignment the true way forward?
A) The entity_view_mode module used in conjunction with media to provide more customized 'view modes' can allow you to create custom view modes (alignments) using Drupal core image styles provides , however CSS classes is a good way to go because it is easier to use in a more WYSIWYG way so that the alignment in the edit mode reflects more closely what the alignment will look like after the save.

Q) UI setting only, css for alignment need to be added permanently
A) sure, there's already alignment css in the media_wysiwyg css (I believe that one), wherever we put it, good place to add more as needed.

Q) media macro (this point is a seperate issue)
A) yes agreed, separate issue. Not sure what you mean by a mess, open a new issue.

kaare’s picture

I interpret your answers as a yes to move forward with the TODO-list. Custom view modes through entity_view_modes adds lots of complexity to site builders. Having different view modes only to align media left or right sounds overkill, but I see the possibility.

joseph.olstad’s picture

Cool Ya sounds like you know as much or more about the challenge than I do. Looking forward to seeing this in action

kaare’s picture

Changes since last patch:

  • CKEditor mediaJustify plugin always loaded whenever media plugin are
  • Moved shared js media alignment utilities to new file
  • Made an alignment aggregator function to address all various methods to align media in macros.
  • Some semi-related code cleanup of media_wysiwyg_token_to_markup() with regard to attribute parsing.

Status: Needs review » Needs work

The last submitted patch, 12: media-2931790-consistent-alignment-12.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

kaare’s picture

Improved tests and fixed some coding style.

joseph.olstad’s picture

Status: Needs work » Needs review
joseph.olstad’s picture

quite the patch there. I'll try to review soon. Meanwhile, hopefully the community can jump in and help review as well.

kaare’s picture

This issue/patch could be split up in several issues, e.g:

  1. "Add CKEditor plugin that uses media settings and classes for alignment" — Example/base for other wysiwyg plugins. This touches almost only the js bits.
  2. "Aggregate and uniform various methods for aligning media in media macros" — Clean up the media macro during content filtering and replace the inline styles 'float's and the 'align' tag with media alignment setting only.
  3. "Add update function or maintenance task that cleans up all media tags in db"
  4. — For large databases this would be a very heavy operation and should probably be run separately from the update hooks. It might also be postponed on or seen in conjunction with the separate issue mentioned in the last point of #8 regarding cleaning up the media tag macro. There is a lot of duplicate information that might appear in each macro.

joseph.olstad’s picture

Hi @kaare , for the 'Add update function or maintenance task' this can definately be done in a hook_update
however as you mention the possible heavy operation, no problem if it's done using the batch api.

Here is an example on using the batch api in a module , I've done it before, it works very well, you can break the jobs down into smaller chunks , that way the job will not timeout, even on the most rediculously large database.

Here is the example:
https://www.drupal.org/forum/support/module-development-and-code-questio...

Any chance you can do this? I'd like to put your patch into the 7.x-3.x branch.

Munge Takk

kaare’s picture

I've started working on this and have come to the conclusion that a forceful db upgrade during hook_update is kind of intrusive and might actually b0rk content. Especially since this patch is backward compatible with the macro format as it is now. Instead I've stared playing with hook_requirements during $phase == 'runtime', i.e. Site status:

Only local images are allowed.

You'll notice that I've introduced a version tag on the macro format. Even though this code will only live for the D7 cycle and eventually die it makes sense to have a version on the macro tag format. I've selected the same version for this format as the upcoming 3.0 release, and its version don't have to bump along with media.module unless the format actually changes (referring to the no-nid-issue about duplicate settings/info in the macro tag).

Thanks for the hints about Batch API. I've worked with this before, so have a good idea how to implement it. Just haven't decided about using QueueAPI as companion. Otherwise it's a rather straight forward look through the {file_usage} table and using the entity type and entity ids from there.

kaare’s picture

Oh btw:

Munge Takk

This made my day :-) And it's spelled "Mange takk"

joseph.olstad’s picture

Keep up the great work.

kaare’s picture

Norway is quite popular (expensive, though) if you want to see spectacular nature, and the northern light in this time of the year :-)

Anyway, here is the latest update which attacks the upgrade part of media macros. As I mentioned above, this introduces versions on the media token format (previously named 'macro'. What is the correct term anyway?), in order to keep track of what has been upgraded. Whether versions on the macro is the right thing to do or use some other kind of state to indicate that the macros need upgrading is an open question. Haven't weighted other possibilities very much. The actual upgrade uses the field attach API to write the upgraded text fields back to storage, omitting all(?) drupal hooks related to entity update. Only touched/upgraded fields are written back to storage. What entities to scan for media tokens in is based on the content of the {file_usage} table.

Status: Needs review » Needs work

The last submitted patch, 22: media-2931790-consistent-alignment-22.patch, failed testing. View results

kaare’s picture

I have no idea what patch I added in previous post. Here is the correct one.

kaare’s picture

Status: Needs review » Needs work

No need to review this. The patch has outgrown its original purpose and i'll split it up as suggested in #17.

joseph.olstad’s picture

If you want a quick sandbox to test this, try cloning the media_dev distribution code
then modify the make file in there containing the media module , add a patch section with your patch
you can then use drush make to create the filesystem (the drupal core, contrib modules and libraries will be downloaded for you)

joseph.olstad’s picture

Meanwhile, I'll try to review whatever you've got asap.

kaare’s picture

Sub-issues created. Only minor glue coded is required to actually perform tag macro upgrades and have this entire shebang rolling.

joseph.olstad’s picture

Kaare, glue code? so is the patch containing this code or do you mean extra code needs to be written on a case-by-case basis?
Munga takk

joseph.olstad’s picture

ah, just looking over the other issues, impressive nice work.

So , to try this out, I basically set up my environment, put some dummy data with the old method, then apply the patches and see if the data is upgraded and test the new functionality?
so need 3 patches in total for the 7.x-3.x branch?

kaare’s picture

You need three all patches and a single function call to media_wysiwyg_aggregate_alignment() from media_wysiwyg_upgrade_token(). This is what glues #2941608: Aggregate and uniform alignment handling during media token filtering and #2941624: Add version and upgrade mechanism to media tokens together. Like this:

function media_wysiwyg_upgrade_token(array &$tag_info) {
  media_wysiwyg_aggregate_alignment($tag_info);
}
kaare’s picture

So something like this.

This issue now depends on all child issues :-)

joseph.olstad’s picture

Seems that the glue code would best go into media_upgrade_7300
In media.install

I'll have a closer look soon.

I'll run some tests and review asap hopefully this weekend.

kaare’s picture

Status: Needs work » Active

I mentioned in #19 that IMHO the update should be run voluntarily, independent of db upgrade. Instead a notification about this semi-required upgrade is provided. The child issues solves different problems and are independent of each other, though they all in combination solves the overall alignment issue. As such, the glue patch in this issue is required in order for the content token update to actually DO anything. Issue #2941624: Add version and upgrade mechanism to media tokens was only providing the mechanism to set everything up for upgrade, nothing is changed. So this issue is postponed upon the child issues :-)

joseph.olstad’s picture

I set up a test environment here: https://w3usine.com/node/6
used the media_dev distribution
then upgraded media to the latest dev release
then applied all the patches, tested, confirmed to work
I also used the glue code, appears to work for me, I had created some dummy data, and ran the upgrade, see screenshots.

There is an issue I noticed, but probably outside the scope of this issue, is that when centering the text doesn't wrap around the embedded element. Perhaps this is a css issue? Haven't looked that hard into that yet.

screenshots from tests run at https://w3usine.com/node/6
upgrade of media embed tokens

align left in wysiwyg highlighted
can change by clicking in wysiwyg editor the alignment button, then going back into media browser, the correct setting is there in the drop down.
align left in media browser also selected

Left and right alignments look great with text wraps
viewing node with alignment settings in place using a few embedded elements
center alignment does not get wrapping , out of scope for this issue, but confirming functionality appears to be working as expected compared before and after patching.

joseph.olstad’s picture

There's 4 patches altogether, all 4 look good, so commit all 4 ? I suggest keeping this in the 7.x-3.x branch , we can cut a 7.x-3.0-rc1 tag including this and release 7.x-3.0-rc1

@kaare please confirm plan of action?

Nice work. Unfortunately I did not yet test TinyMCE to see if there were regressions in wysiwyg editors other than CKeditor , however it doesn't appear that there would be. TinyMCE support would be a new issue, lets keep the scope low for this, from what I've reviewed so far it looks RTBC to me, ready to take action upon confirmation @kaare , thanks again.

kaare’s picture

There is an issue I noticed, but probably outside the scope of this issue, is that when centering the text doesn't wrap around the embedded element. Perhaps this is a css issue? Haven't looked that hard into that yet.

AFAIK I don't think this is possible in css, but my css(3) skills are very limited.

@kaare please confirm plan of action?

Feel free to commit all four :-)

I agree this belongs to the 3.x branch only. That's what I had in mind and there are several reasons why:

  • It changes the behavior of using inline css float on media to css classes. Layout will be different.
  • The css class introduced in the 2.x branch media-float-(left|right) are removed. Site builders will have to adapt to the consolidated class 'media-wysiwyg-align-(left|right)' classes
  • The version and upgrade mechanism is something that needs more testing and since there is no 3.0 release yet the 3.x branch is a suitable playground for this.

I've developed this using both media_dev distro and a dev site of our organization's main website with ~4000 nodes. Works fine here. So yes, the only client side combination this works for is using ckeditor within the wysiwyg.module (and of course media_wysiwyg). Everything else are follow-ups.

joseph.olstad’s picture

Status: Reviewed & tested by the community » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.