/*! * UC JS Library 1.0.0 */ // 兼容旧浏览器,早期的浏览器实现中,undefined并不是全局变量。就是说,你要判断一个变量是否是没定义, // 你需要这样写if (typeof a == 'undefined'),不可以写成if (a == undefined)。所以,上面的代码就可以理解了。 // 右面的window["undefined"],因为window对象没有undefined属性,所以其值为undefined, // 把undefined赋值给window的undefined属性上,就相当于把undefined设置成了全局变量, // 这样以后你再判断一个变量是否是未定义的时候,就不需要使用typeof,直接判断就可以了。 //window.undefined = window.undefined; /** * @class webuc * UC core utilities and functions. * @singleton */ UC = { /** * The version of the framework * @type String */ version : '1.0' }; /** * 把对象c中的属性复制到对象o中,支持默认属性defaults设置。 * 这个方法属于对象属性的一个浅拷贝函数。 * * @param {Object} obj The receiver of the properties * @param {Object} config The source of the properties * @param {Object} defaults A different object that will also be applied for default values * @return {Object} returns obj * @member UC apply */ UC.apply = function(o, c, defaults){ // 如果默认值defaults存在,那么先把defaults上得属性复制给对象o if(defaults){ UC.apply(o, defaults); } if(o && c && typeof c == 'object'){ for(var p in c){ o[p] = c[p]; } } return o; }; (function(window, undefined){ // idSeed,用来生成自增长的id值。 var idSeed = 0, toString = Object.prototype.toString, // ua,浏览器的用户代理,主要用来识别浏览器的型号、版本、内核和操作系统等。 ua = navigator.userAgent.toLowerCase(), check = function(r){ return r.test(ua); }, /** * Iterates an array calling the supplied function. * @param {Array/NodeList/Mixed} array The array to be iterated. If this * argument is not really an array, the supplied function is called once. * @param {Function} fn The function to be called with each item. If the * supplied function returns false, iteration stops and this method returns * the current index. This function is called with * the following arguments: */ isIterable = function(v){ //check for array or arguments if(UC.isArray(v) || v.callee){ return true; } //check for node list type if(/NodeList|HTMLCollection/.test(toString.call(v))){ return true; } //NodeList has an item and length property //IXMLDOMNodeList has nextNode method, needs to be checked first. return ((v.nextNode || v.item) && UC.isNumber(v.length)); }, DOC = document, // isStrict,表示当前浏览器是否是标准模式。 // 如果正确的设置了网页的doctype,则compatMode为CSS1Compat,否则为BackCompat isStrict = DOC.compatMode == "CSS1Compat", // isOpera,表示是否是opera浏览器。 isOpera = check(/opera/), // isChrome,表示是否是谷歌浏览器。 isChrome = check(/chrome/), // isWebKit,表示当前浏览器是否使用WebKit引擎。 // WebKit是浏览器内核,Safari和Chrome使用WebKit引擎。 isWebKit = check(/webkit/), // isSafari,表示是否是苹果浏览器,下面代码是对其版本识别。 isSafari = !isChrome && check(/safari/), isSafari3 = isSafari && check(/version\/3/), isSafari4 = isSafari && check(/version\/4/), isSafari5 = isSafari && check(/version\/5/), // isIE,表示是否是IE浏览器,下面代码是对其版本识别。 isIE = !isOpera && check(/msie/), isIE7 = isIE && check(/msie 7/), isIE8 = isIE && check(/msie 8/), // isGecko,表示当前浏览器是否使用Gecko引擎。 // Gecko是浏览器内核,Firefox使用Gecko引擎。 isGecko = !isWebKit && check(/gecko/), isGecko2 = isGecko && check(/rv:1\.8/), isGecko3 = isGecko && check(/rv:1\.9/), // isBorderBox,表示浏览器是否是IE的盒模式。 // 众所周知,IE的盒模式和W3C的盒模式不一致。当IE浏览器在怪异模式下,就会导致错误的盒模式。 isBorderBox = isIE && !isStrict, // isSecure,表示是否是https连接。 isSecure = /^https/i.test(window.location.protocol); // 扩展webuc对象,有一些属性,这个文件中没有使用,现在先不解释其作用,后面遇到了再讲。 UC.apply(UC, { // isStrict,表示是否是标准模式。 isStrict : isStrict, // isSecure,表示是否是https连接。 isSecure : isSecure, // isReady,表示Dom文档树是否加载完成 isReady : false, // SSL_SECURE_URL,这个值在构造隐藏的iframe时,用来设置src属性的,只是当是https连接的时候才用。 SSL_SECURE_URL : "javascript:false", // BLANK_IMAGE_URL,1像素透明图片地址 BLANK_IMAGE_URL : "http:/"+"/webujs.com/s.gif", // noop,空函数 noop : function(){}, // applyIf,把对象c的属性复制到对象o上,只复制o没有的属性 applyIf : function(o, c){ if(o && c){ for(var p in c){ if(typeof o[p] == "undefined"){ o[p] = c[p]; } } } return o; }, // 类继承函数,基于javascript的prototype,模仿面相对象的继承特性。 // 整个webucJS框架的继承机制就是这个函数实现的。 extend : function(){ // override函数,用来覆盖prototype上的属性的(私有对象,仅下面的return function内部可以使用) var io = function(o){ for(var m in o){ this[m] = o[m]; } }; // Object的构造函数(私有对象,仅下面的return function内部可以使用) var oc = Object.prototype.constructor; return function(sb, sp, overrides){ // sb表示subclass,sp表示superclass,overrides是默认值为对象型 // 如果sp是对象,表示没有传sb变量进来,所以重新设置一下参数 if(typeof sp == 'object'){ overrides = sp; sp = sb; // 如果overrides中提供了构造函数,那么就用提供的, // 否则用下面这个匿名函数,匿名函数会调用父类的构造函数 sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);}; } // F是一个临时的类,其prototype指向superclass的prototype, // 同时也把subclass的prototype指向了F对象, // 这样可以避免在类继承的时候,调用superclass的构造函数 var F = function(){}, sbp, spp = sp.prototype; F.prototype = spp; sbp = sb.prototype = new F(); sbp.constructor=sb; sb.superclass=spp; if(spp.constructor == oc){ spp.constructor=sp; } // sb的override的覆盖函数, // 作用是把所有属性覆盖到prototype上 sb.override = function(o){ UC.override(sb, o); }; // sbp的override // 作用是把所有属性覆盖到 sb上 sbp.override = io; // 设置默认值 UC.override(sb, overrides); // 继承函数,这样写方便,可以直接从别的类继承新类 // 即可以这样写 sb.extend(sp); sb.extend = function(o){UC.extend(sb, o);}; return sb; }; }(), // 覆盖函数,直接把属性复制到origclass的prototype上 override : function(origclass, overrides){ if(overrides){ var p = origclass.prototype; for(var method in overrides){ p[method] = overrides[method]; } // 下面是处理IE浏览器在枚举对象的属性时, // 原生的方法toString枚举不出来,即使是自定义的toString也不行 if(UC.isIE && overrides.toString != origclass.toString){ p.toString = overrides.toString; } } }, /** * 迭代数组,使用数组中的每个元素作为参数来调用传递进来的function * * @param {Mixed}Array/NodeList/Mixed * 如果传递进来的数组不是一个真实的数组,你的function只会被用这个伪数组作参数调用一次 * * @param {function} fn * @param {Object} scope * 指定方法执行的 作用域 ( this 的引用)。 默认为 item 在传递进来的 array 中 的当前 index 。 */ each: function(array, fn, scope){ // 若为空的时候直接退出循环,由于设置true 所以空字符串可以 if(UC.isEmpty(array, true)){ return; } // 如果是不可迭代的或者是三种原始类型 string, number 或 boolean if(!isIterable(array) || UC.isPrimitive(array)){ array = [array]; } for(var i = 0, len = array.length; i < len; i++){ //回调的this对象若没设scope 则使用array[i], fn 回传的参数 // 若在fn中return false 那么each 返回i 并且fn只会调用一次 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; }; } }, /** * 创建一个命名空间来划分变量和类的作用域,这样他们就不是全局的作用域了 * * @param {String} namespace1 * @param {String} namespace2 * @param {String} etc * @method namespace */ namespace : function(){ var o, d; UC.each(arguments, function(v) { d = v.split("."); o = window[d[0]] = window[d[0]] || {}; UC.each(d.slice(1), function(v2){ o = o[v2] = o[v2] || {}; }); }); return o; }, /** * 转化任何可迭代的对象(含有索引值和一个表长度的属性)为一个真正的数组,不要在字符串上用 * @param {Iterable} the iterable object to be turned into a true Array. * @return (Array) array */ toArray : function(){ return isIE ? function(a, i, j, res){ res = []; UC.each(a, function(v) { res.push(v); }); return res.slice(i || 0, j || res.length); } : function(a, i, j){ return Array.prototype.slice.call(a, i || 0, j || a.length); } }(), /** * 迭代数组中的元素,或对象中的每个属性, * * 只是在each上多进行对象遍历 * 注意:如果你仅仅迭代数组,最好调用 each。 */ iterate : function(obj, fn, scope){ if(isIterable(obj)){ UC.each(obj, fn, scope); return; }else if(UC.isObject(obj)){ for(var prop in obj){ if(obj.hasOwnProperty(prop)){ if(fn.call(scope || obj, prop, obj[prop]) === false){ return; }; } } } }, /** * 返回true,如果传递进来的值为null、undefined或者一个空的字符串、空数组 (除非 allowBlank参数为 true)。 * * @param {Mixed} value The value to test * @param {Boolean} allowBlank (optional) true to allow empty strings (defaults to false) * @return {Boolean} */ isEmpty : function(v, allowBlank){ return v === null || v === undefined || ((UC.isArray(v) && !v.length)) || (!allowBlank ? v === '' : false); }, /** * 如果传递的值是JavaScript 的数组则返回true,否则返回 false * @param {Object} object The object to test * @return {Boolean} */ isArray : function(v){ return toString.apply(v) === '[object Array]'; }, /** * 如果传递的值是JavaScript 的数组则返回true,否则返回 false * @param {Object} object The object to test * @return {Boolean} */ isObject : function(v){ return v && typeof v == "object"; }, /** * 如果传递的值是JavaScript 的数组则返回true,否则返回 false * @param {Mixed} value The value to test * @return {Boolean} */ isPrimitive : function(v){ return UC.isString(v) || UC.isNumber(v) || UC.isBoolean(v); }, /** * 如果是一个JavaScript函数则返回true,否则为false。 * @param {Object} object The object to test * @return {Boolean} */ isFunction : function(v){ return toString.apply(v) === '[object Function]'; }, /** * 当传递的值为数字时返回true 。如果为无穷数则返回false * @param {Object} v The object to test * @return {Boolean} */ isNumber: function(v){ return typeof v === 'number' && isFinite(v); }, /** * 如果传递的值为字符串则返回true。 * @param {Object} v The object to test * @return {Boolean} */ isString: function(v){ return typeof v === 'string'; }, /** * 如果传递的值为布尔值则返回true。 * @param {Object} v The object to test * @return {Boolean} */ isBoolean: function(v){ return typeof v === 'boolean'; }, /** * 如果传递的值未定义则为true * @param {Object} v The object to test * @return {Boolean} */ isDefined: function(v){ return typeof v !== 'undefined'; }, /** * True if the detected browser is Opera. * @type Boolean */ isOpera : isOpera, /** * True if the detected browser uses WebKit. * @type Boolean */ isWebKit: isWebKit, /** * True if the detected browser is Chrome. * @type Boolean */ isChrome : isChrome, /** * True if the detected browser is Safari. * @type Boolean */ isSafari : isSafari, /** * True if the detected browser is Safari 3.x. * @type Boolean */ isSafari3 : isSafari3, /** * True if the detected browser is Safari 4.x. * @type Boolean */ isSafari4 : isSafari4, /** /** * True if the detected browser is Internet Explorer. * @type Boolean */ isIE : isIE, /** * True if the detected browser is Internet Explorer 7.x. * @type Boolean */ isIE7 : isIE7, /** * True if the detected browser is Internet Explorer 8.x. * @type Boolean */ isIE8 : isIE8, /** * True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox). * @type Boolean */ isGecko : isGecko, /** * True if the detected browser uses a pre-Gecko 1.9 layout engine (e.g. Firefox 2.x). * @type Boolean */ isGecko2 : isGecko2, /** * True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x). * @type Boolean */ isGecko3 : isGecko3, /** * True if the detected browser is Internet Explorer running in non-strict mode. * @type Boolean */ isBorderBox : isBorderBox }); /** * 创建一个命名空间使得作用域里的变量和类都不会是全局的。 * 具体指定命名空间的最后一个节点来准确的创建其他不同节点 用例 * * UC.namespace('Company.data'); // 和上面的语法等效而且更好 * Company.Widget = function() { ... } * Company.data.CustomStore = function(config) { ... } * * @param {String} namespace1 * @param {String} namespace2 * @param {String} etc * @method namespace */ UC.ns = UC.namespace; })(window); UC.ns("UC", "UC.util", "UC.util.Constants", "UC.Component"); /** * @class String * These functions are available on every String object. */ UC.applyIf(String, { /*允许你自定义含有占位符的字符串,并且传递任意数量的参数去替代这些占位符。 *每一个占位符必须是唯一的,并且以{0}、{1}…这种格式递增。 * *用法示例: * var cls = 'my-class', text = 'Some text'; * var s = String.format('<div class="{0}">{1}</div>', cls, text); * @参数1 {String} string 含有占位符,需要格式化的字符串 * @参数2 {String} value1 替代占位符 {0}的字符串 * @参数3 {String} value2 替代占位符{1}的字符串,以此类推 * @返回值 {String} 格式化好的字符串 * @静态方法 */ format : function(format){ var args = UC.toArray(arguments, 1); return format.replace(/\{(\d+)\}/g, function(m, i){ return args[i]; }); }, /** * 用指定的字符填充一个字符串的左侧。对于格式化数字或者日期字符串,这 *一个非常有用的方法。用法示例: *var s = String.leftPad('123', 5, '0'); * result: s = '00123' * * @参数1 {String} string 原来的字符串 * @参数2 {Number} size 返回字符串的总长度 * @参数3 {String} char (optional) 填充的字符串 (默认用" "填充) * @返回值 {String} 填充好的字符串 * @静态方法 */ leftPad : function (val, size, ch) { var result = new String(val); if(!ch) { ch = " "; } while (result.length < size) { result = ch + result; } return result.toString(); }, eqs : function (str1, str2) { return str1.toLowerCase() === str2.toLowerCase(); } }); /** * @class Array */ UC.applyIf(Array.prototype, { /** * Checks whether or not the specified object exists in the array. * @param {Object} o The object to check for * @return {Number} The index of o in the array (or -1 if it is not found) */ indexOf : function(o){ for (var i = 0, len = this.length; i < len; i++){ if(this[i] == o){ return i; } } return -1; }, /** * Removes the specified object from the array. If the object is not found nothing happens. * @param {Object} o The object to remove * @return {Array} this array */ remove : function(o){ var index = this.indexOf(o); if(index != -1){ this.splice(index, 1); } return this; } }); UC.apply(UC.util.Constants, { STATE_ACTIVE : "active", STATE_DISABLED : "disabled", STATE_NORMAL : "normal", POSITION_UP : "up", POSITION_DOWN : "down", POSITION_LEFT : "left", POSITION_RIGHT : "right", keyCode: { ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, // COMMAND COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, // COMMAND_RIGHT NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108, NUMPAD_MULTIPLY: 106, NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91 // COMMAND } }); UC.Component = function(config){ config = config || {}; if(config.initialConfig){ if(config.isAction){ // actions this.baseAction = config; } config = config.initialConfig; // component cloning / action set up }else if(config.tagName || config.dom || UC.isString(config)){ // element object config = {applyTo: config, id: config.id || config}; } /** * This Component's initial configuration specification. Read-only. * @type Object * @property initialConfig */ this.initialConfig = config; UC.apply(this, config); // UC.Component.superclass.constructor.call(this); this.initComponent(); }; UC.Component.prototype = { /** 父类id **/ appendTo : "", /** 添加的父节点 */ id : "", disabled : false, /** * @cfg {Boolean} hidden * Render this component hidden (default is false). If <tt>true</tt>, the * {@link #hide} method will be called internally. */ hidden : false, /** * True if this component has been rendered. Read-only. * @type Boolean * @property */ rendered : false, // private xtype : 'UC.Component', listeners : {}, tips : "", self : null, getSelf : function(){ return this.self; }, initComponent : UC.noop, /** *在传递进来的HTML元素中渲染当前组件。 */ render : function(){ _this = this; var self = _this.self = $("#" + _this.id); // 添加里面的样式 for (var i in _this.css) { self.css(i, _this.css[i]); } return _this; }, /** * Returns the <code>id</code> of this component or automatically generates and * returns an <code>id</code> if an <code>id</code> is not defined yet:<pre><code> * 'ext-comp-' + (++UC.Component.AUTO_ID) * </code></pre> * @return {String} id */ getId : function(){ return this.id || (this.id = 'ext-comp-' + (++UC.Component.AUTO_ID)); }, /** * Show this component. Listen to the '{@link #beforeshow}' event and return * <tt>false</tt> to cancel showing the component. Fires the '{@link #show}' * event after showing the component. * @return {UC.Component} this */ show : function(){ if(this.fireEvent('beforeshow', this) !== false){ this.hidden = false; if(this.autoRender){ this.render(UC.isBoolean(this.autoRender) ? UC.getBody() : this.autoRender); } if(this.rendered){ this.onShow(); } this.fireEvent('show', this); } return this; }, /** * Hide this component. Listen to the '{@link #beforehide}' event and return * <tt>false</tt> to cancel hiding the component. Fires the '{@link #hide}' * event after hiding the component. Note this method is called internally if * the component is configured to be <code>{@link #hidden}</code>. * @return {UC.Component} this */ hide : function(){ this.self.hide(); } }; (function(){ var constants = UC.util.Constants; var self = null; function onRender(btnObj) { var textname = btnObj.textname || btnObj.text; btnObj.text = lang[btnObj.text] || btnObj.text; var html = '<div id="' + btnObj.id + '" class="button-l">' + '<span class="button-r" textname="' + textname + '">'+btnObj.text+'</span>' + '</div>'; $("#" + btnObj.appendTo).append(html); }; UC.Button = UC.extend(UC.Component, { /** 在dom上的id */ text : "", /** 为了能动态切换国际语言 */ textname : "", /** 这里有 disabled || normal || active 灰色不可点 || 正常 || 按下触发 */ state : constants.STATE_NORMAL, xtype : 'Button', /** 要添加的样式 这里主要做的还是定位 */ css : {}, // Initialze Button initComponent : function () { UC.Button.superclass.initComponent.call(this); this.render(); self = this.self; this.addEventListener(); this.stateFn(this.state); }, // Private addEventListener : function () { // When the menu state is disable, do nothing if (this.stateFn() === constants.STATE_DISABLED) { return; } for (var e in this.listeners) { // Add the event listener if (typeof this.listeners[e] === "function") { var _this = this; // 对传进来的事件进行绑定 并回调 self[e](function(event){ _this.listeners[event.type].call(_this, event); }) } } }, // Private render : function () { onRender(this); UC.Button.superclass.render.call(this); }, /** * set or get Button text */ text : function (value) { return value ? this.text = value : this.text; }, /** * Show Menu * @returns Button */ show : function () { return self.show(); }, /** * hide Menu * @returns Button */ hide : function () { return self.hide(); }, /** * set or get the button state * * @param state active | normal | disabled * @returns */ stateFn : function (state) { // Get state if (state === undefined) { return this.state; } // When set state wrong parameter if (!String.eqs(state, constants.STATE_ACTIVE) && !String.eqs(state, constants.STATE_DISABLED) && !String.eqs(state, constants.STATE_NORMAL)) { throw new Error("state parameter error."); } // Set state this.state = state; self.attr("class", "button-l button-" + state); return state; } }) })();
1 楼
cremains
2014-02-22
没有demo的地址呢?
2 楼
ku_sunny
2014-02-22
cremains 写道
没有demo的地址呢?
那个Button 就是一个简单的组件demo了
3 楼
ku_sunny
2014-02-22
具体的实例 可以通过传参new Button()一个 不过样式的先定义好
4 楼
aunox
2014-02-22
他们说的demo是指带有网页界面和示例说明的。