Javascript library implementing emulation of CSS selectors lookup, as document.querySelector.
View the Project on GitHub jeremiah-shaulov/joyquery
Joyquery allows to add support for pseudo classes, which are not supported by the library. There are 3 standard classes that joyquery doesn't support by default: :active, :hover and :lang(). On this page i'll show how to add them. Also you are free to add your custom pseudo classes.
if (!joyquery.FUNCTIONS.active)
{ function add_event(node, onwhat, callback, capture)
{ if (node.addEventListener)
{ if (onwhat.substr(0, 2) == 'on') onwhat = onwhat.substring(2);
node.addEventListener(onwhat, callback, !!capture);
return function()
{ node.removeEventListener(onwhat, callback, !!capture);
};
}
else
{ node.attachEvent(onwhat, callback);
return function()
{ node.detachEvent(onwhat, callback);
};
}
}
var active_last_target = null;
add_event
( document,
'onmousedown',
function(evt)
{ active_last_target = (evt || window.event || {}).target;
function done(evt)
{ var true_evt = evt || window.event || {};
if (true_evt.type!='mousemove' || true_evt.target!=active_last_target)
{ active_last_target = null;
onmouseup();
onmousemove();
}
}
var onmouseup = add_event(document, 'onmouseup', done);
var onmousemove = add_event(document, 'onmousemove', done);
}
);
joyquery.FUNCTIONS.active = function()
{ var node = this.node;
var last = active_last_target;
while (last && last!=node)
{ last = last.parentNode;
}
return last;
};
}
if (!joyquery.FUNCTIONS.hover)
{ function add_event(node, onwhat, callback, capture)
{ if (node.addEventListener)
{ if (onwhat.substr(0, 2) == 'on') onwhat = onwhat.substring(2);
node.addEventListener(onwhat, callback, !!capture);
return function()
{ node.removeEventListener(onwhat, callback, !!capture);
};
}
else
{ node.attachEvent(onwhat, callback);
return function()
{ node.detachEvent(onwhat, callback);
};
}
}
var hover_last_target = null;
add_event
( document,
'onmouseover',
function(evt)
{ hover_last_target = (evt || window.event || {}).target;
}
);
add_event
( document,
'onmouseout',
function(evt)
{ var target = (evt || window.event || {}).target;
if (target==document.body || target==document.documentElement)
{ hover_last_target = null;
}
}
);
joyquery.FUNCTIONS.hover = function()
{ var node = this.node;
var last = hover_last_target;
while (last && last!=node)
{ last = last.parentNode;
}
return last;
};
}
if (!joyquery.FUNCTIONS.lang)
{ var langs_checked = {};
var langs_checked_length = 0;
var document_language = null;
joyquery.FUNCTIONS['lang.raw_argument'] = true;
joyquery.FUNCTIONS.lang = function(code)
{ var value;
var node = this.node;
while (!value && node)
{ value = node.lang;
node = node.parentNode;
}
if (!value)
{ // lang attribute is not specified
// is document in this language?
if (!(code in langs_checked))
{ try
{ if (langs_checked_length >= 128)
{ langs_checked = {};
langs_checked_length = 0;
}
langs_checked[code] = !!document.querySelector('html:lang('+code+')');
langs_checked_length++;
}
catch (e)
{
}
}
if (code in langs_checked)
{ return langs_checked[code]; // document.querySelector succeeded
}
// does document have a meta tag
if (document_language == null)
{ try
{ var metas = document.getElementsByTagName('meta');
for (var i=metas.length-1; i>=0; i--)
{ if (metas[i].httpEquiv.toLowerCase() == 'content-language')
{ document_language = metas[i].content;
break;
}
}
}
catch (e)
{
}
if (!document_language)
{ document_language = navigator.language || navigator.userLanguage || '';
}
}
value = document_language;
}
value = value.replace('_', '-').toLowerCase();
code = code.toLowerCase();
return value==code || value.substr(0, code.length+1)==code+'-';
};
}
However, some browsers don't allow to determine default document language. If document.querySelector('html:lang('+code+')') fails, this function looks for a meta tag like this:
<meta http-equiv="Content-Language" content="he-IL"/>
If such tag also doesn't exist, the system language (navigator.language) is assumed to be the language of the document.