Skip to content

Commit 0d8b76d

Browse files
committed
Merge pull request openlayers#546 from finn-no/vendor-prefixes
Vendor prefix detection. Thanks @gregersrygg for this excellent contribution.
2 parents 0834593 + 2bd8b5c commit 0d8b76d

File tree

7 files changed

+260
-12
lines changed

7 files changed

+260
-12
lines changed

lib/OpenLayers.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@
132132
jsFiles = [
133133
"OpenLayers/BaseTypes/Class.js",
134134
"OpenLayers/Util.js",
135+
"OpenLayers/Util/vendorPrefix.js",
135136
"OpenLayers/Animation.js",
136137
"OpenLayers/BaseTypes.js",
137138
"OpenLayers/BaseTypes/Bounds.js",

lib/OpenLayers/Animation.js

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* full text of the license.
66
*
77
* @requires OpenLayers/SingleFile.js
8+
* @requires OpenLayers/Util/vendorPrefix.js
89
*/
910

1011
/**
@@ -19,11 +20,8 @@ OpenLayers.Animation = (function(window) {
1920
* Property: isNative
2021
* {Boolean} true if a native requestAnimationFrame function is available
2122
*/
22-
var isNative = !!(window.requestAnimationFrame ||
23-
window.webkitRequestAnimationFrame ||
24-
window.mozRequestAnimationFrame ||
25-
window.oRequestAnimationFrame ||
26-
window.msRequestAnimationFrame);
23+
var requestAnimationFrame = OpenLayers.Util.vendorPrefix.js(window, "requestAnimationFrame");
24+
var isNative = !!(requestAnimationFrame);
2725

2826
/**
2927
* Function: requestFrame
@@ -36,11 +34,7 @@ OpenLayers.Animation = (function(window) {
3634
* element - {DOMElement} Optional element that visually bounds the animation.
3735
*/
3836
var requestFrame = (function() {
39-
var request = window.requestAnimationFrame ||
40-
window.webkitRequestAnimationFrame ||
41-
window.mozRequestAnimationFrame ||
42-
window.oRequestAnimationFrame ||
43-
window.msRequestAnimationFrame ||
37+
var request = window[requestAnimationFrame] ||
4438
function(callback, element) {
4539
window.setTimeout(callback, 16);
4640
};

lib/OpenLayers/Control/PinchZoom.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
* full text of the license. */
55

66
/**
7+
* @requires OpenLayers/Util/vendorPrefix.js
78
* @requires OpenLayers/Handler/Pinch.js
89
*/
910

@@ -162,8 +163,10 @@ OpenLayers.Control.PinchZoom = OpenLayers.Class(OpenLayers.Control, {
162163
*/
163164
applyTransform: function(transform) {
164165
var style = this.map.layerContainerDiv.style;
165-
style['-webkit-transform'] = transform;
166-
style['-moz-transform'] = transform;
166+
var transformProperty = OpenLayers.Util.vendorPrefix.style("transform");
167+
if (transformProperty) {
168+
style[transformProperty] = transform;
169+
}
167170
},
168171

169172
/**

lib/OpenLayers/Util/vendorPrefix.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/**
2+
* Copyright (c) 2006-2012 by OpenLayers Contributors (see authors.txt for
3+
* full list of contributors). Published under the 2-clause BSD license.
4+
* See license.txt in the OpenLayers distribution or repository for the
5+
* full text of the license.
6+
*
7+
* @requires OpenLayers/SingleFile.js
8+
*/
9+
10+
OpenLayers.Util = OpenLayers.Util || {};
11+
/**
12+
* Namespace: OpenLayers.Util.vendorPrefix
13+
* A collection of utility functions to detect vendor prefixed features
14+
*/
15+
OpenLayers.Util.vendorPrefix = (function() {
16+
"use strict";
17+
18+
var VENDOR_PREFIXES = ["", "O", "ms", "Moz", "Webkit"],
19+
divStyle = document.createElement("div").style,
20+
cssCache = {},
21+
jsCache = {};
22+
23+
24+
/**
25+
* Function: domToCss
26+
* Converts a upper camel case DOM style property name to a CSS property
27+
* i.e. transformOrigin -> transform-origin
28+
* or WebkitTransformOrigin -> -webkit-transform-origin
29+
*
30+
* Parameters:
31+
* prefixedDom - {String} The property to convert
32+
*
33+
* Returns:
34+
* {String} The CSS property
35+
*/
36+
function domToCss(prefixedDom) {
37+
if (!prefixedDom) { return null; }
38+
return prefixedDom.
39+
replace(/([A-Z])/g, function(c) { return "-" + c.toLowerCase(); }).
40+
replace(/^ms-/, "-ms-");
41+
}
42+
43+
/**
44+
* APIMethod: css
45+
* Detect which property is used for a CSS property
46+
*
47+
* Parameters:
48+
* property - {String} The standard (unprefixed) CSS property name
49+
*
50+
* Returns:
51+
* {String} The standard CSS property, prefixed property or null if not
52+
* supported
53+
*/
54+
function css(property) {
55+
if (cssCache[property] === undefined) {
56+
var domProperty = property.
57+
replace(/(-[\s\S])/g, function(c) { return c.charAt(1).toUpperCase(); });
58+
var prefixedDom = style(domProperty);
59+
cssCache[property] = domToCss(prefixedDom);
60+
}
61+
return cssCache[property];
62+
}
63+
64+
/**
65+
* APIMethod: js
66+
* Detect which property is used for a JS property/method
67+
*
68+
* Parameters:
69+
* obj - {Object} The object to test on
70+
* property - {String} The standard (unprefixed) JS property name
71+
*
72+
* Returns:
73+
* {String} The standard JS property, prefixed property or null if not
74+
* supported
75+
*/
76+
function js(obj, property) {
77+
if (jsCache[property] === undefined) {
78+
var tmpProp,
79+
i = 0,
80+
l = VENDOR_PREFIXES.length,
81+
prefix,
82+
isStyleObj = (typeof obj.cssText !== "undefined");
83+
84+
jsCache[property] = null;
85+
for(; i<l; i++) {
86+
prefix = VENDOR_PREFIXES[i];
87+
if(prefix) {
88+
if (!isStyleObj) {
89+
// js prefix should be lower-case, while style
90+
// properties have upper case on first character
91+
prefix = prefix.toLowerCase();
92+
}
93+
tmpProp = prefix + property.charAt(0).toUpperCase() + property.slice(1);
94+
} else {
95+
tmpProp = property;
96+
}
97+
98+
if(obj[tmpProp] !== undefined) {
99+
jsCache[property] = tmpProp;
100+
break;
101+
}
102+
}
103+
}
104+
return jsCache[property];
105+
}
106+
107+
/**
108+
* APIMethod: style
109+
* Detect which property is used for a DOM style property
110+
*
111+
* Parameters:
112+
* property - {String} The standard (unprefixed) style property name
113+
*
114+
* Returns:
115+
* {String} The standard style property, prefixed property or null if not
116+
* supported
117+
*/
118+
function style(property) {
119+
return js(divStyle, property);
120+
}
121+
122+
return {
123+
css: css,
124+
js: js,
125+
style: style,
126+
127+
// used for testing
128+
cssCache: cssCache,
129+
jsCache: jsCache
130+
};
131+
}());

tests/Animation.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
// dependencies for tests
88
var OpenLayers = [
9+
"OpenLayers/Util/vendorPrefix.js",
910
"OpenLayers/Animation.js"
1011
];
1112

tests/Util/vendorPrefix.html

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>vendorPrefix.js Tests</title>
5+
<script>
6+
var div = document.createElement("div");
7+
var style = div.style,
8+
orgCreateElement = document.createElement;
9+
10+
// wrap document.createElement to control property values
11+
document.createElement = function(type) {
12+
return div;
13+
};
14+
15+
// dependencies for tests
16+
var OpenLayers = [
17+
"OpenLayers/Util/vendorPrefix.js"
18+
];
19+
20+
</script>
21+
<script src="../OLLoader.js"></script>
22+
23+
<script>
24+
25+
/**
26+
* Test vendor prefixing
27+
*/
28+
function test_vendor_prefixes(t) {
29+
t.plan(20);
30+
var err;
31+
32+
function clearCache(type) {
33+
var cache = OpenLayers.Util.vendorPrefix[type.replace("style", "js") + "Cache"];
34+
for (var key in cache) {
35+
delete cache[key];
36+
}
37+
}
38+
39+
function setStyleMockProp(prop, value) {
40+
if (prop && value === undefined) {
41+
delete style[prop];
42+
} else if (prop) {
43+
style[prop] = value;
44+
}
45+
}
46+
47+
function curryTestPrefix(type) {
48+
return function(standardProp, expectedPrefix, msg) {
49+
var prefixedProp, err;
50+
try {
51+
clearCache(type);
52+
setStyleMockProp(expectedPrefix, "");
53+
prefixedProp = OpenLayers.Util.vendorPrefix[type](standardProp);
54+
} catch(e) {
55+
err = e;
56+
} finally {
57+
setStyleMockProp(expectedPrefix, undefined);
58+
}
59+
60+
if(!err) {
61+
t.eq(prefixedProp, expectedPrefix, msg);
62+
} else {
63+
t.fail("Error when testing " + type.toUpperCase() + " vendor prefix: " + err.message);
64+
}
65+
};
66+
}
67+
var testDomPrefix = curryTestPrefix("style"),
68+
testCssPrefix = curryTestPrefix("css");
69+
70+
testDomPrefix("unsupported", null, "DOM vendor prefix - unsupported");
71+
testCssPrefix("unsupported", null, "CSS vendor prefix - unsupported");
72+
73+
testDomPrefix("test", "test", "DOM vendor prefix - single word");
74+
testCssPrefix("test", "test", "CSS vendor prefix - single word");
75+
76+
testDomPrefix("testMultiWord", "testMultiWord", "DOM vendor prefix - multiple words");
77+
testCssPrefix("test-multi-word", "test-multi-word", "CSS vendor prefix - multiple words");
78+
79+
testDomPrefix("multiWord", "WebkitMultiWord", "DOM vendor prefix - multiple words for WebKit");
80+
testCssPrefix("multi-word", "-webkit-multi-word", "CSS vendor prefix - multiple words for WebKit");
81+
82+
testDomPrefix("multiWord", "MozMultiWord", "DOM vendor prefix - multiple words for Mozilla");
83+
testCssPrefix("multi-word", "-moz-multi-word", "CSS vendor prefix - multiple words for Mozilla");
84+
85+
testDomPrefix("multiWord", "OMultiWord", "DOM vendor prefix - multiple words for Opera");
86+
testCssPrefix("multi-word", "-o-multi-word", "CSS vendor prefix - multiple words for Opera");
87+
88+
testDomPrefix("multiWord", "msMultiWord", "DOM vendor prefix - multiple words for Internet Explorer");
89+
testCssPrefix("multi-word", "-ms-multi-word", "CSS vendor prefix - multiple words for Internet Explorer");
90+
91+
// test vendor prefix on object
92+
clearCache("js");
93+
t.eq( OpenLayers.Util.vendorPrefix.js( {}, "unsupported" ), null, "Standard object property - unsupported");
94+
95+
clearCache("js");
96+
t.eq( OpenLayers.Util.vendorPrefix.js( { "test": true }, "test" ), "test", "Standard object property");
97+
98+
clearCache("js");
99+
t.eq( OpenLayers.Util.vendorPrefix.js( { "oTest": true }, "test" ), "oTest", "Standard object property");
100+
101+
clearCache("js");
102+
t.eq( OpenLayers.Util.vendorPrefix.js( { "msTest": true }, "test" ), "msTest", "Standard object property");
103+
104+
clearCache("js");
105+
t.eq( OpenLayers.Util.vendorPrefix.js( { "mozTest": true }, "test" ), "mozTest", "Standard object property");
106+
107+
clearCache("js");
108+
t.eq( OpenLayers.Util.vendorPrefix.js( { "webkitTest": true }, "test" ), "webkitTest", "Standard object property");
109+
110+
// unwrap document.createElement
111+
document.createElement = orgCreateElement;
112+
}
113+
114+
</script>
115+
</head>
116+
<body></body>
117+
</html>

tests/list-tests.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@
231231
<li>Tween.html</li>
232232
<li>Kinetic.html</li>
233233
<li>Util.html</li>
234+
<li>Util/vendorPrefix.html</li>
234235
<li>deprecated/Ajax.html</li>
235236
<li>deprecated/Util.html</li>
236237
<li>deprecated/BaseTypes/Class.html</li>

0 commit comments

Comments
 (0)