Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge pull request #1242 from ckeditor/t/1239
Browse files Browse the repository at this point in the history
Feature: Allowed passing `true` as `view.Matcher`'s attribute match to check if that attribute is set. Closes #1239.
  • Loading branch information
Piotr Jasiun authored Jan 19, 2018
2 parents 131e9c8 + f0d37a7 commit bc1c3e5
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 5 deletions.
2 changes: 2 additions & 0 deletions src/view/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ export default class Element extends Node {
* @fires module:engine/view/node~Node#change
*/
setAttribute( key, value ) {
value = String( value );

this._fireChange( 'attributes', this );

if ( key == 'class' ) {
Expand Down
15 changes: 10 additions & 5 deletions src/view/matcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ export default class Matcher {
*
* matcher.add( {
* attribute: {
* title: 'foobar',
* foo: /^\w+/
* title: 'foobar', // Attribute title should equal 'foobar'.
* foo: /^\w+/, // Attribute foo should match /^\w+/ regexp.
* bar: true // Attribute bar should be set (can be empty).
* }
* } );
*
Expand Down Expand Up @@ -95,8 +96,10 @@ export default class Matcher {
* {@link module:engine/view/matcher~Matcher#match match} or {@link module:engine/view/matcher~Matcher#matchAll matchAll} methods.
* @param {String|RegExp} [pattern.name] Name or regular expression to match element's name.
* @param {Object} [pattern.attribute] Object with key-value pairs representing attributes to match. Each object key
* represents attribute name. Value under that key can be either a string or a regular expression and it will be
* used to match attribute value.
* represents attribute name. Value under that key can be either:
* * `true` - then attribute is just required (can be empty),
* * a string - then attribute has to be equal, or
* * a regular expression - then attribute has to match the expression.
* @param {String|RegExp|Array} [pattern.class] Class name or array of class names to match. Each name can be
* provided in a form of string or regular expression.
* @param {Object} [pattern.style] Object with key-value pairs representing styles to match. Each object key
Expand Down Expand Up @@ -295,7 +298,9 @@ function matchAttributes( patterns, element ) {
if ( element.hasAttribute( name ) ) {
const attribute = element.getAttribute( name );

if ( pattern instanceof RegExp ) {
if ( pattern === true ) {
match.push( name );
} else if ( pattern instanceof RegExp ) {
if ( pattern.test( attribute ) ) {
match.push( name );
} else {
Expand Down
6 changes: 6 additions & 0 deletions tests/view/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,12 @@ describe( 'Element', () => {
expect( el._attrs.get( 'foo' ) ).to.equal( 'bar' );
} );

it( 'should cast attribute value to a string', () => {
el.setAttribute( 'foo', true );

expect( el._attrs.get( 'foo' ) ).to.equal( 'true' );
} );

it( 'should fire change event with attributes type', done => {
el.once( 'change:attributes', eventInfo => {
expect( eventInfo.source ).to.equal( el );
Expand Down
28 changes: 28 additions & 0 deletions tests/view/matcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,34 @@ describe( 'Matcher', () => {
expect( matcher.match( el3 ) ).to.be.null;
} );

it( 'should match if element has given attribute', () => {
const pattern = {
attribute: {
title: true
}
};
const matcher = new Matcher( pattern );
const el1 = new Element( 'p', { title: 'foobar' } );
const el2 = new Element( 'p', { title: '' } );
const el3 = new Element( 'p' );

let result = matcher.match( el1 );
expect( result ).to.be.an( 'object' );
expect( result ).to.have.property( 'element' ).that.equal( el1 );
expect( result ).to.have.property( 'pattern' ).that.equal( pattern );
expect( result ).to.have.property( 'match' ).that.has.property( 'attribute' ).that.is.an( 'array' );
expect( result.match.attribute[ 0 ] ).equal( 'title' );

result = matcher.match( el2 );
expect( result ).to.be.an( 'object' );
expect( result ).to.have.property( 'element' ).that.equal( el2 );
expect( result ).to.have.property( 'pattern' ).that.equal( pattern );
expect( result ).to.have.property( 'match' ).that.has.property( 'attribute' ).that.is.an( 'array' );
expect( result.match.attribute[ 0 ] ).equal( 'title' );

expect( matcher.match( el3 ) ).to.be.null;
} );

it( 'should match element class names', () => {
const pattern = { class: 'foobar' };
const matcher = new Matcher( pattern );
Expand Down

0 comments on commit bc1c3e5

Please sign in to comment.