1 | define([ |
---|
2 | "dojo/_base/kernel", |
---|
3 | "dojo/_base/array", |
---|
4 | "dojo/_base/config", |
---|
5 | "dojo/_base/connect", |
---|
6 | "dojo/_base/declare", |
---|
7 | "dojo/_base/lang", |
---|
8 | "dojo/_base/window", |
---|
9 | "dojo/dom", |
---|
10 | "dijit/registry" |
---|
11 | ], function(kernel, array, config, connect, declare, lang, win, dom, registry){ |
---|
12 | |
---|
13 | // module: |
---|
14 | // dojox/mobile/ScreenSizeAware |
---|
15 | |
---|
16 | kernel.experimental("dojox.mobile.ScreenSizeAware"); // should consider support for other UI layout patterns |
---|
17 | |
---|
18 | var cls = declare("dojox.mobile.ScreenSizeAware", null, { |
---|
19 | // summary: |
---|
20 | // A module to make a screen size aware application. |
---|
21 | // description: |
---|
22 | // This module helps for creating applications that transform their |
---|
23 | // UI layout according to the screen size. It assumes that the |
---|
24 | // application consists of two horizontally split panes, and the |
---|
25 | // left pane has a list widget. If you require this module in such an |
---|
26 | // application, in a tablet-sized screen, the application shows a horizontally |
---|
27 | // split view whose left pane is a list widget. |
---|
28 | // In a phone-sized screen, the application shows a list widget that fills the screen. |
---|
29 | // |
---|
30 | // example: |
---|
31 | // | <span data-dojo-type="dojox.mobile.ScreenSizeAware"></span> |
---|
32 | // | <div data-dojo-type="dojox.mobile.FixedSplitter" data-dojo-props='orientation:"H"'> |
---|
33 | // | <div data-dojo-type="dojox.mobile.Container" style="width:300px;"> |
---|
34 | // | <div id="leftView" data-dojo-type="dojox.mobile.ScrollableView"> |
---|
35 | // | <h1 data-dojo-type="dojox.mobile.Heading" data-dojo-props='fixed:"top"'>Left Pane</h1> |
---|
36 | // | <ul data-dojo-type="dojox.mobile.EdgeToEdgeList" data-dojo-props='stateful:true'> |
---|
37 | // | <li data-dojo-type="dojox.mobile.ListItem" data-dojo-props='label:"View1", moveTo:"view1"'></li> |
---|
38 | // | .... |
---|
39 | // | </ul> |
---|
40 | // | </div> |
---|
41 | // | </div> |
---|
42 | // | <div data-dojo-type="dojox.mobile.Container"> |
---|
43 | // | <div id="view1" data-dojo-type="dojox.mobile.ScrollableView"> |
---|
44 | // | <h1 data-dojo-type="dojox.mobile.Heading" data-dojo-props='fixed:"top", back:"Home", moveTo:"leftView"'>Right Pane</h1> |
---|
45 | // | .... |
---|
46 | // | </div> |
---|
47 | // | </div> |
---|
48 | // | </div> |
---|
49 | |
---|
50 | // splitterId: String |
---|
51 | // The id of the FixedSplitter. |
---|
52 | splitterId: "", |
---|
53 | |
---|
54 | // leftPaneId: String |
---|
55 | // The id of the left pane. |
---|
56 | leftPaneId: "", |
---|
57 | |
---|
58 | // rightPaneId: String |
---|
59 | // The id of the right pane. |
---|
60 | rightPaneId: "", |
---|
61 | |
---|
62 | // leftViewId: String |
---|
63 | // The id of the left View. |
---|
64 | leftViewId: "", |
---|
65 | |
---|
66 | // leftListId: String |
---|
67 | // The id of the list widget in the left view. |
---|
68 | leftListId: "", |
---|
69 | |
---|
70 | constructor: function(/*Object?*/options){ |
---|
71 | // summary: |
---|
72 | // Creates a new instance of the class. |
---|
73 | // options: |
---|
74 | // Contains properties to be set. |
---|
75 | if (options){ |
---|
76 | lang.mixin(this, options); |
---|
77 | } |
---|
78 | connect.subscribe("/dojox/mobile/screenSize/tablet", this, function(dim){ |
---|
79 | this.transformUI("tablet"); |
---|
80 | }); |
---|
81 | connect.subscribe("/dojox/mobile/screenSize/phone", this, function(dim){ |
---|
82 | this.transformUI("phone"); |
---|
83 | }); |
---|
84 | }, |
---|
85 | |
---|
86 | init: function(){ |
---|
87 | // summary: |
---|
88 | // Initializes the application. |
---|
89 | if(this._initialized){ return; } |
---|
90 | this._initialized = true; |
---|
91 | |
---|
92 | // analyze the page structure |
---|
93 | this.splitter = this.splitterId ? registry.byId(this.splitterId) : |
---|
94 | array.filter(registry.findWidgets(win.body()), |
---|
95 | function(c){ return c.declaredClass.indexOf("Splitter") !== -1; })[0]; |
---|
96 | if(!this.splitter){ |
---|
97 | console.error("Splitter not found."); |
---|
98 | return; |
---|
99 | } |
---|
100 | |
---|
101 | this.leftPane = this.leftPaneId ? registry.byId(this.leftPaneId) : |
---|
102 | this.splitter.getChildren()[0]; |
---|
103 | if(!this.leftPane){ |
---|
104 | console.error("Left pane not found."); |
---|
105 | return; |
---|
106 | } |
---|
107 | |
---|
108 | this.rightPane = this.rightPaneId ? registry.byId(this.rightPaneId) : |
---|
109 | this.splitter.getChildren()[1]; |
---|
110 | if(!this.rightPane){ |
---|
111 | console.error("Right pane not found."); |
---|
112 | return; |
---|
113 | } |
---|
114 | |
---|
115 | this.leftView = this.leftViewId ? registry.byId(this.leftViewId) : |
---|
116 | array.filter(registry.findWidgets(this.leftPane.containerNode), |
---|
117 | function(c){ return c.declaredClass.indexOf("View") !== -1; })[0]; |
---|
118 | if(!this.leftView){ |
---|
119 | console.error("Left view not found."); |
---|
120 | return; |
---|
121 | } |
---|
122 | |
---|
123 | this.leftList = this.leftListId ? registry.byId(this.leftListId) : |
---|
124 | array.filter(registry.findWidgets(this.leftView.containerNode), |
---|
125 | function(c){ return c.declaredClass.indexOf("List") !== -1 || |
---|
126 | c.declaredClass.indexOf("IconContainer") !== -1; })[0]; |
---|
127 | if(!this.leftList){ |
---|
128 | console.error("Left list not found."); |
---|
129 | return; |
---|
130 | } |
---|
131 | }, |
---|
132 | |
---|
133 | isPhone: function(){ |
---|
134 | // summary: |
---|
135 | // Returns true if the current mode set by transformUI(mode) is "phone". |
---|
136 | return this._currentMode === "phone"; // Boolean |
---|
137 | }, |
---|
138 | |
---|
139 | getShowingView: function(){ |
---|
140 | // summary: |
---|
141 | // Returns the view currently shown. |
---|
142 | var firstView = |
---|
143 | array.filter(this.rightPane.getChildren(), function(c){ return c.declaredClass.indexOf("View") !== -1; })[0]; |
---|
144 | if(!firstView){ return null; } |
---|
145 | return firstView.getShowingView() || |
---|
146 | array.filter(this.rightPane.getChildren(), function(c){ return c.selected; })[0] || |
---|
147 | firstView; |
---|
148 | }, |
---|
149 | |
---|
150 | updateStateful: function(){ |
---|
151 | // summary: |
---|
152 | // Updates the stateful property of the list widget in the left-side pane. |
---|
153 | this.leftList.set("stateful", !this.isPhone()); |
---|
154 | }, |
---|
155 | |
---|
156 | getDestinationId: function(item){ |
---|
157 | // summary: |
---|
158 | // Returns the id of the target view of the given item. |
---|
159 | return item.moveTo; |
---|
160 | }, |
---|
161 | |
---|
162 | updateBackButton: function(){ |
---|
163 | // summary: |
---|
164 | // Updates the back button. |
---|
165 | array.forEach(this.leftList.getChildren(), function(item){ |
---|
166 | var id = this.getDestinationId(item); |
---|
167 | var view = registry.byId(id); |
---|
168 | if(view){ |
---|
169 | var heading = array.filter(view.getChildren(), function(c){ return c.declaredClass.indexOf("Heading") !== -1; })[0]; |
---|
170 | if(heading.backButton){ |
---|
171 | heading.backButton.domNode.style.display = this.isPhone() ? "" : "none"; |
---|
172 | } |
---|
173 | if(heading.backBtnNode){ // TODO: remove this block later |
---|
174 | heading.backBtnNode.style.display = this.isPhone() ? "" : "none"; |
---|
175 | } |
---|
176 | } |
---|
177 | }, this); |
---|
178 | }, |
---|
179 | |
---|
180 | updateTransition: function(){ |
---|
181 | // summary: |
---|
182 | // Updates the transition property of the items in the left-side widget. |
---|
183 | var transition = this.isPhone() ? "slide" : "none"; |
---|
184 | array.forEach(this.leftList.getChildren(), function(item){ |
---|
185 | item.set("transition", transition); |
---|
186 | }); |
---|
187 | }, |
---|
188 | |
---|
189 | moveList: function(){ |
---|
190 | // summary: |
---|
191 | // Places the list widget. If the current mode is "phone", it |
---|
192 | // places the list widget in the right pane, otherwise in the left pane. |
---|
193 | var to = this.isPhone() ? this.rightPane: this.leftPane; |
---|
194 | to.containerNode.appendChild(this.leftView.domNode); |
---|
195 | }, |
---|
196 | |
---|
197 | showLeftView: function(){ |
---|
198 | // summary: |
---|
199 | // Shows the left-side view. |
---|
200 | this.leftPane.domNode.style.display = this.isPhone() ? "none" : ""; |
---|
201 | this.leftView.show(); |
---|
202 | }, |
---|
203 | |
---|
204 | showRightView: function(){ |
---|
205 | // summary: |
---|
206 | // Shows the right-side view. |
---|
207 | if(this.isPhone()){ return; } |
---|
208 | var view = this.getShowingView(); |
---|
209 | if(view){ |
---|
210 | view.show(); |
---|
211 | }else{ |
---|
212 | this.leftItemSelected(); |
---|
213 | } |
---|
214 | }, |
---|
215 | |
---|
216 | updateSelectedItem: function(){ |
---|
217 | // summary: |
---|
218 | // Updates the selected item. |
---|
219 | var id; |
---|
220 | var view = this.getShowingView(); |
---|
221 | if(view && !this.isPhone()){ |
---|
222 | id = view.id; |
---|
223 | } |
---|
224 | if(id){ |
---|
225 | var items = array.filter(this.leftList.getChildren(), |
---|
226 | function(item){ return this.getDestinationId(item) === id; }, this); |
---|
227 | if(items && items.length > 0){ |
---|
228 | items[0].set("selected", true); |
---|
229 | } |
---|
230 | }else{ |
---|
231 | this.leftList.deselectAll && this.leftList.deselectAll(); |
---|
232 | } |
---|
233 | }, |
---|
234 | |
---|
235 | leftItemSelected: function(/*Event*/ /*===== e =====*/){ |
---|
236 | // summary: |
---|
237 | // Function called when an item in the left-side list is selected. |
---|
238 | }, |
---|
239 | |
---|
240 | transformUI: function(/*String*/mode){ |
---|
241 | // summary: |
---|
242 | // Applies an UI mode. |
---|
243 | // mode: |
---|
244 | // If this argument is "phone", sets the UI in phone mode, otherwise |
---|
245 | // in tablet mode. |
---|
246 | this.init(); |
---|
247 | if(mode === this._currentMode){ return; } |
---|
248 | this._currentMode = mode; |
---|
249 | this.updateStateful(); |
---|
250 | this.updateBackButton(); |
---|
251 | this.updateTransition(); |
---|
252 | this.moveList(); |
---|
253 | this.showLeftView(); |
---|
254 | this.showRightView(); |
---|
255 | this.updateSelectedItem(); |
---|
256 | } |
---|
257 | }); |
---|
258 | |
---|
259 | cls._instance = null; |
---|
260 | cls.getInstance = function(){ |
---|
261 | if(!cls._instance){ |
---|
262 | cls._instance = new cls(); |
---|
263 | } |
---|
264 | return cls._instance; |
---|
265 | }; |
---|
266 | |
---|
267 | return cls; |
---|
268 | }); |
---|