|
//!\\ Please do not use eval in your everyday production code. And create DOM elements as less times as it possible. |
|
|
|
/* vendorPrefixed */ |
|
function(s){ |
|
return eval( |
|
// Constructing the string: |
|
|
|
// Appending zero at the start, it is needed for correct syntax |
|
0 + |
|
// List of vendor prefixes. dash alone is enough to be a separator |
|
"O-Moz-Webkit-Ms-" |
|
// modifying it |
|
.replace( |
|
// Get anything until dash (ungreedy) or empty line at the end |
|
// so the replacement chunks are: <O-><Moz-><Webkit-><Ms-><> |
|
/.*?-|$/g, |
|
// Do inline replacement. "$&" is the captured string |
|
// Explaination of this mash goes further |
|
"||(s='$&"+s+"')in new Image().style&&s" |
|
) |
|
// Property names are still in dashed-css-notation and we need camelCase |
|
// Replacing all "{dash} + {any char}" into "{any char}.toUpperCase()" |
|
// There is no dashes in the generated code, so we can freely replace all. |
|
.replace( |
|
/-(.)/g, |
|
// $1 is the 1st captured parens |
|
"'+'$1'.toUpperCase()+'" |
|
) |
|
// Here we got the string ready to be evaluated |
|
) |
|
// eval() the string and return what eval returned |
|
} |
|
// If s contained a single quote, we have syntax error here. |
|
// But in real life if you need css property with quote inside, you're doing something wrong. |
|
|
|
|
|
/** END OF FILE *********************************/ |
|
|
|
/** Comments: The generated string: *************/ |
|
/* Let variable s = "transform-origin" */ |
|
/* Indented in order to be clear */ |
|
|
|
// The syntax-correction zero. This will affect nothing as it is always false */ |
|
0 || |
|
|
|
// Here we evaluating the .toUpperCase's inserted by original code */ |
|
// Only if 'string'.replace(/regexp/, ''.toUpperCase.call) worked, I shouldn't do this evil eval tricks */ |
|
(s = 'O' + 't'.toUpperCase() + 'ransform' + 'o'.toUpperCase() + 'rigin') in new Image().style && s || |
|
// After toUpperCase worked we have: |
|
//>>> (s = "OTransformOrigin") in new Image().style && s || |
|
// Assigning string to variable s. |
|
// It is already defined in function's scope as an argument, so we do not pollute the outer scope |
|
//>>> s in new Image().style && s || |
|
// new Image() is like document.createElement("img") but much shorter |
|
// So we create a new, fresh and unpolluted DOM element. And right after that getting its .style |
|
//>>> s in [[style]] && s |
|
// If s is defined in style, we get true. s is always true |
|
// So if there's no such property, we get false and go to next statement after || |
|
// But if there is such prop, the following OR's are not evaluated |
|
// And the last encountered expression is |
|
//>>> s |
|
// So eval returns first property name that exists |
|
|
|
/* Same again */ |
|
(s = 'Moz' + 't'.toUpperCase() + 'ransform' + 'o'.toUpperCase() + 'rigin') in new Image().style && s || |
|
/* and again */ |
|
(s = 'Webkit'+'t'.toUpperCase() + 'ransform' + 'o'.toUpperCase() + 'rigin') in new Image().style && s || |
|
/* and even ms- */ |
|
(s = 'Ms' + 't'.toUpperCase() + 'ransform' + 'o'.toUpperCase() + 'rigin') in new Image().style && s || |
|
/* and finally without any vendor prefixes */ |
|
(s = 'transform' + 'o'.toUpperCase() + 'rigin') in new Image().style && s |
|
|
|
/* And here it ends. If nothing matched, return false */ |
What about this? It should be faster as it doesn't require
eval
.function f(a,b,c,d){for(d?d=b.toUpperCase():b=4;!d&&b--;d=(d=d.replace(/-(.)/g,f))in(new Image).style&&d)d=[['Moz-','Webkit-','Ms-','O-'][b]]+a;return d}