/* About migrationAssist ===================== The migrationAssist is a Dojo module that helps you migrate your dojox/mobile 1.6/1.7 applications to 1.8. To enable migrationAssist, all you need to do is require this module as shown in the examples below. If your application uses deprecated or no longer available functions, this module detects them and displays messages in the browser console. Also, it tries to dynamically fix them as much as possible so that the target application can work somehow. Note, however, that the purpose of migrationAssist is not to run the older applications as they are, but to assist migration. Changes from 1.6/1.7 to 1.8 =========================== Carousel -------- - Carousel has no backward compatibility, since it was experimental in 1.7. There are two subclasses that support data stores. Use DataCarousel if you want to use carousel with dojo/data. Use StoreCarousel if you want to use carousel with dojo/store. FixedSplitter ------------- - FixedSplitter.css is no longer in the themes/common folder. It is in the device theme folder. (e.g. themes/iphone/FixedSplitter.css) FlippableView ------------- - FlippableView was deprecated in 1.7, and removed in 1.8. Use SwapView instead. ListItem -------- - The sync property is no longer supported. It always behaves asynchronously. - The btnClass property is no longer supported. Use rightIcon instead. - The btnClass2 property is no longer supported. Use rightIcon2 instead. SpinWheel --------- - SpinWheel.css is no longer in the themes/common folder. It is in the device theme folder. (e.g. themes/iphone/SpinWheel.css) - getValue() is no longer supported. Use get("values") instead. - setValue() is no longer supported. Use set("values", newValue) instead. SpinWheelSlot ------------- - getValue() is no longer supported. Use get("value") instead. - getKey() is no longer supported. Use get("key") instead. - setValue() is no longer supported. Use set("value", newValue) instead. Switch ------ - When you place it in a ListItem, class="mblItemSwitch" is no longer necessary. TabBar ------ - In 1.7 or older, barType="segmentedControl" produced different UIs according to the current theme. In the iphone theme, it was a segmented control, but in other themes, it was tabs with or without icons. In 1.8, however, barType="segmentedControl" always produces a segmented control UI regardless of the current theme. If you still need the old behavior, barType:{"iphone_theme":"segmentedControl","*":"tallTab"} should produce a segmented control for the iphone theme, and a tall tab bar for the other themes. You need to use deviceTheme.js to specify barType that way. Also, if you want to hide the tab icons on the segmented control in the iphone theme, you could apply a css like this: See test_ScrollableView-demo.html for an example usage. TabBarButton ------------- - Specifying a DOM Button with the class attribute like class="mblDomButtonWhitePlus" is no longer supported. Use icon="mblDomButtonWhitePlus" instead. - select() and deselect() are no longer supported. Use set("selected", boolean) instead. ToolBarButton ------------- - Specifying the button color style with the class attribute like class="mblColorBlue" is no longer supported. Use defaultColor="mblColorBlue" instead. - Specifying a DOM Button with the class attribute like class="mblDomButtonWhitePlus" is no longer supported. Use icon="mblDomButtonWhitePlus" instead. - select() and deselect() are no longer supported. Use set("selected", boolean) instead. dojox/mobile/parser ------------------- - dojox/mobile/parser no longer accepts array-type attribute like labels="['A','B','C','D','E']" Instead, you should specify like labels="A,B,C,D,E", which is the format dojo/parser accepts. bookmarkable ------------ - To enable the bookmarkable feature, require dojox/mobile/bookmarkable instead of dojo/hash */ define("dojox/mobile/migrationAssist", [ "dojo/_base/declare", "dojo/_base/lang", "dojo/_base/window", "dojo/dom-class", "dojo/dom-construct", "dojo/dom-style", "dojo/ready", "dijit/_Container", "dijit/_WidgetBase", "./_ItemBase", "./common", "./FixedSplitterPane", "./Heading", "./iconUtils", "./ListItem", "./RoundRect", "./SpinWheel", "./SpinWheelSlot", "./SwapView", "./TabBarButton", "./ToolBarButton", "./View" ], function(declare, lang, win, domClass, domConstruct, domStyle, ready, Container, WidgetBase, _ItemBase, mobile, FixedSplitterPane, Heading, iconUtils, ListItem, RoundRect, SpinWheel, SpinWheelSlot, SwapView, TabBarButton, ToolBarButton, View){ // module: // dojox/mobile/migrationAssist var currentTheme; var MigrationAssist = function(){ // summary: // Dojo Mobile 1.6/1.7 to 1.8 migration assistance. var get = function(w, key){ return w[key] || w.srcNodeRef && w.srcNodeRef.getAttribute(key); }; this.dispatch = function(/*String*/cls, /*Widget*/ w){ var base = cls.replace(/.*\./, ""); this["check" + base] && this["check" + base](w); }; this.checkCarousel = function(/*Widget*/ w){ console.log('[MIG:error] Carousel has no backward compatibility, since it was experimental in 1.7. The new Carousel supports dojo/store instead of dojo/data.'); }; this.checkFixedSplitter = function(/*Widget*/ w){ // FixedSplitter.css has been moved from the themes/common folder // to the device theme folder such as themes/android. if(!this._fixedSplitter_css_checked){ this._fixedSplitter_css_checked = true; var dummy = domConstruct.create("div", { className: "mblFixedSplitter" }, win.body()); if(domStyle.get(dummy, "height") == 0){ domConstruct.create("link", { href: "../themes/android/FixedSplitter.css", type: "text/css", rel: "stylesheet" }, win.doc.getElementsByTagName('head')[0]); console.log('[MIG:fixed] FixedSplitter.css does not seem to be loaded. Loaded it for you just now. It is in the device theme folder.'); } win.body().removeChild(dummy); setTimeout(function(){ w.resize(); }, 1000); } }; this.checkFixedSplitterPane = function(/*Widget*/ w){ console.log('[MIG:fixed] FixedSplitterPane: Deprecated. Use dojox/mobile/Container instead.'); }; this.checkFixedSplitter = function(/*Widget*/ w){ // FixedSplitter.css has been moved from the themes/common folder // to the device theme folder such as themes/android. if(!this._fixedSplitter_css_checked){ this._fixedSplitter_css_checked = true; var dummy = domConstruct.create("div", { className: "mblFixedSplitter" }, win.body()); if(domStyle.get(dummy, "height") == 0){ domConstruct.create("link", { href: "../themes/android/FixedSplitter.css", type: "text/css", rel: "stylesheet" }, win.doc.getElementsByTagName('head')[0]); console.log('[MIG:fixed] FixedSplitter.css does not seem to be loaded. Loaded it for you just now. It is in the device theme folder.'); } win.body().removeChild(dummy); setTimeout(function(){ w.resize(); }, 1000); } }; this.checkListItem = function(/*Widget*/ w){ if(w.sync !== undefined || w.srcNodeRef && w.srcNodeRef.getAttribute("sync")){ console.log('[MIG:fixed] ListItem: The sync property is no longer supported. (async always)'); } if(w.btnClass !== undefined || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass")){ console.log('[MIG:fixed] ListItem: The btnClass property is no longer supported. Use rightIcon instead.'); w.rightIcon = w.btnClass || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass"); } if(w.btnClass2 !== undefined || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass2")){ console.log('[MIG:fixed] ListItem: The btnClass2 property is no longer supported. Use rightIcon2 instead.'); w.rightIcon2 = w.btnClass2 || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass2"); } }; this.checkSpinWheelSlot = function(/*Widget*/ w){ if(w.labels && w.labels[0] && w.labels[0].charAt(0) === '['){ for(var i = 0; i < w.labels.length; i++){ w.labels[i] = w.labels[i].replace(/^\[*[\'\"]*/, ''); w.labels[i] = w.labels[i].replace(/[\'\"]*\]*$/, ''); } console.log('[MIG:fixed] SpinWheelSlot: dojox/mobile/parser no longer accepts array-type attribute like labels="[\'A\',\'B\',\'C\',\'D\',\'E\']". Specify as labels="A,B,C,D,E" instead.' ); } }; this.checkSwapView = function(/*Widget*/ w){ var n = w.srcNodeRef; if(n){ var type = n.getAttribute("dojoType") || n.getAttribute("data-dojo-type"); if(type === "dojox.mobile.FlippableView"){ console.log('[MIG:fixed] FlippableView: FlippableView is no longer supported. Use SwapView instead.'); } } }; this.checkSwitch = function(/*Widget*/ w){ if(w["class"] === "mblItemSwitch"){ console.log('[MIG:fixed] Switch: class="mblItemSwitch" is no longer necessary.'); } }; this.checkTabBar = function(/*Widget*/ w){ if(get(w, "barType") === "segmentedControl"){ console.log('[MIG:warning] TabBar: segmentedControl in 1.8 produces the same UI regardless of the current theme. See the inline doc in migrationAssist.js for details.'); domConstruct.create("style", { innerHTML: ".iphone_theme .mblTabBarSegmentedControl .mblTabBarButtonIconArea { display: none; }" }, win.doc.getElementsByTagName('head')[0]); } }; this.checkTabBarButton = function(/*Widget*/ w){ if((w["class"] || "").indexOf("mblDomButton") === 0){ console.log('[MIG:fixed] TabBarButton: Use icon="' + w["class"] + '" instead of class="' + w["class"] + '".'); w.icon = w["class"]; w["class"] = ""; if(w.srcNodeRef){ w.srcNodeRef.className = ""; } } }; this.checkToolBarButton = function(/*Widget*/ w){ if((w["class"] || "").indexOf("mblColor") === 0){ console.log('[MIG:fixed] ToolBarButton: Use defaultColor="' + w["class"] + '" instead of class="' + w["class"] + '".'); w.defaultColor = w["class"]; w["class"] = ""; if(w.srcNodeRef){ w.srcNodeRef.className = ""; } } if((w["class"] || "").indexOf("mblDomButton") === 0){ console.log('[MIG:fixed] ToolBarButton: Use icon="' + w["class"] + '" instead of class="' + w["class"] + '".'); w.icon = w["class"]; w["class"] = ""; if(w.srcNodeRef){ w.srcNodeRef.className = ""; } } }; }; dojox.mobile.FlippableView = SwapView; var migrationAssist = new MigrationAssist(); // Hide from the API doc tool, we want to get the documentation for the normal WidgetBase.postMixInProperties() WidgetBase.prototype.postMixInProperties = /*===== WidgetBase.prototype.postMixInProperties || =====*/ function(){ migrationAssist.dispatch(this.declaredClass, this); dojo.forEach([FixedSplitterPane, Heading, RoundRect, SpinWheel, TabBarButton, ToolBarButton, View], function(module){ if(this.declaredClass !== module.prototype.declaredClass && this instanceof module){ migrationAssist.dispatch(module.prototype.declaredClass, this); } }, this); }; extendSelectFunction = function(obj) { lang.extend(obj, { select: function(){ console.log('[MIG:fixed] ' + this.declaredClass + '(id='+this.id+'): Use set("selected", boolean) instead of select/deselect.'); obj.prototype.set.apply(this, ["selected", !arguments[0]]); }, deselect: function(){ this.select(true); } }); }; extendSelectFunction(ToolBarButton); extendSelectFunction(TabBarButton); lang.extend(ListItem, { set: function(key, value){ if(key === "btnClass"){ console.log('[MIG:fixed] ' + this.declaredClass + '(id='+this.id+'): Use set("rightIcon",x) instead of set("btnClass",x).'); key = "rightIcon"; }else if(key === "btnClass2"){ console.log('[MIG:fixed] ' + this.declaredClass + '(id='+this.id+'): Use set("rightIcon2",x) instead of set("btnClass2",x).'); key = "rightIcon2"; } WidgetBase.prototype.set.apply(this, [key, value]); } }); lang.extend(SpinWheel, { getValue: function(){ console.log('[MIG:fixed] SpinWheel: getValue() is no longer supported. Use get("values") instead.'); return this.get("values"); }, setValue: function(newValue){ console.log('[MIG:fixed] SpinWheel: setValue() is no longer supported. Use set("values",x) instead.'); return this.set("values", newValue); } }); lang.extend(SpinWheelSlot, { getValue: function(){ console.log('[MIG:fixed] SpinWheelSlot: getValue() is no longer supported. Use get("value") instead.'); return this.get("value"); }, getKey: function(){ console.log('[MIG:fixed] SpinWheelSlot: getKey() is no longer supported. Use get("key") instead.'); return this.get("key"); }, setValue: function(newValue){ console.log('[MIG:fixed] SpinWheelSlot: setValue() is no longer supported. Use set("value",x) instead.'); return this.set("value", newValue); } }); lang.mixin(mobile, { createDomButton: function(){ console.log('[MIG:fixed] dojox.mobile(id='+arguments[0].id+'): createDomButton was moved to iconUtils.'); return iconUtils.createDomButton.apply(this, arguments); } }); // check css var cssFiles = [], i, j; // collect @import var s = win.doc.styleSheets; for(i = 0; i < s.length; i++){ if(s[i].href){ continue; } var r = s[i].cssRules || s[i].imports; if(!r){ continue; } for(j = 0; j < r.length; j++){ if(r[j].href){ cssFiles.push(r[j].href); } } } // collect var elems = win.doc.getElementsByTagName("link"); for(i = 0; i < elems.length; i++){ cssFiles.push(elems[i].href); } for(i = 0; i < cssFiles.length; i++){ if(cssFiles[i].indexOf("/iphone/") !== -1){ currentTheme = "iphone"; }else if(cssFiles[i].indexOf("/android/") !== -1){ currentTheme = "android"; }else if(cssFiles[i].indexOf("/blackberry/") !== -1){ currentTheme = "blackberry"; }else if(cssFiles[i].indexOf("/custom/") !== -1){ currentTheme = "custom"; } domClass.add(win.doc.documentElement, currentTheme + "_theme"); if(cssFiles[i].match(/themes\/common\/(FixedSplitter.css)|themes\/common\/(SpinWheel.css)/)){ console.log('[MIG:error] ' + (RegExp.$1 || RegExp.$2) + ' is no longer in the themes/common folder. It is in the device theme folder.'); } } ready(function(){ if(dojo.hash){ console.log('[MIG:fixed] dojo/hash detected. If you would like to enable the bookmarkable feature, require dojox/mobile/bookmarkable instead of dojo/hash'); if(dojo.require){ dojo["require"]("dojox.mobile.bookmarkable"); }else{ require(["dojox/mobile/bookmarkable"]); } } }); // Return singleton. (TODO: can we replace LazyLoadUtils class and singleton w/a simple hash of functions?) return migrationAssist; });