Piet Piet - 6 months ago 15
jQuery Question

Javascript not compatible with jQuery v1.11 or below

I want to write a small script to invert black and white colors on a certain area of a page. I used an inverting script that I found on another thread and adjusted it to only invert black and white and only on a certain area of the page: http://jsfiddle.net/yQe9t/87/

This works fine on jQuery 1.12.1 and above but Ive noticed that some of the pages that Im working with they still use jQuery 1.9 and for some reason the script does not work properly on there; http://jsfiddle.net/yQe9t/88/ (jquery 1.9 here). I'm unable to change the jQuery version used on those pages so I need to make it compatible with that.

Can someone please help me figure out how to make my code work on older versions as well? I'd like it to work on new and old but dont know enough about Javascript myself to fix it.

My complete Javascript:

$(".invertAll").click (function () {
var Body = $(".unit.size-col-d.width610");
invertElementColors ( $(Body) );
} );

function rgb2hex(rgb){
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return (rgb && rgb.length === 4) ? "#" +
("0" + parseInt(rgb[1],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[2],10).toString(16)).slice(-2) +
("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : '';
}

function invertElementColors (jNode)
{
jNode.children().each(function () {
invertElementColors ( $(this) );
});

jNode.css ( {
'color' : function (J, oldColor) {
return invertRGB_ColorStr (oldColor);
},
'background-color' : function (J, oldColor) {
return invertRGB_ColorStr (oldColor);
}
} );
}

function invertRGB_ColorStr (oldColorStr)
{

// convert color rgb to hex code so we can easily detect colors
var help = oldColorStr;
var colorHex = rgb2hex(help);

// only convert black and white
if ((colorHex == '#000000') || (colorHex == '#ffffff')) {
//--- Special case
if (oldColorStr == 'transparent') oldColorStr = 'rgb(255, 255, 255)';

//--- Color is text in RGB format. EG: rgb(1, 22, 255)
var colorArray = oldColorStr.match (/\((\d+),\s?(\d+),\s?(\d+)\)/);

var newColorStr = $.map (colorArray, function (byte, J)
{
if (!J) return null;

//--- Invert a decimal byte.
return Math.abs (255 - parseInt (byte) );
}
).join (',');

return 'rgb(' + newColorStr + ')';
} else {
return oldColorStr;
}
}

Answer

The source for map in the two jQuery version is different.

One is checking if the value your mapping over is array like before trying to access the property .length.

map: function( elems, callback, arg ) {
        var length, value,
            i = 0,
            ret = [];

        // Go through the array, translating each of the items to their new values
        if ( isArrayLike( elems ) ) {
            length = elems.length;

The failing does not:

map: function( elems, callback, arg ) {
        var value,
            i = 0,
            length = elems.length,
            isArray = isArraylike( elems ),
            ret = [];

So when your regex fails, you pass map null accessing property .length of null throws an exception.

So solution if you cannot upgrade jQuery your self, only pass a value into map if oldColorStr.match (/\((\d+),\s?(\d+),\s?(\d+)\)/); doesn't return null. That will stop the exception.

Working fiddle

Comments