U4-6267 - Support advanced rule set styles for tinymce rte editor

Created by Shannon Deminick 12 Feb 2015, 23:31:55 Updated by Shannon Deminick 07 Aug 2017, 23:30:57

Tags: Prioritize

Relates to: U4-1736

This is based on the information in this issue: http://issues.umbraco.org/issue/U4-1736

Currently this happens

  1. if the selector started with a "#", create an inline span and add an id= attribute (e.g. "#identifier")
  2. if the selector started with a ".", create an inline span and add an class= attribute (e.g. ".
  3. otherwise transform the selection into the specified block level element (e.g. "h2")

Now with U4-1736 closed you can also define element + classes (including composite ones), so you could do 'div.class1.class2' which will become <div class='class1 class2', etc...

Some additional usages that would be nice to have:

  • wrapping in a block level element (e.g. div.class will wrap the selected elements in a div and apply the class) (I think this already happens.... ?)
  • apply a class to an existing block level element (e.g. img.class or tr.class) (only if the element matches?)

Anthony's previous notes from the last issue:

I've had some difficulty in coming up with an explicit selector syntax to identify the use cases so would welcome some feedback on the following suggested syntax for the use cases above:

  1. ".class" (already implemented)
  2. "h2" or "h2.class" (already implemented)
  3. "!div" or "!blockquote" (optionally with a class name - This was inspired by the upcoming CSS4 spec for selecting the target to apply the styles to)
  4. "* img.class" or "* tr.class" (This was inspired by the fact that TinyMCE will apply the class to any elements of the appropriate type within the selection e.g. if you select a p containing an image, it will apply the class to the image only)

It may be possible to infer the last two use cases by the type of block element involved?

Comments

Mike 23 Mar 2015, 00:07:21

I think some of the trouble with the current approach is that we are using the "style_formats" feature for inserting Umbraco styles. I don't like the way it throws everything into one list and automatically applies the style to it. If you have a lot of styles it just ends up as a long unorganised messy list. Also you have no control over how the style is applied. This makes lots of common styles impossible as they rely upon nesting/order of specific HTML elements. Sometimes you can get round that with insert template/macro but not always.

To get sub-headings to make it neater you can set them up in tinyMcseConfig.config. Previously there was an issue where the custom config was always overwriting the generated one so if you specified it in config you lost the generated styles. The latest code in github fixes this but then it makes it messy again as the generated styles are not in any category (I submitted a patch that adds them to separate sub heading).

I think you are going to keep on getting issues of core code conflicting with peoples custom configurations if you use style_formats.

My solution:

I think the styles generated from Umbraco should be added to the editor as a custom listbox control. By doing so you can ensure the conflicts don't happen and also fix a few other issues/features requests listed on the tracker easier.

This way we will have complete control over how styles are applied so we can add functionality to wrap/parse selections. i.e:

setup: function (editor) {
                editor.addButton('userformats', {
                    type: 'listbox',
                    text: 'User Formats',
                    icon: false,
                    onselect: function (e) {
                        editor.selection.setContent('<div class="' + this.value() + '">' + tinyMCE.activeEditor.selection.getContent() + '</div>');
                    },
                    values: [
                        // generated css classes
                    ]
                });
            }

or have it call a function that has been added to scope with the same name:

onselect: function (e) {
	scope[this._text]();
}

Then you could plug and play extra functionality specifically for certain styles.

Right now there is nothing stopping someone hardcoding all of this inside tinyMceConfig.config but if they want to allow a less technical user to apply it to a style they made then it requires a new property editor or modifying the core so you can pull data from umbraco.

I've played with the code to check it works. Only thing I am unsure about is how to let people add their own formatting function. I feel like non-standard selector syntax should be abstracted away from end user. I think it would be a lot easier if they had check boxes and drop down to say whether to wrap/inline/block or whatever but I don't know where that could be added without too much fuss.

I think it makes most sense to let them do it in the developer section on the RTE editor itself but I am not sure how much work that is as I haven't looked at the code.

I think for time being though:

  1. Change style_formats to a custom listbox
  2. Allow function to be added to scope from tinyMceConfig.config
  3. Add selector/s for "wrap" (my method above is crude, needs to be more flexible and perhaps context aware)
  4. Add selector to announce that custom formatting rule should be used

What do you think?

Edit: Just had my first peek into Umbraco core source code. Looks like there is already code there to expose a function to frontend. Will have a play around with it.


Simon Dingley 19 Oct 2015, 08:53:09

Since upgrading to v7 I have a customer with specific use cases which no longer work as they used to and I am yet to find a suitable solution to the problem.

wrapping in a block level element (e.g. div.class will wrap the selected elements in a div and apply the class) (I think this already happens.... ?)

They often need to wrap <blockquote> tags around multiple block level elements e.g.

This is paragraph one

This is paragraph two

{code}

At present this will result in the following:

This is paragraph one
This is paragraph two
{code}

...instead of

This is paragraph one

This is paragraph two

{code}

In addition, what used to happen in previous versions was that a style with an alias of .class-name could be applied to the currently selected element - this worked perfectly fine, it now wraps that element in a span tag (undesirable) or forces you to have to create a duplicate style for each tag that it may possibly be applied to however this has another unwanted side effect of changing the current tag if editors are not familiar or on the ball with the consequences of their selection. I think this last pint is what was referenced above in the following comment:

apply a class to an existing block level element (e.g. img.class or tr.class) (only if the element matches?)

Advice or recommendations on ways of dealing with these scenarios would be helpful if I have missed something. There are a lot of different scenarios to try and cater for here so is a bit of a headache but from this particular customers point of view it used to do most of what they needed and now to them it seems like a step backwards.

Thanks, Simon


Shannon Deminick 19 Oct 2015, 10:17:48

Simon, you need to tell us exactly what version you are using. If you can replicate your issue with the latest umbraco version (7.3 currently), then you'll need to create an issue for it with steps to reproduce.


Simon Dingley 19 Oct 2015, 10:22:40

Sorry Shannon, the site in question is currently running v7.2.8. I will need to setup a separate install to test in v7.3.0.


Kin Chung Yu 14 Apr 2016, 16:39:24

Will there be a support to specify a format as wrapper directly in Umbraco in the future?

We can add it directly to the tinyMceConfig by adding '''"wrapper": "true"''' to the style, but that style will be available to all RTE, which is not always wanted.

[ { "title": "Wrapper", "block": "div", "classes": "wrapper", "wrapper": "true"} ]

Using Umbraco 7.4.2.


Brian Patton 15 Dec 2016, 16:17:09

Any updates on this? I am still unable to apply a style to an img tag. When doing so, it wraps the img in a span with the style, which doesn't help. For instance need to add that class to the img tag to float it right and add appropriate margins? This was working fine in an older v4 version of umbraco. Any help would be great, thanks!


Shannon Deminick 16 Dec 2016, 02:04:32

@bp2fl please always ensure to tell us what version you are using and to test with the latest umbraco version


Brian Patton 16 Dec 2016, 13:43:16

@Shandem This issue is happening on our 7.5.4 install. Just installed a fresh 7.5.6 and the issue is still prevalent. It adds span tags around the img and adds the selected class to the span. Thanks!


Matthew 16 Dec 2016, 15:45:37

I think this has been an issue for v7's entire release.

I haven't been able to directly format the following elements since 7.1 (my first version):

  • a
  • img
  • ul
  • table


Mark Drake 07 Aug 2017, 13:39:46

Something else that's not working / possible right now is the addition of multiple classes. Let's say I have multiple "Header" styles - like Header, Header Large, Header Bold, etc. We typically follow a element, modifier, hook approach to writing our CSS. So if we wanted to target a header and make it larger, we would give it two class names:

.header.-large

We expect the resulting HTML to include 2 classnames. Currently Umbraco + TinyMCE results in 1 class name, with the period used instead of interpreted as another class.

Is this a limitation of TinyMCE or Umbraco's implementation of it? If somebody would point me in the right direction, this is something I'd like to not only fix locally right now but submit a quick PR to fix. Appreciate the help.


Shannon Deminick 07 Aug 2017, 23:30:57

I'm not entirely sure tbh if this is Umbraco or TinyMCE but i can try to point you at some code

I can't remember which plugins get loaded as a tinymce plugin but since i cannot see the styles being handled in the tinymceservice, i assume it's one of these plugins (sorry i can't remember the name of the styles drop down), could be this one:


Priority: Normal

Type: Bug

State: Open

Assignee:

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted:

Affected versions: 7.5.6

Due in version:

Sprint:

Story Points:

Cycle: