style.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. define("dojox/html/ext-dojo/style", ["dojo/_base/kernel", "dojo/dom-style", "dojo/_base/lang", "dojo/_base/html", "dojo/_base/sniff",
  2. "dojo/_base/window", "dojo/dom", "dojo/dom-construct", "dojo/dom-style", "dojo/dom-attr"],
  3. function(kernel, domStyle, lang, Html, has, win, DOM, DOMConstruct, DOMStyle, DOMAttr){
  4. kernel.experimental("dojox.html.ext-dojo.style");
  5. var st = lang.getObject("dojox.html.ext-dojo.style", true);
  6. var HtmlX = lang.getObject("dojox.html");
  7. // summary: Extensions to dojo.style adding the css3 "transform" and "transform-origin" properties on IE5.5+
  8. // description:
  9. // A Package to extend the dojo.style function
  10. // Supported transformation functions:
  11. // matrix, translate, translateX, translateY, scale, scaleX, scaleY, rotate, skewX, skewY, skew
  12. lang.mixin(HtmlX["ext-dojo"].style, {
  13. supportsTransform: true,
  14. _toPx: function(measure){
  15. var ds = Html.style, _conversion = this._conversion;
  16. if(typeof measure === "number"){
  17. return measure + "px";
  18. }else if(measure.toLowerCase().indexOf("px") != -1){
  19. return measure;
  20. }
  21. // "native" conversion in px
  22. !_conversion.parentNode && DOMConstruct.place(_conversion, win.body());
  23. ds(_conversion, "margin", measure);
  24. return ds(_conversion, "margin");
  25. },
  26. init: function(){
  27. var docStyle = win.doc.documentElement.style, extStyle = HtmlX["ext-dojo"].style,
  28. sget = DOMStyle.get, sset = DOMStyle.set;
  29. DOMStyle.get = function(/*DOMNode|String*/ node, /*String|Object*/ name){
  30. var tr = (name == "transform"),
  31. to = (name == "transformOrigin");
  32. if(tr){
  33. return extStyle.getTransform(node);
  34. }else if(to){
  35. return extStyle.getTransformOrigin(node);
  36. }else{
  37. return sget.apply(this, arguments);
  38. }
  39. };
  40. DOMStyle.set = function(/*DOMNode|String*/ node, /*String|Object*/ name, /*String?*/ value){
  41. var tr = (name == "transform"),
  42. to = (name == "transformOrigin"),
  43. n = DOM.byId(node)
  44. ;
  45. if(tr){
  46. return extStyle.setTransform(n, value, true);
  47. }else if(to){
  48. return extStyle.setTransformOrigin(n, value);
  49. }else{
  50. return sset.apply(this, arguments);
  51. }
  52. };
  53. // prefixes and property names
  54. for(var i = 0, tPrefix = ["WebkitT", "MozT", "OT", "msT", "t"]; i < tPrefix.length; i++){
  55. if(typeof docStyle[tPrefix[i] + "ransform"] !== "undefined"){
  56. this.tPropertyName = tPrefix[i] + "ransform";
  57. }
  58. if(typeof docStyle[tPrefix[i] + "ransformOrigin"] !== "undefined"){
  59. this.toPropertyName = tPrefix[i] + "ransformOrigin";
  60. }
  61. }
  62. if(this.tPropertyName){
  63. this.setTransform = function(/*DomNode*/node, /*String*/ transform){
  64. return DOMStyle.set(node, this.tPropertyName, transform);
  65. };
  66. this.getTransform = function(/*DomNode*/node){
  67. return DOMStyle.get(node, this.tPropertyName);
  68. };
  69. }else if(has("ie")){
  70. this.setTransform = this._setTransformFilter;
  71. this.getTransform = this._getTransformFilter;
  72. }
  73. if(this.toPropertyName){
  74. this.setTransformOrigin = function(/*DomNode*/node, /*String*/ transformOrigin){
  75. return sset(node, this.toPropertyName, transformOrigin);
  76. };
  77. this.getTransformOrigin = function(/*DomNode*/node){
  78. return sget(node, this.toPropertyName);
  79. };
  80. }else if(has("ie")){
  81. this.setTransformOrigin = this._setTransformOriginFilter;
  82. this.getTransformOrigin = this._getTransformOriginFilter;
  83. }else{
  84. this.supportsTransform = false;
  85. }
  86. this._conversion = DOMConstruct.create("div", {
  87. style: {
  88. position: "absolute",
  89. top: "-100px",
  90. left: "-100px",
  91. fontSize: 0,
  92. width: "0",
  93. backgroundPosition: "50% 50%"
  94. }
  95. });
  96. },
  97. _notSupported: function(){
  98. console.warn("Sorry, this browser doesn't support transform and transform-origin");
  99. },
  100. _setTransformOriginFilter: function(/*DomNode*/ node, /*String*/ transformOrigin){
  101. var to = lang.trim(transformOrigin)
  102. .replace(" top", " 0")
  103. .replace("left ", "0 ")
  104. .replace(" center", "50%")
  105. .replace("center ", "50% ")
  106. .replace(" bottom", " 100%")
  107. .replace("right ", "100% ")
  108. .replace(/\s+/, " "),
  109. toAry = to.split(" "),
  110. n = DOM.byId(node),
  111. t = this.getTransform(n),
  112. validOrigin = true
  113. ;
  114. for(var i = 0; i < toAry.length; i++){
  115. validOrigin = validOrigin && /^0|(\d+(%|px|pt|in|pc|mm|cm))$/.test(toAry[i]);
  116. if(toAry[i].indexOf("%") == -1){
  117. toAry[i] = this._toPx(toAry[i]);
  118. }
  119. }
  120. if(!validOrigin || !toAry.length || toAry.length > 2 ){
  121. return transformOrigin;
  122. }
  123. Html.attr(n, "dojo-transform-origin", toAry.join(" "));
  124. t && this.setTransform(node, t);
  125. return transformOrigin;
  126. },
  127. _getTransformOriginFilter: function(/*DomNode*/ node){
  128. return Html.attr(node, "dojo-transform-origin") || "50% 50%";
  129. },
  130. _setTransformFilter: function(/*DomNode*/ node, /*String*/ transform){
  131. // Using the Matrix Filter to implement the transform property on IE
  132. var t = transform.replace(/\s/g, ""),
  133. n = DOM.byId(node),
  134. transforms = t.split(")"),
  135. toRad = 1, toRad1 = 1,
  136. mstr = "DXImageTransform.Microsoft.Matrix",
  137. hasAttr = DOMAttr.has,
  138. attr = Html.attr,
  139. // Math functions
  140. PI = Math.PI, cos = Math.cos, sin = Math.sin, tan = Math.tan, max = Math.max, min = Math.min, abs = Math.abs,
  141. degToRad = PI/180, gradToRad = PI/200,
  142. // current transform
  143. ct = "", currentTransform = "",
  144. matchingTransforms = [],
  145. x0 = 0, y0 = 0, dx = 0, dy = 0, xc = 0, yc = 0, a = 0,
  146. // default transform, identity matrix
  147. m11 = 1, m12 = 0, m21 = 0, m22 = 1,
  148. // no translation
  149. tx = 0, ty = 0,
  150. props = [m11, m12, m21, m22, tx, ty],
  151. hasMatrix = false,
  152. ds = Html.style,
  153. newPosition = ds(n, "position") == "absolute" ? "absolute" : "relative",
  154. w = ds(n, "width") + ds(n, "paddingLeft") + ds(n, "paddingRight"),
  155. h = ds(n, "height") + ds(n, "paddingTop") + ds(n, "paddingBottom"),
  156. toPx = this._toPx
  157. ;
  158. !hasAttr(n, "dojo-transform-origin") && this.setTransformOrigin(n, "50% 50%");
  159. for(var i = 0, l = transforms.length; i < l; i++){
  160. matchingTransforms = transforms[i].match(/matrix|rotate|scaleX|scaleY|scale|skewX|skewY|skew|translateX|translateY|translate/);
  161. currentTransform = matchingTransforms ? matchingTransforms[0] : "";
  162. switch(currentTransform){
  163. case "matrix":
  164. // generic transformation
  165. //
  166. // matrix:
  167. // m11 m12
  168. //
  169. // m21 m22
  170. //
  171. ct = transforms[i].replace(/matrix\(|\)/g, "");
  172. var matrix = ct.split(",");
  173. m11 = props[0]*matrix[0] + props[1]*matrix[2];
  174. m12 = props[0]*matrix[1] + props[1]*matrix[3];
  175. m21 = props[2]*matrix[0] + props[3]*matrix[2];
  176. m22 = props[2]*matrix[1] + props[3]*matrix[3];
  177. tx = props[4] + matrix[4];
  178. ty = props[5] + matrix[5];
  179. break;
  180. case "rotate":
  181. // rotate
  182. //
  183. // rotation angle:
  184. // a (rad, deg or grad)
  185. //
  186. // matrix:
  187. // cos(a) -sin(a)
  188. //
  189. // sin(a) cos(a)
  190. //
  191. ct = transforms[i].replace(/rotate\(|\)/g, "");
  192. toRad = ct.indexOf("deg") != -1 ? degToRad : ct.indexOf("grad") != -1 ? gradToRad : 1;
  193. a = parseFloat(ct)*toRad;
  194. var s = sin(a),
  195. c = cos(a)
  196. ;
  197. m11 = props[0]*c + props[1]*s;
  198. m12 = -props[0]*s + props[1]*c;
  199. m21 = props[2]*c + props[3]*s;
  200. m22 = -props[2]*s + props[3]*c;
  201. break;
  202. case "skewX":
  203. // skewX
  204. //
  205. // skew angle:
  206. // a (rad, deg or grad)
  207. //
  208. // matrix:
  209. // 1 tan(a)
  210. //
  211. // 0 1
  212. //
  213. ct = transforms[i].replace(/skewX\(|\)/g, "");
  214. toRad = ct.indexOf("deg") != -1 ? degToRad : ct.indexOf("grad") != -1 ? gradToRad : 1;
  215. var ta = tan(parseFloat(ct)*toRad);
  216. m11 = props[0];
  217. m12 = props[0]*ta + props[1];
  218. m21 = props[2];
  219. m22 = props[2]*ta + props[3];
  220. break;
  221. case "skewY":
  222. // skewY
  223. //
  224. // skew angle:
  225. // a (rad, deg or grad)
  226. //
  227. // matrix:
  228. // 1 0
  229. //
  230. // tan(a) 1
  231. //
  232. ct = transforms[i].replace(/skewY\(|\)/g, "");
  233. toRad = ct.indexOf("deg") != -1 ? degToRad : ct.indexOf("grad") != -1 ? gradToRad : 1;
  234. ta = tan(parseFloat(ct)*toRad);
  235. m11 = props[0] + props[1]*ta;
  236. m12 = props[1];
  237. m21 = props[2] + props[3]*ta;
  238. m22 = props[3];
  239. break;
  240. case "skew":
  241. // skew
  242. //
  243. // skew angles:
  244. // a0 (rad, deg or grad)
  245. // a1 (rad, deg or grad)
  246. //
  247. // matrix:
  248. // 1 tan(a0)
  249. //
  250. // tan(a1) 1
  251. //
  252. ct = transforms[i].replace(/skew\(|\)/g, "");
  253. var skewAry = ct.split(",");
  254. skewAry[1] = skewAry[1] || "0";
  255. toRad = skewAry[0].indexOf("deg") != -1 ? degToRad : skewAry[0].indexOf("grad") != -1 ? gradToRad : 1;
  256. toRad1 = skewAry[1].indexOf("deg") != -1 ? degToRad : skewAry[1].indexOf("grad") != -1 ? gradToRad : 1;
  257. var a0 = tan(parseFloat(skewAry[0])*toRad),
  258. a1 = tan(parseFloat(skewAry[1])*toRad1)
  259. ;
  260. m11 = props[0] + props[1]*a1;
  261. m12 = props[0]*a0 + props[1];
  262. m21 = props[2]+ props[3]*a1;
  263. m22 = props[2]*a0 + props[3];
  264. break;
  265. case "scaleX":
  266. // scaleX
  267. //
  268. // scale factor:
  269. // sx
  270. //
  271. // matrix:
  272. // sx 0
  273. //
  274. // 0 1
  275. //
  276. ct = parseFloat(transforms[i].replace(/scaleX\(|\)/g, "")) || 1;
  277. m11 = props[0]*ct;
  278. m12 = props[1];
  279. m21 = props[2]*ct;
  280. m22 = props[3];
  281. break;
  282. case "scaleY":
  283. // scaleY
  284. //
  285. // scale factor:
  286. // sy
  287. //
  288. // matrix:
  289. // 1 0
  290. //
  291. // 0 sy
  292. //
  293. ct = parseFloat(transforms[i].replace(/scaleY\(|\)/g, "")) || 1;
  294. m11 = props[0];
  295. m12 = props[1]*ct;
  296. m21 = props[2];
  297. m22 = props[3]*ct;
  298. break;
  299. case "scale":
  300. // scale
  301. //
  302. // scale factor:
  303. // sx, sy
  304. //
  305. // matrix:
  306. // sx 0
  307. //
  308. // 0 sy
  309. //
  310. ct = transforms[i].replace(/scale\(|\)/g, "");
  311. var scaleAry = ct.split(",");
  312. scaleAry[1] = scaleAry[1] || scaleAry[0];
  313. m11 = props[0]*scaleAry[0];
  314. m12 = props[1]*scaleAry[1];
  315. m21 = props[2]*scaleAry[0];
  316. m22 = props[3]*scaleAry[1];
  317. break;
  318. case "translateX":
  319. ct = parseInt(transforms[i].replace(/translateX\(|\)/g, "")) || 1;
  320. m11 = props[0];
  321. m12 = props[1];
  322. m21 = props[2];
  323. m22 = props[3];
  324. tx = toPx(ct);
  325. tx && attr(n, "dojo-transform-matrix-tx", tx);
  326. break;
  327. case "translateY":
  328. ct = parseInt(transforms[i].replace(/translateY\(|\)/g, "")) || 1;
  329. m11 = props[0];
  330. m12 = props[1];
  331. m21 = props[2];
  332. m22 = props[3];
  333. ty = toPx(ct);
  334. ty && attr(n, "dojo-transform-matrix-ty", ty);
  335. break;
  336. case "translate":
  337. ct = transforms[i].replace(/translate\(|\)/g, "");
  338. m11 = props[0];
  339. m12 = props[1];
  340. m21 = props[2];
  341. m22 = props[3];
  342. var translateAry = ct.split(",");
  343. translateAry[0] = parseInt(toPx(translateAry[0])) || 0;
  344. translateAry[1] = parseInt(toPx(translateAry[1])) || 0;
  345. tx = translateAry[0];
  346. ty = translateAry[1];
  347. tx && attr(n, "dojo-transform-matrix-tx", tx);
  348. ty && attr(n, "dojo-transform-matrix-ty", ty);
  349. break;
  350. }
  351. props = [m11, m12, m21, m22, tx, ty];
  352. }
  353. // test
  354. var Bx = min(w*m11 + h*m12, min(min(w*m11, h*m12), 0)),
  355. By = min(w*m21 + h*m22, min(min(w*m21, h*m22), 0))
  356. ;
  357. dx = -Bx;
  358. dy = -By;
  359. if(has("ie") < 8){
  360. // on IE < 8 the node must have hasLayout = true
  361. n.style.zoom = "1";
  362. if(newPosition != "absolute"){
  363. var parentWidth = ds(node.parentNode, "width"),
  364. tw = abs(w*m11),
  365. th = abs(h*m12),
  366. wMax = max(tw + th, max(max(th, tw), 0))
  367. ;
  368. dx -= (wMax - w) / 2 - (parentWidth > wMax ? 0 : (wMax - parentWidth) / 2);
  369. }
  370. }else if(has("ie") == 8){
  371. // IE8 bug, a filter is applied to positioned descendants
  372. // only if the parent has z-index
  373. ds(n, "zIndex") == "auto" && (n.style.zIndex = "0");
  374. }
  375. try{
  376. hasMatrix = !!n.filters.item(mstr);
  377. }catch(e){
  378. hasMatrix = false;
  379. }
  380. if(hasMatrix){
  381. n.filters.item(mstr).M11 = m11;
  382. n.filters.item(mstr).M12 = m12;
  383. n.filters.item(mstr).M21 = m21;
  384. n.filters.item(mstr).M22 = m22;
  385. // use 'nearest' for a faster transform
  386. n.filters.item(mstr).filterType = 'bilinear';
  387. n.filters.item(mstr).Dx = 0;
  388. n.filters.item(mstr).Dy = 0;
  389. n.filters.item(mstr).sizingMethod = 'auto expand';
  390. }else{
  391. n.style.filter +=
  392. " progid:" + mstr + "(M11=" + m11 +
  393. ",M12=" + m12 +
  394. ",M21=" + m21 +
  395. ",M22=" + m22 +
  396. ",FilterType='bilinear',Dx=0,Dy=0,sizingMethod='auto expand')"
  397. ;
  398. }
  399. tx = parseInt(attr(n, "dojo-transform-matrix-tx") || "0");
  400. ty = parseInt(attr(n, "dojo-transform-matrix-ty") || "0");
  401. // transform origin
  402. var toAry = attr(n, "dojo-transform-origin").split(" ");
  403. for(i = 0; i < 2; i++){
  404. toAry[i] = toAry[i] || "50%";
  405. }
  406. xc = (toAry[0].toString().indexOf("%") != -1) ? w * parseInt(toAry[0]) * .01 : toAry[0];
  407. yc = (toAry[1].toString().indexOf("%") != -1) ? h * parseInt(toAry[1]) * .01 : toAry[1];
  408. if(hasAttr(n, "dojo-startX")){
  409. x0 = parseInt(attr(n, "dojo-startX"));
  410. }else{
  411. x0 = parseInt(ds(n, "left"));
  412. attr(n, "dojo-startX", newPosition == "absolute" ? x0 : "0");
  413. }
  414. if(hasAttr(n, "dojo-startY")){
  415. y0 = parseInt(attr(n, "dojo-startY"));
  416. }else{
  417. y0 = parseInt(ds(n, "top"));
  418. attr(n, "dojo-startY", newPosition == "absolute" ? y0 : "0");
  419. }
  420. ds(n, {
  421. position: newPosition,
  422. left: x0 - parseInt(dx) + parseInt(xc) - ((parseInt(xc) - tx)*m11 + (parseInt(yc) - ty)*m12) + "px",
  423. top: y0 - parseInt(dy) + parseInt(yc) - ((parseInt(xc) - tx)*m21 + (parseInt(yc) - ty)*m22) + "px"
  424. });
  425. return transform;
  426. },
  427. _getTransformFilter: function(/*DomNode*/ node){
  428. try{
  429. var n = DOM.byId(node),
  430. item = n.filters.item(0)
  431. ;
  432. return "matrix(" + item.M11 + ", " + item.M12 + ", " + item.M21 + ", " +
  433. item.M22 + ", " + (Html.attr(node, "dojo-transform-tx") || "0") + ", " + (Html.attr(node, "dojo-transform-ty") || "0") + ")";
  434. }catch(e){
  435. return "matrix(1, 0, 0, 1, 0, 0)";
  436. }
  437. },
  438. setTransform: function(){
  439. this._notSupported();
  440. },
  441. setTransformOrigin: function(){
  442. this._notSupported();
  443. }
  444. });
  445. HtmlX["ext-dojo"].style.init();
  446. return Html.style;
  447. });