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
3 changes: 3 additions & 0 deletions blocks/components/editable/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ export default class Editable extends wp.element.Component {

componentWillUpdate( nextProps ) {
if ( this.editor && this.props.tagName !== nextProps.tagName ) {
this.onChange();
this.editor.destroy();
}
}
Expand Down Expand Up @@ -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.

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.

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

}

isAlignmentActive( align ) {
Expand Down
59 changes: 19 additions & 40 deletions blocks/library/list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import './style.scss';
import { registerBlock, query as hpq } from 'api';
import Editable from 'components/editable';

const { children, prop, query } = hpq;
const { children, prop } = hpq;

registerBlock( 'core/list', {
title: wp.i18n.__( 'List' ),
Expand All @@ -14,72 +14,51 @@ registerBlock( 'core/list', {

attributes: {
nodeName: prop( 'ol,ul', 'nodeName' ),
items: query( 'li', {
value: children()
} )
values: children( 'ol,ul' )
},

controls: [
{
icon: 'editor-alignleft',
title: wp.i18n.__( 'Align left' ),
isActive: ( { align } ) => ! align || 'left' === align,
icon: 'editor-ul',
title: wp.i18n.__( 'Convert to unordered' ),
isActive: ( { nodeName = 'OL' } ) => nodeName === 'UL',
onClick( attributes, setAttributes ) {
setAttributes( { align: undefined } );
setAttributes( { nodeName: 'UL' } );
}
},
{
icon: 'editor-aligncenter',
title: wp.i18n.__( 'Align center' ),
isActive: ( { align } ) => 'center' === align,
icon: 'editor-ol',
title: wp.i18n.__( 'Convert to ordered' ),
isActive: ( { nodeName = 'OL' } ) => nodeName === 'OL',
onClick( attributes, setAttributes ) {
setAttributes( { align: 'center' } );
}
},
{
icon: 'editor-alignright',
title: wp.i18n.__( 'Align right' ),
isActive: ( { align } ) => 'right' === align,
onClick( attributes, setAttributes ) {
setAttributes( { align: 'right' } );
}
},
{
icon: 'editor-justify',
title: wp.i18n.__( 'Justify' ),
isActive: ( { align } ) => 'justify' === align,
onClick( attributes, setAttributes ) {
setAttributes( { align: 'justify' } );
setAttributes( { nodeName: 'OL' } );
}
}
],

edit( { attributes, focus, setFocus } ) {
const { nodeName = 'OL', items = [], align } = attributes;
const content = items.map( ( item, i ) => {
return <li key={ i }>{ item.value }</li>;
} );

edit( { attributes, setAttributes, focus, setFocus } ) {
const { nodeName = 'OL', values = [] } = attributes;
return (
<Editable
tagName={ nodeName.toLowerCase() }
style={ align ? { textAlign: align } : null }
value={ content }
onChange={ ( nextValues ) => {
setAttributes( { values: nextValues } );
} }
value={ values }
focus={ focus }
onFocus={ setFocus }
showAlignments
className="blocks-list" />
);
},

save( { attributes } ) {
const { nodeName = 'OL', items = [] } = attributes;
const { nodeName = 'OL', values = [] } = attributes;

return wp.element.createElement(
nodeName.toLowerCase(),
null,
items.map( ( item, index ) => (
<li key={ index }>{ item.value }</li>
) )
values
);
}
} );