diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..9d5248e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# editorconfig.org + +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/README.markdown b/README.markdown deleted file mode 100644 index cf6bf3d..0000000 --- a/README.markdown +++ /dev/null @@ -1,29 +0,0 @@ -Selectivizr ------------ - -**CSS3 selectors for IE 6-8** - - -_selectivizr_ is a JavaScript utility that emulates CSS3 pseudo-classes -and attribute selectors in Internet Explorer 6-8. Simply include the -script in your pages and selectivizr will do the rest. - -To use the library, you'll need to include one of the supported libraries: - - * jQuery (1.3+) - * Dojo (1.5.0+) - * Prototype (1.6.1+) - * Yahoo UI Library (2.8.0+) - * DOMAssistant (2.8.0+) - * MooTools (1.3+) - * NWMatcher (1.2.3+) - -Then add the following conditional comment _AFTER_ your stylesheets: - - - -This adds the `selectivizr.js` and an optional fallback CSS file to IE6-8 while -hiding for other browsers. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..c2fcfd7 --- /dev/null +++ b/README.md @@ -0,0 +1,81 @@ +

Selectivizr 2

+

+ :sparkles: Now with maintenance! :sparkles: +

+ +### What happened to the old project? +[Keith Clark](https://github.com/keithclark) was eaten alive by sabre-tooth rattlesnakes or something. Who knows? + +Good on him for originally inventing this though. :beers: + +### Why support old IE? +Why completely turn your back on it? I'm not saying give it special attention (unless you're making a website for [the most populated country in the world](https://www.techinasia.com/windows-xp-now-dead-but-200-million-machines-in-china-still-using-it)), but why not toss some polyfills in conditional comments and at least give the poor bastards who are stuck on IE6-IE8 *something* to look at. + +It requires almost 0 effort on your part and can make your website viewable to a lot of people. + +### What is Selectivizr? +Selectivizr is a [polyfill](https://en.wikipedia.org/wiki/Polyfill) that makes IE6-8 work with most [CSS3 selectors](https://www.w3.org/TR/selectors/#selectors) (like `:nth-child`). + +### Installation +- `bower install --save selectivizr2` + +### Usage +To use the library, you'll need to include the [latest jQuery 1.x.x](https://jquery.com/download/). + +Then add the following conditional comment **after** your stylesheets and jQuery: + +```html + +``` + +### Example + +```html + + + + Selectivizr Test + + + + +
Hello World
+ + + + + +``` + +```css +div:nth-of-type(1) { + background: blue; +} +``` + +That's it. That's how polyfills typically work. Load the .js and [bam](https://www.youtube.com/watch?v=8dxpMxULHnA)! + +The only people downloading this file will be people below IE9. This means we're not punishing people using modern browsers. + +### How can I test my site in IE7-IE8? +- Use a Virtual Machine + - Learn how to install and setup VMs with [VirtualBox](https://www.virtualbox.org/). It's cross-platform and there are probably lots of [YouTube videos](https://www.youtube.com/results?search_query=virtualbox) on it so grab a :coffee: and enjoy. + - Microsoft offers [Windows images](https://dev.windows.com/en-us/microsoft-edge/tools/vms) specifically so you can try out old browsers. + - [IEVMS](https://github.com/xdissent/ievms) is the incredibly easy way to get/maintain these VMs. +- [BrowserStack](http://browserstack.com) is expensive and **slow**, but if you can't figure out the other techniques you can use it. I highly suggest you figure out how to use VMs though. It's a skill worth learning. + +> I'm not even sure how to test in IE6 anymore, but... seriously? + +### Why shouldn't I use X? +- `bower install selectivizr` installs Selectivizr 1.0.2. 1.0.2 sucks and doesn't work with a bunch of other tools like the wonderful [calc-polyfill](https://github.com/closingtag/calc-polyfill). +- https://github.com/keithclark/selectivizr is unmaintained. +- https://github.com/Mediamoose/selectivizr has issues closed and is broken on Bower. +- https://github.com/shinnn/lt-ie-9 is unmaintained and does more than just Selectivizr anyway. +- `bower install selectivizr-latest` was what this project was until I decided to actually maintain it. + +### Caveats +TBH, I'm not an amazing JS developer yet, so I really have no idea wtf is going on. I'm happy to merge stuff as long as it seems legit but I'm probably not going to spend a ton of time working on this codebase. diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..81d47c0 --- /dev/null +++ b/bower.json @@ -0,0 +1,23 @@ +{ + "name": "selectivizr2", + "main": "selectivizr2.js", + "homepage": "https://github.com/corysimmons/selectivizr2", + "authors": [ + "Keith Clark", + "Cory Simmons" + ], + "description": "A maintained version of Selectivizr.", + "keywords": [ + "selectivizr", + "ie8", + "selectors" + ], + "license": "MIT", + "ignore": [ + "**/.*", + "node_modules", + "bower_components", + "test", + "tests" + ] +} diff --git a/changelog.txt b/changelog.txt deleted file mode 100755 index 0713ea5..0000000 --- a/changelog.txt +++ /dev/null @@ -1,128 +0,0 @@ -selectivizr - change log -======================== - -Current Build -------------- - - * NEW - Removed condiditional comments so 3rd party tools can correctly compress / compile the source. (GMFlash) - * BUG - behaviors (.htc files) are now ignored when processing urls. Fixes "CSS3PIE" issue - * BUG - resolveUrl() fails to resolve protocol relative urls. Fixes "AddThis" issue - * NEW - expose selectiviz'd cssText through styleSheet object via 'rawCssText' expando property - * BUG - incorrect parsing of @media blocks (fixes respondJS compatibility issue) - * BUG - resolveUrl() incorrectly fails external assets urls for violating the same origin policy - * CHG - selectivizr MUST now be included AFTER all 'd stylesheets! - * BUG - IE fails to render page (WSOD (White Screen of Death)) under certain conditions - * BUG - @font-face can cause IE to hang when processing CSS files after DOM load - * BUG - split DOM and CSS parsing into two stages. CSS parsing is now instant - * NEW - selectivizr now honours media specific @imports in style sheets - * BUG - comments placed between @import rules caused the import to fail - - -v1.0.2 ------- - - * BUG - fixed Google Closure Compiler issue that added 2 global vars - sorry about that! - * NEW - removed the eval() from determineSelectorMethod() - * BUG - selectivizr incorrectly detects Yahoo! profiler as YUI selector library - * NEW - selectivizr can now be "lazy-loaded" - * NEW - switched DOMReady back to Diego Perini's (new) ContentLoaded. - * BUG - asset urls using the 'data:' scheme (i.e. background-image) resolved to a path (Chris Korhonen) - * BUG - resolveUrl() failed if the context url contained a hash followed by a '/' (Zee Agency) - * BUG - IE version detection wasn't IE>9 friendly (reported by Paul Irish) - - - -v1.0.1 ------- - - * BUG - @import urls not wrapped with "url()" are now correctly processed - * BUG - relative urls are now correctly resolved - * BUG - patched [*=""] selector in IE8 (returns elements it shouldn't) - - - -v1.0.0 ------- - -ie-css3.js is now stable enough to be released with out a beta suffix - say hello to selectivizr v1! - - - -v0.9.7b -------- - - * NEW - Complete rewrite of the stylesheet parser. - * NEW - :not() pseudo support. - * NEW - Attribute selector support in IE6 [att] [att="x"] [att~="x"] [att^="x"] [att$="x"] [att*="x"] and [att|="x"] - * NEW - Fixes native empty attribute selector support in IE7 [att^=""] [att$=""] [att*=""] and IE8 [att^=""] [att$=""] - * BUG - :enabled and :disabled elements now change state properly. (Uses polling) - * BUG - Emulation no longer fails in IE6 when more than 2 classes are applied to an element - - - -v0.9.6b -------- - - * BUG - IE8 :target pseudo-class emulation fails with jQuery (but not with Sizzle) (reported by Tom Law) - * BUG - ie-css3.js won't run if page is in an iframe (switched DOM Load detection to Dean Edwards deferred script method) - * BUG - A selector that begins with a attribute selector incorrectly parsed (reported by Stephanie Sullivan) - - - -v0.9.5b -------- - - * NEW - Reworked DOM Load detection (using a cut down version of Diego Perini's ContentLoaded technique) - * NEW - Enabled Dojo detection (lowest priority) - Warning: some of Dojo's CSS3 selectors seem very buggy! - * BUG - Fixed mixed content warning when using over SSL - * NEW - :target pseudo for IE8 when running standards mode. Sorry, no support for pre-IE8 or quirks mode - * NWMatcher now higher priority that DOMAssistant when auto-detecting best library - * Internal rewrites / refactoring - more features, but a smaller file :o) - - - -v0.9.4b -------- - - * NEW - added support for :hover (for IE 5.5 - 6) and :focus (for IE 5.5 - 7) - * NEW - added support for ::first-child and ::first-letter (suggested by Philip Renich) - * BUG - style sheets without href values shouldn't get parsed (reported by Jeff Smith) - * BUG - remotely hosted style sheets are now ignored when used in @imports - * BUG - @import rules now honour the href if its specified (reported by Andrea and Tim) - * BUG - various minor bug fixes - - - -v0.9.3b -------- - - * No longer dependent on DOMAssistant. - * Auto-detects best suited selector library from these: - - DOMAssistant (recommended) - - NWmatcher - - Prototype - - YUI 2 - - MooTools - - Sizzle / jQuery - * NEW - pseudo selectors :enabled, :disabled, :checked and :root. - * BUG - Fixed IE 5.5/6 issue with illegal character in replacement class name. - * BUG - Fixed extra spaces issue with modified class names. - * BUG - Stopped triggering a DOM redraw when there are no className changes - * Dynamic building of CSS_PSEUDOS regexp based on IE version so we only patch what's needed. - * XHR compatibility test (reported from twitter.com/kangax). - * Reworked DOMLoaded detection. - - - -v0.9.2b -------- - - * CSS parser updated to crawl @import statements (suggested by Andy "Malarkey" Clarke). - * @font rules support. - - - -v0.9.1b -------- - - * Public beta release. \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..55ff17c --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "selectivizr2", + "description": "Selectivizr maintained.", + "version": "1.0.9", + "main": "selectivizr2.js", + "repository": { + "type": "git", + "url": "git+https://github.com/corysimmons/selectivizr2.git" + }, + "keywords": [ + "selectivizr", + "css3", + "selectors", + "ie8" + ], + "author": "Cory Simmons", + "license": "MIT", + "bugs": { + "url": "https://github.com/corysimmons/selectivizr2/issues" + }, + "homepage": "http://selectivizr.com" +} diff --git a/selectivizr.js b/selectivizr2.js similarity index 83% rename from selectivizr.js rename to selectivizr2.js index 7077c57..961af3c 100755 --- a/selectivizr.js +++ b/selectivizr2.js @@ -1,27 +1,19 @@ /* -selectivizr v1.0.3b - (c) Keith Clark, freely distributable under the terms -of the MIT license. - -selectivizr.com -*/ -/* - -Notes about this source ------------------------ + selectivizr2 + selectivizr.com + Notes about this source + ----------------------- * The #DEBUG_START and #DEBUG_END comments are used to mark blocks of code that will be removed prior to building a final release version (using a pre-compression script) - - -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/ - + + References: + ----------- + * CSS Syntax : https://www.w3.org/TR/2003/WD-css3-syntax-20030813/#style + * Selectors : https://www.w3.org/TR/css3-selectors/#selectors + * IE Compatability : https://msdn.microsoft.com/en-us/library/cc351024%28VS.85%29.aspx + * W3C Selector Tests : https://www.w3.org/Style/CSS/Test/CSS3/Selectors/current/html/tests/ */ (function(win) { @@ -46,19 +38,18 @@ References: if (doc.compatMode != 'CSS1Compat' || ieVersion<6 || ieVersion>8 || !xhr) { return; } - - + // ========================= Common Objects ============================ - // Compatiable selector engines in order of CSS3 support. Note: '*' is - // a placholder for the object key name. (basically, crude compression) + // Compatible selector engines in order of CSS3 support. Note: '*' is + // a placeholder for the object key name. (basically, crude compression) var selectorEngines = { "NW" : "*.Dom.select", "MooTools" : "$$", - "DOMAssistant" : "*.$", + "DOMAssistant" : "*.$", "Prototype" : "$$", "YAHOO" : "*.util.Selector.query", - "Sizzle" : "*", + "Sizzle" : "*", "jQuery" : "*", "dojo" : "*.query" }; @@ -72,15 +63,15 @@ References: // Stylesheet parsing regexp's var RE_COMMENT = /(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)\s*?/g; - var RE_IMPORT = /@import\s*(?:(?:(?:url\(\s*(['"]?)(.*)\1)\s*\))|(?:(['"])(.*)\3))\s*([^;]*);/g; + var RE_IMPORT = /@import\s*(?:(?:(?:url\(\s*(['"]?)([^;]*)\1)\s*\))|(?:(['"])([^;]*)\3))\s*([^;]*);/g; var RE_ASSET_URL = /(behavior\s*?:\s*)?\burl\(\s*(["']?)(?!data:)([^"')]+)\2\s*\)/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*})+)(?:\s*@media[^{]+{)?)\s*([^\{]*?[\[:][^{]+)/g; - var RE_SELECTOR_PARSE = /([ +~>])|(:[a-z-]+(?:\(.*?\)+)?)|(\[.*?\])/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)$/; @@ -93,7 +84,7 @@ References: 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 = " "; @@ -106,41 +97,40 @@ References: // 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) { + replace(RE_SELECTOR_GROUP, function(m, prefix, selectorText) { var selectorGroups = selectorText.split(","); + function comboBreaker (match, combinator, pseudo, attribute, index) { + if (combinator) { + if (patches.length>0) { + domPatches.push( { selector: selector.substring(0, index), patches: patches } ); + patches = []; + } + return combinator; + } + else { + var patch = (pseudo) ? patchPseudoClass( pseudo ) : patchAttribute( attribute ); + if (patch) { + patches.push(patch); + return "." + patch.className; + } + return match; + } + } for (var c = 0, cs = selectorGroups.length; c < cs; c++) { var selector = normalizeSelectorWhitespace(selectorGroups[c]) + SPACE_STRING; var patches = []; - selectorGroups[c] = selector.replace(RE_SELECTOR_PARSE, - function(match, combinator, pseudo, attribute, index) { - if (combinator) { - if (patches.length>0) { - domPatches.push( { selector: selector.substring(0, index), patches: patches } ) - patches = []; - } - return combinator; - } - else { - var patch = (pseudo) ? patchPseudoClass( pseudo ) : patchAttribute( attribute ); - if (patch) { - patches.push(patch); - return "." + patch.className; - } - return match; - } - } - ); + selectorGroups[c] = selector.replace(RE_SELECTOR_PARSE, comboBreaker); } return prefix + selectorGroups.join(","); }); - }; + } // --[ patchAttribute() ]----------------------------------------------- // returns a patch for an attribute selector. function patchAttribute( attr ) { - return (!BROKEN_ATTR_IMPLEMENTATIONS || BROKEN_ATTR_IMPLEMENTATIONS.test(attr)) ? + return (!BROKEN_ATTR_IMPLEMENTATIONS || BROKEN_ATTR_IMPLEMENTATIONS.test(attr)) ? { className: createClassName(attr), applyClass: true } : null; - }; + } // --[ patchPseudoClass() ]--------------------------------------------- // returns a patch for a pseudo-class @@ -152,17 +142,17 @@ References: var activateEventName; var deactivateEventName; - // if negated, remove :not() + // if negated, remove :not() if (isNegated) { pseudo = pseudo.slice(5, -1); } - + // bracket contents are irrelevant - remove them - var bracketIndex = pseudo.indexOf("(") + 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)) { @@ -170,63 +160,65 @@ References: 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 handler = function() { var hash = location.hash; var hashID = hash.slice(1); return isNegated ? (hash == EMPTY_STRING || e.id != hashID) : (hash != EMPTY_STRING && e.id == hashID); }; addEvent( win, "hashchange", function() { toggleElementClass(e, className, handler()); - }) + }); return handler(); - } + }; break; } return false; - + case "checked": - applyClass = function(e) { + 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; + break; case "enabled": - applyClass = function(e) { + 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"; - + break; + case "hover": if (!activateEventName) { activateEventName = "mouseenter"; @@ -235,17 +227,17 @@ References: 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 + // If we don't support this pseudo-class don't create // a patch for it if (!RE_PSEUDO_STRUCTURAL.test(pseudo)) { return false; @@ -254,7 +246,7 @@ References: } } return { className: className, applyClass: applyClass }; - }; + } // --[ applyPatches() ]------------------------------------------------- function applyPatches() { @@ -284,7 +276,6 @@ References: // #DEBUG_END } - if (elms) { for (var d = 0, dl = elms.length; d < dl; d++) { var elm = elms[d]; @@ -301,23 +292,22 @@ References: } } } - }; + } // --[ hasPatch() ]----------------------------------------------------- - // checks for the exsistence of a patch on an element + // checks for the existence of a patch on an element function hasPatch( elm, patch ) { return new RegExp("(^|\\s)" + patch.className + "(\\s|$)").test(elm.className); - }; - - + } + // =========================== Utility ================================= - + function createClassName( className ) { return namespace + "-" + ((ieVersion == 6 && patchIE6MultipleClasses) ? ie6PatchID++ : - className.replace(RE_PATCH_CLASS_NAME_REPLACE, function(a) { return a.charCodeAt(0) })); - }; + className.replace(RE_PATCH_CLASS_NAME_REPLACE, function(a) { return a.charCodeAt(0); })); + } // --[ log() ]---------------------------------------------------------- // #DEBUG_START @@ -325,20 +315,20 @@ References: 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() ]---------------------------------- // tidies whitespace around selector brackets and combinators @@ -347,7 +337,7 @@ References: replace(RE_TIDY_TRAILING_WHITESPACE, PLACEHOLDER_STRING). replace(RE_TIDY_LEADING_WHITESPACE, PLACEHOLDER_STRING) ); - }; + } // --[ toggleElementClass() ]------------------------------------------- // toggles a single className on an element @@ -358,10 +348,10 @@ References: elm.className = newClassName; elm.parentNode.className += EMPTY_STRING; } - }; + } // --[ toggleClass() ]-------------------------------------------------- - // adds / removes a className from a string of classNames. Used to + // 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|$)"); @@ -371,32 +361,32 @@ References: } 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; + return new XMLHttpRequest(); } - try { + try { return new ActiveXObject('Microsoft.XMLHTTP'); - } catch(e) { + } catch(e) { return null; } - }; + } // --[ loadStyleSheet() ]----------------------------------------------- function loadStyleSheet( url ) { xhr.open("GET", url, false); xhr.send(); - return (xhr.status==200) ? xhr.responseText : EMPTY_STRING; - }; - + return (xhr.status==200) ? (xhr.responseText != null ? xhr.responseText : EMPTY_STRING) : 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 @@ -404,11 +394,11 @@ References: function getProtocol( url ) { return url.substring(0, url.indexOf("//")); - }; + } function getProtocolAndHost( url ) { return url.substring(0, url.indexOf("/", 8)); - }; + } if (!contextUrl) { contextUrl = baseUrl; @@ -430,32 +420,32 @@ References: } // relative path - var contextUrlPath = contextUrl.split(/[?#]/)[0]; // ignore query string in the contextUrl + 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) { + if (url && url.indexOf(".css") !== -1) { return loadStyleSheet(url).replace(RE_COMMENT, EMPTY_STRING). replace(RE_IMPORT, function( match, quoteChar, importUrl, quoteChar2, importUrl2, media ) { var cssText = parseStyleSheet(resolveUrl(importUrl || importUrl2, url)); return (media) ? "@media " + media + " {" + cssText + "}" : cssText; }). - replace(RE_ASSET_URL, function( match, isBehavior, quoteChar, assetUrl ) { + replace(RE_ASSET_URL, function( match, isBehavior, quoteChar, assetUrl ) { quoteChar = quoteChar || EMPTY_STRING; - return isBehavior ? match : " url(" + quoteChar + resolveUrl(assetUrl, url, true) + quoteChar + ") "; + return isBehavior ? match : " url(" + quoteChar + resolveUrl(assetUrl, url, true) + quoteChar + ") "; }); } return EMPTY_STRING; - }; + } // --[ getStyleSheets() ]----------------------------------------------- function getStyleSheets() { @@ -465,18 +455,18 @@ References: if (stylesheet.href != EMPTY_STRING) { url = resolveUrl(stylesheet.href); if (url) { - stylesheet.cssText = stylesheet["rawCssText"] = patchStyleSheet( parseStyleSheet( url ) ); + stylesheet.cssText = stylesheet.rawCssText = patchStyleSheet( parseStyleSheet( url ) ); } } } - }; + } // --[ init() ]--------------------------------------------------------- function init() { applyPatches(); - // :enabled & :disabled polling script (since we can't hook - // onpropertychange event when an element is disabled) + // :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 < cl; c++) { @@ -492,16 +482,16 @@ References: } } } - }, 250) + }, 250); } - }; + } // Determine the baseUrl and download the stylesheets var baseTags = doc.getElementsByTagName("BASE"); var baseUrl = (baseTags.length > 0) ? baseTags[0].href : doc.location.href; getStyleSheets(); - // Bind selectivizr to the ContentLoaded event. + // Bind selectivizr to the ContentLoaded event. ContentLoaded(win, function() { // Determine the "best fit" selector engine for (var engine in selectorEngines) { @@ -517,9 +507,7 @@ References: } } }); - - /*! * ContentLoaded.js by Diego Perini, modified for IE<9 only (to save space) * @@ -559,5 +547,5 @@ References: addEvent(doc,"readystatechange", init); addEvent(win,"load", init); } - }; + } })(this); diff --git a/tests/master/css/import-print.css b/tests/master/css/import-print.css index 1bd5e1a..611a225 100644 --- a/tests/master/css/import-print.css +++ b/tests/master/css/import-print.css @@ -1,6 +1,6 @@ /* if @media type filtering doesn't work we want this test to fail */ tr#import-print { - background: #c00; + background: #0c0; } diff --git a/tests/master/css/master.css b/tests/master/css/master.css index 6089ff1..81dc054 100755 --- a/tests/master/css/master.css +++ b/tests/master/css/master.css @@ -29,13 +29,25 @@ @import url("import-print.css") print; @import url("import-screen.css") screen; -#import-print { - background: #0c0; -} +/* When parsing @import of minified CSS, ensure the Regex isn't too greedy */ +@import url("min-import-url-quoted-double.css");.minified{background:url("css/nested/test.png");} +@import url('min-import-url-quoted-single.css');.minified{background:url("css/nested/test.png");} +@import url(min-import-url-unquoted.css);.minified{background:url("css/nested/test.png");} +@import "min-import-quoted-double.css";.minified{background:url("css/nested/test.png");} +@import "min-import-quoted-single.css";.minified{background:url("css/nested/test.png");} +@import url("nested/min-import-url-relative-path.css");.minified{background:url("css/nested/test.png");} +/* + * The following urls will be specific to your own server configuration and will fail + * if used "out of the box". To test root-relative and fully qualifed url's you will + * need to adjust the paths below: + */ -#import-screen { - background: #c00; -} +@import url("/selectivizr-git/tests/master/css/min-import-url-root-relative-path.css");.minified{background:url("css/nested/test.png");} +@import url("http://iis/selectivizr-git/tests/master/css/min-import-url-fully-qualified-path.css");.minified{background:url("css/nested/test.png");} +@import url("//iis/selectivizr-git/tests/master/css/min-import-url-protocol-relative-path.css");.minified{background:url("css/nested/test.png");} + +@import url("min-import-print.css") print;.minified{background:url("css/nested/test.png");} +@import url("min-import-screen.css") screen;.minified{background:url("css/nested/test.png");} body { padding: 10px; diff --git a/tests/master/css/min-import-print.css b/tests/master/css/min-import-print.css new file mode 100644 index 0000000..cfb90ed --- /dev/null +++ b/tests/master/css/min-import-print.css @@ -0,0 +1,6 @@ +/* if @media type filtering doesn't work we want this test to fail */ + +tr#min-import-print { + background: #0c0; +} + diff --git a/tests/master/css/min-import-quoted-double.css b/tests/master/css/min-import-quoted-double.css new file mode 100644 index 0000000..f8f23b5 --- /dev/null +++ b/tests/master/css/min-import-quoted-double.css @@ -0,0 +1 @@ +#min-import-quoted-double { background-color: #0c0 } diff --git a/tests/master/css/min-import-quoted-single.css b/tests/master/css/min-import-quoted-single.css new file mode 100644 index 0000000..777b4e1 --- /dev/null +++ b/tests/master/css/min-import-quoted-single.css @@ -0,0 +1 @@ +#min-import-quoted-single { background-color: #0c0 } diff --git a/tests/master/css/min-import-screen.css b/tests/master/css/min-import-screen.css new file mode 100644 index 0000000..ca3ab89 --- /dev/null +++ b/tests/master/css/min-import-screen.css @@ -0,0 +1,4 @@ +tr#min-import-screen { + background: #0c0; +} + diff --git a/tests/master/css/min-import-url-fully-qualified-path.css b/tests/master/css/min-import-url-fully-qualified-path.css new file mode 100644 index 0000000..482b81e --- /dev/null +++ b/tests/master/css/min-import-url-fully-qualified-path.css @@ -0,0 +1 @@ +#min-import-url-fully-qualfied { background-color: #0c0 } diff --git a/tests/master/css/min-import-url-protocol-relative-path.css b/tests/master/css/min-import-url-protocol-relative-path.css new file mode 100644 index 0000000..3c96e8e --- /dev/null +++ b/tests/master/css/min-import-url-protocol-relative-path.css @@ -0,0 +1,3 @@ +#min-import-url-protocol-relative { + background: #0c0; +} diff --git a/tests/master/css/min-import-url-quoted-double.css b/tests/master/css/min-import-url-quoted-double.css new file mode 100644 index 0000000..027113d --- /dev/null +++ b/tests/master/css/min-import-url-quoted-double.css @@ -0,0 +1 @@ +#min-import-url-quoted-double { background-color: #0c0 } diff --git a/tests/master/css/min-import-url-quoted-single.css b/tests/master/css/min-import-url-quoted-single.css new file mode 100644 index 0000000..56c9f9b --- /dev/null +++ b/tests/master/css/min-import-url-quoted-single.css @@ -0,0 +1 @@ +#min-import-url-quoted-single { background-color: #0c0 } diff --git a/tests/master/css/min-import-url-relative-path.css b/tests/master/css/min-import-url-relative-path.css new file mode 100644 index 0000000..9e1abd6 --- /dev/null +++ b/tests/master/css/min-import-url-relative-path.css @@ -0,0 +1 @@ +#min-import-url-relative { background-image: url("test.png") } diff --git a/tests/master/css/min-import-url-root-relative-path.css b/tests/master/css/min-import-url-root-relative-path.css new file mode 100644 index 0000000..b084ec8 --- /dev/null +++ b/tests/master/css/min-import-url-root-relative-path.css @@ -0,0 +1 @@ +#min-import-url-root-relative { background-color: #0c0 } diff --git a/tests/master/css/min-import-url-unquoted.css b/tests/master/css/min-import-url-unquoted.css new file mode 100644 index 0000000..d5cce4a --- /dev/null +++ b/tests/master/css/min-import-url-unquoted.css @@ -0,0 +1 @@ +#min-import-url-unquoted { background-color: #0c0 } diff --git a/tests/master/index.html b/tests/master/index.html index cb98f25..2ccfbf6 100755 --- a/tests/master/index.html +++ b/tests/master/index.html @@ -111,6 +111,54 @@

@import syntax tests

+

Minified @import syntax tests

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@import url("...")Testing @import rule with url wrapped in double quotes and prefixed with the url() qualifier +
@import url('...')Testing @import rule with url wrapped in single quotes and prefixed with the url() qualifier +
@import url(...)Testing @import rule with url without quotes and prefixed with the url() qualifier +
@import "..."Testing @import rule with url wrapped in double quotes without the url() qualifier +
@import '...'Testing @import rule with url wrapped in single quotes without the url() qualifier +
@import url("../file.css")Testing @import rule with a relative path +
@import url("/path/file.css")Testing @import rule with a root-relative path (see note in 'master.css') +
@import url("http://domain/path/file.css")Testing @import rule with a fully qualified path (see note in 'master.css') +
@import url("//domain/path/file.css")Testing @import rule with a protocol relative path +
@import url("...") printTesting @import rule with a print media type +
@import url("...") screenTesting @import rule with a screen media type +
+

url syntax tests

@@ -359,4 +407,4 @@

HTML5 element tests

- \ No newline at end of file +