diff --git a/API.txt b/API.txt deleted file mode 100644 index b1b4771..0000000 --- a/API.txt +++ /dev/null @@ -1,32 +0,0 @@ -These are the methods, the plugin adds to the different namespaces. - -jQuery.fn - - sheet: returns the stylesheets from the matched styles and links. - - cssRules: return all the rules from all the given sheets. - - ownerNode: returns the nodes that belong to the given sheet (opposite to sheets). - - cssText: returns the text of the first matched style/link. - -jQuery.rule - - constructor( $.rule ): - - 1st argument: nothing, a rule filter, rule literal, css rule or array of rules. - - 2nd argument: nothing, node filter for link/style, nodes link/style. - - sheets: returns the sheets that match the selector or all of them if none. - - clean: converts a rule literal, to array of rules. - - parent: returns the parent of a rule, neccesary for IE. - - outerText: return the selector with the rules of the given rule. - - text: gets/sets the cssText of the rule. - -jQuery.rule.fn - - append: will add one or more styles in the form of "attr:value; attr:value" to the matched rules. - - css : sets a value to all matched rules. - - outerText: return $.rule.outerText of the first rule. - - text: sets the cssText of the rules, or gets the cssText from the first one. - - appendTo: appends the matched rules to the specified stylesheet(1), can be a selector, dom element, sheet. - -All these methods ( from jQuery.rule.fn ) are equal (or very similar) to those in jQuery.fn, but for CSS Rules. - add, andSelf, animate, appendTo, attr, css, dequeue, - each, end, eq, fadeIn, fadeOut, fadeTo, filter, get, - hide, index, is, map, not, pushStack, queue, remove, - setArray, show, size, slice, stop, toggle. - -Some calls to show and hide behave unexpectedly sometimes. Some styles and animations might fail, please report it. \ No newline at end of file diff --git a/changes.txt b/CHANGELOG.md similarity index 75% rename from changes.txt rename to CHANGELOG.md index f2fad6e..e8b42f0 100644 --- a/changes.txt +++ b/CHANGELOG.md @@ -1,39 +1,53 @@ -1.0.1 -[Fix] -- Small fix for Opera 9.55. The created demanded a closing slash. -- Fixed the exclusion of $.rule's sheet in $.rule.sheets(). Thanks to Adrien Gibrat for noticing. -- Literal rules were split by ','. That would break comma-separated selectors. Reported by Adrien Gibrat. - Note that IE doesn't support comma-separated selectors in the addRule method. This could be worked around but would - cause different results among browsers, so just now that it fails in IE and it should not be used. -[Optimization] -- Added a cleanup of the local storage on window.unload -[Docs] -- Added some notes to the source file (jquery.rule.js). - -1.0 -- Added semicolon to the start, for safe file concatenation -- Minor changes for perfomance -- Saved $.rule in a variable to make compressed code much shorter. -- Replaced the 'x:y' for IE when creating empty rules for ';'. -- Made many changes tp $.rule.fn.filter: - * The filtering function used to get element & index as arguments instead of element as 'this' and index as 1st argument. - * String filters are no longer turned into regex, now they are compared (case insensitive) to each (splitted by comma) selector. -- $.data and $.removeData have been extended ( hacked :) ). Instead of the element(rule), they get an empty hash, stored in $.rule.cache. -- The changes in $.data allow cross browser animations. They need some aggressive testing. -- Added show/hide/toggle and slide functions to $.rule.fn. -- Improved the hack to $.curCSS, it returns some default values in case none is set, for animations. It needs some more work. - -0.9.2 -- Added queue,dequeue,animate and stop to $.rule.fn (non-IE) -- Hacked $.curCSS to make the animations work. -- remove() works in Opera 9 and Safari Win! - - Opera needed 'alternate' in the rel of stylesheet - - Safari wanted the sheet to be disabled, not the node. -- $.rule.fn.filter now supports a regex as filter. - -0.9 -- Made the code work faster. -- Extended $.fn with ownerNode,sheet,cssRules and cssText. -- Added text and outerText to $.rule and $.rule.fn. -- Made the example nicer. +1.1.2 +[Fix] +- Changing rules property existence check for CORS + +1.1.1 +[Fix] +- Made compatible with jquery 3.0+. +- Added NPM manifest. + +1.1.0 +[Fix] +- Fix for FireFox "SecurityError: The operation is insecure." if an external CSS ref is present. Thanks for @dorival for the PR + +1.0.1 +[Fix] +- Small fix for Opera 9.55. The \ created demanded a closing slash. +- Fixed the exclusion of $.rule's sheet in $.rule.sheets(). Thanks to Adrien Gibrat for noticing. +- Literal rules were split by ','. That would break comma-separated selectors. Reported by Adrien Gibrat. + - Note that IE doesn't support comma-separated selectors in the addRule method. This could be worked around but would cause different results among browsers, so just now that it fails in IE and it should not be used. + +[Optimization] +- Added a cleanup of the local storage on window.unload + +[Docs] +- Added some notes to the source file (jquery.rule.js). + +1.0 +- Added semicolon to the start, for safe file concatenation +- Minor changes for perfomance +- Saved $.rule in a variable to make compressed code much shorter. +- Replaced the 'x:y' for IE when creating empty rules for ';'. +- Made many changes tp $.rule.fn.filter: + * The filtering function used to get element & index as arguments instead of element as 'this' and index as 1st argument. + * String filters are no longer turned into regex, now they are compared (case insensitive) to each (splitted by comma) selector. +- $.data and $.removeData have been extended ( hacked :) ). Instead of the element(rule), they get an empty hash, stored in $.rule.cache. +- The changes in $.data allow cross browser animations. They need some aggressive testing. +- Added show/hide/toggle and slide functions to $.rule.fn. +- Improved the hack to $.curCSS, it returns some default values in case none is set, for animations. It needs some more work. + +0.9.2 +- Added queue,dequeue,animate and stop to $.rule.fn (non-IE) +- Hacked $.curCSS to make the animations work. +- remove() works in Opera 9 and Safari Win! + - Opera needed 'alternate' in the rel of stylesheet + - Safari wanted the sheet to be disabled, not the node. +- $.rule.fn.filter now supports a regex as filter. + +0.9 +- Made the code work faster. +- Extended $.fn with ownerNode,sheet,cssRules and cssText. +- Added text and outerText to $.rule and $.rule.fn. +- Made the example nicer. - Removed $.fn.collect. \ No newline at end of file diff --git a/License b/License new file mode 100644 index 0000000..ae9038c --- /dev/null +++ b/License @@ -0,0 +1,19 @@ +Copyright (c)2007 Ariel Flesler + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md index 5bff1b0..b2a9fed 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,39 @@ -jquery.rule -=========== \ No newline at end of file +# jQuery.Rule +CSS Rules manipulation, the jQuery way. + +# Usage +These are the methods, the plugin adds to the different namespaces. + +## jQuery.fn +- sheet: returns the stylesheets from the matched styles and links. +- cssRules: return all the rules from all the given sheets. +- ownerNode: returns the nodes that belong to the given sheet (opposite to sheets). +- cssText: returns the text of the first matched style/link. + +## jQuery.rule +- constructor( $.rule ): + - 1st argument: nothing, a rule filter, rule literal, css rule or array of rules. + - 2nd argument: nothing, node filter for link/style, nodes link/style. +- sheets: returns the sheets that match the selector or all of them if none. +- clean: converts a rule literal, to array of rules. +- parent: returns the parent of a rule, neccesary for IE. +- outerText: return the selector with the rules of the given rule. +- text: gets/sets the cssText of the rule. + +## jQuery.rule.fn +- append: will add one or more styles in the form of "attr:value; attr:value" to the matched rules. +- css : sets a value to all matched rules. +- outerText: return $.rule.outerText of the first rule. +- text: sets the cssText of the rules, or gets the cssText from the first one. +- appendTo: appends the matched rules to the specified stylesheet(1), can be a selector, dom element, sheet. + +All these methods ( from jQuery.rule.fn ) are equal (or very similar) to those in jQuery.fn, but for CSS Rules. + add, andSelf, animate, appendTo, attr, css, dequeue, + each, end, eq, fadeIn, fadeOut, fadeTo, filter, get, + hide, index, is, map, not, pushStack, queue, remove, + setArray, show, size, slice, stop, toggle. + +Some calls to show and hide behave unexpectedly sometimes. Some styles and animations might fail, please report it. + +# License +The MIT License. Check 'License'. \ No newline at end of file diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..0558262 --- /dev/null +++ b/bower.json @@ -0,0 +1,13 @@ +{ + "name": "jquery.rule", + "version": "1.1.2", + "main": "jquery.rule.js", + "ignore": [ + "**/.*", + "node_modules", + "components" + ], + "dependencies": { + "jquery": ">= 1.2" + } +} diff --git a/jquery.rule.js b/jquery.rule.js index 5bcf8d2..a77be49 100644 --- a/jquery.rule.js +++ b/jquery.rule.js @@ -1,273 +1,289 @@ -/*! - * jQuery.Rule - Css Rules manipulation, the jQuery way. - * Copyright (c) 2007-2011 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com - * Dual licensed under MIT and GPL. - * Date: 02/7/2011 - * Compatible with jQuery 1.2+ - * - * @author Ariel Flesler - * @version 1.0.2 - * - * @id jQuery.rule - * @param {Undefined|String|jQuery.Rule} The rules, can be a selector, or literal CSS rules. Many can be given, comma separated. - * @param {Undefined|String|DOMElement|jQuery) The context stylesheets, all of them by default. - * @return {jQuery.Rule} Returns a jQuery.Rule object. - * - * @example $.rule('p,div').filter(function(){ return this.style.display != 'block'; }).remove(); - * - * @example $.rule('div{ padding:20px;background:#CCC}, p{ border:1px red solid; }').appendTo('style'); - * - * @example $.rule('div{}').append('margin:40px').css('margin-left',0).appendTo('link:eq(1)'); - * - * @example $.rule().not('div, p.magic').fadeOut('slow'); - * - * @example var text = $.rule('#screen h2').add('h4').end().eq(4).text(); - */ -;(function( $ ){ - - /** - * Notes - * Some styles and animations might fail, please report it. - * The plugin needs a style node to stay in the DOM all along to temporarily hold rules. DON'T TOUCH IT. - * Opera requires this style to have alternate in the rel to allow disabling it. - * Rules in IE don't have .parentStylesheet. We need to find it each time(slow). - * Animations need close attention. Programatically knowing which rule has precedence, would require a LOT of work. - * This plugin adds $.rule and also 4 methods to $.fn: ownerNode, sheet, cssRules and cssText - * Note that rules are not directly inside nodes, you need to do: $('style').sheet().cssRules(). - */ - - var storageNode = $('').appendTo('head')[0],//we must append to get a stylesheet - sheet = storageNode.sheet ? 'sheet' : 'styleSheet', - storage = storageNode[sheet],//css rules must remain in a stylesheet for IE and FF - rules = storage.rules ? 'rules' : 'cssRules', - remove = storage.deleteRule ? 'deleteRule' : 'removeRule', - owner = storage.ownerNode ? 'ownerNode' : 'owningElement', - reRule = /^([^{]+)\{([^}]*)\}/m, - reStyle = /([^:]+):([^;}]+)/; - - storage.disabled = true;//let's ignore your rules - - var $rule = $.rule = function( r, c ){ - if(!(this instanceof $rule)) - return new $rule( r, c ); - - this.sheets = $rule.sheets(c); - if( r && reRule.test(r) ) - r = $rule.clean( r ); - if( typeof r == 'object' && !r.exec ) { - setArray( this, r.get ? r.get() : r.splice ? r : [r] ); - } else { - setArray( this, this.sheets.cssRules().get() ); - if (r) - return this.filter( r ); - } - return this; - }; - - $.extend( $rule, { - sheets:function( c ){ - var o = c; - if( typeof o != 'object' ) - o = $.makeArray(document.styleSheets); - o = $(o).not(storage);//skip our stylesheet - if( typeof c == 'string' ) - o = o.ownerNode().filter(c).sheet(); - return o; - }, - rule:function( str ){ - if( str.selectorText )/* * */ - return [ '', str.selectorText, str.style.cssText ]; - return reRule.exec( str ); - }, - appendTo:function( r, ss, skip ){ - switch( typeof ss ){//find the desired stylesheet - case 'string': ss = this.sheets(ss); - case 'object': - if( ss[0] ) ss = ss[0]; - if( ss[sheet] ) ss = ss[sheet]; - if( ss[rules] ) break;//only if the stylesheet is valid - default: - if( typeof r == 'object' ) return r;//let's not waist time, it is parsed - ss = storage; - } - var p; - if( !skip && (p = this.parent(r)) )//if this is an actual rule, and it's appended. - r = this.remove( r, p ); - - var rule = this.rule( r ); - if( ss.addRule ) - ss.addRule( rule[1], rule[2]||';' );//IE won't allow empty rules - else if( ss.insertRule ) - ss.insertRule( rule[1] + '{'+ rule[2] +'}', ss[rules].length ); - - return ss[rules][ ss[rules].length - 1 ];//return the added/parsed rule - }, - remove:function( r, p ){ - p = p || this.parent(r); - if( p != storage ){//let's save some unnecesary cycles. - var i = p ? $.inArray( r, p[rules] ) : -1; - if( i != -1 ){//if not stored before removal, IE will crash eventually, and some rules in FF get messed up - r = this.appendTo( r, 0 /*storage*/, true );//is faster and shorter to imply storage - p[remove](i); - } - } - return r; - }, - clean:function( r ){ - return $.map( r.split('}'), function( txt ){ - if( txt ) - return $rule.appendTo( txt + '}' /*, storage*/ );//parse the string, storage implied - }); - }, - parent:function( r ){//CSS rules in IE don't have parentStyleSheet attribute - if( typeof r == 'string' || !$.browser.msie )//if it's a string, just return undefined. - return r.parentStyleSheet; - - var par; - this.sheets().each(function(){ - if( $.inArray(r, this[rules]) != -1 ){ - par = this; - return false; - } - }); - return par; - }, - outerText:function( rule ){ - return !rule || !rule.selectorText ? '' : [rule.selectorText+'{', '\t'+rule.style.cssText,'}'].join('\n').toLowerCase(); - }, - text:function( rule, txt ){ - if( txt !== undefined ) - rule.style.cssText = txt; - return !rule ? '' : rule.style.cssText.toLowerCase(); - } - }); - - $rule.fn = $rule.prototype = { - pushStack:function( rs, sh ){ - var ret = $rule( rs, sh || this.sheets ); - ret.prevObject = this; - return ret; - }, - end:function(){ - return this.prevObject || $rule(0,[]); - }, - filter:function( s ){ - var o; - if( !s ) s = /./;//just keep them all. - if( s.split ){ - o = $.trim(s).toLowerCase().split(/\s*,\s*/); - s = function(){ - var s = this.selectorText || ''; - return !!$.grep( s.toLowerCase().split(/\s*,\s*/), function( sel ){ - return $.inArray( sel, o ) != -1; - }).length; - }; - }else if( s.exec ){//string regex, or actual regex - o = s; - s = function(){ return o.test(this.selectorText); }; - } - return this.pushStack($.grep( this, function( e, i ){ - return s.call( e, i ); - })); - }, - add:function( rs, c ){ - return this.pushStack( $.merge(this.get(), $rule(rs, c)) ); - }, - is:function( s ){ - return !!(s && this.filter( s ).length); - }, - not:function( n, c ){ - n = $rule( n, c ); - return this.filter(function(){ - return $.inArray( this, n ) == -1; - }); - }, - append:function( s ){ - var rules = this, rule; - $.each( s.split(/\s*;\s*/),function(i,v){ - if(( rule = reStyle.exec( v ) )) - rules.css( rule[1], rule[2] ); - }); - return this; - }, - text:function( txt ){ - return !arguments.length ? $rule.text( this[0] ) - : this.each(function(){ $rule.text( this, txt ); }); - }, - outerText:function(){ - return $rule.outerText(this[0]); - } - }; - - $.each({ - ownerNode:owner,//when having the stylesheet, get the node that contains it - sheet:sheet, //get the stylesheet from the node - cssRules:rules //get the rules from the stylesheet. - },function( m, a ){ - var many = a == rules;//the rules need some more processing - $.fn[m] = function(){ - return this.map(function(){ - return many ? $.makeArray(this[a]) : this[a]; - }); - }; - }); - - $.fn.cssText = function(){ - return this.filter('link,style').eq(0).sheet().cssRules().map(function(){ - return $rule.outerText(this); - }).get().join('\n'); - }; - - $.each('remove,appendTo,parent'.split(','),function( k, f ){ - $rule.fn[f] = function(){ - var args = $.makeArray(arguments), that = this; - args.unshift(0); - return this.each(function( i ){ - args[0] = this; - that[i] = $rule[f].apply( $rule, args ) || that[i]; - }); - }; - }); - - $.each(('each,index,get,size,eq,slice,map,attr,andSelf,css,show,hide,toggle,'+ - 'queue,dequeue,stop,animate,fadeIn,fadeOut,fadeTo').split(','),function( k, f ){ - $rule.fn[f] = $.fn[f]; - }); - - // this function has been pulled in from jQuery 1.4.1, because it is an internal function and has been dropped as of 1.4.2 - function setArray(rule, elems) { - rule.length = 0; - Array.prototype.push.apply( rule, elems ); - } - - var curCSS = $.curCSS; - $.curCSS = function( e, a ){//this hack is still quite exprimental - return ('selectorText' in e ) ? - e.style[a] || $.prop( e, a=='opacity'? 1 : 0,'curCSS', 0, a )//TODO: improve these defaults - : curCSS.apply(this,arguments); - }; - - /** - * Time to hack jQuery.data for animations. - * Only IE really needs this, but to keep the behavior consistent, I'll hack it for all browsers. - * TODO: This kind of id doesn't seem to be good enough - * TODO: Avoid animating similar rules simultaneously - * TODO: Avoid rules' precedence from interfering on animations ? - */ - $rule.cache = {}; - var mediator = function( original ){ - return function( elm ){ - var id = elm.selectorText; - if( id ) - arguments[0] = $rule.cache[id] = $rule.cache[id] || {}; - return original.apply( $, arguments ); - }; - }; - $.data = mediator( $.data ); - $.removeData = mediator( $.removeData ); - - $(window).unload(function(){ - $(storage).cssRules().remove();//empty our rules bin - }); - -})( jQuery ); \ No newline at end of file +/*! + * jQuery.Rule - CSS Rules manipulation, the jQuery way. + * Copyright (c) 2007 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com + * Dual licensed under MIT and GPL. + * Date: 28/08/2019 + * + * @author Ariel Flesler + * @version 1.1.2 + * + * @id jQuery.rule + * @param {Undefined|String|jQuery.Rule} The rules, can be a selector, or literal CSS rules. Many can be given, comma separated. + * @param {Undefined|String|DOMElement|jQuery) The context stylesheets, all of them by default. + * @return {jQuery.Rule} Returns a jQuery.Rule object. + * + * @example $.rule('p,div').filter(function(){ return this.style.display != 'block'; }).remove(); + * + * @example $.rule('div{ padding:20px;background:#CCC}, p{ border:1px red solid; }').appendTo('style'); + * + * @example $.rule('div{}').append('margin:40px').css('margin-left',0).appendTo('link:eq(1)'); + * + * @example $.rule().not('div, p.magic').fadeOut('slow'); + * + * @example var text = $.rule('#screen h2').add('h4').end().eq(4).text(); + */ +;(function( $ ){ + + /** + * Notes + * Some styles and animations might fail, please report it. + * The plugin needs a style node to stay in the DOM all along to temporarily hold rules. DON'T TOUCH IT. + * Opera requires this style to have alternate in the rel to allow disabling it. + * Rules in IE don't have .parentStylesheet. We need to find it each time(slow). + * Animations need close attention. Programatically knowing which rule has precedence, would require a LOT of work. + * This plugin adds $.rule and also 4 methods to $.fn: ownerNode, sheet, cssRules and cssText + * Note that rules are not directly inside nodes, you need to do: $('style').sheet().cssRules(). + */ + + var storageNode = $('').appendTo('head')[0],//we must append to get a stylesheet + sheet = storageNode.sheet ? 'sheet' : 'styleSheet', + storage = storageNode[sheet],//css rules must remain in a stylesheet for IE and FF + rules = storage.rules ? 'rules' : 'cssRules', + remove = storage.deleteRule ? 'deleteRule' : 'removeRule', + owner = storage.ownerNode ? 'ownerNode' : 'owningElement', + reRule = /^([^{]+)\{([^}]*)\}/m, + reStyle = /([^:]+):([^;}]+)/; + + storage.disabled = true;//let's ignore your rules + + var $rule = $.rule = function( r, c ){ + if(!(this instanceof $rule)) + return new $rule( r, c ); + + this.sheets = $rule.sheets(c); + if( r && reRule.test(r) ) + r = $rule.clean( r ); + if( typeof r == 'object' && !r.exec ) { + setArray( this, r.get ? r.get() : r.splice ? r : [r] ); + } else { + setArray( this, this.sheets.cssRules().get() ); + if (r) + return this.filter( r ); + } + return this; + }; + + $.extend( $rule, { + sheets:function( c ){ + var o = c; + if( typeof o != 'object' ) + o = $.makeArray(document.styleSheets); + o = $(o).not(storage);//skip our stylesheet + if( typeof c == 'string' ) + o = o.ownerNode().filter(c).sheet(); + return o; + }, + rule:function( str ){ + if( str.selectorText )/* * */ + return [ '', str.selectorText, str.style.cssText ]; + return reRule.exec( str ); + }, + appendTo:function( r, ss, skip ){ + switch( typeof ss ){//find the desired stylesheet + case 'string': ss = this.sheets(ss); + case 'object': + if( ss[0] ) ss = ss[0]; + if( ss[sheet] ) ss = ss[sheet]; + if( rules in ss ) break;//only if the stylesheet is valid + default: + if( typeof r == 'object' ) return r;//let's not waist time, it is parsed + ss = storage; + } + var p; + if( !skip && (p = this.parent(r)) )//if this is an actual rule, and it's appended. + r = this.remove( r, p ); + + var rule = this.rule( r ); + if( ss.addRule ) + ss.addRule( rule[1], rule[2]||';' );//IE won't allow empty rules + else if( ss.insertRule ) + ss.insertRule( rule[1] + '{'+ rule[2] +'}', ss[rules].length ); + + return ss[rules][ ss[rules].length - 1 ];//return the added/parsed rule + }, + remove:function( r, p ){ + p = p || this.parent(r); + if( p != storage ){//let's save some unnecesary cycles. + var i = p ? $.inArray( r, p[rules] ) : -1; + if( i != -1 ){//if not stored before removal, IE will crash eventually, and some rules in FF get messed up + r = this.appendTo( r, 0 /*storage*/, true );//is faster and shorter to imply storage + p[remove](i); + } + } + return r; + }, + clean:function( r ){ + return $.map( r.split('}'), function( txt ){ + if( txt ) + return $rule.appendTo( txt + '}' /*, storage*/ );//parse the string, storage implied + }); + }, + parent:function( r ){//CSS rules in IE don't have parentStyleSheet attribute + if( typeof r == 'string' || r.parentStyleSheet !== undefined )//if it's a string, just return undefined. + return r.parentStyleSheet; + + var par; + this.sheets().each(function(){ + if( $.inArray(r, this[rules]) != -1 ){ + par = this; + return false; + } + }); + return par; + }, + outerText:function( rule ){ + return !rule || !rule.selectorText ? '' : [rule.selectorText+'{', '\t'+rule.style.cssText,'}'].join('\n').toLowerCase(); + }, + text:function( rule, txt ){ + if( txt !== undefined ) + rule.style.cssText = txt; + return !rule ? '' : rule.style.cssText.toLowerCase(); + } + }); + + $rule.fn = $rule.prototype = { + pushStack:function( rs, sh ){ + var ret = $rule( rs, sh || this.sheets ); + ret.prevObject = this; + return ret; + }, + end:function(){ + return this.prevObject || $rule(0,[]); + }, + filter:function( s ){ + var o; + if( !s ) s = /./;//just keep them all. + if( s.split ){ + o = $.trim(s).toLowerCase().split(/\s*,\s*/); + s = function(){ + var s = this.selectorText || ''; + return !!$.grep( s.toLowerCase().split(/\s*,\s*/), function( sel ){ + return $.inArray( sel, o ) != -1; + }).length; + }; + }else if( s.exec ){//string regex, or actual regex + o = s; + s = function(){ return o.test(this.selectorText); }; + } + return this.pushStack($.grep( this, function( e, i ){ + return s.call( e, i ); + })); + }, + add:function( rs, c ){ + return this.pushStack( $.merge(this.get(), $rule(rs, c)) ); + }, + is:function( s ){ + return !!(s && this.filter( s ).length); + }, + not:function( n, c ){ + n = $rule( n, c ); + return this.filter(function(){ + return $.inArray( this, n ) == -1; + }); + }, + append:function( s ){ + var rules = this, rule; + $.each( s.split(/\s*;\s*/),function(i,v){ + if(( rule = reStyle.exec( v ) )) + rules.css( rule[1], rule[2] ); + }); + return this; + }, + text:function( txt ){ + return !arguments.length ? $rule.text( this[0] ) + : this.each(function(){ $rule.text( this, txt ); }); + }, + outerText:function(){ + return $rule.outerText(this[0]); + } + }; + + $.each({ + ownerNode:owner,//when having the stylesheet, get the node that contains it + sheet:sheet, //get the stylesheet from the node + cssRules:rules //get the rules from the stylesheet. + },function( m, a ){ + var many = a == rules;//the rules need some more processing + $.fn[m] = function(){ + return this.map(function(){ + var prop; + try { + // In Chrome, if stylesheet originates from a different domain, + // ss.cssRules simply won't exist. I believe the same is true for IE, but + // I haven't tested it. + // + // In Firefox, if stylesheet originates from a different domain, trying + // to access ss.cssRules will throw a SecurityError. Hence, we must use + // try/catch to detect this condition in Firefox. + prop = this[a]; + } catch(e) { + // Rethrow exception if it's not a SecurityError. Note that SecurityError + // exception is specific to Firefox. + if(e.name !== 'SecurityError') + throw e; + prop = null; + } + return many ? $.makeArray(prop) : prop; + }); + }; + }); + + $.fn.cssText = function(){ + return this.filter('link,style').eq(0).sheet().cssRules().map(function(){ + return $rule.outerText(this); + }).get().join('\n'); + }; + + $.each('remove,appendTo,parent'.split(','),function( k, f ){ + $rule.fn[f] = function(){ + var args = $.makeArray(arguments), that = this; + args.unshift(0); + return this.each(function( i ){ + args[0] = this; + that[i] = $rule[f].apply( $rule, args ) || that[i]; + }); + }; + }); + + $.each(('each,index,get,size,eq,slice,map,attr,andSelf,css,show,hide,toggle,'+ + 'queue,dequeue,stop,animate,fadeIn,fadeOut,fadeTo').split(','),function( k, f ){ + $rule.fn[f] = $.fn[f]; + }); + + // this function has been pulled in from jQuery 1.4.1, because it is an internal function and has been dropped as of 1.4.2 + function setArray(rule, elems) { + rule.length = 0; + Array.prototype.push.apply( rule, elems ); + } + + var curCSS = $.curCSS; + $.curCSS = function( e, a ){//this hack is still quite exprimental + return ('selectorText' in e ) ? + e.style[a] || $.prop( e, a=='opacity'? 1 : 0,'curCSS', 0, a )//TODO: improve these defaults + : curCSS.apply(this,arguments); + }; + + /** + * Time to hack jQuery.data for animations. + * Only IE really needs this, but to keep the behavior consistent, I'll hack it for all browsers. + * TODO: This kind of id doesn't seem to be good enough + * TODO: Avoid animating similar rules simultaneously + * TODO: Avoid rules' precedence from interfering on animations ? + */ + $rule.cache = {}; + var mediator = function( original ){ + return function( elm ){ + var id = elm.selectorText; + if( id ) + arguments[0] = $rule.cache[id] = $rule.cache[id] || {}; + return original.apply( $, arguments ); + }; + }; + $.data = mediator( $.data ); + $.removeData = mediator( $.removeData ); + + $(window).on("unload", function () { + $(storage).cssRules().remove();//empty our rules bin + }); + +})( jQuery ); diff --git a/package.json b/package.json new file mode 100644 index 0000000..cebf773 --- /dev/null +++ b/package.json @@ -0,0 +1,24 @@ +{ + "name": "jquery.rule", + "version": "1.1.2", + "description": "CSS Rules manipulation, the jQuery way", + "main": "jquery.rule.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/flesler/jquery.rule.git" + }, + "keywords": [ + "jquery", + "css", + "rules" + ], + "author": "Ariel Flesler", + "license": "MIT", + "bugs": { + "url": "https://github.com/flesler/jquery.rule/issues" + }, + "homepage": "https://github.com/flesler/jquery.rule#readme" +}