forked from verdnatura/hedera-web
287 lines
5.2 KiB
JavaScript
287 lines
5.2 KiB
JavaScript
|
|
var Widget = require ('./widget');
|
|
|
|
/**
|
|
* Class to handle popups.
|
|
*/
|
|
module.exports = new Class
|
|
({
|
|
Extends: Widget
|
|
,Tag: 'htk-popup'
|
|
,Properties:
|
|
{
|
|
/**
|
|
* The popup child.
|
|
*/
|
|
child:
|
|
{
|
|
type: Widget
|
|
,set: function (x)
|
|
{
|
|
this._child = x;
|
|
this._setChildNode (x.node);
|
|
}
|
|
,get: function ()
|
|
{
|
|
return this._child;
|
|
}
|
|
}
|
|
/**
|
|
* The popup child Node.
|
|
*/
|
|
,childNode:
|
|
{
|
|
type: Object
|
|
,set: function (x)
|
|
{
|
|
this._child = null;
|
|
this._setChildNode (x);
|
|
}
|
|
,get: function ()
|
|
{
|
|
return this.node.firstChild;
|
|
}
|
|
}
|
|
/**
|
|
* Indicates how the dialog must be displayed.
|
|
*/
|
|
,modal:
|
|
{
|
|
type: Boolean
|
|
,set: function (x)
|
|
{
|
|
this._modal = x;
|
|
}
|
|
,get: function ()
|
|
{
|
|
return this._modal;
|
|
}
|
|
}
|
|
}
|
|
|
|
,_parent: null
|
|
,_fitParent: false
|
|
,_modal: false
|
|
,_isOpen: false
|
|
,_child: null
|
|
|
|
,initialize: function (props)
|
|
{
|
|
this._bgMouseDownHandler = this._bgMouseDown.bind (this);
|
|
this._bgKeyPressHandler = this._bgKeyPress.bind (this);
|
|
this.parent (props);
|
|
}
|
|
|
|
,render: function ()
|
|
{
|
|
var div = this.createRoot ('div');
|
|
div.className = 'htk-popup';
|
|
}
|
|
|
|
,_setChildNode: function (childNode)
|
|
{
|
|
Vn.Node.removeChilds (this.node);
|
|
this.node.appendChild (childNode);
|
|
}
|
|
|
|
/**
|
|
* Shows the popup relative to another element.
|
|
*
|
|
* @param {Node} parent The relative element
|
|
* @param {Boolean} fitParent Wether to set the width same to the parent
|
|
* @param {HTMLEvent} ignoreEvent An optional event object to ignore
|
|
*/
|
|
,show: function (parent, fitParent, ignoreEvent)
|
|
{
|
|
this._parent = parent;
|
|
this._fitParent = fitParent;
|
|
this.open (ignoreEvent);
|
|
}
|
|
|
|
/**
|
|
* Opens the popup.
|
|
*
|
|
* @param {Node} parent The relative element
|
|
* @param {Boolean} fitParent Wether to set the width same to the parent
|
|
*/
|
|
,open: function (ignoreEvent)
|
|
{
|
|
if (ignoreEvent)
|
|
this._ignoreEvent = ignoreEvent;
|
|
|
|
if (this._isOpen)
|
|
{
|
|
this.resetAsync ();
|
|
return;
|
|
}
|
|
|
|
var node = this.node;
|
|
|
|
node.addEventListener ('mousedown', this._onPopupMouseDown.bind (this));
|
|
this.doc.addEventListener ('keypress', this._bgKeyPressHandler);
|
|
|
|
if (this.isModal ())
|
|
{
|
|
var bg = this._bg = this.createElement ('div');
|
|
bg.className = 'htk-background';
|
|
bg.addEventListener ('mousedown', this._bgMouseDownHandler);
|
|
Htk.Toast.pushTop (bg);
|
|
|
|
Vn.Node.addClass (node, 'modal');
|
|
bg.appendChild (node);
|
|
|
|
this.doc.body.appendChild (bg);
|
|
}
|
|
else
|
|
{
|
|
this.doc.addEventListener ('mousedown', this._bgMouseDownHandler);
|
|
this.doc.body.appendChild (node);
|
|
Vn.Node.addClass (node, 'fixed');
|
|
this.resetAsync ();
|
|
}
|
|
|
|
setTimeout (this._onOpacityTimeout.bind (this), 10);
|
|
this._isOpen = true;
|
|
}
|
|
|
|
/**
|
|
* Returns if the popup window shoud be modal based on the modal property
|
|
* and if the device is mobile.
|
|
*
|
|
* @return {Boolean} %true if it's modal, %false otherwise
|
|
*/
|
|
,isModal: function ()
|
|
{
|
|
return this._modal || Vn.isMobile () || !this._parent;
|
|
}
|
|
|
|
,_onOpacityTimeout: function ()
|
|
{
|
|
if (!this._isOpen)
|
|
return;
|
|
|
|
if (this._bg)
|
|
this._bg.style.opacity = 1;
|
|
|
|
this._node.style.opacity = 1;
|
|
}
|
|
|
|
,_onResetTimeout: function ()
|
|
{
|
|
this.reset ();
|
|
}
|
|
|
|
,resetAsync: function ()
|
|
{
|
|
setTimeout (this._onResetTimeout.bind (this));
|
|
}
|
|
|
|
/**
|
|
* Repositions the popup.
|
|
*/
|
|
,reset: function ()
|
|
{
|
|
if (!this._isOpen || this.isModal ())
|
|
return;
|
|
|
|
var node = this._node;
|
|
|
|
var style = node.style;
|
|
style.visibility = 'hidden';
|
|
style.height = '';
|
|
style.width = '';
|
|
|
|
var margin = 20;
|
|
var dblMargin = margin * 2;
|
|
|
|
var iniWidth;
|
|
var iniHeight;
|
|
var width = iniWidth = node.offsetWidth;
|
|
var height = iniHeight = node.offsetHeight;
|
|
|
|
var windowWidth = window.innerWidth;
|
|
var windowHeight = window.innerHeight;
|
|
|
|
if (width + dblMargin > windowWidth)
|
|
width = windowWidth - dblMargin;
|
|
if (height + dblMargin > windowHeight)
|
|
height = windowHeight - dblMargin;
|
|
|
|
var rect = this._parent.getBoundingClientRect ();
|
|
var left = rect.left;
|
|
var top = rect.top + this._parent.offsetHeight;
|
|
|
|
if (this._fitParent)
|
|
width = this._parent.offsetWidth;
|
|
|
|
if (left + width + margin > windowWidth)
|
|
left -= (left + width) - window.windowWidth + margin;
|
|
if (top + height + margin > windowHeight)
|
|
top -= height + this._parent.offsetHeight;
|
|
|
|
if (left < margin)
|
|
left = margin;
|
|
if (top < margin)
|
|
top = margin;
|
|
|
|
style.top = (top) +'px';
|
|
style.left = (left) +'px';
|
|
|
|
if (width != iniWidth)
|
|
style.width = (width) +'px';
|
|
if (height != iniHeight)
|
|
style.height = (height) +'px';
|
|
|
|
style.visibility = 'initial';
|
|
}
|
|
|
|
/**
|
|
* Hides the popup.
|
|
*/
|
|
,hide: function ()
|
|
{
|
|
if (!this._isOpen)
|
|
return;
|
|
|
|
var node = this._node;
|
|
|
|
if (this._bg)
|
|
{
|
|
Htk.Toast.popTop ();
|
|
Vn.Node.remove (this._bg);
|
|
Vn.Node.removeClass (node, 'modal');
|
|
this._bg = null;
|
|
}
|
|
else
|
|
{
|
|
this.doc.removeEventListener ('mousedown', this._bgMouseDownHandler);
|
|
Vn.Node.removeClass (node, 'fixed');
|
|
}
|
|
|
|
Vn.Node.remove (node);
|
|
this._parent = null;
|
|
this._isOpen = false;
|
|
this.signalEmit ('closed');
|
|
}
|
|
|
|
,_bgMouseDown: function (e)
|
|
{
|
|
if (e !== this._ignoreEvent)
|
|
this.hide ();
|
|
|
|
this._ignoreEvent = null;
|
|
}
|
|
|
|
,_bgKeyPress: function (e)
|
|
{
|
|
if (e.keyCode == 27) // Escape
|
|
this.hide ();
|
|
}
|
|
|
|
,_onPopupMouseDown: function (e)
|
|
{
|
|
this._ignoreEvent = e;
|
|
}
|
|
});
|
|
|