define([ "dojo/_base/window", "dojo/_base/array", "dojo/has" ], function(win, arr, has){ // caches for capitalized names and hypen names var cnames = [], hnames = []; // element style used for feature testing var style = win.doc.createElement("div").style; // We just test webkit prefix for now since our themes only have standard and webkit // (see dojox/mobile/themes/common/css3.less) // More prefixes can be added if/when we add them to css3.less. var prefixes = ["webkit"]; // Does the browser support CSS3 animations? has.add("css3-animations", function(global, document, element){ var style = element.style; return (style["animation"] !== undefined && style["transition"] !== undefined) || arr.some(prefixes, function(p){ return style[p+"Animation"] !== undefined && style[p+"Transition"] !== undefined; }); }); // Indicates whether style 'transition' returns empty string instead of // undefined, although TransitionEvent is not supported. // Reported on Android 4.1.x on some devices: https://bugs.dojotoolkit.org/ticket/17164 has.add("t17164", function(global, document, element){ return (element.style["transition"] !== undefined) && !('TransitionEvent' in window); }); var css3 = { // summary: // This module provide some cross-browser support for CSS3 properties. name: function(/*String*/p, /*Boolean?*/hyphen){ // summary: // Returns the name of a CSS3 property with the correct prefix depending on the browser. // p: // The (non-prefixed) property name. The property name is assumed to be consistent with // the hyphen argument, for example "transition-property" if hyphen is true, or "transitionProperty" // if hyphen is false. If the browser supports the non-prefixed property, the property name will be // returned unchanged. // hyphen: // Optional, true if hyphen notation should be used (for example "transition-property" or "-webkit-transition-property"), // false for camel-case notation (for example "transitionProperty" or "webkitTransitionProperty"). var n = (hyphen?hnames:cnames)[p]; if(!n){ if(/End|Start/.test(p)){ // event names: no good way to feature-detect, so we // assume they have the same prefix as the corresponding style property var idx = p.length - (p.match(/End/) ? 3 : 5); var s = p.substr(0, idx); var pp = this.name(s); if(pp == s){ // no prefix, standard event names are all lowercase n = p.toLowerCase(); }else{ // prefix, e.g. webkitTransitionEnd (camel case) n = pp + p.substr(idx); } }else if(p == "keyframes"){ // special case for keyframes, we also rely on consistency between 'animation' and 'keyframes' var pk = this.name("animation", hyphen); if(pk == "animation"){ n = p; }else if(hyphen){ n = pk.replace(/animation/, "keyframes"); }else{ n = pk.replace(/Animation/, "Keyframes"); } }else{ // convert name to camel-case for feature test var cn = hyphen ? p.replace(/-(.)/g, function(match, p1){ return p1.toUpperCase(); }) : p; if(style[cn] !== undefined && !has('t17164')){ // standard non-prefixed property is supported n = p; }else{ // try prefixed versions cn = cn.charAt(0).toUpperCase() + cn.slice(1); arr.some(prefixes, function(prefix){ if(style[prefix+cn] !== undefined){ if(hyphen){ n = "-" + prefix + "-" + p; }else{ n = prefix + cn; } } }); } } if(!n){ // The property is not supported, just return it unchanged, it will be ignored. n = p; } (hyphen?hnames:cnames)[p] = n; } return n; }, add: function(/*Object*/styles, /*Object*/css3Styles){ // summary: // Prefixes all property names in "css3Styles" and adds the prefixed properties in "styles". // Used as a convenience when an object is passed to domStyle.set to set multiple styles. // example: // domStyle.set(bar, css3.add({ // opacity: 0.6, // position: "absolute", // backgroundColor: "#606060" // }, { // borderRadius: "2px", // transformOrigin: "0 0" // })); // returns: // The "styles" argument where the CSS3 styles have been added. for(var p in css3Styles){ if(css3Styles.hasOwnProperty(p)){ styles[css3.name(p)] = css3Styles[p]; } } return styles; } }; return css3; });