tag:blogger.com,1999:blog-34454975.post5687037587312306116..comments2023-06-28T16:58:41.189+02:00Comments on Web Reflection: Essential Selector - Cross Browser LightWeight Selector EngineAndrea Giammarchihttp://www.blogger.com/profile/16277820774810688474noreply@blogger.comBlogger8125tag:blogger.com,1999:blog-34454975.post-54746231717827618292011-02-25T21:19:56.121+01:002011-02-25T21:19:56.121+01:00Hi Andrea,
I see from your vice-versa library (w...Hi Andrea,<br /> I see from your vice-versa library (which includes this Essential Selector library) that the code is covered by an MIT style license:<br /><br /><a href="http://code.google.com/p/vice-versa/" rel="nofollow">http://code.google.com/p/vice-versa/</a><br /><br /> I don't see an MIT license statement in the Essential source code, but it is your intent to license it with an MIT license, right?<br /><br /> I apologize for all the wordy comments, I talk too much... but here is something that might help people who are looking at the code for the first time. Here is what the $e selector function does, in my words, after it is refactored to properly scope selectors used with the native querySelectorAll (I renamed the context object argument from HTMLElement to ctxtElement in this explanation):<br /><br />Returns an array of DOM Elements matching the given CSS selector(s). The returned array will not contain duplicates if $e.duplicated is set to false.<br /> <br /> The selector arg is a comma-delimited list of CSS selectors.<br /> <br /> The ctxtElement arg is an optional context for the search. The search will be conducted only on children of this element and if no context element is provided then the entire document will be searched. When the ctxtElement arg is present then the selector is applied relative to the ctxtElement (NOT relative to the document root).<br /> <br /> The selectors can be contextual. If they are contextual AND the ctxtElement arg is present then the contextual selectors should be written relative to the ctxtElement context object, NOT relative to the document root.<br /> <br /> If there is a native querySelectAll function then this call delegates to it. If a context element is provided and the call is being delegated to the native querySelectAll then the delegation is made only after automatically scoping the given selector(s) so that the native function will be applying selectors relative to the ctxtElement instead of relative to the root document. <br /> <br /> If there is no native querySelectAll function then the following logic is used:<br /> <br /> If a selector is non-contextual and one of these simple types of selector then a very simple search will be performed:<br /> id selector: #fooId<br /> nodeName selector: div<br /> className selector: .fooClass<br /> tagClass selector: div.fooClass<br /> <br /> If a selector is contextual or is non-contextual but is not one of the simple types of selector that are listed above then a more complex search will be performed using a custom querySelectAll function. This custom querySelectAll function works by temporarily applying a "marker" CSS style to elements that match the given selector(s) and then searching the document for elements with the "marker" style.turnandohttps://www.blogger.com/profile/04580359339191482429noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-26843001354903377612011-02-24T22:58:30.435+01:002011-02-24T22:58:30.435+01:00Me again.
I refactored the branch of code for del...Me again.<br /><br />I refactored the branch of code for delegating to the native querySelectorAll so that it would give consistent results with the custom querySelectorAll impls that are used for old browsers.<br /><br />The problem I'm solving can be seen when using a context object to scope the query. The W3C spec for the selector API says this about using querySelectorAll on an element that is not the root document element: "Even though the method is invoked on an element, selectors are still evaluated in the context of the entire document." <br /><br />http://www.w3.org/TR/selectors-api/<br /><br />John Resig does a better job than me of explaining the issue:<br /><br />http://ejohn.org/blog/thoughts-on-queryselectorall/#postcomment<br /><br />Basically, we want a JavaScript selector library to apply a selector to the DOM below the scoping context element (when a scoping element is used). The Essential library does do that for the custom querySelectorAll but when delegating to the native querySelectorAll it does not take this scoping into consideration and the selector ends up getting evaluated against the root document element.<br /><br />I refactored Essential to scope the selector to the scoping context object before delegating to a native querySelectorAll call. In a nutshell, it does it by adding a temporary marker attribute to the scoping element and then prepending an attribute selector to the original selector. I have another version that will alternatively use the id of the scoping element (if it exists) to be less intrusive, but I'm sticking with this because I'm going for compact code:<br /><br /><br /> if(div.querySelectorAll){ // If querySelectorAll is available then we don't need our custom selectors<br /> div = null;<br /> return function(selector, ctxtElement){ <br /> var results;<br /> if (ctxtElement) {<br /> ctxtElement.setAttribute(mrkr, "");<br /> selector = "[" + mrkr + "] " + selector; // orig selector is now scoped to ctxt element with an attribute selector<br /> }<br /> results = toArray.call((ctxtElement || doc).querySelectorAll(selector));<br /> if (ctxtElement){<br /> ctxtElement.removeAttribute(mrkr);<br /> }<br /> return results;<br /> };<br /> }turnandohttps://www.blogger.com/profile/04580359339191482429noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-16529829258963333162011-02-24T22:37:43.932+01:002011-02-24T22:37:43.932+01:00Hello Andrea,
I'm liking the Essential selec...Hello Andrea,<br /> I'm liking the Essential selector, it is so lightweight.<br /><br /> I refactored the custom querySelectorAll function for IE to take into consideration the limit of 30 stylesheets per document (and a limit of 4095 rules per stylesheet). <br /><br /> It needs a few tweaks but the essence of it is that it tries document.createStyleSheet() and if that fails it uses the first stylesheet in the document that is not disabled and which does not fail when addRule() is used on it (it will fail if the stylesheet has 4095 rules).<br /><br /> I need to make one more change so that the query code is adding a single rule to the stylesheet (like for the FF branch of code) and after I do that I will test it and give it to you.turnandohttps://www.blogger.com/profile/04580359339191482429noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-20252526691953670242011-02-18T18:10:35.532+01:002011-02-18T18:10:35.532+01:00Hey, Dean Edwards posted about a MS IE "featu...Hey, Dean Edwards posted about a MS IE "feature" that throws an exception for document.createStyleSheet() when you try it in a document that has 30 style sheets.<br /><br />http://dean.edwards.name/weblog/2010/02/bug85/<br /><br />I'm going to see if I can solidify the IE version of your custom querySelectorAll with a try/catch that re-uses an existing stylesheet. Don't know if it will be OK to add/remove from an existing stylesheet?turnandohttps://www.blogger.com/profile/04580359339191482429noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-83893395405065425942009-04-17T10:49:00.000+02:002009-04-17T10:49:00.000+02:00@dean, that was simple. I implemented a quick and ...@dean, that was simple. I implemented a quick and simple "resolver" for cases like that and performances are effectively good.<br /><br />@kangax, I updated the standard regexp plus I used slice for the random, happy now?<br /><br />both <A HREF="http://www.devpro.it/code/197.html" REL="nofollow">inside the code now</A> :DAndrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-9551637000238164492009-04-17T10:13:00.000+02:002009-04-17T10:13:00.000+02:00Sorry kangax, I did a mistake via Android clicking...Sorry kangax, I did a mistake via Android clicking the wrong link. You also wrote:<br /><I>It seems to me that `new RegExp("\\b" + split.shift() + "\\b")` will erroneously match values like "foo-bar" when asked for "foo" or "bar".<br /><br />AFAIK, regex like this is considered to be standard - `new RegExp("(?:\\s|^)" + value + "(?:\\s|$)")`<br /><br />It's much easier to catch errors like that if you have unit tests ;) </I>I agree, I did not think that much about that RegExp and I'll fix in few minutes.<br />About slice VS substring, that operation is performed once in the script lifetime, I do not htink it will affect that much performances.<br />I removed "0." from the Math.random() to avoid problems with the counter name but it could be a single char like "a", the random was only to avoid possible conflicts :)Andrea Giammarchihttps://www.blogger.com/profile/16277820774810688474noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-74009892303362627522009-04-17T07:02:00.000+02:002009-04-17T07:02:00.000+02:00I see you generate a random token with -
`"__" +...I see you generate a random token with - <br /><br />`"__" + String(Math.random()).substring(2) + "__"`<br /><br />I usually use a bit shorter alternative -<br /><br />'_' + (Math.random()+'').slice(2);<br /><br />If you care about shaving off those few extra characters, of course : )kangaxhttp://thinkweb2.com/projects/prototype/noreply@blogger.comtag:blogger.com,1999:blog-34454975.post-14834760829076402882009-04-15T16:01:00.000+02:002009-04-15T16:01:00.000+02:00That's a clever solution.
You can speed it up a b...That's a clever solution.<br /><br />You can speed it up a bit by identifying the target tagName.<br /><br />e.g.<br /><br />For this selector:<br /><br />p.example a<br /><br />The target tagName is "a", so you can change the getElementsByTagName("*") to getElementsByTagName(tagName). It should be fairly simple to parse out the target tagName.Unknownhttps://www.blogger.com/profile/00499055929804682884noreply@blogger.com