1 | /* |
---|
2 | |
---|
3 | About migrationAssist |
---|
4 | ===================== |
---|
5 | |
---|
6 | The migrationAssist is a Dojo module that helps you migrate your |
---|
7 | dojox/mobile 1.6/1.7 applications to 1.8. To enable migrationAssist, |
---|
8 | all you need to do is require this module as shown in the examples below. |
---|
9 | |
---|
10 | <script language="JavaScript" type="text/javascript"> |
---|
11 | dojo.require("dojox.mobile.migrationAssist"); |
---|
12 | dojo.require("dojox.mobile"); // This is a mobile app. |
---|
13 | .... |
---|
14 | </script> |
---|
15 | |
---|
16 | <script language="JavaScript" type="text/javascript"> |
---|
17 | require([ |
---|
18 | "dojox/mobile/migrationAssist", |
---|
19 | "dojox/mobile", // This is a mobile app. |
---|
20 | .... |
---|
21 | ]); |
---|
22 | </script> |
---|
23 | |
---|
24 | If your application uses deprecated or no longer available functions, |
---|
25 | this module detects them and displays messages in the browser console. |
---|
26 | |
---|
27 | Also, it tries to dynamically fix them as much as possible so that |
---|
28 | the target application can work somehow. |
---|
29 | |
---|
30 | Note, however, that the purpose of migrationAssist is not to |
---|
31 | run the older applications as they are, but to assist migration. |
---|
32 | |
---|
33 | |
---|
34 | Changes from 1.6/1.7 to 1.8 |
---|
35 | =========================== |
---|
36 | |
---|
37 | Carousel |
---|
38 | -------- |
---|
39 | - Carousel has no backward compatibility, since it was experimental in 1.7. |
---|
40 | There are two subclasses that support data stores. |
---|
41 | Use DataCarousel if you want to use carousel with dojo/data. |
---|
42 | Use StoreCarousel if you want to use carousel with dojo/store. |
---|
43 | |
---|
44 | FixedSplitter |
---|
45 | ------------- |
---|
46 | - FixedSplitter.css is no longer in the themes/common folder. |
---|
47 | It is in the device theme folder. (e.g. themes/iphone/FixedSplitter.css) |
---|
48 | |
---|
49 | FlippableView |
---|
50 | ------------- |
---|
51 | - FlippableView was deprecated in 1.7, and removed in 1.8. Use SwapView instead. |
---|
52 | |
---|
53 | ListItem |
---|
54 | -------- |
---|
55 | - The sync property is no longer supported. It always behaves asynchronously. |
---|
56 | - The btnClass property is no longer supported. Use rightIcon instead. |
---|
57 | - The btnClass2 property is no longer supported. Use rightIcon2 instead. |
---|
58 | |
---|
59 | SpinWheel |
---|
60 | --------- |
---|
61 | - SpinWheel.css is no longer in the themes/common folder. |
---|
62 | It is in the device theme folder. (e.g. themes/iphone/SpinWheel.css) |
---|
63 | - getValue() is no longer supported. Use get("values") instead. |
---|
64 | - setValue() is no longer supported. Use set("values", newValue) instead. |
---|
65 | |
---|
66 | SpinWheelSlot |
---|
67 | ------------- |
---|
68 | - getValue() is no longer supported. Use get("value") instead. |
---|
69 | - getKey() is no longer supported. Use get("key") instead. |
---|
70 | - setValue() is no longer supported. Use set("value", newValue) instead. |
---|
71 | |
---|
72 | Switch |
---|
73 | ------ |
---|
74 | - When you place it in a ListItem, class="mblItemSwitch" is no longer necessary. |
---|
75 | |
---|
76 | TabBar |
---|
77 | ------ |
---|
78 | - In 1.7 or older, barType="segmentedControl" produced different UIs according to the |
---|
79 | current theme. In the iphone theme, it was a segmented control, but in other themes, |
---|
80 | it was tabs with or without icons. In 1.8, however, barType="segmentedControl" |
---|
81 | always produces a segmented control UI regardless of the current theme. |
---|
82 | If you still need the old behavior, |
---|
83 | barType:{"iphone_theme":"segmentedControl","*":"tallTab"} |
---|
84 | should produce a segmented control for the iphone theme, and a tall tab bar for |
---|
85 | the other themes. You need to use deviceTheme.js to specify barType that way. |
---|
86 | Also, if you want to hide the tab icons on the segmented control in the iphone theme, |
---|
87 | you could apply a css like this: |
---|
88 | <style> |
---|
89 | .iphone_theme .mblTabBarSegmentedControl .mblTabBarButtonIconArea { |
---|
90 | display: none; |
---|
91 | } |
---|
92 | </style> |
---|
93 | See test_ScrollableView-demo.html for an example usage. |
---|
94 | |
---|
95 | TabBarButton |
---|
96 | ------------- |
---|
97 | - Specifying a DOM Button with the class attribute like class="mblDomButtonWhitePlus" |
---|
98 | is no longer supported. Use icon="mblDomButtonWhitePlus" instead. |
---|
99 | - select() and deselect() are no longer supported. Use set("selected", boolean) instead. |
---|
100 | |
---|
101 | ToolBarButton |
---|
102 | ------------- |
---|
103 | - Specifying the button color style with the class attribute like class="mblColorBlue" |
---|
104 | is no longer supported. Use defaultColor="mblColorBlue" instead. |
---|
105 | - Specifying a DOM Button with the class attribute like class="mblDomButtonWhitePlus" |
---|
106 | is no longer supported. Use icon="mblDomButtonWhitePlus" instead. |
---|
107 | - select() and deselect() are no longer supported. Use set("selected", boolean) instead. |
---|
108 | |
---|
109 | dojox/mobile/parser |
---|
110 | ------------------- |
---|
111 | - dojox/mobile/parser no longer accepts array-type attribute like |
---|
112 | labels="['A','B','C','D','E']" |
---|
113 | Instead, you should specify like labels="A,B,C,D,E", which is the format dojo/parser |
---|
114 | accepts. |
---|
115 | |
---|
116 | bookmarkable |
---|
117 | ------------ |
---|
118 | - To enable the bookmarkable feature, require dojox/mobile/bookmarkable |
---|
119 | instead of dojo/hash |
---|
120 | |
---|
121 | */ |
---|
122 | |
---|
123 | define([ |
---|
124 | "dojo/_base/declare", |
---|
125 | "dojo/_base/lang", |
---|
126 | "dojo/_base/window", |
---|
127 | "dojo/dom-class", |
---|
128 | "dojo/dom-construct", |
---|
129 | "dojo/dom-style", |
---|
130 | "dojo/ready", |
---|
131 | "dijit/_Container", |
---|
132 | "dijit/_WidgetBase", |
---|
133 | "./_ItemBase", |
---|
134 | "./common", |
---|
135 | "./FixedSplitterPane", |
---|
136 | "./Heading", |
---|
137 | "./iconUtils", |
---|
138 | "./ListItem", |
---|
139 | "./RoundRect", |
---|
140 | "./SpinWheel", |
---|
141 | "./SpinWheelSlot", |
---|
142 | "./SwapView", |
---|
143 | "./TabBarButton", |
---|
144 | "./ToolBarButton", |
---|
145 | "./View" |
---|
146 | ], function(declare, lang, win, domClass, domConstruct, domStyle, ready, Container, WidgetBase, _ItemBase, mobile, FixedSplitterPane, Heading, iconUtils, ListItem, RoundRect, SpinWheel, SpinWheelSlot, SwapView, TabBarButton, ToolBarButton, View){ |
---|
147 | |
---|
148 | // module: |
---|
149 | // dojox/mobile/migrationAssist |
---|
150 | |
---|
151 | var currentTheme; |
---|
152 | |
---|
153 | var MigrationAssist = function(){ |
---|
154 | // summary: |
---|
155 | // Dojo Mobile 1.6/1.7 to 1.8 migration assistance. |
---|
156 | |
---|
157 | var get = function(w, key){ |
---|
158 | return w[key] || w.srcNodeRef && w.srcNodeRef.getAttribute(key); |
---|
159 | }; |
---|
160 | |
---|
161 | this.dispatch = function(/*String*/cls, /*Widget*/ w){ |
---|
162 | var base = cls.replace(/.*\./, ""); |
---|
163 | this["check" + base] && this["check" + base](w); |
---|
164 | }; |
---|
165 | |
---|
166 | this.checkCarousel = function(/*Widget*/ w){ |
---|
167 | 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.'); |
---|
168 | }; |
---|
169 | |
---|
170 | this.checkFixedSplitter = function(/*Widget*/ w){ |
---|
171 | // FixedSplitter.css has been moved from the themes/common folder |
---|
172 | // to the device theme folder such as themes/android. |
---|
173 | if(!this._fixedSplitter_css_checked){ |
---|
174 | this._fixedSplitter_css_checked = true; |
---|
175 | var dummy = domConstruct.create("div", { |
---|
176 | className: "mblFixedSplitter" |
---|
177 | }, win.body()); |
---|
178 | if(domStyle.get(dummy, "height") == 0){ |
---|
179 | domConstruct.create("link", { |
---|
180 | href: "../themes/android/FixedSplitter.css", |
---|
181 | type: "text/css", |
---|
182 | rel: "stylesheet" |
---|
183 | }, win.doc.getElementsByTagName('head')[0]); |
---|
184 | 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.'); |
---|
185 | } |
---|
186 | win.body().removeChild(dummy); |
---|
187 | setTimeout(function(){ |
---|
188 | w.resize(); |
---|
189 | }, 1000); |
---|
190 | } |
---|
191 | }; |
---|
192 | |
---|
193 | this.checkFixedSplitterPane = function(/*Widget*/ w){ |
---|
194 | console.log('[MIG:fixed] FixedSplitterPane: Deprecated. Use dojox/mobile/Container instead.'); |
---|
195 | }; |
---|
196 | this.checkFixedSplitter = function(/*Widget*/ w){ |
---|
197 | // FixedSplitter.css has been moved from the themes/common folder |
---|
198 | // to the device theme folder such as themes/android. |
---|
199 | if(!this._fixedSplitter_css_checked){ |
---|
200 | this._fixedSplitter_css_checked = true; |
---|
201 | var dummy = domConstruct.create("div", { |
---|
202 | className: "mblFixedSplitter" |
---|
203 | }, win.body()); |
---|
204 | if(domStyle.get(dummy, "height") == 0){ |
---|
205 | domConstruct.create("link", { |
---|
206 | href: "../themes/android/FixedSplitter.css", |
---|
207 | type: "text/css", |
---|
208 | rel: "stylesheet" |
---|
209 | }, win.doc.getElementsByTagName('head')[0]); |
---|
210 | 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.'); |
---|
211 | } |
---|
212 | win.body().removeChild(dummy); |
---|
213 | setTimeout(function(){ |
---|
214 | w.resize(); |
---|
215 | }, 1000); |
---|
216 | } |
---|
217 | }; |
---|
218 | |
---|
219 | this.checkListItem = function(/*Widget*/ w){ |
---|
220 | if(w.sync !== undefined || w.srcNodeRef && w.srcNodeRef.getAttribute("sync")){ |
---|
221 | console.log('[MIG:fixed] ListItem: The sync property is no longer supported. (async always)'); |
---|
222 | } |
---|
223 | if(w.btnClass !== undefined || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass")){ |
---|
224 | console.log('[MIG:fixed] ListItem: The btnClass property is no longer supported. Use rightIcon instead.'); |
---|
225 | w.rightIcon = w.btnClass || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass"); |
---|
226 | } |
---|
227 | if(w.btnClass2 !== undefined || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass2")){ |
---|
228 | console.log('[MIG:fixed] ListItem: The btnClass2 property is no longer supported. Use rightIcon2 instead.'); |
---|
229 | w.rightIcon2 = w.btnClass2 || w.srcNodeRef && w.srcNodeRef.getAttribute("btnClass2"); |
---|
230 | } |
---|
231 | }; |
---|
232 | |
---|
233 | this.checkSpinWheelSlot = function(/*Widget*/ w){ |
---|
234 | if(w.labels && w.labels[0] && w.labels[0].charAt(0) === '['){ |
---|
235 | for(var i = 0; i < w.labels.length; i++){ |
---|
236 | w.labels[i] = w.labels[i].replace(/^\[*[\'\"]*/, ''); |
---|
237 | w.labels[i] = w.labels[i].replace(/[\'\"]*\]*$/, ''); |
---|
238 | } |
---|
239 | 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.' ); |
---|
240 | } |
---|
241 | }; |
---|
242 | |
---|
243 | this.checkSwapView = function(/*Widget*/ w){ |
---|
244 | var n = w.srcNodeRef; |
---|
245 | if(n){ |
---|
246 | var type = n.getAttribute("dojoType") || n.getAttribute("data-dojo-type"); |
---|
247 | if(type === "dojox.mobile.FlippableView"){ |
---|
248 | console.log('[MIG:fixed] FlippableView: FlippableView is no longer supported. Use SwapView instead.'); |
---|
249 | } |
---|
250 | } |
---|
251 | }; |
---|
252 | |
---|
253 | this.checkSwitch = function(/*Widget*/ w){ |
---|
254 | if(w["class"] === "mblItemSwitch"){ |
---|
255 | console.log('[MIG:fixed] Switch: class="mblItemSwitch" is no longer necessary.'); |
---|
256 | } |
---|
257 | }; |
---|
258 | |
---|
259 | this.checkTabBar = function(/*Widget*/ w){ |
---|
260 | if(get(w, "barType") === "segmentedControl"){ |
---|
261 | 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.'); |
---|
262 | domConstruct.create("style", { |
---|
263 | innerHTML: ".iphone_theme .mblTabBarSegmentedControl .mblTabBarButtonIconArea { display: none; }" |
---|
264 | }, win.doc.getElementsByTagName('head')[0]); |
---|
265 | } |
---|
266 | }; |
---|
267 | |
---|
268 | this.checkTabBarButton = function(/*Widget*/ w){ |
---|
269 | if((w["class"] || "").indexOf("mblDomButton") === 0){ |
---|
270 | console.log('[MIG:fixed] TabBarButton: Use icon="' + w["class"] + '" instead of class="' + w["class"] + '".'); |
---|
271 | w.icon = w["class"]; |
---|
272 | w["class"] = ""; |
---|
273 | if(w.srcNodeRef){ |
---|
274 | w.srcNodeRef.className = ""; |
---|
275 | } |
---|
276 | } |
---|
277 | }; |
---|
278 | |
---|
279 | this.checkToolBarButton = function(/*Widget*/ w){ |
---|
280 | if((w["class"] || "").indexOf("mblColor") === 0){ |
---|
281 | console.log('[MIG:fixed] ToolBarButton: Use defaultColor="' + w["class"] + '" instead of class="' + w["class"] + '".'); |
---|
282 | w.defaultColor = w["class"]; |
---|
283 | w["class"] = ""; |
---|
284 | if(w.srcNodeRef){ |
---|
285 | w.srcNodeRef.className = ""; |
---|
286 | } |
---|
287 | } |
---|
288 | |
---|
289 | if((w["class"] || "").indexOf("mblDomButton") === 0){ |
---|
290 | console.log('[MIG:fixed] ToolBarButton: Use icon="' + w["class"] + '" instead of class="' + w["class"] + '".'); |
---|
291 | w.icon = w["class"]; |
---|
292 | w["class"] = ""; |
---|
293 | if(w.srcNodeRef){ |
---|
294 | w.srcNodeRef.className = ""; |
---|
295 | } |
---|
296 | } |
---|
297 | }; |
---|
298 | }; |
---|
299 | |
---|
300 | dojox.mobile.FlippableView = SwapView; |
---|
301 | |
---|
302 | var migrationAssist = new MigrationAssist(); |
---|
303 | |
---|
304 | // Hide from the API doc tool, we want to get the documentation for the normal WidgetBase.postMixInProperties() |
---|
305 | WidgetBase.prototype.postMixInProperties = /*===== WidgetBase.prototype.postMixInProperties || =====*/ function(){ |
---|
306 | migrationAssist.dispatch(this.declaredClass, this); |
---|
307 | dojo.forEach([FixedSplitterPane, Heading, RoundRect, SpinWheel, TabBarButton, ToolBarButton, View], function(module){ |
---|
308 | if(this.declaredClass !== module.prototype.declaredClass && this instanceof module){ |
---|
309 | migrationAssist.dispatch(module.prototype.declaredClass, this); |
---|
310 | } |
---|
311 | }, this); |
---|
312 | |
---|
313 | }; |
---|
314 | |
---|
315 | |
---|
316 | extendSelectFunction = function(obj) { |
---|
317 | lang.extend(obj, { |
---|
318 | select: function(){ |
---|
319 | console.log('[MIG:fixed] ' + this.declaredClass + '(id='+this.id+'): Use set("selected", boolean) instead of select/deselect.'); |
---|
320 | obj.prototype.set.apply(this, ["selected", !arguments[0]]); |
---|
321 | }, |
---|
322 | deselect: function(){ |
---|
323 | this.select(true); |
---|
324 | } |
---|
325 | }); |
---|
326 | }; |
---|
327 | |
---|
328 | extendSelectFunction(ToolBarButton); |
---|
329 | extendSelectFunction(TabBarButton); |
---|
330 | |
---|
331 | lang.extend(ListItem, { |
---|
332 | set: function(key, value){ |
---|
333 | if(key === "btnClass"){ |
---|
334 | console.log('[MIG:fixed] ' + this.declaredClass + '(id='+this.id+'): Use set("rightIcon",x) instead of set("btnClass",x).'); |
---|
335 | key = "rightIcon"; |
---|
336 | }else if(key === "btnClass2"){ |
---|
337 | console.log('[MIG:fixed] ' + this.declaredClass + '(id='+this.id+'): Use set("rightIcon2",x) instead of set("btnClass2",x).'); |
---|
338 | key = "rightIcon2"; |
---|
339 | } |
---|
340 | WidgetBase.prototype.set.apply(this, [key, value]); |
---|
341 | } |
---|
342 | }); |
---|
343 | |
---|
344 | lang.extend(SpinWheel, { |
---|
345 | getValue: function(){ |
---|
346 | console.log('[MIG:fixed] SpinWheel: getValue() is no longer supported. Use get("values") instead.'); |
---|
347 | return this.get("values"); |
---|
348 | }, |
---|
349 | setValue: function(newValue){ |
---|
350 | console.log('[MIG:fixed] SpinWheel: setValue() is no longer supported. Use set("values",x) instead.'); |
---|
351 | return this.set("values", newValue); |
---|
352 | } |
---|
353 | }); |
---|
354 | |
---|
355 | lang.extend(SpinWheelSlot, { |
---|
356 | getValue: function(){ |
---|
357 | console.log('[MIG:fixed] SpinWheelSlot: getValue() is no longer supported. Use get("value") instead.'); |
---|
358 | return this.get("value"); |
---|
359 | }, |
---|
360 | getKey: function(){ |
---|
361 | console.log('[MIG:fixed] SpinWheelSlot: getKey() is no longer supported. Use get("key") instead.'); |
---|
362 | return this.get("key"); |
---|
363 | }, |
---|
364 | setValue: function(newValue){ |
---|
365 | console.log('[MIG:fixed] SpinWheelSlot: setValue() is no longer supported. Use set("value",x) instead.'); |
---|
366 | return this.set("value", newValue); |
---|
367 | } |
---|
368 | }); |
---|
369 | |
---|
370 | lang.mixin(mobile, { |
---|
371 | createDomButton: function(){ |
---|
372 | console.log('[MIG:fixed] dojox.mobile(id='+arguments[0].id+'): createDomButton was moved to iconUtils.'); |
---|
373 | return iconUtils.createDomButton.apply(this, arguments); |
---|
374 | } |
---|
375 | }); |
---|
376 | |
---|
377 | // check css |
---|
378 | var cssFiles = [], i, j; |
---|
379 | |
---|
380 | // collect @import |
---|
381 | var s = win.doc.styleSheets; |
---|
382 | for(i = 0; i < s.length; i++){ |
---|
383 | if(s[i].href){ continue; } |
---|
384 | var r = s[i].cssRules || s[i].imports; |
---|
385 | if(!r){ continue; } |
---|
386 | for(j = 0; j < r.length; j++){ |
---|
387 | if(r[j].href){ |
---|
388 | cssFiles.push(r[j].href); |
---|
389 | } |
---|
390 | } |
---|
391 | } |
---|
392 | |
---|
393 | // collect <link> |
---|
394 | var elems = win.doc.getElementsByTagName("link"); |
---|
395 | for(i = 0; i < elems.length; i++){ |
---|
396 | cssFiles.push(elems[i].href); |
---|
397 | } |
---|
398 | |
---|
399 | for(i = 0; i < cssFiles.length; i++){ |
---|
400 | if(cssFiles[i].indexOf("/iphone/") !== -1){ |
---|
401 | currentTheme = "iphone"; |
---|
402 | }else if(cssFiles[i].indexOf("/android/") !== -1){ |
---|
403 | currentTheme = "android"; |
---|
404 | }else if(cssFiles[i].indexOf("/blackberry/") !== -1){ |
---|
405 | currentTheme = "blackberry"; |
---|
406 | }else if(cssFiles[i].indexOf("/custom/") !== -1){ |
---|
407 | currentTheme = "custom"; |
---|
408 | } |
---|
409 | domClass.add(win.doc.documentElement, currentTheme + "_theme"); |
---|
410 | |
---|
411 | if(cssFiles[i].match(/themes\/common\/(FixedSplitter.css)|themes\/common\/(SpinWheel.css)/)){ |
---|
412 | console.log('[MIG:error] ' + (RegExp.$1 || RegExp.$2) + ' is no longer in the themes/common folder. It is in the device theme folder.'); |
---|
413 | } |
---|
414 | } |
---|
415 | |
---|
416 | ready(function(){ |
---|
417 | if(dojo.hash){ |
---|
418 | console.log('[MIG:fixed] dojo/hash detected. If you would like to enable the bookmarkable feature, require dojox/mobile/bookmarkable instead of dojo/hash'); |
---|
419 | if(dojo.require){ |
---|
420 | dojo["require"]("dojox.mobile.bookmarkable"); |
---|
421 | }else{ |
---|
422 | require(["dojox/mobile/bookmarkable"]); |
---|
423 | } |
---|
424 | } |
---|
425 | }); |
---|
426 | |
---|
427 | // Return singleton. (TODO: can we replace LazyLoadUtils class and singleton w/a simple hash of functions?) |
---|
428 | return migrationAssist; |
---|
429 | }); |
---|