javascript控件开发之布局控件

上篇写完了页面控制器,本篇接着写下一个控件--布局控件,布局控件在系统开发中不算最重要,但也是起着举足经重的作用,相信做过网页的应该了解,在Html中页面布局是一件让人蛋痛的事情,有时候花一天都搞不定,因此所有控件开始之前,先把布局控件做好,后续有部份控件需要从这布局控件继承。
在html标签中,有外边距、内边距、还有边框、坐标这几样属性,这几项控制好,布局的大方向基本能做好,再有就是浏览器的兼容问题一并考虑,
首先,我们需要对先前写的com.ui.window.js做修改,把先前的 this.thisWindow改为this.win(前面的变量太长,改短一点)
对渲染函数render()进行修改
添加容器功能,控件内可以添加控件,
思路是
1 先拿到控件dom元素(this.win),
2 通过它获得父dom元素,
3 判断父dom元素的_object是否为空,
4 不为空就把父控件指向_object,
5 设置_object为当前控件的父对象,
6 给当前控件的dom(this.win)元素添加_object属性,指向当前控件this
上面的这个思路是通用思路,不管哪个控件,都会有这上下层关系

//初始化DOM框架
var parent = this.win.parentNode;
if(this.isNotEmpty(parent)) {
if(this.isNotEmpty(parent._object)) {
parent = parent._object;
}
this.setParent(parent, true);
}
this.win._object = this;
parent = null;

把设置内边距、外边距从doResize中移到render函数中来,
接着调用doResize函数.

this.setStyle(this.win, "winStyle");
//边距处理
var valpx = this.option.margin + "px";
if(this.win.style.margin != valpx) {
this.win.style.margin = valpx;
}
valpx = this.option.padding + "px";
if(this.win.style.padding != valpx) {
this.win.style.padding = valpx;
}
if(this.option.borderWidth !== "") {
this.win.style.borderWidth = this.option.borderWidth + "px";
}
//处理大小变量
if(this._hasResize() && this._update) {
this._doResize();
this._afterResize();
}

doReize保留最原始的设置位置、宽度、高度的代码。
其中新增加一个右对齐的代码,思路是获取父控件的宽度,计算靠右的位置,
当然父控件有可能是最原始的dom元素,也可能是别的容器控件,

if(this.isNotEmpty(this.option.right)) {
var pw = this.parent;
if(pw.isComponent) {
pw = pw._getRectWidth();
} else {
pw = this._getRectWidth(pw);
}
valpx = (pw - this.option.right - this.getWidth()) + "px";
if(this.win.style.left !== valpx) {
msg += " left:" + this.win.style.left + " to " + valpx + " ";
this.win.style.left = valpx;
isResize = true;
}
}

另外再修改内部宽高的获取函数,加一个参数,添加支持通过传入任一dom元素,返回除去边距后dom元素的内宽和内高,

/**
* 获取内宽.
* @return 返回宽度
*/
_getRectWidth:function(el) {
var width = this.getWidth();
if(this.isNotEmpty(el)) {
if(el.tagName == "BODY") {
//设置默认边距
width = this._getBodyWidth();
if(this.isEmpty(el.style.marginLeft)) {
el.style.marginLeft = "0px";
}
if(this.isEmpty(el.style.marginRight)) {
el.style.marginRight = "0px";
}
} else {
width = el.offsetWidth;
}
}
//总宽度减去边距宽度
width = width - (this._getMarginLeft(el)
+ this._getMarginRight(el)
+ this._getPaddingLeft(el)
+ this._getPaddingRight(el));
if(!this.browser.msie) {
width = width - (this._getBorderLeft(el)
+ this._getBorderRight(el));
}
return width;
},


修改完com.ui.window后,在component文件夹内添加com.ui.panel.js文件,并且在该件内编写我们的布局控件com.ui.panel,继承com.ui.window控件
控件的创建函数create中,添加默认的控件对齐方式this.align="none",添加是否panel控件的判断属性 this.isPanel=true

/**
* 创建函数
*/
create:function() {
this.base();
this.className = "com.ui.panel";
this.logInfo("create");
//对齐属性
this.align = "alNode";
this.isPanel = true;
},

渲染函数render中,除了调用基类渲染函数this.base()外,添加this.win的绝对样式属性,再调用对齐设置函数。

/**
* 渲染.
*/
render:function() {
this.beginUpdate();
this.base();
this.endUpdate();
//如果父层是控件对象则用绝对定位样式
if(this.isNotEmpty(this.parent)) {
this.win.style.position = "absolute";
}
//设置对齐方式
if(this.isNotEmpty(this.option.align)) {
this.setAlign(this.option.align);
}
},

渲染后函数afterRender中,判断如果父元素是body或其它dom元素时,为元素添加onresize事件,用作布局控件变化的的启动事件,在onresize事件中调用控件的_doResize函数

/**
* 渲染后函数.
*/
afterRender:function(){
//this.logInfo("Panel.afterRender");
var _this = this;
if(this.isNotEmpty(this.parent) &&
!this.parent.isComponent) {
//如果父控件是dom,则添加onResize事件
var _this = this;
var _lock = false;
this.parent.onresize = function(ev) {
if(_lock) return false;
_lock = true;
_this._doResize(_this.getBody());
_lock = false;
};
}
this.base();
},

_doResize事件是本控件的核心,参数有一个,用于传入指定的元素,参数可以不传,在此先计算left, top坐标和height, width

/**
* 执行对齐事件.
*/
_doResize:function(el){
this.base();
var lw = 0,
rw = 0,
th = 0,
bh = 0;
var alcn = null;
if(this.isNotEmpty(el)) {
var rectLeft = this._getPaddingLeft(el),
rectTop = this._getPaddingTop(el),
rectHeight = this._getRectHeight(el),
rectWidth = this._getRectWidth(el);
} else {
var rectLeft = this._getPaddingLeft(),
rectTop = this._getPaddingTop(),
rectHeight = this._getRectHeight(),
rectWidth = this._getRectWidth();
el = this;
}

接着控制当前控件内的所有子控件的布局及宽高,
该段代码的思路是,先运算alTop、alLeft、alRight、alBottom控件,合计已占用的左、右、顶和底的宽度,最后计算alClient

//处理所有子控件的对齐方式.
for(var i = 0, len = el.childComponent.length; i < len; i++) {
var cn = el.childComponent[i];
if(cn.isPanel) {
//只处理内部控件
var al = cn.getAlign();
if(al === "alClient") {
//全屏的留后处理
alcn = cn;
} else if(al === "alRight") {
//靠右
rw += cn.getWidth();
cn.setHeight(rectHeight - th - bh, false);
cn.setTop(th, false);
cn.setLeft(rectWidth - rw + rectLeft);
} else if(al === "alLeft") {
cn.setTop(th, false);
cn.setLeft(lw, false);
lw += cn.getWidth();
cn.setHeight(rectHeight - th - bh);
} else if(al === "alTop") {
cn.setTop(th, false);
cn.setLeft(lw, false);
th += cn.getHeight();
cn.setWidth(rectWidth - lw - rw);
} else if (al === "alBottom") {
//靠底
bh += cn.getHeight();
cn.setWidth(rectWidth - lw - rw, false);
cn.setTop(rectHeight - bh + rectTop);
cn.setLeft(lw, false);
}
} else {
cn._doResize();
}
cn = null;
}
if(this.isNotEmpty(alcn)) {
//最后处理全屏的控件.
alcn.setWidth(rectWidth - lw - rw, false);
alcn.setLeft(lw + rectLeft, false);
alcn.setHeight(rectHeight - th - bh, false);
alcn.setTop(th + rectTop);
}
alcn = null;
this._rectLeft = lw + rectLeft;
this._rectTop = th + rectTop;

最后添加设置对齐方式用的函数,

/**
* 设置对齐属性.
* @param algin 对齐方式
*/
setAlign:function(align) {
if(this.align !== align) {
this.align = align;
if(this.isNotEmpty(this.parent)) {
if(this.parent.isComponent) {
this.parent._doResize();
} else {
this._doResize(this.parent);
}
}
}
}

到此我们的的布局控件编写完成,
下面是test.html中的测试代码,

<!DOCTYPE html>
<head><title>test</title>
<script src="../script/common/init.js" type="text/javascript"></script>
</head>
<body code="controllor/test.js" scroll="no" style="overflow:hidden">
<div id='test1' code='com.ui.panel' option='{"align":"alTop","height":"40","width":"200","borderWidth":1,"padding":1}'></div>
<div id='test6' code='com.ui.panel' option='{"align":"alTop","height":"100","width":"200","borderWidth":1,"padding":1}'></div>
<div id='test4' code='com.ui.panel' option='{"align":"alBottom","height":"50","width":"200","borderWidth":1,"padding":1}'>
<div id='test2' code='com.ui.button' option='{"height":"25","width":"100","top":"12","right":"116"}'></div>
<div id='test3' code='com.ui.button' option='{"height":"25","width":"100","top":"12","right":"8"}'></div>
</div>
<div id='test7' code='com.ui.panel' option='{"align":"alLeft","height":"100","width":"200","borderWidth":1,"padding":1}'></div>
<div id='test5' code='com.ui.panel' option='{"align":"alClient","height":"100","width":"200","borderWidth":1,"padding":1}'></div>

</body>
</html>

完整代码请下载附件,
请关注下一篇,javascript控件开发之工具栏控件

[img]http://dl2.iteye.com/upload/attachment/0097/1294/43224005-885d-3799-b274-158173597522.jpg[/img]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值