(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);