require('./style.scss'); var Component = require('vn/component'); /** * Class to handle popups. */ module.exports = new Class({ Extends: Component ,Tag: 'htk-popup' ,Properties: { /** * The popup child. */ child: { type: Component ,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 ,_modal: false ,_isOpen: false ,_child: null ,initialize: function(props) { this._bgMouseDownHandler = this._bgMouseDown.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); } ,show: function(parent, event) { this._parent = parent; this._lastEvent = event; this.open(); } ,isModal: function() { return this._modal || Vn.isMobile(); } ,open: function() { if (this._isOpen) { this.reset(); return; } this.node.addEventListener('mousedown', this._onMouseDown.bind(this)); 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(this.node, 'modal'); bg.appendChild(this.node); this.doc.body.appendChild(bg); setTimeout(this._onOpacityTimeout.bind(this), 0); } else { this.doc.addEventListener('mousedown', this._bgMouseDownHandler); this.doc.body.appendChild(this.node); } this._isOpen = true; this.reset(); setTimeout(this._onResetTimeout.bind(this), 0); } ,_onOpacityTimeout: function() { if (this._bg) this._bg.style.opacity = 1; } ,_onResetTimeout: function() { this.reset(); } ,reset: function() { if (!this._isOpen) return; var node = this._node; var style = node.style; style.height = ''; style.width = ''; var margin = 20; var dblMargin = margin * 2; var width = node.offsetWidth; var height = node.offsetHeight; var innerWidth = window.innerWidth; var innerHeight = window.innerHeight; if (width + dblMargin > innerWidth) { width = innerWidth - dblMargin; style.width = width +'px'; } if (height + dblMargin > innerHeight) { height = innerHeight - dblMargin; style.height = height +'px'; } if (this.isModal()) { style.marginLeft = (-node.offsetWidth / 2) +'px'; style.marginTop = (-node.offsetHeight / 2) +'px'; } else { var spacing = 4; var rect = this._parent.getBoundingClientRect(); var left = rect.left; var top = rect.top + spacing + this._parent.offsetHeight; if (left + width > innerWidth) left -= (left + width) - window.innerWidth + margin; if (top + height > innerHeight) top -= height + this._parent.offsetHeight + spacing * 2; if (left < 0) left = margin; if (top < 0) top = margin; style.top = (top) +'px'; style.left = (left) +'px'; } } ,hide: function() { if (!this._isOpen) return; if (this._bg) { Htk.Toast.popTop(); Vn.Node.remove(this._bg); Vn.Node.removeClass(this._node, 'modal'); this._bg = null; } else this.doc.removeEventListener('mousedown', this._bgMouseDownHandler); Vn.Node.remove(this._node); this._parent = null; this._isOpen = false; this.emit('closed'); } ,_bgMouseDown: function(e) { if (e !== this._lastEvent) this.hide(); this._lastEvent = null; } ,_onMouseDown: function(e) { this._lastEvent = e; } });