_compat.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  1. define("dojox/mobile/_compat", [
  2. "dojo/_base/array", // array.forEach
  3. "dojo/_base/config",
  4. "dojo/_base/connect", // connect.connect
  5. "dojo/_base/fx", // fx.fadeOut, fx.fadeIn
  6. "dojo/_base/lang", // lang.extend, lang.isArray
  7. "dojo/_base/sniff", // has("webkit"), has("ie")
  8. "dojo/_base/window", // win.doc, win.body
  9. "dojo/dom-class",
  10. "dojo/dom-construct",
  11. "dojo/dom-style",
  12. "dojo/fx",
  13. "dojo/fx/easing",
  14. "dojo/ready",
  15. "dojo/uacss",
  16. "dijit/registry", // registry.byNode
  17. "dojox/fx",
  18. "dojox/fx/flip",
  19. "./EdgeToEdgeList",
  20. "./IconContainer",
  21. "./RoundRect",
  22. "./RoundRectList",
  23. "./ScrollableView",
  24. "./Switch",
  25. "./View",
  26. "require"
  27. ], function(array, config, connect, bfx, lang, has, win, domClass, domConstruct, domStyle, fx, easing, ready, uacss, registry, xfx, flip, EdgeToEdgeList, IconContainer, RoundRect, RoundRectList, ScrollableView, Switch, View, require){
  28. /*=====
  29. var EdgeToEdgeList = dojox.mobile.EdgeToEdgeList;
  30. var IconContainer = dojox.mobile.IconContainer;
  31. var RoundRect = dojox.mobile.RoundRect;
  32. var RoundRectList = dojox.mobile.RoundRectList;
  33. var ScrollableView = dojox.mobile.ScrollableView;
  34. var Switch = dojox.mobile.Switch;
  35. var View = dojox.mobile.View;
  36. =====*/
  37. // module:
  38. // dojox/mobile/compat
  39. // summary:
  40. // CSS3 compatibility module
  41. // description:
  42. // This module provides support for some of the CSS3 features to dojox.mobile
  43. // for non-CSS3 browsers, such as IE or Firefox.
  44. // If you load this module, it directly replaces some of the methods of
  45. // dojox.mobile instead of subclassing. This way, html pages remains the same
  46. // regardless of whether this compatibility module is used or not.
  47. // Recommended usage is as follows. the code below loads dojox.mobile.compat
  48. // only when isWebKit is true.
  49. //
  50. // dojo.require("dojox.mobile");
  51. // dojo.requireIf(!has("webkit"), "dojox.mobile.compat");
  52. //
  53. // This module also loads compatibility CSS files, which has -compat.css
  54. // suffix. You can use either the <link> tag or @import to load theme
  55. // CSS files. Then, this module searches for the loaded CSS files and loads
  56. // compatibility CSS files. For example, if you load iphone.css in a page,
  57. // this module automatically loads iphone-compat.css.
  58. // If you explicitly load iphone-compat.css with <link> or @import,
  59. // this module will not load the already loaded file.
  60. var dm = lang.getObject("dojox.mobile", true);
  61. /*=====
  62. dm = dojox.mobile
  63. =====*/
  64. if(!has("webkit")){
  65. lang.extend(View, {
  66. _doTransition: function(fromNode, toNode, transition, dir){
  67. var anim;
  68. this.wakeUp(toNode);
  69. if(!transition || transition == "none"){
  70. toNode.style.display = "";
  71. fromNode.style.display = "none";
  72. toNode.style.left = "0px";
  73. this.invokeCallback();
  74. }else if(transition == "slide" || transition == "cover" || transition == "reveal"){
  75. var w = fromNode.offsetWidth;
  76. var s1 = fx.slideTo({
  77. node: fromNode,
  78. duration: 400,
  79. left: -w*dir,
  80. top: domStyle.get(fromNode, "top")
  81. });
  82. var s2 = fx.slideTo({
  83. node: toNode,
  84. duration: 400,
  85. left: 0,
  86. top: domStyle.get(toNode, "top")
  87. });
  88. toNode.style.position = "absolute";
  89. toNode.style.left = w*dir + "px";
  90. toNode.style.display = "";
  91. anim = fx.combine([s1,s2]);
  92. connect.connect(anim, "onEnd", this, function(){
  93. fromNode.style.display = "none";
  94. fromNode.style.left = "0px";
  95. toNode.style.position = "relative";
  96. var toWidget = registry.byNode(toNode);
  97. if(toWidget && !domClass.contains(toWidget.domNode, "out")){
  98. // Reset the temporary padding
  99. toWidget.containerNode.style.paddingTop = "";
  100. }
  101. this.invokeCallback();
  102. });
  103. anim.play();
  104. }else if(transition == "slidev" || transition == "coverv" || transition == "reavealv"){
  105. var h = fromNode.offsetHeight;
  106. var s1 = fx.slideTo({
  107. node: fromNode,
  108. duration: 400,
  109. left: 0,
  110. top: -h*dir
  111. });
  112. var s2 = fx.slideTo({
  113. node: toNode,
  114. duration: 400,
  115. left: 0,
  116. top: 0
  117. });
  118. toNode.style.position = "absolute";
  119. toNode.style.top = h*dir + "px";
  120. toNode.style.left = "0px";
  121. toNode.style.display = "";
  122. anim = fx.combine([s1,s2]);
  123. connect.connect(anim, "onEnd", this, function(){
  124. fromNode.style.display = "none";
  125. toNode.style.position = "relative";
  126. this.invokeCallback();
  127. });
  128. anim.play();
  129. }else if(transition == "flip"){
  130. anim = xfx.flip({
  131. node: fromNode,
  132. dir: "right",
  133. depth: 0.5,
  134. duration: 400
  135. });
  136. toNode.style.position = "absolute";
  137. toNode.style.left = "0px";
  138. connect.connect(anim, "onEnd", this, function(){
  139. fromNode.style.display = "none";
  140. toNode.style.position = "relative";
  141. toNode.style.display = "";
  142. this.invokeCallback();
  143. });
  144. anim.play();
  145. }else {
  146. // other transitions - "fade", "dissolve", "swirl"
  147. anim = fx.chain([
  148. bfx.fadeOut({
  149. node: fromNode,
  150. duration: 600
  151. }),
  152. bfx.fadeIn({
  153. node: toNode,
  154. duration: 600
  155. })
  156. ]);
  157. toNode.style.position = "absolute";
  158. toNode.style.left = "0px";
  159. toNode.style.display = "";
  160. domStyle.set(toNode, "opacity", 0);
  161. connect.connect(anim, "onEnd", this, function(){
  162. fromNode.style.display = "none";
  163. toNode.style.position = "relative";
  164. domStyle.set(fromNode, "opacity", 1);
  165. this.invokeCallback();
  166. });
  167. anim.play();
  168. }
  169. dm.currentView = registry.byNode(toNode);
  170. },
  171. wakeUp: function(/*DomNode*/node){
  172. // summary:
  173. // Function to force IE to redraw a node since its layout
  174. // code tends to misrender in partial draws.
  175. // node: DomNode
  176. // The node to forcibly redraw.
  177. // tags:
  178. // public
  179. if(has("ie") && !node._wokeup){
  180. node._wokeup = true;
  181. var disp = node.style.display;
  182. node.style.display = "";
  183. var nodes = node.getElementsByTagName("*");
  184. for(var i = 0, len = nodes.length; i < len; i++){
  185. var val = nodes[i].style.display;
  186. nodes[i].style.display = "none";
  187. nodes[i].style.display = "";
  188. nodes[i].style.display = val;
  189. }
  190. node.style.display = disp;
  191. }
  192. }
  193. });
  194. lang.extend(Switch, {
  195. _changeState: function(/*String*/state, /*Boolean*/anim){
  196. // summary:
  197. // Function to toggle the switch state on the switch
  198. // state:
  199. // The state to toggle, switch 'on' or 'off'
  200. // anim:
  201. // Whether to use animation or not
  202. // tags:
  203. // private
  204. var on = (state === "on");
  205. var pos;
  206. if(!on){
  207. pos = -this.inner.firstChild.firstChild.offsetWidth;
  208. }else{
  209. pos = 0;
  210. }
  211. this.left.style.display = "";
  212. this.right.style.display = "";
  213. var _this = this;
  214. var f = function(){
  215. domClass.remove(_this.domNode, on ? "mblSwitchOff" : "mblSwitchOn");
  216. domClass.add(_this.domNode, on ? "mblSwitchOn" : "mblSwitchOff");
  217. _this.left.style.display = on ? "" : "none";
  218. _this.right.style.display = !on ? "" : "none";
  219. };
  220. if(anim){
  221. var a = fx.slideTo({
  222. node: this.inner,
  223. duration: 300,
  224. left: pos,
  225. onEnd: f
  226. });
  227. a.play();
  228. }else{
  229. if(on || pos){
  230. this.inner.style.left = pos + "px";
  231. }
  232. f();
  233. }
  234. }
  235. });
  236. if(has("ie")){
  237. lang.extend(RoundRect, {
  238. buildRendering: function(){
  239. // summary:
  240. // Function to simulate the borderRadius appearance on
  241. // IE, since IE does not support this CSS style.
  242. // tags:
  243. // protected
  244. dm.createRoundRect(this);
  245. this.domNode.className = "mblRoundRect";
  246. }
  247. });
  248. RoundRectList._addChild = RoundRectList.prototype.addChild;
  249. lang.extend(RoundRectList, {
  250. buildRendering: function(){
  251. // summary:
  252. // Function to simulate the borderRadius appearance on
  253. // IE, since IE does not support this CSS style.
  254. // tags:
  255. // protected
  256. dm.createRoundRect(this, true);
  257. this.domNode.className = "mblRoundRectList";
  258. },
  259. postCreate: function(){
  260. this.redrawBorders();
  261. },
  262. addChild: function(widget, /*Number?*/insertIndex){
  263. RoundRectList._addChild.apply(this, arguments);
  264. this.redrawBorders();
  265. if(dm.applyPngFilter){
  266. dm.applyPngFilter(widget.domNode);
  267. }
  268. },
  269. redrawBorders: function(){
  270. // summary:
  271. // Function to adjust the creation of RoundRectLists on IE.
  272. // Removed undesired styles.
  273. // tags:
  274. // public
  275. // Remove a border of the last ListItem.
  276. // This is for browsers that do not support the last-child CSS pseudo-class.
  277. if(this instanceof EdgeToEdgeList){ return; }
  278. var lastChildFound = false;
  279. for(var i = this.containerNode.childNodes.length - 1; i >= 0; i--){
  280. var c = this.containerNode.childNodes[i];
  281. if(c.tagName == "LI"){
  282. c.style.borderBottomStyle = lastChildFound ? "solid" : "none";
  283. lastChildFound = true;
  284. }
  285. }
  286. }
  287. });
  288. lang.extend(EdgeToEdgeList, {
  289. buildRendering: function(){
  290. this.domNode = this.containerNode = this.srcNodeRef || win.doc.createElement("UL");
  291. this.domNode.className = "mblEdgeToEdgeList";
  292. }
  293. });
  294. IconContainer._addChild = IconContainer.prototype.addChild;
  295. lang.extend(IconContainer, {
  296. addChild: function(widget, /*Number?*/insertIndex){
  297. IconContainer._addChild.apply(this, arguments);
  298. if(dm.applyPngFilter){
  299. dm.applyPngFilter(widget.domNode);
  300. }
  301. }
  302. });
  303. lang.mixin(dm, {
  304. createRoundRect: function(_this, isList){
  305. // summary:
  306. // Function to adjust the creation of rounded rectangles on IE.
  307. // Deals with IE's lack of borderRadius support
  308. // tags:
  309. // public
  310. var i, len;
  311. _this.domNode = win.doc.createElement("DIV");
  312. _this.domNode.style.padding = "0px";
  313. _this.domNode.style.backgroundColor = "transparent";
  314. _this.domNode.style.border = "none"; // borderStyle = "none"; doesn't work on IE9
  315. _this.containerNode = win.doc.createElement(isList?"UL":"DIV");
  316. _this.containerNode.className = "mblRoundRectContainer";
  317. if(_this.srcNodeRef){
  318. _this.srcNodeRef.parentNode.replaceChild(_this.domNode, _this.srcNodeRef);
  319. for(i = 0, len = _this.srcNodeRef.childNodes.length; i < len; i++){
  320. _this.containerNode.appendChild(_this.srcNodeRef.removeChild(_this.srcNodeRef.firstChild));
  321. }
  322. _this.srcNodeRef = null;
  323. }
  324. _this.domNode.appendChild(_this.containerNode);
  325. for(i = 0; i <= 5; i++){
  326. var top = domConstruct.create("DIV");
  327. top.className = "mblRoundCorner mblRoundCorner"+i+"T";
  328. _this.domNode.insertBefore(top, _this.containerNode);
  329. var bottom = domConstruct.create("DIV");
  330. bottom.className = "mblRoundCorner mblRoundCorner"+i+"B";
  331. _this.domNode.appendChild(bottom);
  332. }
  333. }
  334. });
  335. lang.extend(ScrollableView, {
  336. postCreate: function(){
  337. // On IE, margin-top of the first child does not seem to be effective,
  338. // probably because padding-top is specified for containerNode
  339. // to make room for a fixed header. This dummy node is a workaround for that.
  340. var dummy = domConstruct.create("DIV", {className:"mblDummyForIE", innerHTML:"&nbsp;"}, this.containerNode, "first");
  341. domStyle.set(dummy, {
  342. position: "relative",
  343. marginBottom: "-2px",
  344. fontSize: "1px"
  345. });
  346. }
  347. });
  348. } // if (has("ie"))
  349. if(has("ie") <= 6){
  350. dm.applyPngFilter = function(root){
  351. root = root || win.body();
  352. var nodes = root.getElementsByTagName("IMG");
  353. var blank = require.toUrl("dojo/resources/blank.gif");
  354. for(var i = 0, len = nodes.length; i < len; i++){
  355. var img = nodes[i];
  356. var w = img.offsetWidth;
  357. var h = img.offsetHeight;
  358. if(w === 0 || h === 0){
  359. // The reason why the image has no width/height may be because
  360. // display is "none". If that is the case, let's change the
  361. // display to "" temporarily and see if the image returns them.
  362. if(domStyle.get(img, "display") != "none"){ continue; }
  363. img.style.display = "";
  364. w = img.offsetWidth;
  365. h = img.offsetHeight;
  366. img.style.display = "none";
  367. if(w === 0 || h === 0){ continue; }
  368. }
  369. var src = img.src;
  370. if(src.indexOf("resources/blank.gif") != -1){ continue; }
  371. img.src = blank;
  372. img.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src+"')";
  373. img.style.width = w + "px";
  374. img.style.height = h + "px";
  375. }
  376. };
  377. if(!dm._disableBgFilter && dm.createDomButton){
  378. dm._createDomButton_orig = dm.createDomButton;
  379. dm.createDomButton = function(/*DomNode*/refNode, /*Object?*/style, /*DomNode?*/toNode){
  380. var node = dm._createDomButton_orig.apply(this, arguments);
  381. if(node && node.className && node.className.indexOf("mblDomButton") !== -1){
  382. var f = function(){
  383. if(node.currentStyle && node.currentStyle.backgroundImage.match(/url.*(mblDomButton.*\.png)/)){
  384. var img = RegExp.$1;
  385. var src = require.toUrl("dojox/mobile/themes/common/domButtons/compat/") + img;
  386. node.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src+"',sizingMethod='crop')";
  387. node.style.background = "none";
  388. }
  389. };
  390. setTimeout(f, 1000);
  391. setTimeout(f, 5000);
  392. }
  393. return node;
  394. };
  395. }
  396. } // if(has("ie") <= 6)
  397. dm.loadCssFile = function(/*String*/file){
  398. // summary:
  399. // Overrides dojox.mobile.loadCssFile() defined in
  400. // deviceTheme.js.
  401. if(!dm.loadedCssFiles){ dm.loadedCssFiles = []; }
  402. if(win.doc.createStyleSheet){
  403. // for some reason, IE hangs when you try to load
  404. // multiple css files almost at once.
  405. setTimeout(function(file){
  406. return function(){
  407. var ss = win.doc.createStyleSheet(file);
  408. ss && dm.loadedCssFiles.push(ss.owningElement);
  409. };
  410. }(file), 0);
  411. }else{
  412. dm.loadedCssFiles.push(domConstruct.create("LINK", {
  413. href: file,
  414. type: "text/css",
  415. rel: "stylesheet"
  416. }, win.doc.getElementsByTagName('head')[0]));
  417. }
  418. };
  419. dm.loadCss = function(/*String|Array*/files){
  420. // summary:
  421. // Function to load and register CSS files with the page
  422. // files: String|Array
  423. // The CSS files to load and register with the page.
  424. // tags:
  425. // private
  426. if(!dm._loadedCss){
  427. var obj = {};
  428. array.forEach(dm.getCssPaths(), function(path){
  429. obj[path] = true;
  430. });
  431. dm._loadedCss = obj;
  432. }
  433. if(!lang.isArray(files)){ files = [files]; }
  434. for(var i = 0; i < files.length; i++){
  435. var file = files[i];
  436. if(!dm._loadedCss[file]){
  437. dm._loadedCss[file] = true;
  438. dm.loadCssFile(file);
  439. }
  440. }
  441. };
  442. dm.getCssPaths = function(){
  443. var paths = [];
  444. var i, j, len;
  445. // find @import
  446. var s = win.doc.styleSheets;
  447. for(i = 0; i < s.length; i++){
  448. if(s[i].href){ continue; }
  449. var r = s[i].cssRules || s[i].imports;
  450. if(!r){ continue; }
  451. for(j = 0; j < r.length; j++){
  452. if(r[j].href){
  453. paths.push(r[j].href);
  454. }
  455. }
  456. }
  457. // find <link>
  458. var elems = win.doc.getElementsByTagName("link");
  459. for(i = 0, len = elems.length; i < len; i++){
  460. if(elems[i].href){
  461. paths.push(elems[i].href);
  462. }
  463. }
  464. return paths;
  465. };
  466. dm.loadCompatPattern = /\/mobile\/themes\/.*\.css$/;
  467. dm.loadCompatCssFiles = function(/*Boolean?*/force){
  468. // summary:
  469. // Function to perform page-level adjustments on browsers such as
  470. // IE and firefox. It loads compat specific css files into the
  471. // page header.
  472. if(has("ie") && !force){
  473. setTimeout(function(){ // IE needs setTimeout
  474. dm.loadCompatCssFiles(true);
  475. }, 0);
  476. }
  477. dm._loadedCss = undefined;
  478. var paths = dm.getCssPaths();
  479. for(var i = 0; i < paths.length; i++){
  480. var href = paths[i];
  481. if((href.match(dm.loadCompatPattern) || location.href.indexOf("mobile/tests/") !== -1) && href.indexOf("-compat.css") === -1){
  482. var compatCss = href.substring(0, href.length-4)+"-compat.css";
  483. dm.loadCss(compatCss);
  484. }
  485. }
  486. };
  487. dm.hideAddressBar = function(/*Event?*/evt, /*Boolean?*/doResize){
  488. if(doResize !== false){ dm.resizeAll(); }
  489. };
  490. ready(function(){
  491. if(config["mblLoadCompatCssFiles"] !== false){
  492. dm.loadCompatCssFiles();
  493. }
  494. if(dm.applyPngFilter){
  495. dm.applyPngFilter();
  496. }
  497. });
  498. } // end of if(!has("webkit")){
  499. return dm;
  500. });