├── .travis.yml ├── yarn.lock ├── .idea ├── .name ├── encodings.xml ├── vcs.xml ├── modules.xml ├── jsLibraryMappings.xml ├── sparrow.iml ├── libraries │ └── sparrow_node_modules.xml └── misc.xml ├── .npmignore ├── _config.yml ├── .github ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md └── CONTRIBUTING.md ├── docs ├── SUMMARY.md ├── install.md ├── dom.md ├── isobject.md ├── event.md ├── style.md ├── device.md └── method.md ├── snippets ├── SUMMARY.md ├── install.md ├── dom.md ├── isobject.md ├── event.md ├── style.md ├── device.md └── method.md ├── .babelrc ├── bin └── utool.js ├── test ├── sparrow.spec.js └── test.html ├── lib ├── enumerables.js ├── cookies.js ├── extend.js ├── util │ ├── formater.js │ ├── i18n.js │ ├── dataRender.js │ ├── hotKeys.js │ └── ripple.js ├── index.js ├── ajax.js ├── event.js ├── util.js ├── BaseComponent.js ├── core.js ├── class.js ├── fetch.js ├── env.js ├── mobileEvents.js └── dom.js ├── .gitignore ├── src ├── enumerables.js ├── cookies.js ├── extend.js ├── util │ ├── formater.js │ ├── i18n.js │ ├── dataRender.js │ ├── hotKeys.js │ └── ripple.js ├── locales │ ├── zh-CN │ │ └── uui-trans.json │ ├── zh-TW │ │ └── uui-trans.json │ ├── zh │ │ └── uui-trans.json │ ├── zh_CN │ │ └── uui-trans.json │ ├── en │ │ └── uui-trans.json │ ├── en-US │ │ └── uui-trans.json │ └── en_US │ │ └── uui-trans.json ├── fetch.js ├── ajax.js ├── index.js ├── event.js ├── util.js ├── core.js ├── class.js ├── env.js └── mobileEvents.js ├── LICENSE ├── rollup.config.js ├── README_CN.md ├── README.md ├── package.json ├── CHANGELOG.md ├── webpack.config.js └── .eslintrc /.travis.yml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | sparrow -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .babelrc -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # layout布局 2 | source: docs 3 | example: examples 4 | 5 | # 文档片段 6 | snip_dir: snippets 7 | snip_sum: SUMMARY.md 8 | snip_index: README.md 9 | snip_base: base.md 10 | snip_demo: demo 11 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### PR 选择列表 2 | 3 | - [ ] 解决现有问题: #0000 4 | - [ ] 新功能,修正或增强 5 | - [ ] 包括测试 6 | - [ ] 文档更新 7 | 8 | #### 你做了哪些更改? 9 | 10 | (描述一下) 11 | 12 | #### 有什么你想要审阅者关注? 13 | 14 | (可选) 15 | -------------------------------------------------------------------------------- /docs/SUMMARY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [安装介绍](install.md) 4 | - API介绍 5 | * [终端判断](device.md) 6 | * [对象判断](isobject.md) 7 | * [事件绑定](event.md) 8 | * [方法扩展](method.md) 9 | * [样式](style.md) 10 | * [DOM](dom.md) 11 | 12 | -------------------------------------------------------------------------------- /snippets/SUMMARY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | - [安装介绍](install.md) 4 | - API介绍 5 | * [终端判断](device.md) 6 | * [对象判断](isobject.md) 7 | * [事件绑定](event.md) 8 | * [方法扩展](method.md) 9 | * [样式](style.md) 10 | * [DOM](dom.md) 11 | 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Bug 报告 4 | 5 | - __Package version(s)__: (版本号) 6 | 7 | #### 描述这个问题: 8 | 9 | 10 | 11 | #### 当前的行为: 12 | 13 | 14 | 15 | #### 期望的行为: 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["latest", { 4 | "es2015": { 5 | "modules": false 6 | } 7 | }] 8 | ], 9 | "plugins": [ 10 | "external-helpers", 11 | "transform-es3-property-literals", 12 | "transform-es3-member-expression-literals" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /.idea/jsLibraryMappings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /bin/utool.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | 4 | 5 | 6 | /** 7 | * ignore '.'开头隐藏文件 8 | */ 9 | var regDotFile = function(ele){ 10 | return /^[^\.]/g.test(ele); 11 | } 12 | exports.rmdot = function(ary){ 13 | return ary.filter(regDotFile); 14 | } 15 | // example 16 | // var ary = [ '.DS_Store', 'neoui' ]; 17 | // newAry = rm_hideFile(ary); 18 | // console.log(newAry); 19 | 20 | 21 | /** 22 | * 23 | */ 24 | -------------------------------------------------------------------------------- /test/sparrow.spec.js: -------------------------------------------------------------------------------- 1 | import chai from 'chai'; 2 | import sparrow from '../lib/sparrow.js'; 3 | 4 | chai.expect(); 5 | 6 | const expect = chai.expect; 7 | 8 | var lib; 9 | 10 | describe('Given an instance of my sparrow', function () { 11 | before(function () { 12 | lib = new sparrow(); 13 | }); 14 | describe('when I need the name', function () { 15 | it('should return the name', () => { 16 | expect(lib.name).to.be.equal('sparrow'); 17 | }); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /.idea/sparrow.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/libraries/sparrow_node_modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Sparrow.js Test 6 | 7 | 8 |
9 |
10 |
Sparrow is very nice
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /snippets/install.md: -------------------------------------------------------------------------------- 1 | ## 起步 2 | 3 | ### Sparrow介绍 4 | 5 | `tinper-sparrow` 是一个轻量级 `javascript` 库,让开发者能更方便地进行 `DOM`操作、`events`处理、动画效果实现和`AJAX`交互等,并且提供丰富的`API`封装,如多平台多浏览器判断、`Cookies`操作、事件机制、日期转换、数字处理、字符串相关判断等一系列功能方法。 6 | 7 | 8 | 9 | ### 如何使用 10 | 11 | ##### 浏览器环境 12 | 13 | * 离线下载:只需将下载到的`sparrow.js`放置在`script`标签中 14 | 15 | ``` 16 | 17 | ``` 18 | 19 | 20 | ##### 使用ES6模块开发环境 21 | 22 | * 步骤一:安装依赖 23 | 24 | ``` 25 | $ npm install --save tinper-sparrow 26 | ``` 27 | 28 | * 步骤二:在需要依赖的文件中引入 29 | 30 | ``` 31 | import {u} from 'tinper-sparrow/js/index.js' 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Tinper-Sparrow 2 | 3 | ## Sparrow介绍 4 | 5 | `tinper-sparrow` 是一个轻量级 `javascript` 库,让开发者能更方便地进行 `DOM`操作、`events`处理、动画效果实现和`AJAX`交互等,并且提供丰富的`API`封装,如多平台多浏览器判断、`Cookies`操作、事件机制、日期转换、数字处理、字符串相关判断等一系列功能方法。 6 | 7 | 8 | 9 | ## 如何使用 10 | 11 | #### 浏览器环境 12 | 13 | * 离线下载:只需将下载到的`sparrow.js`放置在`script`标签中 14 | 15 | ``` 16 | 17 | ``` 18 | 19 | 20 | #### 使用ES6模块开发环境 21 | 22 | * 步骤一:安装依赖 23 | 24 | ``` 25 | $ npm install --save tinper-sparrow 26 | ``` 27 | 28 | * 步骤二:在需要依赖的文件中引入 29 | 30 | ``` 31 | import {u} from 'tinper-sparrow/js/index.js' 32 | ``` 33 | 34 | -------------------------------------------------------------------------------- /snippets/dom.md: -------------------------------------------------------------------------------- 1 | 2 | ## DOM 3 | 4 | ### wrap(element,parent) 5 | * 说明: 6 | 7 | 将HTML元素添加到某HTML元素中。 8 | 9 | * 参数: 10 | * {HTMLElement} element:必需。被添加的HTML元素。 11 | * {String}/{HTMLElement} parent:必需。作为父项的HTML元素。 12 | * 返回值: 13 | 14 | 无 15 | * 用法:​ 16 | u.wrap(document.getElementById('id1'), '
'); 17 | u.wrap(document.getElementById('id1'), document.getElementById('id2')); 18 | 19 | 20 | 21 | 22 | 23 | ### makeDOM(htmlString) 24 | * 说明: 25 | 26 | 创建HTML元素 27 | 28 | * 参数: 29 | 30 | * {String} htmlString:必需。需要创建的HTML元素对应的html字符串。 31 | 32 | * 返回值: 33 | 34 | 创建之后的HTML元素 35 | * 用法:​ 36 | u.makeDOM('
'); 37 | -------------------------------------------------------------------------------- /docs/dom.md: -------------------------------------------------------------------------------- 1 | 2 | # DOM 3 | 4 | ## # wrap(element,parent) 5 | * 说明: 6 | 7 | 将HTML元素添加到某HTML元素中。 8 | 9 | * 参数: 10 | * {HTMLElement} element:必需。被添加的HTML元素。 11 | * {String}/{HTMLElement} parent:必需。作为父项的HTML元素。 12 | * 返回值: 13 | 14 | 无 15 | * 用法:​ 16 | u.wrap(document.getElementById('id1'), '
'); 17 | u.wrap(document.getElementById('id1'), document.getElementById('id2')); 18 | 19 | 20 | 21 | 22 | 23 | ## # makeDOM(htmlString) 24 | * 说明: 25 | 26 | 创建HTML元素 27 | 28 | * 参数: 29 | 30 | * {String} htmlString:必需。需要创建的HTML元素对应的html字符串。 31 | 32 | * 返回值: 33 | 34 | 创建之后的HTML元素 35 | * 用法:​ 36 | u.makeDOM('
'); 37 | 38 | -------------------------------------------------------------------------------- /lib/enumerables.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow extend enum 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | var U_LANGUAGES = "i_languages"; 8 | var U_THEME = "u_theme"; 9 | var U_LOCALE = "u_locale"; 10 | var U_USERCODE = "usercode"; 11 | var U_TIMEZONE = "u_timezone"; 12 | 13 | var enumerables = true, 14 | enumerablesTest = { 15 | toString: 1 16 | }, 17 | toString = Object.prototype.toString; 18 | for (var i in enumerablesTest) { 19 | enumerables = null; 20 | } 21 | if (enumerables) { 22 | enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString', 'constructor']; 23 | } 24 | 25 | export { enumerables, U_LANGUAGES, U_THEME, U_LOCALE, U_USERCODE, U_TIMEZONE }; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | 33 | # Optional npm cache directory 34 | .npm 35 | 36 | # Optional REPL history 37 | .node_repl_history 38 | .idea/* 39 | .DS_Store -------------------------------------------------------------------------------- /src/enumerables.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow extend enum 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | var U_LANGUAGES = "i_languages"; 8 | var U_THEME = "u_theme"; 9 | var U_LOCALE = "u_locale"; 10 | var U_USERCODE = "usercode"; 11 | var U_TIMEZONE = "u_timezone"; 12 | 13 | var enumerables = true, 14 | enumerablesTest = { 15 | toString: 1 16 | }, 17 | toString = Object.prototype.toString; 18 | for(var i in enumerablesTest) { 19 | enumerables = null; 20 | } 21 | if(enumerables) { 22 | enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable', 23 | 'toLocaleString', 'toString', 'constructor' 24 | ]; 25 | } 26 | 27 | 28 | export {enumerables,U_LANGUAGES,U_THEME,U_LOCALE,U_USERCODE,U_TIMEZONE}; 29 | -------------------------------------------------------------------------------- /lib/cookies.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow cookies 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | var setCookie = function setCookie(sName, sValue, oExpires, sPath, sDomain, bSecure) { 8 | var sCookie = sName + "=" + encodeURIComponent(sValue); 9 | if (oExpires) sCookie += "; expires=" + oExpires.toGMTString(); 10 | if (sPath) sCookie += "; path=" + sPath; 11 | if (sDomain) sCookie += "; domain=" + sDomain; 12 | if (bSecure) sCookie += "; secure=" + bSecure; 13 | document.cookie = sCookie; 14 | }; 15 | 16 | var getCookie = function getCookie(sName) { 17 | var sRE = "(?:; )?" + sName + "=([^;]*);?"; 18 | var oRE = new RegExp(sRE); 19 | 20 | if (oRE.test(document.cookie)) { 21 | return decodeURIComponent(RegExp["$1"]); 22 | } else return null; 23 | }; 24 | 25 | export { setCookie, getCookie }; -------------------------------------------------------------------------------- /src/cookies.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow cookies 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | var setCookie = function(sName, sValue, oExpires, sPath, sDomain, bSecure) { 8 | var sCookie = sName + "=" + encodeURIComponent(sValue); 9 | if(oExpires) 10 | sCookie += "; expires=" + oExpires.toGMTString(); 11 | if(sPath) 12 | sCookie += "; path=" + sPath; 13 | if(sDomain) 14 | sCookie += "; domain=" + sDomain; 15 | if(bSecure) 16 | sCookie += "; secure=" + bSecure; 17 | document.cookie = sCookie; 18 | }; 19 | 20 | var getCookie = function(sName) { 21 | var sRE = "(?:; )?" + sName + "=([^;]*);?"; 22 | var oRE = new RegExp(sRE); 23 | 24 | if(oRE.test(document.cookie)) { 25 | return decodeURIComponent(RegExp["$1"]); 26 | } else 27 | return null; 28 | }; 29 | 30 | export { 31 | setCookie,getCookie 32 | }; -------------------------------------------------------------------------------- /src/extend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow extend 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | import {enumerables} from './enumerables'; 8 | 9 | 10 | /** 11 | * 复制对象属性 12 | * 13 | * @param {Object} 目标对象 14 | * @param {config} 源对象 15 | */ 16 | var extend = function(object, config) { 17 | var args = arguments, 18 | options; 19 | if(args.length > 1) { 20 | for(var len = 1; len < args.length; len++) { 21 | options = args[len]; 22 | if(object && options && typeof options === 'object') { 23 | var i, j, k; 24 | for(i in options) { 25 | object[i] = options[i]; 26 | } 27 | if(enumerables) { 28 | for(j = enumerables.length; j--;) { 29 | k = enumerables[j]; 30 | if(options.hasOwnProperty && options.hasOwnProperty(k)) { 31 | object[k] = options[k]; 32 | } 33 | } 34 | } 35 | } 36 | } 37 | } 38 | return object; 39 | }; 40 | 41 | if(!Object.assign){ 42 | Object.assign = extend; 43 | } 44 | 45 | export {extend}; 46 | -------------------------------------------------------------------------------- /lib/extend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow extend 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | import { enumerables } from './enumerables'; 8 | 9 | /** 10 | * 复制对象属性 11 | * 12 | * @param {Object} 目标对象 13 | * @param {config} 源对象 14 | */ 15 | var extend = function extend(object, config) { 16 | var args = arguments, 17 | options; 18 | if (args.length > 1) { 19 | for (var len = 1; len < args.length; len++) { 20 | options = args[len]; 21 | if (object && options && (typeof options === 'undefined' ? 'undefined' : babelHelpers['typeof'](options)) === 'object') { 22 | var i, j, k; 23 | for (i in options) { 24 | object[i] = options[i]; 25 | } 26 | if (enumerables) { 27 | for (j = enumerables.length; j--;) { 28 | k = enumerables[j]; 29 | if (options.hasOwnProperty && options.hasOwnProperty(k)) { 30 | object[k] = options[k]; 31 | } 32 | } 33 | } 34 | } 35 | } 36 | } 37 | return object; 38 | }; 39 | 40 | if (!Object.assign) { 41 | Object.assign = extend; 42 | } 43 | 44 | export { extend }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 iuap design 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/isobject.md: -------------------------------------------------------------------------------- 1 | # 对象判断 2 | 3 | ## # isDate(obj) 4 | * 说明: 5 | 6 | 判断传入对象是否为Date对象 7 | 8 | * 参数: 9 | 10 | * {Object} obj:必需。需要进行判断的对象。 11 | * 返回值: 12 | 13 | {Boolean}传入对象为Date对象返回true否则返回false 14 | * 用法: 15 | ​ 16 | u.isDate(new Date()); 17 | 18 | ## # isNumber(obj) 19 | * 说明: 20 | 21 | 判断传入对象是否为Number对象 22 | 23 | * 参数: 24 | 25 | * {Object} obj:必需。需要进行判断的对象。 26 | * 返回值: 27 | 28 | {Boolean}传入对象为Number对象返回true否则返回false 29 | * 用法: 30 | ​ 31 | u.isNumber('123'); 32 | 33 | ## # isArray(obj) 34 | * 说明: 35 | 36 | 判断传入对象是否为数组对象 37 | 38 | * 参数: 39 | 40 | * {Object} obj:必需。需要进行判断的对象。 41 | * 返回值: 42 | 43 | {Boolean}传入对象为数组对象返回true否则返回false 44 | * 用法: 45 | ​ 46 | u.isArray(['1','2']); 47 | 48 | 49 | ## # isEmptyObject(obj) 50 | * 说明: 51 | 52 | 判断传入对象是否为空对象 53 | 54 | * 参数: 55 | 56 | * {Object} obj:必需。需要进行判断的对象。 57 | * 返回值: 58 | 59 | {Boolean}传入对象为空对象返回true否则返回false 60 | * 用法: 61 | ​ 62 | u.isEmptyObject({id:'id'}); 63 | 64 | 65 | ## # inArray(node,arr) 66 | * 说明: 67 | 68 | 判断元素是否在数组中 69 | 70 | * 参数: 71 | 72 | * {Object} node:必需。需要进行判断的元素。 73 | * {Array} arr:必需。需要进行判断的数组。 74 | * 返回值: 75 | 76 | {Boolean}如果数组中存在元素则返回true,否则返回false。 77 | * 用法: 78 | ​ 79 | u.inArray('a1',['a2','a3']); 80 | -------------------------------------------------------------------------------- /snippets/isobject.md: -------------------------------------------------------------------------------- 1 | ## 对象判断 2 | 3 | ### isDate(obj) 4 | * 说明: 5 | 6 | 判断传入对象是否为Date对象 7 | 8 | * 参数: 9 | 10 | * {Object} obj:必需。需要进行判断的对象。 11 | * 返回值: 12 | 13 | {Boolean}传入对象为Date对象返回true否则返回false 14 | * 用法: 15 | ​ 16 | u.isDate(new Date()); 17 | 18 | ### isNumber(obj) 19 | * 说明: 20 | 21 | 判断传入对象是否为Number对象 22 | 23 | * 参数: 24 | 25 | * {Object} obj:必需。需要进行判断的对象。 26 | * 返回值: 27 | 28 | {Boolean}传入对象为Number对象返回true否则返回false 29 | * 用法: 30 | ​ 31 | u.isNumber('123'); 32 | 33 | ### isArray(obj) 34 | * 说明: 35 | 36 | 判断传入对象是否为数组对象 37 | 38 | * 参数: 39 | 40 | * {Object} obj:必需。需要进行判断的对象。 41 | * 返回值: 42 | 43 | {Boolean}传入对象为数组对象返回true否则返回false 44 | * 用法: 45 | ​ 46 | u.isArray(['1','2']); 47 | 48 | 49 | ### isEmptyObject(obj) 50 | * 说明: 51 | 52 | 判断传入对象是否为空对象 53 | 54 | * 参数: 55 | 56 | * {Object} obj:必需。需要进行判断的对象。 57 | * 返回值: 58 | 59 | {Boolean}传入对象为空对象返回true否则返回false 60 | * 用法: 61 | ​ 62 | u.isEmptyObject({id:'id'}); 63 | 64 | 65 | ### inArray(node,arr) 66 | * 说明: 67 | 68 | 判断元素是否在数组中 69 | 70 | * 参数: 71 | 72 | * {Object} node:必需。需要进行判断的元素。 73 | * {Array} arr:必需。需要进行判断的数组。 74 | * 返回值: 75 | 76 | {Boolean}如果数组中存在元素则返回true,否则返回false。 77 | * 用法: 78 | ​ 79 | u.inArray('a1',['a2','a3']); 80 | -------------------------------------------------------------------------------- /snippets/event.md: -------------------------------------------------------------------------------- 1 | ## 事件绑定 2 | 3 | ### on(element,eventName,child,listener) 4 | * 说明: 5 | 6 | 为HTML元素绑定事件 7 | 8 | * 参数: 9 | * {HTMLElement} element:必需。需要绑定事件的HTML元素。 10 | * {String} eventName:必需。绑定事件的事件名称。 11 | * {String} child:可选。选择器,是否为element的子元素进行事件绑定。 12 | * {function} listener:必需。触发事件时执行的function。 13 | * 返回值: 14 | 15 | 无 16 | * 用法: 17 | u.on(window, 'resize', function(){ 18 | alert('resizeFun') 19 | }); 20 | 21 | ### off(element,eventName,listener) 22 | * 说明: 23 | 24 | 为HTML元素取消事件绑定 25 | 26 | * 参数: 27 | * {HTMLElement} element:必需。取消绑定事件的HTML元素。 28 | * {String} eventName:必需。绑定事件的事件名称。 29 | * {function} listener:可选。取消绑定的function,如果传入则只取消此function的绑定,对其他function不进行改变。 30 | * 返回值: 31 | 32 | 无 33 | * 用法: 34 | u.off(window, 'resize'); 35 | 36 | 37 | ### trigger(element,eventName) 38 | * 说明: 39 | 40 | 触发HTML元素的事件绑定 41 | 42 | * 参数: 43 | * {HTMLElement} element:必需。触发绑定事件的HTML元素。 44 | * {String} eventName:必需。触发绑定事件的事件名称。 45 | * 返回值: 46 | 47 | 无 48 | * 用法: 49 | ​ 50 | u.trigger(window, 'resize'); 51 | 52 | 53 | 54 | 55 | ##stopEvent(e) 56 | 57 | * 说明: 58 | 59 | 阻止事件传播,兼容不同浏览器 60 | 61 | * 参数: 62 | 63 | * {Event} e:必需。需要阻止传播的事件。 64 | 65 | * 返回值: 66 | 67 | 无 68 | * 用法: 69 | u.stopEvent(e); 70 | -------------------------------------------------------------------------------- /docs/event.md: -------------------------------------------------------------------------------- 1 | # 事件绑定 2 | 3 | ## # on(element,eventName,child,listener) 4 | * 说明: 5 | 6 | 为HTML元素绑定事件 7 | 8 | * 参数: 9 | * {HTMLElement} element:必需。需要绑定事件的HTML元素。 10 | * {String} eventName:必需。绑定事件的事件名称。 11 | * {String} child:可选。选择器,是否为element的子元素进行事件绑定。 12 | * {function} listener:必需。触发事件时执行的function。 13 | * 返回值: 14 | 15 | 无 16 | * 用法: 17 | u.on(window, 'resize', function(){ 18 | alert('resizeFun') 19 | }); 20 | 21 | ## # off(element,eventName,listener) 22 | * 说明: 23 | 24 | 为HTML元素取消事件绑定 25 | 26 | * 参数: 27 | * {HTMLElement} element:必需。取消绑定事件的HTML元素。 28 | * {String} eventName:必需。绑定事件的事件名称。 29 | * {function} listener:可选。取消绑定的function,如果传入则只取消此function的绑定,对其他function不进行改变。 30 | * 返回值: 31 | 32 | 无 33 | * 用法: 34 | u.off(window, 'resize'); 35 | 36 | 37 | ## # trigger(element,eventName) 38 | * 说明: 39 | 40 | 触发HTML元素的事件绑定 41 | 42 | * 参数: 43 | * {HTMLElement} element:必需。触发绑定事件的HTML元素。 44 | * {String} eventName:必需。触发绑定事件的事件名称。 45 | * 返回值: 46 | 47 | 无 48 | * 用法: 49 | ​ 50 | u.trigger(window, 'resize'); 51 | 52 | 53 | 54 | 55 | ## #stopEvent(e) 56 | 57 | * 说明: 58 | 59 | 阻止事件传播,兼容不同浏览器 60 | 61 | * 参数: 62 | 63 | * {Event} e:必需。需要阻止传播的事件。 64 | 65 | * 返回值: 66 | 67 | 无 68 | * 用法: 69 | u.stopEvent(e); 70 | 71 | 72 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from "rollup-plugin-babel"; 2 | import multidest from "rollup-plugin-multidest"; 3 | import nodeResolve from "rollup-plugin-node-resolve"; 4 | import uglify from "rollup-plugin-uglify"; 5 | import license from "rollup-plugin-license"; 6 | 7 | export default { 8 | entry: "src/index.js", 9 | dest: "dist/tinper-sparrow.js", 10 | format: "iife", 11 | moduleName: "bar", 12 | plugins: [ 13 | license({ 14 | banner: `<%= pkg.name %> v<%= pkg.version %> 15 | <%= pkg.description %> 16 | author : <%= pkg.author %> 17 | homepage : <%= pkg.homepage %> 18 | bugs : <%= pkg.bugs.url %>`, 19 | }), 20 | nodeResolve(), 21 | multidest([ 22 | // targets "main" in package.json 23 | // { 24 | // dest: "dist/js/tinper-neoui.cjs.js", 25 | // format: "cjs" 26 | // }, 27 | // targets browsers 28 | { 29 | dest: "dist/tinper-sparrow.min.js", 30 | format: "iife", 31 | plugins: [uglify()] 32 | } 33 | ]), 34 | babel({ 35 | exclude: "node_modules/**" // only transpile our source code 36 | }) 37 | ] 38 | }; 39 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | CSS 12 | 13 | 14 | Probable bugsCSS 15 | 16 | 17 | RELAX NG 18 | 19 | 20 | XPath 21 | 22 | 23 | XSLT 24 | 25 | 26 | 27 | 28 | CssNoGenericFontName 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /lib/util/formater.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow data formater tools 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 15:39:01 5 | */ 6 | import { isNumber } from '../util'; 7 | 8 | function NumberFormater(precision) { 9 | this.precision = precision; 10 | }; 11 | 12 | NumberFormater.prototype.update = function (precision) { 13 | this.precision = precision; 14 | }; 15 | 16 | NumberFormater.prototype.format = function (value) { 17 | if (!isNumber(value)) return ""; 18 | 19 | // 以0开头的数字将其前面的0去掉 20 | while ((value + "").charAt(0) == "0" && value.length > 1 && (value + "").indexOf('0.') != 0) { 21 | value = value.substring(1); 22 | } 23 | var result = value; 24 | if (isNumber(this.precision)) { 25 | if (window.BigNumber) { 26 | // 已经引入BigNumber 27 | result = new BigNumber(value).toFixed(this.precision); 28 | } else { 29 | var digit = parseFloat(value); 30 | // 解决toFixed四舍五入问题,如1.345 31 | result = (Math.round(digit * Math.pow(10, this.precision)) / Math.pow(10, this.precision)).toFixed(this.precision); 32 | } 33 | if (result == "NaN") return ""; 34 | } 35 | 36 | return result; 37 | }; 38 | 39 | function DateFormater(pattern) { 40 | this.pattern = pattern; 41 | }; 42 | 43 | DateFormater.prototype.update = function (pattern) { 44 | this.pattern = pattern; 45 | }; 46 | 47 | DateFormater.prototype.format = function (value) { 48 | return moment(value).format(this.pattern); 49 | }; 50 | 51 | //var NumberFormater = NumberFormater; 52 | //var DateFormater = DateFormater; 53 | export { NumberFormater, DateFormater }; -------------------------------------------------------------------------------- /src/util/formater.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow data formater tools 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 15:39:01 5 | */ 6 | import {isNumber} from '../util'; 7 | 8 | 9 | function NumberFormater(precision) { 10 | this.precision = precision; 11 | }; 12 | 13 | NumberFormater.prototype.update = function (precision) { 14 | this.precision = precision; 15 | } 16 | 17 | NumberFormater.prototype.format = function (value) { 18 | if (!isNumber(value)) return ""; 19 | 20 | // 以0开头的数字将其前面的0去掉 21 | while ((value + "").charAt(0) == "0" && value.length > 1 && (value + "").indexOf('0.') != 0) { 22 | value = value.substring(1); 23 | } 24 | var result = value; 25 | if (isNumber(this.precision)) { 26 | if (window.BigNumber) { 27 | // 已经引入BigNumber 28 | result = (new BigNumber(value)).toFixed(this.precision) 29 | } else { 30 | var digit = parseFloat(value); 31 | // 解决toFixed四舍五入问题,如1.345 32 | result = (Math.round(digit * Math.pow(10, this.precision)) / Math.pow(10, this.precision)).toFixed(this.precision); 33 | } 34 | if (result == "NaN") 35 | return ""; 36 | } 37 | 38 | 39 | return result; 40 | }; 41 | 42 | function DateFormater(pattern) { 43 | this.pattern = pattern; 44 | }; 45 | 46 | DateFormater.prototype.update = function (pattern) { 47 | this.pattern = pattern; 48 | } 49 | 50 | 51 | DateFormater.prototype.format = function (value) { 52 | return moment(value).format(this.pattern) 53 | }; 54 | 55 | //var NumberFormater = NumberFormater; 56 | //var DateFormater = DateFormater; 57 | export {NumberFormater,DateFormater}; 58 | -------------------------------------------------------------------------------- /snippets/style.md: -------------------------------------------------------------------------------- 1 | 2 | ## 样式 3 | 4 | ### addClass(element,value) 5 | * 说明: 6 | 7 | 为HTML元素添加样式 8 | 9 | * 参数: 10 | * {HTMLElement} element:必需。需要添加样式的HTML元素。 11 | * {String} value:必需。添加的样式名。 12 | * 返回值: 13 | 14 | 无 15 | * 用法: 16 | ​ 17 | u.addClass(document.getElementById('id1'), 'add-class'); 18 | 19 | ### removeClass(element,value) 20 | * 说明: 21 | 22 | 为HTML元素删除样式 23 | 24 | * 参数: 25 | * {HTMLElement} element:必需。需要删除样式的HTML元素。 26 | * {String} value:必需。删除的样式名。 27 | * 返回值: 28 | 29 | 无 30 | * 用法: 31 | ​ 32 | u.removeClass(document.getElementById('id1'), 'add-class'); 33 | 34 | ### hasClass(element,value) 35 | * 说明: 36 | 37 | 判断HTML元素是否存在某样式 38 | 39 | * 参数: 40 | * {HTMLElement} element:必需。进行判断的HTML元素。 41 | * {String} value:必需。进行判断的样式名。 42 | * 返回值: 43 | 44 | {Boolean}存在样式则返回true,不存在样式则返回false 45 | * 用法: 46 | ​ 47 | u.hasClass(document.getElementById('id1'), 'add-class'); 48 | 49 | ### toggleClass(element,value) 50 | * 说明: 51 | 52 | 判断HTML元素是否存在某样式,存在则删除此样式,否则添加此样式 53 | 54 | * 参数: 55 | * {HTMLElement} element:必需。进行判断的HTML元素。 56 | * {String} value:必需。进行判断的样式名。 57 | * 返回值: 58 | 59 | {Boolean}执行完方法之后,如果存在样式则返回true,不存在样式则返回false 60 | * 用法: 61 | ​ 62 | u.toggleClass(document.getElementById('id1'), 'add-class'); 63 | 64 | ### css(element,csstext,val) 65 | * 说明: 66 | 67 | 为HTML元素添加css样式属性。传入2个参数且第二个参数为字符串时获取HTML元素的css样式属性。 68 | 69 | * 参数: 70 | * {HTMLElement} element:必需。进行判断的HTML元素。 71 | * {String}/{Object} csstext:必需。传入值为String时表示要添加的css属性名称,传入值为Object时表示要添加的css属性名称及属性值组成的Object对象。 72 | * {String} value:csstext为String时必需。需要添加的css属性值。 73 | * 返回值: 74 | 75 | 设置css样式属性时返回值为空。 76 | 77 | 获取css样式属性时返回值为对应的css样式属性值。 78 | * 用法: 79 | ​ 80 | u.css(document.getElementById('id1'), 'width','200px'); //设置宽度为200px 81 | u.css(document.getElementById('id1'), {width:'500px'}); // 设置宽度为500px 82 | u.css(document.getElementById('id1'), 'width'); // 获取宽度 83 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## CONTRIBUTING.md 2 | 3 | 感谢所有社区贡献者,为助力完善`Tinper`全系列产品,本篇针对*bug反馈* & *pull request流程*作出说明 4 | 5 | * [Bug反馈](#bug) 6 | 7 | * [Pull Request流程图示](#pull) 8 | 9 | 10 |

Bug反馈

11 | 12 | 1.提交途径 13 | 14 | * 推荐使用issue, 15 | 16 | > 简单,拖拽即可上传截图,方便反馈存档,利于帮助其他存在问题的人,避免重复问题 17 | 18 | 2.提交内容 19 | 20 | 针对存在问题反馈不够明确,建议提交包含以下内容,目前提供了一个[在线模板可供参考](https://github.com/iuap-design/neoui/issues/new?title=Bug:%20&body=**%E9%97%AE%E9%A2%98%E6%8F%8F%E8%BF%B0**%0A%EF%BC%88%E6%8F%8F%E8%BF%B0%E4%B8%80%E4%B8%8B%E9%97%AE%E9%A2%98%EF%BC%89%0A%0A**%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83**%20%0A-%20%E6%B5%8F%E8%A7%88%E5%99%A8%E5%8F%8A%E7%89%88%E6%9C%AC%EF%BC%9A%20%0A-%20%E6%BC%94%E7%A4%BA%E5%9C%B0%E5%9D%80:%20%0A-%20%E6%B5%8F%E8%A7%88%E5%99%A8%E6%8A%A5%E9%94%99:%20%0A-%20%E6%88%AA%E5%9B%BE:),个人填写建议包含以下内容: 21 | 22 | ``` 23 | **问题描述** 24 | (描述一下问题) 25 | 26 | **生产环境** 27 | - 浏览器及版本: 28 | - 演示地址: 29 | - 浏览器报错: 30 | - 截图: 31 | ``` 32 | 33 |

Pull Request流程图示

34 | 35 | 以 [neoui](https://github.com/iuap-design/neoui) 仓库为例: 36 | 37 | 1. Fork仓库到个人Respository目录:进入仓库,点击`Fork` 38 | 39 | ![Fork](https://cloud.githubusercontent.com/assets/11772494/18979569/bf247980-86fe-11e6-9b56-6411f5a55a0e.png) 40 | 41 | 2. Clone到本地 42 | 43 | ``` 44 | $ git clone git@github.com:onvno/neoui.git 45 | ``` 46 | 47 | 3. 创建分支 48 | 49 | ``` 50 | $ git checkout -b fixer 51 | ``` 52 | 53 | 4. 修改后提交 54 | 55 | ``` 56 | $ git add . 57 | $ git commit -m "fix:some bug" 58 | $ git push origin fixer 59 | ``` 60 | 61 | 5. 提交`pull request`:登陆github,进入`fork`后的仓库,切换到新提交的`fixer`分支,点击右侧绿色按钮`Compare& pull request` 62 | 63 | ![pull](https://cloud.githubusercontent.com/assets/11772494/18979575/cde1bcf8-86fe-11e6-8ee2-51b7a1deb62b.png) 64 | 65 | 6. 添加注释信息,确认提交 66 | 67 | ![commit](https://cloud.githubusercontent.com/assets/11772494/18979581/d5e35fd8-86fe-11e6-9aae-d36c8f077ac8.png) 68 | ​ -------------------------------------------------------------------------------- /docs/style.md: -------------------------------------------------------------------------------- 1 | 2 | # 样式 3 | 4 | ## # addClass(element,value) 5 | * 说明: 6 | 7 | 为HTML元素添加样式 8 | 9 | * 参数: 10 | * {HTMLElement} element:必需。需要添加样式的HTML元素。 11 | * {String} value:必需。添加的样式名。 12 | * 返回值: 13 | 14 | 无 15 | * 用法: 16 | ​ 17 | u.addClass(document.getElementById('id1'), 'add-class'); 18 | 19 | ## # removeClass(element,value) 20 | * 说明: 21 | 22 | 为HTML元素删除样式 23 | 24 | * 参数: 25 | * {HTMLElement} element:必需。需要删除样式的HTML元素。 26 | * {String} value:必需。删除的样式名。 27 | * 返回值: 28 | 29 | 无 30 | * 用法: 31 | ​ 32 | u.removeClass(document.getElementById('id1'), 'add-class'); 33 | 34 | ## # hasClass(element,value) 35 | * 说明: 36 | 37 | 判断HTML元素是否存在某样式 38 | 39 | * 参数: 40 | * {HTMLElement} element:必需。进行判断的HTML元素。 41 | * {String} value:必需。进行判断的样式名。 42 | * 返回值: 43 | 44 | {Boolean}存在样式则返回true,不存在样式则返回false 45 | * 用法: 46 | ​ 47 | u.hasClass(document.getElementById('id1'), 'add-class'); 48 | 49 | ## # toggleClass(element,value) 50 | * 说明: 51 | 52 | 判断HTML元素是否存在某样式,存在则删除此样式,否则添加此样式 53 | 54 | * 参数: 55 | * {HTMLElement} element:必需。进行判断的HTML元素。 56 | * {String} value:必需。进行判断的样式名。 57 | * 返回值: 58 | 59 | {Boolean}执行完方法之后,如果存在样式则返回true,不存在样式则返回false 60 | * 用法: 61 | ​ 62 | u.toggleClass(document.getElementById('id1'), 'add-class'); 63 | 64 | ## # css(element,csstext,val) 65 | * 说明: 66 | 67 | 为HTML元素添加css样式属性。传入2个参数且第二个参数为字符串时获取HTML元素的css样式属性。 68 | 69 | * 参数: 70 | * {HTMLElement} element:必需。进行判断的HTML元素。 71 | * {String}/{Object} csstext:必需。传入值为String时表示要添加的css属性名称,传入值为Object时表示要添加的css属性名称及属性值组成的Object对象。 72 | * {String} value:csstext为String时必需。需要添加的css属性值。 73 | * 返回值: 74 | 75 | 设置css样式属性时返回值为空。 76 | 77 | 获取css样式属性时返回值为对应的css样式属性值。 78 | * 用法: 79 | ​ 80 | u.css(document.getElementById('id1'), 'width','200px'); //设置宽度为200px 81 | u.css(document.getElementById('id1'), {width:'500px'}); // 设置宽度为500px 82 | u.css(document.getElementById('id1'), 'width'); // 获取宽度 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /lib/util/i18n.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow i18n 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-29 10:16:54 5 | */ 6 | //import {uuii18n} from '?';//缺失故修改为default值 7 | import { getCookie, setCookie } from '../cookies'; 8 | import { U_LOCALE } from '../enumerables'; 9 | 10 | // 从datatable/src/compatiable/u/JsExtension.js抽取 11 | window.getCurrentJsPath = function () { 12 | var doc = document, 13 | a = {}, 14 | expose = +new Date(), 15 | rExtractUri = /((?:http|https|file):\/\/.*?\/[^:]+)(?::\d+)?:\d+/, 16 | isLtIE8 = ('' + doc.querySelector).indexOf('[native code]') === -1; 17 | // FF,Chrome 18 | if (doc.currentScript) { 19 | return doc.currentScript.src; 20 | } 21 | 22 | var stack; 23 | try { 24 | a.b(); 25 | } catch (e) { 26 | stack = e.stack || e.fileName || e.sourceURL || e.stacktrace; 27 | } 28 | // IE10 29 | if (stack) { 30 | var absPath = rExtractUri.exec(stack)[1]; 31 | if (absPath) { 32 | return absPath; 33 | } 34 | } 35 | 36 | // IE5-9 37 | for (var scripts = doc.scripts, i = scripts.length - 1, script; script = scripts[i--];) { 38 | if (script.className !== expose && script.readyState === 'interactive') { 39 | script.className = expose; 40 | // if less than ie 8, must get abs path by getAttribute(src, 4) 41 | return isLtIE8 ? script.getAttribute('src', 4) : script.src; 42 | } 43 | } 44 | }; 45 | 46 | if (window.i18n) { 47 | window.u = window.u || {}; 48 | var scriptPath = getCurrentJsPath(), 49 | _temp = scriptPath.substr(0, scriptPath.lastIndexOf('/')), 50 | __FOLDER__ = _temp.substr(0, _temp.lastIndexOf('/')), 51 | resGetPath = u.i18nPath || __FOLDER__ + '/locales/__lng__/__ns__.json'; 52 | i18n.init({ 53 | postAsync: false, 54 | getAsync: false, 55 | fallbackLng: false, 56 | ns: { namespaces: ['uui-trans'] }, 57 | lng: getCookie(U_LOCALE) || 'zh', 58 | resGetPath: resGetPath 59 | }); 60 | } 61 | 62 | var trans = function trans(key, dftValue) { 63 | return window.i18n ? i18n.t('uui-trans:' + key) : dftValue; 64 | }; 65 | 66 | export { trans }; -------------------------------------------------------------------------------- /src/util/i18n.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow i18n 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-29 10:16:54 5 | */ 6 | //import {uuii18n} from '?';//缺失故修改为default值 7 | import {getCookie,setCookie} from '../cookies'; 8 | import {U_LOCALE} from '../enumerables' 9 | 10 | // 从datatable/src/compatiable/u/JsExtension.js抽取 11 | window.getCurrentJsPath = function() { 12 | var doc = document, 13 | a = {}, 14 | expose = +new Date(), 15 | rExtractUri = /((?:http|https|file):\/\/.*?\/[^:]+)(?::\d+)?:\d+/, 16 | isLtIE8 = ('' + doc.querySelector).indexOf('[native code]') === -1; 17 | // FF,Chrome 18 | if (doc.currentScript){ 19 | return doc.currentScript.src; 20 | } 21 | 22 | var stack; 23 | try{ 24 | a.b(); 25 | } 26 | catch(e){ 27 | stack = e.stack || e.fileName || e.sourceURL || e.stacktrace; 28 | } 29 | // IE10 30 | if (stack){ 31 | var absPath = rExtractUri.exec(stack)[1]; 32 | if (absPath){ 33 | return absPath; 34 | } 35 | } 36 | 37 | // IE5-9 38 | for(var scripts = doc.scripts, 39 | i = scripts.length - 1, 40 | script; script = scripts[i--];){ 41 | if (script.className !== expose && script.readyState === 'interactive'){ 42 | script.className = expose; 43 | // if less than ie 8, must get abs path by getAttribute(src, 4) 44 | return isLtIE8 ? script.getAttribute('src', 4) : script.src; 45 | } 46 | } 47 | } 48 | 49 | if (window.i18n) { 50 | window.u = window.u || {}; 51 | var scriptPath = getCurrentJsPath(), 52 | _temp = scriptPath.substr(0, scriptPath.lastIndexOf('/')), 53 | __FOLDER__ = _temp.substr(0, _temp.lastIndexOf('/')), 54 | resGetPath = u.i18nPath || __FOLDER__ + '/locales/__lng__/__ns__.json'; 55 | i18n.init({ 56 | postAsync: false, 57 | getAsync: false, 58 | fallbackLng: false, 59 | ns: {namespaces: ['uui-trans']}, 60 | lng:getCookie(U_LOCALE) || 'zh', 61 | resGetPath: resGetPath 62 | }) 63 | } 64 | 65 | var trans = function (key, dftValue) { 66 | return window.i18n ? i18n.t('uui-trans:' + key) : dftValue 67 | } 68 | 69 | export {trans}; 70 | -------------------------------------------------------------------------------- /src/locales/zh-CN/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear":"清空", 4 | "confirm": "确定", 5 | "cancel": "取消", 6 | "day": "日", 7 | "ok": "确定" 8 | }, 9 | "gridComp": { 10 | "show_column": "显示 隐藏列", 11 | "clear_set": "清除设置", 12 | "no_rows": "无数据", 13 | "sum": "合计:", 14 | "close":"关闭" 15 | }, 16 | "dialog": { 17 | "info_dialog": "提示窗口", 18 | "title":"提示", 19 | "okText":"确定", 20 | "cancelText":"取消" 21 | }, 22 | "validate": { 23 | "required": "不能为空!", 24 | "integer": "请填写整数!", 25 | "float": "请填写数字!", 26 | "zipCode": "请填写邮政编码!", 27 | "phone": "请填写手机号码!", 28 | "email": "请填写邮箱地址!", 29 | "url": "请填写网址!", 30 | "error_zipCode": "邮政编码格式不对!", 31 | "error_phone": "手机号码格式不对!", 32 | "error_email": "邮箱地址格式不对!", 33 | "error_url": "网址格式不对!", 34 | "input_minlength": "输入长度不能小于 ", 35 | "input_maxlength": "输入长度不能大于 ", 36 | "input_unit": " 位", 37 | "input_maxvalue": "输入值不能大于", 38 | "input_minvalue": "输入值不能小于", 39 | "input_equalMax": "输入值不能大于或等于", 40 | "input_equalMin": "输入值不能小于或等于", 41 | "landline": "请填写座机号码!", 42 | "datetime":"请填写日期!", 43 | "phoneNumber":"请填写正确号码!", 44 | "error_integer":"整数格式不对!", 45 | "error_float":"数字格式不对!", 46 | "error_landline":"座机号码格式不对!", 47 | "error_datetime":"日期格式不对!", 48 | "error_phoneNumber":"号码格式不对!" 49 | }, 50 | "date":{ 51 | "months": ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"], 52 | "monthsShort": ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"], 53 | "weekdays": ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"], 54 | "weekdaysShort": ["周日","周一","周二","周三","周四","周五","周六"], 55 | "weekdaysMin": ["日","一","二","三","四","五","六"] 56 | }, 57 | "pagination":{ 58 | "totalText":"共", 59 | "listText": "条", 60 | "pageText":"页", 61 | "showText":"显示", 62 | "toText":"到" 63 | }, 64 | "dataTable":{ 65 | "Y":"是", 66 | "N":"否" 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/locales/zh-TW/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear":"清空", 4 | "confirm": "確定", 5 | "cancel": "取消", 6 | "day": "日", 7 | "ok": "確定" 8 | }, 9 | "gridComp": { 10 | "show_column": "顯示 隱藏列", 11 | "clear_set": "清除設置", 12 | "no_rows": "無數據", 13 | "sum": "合計:", 14 | "close":"關閉" 15 | }, 16 | "dialog": { 17 | "info_dialog": "提示窗口", 18 | "title":"提示", 19 | "okText":"確定", 20 | "cancelText":"取消" 21 | }, 22 | "validate": { 23 | "required": "不能為空!", 24 | "integer": "請填寫整數!", 25 | "float": "請填寫數字!", 26 | "zipCode": "請填寫郵政編碼!", 27 | "phone": "請填寫手機號碼!", 28 | "email": "請填寫郵箱地址!", 29 | "url": "請填寫網址!", 30 | "error_zipCode": "郵政編碼格式不對!", 31 | "error_phone": "手機號碼格式不對!", 32 | "error_email": "郵箱地址格式不對!", 33 | "error_url": "網址格式不對!", 34 | "input_minlength": "輸入長度不能小於 ", 35 | "input_maxlength": "輸入長度不能大於 ", 36 | "input_unit": " 位", 37 | "input_maxvalue": "輸入值不能大於", 38 | "input_minvalue": "輸入值不能小於", 39 | "input_equalMax": "輸入值不能大於或等於", 40 | "input_equalMin": "輸入值不能小於或等於", 41 | "landline": "請填寫座機號碼!", 42 | "datetime":"請填寫日期!", 43 | "phoneNumber":"請填寫正確號碼!", 44 | "error_integer":"整數格式不對!", 45 | "error_float":"數字格式不對!", 46 | "error_landline":"座機號碼格式不對!", 47 | "error_datetime":"日期格式不對!", 48 | "error_phoneNumber":"號碼格式不對!" 49 | }, 50 | "date":{ 51 | "months": ["壹月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十壹月","十二月"], 52 | "monthsShort": ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"], 53 | "weekdays": ["星期日","星期壹","星期二","星期三","星期四","星期五","星期六"], 54 | "weekdaysShort": ["周日","周壹","周二","周三","周四","周五","周六"], 55 | "weekdaysMin": ["日","壹","二","三","四","五","六"] 56 | }, 57 | "pagination":{ 58 | "totalText":"共", 59 | "listText": "條", 60 | "pageText":"頁", 61 | "showText":"顯示", 62 | "toText":"到" 63 | }, 64 | "dataTable":{ 65 | "Y":"是", 66 | "N":"否" 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/locales/zh/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear":"清空", 4 | "confirm": "确定", 5 | "cancel": "取消", 6 | "day": "日", 7 | "ok": "确定" 8 | }, 9 | "gridComp": { 10 | "show_column": "显示 隐藏列", 11 | "clear_set": "清除设置", 12 | "no_rows": "无数据", 13 | "sum": "合计:", 14 | "close":"关闭" 15 | }, 16 | "dialog": { 17 | "info_dialog": "提示窗口", 18 | "title":"提示", 19 | "okText":"确定", 20 | "cancelText":"取消" 21 | }, 22 | "validate": { 23 | "required": "不能为空!", 24 | "integer": "请填写整数!", 25 | "float": "请填写数字!", 26 | "zipCode": "请填写邮政编码!", 27 | "phone": "请填写手机号码!", 28 | "email": "请填写邮箱地址!", 29 | "url": "请填写网址!", 30 | "error_zipCode": "邮政编码格式不对!", 31 | "error_phone": "手机号码格式不对!", 32 | "error_email": "邮箱地址格式不对!", 33 | "error_url": "网址格式不对!", 34 | "input_minlength": "输入长度不能小于 ", 35 | "input_maxlength": "输入长度不能大于 ", 36 | "input_unit": " 位", 37 | "input_maxvalue": "输入值不能大于", 38 | "input_minvalue": "输入值不能小于", 39 | "input_equalMax": "输入值不能大于或等于", 40 | "input_equalMin": "输入值不能小于或等于", 41 | "landline": "请填写座机号码!", 42 | "datetime":"请填写日期!", 43 | "phoneNumber":"请填写正确号码!", 44 | "error_integer":"整数格式不对!", 45 | "error_float":"数字格式不对!", 46 | "error_landline":"座机号码格式不对!", 47 | "error_datetime":"日期格式不对!", 48 | "error_phoneNumber":"号码格式不对!" 49 | }, 50 | "date":{ 51 | "months": ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"], 52 | "monthsShort": ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"], 53 | "weekdays": ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"], 54 | "weekdaysShort": ["周日","周一","周二","周三","周四","周五","周六"], 55 | "weekdaysMin": ["日","一","二","三","四","五","六"] 56 | }, 57 | "pagination":{ 58 | "totalText":"共", 59 | "listText": "条", 60 | "pageText":"页", 61 | "showText":"显示", 62 | "toText":"到" 63 | }, 64 | "dataTable":{ 65 | "Y":"是", 66 | "N":"否" 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/locales/zh_CN/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear":"清空", 4 | "confirm": "确定", 5 | "cancel": "取消", 6 | "day": "日", 7 | "ok": "确定" 8 | }, 9 | "gridComp": { 10 | "show_column": "显示 隐藏列", 11 | "clear_set": "清除设置", 12 | "no_rows": "无数据", 13 | "sum": "合计:", 14 | "close":"关闭" 15 | }, 16 | "dialog": { 17 | "info_dialog": "提示窗口", 18 | "title":"提示", 19 | "okText":"确定", 20 | "cancelText":"取消" 21 | }, 22 | "validate": { 23 | "required": "不能为空!", 24 | "integer": "请填写整数!", 25 | "float": "请填写数字!", 26 | "zipCode": "请填写邮政编码!", 27 | "phone": "请填写手机号码!", 28 | "email": "请填写邮箱地址!", 29 | "url": "请填写网址!", 30 | "error_zipCode": "邮政编码格式不对!", 31 | "error_phone": "手机号码格式不对!", 32 | "error_email": "邮箱地址格式不对!", 33 | "error_url": "网址格式不对!", 34 | "input_minlength": "输入长度不能小于 ", 35 | "input_maxlength": "输入长度不能大于 ", 36 | "input_unit": " 位", 37 | "input_maxvalue": "输入值不能大于", 38 | "input_minvalue": "输入值不能小于", 39 | "input_equalMax": "输入值不能大于或等于", 40 | "input_equalMin": "输入值不能小于或等于", 41 | "landline": "请填写座机号码!", 42 | "datetime":"请填写日期!", 43 | "phoneNumber":"请填写正确号码!", 44 | "error_integer":"整数格式不对!", 45 | "error_float":"数字格式不对!", 46 | "error_landline":"座机号码格式不对!", 47 | "error_datetime":"日期格式不对!", 48 | "error_phoneNumber":"号码格式不对!" 49 | }, 50 | "date":{ 51 | "months": ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"], 52 | "monthsShort": ["1月","2月","3月","4月","5月","6月","7月","8月","9月","10月","11月","12月"], 53 | "weekdays": ["星期日","星期一","星期二","星期三","星期四","星期五","星期六"], 54 | "weekdaysShort": ["周日","周一","周二","周三","周四","周五","周六"], 55 | "weekdaysMin": ["日","一","二","三","四","五","六"] 56 | }, 57 | "pagination":{ 58 | "totalText":"共", 59 | "listText": "条", 60 | "pageText":"页", 61 | "showText":"显示", 62 | "toText":"到" 63 | }, 64 | "dataTable":{ 65 | "Y":"是", 66 | "N":"否" 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # tinper sparrow 2 | 3 | 4 | [![npm version](https://img.shields.io/npm/v/tinper-sparrow.svg)](https://www.npmjs.com/package/tinper-sparrow) 5 | [![Build Status](https://img.shields.io/travis/iuap-design/tinper-sparrow/master.svg)](https://travis-ci.org/iuap-design/tinper-sparrow) 6 | [![devDependency Status](https://img.shields.io/david/dev/iuap-design/tinper-sparrow.svg)](https://david-dm.org/iuap-design/tinper-sparrow#info=devDependencies) 7 | [![NPM downloads](http://img.shields.io/npm/dm/tinper-sparrow.svg?style=flat)](https://npmjs.org/package/tinper-sparrow) 8 | 9 | 10 | [English Document](./README.md) 11 | ## 介绍 12 | `sparrow.js`是一个短小精悍的前端基础库,它包含对DOM、CSS基本操作、多平台浏览器移动设备判断、Cookies操作、事件的绑定、日期、数字、字符串相关判断、以及浏览器自身函数不足所扩展的一系列功能. 13 | 14 | ## 快速上手 15 | 16 | ### 获取sparrow 17 | 18 | * npm 资源 19 | ``` 20 | npm install tinper-sparrow 21 | ``` 22 | 23 | * cdn 资源 24 | ``` 25 | //design.yonyoucloud.com/static/tinper-sparrow/latest/tinper-sparrow.js 26 | ``` 27 | ### 引入sparrow 28 | - ES6语法 29 | ``` 30 | import { sparrow} from "tinper-sparrow" 31 | 32 | ``` 33 | * HTML直接引入 34 | 35 | ``` 36 | 37 | 38 | ``` 39 | **注**: sparrow依赖于jquery,引入资源时需先引入jquery 40 | 41 | ### 具体使用 42 | ``` 43 | sparrow.isIE //IE浏览器返回true,其他返回false 44 | 45 | sparrow.isDate(new Date()); //传入对象为Date对象返回true否则返回false 46 | 47 | ``` 48 | 开发文档详见[这里](http://tinper.org/dist/sparrow/index.html) 49 | 50 | ## 如何参与贡献 51 | 52 | ### 开发及构建 53 | 54 | 开发者可以一起参与为 sparrow贡献代码,同时也可以基于 sparrow进行二次开发或封装插件。 55 | 56 | 克隆项目文件: 57 | 58 | ``` 59 | $ git clone git@github.com:iuap-design/tinper-sparrow.git 60 | ``` 61 | 62 | 然后进入目录安装依赖: 63 | 64 | ``` 65 | $ npm install 66 | ``` 67 | 68 | 接下来,编译: 69 | 70 | ``` 71 | $ npm run product 72 | ``` 73 | 74 | ### 反馈 75 | 如在使用过程中遇到任何问题,可以在[这里](https://github.com/iuap-design/tinper-sparrow/issues)提交issue反馈; 76 | 77 | 或者直接fork代码到你的github仓库,提交pull request给我们。 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tinper sparrow 2 | 3 | 4 | [![npm version](https://img.shields.io/npm/v/tinper-sparrow.svg)](https://www.npmjs.com/package/tinper-sparrow) 5 | [![Build Status](https://img.shields.io/travis/iuap-design/tinper-sparrow/master.svg)](https://travis-ci.org/iuap-design/tinper-sparrow) 6 | [![devDependency Status](https://img.shields.io/david/dev/iuap-design/tinper-sparrow.svg)](https://david-dm.org/iuap-design/tinper-sparrow#info=devDependencies) 7 | [![NPM downloads](http://img.shields.io/npm/dm/tinper-sparrow.svg?style=flat)](https://npmjs.org/package/tinper-sparrow) 8 | 9 | [中文文档](./README_CN.md) 10 | ## Introduction 11 | `sparrow.js` is a front-end base library, which contains the basic operation of DOM, browser and device judgments, Cookies operations, as well as the browser's own function expansion, etc.. 12 | 13 | ## Quickstart 14 | 15 | ### Get sparrow 16 | 17 | * npm 18 | ``` 19 | npm install tinper-sparrow 20 | ``` 21 | 22 | * cdn 23 | ``` 24 | //design.yonyoucloud.com/static/tinper-sparrow/latest/tinper-sparrow.js 25 | ``` 26 | ### Introducing sparrow 27 | - ES6 28 | ``` 29 | import { sparrow} from "tinper-sparrow" 30 | 31 | ``` 32 | * HTML 33 | 34 | ``` 35 | 36 | 37 | ``` 38 | **Note**: sparrow is dependent on jQuery 39 | 40 | ### Use 41 | ``` 42 | sparrow.isIE //IE browser returns true, others return to false 43 | 44 | sparrow.isDate(new Date()); //Date Object returns true, others return to false 45 | 46 | ``` 47 | Read the [Develop documentation](http://tinper.org/dist/sparrow/index.html) 48 | 49 | ## Contributing 50 | 51 | ### Develop 52 | 53 | Developers can participate in the development of sparrow, but also can be based on sparrow two development 54 | 55 | clone: 56 | 57 | ``` 58 | $ git clone git@github.com:iuap-design/tinper-sparrow.git 59 | ``` 60 | 61 | install: 62 | 63 | ``` 64 | $ npm install 65 | ``` 66 | 67 | build: 68 | 69 | ``` 70 | $ npm run product 71 | ``` 72 | 73 | ### Feedback 74 | 75 | If you encounter any problems , submit [issues]((https://github.com/iuap-design/tinper-sparrow/issues),or pull request。 76 | -------------------------------------------------------------------------------- /snippets/device.md: -------------------------------------------------------------------------------- 1 | ## 终端API 2 | 3 | ### isIE 4 | 5 | * 说明: 6 | 7 | 判断是否为IE浏览器 8 | 9 | * 类型: 10 | 11 | Boolean 12 | 13 | * 用法: 14 | 15 | ``` 16 | u.isIE //IE浏览器返回true,其他返回false 17 | 18 | ``` 19 | 20 | ### isFF 21 | 22 | * 说明: 23 | 24 | 判断是否为火狐浏览器 25 | * 类型: 26 | 27 | Boolean 28 | 29 | ### isOpera 30 | 31 | * 说明: 32 | 33 | 判断是否为Opera浏览器 34 | * 类型: 35 | 36 | Boolean 37 | 38 | ### isChrome 39 | 40 | * 说明: 41 | 42 | 判断是否为Chrome浏览器 43 | * 类型: 44 | 45 | Boolean 46 | 47 | ### isSafari 48 | 49 | * 说明: 50 | 51 | 判断是否为Safari浏览器 52 | * 类型: 53 | 54 | Boolean 55 | 56 | ### isWebkit 57 | 58 | * 说明: 59 | 60 | 判断是否为Webkit内核浏览器 61 | * 类型: 62 | 63 | Boolean 64 | 65 | ### isIE8_BEFORE 66 | 67 | * 说明: 68 | 69 | 判断是否为IE8之前的浏览器 70 | * 类型: 71 | 72 | Boolean 73 | 74 | ### isIE8 75 | 76 | * 说明: 77 | 78 | 判断是否为IE8浏览器 79 | * 类型: 80 | 81 | Boolean 82 | 83 | ### isIE8_CORE 84 | 85 | * 说明: 86 | 87 | 判断是否为IE8内核浏览器 88 | * 类型: 89 | 90 | Boolean 91 | 92 | ### isIE9 93 | 94 | * 说明: 95 | 96 | 判断是否为IE9浏览器 97 | * 类型: 98 | 99 | Boolean 100 | 101 | ### isIE9_CORE 102 | 103 | * 说明: 104 | 105 | 判断是否为IE9内核浏览器 106 | * 类型: 107 | 108 | Boolean 109 | 110 | ### isIE10 111 | 112 | * 说明: 113 | 114 | 判断是否为IE10浏览器 115 | * 类型: 116 | 117 | Boolean 118 | 119 | ### isIE11 120 | 121 | * 说明: 122 | 123 | 判断是否为IE11浏览器 124 | * 类型: 125 | 126 | Boolean 127 | 128 | ### isIOS 129 | 130 | * 说明: 131 | 132 | 判断是否为IOS系统 133 | * 类型: 134 | 135 | Boolean 136 | 137 | ### isIphone 138 | 139 | * 说明: 140 | 141 | 判断是否为iphone浏览器 142 | * 类型: 143 | 144 | Boolean 145 | 146 | ### isIPAD 147 | 148 | * 说明: 149 | 150 | 判断是否为ipad浏览器 151 | * 类型: 152 | 153 | Boolean 154 | 155 | ### isWin 156 | 157 | * 说明: 158 | 159 | 判断是否为window系统 160 | * 类型: 161 | 162 | Boolean 163 | 164 | ### isUnix 165 | 166 | * 说明: 167 | 168 | 判断是否为unix系统 169 | * 类型: 170 | 171 | Boolean 172 | 173 | ### isLinux 174 | 175 | * 说明: 176 | 177 | 判断是否为linux系统 178 | * 类型: 179 | 180 | Boolean 181 | 182 | ### isAndroid 183 | 184 | * 说明: 185 | 186 | 判断是否为安卓系统 187 | * 类型: 188 | 189 | Boolean 190 | 191 | ### isMac 192 | 193 | * 说明: 194 | 195 | 判断是否为MAC 196 | * 类型: 197 | 198 | Boolean 199 | 200 | ### hasTouch 201 | 202 | * 说明: 203 | 204 | 判断是否存在touch事件 205 | * 类型: 206 | 207 | Boolean 208 | -------------------------------------------------------------------------------- /docs/device.md: -------------------------------------------------------------------------------- 1 | # 终端API 2 | 3 | ## # isIE 4 | 5 | * 说明: 6 | 7 | 判断是否为IE浏览器 8 | 9 | * 类型: 10 | 11 | Boolean 12 | 13 | * 用法: 14 | 15 | ``` 16 | u.isIE //IE浏览器返回true,其他返回false 17 | 18 | ``` 19 | 20 | ## # isFF 21 | 22 | * 说明: 23 | 24 | 判断是否为火狐浏览器 25 | * 类型: 26 | 27 | Boolean 28 | 29 | ## # isOpera 30 | 31 | * 说明: 32 | 33 | 判断是否为Opera浏览器 34 | * 类型: 35 | 36 | Boolean 37 | 38 | ## # isChrome 39 | 40 | * 说明: 41 | 42 | 判断是否为Chrome浏览器 43 | * 类型: 44 | 45 | Boolean 46 | 47 | ## # isSafari 48 | 49 | * 说明: 50 | 51 | 判断是否为Safari浏览器 52 | * 类型: 53 | 54 | Boolean 55 | 56 | ## # isWebkit 57 | 58 | * 说明: 59 | 60 | 判断是否为Webkit内核浏览器 61 | * 类型: 62 | 63 | Boolean 64 | 65 | ## # isIE8_BEFORE 66 | 67 | * 说明: 68 | 69 | 判断是否为IE8之前的浏览器 70 | * 类型: 71 | 72 | Boolean 73 | 74 | ## # isIE8 75 | 76 | * 说明: 77 | 78 | 判断是否为IE8浏览器 79 | * 类型: 80 | 81 | Boolean 82 | 83 | ## # isIE8_CORE 84 | 85 | * 说明: 86 | 87 | 判断是否为IE8内核浏览器 88 | * 类型: 89 | 90 | Boolean 91 | 92 | ## # isIE9 93 | 94 | * 说明: 95 | 96 | 判断是否为IE9浏览器 97 | * 类型: 98 | 99 | Boolean 100 | 101 | ## # isIE9_CORE 102 | 103 | * 说明: 104 | 105 | 判断是否为IE9内核浏览器 106 | * 类型: 107 | 108 | Boolean 109 | 110 | ## # isIE10 111 | 112 | * 说明: 113 | 114 | 判断是否为IE10浏览器 115 | * 类型: 116 | 117 | Boolean 118 | 119 | ## # isIE11 120 | 121 | * 说明: 122 | 123 | 判断是否为IE11浏览器 124 | * 类型: 125 | 126 | Boolean 127 | 128 | ## # isIOS 129 | 130 | * 说明: 131 | 132 | 判断是否为IOS系统 133 | * 类型: 134 | 135 | Boolean 136 | 137 | ## # isIphone 138 | 139 | * 说明: 140 | 141 | 判断是否为iphone浏览器 142 | * 类型: 143 | 144 | Boolean 145 | 146 | ## # isIPAD 147 | 148 | * 说明: 149 | 150 | 判断是否为ipad浏览器 151 | * 类型: 152 | 153 | Boolean 154 | 155 | ## # isWin 156 | 157 | * 说明: 158 | 159 | 判断是否为window系统 160 | * 类型: 161 | 162 | Boolean 163 | 164 | ## # isUnix 165 | 166 | * 说明: 167 | 168 | 判断是否为unix系统 169 | * 类型: 170 | 171 | Boolean 172 | 173 | ## # isLinux 174 | 175 | * 说明: 176 | 177 | 判断是否为linux系统 178 | * 类型: 179 | 180 | Boolean 181 | 182 | ## # isAndroid 183 | 184 | * 说明: 185 | 186 | 判断是否为安卓系统 187 | * 类型: 188 | 189 | Boolean 190 | 191 | ## # isMac 192 | 193 | * 说明: 194 | 195 | 判断是否为MAC 196 | * 类型: 197 | 198 | Boolean 199 | 200 | ## # hasTouch 201 | 202 | * 说明: 203 | 204 | 判断是否存在touch事件 205 | * 类型: 206 | 207 | Boolean 208 | 209 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tinper-sparrow", 3 | "version": "3.2.4", 4 | "description": "sparrow.js", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "r-watch": "rollup -c -w", 8 | "r-build": "rollup -c", 9 | "build": "webpack --colors --progress --env.mode=build", 10 | "dev": "webpack --progress --colors --env.mode=dev", 11 | "test": "mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js", 12 | "es": "babel src -d lib", 13 | "prod": "npm run es && npm run r-build", 14 | "product": "npm run es && npm run r-build", 15 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", 16 | "docs": "node bin/mdconcat.js" 17 | }, 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/iuap-design/tinper-sparrow.git" 21 | }, 22 | "keywords": [ 23 | "sparrow", 24 | "iuap", 25 | "design" 26 | ], 27 | "author": "Yonyou FED", 28 | "license": "ISC", 29 | "bugs": { 30 | "url": "https://github.com/iuap-design/tinper-sparrow/issues" 31 | }, 32 | "homepage": "https://github.com/iuap-design/tinper-sparrow#readme", 33 | "dependencies": { 34 | }, 35 | "devDependencies": { 36 | "babel-cli": "^6.11.4", 37 | "babel-core": "^6.11.4", 38 | "babel-eslint": "^6.1.2", 39 | "babel-polyfill": "^6.3.14", 40 | "babel-loader": "^6.2.0", 41 | "babel-preset-es2015": "^6.3.13", 42 | "babel-plugin-add-module-exports": "^0.2.1", 43 | "babel-plugin-transform-es2015-modules-commonjs": "^6.11.5", 44 | "babel-plugin-transform-es3-member-expression-literals": "^6.8.0", 45 | "babel-plugin-transform-es3-property-literals": "^6.8.0", 46 | "babel-preset-es2015-loose": "^8.0.0", 47 | "babel-preset-stage-0": "^6.5.0", 48 | "chai": "^3.5.0", 49 | "deepmerge": "^1.3.2", 50 | "eslint": "^3.1.1", 51 | "eslint-loader": "^1.4.1", 52 | "file": "^0.2.2", 53 | "fs-extra": "^2.0.0", 54 | "mocha": "^2.5.3", 55 | "webpack": "^2.2.1", 56 | "babel-plugin-external-helpers": "^6.22.0", 57 | "babel-preset-latest": "^6.24.1", 58 | "rollup": "^0.41.6", 59 | "rollup-plugin-babel": "^2.7.1", 60 | "rollup-plugin-license": "^0.3.0", 61 | "rollup-plugin-multi-entry": "^2.0.1", 62 | "rollup-plugin-multidest": "^1.0.0", 63 | "rollup-plugin-node-resolve": "^3.0.0", 64 | "rollup-plugin-uglify": "^1.0.2", 65 | "rollup-watch": "^3.2.2", 66 | "yargs": "^4.8.1" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/locales/en/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear": "Clear", 4 | "confirm": "Ok", 5 | "cancel": "Cancel", 6 | "day": "", 7 | "ok": "Ok" 8 | }, 9 | "gridComp": { 10 | "show_column": "show hide column", 11 | "clear_set": "clear set", 12 | "no_rows": "no data", 13 | "sum": "sum:", 14 | "close": "close" 15 | }, 16 | "dialog": { 17 | "info_dialog": "Info Dialog", 18 | "title":"Tips", 19 | "okText":"Confirm", 20 | "cancelText":"Cancel" 21 | }, 22 | "validate": { 23 | "required": "Required!", 24 | "integer": "please input an integer!", 25 | "float": "please input a number!", 26 | "zipCode": "please input zipcode!", 27 | "phone": "please input phone number!", 28 | "email": "please input email!", 29 | "url": "please input url!", 30 | "error_zipCode": "error zipcode!", 31 | "error_phone": "error phone number!", 32 | "error_email": "error email!", 33 | "error_url": "error url!", 34 | "input_minlength": "Input length can not be less than ", 35 | "input_maxlength": "Input length can not be greater than ", 36 | "input_unit": " characters", 37 | "input_maxvalue": "The input value can not be greater than ", 38 | "input_minvalue": "The input value can not be less than ", 39 | "input_equalMax": "The input value can not be greater than or equal to ", 40 | "input_equalMin": "The input value can not be less than or equal to ", 41 | "landline": "please input landline number!", 42 | "datetime":"please input datetime", 43 | "phoneNumber":"please input correct number", 44 | "error_integer":"error integer", 45 | "error_float":"error float", 46 | "error_landline":"error landline", 47 | "error_datetime":"error datetime", 48 | "error_phoneNumber":"error phoneNumber" 49 | 50 | }, 51 | "date":{ 52 | "months": ["January","February","March","April","May","June","July","August","September","October","November","December"], 53 | "monthsShort": ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], 54 | "weekdays": ["Sunday","Monday","Tuesday","Wednesday","Thurday","Friday","Saturday"], 55 | "weekdaysShort": ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], 56 | "weekdaysMin": ["S","M","T","W","T","F","S"] 57 | }, 58 | "pagination":{ 59 | "totalText":"Total ", 60 | "listText": "lists", 61 | "pageText":"Page", 62 | "showText":"Show ", 63 | "toText":"To " 64 | }, 65 | "dataTable":{ 66 | "Y":"Yes", 67 | "N":"No" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/locales/en-US/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear": "Clear", 4 | "confirm": "Ok", 5 | "cancel": "Cancel", 6 | "day": "", 7 | "ok": "Ok" 8 | }, 9 | "gridComp": { 10 | "show_column": "show hide column", 11 | "clear_set": "clear set", 12 | "no_rows": "no data", 13 | "sum": "sum:", 14 | "close": "close" 15 | }, 16 | "dialog": { 17 | "info_dialog": "Info Dialog", 18 | "title":"Tips", 19 | "okText":"Confirm", 20 | "cancelText":"Cancel" 21 | }, 22 | "validate": { 23 | "required": "Required!", 24 | "integer": "please input an integer!", 25 | "float": "please input a number!", 26 | "zipCode": "please input zipcode!", 27 | "phone": "please input phone number!", 28 | "email": "please input email!", 29 | "url": "please input url!", 30 | "error_zipCode": "error zipcode!", 31 | "error_phone": "error phone number!", 32 | "error_email": "error email!", 33 | "error_url": "error url!", 34 | "input_minlength": "Input length can not be less than ", 35 | "input_maxlength": "Input length can not be greater than ", 36 | "input_unit": " characters", 37 | "input_maxvalue": "The input value can not be greater than ", 38 | "input_minvalue": "The input value can not be less than ", 39 | "input_equalMax": "The input value can not be greater than or equal to ", 40 | "input_equalMin": "The input value can not be less than or equal to ", 41 | "landline": "please input landline number!", 42 | "datetime":"please input datetime", 43 | "phoneNumber":"please input correct number", 44 | "error_integer":"error integer", 45 | "error_float":"error float", 46 | "error_landline":"error landline", 47 | "error_datetime":"error datetime", 48 | "error_phoneNumber":"error phoneNumber" 49 | 50 | }, 51 | "date":{ 52 | "months": ["January","February","March","April","May","June","July","August","September","October","November","December"], 53 | "monthsShort": ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], 54 | "weekdays": ["Sunday","Monday","Tuesday","Wednesday","Thurday","Friday","Saturday"], 55 | "weekdaysShort": ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], 56 | "weekdaysMin": ["S","M","T","W","T","F","S"] 57 | }, 58 | "pagination":{ 59 | "totalText":"Total ", 60 | "listText": "lists", 61 | "pageText":"Page", 62 | "showText":"Show ", 63 | "toText":"To " 64 | }, 65 | "dataTable":{ 66 | "Y":"Yes", 67 | "N":"No" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/locales/en_US/uui-trans.json: -------------------------------------------------------------------------------- 1 | { 2 | "public":{ 3 | "clear": "Clear", 4 | "confirm": "Ok", 5 | "cancel": "Cancel", 6 | "day": "", 7 | "ok": "Ok" 8 | }, 9 | "gridComp": { 10 | "show_column": "show hide column", 11 | "clear_set": "clear set", 12 | "no_rows": "no data", 13 | "sum": "sum:", 14 | "close": "close" 15 | }, 16 | "dialog": { 17 | "info_dialog": "Info Dialog", 18 | "title":"Tips", 19 | "okText":"Confirm", 20 | "cancelText":"Cancel" 21 | }, 22 | "validate": { 23 | "required": "Required!", 24 | "integer": "please input an integer!", 25 | "float": "please input a number!", 26 | "zipCode": "please input zipcode!", 27 | "phone": "please input phone number!", 28 | "email": "please input email!", 29 | "url": "please input url!", 30 | "error_zipCode": "error zipcode!", 31 | "error_phone": "error phone number!", 32 | "error_email": "error email!", 33 | "error_url": "error url!", 34 | "input_minlength": "Input length can not be less than ", 35 | "input_maxlength": "Input length can not be greater than ", 36 | "input_unit": " characters", 37 | "input_maxvalue": "The input value can not be greater than ", 38 | "input_minvalue": "The input value can not be less than ", 39 | "input_equalMax": "The input value can not be greater than or equal to ", 40 | "input_equalMin": "The input value can not be less than or equal to ", 41 | "landline": "please input landline number!", 42 | "datetime":"please input datetime", 43 | "phoneNumber":"please input correct number", 44 | "error_integer":"error integer", 45 | "error_float":"error float", 46 | "error_landline":"error landline", 47 | "error_datetime":"error datetime", 48 | "error_phoneNumber":"error phoneNumber" 49 | 50 | }, 51 | "date":{ 52 | "months": ["January","February","March","April","May","June","July","August","September","October","November","December"], 53 | "monthsShort": ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"], 54 | "weekdays": ["Sunday","Monday","Tuesday","Wednesday","Thurday","Friday","Saturday"], 55 | "weekdaysShort": ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"], 56 | "weekdaysMin": ["S","M","T","W","T","F","S"] 57 | }, 58 | "pagination":{ 59 | "totalText":"Total ", 60 | "listText": "lists", 61 | "pageText":"Page", 62 | "showText":"Show ", 63 | "toText":"To " 64 | } , 65 | "dataTable":{ 66 | "Y":"Yes", 67 | "N":"No" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/util/dataRender.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow data display formater 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 15:39:01 5 | */ 6 | import { core } from '../core'; 7 | import { NumberFormater } from './formater'; 8 | import { AddressMasker, NumberMasker, CurrencyMasker, PercentMasker, PhoneNumberMasker } from './masker'; 9 | import { date } from './dateUtils'; 10 | 11 | var floatRender = function floatRender(value, precision) { 12 | var trueValue = value; 13 | if (typeof value === 'undefined' || value === null) return value; 14 | //value 为 ko对象 15 | if (typeof value === 'function') trueValue = value(); 16 | var maskerMeta = core.getMaskerMeta('float') || {}; 17 | if (typeof precision === 'number') maskerMeta.precision = precision; 18 | var formater = new NumberFormater(maskerMeta.precision); 19 | var masker = new NumberMasker(maskerMeta); 20 | return masker.format(formater.format(trueValue)).value; 21 | }; 22 | 23 | var integerRender = function integerRender(value) { 24 | var trueValue = value; 25 | if (typeof value === 'undefined' || value === null) return value; 26 | //value 为 ko对象 27 | if (typeof value === 'function') trueValue = value(); 28 | return trueValue; 29 | }; 30 | 31 | var _dateRender = function _dateRender(value, format, type) { 32 | var trueValue = value; 33 | if (typeof value === 'undefined' || value === null) return value; 34 | //value 为 ko对象 35 | if (typeof value === 'function') trueValue = value(); 36 | var maskerMeta = core.getMaskerMeta(type) || {}; 37 | if (typeof format != 'undefined') maskerMeta.format = format; 38 | var maskerValue = date.format(trueValue, maskerMeta.format); 39 | return maskerValue; 40 | }; 41 | 42 | var dateRender = function dateRender(value, format) { 43 | return _dateRender(value, format, 'date'); 44 | }; 45 | 46 | var dateTimeRender = function dateTimeRender(value, format) { 47 | return _dateRender(value, format, 'datetime'); 48 | }; 49 | 50 | var timeRender = function timeRender(value, format) { 51 | return _dateRender(value, format, 'time'); 52 | }; 53 | 54 | var percentRender = function percentRender(value) { 55 | var trueValue = value; 56 | if (typeof value === 'undefined' || value === null) return value; 57 | //value 为 ko对象 58 | if (typeof value === 'function') trueValue = value(); 59 | var maskerMeta = core.getMaskerMeta('percent') || {}; 60 | var masker = new PercentMasker(maskerMeta); 61 | var maskerValue = masker.format(trueValue); 62 | return maskerValue && maskerValue.value ? maskerValue.value : ''; 63 | }; 64 | 65 | var phoneNumberRender = function phoneNumberRender() { 66 | var trueValue = value; 67 | if (typeof value === 'undefined' || value === null) return value; 68 | //value 为 ko对象 69 | if (typeof value === 'function') trueValue = value(); 70 | var maskerMeta = core.getMaskerMeta('phoneNumber') || {}; 71 | var masker = new PhoneNumberMasker(maskerMeta); 72 | var maskerValue = masker.format(trueValue); 73 | return maskerValue && maskerValue.value ? maskerValue.value : ''; 74 | }; 75 | 76 | var dateToUTCString = function dateToUTCString(date) { 77 | if (!date) return ''; 78 | if (date.indexOf("-") > -1) date = date.replace(/\-/g, "/"); 79 | var utcString = Date.parse(date); 80 | if (isNaN(utcString)) return ""; 81 | return utcString; 82 | }; 83 | 84 | export { floatRender, integerRender, dateRender, dateTimeRender, timeRender, percentRender, dateToUTCString, phoneNumberRender }; -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow entry index 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-08-04 09:48:36 5 | */ 6 | 7 | import { extend } from './extend'; 8 | import { setCookie, getCookie } from './cookies'; 9 | import { createShellObject, execIgnoreError, getFunction, getJSObject, isDate, isNumber, isArray, isEmptyObject, inArray, isDomElement, each } from './util'; 10 | import { env } from './env'; 11 | import { on, off, trigger, stopEvent } from './event'; 12 | import { event } from './mobileEvents'; 13 | import { addClass, removeClass, hasClass, toggleClass, closest, css, wrap, getStyle, getZIndex, makeDOM, makeModal, getOffset, getScroll, showPanelByEle } from './dom'; 14 | import { Class } from './class'; 15 | import { core } from './core'; 16 | 17 | import { ajax } from './ajax'; 18 | 19 | import { get, post } from './fetch'; 20 | 21 | import { floatRender, integerRender, dateRender, dateTimeRender, timeRender, percentRender, dateToUTCString } from './util/dataRender'; 22 | 23 | import { NumberFormater, DateFormater } from './util/formater'; 24 | 25 | import { date } from './util/dateUtils'; 26 | import { AddressMasker, NumberMasker, CurrencyMasker, PercentMasker } from './util/masker'; 27 | 28 | import { hotkeys } from './util/hotKeys'; 29 | 30 | import { Ripple } from './util/ripple'; 31 | 32 | import { RSAUtils, BigInt, BarrettMu, twoDigit } from './util/rsautils'; 33 | 34 | import { trans } from './util/i18n'; 35 | 36 | //公开接口、属性对外暴露 37 | var api = { 38 | ajax: ajax, 39 | get: get, 40 | post: post, 41 | extend: extend, 42 | setCookie: setCookie, 43 | getCookie: getCookie, 44 | createShellObject: createShellObject, 45 | execIgnoreError: execIgnoreError, 46 | getFunction: getFunction, 47 | getJSObject: getJSObject, 48 | isDate: isDate, 49 | isNumber: isNumber, 50 | isArray: isArray, 51 | isEmptyObject: isEmptyObject, 52 | inArray: inArray, 53 | isDomElement: isDomElement, 54 | each: each, 55 | on: on, 56 | off: off, 57 | trigger: trigger, 58 | stopEvent: stopEvent, 59 | event: event, 60 | addClass: addClass, 61 | removeClass: removeClass, 62 | hasClass: hasClass, 63 | toggleClass: toggleClass, 64 | closest: closest, 65 | css: css, 66 | wrap: wrap, 67 | getStyle: getStyle, 68 | getZIndex: getZIndex, 69 | makeDOM: makeDOM, 70 | makeModal: makeModal, 71 | getOffset: getOffset, 72 | getScroll: getScroll, 73 | showPanelByEle: showPanelByEle, 74 | Class: Class, 75 | core: core, 76 | floatRender: floatRender, 77 | integerRender: integerRender, 78 | dateRender: dateRender, 79 | dateTimeRender: dateTimeRender, 80 | timeRender: timeRender, 81 | percentRender: percentRender, 82 | dateToUTCString: dateToUTCString, 83 | date: date, 84 | NumberFormater: NumberFormater, 85 | DateFormater: DateFormater, 86 | AddressMasker: AddressMasker, 87 | NumberMasker: NumberMasker, 88 | CurrencyMasker: CurrencyMasker, 89 | PercentMasker: PercentMasker, 90 | hotkeys: hotkeys, 91 | Ripple: Ripple, 92 | RSAUtils: RSAUtils, 93 | BigInt: BigInt, 94 | BarrettMu: BarrettMu, 95 | twoDigit: twoDigit, 96 | trans: trans 97 | 98 | }; 99 | extend(api, env); 100 | // export api; 101 | //export default api; 102 | extend(api, window.u || {}); 103 | 104 | window.u = api; 105 | window.iweb = {}; 106 | window.iweb.browser = window.u; 107 | window.sparrow = window.u; 108 | export { u, sparrow }; -------------------------------------------------------------------------------- /src/util/dataRender.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow data display formater 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 15:39:01 5 | */ 6 | import { 7 | core 8 | } from '../core'; 9 | import { 10 | NumberFormater 11 | } from './formater'; 12 | import { 13 | AddressMasker, 14 | NumberMasker, 15 | CurrencyMasker, 16 | PercentMasker, 17 | PhoneNumberMasker 18 | } from './masker'; 19 | import { 20 | date 21 | } from './dateUtils'; 22 | 23 | var floatRender = function(value, precision) { 24 | var trueValue = value; 25 | if(typeof value === 'undefined' || value === null) 26 | return value; 27 | //value 为 ko对象 28 | if(typeof value === 'function') 29 | trueValue = value(); 30 | var maskerMeta = core.getMaskerMeta('float') || {}; 31 | if(typeof precision === 'number') 32 | maskerMeta.precision = precision; 33 | var formater = new NumberFormater(maskerMeta.precision); 34 | var masker = new NumberMasker(maskerMeta); 35 | return masker.format(formater.format(trueValue)).value; 36 | }; 37 | 38 | var integerRender = function(value) { 39 | var trueValue = value; 40 | if(typeof value === 'undefined' || value === null) 41 | return value; 42 | //value 为 ko对象 43 | if(typeof value === 'function') 44 | trueValue = value(); 45 | return trueValue 46 | }; 47 | 48 | var _dateRender = function(value, format, type) { 49 | var trueValue = value; 50 | if(typeof value === 'undefined' || value === null) 51 | return value 52 | //value 为 ko对象 53 | if(typeof value === 'function') 54 | trueValue = value() 55 | var maskerMeta = core.getMaskerMeta(type) || {} 56 | if(typeof format != 'undefined') 57 | maskerMeta.format = format 58 | var maskerValue = date.format(trueValue, maskerMeta.format); 59 | return maskerValue; 60 | } 61 | 62 | var dateRender = function(value, format) { 63 | return _dateRender(value, format, 'date'); 64 | }; 65 | 66 | var dateTimeRender = function(value, format) { 67 | return _dateRender(value, format, 'datetime'); 68 | }; 69 | 70 | var timeRender = function(value, format) { 71 | return _dateRender(value, format, 'time'); 72 | }; 73 | 74 | var percentRender = function(value) { 75 | var trueValue = value 76 | if(typeof value === 'undefined' || value === null) 77 | return value 78 | //value 为 ko对象 79 | if(typeof value === 'function') 80 | trueValue = value() 81 | var maskerMeta = core.getMaskerMeta('percent') || {} 82 | var masker = new PercentMasker(maskerMeta); 83 | var maskerValue = masker.format(trueValue); 84 | return(maskerValue && maskerValue.value) ? maskerValue.value : ''; 85 | }; 86 | 87 | var phoneNumberRender = function () { 88 | var trueValue = value 89 | if(typeof value === 'undefined' || value === null) 90 | return value 91 | //value 为 ko对象 92 | if(typeof value === 'function') 93 | trueValue = value() 94 | var maskerMeta = core.getMaskerMeta('phoneNumber') || {} 95 | var masker = new PhoneNumberMasker(maskerMeta); 96 | var maskerValue = masker.format(trueValue); 97 | return(maskerValue && maskerValue.value) ? maskerValue.value : ''; 98 | } 99 | 100 | var dateToUTCString = function(date) { 101 | if(!date) return '' 102 | if(date.indexOf("-") > -1) 103 | date = date.replace(/\-/g, "/"); 104 | var utcString = Date.parse(date); 105 | if(isNaN(utcString)) return ""; 106 | return utcString; 107 | } 108 | 109 | export { 110 | floatRender, 111 | integerRender, 112 | dateRender, 113 | dateTimeRender, 114 | timeRender, 115 | percentRender, 116 | dateToUTCString, 117 | phoneNumberRender 118 | }; 119 | -------------------------------------------------------------------------------- /src/fetch.js: -------------------------------------------------------------------------------- 1 | import { extend } from './extend'; 2 | const getHost = (key = 'api') => { 3 | const hosts = { 4 | api: { 5 | production: process.env.HOST || "", 6 | development: process.env.HOST || "", 7 | } 8 | }; 9 | return hosts[key][process.env.NODE_ENV]; 10 | }; 11 | 12 | const fetchTools = { 13 | params(params) { 14 | try { 15 | return Object.keys(params).map((key) => { 16 | let param = params[key]; 17 | switch (typeof param) { 18 | case 'object': 19 | param = escape(JSON.stringify(param)); 20 | break; 21 | case 'undefined': 22 | param = ''; 23 | break; 24 | default: 25 | break; 26 | } 27 | return `${key}=${param}`; 28 | }).join('&'); 29 | } catch (e) { 30 | console.log('error in urlParams'); 31 | return ''; 32 | } 33 | }, 34 | fetch(url, options) { 35 | return fetch(url, options).then((response) => { 36 | if (response.ok) { 37 | return response.text().then((text) => { 38 | if (text) { 39 | let result = { 40 | success: false, 41 | message: '接口请求失败', 42 | }; 43 | try { 44 | result = JSON.parse(text); 45 | } catch (e) { 46 | return Promise.reject(new Error('接口返回数据无法解析')); 47 | } 48 | const { success, data, message } = result; 49 | if (success) { 50 | return Promise.resolve(data); 51 | } 52 | return Promise.reject(message); 53 | } 54 | return Promise.reject(new Error('接口未返回数据')); 55 | }); 56 | } 57 | return Promise.reject(new Error('请求失败')); 58 | }); 59 | }, 60 | options(method = 'get', options = {}) { 61 | return extend({ 62 | method: method.toUpperCase(), 63 | credentials: 'include', 64 | cache: 'no-cache', 65 | headers: { 66 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 67 | 'isAjax': 1, 68 | }, 69 | },options); 70 | }, 71 | urlMaker(url) { 72 | if (!url) { 73 | throw new Error('has no url!'); 74 | } else if (url.indexOf('http') !== 0) { 75 | url = `${getHost()}${url}`; 76 | } 77 | return url; 78 | }, 79 | }; 80 | 81 | export function post(oriUrl, oriParams = {}) { 82 | const { 83 | params, 84 | fetch, 85 | options: optionsMaker, 86 | urlMaker, 87 | } = fetchTools; 88 | const data = params(oriParams); 89 | const options = optionsMaker('post'); 90 | options.headers['Content-Type'] = 'application/json;charset=UTF-8'; 91 | try { 92 | options.body = JSON.stringify(oriParams); 93 | } catch (e) { 94 | return Promise.reject(e); 95 | } 96 | return fetch(urlMaker(oriUrl), options); 97 | } 98 | 99 | export function get(oriUrl, oriParams = {}) { 100 | const { 101 | params, 102 | fetch, 103 | options, 104 | urlMaker 105 | } = fetchTools; 106 | 107 | const data = params(oriParams); 108 | let url = urlMaker(oriUrl); 109 | if (data) { 110 | url = `${url}?${data}`; 111 | } 112 | return fetch(url, options()); 113 | } -------------------------------------------------------------------------------- /src/ajax.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow ajax 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 19:06:36 5 | */ 6 | 7 | import {env} from './env'; 8 | 9 | var XmlHttp = { 10 | get: "get", 11 | post: "post", 12 | reqCount: 4, 13 | createXhr: function() { 14 | var xmlhttp = null; 15 | /*if (window.XMLHttpRequest) { 16 | xmlhttp = new XMLHttpRequest(); 17 | } else { 18 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 19 | }*/ 20 | if(env.isIE8) { 21 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); //IE低版本创建XMLHTTP 22 | } else if(env.isIE) { 23 | xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); //IE高版本创建XMLHTTP 24 | } else if(window.XMLHttpRequest) { 25 | xmlhttp = new XMLHttpRequest(); 26 | } 27 | return xmlhttp; 28 | }, 29 | ajax: function(_json) { 30 | var url = _json["url"]; 31 | var callback = _json["success"]; 32 | var async = (_json["async"] == undefined ? true : _json["async"]); 33 | var error = _json["error"]; 34 | var params = _json["data"] || {}; 35 | var method = (_json["type"] == undefined ? XmlHttp.post : _json["type"]).toLowerCase(); 36 | var gzipFlag = params.compressType; 37 | url = XmlHttp.serializeUrl(url); 38 | params = XmlHttp.serializeParams(params); 39 | if(method == XmlHttp.get && params != null) { 40 | url += ("&" + params); 41 | params = null; //如果是get请求,保证最终会执行send(null) 42 | } 43 | 44 | var xmlhttp = XmlHttp.createXhr(); 45 | //xmlhttp.open(method, url+ escape(new Date()), async); 46 | xmlhttp.open(method, url, async); 47 | 48 | if(method == XmlHttp.post) { 49 | xmlhttp.setRequestHeader("Content-type", 50 | "application/x-www-form-urlencoded;charset=UTF-8"); 51 | } 52 | 53 | var execount = 0; 54 | // 异步 55 | if(async) { 56 | // readyState 从 1~4发生4次变化 57 | xmlhttp.onreadystatechange = function() { 58 | execount++; 59 | // 等待readyState状态不再变化之后,再执行回调函数 60 | //if (execount == XmlHttp.reqCount) {// 火狐下存在问题,修改判断方式 61 | if(xmlhttp.readyState == XmlHttp.reqCount) { 62 | XmlHttp.execBack(xmlhttp, callback, error); 63 | } 64 | }; 65 | // send方法要在在回调函数之后执行 66 | xmlhttp.send(params); 67 | } else { 68 | // 同步 readyState 直接变为 4 69 | // 并且 send 方法要在回调函数之前执行 70 | xmlhttp.send(params); 71 | XmlHttp.execBack(xmlhttp, callback, error); 72 | } 73 | }, 74 | execBack: function(xmlhttp, callback, error) { 75 | //if (xmlhttp.readyState == 4 76 | if(xmlhttp.status == 200 || xmlhttp.status == 304 || xmlhttp.readyState == 4) { 77 | callback(xmlhttp.responseText, xmlhttp.status, xmlhttp); 78 | } else { 79 | if(error) { 80 | error(xmlhttp.responseText, xmlhttp.status, xmlhttp); 81 | } else { 82 | var errorMsg = "no error callback function!"; 83 | if(xmlhttp.responseText) { 84 | errorMsg = xmlhttp.responseText; 85 | } 86 | alert(errorMsg); 87 | // throw errorMsg; 88 | } 89 | } 90 | }, 91 | serializeUrl: function(url) { 92 | var cache = "cache=" + Math.random(); 93 | if(url.indexOf("?") > 0) { 94 | url += ("&" + cache); 95 | } else { 96 | url += ("?" + cache); 97 | } 98 | return url; 99 | }, 100 | serializeParams: function(params) { 101 | var ud = undefined; 102 | if(ud == params || params == null || params == "") { 103 | return null; 104 | } 105 | if(params.constructor == Object) { 106 | var result = ""; 107 | for(var p in params) { 108 | result += (p + "=" + encodeURIComponent(params[p]) + "&"); 109 | } 110 | return result.substring(0, result.length - 1); 111 | } 112 | return params; 113 | } 114 | }; 115 | 116 | 117 | var ajax = XmlHttp.ajax; 118 | export {ajax}; 119 | -------------------------------------------------------------------------------- /lib/ajax.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow ajax 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 19:06:36 5 | */ 6 | 7 | import { env } from './env'; 8 | 9 | var XmlHttp = { 10 | get: "get", 11 | post: "post", 12 | reqCount: 4, 13 | createXhr: function createXhr() { 14 | var xmlhttp = null; 15 | /*if (window.XMLHttpRequest) { 16 | xmlhttp = new XMLHttpRequest(); 17 | } else { 18 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 19 | }*/ 20 | if (env.isIE8) { 21 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); //IE低版本创建XMLHTTP 22 | } else if (env.isIE) { 23 | xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); //IE高版本创建XMLHTTP 24 | } else if (window.XMLHttpRequest) { 25 | xmlhttp = new XMLHttpRequest(); 26 | } 27 | return xmlhttp; 28 | }, 29 | ajax: function ajax(_json) { 30 | var url = _json["url"]; 31 | var callback = _json["success"]; 32 | var async = _json["async"] == undefined ? true : _json["async"]; 33 | var error = _json["error"]; 34 | var params = _json["data"] || {}; 35 | var method = (_json["type"] == undefined ? XmlHttp.post : _json["type"]).toLowerCase(); 36 | var gzipFlag = params.compressType; 37 | url = XmlHttp.serializeUrl(url); 38 | params = XmlHttp.serializeParams(params); 39 | if (method == XmlHttp.get && params != null) { 40 | url += "&" + params; 41 | params = null; //如果是get请求,保证最终会执行send(null) 42 | } 43 | 44 | var xmlhttp = XmlHttp.createXhr(); 45 | //xmlhttp.open(method, url+ escape(new Date()), async); 46 | xmlhttp.open(method, url, async); 47 | 48 | if (method == XmlHttp.post) { 49 | xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); 50 | } 51 | 52 | var execount = 0; 53 | // 异步 54 | if (async) { 55 | // readyState 从 1~4发生4次变化 56 | xmlhttp.onreadystatechange = function () { 57 | execount++; 58 | // 等待readyState状态不再变化之后,再执行回调函数 59 | //if (execount == XmlHttp.reqCount) {// 火狐下存在问题,修改判断方式 60 | if (xmlhttp.readyState == XmlHttp.reqCount) { 61 | XmlHttp.execBack(xmlhttp, callback, error); 62 | } 63 | }; 64 | // send方法要在在回调函数之后执行 65 | xmlhttp.send(params); 66 | } else { 67 | // 同步 readyState 直接变为 4 68 | // 并且 send 方法要在回调函数之前执行 69 | xmlhttp.send(params); 70 | XmlHttp.execBack(xmlhttp, callback, error); 71 | } 72 | }, 73 | execBack: function execBack(xmlhttp, callback, error) { 74 | //if (xmlhttp.readyState == 4 75 | if (xmlhttp.status == 200 || xmlhttp.status == 304 || xmlhttp.readyState == 4) { 76 | callback(xmlhttp.responseText, xmlhttp.status, xmlhttp); 77 | } else { 78 | if (error) { 79 | error(xmlhttp.responseText, xmlhttp.status, xmlhttp); 80 | } else { 81 | var errorMsg = "no error callback function!"; 82 | if (xmlhttp.responseText) { 83 | errorMsg = xmlhttp.responseText; 84 | } 85 | alert(errorMsg); 86 | // throw errorMsg; 87 | } 88 | } 89 | }, 90 | serializeUrl: function serializeUrl(url) { 91 | var cache = "cache=" + Math.random(); 92 | if (url.indexOf("?") > 0) { 93 | url += "&" + cache; 94 | } else { 95 | url += "?" + cache; 96 | } 97 | return url; 98 | }, 99 | serializeParams: function serializeParams(params) { 100 | var ud = undefined; 101 | if (ud == params || params == null || params == "") { 102 | return null; 103 | } 104 | if (params.constructor == Object) { 105 | var result = ""; 106 | for (var p in params) { 107 | result += p + "=" + encodeURIComponent(params[p]) + "&"; 108 | } 109 | return result.substring(0, result.length - 1); 110 | } 111 | return params; 112 | } 113 | }; 114 | 115 | var ajax = XmlHttp.ajax; 116 | export { ajax }; -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [3.2.4](https://github.com/iuap-design/tinper-sparrow/compare/v3.2.5...v3.2.4) (2017-08-07) 3 | 4 | 5 | 6 | 7 | ## [3.2.5](https://github.com/iuap-design/tinper-sparrow/compare/v3.2.4...v3.2.5) (2017-06-28) 8 | 9 | 10 | 11 | 12 | ## [3.2.3](https://github.com/iuap-design/tinper-sparrow/compare/v3.2.2...v3.2.3) (2017-06-23) 13 | 14 | 15 | 16 | 17 | ## [3.2.2](https://github.com/iuap-design/tinper-sparrow/compare/v3.2.1...v3.2.2) (2017-05-05) 18 | 19 | 20 | 21 | 22 | ## [3.2.1](https://github.com/iuap-design/tinper-sparrow/compare/v3.2.0...v3.2.1) (2017-04-06) 23 | 24 | 25 | 26 | 27 | # [3.2.0](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.27...v3.2.0) (2017-03-22) 28 | 29 | 30 | 31 | 32 | ## [3.1.27](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.26...v3.1.27) (2017-02-23) 33 | 34 | 35 | 36 | 37 | ## [3.1.26](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.25...v3.1.26) (2017-02-20) 38 | 39 | 40 | 41 | 42 | ## [3.1.25](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.22...v3.1.25) (2017-02-10) 43 | 44 | 45 | 46 | 47 | ## [3.1.22](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.21...v3.1.22) (2017-01-12) 48 | 49 | 50 | 51 | 52 | ## [3.1.21](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.20...v3.1.21) (2017-01-05) 53 | 54 | 55 | 56 | 57 | ## [3.1.20](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.19...v3.1.20) (2017-01-05) 58 | 59 | 60 | ### Bug Fixes 61 | 62 | * isNumber判断 ([ebd1848](https://github.com/iuap-design/tinper-sparrow/commit/ebd1848)) 63 | * isNumber判断 ([ff8b74f](https://github.com/iuap-design/tinper-sparrow/commit/ff8b74f)) 64 | * setFmormat输入undefined造成bug ([e7bb1e3](https://github.com/iuap-design/tinper-sparrow/commit/e7bb1e3)) 65 | 66 | 67 | 68 | 69 | ## [3.1.18](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.17...v3.1.18) (2016-12-20) 70 | 71 | 72 | 73 | 74 | ## [3.1.17](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.16...v3.1.17) (2016-12-14) 75 | 76 | 77 | ### Bug Fixes 78 | 79 | * addClass ie9兼容 ([b2bb857](https://github.com/iuap-design/tinper-sparrow/commit/b2bb857)) 80 | * i18n bug ([06ed3fc](https://github.com/iuap-design/tinper-sparrow/commit/06ed3fc)) 81 | * removeClass hasClass bug other2jquery ([6fec69e](https://github.com/iuap-design/tinper-sparrow/commit/6fec69e)) 82 | 83 | 84 | 85 | 86 | ## [3.1.15](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.14...v3.1.15) (2016-11-29) 87 | 88 | 89 | 90 | 91 | ## [3.1.14](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.13...v3.1.14) (2016-11-24) 92 | 93 | 94 | 95 | 96 | ## [3.1.13](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.12...v3.1.13) (2016-11-18) 97 | 98 | 99 | 100 | 101 | ## [3.1.12](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.10...v3.1.12) (2016-11-17) 102 | 103 | 104 | 105 | 106 | ## [3.1.10](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.9...v3.1.10) (2016-11-17) 107 | 108 | 109 | ### Bug Fixes 110 | 111 | * IUAPDESIGN:云表单:日期年月ios获取bug ([02c2f80](https://github.com/iuap-design/tinper-sparrow/commit/02c2f80)) 112 | 113 | 114 | 115 | 116 | ## [3.1.7](https://github.com/iuap-design/tinper-sparrow/compare/v3.1.1...v3.1.7) (2016-11-04) 117 | 118 | 119 | 120 | 121 | ## 3.1.1 (2016-10-17) 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow entry index 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-08-04 09:48:36 5 | */ 6 | 7 | import {extend} from './extend'; 8 | import { 9 | setCookie, 10 | getCookie 11 | } from './cookies'; 12 | import { 13 | createShellObject, 14 | execIgnoreError, 15 | getFunction, 16 | getJSObject, 17 | isDate, 18 | isNumber, 19 | isArray, 20 | isEmptyObject, 21 | inArray, 22 | isDomElement, 23 | each 24 | } from './util'; 25 | import { 26 | env 27 | } from './env'; 28 | import { 29 | on, 30 | off, 31 | trigger, 32 | stopEvent 33 | } from './event'; 34 | import{ 35 | event 36 | } from './mobileEvents' 37 | import { 38 | addClass, 39 | removeClass, 40 | hasClass, 41 | toggleClass, 42 | closest, 43 | css, 44 | wrap, 45 | getStyle, 46 | getZIndex, 47 | makeDOM, 48 | makeModal, 49 | getOffset, 50 | getScroll, 51 | showPanelByEle 52 | } from './dom'; 53 | import { 54 | Class 55 | } from './class'; 56 | import { 57 | core 58 | } from './core'; 59 | 60 | import { 61 | ajax 62 | } from './ajax'; 63 | 64 | import { 65 | get, 66 | post 67 | } from './fetch'; 68 | 69 | import { 70 | floatRender, 71 | integerRender, 72 | dateRender, 73 | dateTimeRender, 74 | timeRender, 75 | percentRender, 76 | dateToUTCString 77 | } from './util/dataRender'; 78 | 79 | import { 80 | NumberFormater, 81 | DateFormater 82 | } from './util/formater'; 83 | 84 | import { 85 | date 86 | } from './util/dateUtils'; 87 | import { 88 | AddressMasker, 89 | NumberMasker, 90 | CurrencyMasker, 91 | PercentMasker 92 | } from './util/masker' 93 | 94 | import { 95 | hotkeys 96 | } from './util/hotKeys'; 97 | 98 | import { 99 | Ripple 100 | } from './util/ripple'; 101 | 102 | import { 103 | RSAUtils, 104 | BigInt, 105 | BarrettMu, 106 | twoDigit 107 | } from './util/rsautils'; 108 | 109 | import { 110 | trans 111 | } from './util/i18n'; 112 | 113 | 114 | //公开接口、属性对外暴露 115 | let api = { 116 | ajax: ajax, 117 | get, 118 | post, 119 | extend : extend, 120 | setCookie: setCookie, 121 | getCookie: getCookie, 122 | createShellObject: createShellObject, 123 | execIgnoreError: execIgnoreError, 124 | getFunction: getFunction, 125 | getJSObject: getJSObject, 126 | isDate: isDate, 127 | isNumber: isNumber, 128 | isArray: isArray, 129 | isEmptyObject: isEmptyObject, 130 | inArray: inArray, 131 | isDomElement: isDomElement, 132 | each: each, 133 | on: on, 134 | off: off, 135 | trigger: trigger, 136 | stopEvent: stopEvent, 137 | event: event, 138 | addClass: addClass, 139 | removeClass: removeClass, 140 | hasClass: hasClass, 141 | toggleClass: toggleClass, 142 | closest: closest, 143 | css: css, 144 | wrap: wrap, 145 | getStyle: getStyle, 146 | getZIndex: getZIndex, 147 | makeDOM: makeDOM, 148 | makeModal: makeModal, 149 | getOffset: getOffset, 150 | getScroll: getScroll, 151 | showPanelByEle: showPanelByEle, 152 | Class: Class, 153 | core: core, 154 | floatRender: floatRender, 155 | integerRender: integerRender, 156 | dateRender: dateRender, 157 | dateTimeRender: dateTimeRender, 158 | timeRender: timeRender, 159 | percentRender: percentRender, 160 | dateToUTCString: dateToUTCString, 161 | date: date, 162 | NumberFormater: NumberFormater, 163 | DateFormater: DateFormater, 164 | AddressMasker: AddressMasker, 165 | NumberMasker: NumberMasker, 166 | CurrencyMasker: CurrencyMasker, 167 | PercentMasker: PercentMasker, 168 | hotkeys: hotkeys, 169 | Ripple: Ripple, 170 | RSAUtils: RSAUtils, 171 | BigInt: BigInt, 172 | BarrettMu: BarrettMu, 173 | twoDigit: twoDigit, 174 | trans: trans, 175 | 176 | }; 177 | extend(api,env); 178 | // export api; 179 | //export default api; 180 | extend(api,window.u || {}); 181 | 182 | window.u = api; 183 | window.iweb = {} 184 | window.iweb.browser = window.u; 185 | window.sparrow = window.u; 186 | export { 187 | u, 188 | sparrow 189 | }; 190 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* global __dirname */ 2 | 3 | var path = require('path'); 4 | var webpack = require('webpack'); 5 | var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin; 6 | var fs = require('fs'); 7 | 8 | var dir_js = path.resolve(__dirname, 'src'); 9 | var dir_build = path.resolve(__dirname, 'dist'); 10 | 11 | var libraryName = 'tinper-sparrow'; 12 | 13 | var data = fs.readFileSync('./package.json', 'utf8'); 14 | var packageObj = JSON.parse(data); 15 | var headerStr = ''; 16 | headerStr += packageObj.name + ' v' + packageObj.version + '\r\n'; 17 | headerStr += packageObj.description + '\r\n'; 18 | headerStr += 'author : ' + packageObj.author + '\r\n'; 19 | headerStr += 'homepage : ' + packageObj.homepage + '\r\n'; 20 | headerStr += 'bugs : ' + packageObj.bugs.url; 21 | var plugins = [new webpack.BannerPlugin(headerStr), 22 | new webpack.LoaderOptionsPlugin({ 23 | minimize: true 24 | }), 25 | new webpack.NoErrorsPlugin() 26 | ] 27 | 28 | var returnFUn = function(env) { 29 | var mode = env.mode, 30 | outputFile; 31 | 32 | if (mode == 'build') { 33 | outputFile = libraryName + '.min.js'; 34 | plugins.push(new webpack.optimize.UglifyJsPlugin({ 35 | mangle: true, 36 | beautify: true 37 | })) 38 | plugins.push(new UglifyJsPlugin({ 39 | minimize: true 40 | })); 41 | } else { 42 | outputFile = libraryName + '.js'; 43 | plugins.push(new webpack.optimize.UglifyJsPlugin({ 44 | mangle: false, 45 | beautify: true 46 | })) 47 | } 48 | 49 | var obj = { 50 | entry: path.resolve(dir_js, 'index.js'), 51 | output: { 52 | path: dir_build, 53 | filename: outputFile 54 | }, 55 | devServer: { 56 | contentBase: dir_build, 57 | }, 58 | module: { 59 | loaders: [{ 60 | loader: 'babel-loader', 61 | test: dir_js, 62 | query: { 63 | //presets: ['es2015'], 64 | 65 | // All of the plugins of babel-preset-es2015, 66 | // minus babel-plugin-transform-es2015-modules-commonjs 67 | plugins: [ 68 | 'transform-es2015-template-literals', 69 | 'transform-es2015-literals', 70 | 'transform-es2015-function-name', 71 | 'transform-es2015-arrow-functions', 72 | 'transform-es2015-block-scoped-functions', 73 | 'transform-es2015-classes', 74 | 'transform-es2015-object-super', 75 | 'transform-es2015-shorthand-properties', 76 | 'transform-es2015-computed-properties', 77 | 'transform-es2015-for-of', 78 | 'transform-es2015-sticky-regex', 79 | 'transform-es2015-unicode-regex', 80 | 'check-es2015-constants', 81 | 'transform-es2015-spread', 82 | 'transform-es2015-parameters', 83 | 'transform-es2015-destructuring', 84 | 'transform-es2015-block-scoping', 85 | 'transform-es2015-typeof-symbol', ['transform-regenerator', { 86 | async: false, 87 | asyncGenerators: false 88 | }], 89 | ], 90 | }, 91 | }] 92 | }, 93 | plugins: plugins, 94 | stats: { 95 | // Nice colored output 96 | colors: true 97 | }, 98 | // Create source maps for the bundle 99 | devtool: 'source-map', 100 | } 101 | return obj; 102 | } 103 | module.exports = returnFUn; 104 | -------------------------------------------------------------------------------- /lib/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow touch event 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 14:41:17 5 | */ 6 | 7 | var on = function on(element, eventName, child, listener) { 8 | if (!element) return; 9 | if (arguments.length < 4) { 10 | listener = child; 11 | child = undefined; 12 | } else { 13 | var childlistener = function childlistener(e) { 14 | if (!e) { 15 | return; 16 | } 17 | var tmpchildren = element.querySelectorAll(child); 18 | tmpchildren.forEach(function (node) { 19 | if (node == e.target) { 20 | listener.call(e.target, e); 21 | } 22 | }); 23 | }; 24 | } 25 | //capture = capture || false; 26 | 27 | if (!element["uEvent"]) { 28 | //在dom上添加记录区 29 | element["uEvent"] = {}; 30 | } 31 | //判断是否元素上是否用通过on方法填加进去的事件 32 | if (!element["uEvent"][eventName]) { 33 | element["uEvent"][eventName] = [child ? childlistener : listener]; 34 | if (u.event && u.event[eventName] && u.event[eventName].setup) { 35 | u.event[eventName].setup.call(element); 36 | } 37 | element["uEvent"][eventName + 'fn'] = function (e) { 38 | //火狐下有问题修改判断 39 | if (!e) e = typeof event != 'undefined' && event ? event : window.event; 40 | element["uEvent"][eventName].forEach(function (fn) { 41 | try { 42 | e.target = e.target || e.srcElement; //兼容IE8 43 | } catch (ee) {} 44 | if (fn) fn.call(element, e); 45 | }); 46 | }; 47 | if (element.addEventListener) { 48 | // 用于支持DOM的浏览器 49 | element.addEventListener(eventName, element["uEvent"][eventName + 'fn']); 50 | } else if (element.attachEvent) { 51 | // 用于IE浏览器 52 | element.attachEvent("on" + eventName, element["uEvent"][eventName + 'fn']); 53 | } else { 54 | // 用于其它浏览器 55 | element["on" + eventName] = element["uEvent"][eventName + 'fn']; 56 | } 57 | } else { 58 | //如果有就直接往元素的记录区添加事件 59 | var lis = child ? childlistener : listener; 60 | var hasLis = false; 61 | element["uEvent"][eventName].forEach(function (fn) { 62 | if (fn == lis) { 63 | hasLis = true; 64 | } 65 | }); 66 | if (!hasLis) { 67 | element["uEvent"][eventName].push(child ? childlistener : listener); 68 | } 69 | } 70 | }; 71 | 72 | var off = function off(element, eventName, listener) { 73 | //删除事件数组 74 | if (listener) { 75 | if (element && element["uEvent"] && element["uEvent"][eventName]) { 76 | element["uEvent"][eventName].forEach(function (fn, i) { 77 | if (fn == listener) { 78 | element["uEvent"][eventName].splice(i, 1); 79 | } 80 | }); 81 | } 82 | return; 83 | } 84 | var eventfn; 85 | if (element && element["uEvent"] && element["uEvent"][eventName + 'fn']) eventfn = element["uEvent"][eventName + 'fn']; 86 | if (element.removeEventListener) { 87 | // 用于支持DOM的浏览器 88 | element.removeEventListener(eventName, eventfn); 89 | } else if (element.removeEvent) { 90 | // 用于IE浏览器 91 | element.removeEvent("on" + eventName, eventfn); 92 | } else { 93 | // 用于其它浏览器 94 | delete element["on" + eventName]; 95 | } 96 | if (u.event && u.event[eventName] && u.event[eventName].teardown) { 97 | u.event[eventName].teardown.call(element); 98 | } 99 | 100 | if (element && element["uEvent"] && element["uEvent"][eventName]) element["uEvent"][eventName] = undefined; 101 | if (element && element["uEvent"] && element["uEvent"][eventName + 'fn']) element["uEvent"][eventName + 'fn'] = undefined; 102 | }; 103 | var trigger = function trigger(element, eventName) { 104 | if (element["uEvent"] && element["uEvent"][eventName]) { 105 | element["uEvent"][eventName + 'fn'](); 106 | } 107 | }; 108 | 109 | /** 110 | * 阻止冒泡 111 | */ 112 | var stopEvent = function stopEvent(e) { 113 | if (typeof e != "undefined") { 114 | if (e.stopPropagation) e.stopPropagation();else { 115 | e.cancelBubble = true; 116 | } 117 | //阻止默认浏览器动作(W3C) 118 | if (e && e.preventDefault) e.preventDefault(); 119 | //IE中阻止函数器默认动作的方式 120 | else window.event.returnValue = false; 121 | } 122 | }; 123 | 124 | export { on, off, trigger, stopEvent }; -------------------------------------------------------------------------------- /src/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow touch event 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 14:41:17 5 | */ 6 | 7 | var on = function(element, eventName, child, listener) { 8 | if(!element) 9 | return; 10 | if(arguments.length < 4) { 11 | listener = child; 12 | child = undefined; 13 | } else { 14 | var childlistener = function(e) { 15 | if(!e) { 16 | return; 17 | } 18 | var tmpchildren = element.querySelectorAll(child) 19 | tmpchildren.forEach(function(node) { 20 | if(node == e.target) { 21 | listener.call(e.target, e) 22 | } 23 | }) 24 | } 25 | } 26 | //capture = capture || false; 27 | 28 | if(!element["uEvent"]) { 29 | //在dom上添加记录区 30 | element["uEvent"] = {} 31 | } 32 | //判断是否元素上是否用通过on方法填加进去的事件 33 | if(!element["uEvent"][eventName]) { 34 | element["uEvent"][eventName] = [child ? childlistener : listener] 35 | if(u.event && u.event[eventName] && u.event[eventName].setup) { 36 | u.event[eventName].setup.call(element); 37 | } 38 | element["uEvent"][eventName + 'fn'] = function(e) { 39 | //火狐下有问题修改判断 40 | if(!e) 41 | e = typeof event != 'undefined' && event ? event : window.event; 42 | element["uEvent"][eventName].forEach(function(fn) { 43 | try { 44 | e.target = e.target || e.srcElement; //兼容IE8 45 | } catch(ee) {} 46 | if(fn) 47 | fn.call(element, e) 48 | }) 49 | } 50 | if(element.addEventListener) { // 用于支持DOM的浏览器 51 | element.addEventListener(eventName, element["uEvent"][eventName + 'fn']); 52 | } else if(element.attachEvent) { // 用于IE浏览器 53 | element.attachEvent("on" + eventName, element["uEvent"][eventName + 'fn']); 54 | } else { // 用于其它浏览器 55 | element["on" + eventName] = element["uEvent"][eventName + 'fn'] 56 | } 57 | } else { 58 | //如果有就直接往元素的记录区添加事件 59 | var lis = child ? childlistener : listener; 60 | var hasLis = false; 61 | element["uEvent"][eventName].forEach(function(fn) { 62 | if(fn == lis) { 63 | hasLis = true; 64 | } 65 | }); 66 | if(!hasLis) { 67 | element["uEvent"][eventName].push(child ? childlistener : listener) 68 | } 69 | } 70 | 71 | }; 72 | 73 | var off = function(element, eventName, listener) { 74 | //删除事件数组 75 | if(listener) { 76 | if(element && element["uEvent"] && element["uEvent"][eventName]) { 77 | element["uEvent"][eventName].forEach(function(fn, i) { 78 | if(fn == listener) { 79 | element["uEvent"][eventName].splice(i, 1); 80 | } 81 | }); 82 | } 83 | return; 84 | } 85 | var eventfn; 86 | if(element && element["uEvent"] && element["uEvent"][eventName + 'fn']) 87 | eventfn = element["uEvent"][eventName + 'fn'] 88 | if(element.removeEventListener) { // 用于支持DOM的浏览器 89 | element.removeEventListener(eventName, eventfn); 90 | } else if(element.removeEvent) { // 用于IE浏览器 91 | element.removeEvent("on" + eventName, eventfn); 92 | } else { // 用于其它浏览器 93 | delete element["on" + eventName] 94 | } 95 | if(u.event && u.event[eventName] && u.event[eventName].teardown) { 96 | u.event[eventName].teardown.call(element); 97 | } 98 | 99 | if(element && element["uEvent"] && element["uEvent"][eventName]) 100 | element["uEvent"][eventName] = undefined 101 | if(element && element["uEvent"] && element["uEvent"][eventName + 'fn']) 102 | element["uEvent"][eventName + 'fn'] = undefined 103 | 104 | }; 105 | var trigger = function(element, eventName) { 106 | if(element["uEvent"] && element["uEvent"][eventName]) { 107 | element["uEvent"][eventName + 'fn']() 108 | } 109 | }; 110 | 111 | /** 112 | * 阻止冒泡 113 | */ 114 | var stopEvent = function(e) { 115 | if(typeof(e) != "undefined") { 116 | if(e.stopPropagation) 117 | e.stopPropagation(); 118 | else { 119 | e.cancelBubble = true; 120 | } 121 | //阻止默认浏览器动作(W3C) 122 | if(e && e.preventDefault) 123 | e.preventDefault(); 124 | //IE中阻止函数器默认动作的方式 125 | else 126 | window.event.returnValue = false; 127 | } 128 | }; 129 | 130 | export { 131 | on, 132 | off, 133 | trigger, 134 | stopEvent 135 | }; 136 | -------------------------------------------------------------------------------- /src/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow util tools 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | /** 8 | * 创建一个带壳的对象,防止外部修改 9 | * @param {Object} proto 10 | */ 11 | var createShellObject = function(proto) { 12 | var exf = function() {} 13 | exf.prototype = proto; 14 | return new exf(); 15 | }; 16 | var execIgnoreError = function(a, b, c) { 17 | try { 18 | a.call(b, c); 19 | } catch(e) {} 20 | }; 21 | 22 | var getFunction = function(target, val) { 23 | if(!val || typeof val == 'function') return val 24 | if(typeof target[val] == 'function') 25 | return target[val] 26 | else if(typeof window[val] == 'function') 27 | return window[val] 28 | else if(val.indexOf('.') != -1) { 29 | var func = getJSObject(target, val) 30 | if(typeof func == 'function') return func 31 | func = getJSObject(window, val) 32 | if(typeof func == 'function') return func 33 | } 34 | return val 35 | }; 36 | var getJSObject = function(target, names) { 37 | if(!names) { 38 | return; 39 | } 40 | if(typeof names == 'object') 41 | return names 42 | var nameArr = names.split('.') 43 | var obj = target 44 | for(var i = 0; i < nameArr.length; i++) { 45 | obj = obj[nameArr[i]] 46 | if(!obj) return null 47 | } 48 | return obj 49 | }; 50 | var isDate = function(input) { 51 | return Object.prototype.toString.call(input) === '[object Date]' || 52 | input instanceof Date; 53 | }; 54 | var isNumber = function(obj) { 55 | //return obj === +obj 56 | //加了个typeof 判断,因为'431027199110.078573'会解析成number 57 | return obj - parseFloat(obj) + 1 >= 0; 58 | }; 59 | var isArray = Array.isArray || function(val) { 60 | return Object.prototype.toString.call(val) === '[object Array]'; 61 | }; 62 | var isEmptyObject = function(obj) { 63 | var name; 64 | for(name in obj) { 65 | return false; 66 | } 67 | return true; 68 | }; 69 | var inArray = function(node, arr) { 70 | if(!arr instanceof Array) { 71 | throw "arguments is not Array"; 72 | } 73 | for(var i = 0, k = arr.length; i < k; i++) { 74 | if(node == arr[i]) { 75 | return true; 76 | } 77 | } 78 | return false; 79 | }; 80 | var isDomElement = function(obj) { 81 | if(window['HTMLElement']) { 82 | return obj instanceof HTMLElement; 83 | } else { 84 | return obj && obj.tagName && obj.nodeType === 1; 85 | } 86 | }; 87 | var each = function(obj, callback) { 88 | if(obj.forEach) { 89 | obj.forEach(function(v, k) { 90 | callback(k, v); 91 | }); 92 | 93 | } else if(obj instanceof Object) { 94 | for(var k in obj) { 95 | callback(k, obj[k]); 96 | } 97 | } else { 98 | return; 99 | } 100 | 101 | }; 102 | try{ 103 | NodeList.prototype.forEach = Array.prototype.forEach; 104 | }catch(e){ 105 | 106 | } 107 | 108 | 109 | /** 110 | * 获得字符串的字节长度 111 | */ 112 | String.prototype.lengthb = function() { 113 | // var str = this.replace(/[^\x800-\x10000]/g, "***"); 114 | var str = this.replace(/[^\x00-\xff]/g, "**"); 115 | return str.length; 116 | }; 117 | 118 | /** 119 | * 将AFindText全部替换为ARepText 120 | */ 121 | String.prototype.replaceAll = function(AFindText, ARepText) { 122 | //自定义String对象的方法 123 | var raRegExp = new RegExp(AFindText, "g"); 124 | return this.replace(raRegExp, ARepText); 125 | }; 126 | 127 | 128 | var dateFormat = function ( str ) { 129 | //如果不是string类型 原型返回 130 | if ( typeof ( str ) !== 'string') 131 | { 132 | return str; 133 | } 134 | //判断 str 格式如果是 yy-mm-dd 135 | if (str && str.indexOf ('-') > -1){ 136 | //获取当前是否是 ios版本,>8是因为ios不识别new Date(“2016/11”)格式 137 | var ua = navigator.userAgent.toLowerCase(); 138 | if (/iphone|ipad|ipod/.test(ua)) { 139 | //转换成 yy/mm/dd 140 | str = str.replace(/-/g,"/"); 141 | str = str.replace(/(^\s+)|(\s+$)/g,""); 142 | if(str.length <= 8){ 143 | str = str += "/01"; 144 | } 145 | } 146 | } 147 | 148 | 149 | return str; 150 | } 151 | 152 | export { 153 | createShellObject, 154 | execIgnoreError, 155 | getFunction, 156 | getJSObject, 157 | isDate, 158 | isNumber, 159 | isArray, 160 | isEmptyObject, 161 | inArray, 162 | isDomElement, 163 | each, 164 | dateFormat 165 | }; 166 | -------------------------------------------------------------------------------- /lib/util.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow util tools 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | /** 8 | * 创建一个带壳的对象,防止外部修改 9 | * @param {Object} proto 10 | */ 11 | var createShellObject = function createShellObject(proto) { 12 | var exf = function exf() {}; 13 | exf.prototype = proto; 14 | return new exf(); 15 | }; 16 | var execIgnoreError = function execIgnoreError(a, b, c) { 17 | try { 18 | a.call(b, c); 19 | } catch (e) {} 20 | }; 21 | 22 | var getFunction = function getFunction(target, val) { 23 | if (!val || typeof val == 'function') return val; 24 | if (typeof target[val] == 'function') return target[val];else if (typeof window[val] == 'function') return window[val];else if (val.indexOf('.') != -1) { 25 | var func = getJSObject(target, val); 26 | if (typeof func == 'function') return func; 27 | func = getJSObject(window, val); 28 | if (typeof func == 'function') return func; 29 | } 30 | return val; 31 | }; 32 | var getJSObject = function getJSObject(target, names) { 33 | if (!names) { 34 | return; 35 | } 36 | if ((typeof names === 'undefined' ? 'undefined' : babelHelpers['typeof'](names)) == 'object') return names; 37 | var nameArr = names.split('.'); 38 | var obj = target; 39 | for (var i = 0; i < nameArr.length; i++) { 40 | obj = obj[nameArr[i]]; 41 | if (!obj) return null; 42 | } 43 | return obj; 44 | }; 45 | var isDate = function isDate(input) { 46 | return Object.prototype.toString.call(input) === '[object Date]' || input instanceof Date; 47 | }; 48 | var isNumber = function isNumber(obj) { 49 | //return obj === +obj 50 | //加了个typeof 判断,因为'431027199110.078573'会解析成number 51 | return obj - parseFloat(obj) + 1 >= 0; 52 | }; 53 | var isArray = Array.isArray || function (val) { 54 | return Object.prototype.toString.call(val) === '[object Array]'; 55 | }; 56 | var isEmptyObject = function isEmptyObject(obj) { 57 | var name; 58 | for (name in obj) { 59 | return false; 60 | } 61 | return true; 62 | }; 63 | var inArray = function inArray(node, arr) { 64 | if (!arr instanceof Array) { 65 | throw "arguments is not Array"; 66 | } 67 | for (var i = 0, k = arr.length; i < k; i++) { 68 | if (node == arr[i]) { 69 | return true; 70 | } 71 | } 72 | return false; 73 | }; 74 | var isDomElement = function isDomElement(obj) { 75 | if (window['HTMLElement']) { 76 | return obj instanceof HTMLElement; 77 | } else { 78 | return obj && obj.tagName && obj.nodeType === 1; 79 | } 80 | }; 81 | var each = function each(obj, callback) { 82 | if (obj.forEach) { 83 | obj.forEach(function (v, k) { 84 | callback(k, v); 85 | }); 86 | } else if (obj instanceof Object) { 87 | for (var k in obj) { 88 | callback(k, obj[k]); 89 | } 90 | } else { 91 | return; 92 | } 93 | }; 94 | try { 95 | NodeList.prototype.forEach = Array.prototype.forEach; 96 | } catch (e) {} 97 | 98 | /** 99 | * 获得字符串的字节长度 100 | */ 101 | String.prototype.lengthb = function () { 102 | // var str = this.replace(/[^\x800-\x10000]/g, "***"); 103 | var str = this.replace(/[^\x00-\xff]/g, "**"); 104 | return str.length; 105 | }; 106 | 107 | /** 108 | * 将AFindText全部替换为ARepText 109 | */ 110 | String.prototype.replaceAll = function (AFindText, ARepText) { 111 | //自定义String对象的方法 112 | var raRegExp = new RegExp(AFindText, "g"); 113 | return this.replace(raRegExp, ARepText); 114 | }; 115 | 116 | var dateFormat = function dateFormat(str) { 117 | //如果不是string类型 原型返回 118 | if (typeof str !== 'string') { 119 | return str; 120 | } 121 | //判断 str 格式如果是 yy-mm-dd 122 | if (str && str.indexOf('-') > -1) { 123 | //获取当前是否是 ios版本,>8是因为ios不识别new Date(“2016/11”)格式 124 | var ua = navigator.userAgent.toLowerCase(); 125 | if (/iphone|ipad|ipod/.test(ua)) { 126 | //转换成 yy/mm/dd 127 | str = str.replace(/-/g, "/"); 128 | str = str.replace(/(^\s+)|(\s+$)/g, ""); 129 | if (str.length <= 8) { 130 | str = str += "/01"; 131 | } 132 | } 133 | } 134 | 135 | return str; 136 | }; 137 | 138 | export { createShellObject, execIgnoreError, getFunction, getJSObject, isDate, isNumber, isArray, isEmptyObject, inArray, isDomElement, each, dateFormat }; -------------------------------------------------------------------------------- /lib/BaseComponent.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.BaseComponent = undefined; 7 | 8 | var _class = require('./class'); 9 | 10 | var _util = require('./util'); 11 | 12 | var _event = require('./event'); 13 | 14 | var _compMgr = require('./compMgr'); 15 | 16 | /** 17 | * Module : Sparrow base component 18 | * Author : Kvkens(yueming@yonyou.com) 19 | * Date : 2016-07-28 18:45:08 20 | */ 21 | 22 | var BaseComponent = _class.Class.create({ 23 | initialize: function initialize(element) { 24 | if ((0, _util.isDomElement)(element)) { 25 | this.element = element; 26 | this.options = {}; 27 | } else { 28 | this.element = element['el']; 29 | this.options = element; 30 | } 31 | this.element = typeof this.element === 'string' ? document.querySelector(this.element) : this.element; 32 | 33 | this.compType = this.compType || this.constructor.compType; 34 | this.element[this.compType] = this; 35 | this.element['init'] = true; 36 | this.init(); 37 | }, 38 | /** 39 | * 绑定事件 40 | * @param {String} name 41 | * @param {Function} callback 42 | */ 43 | on: function on(name, callback) { 44 | name = name.toLowerCase(); 45 | this._events || (this._events = {}); 46 | var events = this._events[name] || (this._events[name] = []); 47 | events.push({ 48 | callback: callback 49 | }); 50 | return this; 51 | }, 52 | /** 53 | * 触发事件 54 | * @param {String} name 55 | */ 56 | trigger: function trigger(name) { 57 | name = name.toLowerCase(); 58 | if (!this._events || !this._events[name]) return this; 59 | var args = Array.prototype.slice.call(arguments, 1); 60 | var events = this._events[name]; 61 | for (var i = 0, count = events.length; i < count; i++) { 62 | events[i].callback.apply(this, args); 63 | } 64 | return this; 65 | }, 66 | /** 67 | * 初始化 68 | */ 69 | init: function init() {}, 70 | /** 71 | * 渲染控件 72 | */ 73 | render: function render() {}, 74 | /** 75 | * 销毁控件 76 | */ 77 | destroy: function destroy() { 78 | delete this.element['comp']; 79 | this.element.innerHTML = ''; 80 | }, 81 | /** 82 | * 增加dom事件 83 | * @param {String} name 84 | * @param {Function} callback 85 | */ 86 | addDomEvent: function addDomEvent(name, callback) { 87 | (0, _event.on)(this.element, name, callback); 88 | return this; 89 | }, 90 | /** 91 | * 移除dom事件 92 | * @param {String} name 93 | */ 94 | removeDomEvent: function removeDomEvent(name, callback) { 95 | (0, _event.off)(this.element, name, callback); 96 | return this; 97 | }, 98 | setEnable: function setEnable(enable) { 99 | return this; 100 | }, 101 | /** 102 | * 判断是否为DOM事件 103 | */ 104 | isDomEvent: function isDomEvent(eventName) { 105 | if (this.element['on' + eventName] === undefined) return false;else return true; 106 | }, 107 | createDateAdapter: function createDateAdapter(options) { 108 | var opt = options['options'], 109 | model = options['model']; 110 | var Adapter = _compMgr.compMgr.getDataAdapter(this.compType, opt['dataType']); 111 | if (Adapter) { 112 | this.dataAdapter = new Adapter(this, options); 113 | } 114 | }, 115 | Statics: { 116 | compName: '', 117 | EVENT_VALUE_CHANGE: 'valueChange', 118 | getName: function getName() { 119 | return this.compName; 120 | } 121 | } 122 | }); 123 | 124 | function adjustDataType(options) { 125 | var types = ['integer', 'float', 'currency', 'percent', 'string', 'textarea']; 126 | var _type = options['type'], 127 | _dataType = options['dataType']; 128 | if (types.indexOf(_type) != -1) { 129 | options['dataType'] = _type; 130 | options['type'] = 'originText'; 131 | } 132 | } 133 | 134 | var BaseComponent = BaseComponent; 135 | 136 | exports.BaseComponent = BaseComponent; -------------------------------------------------------------------------------- /lib/core.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow core context 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 13:52:19 5 | */ 6 | import { extend } from './extend'; 7 | import { createShellObject } from './util'; 8 | import { getCookie, setCookie } from './cookies'; 9 | import { U_LANGUAGES, U_THEME, U_LOCALE, U_USERCODE } from './enumerables'; 10 | 11 | var environment = {}; 12 | /** 13 | * client attributes 14 | */ 15 | var clientAttributes = {}; 16 | 17 | var sessionAttributes = {}; 18 | 19 | var fn = {}; 20 | var maskerMeta = { 21 | 'float': { 22 | precision: 2 23 | }, 24 | 'datetime': { 25 | format: 'YYYY-MM-DD HH:mm:ss', 26 | metaType: 'DateTimeFormatMeta', 27 | speratorSymbol: '-' 28 | }, 29 | 'time': { 30 | format: 'HH:mm' 31 | }, 32 | 'date': { 33 | format: 'YYYY-MM-DD' 34 | }, 35 | 'currency': { 36 | precision: 2, 37 | curSymbol: '¥' 38 | }, 39 | 'percent': {}, 40 | 'phoneNumber': {} 41 | }; 42 | /** 43 | * 获取环境信息 44 | * @return {environment} 45 | */ 46 | fn.getEnvironment = function () { 47 | return createShellObject(environment); 48 | }; 49 | 50 | /** 51 | * 获取客户端参数对象 52 | * @return {clientAttributes} 53 | */ 54 | fn.getClientAttributes = function () { 55 | var exf = function exf() {}; 56 | return createShellObject(clientAttributes); 57 | }; 58 | 59 | fn.setContextPath = function (contextPath) { 60 | return environment[IWEB_CONTEXT_PATH] = contextPath; 61 | }; 62 | fn.getContextPath = function (contextPath) { 63 | return environment[IWEB_CONTEXT_PATH]; 64 | }; 65 | /** 66 | * 设置客户端参数对象 67 | * @param {Object} k 对象名称 68 | * @param {Object} v 对象值(建议使用简单类型) 69 | */ 70 | fn.setClientAttribute = function (k, v) { 71 | clientAttributes[k] = v; 72 | }; 73 | /** 74 | * 获取会话级参数对象 75 | * @return {clientAttributes} 76 | */ 77 | fn.getSessionAttributes = function () { 78 | var exf = function exf() {}; 79 | return createShellObject(sessionAttributes); 80 | }; 81 | 82 | /** 83 | * 设置会话级参数对象 84 | * @param {Object} k 对象名称 85 | * @param {Object} v 对象值(建议使用简单类型) 86 | */ 87 | fn.setSessionAttribute = function (k, v) { 88 | sessionAttributes[k] = v; 89 | setCookie("ISES_" + k, v); 90 | }; 91 | 92 | /** 93 | * 移除客户端参数 94 | * @param {Object} k 对象名称 95 | */ 96 | fn.removeClientAttribute = function (k) { 97 | clientAttributes[k] = null; 98 | execIgnoreError(function () { 99 | delete clientAttributes[k]; 100 | }); 101 | }; 102 | 103 | /** 104 | * 获取地区信息编码 105 | */ 106 | fn.getLocale = function () { 107 | return this.getEnvironment().locale; 108 | }; 109 | 110 | /** 111 | * 获取多语信息 112 | */ 113 | fn.getLanguages = function () { 114 | return this.getEnvironment().languages; 115 | }; 116 | /** 117 | * 收集环境信息(包括客户端参数) 118 | * @return {Object} 119 | */ 120 | fn.collectEnvironment = function () { 121 | var _env = this.getEnvironment(); 122 | var _ses = this.getSessionAttributes(); 123 | 124 | for (var i in clientAttributes) { 125 | _ses[i] = clientAttributes[i]; 126 | } 127 | _env.clientAttributes = _ses; 128 | return _env; 129 | }; 130 | 131 | /** 132 | * 设置数据格式信息 133 | * @param {String} type 134 | * @param {Object} meta 135 | */ 136 | fn.setMaskerMeta = function (type, meta) { 137 | if (typeof type == 'function') { 138 | getMetaFunc = type; 139 | } else { 140 | if (!maskerMeta[type]) maskerMeta[type] = meta;else { 141 | if ((typeof meta === 'undefined' ? 'undefined' : babelHelpers['typeof'](meta)) != 'object') maskerMeta[type] = meta;else for (var key in meta) { 142 | maskerMeta[type][key] = meta[key]; 143 | } 144 | } 145 | } 146 | }; 147 | fn.getMaskerMeta = function (type) { 148 | if (typeof getMetaFunc == 'function') { 149 | var meta = getMetaFunc.call(this); 150 | return meta[type]; 151 | } else return extend({}, maskerMeta[type]); 152 | }; 153 | environment.languages = getCookie(U_LANGUAGES) ? getCookie(U_LANGUAGES).split(',') : navigator.language ? navigator.language : 'zh-CN'; 154 | if (environment.languages == 'zh-cn') environment.languages = 'zh-CN'; 155 | if (environment.languages == 'en-us') environment.languages = 'en-US'; 156 | 157 | environment.theme = getCookie(U_THEME); 158 | environment.locale = getCookie(U_LOCALE); 159 | //environment.timezoneOffset = (new Date()).getTimezoneOffset() 160 | environment.usercode = getCookie(U_USERCODE); 161 | //init session attribute 162 | document.cookie.replace(/ISES_(\w*)=([^;]*);?/ig, function (a, b, c) { 163 | sessionAttributes[b] = c; 164 | }); 165 | 166 | var Core = function Core() {}; 167 | Core.prototype = fn; 168 | 169 | var core = new Core(); 170 | 171 | export { core }; -------------------------------------------------------------------------------- /src/core.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow core context 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 13:52:19 5 | */ 6 | import {extend} from './extend'; 7 | import {createShellObject} from './util'; 8 | import {getCookie,setCookie} from './cookies'; 9 | import {U_LANGUAGES,U_THEME,U_LOCALE,U_USERCODE} from './enumerables' 10 | 11 | 12 | var environment = {}; 13 | /** 14 | * client attributes 15 | */ 16 | var clientAttributes = {}; 17 | 18 | var sessionAttributes = {}; 19 | 20 | var fn = {}; 21 | var maskerMeta = { 22 | 'float': { 23 | precision: 2 24 | }, 25 | 'datetime': { 26 | format: 'YYYY-MM-DD HH:mm:ss', 27 | metaType: 'DateTimeFormatMeta', 28 | speratorSymbol: '-' 29 | }, 30 | 'time': { 31 | format: 'HH:mm' 32 | }, 33 | 'date': { 34 | format: 'YYYY-MM-DD' 35 | }, 36 | 'currency': { 37 | precision: 2, 38 | curSymbol: '¥' 39 | }, 40 | 'percent': { 41 | 42 | }, 43 | 'phoneNumber': { 44 | 45 | } 46 | }; 47 | /** 48 | * 获取环境信息 49 | * @return {environment} 50 | */ 51 | fn.getEnvironment = function() { 52 | return createShellObject(environment); 53 | }; 54 | 55 | /** 56 | * 获取客户端参数对象 57 | * @return {clientAttributes} 58 | */ 59 | fn.getClientAttributes = function() { 60 | var exf = function() {} 61 | return createShellObject(clientAttributes); 62 | } 63 | 64 | fn.setContextPath = function(contextPath) { 65 | return environment[IWEB_CONTEXT_PATH] = contextPath 66 | } 67 | fn.getContextPath = function(contextPath) { 68 | return environment[IWEB_CONTEXT_PATH] 69 | } 70 | /** 71 | * 设置客户端参数对象 72 | * @param {Object} k 对象名称 73 | * @param {Object} v 对象值(建议使用简单类型) 74 | */ 75 | fn.setClientAttribute = function(k, v) { 76 | clientAttributes[k] = v; 77 | } 78 | /** 79 | * 获取会话级参数对象 80 | * @return {clientAttributes} 81 | */ 82 | fn.getSessionAttributes = function() { 83 | var exf = function() {} 84 | return createShellObject(sessionAttributes); 85 | } 86 | 87 | /** 88 | * 设置会话级参数对象 89 | * @param {Object} k 对象名称 90 | * @param {Object} v 对象值(建议使用简单类型) 91 | */ 92 | fn.setSessionAttribute = function(k, v) { 93 | sessionAttributes[k] = v; 94 | setCookie("ISES_" + k, v); 95 | } 96 | 97 | /** 98 | * 移除客户端参数 99 | * @param {Object} k 对象名称 100 | */ 101 | fn.removeClientAttribute = function(k) { 102 | clientAttributes[k] = null; 103 | execIgnoreError(function() { 104 | delete clientAttributes[k]; 105 | }) 106 | } 107 | 108 | /** 109 | * 获取地区信息编码 110 | */ 111 | fn.getLocale = function() { 112 | return this.getEnvironment().locale 113 | } 114 | 115 | /** 116 | * 获取多语信息 117 | */ 118 | fn.getLanguages = function() { 119 | return this.getEnvironment().languages 120 | }; 121 | /** 122 | * 收集环境信息(包括客户端参数) 123 | * @return {Object} 124 | */ 125 | fn.collectEnvironment = function() { 126 | var _env = this.getEnvironment(); 127 | var _ses = this.getSessionAttributes(); 128 | 129 | for(var i in clientAttributes) { 130 | _ses[i] = clientAttributes[i]; 131 | } 132 | _env.clientAttributes = _ses; 133 | return _env 134 | } 135 | 136 | /** 137 | * 设置数据格式信息 138 | * @param {String} type 139 | * @param {Object} meta 140 | */ 141 | fn.setMaskerMeta = function(type, meta) { 142 | if(typeof type == 'function') { 143 | getMetaFunc = type; 144 | } else { 145 | if(!maskerMeta[type]) 146 | maskerMeta[type] = meta; 147 | else { 148 | if(typeof meta != 'object') 149 | maskerMeta[type] = meta; 150 | else 151 | for(var key in meta) { 152 | maskerMeta[type][key] = meta[key]; 153 | } 154 | } 155 | } 156 | }; 157 | fn.getMaskerMeta = function(type) { 158 | if(typeof getMetaFunc == 'function') { 159 | var meta = getMetaFunc.call(this); 160 | return meta[type]; 161 | } else 162 | return extend({}, maskerMeta[type]); 163 | }; 164 | environment.languages = getCookie(U_LANGUAGES) ? getCookie(U_LANGUAGES).split(',') : navigator.language ? navigator.language : 'zh-CN'; 165 | if(environment.languages == 'zh-cn') 166 | environment.languages = 'zh-CN' 167 | if(environment.languages == 'en-us') 168 | environment.languages = 'en-US' 169 | 170 | environment.theme = getCookie(U_THEME); 171 | environment.locale = getCookie(U_LOCALE); 172 | //environment.timezoneOffset = (new Date()).getTimezoneOffset() 173 | environment.usercode = getCookie(U_USERCODE); 174 | //init session attribute 175 | document.cookie.replace(/ISES_(\w*)=([^;]*);?/ig, function(a, b, c) { 176 | sessionAttributes[b] = c; 177 | }); 178 | 179 | var Core = function() {}; 180 | Core.prototype = fn; 181 | 182 | var core = new Core(); 183 | 184 | export { core }; 185 | -------------------------------------------------------------------------------- /snippets/method.md: -------------------------------------------------------------------------------- 1 | ## 方法扩展 2 | 3 | ### extend(object, config) 4 | * 说明: 5 | 6 | 复制对象属性 7 | 8 | * 参数: 9 | * {Object} object:必需。目标对象 10 | * {Object} config:必需。源对象 11 | * 返回值: 12 | 13 | {Object}复制之后的object 14 | * 用法:​ 15 | var obj1 = { 16 | id : 'id', 17 | name : 'name' 18 | } 19 | var obj2 = { 20 | code : 'code', 21 | name : 'newName' 22 | } 23 | u.extend(obj1, obj2); //obj1为{id: "id", name: "newName", code: "code"} 24 | 25 | ### setCookie(sName, sValue, oExpires, sPath, sDomain, bSecure) 26 | * 说明: 27 | 28 | 设置cookie属性 29 | 30 | * 参数: 31 | * {String} sName:必需。规定 cookie 的名称。 32 | * {String} sValue:必需。规定 cookie 的值。 33 | * {String} oExpires:可选。规定 cookie 的有效期。 34 | * {String} sPath:可选。规定 cookie 的服务器路径。 35 | * {String} sDomain:可选。规定 cookie 的域名。 36 | * {String} bSecure:可选。规定是否通过安全的 HTTPS 连接来传输 cookie。 37 | * 返回值: 38 | 39 | 无 40 | * 用法: 41 | u.setCookie('COOKIENAME', 'COOKIVALUE'); //设置cookie的COOKIENAME为COOKIVALUE 42 | 43 | ### getCookie(sName) 44 | * 说明: 45 | 46 | 获取cookie属性 47 | 48 | 49 | * 参数: 50 | * {String} sName:必需。获取 cookie 的名称。 51 | * 返回值: 52 | 53 | cookie中sName对应的属性 54 | * 用法:​​ 55 | u.getCookie('COOKIENAME'); //获取cookie的COOKIENAME 56 | 57 | ### getFunction(target, val) 58 | * 说明: 59 | 60 | 获取function 61 | 62 | * 参数: 63 | 64 | * {Object} target:必需。function定义的上下文。 65 | * {String} value:必需。function名称。 66 | * 返回值: 67 | 68 | {function}获取到的function 69 | * 用法: 70 | ​ 71 | u.getFunction(window,'funName1'); 72 | 73 | 74 | ### getJSObject(target, names) 75 | * 说明: 76 | 77 | 获取Object对象 78 | 79 | * 参数: 80 | 81 | * {Object} target:必需。Object定义的上下文。 82 | * {String} names:必需。Objcet名称。 83 | * 返回值: 84 | 85 | {Object}获取到的Object 86 | * 用法:​ 87 | u.getJSObject(window,'funName1'); //获取window对象上的funName1对象 88 | 89 | 90 | ### each(obj,callback) 91 | * 说明: 92 | 93 | 遍历传入的obj执行callback方法 94 | 95 | * 参数: 96 | 97 | * {Object}/{Array} obj:必需。需要进行遍历的对象或数组。 98 | * {function} callback:必需。需要执行的function。 99 | * 返回值: 100 | 101 | 无 102 | * 用法:​ 103 | var tmpdata = []; 104 | u.each(target_div.querySelectorAll(".m_context"),function(i,node){ 105 | tmpdata[i] = node.innerHTML 106 | }) 107 | //遍历将class为m_context的HTML的内容翻入数组tmpdata中。 108 | 109 | 110 | ### getStyle(element,key) 111 | * 说明: 112 | 113 | 获取HTML元素的style属性。 114 | 115 | * 参数: 116 | * {HTMLElement} element:必需。HTML元素。 117 | * {String} key:必需。需要获取的style属性名称。 118 | * 返回值: 119 | 120 | HTML元素的style属性值 121 | * 用法:​ 122 | u.getStyle(document.getElementById('id1'), 'width'); 123 | 124 | ### getZIndex() 125 | * 说明: 126 | 127 | 统一zindex值, 不同控件每次显示时都取最大的zindex,防止显示错乱 128 | 129 | * 参数: 130 | 131 | 无 132 | 133 | * 返回值: 134 | 135 | 新的zindex最大值 136 | * 用法:​ 137 | u.getZIndex(); 138 | 139 | 140 | 141 | 142 | ### getOffset(ele, offset) 143 | * 说明: 144 | 145 | 获取/设置元素`ele`相对顶层`body`的偏移量 146 | 147 | * 参数: 148 | * {HTMLElement} element:必需。目标对象 149 | * {Object} config:可选。设置的元素偏移量。默认则最终返回`ele`相对`body`的偏移量 150 | * 返回值: 151 | 152 | {Object}:包含`top`,`left`值 153 | * 用法: 154 | var offsetObj = { 155 | top : 10, 156 | left : 20 157 | }; 158 | var ele = document.getElementById('tit'); 159 | 160 | u.getOffset(ele,offsetObj) // {top: 120, left:100} 161 | 162 | 163 | 164 | ### getScroll(ele, offset) 165 | 166 | - 说明: 167 | 168 | 获取/设置元素`ele`滚动的偏移量 169 | 170 | - 参数: 171 | 172 | - {HTMLElement} element:必需。目标对象 173 | - {Object} config:可选。设置的元素偏移量。默认则最终返回`ele`相对浏览器顶部的偏移量 174 | 175 | - 返回值: 176 | 177 | {Object}:包含`top`,`left`值 178 | 179 | - 用法: 180 | 181 | ``` 182 | 同getOffset 183 | ``` 184 | 185 | 186 | 187 | ### ajax({...}) 188 | 189 | - 说明: 190 | 191 | 执行Ajax数交互 192 | 193 | - 参数: 194 | 195 | ``` 196 | { 197 | url: 'test.html', 198 | type: 'GET' 199 | success: function(){}, 200 | async: true, 201 | error: function(){}, 202 | } 203 | ``` 204 | 205 | ​ 206 | 207 | - {String} url:必需,文件在服务器上的位置 208 | - {String} type:可选,默认为`post` 209 | - {Function} success:可选,回调函数 210 | - {Function} error:可选,回调函数 211 | - {Boolean} async: 可选,默认为`true` 212 | 213 | - 返回值: 214 | 215 | {Object} 216 | 217 | - 用法: 218 | 219 | ``` 220 | 221 | document.getElementById('btn').addEventListener('click', function(){ 222 | u.ajax({ 223 | url: './package.json', 224 | type: 'GET', 225 | success: function(data){ 226 | alert(data) 227 | }, 228 | error: function(){ 229 | alert("error") 230 | } 231 | }) 232 | }) 233 | ``` 234 | -------------------------------------------------------------------------------- /docs/method.md: -------------------------------------------------------------------------------- 1 | # 方法扩展 2 | 3 | ## # extend(object, config) 4 | * 说明: 5 | 6 | 复制对象属性 7 | 8 | * 参数: 9 | * {Object} object:必需。目标对象 10 | * {Object} config:必需。源对象 11 | * 返回值: 12 | 13 | {Object}复制之后的object 14 | * 用法:​ 15 | var obj1 = { 16 | id : 'id', 17 | name : 'name' 18 | } 19 | var obj2 = { 20 | code : 'code', 21 | name : 'newName' 22 | } 23 | u.extend(obj1, obj2); //obj1为{id: "id", name: "newName", code: "code"} 24 | 25 | ## # setCookie(sName, sValue, oExpires, sPath, sDomain, bSecure) 26 | * 说明: 27 | 28 | 设置cookie属性 29 | 30 | * 参数: 31 | * {String} sName:必需。规定 cookie 的名称。 32 | * {String} sValue:必需。规定 cookie 的值。 33 | * {String} oExpires:可选。规定 cookie 的有效期。 34 | * {String} sPath:可选。规定 cookie 的服务器路径。 35 | * {String} sDomain:可选。规定 cookie 的域名。 36 | * {String} bSecure:可选。规定是否通过安全的 HTTPS 连接来传输 cookie。 37 | * 返回值: 38 | 39 | 无 40 | * 用法: 41 | u.setCookie('COOKIENAME', 'COOKIVALUE'); //设置cookie的COOKIENAME为COOKIVALUE 42 | 43 | ## # getCookie(sName) 44 | * 说明: 45 | 46 | 获取cookie属性 47 | 48 | 49 | * 参数: 50 | * {String} sName:必需。获取 cookie 的名称。 51 | * 返回值: 52 | 53 | cookie中sName对应的属性 54 | * 用法:​​ 55 | u.getCookie('COOKIENAME'); //获取cookie的COOKIENAME 56 | 57 | ## # getFunction(target, val) 58 | * 说明: 59 | 60 | 获取function 61 | 62 | * 参数: 63 | 64 | * {Object} target:必需。function定义的上下文。 65 | * {String} value:必需。function名称。 66 | * 返回值: 67 | 68 | {function}获取到的function 69 | * 用法: 70 | ​ 71 | u.getFunction(window,'funName1'); 72 | 73 | 74 | ## # getJSObject(target, names) 75 | * 说明: 76 | 77 | 获取Object对象 78 | 79 | * 参数: 80 | 81 | * {Object} target:必需。Object定义的上下文。 82 | * {String} names:必需。Objcet名称。 83 | * 返回值: 84 | 85 | {Object}获取到的Object 86 | * 用法:​ 87 | u.getJSObject(window,'funName1'); //获取window对象上的funName1对象 88 | 89 | 90 | ## # each(obj,callback) 91 | * 说明: 92 | 93 | 遍历传入的obj执行callback方法 94 | 95 | * 参数: 96 | 97 | * {Object}/{Array} obj:必需。需要进行遍历的对象或数组。 98 | * {function} callback:必需。需要执行的function。 99 | * 返回值: 100 | 101 | 无 102 | * 用法:​ 103 | var tmpdata = []; 104 | u.each(target_div.querySelectorAll(".m_context"),function(i,node){ 105 | tmpdata[i] = node.innerHTML 106 | }) 107 | //遍历将class为m_context的HTML的内容翻入数组tmpdata中。 108 | 109 | 110 | ## # getStyle(element,key) 111 | * 说明: 112 | 113 | 获取HTML元素的style属性。 114 | 115 | * 参数: 116 | * {HTMLElement} element:必需。HTML元素。 117 | * {String} key:必需。需要获取的style属性名称。 118 | * 返回值: 119 | 120 | HTML元素的style属性值 121 | * 用法:​ 122 | u.getStyle(document.getElementById('id1'), 'width'); 123 | 124 | ## # getZIndex() 125 | * 说明: 126 | 127 | 统一zindex值, 不同控件每次显示时都取最大的zindex,防止显示错乱 128 | 129 | * 参数: 130 | 131 | 无 132 | 133 | * 返回值: 134 | 135 | 新的zindex最大值 136 | * 用法:​ 137 | u.getZIndex(); 138 | 139 | 140 | 141 | 142 | ## # getOffset(ele, offset) 143 | * 说明: 144 | 145 | 获取/设置元素`ele`相对顶层`body`的偏移量 146 | 147 | * 参数: 148 | * {HTMLElement} element:必需。目标对象 149 | * {Object} config:可选。设置的元素偏移量。默认则最终返回`ele`相对`body`的偏移量 150 | * 返回值: 151 | 152 | {Object}:包含`top`,`left`值 153 | * 用法: 154 | var offsetObj = { 155 | top : 10, 156 | left : 20 157 | }; 158 | var ele = document.getElementById('tit'); 159 | 160 | u.getOffset(ele,offsetObj) // {top: 120, left:100} 161 | 162 | 163 | 164 | ## # getScroll(ele, offset) 165 | 166 | - 说明: 167 | 168 | 获取/设置元素`ele`滚动的偏移量 169 | 170 | - 参数: 171 | 172 | - {HTMLElement} element:必需。目标对象 173 | - {Object} config:可选。设置的元素偏移量。默认则最终返回`ele`相对浏览器顶部的偏移量 174 | 175 | - 返回值: 176 | 177 | {Object}:包含`top`,`left`值 178 | 179 | - 用法: 180 | 181 | ``` 182 | 同getOffset 183 | ``` 184 | 185 | 186 | 187 | ## # ajax({...}) 188 | 189 | - 说明: 190 | 191 | 执行Ajax数交互 192 | 193 | - 参数: 194 | 195 | ``` 196 | { 197 | url: 'test.html', 198 | type: 'GET' 199 | success: function(){}, 200 | async: true, 201 | error: function(){}, 202 | } 203 | ``` 204 | 205 | ​ 206 | 207 | - {String} url:必需,文件在服务器上的位置 208 | - {String} type:可选,默认为`post` 209 | - {Function} success:可选,回调函数 210 | - {Function} error:可选,回调函数 211 | - {Boolean} async: 可选,默认为`true` 212 | 213 | - 返回值: 214 | 215 | {Object} 216 | 217 | - 用法: 218 | 219 | ``` 220 | 221 | document.getElementById('btn').addEventListener('click', function(){ 222 | u.ajax({ 223 | url: './package.json', 224 | type: 'GET', 225 | success: function(data){ 226 | alert(data) 227 | }, 228 | error: function(){ 229 | alert("error") 230 | } 231 | }) 232 | }) 233 | ``` 234 | 235 | -------------------------------------------------------------------------------- /src/class.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow class 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 08:45:39 5 | */ 6 | 7 | var Class = function(o) { 8 | if(!(this instanceof Class) && isFunction(o)) { 9 | return classify(o); 10 | } 11 | } 12 | 13 | // Create a new Class. 14 | // 15 | // var SuperPig = Class.create({ 16 | // Extends: Animal, 17 | // Implements: Flyable, 18 | // initialize: function() { 19 | // SuperPig.superclass.initialize.apply(this, arguments) 20 | // }, 21 | // Statics: { 22 | // COLOR: 'red' 23 | // } 24 | // }) 25 | // 26 | Class.create = function(parent, properties) { 27 | if(!isFunction(parent)) { 28 | properties = parent; 29 | parent = null; 30 | } 31 | 32 | properties || (properties = {}); 33 | parent || (parent = properties.Extends || Class); 34 | properties.Extends = parent; 35 | 36 | // The created class constructor 37 | function SubClass() { 38 | var ret; 39 | // Call the parent constructor. 40 | parent.apply(this, arguments); 41 | 42 | // Only call initialize in self constructor. 43 | if(this.constructor === SubClass && this.initialize) { 44 | ret = this.initialize.apply(this, arguments); 45 | } 46 | return ret ? ret : this; 47 | } 48 | 49 | // Inherit class (static) properties from parent. 50 | if(parent !== Class) { 51 | mix(SubClass, parent, parent.StaticsWhiteList); 52 | } 53 | 54 | // Add instance properties to the subclass. 55 | implement.call(SubClass, properties); 56 | 57 | // Make subclass extendable. 58 | return classify(SubClass); 59 | } 60 | 61 | function implement(properties) { 62 | var key, value 63 | 64 | for(key in properties) { 65 | value = properties[key]; 66 | 67 | if(Class.Mutators.hasOwnProperty(key)) { 68 | Class.Mutators[key].call(this, value); 69 | } else { 70 | this.prototype[key] = value; 71 | } 72 | } 73 | } 74 | 75 | // Create a sub Class based on `Class`. 76 | Class.extend = function(properties) { 77 | properties || (properties = {}); 78 | properties.Extends = this; 79 | 80 | return Class.create(properties); 81 | } 82 | 83 | function classify(cls) { 84 | cls.extend = Class.extend; 85 | cls.implement = implement; 86 | return cls; 87 | } 88 | 89 | // Mutators define special properties. 90 | Class.Mutators = { 91 | 92 | 'Extends': function(parent) { 93 | var existed = this.prototype; 94 | var proto = createProto(parent.prototype); 95 | 96 | // Keep existed properties. 97 | mix(proto, existed); 98 | 99 | // Enforce the constructor to be what we expect. 100 | proto.constructor = this; 101 | 102 | // Set the prototype chain to inherit from `parent`. 103 | this.prototype = proto; 104 | 105 | // Set a convenience property in case the parent's prototype is 106 | // needed later. 107 | this.superclass = parent.prototype; 108 | }, 109 | 110 | 'Implements': function(items) { 111 | isArray(items) || (items = [items]); 112 | var proto = this.prototype, 113 | item; 114 | 115 | while(item = items.shift()) { 116 | mix(proto, item.prototype || item); 117 | } 118 | }, 119 | 120 | 'Statics': function(staticProperties) { 121 | mix(this, staticProperties); 122 | } 123 | } 124 | 125 | // Shared empty constructor function to aid in prototype-chain creation. 126 | function Ctor() {} 127 | 128 | // See: http://jsperf.com/object-create-vs-new-ctor 129 | var createProto = Object.__proto__ ? 130 | function(proto) { 131 | return { 132 | __proto__: proto 133 | } 134 | } : 135 | function(proto) { 136 | Ctor.prototype = proto; 137 | return new Ctor(); 138 | } 139 | 140 | // Helpers 141 | // ------------ 142 | 143 | function mix(r, s, wl) { 144 | // Copy "all" properties including inherited ones. 145 | for(var p in s) { 146 | if(s.hasOwnProperty(p)) { 147 | if(wl && indexOf(wl, p) === -1) continue; 148 | 149 | // 在 iPhone 1 代等设备的 Safari 中,prototype 也会被枚举出来,需排除 150 | if(p !== 'prototype') { 151 | r[p] = s[p]; 152 | } 153 | } 154 | } 155 | } 156 | 157 | var toString = Object.prototype.toString; 158 | 159 | var isArray = Array.isArray || function(val) { 160 | return toString.call(val) === '[object Array]'; 161 | } 162 | 163 | var isFunction = function(val) { 164 | return toString.call(val) === '[object Function]'; 165 | } 166 | 167 | var indexOf = function(arr, item) { 168 | if(Array.prototype.indexOf && arr.indexOf) { 169 | return arr.indexOf(item); 170 | } else { 171 | for(var i = 0, len = arr.length; i < len; i++) { 172 | if(arr[i] === item) { 173 | return i; 174 | } 175 | } 176 | return -1; 177 | } 178 | } 179 | 180 | export { 181 | Class, 182 | isFunction 183 | }; -------------------------------------------------------------------------------- /lib/class.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow class 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 08:45:39 5 | */ 6 | 7 | var Class = function Class(o) { 8 | if (!(this instanceof Class) && isFunction(o)) { 9 | return classify(o); 10 | } 11 | }; 12 | 13 | // Create a new Class. 14 | // 15 | // var SuperPig = Class.create({ 16 | // Extends: Animal, 17 | // Implements: Flyable, 18 | // initialize: function() { 19 | // SuperPig.superclass.initialize.apply(this, arguments) 20 | // }, 21 | // Statics: { 22 | // COLOR: 'red' 23 | // } 24 | // }) 25 | // 26 | Class.create = function (parent, properties) { 27 | if (!isFunction(parent)) { 28 | properties = parent; 29 | parent = null; 30 | } 31 | 32 | properties || (properties = {}); 33 | parent || (parent = properties.Extends || Class); 34 | properties.Extends = parent; 35 | 36 | // The created class constructor 37 | function SubClass() { 38 | var ret; 39 | // Call the parent constructor. 40 | parent.apply(this, arguments); 41 | 42 | // Only call initialize in self constructor. 43 | if (this.constructor === SubClass && this.initialize) { 44 | ret = this.initialize.apply(this, arguments); 45 | } 46 | return ret ? ret : this; 47 | } 48 | 49 | // Inherit class (static) properties from parent. 50 | if (parent !== Class) { 51 | mix(SubClass, parent, parent.StaticsWhiteList); 52 | } 53 | 54 | // Add instance properties to the subclass. 55 | implement.call(SubClass, properties); 56 | 57 | // Make subclass extendable. 58 | return classify(SubClass); 59 | }; 60 | 61 | function implement(properties) { 62 | var key, value; 63 | 64 | for (key in properties) { 65 | value = properties[key]; 66 | 67 | if (Class.Mutators.hasOwnProperty(key)) { 68 | Class.Mutators[key].call(this, value); 69 | } else { 70 | this.prototype[key] = value; 71 | } 72 | } 73 | } 74 | 75 | // Create a sub Class based on `Class`. 76 | Class.extend = function (properties) { 77 | properties || (properties = {}); 78 | properties.Extends = this; 79 | 80 | return Class.create(properties); 81 | }; 82 | 83 | function classify(cls) { 84 | cls.extend = Class.extend; 85 | cls.implement = implement; 86 | return cls; 87 | } 88 | 89 | // Mutators define special properties. 90 | Class.Mutators = { 91 | 92 | 'Extends': function Extends(parent) { 93 | var existed = this.prototype; 94 | var proto = createProto(parent.prototype); 95 | 96 | // Keep existed properties. 97 | mix(proto, existed); 98 | 99 | // Enforce the constructor to be what we expect. 100 | proto.constructor = this; 101 | 102 | // Set the prototype chain to inherit from `parent`. 103 | this.prototype = proto; 104 | 105 | // Set a convenience property in case the parent's prototype is 106 | // needed later. 107 | this.superclass = parent.prototype; 108 | }, 109 | 110 | 'Implements': function Implements(items) { 111 | isArray(items) || (items = [items]); 112 | var proto = this.prototype, 113 | item; 114 | 115 | while (item = items.shift()) { 116 | mix(proto, item.prototype || item); 117 | } 118 | }, 119 | 120 | 'Statics': function Statics(staticProperties) { 121 | mix(this, staticProperties); 122 | } 123 | 124 | // Shared empty constructor function to aid in prototype-chain creation. 125 | };function Ctor() {} 126 | 127 | // See: http://jsperf.com/object-create-vs-new-ctor 128 | var createProto = Object.__proto__ ? function (proto) { 129 | return { 130 | __proto__: proto 131 | }; 132 | } : function (proto) { 133 | Ctor.prototype = proto; 134 | return new Ctor(); 135 | }; 136 | 137 | // Helpers 138 | // ------------ 139 | 140 | function mix(r, s, wl) { 141 | // Copy "all" properties including inherited ones. 142 | for (var p in s) { 143 | if (s.hasOwnProperty(p)) { 144 | if (wl && indexOf(wl, p) === -1) continue; 145 | 146 | // 在 iPhone 1 代等设备的 Safari 中,prototype 也会被枚举出来,需排除 147 | if (p !== 'prototype') { 148 | r[p] = s[p]; 149 | } 150 | } 151 | } 152 | } 153 | 154 | var toString = Object.prototype.toString; 155 | 156 | var isArray = Array.isArray || function (val) { 157 | return toString.call(val) === '[object Array]'; 158 | }; 159 | 160 | var isFunction = function isFunction(val) { 161 | return toString.call(val) === '[object Function]'; 162 | }; 163 | 164 | var indexOf = function indexOf(arr, item) { 165 | if (Array.prototype.indexOf && arr.indexOf) { 166 | return arr.indexOf(item); 167 | } else { 168 | for (var i = 0, len = arr.length; i < len; i++) { 169 | if (arr[i] === item) { 170 | return i; 171 | } 172 | } 173 | return -1; 174 | } 175 | }; 176 | 177 | export { Class, isFunction }; -------------------------------------------------------------------------------- /lib/fetch.js: -------------------------------------------------------------------------------- 1 | import { extend } from './extend'; 2 | var getHost = function getHost() { 3 | var key = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'api'; 4 | 5 | var hosts = { 6 | api: { 7 | production: process.env.HOST || "", 8 | development: process.env.HOST || "" 9 | } 10 | }; 11 | return hosts[key][process.env.NODE_ENV]; 12 | }; 13 | 14 | var fetchTools = { 15 | params: function params(_params) { 16 | try { 17 | return Object.keys(_params).map(function (key) { 18 | var param = _params[key]; 19 | switch (typeof param === 'undefined' ? 'undefined' : babelHelpers['typeof'](param)) { 20 | case 'object': 21 | param = escape(JSON.stringify(param)); 22 | break; 23 | case 'undefined': 24 | param = ''; 25 | break; 26 | default: 27 | break; 28 | } 29 | return key + '=' + param; 30 | }).join('&'); 31 | } catch (e) { 32 | console.log('error in urlParams'); 33 | return ''; 34 | } 35 | }, 36 | fetch: function (_fetch) { 37 | function fetch(_x2, _x3) { 38 | return _fetch.apply(this, arguments); 39 | } 40 | 41 | fetch.toString = function () { 42 | return _fetch.toString(); 43 | }; 44 | 45 | return fetch; 46 | }(function (url, options) { 47 | return fetch(url, options).then(function (response) { 48 | if (response.ok) { 49 | return response.text().then(function (text) { 50 | if (text) { 51 | var result = { 52 | success: false, 53 | message: '接口请求失败' 54 | }; 55 | try { 56 | result = JSON.parse(text); 57 | } catch (e) { 58 | return Promise.reject(new Error('接口返回数据无法解析')); 59 | } 60 | var _result = result, 61 | success = _result.success, 62 | data = _result.data, 63 | message = _result.message; 64 | 65 | if (success) { 66 | return Promise.resolve(data); 67 | } 68 | return Promise.reject(message); 69 | } 70 | return Promise.reject(new Error('接口未返回数据')); 71 | }); 72 | } 73 | return Promise.reject(new Error('请求失败')); 74 | }); 75 | }), 76 | options: function options() { 77 | var method = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'get'; 78 | 79 | var _options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 80 | 81 | return extend({ 82 | method: method.toUpperCase(), 83 | credentials: 'include', 84 | cache: 'no-cache', 85 | headers: { 86 | 'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8', 87 | 'isAjax': 1 88 | } 89 | }, _options); 90 | }, 91 | urlMaker: function urlMaker(url) { 92 | if (!url) { 93 | throw new Error('has no url!'); 94 | } else if (url.indexOf('http') !== 0) { 95 | url = '' + getHost() + url; 96 | } 97 | return url; 98 | } 99 | }; 100 | 101 | export function post(oriUrl) { 102 | var oriParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 103 | var params = fetchTools.params, 104 | fetch = fetchTools.fetch, 105 | optionsMaker = fetchTools.options, 106 | urlMaker = fetchTools.urlMaker; 107 | 108 | var data = params(oriParams); 109 | var options = optionsMaker('post'); 110 | options.headers['Content-Type'] = 'application/json;charset=UTF-8'; 111 | try { 112 | options.body = JSON.stringify(oriParams); 113 | } catch (e) { 114 | return Promise.reject(e); 115 | } 116 | return fetch(urlMaker(oriUrl), options); 117 | } 118 | 119 | export function get(oriUrl) { 120 | var oriParams = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; 121 | var params = fetchTools.params, 122 | fetch = fetchTools.fetch, 123 | options = fetchTools.options, 124 | urlMaker = fetchTools.urlMaker; 125 | 126 | 127 | var data = params(oriParams); 128 | var url = urlMaker(oriUrl); 129 | if (data) { 130 | url = url + '?' + data; 131 | } 132 | return fetch(url, options()); 133 | } -------------------------------------------------------------------------------- /src/env.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow browser environment 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | import {extend} from './extend'; 8 | var u = {}; 9 | 10 | 11 | extend(u, { 12 | isIE: false, 13 | isFF: false, 14 | isOpera: false, 15 | isChrome: false, 16 | isSafari: false, 17 | isWebkit: false, 18 | isIE8_BEFORE: false, 19 | isIE8: false, 20 | isIE8_CORE: false, 21 | isIE9: false, 22 | isIE9_CORE: false, 23 | isIE10: false, 24 | isIE10_ABOVE: false, 25 | isIE11: false, 26 | isEdge: false, 27 | isIOS: false, 28 | isIphone: false, 29 | isIPAD: false, 30 | isStandard: false, 31 | version: 0, 32 | isWin: false, 33 | isUnix: false, 34 | isLinux: false, 35 | isAndroid: false, 36 | isAndroidPAD:false, 37 | isAndroidPhone:false, 38 | isMac: false, 39 | hasTouch: false, 40 | isMobile: false 41 | }); 42 | 43 | (function() { 44 | var userAgent = navigator.userAgent, 45 | rMsie = /(msie\s|trident.*rv:)([\w.]+)/, 46 | rFirefox = /(firefox)\/([\w.]+)/, 47 | rOpera = /(opera).+version\/([\w.]+)/, 48 | rChrome = /(chrome)\/([\w.]+)/, 49 | rSafari = /version\/([\w.]+).*(safari)/, 50 | version, 51 | ua = userAgent.toLowerCase(), 52 | s, 53 | browserMatch = { 54 | browser: "", 55 | version: '' 56 | }, 57 | match = rMsie.exec(ua); 58 | 59 | if(match != null) { 60 | browserMatch = { 61 | browser: "IE", 62 | version: match[2] || "0" 63 | }; 64 | } 65 | match = rFirefox.exec(ua); 66 | if(match != null) { 67 | browserMatch = { 68 | browser: match[1] || "", 69 | version: match[2] || "0" 70 | }; 71 | } 72 | match = rOpera.exec(ua); 73 | if(match != null) { 74 | browserMatch = { 75 | browser: match[1] || "", 76 | version: match[2] || "0" 77 | }; 78 | } 79 | match = rChrome.exec(ua); 80 | if(match != null) { 81 | browserMatch = { 82 | browser: match[1] || "", 83 | version: match[2] || "0" 84 | }; 85 | } 86 | match = rSafari.exec(ua); 87 | if(match != null) { 88 | browserMatch = { 89 | browser: match[2] || "", 90 | version: match[1] || "0" 91 | }; 92 | } 93 | 94 | if(userAgent.indexOf("Edge") > -1){ 95 | u.isEdge = true; 96 | } 97 | if(s = ua.match(/opera.([\d.]+)/)) { 98 | u.isOpera = true; 99 | } else if(browserMatch.browser == "IE" && browserMatch.version == 11) { 100 | u.isIE11 = true; 101 | u.isIE = true; 102 | } else if(s = ua.match(/chrome\/([\d.]+)/)) { 103 | u.isChrome = true; 104 | u.isStandard = true; 105 | } else if(s = ua.match(/version\/([\d.]+).*safari/)) { 106 | u.isSafari = true; 107 | u.isStandard = true; 108 | } else if(s = ua.match(/gecko/)) { 109 | //add by licza : support XULRunner 110 | u.isFF = true; 111 | u.isStandard = true; 112 | } else if(s = ua.match(/msie ([\d.]+)/)) { 113 | u.isIE = true; 114 | } else if(s = ua.match(/firefox\/([\d.]+)/)) { 115 | u.isFF = true; 116 | u.isStandard = true; 117 | } 118 | if(ua.match(/webkit\/([\d.]+)/)) { 119 | u.isWebkit = true; 120 | } 121 | if(ua.match(/ipad/i)) { 122 | u.isIOS = true; 123 | u.isIPAD = true; 124 | u.isStandard = true; 125 | } 126 | 127 | if(ua.match(/iphone/i)) { 128 | u.isIOS = true; 129 | u.isIphone = true; 130 | } 131 | 132 | if((navigator.platform == "Mac68K") || (navigator.platform == "MacPPC") || (navigator.platform == "Macintosh") || (navigator.platform == "MacIntel")) { 133 | //u.isIOS = true; 134 | u.isMac = true; 135 | } 136 | 137 | if((navigator.platform == "Win32") || (navigator.platform == "Windows") || (navigator.platform == "Win64")) { 138 | u.isWin = true; 139 | } 140 | 141 | if((navigator.platform == "X11") && !u.isWin && !u.isMac) { 142 | u.isUnix = true; 143 | } 144 | if((String(navigator.platform).indexOf("Linux") > -1)) { 145 | u.isLinux = true; 146 | } 147 | 148 | if(ua.indexOf('Android') > -1 || ua.indexOf('android') > -1 || ua.indexOf('Adr') > -1 || ua.indexOf('adr') > -1) { 149 | u.isAndroid = true; 150 | } 151 | 152 | u.version = version ? (browserMatch.version ? browserMatch.version : 0) : 0; 153 | if(u.isAndroid){ 154 | if(window.screen.width>=768&&window.screen.width<1024){ 155 | u.isAndroidPAD=true; 156 | } 157 | if(window.screen.width<=768) { 158 | u.isAndroidPhone = true; 159 | } 160 | } 161 | if(u.isIE) { 162 | var intVersion = parseInt(u.version); 163 | var mode = document.documentMode; 164 | if(mode == null) { 165 | if(intVersion == 6 || intVersion == 7) { 166 | u.isIE8_BEFORE = true; 167 | } 168 | } else { 169 | if(mode == 7) { 170 | u.isIE8_BEFORE = true; 171 | } else if(mode == 8) { 172 | u.isIE8 = true; 173 | } else if(mode == 9) { 174 | u.isIE9 = true; 175 | u.isSTANDARD = true; 176 | } else if(mode == 10) { 177 | u.isIE10 = true; 178 | u.isSTANDARD = true; 179 | u.isIE10_ABOVE = true; 180 | } else { 181 | u.isSTANDARD = true; 182 | } 183 | if(intVersion == 8) { 184 | u.isIE8_CORE = true; 185 | } else if(intVersion == 9) { 186 | u.isIE9_CORE = true; 187 | } else if(browserMatch.version == 11) { 188 | u.isIE11 = true; 189 | } 190 | } 191 | } 192 | if("ontouchend" in document) { 193 | u.hasTouch = true; 194 | } 195 | if(u.isIphone || u.isAndroidPhone) 196 | u.isMobile = true; 197 | 198 | })(); 199 | 200 | var env = u; 201 | export {env}; 202 | -------------------------------------------------------------------------------- /lib/env.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow browser environment 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-27 21:46:50 5 | */ 6 | 7 | import { extend } from './extend'; 8 | var u = {}; 9 | 10 | extend(u, { 11 | isIE: false, 12 | isFF: false, 13 | isOpera: false, 14 | isChrome: false, 15 | isSafari: false, 16 | isWebkit: false, 17 | isIE8_BEFORE: false, 18 | isIE8: false, 19 | isIE8_CORE: false, 20 | isIE9: false, 21 | isIE9_CORE: false, 22 | isIE10: false, 23 | isIE10_ABOVE: false, 24 | isIE11: false, 25 | isEdge: false, 26 | isIOS: false, 27 | isIphone: false, 28 | isIPAD: false, 29 | isStandard: false, 30 | version: 0, 31 | isWin: false, 32 | isUnix: false, 33 | isLinux: false, 34 | isAndroid: false, 35 | isAndroidPAD: false, 36 | isAndroidPhone: false, 37 | isMac: false, 38 | hasTouch: false, 39 | isMobile: false 40 | }); 41 | 42 | (function () { 43 | var userAgent = navigator.userAgent, 44 | rMsie = /(msie\s|trident.*rv:)([\w.]+)/, 45 | rFirefox = /(firefox)\/([\w.]+)/, 46 | rOpera = /(opera).+version\/([\w.]+)/, 47 | rChrome = /(chrome)\/([\w.]+)/, 48 | rSafari = /version\/([\w.]+).*(safari)/, 49 | version, 50 | ua = userAgent.toLowerCase(), 51 | s, 52 | browserMatch = { 53 | browser: "", 54 | version: '' 55 | }, 56 | match = rMsie.exec(ua); 57 | 58 | if (match != null) { 59 | browserMatch = { 60 | browser: "IE", 61 | version: match[2] || "0" 62 | }; 63 | } 64 | match = rFirefox.exec(ua); 65 | if (match != null) { 66 | browserMatch = { 67 | browser: match[1] || "", 68 | version: match[2] || "0" 69 | }; 70 | } 71 | match = rOpera.exec(ua); 72 | if (match != null) { 73 | browserMatch = { 74 | browser: match[1] || "", 75 | version: match[2] || "0" 76 | }; 77 | } 78 | match = rChrome.exec(ua); 79 | if (match != null) { 80 | browserMatch = { 81 | browser: match[1] || "", 82 | version: match[2] || "0" 83 | }; 84 | } 85 | match = rSafari.exec(ua); 86 | if (match != null) { 87 | browserMatch = { 88 | browser: match[2] || "", 89 | version: match[1] || "0" 90 | }; 91 | } 92 | 93 | if (userAgent.indexOf("Edge") > -1) { 94 | u.isEdge = true; 95 | } 96 | if (s = ua.match(/opera.([\d.]+)/)) { 97 | u.isOpera = true; 98 | } else if (browserMatch.browser == "IE" && browserMatch.version == 11) { 99 | u.isIE11 = true; 100 | u.isIE = true; 101 | } else if (s = ua.match(/chrome\/([\d.]+)/)) { 102 | u.isChrome = true; 103 | u.isStandard = true; 104 | } else if (s = ua.match(/version\/([\d.]+).*safari/)) { 105 | u.isSafari = true; 106 | u.isStandard = true; 107 | } else if (s = ua.match(/gecko/)) { 108 | //add by licza : support XULRunner 109 | u.isFF = true; 110 | u.isStandard = true; 111 | } else if (s = ua.match(/msie ([\d.]+)/)) { 112 | u.isIE = true; 113 | } else if (s = ua.match(/firefox\/([\d.]+)/)) { 114 | u.isFF = true; 115 | u.isStandard = true; 116 | } 117 | if (ua.match(/webkit\/([\d.]+)/)) { 118 | u.isWebkit = true; 119 | } 120 | if (ua.match(/ipad/i)) { 121 | u.isIOS = true; 122 | u.isIPAD = true; 123 | u.isStandard = true; 124 | } 125 | 126 | if (ua.match(/iphone/i)) { 127 | u.isIOS = true; 128 | u.isIphone = true; 129 | } 130 | 131 | if (navigator.platform == "Mac68K" || navigator.platform == "MacPPC" || navigator.platform == "Macintosh" || navigator.platform == "MacIntel") { 132 | //u.isIOS = true; 133 | u.isMac = true; 134 | } 135 | 136 | if (navigator.platform == "Win32" || navigator.platform == "Windows" || navigator.platform == "Win64") { 137 | u.isWin = true; 138 | } 139 | 140 | if (navigator.platform == "X11" && !u.isWin && !u.isMac) { 141 | u.isUnix = true; 142 | } 143 | if (String(navigator.platform).indexOf("Linux") > -1) { 144 | u.isLinux = true; 145 | } 146 | 147 | if (ua.indexOf('Android') > -1 || ua.indexOf('android') > -1 || ua.indexOf('Adr') > -1 || ua.indexOf('adr') > -1) { 148 | u.isAndroid = true; 149 | } 150 | 151 | u.version = version ? browserMatch.version ? browserMatch.version : 0 : 0; 152 | if (u.isAndroid) { 153 | if (window.screen.width >= 768 && window.screen.width < 1024) { 154 | u.isAndroidPAD = true; 155 | } 156 | if (window.screen.width <= 768) { 157 | u.isAndroidPhone = true; 158 | } 159 | } 160 | if (u.isIE) { 161 | var intVersion = parseInt(u.version); 162 | var mode = document.documentMode; 163 | if (mode == null) { 164 | if (intVersion == 6 || intVersion == 7) { 165 | u.isIE8_BEFORE = true; 166 | } 167 | } else { 168 | if (mode == 7) { 169 | u.isIE8_BEFORE = true; 170 | } else if (mode == 8) { 171 | u.isIE8 = true; 172 | } else if (mode == 9) { 173 | u.isIE9 = true; 174 | u.isSTANDARD = true; 175 | } else if (mode == 10) { 176 | u.isIE10 = true; 177 | u.isSTANDARD = true; 178 | u.isIE10_ABOVE = true; 179 | } else { 180 | u.isSTANDARD = true; 181 | } 182 | if (intVersion == 8) { 183 | u.isIE8_CORE = true; 184 | } else if (intVersion == 9) { 185 | u.isIE9_CORE = true; 186 | } else if (browserMatch.version == 11) { 187 | u.isIE11 = true; 188 | } 189 | } 190 | } 191 | if ("ontouchend" in document) { 192 | u.hasTouch = true; 193 | } 194 | if (u.isIphone || u.isAndroidPhone) u.isMobile = true; 195 | })(); 196 | 197 | var env = u; 198 | export { env }; -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "ecmaFeatures": { 3 | "globalReturn": true, 4 | "jsx": true, 5 | "modules": true 6 | }, 7 | 8 | "env": { 9 | "browser": true, 10 | "es6": true, 11 | "node": true 12 | }, 13 | 14 | "globals": { 15 | "document": false, 16 | "escape": false, 17 | "navigator": false, 18 | "unescape": false, 19 | "window": false, 20 | "describe": true, 21 | "before": true, 22 | "it": true, 23 | "expect": true, 24 | "sinon": true 25 | }, 26 | 27 | "parser": "babel-eslint", 28 | 29 | "plugins": [ 30 | 31 | ], 32 | 33 | "rules": { 34 | /* "block-scoped-var": 2, 35 | "brace-style": [2, "1tbs", { "allowSingleLine": true }], 36 | "camelcase": [2, { "properties": "always" }], 37 | "comma-dangle": [2, "never"], 38 | "comma-spacing": [2, { "before": false, "after": true }], 39 | "comma-style": [2, "last"], 40 | "complexity": 0, 41 | "consistent-return": 2, 42 | "consistent-this": 0, 43 | "curly": [2, "multi-line"], 44 | "default-case": 0, 45 | "dot-location": [2, "property"], 46 | "dot-notation": 0, 47 | "eol-last": 2, 48 | "eqeqeq": [2, "allow-null"], 49 | "func-names": 0, 50 | "func-style": 0, 51 | "generator-star-spacing": [2, "both"], 52 | "guard-for-in": 0, 53 | "handle-callback-err": [2, "^(err|error|anySpecificError)$" ], 54 | "indent": [2, 2, { "SwitchCase": 1 }], 55 | "key-spacing": [2, { "beforeColon": false, "afterColon": true }], 56 | "linebreak-style": 0, 57 | "max-depth": 0, 58 | "max-len": [2, 120, 4], 59 | "max-nested-callbacks": 0, 60 | "max-params": 0, 61 | "max-statements": 0, 62 | "new-cap": [2, { "newIsCap": true, "capIsNew": false }], 63 | "newline-after-var": [2, "always"], 64 | "new-parens": 2, 65 | "no-alert": 0, 66 | "no-array-constructor": 2, 67 | "no-bitwise": 0, 68 | "no-caller": 2, 69 | "no-catch-shadow": 0, 70 | "no-cond-assign": 2, 71 | "no-console": 0, 72 | "no-constant-condition": 0, 73 | "no-continue": 0, 74 | "no-control-regex": 2, 75 | "no-debugger": 2, 76 | "no-delete-var": 2, 77 | "no-div-regex": 0, 78 | "no-dupe-args": 2, 79 | "no-dupe-keys": 2, 80 | "no-duplicate-case": 2, 81 | "no-else-return": 2, 82 | "no-empty": 0, 83 | "no-empty-character-class": 2, 84 | "no-empty-label": 2, 85 | "no-eq-null": 0, 86 | "no-eval": 2, 87 | "no-ex-assign": 2, 88 | "no-extend-native": 2, 89 | "no-extra-bind": 2, 90 | "no-extra-boolean-cast": 2, 91 | "no-extra-parens": 0, 92 | "no-extra-semi": 0, 93 | "no-extra-strict": 0, 94 | "no-fallthrough": 2, 95 | "no-floating-decimal": 2, 96 | "no-func-assign": 2, 97 | "no-implied-eval": 2, 98 | "no-inline-comments": 0, 99 | "no-inner-declarations": [2, "functions"], 100 | "no-invalid-regexp": 2, 101 | "no-irregular-whitespace": 2, 102 | "no-iterator": 2, 103 | "no-label-var": 2, 104 | "no-labels": 2, 105 | "no-lone-blocks": 0, 106 | "no-lonely-if": 0, 107 | "no-loop-func": 0, 108 | "no-mixed-requires": 0, 109 | "no-mixed-spaces-and-tabs": [2, false], 110 | "no-multi-spaces": 2, 111 | "no-multi-str": 2, 112 | "no-multiple-empty-lines": [2, { "max": 1 }], 113 | "no-native-reassign": 2, 114 | "no-negated-in-lhs": 2, 115 | "no-nested-ternary": 0, 116 | "no-new": 2, 117 | "no-new-func": 2, 118 | "no-new-object": 2, 119 | "no-new-require": 2, 120 | "no-new-wrappers": 2, 121 | "no-obj-calls": 2, 122 | "no-octal": 2, 123 | "no-octal-escape": 2, 124 | "no-path-concat": 0, 125 | "no-plusplus": 0, 126 | "no-process-env": 0, 127 | "no-process-exit": 0, 128 | "no-proto": 2, 129 | "no-redeclare": 2, 130 | "no-regex-spaces": 2, 131 | "no-reserved-keys": 0, 132 | "no-restricted-modules": 0, 133 | "no-return-assign": 2, 134 | "no-script-url": 0, 135 | "no-self-compare": 2, 136 | "no-sequences": 2, 137 | "no-shadow": 0, 138 | "no-shadow-restricted-names": 2, 139 | "no-spaced-func": 2, 140 | "no-sparse-arrays": 2, 141 | "no-sync": 0, 142 | "no-ternary": 0, 143 | "no-throw-literal": 2, 144 | "no-trailing-spaces": 2, 145 | "no-undef": 2, 146 | "no-undef-init": 2, 147 | "no-undefined": 0, 148 | "no-underscore-dangle": 0, 149 | "no-unneeded-ternary": 2, 150 | "no-unreachable": 2, 151 | "no-unused-expressions": 0, 152 | "no-unused-vars": [2, { "vars": "all", "args": "none" }], 153 | "no-use-before-define": 2, 154 | "no-var": 0, 155 | "no-void": 0, 156 | "no-warning-comments": 0, 157 | "no-with": 2, 158 | "one-var": 0, 159 | "operator-assignment": 0, 160 | "operator-linebreak": [2, "after"], 161 | "padded-blocks": 0, 162 | "quote-props": 0, 163 | "quotes": [2, "single", "avoid-escape"], 164 | "radix": 2, 165 | "semi": [2, "always"], 166 | "semi-spacing": 0, 167 | "sort-vars": 0, 168 | "space-after-keywords": [2, "always"], 169 | "space-before-blocks": [2, "always"], 170 | "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], 171 | "space-in-brackets": 0, 172 | "space-in-parens": [2, "never"], 173 | "space-infix-ops": 2, 174 | "space-return-throw-case": 2, 175 | "space-unary-ops": [2, { "words": true, "nonwords": false }], 176 | "spaced-comment": [2, "always"], 177 | "strict": 0, 178 | "use-isnan": 2, 179 | "valid-jsdoc": 0, 180 | "valid-typeof": 2, 181 | "vars-on-top": 2, 182 | "wrap-iife": [2, "any"], 183 | "wrap-regex": 0, 184 | "yoda": [2, "never"] */ 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/util/hotKeys.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow hotKeys 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 20:25:39 5 | */ 6 | 7 | import {isFunction} from '../class'; 8 | import {extend} from '../extend'; 9 | import {getFunction} from '../util'; 10 | var hotkeys = {}; 11 | hotkeys.special_keys = { 12 | 27: 'esc', 9: 'tab', 32: 'space', 13: 'enter', 8: 'backspace', 145: 'scroll', 20: 'capslock', 13 | 144: 'numlock', 19: 'pause', 45: 'insert', 36: 'home', 46: 'del', 35: 'end', 33: 'pageup', 14 | 34: 'pagedown', 37: 'left', 38: 'up', 39: 'right', 40: 'down', 112: 'f1', 113: 'f2', 114: 'f3', 15 | 115: 'f4', 116: 'f5', 117: 'f6', 118: 'f7', 119: 'f8', 120: 'f9', 121: 'f10', 122: 'f11', 123: 'f12' 16 | }; 17 | 18 | hotkeys.shift_nums = { 19 | "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", 20 | "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ":", "'": "\"", ",": "<", 21 | ".": ">", "/": "?", "\\": "|" 22 | }; 23 | 24 | hotkeys.add = function (combi, options, callback) { 25 | if (isFunction(options)) { 26 | callback = options; 27 | options = {}; 28 | } 29 | var opt = {}, 30 | defaults = {type: 'keydown', propagate: false, disableInInput: false, target: document.body, checkParent: true}, 31 | that = this; 32 | opt = extend(opt, defaults, options || {}); 33 | combi = combi.toLowerCase(); 34 | 35 | // inspect if keystroke matches 36 | var inspector = function (event) { 37 | //event = $.event.fix(event); // jQuery event normalization. 38 | var element = this//event.target; 39 | // @ TextNode -> nodeType == 3 40 | element = (element.nodeType == 3) ? element.parentNode : element; 41 | 42 | if (opt['disableInInput']) { // Disable shortcut keys in Input, Textarea fields 43 | var target = element;//$(element); 44 | if (target.tagName == "INPUT" || target.tagName == "TEXTAREA") { 45 | return; 46 | } 47 | } 48 | var code = event.which, 49 | type = event.type, 50 | character = String.fromCharCode(code).toLowerCase(), 51 | special = that.special_keys[code], 52 | shift = event.shiftKey, 53 | ctrl = event.ctrlKey, 54 | alt = event.altKey, 55 | propagate = true, // default behaivour 56 | mapPoint = null; 57 | 58 | // in opera + safari, the event.target is unpredictable. 59 | // for example: 'keydown' might be associated with HtmlBodyElement 60 | // or the element where you last clicked with your mouse. 61 | if (opt.checkParent) { 62 | // while (!that.all[element] && element.parentNode){ 63 | while (!element['hotkeys'] && element.parentNode) { 64 | element = element.parentNode; 65 | } 66 | } 67 | 68 | // var cbMap = that.all[element].events[type].callbackMap; 69 | var cbMap = element['hotkeys'].events[type].callbackMap; 70 | if (!shift && !ctrl && !alt) { // No Modifiers 71 | mapPoint = cbMap[special] || cbMap[character] 72 | } 73 | // deals with combinaitons (alt|ctrl|shift+anything) 74 | else { 75 | var modif = ''; 76 | if (alt) modif += 'alt+'; 77 | if (ctrl) modif += 'ctrl+'; 78 | if (shift) modif += 'shift+'; 79 | // modifiers + special keys or modifiers + characters or modifiers + shift characters 80 | mapPoint = cbMap[modif + special] || cbMap[modif + character] || cbMap[modif + that.shift_nums[character]] 81 | } 82 | if (mapPoint) { 83 | mapPoint.cb(event); 84 | if (!mapPoint.propagate) { 85 | event.stopPropagation(); 86 | event.preventDefault(); 87 | return false; 88 | } 89 | } 90 | }; 91 | // first hook for this element 92 | var data = opt.target['hotkeys']; 93 | if (!data) { 94 | opt.target['hotkeys'] = data = {events: {}}; 95 | } 96 | // if (!hotkeys.all[opt.target]){ 97 | // hotkeys.all[opt.target] = {events:{}}; 98 | // } 99 | if (!data.events[opt.type]) { 100 | data.events[opt.type] = {callbackMap: {}}; 101 | on(opt.target, opt.type, inspector); 102 | //$.event.add(opt.target, opt.type, inspector); 103 | } 104 | // if (!hotkeys.all[opt.target].events[opt.type]){ 105 | // hotkeys.all[opt.target].events[opt.type] = {callbackMap: {}} 106 | // $.event.add(opt.target, opt.type, inspector); 107 | // } 108 | data.events[opt.type].callbackMap[combi] = {cb: callback, propagate: opt.propagate}; 109 | // hotkeys.all[opt.target].events[opt.type].callbackMap[combi] = {cb: callback, propagate:opt.propagate}; 110 | return hotkeys; 111 | }; 112 | hotkeys.remove = function (exp, opt) { 113 | opt = opt || {}; 114 | target = opt.target || document.body; 115 | type = opt.type || 'keydown'; 116 | exp = exp.toLowerCase(); 117 | 118 | delete target['hotkeys'].events[type].callbackMap[exp]; 119 | }; 120 | 121 | hotkeys.scan = function (element, target) { 122 | element = element || document.body; 123 | element.querySelectorAll('[u-enter]').forEach(function(el){ 124 | var enterValue = el.getAttribute('u-enter'); 125 | if (!enterValue) return; 126 | if (enterValue.substring(0, 1) == '#') 127 | hotkeys.add('enter', {target: this}, function () { 128 | var _el = element.querySelector(enterValue); 129 | if (_el){ 130 | _el.focus(); 131 | } 132 | }); 133 | else { 134 | target = target || window 135 | var func = h(target, enterValue) 136 | hotkeys.add('enter', {target: this}, function () { 137 | func.call(this) 138 | }) 139 | } 140 | }); 141 | element.querySelectorAll('[u-hotkey]').forEach(function(el){ 142 | var hotkey = el.getAttribute('u-hotkey'); 143 | if (!hotkey) return; 144 | hotkeys.add(hotkey, function () { 145 | el.click(); 146 | }) 147 | 148 | }); 149 | } 150 | 151 | var hotkeys = hotkeys; 152 | 153 | export {hotkeys}; 154 | -------------------------------------------------------------------------------- /lib/util/hotKeys.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow hotKeys 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-28 20:25:39 5 | */ 6 | 7 | import { isFunction } from '../class'; 8 | import { extend } from '../extend'; 9 | import { getFunction } from '../util'; 10 | var hotkeys = {}; 11 | hotkeys.special_keys = { 12 | 27: 'esc', 9: 'tab', 32: 'space', 13: 'enter', 8: 'backspace', 145: 'scroll', 20: 'capslock', 13 | 144: 'numlock', 19: 'pause', 45: 'insert', 36: 'home', 46: 'del', 35: 'end', 33: 'pageup', 14 | 34: 'pagedown', 37: 'left', 38: 'up', 39: 'right', 40: 'down', 112: 'f1', 113: 'f2', 114: 'f3', 15 | 115: 'f4', 116: 'f5', 117: 'f6', 118: 'f7', 119: 'f8', 120: 'f9', 121: 'f10', 122: 'f11', 123: 'f12' 16 | }; 17 | 18 | hotkeys.shift_nums = { 19 | "`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", 20 | "8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ":", "'": "\"", ",": "<", 21 | ".": ">", "/": "?", "\\": "|" 22 | }; 23 | 24 | hotkeys.add = function (combi, options, callback) { 25 | if (isFunction(options)) { 26 | callback = options; 27 | options = {}; 28 | } 29 | var opt = {}, 30 | defaults = { type: 'keydown', propagate: false, disableInInput: false, target: document.body, checkParent: true }, 31 | that = this; 32 | opt = extend(opt, defaults, options || {}); 33 | combi = combi.toLowerCase(); 34 | 35 | // inspect if keystroke matches 36 | var inspector = function inspector(event) { 37 | //event = $.event.fix(event); // jQuery event normalization. 38 | var element = this; //event.target; 39 | // @ TextNode -> nodeType == 3 40 | element = element.nodeType == 3 ? element.parentNode : element; 41 | 42 | if (opt['disableInInput']) { 43 | // Disable shortcut keys in Input, Textarea fields 44 | var target = element; //$(element); 45 | if (target.tagName == "INPUT" || target.tagName == "TEXTAREA") { 46 | return; 47 | } 48 | } 49 | var code = event.which, 50 | type = event.type, 51 | character = String.fromCharCode(code).toLowerCase(), 52 | special = that.special_keys[code], 53 | shift = event.shiftKey, 54 | ctrl = event.ctrlKey, 55 | alt = event.altKey, 56 | propagate = true, 57 | // default behaivour 58 | mapPoint = null; 59 | 60 | // in opera + safari, the event.target is unpredictable. 61 | // for example: 'keydown' might be associated with HtmlBodyElement 62 | // or the element where you last clicked with your mouse. 63 | if (opt.checkParent) { 64 | // while (!that.all[element] && element.parentNode){ 65 | while (!element['hotkeys'] && element.parentNode) { 66 | element = element.parentNode; 67 | } 68 | } 69 | 70 | // var cbMap = that.all[element].events[type].callbackMap; 71 | var cbMap = element['hotkeys'].events[type].callbackMap; 72 | if (!shift && !ctrl && !alt) { 73 | // No Modifiers 74 | mapPoint = cbMap[special] || cbMap[character]; 75 | } 76 | // deals with combinaitons (alt|ctrl|shift+anything) 77 | else { 78 | var modif = ''; 79 | if (alt) modif += 'alt+'; 80 | if (ctrl) modif += 'ctrl+'; 81 | if (shift) modif += 'shift+'; 82 | // modifiers + special keys or modifiers + characters or modifiers + shift characters 83 | mapPoint = cbMap[modif + special] || cbMap[modif + character] || cbMap[modif + that.shift_nums[character]]; 84 | } 85 | if (mapPoint) { 86 | mapPoint.cb(event); 87 | if (!mapPoint.propagate) { 88 | event.stopPropagation(); 89 | event.preventDefault(); 90 | return false; 91 | } 92 | } 93 | }; 94 | // first hook for this element 95 | var data = opt.target['hotkeys']; 96 | if (!data) { 97 | opt.target['hotkeys'] = data = { events: {} }; 98 | } 99 | // if (!hotkeys.all[opt.target]){ 100 | // hotkeys.all[opt.target] = {events:{}}; 101 | // } 102 | if (!data.events[opt.type]) { 103 | data.events[opt.type] = { callbackMap: {} }; 104 | on(opt.target, opt.type, inspector); 105 | //$.event.add(opt.target, opt.type, inspector); 106 | } 107 | // if (!hotkeys.all[opt.target].events[opt.type]){ 108 | // hotkeys.all[opt.target].events[opt.type] = {callbackMap: {}} 109 | // $.event.add(opt.target, opt.type, inspector); 110 | // } 111 | data.events[opt.type].callbackMap[combi] = { cb: callback, propagate: opt.propagate }; 112 | // hotkeys.all[opt.target].events[opt.type].callbackMap[combi] = {cb: callback, propagate:opt.propagate}; 113 | return hotkeys; 114 | }; 115 | hotkeys.remove = function (exp, opt) { 116 | opt = opt || {}; 117 | target = opt.target || document.body; 118 | type = opt.type || 'keydown'; 119 | exp = exp.toLowerCase(); 120 | 121 | delete target['hotkeys'].events[type].callbackMap[exp]; 122 | }; 123 | 124 | hotkeys.scan = function (element, target) { 125 | element = element || document.body; 126 | element.querySelectorAll('[u-enter]').forEach(function (el) { 127 | var enterValue = el.getAttribute('u-enter'); 128 | if (!enterValue) return; 129 | if (enterValue.substring(0, 1) == '#') hotkeys.add('enter', { target: this }, function () { 130 | var _el = element.querySelector(enterValue); 131 | if (_el) { 132 | _el.focus(); 133 | } 134 | });else { 135 | target = target || window; 136 | var func = h(target, enterValue); 137 | hotkeys.add('enter', { target: this }, function () { 138 | func.call(this); 139 | }); 140 | } 141 | }); 142 | element.querySelectorAll('[u-hotkey]').forEach(function (el) { 143 | var hotkey = el.getAttribute('u-hotkey'); 144 | if (!hotkey) return; 145 | hotkeys.add(hotkey, function () { 146 | el.click(); 147 | }); 148 | }); 149 | }; 150 | 151 | var hotkeys = hotkeys; 152 | 153 | export { hotkeys }; -------------------------------------------------------------------------------- /lib/util/ripple.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow ripple 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-29 08:42:13 5 | */ 6 | 7 | import { env } from '../env'; 8 | import { addClass, removeClass } from '../dom'; 9 | import { on, off } from '../event'; 10 | 11 | var URipple = function URipple(element) { 12 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 13 | this._element = element; 14 | 15 | // Initialize instance. 16 | this.init(); 17 | }; 18 | //window['URipple'] = URipple; 19 | 20 | URipple.prototype._down = function (event) { 21 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 22 | if (!this._rippleElement.style.width && !this._rippleElement.style.height) { 23 | var rect = this._element.getBoundingClientRect(); 24 | this.rippleSize_ = Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2; 25 | if (this.rippleSize_ > 0) { 26 | this._rippleElement.style.width = this.rippleSize_ + 'px'; 27 | this._rippleElement.style.height = this.rippleSize_ + 'px'; 28 | } 29 | } 30 | 31 | addClass(this._rippleElement, 'is-visible'); 32 | 33 | if (event.type === 'mousedown' && this._ignoringMouseDown) { 34 | this._ignoringMouseDown = false; 35 | } else { 36 | if (event.type === 'touchstart') { 37 | this._ignoringMouseDown = true; 38 | } 39 | var frameCount = this.getFrameCount(); 40 | if (frameCount > 0) { 41 | return; 42 | } 43 | this.setFrameCount(1); 44 | var t = event.currentTarget || event.target || event.srcElement; 45 | var bound = t.getBoundingClientRect(); 46 | var x; 47 | var y; 48 | // Check if we are handling a keyboard click. 49 | if (event.clientX === 0 && event.clientY === 0) { 50 | x = Math.round(bound.width / 2); 51 | y = Math.round(bound.height / 2); 52 | } else { 53 | var clientX = event.clientX ? event.clientX : event.touches[0].clientX; 54 | var clientY = event.clientY ? event.clientY : event.touches[0].clientY; 55 | x = Math.round(clientX - bound.left); 56 | y = Math.round(clientY - bound.top); 57 | } 58 | this.setRippleXY(x, y); 59 | this.setRippleStyles(true); 60 | if (window.requestAnimationFrame) window.requestAnimationFrame(this.animFrameHandler.bind(this)); 61 | } 62 | }; 63 | 64 | /** 65 | * Handle mouse / finger up on element. 66 | * 67 | * @param {Event} event The event that fired. 68 | * @private 69 | */ 70 | URipple.prototype._up = function (event) { 71 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 72 | var self = this; 73 | // Don't fire for the artificial "mouseup" generated by a double-click. 74 | if (event && event.detail !== 2) { 75 | removeClass(this._rippleElement, 'is-visible'); 76 | } 77 | // Allow a repaint to occur before removing this class, so the animation 78 | // shows for tap events, which seem to trigger a mouseup too soon after 79 | // mousedown. 80 | window.setTimeout(function () { 81 | removeClass(self._rippleElement, 'is-visible'); 82 | }, 0); 83 | }; 84 | 85 | /** 86 | * Getter for frameCount_. 87 | * @return {number} the frame count. 88 | */ 89 | URipple.prototype.getFrameCount = function () { 90 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 91 | return this.frameCount_; 92 | }; 93 | /** 94 | * Setter for frameCount_. 95 | * @param {number} fC the frame count. 96 | */ 97 | URipple.prototype.setFrameCount = function (fC) { 98 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 99 | this.frameCount_ = fC; 100 | }; 101 | 102 | /** 103 | * Getter for _rippleElement. 104 | * @return {Element} the ripple element. 105 | */ 106 | URipple.prototype.getRippleElement = function () { 107 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 108 | return this._rippleElement; 109 | }; 110 | 111 | /** 112 | * Sets the ripple X and Y coordinates. 113 | * @param {number} newX the new X coordinate 114 | * @param {number} newY the new Y coordinate 115 | */ 116 | URipple.prototype.setRippleXY = function (newX, newY) { 117 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 118 | this.x_ = newX; 119 | this.y_ = newY; 120 | }; 121 | 122 | /** 123 | * Sets the ripple styles. 124 | * @param {boolean} start whether or not this is the start frame. 125 | */ 126 | URipple.prototype.setRippleStyles = function (start) { 127 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 128 | if (this._rippleElement !== null) { 129 | var transformString; 130 | var scale; 131 | var size; 132 | var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)'; 133 | 134 | if (start) { 135 | scale = 'scale(0.0001, 0.0001)'; 136 | size = '1px'; 137 | } else { 138 | scale = ''; 139 | size = this.rippleSize_ + 'px'; 140 | } 141 | 142 | transformString = 'translate(-50%, -50%) ' + offset + scale; 143 | 144 | this._rippleElement.style.webkitTransform = transformString; 145 | this._rippleElement.style.msTransform = transformString; 146 | this._rippleElement.style.transform = transformString; 147 | 148 | if (start) { 149 | removeClass(this._rippleElement, 'is-animating'); 150 | } else { 151 | addClass(this._rippleElement, 'is-animating'); 152 | } 153 | } 154 | }; 155 | 156 | /** 157 | * Handles an animation frame. 158 | */ 159 | URipple.prototype.animFrameHandler = function () { 160 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 161 | if (this.frameCount_-- > 0) { 162 | window.requestAnimationFrame(this.animFrameHandler.bind(this)); 163 | } else { 164 | this.setRippleStyles(false); 165 | } 166 | }; 167 | 168 | /** 169 | * Initialize element. 170 | */ 171 | URipple.prototype.init = function () { 172 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 173 | var self = this; 174 | if (this._element) { 175 | this._rippleElement = this._element.querySelector('.u-ripple'); 176 | if (!this._rippleElement) { 177 | this._rippleElement = document.createElement('span'); 178 | addClass(this._rippleElement, 'u-ripple'); 179 | this._element.appendChild(this._rippleElement); 180 | this._element.style.overflow = 'hidden'; 181 | this._element.style.position = 'relative'; 182 | } 183 | this.frameCount_ = 0; 184 | this.rippleSize_ = 0; 185 | this.x_ = 0; 186 | this.y_ = 0; 187 | 188 | // Touch start produces a compat mouse down event, which would cause a 189 | // second ripples. To avoid that, we use this property to ignore the first 190 | // mouse down after a touch start. 191 | this._ignoringMouseDown = false; 192 | on(this._element, 'mousedown', function (e) { 193 | self._down(e); 194 | }); 195 | on(this._element, 'touchstart', function (e) { 196 | self._down(e); 197 | }); 198 | 199 | on(this._element, 'mouseup', function (e) { 200 | self._up(e); 201 | }); 202 | on(this._element, 'mouseleave', function (e) { 203 | self._up(e); 204 | }); 205 | on(this._element, 'touchend', function (e) { 206 | self._up(e); 207 | }); 208 | on(this._element, 'blur', function (e) { 209 | self._up(e); 210 | }); 211 | } 212 | }; 213 | 214 | var Ripple = URipple; 215 | 216 | export { Ripple, URipple }; -------------------------------------------------------------------------------- /src/util/ripple.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow ripple 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-07-29 08:42:13 5 | */ 6 | 7 | import {env} from '../env'; 8 | import {addClass,removeClass} from '../dom'; 9 | import {on,off} from '../event'; 10 | 11 | 12 | var URipple = function URipple(element) { 13 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 14 | this._element = element; 15 | 16 | // Initialize instance. 17 | this.init(); 18 | }; 19 | //window['URipple'] = URipple; 20 | 21 | URipple.prototype._down = function(event) { 22 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 23 | if (!this._rippleElement.style.width && !this._rippleElement.style.height) { 24 | var rect = this._element.getBoundingClientRect(); 25 | this.rippleSize_ = Math.sqrt(rect.width * rect.width + rect.height * rect.height) * 2 + 2; 26 | if(this.rippleSize_ > 0){ 27 | this._rippleElement.style.width = this.rippleSize_ + 'px'; 28 | this._rippleElement.style.height = this.rippleSize_ + 'px'; 29 | } 30 | 31 | } 32 | 33 | addClass(this._rippleElement, 'is-visible'); 34 | 35 | if (event.type === 'mousedown' && this._ignoringMouseDown) { 36 | this._ignoringMouseDown = false; 37 | } else { 38 | if (event.type === 'touchstart') { 39 | this._ignoringMouseDown = true; 40 | } 41 | var frameCount = this.getFrameCount(); 42 | if (frameCount > 0) { 43 | return; 44 | } 45 | this.setFrameCount(1); 46 | var t = event.currentTarget || event.target || event.srcElement; 47 | var bound = t.getBoundingClientRect(); 48 | var x; 49 | var y; 50 | // Check if we are handling a keyboard click. 51 | if (event.clientX === 0 && event.clientY === 0) { 52 | x = Math.round(bound.width / 2); 53 | y = Math.round(bound.height / 2); 54 | } else { 55 | var clientX = event.clientX ? event.clientX : event.touches[0].clientX; 56 | var clientY = event.clientY ? event.clientY : event.touches[0].clientY; 57 | x = Math.round(clientX - bound.left); 58 | y = Math.round(clientY - bound.top); 59 | } 60 | this.setRippleXY(x, y); 61 | this.setRippleStyles(true); 62 | if(window.requestAnimationFrame) 63 | window.requestAnimationFrame(this.animFrameHandler.bind(this)); 64 | } 65 | }; 66 | 67 | /** 68 | * Handle mouse / finger up on element. 69 | * 70 | * @param {Event} event The event that fired. 71 | * @private 72 | */ 73 | URipple.prototype._up = function(event) { 74 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 75 | var self = this; 76 | // Don't fire for the artificial "mouseup" generated by a double-click. 77 | if (event && event.detail !== 2) { 78 | removeClass(this._rippleElement,'is-visible') 79 | } 80 | // Allow a repaint to occur before removing this class, so the animation 81 | // shows for tap events, which seem to trigger a mouseup too soon after 82 | // mousedown. 83 | window.setTimeout(function() { 84 | removeClass(self._rippleElement,'is-visible') 85 | }, 0); 86 | }; 87 | 88 | /** 89 | * Getter for frameCount_. 90 | * @return {number} the frame count. 91 | */ 92 | URipple.prototype.getFrameCount = function() { 93 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 94 | return this.frameCount_; 95 | }; 96 | /** 97 | * Setter for frameCount_. 98 | * @param {number} fC the frame count. 99 | */ 100 | URipple.prototype.setFrameCount = function(fC) { 101 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 102 | this.frameCount_ = fC; 103 | }; 104 | 105 | 106 | /** 107 | * Getter for _rippleElement. 108 | * @return {Element} the ripple element. 109 | */ 110 | URipple.prototype.getRippleElement = function() { 111 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 112 | return this._rippleElement; 113 | }; 114 | 115 | /** 116 | * Sets the ripple X and Y coordinates. 117 | * @param {number} newX the new X coordinate 118 | * @param {number} newY the new Y coordinate 119 | */ 120 | URipple.prototype.setRippleXY = function(newX, newY) { 121 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 122 | this.x_ = newX; 123 | this.y_ = newY; 124 | }; 125 | 126 | /** 127 | * Sets the ripple styles. 128 | * @param {boolean} start whether or not this is the start frame. 129 | */ 130 | URipple.prototype.setRippleStyles = function(start) { 131 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 132 | if (this._rippleElement !== null) { 133 | var transformString; 134 | var scale; 135 | var size; 136 | var offset = 'translate(' + this.x_ + 'px, ' + this.y_ + 'px)'; 137 | 138 | if (start) { 139 | scale = 'scale(0.0001, 0.0001)'; 140 | size = '1px'; 141 | } else { 142 | scale = ''; 143 | size = this.rippleSize_ + 'px'; 144 | } 145 | 146 | transformString = 'translate(-50%, -50%) ' + offset + scale; 147 | 148 | this._rippleElement.style.webkitTransform = transformString; 149 | this._rippleElement.style.msTransform = transformString; 150 | this._rippleElement.style.transform = transformString; 151 | 152 | if (start) { 153 | removeClass(this._rippleElement,'is-animating') 154 | } else { 155 | addClass(this._rippleElement,'is-animating') 156 | } 157 | } 158 | }; 159 | 160 | /** 161 | * Handles an animation frame. 162 | */ 163 | URipple.prototype.animFrameHandler = function() { 164 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 165 | if (this.frameCount_-- > 0) { 166 | window.requestAnimationFrame(this.animFrameHandler.bind(this)); 167 | } else { 168 | this.setRippleStyles(false); 169 | } 170 | }; 171 | 172 | /** 173 | * Initialize element. 174 | */ 175 | URipple.prototype.init = function() { 176 | if (env.isIE8 || env.isMobile || env.isAndroidPAD || env.isIPAD) return; 177 | var self = this; 178 | if (this._element) { 179 | this._rippleElement = this._element.querySelector('.u-ripple'); 180 | if (!this._rippleElement){ 181 | this._rippleElement = document.createElement('span'); 182 | addClass(this._rippleElement,'u-ripple'); 183 | this._element.appendChild(this._rippleElement); 184 | this._element.style.overflow = 'hidden'; 185 | this._element.style.position = 'relative'; 186 | } 187 | this.frameCount_ = 0; 188 | this.rippleSize_ = 0; 189 | this.x_ = 0; 190 | this.y_ = 0; 191 | 192 | // Touch start produces a compat mouse down event, which would cause a 193 | // second ripples. To avoid that, we use this property to ignore the first 194 | // mouse down after a touch start. 195 | this._ignoringMouseDown = false; 196 | on(this._element, 'mousedown',function(e){self._down(e);}) 197 | on(this._element, 'touchstart',function(e){self._down(e);}) 198 | 199 | on(this._element, 'mouseup',function(e){self._up(e);}) 200 | on(this._element, 'mouseleave',function(e){self._up(e);}) 201 | on(this._element, 'touchend',function(e){self._up(e);}) 202 | on(this._element, 'blur',function(e){self._up(e);}) 203 | } 204 | }; 205 | 206 | var Ripple = URipple; 207 | 208 | export {Ripple,URipple}; 209 | -------------------------------------------------------------------------------- /lib/mobileEvents.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow touch mobileEvents 3 | * Author : liuyk(liuyk@yonyou.com) 4 | * Date : 2017-03-16 14:41:17 5 | */ 6 | 7 | import { env } from './env'; 8 | 9 | var u = {}; 10 | u.event = {}; 11 | 12 | var touchStartEvent = env.hasTouch ? "touchstart" : "mousedown", 13 | touchStopEvent = env.hasTouch ? "touchend" : "mouseup", 14 | touchMoveEvent = env.hasTouch ? "touchmove" : "mousemove"; 15 | 16 | // tap和taphold 17 | u.event.tap = { 18 | tapholdThreshold: 750, 19 | emitTapOnTaphold: true, 20 | touchstartFun: function touchstartFun() { 21 | trigger(this, 'vmousedown'); 22 | }, 23 | touchendFun: function touchendFun() { 24 | trigger(this, 'vmouseup'); 25 | trigger(this, 'vclick'); 26 | }, 27 | setup: function setup() { 28 | var thisObject = this, 29 | isTaphold = false; 30 | 31 | on(thisObject, "vmousedown", function (event) { 32 | isTaphold = false; 33 | if (event.which && event.which !== 1) { 34 | return false; 35 | } 36 | 37 | var origTarget = event.target, 38 | timer; 39 | 40 | function clearTapTimer() { 41 | clearTimeout(timer); 42 | } 43 | 44 | function clearTapHandlers() { 45 | clearTapTimer(); 46 | 47 | off(thisObject, 'vclick'); 48 | off(thisObject, 'vmouseup'); 49 | off(document, 'vmousecancel'); 50 | } 51 | 52 | function clickHandler(event) { 53 | clearTapHandlers(); 54 | 55 | // ONLY trigger a 'tap' event if the start target is 56 | // the same as the stop target. 57 | if (!isTaphold && origTarget === event.target) { 58 | trigger(thisObject, 'tap'); 59 | } else if (isTaphold) { 60 | event.preventDefault(); 61 | } 62 | } 63 | on(thisObject, 'vmouseup', clearTapTimer); 64 | on(thisObject, 'vclick', clickHandler); 65 | on(document, 'vmousecancel', clearTapHandlers); 66 | 67 | timer = setTimeout(function () { 68 | if (!u.event.tap.emitTapOnTaphold) { 69 | isTaphold = true; 70 | } 71 | trigger(thisObject, "taphold"); 72 | clearTapHandlers(); 73 | }, u.event.tap.tapholdThreshold); 74 | }); 75 | 76 | on(thisObject, 'touchstart', u.event.tap.touchstartFun); 77 | on(thisObject, 'touchend', u.event.tap.touchendFun); 78 | }, 79 | teardown: function teardown() { 80 | off(thisObject, 'vmousedown'); 81 | off(thisObject, 'vclick'); 82 | off(thisObject, 'vmouseup'); 83 | off(document, 'vmousecancel'); 84 | } 85 | }; 86 | 87 | u.event.taphold = u.event.tap; 88 | 89 | u.event.swipe = { 90 | 91 | // More than this horizontal displacement, and we will suppress scrolling. 92 | scrollSupressionThreshold: 30, 93 | 94 | // More time than this, and it isn't a swipe. 95 | durationThreshold: 1000, 96 | 97 | // Swipe horizontal displacement must be more than this. 98 | horizontalDistanceThreshold: 30, 99 | 100 | // Swipe vertical displacement must be less than this. 101 | verticalDistanceThreshold: 30, 102 | 103 | getLocation: function getLocation(event) { 104 | var winPageX = window.pageXOffset, 105 | winPageY = window.pageYOffset, 106 | x = event.clientX, 107 | y = event.clientY; 108 | 109 | if (event.pageY === 0 && Math.floor(y) > Math.floor(event.pageY) || event.pageX === 0 && Math.floor(x) > Math.floor(event.pageX)) { 110 | 111 | // iOS4 clientX/clientY have the value that should have been 112 | // in pageX/pageY. While pageX/page/ have the value 0 113 | x = x - winPageX; 114 | y = y - winPageY; 115 | } else if (y < event.pageY - winPageY || x < event.pageX - winPageX) { 116 | 117 | // Some Android browsers have totally bogus values for clientX/Y 118 | // when scrolling/zooming a page. Detectable since clientX/clientY 119 | // should never be smaller than pageX/pageY minus page scroll 120 | x = event.pageX - winPageX; 121 | y = event.pageY - winPageY; 122 | } 123 | 124 | return { 125 | x: x, 126 | y: y 127 | }; 128 | }, 129 | 130 | start: function start(event) { 131 | var data = event.touches ? event.touches[0] : event, 132 | location = u.event.swipe.getLocation(data); 133 | return { 134 | time: new Date().getTime(), 135 | coords: [location.x, location.y], 136 | origin: event.target 137 | }; 138 | }, 139 | 140 | stop: function stop(event) { 141 | var data = event.touches ? event.touches[0] : event, 142 | location = u.event.swipe.getLocation(data); 143 | return { 144 | time: new Date().getTime(), 145 | coords: [location.x, location.y] 146 | }; 147 | }, 148 | 149 | handleSwipe: function handleSwipe(start, stop, thisObject, origTarget) { 150 | if (stop.time - start.time < u.event.swipe.durationThreshold && Math.abs(start.coords[0] - stop.coords[0]) > u.event.swipe.horizontalDistanceThreshold && Math.abs(start.coords[1] - stop.coords[1]) < u.event.swipe.verticalDistanceThreshold) { 151 | var direction = start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight"; 152 | 153 | trigger(thisObject, "swipe"); 154 | trigger(thisObject, direction); 155 | return true; 156 | } 157 | return false; 158 | }, 159 | 160 | // This serves as a flag to ensure that at most one swipe event event is 161 | // in work at any given time 162 | eventInProgress: false, 163 | 164 | setup: function setup() { 165 | var events, 166 | thisObject = this, 167 | context = {}; 168 | 169 | // Retrieve the events data for this element and add the swipe context 170 | events = thisObject["mobile-events"]; 171 | if (!events) { 172 | events = { 173 | length: 0 174 | }; 175 | thisObject["mobile-events"] = events; 176 | } 177 | events.length++; 178 | events.swipe = context; 179 | 180 | context.start = function (event) { 181 | 182 | // Bail if we're already working on a swipe event 183 | if (u.event.swipe.eventInProgress) { 184 | return; 185 | } 186 | u.event.swipe.eventInProgress = true; 187 | 188 | var stop, 189 | start = u.event.swipe.start(event), 190 | origTarget = event.target, 191 | emitted = false; 192 | 193 | context.move = function (event) { 194 | // if ( !start || event.isDefaultPrevented() ) { 195 | if (!start) { 196 | return; 197 | } 198 | 199 | stop = u.event.swipe.stop(event); 200 | if (!emitted) { 201 | emitted = u.event.swipe.handleSwipe(start, stop, thisObject, origTarget); 202 | if (emitted) { 203 | 204 | // Reset the context to make way for the next swipe event 205 | u.event.swipe.eventInProgress = false; 206 | } 207 | } 208 | // prevent scrolling 209 | if (Math.abs(start.coords[0] - stop.coords[0]) > u.event.swipe.scrollSupressionThreshold) { 210 | event.preventDefault(); 211 | } 212 | }; 213 | 214 | context.stop = function () { 215 | emitted = true; 216 | 217 | // Reset the context to make way for the next swipe event 218 | u.event.swipe.eventInProgress = false; 219 | off(document, touchMoveEvent, context.move); 220 | context.move = null; 221 | }; 222 | 223 | on(document, touchMoveEvent, context.move); 224 | on(document, touchStopEvent, context.stop); 225 | }; 226 | on(thisObject, touchStartEvent, context.start); 227 | }, 228 | 229 | teardown: function teardown() { 230 | var events, context; 231 | 232 | events = thisObject["mobile-events"]; 233 | if (events) { 234 | context = events.swipe; 235 | delete events.swipe; 236 | events.length--; 237 | if (events.length === 0) { 238 | thisObject["mobile-events"] = null; 239 | } 240 | } 241 | 242 | if (context) { 243 | if (context.start) { 244 | off(thisObject, touchStartEvent, context.start); 245 | } 246 | if (context.move) { 247 | off(document, touchMoveEvent, context.move); 248 | } 249 | if (context.stop) { 250 | off(document, touchStopEvent, context.stop); 251 | } 252 | } 253 | } 254 | }; 255 | 256 | u.event.swipeleft = u.event.swipe; 257 | 258 | u.event.swiperight = u.event.swipe; 259 | 260 | var event = u.event; 261 | 262 | export { event }; -------------------------------------------------------------------------------- /src/mobileEvents.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow touch mobileEvents 3 | * Author : liuyk(liuyk@yonyou.com) 4 | * Date : 2017-03-16 14:41:17 5 | */ 6 | 7 | import { 8 | env 9 | } from './env'; 10 | 11 | var u = {}; 12 | u.event = {}; 13 | 14 | var touchStartEvent = env.hasTouch ? "touchstart" : "mousedown", 15 | touchStopEvent = env.hasTouch ? "touchend" : "mouseup", 16 | touchMoveEvent = env.hasTouch ? "touchmove" : "mousemove"; 17 | 18 | // tap和taphold 19 | u.event.tap = { 20 | tapholdThreshold: 750, 21 | emitTapOnTaphold: true, 22 | touchstartFun: function() { 23 | trigger(this, 'vmousedown'); 24 | }, 25 | touchendFun: function() { 26 | trigger(this, 'vmouseup'); 27 | trigger(this, 'vclick'); 28 | }, 29 | setup: function() { 30 | var thisObject = this, 31 | isTaphold = false; 32 | 33 | on(thisObject, "vmousedown", function(event) { 34 | isTaphold = false; 35 | if (event.which && event.which !== 1) { 36 | return false; 37 | } 38 | 39 | var origTarget = event.target, 40 | timer; 41 | 42 | function clearTapTimer() { 43 | clearTimeout(timer); 44 | } 45 | 46 | function clearTapHandlers() { 47 | clearTapTimer(); 48 | 49 | off(thisObject, 'vclick'); 50 | off(thisObject, 'vmouseup'); 51 | off(document, 'vmousecancel'); 52 | } 53 | 54 | function clickHandler(event) { 55 | clearTapHandlers(); 56 | 57 | // ONLY trigger a 'tap' event if the start target is 58 | // the same as the stop target. 59 | if (!isTaphold && origTarget === event.target) { 60 | trigger(thisObject, 'tap'); 61 | } else if (isTaphold) { 62 | event.preventDefault(); 63 | } 64 | } 65 | on(thisObject, 'vmouseup', clearTapTimer); 66 | on(thisObject, 'vclick', clickHandler); 67 | on(document, 'vmousecancel', clearTapHandlers); 68 | 69 | timer = setTimeout(function() { 70 | if (!u.event.tap.emitTapOnTaphold) { 71 | isTaphold = true; 72 | } 73 | trigger(thisObject, "taphold"); 74 | clearTapHandlers(); 75 | }, u.event.tap.tapholdThreshold); 76 | }); 77 | 78 | on(thisObject, 'touchstart', u.event.tap.touchstartFun); 79 | on(thisObject, 'touchend', u.event.tap.touchendFun); 80 | }, 81 | teardown: function() { 82 | off(thisObject, 'vmousedown'); 83 | off(thisObject, 'vclick'); 84 | off(thisObject, 'vmouseup'); 85 | off(document, 'vmousecancel'); 86 | } 87 | }; 88 | 89 | u.event.taphold = u.event.tap; 90 | 91 | u.event.swipe = { 92 | 93 | // More than this horizontal displacement, and we will suppress scrolling. 94 | scrollSupressionThreshold: 30, 95 | 96 | // More time than this, and it isn't a swipe. 97 | durationThreshold: 1000, 98 | 99 | // Swipe horizontal displacement must be more than this. 100 | horizontalDistanceThreshold: 30, 101 | 102 | // Swipe vertical displacement must be less than this. 103 | verticalDistanceThreshold: 30, 104 | 105 | getLocation: function(event) { 106 | var winPageX = window.pageXOffset, 107 | winPageY = window.pageYOffset, 108 | x = event.clientX, 109 | y = event.clientY; 110 | 111 | if (event.pageY === 0 && Math.floor(y) > Math.floor(event.pageY) || 112 | event.pageX === 0 && Math.floor(x) > Math.floor(event.pageX)) { 113 | 114 | // iOS4 clientX/clientY have the value that should have been 115 | // in pageX/pageY. While pageX/page/ have the value 0 116 | x = x - winPageX; 117 | y = y - winPageY; 118 | } else if (y < (event.pageY - winPageY) || x < (event.pageX - winPageX)) { 119 | 120 | // Some Android browsers have totally bogus values for clientX/Y 121 | // when scrolling/zooming a page. Detectable since clientX/clientY 122 | // should never be smaller than pageX/pageY minus page scroll 123 | x = event.pageX - winPageX; 124 | y = event.pageY - winPageY; 125 | } 126 | 127 | return { 128 | x: x, 129 | y: y 130 | }; 131 | }, 132 | 133 | start: function(event) { 134 | var data = event.touches ? 135 | event.touches[0] : event, 136 | location = u.event.swipe.getLocation(data); 137 | return { 138 | time: (new Date()).getTime(), 139 | coords: [location.x, location.y], 140 | origin: event.target 141 | }; 142 | }, 143 | 144 | stop: function(event) { 145 | var data = event.touches ? 146 | event.touches[0] : event, 147 | location = u.event.swipe.getLocation(data); 148 | return { 149 | time: (new Date()).getTime(), 150 | coords: [location.x, location.y] 151 | }; 152 | }, 153 | 154 | handleSwipe: function(start, stop, thisObject, origTarget) { 155 | if (stop.time - start.time < u.event.swipe.durationThreshold && 156 | Math.abs(start.coords[0] - stop.coords[0]) > u.event.swipe.horizontalDistanceThreshold && 157 | Math.abs(start.coords[1] - stop.coords[1]) < u.event.swipe.verticalDistanceThreshold) { 158 | var direction = start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight"; 159 | 160 | trigger(thisObject, "swipe"); 161 | trigger(thisObject, direction); 162 | return true; 163 | } 164 | return false; 165 | 166 | }, 167 | 168 | // This serves as a flag to ensure that at most one swipe event event is 169 | // in work at any given time 170 | eventInProgress: false, 171 | 172 | setup: function() { 173 | var events, 174 | thisObject = this, 175 | context = {}; 176 | 177 | // Retrieve the events data for this element and add the swipe context 178 | events = thisObject["mobile-events"]; 179 | if (!events) { 180 | events = { 181 | length: 0 182 | }; 183 | thisObject["mobile-events"] = events; 184 | } 185 | events.length++; 186 | events.swipe = context; 187 | 188 | context.start = function(event) { 189 | 190 | // Bail if we're already working on a swipe event 191 | if (u.event.swipe.eventInProgress) { 192 | return; 193 | } 194 | u.event.swipe.eventInProgress = true; 195 | 196 | var stop, 197 | start = u.event.swipe.start(event), 198 | origTarget = event.target, 199 | emitted = false; 200 | 201 | context.move = function(event) { 202 | // if ( !start || event.isDefaultPrevented() ) { 203 | if (!start) { 204 | return; 205 | } 206 | 207 | stop = u.event.swipe.stop(event); 208 | if (!emitted) { 209 | emitted = u.event.swipe.handleSwipe(start, stop, thisObject, origTarget); 210 | if (emitted) { 211 | 212 | // Reset the context to make way for the next swipe event 213 | u.event.swipe.eventInProgress = false; 214 | } 215 | } 216 | // prevent scrolling 217 | if (Math.abs(start.coords[0] - stop.coords[0]) > u.event.swipe.scrollSupressionThreshold) { 218 | event.preventDefault(); 219 | } 220 | }; 221 | 222 | context.stop = function() { 223 | emitted = true; 224 | 225 | // Reset the context to make way for the next swipe event 226 | u.event.swipe.eventInProgress = false; 227 | off(document, touchMoveEvent, context.move); 228 | context.move = null; 229 | }; 230 | 231 | on(document, touchMoveEvent, context.move); 232 | on(document, touchStopEvent, context.stop); 233 | }; 234 | on(thisObject, touchStartEvent, context.start); 235 | }, 236 | 237 | teardown: function() { 238 | var events, context; 239 | 240 | events = thisObject["mobile-events"]; 241 | if (events) { 242 | context = events.swipe; 243 | delete events.swipe; 244 | events.length--; 245 | if (events.length === 0) { 246 | thisObject["mobile-events"] = null; 247 | } 248 | } 249 | 250 | if (context) { 251 | if (context.start) { 252 | off(thisObject, touchStartEvent, context.start); 253 | } 254 | if (context.move) { 255 | off(document, touchMoveEvent, context.move); 256 | } 257 | if (context.stop) { 258 | off(document, touchStopEvent, context.stop); 259 | } 260 | } 261 | } 262 | }; 263 | 264 | u.event.swipeleft = u.event.swipe; 265 | 266 | u.event.swiperight = u.event.swipe; 267 | 268 | var event = u.event; 269 | 270 | export { 271 | event 272 | } 273 | -------------------------------------------------------------------------------- /lib/dom.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module : Sparrow dom 3 | * Author : Kvkens(yueming@yonyou.com) 4 | * Date : 2016-08-16 13:59:17 5 | */ 6 | import { on, stopEvent } from './event'; 7 | /** 8 | * 元素增加指定样式 9 | * @param value 10 | * @returns {*} 11 | */ 12 | var addClass = function addClass(element, value) { 13 | if (element) { 14 | if (typeof element.classList === 'undefined') { 15 | if (u._addClass) { 16 | u._addClass(element, value); 17 | } else { 18 | $(element).addClass(value); 19 | } 20 | } else { 21 | element.classList.add(value); 22 | } 23 | } 24 | 25 | return this; 26 | }; 27 | /** 28 | * 删除元素上指定样式 29 | * @param {Object} element 30 | * @param {Object} value 31 | */ 32 | var removeClass = function removeClass(element, value) { 33 | if (element) { 34 | if (typeof element.classList === 'undefined') { 35 | if (u._removeClass) { 36 | u._removeClass(element, value); 37 | } else { 38 | $(element).removeClass(value); 39 | } 40 | } else { 41 | element.classList.remove(value); 42 | } 43 | } 44 | return this; 45 | }; 46 | /** 47 | * 元素上是否存在该类 48 | * @param {Object} element 49 | * @param {Object} value 50 | */ 51 | var hasClass = function hasClass(element, value) { 52 | if (!element) return false; 53 | if (element.nodeName && (element.nodeName === '#text' || element.nodeName === '#comment')) return false; 54 | if (typeof element.classList === 'undefined') { 55 | if (u._hasClass) { 56 | return u._hasClass(element, value); 57 | } else { 58 | return $(element).hasClass(value); 59 | } 60 | 61 | return false; 62 | } else { 63 | return element.classList.contains(value); 64 | } 65 | }; 66 | /** 67 | * 选择元素类切换 68 | * @param {Object} element 69 | * @param {Object} value 70 | */ 71 | var toggleClass = function toggleClass(element, value) { 72 | if (typeof element.classList === 'undefined') { 73 | return u._toggleClass(element, value); 74 | } else { 75 | return element.classList.toggle(value); 76 | } 77 | }; 78 | 79 | /** 80 | * 向上查找指定类元素 81 | * @param {Object} element 82 | * @param {Object} selector 83 | */ 84 | var closest = function closest(element, selector) { 85 | var tmp = element; 86 | while (tmp != null && !hasClass(tmp, selector) && tmp != document.body) { 87 | tmp = tmp.parentNode; 88 | } 89 | if (tmp == document.body) return null; 90 | return tmp; 91 | }; 92 | 93 | /** 94 | * 元素CSS操作 95 | * @param {Object} element 96 | * @param {Object} csstext 97 | * @param {Object} val 98 | */ 99 | var css = function css(element, csstext, val) { 100 | //TO DO : 实现u.相关方法 101 | if (csstext instanceof Object) { 102 | for (var k in csstext) { 103 | var tmpcss = csstext[k]; 104 | if (["width", "height", "top", "bottom", "left", "right"].indexOf(k) > -1 && isNumber(tmpcss)) { 105 | tmpcss = tmpcss + "px"; 106 | } 107 | element.style[k] = tmpcss; 108 | } 109 | } else { 110 | if (arguments.length > 2) { 111 | element.style[csstext] = val; 112 | } else { 113 | return getStyle(element, csstext); 114 | } 115 | } 116 | }; 117 | 118 | var wrap = function wrap(element, parent) { 119 | var p = makeDOM(parent); 120 | element.parentNode.insertBefore(p, element); 121 | p.appendChild(element); 122 | }; 123 | var getStyle = function getStyle(element, key) { 124 | //不要在循环里用 125 | var allCSS; 126 | if (window.getComputedStyle) { 127 | allCSS = window.getComputedStyle(element); 128 | } else { 129 | allCSS = element.currentStyle; 130 | } 131 | if (allCSS[key] !== undefined) { 132 | return allCSS[key]; 133 | } else { 134 | return ""; 135 | } 136 | }; 137 | var globalZIndex; 138 | /** 139 | * 统一zindex值, 不同控件每次显示时都取最大的zindex,防止显示错乱 140 | */ 141 | var getZIndex = function getZIndex() { 142 | if (!globalZIndex) { 143 | globalZIndex = 2000; 144 | } 145 | return globalZIndex++; 146 | }; 147 | var makeDOM = function makeDOM(htmlString) { 148 | var tempDiv = document.createElement("div"); 149 | tempDiv.innerHTML = htmlString; 150 | var _dom = tempDiv.children[0]; 151 | return _dom; 152 | }; 153 | /** 154 | * element 155 | */ 156 | var makeModal = function makeModal(element, parEle) { 157 | var overlayDiv = document.createElement('div'); 158 | $(overlayDiv).addClass('u-overlay'); 159 | overlayDiv.style.zIndex = getZIndex(); 160 | // 如果有父元素则插入到父元素上,没有则添加到body上 161 | if (parEle && parEle != document.body) { 162 | addClass(overlayDiv, 'hasPar'); 163 | parEle.appendChild(overlayDiv); 164 | } else { 165 | document.body.appendChild(overlayDiv); 166 | } 167 | 168 | element.style.zIndex = getZIndex(); 169 | on(overlayDiv, 'click', function (e) { 170 | stopEvent(e); 171 | }); 172 | return overlayDiv; 173 | }; 174 | 175 | var makModalAssign = function makModalAssign(element, parEle) { 176 | var overlayDiv = document.createElement('div'); 177 | $(overlayDiv).addClass('u-overlay-assign'); 178 | overlayDiv.style.zIndex = getZIndex(); 179 | // 如果有父元素则插入到父元素上,没有则添加到body上 180 | if (parEle && parEle != document.body) { 181 | addClass(overlayDiv, 'hasPar'); 182 | parEle.appendChild(overlayDiv); 183 | } else { 184 | document.body.appendChild(overlayDiv); 185 | } 186 | $('.u-overlay-assign').css('display', "none"); 187 | $('.u-overlay-assign:eq(0)').css('display', "block"); 188 | 189 | element.style.zIndex = getZIndex(); 190 | on(overlayDiv, 'click', function (e) { 191 | stopEvent(e); 192 | }); 193 | return overlayDiv; 194 | }; 195 | var getOffset = function getOffset(Node, offset) { 196 | if (!offset) { 197 | offset = {}; 198 | offset.top = 0; 199 | offset.left = 0; 200 | } 201 | if (Node == document.body) { 202 | return offset; 203 | } 204 | offset.top += Node.offsetTop; 205 | offset.left += Node.offsetLeft; 206 | if (Node.offsetParent) return getOffset(Node.offsetParent, offset);else return offset; 207 | }; 208 | var getScroll = function getScroll(Node, offset) { 209 | if (!offset) { 210 | offset = {}; 211 | offset.top = 0; 212 | offset.left = 0; 213 | } 214 | if (Node == document.body) { 215 | offset.top += Node.scrollTop || document.documentElement.scrollTop; 216 | offset.left += Node.scrollLeft || document.documentElement.scrollLeft; 217 | return offset; 218 | } 219 | if (Node.tagName != 'INPUT') { 220 | offset.top += Node.scrollTop; 221 | offset.left += Node.scrollLeft; 222 | } 223 | 224 | if (Node.parentNode) return getScroll(Node.parentNode, offset);else return offset; 225 | }; 226 | var showPanelByEle = function showPanelByEle(obj) { 227 | var ele = obj.ele, 228 | panel = obj.panel, 229 | position = obj.position, 230 | 231 | // off = u.getOffset(ele),scroll = u.getScroll(ele), 232 | // offLeft = off.left,offTop = off.top, 233 | // scrollLeft = scroll.left,scrollTop = scroll.top, 234 | // eleWidth = ele.offsetWidth,eleHeight = ele.offsetHeight, 235 | // panelWidth = panel.offsetWidth,panelHeight = panel.offsetHeight, 236 | bodyWidth = document.body.clientWidth, 237 | bodyHeight = document.body.clientHeight, 238 | position = position || 'top', 239 | 240 | // left = offLeft - scrollLeft,top = offTop - scrollTop, 241 | eleRect = obj.ele.getBoundingClientRect(), 242 | panelRect = obj.panel.getBoundingClientRect(), 243 | eleWidth = eleRect.width || 0, 244 | eleHeight = eleRect.height || 0, 245 | left = eleRect.left || 0, 246 | top = eleRect.top || 0, 247 | panelWidth = panelRect.width || 0, 248 | panelHeight = panelRect.height || 0, 249 | docWidth = document.documentElement.clientWidth, 250 | docHeight = document.documentElement.clientHeight; 251 | 252 | // 基准点为Ele的左上角 253 | // 后续根据需要完善 254 | if (position == 'left') { 255 | left = left - panelWidth; 256 | top = top + (eleHeight - panelHeight) / 2; 257 | } else if (position == 'right') { 258 | left = left + eleWidth; 259 | top = top + (eleHeight - panelHeight) / 2; 260 | } else if (position == 'top' || position == 'topCenter') { 261 | left = left + (eleWidth - panelWidth) / 2; 262 | top = top - panelHeight; 263 | } else if (position == 'bottom' || position == 'bottomCenter') { 264 | left = left + (eleWidth - panelWidth) / 2; 265 | top = top + eleHeight; 266 | } else if (position == 'bottomLeft') { 267 | left = left; 268 | top = top + eleHeight; 269 | } 270 | 271 | if (left + panelWidth > docWidth) left = docWidth - panelWidth - 10; 272 | if (left < 0) left = 0; 273 | 274 | if (top + panelHeight > docHeight) { 275 | top = docHeight - panelHeight - 10; 276 | } 277 | 278 | if (top < 0) top = 0; 279 | panel.style.left = left + 'px'; 280 | panel.style.top = top + 'px'; 281 | }; 282 | 283 | var getElementLeft = function getElementLeft(element) { 284 | var actualLeft = element.offsetLeft; 285 | var current = element.offsetParent; 286 | while (current !== null) { 287 | actualLeft += current.offsetLeft; 288 | current = current.offsetParent; 289 | } 290 | if (document.compatMode == "BackCompat") { 291 | var elementScrollLeft = document.body.scrollLeft; 292 | } else { 293 | var elementScrollLeft = document.documentElement.scrollLeft; 294 | } 295 | return actualLeft - elementScrollLeft; 296 | }; 297 | var getElementTop = function getElementTop(element) { 298 | var actualTop = element.offsetTop; 299 | var current = element.offsetParent; 300 | while (current !== null) { 301 | actualTop += current.offsetTop; 302 | current = current.offsetParent; 303 | } 304 | if (document.compatMode == "BackCompat") { 305 | var elementScrollTop = document.body.scrollTop; 306 | } else { 307 | var elementScrollTop = document.documentElement.scrollTop; 308 | } 309 | return actualTop - elementScrollTop; 310 | }; 311 | export { addClass, removeClass, hasClass, toggleClass, closest, css, wrap, getStyle, getZIndex, makeDOM, makeModal, makModalAssign, getOffset, getScroll, showPanelByEle, getElementLeft, getElementTop }; --------------------------------------------------------------------------------