Skip to content

Instantly share code, notes, and snippets.

@patik
Created December 10, 2011 22:16
Show Gist options
  • Save patik/1456711 to your computer and use it in GitHub Desktop.
Save patik/1456711 to your computer and use it in GitHub Desktop.
Customized Zepto for fake selectors
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<style> .hidden { display: none; } </style>
<script src="zepto.custom.js"></script>
<script>
$(document).ready(function(e) {
// This should print 2 results: #div3 and #div4
console.log("visible:", $("div:visible"));
// This should print 3 results: #div1, #div2, and #div5
console.log("hidden:", $("div:hidden"));
});
</script>
</head>
<body>
<div class="hidden" id="div1">
<div id="div2"></div>
</div>
<div id="div3"></div>
<div id="div4">
<div style="display:none;" id="div5"></div>
</div>
</body>
</html>
var Zepto = (function() {
//
// ... snipped the Zepto code for brevity ...
//
// Custom selectors
// Each method takes an array/list and returns an array of matching elements
// Method names match the custom selector name (eg, hidden() is for :hidden)
$.customSelectors = {
hidden: function(elems) {
var matches = [], len = elems.length, i = 0;
while (i < len) {
if ($.customSelectors.test.hidden(elems[i])) {
matches.push(elems[i]);
}
i++;
}
return matches;
},
visible: function(elems) {
var matches = [], len = elems.length, i = 0;
while (i < len) {
if ($.customSelectors.test.visible(elems[i])) {
matches.push(elems[i]);
}
i++;
}
return matches;
},
// This contains the Boolean functions which test a single element
// Which means you can't create a fake selector div:test unless you rename this...
test: {
// Pulled from jQuery and trimmed down to the basics
hidden: function(elem) {
var width = elem.offsetWidth,
height = elem.offsetHeight;
return (width === 0 && height === 0) || ((elem.style.display || $(elem).css("display")) === "none");
},
visible: function(elem) {
return !$.customSelectors.test.hidden(elem);
}
}
}
$.qsa = $$ = function(element, selector) {
var found, standard = "", custom = "";
// Look for a colon to indicate the presence of a custom selector
if (selector && ~selector.indexOf(":")) {
standard = selector.split(":")[0];
custom = selector.split(":")[1];
}
if (custom.length && custom in $.customSelectors) {
// First find all elements matching the non-custom selector(s)
found = standard.length ? $$(element, standard) : $$(element);
// Then filter that result by testing against the custom selector
return $.customSelectors[custom](found);
}
else {
// No function exists for this selector, so we can't perform a query
return emptyArray;
}
}
else {
// This is the original, untouched code from $.qsa
return (element === document && idSelectorRE.test(selector)) ?
( (found = element.getElementById(RegExp.$1)) ? [found] : emptyArray ) :
slice.call(
classSelectorRE.test(selector) ? element.getElementsByClassName(RegExp.$1) :
tagSelectorRE.test(selector) ? element.getElementsByTagName(selector) :
element.querySelectorAll(selector)
);
}
}
// ... futher down ...
$.fn = {
// ... functions snipped for brevity ...
filter: function(selector){
return $([].filter.call(this, function(element){
var custom = "";
// Look for a colon to indicate the presence of a custom selector
if (selector && ~selector.indexOf(":")) {
custom = selector.split(":")[1];
}
if (custom.length && custom in $.customSelectors.test) {
return $.customSelectors.test[custom](element);
}
else {
return element.parentNode && $$(element.parentNode, selector).indexOf(element) >= 0;
}
}));
},
// ... the rest of $.fn
};
//
// ... the rest of the Zepto code snipped for brevity ...
//
})();
@arextar
Copy link

arextar commented Dec 10, 2011

I'm not sure you should return an empty array if the custom selector doesn't exist, what if you run $("div:nth-child(2)")?

@patik
Copy link
Author

patik commented Dec 10, 2011

Actually I wanted to avoid that initial if() clause entirely unless the part after the colon was a defined custom selector. (That's why I threw in the check for :not, the only pseudo-class that came to mind at the moment.)

I updated the code so it will use the native qsa for :nth-child, :not, and any other real pseudo-class. I also added code for modifying $.fn.filter so that you can do things like $("div").is(":hidden").

BTW, the fact that I am repeating myself in the $.qsa and $.fn.filter functions is another BIG RED FLAG that this code is inefficient and not for production use :)

@arextar
Copy link

arextar commented Dec 10, 2011

I have a pull open in Zepto that creates a function that checks whether or not an element matches a selector(using the speedy native matchesSelector), if that gets accepted that would probably be a good spot to put code like this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment