(function (_super) { var ns = 'hui_panel'; /** * @constructor */ hui.ui.Panel = function(options) { _super.call(this, options); this.options = options; this.visible = false; this._attach(); if (options.listener) { this.listen(options.listener); } }; hui.ui.Panel.create = function(options) { options = hui.override({}, options); var html = (options.closable ? '<div class="hui_panel_close"></div>' : '')+ '<div class="hui_panel_arrow"></div><div class="hui_panel_titlebar">'; if (options.icon) { html+='<span class="hui_icon hui_icon_16 hui_panel_icon" style="background-image: url('+hui.ui.getIconUrl(options.icon,16)+'); background-image: -webkit-image-set(url('+hui.ui.getIconUrl(options.icon,16)+') 1x,url('+hui.ui.getIconUrl(options.icon,32+'x2')+') 2x);"></span>'; } html+='<span class="hui_panel_title">' + hui.ui.getTranslated(options.title) + '</span></div>'+ '<div class="hui_panel_body" style="'+ (options.width ? 'width:'+options.width+'px;':'')+ (options.height ? 'height:'+options.height+'px;':'')+ (options.padding ? 'padding:'+options.padding+'px;':'')+ '">'+ '</div>'+ ''; var cls = 'hui_panel hui-is-floating'+(options.variant ? ' hui_panel_'+options.variant : ''); if (options.title) { cls+= ' hui-is-titled'; } if (options.variant=='dark') { cls+=' hui_context_dark'; } options.element = hui.build('div', {'class' : cls, html : html, parent: options.parent || document.body}); return new hui.ui.Panel(options); }; hui.ui.Panel.prototype = { _target : null, nodes : { close: '.hui_panel_close', titlebar: '.hui_panel_titlebar', title: '.hui_panel_title', body: '.hui_panel_body', arrow: '.hui_panel_arrow' }, _attach : function() { if (this.nodes.close) { hui.listen(this.nodes.close,'click',function(e) { this.hide(); this.fire('close'); }.bind(this)); hui.listen(this.nodes.close,'mousedown',function(e) {hui.stop(e);}); } hui.drag.register({ touch: true, window: this.element.ownerDocument.defaultView, element : this.nodes.titlebar, $before : this._onDragStart.bind(this) , $startMove : this._onBeforeMove.bind(this) , $move : this._onMove.bind(this), $endMove : this._onAfterMove.bind(this) }); hui.listen(this.element,'mousedown',function() { this.element.style.zIndex = hui.ui.nextPanelIndex(); }.bind(this)); }, _attachHider : function() { if (this.options.autoHide && !this._hideListener) { this._hideListener = hui.on(document.body, 'tap', function(e) { if (!hui.ui.isWithin(e, this.element) && (!this._target || !hui.ui.isWithin(e, this._target))) { this.hide(); } }.bind(this)); } if (!this._resizeListener) { var go = function() { this._adjustSize(); this._positionAtTarget(); }.bind(this) this._resizeListener = hui.listen(window, 'resize', function(e) { if (this.visible) { hui.onDraw(go); } }.bind(this)); } }, setTitle : function(title) { hui.dom.setText(this.nodes.title,hui.ui.getTranslated(title)); hui.cls.set(this.element,'hui-is-titled', !hui.isBlank(title)); }, _positionInView : function() { var scrollTop = hui.window.getScrollTop(); var winTop = hui.position.getTop(this.element); if (winTop < scrollTop || winTop+this.element.clientHeight > hui.window.getViewHeight()+scrollTop) { hui.animate({ node: this.element, css: {top: (scrollTop+40)+'px'}, duration: 500, ease: hui.ease.slowFastSlow }); } }, _ensureInView : function() { if (!this.visible || this._target) return; var viewWidth = hui.window.getViewWidth() - 3; var right = hui.position.getLeft(this.element) + this.element.offsetWidth; if (viewWidth - right < 0) { this.element.style.left = (viewWidth - this.element.offsetWidth) + 'px'; } }, _adjustSize : function() { var viewWidth = hui.window.getViewWidth(); var isTooLarge = this.options.width + 40 > viewWidth; hui.cls.set(this.element, 'hui-is-full', isTooLarge); if (!isTooLarge) { this._ensureInView(); } }, _placeOnTop : function() { if (this.visible) { hui.style.set(this.element,{ zIndex : hui.ui.nextPanelIndex() }); } else { hui.style.set(this.element,{ zIndex : hui.ui.nextPanelIndex(), visibility : 'hidden', display : 'block' }); } }, show : function(options) { var element = this.element; options = options || {}; this._target = options.target; this._adjustSize(); this._placeOnTop(); if (this._target) { if (!this.visible) { this._positionAtTarget(); hui.style.set(element,{ opacity: '0', transform: 'scale(0.5)', visibility : 'visible' }); setTimeout(function() { hui.cls.add(element, 'hui-is-animating'); }) } else { hui.cls.add(element, 'hui-is-animating'); this._positionAtTarget(); } hui.cls.add(element,'hui-is-targeted'); if (!this.visible) { setTimeout(function() { hui.style.set(element, { opacity: 1, transform: 'scale(1) ' }); }); } setTimeout(function() { hui.cls.remove(element,'hui-is-animating'); }, 600); } else { if (this.visible) { this._positionInView(); return; } hui.style.set(element,{ visibility : 'visible' }); if (options.avoid) { hui.position.place({ insideViewPort : true, target : {element : options.avoid, vertical : 0.5, horizontal : 1}, source : {element : element, vertical : 0.5, horizontal : 0} }); } else { if (!element.style.top) { element.style.top = (hui.window.getScrollTop()+40)+'px'; } else { this._positionInView(); } if (!element.style.left) { element.style.left = Math.round((hui.window.getViewWidth()-element.clientWidth)/2)+'px'; } } hui.animate(element,'opacity',1,0); } this.visible = true; hui.ui.callVisible(this); this._attachHider(); }, _positionAtTarget : function() { if (!this._target) { return; } var panel = { width: this.element.clientWidth, height: this.element.clientHeight }; var target = this._target; var scrollOffset; if (target.nodeType===1) { scrollOffset = hui.position.getScrollOffset(this._target); target = hui.position.get(this._target); target.height = this._target.offsetHeight || this._target.clientHeight; target.width = this._target.offsetWidth || this._target.clientWidth; } else { scrollOffset = {top: 0, left: 0}; } var view = { height: hui.window.getViewHeight(), width: hui.window.getViewWidth(), scrollTop: hui.window.getScrollTop(), scrollLeft: hui.window.getScrollLeft() } var dist = { above: (target.top - view.scrollTop) / panel.height, below: (view.height - (target.top - view.scrollTop + target.height)) / panel.height, left: (target.left - view.scrollLeft) / panel.width, right: (view.width - (target.left - view.scrollLeft + target.width)) / panel.width } var pos = { top: 0, left: 0 } var orientation = this._getOrientation(dist); if (orientation == 'below') { pos.top = target.top + target.height + 5; pos.left = target.left + target.width/2 - panel.width/2; } else if (orientation == 'above') { pos.top = target.top - panel.height - 5; pos.left = target.left + target.width/2 - panel.width/2; } else if (orientation == 'left') { pos.top = target.top + target.height/2 - panel.height/2; pos.left = target.left - panel.width - 5; } else if (orientation == 'right') { pos.top = target.top + target.height/2 - panel.height/2; pos.left = target.left + target.width + 5; } pos.top -= scrollOffset.top; pos.left -= scrollOffset.left; var gutter = 5; pos.top = hui.between(gutter, pos.top, view.scrollTop + view.height - panel.height - gutter); pos.left = hui.between(gutter, pos.left, view.scrollLeft + view.width - panel.width - gutter); this.nodes.arrow.className = 'hui_panel_arrow hui_panel_arrow-'+orientation; if (orientation == 'above' || orientation == 'below') { hui.style.set(this.nodes.arrow,{ left: hui.between(3, (target.left - pos.left + target.width/2 - 10), panel.width - 3 - 20) + 'px', top: '' }); } else { hui.style.set(this.nodes.arrow,{ top: hui.between(3, (target.top - pos.top + target.height/2 - 10), panel.height - 3 - 20) + 'px', left: '' }); } hui.style.set(this.element,{ top: pos.top + 'px', left: pos.left + 'px' }) }, _getOrientation : function(distances) { var prop, value = 0; for (dim in distances) { if (distances.hasOwnProperty(dim)) { if (distances[dim] > value) { value = distances[dim]; prop = dim; } } } return prop; }, toggle : function(options) { if (this.visible) { this.hide(); } else { this.show(options); } }, isVisible : function() { return this.visible; }, hide : function() { if (!this.visible) return; this._unFocus(); hui.cls.add(this.element, 'hui-is-animating'); this.element.style.opacity='0'; setTimeout(function() { hui.cls.remove(this.element, 'hui-is-animating'); this.element.style.display='none'; hui.ui.callVisible(this); }.bind(this),500); this.visible = false; }, _unFocus : function() { var active = document.activeElement; if (active && hui.dom.isDescendantOrSelf(active, this.element)) { active.blur(); } }, clear : function() { hui.ui.destroyDescendants(this.nodes.body); this.nodes.body.innerHTML = ''; }, add : function(widgetOrNode) { if (widgetOrNode.getElement) { this.nodes.body.appendChild(widgetOrNode.getElement()); } else { this.nodes.body.appendChild(widgetOrNode); } this._positionAtTarget(); }, setBusy : function(stringOrBoolean) { if (stringOrBoolean===false) { clearTimeout(this._busyTimer); if (this._busyCurtain) { hui.cls.remove(this._busyCurtain, 'hui-is-visible'); } return; } var curtain = this._busyCurtain; if (!curtain) { curtain = this._busyCurtain = hui.build('div.hui_panel_busy',{parentFirst:this.nodes.body}); if (hui.browser.msie) { hui.cls.add(curtain,'hui_panel_busy-legacy'); } } var text = hui.isString(stringOrBoolean) ? hui.string.escape(stringOrBoolean) : ''; curtain.innerHTML = '<span class="hui_panel_busy_text">' + text + '</span>'; this._busyTimer = setTimeout(function() { hui.cls.add(curtain, 'hui-is-visible'); },16); }, move : function(point) { hui.style.set(this.element,{top:point.top+'px',left:point.left+'px'}); }, _onDragStart : function(e) { this.element.style.zIndex = hui.ui.nextPanelIndex(); }, _onBeforeMove : function(e) { e = hui.event(e); var pos = hui.position.get(this.element); this.dragState = { left: e.getLeft() - pos.left, top: e.getTop() - pos.top, maxLeft: hui.window.getViewWidth() - this.element.offsetWidth - 3 }; this.element.style.right = 'auto'; hui.cls.add(this.element,'hui-is-dragging'); hui.cls.remove(this.element,'hui-is-targeted'); }, _onMove : function(e) { var top = (e.getTop()-this.dragState.top); var left = (e.getLeft()-this.dragState.left); this.element.style.top = Math.max(top, 3) + 'px'; this.element.style.left = hui.between(3, left, this.dragState.maxLeft) + 'px'; }, _onAfterMove : function() { hui.ui.callDescendants(this,'$$parentMoved'); hui.cls.remove(this.element,'hui-is-dragging'); } }; hui.extend(hui.ui.Panel, _super); hui.define('hui.ui.Panel', hui.ui.Panel); })(hui.ui.Component);