• Авторизация


№ 2 07-11-2010 22:03 к комментариям - к полной версии - понравилось!


/*
selectivizr v1.0.0 - (c) Keith Clark, freely distributable under the terms
of the MIT license.

selectivizr.com
*/
/*

References:
-----------

* CSS Syntax : http://www.w3.org/TR/2003/WD-css3-syntax-20030813/#style
* Selectors : http://www.w3.org/TR/css3-selectors/#selectors
* IE Compatability : http://msdn.microsoft.com/en-us/library/cc351024(VS.85).aspx
* W3C Selector Tests : http://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/tests/

*/

(function(win) {

// If browser isn't IE, then stop execution! This handles the script
// being loaded by non IE browsers because the developer didn't use
// conditional comments.
if (/*@cc_on!@*/true) return;

// =========================== Init Objects ============================

var doc = document
var root = doc.documentElement
var xhr = getXHRObject()
var ieVersion = /MSIE ([\d])/.exec(navigator.userAgent)[1];

// If were not in standards mode, IE is too old / new or we can't create
// an XMLHttpRequest object then we should get out now.
if (doc.compatMode != 'CSS1Compat' || ieVersion<6 || ieVersion>8 || !xhr) {
return
}


// ========================= Common Objects ============================

// compatiable selector engines in order of CSS3 support
var selectorEngines = {
"NW" : "*.Dom.select",
"DOMAssistant" : "*.$",
"Prototype" : "$$",
"YAHOO" : "*.util.Selector.query",
"MooTools" : "$$",
"Sizzle" : "*",
"jQuery" : "*",
"dojo" : "*.query"
}

var selectorMethod
var enabledWatchers = []; // array of :enabled/:dsiabled elements to poll
var ie6PatchID = 0; // used to solve ie6's multiple class bug
var patchIE6MultipleClasses = true; // if true adds class bloat to ie6
var namespace = "slvzr"
var domReadyScriptID = namespace + "DOMReady"

// Stylesheet parsing regexp's
var RE_COMMENT = /(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)\s*/g
var RE_IMPORT = /@import\s*url\(\s*(["'])?(.*?)\1\s*\)[\w\W]*?;/g
var RE_PSEUDO_STRUCTURAL = /^:(empty|(first|last|only|nth(-last)?)-(child|of-type))$/
var RE_PSEUDO_ELEMENTS = /:(:first-(?:line|letter))/g
var RE_SELECTOR_GROUP = /(^|})\s*([^\{]*?[\[:][^{]+)/g
var RE_SELECTOR_PARSE = /([ +~>])|(:[a-z-]+(?:\(.*?\)+)?)|(\[.*?\])/g;
var RE_LIBRARY_INCOMPATIBLE_PSEUDOS = /(:not\()?:(hover|enabled|disabled|focus|checked|target|active|visited|first-line|first-letter)\)?/g
var RE_PATCH_CLASS_NAME_REPLACE = /[^\w-]/g

// HTML UI element regexp's
var RE_INPUT_ELEMENTS = /^(INPUT|SELECT|TEXTAREA|BUTTON)$/
var RE_INPUT_CHECKABLE_TYPES = /^(checkbox|radio)$/

// Broken attribute selector implementations
// fixes IE7 native implementation of [^=""], [$=""] and [=""]
// fixes IE8 native implementation of [^=""] and [$=""]
var BROKEN_ATTR_IMPLEMENTATIONS = ieVersion==8 ? /[\$\^]=(['"])\1/ : ieVersion==7 ? /[\$\^*]=(['"])\1/ : null

// Whitespace normalization regexp's
var RE_TIDY_TRAILING_WHITESPACE = /([(\[+~])\s+/g
var RE_TIDY_LEADING_WHITESPACE = /\s+([)\]+~])/g
var RE_TIDY_CONSECUTIVE_WHITESPACE = /\s+/g
var RE_TIDY_TRIM_WHITESPACE = /^\s*((?:[\S\s]*\S)?)\s*$/

// String constants
var EMPTY_STRING = ""
var SPACE_STRING = " "
var PLACEHOLDER_STRING = "$1"


// =========================== Patching ================================

// --[ patchStyleSheet() ]----------------------------------------------
// Scans the passed cssText for selectors that require emulation and
// creates one or more patches for each matched selector.
function patchStyleSheet( cssText ) {
return cssText.replace(RE_PSEUDO_ELEMENTS, PLACEHOLDER_STRING)
.replace(RE_SELECTOR_GROUP, function(m, prefix, selectorText) {
var selectorGroups = selectorText.split(",")
for (var c=0, cs=selectorGroups.length; c0) {
applyPatches( selector.substring(0, index), patches )
patches = []
}
return combinator
}
else {
var patch = (pseudo) ? patchPseudoClass( pseudo ) : patchAttribute( attribute );
if (patch) {
patches.push(patch);
return "." + patch.className
}
return match
}
}
)
}
return prefix + selectorGroups.join(",");
})
}

// --[ patchAttribute() ]-----------------------------------------------
// returns a patch for an attribute selector.
function patchAttribute( attr ) {
return (!BROKEN_ATTR_IMPLEMENTATIONS || BROKEN_ATTR_IMPLEMENTATIONS.test(attr)) ?
{ className: createClassName(attr), applyClass: true } : null
}


// --[ patchPseudoClass() ]---------------------------------------------
// returns a patch for a pseudo-class
function patchPseudoClass( pseudo ) {

var applyClass = true;
var className = createClassName(pseudo.slice(1))
var isNegated = pseudo.substring(0, 5)==":not(";
var activateEventName;
var deactivateEventName;

// if negated, remove :not()
if (isNegated) {
pseudo = pseudo.slice(5, -1)
}

// bracket contents are irrelevant - remove them
var bracketIndex = pseudo.indexOf("(")
if (bracketIndex>-1) {
pseudo = pseudo.substring(0, bracketIndex)
}

// check we're still dealing with a pseudo-class
if (pseudo.charAt(0)==":") {
switch (pseudo.slice(1)) {

case "root":
applyClass = function(e) {
return isNegated ? e!=root : e==root
}
break;

case "target":
// :target is only supported in IE8
if (ieVersion == 8) {
applyClass = function(e) {
var handler = function() {
var hash = location.hash
var hashID = hash.slice(1)
return isNegated ? (hash=="" || e.id != hashID) : (hash!="" && e.id == hashID)
};
addEvent( win, "hashchange", function() {
toggleElementClass(e, className, handler());
})
return handler()
}
break;
}
return false;

case "checked":
applyClass = function(e) {
if (RE_INPUT_CHECKABLE_TYPES.test(e.type)) {
addEvent( e, "propertychange", function() {
if (event.propertyName == "checked") {
toggleElementClass( e, className, e.checked !== isNegated )
}
})
}
return e.checked !== isNegated
}
break;

case "disabled":
isNegated = !isNegated

case "enabled":
applyClass = function(e) {
if (RE_INPUT_ELEMENTS.test(e.tagName)) {
addEvent( e, "propertychange", function() {
if (event.propertyName == "$disabled") {
toggleElementClass( e, className, e.$disabled === isNegated )
}
})
enabledWatchers.push(e);
e.$disabled = e.disabled;
return e.disabled === isNegated;
}
return pseudo==":enabled" ? isNegated : !isNegated;
}
break;

case "focus":
activateEventName = "focus"
deactivateEventName = "blur"

case "hover":
if (!activateEventName) {
activateEventName = "mouseenter"
deactivateEventName = "mouseleave"
}
applyClass = function(e) {
addEvent( e, isNegated ? deactivateEventName : activateEventName, function() {
toggleElementClass( e, className, true )
})
addEvent( e, isNegated ? activateEventName : deactivateEventName, function() {
toggleElementClass( e, className, false )
})
return isNegated
}
break;

// everything else
default:
// If we don't support this pseudo-class don't create
// a patch for it
if (!RE_PSEUDO_STRUCTURAL.test(pseudo)) {
return false
}
break;
}
}
return { className: className, applyClass: applyClass }
}

// --[ applyPatches() ]-------------------------------------------------
// uses the passed selector text to find DOM nodes and patch them
function applyPatches(selectorText, patches) {
var elms;

// Although some selector libraries can find :checked :enabled etc.
// we need to find all elements that could have that state because
// it can be changed by the user.
var domSelectorText = selectorText.replace(RE_LIBRARY_INCOMPATIBLE_PSEUDOS, EMPTY_STRING)

// If the dom selector equates to an empty string or ends with
// whitespace then we need to append a universal selector (*) to it.
if (domSelectorText == EMPTY_STRING || domSelectorText.charAt(domSelectorText.length-1) == SPACE_STRING) {
domSelectorText += "*"
}

// Ensure we catch errors from the selector library
try {
elms = selectorMethod( domSelectorText )
} catch (ex) {
// #DEBUG_START
log( "Selector '" + selectorText + "' threw exception '"+ ex +"'" )
// #DEBUG_END
}


if (elms) {
for (var d=0, dl=elms.length; d/ --[ hasPatch() ]-----------------------------------------------------
// checks for the exsistence of a patch on an element
function hasPatch( elm, patch ) {
return new RegExp("(^|\\s)" + patch.className + "(\\s|$)").test(elm.className)
}


// =========================== Utilitiy ================================

function createClassName( className ) {
return namespace + "-" + ((ieVersion==6 && patchIE6MultipleClasses) ?
ie6PatchID++
:
className.replace(RE_PATCH_CLASS_NAME_REPLACE, function(a){return a.charCodeAt(0)}))
}

// --[ log() ]----------------------------------------------------------
// #DEBUG_START
function log( message ) {
if (win.console) {
win.console.log(message)
}
}
// #DEBUG_END

// --[ trim() ]---------------------------------------------------------
// removes leading, trailing whitespace from a string
function trim( text ) {
return text.replace(RE_TIDY_TRIM_WHITESPACE, PLACEHOLDER_STRING)
}

// --[ normalizeWhitespace() ]------------------------------------------
// removes leading, trailing and consecutive whitespace from a string
function normalizeWhitespace( text ) {
return trim(text).replace(RE_TIDY_CONSECUTIVE_WHITESPACE, SPACE_STRING)
}

// --[ normalizeSelectorWhitespace() ]----------------------------------
// tidys whitespace around selector brackets and combinators
function normalizeSelectorWhitespace( selectorText ) {
return normalizeWhitespace(selectorText
.replace(RE_TIDY_TRAILING_WHITESPACE, PLACEHOLDER_STRING)
.replace(RE_TIDY_LEADING_WHITESPACE, PLACEHOLDER_STRING)
)
}

// --[ toggleElementClass() ]-------------------------------------------
// toggles a single className on an element
function toggleElementClass( elm, className, on ) {
var oldClassName = elm.className
var newClassName = toggleClass(oldClassName, className, on)
if (newClassName != oldClassName) {
elm.className = newClassName
elm.parentNode.className += EMPTY_STRING
}
}

// --[ toggleClass() ]--------------------------------------------------
// adds / removes a className from a string of classNames. Used to
// manage multiple class changes without forcing a DOM redraw
function toggleClass( classList, className, on ) {
var re = RegExp("(^|\\s)" + className + "(\\s|$)")
var classExists = re.test(classList)
if (on) {
return classExists ? classList : classList + SPACE_STRING + className;
} else {
return classExists ? trim(classList.replace(re, PLACEHOLDER_STRING)) : classList
}
}

// --[ addEvent() ]-----------------------------------------------------
function addEvent(elm, eventName, eventHandler) {
elm.attachEvent("on"+eventName, eventHandler)
}


// --[ getXHRObject() ]-------------------------------------------------
function getXHRObject()
{
if (win.XMLHttpRequest) {
return new XMLHttpRequest;
}
try {
return new ActiveXObject('Microsoft.XMLHTTP') ;
} catch(e) {
return null;
}
}

// --[ loadStyleSheet() ]-----------------------------------------------
function loadStyleSheet( url ) {
xhr.open("GET", url, false);
xhr.send();
return (xhr.status==200) ? xhr.responseText : EMPTY_STRING;
}

// --[ resolveUrl() ]---------------------------------------------------
// Converts a URL fragment to a fully qualified URL using the specified
// context URL. Returns null if same-origin policy is broken
function resolveUrl( url, contextUrl ) {

function getProtocolAndHost( url ) {
return url.substring(0, url.indexOf("/", 8))
}

// absolute path
if (/^https?:\/\//i.test(url)) {
return getProtocolAndHost(contextUrl) == getProtocolAndHost(url) ? url : null
}

// root-relative path
if (url.charAt(0)=="/") {
return getProtocolAndHost(contextUrl) + url
}

// relative path
var contextUrlPath = contextUrl.split("?")[0]; // ignore query string in the contextUrl
if (url.charAt(0)!="?" && contextUrlPath.charAt(contextUrlPath.length-1) != "/") {
contextUrlPath = contextUrlPath.substring(0, contextUrlPath.lastIndexOf("/") + 1)
}

return contextUrlPath + url
}

// --[ parseStyleSheet() ]----------------------------------------------
// Downloads the stylesheet specified by the URL, removes it's comments
// and recursivly replaces @import rules with their contents, ultimately
// returning the full cssText.
function parseStyleSheet( url ) {
if (url) {
var cssText = loadStyleSheet(url)
return cssText.replace(RE_COMMENT, EMPTY_STRING).replace(RE_IMPORT, function( match, quoteChar, importUrl ) {
return parseStyleSheet(resolveUrl(importUrl, url))
})
}
return EMPTY_STRING
}

// --[ init() ]---------------------------------------------------------
function init() {
// honour the tag
var url,stylesheet
var baseTags = doc.getElementsByTagName("BASE")
var baseUrl = (baseTags.length>0) ? baseTags[0].href : doc.location.href

for (var c=0; c/ :enabled & :disabled polling script (since we can't hook
// onpropertychange event when an element is disabled)
if (enabledWatchers.length>0) {
setInterval( function() {
for (var c=0, cl=enabledWatchers.length; c/ --[ determineSelectorMethod() ]--------------------------------------
// walks through the selectorEngines object testing for an suitable
// selector engine.
function determineSelectorMethod() {
var method
for (var engine in selectorEngines) {
if (win[engine] && (method = eval(selectorEngines[engine].replace("*",engine)))) {
return method
}
}
return false
}

// Emulate DOMReady event (Dean Edwards)
doc.write("
вверх^ к полной версии понравилось! в evernote


Вы сейчас не можете прокомментировать это сообщение.

Дневник № 2 | Lis3n0k - Lis3n0k | Лента друзей Lis3n0k / Полная версия Добавить в друзья Страницы: раньше»