| 1 |
efrain |
1 |
YUI.add('widget-modality', function (Y, NAME) {
|
|
|
2 |
|
|
|
3 |
/**
|
|
|
4 |
* Provides modality support for Widgets, though an extension
|
|
|
5 |
*
|
|
|
6 |
* @module widget-modality
|
|
|
7 |
*/
|
|
|
8 |
|
|
|
9 |
var WIDGET = 'widget',
|
|
|
10 |
RENDER_UI = 'renderUI',
|
|
|
11 |
BIND_UI = 'bindUI',
|
|
|
12 |
SYNC_UI = 'syncUI',
|
|
|
13 |
BOUNDING_BOX = 'boundingBox',
|
|
|
14 |
VISIBLE = 'visible',
|
|
|
15 |
Z_INDEX = 'zIndex',
|
|
|
16 |
CHANGE = 'Change',
|
|
|
17 |
isBoolean = Y.Lang.isBoolean,
|
|
|
18 |
getCN = Y.ClassNameManager.getClassName,
|
|
|
19 |
MaskShow = "maskShow",
|
|
|
20 |
MaskHide = "maskHide",
|
|
|
21 |
ClickOutside = "clickoutside",
|
|
|
22 |
FocusOutside = "focusoutside",
|
|
|
23 |
|
|
|
24 |
supportsPosFixed = (function(){
|
|
|
25 |
|
|
|
26 |
/*! IS_POSITION_FIXED_SUPPORTED - Juriy Zaytsev (kangax) - http://yura.thinkweb2.com/cft/ */
|
|
|
27 |
|
|
|
28 |
var doc = Y.config.doc,
|
|
|
29 |
isSupported = null,
|
|
|
30 |
el, root;
|
|
|
31 |
|
|
|
32 |
if (doc.createElement) {
|
|
|
33 |
el = doc.createElement('div');
|
|
|
34 |
if (el && el.style) {
|
|
|
35 |
el.style.position = 'fixed';
|
|
|
36 |
el.style.top = '10px';
|
|
|
37 |
root = doc.body;
|
|
|
38 |
if (root && root.appendChild && root.removeChild) {
|
|
|
39 |
root.appendChild(el);
|
|
|
40 |
isSupported = (el.offsetTop === 10);
|
|
|
41 |
root.removeChild(el);
|
|
|
42 |
}
|
|
|
43 |
}
|
|
|
44 |
}
|
|
|
45 |
|
|
|
46 |
return isSupported;
|
|
|
47 |
}());
|
|
|
48 |
|
|
|
49 |
/**
|
|
|
50 |
* Widget extension, which can be used to add modality support to the base Widget class,
|
|
|
51 |
* through the Base.create method.
|
|
|
52 |
*
|
|
|
53 |
* @class WidgetModality
|
|
|
54 |
* @param {Object} config User configuration object
|
|
|
55 |
*/
|
|
|
56 |
function WidgetModal(config) {}
|
|
|
57 |
|
|
|
58 |
var MODAL = 'modal',
|
|
|
59 |
MASK = 'mask',
|
|
|
60 |
MODAL_CLASSES = {
|
|
|
61 |
modal : getCN(WIDGET, MODAL),
|
|
|
62 |
mask : getCN(WIDGET, MASK)
|
|
|
63 |
};
|
|
|
64 |
|
|
|
65 |
/**
|
|
|
66 |
* Static property used to define the default attribute
|
|
|
67 |
* configuration introduced by WidgetModality.
|
|
|
68 |
*
|
|
|
69 |
* @property ATTRS
|
|
|
70 |
* @static
|
|
|
71 |
* @type Object
|
|
|
72 |
*/
|
|
|
73 |
WidgetModal.ATTRS = {
|
|
|
74 |
/**
|
|
|
75 |
* @attribute maskNode
|
|
|
76 |
* @type Y.Node
|
|
|
77 |
*
|
|
|
78 |
* @description Returns a Y.Node instance of the node being used as the mask.
|
|
|
79 |
*/
|
|
|
80 |
maskNode : {
|
|
|
81 |
getter : '_getMaskNode',
|
|
|
82 |
readOnly : true
|
|
|
83 |
},
|
|
|
84 |
|
|
|
85 |
|
|
|
86 |
/**
|
|
|
87 |
* @attribute modal
|
|
|
88 |
* @type boolean
|
|
|
89 |
*
|
|
|
90 |
* @description Whether the widget should be modal or not.
|
|
|
91 |
*/
|
|
|
92 |
modal: {
|
|
|
93 |
value:false,
|
|
|
94 |
validator: isBoolean
|
|
|
95 |
},
|
|
|
96 |
|
|
|
97 |
/**
|
|
|
98 |
* @attribute focusOn
|
|
|
99 |
* @type array
|
|
|
100 |
*
|
|
|
101 |
* @description An array of objects corresponding to the nodes and events that will trigger a re-focus back on the widget.
|
|
|
102 |
* The implementer can supply an array of objects, with each object having the following properties:
|
|
|
103 |
* <p>eventName: (string, required): The eventName to listen to.</p>
|
|
|
104 |
* <p>node: (Y.Node, optional): The Y.Node that will fire the event (defaults to the boundingBox of the widget)</p>
|
|
|
105 |
* <p>By default, this attribute consists of two objects which will cause the widget to re-focus if anything
|
|
|
106 |
* outside the widget is clicked on or focussed upon.</p>
|
|
|
107 |
*/
|
|
|
108 |
focusOn: {
|
|
|
109 |
valueFn: function() {
|
|
|
110 |
return [
|
|
|
111 |
{
|
|
|
112 |
// node: this.get(BOUNDING_BOX),
|
|
|
113 |
eventName: ClickOutside
|
|
|
114 |
},
|
|
|
115 |
{
|
|
|
116 |
//node: this.get(BOUNDING_BOX),
|
|
|
117 |
eventName: FocusOutside
|
|
|
118 |
}
|
|
|
119 |
];
|
|
|
120 |
},
|
|
|
121 |
|
|
|
122 |
validator: Y.Lang.isArray
|
|
|
123 |
}
|
|
|
124 |
|
|
|
125 |
};
|
|
|
126 |
|
|
|
127 |
|
|
|
128 |
WidgetModal.CLASSES = MODAL_CLASSES;
|
|
|
129 |
|
|
|
130 |
|
|
|
131 |
WidgetModal._MASK = null;
|
|
|
132 |
/**
|
|
|
133 |
* Returns the mask if it exists on the page - otherwise creates a mask. There's only
|
|
|
134 |
* one mask on a page at a given time.
|
|
|
135 |
* <p>
|
|
|
136 |
* This method in invoked internally by the getter of the maskNode ATTR.
|
|
|
137 |
* </p>
|
|
|
138 |
* @method _GET_MASK
|
|
|
139 |
* @static
|
|
|
140 |
*/
|
|
|
141 |
WidgetModal._GET_MASK = function() {
|
|
|
142 |
|
|
|
143 |
var mask = WidgetModal._MASK,
|
|
|
144 |
win = Y.one('win');
|
|
|
145 |
|
|
|
146 |
if (mask && (mask.getDOMNode() !== null) && mask.inDoc()) {
|
|
|
147 |
return mask;
|
|
|
148 |
}
|
|
|
149 |
|
|
|
150 |
mask = Y.Node.create('<div></div>').addClass(MODAL_CLASSES.mask);
|
|
|
151 |
WidgetModal._MASK = mask;
|
|
|
152 |
|
|
|
153 |
if (supportsPosFixed) {
|
|
|
154 |
mask.setStyles({
|
|
|
155 |
position: 'fixed',
|
|
|
156 |
width : '100%',
|
|
|
157 |
height : '100%',
|
|
|
158 |
top : '0',
|
|
|
159 |
left : '0',
|
|
|
160 |
display : 'block'
|
|
|
161 |
});
|
|
|
162 |
} else {
|
|
|
163 |
mask.setStyles({
|
|
|
164 |
position: 'absolute',
|
|
|
165 |
width : win.get('winWidth') +'px',
|
|
|
166 |
height : win.get('winHeight') + 'px',
|
|
|
167 |
top : '0',
|
|
|
168 |
left : '0',
|
|
|
169 |
display : 'block'
|
|
|
170 |
});
|
|
|
171 |
}
|
|
|
172 |
|
|
|
173 |
return mask;
|
|
|
174 |
};
|
|
|
175 |
|
|
|
176 |
/**
|
|
|
177 |
* A stack of Y.Widget objects representing the current hierarchy of modal widgets presently displayed on the screen
|
|
|
178 |
* @property STACK
|
|
|
179 |
*/
|
|
|
180 |
WidgetModal.STACK = [];
|
|
|
181 |
|
|
|
182 |
|
|
|
183 |
WidgetModal.prototype = {
|
|
|
184 |
|
|
|
185 |
initializer: function () {
|
|
|
186 |
Y.after(this._renderUIModal, this, RENDER_UI);
|
|
|
187 |
Y.after(this._syncUIModal, this, SYNC_UI);
|
|
|
188 |
Y.after(this._bindUIModal, this, BIND_UI);
|
|
|
189 |
},
|
|
|
190 |
|
|
|
191 |
destructor: function () {
|
|
|
192 |
// Hack to remove this thing from the STACK.
|
|
|
193 |
this._uiSetHostVisibleModal(false);
|
|
|
194 |
},
|
|
|
195 |
|
|
|
196 |
// *** Instance Members *** //
|
|
|
197 |
|
|
|
198 |
_uiHandlesModal: null,
|
|
|
199 |
|
|
|
200 |
|
|
|
201 |
/**
|
|
|
202 |
* Adds modal class to the bounding box of the widget
|
|
|
203 |
* <p>
|
|
|
204 |
* This method in invoked after renderUI is invoked for the Widget class
|
|
|
205 |
* using YUI's aop infrastructure.
|
|
|
206 |
* </p>
|
|
|
207 |
* @method _renderUIModal
|
|
|
208 |
* @protected
|
|
|
209 |
*/
|
|
|
210 |
_renderUIModal : function () {
|
|
|
211 |
|
|
|
212 |
var bb = this.get(BOUNDING_BOX);
|
|
|
213 |
//cb = this.get(CONTENT_BOX);
|
|
|
214 |
|
|
|
215 |
//this makes the content box content appear over the mask
|
|
|
216 |
// cb.setStyles({
|
|
|
217 |
// position: ""
|
|
|
218 |
// });
|
|
|
219 |
|
|
|
220 |
this._repositionMask(this);
|
|
|
221 |
bb.addClass(MODAL_CLASSES.modal);
|
|
|
222 |
|
|
|
223 |
},
|
|
|
224 |
|
|
|
225 |
|
|
|
226 |
/**
|
|
|
227 |
* Hooks up methods to be executed when the widget's visibility or z-index changes
|
|
|
228 |
* <p>
|
|
|
229 |
* This method in invoked after bindUI is invoked for the Widget class
|
|
|
230 |
* using YUI's aop infrastructure.
|
|
|
231 |
* </p>
|
|
|
232 |
* @method _bindUIModal
|
|
|
233 |
* @protected
|
|
|
234 |
*/
|
|
|
235 |
_bindUIModal : function () {
|
|
|
236 |
|
|
|
237 |
this.after(VISIBLE+CHANGE, this._afterHostVisibleChangeModal);
|
|
|
238 |
this.after(Z_INDEX+CHANGE, this._afterHostZIndexChangeModal);
|
|
|
239 |
this.after("focusOnChange", this._afterFocusOnChange);
|
|
|
240 |
|
|
|
241 |
// Re-align the mask in the viewport if `position: fixed;` is not
|
|
|
242 |
// supported. iOS < 5 and Android < 3 don't actually support it even
|
|
|
243 |
// though they both pass the feature test; the UA sniff is here to
|
|
|
244 |
// account for that. Ideally this should be replaced with a better
|
|
|
245 |
// feature test.
|
|
|
246 |
if (!supportsPosFixed ||
|
|
|
247 |
(Y.UA.ios && Y.UA.ios < 5) ||
|
|
|
248 |
(Y.UA.android && Y.UA.android < 3)) {
|
|
|
249 |
|
|
|
250 |
Y.one('win').on('scroll', this._resyncMask, this);
|
|
|
251 |
}
|
|
|
252 |
},
|
|
|
253 |
|
|
|
254 |
/**
|
|
|
255 |
* Syncs the mask with the widget's current state, namely the visibility and z-index of the widget
|
|
|
256 |
* <p>
|
|
|
257 |
* This method in invoked after syncUI is invoked for the Widget class
|
|
|
258 |
* using YUI's aop infrastructure.
|
|
|
259 |
* </p>
|
|
|
260 |
* @method _syncUIModal
|
|
|
261 |
* @protected
|
|
|
262 |
*/
|
|
|
263 |
_syncUIModal : function () {
|
|
|
264 |
|
|
|
265 |
//var host = this.get(HOST);
|
|
|
266 |
|
|
|
267 |
this._uiSetHostVisibleModal(this.get(VISIBLE));
|
|
|
268 |
|
|
|
269 |
},
|
|
|
270 |
|
|
|
271 |
/**
|
|
|
272 |
* Provides mouse and tab focus to the widget's bounding box.
|
|
|
273 |
*
|
|
|
274 |
* @method _focus
|
|
|
275 |
*/
|
|
|
276 |
_focus : function () {
|
|
|
277 |
|
|
|
278 |
var bb = this.get(BOUNDING_BOX),
|
|
|
279 |
oldTI = bb.get('tabIndex');
|
|
|
280 |
|
|
|
281 |
bb.set('tabIndex', oldTI >= 0 ? oldTI : 0);
|
|
|
282 |
this.focus();
|
|
|
283 |
},
|
|
|
284 |
/**
|
|
|
285 |
* Blurs the widget.
|
|
|
286 |
*
|
|
|
287 |
* @method _blur
|
|
|
288 |
*/
|
|
|
289 |
_blur : function () {
|
|
|
290 |
|
|
|
291 |
this.blur();
|
|
|
292 |
},
|
|
|
293 |
|
|
|
294 |
/**
|
|
|
295 |
* Returns the Y.Node instance of the maskNode
|
|
|
296 |
*
|
|
|
297 |
* @method _getMaskNode
|
|
|
298 |
* @return {Node} The Y.Node instance of the mask, as returned from WidgetModal._GET_MASK
|
|
|
299 |
*/
|
|
|
300 |
_getMaskNode : function () {
|
|
|
301 |
|
|
|
302 |
return WidgetModal._GET_MASK();
|
|
|
303 |
},
|
|
|
304 |
|
|
|
305 |
/**
|
|
|
306 |
* Performs events attaching/detaching, stack shifting and mask repositioning based on the visibility of the widget
|
|
|
307 |
*
|
|
|
308 |
* @method _uiSetHostVisibleModal
|
|
|
309 |
* @param {boolean} Whether the widget is visible or not
|
|
|
310 |
*/
|
|
|
311 |
_uiSetHostVisibleModal : function (visible) {
|
|
|
312 |
var stack = WidgetModal.STACK,
|
|
|
313 |
maskNode = this.get('maskNode'),
|
|
|
314 |
isModal = this.get('modal'),
|
|
|
315 |
topModal, index;
|
|
|
316 |
|
|
|
317 |
if (visible) {
|
|
|
318 |
|
|
|
319 |
Y.Array.each(stack, function(modal){
|
|
|
320 |
modal._detachUIHandlesModal();
|
|
|
321 |
modal._blur();
|
|
|
322 |
});
|
|
|
323 |
|
|
|
324 |
// push on top of stack
|
|
|
325 |
stack.unshift(this);
|
|
|
326 |
|
|
|
327 |
this._repositionMask(this);
|
|
|
328 |
this._uiSetHostZIndexModal(this.get(Z_INDEX));
|
|
|
329 |
|
|
|
330 |
if (isModal) {
|
|
|
331 |
maskNode.show();
|
|
|
332 |
Y.later(1, this, '_attachUIHandlesModal');
|
|
|
333 |
this._focus();
|
|
|
334 |
}
|
|
|
335 |
|
|
|
336 |
|
|
|
337 |
} else {
|
|
|
338 |
|
|
|
339 |
index = Y.Array.indexOf(stack, this);
|
|
|
340 |
if (index >= 0) {
|
|
|
341 |
// Remove modal widget from global stack.
|
|
|
342 |
stack.splice(index, 1);
|
|
|
343 |
}
|
|
|
344 |
|
|
|
345 |
this._detachUIHandlesModal();
|
|
|
346 |
this._blur();
|
|
|
347 |
|
|
|
348 |
if (stack.length) {
|
|
|
349 |
topModal = stack[0];
|
|
|
350 |
this._repositionMask(topModal);
|
|
|
351 |
//topModal._attachUIHandlesModal();
|
|
|
352 |
topModal._uiSetHostZIndexModal(topModal.get(Z_INDEX));
|
|
|
353 |
|
|
|
354 |
if (topModal.get('modal')) {
|
|
|
355 |
//topModal._attachUIHandlesModal();
|
|
|
356 |
Y.later(1, topModal, '_attachUIHandlesModal');
|
|
|
357 |
topModal._focus();
|
|
|
358 |
}
|
|
|
359 |
|
|
|
360 |
} else {
|
|
|
361 |
|
|
|
362 |
if (maskNode.getStyle('display') === 'block') {
|
|
|
363 |
maskNode.hide();
|
|
|
364 |
}
|
|
|
365 |
|
|
|
366 |
}
|
|
|
367 |
|
|
|
368 |
}
|
|
|
369 |
},
|
|
|
370 |
|
|
|
371 |
/**
|
|
|
372 |
* Sets the z-index of the mask node.
|
|
|
373 |
*
|
|
|
374 |
* @method _uiSetHostZIndexModal
|
|
|
375 |
* @param {Number} Z-Index of the widget
|
|
|
376 |
*/
|
|
|
377 |
_uiSetHostZIndexModal : function (zIndex) {
|
|
|
378 |
|
|
|
379 |
if (this.get('modal')) {
|
|
|
380 |
this.get('maskNode').setStyle(Z_INDEX, zIndex || 0);
|
|
|
381 |
}
|
|
|
382 |
|
|
|
383 |
},
|
|
|
384 |
|
|
|
385 |
/**
|
|
|
386 |
* Attaches UI Listeners for "clickoutside" and "focusoutside" on the
|
|
|
387 |
* widget. When these events occur, and the widget is modal, focus is
|
|
|
388 |
* shifted back onto the widget.
|
|
|
389 |
*
|
|
|
390 |
* @method _attachUIHandlesModal
|
|
|
391 |
*/
|
|
|
392 |
_attachUIHandlesModal : function () {
|
|
|
393 |
|
|
|
394 |
if (this._uiHandlesModal || WidgetModal.STACK[0] !== this) {
|
|
|
395 |
// Quit early if we have ui handles, or if we not at the top
|
|
|
396 |
// of the global stack.
|
|
|
397 |
return;
|
|
|
398 |
}
|
|
|
399 |
|
|
|
400 |
var bb = this.get(BOUNDING_BOX),
|
|
|
401 |
maskNode = this.get('maskNode'),
|
|
|
402 |
focusOn = this.get('focusOn'),
|
|
|
403 |
focus = Y.bind(this._focus, this),
|
|
|
404 |
uiHandles = [],
|
|
|
405 |
i, len, o;
|
|
|
406 |
|
|
|
407 |
for (i = 0, len = focusOn.length; i < len; i++) {
|
|
|
408 |
|
|
|
409 |
o = {};
|
|
|
410 |
o.node = focusOn[i].node;
|
|
|
411 |
o.ev = focusOn[i].eventName;
|
|
|
412 |
o.keyCode = focusOn[i].keyCode;
|
|
|
413 |
|
|
|
414 |
//no keycode or node defined
|
|
|
415 |
if (!o.node && !o.keyCode && o.ev) {
|
|
|
416 |
uiHandles.push(bb.on(o.ev, focus));
|
|
|
417 |
}
|
|
|
418 |
|
|
|
419 |
//node defined, no keycode (not a keypress)
|
|
|
420 |
else if (o.node && !o.keyCode && o.ev) {
|
|
|
421 |
uiHandles.push(o.node.on(o.ev, focus));
|
|
|
422 |
}
|
|
|
423 |
|
|
|
424 |
//node defined, keycode defined, event defined (its a key press)
|
|
|
425 |
else if (o.node && o.keyCode && o.ev) {
|
|
|
426 |
uiHandles.push(o.node.on(o.ev, focus, o.keyCode));
|
|
|
427 |
}
|
|
|
428 |
|
|
|
429 |
else {
|
|
|
430 |
Y.log('focusOn ATTR Error: The event with name "'+o.ev+'" could not be attached.');
|
|
|
431 |
}
|
|
|
432 |
|
|
|
433 |
}
|
|
|
434 |
|
|
|
435 |
if ( ! supportsPosFixed) {
|
|
|
436 |
uiHandles.push(Y.one('win').on('scroll', Y.bind(function(){
|
|
|
437 |
maskNode.setStyle('top', maskNode.get('docScrollY'));
|
|
|
438 |
}, this)));
|
|
|
439 |
}
|
|
|
440 |
|
|
|
441 |
this._uiHandlesModal = uiHandles;
|
|
|
442 |
},
|
|
|
443 |
|
|
|
444 |
/**
|
|
|
445 |
* Detaches all UI Listeners that were set in _attachUIHandlesModal from the widget.
|
|
|
446 |
*
|
|
|
447 |
* @method _detachUIHandlesModal
|
|
|
448 |
*/
|
|
|
449 |
_detachUIHandlesModal : function () {
|
|
|
450 |
Y.each(this._uiHandlesModal, function(h){
|
|
|
451 |
h.detach();
|
|
|
452 |
});
|
|
|
453 |
this._uiHandlesModal = null;
|
|
|
454 |
},
|
|
|
455 |
|
|
|
456 |
/**
|
|
|
457 |
* Default function that is called when visibility is changed on the widget.
|
|
|
458 |
*
|
|
|
459 |
* @method _afterHostVisibleChangeModal
|
|
|
460 |
* @param {EventFacade} e The event facade of the change
|
|
|
461 |
*/
|
|
|
462 |
_afterHostVisibleChangeModal : function (e) {
|
|
|
463 |
|
|
|
464 |
this._uiSetHostVisibleModal(e.newVal);
|
|
|
465 |
},
|
|
|
466 |
|
|
|
467 |
/**
|
|
|
468 |
* Default function that is called when z-index is changed on the widget.
|
|
|
469 |
*
|
|
|
470 |
* @method _afterHostZIndexChangeModal
|
|
|
471 |
* @param {EventFacade} e The event facade of the change
|
|
|
472 |
*/
|
|
|
473 |
_afterHostZIndexChangeModal : function (e) {
|
|
|
474 |
|
|
|
475 |
this._uiSetHostZIndexModal(e.newVal);
|
|
|
476 |
},
|
|
|
477 |
|
|
|
478 |
/**
|
|
|
479 |
* Returns a boolean representing whether the current widget is in a "nested modality" state.
|
|
|
480 |
* This is done by checking the number of widgets currently on the stack.
|
|
|
481 |
*
|
|
|
482 |
* @method isNested
|
|
|
483 |
* @public
|
|
|
484 |
*/
|
|
|
485 |
isNested: function() {
|
|
|
486 |
var length = WidgetModal.STACK.length,
|
|
|
487 |
retval = (length > 1) ? true : false;
|
|
|
488 |
return retval;
|
|
|
489 |
},
|
|
|
490 |
|
|
|
491 |
/**
|
|
|
492 |
* Repositions the mask in the DOM for nested modality cases.
|
|
|
493 |
*
|
|
|
494 |
* @method _repositionMask
|
|
|
495 |
* @param {Widget} nextElem The Y.Widget instance that will be visible in the stack once the current widget is closed.
|
|
|
496 |
*/
|
|
|
497 |
_repositionMask: function(nextElem) {
|
|
|
498 |
|
|
|
499 |
var currentModal = this.get('modal'),
|
|
|
500 |
nextModal = nextElem.get('modal'),
|
|
|
501 |
maskNode = this.get('maskNode'),
|
|
|
502 |
bb, bbParent;
|
|
|
503 |
|
|
|
504 |
//if this is modal and host is not modal
|
|
|
505 |
if (currentModal && !nextModal) {
|
|
|
506 |
//leave the mask where it is, since the host is not modal.
|
|
|
507 |
maskNode.remove();
|
|
|
508 |
this.fire(MaskHide);
|
|
|
509 |
}
|
|
|
510 |
|
|
|
511 |
//if the main widget is not modal but the host is modal, or both of them are modal
|
|
|
512 |
else if ((!currentModal && nextModal) || (currentModal && nextModal)) {
|
|
|
513 |
|
|
|
514 |
//then remove the mask off DOM, reposition it, and reinsert it into the DOM
|
|
|
515 |
maskNode.remove();
|
|
|
516 |
this.fire(MaskHide);
|
|
|
517 |
bb = nextElem.get(BOUNDING_BOX);
|
|
|
518 |
bbParent = bb.get('parentNode') || Y.one('body');
|
|
|
519 |
bbParent.insert(maskNode, bbParent.get('firstChild'));
|
|
|
520 |
this.fire(MaskShow);
|
|
|
521 |
}
|
|
|
522 |
|
|
|
523 |
},
|
|
|
524 |
|
|
|
525 |
/**
|
|
|
526 |
* Resyncs the mask in the viewport for browsers that don't support fixed positioning
|
|
|
527 |
*
|
|
|
528 |
* @method _resyncMask
|
|
|
529 |
* @param {Y.Widget} nextElem The Y.Widget instance that will be visible in the stack once the current widget is closed.
|
|
|
530 |
* @private
|
|
|
531 |
*/
|
|
|
532 |
_resyncMask: function (e) {
|
|
|
533 |
var o = e.currentTarget,
|
|
|
534 |
offsetX = o.get('docScrollX'),
|
|
|
535 |
offsetY = o.get('docScrollY'),
|
|
|
536 |
w = o.get('innerWidth') || o.get('winWidth'),
|
|
|
537 |
h = o.get('innerHeight') || o.get('winHeight'),
|
|
|
538 |
mask = this.get('maskNode');
|
|
|
539 |
|
|
|
540 |
mask.setStyles({
|
|
|
541 |
"top": offsetY + "px",
|
|
|
542 |
"left": offsetX + "px",
|
|
|
543 |
"width": w + 'px',
|
|
|
544 |
"height": h + 'px'
|
|
|
545 |
});
|
|
|
546 |
},
|
|
|
547 |
|
|
|
548 |
/**
|
|
|
549 |
* Default function called when focusOn Attribute is changed. Remove existing listeners and create new listeners.
|
|
|
550 |
*
|
|
|
551 |
* @method _afterFocusOnChange
|
|
|
552 |
*/
|
|
|
553 |
_afterFocusOnChange : function() {
|
|
|
554 |
this._detachUIHandlesModal();
|
|
|
555 |
|
|
|
556 |
if (this.get(VISIBLE)) {
|
|
|
557 |
this._attachUIHandlesModal();
|
|
|
558 |
}
|
|
|
559 |
}
|
|
|
560 |
};
|
|
|
561 |
|
|
|
562 |
Y.WidgetModality = WidgetModal;
|
|
|
563 |
|
|
|
564 |
|
|
|
565 |
|
|
|
566 |
}, '3.18.1', {"requires": ["base-build", "event-outside", "widget"], "skinnable": true});
|