1 | define([ |
---|
2 | "dojo/_base/declare", |
---|
3 | "dojo/_base/window", |
---|
4 | "dojo/dom-class", |
---|
5 | "dojo/dom-attr", |
---|
6 | "dojo/dom-construct", |
---|
7 | "dojo/on", |
---|
8 | "dojo/touch", |
---|
9 | "dijit/registry", |
---|
10 | "./Pane", |
---|
11 | "./iconUtils", |
---|
12 | "./sniff" |
---|
13 | ], function(declare, win, domClass, domAttr, domConstruct, on, touch, registry, Pane, iconUtils, has){ |
---|
14 | // module: |
---|
15 | // dojox/mobile/SimpleDialog |
---|
16 | |
---|
17 | return declare("dojox.mobile.SimpleDialog", Pane, { |
---|
18 | // summary: |
---|
19 | // A dialog box for mobile. |
---|
20 | // description: |
---|
21 | // SimpleDialog is a dialog box for mobile. |
---|
22 | // When a SimpleDialog is created, it is initially hidden |
---|
23 | // (display="none"). To show the dialog box, you need to |
---|
24 | // get a reference to the widget and to call its show() method. |
---|
25 | // |
---|
26 | // The contents can be arbitrary HTML, text, or widgets. Note, |
---|
27 | // however, that the widget is initially hidden. You need to be |
---|
28 | // careful when you place in a SimpleDialog elements that cannot |
---|
29 | // be initialized in hidden state. |
---|
30 | // |
---|
31 | // This widget has much less functionalities than dijit/Dialog, |
---|
32 | // but it has the advantage of a much smaller code size. |
---|
33 | |
---|
34 | // top: String |
---|
35 | // The top edge position of the widget. If "auto", the widget is |
---|
36 | // placed at the middle of the screen. Otherwise, the value |
---|
37 | // (ex. "20px") is used as the top style of widget's domNode. |
---|
38 | top: "auto", |
---|
39 | |
---|
40 | // left: String |
---|
41 | // The left edge position of the widget. If "auto", the widget is |
---|
42 | // placed at the center of the screen. Otherwise, the value |
---|
43 | // (ex. "20px") is used as the left style of widget's domNode. |
---|
44 | left: "auto", |
---|
45 | |
---|
46 | // modal: Boolean |
---|
47 | // If true, a translucent cover is added over the entire page to |
---|
48 | // prevent the user from interacting with elements on the page. |
---|
49 | modal: true, |
---|
50 | |
---|
51 | // closeButton: [const] Boolean |
---|
52 | // If true, a button to close the dialog box is displayed at the |
---|
53 | // top-right corner. |
---|
54 | // Note that changing the value of the property after the widget |
---|
55 | // creation has no effect. |
---|
56 | closeButton: false, |
---|
57 | |
---|
58 | // closeButtonClass: String |
---|
59 | // A class name of a DOM button to be used as a close button. |
---|
60 | closeButtonClass: "mblDomButtonSilverCircleRedCross", |
---|
61 | |
---|
62 | // tabIndex: String |
---|
63 | // Tabindex setting for the item so users can hit the tab key to |
---|
64 | // focus on it. |
---|
65 | tabIndex: "0", |
---|
66 | |
---|
67 | // _setTabIndexAttr: [private] String |
---|
68 | // Sets tabIndex to domNode. |
---|
69 | _setTabIndexAttr: "", |
---|
70 | |
---|
71 | /* internal properties */ |
---|
72 | |
---|
73 | // baseClass: String |
---|
74 | // The name of the CSS class of this widget. |
---|
75 | baseClass: "mblSimpleDialog", |
---|
76 | |
---|
77 | // _cover: [private] Array |
---|
78 | // Array for sharing the cover instances. |
---|
79 | _cover: [], |
---|
80 | |
---|
81 | buildRendering: function(){ |
---|
82 | this.containerNode = domConstruct.create("div", {className:"mblSimpleDialogContainer"}); |
---|
83 | if(this.srcNodeRef){ |
---|
84 | // reparent |
---|
85 | for(var i = 0, len = this.srcNodeRef.childNodes.length; i < len; i++){ |
---|
86 | this.containerNode.appendChild(this.srcNodeRef.removeChild(this.srcNodeRef.firstChild)); |
---|
87 | } |
---|
88 | } |
---|
89 | this.inherited(arguments); |
---|
90 | domAttr.set(this.domNode, "role", "dialog"); |
---|
91 | |
---|
92 | if(this.containerNode.getElementsByClassName){ //TODO: Do we need to support IE8 a11y? |
---|
93 | var titleNode = this.containerNode.getElementsByClassName("mblSimpleDialogTitle")[0]; |
---|
94 | if (titleNode){ |
---|
95 | titleNode.id = titleNode.id || registry.getUniqueId("dojo_mobile_mblSimpleDialogTitle"); |
---|
96 | domAttr.set(this.domNode, "aria-labelledby", titleNode.id); |
---|
97 | } |
---|
98 | var textNode = this.containerNode.getElementsByClassName("mblSimpleDialogText")[0]; |
---|
99 | if (textNode){ |
---|
100 | textNode.id = textNode.id || registry.getUniqueId("dojo_mobile_mblSimpleDialogText"); |
---|
101 | domAttr.set(this.domNode, "aria-describedby", textNode.id); |
---|
102 | } |
---|
103 | } |
---|
104 | domClass.add(this.domNode, "mblSimpleDialogDecoration"); |
---|
105 | this.domNode.style.display = "none"; |
---|
106 | this.domNode.appendChild(this.containerNode); |
---|
107 | if(this.closeButton){ |
---|
108 | this.closeButtonNode = domConstruct.create("div", { |
---|
109 | className: "mblSimpleDialogCloseBtn "+this.closeButtonClass |
---|
110 | }, this.domNode); |
---|
111 | iconUtils.createDomButton(this.closeButtonNode); |
---|
112 | this.connect(this.closeButtonNode, "onclick", "_onCloseButtonClick"); |
---|
113 | } |
---|
114 | this.connect(this.domNode, "onkeydown", "_onKeyDown"); // for desktop browsers |
---|
115 | }, |
---|
116 | |
---|
117 | startup: function(){ |
---|
118 | if(this._started){ return; } |
---|
119 | this.inherited(arguments); |
---|
120 | win.body().appendChild(this.domNode); |
---|
121 | }, |
---|
122 | |
---|
123 | addCover: function(){ |
---|
124 | // summary: |
---|
125 | // Adds the transparent DIV cover. |
---|
126 | if(!this._cover[0]){ |
---|
127 | this._cover[0] = domConstruct.create("div", { |
---|
128 | className: "mblSimpleDialogCover" |
---|
129 | }, win.body()); |
---|
130 | }else{ |
---|
131 | this._cover[0].style.display = ""; |
---|
132 | } |
---|
133 | |
---|
134 | if(has("windows-theme")) { |
---|
135 | // Hack to prevent interaction with elements placed under cover div. |
---|
136 | this.own(on(this._cover[0], touch.press, function() {})); |
---|
137 | } |
---|
138 | }, |
---|
139 | |
---|
140 | removeCover: function(){ |
---|
141 | // summary: |
---|
142 | // Removes the transparent DIV cover. |
---|
143 | this._cover[0].style.display = "none"; |
---|
144 | }, |
---|
145 | |
---|
146 | _onCloseButtonClick: function(e){ |
---|
147 | // tags: |
---|
148 | // private |
---|
149 | if(this.onCloseButtonClick(e) === false){ return; } // user's click action |
---|
150 | this.hide(); |
---|
151 | }, |
---|
152 | |
---|
153 | onCloseButtonClick: function(/*Event*/ /*===== e =====*/){ |
---|
154 | // summary: |
---|
155 | // User-defined function to handle clicks. |
---|
156 | // tags: |
---|
157 | // callback |
---|
158 | }, |
---|
159 | |
---|
160 | _onKeyDown: function(e){ |
---|
161 | // tags: |
---|
162 | // private |
---|
163 | if(e.keyCode == 27){ // ESC |
---|
164 | this.hide(); |
---|
165 | } |
---|
166 | }, |
---|
167 | |
---|
168 | refresh: function(){ // TODO: should we call refresh on resize? |
---|
169 | // summary: |
---|
170 | // Refreshes the layout of the dialog. |
---|
171 | var n = this.domNode; |
---|
172 | var h; |
---|
173 | if(this.closeButton){ |
---|
174 | var b = this.closeButtonNode; |
---|
175 | var s = Math.round(b.offsetHeight / 2); |
---|
176 | b.style.top = -s + "px"; |
---|
177 | b.style.left = n.offsetWidth - s + "px"; |
---|
178 | } |
---|
179 | if(this.top === "auto"){ |
---|
180 | h = win.global.innerHeight || win.doc.documentElement.clientHeight; |
---|
181 | n.style.top = Math.round((h - n.offsetHeight) / 2) + "px"; |
---|
182 | }else{ |
---|
183 | n.style.top = this.top; |
---|
184 | } |
---|
185 | if(this.left === "auto"){ |
---|
186 | h = win.global.innerWidth || win.doc.documentElement.clientWidth; |
---|
187 | n.style.left = Math.round((h - n.offsetWidth) / 2) + "px"; |
---|
188 | }else{ |
---|
189 | n.style.left = this.left; |
---|
190 | } |
---|
191 | }, |
---|
192 | |
---|
193 | show: function(){ |
---|
194 | // summary: |
---|
195 | // Shows the dialog. |
---|
196 | if(this.domNode.style.display === ""){ return; } |
---|
197 | if(this.modal){ |
---|
198 | this.addCover(); |
---|
199 | } |
---|
200 | this.domNode.style.display = ""; |
---|
201 | this.resize(); // #15628 |
---|
202 | this.refresh(); |
---|
203 | var diaglogButton; |
---|
204 | if(this.domNode.getElementsByClassName){ |
---|
205 | diaglogButton = this.domNode.getElementsByClassName("mblSimpleDialogButton")[0]; |
---|
206 | } |
---|
207 | var focusNode = diaglogButton || this.closeButtonNode || this.domNode; // Focus preference is: user supplied button, close button, entire dialog |
---|
208 | /// on Safari iOS the focus is not taken without a timeout |
---|
209 | this.defer(function(){ focusNode.focus();}, 1000); |
---|
210 | }, |
---|
211 | |
---|
212 | hide: function(){ |
---|
213 | // summary: |
---|
214 | // Hides the dialog. |
---|
215 | if(this.domNode.style.display === "none"){ return; } |
---|
216 | this.domNode.style.display = "none"; |
---|
217 | if(this.modal){ |
---|
218 | this.removeCover(); |
---|
219 | } |
---|
220 | } |
---|
221 | }); |
---|
222 | }); |
---|