├── core ├── tmod │ └── app │ │ ├── app.css │ │ ├── dest │ │ ├── app.css │ │ ├── appDo.tpl │ │ ├── app.html │ │ └── app.tpl │ │ ├── appDo.tpl │ │ ├── entrance.tpl │ │ ├── app.tpl │ │ ├── class.tpl │ │ ├── app.html │ │ └── common.js ├── build │ ├── config.sh │ └── rjs.sh ├── yuidoc.json ├── package.json ├── coreApi │ ├── baseApi.js │ ├── device │ │ └── platform.js │ ├── helper │ │ └── util.js │ └── nativeUI │ │ └── widget.js ├── lib │ ├── jquery.lazyload.js │ └── when.js ├── plugins │ ├── domReady.js │ ├── normalize.js │ ├── require.css.js │ ├── css-builder.js │ ├── almond.js │ └── require.text.js └── kerkee.js ├── html ├── conf │ ├── version.conf │ └── urlmapping.conf ├── cache.manifest ├── modules │ └── test │ │ ├── test.js │ │ ├── testDo.js │ │ └── test.html ├── build │ ├── build.js │ └── example.build.js ├── lib │ ├── jquery.lazyload.js │ └── when.js ├── clientApi │ ├── testApi.js │ ├── objExampleApi.js │ ├── clientUI.js │ └── clientInfo.js └── widget │ ├── domReady.js │ ├── normalize.js │ ├── require.css.js │ ├── css-builder.js │ ├── almond.js │ └── require.text.js ├── .gitignore └── README.md /core/tmod/app/app.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /html/conf/version.conf: -------------------------------------------------------------------------------- 1 | 1 -------------------------------------------------------------------------------- /core/tmod/app/dest/app.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .idea 3 | node_modules 4 | output 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /core/tmod/app/appDo.tpl: -------------------------------------------------------------------------------- 1 | @@include('./class.tpl', { 2 | "main": "app", 3 | "body": "appDo" 4 | }) -------------------------------------------------------------------------------- /core/build/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | export project="kerkee"; 3 | export devRootDir="html"; 4 | export basePath=".."; -------------------------------------------------------------------------------- /core/tmod/app/entrance.tpl: -------------------------------------------------------------------------------- 1 | require(["<%=@@main%>/<%=@@body%>"],function(<%=@@body%>){ 2 | <%=@@body%>.init(); 3 | }); -------------------------------------------------------------------------------- /core/tmod/app/app.tpl: -------------------------------------------------------------------------------- 1 | @@include('./common.js') 2 | @@include('./entrance.tpl', { 3 | "main": "app", 4 | "body": "appDo" 5 | }) -------------------------------------------------------------------------------- /html/cache.manifest: -------------------------------------------------------------------------------- 1 | # Version: 1.0.4 2 | 3 | # RequiredVersion:2.2.0 4 | 5 | # Dek: html.dek 6 | 7 | CACHE: 8 | 9 | NETWORK: 10 | * -------------------------------------------------------------------------------- /core/build/rjs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #npm install requirejs -g 3 | 4 | echo $(pwd) 5 | cd build 6 | echo $(pwd) 7 | 8 | if [ "$1" = "client" ]; 9 | then 10 | node r.js -o ../../html/build/build.js 11 | else 12 | node r.js -o ../../html/build/webbuild.js 13 | fi -------------------------------------------------------------------------------- /core/yuidoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Documenting JavaScript with YUIDoc", 3 | "description": "A tutorial about YUIDoc, for Nettuts+", 4 | "version": "1.0.0", 5 | "url": "http://net.tutsplus.com", 6 | "options": { 7 | "linkNatives": "true", 8 | "outdir": "../output/docs", 9 | "paths": "../html/clientApi" 10 | } 11 | } -------------------------------------------------------------------------------- /html/conf/urlmapping.conf: -------------------------------------------------------------------------------- 1 | #路由映射表 UrlMapping 2 | 3 | #-----------------------------------------------# 4 | # 客户端需要用到的URL # 5 | #-----------------------------------------------# 6 | # test.html: 测试文件 7 | #-----------------------------------------------# 8 | 9 | /test.html /modules/article/test.html 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /core/tmod/app/dest/appDo.tpl: -------------------------------------------------------------------------------- 1 | define([ 2 | 'zepto', 3 | 'template', 4 | 'when', 5 | 'api/helper/util', 6 | 'api/helper/interface', 7 | //自匹配无串参项 8 | 'domReady!' 9 | 10 | ],function($,template,when,util,interface){ 11 | 12 | function special(){ 13 | this.mainBox=$("#mainBox"); 14 | }; 15 | 16 | special.prototype.settings=function(){ 17 | 18 | }; 19 | 20 | special.prototype.render=function(){ 21 | var t=this; 22 | } 23 | 24 | special.prototype.init=function(){ 25 | var t = this; 26 | interface.start(function () { 27 | t.settings(); 28 | t.render(); 29 | }); 30 | } 31 | 32 | return new special(); 33 | }); -------------------------------------------------------------------------------- /core/tmod/app/class.tpl: -------------------------------------------------------------------------------- 1 | define([ 2 | 'zepto', 3 | 'template', 4 | 'when', 5 | 'api/helper/util', 6 | 'api/helper/interface', 7 | //自匹配无串参项 8 | 'domReady!' 9 | 10 | ],function($,template,when,util,interface){ 11 | 12 | function <%=@@body%>(){ 13 | this.mainBox=$("#mainBox"); 14 | }; 15 | 16 | <%=@@body%>.prototype.settings=function(){ 17 | 18 | }; 19 | 20 | <%=@@body%>.prototype.render=function(){ 21 | var t=this; 22 | } 23 | 24 | <%=@@body%>.prototype.init=function(){ 25 | var t = this; 26 | interface.start(function () { 27 | t.settings(); 28 | t.render(); 29 | }); 30 | } 31 | 32 | return new <%=@@body%>(); 33 | }); -------------------------------------------------------------------------------- /core/tmod/app/dest/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | example 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/tmod/app/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | <%=title%> 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /core/tmod/app/common.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //requirejs通用模块设置 4 | requirejs.config({ 5 | 6 | baseUrl:"../../../html", 7 | 8 | paths: { 9 | core: "../core", 10 | api:"../core/coreApi", 11 | when:"lib/when", 12 | kerkee: "../core/kerkee", 13 | swiper: "lib/swiper.min", 14 | zepto:"lib/zepto.min", 15 | lazyload:"lib/jquery.lazyload", 16 | underscore: 'lib/underscore', 17 | fastclick: "lib/fastclick", 18 | template: 'lib/template', 19 | domReady: 'widget/domReady', 20 | text: 'widget/require.text', 21 | css: 'widget/require.css', 22 | text_path:"modules", // eg:"text!text_path/channel.tpl.html" 23 | css_path:"static/css", // eg:"css!css_path/new.css" 24 | }, 25 | 26 | waitSeconds: 10, 27 | 28 | '*':{ 29 | 'text':'widget/require.text', 30 | 'css':'widget/require.css' 31 | }, 32 | 33 | shim: { 34 | "kerkee": { 35 | exports: "kerkee" 36 | }, 37 | 38 | 'zepto':{ 39 | exports:'$' 40 | }, 41 | 42 | 'template': { 43 | exports: "template" 44 | }, 45 | 46 | lazyload:{ 47 | deps:['zepto'], 48 | exports:"lazyload" 49 | }, 50 | 51 | when:{ 52 | deps:['zepto'] 53 | } 54 | } 55 | }); -------------------------------------------------------------------------------- /core/tmod/app/dest/app.tpl: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //requirejs通用模块设置 4 | requirejs.config({ 5 | 6 | baseUrl:"../../../html", 7 | 8 | paths: { 9 | core: "../core", 10 | api:"../core/coreApi", 11 | when:"lib/when", 12 | kerkee: "../core/kerkee", 13 | swiper: "lib/swiper.min", 14 | zepto:"lib/zepto.min", 15 | lazyload:"lib/jquery.lazyload", 16 | underscore: 'lib/underscore', 17 | fastclick: "lib/fastclick", 18 | template: 'lib/template', 19 | domReady: 'widget/domReady', 20 | text: 'widget/require.text', 21 | css: 'widget/require.css', 22 | text_path:"modules", // eg:"text!text_path/channel.tpl.html" 23 | css_path:"static/css", // eg:"css!css_path/new.css" 24 | }, 25 | 26 | waitSeconds: 10, 27 | 28 | '*':{ 29 | 'text':'widget/require.text', 30 | 'css':'widget/require.css' 31 | }, 32 | 33 | shim: { 34 | "kerkee": { 35 | exports: "kerkee" 36 | }, 37 | 38 | 'zepto':{ 39 | exports:'$' 40 | }, 41 | 42 | 'template': { 43 | exports: "template" 44 | }, 45 | 46 | lazyload:{ 47 | deps:['zepto'], 48 | exports:"lazyload" 49 | }, 50 | 51 | when:{ 52 | deps:['zepto'] 53 | } 54 | } 55 | }); -------------------------------------------------------------------------------- /html/modules/test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | //requirejs通用模块设置 4 | requirejs.config({ 5 | 6 | baseUrl:"../../../html", 7 | 8 | paths: { 9 | core: "../core", 10 | api:"../core/coreApi", 11 | when:"lib/when", 12 | kerkee: "../core/kerkee", 13 | swiper: "lib/swiper.min", 14 | zepto:"lib/zepto.min", 15 | lazyload:"lib/jquery.lazyload", 16 | underscore: 'lib/underscore', 17 | fastclick: "lib/fastclick", 18 | template: 'lib/template', 19 | domReady: 'widget/domReady', 20 | text: 'widget/require.text', 21 | css: 'widget/require.css', 22 | text_path:"modules", // eg:"text!text_path/channel.tpl.html" 23 | css_path:"static/css", // eg:"css!css_path/new.css" 24 | }, 25 | 26 | waitSeconds: 10, 27 | 28 | '*':{ 29 | 'text':'widget/require.text', 30 | 'css':'widget/require.css' 31 | }, 32 | 33 | shim: { 34 | "kerkee": { 35 | exports: "kerkee" 36 | }, 37 | 38 | 'zepto':{ 39 | exports:'$' 40 | }, 41 | 42 | 'template': { 43 | exports: "template" 44 | }, 45 | 46 | lazyload:{ 47 | deps:['zepto'], 48 | exports:"lazyload" 49 | }, 50 | 51 | when:{ 52 | deps:['zepto'] 53 | } 54 | } 55 | }); 56 | 57 | //入口方法初始化 58 | require(["modules/test/testDo"],function(testDo){ 59 | testDo.init(); 60 | }); 61 | -------------------------------------------------------------------------------- /core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kerkee", 3 | "project": "kerkee", 4 | "version": "0.9.0", 5 | "host": "", 6 | "path": "", 7 | "devDependencies": { 8 | "del": "^1.1.1", 9 | "gulp": "^3.9.0", 10 | "gulp-autoprefixer": "^2.0.0", 11 | "gulp-cache": "^0.2.4", 12 | "gulp-clean": "^0.2.4", 13 | "gulp-concat": "^2.4.3", 14 | "gulp-data": "^1.2.0", 15 | "gulp-file-copy": "0.0.1", 16 | "gulp-file-include": "^0.13.7", 17 | "gulp-html-replace": "^1.4.3", 18 | "gulp-htmlmin": "^1.1.0", 19 | "gulp-imagemin": "^2.1.0", 20 | "gulp-include-source": "0.0.5", 21 | "gulp-jshint": "^1.11.2", 22 | "gulp-less": "^1.0.1", 23 | "gulp-livereload": "^3.5.0", 24 | "gulp-load-plugins": "^0.10.0", 25 | "gulp-md5-plus": "^0.1.6", 26 | "gulp-minify-css": "^0.4.3", 27 | "gulp-notify": "^2.2.0", 28 | "gulp-remove-code": "^1.0.2", 29 | "gulp-rename": "^1.2.0", 30 | "gulp-ruby-sass": "^1.0.0-alpha.3", 31 | "gulp-shell": "^0.4.2", 32 | "gulp-sourcemaps": "^1.3.0", 33 | "gulp-template": "^2.1.0", 34 | "gulp-tmod": "^0.1.2", 35 | "gulp-uglify": "^0.2.1", 36 | "gulp-util": "^3.0.6", 37 | "gulp-webserver": "^0.9.0", 38 | "gulp-yuidoc": "^0.1.2", 39 | "gulp-zip": "^3.0.2", 40 | "imagemin-jpegtran": "^4.0.0", 41 | "imagemin-optipng": "^4.2.0", 42 | "log4js": "^0.6.26", 43 | "path": "^0.11.11", 44 | "through2": "^2.0.0" 45 | }, 46 | "log4js": { 47 | "appenders": [ 48 | { 49 | "type": "console", 50 | "pattern": "yyyy-MM-dd", 51 | "alwaysIncludePattern": true, 52 | "pollInterval": 1 53 | } 54 | ], 55 | "replaceConsole": true 56 | }, 57 | "dependencies": { 58 | "q": "^1.4.1" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 这是一个kerkee v0.9.0 的javascript前端项目模板 ### 2 | 3 | ### 本工程提供一个项目模板,可减轻开发环境搭建工作和客户端的前端模块功能划分。### 4 | 5 | #### 该模块包含如下内容:#### 6 | >1. 使用MVC模式,高度解耦 7 | >2. 引入webapp概念,配合kerkee进行无缝增量更新 8 | >3. 本框架目标包为html.zip,无进行加密,可自行对zip包进行文件加密 9 | >4. 可作为kerkee的h5框架使用,也可单独使用。当然kerkee native的H5可以不使用此框架,你只需引入kerkee.js到你的工程中即可 10 | >5. 使用zepto underscore jquery atrtemplate等框架 11 | >6. 使用kerkee的kerkee.js用于配合kerkee环境的搭建 12 | >7. 使用requirejs amd模块加载器 13 | >8. 使用gulp构建 14 | >9. 展示了页面切分和逻辑模块划分(html、css、js),及如何根据实际切换模块。适用团队分工合作 15 | >10. 支持两种应用场景,浏览器,移动app 16 | >11. 支持生产环境,即可将js合并压缩成单个js文件,优化css文件,优化html文件 17 | >12. 后期会逐步引入页面路由技术,页面转换的有限状态机应用等。 18 | >13. 可使用URD技术配合使用更佳(URD是我2015年9月份刚提出的架构理念,目前只用在斗米客户端中,还未成熟,以后个时间分享一下) 19 | > 20 | 21 | ## 目录结构 22 | ~~~ 23 | ├── html -------------------------------- kerkee的开发目录 24 | │ ├── cache.manifest ------------------------ 项目模块配置信息,包含依赖客户端版本,当前模块版本等,便于升级使用 25 | │   ├── build --------------------------- 前端项目构建配置模块,基于r.js,具体配置信息查看build.js 26 | │   │   └── build.js ---------------------- 客户端构建文件 27 | │   ├── static -------------------------- 静态资源存放目录 28 | │   │   ├── css ------------------------- css样式表资源存放目录 29 | │   │   └── images ---------------------- 图片资源存放文件 30 | │   ├── modules 31 | │   │   └── test ----------------------- 模块包名,如test等。放置模块的js、html、less等文件 32 | │   │     ├── test.js ----------------- 模块配置,test.html对应的script引入的入口文件,通常用于配置加载器所需要的资源路径和初始化方法(使用r.js压缩合并后,modules里对应的模块包里的资源会合并到这个里面) 33 | │  │ ├── testDo.js --------------- 模块功能初始化入口,需要包含一个和模块名+Do方法的模块,作为初始化方法模块(类似java里的main方法) 34 | │   │   └── test.html --------------- 前端项目开发中需要的模块主入口页面 35 | │ ├── conf ---------------------------- 项目配置目录 36 | │   │   ├── urlmapping.conf ------------- 路由配置 37 | │   │   └── version.conf ---------------- 版本配置文件 38 | │ ├── clientApi ----------------------- API接口目录 39 | │  │    ├── testApi.js -------------- 接口模块 40 | │  │    └── util.js------------------ 工具库函数 41 | │ ├── lib ----------------------------- 第三方库目录 42 | │ └── widget -------------------------- 组件存放目录 43 | │ 44 | └──core -------------------------------- 核心框架 45 | 46 | ~~~ 47 | 48 | 49 | ## 配置环境 50 | 1、先安装node 51 | 52 | 2、安装gulp 53 | 54 | `npm install -g gulp` 55 | 56 | 3、cd到core目录,安装依赖 57 | 58 | `npm install` 59 | 60 | ## 项目构建 ## 61 | `gulp build` 62 | 63 | 64 | -------------------------------------------------------------------------------- /html/build/build.js: -------------------------------------------------------------------------------- 1 | ({ 2 | /*npm install requirejs -g*/ 3 | /*node r.js -o build.js*/ 4 | appDir: '../../html', //相对build.js的当前路径的所属地址 5 | baseUrl: './', //定位到appDir后,找到js脚本相对页面地址的位置 6 | dir: '../../output/target', //生成的文件地址 7 | modules: [ 8 | { 9 | name: 'modules/test/test', 10 | include: ['almond', 'modules/test/testDo'] 11 | }/*,{ 12 | name: 'modules/index/index', 13 | include: ['almond', 'modules/index/indexDo'] 14 | }*/ 15 | ], 16 | fileExclusionRegExp: /(^build)|(.idea)|(gulpfile.js)|(gulp.sh)|(package.json)|(.gitignore)|(tpl)|(less)$/, 17 | optimizeCss: 'standard', /* none|standard|standard.keepLines|standard.keepComments|standard.keepComments.keepLines */ 18 | removeCombined: true, 19 | inlineText: false, 20 | //optimize: "none", 21 | 22 | waitSeconds: 10, 23 | 24 | '*':{ 25 | 'text':'widget/require.text', 26 | 'css':'widget/require.css' 27 | }, 28 | 29 | paths: { 30 | core: "../core", 31 | api:"../core/coreApi", 32 | when:"lib/when", 33 | kerkee: "../core/kerkee", 34 | swiper: "lib/swiper.min", 35 | zepto:"lib/zepto.min", 36 | lazyload:"lib/jquery.lazyload", 37 | underscore: 'lib/underscore', 38 | fastclick: "lib/fastclick", 39 | template: 'lib/template', 40 | domReady: 'widget/domReady', 41 | text: 'widget/require.text', 42 | css: 'widget/require.css', 43 | text_path:"modules", // eg:"text!text_path/channel.tpl.html" 44 | css_path:"static/css", // eg:"css!css_path/new.css" 45 | jquery: 'lib/jquery-2.1.3', 46 | almond:"widget/almond" 47 | }, 48 | 49 | shim: { 50 | "kerkee": { 51 | exports: "kerkee" 52 | }, 53 | 54 | "video": { 55 | exports: "video" 56 | }, 57 | 58 | 'zepto': { 59 | exports: '$' 60 | }, 61 | 62 | when:{ 63 | deps:['zepto'], 64 | exports:"when" 65 | }, 66 | 67 | 'template': { 68 | exports: "template" 69 | }, 70 | 71 | lazyload: { 72 | deps: ['zepto'], 73 | exports: "lazyload" 74 | } 75 | } 76 | 77 | }) 78 | -------------------------------------------------------------------------------- /core/coreApi/baseApi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * base基础Api类 3 | * @class BaseApi 4 | * @extends Klass 5 | * @constructor 6 | * @module modules 7 | * @example 8 | * define('clientApi/baseApi',',function(base){ 9 | * base.sub(child); 10 | * }); 11 | * @since 1.0.0 12 | * @public 13 | */ 14 | 15 | define(["api/helper/util"], function (util) { 16 | 17 | var BaseApi = (function () { 18 | 19 | //继承自Util类 20 | util.Klass().sub(BaseApi); 21 | 22 | //构造函数 23 | function BaseApi() { 24 | 25 | BaseApi.__super__.constructor.apply(this, arguments); 26 | } 27 | 28 | BaseApi.include({ 29 | 30 | /** 31 | * 向客户端请求参数 32 | * @method getOptions 33 | * @public 34 | * @param {Function} callBack 回调函数 35 | * @return {Object} 36 | * @example 37 | * indexApi.getOptions(function(data){ 38 | * console.log(data); 39 | * }); 40 | * @since 1.0.0 41 | */ 42 | getOptions: function (callBack) { 43 | this.sendData({ 44 | method: "getOptions", 45 | param: { 46 | "info": "getOptions" 47 | }, 48 | callBack: callBack 49 | }); 50 | }, 51 | 52 | /** 53 | * 通知客户端数据已加载完毕 54 | * @method dataDownloadFinished 55 | * @example 56 | * indexApi.dataDownloadFinished(); 57 | * @since 1.0.0 58 | */ 59 | dataDownloadFinished: function(){ 60 | this.sendData({ 61 | method: "dataDownloadFinished", 62 | param: { 63 | "info": "dataDownloadFinished" 64 | } 65 | }); 66 | }, 67 | 68 | /** 69 | * 调用客户端刷新 70 | * @method refreshPage 71 | * @example 72 | * indexApi.refreshPage(); 73 | * @since 1.0.0 74 | */ 75 | refreshPage: function(type){ 76 | this.sendData({ 77 | method: "refreshPage", 78 | param: { 79 | "info": "refreshPage", 80 | "type": type 81 | } 82 | }); 83 | } 84 | 85 | 86 | }); 87 | 88 | return BaseApi; 89 | })(); 90 | 91 | return BaseApi; 92 | 93 | }); -------------------------------------------------------------------------------- /html/modules/test/testDo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by zihong on 2015/9/14. 3 | */ 4 | define([ 5 | 'zepto', 6 | 'template', 7 | 'clientApi/clientUI', 8 | 'clientApi/clientInfo', 9 | 'api/helper/util', 10 | 'api/nativeUI/widget', 11 | 'clientApi/testApi', 12 | 'clientApi/objExampleApi', 13 | 'domReady!' 14 | ], 15 | 16 | function ($,template,clientUI,clientInfo,util,widget,testApi,objExampleApi) { 17 | function TestDo(){ 18 | } 19 | 20 | TestDo.prototype.render=function(){ 21 | $('body').on('click','.toast',function(){ 22 | widget.toast('this is a test'); 23 | }); 24 | 25 | $('body').on('click','.alert',function(){ 26 | widget.alertDialog('this is a test','this is a test message',function(){ alert("callback normal"); },'OK'); 27 | }); 28 | 29 | // alertClientUI 30 | $('body').on('click','.alertClientUI',function(){ 31 | clientUI.clientToast('this is a test','warn'); 32 | }); 33 | 34 | $('body').on('click','.testInfo',function(){ 35 | alert(1); 36 | testApi.getTestInfo(function(data){ 37 | console.log("callback:"+data); 38 | },"test getTestInfo fun"); 39 | }); 40 | 41 | //objExampleNotStaticFunction 42 | $('body').on('click','.objExampleNotStaticFunction',function(){ 43 | objExampleApi.objExampleNotStaticFunction(function(data){ 44 | console.log("callback:"+data); 45 | },"objExampleApi.objExampleNotStaticFunction that click from js"); 46 | }); 47 | 48 | //objExampleStaticFunction 49 | $('body').on('click','.objExampleStaticFunction',function(){ 50 | objExampleApi.objExampleStaticFunction(function(data){ 51 | console.log("callback:"+data); 52 | },"objExampleApi.objExampleStaticFunction that click from js"); 53 | }); 54 | 55 | window.testReturnString = function (json){ 56 | 57 | // var test = {}; 58 | // test.a = "t1"; 59 | // test.b = "t2"; 60 | // test.c = "t3"; 61 | // test.d = "t4"; 62 | // alert(JSON.stringify(test)); 63 | alert(typeof(json)); 64 | alert(json); 65 | alert(JSON.stringify(json)); 66 | 67 | // return test; 68 | return "Im testReturnString"; 69 | }; 70 | }; 71 | 72 | TestDo.prototype.init=function(){ 73 | var t=this; 74 | testApi.start(function () { 75 | t.render(); 76 | }); 77 | }; 78 | 79 | return new TestDo(); 80 | }); 81 | -------------------------------------------------------------------------------- /core/lib/jquery.lazyload.js: -------------------------------------------------------------------------------- 1 | !function(a,b,c,d){var e=a(b);a.fn.lazyload=function(c){function i(){var b=0;f.each(function(){var c=a(this);if(!h.skip_invisible||"none"!==c.css("display"))if(a.abovethetop(this,h)||a.leftofbegin(this,h));else if(a.belowthefold(this,h)||a.rightoffold(this,h)){if(++b>h.failure_limit)return!1}else c.trigger("appear"),b=0})}var g,f=this,h={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null};return c&&(d!==c.failurelimit&&(c.failure_limit=c.failurelimit,delete c.failurelimit),d!==c.effectspeed&&(c.effect_speed=c.effectspeed,delete c.effectspeed),a.extend(h,c)),g=h.container===d||h.container===b?e:a(h.container),0===h.event.indexOf("scroll")&&g.on(h.event,function(){return i()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,c.one("appear",function(){if(!this.loaded){if(h.appear){var d=f.length;h.appear.call(b,d,h)}a("").on("load",function(){var d,e;c.hide().attr("src",c.data(h.data_attribute))[h.effect](h.effect_speed),b.loaded=!0,d=a.grep(f,function(a){return!a.loaded}),f=a(d),h.load&&(e=f.length,h.load.call(b,e,h))}).attr("src",c.data(h.data_attribute))}}),0!==h.event.indexOf("scroll")&&c.on(h.event,function(){b.loaded||c.trigger("appear")})}),e.on("resize",function(){i()}),/iphone|ipod|ipad.*os 5/gi.test(navigator.appVersion)&&e.on("pageshow",function(b){b=b.originalEvent||b,b.persisted&&f.each(function(){a(this).trigger("appear")})}),a(b).on("load",function(){i()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?e.height()+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e[0].scrollX:a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e[0].scrollX:a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.fn,{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}($,window,document); -------------------------------------------------------------------------------- /html/lib/jquery.lazyload.js: -------------------------------------------------------------------------------- 1 | !function(a,b,c,d){var e=a(b);a.fn.lazyload=function(c){function i(){var b=0;f.each(function(){var c=a(this);if(!h.skip_invisible||"none"!==c.css("display"))if(a.abovethetop(this,h)||a.leftofbegin(this,h));else if(a.belowthefold(this,h)||a.rightoffold(this,h)){if(++b>h.failure_limit)return!1}else c.trigger("appear"),b=0})}var g,f=this,h={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null};return c&&(d!==c.failurelimit&&(c.failure_limit=c.failurelimit,delete c.failurelimit),d!==c.effectspeed&&(c.effect_speed=c.effectspeed,delete c.effectspeed),a.extend(h,c)),g=h.container===d||h.container===b?e:a(h.container),0===h.event.indexOf("scroll")&&g.on(h.event,function(){return i()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,c.one("appear",function(){if(!this.loaded){if(h.appear){var d=f.length;h.appear.call(b,d,h)}a("").on("load",function(){var d,e;c.hide().attr("src",c.data(h.data_attribute))[h.effect](h.effect_speed),b.loaded=!0,d=a.grep(f,function(a){return!a.loaded}),f=a(d),h.load&&(e=f.length,h.load.call(b,e,h))}).attr("src",c.data(h.data_attribute))}}),0!==h.event.indexOf("scroll")&&c.on(h.event,function(){b.loaded||c.trigger("appear")})}),e.on("resize",function(){i()}),/iphone|ipod|ipad.*os 5/gi.test(navigator.appVersion)&&e.on("pageshow",function(b){b=b.originalEvent||b,b.persisted&&f.each(function(){a(this).trigger("appear")})}),a(b).on("load",function(){i()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?e.height()+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e[0].scrollX:a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e[0].scrollX:a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.fn,{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}($,window,document); -------------------------------------------------------------------------------- /html/clientApi/testApi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Demo相关接口 3 | * @class TestApi 4 | * @extends Klass 5 | * @constructor 6 | * @module modules 7 | * @example 8 | * define('helper/testApi',',function(platform){ 9 | * testApi.getTestInfo(); 10 | * }); 11 | * @since 1.0.0 12 | * @public 13 | */ 14 | 15 | define(["api/helper/util"], function ( util) { 16 | 17 | var TestApi = (function () { 18 | 19 | //构建一个TestApi类,继承自基础类 20 | util.Klass().sub(TestApi); 21 | 22 | //构造函数 23 | function TestApi() { 24 | /** 25 | * 映射客户端类的名称 (必选) 26 | * @property nativeCls 27 | * @type string 28 | * @since 1.0.0 29 | * @default "jsBridgeClient" 30 | * @public 31 | */ 32 | 33 | /** 34 | * jsBridgeClient通信对象 (必选) 35 | * @property jsbc 36 | * @type string 37 | * @since 1.0.0 38 | * @default jsBridgeClient 39 | * @public 40 | */ 41 | 42 | /** 43 | * 模块信息描述 (可选) 44 | * @property name 45 | * @type string 46 | * @since 1.0.0 47 | * @public 48 | */ 49 | 50 | /** 51 | * 模块版本 (可选) 52 | * @property verison 53 | * @type int 54 | * @since 1.0.0 55 | * @public 56 | */ 57 | 58 | /** 59 | * 模块作者 (可选) 60 | * @property author 61 | * @type string 62 | * @since 1.0.0 63 | * @public 64 | */ 65 | 66 | TestApi.__super__.constructor.apply(this, arguments); 67 | } 68 | 69 | TestApi.include({ 70 | 71 | /** 72 | * 获取测试信息 73 | * @method getTestInfo 74 | * @public 75 | * @param {Function} callBack 回调函数 76 | * @param {String} testInfo 测试信息 77 | * @return {Object} 78 | * @example 79 | * testApi.getTestInfo(function(data){ 80 | * console.log(data); 81 | * },"test"); 82 | * @since 1.0.0 83 | */ 84 | getTestInfo: function (callBack, testInfo) { 85 | this.sendData({ 86 | method: "testInfo", 87 | param: { 88 | "testInfo": "I'm testInfo" 89 | }, 90 | callBack: callBack 91 | }); 92 | } 93 | 94 | 95 | }); 96 | return TestApi; 97 | })(); 98 | 99 | return new TestApi({ 100 | name: "kerkee testApi", 101 | author: "zihong", 102 | version: "1.0", 103 | jsbc: jsBridgeClient, 104 | nativeCls: "testModule" 105 | }); 106 | 107 | }); 108 | -------------------------------------------------------------------------------- /html/clientApi/objExampleApi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Demo相关接口 3 | * @class objExampleApi 4 | * @extends Klass 5 | * @constructor 6 | * @module modules 7 | * @example 8 | * define('helper/objExampleApi',',function(platform){ 9 | * testApi.getTestInfo(); 10 | * }); 11 | * @since 1.0.0 12 | * @public 13 | */ 14 | 15 | define(["api/helper/util"], function (util) { 16 | 17 | var ObjExampleApi = (function () { 18 | 19 | //构建一个TestApi类,继承自基础类 20 | util.Klass().sub(ObjExampleApi); 21 | 22 | //构造函数 23 | function ObjExampleApi() { 24 | /** 25 | * 映射客户端类的名称 (必选) 26 | * @property nativeCls 27 | * @type string 28 | * @since 1.0.0 29 | * @default "jsBridgeClient" 30 | * @public 31 | */ 32 | 33 | /** 34 | * jsBridgeClient通信对象 (必选) 35 | * @property jsbc 36 | * @type string 37 | * @since 1.0.0 38 | * @default jsBridgeClient 39 | * @public 40 | */ 41 | 42 | /** 43 | * 模块信息描述 (可选) 44 | * @property name 45 | * @type string 46 | * @since 1.0.0 47 | * @public 48 | */ 49 | 50 | /** 51 | * 模块版本 (可选) 52 | * @property verison 53 | * @type int 54 | * @since 1.0.0 55 | * @public 56 | */ 57 | 58 | /** 59 | * 模块作者 (可选) 60 | * @property author 61 | * @type string 62 | * @since 1.0.0 63 | * @public 64 | */ 65 | 66 | ObjExampleApi.__super__.constructor.apply(this, arguments); 67 | } 68 | 69 | ObjExampleApi.include({ 70 | 71 | /** 72 | * 测试非静态的Native函数 73 | * @method objExampleNotStaticFunction 74 | * @public 75 | * @param {Function} callBack 回调函数 76 | * @param {String} testInfo 测试信息 77 | * @return {Object} 78 | * @example 79 | * objExampleApi.objExampleNotStaticFunction(function(data){ 80 | * console.log(data); 81 | * },"test"); 82 | * @since 1.0.0 83 | */ 84 | objExampleNotStaticFunction: function (callBack, testInfo) { 85 | this.sendData({ 86 | method: "objExampleNotStaticFunction", 87 | param: { 88 | "testInfo": "I'm objExampleNotStaticFunction" 89 | }, 90 | callBack: callBack 91 | }); 92 | }, 93 | 94 | /** 95 | * 测试静态的Native函数 96 | * @method objExampleStaticFunction 97 | * @public 98 | * @param {Function} callBack 回调函数 99 | * @param {String} testInfo 测试信息 100 | * @return {Object} 101 | * @example 102 | * objExampleApi.objExampleStaticFunction(function(data){ 103 | * console.log(data); 104 | * },"test"); 105 | * @since 1.0.0 106 | */ 107 | objExampleStaticFunction: function (callBack, testInfo) { 108 | this.sendData({ 109 | method: "objExampleStaticFunction", 110 | param: { 111 | "testInfo": "I'm objExampleStaticFunction" 112 | }, 113 | callBack: callBack 114 | }); 115 | } 116 | 117 | }); 118 | return ObjExampleApi; 119 | })(); 120 | 121 | return new ObjExampleApi({ 122 | name: "kerkee objExampleApi", 123 | author: "zihong", 124 | version: "1.0", 125 | jsbc: jsBridgeClient, 126 | nativeCls: "objExampleApi" 127 | }); 128 | 129 | }); -------------------------------------------------------------------------------- /core/plugins/domReady.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | 'use strict'; 3 | 4 | var isTop, testDiv, scrollIntervalId, 5 | isBrowser = typeof window !== "undefined" && window.document, 6 | isPageLoaded = !isBrowser, 7 | doc = isBrowser ? document : null, 8 | readyCalls = []; 9 | 10 | function runCallbacks(callbacks) { 11 | var i; 12 | for (i = 0; i < callbacks.length; i += 1) { 13 | callbacks[i](doc); 14 | } 15 | } 16 | 17 | function callReady() { 18 | var callbacks = readyCalls; 19 | 20 | if (isPageLoaded) { 21 | //Call the DOM ready callbacks 22 | if (callbacks.length) { 23 | readyCalls = []; 24 | runCallbacks(callbacks); 25 | } 26 | } 27 | } 28 | 29 | /** 30 | * Sets the page as loaded. 31 | */ 32 | function pageLoaded() { 33 | if (!isPageLoaded) { 34 | isPageLoaded = true; 35 | if (scrollIntervalId) { 36 | clearInterval(scrollIntervalId); 37 | } 38 | 39 | callReady(); 40 | } 41 | } 42 | 43 | if (isBrowser) { 44 | if (document.addEventListener) { 45 | //Standards. Hooray! Assumption here that if standards based, 46 | //it knows about DOMContentLoaded. 47 | document.addEventListener("DOMContentLoaded", pageLoaded, false); 48 | window.addEventListener("load", pageLoaded, false); 49 | } else if (window.attachEvent) { 50 | window.attachEvent("onload", pageLoaded); 51 | 52 | testDiv = document.createElement('div'); 53 | try { 54 | isTop = window.frameElement === null; 55 | } catch (e) {} 56 | 57 | //DOMContentLoaded approximation that uses a doScroll, as found by 58 | //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/, 59 | //but modified by other contributors, including jdalton 60 | if (testDiv.doScroll && isTop && window.external) { 61 | scrollIntervalId = setInterval(function () { 62 | try { 63 | testDiv.doScroll(); 64 | pageLoaded(); 65 | } catch (e) {} 66 | }, 30); 67 | } 68 | } 69 | 70 | //Check if document already complete, and if so, just trigger page load 71 | //listeners. Latest webkit browsers also use "interactive", and 72 | //will fire the onDOMContentLoaded before "interactive" but not after 73 | //entering "interactive" or "complete". More details: 74 | //http://dev.w3.org/html5/spec/the-end.html#the-end 75 | //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded 76 | //Hmm, this is more complicated on further use, see "firing too early" 77 | //bug: https://github.com/requirejs/domReady/issues/1 78 | //so removing the || document.readyState === "interactive" test. 79 | //There is still a window.onload binding that should get fired if 80 | //DOMContentLoaded is missed. 81 | if (document.readyState === "complete") { 82 | pageLoaded(); 83 | } 84 | } 85 | 86 | /** START OF PUBLIC API **/ 87 | 88 | /** 89 | * Registers a callback for DOM ready. If DOM is already ready, the 90 | * callback is called immediately. 91 | * @param {Function} callback 92 | */ 93 | function domReady(callback) { 94 | if (isPageLoaded) { 95 | callback(doc); 96 | } else { 97 | readyCalls.push(callback); 98 | } 99 | return domReady; 100 | } 101 | 102 | domReady.version = '2.0.1'; 103 | 104 | /** 105 | * Loader Plugin API method 106 | */ 107 | domReady.load = function (name, req, onLoad, config) { 108 | if (config.isBuild) { 109 | onLoad(null); 110 | } else { 111 | domReady(onLoad); 112 | } 113 | }; 114 | 115 | /** END OF PUBLIC API **/ 116 | 117 | return domReady; 118 | }); 119 | -------------------------------------------------------------------------------- /html/widget/domReady.js: -------------------------------------------------------------------------------- 1 | define(function () { 2 | 'use strict'; 3 | 4 | var isTop, testDiv, scrollIntervalId, 5 | isBrowser = typeof window !== "undefined" && window.document, 6 | isPageLoaded = !isBrowser, 7 | doc = isBrowser ? document : null, 8 | readyCalls = []; 9 | 10 | function runCallbacks(callbacks) { 11 | var i; 12 | for (i = 0; i < callbacks.length; i += 1) { 13 | callbacks[i](doc); 14 | } 15 | } 16 | 17 | function callReady() { 18 | var callbacks = readyCalls; 19 | 20 | if (isPageLoaded) { 21 | //Call the DOM ready callbacks 22 | if (callbacks.length) { 23 | readyCalls = []; 24 | runCallbacks(callbacks); 25 | } 26 | } 27 | } 28 | 29 | /** 30 | * Sets the page as loaded. 31 | */ 32 | function pageLoaded() { 33 | if (!isPageLoaded) { 34 | isPageLoaded = true; 35 | if (scrollIntervalId) { 36 | clearInterval(scrollIntervalId); 37 | } 38 | 39 | callReady(); 40 | } 41 | } 42 | 43 | if (isBrowser) { 44 | if (document.addEventListener) { 45 | //Standards. Hooray! Assumption here that if standards based, 46 | //it knows about DOMContentLoaded. 47 | document.addEventListener("DOMContentLoaded", pageLoaded, false); 48 | window.addEventListener("load", pageLoaded, false); 49 | } else if (window.attachEvent) { 50 | window.attachEvent("onload", pageLoaded); 51 | 52 | testDiv = document.createElement('div'); 53 | try { 54 | isTop = window.frameElement === null; 55 | } catch (e) {} 56 | 57 | //DOMContentLoaded approximation that uses a doScroll, as found by 58 | //Diego Perini: http://javascript.nwbox.com/IEContentLoaded/, 59 | //but modified by other contributors, including jdalton 60 | if (testDiv.doScroll && isTop && window.external) { 61 | scrollIntervalId = setInterval(function () { 62 | try { 63 | testDiv.doScroll(); 64 | pageLoaded(); 65 | } catch (e) {} 66 | }, 30); 67 | } 68 | } 69 | 70 | //Check if document already complete, and if so, just trigger page load 71 | //listeners. Latest webkit browsers also use "interactive", and 72 | //will fire the onDOMContentLoaded before "interactive" but not after 73 | //entering "interactive" or "complete". More details: 74 | //http://dev.w3.org/html5/spec/the-end.html#the-end 75 | //http://stackoverflow.com/questions/3665561/document-readystate-of-interactive-vs-ondomcontentloaded 76 | //Hmm, this is more complicated on further use, see "firing too early" 77 | //bug: https://github.com/requirejs/domReady/issues/1 78 | //so removing the || document.readyState === "interactive" test. 79 | //There is still a window.onload binding that should get fired if 80 | //DOMContentLoaded is missed. 81 | if (document.readyState === "complete") { 82 | pageLoaded(); 83 | } 84 | } 85 | 86 | /** START OF PUBLIC API **/ 87 | 88 | /** 89 | * Registers a callback for DOM ready. If DOM is already ready, the 90 | * callback is called immediately. 91 | * @param {Function} callback 92 | */ 93 | function domReady(callback) { 94 | if (isPageLoaded) { 95 | callback(doc); 96 | } else { 97 | readyCalls.push(callback); 98 | } 99 | return domReady; 100 | } 101 | 102 | domReady.version = '2.0.1'; 103 | 104 | /** 105 | * Loader Plugin API method 106 | */ 107 | domReady.load = function (name, req, onLoad, config) { 108 | if (config.isBuild) { 109 | onLoad(null); 110 | } else { 111 | domReady(onLoad); 112 | } 113 | }; 114 | 115 | /** END OF PUBLIC API **/ 116 | 117 | return domReady; 118 | }); 119 | -------------------------------------------------------------------------------- /core/plugins/normalize.js: -------------------------------------------------------------------------------- 1 | //>>excludeStart('excludeRequireCss', pragmas.excludeRequireCss) 2 | /* 3 | * css.normalize.js 4 | * 5 | * CSS Normalization 6 | * 7 | * CSS paths are normalized based on an optional basePath and the RequireJS config 8 | * 9 | * Usage: 10 | * normalize(css, fromBasePath, toBasePath); 11 | * 12 | * css: the stylesheet content to normalize 13 | * fromBasePath: the absolute base path of the css relative to any root (but without ../ backtracking) 14 | * toBasePath: the absolute new base path of the css relative to the same root 15 | * 16 | * Absolute dependencies are left untouched. 17 | * 18 | * Urls in the CSS are picked up by regular expressions. 19 | * These will catch all statements of the form: 20 | * 21 | * url(*) 22 | * url('*') 23 | * url("*") 24 | * 25 | * @import '*' 26 | * @import "*" 27 | * 28 | * (and so also @import url(*) variations) 29 | * 30 | * For urls needing normalization 31 | * 32 | */ 33 | 34 | define(function() { 35 | 36 | // regular expression for removing double slashes 37 | // eg http://www.example.com//my///url/here -> http://www.example.com/my/url/here 38 | var slashes = /([^:])\/+/g 39 | var removeDoubleSlashes = function(uri) { 40 | return uri.replace(slashes, '$1/'); 41 | } 42 | 43 | // given a relative URI, and two absolute base URIs, convert it from one base to another 44 | var protocolRegEx = /[^\:\/]*:\/\/([^\/])*/; 45 | var absUrlRegEx = /^(\/|data:)/; 46 | function convertURIBase(uri, fromBase, toBase) { 47 | if (uri.match(absUrlRegEx) || uri.match(protocolRegEx)) 48 | return uri; 49 | uri = removeDoubleSlashes(uri); 50 | // if toBase specifies a protocol path, ensure this is the same protocol as fromBase, if not 51 | // use absolute path at fromBase 52 | var toBaseProtocol = toBase.match(protocolRegEx); 53 | var fromBaseProtocol = fromBase.match(protocolRegEx); 54 | if (fromBaseProtocol && (!toBaseProtocol || toBaseProtocol[1] != fromBaseProtocol[1] || toBaseProtocol[2] != fromBaseProtocol[2])) 55 | return absoluteURI(uri, fromBase); 56 | 57 | else { 58 | return relativeURI(absoluteURI(uri, fromBase), toBase); 59 | } 60 | }; 61 | 62 | // given a relative URI, calculate the absolute URI 63 | function absoluteURI(uri, base) { 64 | if (uri.substr(0, 2) == './') 65 | uri = uri.substr(2); 66 | 67 | // absolute urls are left in tact 68 | if (uri.match(absUrlRegEx) || uri.match(protocolRegEx)) 69 | return uri; 70 | 71 | var baseParts = base.split('/'); 72 | var uriParts = uri.split('/'); 73 | 74 | baseParts.pop(); 75 | 76 | while (curPart = uriParts.shift()) 77 | if (curPart == '..') 78 | baseParts.pop(); 79 | else 80 | baseParts.push(curPart); 81 | 82 | return baseParts.join('/'); 83 | }; 84 | 85 | 86 | // given an absolute URI, calculate the relative URI 87 | function relativeURI(uri, base) { 88 | 89 | // reduce base and uri strings to just their difference string 90 | var baseParts = base.split('/'); 91 | baseParts.pop(); 92 | base = baseParts.join('/') + '/'; 93 | i = 0; 94 | while (base.substr(i, 1) == uri.substr(i, 1)) 95 | i++; 96 | while (base.substr(i, 1) != '/') 97 | i--; 98 | base = base.substr(i + 1); 99 | uri = uri.substr(i + 1); 100 | 101 | // each base folder difference is thus a backtrack 102 | baseParts = base.split('/'); 103 | var uriParts = uri.split('/'); 104 | out = ''; 105 | while (baseParts.shift()) 106 | out += '../'; 107 | 108 | // finally add uri parts 109 | while (curPart = uriParts.shift()) 110 | out += curPart + '/'; 111 | 112 | return out.substr(0, out.length - 1); 113 | }; 114 | 115 | var normalizeCSS = function(source, fromBase, toBase) { 116 | 117 | fromBase = removeDoubleSlashes(fromBase); 118 | toBase = removeDoubleSlashes(toBase); 119 | 120 | var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\((?!#)\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig; 121 | var result, url, source; 122 | 123 | while (result = urlRegEx.exec(source)) { 124 | url = result[3] || result[2] || result[5] || result[6] || result[4]; 125 | var newUrl; 126 | newUrl = convertURIBase(url, fromBase, toBase); 127 | var quoteLen = result[5] || result[6] ? 1 : 0; 128 | source = source.substr(0, urlRegEx.lastIndex - url.length - quoteLen - 1) + newUrl + source.substr(urlRegEx.lastIndex - quoteLen - 1); 129 | urlRegEx.lastIndex = urlRegEx.lastIndex + (newUrl.length - url.length); 130 | } 131 | 132 | return source; 133 | }; 134 | 135 | normalizeCSS.convertURIBase = convertURIBase; 136 | normalizeCSS.absoluteURI = absoluteURI; 137 | normalizeCSS.relativeURI = relativeURI; 138 | 139 | return normalizeCSS; 140 | }); 141 | //>>excludeEnd('excludeRequireCss') 142 | -------------------------------------------------------------------------------- /html/widget/normalize.js: -------------------------------------------------------------------------------- 1 | //>>excludeStart('excludeRequireCss', pragmas.excludeRequireCss) 2 | /* 3 | * css.normalize.js 4 | * 5 | * CSS Normalization 6 | * 7 | * CSS paths are normalized based on an optional basePath and the RequireJS config 8 | * 9 | * Usage: 10 | * normalize(css, fromBasePath, toBasePath); 11 | * 12 | * css: the stylesheet content to normalize 13 | * fromBasePath: the absolute base path of the css relative to any root (but without ../ backtracking) 14 | * toBasePath: the absolute new base path of the css relative to the same root 15 | * 16 | * Absolute dependencies are left untouched. 17 | * 18 | * Urls in the CSS are picked up by regular expressions. 19 | * These will catch all statements of the form: 20 | * 21 | * url(*) 22 | * url('*') 23 | * url("*") 24 | * 25 | * @import '*' 26 | * @import "*" 27 | * 28 | * (and so also @import url(*) variations) 29 | * 30 | * For urls needing normalization 31 | * 32 | */ 33 | 34 | define(function() { 35 | 36 | // regular expression for removing double slashes 37 | // eg http://www.example.com//my///url/here -> http://www.example.com/my/url/here 38 | var slashes = /([^:])\/+/g 39 | var removeDoubleSlashes = function(uri) { 40 | return uri.replace(slashes, '$1/'); 41 | } 42 | 43 | // given a relative URI, and two absolute base URIs, convert it from one base to another 44 | var protocolRegEx = /[^\:\/]*:\/\/([^\/])*/; 45 | var absUrlRegEx = /^(\/|data:)/; 46 | function convertURIBase(uri, fromBase, toBase) { 47 | if (uri.match(absUrlRegEx) || uri.match(protocolRegEx)) 48 | return uri; 49 | uri = removeDoubleSlashes(uri); 50 | // if toBase specifies a protocol path, ensure this is the same protocol as fromBase, if not 51 | // use absolute path at fromBase 52 | var toBaseProtocol = toBase.match(protocolRegEx); 53 | var fromBaseProtocol = fromBase.match(protocolRegEx); 54 | if (fromBaseProtocol && (!toBaseProtocol || toBaseProtocol[1] != fromBaseProtocol[1] || toBaseProtocol[2] != fromBaseProtocol[2])) 55 | return absoluteURI(uri, fromBase); 56 | 57 | else { 58 | return relativeURI(absoluteURI(uri, fromBase), toBase); 59 | } 60 | }; 61 | 62 | // given a relative URI, calculate the absolute URI 63 | function absoluteURI(uri, base) { 64 | if (uri.substr(0, 2) == './') 65 | uri = uri.substr(2); 66 | 67 | // absolute urls are left in tact 68 | if (uri.match(absUrlRegEx) || uri.match(protocolRegEx)) 69 | return uri; 70 | 71 | var baseParts = base.split('/'); 72 | var uriParts = uri.split('/'); 73 | 74 | baseParts.pop(); 75 | 76 | while (curPart = uriParts.shift()) 77 | if (curPart == '..') 78 | baseParts.pop(); 79 | else 80 | baseParts.push(curPart); 81 | 82 | return baseParts.join('/'); 83 | }; 84 | 85 | 86 | // given an absolute URI, calculate the relative URI 87 | function relativeURI(uri, base) { 88 | 89 | // reduce base and uri strings to just their difference string 90 | var baseParts = base.split('/'); 91 | baseParts.pop(); 92 | base = baseParts.join('/') + '/'; 93 | i = 0; 94 | while (base.substr(i, 1) == uri.substr(i, 1)) 95 | i++; 96 | while (base.substr(i, 1) != '/') 97 | i--; 98 | base = base.substr(i + 1); 99 | uri = uri.substr(i + 1); 100 | 101 | // each base folder difference is thus a backtrack 102 | baseParts = base.split('/'); 103 | var uriParts = uri.split('/'); 104 | out = ''; 105 | while (baseParts.shift()) 106 | out += '../'; 107 | 108 | // finally add uri parts 109 | while (curPart = uriParts.shift()) 110 | out += curPart + '/'; 111 | 112 | return out.substr(0, out.length - 1); 113 | }; 114 | 115 | var normalizeCSS = function(source, fromBase, toBase) { 116 | 117 | fromBase = removeDoubleSlashes(fromBase); 118 | toBase = removeDoubleSlashes(toBase); 119 | 120 | var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\((?!#)\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig; 121 | var result, url, source; 122 | 123 | while (result = urlRegEx.exec(source)) { 124 | url = result[3] || result[2] || result[5] || result[6] || result[4]; 125 | var newUrl; 126 | newUrl = convertURIBase(url, fromBase, toBase); 127 | var quoteLen = result[5] || result[6] ? 1 : 0; 128 | source = source.substr(0, urlRegEx.lastIndex - url.length - quoteLen - 1) + newUrl + source.substr(urlRegEx.lastIndex - quoteLen - 1); 129 | urlRegEx.lastIndex = urlRegEx.lastIndex + (newUrl.length - url.length); 130 | } 131 | 132 | return source; 133 | }; 134 | 135 | normalizeCSS.convertURIBase = convertURIBase; 136 | normalizeCSS.absoluteURI = absoluteURI; 137 | normalizeCSS.relativeURI = relativeURI; 138 | 139 | return normalizeCSS; 140 | }); 141 | //>>excludeEnd('excludeRequireCss') 142 | -------------------------------------------------------------------------------- /core/coreApi/device/platform.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 客户端基础信息获取 3 | * @class Platform 4 | * @extends Klass 5 | * @constructor 6 | * @module device 7 | * @example 8 | * define('api/client/Platform',function(platform){ 9 | * platform.getNetworkType(); 10 | * }); 11 | * @since 1.0.0 12 | * @public 13 | */ 14 | 15 | define(['api/helper/util'],function(util){ 16 | 17 | var Platform=(function(){ 18 | 19 | //构建一个Platform类,继承自基础类 20 | util.Klass().sub(Platform); 21 | 22 | //构造函数 23 | function Platform() { 24 | /** 25 | * 映射客户端类的名称 (必选) 26 | * @property nativeCls 27 | * @type string 28 | * @since 1.0.0 29 | * @default "platform" 30 | * @public 31 | */ 32 | 33 | /** 34 | * jsBridgeClient通信对象 (必选) 35 | * @property jsbc 36 | * @type string 37 | * @since 1.0.0 38 | * @default jsBridgeClient 39 | * @public 40 | */ 41 | 42 | /** 43 | * 模块信息描述 (可选) 44 | * @property name 45 | * @type string 46 | * @since 1.0.0 47 | * @public 48 | */ 49 | 50 | /** 51 | * 模块版本 (可选) 52 | * @property verison 53 | * @type int 54 | * @since 1.0.0 55 | * @public 56 | */ 57 | 58 | /** 59 | * 模块作者 (可选) 60 | * @property author 61 | * @type string 62 | * @since 1.0.0 63 | * @public 64 | */ 65 | 66 | Platform.__super__.constructor.apply(this, arguments); 67 | } 68 | 69 | Platform.include({ 70 | /** 71 | * 判断当前的网络状态 72 | * @method getNetwork 73 | * @public 74 | * @param {Function} callBack 回调函数 75 | * @return {Object} 76 | * { 77 | * "type":"wifi", 78 | * "p1":"NjAxMjIzODg3Nzc3NDIyOTU4Mg==" 79 | * } 80 | *

主要字段

81 | * 82 | * 83 | * 84 | * 85 | *
字段名称字段说明
type网络状态
p1设备p1值
86 | * @example 87 | * clientInfo.getNetwork(function(status){ 88 | * console.log(status.type); 89 | * }); 90 | * @since 1.0.0 91 | */ 92 | getNetworkType:function(callBack){ 93 | this.sendData({ 94 | method: "getNetworkType", 95 | param: { 96 | "info": "getNetworkType" 97 | }, 98 | callBack: callBack 99 | }); 100 | }, 101 | 102 | /** 103 | * 读取设备分辨率信息 104 | * @method getDevice 105 | * @public 106 | * @param {Function} callBack 回调函数 107 | * @return {Object} 108 | * { 109 | * "model":"Nexus 4", 110 | * "brand":"google", 111 | * "device":"mako", 112 | * "display":"768x1184", 113 | * "product":"occam", 114 | * "hardware":"mako", 115 | * "density":"2", 116 | * "densityDpi":"320", 117 | * } 118 | *

主要字段

119 | * 120 | * 121 | * 122 | * 123 | * 124 | * 125 | * 126 | * 127 | *
字段名称字段说明
model手机型号
brand手机出品商
device设备信息
hardware设备信息
density屏幕精度倍数
densityDpi屏幕精度
128 | * @example 129 | * clientInfo.getDevice(function(data){ 130 | * console.log(data); 131 | * } 132 | * @since 1.0.0 133 | */ 134 | getDevice:function(callBack){ 135 | this.sendData({ 136 | method: "getDevice", 137 | param: { 138 | "info": "getDevice" 139 | }, 140 | callBack: callBack 141 | }); 142 | } 143 | }); 144 | 145 | 146 | return Platform; 147 | })(); 148 | 149 | 150 | return new Platform({ 151 | name: "device infomation", 152 | author: "huangjian", 153 | version: "1.0", 154 | jsbc: jsBridgeClient, 155 | nativeCls: "platform" 156 | }); 157 | }); -------------------------------------------------------------------------------- /html/widget/require.css.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Require-CSS RequireJS css! loader plugin 3 | * 0.1.2 4 | * Guy Bedford 2013 5 | * MIT 6 | */ 7 | 8 | /* 9 | * 10 | * Usage: 11 | * require(['css!./mycssFile']); 12 | * 13 | * Tested and working in (up to latest versions as of March 2013): 14 | * Android 15 | * iOS 6 16 | * IE 6 - 10 17 | * Chome 3 - 26 18 | * Firefox 3.5 - 19 19 | * Opera 10 - 12 20 | * 21 | * browserling.com used for virtual testing environment 22 | * 23 | * Credit to B Cavalier & J Hann for the IE 6 - 9 method, 24 | * refined with help from Martin Cermak 25 | * 26 | * Sources that helped along the way: 27 | * - https://developer.mozilla.org/en-US/docs/Browser_detection_using_the_user_agent 28 | * - http://www.phpied.com/when-is-a-stylesheet-really-loaded/ 29 | * - https://github.com/cujojs/curl/blob/master/src/curl/plugin/css.js 30 | * 31 | */ 32 | 33 | define(function() { 34 | //>>excludeStart('excludeRequireCss', pragmas.excludeRequireCss) 35 | if (typeof window == 'undefined') 36 | return { load: function(n, r, load){ load() } }; 37 | 38 | var head = document.getElementsByTagName('head')[0]; 39 | 40 | var engine = window.navigator.userAgent.match(/Trident\/([^ ;]*)|AppleWebKit\/([^ ;]*)|Opera\/([^ ;]*)|rv\:([^ ;]*)(.*?)Gecko\/([^ ;]*)|MSIE\s([^ ;]*)/) || 0; 41 | 42 | // use