Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

List blocks can now save changes to their content #598

Merged
merged 9 commits into from
May 5, 2017

Conversation

BoardJames
Copy link

This is an update of the pull request originally submitted by @mimo84 #396
The purpose of the pull request is to:

  • enable the list block to preserve changes to its content using onChange
  • Add the ability to change the list type
  • Cause formating changes (like bold) to mark the editor as dirty (otherwise these changes are not saved on change of list type)

Note an alternative to changing the list type like we are currently might be to create 2 list types (for unordered and ordered) and provide transformer rules so they appear in the drop down menu. I am unsure which is desired.

@BoardJames BoardJames mentioned this pull request May 2, 2017
@youknowriad
Copy link
Contributor

We should probably update this line https://github.com/WordPress/gutenberg/pull/598/files#diff-059d9a0231c4f69adca5a0f1eb8ba116L238 to match the node where TinyMCE adds the alignment style. Is there a TinyMCE config or getter for this?

@@ -329,6 +329,7 @@ export default class Editable extends wp.element.Component {
} else {
this.editor.formatter.apply( format );
}
this.editor.setDirty( true );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this done automatically by the formatter calls? Sometimes calling a formatter doesn't change the content (end of text for example) and we may want to avoid this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apparently it isn't. I inspected the dirty state before and after the formatter call and it wasn't being set. This is probably a bug in TinyMCE though.

@BoardJames
Copy link
Author

I've updated the pull request with the latest changes on master.

After the changes on master it seems that just setting dirty is not sufficient to get it to save state on change of tagName (where the editor must be destroyed and reinitialized). The simplest fix seemed to be to call onChange() before destroying the editor.

Also note that the new changeFormats seems to be buggy as the generated ranges are not always valid when it tries to apply them (happens all the time on Firefox and occasionally on Chrome). This can prevent the setDirty call which can prevent saving in onChange however I am not sure what the appropriate fix is. You will probably have to use marker DOM elements to store the selection when formatting is applied.

@@ -349,6 +350,8 @@ export default class Editable extends wp.element.Component {
this.setState( {
formats: merge( {}, this.state.formats, formats )
} );

this.editor.setDirty( true );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't see why is this needed. I dropped it and it works just as well.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Chrome? I confirmed that it seems to work on Chrome too. I'm not sure why because if you throw a log statement in after all the formatting is set then this.editor.isDirty() is false which means in onChange it shouldn't save, however it is saving... One of the other developers here suggested that it might be picking up a node change event and setting the dirty flag later.

On Firefox there are a few problems. Firstly it seems to always throw an IndexSizeError within the call to this.editor.formatter.apply( format ) (apparently it is trying to restore the original selection but the text node that it is trying to select has since been split by the formatting operation and the previous range is not valid). I haven't attempted to fix this in my pull request because it seems out of scope. If I do wrap these problematic calls with a try/catch then as with Chrome the isDirty function still returns false after the formatting has been applied but unlike Chrome it never seems to get corrected so it does not save in the onChange handler.

So the reason I put this.editor.setDirty(true) there is so that this will work when the Firefox IndexSizeError problem has been fixed. Still I suppose that really we just need to get it fixed in TinyMCE.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to remove the setDirty call since it seems controversial. Note that applying formatting is very buggy/broken on Firefox but I don't know how to address that and it is not really anything to do with the list block.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to re-add setDirty as it was not saving on Chrome after merging the latest changes from master without it.
Note my test procedure was:

  1. select a word in unordered list
  2. click bold button
  3. click button to change to ordered list

@youknowriad
Copy link
Contributor

Notice that the Alignment control is not "toggled" when we click on it (it's not darkened). That's because we're not checking the right parent node for the classname here:

 			if ( tag === 'p' ) {
 				alignment = node.style.textAlign || 'left';
 			}

The p here should match the node where TinyMCE applies the alignment. Is there any setting or getter for that? (It's p for by default but I guess it is changed when the parent tag name is not a div)

@mtias mtias added the [Feature] Blocks Overall functionality of blocks label May 3, 2017
@BoardJames
Copy link
Author

BoardJames commented May 4, 2017

@youknowriad
Regarding
if ( tag === 'p' ) { alignment = node.style.textAlign || 'left'; }
Looking at the code ( /src/core/src/main/js/Formatter.js ) it seems that by default TinyMCE will:
For the selector 'figure.image' apply the class 'align-left';
for the selector 'figure,p,h1,h2,h3,h4,h5,h6,td,th,tr,div,ul,ol,li' apply the style "textAlign: left";
and for the selector 'img,table' apply the style "float: left".

I will try to find out if there's a way to programatically query this in TinyMCE's API.

@BoardJames
Copy link
Author

BoardJames commented May 4, 2017

Ok, it seems the correct way to do this is to use:
editor.formatter.formatChanged(formats:String, callback:function, similar:Boolean):void

I'll see if I can get a working prototype.

@BoardJames
Copy link
Author

BoardJames commented May 4, 2017

I ended up using editor.formatter.matchAll to determine the active formats which fixes the alignment button problem you noted.

@BoardJames
Copy link
Author

@youknowriad Are there any more problems you need me to address?

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for handling this. Great work 👍


if ( tag === 'p' ) {
alignment = node.style.textAlign || 'left';
}
} );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: a bit more performant maybe

const link = parents.find( ( node ) = node.nodeName.toLowerCase() === 'a' );
if ( link ) {
  formats.link = { value: node.getAttribute( 'href' ), node };
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added your suggested efficiency improvement

@BoardJames BoardJames merged commit 3225c46 into master May 5, 2017
@youknowriad youknowriad deleted the update/346-list-block-save-fix branch May 5, 2017 08:43
@nylen
Copy link
Member

nylen commented May 5, 2017

Related: #567

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Blocks Overall functionality of blocks
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants