c9-core/plugins/c9.ide.ui/lib/flexbox.js

995 wiersze
38 KiB
JavaScript

define(function(require, module, exports) {
return function(apf) {
var $setTimeout = setTimeout;
var $setInterval = setInterval;
/**
* A container that stacks its children vertically.
*
* #### Example
*
* ```xml, demo
* <a:application xmlns:a="http://ajax.org/2005/aml">
* <!-- startcontent -->
* <a:vbox width="100">
* <a:button height="28" edge="5">Button 1</a:button>
* <a:button height="28" edge="5">Button 2</a:button>
* <a:button height="28" edge="5">Button 3</a:button>
* </a:vbox>
* <!-- endcontent -->
* </a:application>
* ```
*
* @class apf.vbox
* @layout
* @define vbox
*
*
* @see element.hbox
*
* @author Ruben Daniels (ruben AT ajax DOT org)
* @version %I%, %G%
* @since 0.9
* @layout
*/
/**
* A container that stacks its children horizontally.
*
* #### Example
*
* ```xml, demo
* <a:application xmlns:a="http://ajax.org/2005/aml">
* <!-- startcontent -->
* <a:hbox height="29" width="300" lean="right" margin="5 0 0 0">
* <a:button width="100" edge="5">Button 1</a:button>
* <a:button width="100">Button 2</a:button>
* <a:button width="100">Button 3</a:button>
* </a:hbox>
* <!-- endcontent -->
* </a:application>
* ```
*
*
* #### Remarks
*
* Firefox has some issues:
*
* 1. Sometimes it's necessary to put a fixed width to have it calculate the right
* height value.
* 2. Using flex="1" on non fixed height/width tree's will give unexpected results.
*
*
*
* @class apf.hbox
* @inherits apf.GuiElement
* @define hbox
* @layout
*
* @see element.vbox
* @author Ruben Daniels (ruben AT ajax DOT org)
* @version %I%, %G%
* @since 0.9
*/
apf.hbox = function(struct, tagName) {
this.$init(tagName || "hbox", apf.NODE_VISIBLE, struct);
};
apf.vbox = function(struct, tagName) {
this.$init(tagName || "vbox", apf.NODE_VISIBLE, struct);
};
(function(){
this.minwidth = 0;
this.minheight = 0;
// *** Properties and Attributes *** //
this.$focussable = false;
this.$useLateDom = true;
this.$box = true;
this.$layout = true;
var input = {"INPUT":1, "SELECT":1, "TEXTAREA":1};
/**
* @attribute {String} [padding=2] Sets or gets the space between each element.
*/
/**
* @attribute {Boolean} reverse Sets or gets whether the sequence of the elements is in reverse order.
*/
/**
* @attribute {String} [edge="5,5,5,5"] Sets or gets the space between the container and the elements, space seperated in pixels for each side. Similar to CSS in the sequence (_.i.e._. `top right bottom left`).
*
* #### Example
*
* ```xml
* <a:vbox edge="10 10 40 10" />
* ```
*/
// @todo Doc
/**
* @attribute {String} pack
*
* Possible values include:
*
* - `"start"`:
* - `"center"`:
* - `"end"`:
*/
/**
* @attribute {Boolean} align
*
* Possible values include:
*
* - `"start"`:
* - `"center"`:
* - `"end"`:
* - `"stretch"`:
*/
this.$booleanProperties["splitters"] = true;
this.$supportedProperties.push("padding", "reverse", "edge", "pack", "align", "splitters");
this.$propHandlers["padding"] = function(value) {
this.padding = parseInt(value);
var node, nodes = this.childNodes, elms = [];
for (var i = 0, l = nodes.length; i < l; i++) {
if ((node = nodes[i]).nodeFunc == apf.NODE_VISIBLE
&& node.$ext && node.visible !== false)
elms.push(node);
}
if (!elms.length)
return;
for (var last, b, el, i = elms.length - 2; i >= 0; i--) {
b = (el = elms[i]).margin && apf.getBox(el.margin) || [0,0,0,0];
if ((!last || !last.$splitter) && !el.$splitter) {
b[this.$vbox ? 2 : 1] += this.padding;
if (!apf.hasFlexibleBox && i != 0 && this.align == "stretch" && this.$vbox)
b[0] += this.padding;
}
el.$ext.style.margin = b.join("px ") + "px";
last = el;
}
b = (el = elms[elms.length - 1]).margin && apf.getBox(el.margin) || [0,0,0,0];
el.$ext.style.margin = b.join("px ") + "px";
if (!apf.hasFlexibleBox)
this.$resize();
}
this.$propHandlers["reverse"] = function(value) {
if (apf.hasFlexibleBox)
this.$int.style[apf.CSSPREFIX + "BoxDirection"] = value ? "reverse" : "normal";
else {
//@todo
}
};
this.$propHandlers["edge"] = function(value) {
var el = !apf.hasFlexibleBox && this.$vbox ? this.$ext : this.$int;
el.style.padding = (this.$edge = apf.getBox(value)).join("px ") + "px";
if (!apf.hasFlexibleBox)
this.$resize();
};
this.$propHandlers["pack"] = function(value) {
if (apf.hasFlex) {
if (value == "start" || value == "end")
value = "flex-" + value;
this.$int.style.justifyContent = value || "flex-start";
} else if (apf.hasFlexibleBox) {
this.$int.style[apf.CSSPREFIX + "BoxPack"] = value || "start";
} else if (this.$amlLoaded) {
if (this.$vbox) {
this.$int.style.verticalAlign = value == "center" ? "middle" : (value == "end" ? "bottom" : "top");
}
else {
this.$int.style.textAlign = "";
var nodes = this.childNodes;
for (var i = 0, l = nodes.length; i < l; i++) {
var node = nodes[i];
if (node.nodeFunc != apf.NODE_VISIBLE || !node.$amlLoaded) //|| node.visible === false
continue;
node.$ext.style.textAlign = apf.getStyle(node.$ext, "textAlign") || "left";
}
this.$int.style.textAlign = value == "center" ? "center" : (value == "end" ? "right" : "left");
}
}
};
//@todo change overflow when height/width changes depending on $vbox
this.$propHandlers["align"] = function(value) {
if (apf.hasFlex) {
if (value == "start" || value == "end")
value = "flex-" + value;
this.$int.style.alignItems = value || "stretch"; // flex-start
}
else if (apf.hasFlexibleBox) {
this.$int.style[apf.CSSPREFIX + "BoxAlign"] = value || "stretch";
//@todo this should probably be reinstated
var stretch = !value || value == "stretch";
var nodes = this.childNodes;
var size = this.$vbox ? "width" : "height";
var isInFixed = false, loopNode = this;
while (!isInFixed && loopNode) {
isInFixed = loopNode[size] || loopNode.anchors || (loopNode.$vbox ? loopNode.top && loopNode.bottom : loopNode.left && loopNode.right);
if (!loopNode.flex)
break;
loopNode = loopNode.parentNode || loopNode.$parentNode;
}
for (var i = 0, l = nodes.length; i < l; i++) {
if (!(node = nodes[i]).$ext || node.$ext.nodeType != 1)
continue;
//(this[size] || this.anchors || (this.$vbox ? this.top && this.bottom : this.left && this.right)
if (stretch && !node[size]) //(node.$altExt ||
node.$ext.style[size] = (input[node.$ext.tagName]
? "100%" : "auto");
else if (node[size])
handlers["true"][size].call(node, node[size]);
}
}
else if (this.$amlLoaded) {
var stretch = !value || value == "stretch";
if (!this.$vbox) {
var nodes = this.childNodes;
for (var i = 0, l = nodes.length; i < l; i++) {
if ((node = nodes[i]).nodeFunc != apf.NODE_VISIBLE || !node.$amlLoaded) //|| node.visible === false
continue;
node.$ext.style.verticalAlign = value == "center" ? "middle" : (value == "end" ? "bottom" : "top");
}
}
else {
var el = !apf.hasFlexibleBox && this.$vbox ? this.$ext : this.$int;
el.style.textAlign = "";
var node, nodes = this.childNodes;
for (var i = 0, l = nodes.length; i < l; i++) {
if ((node = nodes[i]).nodeFunc != apf.NODE_VISIBLE || !node.$amlLoaded) //|| node.visible === false
continue;
if (node.visible !== false) {
node.$ext.style.display = value == "stretch" ? "block" : "inline-block";
node.$br.style.display = value == "stretch" ? "none" : "";
}
node.$ext.style.textAlign = apf.getStyle(node.$ext, "textAlign") || "left";
}
el.style.textAlign = value == "center" ? "center" : (value == "end" ? "right" : "left");
}
}
};
function visibleHandler(e) {
if (this.parentNode.splitters && !this.$splitter) {
if (!e.value) {
if (this.nextSibling && this.nextSibling.$splitter)
this.nextSibling.removeNode();
else if (this.previousSibling && this.previousSibling.$splitter)
this.previousSibling.removeNode();
}
else {
var isLast = isLastVisibleChild(this);
if (!isLast) {
if (!this.nextSibling.$splitter && !this.nextSibling.nosplitter
&& !isFirstVisibleChild(this) && !this.nosplitter) {
this.parentNode.insertBefore(
this.ownerDocument.createElementNS(apf.ns.aml, "splitter"),
this.nextSibling);
}
}
else if (this.previousSibling && !this.previousSibling.$splitter
&& !this.previousSibling.nosplitter) {
this.parentNode.insertBefore(
this.ownerDocument.createElementNS(apf.ns.aml, "splitter"),
this);
}
}
}
//@todo this can be more optimized by calcing if it WAS the last vis child.
if (this.parentNode.$propHandlers["padding"]) {// && isLastVisibleChild(this)) {
this.parentNode.$propHandlers["padding"]
.call(this.parentNode, this.parentNode.padding);
}
apf.layout.forceResize(this.parentNode.$int);
if (apf.hasFlexibleBox) {
if (this.$altExt)
this.$altExt.style.display = e.value
? apf.CSS_DISPLAY_FLEX
: "none";
return;
}
if (e.value) {
this.$ext.style.display = this.parentNode.$vbox
&& this.parentNode.align == "stretch" ? "block" : "inline-block";
if (this.$br)
this.$br.style.display = this.parentNode.align == "stretch" ? "none" : "";
}
else {
if (this.$br)
this.$br.style.display = "none";
}
this.parentNode.$resize();
}
function resizeHandler(){
if (!this.flex) {
if (this.$isRszHandling || this.$lastSizeChild &&
this.$lastSizeChild[0] == this.$ext.offsetWidth &&
this.$lastSizeChild[1] == this.$ext.offsetHeight)
return;
/*if (this.$skipResizeOnce)
delete this.$skipResizeOnce;
else*/
this.parentNode.$resize(true);
this.$lastSizeChild = [this.$ext.offsetWidth, this.$ext.offsetHeight];
}
}
var handlers = {
//Handlers for flexible box layout
"true" : {
"optimize" : function(value) {
this.optimize = apf.isTrue(value);
},
"width" : function(value) {
//@todo this should check the largest and only allow that one
//if (this.parentNode.$vbox && this.parentNode.align == "stretch")
//return;
(this.$altExt || this.$ext).style.width = !apf.isNot(value)
? (parseFloat(value) == value
? value + "px"
: value)
: "";
},
"height" : function(value) {
//@todo this should check the largest and only allow that one
//if (!this.parentNode.$vbox && this.parentNode.align == "stretch")
//return;
(this.$altExt || this.$ext).style.height = !apf.isNot(value)
? (parseFloat(value) == value
? value + "px"
: value)
: (apf.isGecko && this.flex && this.parentNode.$vbox ? "auto" : "");
},
"margin" : function(value) {
var b = apf.getBox(value);
if (!isLastVisibleChild(this))
b[this.parentNode.$vbox ? 2 : 1] += this.parentNode.padding;
this.$ext.style.margin = b.join("px ") + "px";
},
"flex" : function(value) {
this.flex = value = parseInt(value);
if (value) {
if (!this.optimize && !this.$altExt) {
this.$altExt = this.$ext.ownerDocument.createElement("div");
this.parentNode.$int.replaceChild(this.$altExt, this.$ext);
this.$altExt.appendChild(this.$ext);
this.$altExt.style.boxSizing = "border-box";
this.$altExt.style.display = apf.CSS_DISPLAY_FLEX;
this.$altExt.style[apf.CSSPREFIX + "BoxOrient"] = "vertical";
this.$ext.style[apf.CSS_FLEX_PROP] = 1;
var size = this.parentNode.$vbox ? "height" : "width";
//var osize = this.parentNode.$vbox ? "width" : "height";
if (!this.preventforcezero)
this.$altExt.style[size] = "0px";
}
(this.$altExt || this.$ext).style[apf.CSS_FLEX_PROP] = parseInt(value) || 1;
}
else if (this.$altExt) {
this.parentNode.$int.replaceChild(this.$ext, this.$altExt);
this.$ext.style[apf.CSS_FLEX_PROP] = "";
delete this.$altExt;
}
}
},
//Handlers for older browsers
"false" : {
"width" : function(value) {
//@todo this should check the largest and only allow that one
//if (this.parentNode.$vbox && this.parentNode.align == "stretch")
//return;
this.$ext.style.width = value
? (parseFloat(value) == value
? Math.max(0, value - apf.getWidthDiff(this.$ext)) + "px"
: value)
: "";
},
"height" : function(value) {
//@todo this should check the largest and only allow that one
//if (this.parentNode.localName == "hbox" && this.parentNode.align == "stretch")
//return;
this.$ext.style.height = value
? (parseFloat(value) == value
? Math.max(0, value - apf.getHeightDiff(this.$ext)) + "px"
: value)
: "";
},
"margin" : function(value) {
var b = apf.getBox(value);
if (this.padding) {
if (!isLastVisibleChild(this))
b[this.parentNode.$vbox ? 2 : 1] += this.padding;
if (this != this.parentNode.firstChild && this.parentNode.align == "stretch" && this.parentNode.$vbox) //@todo
b[0] += this.padding;
}
this.$ext.style.margin = b.join("px ") + "px";
},
"flex" : function(value) {
this.flex = parseInt(value);
if (this.$amlLoaded)
this.parentNode.$resize(true);
}
}
}
function isFirstVisibleChild(amlNode) {
var firstChild = amlNode.parentNode.firstChild;
while (firstChild && (firstChild.nodeFunc != apf.NODE_VISIBLE
|| firstChild.visible === false
|| firstChild.visible == 2 && apf.isFalse(firstChild.getAttribute("visible")))) {
firstChild = firstChild.nextSibling;
}
return firstChild && firstChild == amlNode;
}
function isLastVisibleChild(amlNode) {
var lastChild = amlNode.parentNode.lastChild;
while (lastChild && (lastChild.nodeFunc != apf.NODE_VISIBLE
|| lastChild.visible === false
|| lastChild.visible == 2 && apf.isFalse(lastChild.getAttribute("visible")))) {
lastChild = lastChild.previousSibling;
}
return lastChild && lastChild == amlNode;
}
//@todo move this to enableTable, disableTable
this.register = function(amlNode, insert) {
if (amlNode.$altExt) //@todo hack, need to re-arch layouting
return;
amlNode.$propHandlers["left"] =
amlNode.$propHandlers["top"] =
amlNode.$propHandlers["right"] =
amlNode.$propHandlers["bottom"] = apf.K;
var propHandlers = handlers[apf.hasFlexibleBox];
for (var prop in propHandlers) {
amlNode.$propHandlers[prop] = propHandlers[prop];
}
if (amlNode.nodeFunc == apf.NODE_VISIBLE) {
if (apf.hasFlexibleBox) {
//input elements are not handled correctly by firefox and webkit
if (amlNode.$ext.tagName == "INPUT" || input[amlNode.$ext.tagName]) {
var doc = amlNode.$ext.ownerDocument;
amlNode.$altExt = doc.createElement("div");
amlNode.parentNode.$int.replaceChild(amlNode.$altExt, amlNode.$ext);
amlNode.$altExt.style.boxSizing = "border-box";
amlNode.$altExt.appendChild(amlNode.$ext);
var d = apf.getDiff(amlNode.$ext);
//amlNode.$altExt.style.padding = "0 " + d[0] + "px " + d[1] + "px 0";
amlNode.$altExt.style.height = "100%";
amlNode.$altExt.style.width = "0";
amlNode.$altExt.style.lineHeight = 0;
amlNode.$altExt.style.margin = "-1px 0 0 0";
amlNode.$ext.style.width = "100%";
amlNode.$ext.style.height = "100%";
amlNode.$ext.style.top = "1px";
amlNode.$ext.style.position = "relative";
}
else {
if (apf.getStyle(amlNode.$ext, "display") == "inline")
amlNode.$ext.style.display = "block"; //@todo undo
//This is nice for positioning elements in the context of an hbox/vbox
//if (apf.getStyle(amlNode.$ext, "position") == "absolute")
//amlNode.$ext.style.position = "relative"; //@todo undo
}
amlNode.$ext.style.boxSizing = "border-box";
}
else {
if (this.$vbox) {
amlNode.$br = this.$int.insertBefore(amlNode.$ext.ownerDocument.createElement("br"), amlNode.$ext.nextSibling);
if (amlNode.visible === false)
amlNode.$br.style.display = "none";
}
else {
if (amlNode.visible !== false) {
amlNode.$ext.style.display = "inline-block";
}
this.$int.style.whiteSpace = "";
amlNode.$ext.style.whiteSpace = apf.getStyle(amlNode.$ext, "whiteSpace") || "normal";
this.$int.style.whiteSpace = "nowrap";
}
this.$int.style.fontSize = "0";
if (!amlNode.$box) {
var fontSize = apf.getStyle(amlNode.$ext, "fontSize");
if (fontSize == "0px") {
amlNode.$ext.style.fontSize = "";
var pNode = this.$int.parentNode;
while (apf.getStyle(pNode, "fontSize") == "0px") {
pNode = pNode.parentNode;
}
fontSize = apf.getStyle(pNode, "fontSize");
}
amlNode.$ext.style.fontSize = fontSize;//apf.getStyle(amlNode.$ext, "fontSize") || "normal";
}
amlNode.addEventListener("resize", resizeHandler);
}
amlNode.addEventListener("prop.visible", visibleHandler);
this.$noResize = true;
if (amlNode.height)
propHandlers.height.call(amlNode, amlNode.height);
if (amlNode.width)
propHandlers.width.call(amlNode, amlNode.width);
if (amlNode.margin)
propHandlers.margin.call(amlNode, amlNode.margin);
if (amlNode.flex)
propHandlers.flex.call(amlNode, amlNode.flex);
//Ie somehow sets the visible flags in between registration
var isLast = isLastVisibleChild(amlNode);
if (isLast || insert) {
this.$propHandlers["padding"].call(this, this.padding);
this.$propHandlers["align"].call(this, this.align);
if (!apf.hasFlexibleBox)
this.$propHandlers["pack"].call(this, this.pack);
if (amlNode.visible !== false) //insert && - removed because for new nodes that are being attached to the tree insert is not set
visibleHandler.call(amlNode, {value: true});
//@todo this needs more work
if (insert && amlNode.previousSibling) {
var prev = amlNode.previousSibling;
while (prev && (prev.nodeType != 1 || prev.localName == "splitter"))
prev = prev.previousSibling;
if (prev)
visibleHandler.call(prev, {value: true});
}
}
else if (this.splitters && !amlNode.$splitter && amlNode.visible !== false && !amlNode.nosplitter) {
if (amlNode.$ext.nextSibling != (amlNode.nextSibling
&& (amlNode.nextSibling.$altExt || amlNode.nextSibling.$ext))) {
var _self = this;
setTimeout(function(){
_self.insertBefore(
_self.ownerDocument.createElementNS(apf.ns.aml, "splitter"),
amlNode.nextSibling);
});
}
else {
this.insertBefore(
this.ownerDocument.createElementNS(apf.ns.aml, "splitter"),
amlNode.nextSibling);
}
}
delete this.$noResize;
if (!apf.hasFlexibleBox && isLast)
this.$resize();
}
}
this.unregister = function(amlNode) {
if (!amlNode.$propHandlers)
return;
amlNode.$propHandlers["left"] =
amlNode.$propHandlers["top"] =
amlNode.$propHandlers["right"] =
amlNode.$propHandlers["bottom"] = null;
var propHandlers = handlers[apf.hasFlexibleBox];
for (var prop in propHandlers) {
delete amlNode.$propHandlers[prop];
}
//Clear css properties and set layout
if (amlNode.nodeFunc == apf.NODE_VISIBLE) {
if (amlNode.flex) {
var flex = amlNode.flex;
propHandlers.flex.call(amlNode, 0);
amlNode.flex = flex;
}
if (apf.hasFlexibleBox) {
amlNode.$ext.style.boxSizing = "";
}
else {
amlNode.$ext.style.verticalAlign = "";
amlNode.$ext.style.textAlign = "";
amlNode.$ext.style.whiteSpace = "";
if (amlNode.$br) {
amlNode.$br.parentNode.removeChild(amlNode.$br);
delete amlNode.$br;
//amlNode.$ext.style.fontSize = "";
}
amlNode.removeEventListener("resize", resizeHandler);
}
amlNode.removeEventListener("prop.visible", visibleHandler);
amlNode.$ext.style.display = amlNode.visible ? "block" : "none";
if (amlNode.margin)
amlNode.$ext.style.margin = "";
if (amlNode.width)
amlNode.$ext.style.width = "";
if (this.splitters && !amlNode.$splitter) {
if (amlNode.nextSibling && amlNode.nextSibling.$splitter)
amlNode.nextSibling.removeNode();
if (isLastVisibleChild(amlNode) && amlNode.previousSibling
&& amlNode.previousSibling.$splitter)
amlNode.previousSibling.removeNode();
}
}
}
/*
this.addEventListener("DOMNodeInsertedIntoDocument", function(e) {
this.register(this.parentNode);
});
*/
// *** DOM Hooks *** //
this.addEventListener("DOMNodeRemoved", function(e) {
if (e.$doOnlyAdmin || e.currentTarget == this)
return;
if (e.relatedNode == this) {
this.unregister(e.currentTarget);
//e.currentTarget.$setLayout();
}
});
this.addEventListener("DOMNodeInserted", function(e) {
if (e.currentTarget == this) {
if (this.visible)
this.$ext.style.display = apf.CSS_DISPLAY_FLEX; //Webkit issue
return;
}
if (e.currentTarget.nodeType != 1
|| e.currentTarget.nodeFunc != apf.NODE_VISIBLE)
return;
if (e.relatedNode == this && !e.$isMoveWithinParent) {
e.currentTarget.$setLayout(this.localName, true);
if (e.currentTarget.$altExt) {
return false;
}
}
});
function myVisibleHandler(e) {
if (e.value)
this.$int.style.display = apf.CSS_DISPLAY_FLEX;
}
function myHeightHandler(e) {
clearInterval(this.$heighttimer);
if (e.value || this.align != "stretch") {
delete this.$heighttimer;
}
else if (!this.$heighttimer) {
var _self = this;
this.$heighttimer = $setInterval(function(){
if (_self.$amlDestroyed)
return;
var nodes = _self.childNodes;
for (var $int, i = 0, l = nodes.length; i < l; i++) {
if (!($int = (node = nodes[i]).$int || node.$container))
continue;
if (Math.min($int.scrollHeight, node["maxheight"] || 10000) > $int.offsetHeight)
return _self.$resize(true);
}
if (_self.flex)
clearInterval(this.$heighttimer);
}, this.flex ? 1 : 500);
}
}
this.$draw = function(){
var doc = this.$pHtmlNode.ownerDocument;
this.$ext = this.$pHtmlNode.appendChild(doc.createElement("div"));
if (this.getAttribute("style"))
this.$ext.setAttribute("style", this.getAttribute("style"));
this.$ext.className = this.localName;
this.$vbox = this.localName == "vbox";
this.$int = !apf.hasFlexibleBox && this.$vbox //@todo reparenting for gecko needs some admin work
? this.$ext.appendChild(doc.createElement("div"))
: this.$ext;
this.$ext.host = this;
if (!apf.hasFlexibleBox && this.$vbox) {
this.$int.style.display = "inline-block";
this.$int.style.width = "100%";
}
if (apf.hasFlex) {
this.$display = "-" + apf.CSSPREFIX +"-box";
this.$int.style.display = this.$int.style.display || apf.CSS_DISPLAY_FLEX;
this.$int.style.flexDirection = this.localName == "hbox" ? "" : "column";
this.$int.style.alignItems = "stretch";
this.addEventListener("prop.visible", myVisibleHandler);
}
else if (apf.hasFlexibleBox) {
this.$display = "-" + apf.CSSPREFIX +"-box";
this.$int.style.display = apf.CSS_DISPLAY_FLEX;
this.$int.style[apf.CSSPREFIX + "BoxOrient"] = this.localName == "hbox" ? "horizontal" : "vertical";
this.$int.style[apf.CSSPREFIX + "BoxAlign"] = "stretch";
this.addEventListener("prop.visible", myVisibleHandler);
}
else {
if (!this.$vbox) {
this.$int.style.whiteSpace = "nowrap";
this.addEventListener("prop.height", myHeightHandler);
}
var spacer = (!apf.hasFlexibleBox && this.$vbox ? this.$ext : this.$int)
.appendChild(doc.createElement("strong"));
spacer.style.height = "100%";
spacer.style.display = "inline-block";
//spacer.style.marginLeft = "-4px";
spacer.style.verticalAlign = "middle";
this.addEventListener("resize", this.$resize);
}
if (this.getAttribute("class"))
apf.setStyleClass(this.$ext, this.getAttribute("class"));
this.$originalMin = [this.minwidth || 0, this.minheight || 0];
};
this.$resize = function(force) {
if (!this.$amlLoaded || this.$noResize)
return;
//Protection for stretch re-resizing
if (force !== true && this.$lastSize &&
this.$lastSize[0] == this.$int.offsetWidth &&
this.$lastSize[1] == this.$int.offsetHeight)
return;
if (!apf.window.vManager.check(this, this.$uniqueId, this.$resize))
return;
this.$noResize = true;
this.$lastSize = [this.$int.offsetWidth, this.$int.offsetHeight];
//this.$ext.style.border = "1px solid " + (["red", "green", "blue", "orange", "pink", "yellow"])[Math.round(Math.random() * 5)];
/*if (this.$table.offsetWidth >= this.$ext.offsetWidth)
this.$ext.style.minWidth = (this.minwidth = Math.max(0, this.$table.offsetWidth
- apf.getWidthDiff(this.$ext))) + "px";
else {
this.$ext.style.minWidth = "";
this.minwidth = this.$originalMin[0];
}
if (this.$table.offsetHeight >= this.$ext.offsetHeight)
this.$ext.style.minHeight = (this.minheight = Math.max(0, this.$table.offsetHeight
- apf.getHeightDiff(this.$ext))) + "px";
else {
this.$ext.style.minHeight = "";
this.minheight = this.$originalMin[1];
}*/
//if (!this.$vbox) alert("here");
var total = 0;
var size = this.$vbox ? "width" : "height";
var minsize = this.$vbox ? "minWidth" : "minHeight";
var osize = this.$vbox ? "height" : "width";
var scroll = this.$vbox ? "scrollWidth" : "scrollHeight";
var offset = this.$vbox ? "offsetWidth" : "offsetHeight";
var ooffset = this.$vbox ? "offsetHeight" : "offsetWidth";
var getDiff = this.$vbox ? "getWidthDiff" : "getHeightDiff";
var ogetDiff = this.$vbox ? "getHeightDiff" : "getWidthDiff";
var inner = this.$vbox ? "getHtmlInnerWidth" : "getHtmlInnerHeight";
var oinner = this.$vbox ? "getHtmlInnerHeight" : "getHtmlInnerWidth";
var borders = this.$vbox ? "getVerBorders" : "getHorBorders";
var nodes = this.childNodes, hNodes = [], fW = 0, max = 0;
for (var node, i = 0; i < nodes.length; i++) {
if ((node = nodes[i]).nodeFunc != apf.NODE_VISIBLE || node.visible === false || !node.$amlLoaded)
continue;
hNodes.push(node);
if (!node[size]) {
//if (!node.$skipResizeOnce) node.$skipResizeOnce = 1;
//else node.$skipResizeOnce++;
//node.$skipResizeOnce = 1
//node.$ext.style[size] = ""; //@todo this is a sucky way of measuring
var m = node.margin && apf.getBox(node.margin);
if (m && this.$vbox) m.unshift();
var mdiff = (m ? m[0] + m[2] : 0);
max = Math.max(max, mdiff + Math.min(node.$ext[scroll] + apf[borders](node.$ext), node["max" + size] || 10000));
}
if (parseInt(node.flex))
total += parseFloat(node.flex);
else {
var m = node.margin && apf.getBox(node.margin);
if (m && !this.$vbox) m.shift();
fW += node.$ext[ooffset] + (m ? m[0] + m[2] : 0); //this.padding +
}
}
if (!max && this[size]) {
max = this[size]
//- (this.$vbox ? this.$edge[0] + this.$edge[2] : this.$edge[1] + this.$edge[3]);
- apf[ogetDiff](this.$ext);
}
/*
&& (this[size] || this.flex)
*/
if (this.align == "stretch") {
//var hasSize = this[size] || this.flex;
var l = hNodes.length;
var pH = max;//this.$int[offset] - apf[getDiff](this.$int);// - (2 * this.padding);
for (var i = 0; i < l; i++) {
node = hNodes[i];
if (!node[size] && !this.$vbox || this.$vbox && input[node.$ext.tagName]) {
var m = node.margin && apf.getBox(node.margin);
if (m && this.$vbox) m.unshift();
var mdiff = (m ? m[0] + m[2] : 0);
/*shouldClear = !this[size] && !this.flex && node.$ext.offsetHeight == (pH - mdiff);
if (shouldClear)
node.$ext.style[size] = "";
else
node.$ext.style[size] = Math.max(0, pH - apf[getDiff](node.$ext) - mdiff) + "px";
node.$setResizeHeight = !shouldClear;*/
//!this[size] && !this.flex
if (max && Math.min(node.$ext[scroll], node["max" + size] || 10000) != max)
node.$ext.style[size] = Math.max(0, max - apf[getDiff](node.$ext) - mdiff) + "px";
else
node.$ext.style[size] = "";
/*node.$ext.style[size] = !this[size] && !this.flex && node.$ext.offsetHeight == pH - mdiff
? ""
: Math.max(0, pH - apf[getDiff](node.$ext) - mdiff) + "px";*/
}
}
}
//Flexing
if (total > 0) {
if (this.$vbox)
this.$int.style.height = "100%";
this.$int.style.overflow = "hidden";
var splitterCount = this.$aml.querySelectorAll("splitter").length * 2;
var rW = this.$int[ooffset] - apf[ogetDiff](this.$int) - fW
- ((hNodes.length - 1 - splitterCount) * this.padding);// - (2 * this.edge);
var lW = rW, done = 0;
for (var i = 0, l = hNodes.length; i < l; i++) {
if ((node = hNodes[i]).flex) {
var v = (i % 2 == 0 ? Math.floor : Math.ceil)((rW / total) * parseInt(node.flex));
done += parseInt(node.flex);
var m = node.margin && apf.getBox(node.margin);
if (m && !this.$vbox) m.shift();
node.$ext.style[osize] = Math.max(0, (done == total ? lW : v) - apf[ogetDiff](node.$ext) - (m ? m[0] + m[2] : 0)) + "px";
lW -= v;
}
}
}
else {
if (this.$vbox)
this.$int.style.height = "";
this.$int.style.overflow = "";
}
this.$noResize = false;
/*this.$noResize = true;
var _self = this;
setTimeout(function(){
_self.$noResize = false;
});*/
}
this.$loadAml = function(x) {
if (this.padding == undefined)
this.padding = 0;
//this.$propHandlers.padding.call(this, this.padding = 0);
if (this.edge == undefined)
this.$propHandlers.edge.call(this, this.edge = 0);
if (this.pack == undefined)
this.$propHandlers.pack.call(this, this.edge = "start");
if (this.align == undefined)
this.align = "stretch";
//this.$propHandlers.align.call(this, this.align = "stretch");
if (!apf.hasFlexibleBox && !this.$vbox && !this.height && this.align == "stretch")
myHeightHandler.call(this, {});
};
}).call(apf.vbox.prototype = new apf.GuiElement());
apf.hbox.prototype = apf.vbox.prototype;
apf.aml.setElement("hbox", apf.hbox);
apf.aml.setElement("vbox", apf.vbox);
};
});