'::hui_control::';
'use strict';
// __ __ ______ ______ _____ __ __
// /\ \ /\ \ /'\_/`\ /\ _ \ /\__ _\/\ __`\ /\ \/\ \
// \ `\`\\/'//\ \\ \ \/\ \\/_/\ \/\ \ \/\ \\ \ \ \ \
// `\ `\ /' \ \ \__\ \\ \ __ \ \ \ \ \ \ \ \ \\ \ \ \ \
// `\ \ \ \ \ \_/\ \\ \ \/\ \ \ \ \ \ \ \_\ \\ \ \_\ \
// \ \_\ \ \_\\ \_\\ \_\ \_\ \ \_\ \ \_____\\ \_____\
// \/_/ \/_/ \/_/ \/_/\/_/ \/_/ \/_____/ \/_____/
//
/**
* @namespace hui.Control
* @description 基础控件类
* @public
* @author haiyang5210
* @since 2015-06-25 10:48
*/
hui.define('hui_control', ['hui_eventdispatcher'], function () {
/**
* @class hui.Flow
* @description Javascript简单异步框架。注:异步队列中的函数需要实现callback的接口
*/
hui.Flow = function () {
var me = this;
/**
* @property {Array} que 保存回调队列
* @memerberof hui.Flow
*/
me.que = [hui.fn(me.endFlow, me)]; // 注:存放要调用的函数列表
me.id = hui.Flow.getIndex(); // 注:仅用于标示,不会被调用(即使删掉也没什么影响)
me.parentflow = [];
/**
* @method hui.Flow.next
* @description 开始执行异步队列
* @public
* @memerberof hui.Flow
* @param {Function} callback 嵌套时的回调函数,其实就是hui.Flow.prototype.next
*/
me.next = function (callback) {
var args = [].slice.call(arguments, 0);
// console.log(me.id);
if (me.que.length > 0) {
var fn = me.que.shift();
fn.apply(null, args);
}
};
me.next._isFlowPrivate = hui.Flow.getIdentity();
me.next.mainFlow = me;
};
hui.Flow.getIdentity = (function () {
var guid = new Date().toString() + Math.random();
return function (formname) {
return guid;
};
})();
hui.Flow.getIndex = (function () {
var guid = 1;
return function (formname) {
return guid++;
};
})();
/**
* @method hui.Flow.push
* @description 添加需要异步执行的函数
* @public
* @memerberof hui.Flow
* @param {Function} fn 需要异步执行的函数
* @return {this} 返回主体以便于后续操作
* @example
* function doit() {
* alert('a');
*
* var que1 = new hui.Flow();
* que1.push(a);
* que1.push(d);
* setTimeout(function(){
* que1.next();
* },400);
* }
*
* function a(callback) {
* alert('a');
*
* var que2 = new hui.Flow();
* que2.push(b).push(c).push(callback);
*
* setTimeout(function(){
* que2.next();
* },400);
* }
* function b(callback) {
* alert('b');
* callback&&callback();
* }
* function c(callback) {
* alert('c');
* callback&&callback();
* }
*/
hui.Flow.prototype.push = function (fn) {
var me = this;
if (fn && fn._isFlowPrivate === hui.Flow.getIdentity()) {
var endFlow = me.que.pop();
me.que.push(fn);
me.que.push(endFlow);
if (fn.mainFlow) {
fn.mainFlow.parentflow.push(me);
}
}
else {
var callback = hui.fn(me.next, me);
callback._isFlowPrivate = hui.Flow.getIdentity();
var endFlow = me.que.pop();
me.que.push(function () {
fn.apply(me, [callback].concat([].slice.call(arguments, 0)));
});
me.que.push(endFlow);
}
return me;
};
hui.Flow.prototype.endFlow = function () {
var me = this;
if (me.parentflow) {
while (me.parentflow.length) {
me.parentflow.pop().next();
}
}
};
/**
* @class hui.Control
* @description 基础控件类
* @param {Object} options 传入的初始化参数
* @param {String} pending 子类调用此构造函数时需传入'pending'
*/
hui.Control = function (options, pending) {
hui.EventDispatcher.call(this);
// 状态列表
options = options || {};
// 初始化参数
this.initOptions(options);
// 生成控件id
if (!this.id) {
this.id = hui.Control.makeGUID(this.formname);
}
hui.Control.appendControl(options.parentControl, this);
// 子类调用此构造函数不可以立即执行!!只能放在子类的构造函数中执行!否则实例化时找不到子类中定义的属性!
// 进入控件处理主流程!
if (pending != 'pending') {
this.enterControl();
}
};
/**
* @property {Object} hui.Control.prototype 基础控件类原型
*/
hui.Control.prototype = {
/**
* @method initOptions
* @description 初始化参数
* @protected
* @memerberof hui.Control.prototype
* @param {Object} options 参数集合
*/
initOptions: function (options) {
for (var k in options) {
if (options.hasOwnProperty(k)) {
this[k] = options[k];
}
}
},
// 注: childControl不能放在这里,放在这里会导致"原型继承属性只是用一个副本的坑"!!
// cc: [],
/**
* @method getClass
* @description 获取dom子部件的css class
* @memerberof hui.Control.prototype
* @protected
* @return {String}
*/
getClass: function (opt_key) {
if (!this.type) {
return '';
}
var me = this,
type = String(me.type).toLowerCase(),
className = 'hui_' + type,
skinName = 'skin_' + type + '_' + me.skin;
if (opt_key) {
className += '_' + opt_key;
skinName += '_' + opt_key;
}
if (me.skin) {
className = skinName + ' ' + className;
}
return className;
},
/**
* @method getId
* @description 获取dom子部件的id
* @memerberof hui.Control.prototype
* @public
* @return {String}
*/
getId: function (key) {
var me = this,
// uiAttr = hui.Control.UI_ATTRIBUTE || 'ui';
// idPrefix = 'ctrl' + this.type + this.id;
idPrefix = me.id === undefined ? '' : me.id;
if (key) {
idPrefix = idPrefix + key;
}
return idPrefix;
},
/**
* @method getMain
* @description 获取控件的elem(nodejs). 注:控件即使不需要显示任何内容也必须有一个挂载的elem(可以是隐藏的),
* @memerberof hui.Control.prototype
* 通过模板解析控件时会用到 [nodejs&browser]
* @public
* @return {String}
*/
getMain: function () {
var me = this,
elem;
elem = me.main ? document.getElementById(me.main) : null;
return elem;
},
mainFocus: function () {
// Fix IE8 bug: hidden elem focus() cause error
var main = this.getMain();
try {
main.focus();
}
catch (e) {}
},
/**
* @method getInnerHTML
* @description 获取控件的innerHTML
* @memerberof hui.Control.prototype
* @public
* @param {HTMLElement} elem 默认为控件主DOM[可选]
* @return {String}
*/
getInnerHTML: function (elem) {
var me = this,
elem = elem || me.getMain(),
html = '';
if (elem.getInnerHTML) {
html = elem.getInnerHTML();
}
else if (elem.innerHTML !== undefined) {
html = elem.innerHTML;
}
return html;
},
/**
* @method setInnerHTML
* @description 设定控件的innerHTML[nodejs&browser]
* @memerberof hui.Control.prototype
* @public
* @param {String} html innerHTML
* @param {HTMLElement} elem 默认为控件主DOM[可选]
* @return {String}
*/
setInnerHTML: function (elem, html) {
if (!html && typeof elem === 'string' && this.getMain) {
html = elem;
elem = this.getMain();
}
return hui.Control.setInnerHTML(elem, html);
},
/**
* @method render
* @description 渲染控件
* @memerberof hui.Control.prototype
* @public
*/
render: function () {
// var me = this;
// var main = me.getMain();
// var data = me.model && me.model.getData && typeof me.model.getData === 'function' ? me.model.getData() : {};
// hui.Control.init(main, data, me);
// main.setAttribute('_rendered', 'true');
},
//
/**
* @description 生成HTML
* @memerberof hui.Control.prototype
* @public
*/
// initView: function (callback) {
// callback && callback();
// },
/**
* @method initBehavior
* @description 绑定事件
* @memerberof hui.Control.prototype
* @public
*/
initBehavior: function () {
//var me = this;
},
initBehaviorByTree: function () {
var me = this,
main = me.getMain();
if (me.cc) {
for (var i = 0, len = me.cc.length; i < len; i++) {
me.cc[i].initBehaviorByTree();
}
}
if (main && main.getAttribute('_initbehavior') != 'true') {
main.setAttribute('_initbehavior', 'true');
me.initBehavior();
}
},
/**
* @method validate
* @description 验证控件的值
* @memerberof hui.Control.prototype
* @public
*/
validate: function (show_error) {
var me = this,
result = true,
cc = me.cc,
Validator = hui.Control.getExtClass('hui.Validator'),
c,
list,
m,
n;
if (me.rule && !me.isDisabled()) {
result = false;
list = String(me.rule).split('||');
for (var i = 0, len = list.length; i < len && !result; i++) {
c = true;
m = list[i].split('&&');
for (var j = 0, len2 = m.length; j < len2; j++) {
n = m[j];
c = c && Validator.applyRule(me, n, show_error);
}
result = result || c;
}
}
// result === null
if (!me.rule && cc && !me.isDisabled()) {
result = true;
m = null;
for (var i = 0, len = cc.length; i < len; i++) {
n = cc[i].validate(show_error);
result = n && result;
m = m === null && !n ? cc[i] : m;
}
//m && m.getInput && m.getInput() && m.getInput().focus();
}
return result;
},
hideError: function () {
var me = this,
Validator = hui.Control.getExtClass('hui.Validator');
Validator.cancelNotice(me.getMain());
if (me.cc) {
for (var i = 0, len = me.cc.length; i < len; i++) {
me.cc[i].hideError();
}
}
return me;
},
showError: function (errorMsg, code) {
var me = this,
Validator = hui.Control.getExtClass('hui.Validator'),
rule = Validator.getRule(me.rule);
if (rule && code === 'by_code') {
errorMsg = rule.noticeText[errorMsg];
}
Validator.showError(me.getMain(), errorMsg);
return me;
},
showErrorByTree: function (paramMap, code) {
var me = this,
value,
list,
ctr;
if (me.cc && paramMap) {
for (var formname in paramMap) {
if (formname && paramMap.hasOwnProperty(formname)) {
value = Object.prototype.toString.call(paramMap[formname]) !== '[object Array]' ? [paramMap[formname]] : paramMap[formname];
list = me.getByFormnameAll(formname, false);
if (list.length < 1) {
continue;
}
for (var i = 0, len = value.length; i < len; i++) {
ctr = list[i];
if (ctr) {
if (Object.prototype.toString.call(value[i]) === '[object Object]' &&
ctr.cc) {
ctr.showErrorByTree(value[i], code);
}
else if (ctr.showError) {
ctr.showError(value[i], code);
}
ctr = null;
}
}
}
}
}
return me;
},
showOK: function () {
var me = this,
Validator = hui.Control.getExtClass('hui.Validator');
Validator.showOK(me);
return me;
},
showWaiting: function () {
var me = this,
Validator = hui.Control.getExtClass('hui.Validator');
Validator.showWaiting(me);
return me;
},
// 返回控件的值
//getValue: new Function(), // 注: 控件直接返回值(对象/数组/字符串)时才能使用getValue! 获取所有子控件的值,应该用getParamMap
setValue: function (paramMap) {
var me = this;
if (me.cc && (/\[object Object\]/.test(Object.prototype.toString.call(paramMap)))) {
me.setValueByTree(this.value);
}
else {
// 注:在setValue/getValue时不允许使用me.getMain().setAttirbute('value', value)和me.getMain()
// .getAttirbute('value'),因为value有可能是数组/对象!!
// 如果确定value是num或str可以在子类中覆盖setValue/getValue!!
me.getMain().value = paramMap;
}
return me;
},
/**
* @method setValueByTree
* @description 给控件树一次性赋值
* @memerberof hui.Control.prototype
* @param {Object} paramMap 值
*/
setValueByTree: function (paramMap) {
var me = this,
value,
list,
ctr,
main;
if (me.cc && paramMap) {
for (var formname in paramMap) {
if (formname && paramMap.hasOwnProperty(formname)) {
value = Object.prototype.toString.call(paramMap[formname]) !== '[object Array]' ? [paramMap[formname]] : paramMap[formname];
list = me.getByFormnameAll(formname, false);
if (list.length < 1) {
continue;
}
for (var i = 0, len = list.length; i < len; i++) {
ctr = list[i];
if (ctr.constructor &&
ctr.setValue &&
ctr.getPresetValue) {
var presetValue = ctr.getPresetValue();
for (var j = 0, len2 = value.length; j < len2; j++) {
if (value[j] && presetValue === String(value[j])) {
ctr.setValue(value[j]);
break;
}
}
}
else if (ctr.constructor &&
ctr.setValue &&
ctr.setValue !== hui.Control.prototype.setValue) {
ctr.setValue(value[i]);
}
else if (ctr.cc) {
ctr.setValueByTree(value[i]);
}
else if (ctr.getMain || ctr.main) {
main = (ctr.getMain ? ctr.getMain() : document.getElementById(ctr.main)) || {};
main.value = value[i];
}
ctr = null;
}
}
}
}
return me;
},
getValue: function () {
var me = this,
main = me.getMain ? me.getMain() : document.getElementById(me.main),
value = main.value;
if (me.cc) {
value = me.getParamMap();
}
return value;
},
/**
* @method getParamMap
* @description 获取子控件的值,返回一个map
* @memerberof hui.Control.prototype
* @public
*/
getParamMap: function () {
var me = this,
paramMap = {},
ctr,
formname,
value,
groupList = {};
// 如果有子控件建议递归调用子控件的getValue!!
if (me.cc) {
for (var i = 0, len = me.cc.length; i < len; i++) {
ctr = me.cc[i];
formname = hui.Control.prototype.getFormname.call(ctr);
groupList[formname] = !!ctr.group;
if (String(ctr.isFormItem) !== 'false') {
paramMap[formname] = paramMap[formname] ? paramMap[formname] : [];
if (ctr.getValue) {
value = ctr.getValue();
paramMap[formname].push(value);
}
else if (ctr.getMain || ctr.main) {
value = (ctr.getMain ? ctr.getMain() : document.getElementById(ctr.main)).value;
paramMap[formname].push(value);
}
else if (ctr.cc) {
value = ctr.getParamMap();
paramMap[formname].push(value);
}
}
}
// 注:默认都用数组包装,此处还原为值
for (var i in paramMap) {
if (paramMap[i] && paramMap[i].length < 2) {
paramMap[i] = paramMap[i][0] !== undefined ? (groupList[i] ? paramMap[i] : paramMap[i][0]) : '';
}
}
}
return paramMap;
},
/**
* @method getByFormname
* @description 通过formname访问子控件
* @memerberof hui.Control.prototype
* @public
* @param {String} formname 子控件的formname
* @example
* <button hui-type="Button" hui-formname="save">Save</button>
* var save = hui.Control.getByFormname('save');
*/
getByFormname: function (formname) {
var me = this;
return hui.Control.getByFormname(formname, me);
},
getByFormnameAll: function (formname, all) {
var me = this;
return hui.Control.getByFormnameAll(formname, me, all);
},
/**
* @method show
* @description 显示控件
* @memerberof hui.Control.prototype
* @public
*/
show: function () {
this.getMain().style.display = 'block';
hui.Control.removeClass(this.getMain(), 'hide');
return this;
},
/**
* @method hide
* @description 隐藏控件
* @memerberof hui.Control.prototype
* @public
*/
hide: function () {
hui.Control.addClass(this.getMain(), 'hide');
this.getMain().style.display = 'none';
return this;
},
/**
* @method setDisabled
* @description 设置控件不可用状态
* @memerberof hui.Control.prototype
* @public
* @param {Boolean} disabled
*/
setDisabled: function (disabled) {
var me = this,
main = me.getMain();
main.disabled = typeof disabled === 'undefined' ? disabled = true : disabled;
if (main.disabled) {
hui.Control.addClass(main, me.getClass('disabled'));
}
else {
hui.Control.removeClass(main, me.getClass('disabled'));
}
return me;
},
/**
* @method setReadonly
* @description 设置控件不可用状态
* @memerberof hui.Control.prototype
* @public
* @param {Boolean} disabled
*/
setReadonly: function (readOnly) {
if (typeof readOnly === 'undefined') {
readOnly = true;
}
this.getMain().readOnly = readOnly;
return this;
},
/**
* @method isDisabled
* @description 判断控件不可用状态
* @memerberof hui.Control.prototype
* @public
* @return {boolean}
*/
isDisabled: function () {
return this.getMain().disabled;
},
isReadonly: function () {
return this.getMain().readOnly;
},
/**
* @method setSize
* @description 设置控件width和height
* @memerberof hui.Control.prototype
* @public
*/
setSize: function (size) {
var me = this,
main = me.getMain();
me.size = size ? size : me.size || {};
me.size.width = me.size.width === undefined ? me.size.w : me.size.width;
me.size.height = me.size.height === undefined ? me.size.h : me.size.height;
me.size.top = me.size.top === undefined ? me.size.t : me.size.top;
me.size.bottom = me.size.bottom === undefined ? me.size.b : me.size.bottom;
me.size.left = me.size.left === undefined ? me.size.l : me.size.left;
me.size.right = me.size.right === undefined ? me.size.r : me.size.right;
if (me.size && me.size.width) {
main.style.width = me.size.width + (typeof me.size.width !== 'string' ? 'px' : '');
}
if (me.size && me.size.height) {
main.style.height = me.size.height + (typeof me.size.height !== 'string' ? 'px' : '');
}
if (me.size && me.size.top) {
main.style.top = me.size.top + (typeof me.size.top !== 'string' ? 'px' : '');
}
if (me.size && me.size.bottom) {
main.style.bottom = me.size.bottom + (typeof me.size.bottom !== 'string' ? 'px' : '');
}
if (me.size && me.size.left) {
main.style.left = me.size.left + (typeof me.size.left !== 'string' ? 'px' : '');
}
if (me.size && me.size.right) {
main.style.right = me.size.right + (typeof me.size.right !== 'string' ? 'px' : '');
}
},
/**
* @method getFormname
* @description 获取表单控件的表单名
* @memerberof hui.Control.prototype
* @public
* @param {Object} control
*/
getFormname: function () {
var me = this,
main = me.getMain ? me.getMain() : document.getElementById(me.main);
var itemName = me.formname || me['name'] || (main ? main.getAttribute('name') : null);
return itemName;
},
/**
* @method dispose
* @description 释放控件
* @memerberof hui.Control.prototype
* @protected
*/
dispose: function () {
var me = this,
cc,
main = me.getMain ? me.getMain() : document.getElementById(me.main),
list;
// 从父控件的childControl中删除引用
if (me.parentControl) {
cc = me.parentControl.cc;
for (var i = 0, len = cc.length; i < len; i++) {
if (cc[i] === me) {
cc.splice(i, 1);
break;
}
}
}
me.disposeChild && me.disposeChild();
if (main) {
// 释放控件主区域的常用事件
list = 'onmouseover|onmouseout|onmousedown|onmouseup|onkeyup|onkeydown|onkeypress|onchange|onpropertychange|' +
'onfocus|onblur|onclick|ondblclick|ontouchstart|ontouchmove|ontouchend|ondragover|ondrop|ondragstart'.split('|');
for (var i = 0, len = list.length; i < len; i++) {
try {
main[list[i]] = Function('');
}
catch (e) {}
}
// 清空HTML内容
if (main.setInnerHTML) {
main.setInnerHTML(main, '');
}
else if (main.innerHTML) {
main.innerHTML = '';
}
main.parentNode.removeChild(main);
}
// 因为使用的属性而非闭包实现的EventDispatcher,因此无需担心内存回收的问题。
},
disposeChild: function () {
var me = this;
// dispose子控件
if (me.cc) {
for (var i = me.cc.length - 1; i > -1; i--) {
me.cc[i].dispose();
me.cc[i] = null;
}
me.cc = [];
}
},
//
// * @method getView
// * @description 获取视图模板名
// * @memerberof hui.Control.prototype
// * @protected
// * @return {String} target名字
// * @default 默认为action的id
// */
// getView: function () {
// var view = (this.view === null ? '' : this.view);
// // 获取view
// if (typeof view === 'function') {
// view = view();
// }
// view = hui.Control.getExtClass('hui.Template').getTarget(String(view));
// return view;
// },
/**
* @method enterControl
* @description Control的主要处理流程
* @memerberof hui.Control.prototype
* @protected
* @param {Object} argMap arg表.
*/
enterControl: function (callback) {
var uiObj = this,
parentControl = uiObj.parentControl;
// 注:默认增加一个空元素作为控件主元素!
if (typeof uiObj.getMain !== 'function') {
uiObj.getMain = hui.Control.prototype.getMain;
}
var elem = uiObj.getMain() || (uiObj.createMain ? uiObj.createMain() : hui.Control.prototype.createMain.call(uiObj));
if (!elem) {
return hui.Control.error('Control\'s main element is invalid');
}
else {
elem.setAttribute('_rendered', '');
elem.setAttribute('_initbehavior', '');
}
var que = new hui.Flow(); // 注:可以参照hui_flow.js文件。非常简单,不到30行代码
if (elem.getAttribute && !elem.getAttribute('ctrid')) {
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
// 默认设置value
if (uiObj.value !== undefined) {
main.value = uiObj.value;
}
// 便于通过main.getAttribute('ctrid')找到control
main.setAttribute('ctrid', uiObj.getId ? uiObj.getId() : uiObj.id);
me.getClass && hui.Control.addClass(main, me.getClass());
me.setSize && me.setSize();
next && next();
});
}
// 初始化Model
if (elem.getAttribute && elem.getAttribute('_initModel') != 'true') {
if (uiObj.initModel && uiObj.initModelMethod !== 'async' && uiObj.initModelMethod !== 'skip') {
que.push(function (next) {
var me = uiObj;
me.initModel();
next && next();
});
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
main.getAttribute('_initModel', 'true');
next && next();
});
}
else if (uiObj.initModelAsync && uiObj.initModelMethod !== 'sync' && uiObj.initModelMethod !== 'skip') {
que.push(function (next) {
uiObj.initModelAsync(next);
});
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
main.getAttribute('_initModel', 'true');
next && next();
});
}
}
// 渲染视图
if (elem.getAttribute && elem.getAttribute('_initView') != 'true') {
if (uiObj.getView && uiObj.getViewMethod !== 'async' && uiObj.getViewMethod !== 'skip') {
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
var tpl = me.getView();
var mainHTML = me.model && me.model.getData ? hui.Control.getExtClass('hui.Template').merge(tpl, me.model.getData()) : tpl;
hui.Control.prototype.setInnerHTML(main, mainHTML);
next && next();
});
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
main.getAttribute('_initView', 'true');
next && next();
});
}
else if (uiObj.getViewAsync && uiObj.getViewMethod !== 'sync' && uiObj.getViewMethod !== 'skip') {
que.push(function (next) {
var me = uiObj;
me.getViewAsync(function (tpl) {
var main = me.getMain();
var mainHTML = me.model && me.model.getData ? hui.Control.getExtClass('hui.Template').merge(tpl, me.model.getData()) : tpl;
hui.Control.prototype.setInnerHTML(main, mainHTML);
next && next();
});
});
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
main.getAttribute('_initView', 'true');
next && next();
});
}
else if (!uiObj.getView && !uiObj.getViewAsync && uiObj.view) {
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
var tpl = hui.Control.getExtClass('hui.Template').getTarget(String(uiObj.view));
var mainHTML = me.model && me.model.getData ? hui.Control.getExtClass('hui.Template').merge(tpl, me.model.getData()) : tpl;
hui.Control.prototype.setInnerHTML(main, mainHTML);
next && next();
});
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
main.getAttribute('_initView', 'true');
next && next();
});
}
}
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
// 动态生成control需手动维护me.parentControl
// 回溯找到父控件,若要移动控件,则需手动维护parentControl属性!!
var parentElement = main;
while (parentElement && parentElement.tagName && parentElement.parentNode) {
parentElement = parentElement.parentNode;
//label标签自带control属性!!
if (parentElement && hui.Control.isControlMain(parentElement)) {
var control = hui.Control.getById(parentElement.getAttribute('ctrid'), parentControl);
hui.Control.appendControl(control, me);
break;
}
// 未找到直接父控件则将control从hui.window.childControl移动到action.childControl中
else if (~',html,body,'.indexOf(',' + String(parentElement.tagName).toLowerCase() + ',')) {
hui.Control.appendControl(null, me);
break;
}
}
next && next();
});
// 1. initView()会在render调用父类的render时自动调用,
// 2. 不管是批量hui.Control.init()还是hui.Control.create(), 都会通过enterControl来执行render
// 3. initBehavior()会在后面执行
if (elem.getAttribute && elem.getAttribute('_rendered') != 'true') {
que.push(function (next) {
var me = uiObj;
var main = me.getMain();
me.render && me.render();
if (!me.render || main.getAttribute('_rendered') === 'false') {
var data = me.model && me.model.getData && typeof me.model.getData === 'function' ? me.model.getData() : {};
hui.Control.init(main, data, me);
main.setAttribute('_rendered', 'true');
}
next && next();
});
}
if (elem.getAttribute && elem.getAttribute('_initbehavior') != 'true') {
que.push(function (next) {
var me = uiObj;
if (me.initBehaviorByTree) {
me.initBehaviorByTree();
}
else if (me.initBehavior) {
me.initBehavior();
}
next && next();
});
}
que.push(function (next) {
var me = uiObj;
me.finish && me.finish();
callback && callback();
});
que.next();
},
/**
* @method createMain
* @description 生成主DOM
* @memerberof hui.Control.prototype
* @protected
*/
createMain: function () {
var me = this,
tagName = this.tagName || 'DIV',
main = document.createElement(String(tagName).toUpperCase()),
control = me.parentControl,
wrap = null;
if (!wrap && control && control.getMain) {
wrap = control.getMain();
}
if (!wrap && control && control.main) {
wrap = document.getElementById(control.main);
}
if (!wrap) {
wrap = document.body || document.documentElement;
}
if (me.parentElement) {
wrap = typeof me.parentElement === 'string' ? (document.getElementById(me.parentElement) || document.documentElement) : me.parentElement;
}
wrap.appendChild(main);
main.id = hui.Control.makeElemGUID(me.id);
me.main = main.id;
return main;
},
/**
* @method appendControl
* @description 父控件添加子控件. 注: 将子控件加到父控件下面的容器中也可以调用appendSelfTo
* @memerberof hui.Control.prototype
* @public
* @param {Control} uiObj 子控件.
*/
appendControl: function (uiObj) {
return hui.Control.appendControl(this, uiObj);
}
};
hui.inherits(hui.Control, hui.EventDispatcher);
/**
* @method hui.Control.makeGUID
* @description 获取唯一id
* @private
* @return {String}
*/
hui.Control.makeGUID = (function () {
var guid = 1;
return function (formname) {
return (formname ? formname : 'inner') + '_' + hui.Control.getHashCode('inner') + (guid++);
};
})();
hui.Control.getHashCode = function (str) {
var hash = 0;
if (str.length === 0) return hash;
for (var i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
hash = ((hash << 5) - hash) + c;
hash = hash & hash; // Convert to 32bit integer
}
return hash;
};
/**
* @method hui.Control.makeElemGUID
* @description 获取唯一id
* @private
* @return {String}
*/
hui.Control.makeElemGUID = (function () {
var guid = 1;
return function (id) {
return (id !== undefined ? id + hui.Control.getHashCode(id) : ('_' + hui.Control.formatDate(new Date(), 'yyyyMMddHHmm') + '_' + (guid++)));
};
})();
/**
* @method hui.Control.parseCustomAttribute
* @description 解析自定义ui属性
* @private
* @param {String} attrStr ui属性
* @param {Hashmap} opt_propMap 数据model
* @return {Hashmap}
*/
hui.Control.parseCustomAttribute = function (attrStr, opt_propMap) {
var attrStr = '{' + (attrStr || '') + '}',
attrs,
attrValue,
attrName;
// 解析ui属性
attrs = (new Function('return ' + attrStr))();
for (var j in attrs) {
if (attrs.hasOwnProperty(j)) {
// 通过@定义的需要到传入的model中找
attrValue = attrs[j];
if (attrValue && typeof attrValue == 'string' && attrValue.indexOf('@') === 0) {
attrName = attrValue.substr(1);
attrValue = opt_propMap && opt_propMap.get ? opt_propMap.get(attrName) : opt_propMap[attrName];
// 默认读取opt_propMap中的,没有再到全局context中取,防止强耦合.
if (attrValue === undefined) {
attrValue = hui.Control.getExtClass('hui.context').get(attrName);
}
attrs[j] = attrValue;
}
}
}
return attrs;
};
/**
* @method hui.Control.isChildControl
* @description 判断一个解析前DOM元素是否是子控件,是则跳过非父控件的hui.Control.init()
* @public
* @param {String} elem DOM元素
*/
hui.Control.isChildControl = function (elem, list) {
var result = false;
// 回溯找到父控件,若要移动控件,则需手动维护parentControl属性!!
while (elem && elem.tagName && elem.parentNode) {
elem = elem.parentNode;
if (~',html,body,'.indexOf(',' + String(elem.tagName).toLowerCase() + ',') == -1) break;
for (var i = 0, len = list.length; i < len; i++) {
if (list[i] == elem) {
result = true;
break;
}
}
}
return result;
};
/**
* @method hui.Control.isControlMain
* @description 判断一个解析前DOM元素是否已解析控件
* @public
* @param {String} elem DOM元素
*/
hui.Control.isControlMain = function (elem) {
var result = false;
// label的control是DOM
if (elem && elem.getAttribute && elem.getAttribute('ctrid')) {
result = true;
}
return result;
};
/**
* @method hui.Control.init
* @description 批量生成控件
* @public
* @param {HTMLElement} opt_wrap 渲染的区域容器元素
* @param {Object} opt_propMap 控件需要用到的数据Model{@key}
* @param {Object} parentControl 渲染的action,不传则默认为window对象
* @return {Object} 控件集合
* @example
* hui.Control.init(hui.bocument.getElementById('content'));
*/
//hui.Control.init('<div ui="type:"></div>');//暂时禁止此方法生成控件树
hui.Control.init = function (opt_wrap, opt_propMap, parentControl) {
if (!opt_wrap || opt_wrap.getAttribute('_rendered') === 'true') {
return false;
}
/*Step 1: 转换string到DOM
// 容器为空的判断
if (typeof (opt_wrap) == 'string') {
hui.bocument.documentElement.setInnerHTML(elem, opt_wrap);
opt_wrap = hui.bocument.documentElement;
}*/
/*Step 2: 转换DOM到control*/
opt_propMap = opt_propMap || {}; // 这里并不会缓存BaseModel,因此销毁空间时无须担心BaseModel
// parentControl不传默认为window对象
parentControl = parentControl || hui.window;
parentControl.cc = parentControl.cc || [];
var uiAttr = hui.Control.UI_ATTRIBUTE || 'ui';
var realEls = [],
uiEls = [];
var elem, control;
// 把dom元素存储到临时数组中
// 控件渲染的过程会导致elements的改变
realEls = hui.Control.findAllNodes(opt_wrap);
// 循环解析自定义的ui属性并渲染控件
// <div ui="type:'UIType',id:'uiId',..."></div>
for (var i = 0, len = realEls.length; i < len; i++) {
elem = realEls[i];
if (elem && elem.getAttribute && (elem.getAttribute(uiAttr) || elem.getAttribute('hui-type')) && (elem.getAttribute('_initview') !== 'true' || elem.getAttribute('_initbehavior') !== 'true')) {
uiEls.push(elem);
}
}
for (var i = 0, len = uiEls.length; i < len; i++) {
elem = uiEls[i];
if (!hui.Control.isChildControl(elem, uiEls) && elem.getAttribute('_rendered') !== 'true') {
control = hui.Control.create(elem, {
parentControl: parentControl
});
/*var attrStr = elem.getAttribute(uiAttr);
var attrs = hui.Control.parseCustomAttribute(attrStr, opt_propMap);
// 主元素参数初始化
if(attrs.main == undefined && elem) {attrs.main = elem.id ? elem.id : hui.Control.makeElemGUID(); elem.id = attrs.main;}
if(attrs.parentControl == undefined && parentControl) {attrs.parentControl = parentControl;}
// 生成控件 //这里的parentControl, elem不能去掉!!否则在后面的enterControl理会重复生成elem!!!
//control = hui.Control.create( options[ 'type' ], options, parentControl, elem);
//放在了上上一行,故去掉了parentControl, elem
control = hui.Control.create( attrs[ 'type' ], attrs);
/**
* 保留ui属性便于调试与学习
*/
// elem.setAttribute( uiAttr, '' );
}
}
return parentControl.cc;
};
/**
* @method hui.Control.create
* @description 创建一个控件对象
* @public
* @param {String} type 控件类型
* @param {Object} options 控件初始化参数
* @return {hui.Control} 创建的控件对象
* @example
* <button hui-type="Button" id="submit">submit</button>
* hui.Control.init(hui.bocument.getElementById('submit'));
*/
hui.Control.create = function (type, options) {
// 注:扩展了一下,直接支持hui.Control.create(Element);
if (type && Object.prototype.toString.call(type) != '[object String]' && type.getAttribute) {
options = options || {};
if (hui.Control.isControlMain(type)) {
var control = hui.Control.getById(type.getAttribute('ctrid'));
if (control) {
hui.Control.appendControl(options.parentControl, control);
}
}
var str, attrs;
try {
str = type.getAttribute(hui.Control.UI_ATTRIBUTE || 'ui');
try {
attrs = hui.Control.parseCustomAttribute(str);
}
catch (e) {
attrs = hui.Control.parseCustomAttribute(str.replace(/\\\'/g, '\'').replace(/\\\"/g, '\"')); //"
}
// hui-type="TextInput"
var list = type.attributes;
for (var i = 0, len = list.length; i < len; i++) {
var item = list[i];
if (item.nodeName.indexOf('hui-') === 0) {
attrs[item.nodeName.replace('hui-', '')] = item.nodeValue;
}
}
}
catch (e) {
hui.window.JSON && hui.window.JSON.stringify && hui.window.console && hui.window.console.error && hui.window.console.error('JSON Error: ', str);
return;
}
var text, action, key;
for (var i in attrs) {
text = attrs[i];
if (text && Object.prototype.toString.call(text) === '[object String]') {
if (text.indexOf('&') === 0) {
key = text.replace('&', '');
attrs[i] = hui.window[key];
}
else if (text.indexOf('@') === 0 && hui.Action && (typeof hui.Master.get) === 'function') {
key = text.replace('&', '');
action = hui.Master.get();
if (action && action.model && (typeof action.model.get) === 'function') {
attrs[i] = action.model.get(key);
}
else if (action && action.model) {
attrs[i] = action.model[key];
}
else if (action) {
attrs[i] = action[key];
}
}
}
}
for (var i in options) {
if (i && options.hasOwnProperty(i)) {
attrs[i] = attrs[i] !== undefined ? attrs[i] : options[i];
}
}
// 注:每个控件必须有id
attrs.id = attrs.id ? attrs.id : hui.Control.makeGUID(attrs['formname']);
// 注:type即elem
type.id = type.id || hui.Control.makeElemGUID(attrs.id);
attrs.main = type.id;
attrs.bocument = type.bocument;
return hui.Control.create(attrs['type'], attrs);
}
options = options || {};
// 注:创建并渲染控件,每个控件必须有id
var objId = options.id;
if (!objId) {
objId = hui.Control.makeGUID(options['formname']);
options.id = objId;
}
var existControl = hui.Control.getById(objId);
if (existControl) {
existControl.dispose();
}
var uiClazz = hui[type];
if (!uiClazz) {
hui.Control.error('Not use require(\'' + String(type).toLowerCase() + '\') or "' + String(type).toLowerCase() + '.js" is not loaded successfully.');
}
// 1. 模版批量生成控件时,options里一般没有m ain,m ain指向元素自身! //注:已改成默认有m ain
// 2. new的方式创建控件时,options里一般有m ain!
// 在这里设置m ain属性注意不能覆盖new uiClazz(options)的设置,也便于后面render时重新设置
//if(options.m ain == undefined && m ain) {options.m ain = m ain;}//注:已移动到hui.Control.init中了
// 设置临时parentControl放置子控件//注释掉原因:创建控件默认放在hui.window下//放到hui.Control.init中了
//if(options.parentControl == undefined && parentControl) {options.parentControl = parentControl;}
// 创建控件对象
var uiObj = new uiClazz(options);
uiObj.id = uiObj.id || objId;
/*Hack方式不利于理解程序,所以去掉!!*/
// 调用父类的构造函数
//hui.Control.call( uiObj, options );
/**
* @description 再次调用子类的构造函数
* @comment 这里为什么不直接放到new uiClazz(options)里呢? 因为调用父类的构造函数会被覆盖掉.
uiClazz.call( uiObj, options );/*已废弃*
/**/
/*uiObj.clazz = uiClazz;// 已经使用this.constructor代替*/
/*
// 加到父控件的childControl中
if (!((uiObj.parentControl && uiObj.parentControl.cc && uiObj.parentControl.cc[objId] == uiObj) &&
(uiObj.getId && uiObj.getId() !== objId) || (uiObj.id !== objId))) {
if (uiObj.parentControl && uiObj.parentControl.cc && uiObj.parentControl.cc[objId] !== uiObj) {
hui.Control.appendControl(uiObj.parentControl, uiObj);
//uiObj.parentControl.cc[objId] = uiObj;
}
else if (options.parentControl && options.parentControl.cc && options.parentControl.cc[objId] !== uiObj) {
hui.Control.appendControl(options.parentControl, uiObj);
//options.parentControl.cc[objId] = uiObj;
}
}
*/
// 检查是否有 enterControl 方法
if (!uiObj.enterControl) {
var child = uiObj,
parent = hui.Control.prototype;
for (var key in parent) {
if (parent.hasOwnProperty(key)) {
child[key] = parent[key];
}
}
uiObj.enterControl();
}
return uiObj;
};
/**
* @method hui.Control.appendControl
* @description 父控件添加子控件. 注: 将子控件加到父控件下面的容器中也可以调用appendSelfTo
* @public
* @param {Control} uiObj 子控件.
*/
hui.Control.appendControl = function (parent, uiObj) {
// parentControl父控件不传则默认为window对象
// parentControl父控件默认为window对象, 不是的话后面会再改回来.
// var parentControl = hui.window;
// Add: 上面这样做静态没问题,动态生成appendSelfTo就会出问题,因此需要加上options.parentControl
// Fixme: 第二次执行到这里hui.Master.get()居然是前一个action?
parent = parent || hui.window;
parent.cc = parent.cc || [];
// var ctrId = uiObj.getId ? uiObj.getId() : uiObj.id;
// 注:从原来的父控件childControl中移除
if (uiObj.parentControl && uiObj.parentControl.cc && uiObj.parentControl.cc != parent.cc) {
var list = uiObj.parentControl.cc;
for (var i = list.length - 1; i > -1; i--) {
if (list[i] === uiObj) {
list.splice(i, 1);
}
}
}
// !!!悲催的案例,如果将childControl放在prototype里, 这里parent.cc===uiObj.cc!!!
var exist = false;
for (var i = 0, len = parent.cc.length; i < len; i++) {
if (parent.cc[i] === uiObj) {
exist = true;
break;
}
}
if (!exist) {
parent.cc.push(uiObj);
}
// 重置parentControl标识
uiObj.parentControl = parent;
// !!!不能移动DOM,需自行解决,因为会打乱html布局
/*var parentNode = parent.getMain ? parent.getMain() : null,
main = uiObj.getMain();
if (parentNode && main) {
parentNode.appendChild(main);
};*/
};
/**
* @method hui.Control.findAllNodes
* @description 获取所有子节点element
* @private
* @param {HTMLElement} main
* @param {String} stopAttr 如果元素存在该属性,如'ui',则不遍历其下面的子元素
*/
hui.Control.findAllNodes = function (main, stopAttr) {
var childNode,
elements,
list,
childlist,
node;
elements = [];
list = [main];
while (list.length) {
childNode = list.pop();
if (!childNode) continue;
// Not set 'stopAttr', get all nodeds.
if (stopAttr === undefined || (childNode.getAttribute && childNode.getAttribute(stopAttr))) {
elements.push(childNode);
}
childlist = childNode.childNodes;
if (!childlist || childlist.length < 1) continue;
if (childNode != main && stopAttr !== undefined && childNode.getAttribute(stopAttr)) {
continue;
}
// 注:Nodelist是伪数组且IE不支持Array.prototype.slice.call(Nodelist)转化数组
for (var i = 0, len = childlist.length; i < len; i++) {
node = childlist[i];
list.push(node);
}
}
// 去掉顶层main,如不去掉处理复合控件时会导致死循环!!
if (elements[0] === main) elements.shift();
return elements.reverse();
};
/**
* @method hui.Control.findAllControl
* @description 获取父控件或Action下所有控件
* @private
* @param {Object} control
*/
hui.Control.findAllControl = function (parentControl) {
var childNode,
results,
list,
control;
results = [];
if (Object.prototype.toString.call(parentControl).indexOf('Element') > -1) {
list = hui.Control.findAllNodes(parentControl);
for (var i = 0, len = list.length; i < len; i++) {
if (hui.Control.isControlMain(list[i])) {
control = hui.Control.getById(list[i].getAttribute('ctrid'));
if (control) {
results.push(control);
}
}
}
}
else {
list = [parentControl];
while (list.length) {
childNode = list.pop();
if (!childNode) continue;
results.push(childNode);
if (!childNode.cc) continue;
list = list.concat(childNode.cc);
}
// 去掉顶层父控件或Action,如不去掉处理复合控件时会导致死循环!!
if (results.length > 0) results.shift();
// 后序遍历出来的结果,因此需要反转数组
results.reverse();
}
return results;
};
// 所有控件实例的索引. 注释掉原因: 建了索引会造成无法GC内存暴涨!
// hui.Control.elemList = [];
/**
* @method hui.Control.findByElem
* @description 回溯找到当前元素所在的控件
* @public
* @param {Element} parentElement DOM元素
*/
hui.Control.findByElem = function (parentElement) {
var control = null;
while (parentElement && parentElement.tagName) {
//label标签自带control属性!!
if (parentElement && hui.Control.isControlMain(parentElement)) {
control = hui.Control.getById(parentElement.getAttribute('ctrid'));
break;
}
else if (~',html,body,'.indexOf(',' + String(parentElement.tagName).toLowerCase() + ',')) {
break;
}
parentElement = parentElement.parentNode;
}
return control;
};
/**
* @method hui.Control.getById
* @description 根据控件id找到对应控件
* @public
* @param {Control} [parentControl] 可不传, 默认从当前Action开始找, 如果未使用action则直接从window.cc开始找
* @param {String} id 控件id
*/
hui.Control.getById = function (id, parentControl) {
var list,
result = null;
// parentControl || hui.Control.getById(parentControl) || hui.Master.get(parentControl) || hui.Master.get() || window
if (typeof parentControl == 'string') {
parentControl = hui.Control.getById(parentControl);
}
// 如果传入的parentControl是DOM元素,视为未传入值处理
parentControl = parentControl && parentControl.getId ? parentControl :
(hui.Action && hui.Action.ready && hui.Master.get ? (hui.Master.get(parentControl) || hui.Master.get()) : hui.window);
if (id === undefined || (parentControl && parentControl.getId && id === parentControl.getId())) {
result = parentControl;
}
else if (parentControl) {
list = hui.Control.findAllControl(parentControl);
for (var i = 0, len = list.length; i < len; i++) {
if (list[i].id == id) {
result = list[i];
}
}
}
// If not found then find in 'window.cc'
if (!result) {
list = hui.Control.findAllControl(hui.window);
for (var i = 0, len = list.length; i < len; i++) {
if (list[i].id == id) {
result = list[i];
}
}
}
return result;
};
/**
* @method hui.Control.getByFormnameAll
* @description 根据控件formname找到对应控件
* @static
* @param {String} formname 控件formname
* @param {Control} parentNode 父控件
* @param {Boolean} all 仅查找直接子级,默认所有子级
*/
hui.Control.getByFormnameAll = function (formname, parentNode, all) {
var list = [],
childNodes,
item,
/* 强制确认parentControl */
parentControl = parentNode && typeof parentNode == 'object' ? parentNode : hui.window;
if (formname) {
formname = String(formname);
// 注掉原因:不应该找自身!!
// // 先查找自身
// childNodes = parentControl && parentControl.cc ? parentControl.cc : [];
// //childNodes.unshift(parentControl);
// if (parentControl.getFormname && parentControl.getFormname() === formname) {
// list.push(parentControl);
// }
// 再遍历控件树
childNodes = parentControl && parentControl.cc ?
(all === false ? parentControl.cc : hui.Control.findAllControl(parentControl)) : [];
for (var i = 0, len = childNodes.length; i < len; i++) {
item = childNodes[i];
if ((item.getFormname && item.getFormname() === formname) || item['formname'] === formname) {
list.push(childNodes[i]);
}
}
}
return list;
};
/**
* @method hui.Control.getByFormname
* @description 根据控件formname找到对应控件,只返回一个结果
* @static
* @param {String} formname 控件formname
* @param {Control} parentNode 父控件
* @example
* <button hui-type="Button" hui-formname="save">Save</button>
* var save = hui.Control.getByFormname('save');
*/
hui.Control.getByFormname = function (formname, parentNode) {
var result = null,
list,
min = Number.MAX_VALUE,
deep,
ctr;
parentNode = parentNode && typeof parentNode === 'object' ? parentNode : hui.window;
list = hui.Control.getByFormnameAll(formname, parentNode);
// 注:默认返回直接子级第一个,直接子级没有才会返回最近子级的第一个
// 注:要找到所有直接子级等于formname的可以用getByFormnameAll(formname, parentNode, false)
for (var i = 0, len = list.length; i < len && min > 0; i++) {
deep = 0;
ctr = list[i];
while (ctr.parentControl && ctr.parentControl !== parentNode) {
deep++;
ctr = ctr.parentControl;
}
if (deep < min) {
min = deep;
result = list[i];
}
}
return result;
};
/**
* @method hui.Control.disposeList
* @description 销毁一组控件
* @static
* @param {String} list 一组控件
*/
hui.Control.disposeList = function (list) {
if (Object.prototype.toString.call(list) === '[object Array]') {
for (var i = 0, len = list.length; i < len; i++) {
if (list[i] && list[i].dispose) {
list[i].dispose();
}
}
}
};
/**
* @method hasClass,addClass,removeClass
* @description 操作目标元素的className
* @public
* @param {HTMLElement|string} element 目标元素或目标元素的id
* @param {String} className 要添加的className,允许同时添加多个class,中间使用空白符分隔
* @remark
* 使用者应保证提供的className合法性,不应包含不合法字符,className合法字符参考:http://www.w3.org/TR/CSS2/syndata.html。
* @returns {HTMLElement} 目标元素
*/
hui.Control.hasClass = function (element, className) {
return ~(' ' + element.className + ' ').indexOf(' ' + className + ' ');
};
hui.Control.addClass = function (element, className) {
if (~'[object Array][object NodeList]'.indexOf(Object.prototype.toString.call(element))) {
for (var i = 0, len = element.length; i < len; i++) {
hui.Control.addClass(element[i], className);
}
}
else if (element) {
hui.Control.removeClass(element, className);
element.className = (element.className + ' ' + className).replace(/(\s)+/ig, ' ');
}
return element;
};
// Support * and ?, like hui.Control.removeClass(elem, 'daneden-*');
hui.Control.removeClass = function (element, className) {
if (~'[object Array][object NodeList]'.indexOf(Object.prototype.toString.call(element))) {
for (var i = 0, len = element.length; i < len; i++) {
hui.Control.removeClass(element[i], className);
}
}
else if (element) {
var list = className.replace(/\s+/ig, ' ').split(' '),
/* Attention: str need two spaces!! */
str = (' ' + (element.className || '').replace(/(\s)/ig, ' ') + ' '),
name,
rex;
// 用list[i]移除str
for (var i = 0, len = list.length; i < len; i++) {
name = list[i];
name = name.replace(/(\*)/g, '\\S*').replace(/(\?)/g, '\\S?');
rex = new RegExp(' ' + name + ' ', 'ig');
str = str.replace(rex, ' ');
}
str = str.replace(/(\s)+/ig, ' ');
str = str.replace(/^(\s)+/ig, '').replace(/(\s)+$/ig, '');
element.className = str;
}
return element;
};
/**
* @method hasCssString, removeCssString, importCssString
* @description JS操作CSS
* @public
* @param {String} <style>的id
*/
hui.Control.hasCssString = function hasCssString(id) {
var sheets,
c,
result = false;
if (document.createStyleSheet && (sheets = document.styleSheets)) {
for (var i = 0, len = sheets.length; i < len; i++) {
c = sheets[i];
if (c && c.owningElement && c.owningElement.id === id) {
result = c.owningElement;
break;
}
else if (c && c.ownerNode && c.ownerNode.id === id) {
result = c.ownerNode;
break;
}
}
}
else if ((sheets = document.getElementsByTagName('style'))) {
for (var i = 0, len = sheets.length; i < len; i++) {
c = sheets[i];
if (c.id === id) {
result = c;
break;
}
}
}
return result;
};
hui.Control.removeCssString = function removeCssString(id) {
var parent,
result = hui.Control.hasCssString(id);
if (result) {
parent = result.parentNode;
parent.removeChild(result);
}
};
hui.Control.importCssString = function importCssString(cssText, id) {
hui.Control.removeCssString(id);
var style = document.createElement('style');
if (id) {
style.id = id;
}
var head = document.head || document.body || document.documentElement;
head.insertBefore(style, head.lastChild);
if (head !== document.documentElement && style.nextSibling) {
head.insertBefore(style.nextSibling, style);
}
style.setAttribute('type', 'text/css');
// all browsers, except IE before version 9
if (style.styleSheet) {
style.styleSheet.cssText = cssText;
}
// Internet Explorer before version 9
else {
style.appendChild(document.createTextNode(cssText));
}
return style;
};
/**
* @method hui.Control.format
* @description 合并模板和数据
* @public
* @param {String} source 待格式化的字符串
* @param {Object|Array} opts 要合并到字符串中的数据
* @returns {String} 格式化之后的字符串
* @example
* hui.Control.format('Hello {{user}}', {user: 'Tom'});
* >> Hello Tom
*/
hui.Control.format = function (source, opts) {
function handler(match, key) {
var type = String(key).indexOf('!!') === 0 ? 'decode' : String(key).indexOf('!') === 0 ? '' : 'encode',
parts = key.replace(/^!!?/, '').split('.'),
part = parts.shift(),
cur = data,
variable;
while (part) {
if (cur[part] !== undefined) {
cur = cur[part];
}
else {
cur = undefined;
break;
}
part = parts.shift();
}
variable = cur;
if ('[object Function]' === toString.call(variable)) {
variable = variable(key);
}
if (undefined !== variable) {
variable = String(variable);
// encodeURIComponent not encode '
var fr = '&|<|>| |\'|"|\\'.split('|'),
to = '&|<|>| |'|"|\'.split('|');
if (type === 'decode') {
for (var i = fr.length - 1; i > -1; i--) {
variable = variable.replace(new RegExp('\\' + to[i], 'ig'), fr[i]);
}
}
else if (type === 'encode') {
for (var i = 0, l = fr.length; i < l; i++) {
variable = variable.replace(new RegExp('\\' + fr[i], 'ig'), to[i]);
}
}
}
return (undefined === variable ? '' : variable);
}
source = String(source);
var data = Array.prototype.slice.call(arguments, 1),
toString = Object.prototype.toString;
if (data.length) {
data = (data.length == 1 ?
/* ie 下 Object.prototype.toString.call(null) == '[object Object]' */
(opts !== null && (/\[object (Array|Object)\]/.test(toString.call(opts))) ? opts : data) : data);
return source.replace(/#\{(.+?)\}/g, handler).replace(/\{\{([^\{]+?)\}\}/g, handler);
}
return source;
};
/**
* @method hui.Control.formatDate
* @description 将Date类型解析为String类型.
* @param {Date} date 输入的日期
* @param {String} fmt 输出日期格式
* @example
* hui.Control.formatDate(new Date(2006,0,1), 'yyyy-MM-dd HH:mm');
*/
hui.Control.formatDate = function (date, fmt) {
if (!date) date = new Date();
fmt = fmt || 'yyyy-MM-dd HH:mm';
var o = {
'M+': date.getMonth() + 1, //月份
'd+': date.getDate(), //日
'h+': date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, //小时
'H+': date.getHours(), //小时
'm+': date.getMinutes(), //分
's+': date.getSeconds(), //秒
'q+': Math.floor((date.getMonth() + 3) / 3), //季度
'S': date.getMilliseconds() //毫秒
};
var week = {
'0': '/u65e5',
'1': '/u4e00',
'2': '/u4e8c',
'3': '/u4e09',
'4': '/u56db',
'5': '/u4e94',
'6': '/u516d'
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length));
}
if (/(E+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? '/u661f/u671f' : '/u5468') : '') + week[date.getDay() + '']);
}
for (var k in o) {
if (o.hasOwnProperty(k) && new RegExp('(' + k + ')').test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)));
}
}
return fmt;
};
/**
* @method hui.Control.parseDate
* @description 将String类型解析为Date类型.
* @param {String} fmt 输入的字符串格式的日期
* @example
* parseDate('2006-1-1') return new Date(2006,0,1)
* parseDate(' 2006-1-1 ') return new Date(2006,0,1)
* parseDate('2006-1-1 15:14:16') return new Date(2006,0,1,15,14,16)
* parseDate(' 2006-1-1 15:14:16 ') return new Date(2006,0,1,15,14,16);
* parseDate('不正确的格式') retrun null
*/
hui.Control.parseDate = function (str) {
str = String(str).replace(/^[\s\xa0]+|[\s\xa0]+$/ig, '');
var results = null;
//秒数 #9744242680
results = str.match(/^ *(\d{10}) *$/);
if (results && results.length > 0)
return new Date(parseInt(str) * 1000);
//毫秒数 #9744242682765
results = str.match(/^ *(\d{13}) *$/);
if (results && results.length > 0)
return new Date(parseInt(str));
//20110608
results = str.match(/^ *(\d{4})(\d{2})(\d{2}) *$/);
if (results && results.length > 3)
return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]));
//20110608 1010
results = str.match(/^ *(\d{4})(\d{2})(\d{2}) +(\d{2})(\d{2}) *$/);
if (results && results.length > 5)
return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]), parseInt(results[4]), parseInt(results[5]));
//2011-06-08
results = str.match(/^ *(\d{4})[\._\-\/\\](\d{1,2})[\._\-\/\\](\d{1,2}) *$/);
if (results && results.length > 3)
return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]));
//2011-06-08 10:10
results = str.match(/^ *(\d{4})[\._\-\/\\](\d{1,2})[\._\-\/\\](\d{1,2}) +(\d{1,2}):(\d{1,2}) *$/);
if (results && results.length > 5)
return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]), parseInt(results[4]), parseInt(results[5]));
//2011/06\\08 10:10:10
results = str.match(/^ *(\d{4})[\._\-\/\\](\d{1,2})[\._\-\/\\](\d{1,2}) +(\d{1,2}):(\d{1,2}):(\d{1,2}) *$/);
if (results && results.length > 6)
return new Date(parseInt(results[1]), parseInt(results[2]) - 1, parseInt(results[3]), parseInt(results[4]), parseInt(results[5]), parseInt(results[6]));
return (new Date(str));
};
/**
* @method hui.Control.encode
* @description 对特殊字符和换行符编解码
* @param {String} str 待编解码的字符串
* @param {String} [decode] 是否是解码
* @example
* hui.Control.encode('%| |&|;|=|+|<|>|,');
*/
hui.Control.encode = function (str, decode) {
str = String(str);
// encodeURIComponent not encode '
var fr = '%| |&|;|=|+|<|>|,|"|\'|#|/|\\|\n|\r|\t'.split('|'),
to = '%25|%20|%26|%3B|%3D|%2B|%3C|%3E|%2C|%22|%27|%23|%2F|%5C|%0A|%0D|%09'.split('|');
if (decode == 'decode') {
for (var i = fr.length - 1; i > -1; i--) {
str = str.replace(new RegExp('\\' + to[i], 'ig'), fr[i]);
}
}
else {
for (var i = 0, l = fr.length; i < l; i++) {
str = str.replace(new RegExp('\\' + fr[i], 'ig'), to[i]);
}
}
return str;
};
hui.Control.decode = function (str) {
return this.encode(str, 'decode');
};
hui.Control.encodehtml = function (str, decode) {
str = String(str);
// encodeURIComponent not encode '
var fr = '&|<|>| |\'|"|\\'.split('|'),
to = '&|<|>| |'|"|\'.split('|');
if (decode == 'decode') {
for (var i = fr.length - 1; i > -1; i--) {
str = str.replace(new RegExp('\\' + to[i], 'ig'), fr[i]);
}
}
else {
for (var i = 0, l = fr.length; i < l; i++) {
str = str.replace(new RegExp('\\' + fr[i], 'ig'), to[i]);
}
}
return str;
};
hui.Control.decodehtml = function (str) {
return this.encodehtml(str, 'decode');
};
//setInnerHTML: function (elem, html){}
hui.Control.setInnerHTML = function (elem, html) {
elem = elem && elem.getMain ? elem.getMain() : elem;
if (elem && elem.innerHTML !== undefined) {
elem.innerHTML = html;
}
return elem;
};
hui.Control.setInnerText = function (elem, text) {
if (!elem) return;
if (elem.textContent !== undefined) {
elem.textContent = text;
}
else {
elem.innerText = text;
}
};
hui.Control.error = function (str) {
if (hui.window && hui.window.console && hui.window.console.error) {
hui.window.console.error(str);
}
};
hui.Control.log = function (str) {
if (hui.window && hui.window.console && hui.window.console.log) {
hui.window.console.log(str);
}
};
hui.Control.getExtClass = function (clazz) {
var result = function () {};
switch (clazz) {
case 'hui.BaseModel':
if (typeof hui !== 'undefined' && hui.BaseModel) {
result = hui.BaseModel;
}
else {
result.get = new Function();
result.set = new Function();
}
break;
case 'hui.Template':
if (typeof hui !== 'undefined' && hui && hui.Template) {
result = hui.Template;
}
else {
result.getTarget = new Function();
result.merge = new Function();
}
break;
case 'hui.Validator':
if (typeof hui !== 'undefined' && hui.Validator) {
result = hui.Validator;
}
else {
result.showWaiting = new Function();
result.showError = new Function();
result.showOK = new Function();
result.cancelNotice = new Function();
result.set = new Function();
}
break;
case 'hui.Action':
if (typeof hui !== 'undefined' && hui.Validator) {
result = hui.Validator;
}
else {
result.get = new Function();
}
break;
case 'hui.context':
if (typeof hui !== 'undefined' && hui.context) {
result = hui.context;
}
else {
result = {};
result.get = new Function();
}
break;
default:
}
return result;
};
});