📜 ⬆️ ⬇️

cssHooks - extend many CSS properties

In this article I will talk about the jQuery.cssHooks object, which by default is contained in jQuery. The extension of this object allows you to add new properties or values ​​that are written in the .css () method that are not initially supported by any particular browser. Perhaps for many, the presence of CSS hooks is not news, but for me it was a small discovery.
For those who are too lazy to read further, I cite the main idea. Suppose you want to add the chuck-norris CSS property to jQuery:
$.cssHooks.chuckNorris = { get: function(elem) { //    elem,  value return value; }, set: function(elem, value) { //    elem,  value } } $(el).css('chuck-norris', Infinity); // $(el).css({'chuck-norris': Infinity}); alert($(el).css('chuck-norris')); //Infinity 


Next will be described in detail the "modification" of the background-color property to support rgba in older versions of IE and the addition of a new, non-existent in the specification background-alpha property for easy setting of the background color transparency. In IE, color transparency will be implemented by using the filter property, adding a gradient element consisting of two identical colors to the element.

This method has two drawbacks.

Firstly, the gradients do not work for blocks with auto width, for this you have to use the hack:
 $('div').width('100%'); 

Secondly, filters act on background images. Instead of the expected (the first picture) in the old versions of the donkey, you will get this (the second picture).

')
First we need a function (parseColor) that will parse the color in different formats and return the object {r, g, b, a}. The following options are taken into account:

The code of this parser (which will be out of place due to the size) and, in fact, the idea is partially partial from here .

The second step is to create a Color class that accepts an html node as an input and contains a number of functions that will be needed later.
 var Color = function(el){ //     : //   IE8-,      ,     var ieDetect = (function(){ var ua = navigator.userAgent; var result = {} result.isOldIe = ~ua.indexOf('MSIE 6') || ~ua.indexOf('MSIE 7') || ~ua.indexOf('MSIE 8'); result.hasGradient = result.isOldIe && ~el.style.filter.toLowerCase().indexOf('gradient'); result.isGradientEnabled = result.hasGradient && !!el.filters.item("DXImageTransform.Microsoft.gradient").enabled; return result; })(); //          var colorToHex = function (objColor) { var hex = {}; for (var i in objColor) { hex[i] = objColor[i]; if (i==='a') { hex.a = Math.round(hex.a*255); } hex[i] = hex[i].toString(16); // '0',        hex[i] = hex[i].length == 2 ? hex[i] : '0' + hex[i]; } return hex; } //  {r,g,b,a}      var colorToString = function(objColor, format) { var hexColor = colorToHex(objColor); switch(format) { case 'rgb': return 'rgb(' + objColor.r + ',' + objColor.g + ',' + objColor.b + ')'; case 'rgba': return 'rgba(' + objColor.r + ',' + objColor.g + ',' + objColor.b +',' + objColor.a + ')'; case '#6': return '#' + hexColor.r + hexColor.g + hexColor.b; case '#8': return '#' + hexColor.a + hexColor.r + hexColor.g + hexColor.b; } } //      var convertColor = function(color, format) { var colorObj = parseColor(color); return colorToString(colorObj, format) } //  getComputedStyle    //  ,  if (!window.getComputedStyle) { window.getComputedStyle = function(el, pseudo) { this.el = el; this.getPropertyValue = function(prop) { var re = /(\-([az]){1})/g; if (re.test(prop)) { prop = prop.replace(re, function () { return arguments[2].toUpperCase(); }); } return el.currentStyle[prop] ? el.currentStyle[prop] : null; } return this; } } ... 


We now turn to the actual setting of the color value. I hope the reader will not be hard to understand the code, despite its nesting.
 this.setBackgroundColor = function(color) { var newColor, newColorObj = parseColor(color); if(ieDetect.isOldIe) { //  IE if(newColorObj.a < 1) { //     el.style.backgroundColor = 'transparent'; newColor = colorToString(newColorObj, '#8'); if(ieDetect.hasGradient) { //     el.filters.item("DXImageTransform.Microsoft.gradient").enabled = true; el.filters.item("DXImageTransform.Microsoft.gradient").startColorstr = newColor; el.filters.item("DXImageTransform.Microsoft.gradient").endColorstr = newColor; } else { //     el.style.filter += "progid:DXImageTransform.Microsoft.gradient(enabled='true', startColorstr=" + newColor + ", endColorstr=" + newColor + ")"; } } else { //     newColor = colorToString(newColorObj, '#6'); if(ieDetect.hasGradient) { //     el.filters.item("DXImageTransform.Microsoft.gradient").enabled = false; el.style.backgroundColor = newColor; } else { //     el.style.backgroundColor = newColor; } } } else { //   IE if(newColorObj.a < 1) { //     newColor = colorToString(newColorObj, 'rgba'); el.style.backgroundColor = newColor; } else { //     newColor = colorToString(newColorObj, '#6'); el.style.backgroundColor = newColor; } } } 


The next part of the code is responsible for getting the color value. Here is much easier.
 this.getBackgroundColor = function() { var color; if(ieDetect.isGradientEnabled) { //  IE    color = el.filters.item("DXImageTransform.Microsoft.gradient").startColorstr; return convertColor(color, 'rgba'); } else { //  : http://snipplr.com/view/13523/getcomputedstyle-for-ie/ //      $(el).css('background-color'); //    ,     color = el.style.BackgroundColor || window.getComputedStyle(el,null).getPropertyValue('background-color'); return color; } } 


Now the main part. Add backgroundColor hook.
 $.cssHooks.backgroundColor = { get: function(elem) { var color = new Color(elem); return color.getBackgroundColor(); }, set: function( elem, value ) { var color = new Color(elem); color.setBackgroundColor(value); } } 


Add backgroundAlpha Hook
 $.cssHooks.backgroundAlpha = { get: function(elem) { var color = new Color(elem); var colorStr = color.getBackgroundColor(); var colorObj = parseColor(colorStr); return colorObj.a; }, set: function(elem, value) { var color = new Color(elem); var colorStr = color.getBackgroundColor(); var colorObj = parseColor(colorStr); //    ,  jQuery  'px';  colorObj.a = String(value).replace('px', ''); color.setBackgroundColor('rgba('+ colorObj.r+','+colorObj.g+','+colorObj.b+','+colorObj.a+')'); } } 


Everything is done, now you can use.
 p{background-color: #991111; ...} div{background: url(...) ...} 

 <div> <p>...</p> <p>...</p> </div> 

 $('p').width('100%'); $('p:eq(0)').css({'background-color':'rgba(0,111,221,0.9)'}); $('p:eq(1)').css('background-alpha', 0.5); 


As we can see, for objects with names in the “camel case” style, jQuery automatically adds support for the “hyphenated” style.

Conclusion

If you want to add support for some property that is not supported (or partially supported) by these or other browsers, then you should forget that this can be done by creating a plugin and, instead, use $ .cssHooks.

References:
The final version: finom.ho.ua/bgalpha
The hook code from the article: finom.ho.ua/bgalpha/background-rgba.csshook.jquery.js
cssHooks in alternative documentation: jqapi.com/#p=jQuery.cssHooks

Source: https://habr.com/ru/post/123241/


All Articles