widget-modality-debug.js revision e7a8cf714fd2334c7ca3ccf2fcfac3163964ddd4
8a485a720d4a37f68766d1022297dca2bd4549b7Allen RabinovichYUI.add('widget-modality', function(Y) {
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovichvar WIDGET = 'widget',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich HOST = 'host',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich RENDER_UI = 'renderUI',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich BIND_UI = 'bindUI',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich SYNC_UI = 'syncUI',
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove RENDERED = 'rendered',
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove BOUNDING_BOX = 'boundingBox',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich CONTENT_BOX = 'contentBox',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich VISIBLE = 'visible',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich Z_INDEX = 'zIndex',
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich ALIGN = 'align',
c1cc0c913c4ed9ac3de73aaadd3d0db93d2240dfAllen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich CHANGE = 'Change',
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove isBoolean = Y.Lang.isBoolean,
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove getCN = Y.ClassNameManager.getClassName,
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove supportsPosFixed = (function(){
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove /*! IS_POSITION_FIXED_SUPPORTED - Juriy Zaytsev (kangax) - http://yura.thinkweb2.com/cft/ */
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove var isSupported = null,
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove el, root;
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove if (document.createElement) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove el = document.createElement('div');
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove if (el && el.style) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove el.style.position = 'fixed';
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove el.style.top = '10px';
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove root = document.body;
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove if (root && root.appendChild && root.removeChild) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove root.appendChild(el);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove isSupported = (el.offsetTop === 10);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove root.removeChild(el);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove }
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove }
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove }
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove return isSupported;
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove }()),
e0047f099a90bbd6805761981cd17c03e354e237Allen Rabinovich
e0047f099a90bbd6805761981cd17c03e354e237Allen Rabinovich WidgetModal;
e0047f099a90bbd6805761981cd17c03e354e237Allen Rabinovich
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove(function(){
e0047f099a90bbd6805761981cd17c03e354e237Allen Rabinovich
e0047f099a90bbd6805761981cd17c03e354e237Allen Rabinovich var WIDGET_MODAL = 'widgetModal',
e0047f099a90bbd6805761981cd17c03e354e237Allen Rabinovich MODAL = 'modal',
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove MASK = 'mask',
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove MODAL_CLASSES = {
0a90ef96933fdee0702794b1276c18fc95609b85Allen Rabinovich modal : getCN(WIDGET, MODAL),
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove mask : getCN(WIDGET, MASK)
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove };
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove WidgetModal = Y.Base.create(WIDGET_MODAL, Y.Plugin.Base, [], {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich // *** Instance Members *** //
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich _maskNode : null,
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich _uiHandles : null,
829f44d633f4910c12181f3295e5c6b996d7e559Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich // *** Lifecycle Methods *** //
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich initializer : function (config) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove var self = this;
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.afterHostMethod(RENDER_UI, this.renderUI);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.afterHostMethod(BIND_UI, this.bindUI);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.afterHostMethod(SYNC_UI, this.syncUI);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove if (this.get(HOST).get(RENDERED)) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.renderUI();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.bindUI();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.syncUI();
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich }
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._maskNode = WidgetModal._GET_MASK();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove },
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove destructor : function () {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove if (this._maskNode) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._maskNode.remove(true);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove }
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._detachUIHandles();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.get(HOST).get(BOUNDING_BOX).removeClass(MODAL_CLASSES.modal);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove },
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove renderUI : function () {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove var bb = this.get(HOST).get(BOUNDING_BOX),
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove cb = this.get(HOST).get(CONTENT_BOX);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove //this makes the content box content appear over the mask
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove cb.setStyles({
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove position: "relative"
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove });
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._repositionMask(this.get(HOST));
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove bb.addClass(MODAL_CLASSES.modal);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove },
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove bindUI : function () {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.afterHostEvent(VISIBLE+CHANGE, this._afterHostVisibleChange);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this.afterHostEvent(Z_INDEX+CHANGE, this._afterHostZIndexChange);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove },
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove syncUI : function () {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove var host = this.get(HOST);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._uiSetHostVisible(host.get(VISIBLE));
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._uiSetHostZIndex(host.get(Z_INDEX));
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove },
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove // *** Private Methods *** //
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove _focus : function (e) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove var host = this.get(HOST),
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich bb = host.get(BOUNDING_BOX),
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich oldTI = bb.get('tabIndex');
0a90ef96933fdee0702794b1276c18fc95609b85Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich bb.set('tabIndex', oldTI >= 0 ? oldTI : 0);
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich host.focus();
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich //Y.later(0, host, 'focus');
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich //this._detachUIHandles();
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich //host.focus();
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich //bb.set('tabIndex', oldTI);
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich },
0a90ef96933fdee0702794b1276c18fc95609b85Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich _blur : function () {
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich this.get(HOST).blur();
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich },
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich _getMaskNode : function () {
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove return WidgetModal._GET_MASK();
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich },
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove _uiSetHostVisible : function (visible) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove var stack = WidgetModal.STACK,
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove host = this.get('host'),
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove topModal, topModalHost;
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove if (visible) {
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove Y.Array.each(stack, function(modal){
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove modal._detachUIHandles();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove modal._blur();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove });
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove // push on top of stack
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove stack.unshift(this);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._attachUIHandles();
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._repositionMask(host);
fa9bf5a0f37d4bea5588392a65e67c1197cc89e0Ryan Grove this._uiSetHostZIndex(host.get(Z_INDEX));
829f44d633f4910c12181f3295e5c6b996d7e559Allen Rabinovich this._maskNode.show();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich this._focus();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich } else {
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich stack.splice(Y.Array.indexOf(stack, this), 1);
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich this._detachUIHandles();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich this._blur();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich if (stack.length) {
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich topModal = stack[0];
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich topModalHost = topModal.get('host');
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich topModal._repositionMask(topModalHost);
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich topModal._attachUIHandles();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich topModal._uiSetHostZIndex(topModalHost.get(Z_INDEX));
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich topModal._focus();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich } else {
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich this._maskNode.hide();
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich }
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich }
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich },
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich _uiSetHostZIndex : function (zIndex) {
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich this._maskNode.setStyle(Z_INDEX, zIndex || 0);
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich },
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich
71bbbe94567d63ab107a7eab263595bcc6e47833Allen Rabinovich _attachUIHandles : function (modal) {
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich if (this._uiHandles) { return; }
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich var host = this.get(HOST),
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich bb = host.get(BOUNDING_BOX);
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich
8a485a720d4a37f68766d1022297dca2bd4549b7Allen Rabinovich this._uiHandles = [
c1cc0c913c4ed9ac3de73aaadd3d0db93d2240dfAllen Rabinovich bb.on('clickoutside', Y.bind(this._focus, this)),
bb.on('focusoutside', Y.bind(this._focus, this))
];
if ( ! supportsPosFixed) {
this._uiHandles.push(Y.one('win').on('scroll', Y.bind(function(e){
var maskNode = this._maskNode;
maskNode.setStyle('top', maskNode.get('docScrollY'));
}, this)));
}
},
_detachUIHandles : function () {
console.log(this);
Y.each(this._uiHandles, function(h){
h.detach();
});
this._uiHandles = null;
},
_afterHostVisibleChange : function (e) {
this._uiSetHostVisible(e.newVal);
},
_afterHostZIndexChange : function (e) {
this._uiSetHostZIndex(e.newVal);
},
_isNested: function() {
var m = WidgetModal._GET_MASK();
return m.get(VISIBLE);
},
//w is the host behind which mask should be repositioned
_repositionMask: function(host) {
//get rid of the mask and reposition it behind the last element in the stack
this._maskNode.remove();
var bb = host.get(BOUNDING_BOX),
bbParent = bb.get('parentNode') || Y.one('body');
bbParent.insert(this._maskNode, bbParent.get('firstChild'));
}
}, {
// *** Static *** //
NS : MODAL,
ATTRS : {
maskNode : {
getter : '_getMaskNode',
readOnly : true
},
node: {
value: undefined
}
},
CLASSES : MODAL_CLASSES,
//Returns the mask if it exists on the page - otherwise creates a mask. There's only
//one mask on a page at a given time.
_GET_MASK: function() {
var mask = Y.one(".yui3-widget-mask") || null;
if (mask) {
return mask;
}
else {
mask = Y.Node.create('<div></div>');
mask.addClass(MODAL_CLASSES.mask);
mask.setStyles({
position : supportsPosFixed ? 'fixed' : 'absolute',
width : '100%',
height : '100%',
top : '0',
left : '0',
display : 'block'
});
return mask;
}
},
//associative array of objects
STACK: []
});
Y.namespace("Plugin").Modal = WidgetModal;
}());
}, '@VERSION@' ,{requires:['widget','plugin','event-outside','base-build']});