UNPKG

nuijs

Version:

nui框架

575 lines (561 loc) 21.1 kB
/** * @author Aniu[2016-11-11 16:54] * @update Aniu[2016-11-11 16:54] * @version 1.0.1 * @description 组件基类 */ Nui.define(function(require){ var template = require('./template'); var events = require('./events'); var ext = require('./extends'); var slice = Array.prototype.slice; var callMethod = function(method, args, obj){ if(typeof method === 'function'){ //实参大于形参,最后一个实参表示id if(args.length > method.length){ var id = args[args.length-1]; if(id && Nui.type(id, ['String', 'Number']) && obj._options.id !== id && obj.__id !== id){ return } } method.apply(obj, args) } } var bindComponent = function(name, elem, mod, options){ //不能重复绑定 if(elem.nui && elem.nui[name]){ return } var $elem = jQuery(elem), _options; if(options === undefined){ options = $elem.data(name+'Options'); } if((options && typeof options === 'string') || typeof options === 'number'){ if(/^{[\s\S]*}$/.test(options)){ options = eval('('+ options +')'); } else if(_options = require(options)){ if(typeof _options === 'function'){ options = _options($elem) } else{ options = _options } } } if(Nui.type(options, 'Object')){ mod(Nui.extend({}, options, { target:elem })) } else{ mod({ target:elem }) } } /** * 单和双下划线开头表示私有方法或者属性,只能在内部使用, * 单下划线继承后可重写或修改,双下划线为系统预置无法修改 * 系统预置属性方法:__id, __instances, __eventList, __parent, __component_name, __setMethod */ var statics = { //实例对象唯一标记 __id:0, //实例对象容器 __instances:{}, /* * 将实例方法接口设置为静态方法,这样可以操作多个实例, * 默认有 init, option, reset, destroy * init表示初始化组件,会查询容器内包含属性为 data-组件名-options的dom元素,并调用组件 */ __setMethod:function(apis, components){ var self = this; Nui.each(apis, function(val, methodName){ if(self[methodName] === undefined){ self[methodName] = function(){ var self = this, name = self.__component_name, args = arguments, container = args[0], isContainer = container && container instanceof jQuery, mod = components[name], init = methodName === 'init'; if(name && name !== 'component' && mod){ if(isContainer){ if(init){ container.find('[data-'+name+'-options]').each(function(){ bindComponent(name, this, mod) }) } else{ container.find('[nui_component_'+ name +']').each(function(){ var obj, nui = this.nui; if(nui && (obj = nui[name])){ callMethod(obj[methodName], slice.call(args, 1), obj) } }) } } else{ Nui.each(self.__instances, function(obj){ callMethod(obj[methodName], args, obj) }) } } else if(name === 'component'){ var attributes = []; Nui.each(components, function(v, k){ if(k !== 'component' && typeof v[methodName] === 'function'){ if(isContainer){ if(init){ attributes.push('[data-'+ k +'-options]') } else{ attributes.push('[nui_component_'+ k +']') } } else{ Nui.each(v.constructor.__instances, function(obj){ callMethod(obj[methodName], args, obj) }) } } }) if(attributes.length){ var matchRegexp = init ? /^data-(\w+)-options/i : /^nui_component_(\w+)/i; container.find(attributes.join(',')).each(function(index, elem){ var attrs = elem.attributes, nui = elem.nui, obj, i = attrs.length, data = []; while(i--){ var attr = attrs[i]; if(attr && attr.name){ var match = attr.name.match(matchRegexp); if(match){ data.push({ name:match[1], value:attr.value }) } } } Nui.each(data, function(v){ if(init){ bindComponent(v.name, elem, components[v.name], v.value) } else if(nui && (obj = nui[v.name])){ callMethod(obj[methodName], slice.call(args, 1), obj) } }) }) } } } } }) return self }, _listeners:{}, //对所有实例设置默认选项 _options:{}, //创建组件模块时会调用一次,可用于在document上绑定事件操作实例 _init:jQuery.noop, _getSize:function(selector, dir, attr){ var size = 0; attr = attr || 'border'; dir = dir || 'tb'; if(attr === 'all'){ return (this._getSize(selector, dir) + this._getSize(selector, dir, 'padding') + this._getSize(selector, dir, 'margin')) } var group = { l:['Left'], r:['Right'], lr:['Left', 'Right'], t:['Top'], b:['Bottom'], tb:['Top', 'Bottom'] } var arr = [{ border:{ l:['LeftWidth'], r:['RightWidth'], lr:['LeftWidth', 'RightWidth'], t:['TopWidth'], b:['BottomWidth'], tb:['TopWidth', 'BottomWidth'] } }, { padding:group }, { margin:group }]; Nui.each(arr, function(val){ if(val[attr]){ Nui.each(val[attr][dir], function(v){ var value = parseFloat(selector.css(attr+v)); size += isNaN(value) ? 0 : value }); } }); return size }, _$fn:function(name, module){ jQuery.fn[name] = function(){ var args = arguments; return this.each(function(){ var dom = this, object, options = args[0]; var execMethod = function(){ if(typeof options === 'string'){ if(options === 'options'){ object.option(args[1], args[2]) } else if(options.indexOf('_') !== 0){ var attr = object[options]; if(typeof attr === 'function'){ attr.apply(object, slice.call(args, 1)) } } } } if(dom.nui && (object = dom.nui[name])){ execMethod() } else if(!object){ object = module((function(opts){ if(Nui.type(opts, 'Object')){ opts.target = dom return opts } else{ return {target:dom} } })(options)) execMethod() } }) } }, config:function(){ var args = arguments; var len = args.length; var attr = args[0]; if(Nui.type(attr, 'Object')){ return this._options = Nui.extend(true, this._options, attr) } else if(Nui.type(attr, 'String')){ if(args.length === 1){ return this._options[attr] } return this._options[attr] = args[1] } }, hasInstance:function(id){ var exist = false; var instances = this.__instances; if(id !== undefined){ Nui.each(instances, function(v){ if(v.__id === id || v._options.id === id){ exist = v; return false } }) } else{ for(i in instances){ return true } } return exist }, listener:function(type, callback){ var self = this; if(type && typeof callback === 'function'){ if(!this._listeners[type]){ this._listeners[type] = [] } this._listeners[type].push(callback) } return function() { self.removeListener(type, callback); } }, removeListener:function(type, callback){ if(type && typeof callback === 'function'){ var listeners = this._listeners[type]; if(listeners){ var index; Nui.each(listeners, function(cb, i){ if(callback === cb){ index = i return false; } }) if(index !== undefined){ this._listeners[type] = listeners.slice(0, index).concat(listeners.slice(index+1)); if(!this._listeners[type]){ delete this._listeners[type] } } } } } } return this.extend({ _static:statics, _options:{ target:null, //组件id,element会增加class 组件名-组件id id:'', //组件皮肤,element会增加class nui-组件名-皮肤名 skin:'', //element增加一个或多个类 className:'', onInit:null, onReset:null, onDestroy:null }, _template:{ style:'<%each style%><%$index%>:<%$value%>;<%/each%>' }, _init:function(){ this._exec() }, _exec:jQuery.noop, _emitListener:function(type){ var self = this; var _class = self.constructor; var listeners = _class._listeners[type]; if(listeners){ Nui.each(listeners, function(cb){ cb(self) }) } }, _jquery:function(elem){ if(typeof elem === 'function'){ elem = elem.call(this._options, this) } if(!elem){ return } if(elem instanceof jQuery){ return elem } return jQuery(elem) }, _getTarget:function(){ var self = this; if(!self.target){ var target = self._options.target; target = self._jquery(target); if(!target){ return } self.target = self._bindComponentName(target); } return self.target }, _bindComponentName:function(element){ var self = this, _class = self.constructor; var attr = 'nui_component_'+_class.__component_name; element.attr(attr, '').each(function(){ if(!this.nui){ this.nui = {}; } this.nui[_class.__component_name] = self }) return element }, _disabled:function(){ return this.target.prop('disabled') }, _getName:function(_class, array){ var skin = Nui.trim(this._options.skin); _class = _class || this.constructor; if(_class.__parent){ var _pclass = _class.__parent.constructor; var _name = _pclass.__component_name; if(_name !== 'component'){ if(skin){ array.unshift('nui-'+_name+'-'+skin); } array.unshift('nui-'+_name); return this._getName(_pclass, array) } } return array }, _tplData:function(data){ var opts = this._options, skin = Nui.trim(opts.skin), _class = this.constructor, name = 'nui-' + _class.__component_name, className = this._getName(_class, []); className.push(name); if(skin){ className.push(name+'-'+skin) } if(opts.id){ className.push(_class.__component_name + '-' + opts.id) } if(!data){ data = {} } if(opts.className){ className.push(opts.className) } data.className = className.join(' '); return data }, _event:function(){ var self = this, opts = self._options; if(self.element && opts.events){ opts.element = self.element; events.call(self, opts) } return events.call(self) }, _on:function(type, dalegate, selector, callback, trigger){ var self = this; if(typeof selector === 'function'){ trigger = callback; callback = selector; selector = dalegate; dalegate = null; selector = self._jquery(selector) } var _callback = function(e){ return callback.call(this, e, jQuery(this)) } if(dalegate){ if(typeof selector !== 'string'){ selector = selector.selector; if(!selector){ selector = self._options.target } } dalegate.on(type, selector, _callback); if(trigger){ dalegate.find(selector).trigger(type) } } else{ selector.on(type, _callback); if(trigger){ selector.trigger(type) } } self.__eventList.push({ dalegate:dalegate, selector:selector, type:type, callback:_callback }); return self }, _off:function(){ var self = this, _eventList = self.__eventList; Nui.each(_eventList, function(val, key){ if(val.dalegate){ val.dalegate.off(val.type, val.selector, val.callback) } else{ val.selector.off(val.type, val.callback) } _eventList[key] = null; delete _eventList[key] }); self.__eventList = []; return self }, _delete:function(){ var self = this, _class = self.constructor; if(self.target){ var attr = 'nui_component_'+_class.__component_name; self.target.removeAttr(attr).each(function(){ if(this.nui){ this.nui[_class.__component_name] = null; delete this.nui[_class.__component_name]; } }) } _class.__instances[self.__id] = null; delete _class.__instances[self.__id] }, _reset:function(){ this._off(); if(this.element){ this.element.remove(); this.element = null; } return this }, _tpl2html:function(id, data){ var opts = { openTag:'<%', closeTag:'%>' } if(arguments.length === 1){ return template.render(this._template, id, opts) } return template.render.call(this._template, this._template[id], data, opts) }, _callback:function(method, args){ var self = this, opts = self._options; var callback = opts['on'+method]; if(typeof callback === 'function'){ if(args){ Array.prototype.unshift.call(args, self); return callback.apply(opts, args); } return callback.call(opts, self) } }, option:function(opts, isOriginal){ var args = arguments; var isdef = false; var options; if(args[0] === true){ isdef = true } else if(jQuery.isPlainObject(args[0])){ options = args[0] isdef = args[1] } else if(args.length > 1 && typeof args[0] === 'string'){ options = {}; options[args[0]] = args[1] isdef = args[2] } if(options||isdef){ this._options = Nui.extend(true, {}, this[isdef === true ? '_defaultOptions' : '_options'], options) this._reset(); this._exec(); } return this }, on:function(name, callback){ var self = this, callbacks = {}; if( typeof name === 'string' && typeof callback === 'function' ){ callbacks[name] = callback } else if(typeof name === 'object'){ callbacks = name } Nui.each(callbacks, function(v, k){ self._options['on' + k.substr(0, 1).toUpperCase() + k.substr(1)] = v }) return this }, reset:function(){ this.option(true); this._callback('Reset'); return this; }, destroy:function(){ this._delete(); this._reset(); this._callback('Destroy'); } }) })