source: Dev/branches/rest-dojo-ui/client/dojox/mobile/_compat.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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