This project is archived and is in readonly mode.

#649 ✓resolved
Chris the Developer

Selectors inconsistancy

Reported by Chris the Developer | April 28th, 2009 @ 12:35 PM | in 2.0 (closed)

this code:


var el = $('container').getFirst('*[data-custom-type=root]');

returns a match for:


<div type="root"></div>

but not for:


<div data-custom-type="root"></div>

The spec for this is in html5, here

Comments and changes to this ticket

  • Chris the Developer

    Chris the Developer April 28th, 2009 @ 12:48 PM

    and...

    
    var el = $('container').getElements('div[data-custom-type=root]');
    

    returns all elements as if no selector was passed.

  • Daniele C.

    Daniele C. April 28th, 2009 @ 04:40 PM

    Ok, I've made a little test and it seems to me a RegExp problem:

    Both getElements and getFirst functions (and others functions in Selectors) use the function defined in Selectors.Utils.parseSelector. This function use some regular expressions to perform the match in the passed string.

    
    Selectors.RegExps = {
    	id: (/#([\w-]+)/),
    	tag: (/^(\w+|\*)/),
    	quick: (/^(\w+|\*)$/),
    	splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),
    	combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)
    };
    

    if you look at the last one you see it uses the pattern ([\w-]+) to math every class name in [a-zA-Z0-9-] repeated at least one time. The problem is in the second pattern, that is (\w+), that means [a-zA-Z0-9] at least one time, so if you test a string like data-custom-type it fails the whole match.

    Try use:

    
    Selectors.RegExps = {
    	id: (/#([\w-]+)/),
    	tag: (/^(\w+|\*)/),
    	quick: (/^(\w+|\*)$/),
    	splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),
    	combined: (/\.([\w-]+)|\[([\w-]+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)
    };
    

    it seems to work form me!

    D.

  • Chris the Developer

    Chris the Developer April 29th, 2009 @ 07:00 AM

    This does indeed work! 10 points for you! :)

  • Chris the Developer

    Chris the Developer April 29th, 2009 @ 07:14 AM

    Next challenge:

    The selectors:

    
    'div[data-priority-type~=primary secondary]'
    'div[data-priority-type|=primary-secondary]'
    

    should return divs with data-priority-type set to either primary or secondary, but they return neither.

  • Daniele C.

    Daniele C. April 29th, 2009 @ 11:22 AM

    Ok, I've found the problem for the second one:

    Selectors.Filters.byAttribute this function contain a logical error for the operators ~= and |=

    
    byAttribute: function(self, name, operator, value){
    	var result = Element.prototype.getProperty.call(self, name);
    	if (!result) return (operator == '!=');
    	if (!operator || value == undefined) return true;
    	switch (operator){
    		case '=': return (result == value);
    		case '*=': return (result.contains(value));
    		case '^=': return (result.substr(0, value.length) == value);
    		case '$=': return (result.substr(result.length - value.length) == value);
    		case '!=': return (result != value);
    		case '~=': return result.contains(value, ' ');
    		case '|=': return result.contains(value, '-');
    	}
    	return false;
    }
    

    If you look at the last cases you will see the problem: result contains the value in the attribute and value the value I'm looking for, so the second case is correct test if the attribute contains the value. But, in the last two cases is completely wrong, because if you search:

    "div[data-priority-type|=primary-secondary]"

    in a div:

    you will have:

    value = "primary-secondary" result = "primary"

    so the test is ALWAYS false.

    The function must be corrected:

    
    byAttribute: function(self, name, operator, value){
    	var result = Element.prototype.getProperty.call(self, name);
    	if (!result) return (operator == '!=');
    	if (!operator || value == undefined) return true;
    	switch (operator){
    		case '=': return (result == value);
    		case '*=': return (result.contains(value));
    		case '^=': return (result.substr(0, value.length) == value);
    		case '$=': return (result.substr(result.length - value.length) == value);
    		case '!=': return (result != value);
    		case '~=': return value.contains(result, ' ');
    		case '|=': return value.contains(result, '-');
    	}
    	return false;
    }
    
  • Daniele C.

    Daniele C. April 29th, 2009 @ 11:24 AM

    Sorry the div was not printed:

    <div data-priority-type="primary"></div>

  • Chris the Developer
  • Daniele C.

    Daniele C. April 29th, 2009 @ 01:47 PM

    Ok, I think I've found the problem for the 'div[data-priority-type~=primary secondary]' error, it is still in the Selectors.RegExps:

    in the Selectors.Utils.search function, MooTools use the Selectors.RegExps.splitter Regular Expression in order to split the query and retrive the data for the parser.

    If you look at the RegExp splitter: (/\s([+>~\s])\s([a-zA-Z#.*:[])/g) you will see that tha matching pattern for the operator is: ([+>~\s]) so +, >, ~ and space. This cause some troubles, because you query ("div[data-priority-type~=primary secondary]"), that sould return the entire parser, return, instead, ["div[data-priority-type~=primary", "secondary]"]. Each elements of the array is syntatically incorrect so it fails every match.

    The splitter RegExp should be:

    splitter: (/\s([+>~])\s([a-zA-Z#.*:[])/g),

    One Thing: I really have no idea if the \s in the RegExp pattern is used elsewhere, but, in that case, it will probably fail the match/test/exec/whatever use the RegExp.

  • Chris the Developer

    Chris the Developer April 29th, 2009 @ 01:52 PM

    Some people run into development problems, so they look at them and think: 'I know! I'll use regular expressions'. Then they have 2 problems. ^^

    Thanks for all the help!

  • Chris the Developer

    Chris the Developer April 29th, 2009 @ 01:53 PM

    Anyone in the core team wanna stick their neck out and say whether they think these issues will be address/committed in the next version?

  • Thomas Aylott

    Thomas Aylott May 2nd, 2009 @ 04:30 PM

    • Assigned user set to “Thomas Aylott”
    • Tag set to selectors
    • State changed from “new” to “resolved”

    The entire selectors functionality is being replaced in 2.0. Check out slick on my github for the latest. Or MooTools-core on kamicane on github.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

Shared Ticket Bins

Tags

Referenced by

Pages