//WA 核心部分 (function () { var WA = this.WA = this.WA || { global: this }; var emptyConstructor = function () { }; /** * WA框架的继承方法。 * @param {Function} childClass 子类。 * @param {Function} parentClass 父类。 */ WA.inherit = function (childClass, parentClass) { emptyConstructor.prototype = parentClass.prototype; childClass.superClass = parentClass.prototype; childClass.prototype = new emptyConstructor(); childClass.prototype.constructor = childClass; //WA.merge(childClass.prototype, parentClass.prototype); }; /** * 把props参数指定的属性或方法复制到obj对象上。 * @param {Object} obj Object对象。 * @param {Object} props 包含要复制到obj对象上的属性或方法的对象。 * @param {Boolean} strict 指定是否采用严格模式复制。默认为false。 * @return {Object} 复制后的obj对象。 */ WA.merge = function (obj, props, strict) { for (var key in props) { if (!strict || obj.hasOwnProperty(key) || obj[key] !== undefined) obj[key] = props[key]; } return obj; }; /** * 根据限定名称返回一个命名空间(从global开始)。如:WA.use('WA.test')。 * @param {String} 指定新的命名空间的名称。如WA.test等。 * @return {Object} 参数name指定的命名空间对象。 */ WA.use = function (name, win) { win = win || WA.global; var parts = name.split("."), obj = win; for (var i = 0; i < parts.length; i++) { var p = parts[i]; obj = obj[p] || (obj[p] = {}); } return obj; }; WA.Guid = function () { var guid = 0; return function () { return guid++; } }(); /** * 根据id获得DOM对象。 * @param {String} id DOM对象的id。 * @return {HTMLElement} DOM对象。 */ WA.getDOM = function (id, doc) { doc = doc || document; return doc.getElementById(id); } /** * 创建一个指定类型type和属性props的DOM对象。 * @param {String} type 指定DOM的类型。比如canvas,div等。 * @param {Object} props 指定生成的DOM的属性对象。 * @return {HTMLElement} 新生成的DOM对象。 */ WA.createDOM = function (type, props) { var dom = document.createElement(type); for (var p in props) { var val = props[p]; if (p == "style") { for (var s in val) dom.style[s] = val[s]; } else { dom[p] = val; } } return dom; }; WA.isNumber = function (obj) { return Object.prototype.toString.call(obj) == "[object Number]"; } WA.isArray = function (obj) { return Object.prototype.toString.call(obj) == "[object Array]"; } WA.isObject = function (obj) { return Object.prototype.toString.call(obj) == "[object Object]"; } WA.isDom = function (obj) { if (obj.nodeType !== undefined && !WA.isObject(obj)) return true; return false; } if (this.W === undefined) this.W = WA; })(); //WA.EventDispatcher (function () { /** * 构造函数. * @name EventDispatcher * @class EventDispatcher类是可调度事件的类的基类,它允许显示列表上的任何对象都是一个事件目标。 */ var EventDispatcher = WA.EventDispatcher = function () { //事件映射表,格式为:{type1:[listener1, listener2], type2:[listener3, listener4]} this._eventMap = {}; }; /** * 注册事件侦听器对象,以使侦听器能够接收事件通知。 */ EventDispatcher.prototype.addEvent = function (type, listener) { var map = this._eventMap[type]; if (map == null) map = this._eventMap[type] = []; if (map.indexOf(listener) == -1) { map.push(listener); return true; } return false; }; /** * 删除事件侦听器。 */ EventDispatcher.prototype.removeEvent = function (type, listener) { if (arguments.length == 1) return this.removeEventListenerByType(type); var map = this._eventMap[type]; if (map == null) return false; for (var i = 0; i < map.length; i++) { var li = map[i]; if (li === listener) { map.splice(i, 1); if (map.length == 0) delete this._eventMap[type]; return true; } } return false; }; /** * 删除所有事件侦听器。 */ EventDispatcher.prototype.removeAllEvents = function () { this._eventMap = {}; }; /** * 派发事件,调用事件侦听器。 */ EventDispatcher.prototype.fireEvent = function (event) { var map = this._eventMap[event.type]; if (map == null) return false; if (!event.target) event.target = this; map = map.slice(); for (var i = 0; i < map.length; i++) { var listener = map[i]; if (typeof (listener) == "function") { listener.call(this, event); } } return true; }; /** * 检查是否为指定事件类型注册了任何侦听器。 */ EventDispatcher.prototype.hasEventListener = function (type) { var map = this._eventMap[type]; return map != null && map.length > 0; }; //添加若干的常用的快捷缩写方法 EventDispatcher.prototype.on = EventDispatcher.prototype.addEvent; EventDispatcher.prototype.un = EventDispatcher.prototype.removeEvent; EventDispatcher.prototype.fire = EventDispatcher.prototype.fireEvent; })(); //WA.UIUtil (function () { var UIUtil = WA.UIUtil = { //解析CSS属性 panding,转换成对象 Transform: function (value) { var result = { top: 0, left: 0, right: 0, buttom: 0 }; if (value != "") { var vle = value.split(" "); if (vle.length == 1) { vle[1] = vle[2] = vle[3] = vle[0] } else if (vle.length == 2) { vle[2] = vle[0] vle[3] = vle[1] } else if (vle.length == 3) { vle[3] = vle[1] } result.top = parseInt(vle[0]), result.right = parseInt(vle[1]), result.buttom = parseInt(vle[2]), result.left = parseInt(vle[3]); } return result; }, //根据布局类型,计算子元素宽高 ExecItemLayout: function () { } } })(); //WA.UI (function () { /* 所有视图的基类 */ var UI = WA.UI = function (props) { this.config = props; //配置参数 this._tag = "div"; //默认的标签 this.domElement = null //该类对应的DOM元素 this.renderTo = null; //要渲染的目标对象 this.width = null; //设置的宽度 this.height = null; //设置的高度 this.html = ""; //视图的HTML this.lookProperty = {}; //锁定属性,只由父视图更改 UI.superClass.constructor.call(this, props); WA.merge(this, props, true); this.init(); } WA.inherit(UI, WA.EventDispatcher); UI.prototype.init = function () { this.initElement(); this._update(); } //初始化DOM UI.prototype.initElement = function () { this.domElement = $(WA.createDOM(this._tag)); } //渲染到页面 UI.prototype._render = function () { this.render(); } //更新数据 UI.prototype._update = function () { this.update(); } UI.prototype.update = function () { } //更新布局位置 UI.prototype._doLayout = function () { var con = this.compute(); this.doLayout(con); this.doLayoutContent(con); } UI.prototype.doLayout = function (config) { var size = { width: null, height: null } WA.merge(size, config, true); WA.merge(size, this.lookProperty, true); this.domElement.setStyles(size); } //更新内容布局 UI.prototype.doLayoutContent = function () { } //计算布局相关数据 UI.prototype.compute = function () { return { width: this.width, height: this.height } } UI.prototype.render = function (parent) { if (this.renderTo) WA.getDOM(this.renderTo).appendChild(this.toElement()); } //返回对象对应的DOM UI.prototype.toElement = function () { return this.domElement; } })(); //WA.UI.Container (function () { //容器视图,允许有子对象 var Container = WA.UI.Container = function (props) { this.domContent = null; //内容区对象 this.padding = ""; //内容区Padding值 this.parent = null; //父容器 this.items = []; //自容器 this.layout = "Auto"; //指定子元素布局类型 Container.superClass.constructor.call(this, props); if (props.item) this.addChild.apply(this, props.item); } WA.inherit(Container, WA.UI); //添加子对象 Container.prototype.addChild = function () { for (var i = 0; i < arguments.length; i++) { var con = arguments[i]; if (con.parent) { con.parent.removeChild(con); } con.parent = this; var ix = this.items.indexOf(con) if (ix != -1) { this.items.splice(ix, 1); } this.domContent.appendChild(con.toElement()); this.items.push(con); } } //移除子对象 Container.prototype.removeChild = function (child) { var ix = this.items.indexOf(child); if (ix != -1) { this.items.splice(ix, 1); child.domElement.parentNode.removeChild(child.domElement); } } Container.prototype.compute = function () { var com = Container.superClass.compute.call(this); com.padding = WA.UIUtil.Transform(this.padding); return com; } Container.prototype._doLayout = function () { Container.superClass._doLayout.call(this); for (var i = 0; i < this.items.length; i++) { this.items[i]._doLayout(); } } Container.prototype._render = function () { this.render(); } })(); //WA.UI.Panel (function () { //面板视图,由标题,内容区组成 var Panel = WA.UI.Panel = function (props) { this.title = ""; //标题内容 this.isTitle = true; //是否显示标题栏 this.domTitle = null; //标题栏DOM Panel.superClass.constructor.call(this, props); } WA.inherit(Panel, WA.UI.Container); Panel.prototype.initElement = function () { Panel.superClass.initElement.call(this); this.domElement.addClass("ui-panel"); this.domElement.innerHTML = '' + '' + '' + '' + '' + '' + '' this.domTitle = this.domElement.getElement(".ui-panel-title"); this.domContent = this.domElement.getElement(".ui-content"); } Panel.prototype.update = function () { this.domTitle.set("html", this.title); this.domContent.set("html", this.html); } Panel.prototype.doLayoutContent = function (option) { Panel.superClass.doLayoutContent.call(this, option); this.domContent.getParent().setStyle("padding", this.padding); this.domContent.setStyles({ width: option.width - option.padding.left - option.padding.right, height: option.height - option.padding.top - option.padding.top - 25 }); } })(); //WA.UI.ViewPort (function () { //视窗,会根据窗口变化而变化,一个页面只有一个 var ViewPort = WA.UI.ViewPort = function (props) { ViewPort.superClass.constructor.call(this, props); this._render(); this._doLayout(); } WA.inherit(ViewPort, WA.UI.Panel); ViewPort.prototype.init = function () { ViewPort.superClass.init.call(this); this.addEvent("doLayout", this._doLayout); this._doLayout(); window.addEvent("resize", function () { this._doLayout(); }.bind(this)); } ViewPort.prototype.render = function () { document.body.appendChild(this.toElement()); } ViewPort.prototype.compute = function () { var com = ViewPort.superClass.compute.call(this); var winSize = window.getSize(); com.width = winSize.x - 2; com.height = winSize.y - 2; return com; } })();
经过了一天多的构思和编写,大致完成了一个模型,实现了一个最基本的功能.
WA //实现了继承机制
WA.UI //所有UI的基类
WA.UI.Container // UI容器,继承UI,定义实现添加子对象,在更新布局时,自动更新子对象,和布局类型
WA.UI.Panel //Panel控件,一个有标题,然后和内容区的一个UI控件,继承自UI.Container,也是最常用的控件了
WA.UI.ViewPort //视窗UI, 自动根据浏览器窗口大小变化而变化
简单案例:
new WA.UI.ViewPort({ title: "ViewPort 标题", padding: "10px", item: [ new WA.UI.Panel({ title: "Panel1 标题部分", width: 200, height: 220, padding: "5px 10px", html: "这是Panel1的内容, html和item不可共存" }) ] });
当然运行至此,还需要一个简单的CSS文件和1张图片,和 mootools.js(一个框架) , 后期不会依赖mootools.js
--------------------------------------------------------------------------------------------
预期下一步 , 实现一些布局方式,代码还得继续修改.