├── .bowerrc ├── .gitignore ├── .gulp ├── build.js ├── demo.js ├── docs.js ├── e2e-tests.js ├── inject.js ├── proxy.js ├── server.js ├── styles.js ├── unit-tests.js └── watch.js ├── .jshintrc ├── .yo-rc.json ├── LICENSE ├── README.md ├── bower.json ├── deploy_version.sh ├── dist ├── angular-weui.js └── angular-weui.min.js ├── docs ├── demo-gallery.html ├── demo.html ├── scripts │ ├── app-75093ba9.js │ └── vendor-b4efd6af.js └── styles │ ├── app-e8d70c78.css │ └── vendor-70892d8a.css ├── gulpfile.js ├── karma.conf.js ├── package.json ├── protractor.conf.js ├── src ├── css │ ├── actionsheet.styl │ ├── gallery.styl │ └── toast.styl ├── js │ ├── Dialog.js │ ├── Toast.js │ ├── action-sheet.js │ ├── button.js │ ├── core.js │ ├── form.js │ ├── gallery.js │ ├── loading.js │ ├── module.js │ ├── ng-swiper.js │ ├── progress.js │ └── wx-jssdk.js └── weui │ └── template │ ├── action-sheet │ └── action-sheet.html │ ├── dialog │ ├── android.html │ └── default.html │ ├── form │ ├── input-image.html │ └── input-textarea.html │ ├── gallery │ └── gallery.html │ ├── loading │ └── loading.html │ ├── toast │ ├── complete.html │ ├── loading.html │ └── message.html │ └── wu-window.html └── test ├── e2e ├── main.po.js └── main.spec.js ├── serve ├── demo-gallery.html ├── demo.html ├── demo_js │ ├── test-gallery.js │ └── test.js └── images │ └── pic_article.png └── unit └── localize-test.js /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Eclipse template 3 | *.pydevproject 4 | .metadata 5 | .gradle 6 | bin/ 7 | tmp/ 8 | *.tmp 9 | *.bak 10 | *.swp 11 | *~.nib 12 | local.properties 13 | .settings/ 14 | .loadpath 15 | 16 | # Eclipse Core 17 | .project 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # JDT-specific (Eclipse Java Development Tools) 29 | .classpath 30 | 31 | # Java annotation processor (APT) 32 | .factorypath 33 | 34 | # PDT-specific 35 | .buildpath 36 | 37 | # sbteclipse plugin 38 | .target 39 | 40 | # TeXlipse plugin 41 | .texlipse 42 | 43 | 44 | ### Windows template 45 | # Windows image file caches 46 | Thumbs.db 47 | ehthumbs.db 48 | 49 | # Folder config file 50 | Desktop.ini 51 | 52 | # Recycle Bin used on file shares 53 | $RECYCLE.BIN/ 54 | 55 | # Windows Installer files 56 | *.cab 57 | *.msi 58 | *.msm 59 | *.msp 60 | 61 | # Windows shortcuts 62 | *.lnk 63 | 64 | 65 | ### Sass template 66 | .sass-cache 67 | *.css.map 68 | 69 | 70 | ### Vim template 71 | [._]*.s[a-w][a-z] 72 | [._]s[a-w][a-z] 73 | *.un~ 74 | Session.vim 75 | .netrwhist 76 | *~ 77 | 78 | 79 | ### Emacs template 80 | # -*- mode: gitignore; -*- 81 | *~ 82 | \#*\# 83 | /.emacs.desktop 84 | /.emacs.desktop.lock 85 | *.elc 86 | auto-save-list 87 | tramp 88 | .\#* 89 | 90 | # Org-mode 91 | .org-id-locations 92 | *_archive 93 | 94 | # flymake-mode 95 | *_flymake.* 96 | 97 | # eshell files 98 | /eshell/history 99 | /eshell/lastdir 100 | 101 | # elpa packages 102 | /elpa/ 103 | 104 | # reftex files 105 | *.rel 106 | 107 | # AUCTeX auto folder 108 | /auto/ 109 | 110 | # cask packages 111 | .cask/ 112 | 113 | 114 | ### Xcode template 115 | build/ 116 | *.pbxuser 117 | !default.pbxuser 118 | *.mode1v3 119 | !default.mode1v3 120 | *.mode2v3 121 | !default.mode2v3 122 | *.perspectivev3 123 | !default.perspectivev3 124 | xcuserdata 125 | *.xccheckout 126 | *.moved-aside 127 | DerivedData 128 | *.xcuserstate 129 | 130 | 131 | ### SublimeText template 132 | # cache files for sublime text 133 | *.tmlanguage.cache 134 | *.tmPreferences.cache 135 | *.stTheme.cache 136 | 137 | # workspace files are user-specific 138 | *.sublime-workspace 139 | 140 | # project files should be checked into the repository, unless a significant 141 | # proportion of contributors will probably not be using SublimeText 142 | # *.sublime-project 143 | 144 | # sftp configuration file 145 | sftp-config.json 146 | 147 | 148 | ### JetBrains template 149 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion 150 | 151 | *.iml 152 | 153 | ## Directory-based project format: 154 | .idea/ 155 | # if you remove the above rule, at least ignore the following: 156 | 157 | # User-specific stuff: 158 | # .idea/workspace.xml 159 | # .idea/tasks.xml 160 | # .idea/dictionaries 161 | 162 | # Sensitive or high-churn files: 163 | # .idea/dataSources.ids 164 | # .idea/dataSources.xml 165 | # .idea/sqlDataSources.xml 166 | # .idea/dynamic.xml 167 | # .idea/uiDesigner.xml 168 | 169 | # Gradle: 170 | # .idea/gradle.xml 171 | # .idea/libraries 172 | 173 | # Mongo Explorer plugin: 174 | # .idea/mongoSettings.xml 175 | 176 | ## File-based project format: 177 | *.ipr 178 | *.iws 179 | 180 | ## Plugin-specific files: 181 | 182 | # IntelliJ 183 | /out/ 184 | 185 | # mpeltonen/sbt-idea plugin 186 | .idea_modules/ 187 | 188 | # JIRA plugin 189 | atlassian-ide-plugin.xml 190 | 191 | # Crashlytics plugin (for Android Studio and IntelliJ) 192 | com_crashlytics_export_strings.xml 193 | crashlytics.properties 194 | crashlytics-build.properties 195 | 196 | # node bower npm 197 | bower_components/ 198 | node_modules/ -------------------------------------------------------------------------------- /.gulp/build.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var paths = gulp.paths; 6 | 7 | var $ = require('gulp-load-plugins')({ 8 | pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del'] 9 | }); 10 | 11 | gulp.task('partials', function () { 12 | return gulp.src([ 13 | paths.src + '/**/*.html' 14 | ]) 15 | .pipe($.minifyHtml({ 16 | empty: true, 17 | spare: true, 18 | quotes: true 19 | })) 20 | .pipe($.angularTemplatecache('templateCacheHtml.js', { 21 | module: gulp.moduleName 22 | })) 23 | .pipe(gulp.dest(paths.tmp + '/partials/')); 24 | }); 25 | 26 | gulp.task('js',['partials'], function () { 27 | gulp.src([ 28 | paths.src + '/js/**/*.js', 29 | paths.tmp + '/partials/**/*.js' 30 | ]) 31 | .pipe($.angularFilesort()) 32 | .pipe($.concat(gulp.appName+'.js')) //合并所有js到gulp.appName + .js 33 | .pipe($.useref()) 34 | .pipe($.revReplace()) 35 | .pipe(gulp.dest(paths.dist + '/')) //输出gulp.appName + .js到文件夹 36 | .pipe($.rename({suffix: '.min'})) //rename压缩后的文件名 37 | .pipe($.uglify({preserveComments: $.uglifySaveLicense})) //压缩 38 | .pipe(gulp.dest(paths.dist + '/')) 39 | .pipe($.size({ title: paths.dist + '/', showFiles: true })); 40 | }); 41 | 42 | gulp.task('styles:dest', function () { 43 | 44 | return gulp.src([ 45 | paths.src + '/css/**/*.less' 46 | 47 | ]).pipe($.plumber({errorHandler: function handleError(err) { 48 | console.error(err.toString()); 49 | }})) 50 | .pipe($.less()) 51 | .pipe($.autoprefixer()) 52 | .pipe($.concat(gulp.appName+'.css')) //合并所有js到gulp.appName + .css 53 | .pipe($.useref()) 54 | .pipe($.revReplace()) 55 | .pipe(gulp.dest(paths.dist + '/')) //输出gulp.appName + .css到文件夹 56 | .pipe($.rename({suffix: '.min'})) //rename压缩后的文件名 57 | .pipe($.minifyCss()) //压缩 58 | .pipe(gulp.dest(paths.dist + '/')) 59 | .pipe($.size({ title: paths.dist + '/', showFiles: true })); 60 | }); 61 | 62 | gulp.task('images', function () { 63 | return gulp.src(paths.src + '/images/**/*') 64 | .pipe(gulp.dest(paths.dist + '/images/')); 65 | }); 66 | 67 | gulp.task('fonts', function () { 68 | return gulp.src(paths.src + '/fonts/**/*') 69 | .pipe(gulp.dest(paths.dist + '/fonts/')); 70 | }); 71 | 72 | gulp.task('misc', function () { 73 | return gulp.src(paths.src + '/**/*.ico') 74 | .pipe(gulp.dest(paths.dist + '/')); 75 | }); 76 | 77 | gulp.task('langs', function () { 78 | return gulp.src([ 79 | paths.src + '/langs/*.json' 80 | ]) 81 | .pipe(gulp.dest(paths.dist + '/langs/')); 82 | }); 83 | 84 | gulp.task('clean', function (done) { 85 | $.del([paths.dist + '/', paths.tmp + '/', paths.reports + '/'], done); 86 | }); 87 | 88 | gulp.task('build', ['js', 'styles:dest', 'images', 'fonts', 'misc','langs']); 89 | -------------------------------------------------------------------------------- /.gulp/demo.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | 3 | var paths = gulp.paths; 4 | 5 | var $ = require('gulp-load-plugins')({ 6 | pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del'] 7 | }); 8 | 9 | gulp.task("demo",['clean:demo','html'], function (done) { 10 | $.del([paths.tmp + '/'], done); 11 | }); 12 | 13 | gulp.task('html', ['inject', 'partials'], function () { 14 | var partialsInjectFile = gulp.src(paths.tmp + '/partials/templateCacheHtml.js', { read: false }); 15 | var partialsInjectOptions = { 16 | starttag: '', 17 | ignorePath: paths.tmp + '/partials', 18 | addRootSlash: false 19 | }; 20 | 21 | var htmlFilter = $.filter('*.html'); 22 | var jsFilter = $.filter('**/*.js'); 23 | var cssFilter = $.filter('**/*.css'); 24 | var assets; 25 | 26 | return gulp.src(paths.tmp + '/serve/*.html') 27 | .pipe($.inject(partialsInjectFile, partialsInjectOptions)) 28 | .pipe(assets = $.useref.assets()) 29 | .pipe($.rev()) 30 | .pipe(jsFilter) 31 | //.pipe($.ngAnnotate()) 32 | .pipe($.uglify({preserveComments: $.uglifySaveLicense})) 33 | .pipe(jsFilter.restore()) 34 | .pipe(cssFilter) 35 | .pipe($.replace('../bootstrap/fonts', '../fonts')) 36 | .pipe($.replace('bower_components/bootstrap/fonts', '../fonts')) 37 | .pipe($.replace('/bower_components/font-awesome/fonts', '../fonts')) 38 | //.pipe($.replace('font-awesome/fonts', '../fonts')) 39 | .pipe($.replace('../../../images', '../images')) 40 | .pipe($.replace('../../images', '../images')) 41 | .pipe($.csso()) 42 | .pipe(cssFilter.restore()) 43 | .pipe(assets.restore()) 44 | .pipe($.useref()) 45 | .pipe($.revReplace()) 46 | .pipe(htmlFilter) 47 | .pipe($.minifyHtml({ 48 | empty: true, 49 | spare: true, 50 | quotes: true 51 | })) 52 | .pipe(htmlFilter.restore()) 53 | .pipe(gulp.dest(paths.demo + '/')) 54 | .pipe($.size({ title: paths.demo + '/', showFiles: true })); 55 | }); 56 | 57 | gulp.task("clean:demo", function (done) { 58 | $.del([paths.demo + '/'], done); 59 | }) 60 | -------------------------------------------------------------------------------- /.gulp/docs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 15/9/9. 3 | */ 4 | 5 | 'use strict'; 6 | 7 | var gulp = require('gulp'); 8 | 9 | var paths = gulp.paths; 10 | 11 | var $ = require('gulp-load-plugins')({ 12 | pattern: ['gulp-*', 'main-bower-files', 'uglify-save-license', 'del'] 13 | }); 14 | 15 | gulp.task('docs', ['clean'], function () { 16 | gulp.src([ 17 | paths.src + '/js/**/*.js' 18 | ]) 19 | .pipe($.jsdoc.parser()) 20 | .pipe($.jsdoc.generator('./docs/api')); 21 | //.pipe($.jsdoc('./docs')); 22 | }); 23 | 24 | gulp.task('lintHTML', function () { 25 | gulp.src([ 26 | paths.src + '/**/*.html' 27 | ]) 28 | .pipe($.jshint.extract('auto|always|never')) 29 | .pipe($.jshint()) 30 | .pipe($.jshint.reporter('default', { verbose: true })) 31 | }); 32 | 33 | gulp.task('lint', function () { 34 | gulp.src([ 35 | paths.src + '/js/**/*.js' 36 | ]) 37 | .pipe($.jshint.extract('auto|always|never')) 38 | .pipe($.jshint()) 39 | .pipe($.jshint.reporter('default', { verbose: true })) 40 | .pipe($.jshint.reporter('fail')) 41 | }); 42 | -------------------------------------------------------------------------------- /.gulp/e2e-tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var $ = require('gulp-load-plugins')(); 6 | 7 | var browserSync = require('browser-sync'); 8 | 9 | var paths = gulp.paths; 10 | 11 | // Downloads the selenium webdriver 12 | gulp.task('webdriver-update', $.protractor.webdriver_update); 13 | 14 | gulp.task('webdriver-standalone', $.protractor.webdriver_standalone); 15 | 16 | function runProtractor (done) { 17 | 18 | gulp.src(paths.e2e + '/**/*.js') 19 | .pipe($.protractor.protractor({ 20 | configFile: 'protractor.conf.js' 21 | })) 22 | .on('error', function (err) { 23 | // Make sure failed tests cause gulp to exit non-zero 24 | throw err; 25 | }) 26 | .on('end', function () { 27 | // Close browser sync server 28 | browserSync.exit(); 29 | done(); 30 | }); 31 | } 32 | 33 | gulp.task('protractor', ['protractor:src']); 34 | gulp.task('protractor:src', ['serve:e2e'], runProtractor); 35 | gulp.task('protractor:dist', ['serve:e2e-dist'], runProtractor); 36 | -------------------------------------------------------------------------------- /.gulp/inject.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var paths = gulp.paths; 6 | 7 | var $ = require('gulp-load-plugins')(); 8 | 9 | var wiredep = require('wiredep').stream; 10 | 11 | gulp.task('inject', ['styles'], function () { 12 | 13 | var injectStyles = gulp.src([ 14 | paths.tmp + '/serve/{app,css}/**/*.css', 15 | paths.test_server + '/**/*.css' 16 | ], {read: false}); 17 | 18 | var injectScripts = gulp.src([ 19 | paths.src + '/**/*.js', 20 | paths.test_server + '/**/*.js' 21 | ]).pipe($.plumber({errorHandler: function handleError(err) { 22 | console.error(err.toString()); 23 | //this.emit('end'); 24 | }})).pipe($.angularFilesort()); 25 | 26 | var injectOptions = { 27 | ignorePath: [paths.src, paths.tmp + '/serve', paths.test_server], 28 | addRootSlash: false 29 | }; 30 | 31 | var wiredepOptions = { 32 | directory: 'bower_components', 33 | exclude: []// /bootstrap\.js/, /bootstrap\.css/, /bootstrap\.css/, /foundation\.css/ 34 | }; 35 | 36 | 37 | return gulp.src(paths.test_server + '/*.html') 38 | .pipe($.plumber({errorHandler: function handleError(err) { 39 | console.error(err.toString()); 40 | //this.emit('end'); 41 | }})) 42 | .pipe($.inject(injectStyles, injectOptions)) 43 | .pipe($.inject(injectScripts, injectOptions)) 44 | .pipe(wiredep(wiredepOptions)) 45 | .pipe(gulp.dest(paths.tmp + '/serve')); 46 | 47 | }); 48 | -------------------------------------------------------------------------------- /.gulp/proxy.js: -------------------------------------------------------------------------------- 1 | /*jshint unused:false */ 2 | 3 | /*************** 4 | 5 | This file allow to configure a proxy system plugged into BrowserSync 6 | in order to redirect backend requests while still serving and watching 7 | files from the web project 8 | 9 | IMPORTANT: The proxy is disabled by default. 10 | 11 | If you want to enable it, watch at the configuration options and finally 12 | change the `module.exports` at the end of the file 13 | 14 | ***************/ 15 | 16 | 'use strict'; 17 | 18 | var httpProxy = require('http-proxy'); 19 | var chalk = require('chalk'); 20 | 21 | /* 22 | * Location of your backend server 23 | */ 24 | var proxyTarget = 'http://server/context/'; 25 | 26 | var proxy = httpProxy.createProxyServer({ 27 | target: proxyTarget 28 | }); 29 | 30 | proxy.on('error', function(error, req, res) { 31 | res.writeHead(500, { 32 | 'Content-Type': 'text/plain' 33 | }); 34 | 35 | console.error(chalk.red('[Proxy]'), error); 36 | }); 37 | 38 | /* 39 | * The proxy middleware is an Express middleware added to BrowserSync to 40 | * handle backend request and proxy them to your backend. 41 | */ 42 | function proxyMiddleware(req, res, next) { 43 | /* 44 | * This test is the switch of each request to determine if the request is 45 | * for a static file to be handled by BrowserSync or a backend request to proxy. 46 | * 47 | * The existing test is a standard check on the files extensions but it may fail 48 | * for your needs. If you can, you could also check on a context in the url which 49 | * may be more reliable but can't be generic. 50 | */ 51 | if (/\.(html|css|js|png|jpg|jpeg|gif|ico|xml|rss|txt|eot|svg|ttf|woff|cur)(\?((r|v|rel|rev)=[\-\.\w]*)?)?$/.test(req.url)) { 52 | next(); 53 | } else { 54 | proxy.web(req, res); 55 | } 56 | } 57 | 58 | /* 59 | * This is where you activate or not your proxy. 60 | * 61 | * The first line activate if and the second one ignored it 62 | */ 63 | 64 | //module.exports = [proxyMiddleware]; 65 | module.exports = []; 66 | -------------------------------------------------------------------------------- /.gulp/server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var opn = require('opn'); 6 | 7 | var paths = gulp.paths; 8 | 9 | var util = require('util'); 10 | 11 | var browserSync = require('browser-sync'); 12 | 13 | var middleware = require('./proxy'); 14 | 15 | function browserSyncInit(baseDir, files, browser) { 16 | // browser = browser === undefined ? 'default' : browser; 17 | 18 | var routes = null; 19 | if(baseDir === paths.src || (util.isArray(baseDir) && baseDir.indexOf(paths.src) !== -1)) { 20 | routes = { 21 | '/bower_components': 'bower_components', 22 | '/demo_js': paths.test_server+'/demo_js', 23 | '/images': paths.test_server+'/images', 24 | }; 25 | } 26 | 27 | browserSync.instance = browserSync.init(files, { 28 | startPath: '/', 29 | server: { 30 | baseDir: baseDir, 31 | middleware: middleware, 32 | routes: routes 33 | }, 34 | port: 3002, 35 | open: false, 36 | browser: browser 37 | }, function(){ 38 | var homepage = 'http://localhost:3002/demo.html'; 39 | if(browser){ 40 | //opn(homepage, {app: browser}) 41 | }else{ 42 | opn(homepage) 43 | } 44 | }); 45 | } 46 | 47 | gulp.task('serve', ['watch'], function () { 48 | browserSyncInit([ 49 | paths.tmp + '/serve', 50 | paths.src 51 | ], [ 52 | paths.tmp + '/serve/{app,lib,components}/**/*.css', 53 | paths.src + '/{app,lib,components}/**/*.js', 54 | paths.src + 'src/assets/images/**/*', 55 | paths.tmp + '/serve/*.html', 56 | paths.tmp + '/serve/{app,lib,components,common}/**/*.html', 57 | paths.src + '/{app,lib,components,common}/**/*.html', 58 | paths.test_server + '/**/*' 59 | ]); 60 | }); 61 | 62 | gulp.task('serve:test', ['watch'], function () { 63 | browserSyncInit([paths.tmp + '/serve', paths.src], [ 64 | paths.tmp + '/**/*', 65 | paths.tmp + '/*', 66 | paths.src + '/**/*', 67 | paths.src + '/*', 68 | paths.test_server + '/**/*', 69 | paths.test_server + '/*' 70 | ]); 71 | }); 72 | 73 | gulp.task('serve:dist', ['build'], function () { 74 | browserSyncInit(paths.dist); 75 | }); 76 | 77 | gulp.task('serve:e2e', ['inject'], function () { 78 | browserSyncInit([paths.tmp + '/serve', paths.src], null, []); 79 | }); 80 | 81 | gulp.task('serve:e2e-dist', ['build'], function () { 82 | browserSyncInit(paths.dist, null, []); 83 | }); 84 | -------------------------------------------------------------------------------- /.gulp/styles.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var paths = gulp.paths; 6 | 7 | var $ = require('gulp-load-plugins')(); 8 | 9 | gulp.task('css', function() { 10 | gulp.src([ 11 | paths.src + '/**/*.css' 12 | ]).pipe($.plumber({errorHandler: function handleError(err) { 13 | console.error(err.toString()); 14 | //this.emit('end'); 15 | }})) 16 | .pipe($.autoprefixer()) 17 | .pipe(gulp.dest(paths.tmp + '/serve/app/')); 18 | }); 19 | 20 | gulp.task('sass', function() { 21 | gulp.src([ 22 | paths.src + '/css/**/*.scss' 23 | ]).pipe($.plumber({errorHandler: function handleError(err) { 24 | console.error(err.toString()); 25 | //this.emit('end'); 26 | }})) 27 | .pipe($.sass({outputStyle: 'compressed'}).on('error', $.sass.logError)) 28 | .pipe($.autoprefixer()) 29 | .pipe(gulp.dest(paths.tmp + '/serve/app/')); 30 | }); 31 | 32 | gulp.task('stylus', function() { 33 | return gulp.src([ 34 | paths.src + '/css/**/*.styl' 35 | ]).pipe($.plumber({errorHandler: function handleError(err) { 36 | console.error(err.toString()); 37 | //this.emit('end'); 38 | }})) 39 | .pipe($.stylus()) 40 | //.pipe($.autoprefixer()) 41 | .pipe(gulp.dest(paths.tmp + '/serve/app/')); 42 | }); 43 | 44 | gulp.task('less', function() { 45 | return gulp.src([ 46 | paths.src + '/css/**/*.less' 47 | ]).pipe($.plumber({errorHandler: function handleError(err) { 48 | console.error(err.toString()); 49 | //this.emit('end'); 50 | }})) 51 | .pipe($.less()) 52 | //.pipe($.autoprefixer()) 53 | .pipe(gulp.dest(paths.tmp + '/serve/app/')); 54 | }); 55 | 56 | gulp.task('styles', ['css', 'stylus','sass'], function () { 57 | 58 | var lessOptions = { 59 | paths: [ 60 | 'bower_components', 61 | paths.src + '/app', 62 | paths.src + '/components' 63 | ] 64 | }; 65 | 66 | var injectFiles = gulp.src([ 67 | paths.src + '/{app,components}/**/*.css', 68 | '!' + paths.src + '/css/index.less', 69 | '!' + paths.src + '/css/vendor.less' 70 | ], {read: false}); 71 | 72 | var injectOptions = { 73 | transform: function (filePath) { 74 | filePath = filePath.replace(paths.src + '/app/', ''); 75 | filePath = filePath.replace(paths.src + '/components/', '../components/'); 76 | return '@import \'' + filePath + '\';'; 77 | }, 78 | starttag: '// injector', 79 | endtag: '// endinjector', 80 | addRootSlash: false 81 | }; 82 | 83 | var indexFilter = $.filter('index.less'); 84 | 85 | return gulp.src([ 86 | //paths.src + '/css/**/*.css' 87 | ]).pipe($.plumber({errorHandler: function handleError(err) { 88 | console.error(err.toString()); 89 | //this.emit('end'); 90 | }})) 91 | //.pipe(indexFilter) 92 | .pipe($.inject(injectFiles, injectOptions)) 93 | //.pipe(indexFilter.restore()) 94 | //.pipe($.autoprefixer()) 95 | .on('error', function handleError(err) { 96 | console.error(err.toString()); 97 | //this.emit('end'); 98 | }) 99 | .pipe(gulp.dest(paths.tmp + '/serve/app/')); 100 | }); 101 | -------------------------------------------------------------------------------- /.gulp/unit-tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var $ = require('gulp-load-plugins')(); 6 | 7 | var wiredep = require('wiredep'); 8 | 9 | var paths = gulp.paths; 10 | 11 | function runTests (singleRun, done) { 12 | var bowerDeps = wiredep({ 13 | directory: 'bower_components', 14 | exclude: ['bootstrap-sass-official'], 15 | dependencies: true, 16 | devDependencies: true 17 | }); 18 | 19 | var testFiles = bowerDeps.js.concat([ 20 | paths.src + '/js/poler.js', 21 | paths.src + '/**/*.js', 22 | paths.unit +'/**/*.js' 23 | ]); 24 | 25 | gulp.src(testFiles) 26 | //.pipe($.angularFilesort()) 27 | .on('end', function () { 28 | 29 | }) 30 | .pipe($.karma({ 31 | configFile: 'karma.conf.js', 32 | action: (singleRun)? 'run': 'watch' 33 | })) 34 | .on('error', function (err) { 35 | // Make sure failed tests cause gulp to exit non-zero 36 | throw err; 37 | }); 38 | } 39 | 40 | gulp.task('test', ['clean'], function (done) { runTests(true /* singleRun */, done) }); 41 | gulp.task('test:auto', function (done) { runTests(false /* singleRun */, done) }); 42 | -------------------------------------------------------------------------------- /.gulp/watch.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | 5 | var paths = gulp.paths; 6 | 7 | gulp.task('watch', ['inject'], function () { 8 | gulp.watch([ 9 | paths.src + '/*', 10 | paths.src + '/**/*.js', 11 | paths.src + '/**/*.html', 12 | paths.src + '/**/*.css', 13 | paths.src + '/**/*.less', 14 | paths.src + '/**/*.scss', 15 | paths.src + '/**/*.styl', 16 | paths.test_server + '/*', 17 | paths.test_server + '/**/*.html', 18 | paths.test_server + '/**/*.js', 19 | paths.test_server + '/**/*.css', 20 | 'bower.json' 21 | ], ['inject']); 22 | }); 23 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "node": true, 3 | "esnext": true, 4 | "bitwise": true, 5 | "camelcase": true, 6 | "curly": true, 7 | "eqeqeq": true, 8 | "immed": true, 9 | "indent": 2, 10 | "latedef": true, 11 | "newcap": true, 12 | "noarg": true, 13 | "quotmark": "single", 14 | "regexp": true, 15 | "undef": true, 16 | "unused": true, 17 | "strict": true, 18 | "trailing": true, 19 | "smarttabs": true, 20 | "white": true, 21 | "validthis": true, 22 | "globals": { 23 | "angular": false, 24 | // Angular Mocks 25 | "inject": false, 26 | // JASMINE 27 | "describe": false, 28 | "it": false, 29 | "before": false, 30 | "beforeEach": false, 31 | "after": false, 32 | "afterEach": false, 33 | "expect": false 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-gulp-angular": { 3 | "props": { 4 | "paths": { 5 | "src": "src", 6 | "dist": "dist", 7 | "e2e": "test/e2e", 8 | "tmp": ".tmp" 9 | }, 10 | "angularVersion": "~1.3.4", 11 | "angularModules": [ 12 | { 13 | "name": "angular-animate", 14 | "module": "ngAnimate" 15 | }, 16 | { 17 | "name": "angular-cookies", 18 | "module": "ngCookies" 19 | }, 20 | { 21 | "name": "angular-touch", 22 | "module": "ngTouch" 23 | }, 24 | { 25 | "name": "angular-sanitize", 26 | "module": "ngSanitize" 27 | } 28 | ], 29 | "jQuery": { 30 | "name": "jquery", 31 | "version": "~2.1.1" 32 | }, 33 | "resource": { 34 | "name": "angular-resource", 35 | "module": "ngResource" 36 | }, 37 | "router": { 38 | "name": "angular-ui-router", 39 | "version": "~0.2.13", 40 | "module": "ui.router" 41 | }, 42 | "ui": { 43 | "name": "bootstrap-sass-official", 44 | "version": "~3.3.1", 45 | "key": "bootstrap", 46 | "module": null 47 | }, 48 | "bootstrapComponents": { 49 | "name": "angular-bootstrap", 50 | "version": "0.12.x", 51 | "key": "ui-bootstrap", 52 | "module": "ui.bootstrap" 53 | }, 54 | "cssPreprocessor": { 55 | "key": "less", 56 | "extension": "less", 57 | "module": "gulp-less", 58 | "version": "~1.3.6" 59 | }, 60 | "jsPreprocessor": { 61 | "key": "none", 62 | "extension": "js", 63 | "srcExtension": "js", 64 | "module": null, 65 | "version": null 66 | }, 67 | "htmlPreprocessor": { 68 | "key": "none", 69 | "extension": "html", 70 | "module": null, 71 | "version": null 72 | }, 73 | "foundationComponents": { 74 | "name": null, 75 | "version": null, 76 | "key": null, 77 | "module": null 78 | } 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 three 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # angular-weui 2 | 3 | weui的angular组件版本。同时封装微信jssdk接口为angular服务。依赖: 4 | > angular 1.x 5 | > 6 | > weui: [https://github.com/weui/weui](https://github.com/weui/weui) 7 | > 8 | > jquery 9 | > 10 | > 微信jssdk 1.1.0 11 | 12 | # TODO list 13 | 14 | 1. [x] 核心组件 15 | > * 浏览器检测组件 16 | 17 | 1. [x] actionsheet 组件 18 | 19 | 1. [x] dialog 组件 20 | > * alert 21 | > * confirm 22 | 23 | 1. [x] toast 组件 24 | > * loading 25 | > * complete 26 | > * show message 27 | 28 | 1. [x] wu-click 组件:防止重复点击 29 | 1. [x] 进度条组件 30 | 1. [ ] 图片预览组件 31 | 32 | 1. [ ] 表单组件 33 | > * 图片上传 34 | > * 文本域 35 | 36 | # api说明 37 | 38 | ### WuBrowserChecker 39 | 40 | 客户端检测.支持android/ios/window版本微信客户端,mac/linux/window平台上的各种浏览器检测. 41 | 同时会在window作用域中创建一个weui_client_browser_checker对象存放客户端信息 42 | 43 | WuBrowserChecker.engine // 呈现引擎信息 44 | 45 | WuBrowserChecker.browser // 浏览器信息 46 | 47 | WuBrowserChecker.system // 系统平台信息 48 | 49 | 50 | ### WuActionSheet 51 | 52 | WuActionSheet是一个angular服务,只提供一个方法:`open(options)` 53 | 54 | #### WuActionsSheet open 方法 55 | 56 | ##### options参数 57 | 58 | * btnGroups *(Type: Array)* - 按钮组配置列表。每个按钮组提供 `action` *`(Type:String, Default: cancel)`* 和 `buttons`参数:`action`指定点击过后执行结果通知时的通道,取值只能是`ok`或`cancel`;`buttons`指定一组中包含的按钮对象,每个对象包含的属性有`title`和`value`,`title`按钮显示信息,`value`按钮点击时的返回值 59 | * 返回值:返回一个angular的 WuActionSheet 实例。提供有result,close等方法,对用户点击结果和 WuActionSheet 进行控制 60 | 61 | ##### Example 62 | 63 | ```javascript 64 | WuActionSheet.open({ 65 | btnGroups:[ 66 | { 67 | action: 'Ok', 68 | buttons:[ 69 | { 70 | title:'11', 71 | value:'11' 72 | }, 73 | { 74 | title:'22', 75 | value:'22' 76 | }, 77 | { 78 | title:'33', 79 | value:'33' 80 | }, 81 | { 82 | title:'44', 83 | value:'44' 84 | } 85 | ] 86 | }, 87 | { 88 | action: 'Cancel', 89 | buttons:[ 90 | { title: 'cancel1', value: 'cancel1'} 91 | ] 92 | }, 93 | { 94 | action: 'Close', 95 | buttons:[ 96 | { title: 'cancel11', value: 'cancel1'} 97 | ] 98 | } 99 | ] 100 | }).result.then(function (btn) { 101 | console.log(btn) 102 | }, function (cancel) { 103 | console.log(cancel) 104 | }); 105 | ``` 106 | ### WuDialog 107 | 108 | WuDialog是个angular服务,提供弹框服务。提供的方法有:`open(options)`、`alert(options)`、`confirm(options)` 109 | 110 | #### WuDialog open 方法 111 | 112 | ```javascript 113 | WuDialog.open({ 114 | title:'自定义按钮', 115 | content:'自定义按钮测试', 116 | buttons:[ 117 | { action:'ok', title:'btn1', class: 'default', value:'btn1' }, 118 | { action:'ok', title:'btn2', class: 'primary', value:'btn2' }, 119 | { action:'cancel', title:'btn3', class: 'default', value:'btn3' }, 120 | { action:'cancel', title:'btn4', class: 'primary', value:'btn4' } 121 | ] 122 | }).result.then(function () { 123 | console.log("OK: ", arguments[0]) 124 | },function () { 125 | console.log("Cancel: ", arguments[0]) 126 | }) 127 | ``` 128 | 129 | #### WuDialog alert 方法 130 | 131 | ```javascript 132 | WuDialog.alert({ 133 | title: '提示框', 134 | content: '
xxxx Alert内容
' 135 | }).result.then(function () { 136 | console.log('ok'); 137 | }, function () { 138 | console.log('close alert') 139 | }); 140 | ``` 141 | 142 | #### WuDialog confirm 方法 143 | 144 | ```javascript 145 | WuDialog.confirm({ 146 | title: '确认框', 147 | content: '
xxxx确认内容
' 148 | }).result.then(function () { 149 | console.log('ok'); 150 | }, function () { 151 | console.log('cancel') 152 | }); 153 | ``` 154 | 155 | ### WuToast 156 | 157 | WuDialog是个angular服务,提供消息提醒服务。提供的方法有:`message(options)`、`complete(options)`、`loading(options)` 158 | 159 | #### WuToast message 方法 160 | 161 | ```javascript 162 | var loadingObj = WuToast.message({ 163 | message:'test asdfasdf sdfasdf asdfsadfv sdfsad asfsadf sdfasfda sdfasfasdf message show' 164 | time: 2000 165 | }); 166 | 167 | // 或者手多关闭 168 | setTimeout(function () { 169 | loadingObj.close(); 170 | }, 1000) 171 | ``` 172 | 173 | #### WuToast complete 方法 174 | 175 | ```javascript 176 | WuToast.complete({ 177 | time:1000 178 | }); 179 | ``` 180 | 181 | #### WuToast loading 方法 182 | 183 | ```javascript 184 | var loadingObj = WuToast.loading({ 185 | message:'数据加载中' 186 | }); 187 | setTimeout(function () { 188 | loadingObj.close(); 189 | }, 1000) 190 | ``` 191 | 192 | ### wu-progress 193 | 194 | wu-progress 是一个angular指令,提供进度条显示。 195 | 196 | ```html 197 |

wuProgress

198 | 199 | 200 |
201 | 202 | 203 |
204 |
205 | ``` 206 | 207 | ### wu-click 208 | 209 | wu-click 是一个angular指令,提供事件点击服务,可以防止用户快速点击按钮。 210 | 211 | ```html 212 |

button wu-click test

213 | 按钮 214 | 按钮 215 | 216 | ``` 217 | 218 | # angular-weui 开发 219 | 220 | 1. 克隆 angular-weui 工程 221 | 222 | ``` 223 | git clone git@github.com:threeq/angular-weui.git 224 | 225 | cd angular-weui 226 | ``` 227 | 228 | 2. 安装工程依赖库 229 | 230 | ``` 231 | # npm 环境依赖 232 | npm intall 233 | 234 | # 使用 bower 安装angular-weui依赖库 235 | npm run bower 236 | ``` 237 | 238 | 3. 启动工程 239 | 240 | ``` 241 | npm run dev 242 | ``` 243 | 244 | 这时会自动启动浏览器打开 demo 界面,如果没有打开可以自己打开浏览器输入地址: http://localhost:3002/test.html 245 | 246 | 4. 工程打包 247 | 248 | ``` 249 | npm run dist 250 | ``` 251 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-weui", 3 | "version": "0.0.1", 4 | "authors": [ 5 | "three <448987046@qq.com>" 6 | ], 7 | "description": "angular weui plugins", 8 | "main": [ 9 | "dist/*.min.js", 10 | "dist/*.min.css" 11 | ], 12 | "keywords": [ 13 | "angular", 14 | "weui", 15 | "angular-weui" 16 | ], 17 | "license": "MIT", 18 | "ignore": [ 19 | "**/.*", 20 | "node_modules", 21 | "bower_components", 22 | "test", 23 | "tests" 24 | ], 25 | "dependencies": { 26 | "jquery": "~2.1.4", 27 | "angular": "~1.4.5", 28 | "weui": "^1.0.0", 29 | "swiper": "^3.4.0" 30 | }, 31 | "devDependencies": { 32 | "angular-mocks": "~1.4.5" 33 | }, 34 | "resolutions": { 35 | "jquery": "~2.1.4", 36 | "angular": "~1.4.5" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /deploy_version.sh: -------------------------------------------------------------------------------- 1 | echo build version: $1 2 | echo build message: $2 3 | 4 | gulp clean 5 | gulp build 6 | git add . 7 | git commit -am "$2" 8 | git tag -a $1 -m "$2" 9 | 10 | -------------------------------------------------------------------------------- /dist/angular-weui.min.js: -------------------------------------------------------------------------------- 1 | "use strict";angular.module("ng.weui.core",[]),angular.module("ng.weui.jssdk",[]),angular.module("ng.weui.swiper",["ng.weui.core"]),angular.module("ng.weui.button",[]),angular.module("ng.weui.progress",[]),angular.module("ng.weui.dialog",["ng.weui.core"]),angular.module("ng.weui.actionsheet",["ng.weui.core"]),angular.module("ng.weui.toast",["ng.weui.core"]),angular.module("ng.weui.form",["ng.weui.core"]),angular.module("ng.weui.gallery",["ng.weui.core","ng.weui.swiper"]),angular.module("ng.weui.loading",["ng.weui.core"]),angular.module("ng.weui",["ng.weui.core","ng.weui.button","ng.weui.actionsheet","ng.weui.dialog","ng.weui.toast","ng.weui.form","ng.weui.gallery","ng.weui.loading","ng.weui.progress"]),angular.module("ng.weui").run(["$templateCache",function(e){e.put("weui/template/wu-window.html",'
'),e.put("weui/template/action-sheet/action-sheet.html",'
{{btn.title}}
'),e.put("weui/template/dialog/android.html",'
'),e.put("weui/template/dialog/default.html",'
'),e.put("weui/template/form/input-image.html",'

图片上传

0/2
  • 50%
'),e.put("weui/template/form/input-textarea.html",'
0/200
'),e.put("weui/template/gallery/gallery.html",'
'),e.put("weui/template/loading/loading.html",'
正在加载
暂无数据
'),e.put("weui/template/toast/complete.html",'

'),e.put("weui/template/toast/loading.html",'

'),e.put("weui/template/toast/message.html",'
')}]),function(e,t){e.factory("WuWxJsSdk",["$q",function(e){function n(e){return t.wx?t.wx:(e({errMsg:"没有js接口对象,请确认是否引入微信js文件"}),!1)}function i(e,t,n){return e.success=function(e){t(e)},e.fail=function(e){n(e)},e.complete=function(){},e.cancel=function(){n({errMsg:"用户取消"})},e.trigger=function(){},e}for(var a={config:function(){return e(function(e,i){var a=n(i);a&&(a.config.apply(t,arguments),a.ready(function(){e({errMsg:"config:ok"})}),a.error(function(e){i(e)}))})}},o=["checkJsApi","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareWeibo","onMenuShareWeibo","chooseImage","previewImage","uploadImage","downloadImage","startRecord","stopRecord","onVoiceRecordEnd","playVoice","pauseVoice","stopVoice","onVoicePlayEnd","uploadVoice","downloadVoice","translateVoice","getNetworkType","openLocation","getLocation","hideOptionMenu","showOptionMenu","closeWindow","hideMenuItems","showMenuItems","hideAllNonBaseMenuItem","showAllNonBaseMenuItem","scanQRCode","startSearchBeacons","stopSearchBeacons","onSearchBeacons","openProductSpecificView","chooseCard","addCard","openCard","consumeAndShareCard","chooseWXPay"],r=0;r
',link:function(e){e.filterProgress=function(e){return e>100?"100%":0>e?"0%":parseFloat(e)+"%"},e.filterHeight=function(e){return(e&&e>1?e:3)+"px"}}}}])}(angular.module("ng.weui.progress")),function(e,t){t.directive("wuSwiperContainer",["IdWorkerFactory",function(e){var t=e("wuSwiperContainer");return{restrict:"E",transclude:!0,scope:{onReady:"&",slidesPerView:"=",slidesPerColumn:"=",spaceBetween:"=",parallax:"=",parallaxTransition:"@",paginationIsActive:"=",paginationClickable:"=",showNavButtons:"=",showScrollBar:"=",loop:"=",autoplay:"=",initialSlide:"=",containerCls:"@",wrapperCls:"@",paginationCls:"@",slideCls:"@",direction:"@",swiper:"=",overrideParameters:"="},controller:function(e,n,i){var a=t();e.swiper_uuid=a;var o={slidesPerView:e.slidesPerView||1,slidesPerColumn:e.slidesPerColumn||1,spaceBetween:e.spaceBetween||0,direction:e.direction||"horizontal",loop:e.loop||!1,initialSlide:e.initialSlide||0,showNavButtons:!1};angular.isUndefined(e.autoplay)||"number"!=typeof e.autoplay||(o=angular.extend({},o,{autoplay:e.autoplay})),e.paginationIsActive===!0&&(o=angular.extend({},o,{paginationClickable:e.paginationClickable||!0,pagination:"#paginator-"+e.swiper_uuid})),e.showNavButtons===!0&&(o.nextButton="#nextButton-"+e.swiper_uuid,o.prevButton="#prevButton-"+e.swiper_uuid),e.showScrollBar===!0&&(o.scrollbar="#scrollBar-"+e.swiper_uuid),e.overrideParameters&&(o=angular.extend({},o,e.overrideParameters)),i(function(){var t=null;angular.isObject(e.swiper)?(e.swiper=new Swiper(n[0].firstChild,o),t=e.swiper):t=new Swiper(n[0].firstChild,o),angular.isUndefined(e.onReady)||e.onReady({swiper:t})})},link:function(e,t){var n=e.swiper_uuid,i="paginator-"+n,a="prevButton-"+n,o="nextButton-"+n,r="scrollBar-"+n,s=t[0];angular.element(s.querySelector(".swiper-pagination")).attr("id",i),angular.element(s.querySelector(".swiper-button-next")).attr("id",o),angular.element(s.querySelector(".swiper-button-prev")).attr("id",a),angular.element(t[0].querySelector(".swiper-scrollbar")).attr("id",r)},template:'
'}}]).directive("wuSwiperSlide",[function(){return{restrict:"E",require:"^ksSwiperContainer",transclude:!0,scope:{sliderCls:"@"},template:'
',replace:!0}}])}(window,angular.module("ng.weui.swiper"),void 0),function(e){e.directive("loadingEnable",[function(){return{restrict:"A",replace:!0,templateUrl:"weui/template/loading/loading.html",transclude:!0,link:function(){}}}])}(angular.module("ng.weui.loading"),window),function(e){e.factory("PreviewImages",["WuWxJsSdk",function(e){return{show:function(t,n){e.previewImage({current:t,urls:n})}}}]),e.directive("previewImages",["PreviewImages",function(e){return{restrict:"AE",link:function(t,n,i){var a=n,o=i.preview?i.preview:"img",r=i.attrName?i.attrName:"src";n.on("click",o,function(t){var n=$(this),i=[];return a.find(o).each(function(e,t){i.push(t.attr(r))}),e.show(n.attr(r),i),t.preventDefault(),t.stopPropagation(),!1})}}}]),e.directive("gallery",["$timeout","IdWorkerFactory",function(e,t){var n=t.new("weui-gallery_swiper");return{restrict:"EA",templateUrl:"weui/template/gallery/gallery.html",scope:{images:"="},link:function(t,i){function a(){e(function(){console.log("#"+o+" .swiper-images");var e=new Swiper("#"+o+" .swiper-images",{nextButton:".swiper-button-next",prevButton:".swiper-button-prev",spaceBetween:10,effect:"coverflow",grabCursor:!0,centeredSlides:!0,slidesPerView:"auto",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0}});if(t.showThumb){var n=new Swiper("#"+o+" .gallery-thumbs",{spaceBetween:10,centeredSlides:!0,slidesPerView:"auto",touchRatio:.2,slideToClickedSlide:!0});e.params.control=n,n.params.control=e}},10)}var o=n();i.attr("id",o),i.addClass("weui-gallery"),i.show(),t.showThumb=!1,angular.isArray(t.images)&&t.images.length>0&&(t.images[0].hasOwnProperty("thumb")&&(t.showThumb=!0),a()),t.imageStyle=function(e){return{"background-image":"url("+e.url+")"}}}}}])}(angular.module("ng.weui.gallery")),function(e){e.directive("inputTextarea",[function(){return{restrict:"EA",replace:!0,templateUrl:"weui/template/form/input-textarea.html",require:"ngModel",link:function(e,t,n,i){i.$render=function(){console.log()}}}}]),e.directive("inputImage",[function(){return{restrict:"EA",replace:!0,templateUrl:"weui/template/form/input-image.html",require:"ngModel",link:function(e,t,n,i){i.$render=function(){console.log()}}}}])}(angular.module("ng.weui.form")),function(e){e.provider("WuDialog",[function(){var e=this;e.$get=["$wuModal",function(e){return{open:function(t){t.buttons=t.buttons||[{action:"ok",title:"确定","class":"default",value:"ok"}];var n="wu-dialog-default-template";return t.hasOwnProperty("template")&&t.template&&(n=t.template),e.open({backdrop:!1,windowTemplateUrl:"weui/template/wu-window.html",template:"
",controller:["$scope",function(e){e.title=t.title,e.content=t.content,e.buttons=t.buttons,e.clickBtn=function(t){"ok"===t.action.toLowerCase()?e.$close(t.value):e.$dismiss(t.value)}}]})},alert:function(e){return this.open({title:e.title,content:e.content})},confirm:function(e){return this.open({title:e.title,content:e.content,buttons:[{action:"cancel",title:"取消","class":"default",value:"cancel"},{action:"ok",title:"确定","class":"primary",value:"ok"}]})}}}]}]);var t=function(e,t){var n=t.find(".weui-mask");n.on("click",function(){e.$apply(function(){e.$dismiss("mask:click")})});var i="weui-dialog__alert";e.buttons.length>1&&(i="weui-dialog__confirm"),t.addClass(i)};e.directive("wuDialogDefaultTemplate",[function(){return{restrict:"A",templateUrl:"weui/template/dialog/default.html",link:t}}]).directive("wuDialogAndroidTemplate",[function(){return{restrict:"A",templateUrl:"weui/template/dialog/android.html",link:t}}]),e.directive("unsafeShowHtml",["$compile",function(e){return{restrict:"A",scope:{content:"=unsafeShowHtml"},link:function(t,n){var i=function(){var i="
"+t.content+"
";n.html("").append(e(i)(t))};i()}}}])}(angular.module("ng.weui.dialog")),function(e,t){e.factory("$$stackedMap",function(){return{createNew:function(){var e=[];return{add:function(t,n){e.push({key:t,value:n})},get:function(t){for(var n=0;n0&&(t=b.top().value,t.modalDomEl.toggleClass(t.windowTopClass||"",e))}function d(){if(m&&-1===l()){var e=v;p(m,v,function(){e=null}),m=void 0,v=void 0}}function p(e,n,i,a){function r(){r.done||(r.done=!0,t(e,{event:"leave"}).start().then(function(){e.remove(),a&&a.resolve()}),n.$destroy(),i&&i())}var s,l=null,u=function(){return s||(s=o.defer(),l=s.promise),function(){s.resolve()}};return n.$broadcast(_.NOW_CLOSING_EVENT,u),o.when(l).then(r)}function w(e){if(e.isDefaultPrevented())return e;var t=b.top();if(t)switch(e.which){case 27:t.value.keyboard&&(e.preventDefault(),a.$apply(function(){_.dismiss(t.key,"escape key press")}));break;case 9:_.loadFocusElementList(t);var n=!1;e.shiftKey?_.isFocusInFirstItem(e)&&(n=_.focusLastFocusableElement()):_.isFocusInLastItem(e)&&(n=_.focusFirstFocusableElement()),n&&(e.preventDefault(),e.stopPropagation())}}function g(e,t,n){return!e.value.modalScope.$broadcast("modal.closing",t,n).defaultPrevented}var m,v,f,h="modal-open",b=s.createNew(),k=r.createNew(),_={NOW_CLOSING_EVENT:"modal.stack.now-closing"},$=0,y="a[href], area[href], input:not([disabled]), button:not([disabled]),select:not([disabled]), textarea:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable=true]";return a.$watch(l,function(e){v&&(v.index=e)}),n.on("keydown",w),a.$on("$destroy",function(){n.off("keydown",w)}),_.open=function(t,o){var r=n[0].activeElement,s=o.openedClass||h;c(!1),b.add(t,{deferred:o.deferred,renderDeferred:o.renderDeferred,closedDeferred:o.closedDeferred,modalScope:o.scope,backdrop:o.backdrop,keyboard:o.keyboard,openedClass:o.openedClass,windowTopClass:o.windowTopClass,animation:o.animation,appendTo:o.appendTo}),k.put(s,t);var u=o.appendTo,d=l();if(!u.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");d>=0&&!m&&(v=a.$new(!0),v.modalOptions=o,v.index=d,m=angular.element('
'),m.attr("backdrop-class",o.backdropClass),o.animation&&m.attr("modal-animation","true"),i(m)(v),e.enter(m,u));var p=angular.element('
');p.attr({"template-url":o.windowTemplateUrl,"window-class":o.windowClass,"window-top-class":o.windowTopClass,size:o.size,index:b.length()-1,animate:"animate"}).html(o.content),o.animation&&p.attr("modal-animation","true"),e.enter(p,u).then(function(){i(p)(o.scope),e.addClass(u,s)}),b.top().value.modalDomEl=p,b.top().value.modalOpener=r,_.clearFocusListCache()},_.close=function(e,t){var n=b.get(e);return n&&g(n,t,!0)?(n.value.modalScope.$$wuDestructionScheduled=!0,n.value.deferred.resolve(t),u(e,n.value.modalOpener),!0):!n},_.dismiss=function(e,t){var n=b.get(e);return n&&g(n,t,!1)?(n.value.modalScope.$$wuDestructionScheduled=!0,n.value.deferred.reject(t),u(e,n.value.modalOpener),!0):!n},_.dismissAll=function(e){for(var t=this.getTop();t&&this.dismiss(t.key,e);)t=this.getTop()},_.getTop=function(){return b.top()},_.modalRendered=function(e){var t=b.get(e);t&&t.value.renderDeferred.resolve()},_.focusFirstFocusableElement=function(){return f.length>0?(f[0].focus(),!0):!1},_.focusLastFocusableElement=function(){return f.length>0?(f[f.length-1].focus(),!0):!1},_.isFocusInFirstItem=function(e){return f.length>0?(e.target||e.srcElement)===f[0]:!1},_.isFocusInLastItem=function(e){return f.length>0?(e.target||e.srcElement)===f[f.length-1]:!1},_.clearFocusListCache=function(){f=[],$=0},_.loadFocusElementList=function(e){if((void 0===f||!f.length)&&e){var t=e.value.modalDomEl;t&&t.length&&(f=t[0].querySelectorAll(y))}},_}]).provider("$wuModal",function(){var e={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$wuResolve","$wuModalStack",function(t,n,i,a,o,r,s){function l(e){return e.template?n.when(e.template):a(angular.isFunction(e.templateUrl)?e.templateUrl():e.templateUrl)}var u={},c=null;return u.getPromiseChain=function(){return c},u.open=function(a){function u(){return f}var d=n.defer(),p=n.defer(),w=n.defer(),g=n.defer(),m={result:d.promise,opened:p.promise,closed:w.promise,rendered:g.promise,close:function(e){return s.close(m,e)},dismiss:function(e){return s.dismiss(m,e)}};if(a=angular.extend({},e.options,a),a.resolve=a.resolve||{},a.appendTo=a.appendTo||i.find("body").eq(0),!a.template&&!a.templateUrl)throw new Error("One of template or templateUrl options is required.");var v,f=n.all([l(a),r.resolve(a.resolve,{},null,null)]);return v=c=n.all([c]).then(u,u).then(function(e){var n=a.scope||t,i=n.$new();i.$close=m.close,i.$dismiss=m.dismiss,i.$on("$destroy",function(){i.$$wuDestructionScheduled||i.$dismiss("$wuUnscheduledDestruction")});var r,l={};a.controller&&(l.$scope=i,l.$wuModalInstance=m,angular.forEach(e[1],function(e,t){l[t]=e}),r=o(a.controller,l),a.controllerAs&&(a.bindToController&&(r.$close=i.$close,r.$dismiss=i.$dismiss,angular.extend(r,n)),i[a.controllerAs]=r)),s.open(m,{scope:i,deferred:d,renderDeferred:g,closedDeferred:w,content:e[0],animation:a.animation,backdrop:a.backdrop,keyboard:a.keyboard,backdropClass:a.backdropClass,windowTopClass:a.windowTopClass,windowClass:a.windowClass,windowTemplateUrl:a.windowTemplateUrl,size:a.size,openedClass:a.openedClass,appendTo:a.appendTo}),p.resolve(!0)},function(e){p.reject(e),d.reject(e)})["finally"](function(){c===v&&(c=null)}),m},u}]};return e}),t.weui_client_browser_checker=function(){var e={ie:0,gecko:0,webkit:0,khtml:0,opera:0,ver:null},n={ie:0,firefox:0,safari:0,konq:0,opera:0,chrome:0,wx:0,wxpc:0,ver:null},i={win:!1,mac:!1,x11:!1,iphone:!1,ipod:!1,ipad:!1,ios:!1,android:!1,nokiaN:!1,winMobile:!1,wii:!1,ps:!1},a=navigator.userAgent;if(t.opera)e.ver=n.ver=t.opera.version(),e.opera=n.opera=parseFloat(e.ver);else if(/AppleWebKit\/(\S+)/.test(a))if(e.ver=RegExp.$1,e.webkit=parseFloat(e.ver),/Chrome\/(\S+)/.test(a))n.ver=RegExp.$1,n.chrome=parseFloat(n.ver);else if(/Version\/(\S+)/.test(a))n.ver=RegExp.$1,n.safari=parseFloat(n.ver);else{var o=1;o=e.webkit<100?1:e.webkit<312?1.2:e.webkit<412?1.3:2,n.safari=n.ver=o}else/KHTML\/(\S+)/.test(a)||/Konqueror\/([^;]+])/.test(a)?(e.ver=n.ver=RegExp.$1,e.khtml=n.konq=parseFloat(e.ver)):/rv:([^\)]+)\) Gecko\/\d{8}/.test(a)?(e.ver=RegExp.$1,n.gecko=parseFloat(e.ver),/Firefox\/(\S+)/.test(a)&&(n.ver=RegExp.$1,n.firefox=parseFloat(n.ver))):/MSIE ([^;]+)/.test(a)&&(e.ver=n.ver=RegExp.$1,e.ie=n.ie=parseFloat(e.ver));/MicroMessenger\/([\d\.]+)/i.test(a)&&(n.ver=RegExp.$1,n.wx="micromessenger",n.wxpc=/WindowsWechat/i.test(a)),n.ie=e.ie,n.opera=e.opera;var r=navigator.platform;if(i.win=r.indexOf("Win")>=0,i.mac=r.indexOf("Mac")>=0,i.x11="X11"==r||0==r.indexOf("Linux"),i.win&&/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(a))if("NT"==RegExp.$1)switch(RegExp.$2){case"5.0":i.win="2000";break;case"5.1":i.win="XP";break;case"6.0":i.win="vista";break;case"6.1":i.win="7";break;default:i.win="NT"}else i.win="9x"==RegExp.$1?"ME":RegExp.$1;return i.iphone=a.indexOf("iPhone")>-1,i.ipod=a.indexOf("iPod")>-1,i.ipad=a.indexOf("iPad")>-1,i.nokiaN=a.indexOf("NokinaN")>-1,"CE"==i.win?i.winMobile=i.win:"Ph"==i.win&&/Window Phone OS (\d+.\d+)/.test(a)&&(i.win="Phone",i.winMobile=parseFloat(RegExp.$1)),i.iphone&&a.indexOf("Mobile")>-1&&(i.ios=/CPU (?:iPhone)?[ ]?OS (\d+_\d+)/.test(a)?parseFloat(RegExp.$1.replace("_",".")):2),/Android (\d+\.\d+)/.test(a)&&(i.android=parseFloat(RegExp.$1)),i.wii=a.indexOf("Wii")>-1,i.ps=/playstation/i.test(a),{engine:e,browser:n,system:i}}(),e.provider("WuBrowserChecker",[function(){var e=this;e.$get=[function(){return t.weui_client_browser_checker}]}]),e.provider("IdWorkerFactory",[function(){var e={};this.new=function(t){return e.hasOwnProperty(t)||(e[t]=function(e){var t=0;return function(){return e+"_"+t++}}(t)),e[t]},this.$get=[function(){return this}]}])}(angular.module("ng.weui.core"),window),function(e){e.directive("wuClick",["$parse","$timeout","$rootScope",function(e,t){return{restrict:"EA",compile:function(n,i){var a=e(i.wuClick),o=e(i.wuInterval||"300");return function(e,n){var i=parseInt(o(e)),r=!1;n.on("click",function(o){r||(e.$apply(function(){a(e,{$event:o})}),n.attr("disabled","disabled").addClass("weui_btn_disabled"),r=!0,t(function(){n.removeAttr("disabled").removeClass("weui_btn_disabled"),r=!1},i))})}}}}])}(angular.module("ng.weui.button")),function(e){e.provider("WuActionSheet",[function(){var e=this;e.$get=["$wuModal",function(e){return{open:function(t){return e.open({backdrop:!1,windowTemplateUrl:"weui/template/wu-window.html",template:"
",controller:["$scope",function(e){e.btnGroups=t.btnGroups||[{action:"Cancel",buttons:[{title:"取消",value:"cancel"}]}],e.triggerBtn=function(t,n){var i=t.action.toLowerCase();"ok"===i?e.$close(n.value):e.$dismiss(n.value)}}]})}}}]}]).directive("wuActionSheetTemplate",["$q",function(e){return{restrict:"A",templateUrl:"weui/template/action-sheet/action-sheet.html",link:function(t,n){function i(t,n){return e(function(e){t.removeClass("weui-actionsheet_toggle"),n.removeClass("actionsheet__mask_show"),t.on("transitionend",function(){n.hide(),e()}).on("webkitTransitionEnd",function(){n.hide(),e()})})}var a=n.find(".weui-mask_transparent.actionsheet__mask"),o=n.find(".weui-actionsheet");!function(){a.show().addClass("actionsheet__mask_show").on("click",function(){i(o,a).then(function(){t.$dismiss("mask:click")})}),o.addClass("weui-actionsheet_toggle")}(),t.clickBtn=function(e,n){i(o,a).then(function(){t.triggerBtn(e,n)})}}}}])}(angular.module("ng.weui.actionsheet")); -------------------------------------------------------------------------------- /docs/demo-gallery.html: -------------------------------------------------------------------------------- 1 | angular-WeUI
-------------------------------------------------------------------------------- /docs/demo.html: -------------------------------------------------------------------------------- 1 | angular-WeUIAction Sheet confirm confirm no title alert 自定义按钮 自定义按钮 android Toast 完成 Toast Loading Toast Message show

button wu-click test

按钮 按钮

wuProgress




swiper 测试 -------------------------------------------------------------------------------- /docs/scripts/app-75093ba9.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 15/9/7. 3 | */ 4 | !function(e){e.controller("TestCtrl",["WuActionSheet","WuDialog","WuToast",function(e,t,n){this.actionSheet=function(){e.open({btnGroups:[{action:"Ok",buttons:[{title:"11",value:"11"},{title:"22",value:"22"},{title:"33",value:"33"},{title:"44",value:"44"}]},{action:"Cancel",buttons:[{title:"cancel1",value:"cancel1"}]},{action:"Close",buttons:[{title:"cancel11",value:"cancel1"}]}]}).result.then(function(e){console.log(e)},function(e){console.log(e)})},this.confirm=function(){t.confirm({title:"确认框",content:"xxxx确认内容sfsfsdfsadfsadfdsafdsafsdaf"}).result.then(function(){console.log("ok")},function(){console.log("cancel")})},this.confirmNoTitle=function(){t.confirm({content:"sfsafsfsasadfsfsfsfasfas"}).result.then(function(){console.log("ok")},function(){console.log("cancel")})},this.alert=function(){t.alert({title:"提示框",content:'
xxxx Alert内容
'}).result.then(function(){console.log("ok")},function(){console.log("close alert")})},this.dialog=function(){t.open({title:"自定义按钮",content:"自定义按钮测试",buttons:[{action:"ok",title:"btn1","class":"default",value:"btn1"},{action:"ok",title:"btn2","class":"primary",value:"btn2"},{action:"cancel",title:"btn3","class":"default",value:"btn3"},{action:"cancel",title:"btn4","class":"primary",value:"btn4"}]}).result.then(function(){console.log("OK: ",arguments[0])},function(){console.log("Cancel: ",arguments[0])})},this.dialogAndroid=function(){t.open({title:"自定义按钮",content:"自定义按钮测试",template:"wu-dialog-android-template",buttons:[{action:"ok",title:"btn1","class":"default",value:"btn1"},{action:"ok",title:"btn2","class":"primary",value:"btn2"},{action:"cancel",title:"btn3","class":"default",value:"btn3"},{action:"cancel",title:"btn4","class":"primary",value:"btn4"}]}).result.then(function(){console.log("OK: ",arguments[0])},function(){console.log("Cancel: ",arguments[0])})},this.toastComplete=function(){n.complete({time:1e3})},this.toastLoading=function(){var e=n.loading({message:"数据加载中"});setTimeout(function(){e.close()},1e3)},this.toastMessage=function(){n.message({message:"test asdfasdf sdfasdf asdfsadfv sdfsad asfsadf sdfasfda sdfasfasdf message show"})},this.wuButtonTest=function(){console.log("xxxxxxxxxxxxxxx")},this.testVar="nihao",this.wuButtonTest1=function(e){console.log("000000000000000",e)},this.cancelProgress=function(){this.wuProgress=50}}])}(angular.module("test",["ng.weui"])),function(e){e.controller("TestGalleryCtrl",["WuActionSheet","WuDialog","WuToast",function(){this.previewImages=[{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"},{thumb:"images/pic_article.png",url:"images/pic_article.png"}]}])}(angular.module("test.gallery",["ng.weui"])),angular.module("ng.weui.core",[]),angular.module("ng.weui.jssdk",[]),angular.module("ng.weui.swiper",["ng.weui.core"]),angular.module("ng.weui.button",[]),angular.module("ng.weui.progress",[]),angular.module("ng.weui.dialog",["ng.weui.core"]),angular.module("ng.weui.actionsheet",["ng.weui.core"]),angular.module("ng.weui.toast",["ng.weui.core"]),angular.module("ng.weui.form",["ng.weui.core"]),angular.module("ng.weui.gallery",["ng.weui.core","ng.weui.swiper"]),angular.module("ng.weui.loading",["ng.weui.core"]),angular.module("ng.weui",["ng.weui.core","ng.weui.button","ng.weui.actionsheet","ng.weui.dialog","ng.weui.toast","ng.weui.form","ng.weui.gallery","ng.weui.loading","ng.weui.progress"]),function(e,t){e.factory("WuWxJsSdk",["$q",function(e){function n(e){return t.wx?t.wx:(e({errMsg:"没有js接口对象,请确认是否引入微信js文件"}),!1)}function i(e,t,n){return e.success=function(e){t(e)},e.fail=function(e){n(e)},e.complete=function(){},e.cancel=function(){n({errMsg:"用户取消"})},e.trigger=function(){},e}for(var a={config:function(){return e(function(e,i){var a=n(i);a&&(a.config.apply(t,arguments),a.ready(function(){e({errMsg:"config:ok"})}),a.error(function(e){i(e)}))})}},o=["checkJsApi","onMenuShareTimeline","onMenuShareAppMessage","onMenuShareQQ","onMenuShareWeibo","onMenuShareWeibo","chooseImage","previewImage","uploadImage","downloadImage","startRecord","stopRecord","onVoiceRecordEnd","playVoice","pauseVoice","stopVoice","onVoicePlayEnd","uploadVoice","downloadVoice","translateVoice","getNetworkType","openLocation","getLocation","hideOptionMenu","showOptionMenu","closeWindow","hideMenuItems","showMenuItems","hideAllNonBaseMenuItem","showAllNonBaseMenuItem","scanQRCode","startSearchBeacons","stopSearchBeacons","onSearchBeacons","openProductSpecificView","chooseCard","addCard","openCard","consumeAndShareCard","chooseWXPay"],r=0;r
',link:function(e){e.filterProgress=function(e){return e>100?"100%":0>e?"0%":parseFloat(e)+"%"},e.filterHeight=function(e){return(e&&e>1?e:3)+"px"}}}}])}(angular.module("ng.weui.progress")),function(e,t){"use strict";t.directive("wuSwiperContainer",["IdWorkerFactory",function(e){var t=e("wuSwiperContainer");return{restrict:"E",transclude:!0,scope:{onReady:"&",slidesPerView:"=",slidesPerColumn:"=",spaceBetween:"=",parallax:"=",parallaxTransition:"@",paginationIsActive:"=",paginationClickable:"=",showNavButtons:"=",showScrollBar:"=",loop:"=",autoplay:"=",initialSlide:"=",containerCls:"@",wrapperCls:"@",paginationCls:"@",slideCls:"@",direction:"@",swiper:"=",overrideParameters:"="},controller:function(e,n,i){var a=t();e.swiper_uuid=a;var o={slidesPerView:e.slidesPerView||1,slidesPerColumn:e.slidesPerColumn||1,spaceBetween:e.spaceBetween||0,direction:e.direction||"horizontal",loop:e.loop||!1,initialSlide:e.initialSlide||0,showNavButtons:!1};angular.isUndefined(e.autoplay)||"number"!=typeof e.autoplay||(o=angular.extend({},o,{autoplay:e.autoplay})),e.paginationIsActive===!0&&(o=angular.extend({},o,{paginationClickable:e.paginationClickable||!0,pagination:"#paginator-"+e.swiper_uuid})),e.showNavButtons===!0&&(o.nextButton="#nextButton-"+e.swiper_uuid,o.prevButton="#prevButton-"+e.swiper_uuid),e.showScrollBar===!0&&(o.scrollbar="#scrollBar-"+e.swiper_uuid),e.overrideParameters&&(o=angular.extend({},o,e.overrideParameters)),i(function(){var t=null;angular.isObject(e.swiper)?(e.swiper=new Swiper(n[0].firstChild,o),t=e.swiper):t=new Swiper(n[0].firstChild,o),angular.isUndefined(e.onReady)||e.onReady({swiper:t})})},link:function(e,t){var n=e.swiper_uuid,i="paginator-"+n,a="prevButton-"+n,o="nextButton-"+n,r="scrollBar-"+n,l=t[0];angular.element(l.querySelector(".swiper-pagination")).attr("id",i),angular.element(l.querySelector(".swiper-button-next")).attr("id",o),angular.element(l.querySelector(".swiper-button-prev")).attr("id",a),angular.element(t[0].querySelector(".swiper-scrollbar")).attr("id",r)},template:'
'}}]).directive("wuSwiperSlide",[function(){return{restrict:"E",require:"^ksSwiperContainer",transclude:!0,scope:{sliderCls:"@"},template:'
',replace:!0}}])}(window,angular.module("ng.weui.swiper"),void 0),function(e){e.directive("loadingEnable",[function(){return{restrict:"A",replace:!0,templateUrl:"weui/template/loading/loading.html",transclude:!0,link:function(){}}}])}(angular.module("ng.weui.loading"),window),function(e){e.factory("PreviewImages",["WuWxJsSdk",function(e){return{show:function(t,n){e.previewImage({current:t,urls:n})}}}]),e.directive("previewImages",["PreviewImages",function(e){return{restrict:"AE",link:function(t,n,i){var a=n,o=i.preview?i.preview:"img",r=i.attrName?i.attrName:"src";n.on("click",o,function(t){var n=$(this),i=[];return a.find(o).each(function(e,t){i.push(t.attr(r))}),e.show(n.attr(r),i),t.preventDefault(),t.stopPropagation(),!1})}}}]),e.directive("gallery",["$timeout","IdWorkerFactory",function(e,t){var n=t.new("weui-gallery_swiper");return{restrict:"EA",templateUrl:"weui/template/gallery/gallery.html",scope:{images:"="},link:function(t,i){function a(){e(function(){console.log("#"+o+" .swiper-images");var e=new Swiper("#"+o+" .swiper-images",{nextButton:".swiper-button-next",prevButton:".swiper-button-prev",spaceBetween:10,effect:"coverflow",grabCursor:!0,centeredSlides:!0,slidesPerView:"auto",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0}});if(t.showThumb){var n=new Swiper("#"+o+" .gallery-thumbs",{spaceBetween:10,centeredSlides:!0,slidesPerView:"auto",touchRatio:.2,slideToClickedSlide:!0});e.params.control=n,n.params.control=e}},10)}var o=n();i.attr("id",o),i.addClass("weui-gallery"),i.show(),t.showThumb=!1,angular.isArray(t.images)&&t.images.length>0&&(t.images[0].hasOwnProperty("thumb")&&(t.showThumb=!0),a()),t.imageStyle=function(e){return{"background-image":"url("+e.url+")"}}}}}])}(angular.module("ng.weui.gallery")),function(e){e.directive("inputTextarea",[function(){return{restrict:"EA",replace:!0,templateUrl:"weui/template/form/input-textarea.html",require:"ngModel",link:function(e,t,n,i){i.$render=function(){console.log()}}}}]),e.directive("inputImage",[function(){return{restrict:"EA",replace:!0,templateUrl:"weui/template/form/input-image.html",require:"ngModel",link:function(e,t,n,i){i.$render=function(){console.log()}}}}])}(angular.module("ng.weui.form")),function(e){e.provider("WuDialog",[function(){var e=this;e.$get=["$wuModal",function(e){return{open:function(t){t.buttons=t.buttons||[{action:"ok",title:"确定","class":"default",value:"ok"}];var n="wu-dialog-default-template";return t.hasOwnProperty("template")&&t.template&&(n=t.template),e.open({backdrop:!1,windowTemplateUrl:"weui/template/wu-window.html",template:"
",controller:["$scope",function(e){e.title=t.title,e.content=t.content,e.buttons=t.buttons,e.clickBtn=function(t){"ok"===t.action.toLowerCase()?e.$close(t.value):e.$dismiss(t.value)}}]})},alert:function(e){return this.open({title:e.title,content:e.content})},confirm:function(e){return this.open({title:e.title,content:e.content,buttons:[{action:"cancel",title:"取消","class":"default",value:"cancel"},{action:"ok",title:"确定","class":"primary",value:"ok"}]})}}}]}]);var t=function(e,t){var n=t.find(".weui-mask");n.on("click",function(){e.$apply(function(){e.$dismiss("mask:click")})});var i="weui-dialog__alert";e.buttons.length>1&&(i="weui-dialog__confirm"),t.addClass(i)};e.directive("wuDialogDefaultTemplate",[function(){return{restrict:"A",templateUrl:"weui/template/dialog/default.html",link:t}}]).directive("wuDialogAndroidTemplate",[function(){return{restrict:"A",templateUrl:"weui/template/dialog/android.html",link:t}}]),e.directive("unsafeShowHtml",["$compile",function(e){return{restrict:"A",scope:{content:"=unsafeShowHtml"},link:function(t,n){var i=function(){var i="
"+t.content+"
";n.html("").append(e(i)(t))};i()}}}])}(angular.module("ng.weui.dialog")),function(e,t){e.factory("$$stackedMap",function(){return{createNew:function(){var e=[];return{add:function(t,n){e.push({key:t,value:n})},get:function(t){for(var n=0;n0&&(t=b.top().value,t.modalDomEl.toggleClass(t.windowTopClass||"",e))}function d(){if(m&&-1===s()){var e=f;p(m,f,function(){e=null}),m=void 0,f=void 0}}function p(e,n,i,a){function r(){r.done||(r.done=!0,t(e,{event:"leave"}).start().then(function(){e.remove(),a&&a.resolve()}),n.$destroy(),i&&i())}var l,s=null,u=function(){return l||(l=o.defer(),s=l.promise),function(){l.resolve()}};return n.$broadcast(k.NOW_CLOSING_EVENT,u),o.when(s).then(r)}function g(e){if(e.isDefaultPrevented())return e;var t=b.top();if(t)switch(e.which){case 27:t.value.keyboard&&(e.preventDefault(),a.$apply(function(){k.dismiss(t.key,"escape key press")}));break;case 9:k.loadFocusElementList(t);var n=!1;e.shiftKey?k.isFocusInFirstItem(e)&&(n=k.focusLastFocusableElement()):k.isFocusInLastItem(e)&&(n=k.focusFirstFocusableElement()),n&&(e.preventDefault(),e.stopPropagation())}}function w(e,t,n){return!e.value.modalScope.$broadcast("modal.closing",t,n).defaultPrevented}var m,f,v,h="modal-open",b=l.createNew(),_=r.createNew(),k={NOW_CLOSING_EVENT:"modal.stack.now-closing"},y=0,$="a[href], area[href], input:not([disabled]), button:not([disabled]),select:not([disabled]), textarea:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable=true]";return a.$watch(s,function(e){f&&(f.index=e)}),n.on("keydown",g),a.$on("$destroy",function(){n.off("keydown",g)}),k.open=function(t,o){var r=n[0].activeElement,l=o.openedClass||h;c(!1),b.add(t,{deferred:o.deferred,renderDeferred:o.renderDeferred,closedDeferred:o.closedDeferred,modalScope:o.scope,backdrop:o.backdrop,keyboard:o.keyboard,openedClass:o.openedClass,windowTopClass:o.windowTopClass,animation:o.animation,appendTo:o.appendTo}),_.put(l,t);var u=o.appendTo,d=s();if(!u.length)throw new Error("appendTo element not found. Make sure that the element passed is in DOM.");d>=0&&!m&&(f=a.$new(!0),f.modalOptions=o,f.index=d,m=angular.element('
'),m.attr("backdrop-class",o.backdropClass),o.animation&&m.attr("modal-animation","true"),i(m)(f),e.enter(m,u));var p=angular.element('
');p.attr({"template-url":o.windowTemplateUrl,"window-class":o.windowClass,"window-top-class":o.windowTopClass,size:o.size,index:b.length()-1,animate:"animate"}).html(o.content),o.animation&&p.attr("modal-animation","true"),e.enter(p,u).then(function(){i(p)(o.scope),e.addClass(u,l)}),b.top().value.modalDomEl=p,b.top().value.modalOpener=r,k.clearFocusListCache()},k.close=function(e,t){var n=b.get(e);return n&&w(n,t,!0)?(n.value.modalScope.$$wuDestructionScheduled=!0,n.value.deferred.resolve(t),u(e,n.value.modalOpener),!0):!n},k.dismiss=function(e,t){var n=b.get(e);return n&&w(n,t,!1)?(n.value.modalScope.$$wuDestructionScheduled=!0,n.value.deferred.reject(t),u(e,n.value.modalOpener),!0):!n},k.dismissAll=function(e){for(var t=this.getTop();t&&this.dismiss(t.key,e);)t=this.getTop()},k.getTop=function(){return b.top()},k.modalRendered=function(e){var t=b.get(e);t&&t.value.renderDeferred.resolve()},k.focusFirstFocusableElement=function(){return v.length>0?(v[0].focus(),!0):!1},k.focusLastFocusableElement=function(){return v.length>0?(v[v.length-1].focus(),!0):!1},k.isFocusInFirstItem=function(e){return v.length>0?(e.target||e.srcElement)===v[0]:!1},k.isFocusInLastItem=function(e){return v.length>0?(e.target||e.srcElement)===v[v.length-1]:!1},k.clearFocusListCache=function(){v=[],y=0},k.loadFocusElementList=function(e){if((void 0===v||!v.length)&&e){var t=e.value.modalDomEl;t&&t.length&&(v=t[0].querySelectorAll($))}},k}]).provider("$wuModal",function(){var e={options:{animation:!0,backdrop:!0,keyboard:!0},$get:["$rootScope","$q","$document","$templateRequest","$controller","$wuResolve","$wuModalStack",function(t,n,i,a,o,r,l){function s(e){return e.template?n.when(e.template):a(angular.isFunction(e.templateUrl)?e.templateUrl():e.templateUrl)}var u={},c=null;return u.getPromiseChain=function(){return c},u.open=function(a){function u(){return v}var d=n.defer(),p=n.defer(),g=n.defer(),w=n.defer(),m={result:d.promise,opened:p.promise,closed:g.promise,rendered:w.promise,close:function(e){return l.close(m,e)},dismiss:function(e){return l.dismiss(m,e)}};if(a=angular.extend({},e.options,a),a.resolve=a.resolve||{},a.appendTo=a.appendTo||i.find("body").eq(0),!a.template&&!a.templateUrl)throw new Error("One of template or templateUrl options is required.");var f,v=n.all([s(a),r.resolve(a.resolve,{},null,null)]);return f=c=n.all([c]).then(u,u).then(function(e){var n=a.scope||t,i=n.$new();i.$close=m.close,i.$dismiss=m.dismiss,i.$on("$destroy",function(){i.$$wuDestructionScheduled||i.$dismiss("$wuUnscheduledDestruction")});var r,s={};a.controller&&(s.$scope=i,s.$wuModalInstance=m,angular.forEach(e[1],function(e,t){s[t]=e}),r=o(a.controller,s),a.controllerAs&&(a.bindToController&&(r.$close=i.$close,r.$dismiss=i.$dismiss,angular.extend(r,n)),i[a.controllerAs]=r)),l.open(m,{scope:i,deferred:d,renderDeferred:w,closedDeferred:g,content:e[0],animation:a.animation,backdrop:a.backdrop,keyboard:a.keyboard,backdropClass:a.backdropClass,windowTopClass:a.windowTopClass,windowClass:a.windowClass,windowTemplateUrl:a.windowTemplateUrl,size:a.size,openedClass:a.openedClass,appendTo:a.appendTo}),p.resolve(!0)},function(e){p.reject(e),d.reject(e)})["finally"](function(){c===f&&(c=null)}),m},u}]};return e}),t.weui_client_browser_checker=function(){var e={ie:0,gecko:0,webkit:0,khtml:0,opera:0,ver:null},n={ie:0,firefox:0,safari:0,konq:0,opera:0,chrome:0,wx:0,wxpc:0,ver:null},i={win:!1,mac:!1,x11:!1,iphone:!1,ipod:!1,ipad:!1,ios:!1,android:!1,nokiaN:!1,winMobile:!1,wii:!1,ps:!1},a=navigator.userAgent;if(t.opera)e.ver=n.ver=t.opera.version(),e.opera=n.opera=parseFloat(e.ver);else if(/AppleWebKit\/(\S+)/.test(a))if(e.ver=RegExp.$1,e.webkit=parseFloat(e.ver),/Chrome\/(\S+)/.test(a))n.ver=RegExp.$1,n.chrome=parseFloat(n.ver);else if(/Version\/(\S+)/.test(a))n.ver=RegExp.$1,n.safari=parseFloat(n.ver);else{var o=1;o=e.webkit<100?1:e.webkit<312?1.2:e.webkit<412?1.3:2,n.safari=n.ver=o}else/KHTML\/(\S+)/.test(a)||/Konqueror\/([^;]+])/.test(a)?(e.ver=n.ver=RegExp.$1,e.khtml=n.konq=parseFloat(e.ver)):/rv:([^\)]+)\) Gecko\/\d{8}/.test(a)?(e.ver=RegExp.$1,n.gecko=parseFloat(e.ver),/Firefox\/(\S+)/.test(a)&&(n.ver=RegExp.$1,n.firefox=parseFloat(n.ver))):/MSIE ([^;]+)/.test(a)&&(e.ver=n.ver=RegExp.$1,e.ie=n.ie=parseFloat(e.ver));/MicroMessenger\/([\d\.]+)/i.test(a)&&(n.ver=RegExp.$1,n.wx="micromessenger",n.wxpc=/WindowsWechat/i.test(a)),n.ie=e.ie,n.opera=e.opera;var r=navigator.platform;if(i.win=r.indexOf("Win")>=0,i.mac=r.indexOf("Mac")>=0,i.x11="X11"==r||0==r.indexOf("Linux"),i.win&&/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(a))if("NT"==RegExp.$1)switch(RegExp.$2){case"5.0":i.win="2000";break;case"5.1":i.win="XP";break;case"6.0":i.win="vista";break;case"6.1":i.win="7";break;default:i.win="NT"}else i.win="9x"==RegExp.$1?"ME":RegExp.$1;return i.iphone=a.indexOf("iPhone")>-1,i.ipod=a.indexOf("iPod")>-1,i.ipad=a.indexOf("iPad")>-1,i.nokiaN=a.indexOf("NokinaN")>-1,"CE"==i.win?i.winMobile=i.win:"Ph"==i.win&&/Window Phone OS (\d+.\d+)/.test(a)&&(i.win="Phone",i.winMobile=parseFloat(RegExp.$1)),i.iphone&&a.indexOf("Mobile")>-1&&(i.ios=/CPU (?:iPhone)?[ ]?OS (\d+_\d+)/.test(a)?parseFloat(RegExp.$1.replace("_",".")):2),/Android (\d+\.\d+)/.test(a)&&(i.android=parseFloat(RegExp.$1)),i.wii=a.indexOf("Wii")>-1,i.ps=/playstation/i.test(a),{engine:e,browser:n,system:i}}(),e.provider("WuBrowserChecker",[function(){var e=this;e.$get=[function(){return t.weui_client_browser_checker}]}]),e.provider("IdWorkerFactory",[function(){var e={};this.new=function(t){return e.hasOwnProperty(t)||(e[t]=function(e){var t=0;return function(){return e+"_"+t++}}(t)),e[t]},this.$get=[function(){return this}]}])}(angular.module("ng.weui.core"),window),function(e){e.directive("wuClick",["$parse","$timeout","$rootScope",function(e,t){return{restrict:"EA",compile:function(n,i){var a=e(i.wuClick),o=e(i.wuInterval||"300");return function(e,n){var i=parseInt(o(e)),r=!1;n.on("click",function(o){r||(e.$apply(function(){a(e,{$event:o})}),n.attr("disabled","disabled").addClass("weui_btn_disabled"),r=!0,t(function(){n.removeAttr("disabled").removeClass("weui_btn_disabled"),r=!1},i))})}}}}])}(angular.module("ng.weui.button")),function(e){e.provider("WuActionSheet",[function(){var e=this;e.$get=["$wuModal",function(e){return{open:function(t){return e.open({backdrop:!1,windowTemplateUrl:"weui/template/wu-window.html",template:"
",controller:["$scope",function(e){e.btnGroups=t.btnGroups||[{action:"Cancel",buttons:[{title:"取消",value:"cancel"}]}],e.triggerBtn=function(t,n){var i=t.action.toLowerCase();"ok"===i?e.$close(n.value):e.$dismiss(n.value)}}]})}}}]}]).directive("wuActionSheetTemplate",["$q",function(e){return{restrict:"A",templateUrl:"weui/template/action-sheet/action-sheet.html",link:function(t,n){function i(t,n){return e(function(e){t.removeClass("weui-actionsheet_toggle"),n.removeClass("actionsheet__mask_show"),t.on("transitionend",function(){n.hide(),e()}).on("webkitTransitionEnd",function(){n.hide(),e()})})}var a=n.find(".weui-mask_transparent.actionsheet__mask"),o=n.find(".weui-actionsheet");!function(){a.show().addClass("actionsheet__mask_show").on("click",function(){i(o,a).then(function(){t.$dismiss("mask:click")})}),o.addClass("weui-actionsheet_toggle")}(),t.clickBtn=function(e,n){i(o,a).then(function(){t.triggerBtn(e,n)})}}}}])}(angular.module("ng.weui.actionsheet")),angular.module("ng.weui").run(["$templateCache",function(e){e.put("weui/template/wu-window.html",'
'),e.put("weui/template/action-sheet/action-sheet.html",'
{{btn.title}}
'),e.put("weui/template/dialog/android.html",'
'),e.put("weui/template/dialog/default.html",'
'),e.put("weui/template/form/input-image.html",'

图片上传

0/2
  • 50%
'),e.put("weui/template/form/input-textarea.html",'
0/200
'),e.put("weui/template/gallery/gallery.html",'
'),e.put("weui/template/loading/loading.html",'
正在加载
暂无数据
'),e.put("weui/template/toast/complete.html",'

'),e.put("weui/template/toast/loading.html",'

'),e.put("weui/template/toast/message.html",'
')}]); -------------------------------------------------------------------------------- /docs/styles/app-e8d70c78.css: -------------------------------------------------------------------------------- 1 | .actionsheet__mask_show{background:rgba(0,0,0,.6)}.weui-gallery .weui-page{width:100%;height:100%}.weui-gallery .weui-gallery_swiper{position:relative;height:100%;width:100%;overflow:hidden}.weui-gallery .swiper-container{width:100%;height:90%;margin-left:auto;margin-right:auto}.weui-gallery .swiper-container.gallery-top{height:80%;width:100%}.weui-gallery .swiper-slide{top:0;right:0;bottom:60px;left:0;background:center center no-repeat;background-size:contain}.weui-gallery .gallery-thumbs.swiper-container{height:20%;box-sizing:border-box;padding:10px 0}.weui-gallery .gallery-thumbs .swiper-slide{width:25%;height:100%;opacity:.4}.weui-gallery .gallery-thumbs .swiper-slide-active{opacity:1}.weui-toast.wu_toast_message{bottom:32px;top:auto;min-height:inherit;width:15.6em;margin-left:-7.8em} -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | gulp.appName = 'angular-weui'; 5 | gulp.moduleName = 'ng.weui'; 6 | gulp.paths = { 7 | src: 'src', 8 | dist: 'dist', 9 | tmp: '.tmp', 10 | e2e: 'test/e2e', 11 | unit: 'test/unit', 12 | test_server:'test/serve', 13 | docs: 'docs/api', 14 | demo: 'docs', 15 | reports: 'reports' 16 | }; 17 | 18 | require('require-dir')('./.gulp'); 19 | 20 | gulp.task('default', ['clean'], function () { 21 | gulp.start('build'); 22 | }); 23 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function(config) { 4 | 5 | config.set({ 6 | autoWatch : true, 7 | 8 | frameworks: ['jasmine'], 9 | 10 | browsers : ['PhantomJS'], 11 | 12 | plugins : [ 13 | 'karma-phantomjs-launcher', 14 | 'karma-jasmine', 15 | 'karma-coverage' 16 | ], 17 | preprocessors: { 18 | 'src/**/*.js': ['coverage'] 19 | }, 20 | reporters: ['progress', 'coverage'], 21 | coverageReporter: { 22 | type: 'lcov', 23 | dir: 'reports', 24 | subdir: 'coverage' 25 | }, 26 | 27 | colors: true 28 | }); 29 | }; 30 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-weui", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "install:bower": "bower install --save", 6 | "dev": "gulp serve", 7 | "build:dist": "gulp", 8 | "build:docs": "gulp docs", 9 | "build:demo": "gulp demo", 10 | "gulp": "gulp" 11 | }, 12 | "dependencies": {}, 13 | "devDependencies": { 14 | "bower": "^1.7.9", 15 | "browser-sync": "~1.7.1", 16 | "chalk": "~0.5.1", 17 | "del": "~0.1.3", 18 | "gulp": "^3.9.0", 19 | "gulp-angular-filesort": "~1.0.4", 20 | "gulp-angular-templatecache": "~1.4.2", 21 | "gulp-autoprefixer": "~2.0.0", 22 | "gulp-concat": "~2.6.0", 23 | "gulp-consolidate": "~0.1.2", 24 | "gulp-csso": "~0.2.9", 25 | "gulp-filter": "~1.0.2", 26 | "gulp-flatten": "~0.0.4", 27 | "gulp-inject": "~1.0.2", 28 | "gulp-jsdoc": "~0.1.4", 29 | "gulp-jshint": "~1.9.0", 30 | "gulp-karma": "~0.0.4", 31 | "gulp-less": "~1.3.6", 32 | "gulp-load-plugins": "~0.7.1", 33 | "gulp-minify-css": "~1.2.1", 34 | "gulp-minify-html": "~0.1.7", 35 | "gulp-ng-annotate": "~0.3.6", 36 | "gulp-plumber": "~1.0.1", 37 | "gulp-protractor": "~0.0.11", 38 | "gulp-rename": "~1.2.0", 39 | "gulp-replace": "~0.5.0", 40 | "gulp-rev": "~2.0.1", 41 | "gulp-rev-replace": "~0.3.1", 42 | "gulp-sass": "^2.3.2", 43 | "gulp-size": "~1.1.0", 44 | "gulp-stylus": "^2.2.0", 45 | "gulp-uglify": "~1.0.1", 46 | "gulp-useref": "~1.0.2", 47 | "http-proxy": "~1.7.0", 48 | "jshint-stylish": "~1.0.0", 49 | "karma-coverage": "~0.5.2", 50 | "karma-jasmine": "~0.3.1", 51 | "karma-phantomjs-launcher": "~0.1.4", 52 | "main-bower-files": "~2.4.0", 53 | "opn": "^3.0.2", 54 | "protractor": "~1.4.0", 55 | "require-dir": "~0.1.0", 56 | "uglify-save-license": "~0.4.1", 57 | "wiredep": "~2.2.0" 58 | }, 59 | "engines": { 60 | "node": ">=0.10.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var paths = require('./.yo-rc.json')['generator-gulp-angular'].props.paths; 4 | 5 | /* 6 | npm install chai 7 | npm install chai-as-promised 8 | */ 9 | 10 | // An example configuration file. 11 | exports.config = { 12 | // The address of a running selenium server. 13 | seleniumAddress: 'http://localhost:4444/wd/hub', 14 | //seleniumServerJar: deprecated, this should be set on node_modules/protractor/config.json 15 | // framework: 'jasmine', // jasmine2 mocha cucumber 16 | 17 | chromeDriver: '/Users/three/tools/selenium/chromedriver', 18 | seleniumServerJar: '/Users/three/tools/selenium/selenium-server-standalone-2.44.0.jar', 19 | 20 | //firefoxPath:'/Applications/Firefox.app/Contents/MacOS/firefox-bin', 21 | 22 | 23 | // Capabilities to be passed to the webdriver instance. 24 | //capabilities: { 25 | // 'browserName': 'chrome' 26 | //}, 27 | multiCapabilities: [{ 28 | name: 'chrome_mac', 29 | browserName: 'chrome', 30 | platformName: 'MAC', 31 | deviceName: 'ChromeDriver' 32 | }, { 33 | name: 'chrome_android', 34 | browserName: 'chrome', 35 | platformName: 'ANDROID', 36 | deviceName: 'ChromeDriver', 37 | 'chromeOptions': { 38 | 'androidPackage': 'com.android.chrome' 39 | } 40 | }, { 41 | name: 'chrome_firefox', 42 | browserName: 'firefox', 43 | platformName: 'MAC', 44 | deviceName: 'FirefoxDriver' 45 | }/*,{ 46 | 'browserName': 'phantomjs', 47 | 48 | /!* 49 | * Can be used to specify the phantomjs binary path. 50 | * This can generally be ommitted if you installed phantomjs globally. 51 | *!/ 52 | 'phantomjs.binary.path': require('phantomjs').path, 53 | 54 | /!* 55 | * Command line args to pass to ghostdriver, phantomjs's browser driver. 56 | * See https://github.com/detro/ghostdriver#faq 57 | *!/ 58 | 'phantomjs.ghostdriver.cli.args': ['--loglevel=DEBUG'] 59 | }*/], 60 | 61 | //directConnect:true, 62 | // Spec patterns are relative to the current working directly when 63 | // protractor is called. 64 | specs: [paths.e2e + '/**/*.js'], 65 | 66 | mochaOpts: { 67 | ui: 'bdd', 68 | reporter: 'list' 69 | }, 70 | // Options to be passed to Jasmine-node. 71 | jasmineNodeOpts: { 72 | showColors: true, 73 | defaultTimeoutInterval: 30000 74 | } 75 | }; 76 | -------------------------------------------------------------------------------- /src/css/actionsheet.styl: -------------------------------------------------------------------------------- 1 | .actionsheet__mask_show { 2 | background: rgba(0,0,0,.6); 3 | } 4 | -------------------------------------------------------------------------------- /src/css/gallery.styl: -------------------------------------------------------------------------------- 1 | .weui-gallery{ 2 | .weui-page { 3 | width 100% 4 | height 100% 5 | } 6 | .weui-gallery_swiper { 7 | position: relative; 8 | height:100% 9 | width 100% 10 | overflow hidden 11 | } 12 | .swiper-container { 13 | width: 100%; 14 | height: 90%; 15 | margin-left: auto; 16 | margin-right: auto; 17 | &.gallery-top { 18 | height: 80%; 19 | width: 100%; 20 | } 21 | //position: absolute; 22 | } 23 | .swiper-slide { 24 | //background-size: cover; 25 | //background-position: center; 26 | //position: absolute; 27 | top: 0; 28 | right: 0; 29 | bottom: 60px; 30 | left: 0; 31 | background: center center no-repeat; 32 | background-size: contain; 33 | } 34 | 35 | .gallery-thumbs { 36 | &.swiper-container { 37 | height: 20%; 38 | box-sizing: border-box; 39 | padding: 10px 0; 40 | } 41 | .swiper-slide { 42 | width: 25%; 43 | height: 100%; 44 | opacity: 0.4; 45 | } 46 | .swiper-slide-active { 47 | opacity: 1; 48 | } 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/css/toast.styl: -------------------------------------------------------------------------------- 1 | .weui-toast.wu_toast_message { 2 | bottom: 32px; 3 | top: auto; 4 | min-height: inherit; 5 | width: 15.6em; 6 | margin-left: -7.8em 7 | } 8 | -------------------------------------------------------------------------------- /src/js/Dialog.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 16/1/13. 3 | * 4 | * 目前 `WuDialog` 并不是安全的,需要调用者控制输出的 html 代码防止 xss 5 | * 可以参考:https://github.com/leizongmin/js-xss 6 | */ 7 | 8 | (function (app) { 9 | app.provider('WuDialog', [function () { 10 | var _self = this; 11 | 12 | _self.$get = ['$wuModal',function ($wuModal) { 13 | return { 14 | open: function (config) { 15 | config.buttons = config.buttons || [ 16 | { 17 | action:'ok', 18 | title:'确定', 19 | class: 'default', 20 | value:'ok' 21 | } 22 | ]; 23 | 24 | var template = 'wu-dialog-default-template'; 25 | if(config.hasOwnProperty('template') && !!config.template) { 26 | template = config.template; 27 | } 28 | return $wuModal.open({ 29 | backdrop: false, 30 | windowTemplateUrl: 'weui/template/wu-window.html', 31 | template: '
', 32 | controller: ['$scope', function ($scope) { 33 | $scope.title = config.title; 34 | $scope.content = config.content; 35 | $scope.buttons = config.buttons; 36 | 37 | $scope.clickBtn = function (btn) { 38 | if(btn.action.toLowerCase()==='ok') { 39 | $scope.$close(btn.value); 40 | } else { 41 | $scope.$dismiss(btn.value); 42 | } 43 | } 44 | }] 45 | }) 46 | }, 47 | alert: function(config){ 48 | return this.open({ 49 | title: config.title, 50 | content: config.content 51 | }); 52 | }, 53 | confirm: function(config) { 54 | return this.open({ 55 | title: config.title, 56 | content: config.content, 57 | buttons: [ 58 | { 59 | action:'cancel', 60 | title:'取消', 61 | class: 'default', 62 | value:'cancel' 63 | }, 64 | { 65 | action:'ok', 66 | title:'确定', 67 | class: 'primary', 68 | value:'ok' 69 | } 70 | ] 71 | }); 72 | } 73 | } 74 | }]; 75 | }]); 76 | 77 | var linkFunction = function (scope, element, attrs) { 78 | var mask = element.find('.weui-mask'); 79 | mask.on('click', function () { 80 | scope.$apply(function () { 81 | scope.$dismiss('mask:click'); 82 | }); 83 | }); 84 | 85 | var openedClass = 'weui-dialog__alert'; 86 | if(scope.buttons.length>1) { 87 | openedClass= 'weui-dialog__confirm' 88 | } 89 | element.addClass(openedClass); 90 | } 91 | app.directive('wuDialogDefaultTemplate', [function () { 92 | return { 93 | restrict: 'A', 94 | templateUrl: 'weui/template/dialog/default.html', 95 | link: linkFunction 96 | }; 97 | }]) 98 | .directive('wuDialogAndroidTemplate', [function () { 99 | return { 100 | restrict: 'A', 101 | templateUrl: 'weui/template/dialog/android.html', 102 | link: linkFunction 103 | }; 104 | }]) 105 | ; 106 | /** 107 | * 表格数据 html 输出 108 | * 这个会有 xss 风险 109 | */ 110 | app.directive('unsafeShowHtml', ['$compile', function ($compile) { 111 | 112 | /** 113 | * html 编码,html源码输出 114 | * @param {[type]} html [description] 115 | */ 116 | function HTMLEncode(html) { 117 | var temp = document.createElement("div"); 118 | (temp.textContent != null) ? (temp.textContent = html) : (temp.innerText = html); 119 | var output = temp.innerHTML; 120 | temp = null; 121 | return output; 122 | } 123 | 124 | return { 125 | restrict: 'A', 126 | scope: { 127 | content: '=unsafeShowHtml' 128 | }, 129 | link: function (scope, element, attrs) { 130 | 131 | var change = function () { 132 | var showHtml = '
'+scope.content+'
'; 133 | element.html('').append($compile(showHtml)(scope)); 134 | }; 135 | //scope.$watch('content', function () { 136 | change(); 137 | //}); 138 | } 139 | } 140 | }]); 141 | })(angular.module('ng.weui.dialog')); 142 | -------------------------------------------------------------------------------- /src/js/Toast.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 16/1/13. 3 | */ 4 | 5 | (function (app) { 6 | app.provider('WuToast',[function () { 7 | var _self = this; 8 | 9 | _self.$get = ['$wuModal','$timeout',function ($wuModal,$timeout) { 10 | return { 11 | complete: function (config) { 12 | config = config || {}; 13 | var toastInstance = $wuModal.open({ 14 | backdrop: false, 15 | windowTemplateUrl:'weui/template/wu-window.html', 16 | templateUrl:'weui/template/toast/complete.html', 17 | controller:['$scope', function ($scope) { 18 | $scope.message = config.message || '已完成'; 19 | }] 20 | }); 21 | if(config.hasOwnProperty('time')) { 22 | $timeout(function () { 23 | toastInstance.close(); 24 | }, parseInt(config.time)) 25 | } 26 | return { 27 | close: function () { 28 | toastInstance.close(); 29 | } 30 | } 31 | }, 32 | loading: function (config) { 33 | config = config || {}; 34 | var toastInstance = $wuModal.open({ 35 | backdrop: false, 36 | windowTemplateUrl:'weui/template/wu-window.html', 37 | templateUrl:'weui/template/toast/loading.html', 38 | controller:['$scope', function ($scope) { 39 | $scope.message = config.message || '数据加载中'; 40 | }] 41 | }); 42 | if(config.hasOwnProperty('time')) { 43 | $timeout(function () { 44 | toastInstance.close(); 45 | }, parseInt(config.time)) 46 | } 47 | return { 48 | close: function () { 49 | toastInstance.close(); 50 | } 51 | } 52 | }, 53 | message: function (config) { 54 | config = config || {}; 55 | var toastInstance = $wuModal.open({ 56 | backdrop: false, 57 | windowTemplateUrl:'weui/template/wu-window.html', 58 | templateUrl:'weui/template/toast/message.html', 59 | controller:['$scope', function ($scope) { 60 | $scope.message = config.message || '消息提示'; 61 | }] 62 | }); 63 | if(config.hasOwnProperty('time')) { 64 | $timeout(function () { 65 | toastInstance.close(); 66 | }, parseInt(config.time)) 67 | } 68 | return { 69 | close: function () { 70 | toastInstance.close(); 71 | } 72 | } 73 | } 74 | } 75 | }]; 76 | }]) 77 | })(angular.module('ng.weui.toast')); 78 | -------------------------------------------------------------------------------- /src/js/action-sheet.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 16/1/13. 3 | */ 4 | 5 | /** 6 | * ActionSheet 封装 7 | */ 8 | (function (app) { 9 | app.provider('WuActionSheet',[function () { 10 | var _self = this; 11 | 12 | _self.$get = ['$wuModal',function ($wuModal) { 13 | return { 14 | open: function(config){ 15 | return $wuModal.open({ 16 | backdrop: false, 17 | windowTemplateUrl:'weui/template/wu-window.html', 18 | template:'
', 19 | controller:['$scope', function ($scope) { 20 | $scope.btnGroups = config.btnGroups || [ 21 | { 22 | action: 'Cancel', 23 | buttons:[ 24 | { title: '取消', value: 'cancel'} 25 | ] 26 | } 27 | ]; 28 | 29 | $scope.triggerBtn = function(group, btn) { 30 | var action = group.action.toLowerCase(); 31 | if(action==='ok'){ 32 | $scope.$close(btn.value); 33 | } else { 34 | $scope.$dismiss(btn.value); 35 | } 36 | } 37 | }] 38 | }); 39 | } 40 | } 41 | }]; 42 | }]) 43 | .directive('wuActionSheetTemplate',['$q', function ($q) { 44 | return { 45 | restrict:'A', 46 | templateUrl:'weui/template/action-sheet/action-sheet.html', 47 | link: function (scope, element, attrs) { 48 | var mask = element.find('.weui-mask_transparent.actionsheet__mask'); 49 | var actionSheet = element.find('.weui-actionsheet'); 50 | 51 | /** 52 | * 打开初始化 53 | */ 54 | (function () { 55 | mask.show().addClass('actionsheet__mask_show').on('click',function () { 56 | closeActionSheetAnimate(actionSheet, mask).then(function () { 57 | scope.$dismiss('mask:click'); 58 | }) 59 | }); 60 | actionSheet.addClass('weui-actionsheet_toggle'); 61 | })(); 62 | 63 | /** 64 | * 点击按钮 65 | * @param group 66 | * @param btn 67 | */ 68 | scope.clickBtn = function(group, btn) { 69 | closeActionSheetAnimate(actionSheet, mask).then(function () { 70 | scope.triggerBtn(group, btn); 71 | }); 72 | }; 73 | 74 | /** 75 | * 关闭ActionSheet动画 76 | * @param actionSheet 77 | * @param mask 78 | * @returns {*} 79 | */ 80 | function closeActionSheetAnimate(actionSheet, mask) { 81 | return $q(function (resovle, reject) { 82 | actionSheet.removeClass('weui-actionsheet_toggle'); 83 | mask.removeClass('actionsheet__mask_show'); 84 | actionSheet.on('transitionend', function () { 85 | mask.hide(); 86 | resovle(); 87 | }).on('webkitTransitionEnd', function () { 88 | mask.hide(); 89 | resovle(); 90 | }) 91 | }); 92 | } 93 | } 94 | } 95 | }]) 96 | ; 97 | })(angular.module('ng.weui.actionsheet')); 98 | -------------------------------------------------------------------------------- /src/js/button.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 16/1/13. 3 | */ 4 | 5 | (function (app) { 6 | app.directive('wuClick',['$parse','$timeout','$rootScope',function ($parse,$timeout,$rootScope) { 7 | return { 8 | restrict:'EA', 9 | compile: function (element, attrs) { 10 | 11 | var wuClickFn = $parse(attrs['wuClick']); 12 | var wuIntervalFn = $parse(attrs['wuInterval'] || '300'); 13 | 14 | return function (scope, element, attrs) { 15 | var wuInterval = parseInt(wuIntervalFn(scope)); 16 | var isBusy = false; 17 | 18 | element.on('click', function(event) { 19 | if(!isBusy) { 20 | scope.$apply(function() { 21 | wuClickFn(scope, {$event:event}); 22 | }); 23 | 24 | element.attr('disabled','disabled').addClass('weui_btn_disabled'); 25 | isBusy = true; 26 | $timeout(function () { 27 | element.removeAttr('disabled').removeClass('weui_btn_disabled'); 28 | isBusy = false; 29 | },wuInterval); 30 | } 31 | 32 | }) 33 | }; 34 | } 35 | } 36 | }]) 37 | })(angular.module('ng.weui.button')); 38 | -------------------------------------------------------------------------------- /src/js/core.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 16/1/13. 3 | */ 4 | (function (app,window) { app 5 | /** 6 | * A helper, internal data structure that acts as a map but also allows getting / removing 7 | * elements in the LIFO order 8 | */ 9 | .factory('$$stackedMap', function() { 10 | return { 11 | createNew: function() { 12 | var stack = []; 13 | 14 | return { 15 | add: function(key, value) { 16 | stack.push({ 17 | key: key, 18 | value: value 19 | }); 20 | }, 21 | get: function(key) { 22 | for (var i = 0; i < stack.length; i++) { 23 | if (key === stack[i].key) { 24 | return stack[i]; 25 | } 26 | } 27 | }, 28 | keys: function() { 29 | var keys = []; 30 | for (var i = 0; i < stack.length; i++) { 31 | keys.push(stack[i].key); 32 | } 33 | return keys; 34 | }, 35 | top: function() { 36 | return stack[stack.length - 1]; 37 | }, 38 | remove: function(key) { 39 | var idx = -1; 40 | for (var i = 0; i < stack.length; i++) { 41 | if (key === stack[i].key) { 42 | idx = i; 43 | break; 44 | } 45 | } 46 | return stack.splice(idx, 1)[0]; 47 | }, 48 | removeTop: function() { 49 | return stack.splice(stack.length - 1, 1)[0]; 50 | }, 51 | length: function() { 52 | return stack.length; 53 | } 54 | }; 55 | } 56 | }; 57 | }) 58 | /** 59 | * A helper, internal data structure that stores all references attached to key 60 | */ 61 | .factory('$$multiMap', function() { 62 | return { 63 | createNew: function() { 64 | var map = {}; 65 | 66 | return { 67 | entries: function() { 68 | return Object.keys(map).map(function(key) { 69 | return { 70 | key: key, 71 | value: map[key] 72 | }; 73 | }); 74 | }, 75 | get: function(key) { 76 | return map[key]; 77 | }, 78 | hasKey: function(key) { 79 | return !!map[key]; 80 | }, 81 | keys: function() { 82 | return Object.keys(map); 83 | }, 84 | put: function(key, value) { 85 | if (!map[key]) { 86 | map[key] = []; 87 | } 88 | 89 | map[key].push(value); 90 | }, 91 | remove: function(key, value) { 92 | var values = map[key]; 93 | 94 | if (!values) { 95 | return; 96 | } 97 | 98 | var idx = values.indexOf(value); 99 | 100 | if (idx !== -1) { 101 | values.splice(idx, 1); 102 | } 103 | 104 | if (!values.length) { 105 | delete map[key]; 106 | } 107 | } 108 | }; 109 | } 110 | }; 111 | }) 112 | 113 | /** 114 | * Pluggable resolve mechanism for the modal resolve resolution 115 | * Supports UI Router's $resolve service 116 | */ 117 | .provider('$wuResolve', function() { 118 | var resolve = this; 119 | this.resolver = null; 120 | 121 | this.setResolver = function(resolver) { 122 | this.resolver = resolver; 123 | }; 124 | 125 | this.$get = ['$injector', '$q', function($injector, $q) { 126 | var resolver = resolve.resolver ? $injector.get(resolve.resolver) : null; 127 | return { 128 | resolve: function(invocables, locals, parent, self) { 129 | if (resolver) { 130 | return resolver.resolve(invocables, locals, parent, self); 131 | } 132 | 133 | var promises = []; 134 | 135 | angular.forEach(invocables, function(value) { 136 | if (angular.isFunction(value) || angular.isArray(value)) { 137 | promises.push($q.resolve($injector.invoke(value))); 138 | } else if (angular.isString(value)) { 139 | promises.push($q.resolve($injector.get(value))); 140 | } else { 141 | promises.push($q.resolve(value)); 142 | } 143 | }); 144 | 145 | return $q.all(promises).then(function(resolves) { 146 | var resolveObj = {}; 147 | var resolveIter = 0; 148 | angular.forEach(invocables, function(value, key) { 149 | resolveObj[key] = resolves[resolveIter++]; 150 | }); 151 | 152 | return resolveObj; 153 | }); 154 | } 155 | }; 156 | }]; 157 | }) 158 | 159 | /** 160 | * A helper directive for the $modal service. It creates a backdrop element. 161 | *//* 162 | .directive('wuModalBackdrop', ['$animateCss', '$injector', '$wuModalStack', 163 | function($animateCss, $injector, $modalStack) { 164 | return { 165 | replace: true, 166 | templateUrl: 'wu/template/modal/backdrop.html', 167 | compile: function(tElement, tAttrs) { 168 | tElement.addClass(tAttrs.backdropClass); 169 | return linkFn; 170 | } 171 | }; 172 | 173 | function linkFn(scope, element, attrs) { 174 | if (attrs.modalInClass) { 175 | $animateCss(element, { 176 | addClass: attrs.modalInClass 177 | }).start(); 178 | 179 | scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { 180 | var done = setIsAsync(); 181 | if (scope.modalOptions.animation) { 182 | $animateCss(element, { 183 | removeClass: attrs.modalInClass 184 | }).start().then(done); 185 | } else { 186 | done(); 187 | } 188 | }); 189 | } 190 | } 191 | }]) 192 | 193 | .directive('wuModalWindow', ['$wuModalStack', '$q', '$animate', '$animateCss', '$document', 194 | function($modalStack, $q, $animate, $animateCss, $document) { 195 | return { 196 | scope: { 197 | index: '@' 198 | }, 199 | replace: true, 200 | transclude: true, 201 | templateUrl: function(tElement, tAttrs) { 202 | return tAttrs.templateUrl || 'wu/template/modal/window.html'; 203 | }, 204 | link: function(scope, element, attrs) { 205 | element.addClass(attrs.windowClass || ''); 206 | element.addClass(attrs.windowTopClass || ''); 207 | scope.size = attrs.size; 208 | 209 | scope.close = function(evt) { 210 | var modal = $modalStack.getTop(); 211 | if (modal && modal.value.backdrop && 212 | modal.value.backdrop !== 'static' && 213 | evt.target === evt.currentTarget) { 214 | evt.preventDefault(); 215 | evt.stopPropagation(); 216 | $modalStack.dismiss(modal.key, 'backdrop click'); 217 | } 218 | }; 219 | 220 | // moved from template to fix issue #2280 221 | element.on('click', scope.close); 222 | 223 | // This property is only added to the scope for the purpose of detecting when this directive is rendered. 224 | // We can detect that by using this property in the template associated with this directive and then use 225 | // {@link Attribute#$observe} on it. For more details please see {@link TableColumnResize}. 226 | scope.$isRendered = true; 227 | 228 | // Deferred object that will be resolved when this modal is render. 229 | var modalRenderDeferObj = $q.defer(); 230 | // Observe function will be called on next digest cycle after compilation, ensuring that the DOM is ready. 231 | // In order to use this way of finding whether DOM is ready, we need to observe a scope property used in modal's template. 232 | attrs.$observe('modalRender', function(value) { 233 | if (value === 'true') { 234 | modalRenderDeferObj.resolve(); 235 | } 236 | }); 237 | 238 | modalRenderDeferObj.promise.then(function() { 239 | var animationPromise = null; 240 | 241 | if (attrs.modalInClass) { 242 | animationPromise = $animateCss(element, { 243 | addClass: attrs.modalInClass 244 | }).start(); 245 | 246 | scope.$on($modalStack.NOW_CLOSING_EVENT, function(e, setIsAsync) { 247 | var done = setIsAsync(); 248 | if ($animateCss) { 249 | $animateCss(element, { 250 | removeClass: attrs.modalInClass 251 | }).start().then(done); 252 | } else { 253 | $animate.removeClass(element, attrs.modalInClass).then(done); 254 | } 255 | }); 256 | } 257 | 258 | 259 | $q.when(animationPromise).then(function() { 260 | /!** 261 | * If something within the freshly-opened modal already has focus (perhaps via a 262 | * directive that causes focus). then no need to try and focus anything. 263 | *!/ 264 | if (!($document[0].activeElement && element[0].contains($document[0].activeElement))) { 265 | var inputWithAutofocus = element[0].querySelector('[autofocus]'); 266 | /!** 267 | * Auto-focusing of a freshly-opened modal element causes any child elements 268 | * with the autofocus attribute to lose focus. This is an issue on touch 269 | * based devices which will show and then hide the onscreen keyboard. 270 | * Attempts to refocus the autofocus element via JavaScript will not reopen 271 | * the onscreen keyboard. Fixed by updated the focusing logic to only autofocus 272 | * the modal element if the modal does not contain an autofocus element. 273 | *!/ 274 | if (inputWithAutofocus) { 275 | inputWithAutofocus.focus(); 276 | } else { 277 | element[0].focus(); 278 | } 279 | } 280 | }); 281 | 282 | // Notify {@link $modalStack} that modal is rendered. 283 | var modal = $modalStack.getTop(); 284 | if (modal) { 285 | $modalStack.modalRendered(modal.key); 286 | } 287 | }); 288 | } 289 | }; 290 | }]) 291 | 292 | .directive('wuModalAnimationClass', function() { 293 | return { 294 | compile: function(tElement, tAttrs) { 295 | if (tAttrs.modalAnimation) { 296 | tElement.addClass(tAttrs.wuModalAnimationClass); 297 | } 298 | } 299 | }; 300 | }) 301 | */ 302 | .directive('wuModalTransclude', function() { 303 | return { 304 | link: function(scope, element, attrs, controller, transclude) { 305 | transclude(scope.$parent, function(clone) { 306 | element.empty(); 307 | element.append(clone); 308 | }); 309 | } 310 | }; 311 | }) 312 | 313 | .factory('$wuModalStack', ['$animate', '$animateCss', '$document', 314 | '$compile', '$rootScope', '$q', '$$multiMap', '$$stackedMap', 315 | function($animate, $animateCss, $document, $compile, $rootScope, $q, $$multiMap, $$stackedMap) { 316 | var OPENED_MODAL_CLASS = 'modal-open'; 317 | 318 | var backdropDomEl, backdropScope; 319 | var openedWindows = $$stackedMap.createNew(); 320 | var openedClasses = $$multiMap.createNew(); 321 | var $modalStack = { 322 | NOW_CLOSING_EVENT: 'modal.stack.now-closing' 323 | }; 324 | 325 | //Modal focus behavior 326 | var focusableElementList; 327 | var focusIndex = 0; 328 | var tababbleSelector = 'a[href], area[href], input:not([disabled]), ' + 329 | 'button:not([disabled]),select:not([disabled]), textarea:not([disabled]), ' + 330 | 'iframe, object, embed, *[tabindex], *[contenteditable=true]'; 331 | 332 | function backdropIndex() { 333 | var topBackdropIndex = -1; 334 | var opened = openedWindows.keys(); 335 | for (var i = 0; i < opened.length; i++) { 336 | if (openedWindows.get(opened[i]).value.backdrop) { 337 | topBackdropIndex = i; 338 | } 339 | } 340 | return topBackdropIndex; 341 | } 342 | 343 | $rootScope.$watch(backdropIndex, function(newBackdropIndex) { 344 | if (backdropScope) { 345 | backdropScope.index = newBackdropIndex; 346 | } 347 | }); 348 | 349 | function removeModalWindow(modalInstance, elementToReceiveFocus) { 350 | var modalWindow = openedWindows.get(modalInstance).value; 351 | var appendToElement = modalWindow.appendTo; 352 | 353 | //clean up the stack 354 | openedWindows.remove(modalInstance); 355 | 356 | removeAfterAnimate(modalWindow.modalDomEl, modalWindow.modalScope, function() { 357 | var modalBodyClass = modalWindow.openedClass || OPENED_MODAL_CLASS; 358 | openedClasses.remove(modalBodyClass, modalInstance); 359 | appendToElement.toggleClass(modalBodyClass, openedClasses.hasKey(modalBodyClass)); 360 | toggleTopWindowClass(true); 361 | }); 362 | checkRemoveBackdrop(); 363 | 364 | //move focus to specified element if available, or else to body 365 | if (elementToReceiveFocus && elementToReceiveFocus.focus) { 366 | elementToReceiveFocus.focus(); 367 | } else if (appendToElement.focus) { 368 | appendToElement.focus(); 369 | } 370 | } 371 | 372 | // Add or remove "windowTopClass" from the top window in the stack 373 | function toggleTopWindowClass(toggleSwitch) { 374 | var modalWindow; 375 | 376 | if (openedWindows.length() > 0) { 377 | modalWindow = openedWindows.top().value; 378 | modalWindow.modalDomEl.toggleClass(modalWindow.windowTopClass || '', toggleSwitch); 379 | } 380 | } 381 | 382 | function checkRemoveBackdrop() { 383 | //remove backdrop if no longer needed 384 | if (backdropDomEl && backdropIndex() === -1) { 385 | var backdropScopeRef = backdropScope; 386 | removeAfterAnimate(backdropDomEl, backdropScope, function() { 387 | backdropScopeRef = null; 388 | }); 389 | backdropDomEl = undefined; 390 | backdropScope = undefined; 391 | } 392 | } 393 | 394 | function removeAfterAnimate(domEl, scope, done, closedDeferred) { 395 | var asyncDeferred; 396 | var asyncPromise = null; 397 | var setIsAsync = function() { 398 | if (!asyncDeferred) { 399 | asyncDeferred = $q.defer(); 400 | asyncPromise = asyncDeferred.promise; 401 | } 402 | 403 | return function asyncDone() { 404 | asyncDeferred.resolve(); 405 | }; 406 | }; 407 | scope.$broadcast($modalStack.NOW_CLOSING_EVENT, setIsAsync); 408 | 409 | // Note that it's intentional that asyncPromise might be null. 410 | // That's when setIsAsync has not been called during the 411 | // NOW_CLOSING_EVENT broadcast. 412 | return $q.when(asyncPromise).then(afterAnimating); 413 | 414 | function afterAnimating() { 415 | if (afterAnimating.done) { 416 | return; 417 | } 418 | afterAnimating.done = true; 419 | 420 | $animateCss(domEl, { 421 | event: 'leave' 422 | }).start().then(function() { 423 | domEl.remove(); 424 | if (closedDeferred) { 425 | closedDeferred.resolve(); 426 | } 427 | }); 428 | 429 | scope.$destroy(); 430 | if (done) { 431 | done(); 432 | } 433 | } 434 | } 435 | 436 | $document.on('keydown', keydownListener); 437 | 438 | $rootScope.$on('$destroy', function() { 439 | $document.off('keydown', keydownListener); 440 | }); 441 | 442 | function keydownListener(evt) { 443 | if (evt.isDefaultPrevented()) { 444 | return evt; 445 | } 446 | 447 | var modal = openedWindows.top(); 448 | if (modal) { 449 | switch (evt.which) { 450 | case 27: { 451 | if (modal.value.keyboard) { 452 | evt.preventDefault(); 453 | $rootScope.$apply(function() { 454 | $modalStack.dismiss(modal.key, 'escape key press'); 455 | }); 456 | } 457 | break; 458 | } 459 | case 9: { 460 | $modalStack.loadFocusElementList(modal); 461 | var focusChanged = false; 462 | if (evt.shiftKey) { 463 | if ($modalStack.isFocusInFirstItem(evt)) { 464 | focusChanged = $modalStack.focusLastFocusableElement(); 465 | } 466 | } else { 467 | if ($modalStack.isFocusInLastItem(evt)) { 468 | focusChanged = $modalStack.focusFirstFocusableElement(); 469 | } 470 | } 471 | 472 | if (focusChanged) { 473 | evt.preventDefault(); 474 | evt.stopPropagation(); 475 | } 476 | break; 477 | } 478 | } 479 | } 480 | } 481 | 482 | $modalStack.open = function(modalInstance, modal) { 483 | var modalOpener = $document[0].activeElement, 484 | modalBodyClass = modal.openedClass || OPENED_MODAL_CLASS; 485 | 486 | toggleTopWindowClass(false); 487 | 488 | openedWindows.add(modalInstance, { 489 | deferred: modal.deferred, 490 | renderDeferred: modal.renderDeferred, 491 | closedDeferred: modal.closedDeferred, 492 | modalScope: modal.scope, 493 | backdrop: modal.backdrop, 494 | keyboard: modal.keyboard, 495 | openedClass: modal.openedClass, 496 | windowTopClass: modal.windowTopClass, 497 | animation: modal.animation, 498 | appendTo: modal.appendTo 499 | }); 500 | 501 | openedClasses.put(modalBodyClass, modalInstance); 502 | 503 | var appendToElement = modal.appendTo, 504 | currBackdropIndex = backdropIndex(); 505 | 506 | if (!appendToElement.length) { 507 | throw new Error('appendTo element not found. Make sure that the element passed is in DOM.'); 508 | } 509 | 510 | if (currBackdropIndex >= 0 && !backdropDomEl) { 511 | backdropScope = $rootScope.$new(true); 512 | backdropScope.modalOptions = modal; 513 | backdropScope.index = currBackdropIndex; 514 | backdropDomEl = angular.element('
'); 515 | backdropDomEl.attr('backdrop-class', modal.backdropClass); 516 | if (modal.animation) { 517 | backdropDomEl.attr('modal-animation', 'true'); 518 | } 519 | $compile(backdropDomEl)(backdropScope); 520 | $animate.enter(backdropDomEl, appendToElement); 521 | } 522 | 523 | var angularDomEl = angular.element('
'); 524 | angularDomEl.attr({ 525 | 'template-url': modal.windowTemplateUrl, 526 | 'window-class': modal.windowClass, 527 | 'window-top-class': modal.windowTopClass, 528 | 'size': modal.size, 529 | 'index': openedWindows.length() - 1, 530 | 'animate': 'animate' 531 | }).html(modal.content); 532 | if (modal.animation) { 533 | angularDomEl.attr('modal-animation', 'true'); 534 | } 535 | 536 | $animate.enter(angularDomEl, appendToElement) 537 | .then(function() { 538 | $compile(angularDomEl)(modal.scope); 539 | $animate.addClass(appendToElement, modalBodyClass); 540 | }); 541 | 542 | openedWindows.top().value.modalDomEl = angularDomEl; 543 | openedWindows.top().value.modalOpener = modalOpener; 544 | 545 | $modalStack.clearFocusListCache(); 546 | }; 547 | 548 | function broadcastClosing(modalWindow, resultOrReason, closing) { 549 | return !modalWindow.value.modalScope.$broadcast('modal.closing', resultOrReason, closing).defaultPrevented; 550 | } 551 | 552 | $modalStack.close = function(modalInstance, result) { 553 | var modalWindow = openedWindows.get(modalInstance); 554 | if (modalWindow && broadcastClosing(modalWindow, result, true)) { 555 | modalWindow.value.modalScope.$$wuDestructionScheduled = true; 556 | modalWindow.value.deferred.resolve(result); 557 | removeModalWindow(modalInstance, modalWindow.value.modalOpener); 558 | return true; 559 | } 560 | return !modalWindow; 561 | }; 562 | 563 | $modalStack.dismiss = function(modalInstance, reason) { 564 | var modalWindow = openedWindows.get(modalInstance); 565 | if (modalWindow && broadcastClosing(modalWindow, reason, false)) { 566 | modalWindow.value.modalScope.$$wuDestructionScheduled = true; 567 | modalWindow.value.deferred.reject(reason); 568 | removeModalWindow(modalInstance, modalWindow.value.modalOpener); 569 | return true; 570 | } 571 | return !modalWindow; 572 | }; 573 | 574 | $modalStack.dismissAll = function(reason) { 575 | var topModal = this.getTop(); 576 | while (topModal && this.dismiss(topModal.key, reason)) { 577 | topModal = this.getTop(); 578 | } 579 | }; 580 | 581 | $modalStack.getTop = function() { 582 | return openedWindows.top(); 583 | }; 584 | 585 | $modalStack.modalRendered = function(modalInstance) { 586 | var modalWindow = openedWindows.get(modalInstance); 587 | if (modalWindow) { 588 | modalWindow.value.renderDeferred.resolve(); 589 | } 590 | }; 591 | 592 | $modalStack.focusFirstFocusableElement = function() { 593 | if (focusableElementList.length > 0) { 594 | focusableElementList[0].focus(); 595 | return true; 596 | } 597 | return false; 598 | }; 599 | $modalStack.focusLastFocusableElement = function() { 600 | if (focusableElementList.length > 0) { 601 | focusableElementList[focusableElementList.length - 1].focus(); 602 | return true; 603 | } 604 | return false; 605 | }; 606 | 607 | $modalStack.isFocusInFirstItem = function(evt) { 608 | if (focusableElementList.length > 0) { 609 | return (evt.target || evt.srcElement) === focusableElementList[0]; 610 | } 611 | return false; 612 | }; 613 | 614 | $modalStack.isFocusInLastItem = function(evt) { 615 | if (focusableElementList.length > 0) { 616 | return (evt.target || evt.srcElement) === focusableElementList[focusableElementList.length - 1]; 617 | } 618 | return false; 619 | }; 620 | 621 | $modalStack.clearFocusListCache = function() { 622 | focusableElementList = []; 623 | focusIndex = 0; 624 | }; 625 | 626 | $modalStack.loadFocusElementList = function(modalWindow) { 627 | if (focusableElementList === undefined || !focusableElementList.length) { 628 | if (modalWindow) { 629 | var modalDomE1 = modalWindow.value.modalDomEl; 630 | if (modalDomE1 && modalDomE1.length) { 631 | focusableElementList = modalDomE1[0].querySelectorAll(tababbleSelector); 632 | } 633 | } 634 | } 635 | }; 636 | 637 | return $modalStack; 638 | }]) 639 | 640 | .provider('$wuModal', function() { 641 | var $modalProvider = { 642 | options: { 643 | animation: true, 644 | backdrop: true, //can also be false or 'static' 645 | keyboard: true 646 | }, 647 | $get: ['$rootScope', '$q', '$document', '$templateRequest', '$controller', '$wuResolve', '$wuModalStack', 648 | function ($rootScope, $q, $document, $templateRequest, $controller, $wuResolve, $modalStack) { 649 | var $modal = {}; 650 | 651 | function getTemplatePromise(options) { 652 | return options.template ? $q.when(options.template) : 653 | $templateRequest(angular.isFunction(options.templateUrl) ? 654 | options.templateUrl() : options.templateUrl); 655 | } 656 | 657 | var promiseChain = null; 658 | $modal.getPromiseChain = function() { 659 | return promiseChain; 660 | }; 661 | 662 | $modal.open = function(modalOptions) { 663 | var modalResultDeferred = $q.defer(); 664 | var modalOpenedDeferred = $q.defer(); 665 | var modalClosedDeferred = $q.defer(); 666 | var modalRenderDeferred = $q.defer(); 667 | 668 | //prepare an instance of a modal to be injected into controllers and 669 | // returned to a caller 670 | var modalInstance = { 671 | result: modalResultDeferred.promise, 672 | opened: modalOpenedDeferred.promise, 673 | closed: modalClosedDeferred.promise, 674 | rendered: modalRenderDeferred.promise, 675 | close: function (result) { 676 | return $modalStack.close(modalInstance, result); 677 | }, 678 | dismiss: function (reason) { 679 | return $modalStack.dismiss(modalInstance, reason); 680 | } 681 | }; 682 | 683 | //merge and clean up options 684 | modalOptions = angular.extend({}, $modalProvider.options, modalOptions); 685 | modalOptions.resolve = modalOptions.resolve || {}; 686 | modalOptions.appendTo = modalOptions.appendTo || $document.find('body').eq(0); 687 | 688 | //verify options 689 | if (!modalOptions.template && !modalOptions.templateUrl) { 690 | throw new Error('One of template or templateUrl options is required.'); 691 | } 692 | 693 | var templateAndResolvePromise = 694 | $q.all([getTemplatePromise(modalOptions), $wuResolve.resolve(modalOptions.resolve, {}, null, null)]); 695 | 696 | function resolveWithTemplate() { 697 | return templateAndResolvePromise; 698 | } 699 | 700 | // Wait for the resolution of the existing promise chain. 701 | // Then switch to our own combined promise dependency (regardless of how 702 | // the previous modal fared). Then add to $modalStack and resolve opened. 703 | // Finally clean up the chain variable if no subsequent modal has 704 | // overwritten it. 705 | var samePromise; 706 | samePromise = promiseChain = $q.all([promiseChain]) 707 | .then(resolveWithTemplate, resolveWithTemplate) 708 | .then(function resolveSuccess(tplAndVars) { 709 | var providedScope = modalOptions.scope || $rootScope; 710 | 711 | var modalScope = providedScope.$new(); 712 | modalScope.$close = modalInstance.close; 713 | modalScope.$dismiss = modalInstance.dismiss; 714 | 715 | modalScope.$on('$destroy', function() { 716 | if (!modalScope.$$wuDestructionScheduled) { 717 | modalScope.$dismiss('$wuUnscheduledDestruction'); 718 | } 719 | }); 720 | 721 | var ctrlInstance, ctrlLocals = {}; 722 | 723 | //controllers 724 | if (modalOptions.controller) { 725 | ctrlLocals.$scope = modalScope; 726 | ctrlLocals.$wuModalInstance = modalInstance; 727 | angular.forEach(tplAndVars[1], function(value, key) { 728 | ctrlLocals[key] = value; 729 | }); 730 | 731 | ctrlInstance = $controller(modalOptions.controller, ctrlLocals); 732 | if (modalOptions.controllerAs) { 733 | if (modalOptions.bindToController) { 734 | ctrlInstance.$close = modalScope.$close; 735 | ctrlInstance.$dismiss = modalScope.$dismiss; 736 | angular.extend(ctrlInstance, providedScope); 737 | } 738 | 739 | modalScope[modalOptions.controllerAs] = ctrlInstance; 740 | } 741 | } 742 | 743 | $modalStack.open(modalInstance, { 744 | scope: modalScope, 745 | deferred: modalResultDeferred, 746 | renderDeferred: modalRenderDeferred, 747 | closedDeferred: modalClosedDeferred, 748 | content: tplAndVars[0], 749 | animation: modalOptions.animation, 750 | backdrop: modalOptions.backdrop, 751 | keyboard: modalOptions.keyboard, 752 | backdropClass: modalOptions.backdropClass, 753 | windowTopClass: modalOptions.windowTopClass, 754 | windowClass: modalOptions.windowClass, 755 | windowTemplateUrl: modalOptions.windowTemplateUrl, 756 | size: modalOptions.size, 757 | openedClass: modalOptions.openedClass, 758 | appendTo: modalOptions.appendTo 759 | }); 760 | modalOpenedDeferred.resolve(true); 761 | 762 | }, function resolveError(reason) { 763 | modalOpenedDeferred.reject(reason); 764 | modalResultDeferred.reject(reason); 765 | })['finally'](function() { 766 | if (promiseChain === samePromise) { 767 | promiseChain = null; 768 | } 769 | }); 770 | 771 | return modalInstance; 772 | }; 773 | 774 | return $modal; 775 | } 776 | ] 777 | }; 778 | 779 | return $modalProvider; 780 | }); 781 | 782 | /** 783 | * 客户端检测代码 784 | */ 785 | window.weui_client_browser_checker = (function () { 786 | // 呈现引擎 787 | var engine = { 788 | ie: 0, 789 | gecko: 0, 790 | webkit: 0, 791 | khtml: 0, 792 | opera: 0, 793 | // 完整的版本号 794 | ver: null 795 | }; 796 | 797 | // 浏览器 798 | var browser = { 799 | // 主要浏览器 800 | ie: 0, 801 | firefox: 0, 802 | safari: 0, 803 | konq: 0, 804 | opera: 0, 805 | chrome: 0, 806 | wx: 0, 807 | wxpc: 0, 808 | // 具体的版本号 809 | ver: null 810 | }; 811 | 812 | // 平台、设备和操作系统 813 | var system = { 814 | win: false, 815 | mac: false, 816 | x11: false, 817 | 818 | // 移动设备 819 | iphone: false, 820 | ipod: false, 821 | ipad: false, 822 | ios: false, 823 | android: false, 824 | nokiaN: false, 825 | winMobile: false, 826 | 827 | //游戏系统 828 | wii: false, 829 | ps: false 830 | }; 831 | 832 | // 检测呈现引擎和浏览器 833 | var ua = navigator.userAgent; 834 | if (window.opera) { 835 | engine.ver = browser.ver = window.opera.version(); 836 | engine.opera = browser.opera = parseFloat(engine.ver); 837 | } else if (/AppleWebKit\/(\S+)/.test(ua)) { 838 | engine.ver = RegExp["$1"]; 839 | engine.webkit = parseFloat(engine.ver); 840 | 841 | // 确定是 chrome 还是 safari 842 | if (/Chrome\/(\S+)/.test(ua)) { 843 | browser.ver = RegExp["$1"]; 844 | browser.chrome = parseFloat(browser.ver); 845 | } else if (/Version\/(\S+)/.test(ua)) { 846 | browser.ver = RegExp["$1"]; 847 | browser.safari = parseFloat(browser.ver); 848 | } else { 849 | // 近似地确定版本号 850 | var safariVersion = 1; 851 | if (engine.webkit < 100) { 852 | safariVersion = 1; 853 | } else if (engine.webkit < 312) { 854 | safariVersion = 1.2; 855 | } else if (engine.webkit < 412) { 856 | safariVersion = 1.3; 857 | } else { 858 | safariVersion = 2; 859 | } 860 | browser.safari = browser.ver = safariVersion; 861 | } 862 | } else if (/KHTML\/(\S+)/.test(ua) || /Konqueror\/([^;]+])/.test(ua)) { 863 | engine.ver = browser.ver = RegExp["$1"]; 864 | engine.khtml = browser.konq = parseFloat(engine.ver); 865 | } else if (/rv:([^\)]+)\) Gecko\/\d{8}/.test(ua)) { 866 | engine.ver = RegExp["$1"]; 867 | browser.gecko = parseFloat(engine.ver); 868 | 869 | // 确定是否是firefox 870 | if (/Firefox\/(\S+)/.test(ua)) { 871 | browser.ver = RegExp["$1"]; 872 | browser.firefox = parseFloat(browser.ver); 873 | } 874 | } else if (/MSIE ([^;]+)/.test(ua)) { 875 | engine.ver = browser.ver = RegExp["$1"]; 876 | engine.ie = browser.ie = parseFloat(engine.ver); 877 | } 878 | 879 | // 微信检查 880 | if (/MicroMessenger\/([\d\.]+)/i.test(ua)) { 881 | browser.ver = RegExp["$1"]; 882 | browser.wx = 'micromessenger'; 883 | 884 | browser.wxpc = /WindowsWechat/i.test(ua); 885 | } 886 | 887 | // 坚持浏览器 888 | browser.ie = engine.ie; 889 | browser.opera = engine.opera; 890 | 891 | // 检测平台 892 | var p = navigator.platform; 893 | system.win = p.indexOf("Win") >= 0; 894 | system.mac = p.indexOf("Mac") >= 0; 895 | system.x11 = (p == "X11") || (p.indexOf("Linux") == 0); 896 | 897 | // 检测 windows 操作版本 898 | if (system.win) { 899 | if (/Win(?:dows )?([^do]{2})\s?(\d+\.\d+)?/.test(ua)) { 900 | if (RegExp["$1"] == "NT") { 901 | switch (RegExp["$2"]) { 902 | case "5.0": 903 | system.win = "2000"; 904 | break; 905 | case "5.1": 906 | system.win = "XP"; 907 | break; 908 | case "6.0": 909 | system.win = "vista"; 910 | break; 911 | case "6.1": 912 | system.win = "7"; 913 | break; 914 | default : 915 | system.win = "NT"; 916 | break; 917 | } 918 | } else if (RegExp["$1"] == "9x") { 919 | system.win = "ME"; 920 | } else { 921 | system.win = RegExp["$1"]; 922 | } 923 | } 924 | } 925 | 926 | // 检测移动设备 927 | system.iphone = ua.indexOf("iPhone") > -1; 928 | system.ipod = ua.indexOf("iPod") > -1; 929 | system.ipad = ua.indexOf("iPad") > -1; 930 | system.nokiaN = ua.indexOf("NokinaN") > -1; 931 | 932 | // windows mobile 933 | if (system.win == "CE") { 934 | system.winMobile = system.win; 935 | } else if (system.win == "Ph") { 936 | if (/Window Phone OS (\d+.\d+)/.test(ua)) { 937 | system.win = "Phone"; 938 | system.winMobile = parseFloat(RegExp["$1"]); 939 | } 940 | } 941 | 942 | // 检测 iOS 版本 943 | if (system.iphone && ua.indexOf("Mobile") > -1) { 944 | if (/CPU (?:iPhone)?[ ]?OS (\d+_\d+)/.test(ua)) { 945 | system.ios = parseFloat(RegExp.$1.replace("_", ".")); 946 | } else { 947 | system.ios = 2; // 不能真正检测出来,所以只能猜测 948 | } 949 | } 950 | 951 | // 检测 android 版本 952 | if (/Android (\d+\.\d+)/.test(ua)) { 953 | system.android = parseFloat(RegExp.$1); 954 | } 955 | 956 | // 游戏系统 957 | system.wii = ua.indexOf("Wii") > -1; 958 | system.ps = /playstation/i.test(ua); 959 | 960 | // 返回对象 961 | return { 962 | engine: engine, 963 | browser: browser, 964 | system: system 965 | } 966 | })(); 967 | app.provider('WuBrowserChecker', [function () { 968 | var self = this; 969 | self.$get = [function () { 970 | return window.weui_client_browser_checker; 971 | }] 972 | }]); 973 | 974 | app.provider('IdWorkerFactory',[function () { 975 | var factories = {}; 976 | this.new = function IdWorkerFactory(prefix) { 977 | if(!factories.hasOwnProperty(prefix)) { 978 | factories[prefix] = (function (p) { 979 | var count = 0; 980 | return function () { 981 | return p+'_'+(count++); 982 | } 983 | })(prefix); 984 | } 985 | return factories[prefix]; 986 | }; 987 | 988 | this.$get = [function() { 989 | return this; 990 | }] 991 | }]) 992 | 993 | })(angular.module('ng.weui.core'), window); 994 | -------------------------------------------------------------------------------- /src/js/form.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 常用form组件封装,包含表单验证 3 | */ 4 | (function (app) { 5 | // input-text 6 | // input-textarea 7 | // input-file 8 | // input-image 9 | // input-date 10 | // input-map 11 | // input-address 12 | // input-phone 13 | // input-email 14 | // input-number 15 | // input-search 16 | // input-select 17 | // input-checkbox 18 | // input-radio 19 | // input-switch 20 | /** 21 | * TODO 还不知道是否必要 form 组件 22 | */ 23 | app.directive('inputTextarea',[function () { 24 | 25 | return { 26 | restrict:'EA', 27 | replace: true, 28 | templateUrl:'weui/template/form/input-textarea.html', 29 | require:'ngModel', 30 | link: function(scope, element, attrs, ngModelCtrl) { 31 | ngModelCtrl.$render = function() { 32 | console.log() 33 | } 34 | } 35 | } 36 | }]); 37 | 38 | /** 39 | * 微信上传图片 40 | * TODO 需要识别微信手机端和微信pc端,需要微信jssdk支持 41 | */ 42 | app.directive('inputImage', [function () { 43 | return { 44 | restrict:'EA', 45 | replace: true, 46 | templateUrl:'weui/template/form/input-image.html', 47 | require:'ngModel', 48 | link: function(scope, element, attrs, ngModelCtrl) { 49 | ngModelCtrl.$render = function() { 50 | console.log() 51 | } 52 | } 53 | } 54 | }]) 55 | })(angular.module('ng.weui.form')); 56 | -------------------------------------------------------------------------------- /src/js/gallery.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @Date 16/10/6 4 | * @User three 5 | */ 6 | 7 | (function (app) { 8 | /** 9 | * 调用微信js api 演示图片预览 10 | */ 11 | app.factory('PreviewImages', ['WuWxJsSdk', function (WuWxJsSdk) { 12 | return { 13 | show: function (current, imgList) { 14 | WuWxJsSdk.previewImage({ 15 | current: current, 16 | urls: imgList 17 | }); 18 | } 19 | } 20 | }]); 21 | /** 22 | * 调用微信js api 演示图片预览指令 23 | */ 24 | app.directive('previewImages', ['PreviewImages', function (PreviewImages) { 25 | return { 26 | restrict: 'AE', 27 | link: function (scope, element, attrs) { 28 | var box = element; 29 | var selector = attrs.preview? attrs.preview : 'img'; 30 | var attrName = attrs.attrName? attrs.attrName : 'src'; 31 | 32 | element.on('click', selector, function (e) { 33 | var src = $(this), 34 | imgList = []; 35 | box.find(selector).each(function (index,item) { 36 | imgList.push(item.attr(attrName)); 37 | }); 38 | 39 | PreviewImages.show(src.attr(attrName), imgList); 40 | 41 | e.preventDefault(); 42 | e.stopPropagation(); 43 | return false; 44 | }); 45 | } 46 | } 47 | }]); 48 | 49 | /** 50 | * h5 实现预览功能 51 | */ 52 | app.directive('gallery', ['$timeout','IdWorkerFactory', function ($timeout,IdWorkerFactory) { 53 | 54 | var galleryIdWorker = IdWorkerFactory.new('weui-gallery_swiper'); 55 | 56 | return { 57 | restrict: 'EA', 58 | //replace: true, 59 | templateUrl: 'weui/template/gallery/gallery.html', 60 | scope: { 61 | images: "=" 62 | }, 63 | link: function (scope, element, attrs) { 64 | 65 | var galleryId = galleryIdWorker(); 66 | element.attr("id", galleryId); 67 | element.addClass("weui-gallery"); 68 | 69 | element.show(); 70 | //scope.clickElement = function () { 71 | // element.hide(); 72 | //}; 73 | 74 | ///** 75 | // * 用户操作回调 76 | // */ 77 | //scope.clickBtn = function (e) { 78 | // scope.action && scope.action({ 79 | // image: scope.image 80 | // }); 81 | // e.preventDefault(); 82 | //}; 83 | 84 | /** 85 | * 显示缩略图 86 | * @type {boolean} 87 | */ 88 | scope.showThumb = false; 89 | if(angular.isArray(scope.images) && scope.images.length>0) { 90 | 91 | if(scope.images[0].hasOwnProperty('thumb')) { 92 | scope.showThumb = true; 93 | } 94 | 95 | initSwiper(); 96 | } 97 | 98 | scope.imageStyle = function (image) { 99 | return { 100 | 'background-image': 'url('+image.url+')' 101 | } 102 | }; 103 | 104 | function initSwiper() { 105 | 106 | $timeout(function () { 107 | console.log('#'+galleryId+' .swiper-images'); 108 | 109 | var galleryTop = new Swiper('#'+galleryId+' .swiper-images', { 110 | nextButton: '.swiper-button-next', 111 | prevButton: '.swiper-button-prev', 112 | spaceBetween: 10, 113 | effect: 'coverflow', 114 | grabCursor: true, 115 | centeredSlides: true, 116 | slidesPerView: 'auto', 117 | coverflow: { 118 | rotate: 50, 119 | stretch: 0, 120 | depth: 100, 121 | modifier: 1, 122 | slideShadows : true 123 | } 124 | }); 125 | 126 | if(scope.showThumb) { 127 | var galleryThumbs = new Swiper('#'+galleryId+' .gallery-thumbs', { 128 | spaceBetween: 10, 129 | centeredSlides: true, 130 | slidesPerView: 'auto', 131 | touchRatio: 0.2, 132 | slideToClickedSlide: true 133 | }); 134 | galleryTop.params.control = galleryThumbs; 135 | galleryThumbs.params.control = galleryTop; 136 | } 137 | 138 | },10) 139 | } 140 | 141 | } 142 | } 143 | }]) 144 | })(angular.module('ng.weui.gallery')); 145 | 146 | -------------------------------------------------------------------------------- /src/js/loading.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @Date 16/10/6 4 | * @User three 5 | */ 6 | 7 | (function(app){ 8 | app.directive('loadingEnable', [function () { 9 | return { 10 | restrict: 'A', 11 | replace:true, 12 | templateUrl: 'weui/template/loading/loading.html', 13 | transclude:true, 14 | link: function ($scope, $element, $attrs) { 15 | 16 | } 17 | } 18 | }]) 19 | })(angular.module('ng.weui.loading'), window); -------------------------------------------------------------------------------- /src/js/module.js: -------------------------------------------------------------------------------- 1 | 2 | 'use strict'; 3 | angular.module('ng.weui.core',[]); 4 | 5 | /** 6 | * 企业号/服务号jssdk封装 7 | */ 8 | angular.module('ng.weui.jssdk',[]); 9 | /** 10 | * swiper 封装 11 | */ 12 | angular.module('ng.weui.swiper', ['ng.weui.core']); 13 | 14 | angular.module('ng.weui.button',[]); 15 | angular.module('ng.weui.progress',[]); 16 | angular.module('ng.weui.dialog',['ng.weui.core']); 17 | angular.module('ng.weui.actionsheet',['ng.weui.core']); 18 | angular.module('ng.weui.toast',['ng.weui.core']); 19 | angular.module('ng.weui.form',['ng.weui.core']); 20 | angular.module('ng.weui.gallery',['ng.weui.core', 'ng.weui.swiper']); 21 | angular.module('ng.weui.loading',['ng.weui.core']); 22 | angular.module('ng.weui',[ 23 | 'ng.weui.core', 24 | 'ng.weui.button', 25 | 'ng.weui.actionsheet', 26 | 'ng.weui.dialog', 27 | 'ng.weui.toast', 28 | 'ng.weui.form', 29 | 'ng.weui.gallery', 30 | 'ng.weui.loading', 31 | 'ng.weui.progress' 32 | ]); 33 | -------------------------------------------------------------------------------- /src/js/ng-swiper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * @Date 2016/11/3 4 | * @User three 5 | */ 6 | 7 | (function(window, app, undefined) { 8 | 9 | 'use strict'; 10 | 11 | app 12 | .directive('wuSwiperContainer', ['IdWorkerFactory', function (IdWorkerFactory) { 13 | var IdWorker = IdWorkerFactory('wuSwiperContainer'); 14 | return { 15 | restrict: 'E', 16 | transclude: true, 17 | scope: { 18 | onReady: '&', 19 | slidesPerView: '=', 20 | slidesPerColumn: '=', 21 | spaceBetween: '=', 22 | parallax: '=', 23 | parallaxTransition: '@', 24 | paginationIsActive: '=', 25 | paginationClickable: '=', 26 | showNavButtons: '=', 27 | showScrollBar: '=', 28 | loop: '=', 29 | autoplay: '=', 30 | initialSlide: '=', 31 | containerCls: '@', 32 | wrapperCls: '@', 33 | paginationCls: '@', 34 | slideCls: '@', 35 | direction: '@', 36 | swiper: '=', 37 | overrideParameters: '=' 38 | }, 39 | controller: function($scope, $element, $timeout) { 40 | var uuid = IdWorker(); 41 | 42 | $scope.swiper_uuid = uuid; 43 | 44 | // directive defaults 45 | var params = { 46 | slidesPerView: $scope.slidesPerView || 1, 47 | slidesPerColumn: $scope.slidesPerColumn || 1, 48 | spaceBetween: $scope.spaceBetween || 0, 49 | direction: $scope.direction || 'horizontal', 50 | loop: $scope.loop || false, 51 | initialSlide: $scope.initialSlide || 0, 52 | showNavButtons: false 53 | }; 54 | 55 | if (!angular.isUndefined($scope.autoplay) && typeof $scope.autoplay === 'number') { 56 | params = angular.extend({}, params, { 57 | autoplay: $scope.autoplay 58 | }); 59 | } 60 | 61 | if ($scope.paginationIsActive === true) { 62 | params = angular.extend({}, params, { 63 | paginationClickable: $scope.paginationClickable || true, 64 | pagination: '#paginator-' + $scope.swiper_uuid 65 | }); 66 | } 67 | 68 | if ($scope.showNavButtons === true) { 69 | params.nextButton = '#nextButton-' + $scope.swiper_uuid; 70 | params.prevButton = '#prevButton-' + $scope.swiper_uuid; 71 | } 72 | 73 | if ($scope.showScrollBar === true) { 74 | params.scrollbar = '#scrollBar-' + $scope.swiper_uuid; 75 | } 76 | 77 | if ($scope.overrideParameters) { 78 | params = angular.extend({}, params, $scope.overrideParameters); 79 | } 80 | 81 | $timeout(function() { 82 | var swiper = null; 83 | 84 | if (angular.isObject($scope.swiper)) { 85 | $scope.swiper = new Swiper($element[0].firstChild, params); 86 | swiper = $scope.swiper; 87 | } else { 88 | swiper = new Swiper($element[0].firstChild, params); 89 | } 90 | 91 | //If specified, calls this function when the swiper object is available 92 | if (!angular.isUndefined($scope.onReady)) { 93 | $scope.onReady({ 94 | swiper: swiper 95 | }); 96 | } 97 | }); 98 | }, 99 | 100 | link: function(scope, element) { 101 | 102 | var uuid = scope.swiper_uuid; 103 | 104 | var paginatorId = "paginator-" + uuid; 105 | var prevButtonId = "prevButton-" + uuid; 106 | var nextButtonId = "nextButton-" + uuid; 107 | var scrollBarId = 'scrollBar-' + uuid; 108 | 109 | var containerElement = element[0]; 110 | 111 | angular.element(containerElement.querySelector('.swiper-pagination')) 112 | .attr('id', paginatorId); 113 | 114 | angular.element(containerElement.querySelector('.swiper-button-next')) 115 | .attr('id', nextButtonId); 116 | 117 | angular.element(containerElement.querySelector('.swiper-button-prev')) 118 | .attr('id', prevButtonId); 119 | 120 | angular.element(element[0].querySelector('.swiper-scrollbar')) 121 | .attr('id', scrollBarId); 122 | }, 123 | 124 | template: '
' + 125 | '
' + 126 | '
' + 127 | '
' + 128 | '
' + 129 | '
' + 130 | '
' + 131 | '
' 132 | }; 133 | }]) 134 | .directive('wuSwiperSlide', [function SwiperSlide() { 135 | return { 136 | restrict: 'E', 137 | require: '^ksSwiperContainer', 138 | transclude: true, 139 | scope: { 140 | sliderCls: '@', 141 | }, 142 | template: '
', 143 | replace: true 144 | }; 145 | }]); 146 | 147 | })(window, angular.module('ng.weui.swiper'), undefined); -------------------------------------------------------------------------------- /src/js/progress.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by three on 16/1/14. 3 | */ 4 | 5 | (function (app) { 6 | app.directive('wuProgress',[function () { 7 | return { 8 | restrict:'EA', 9 | replace: true, 10 | scope: { 11 | wuProgress:"=", 12 | wuColor:'=', 13 | wuHeight:'=' 14 | }, 15 | transclude:true, 16 | template:'\ 17 |
\ 18 |
\ 19 |
\ 23 |
\ 24 | \ 25 | \ 26 |
', 27 | link: function (scope, element, attrs) { 28 | scope.filterProgress = function (number) { 29 | if(number>100) { 30 | return '100%'; 31 | } 32 | if(number<0) { 33 | return '0%'; 34 | } 35 | return parseFloat(number)+'%'; 36 | }; 37 | scope.filterHeight = function (height) { 38 | return ((height && height>1)?height:3)+'px'; 39 | } 40 | } 41 | } 42 | }]); 43 | })(angular.module('ng.weui.progress')); 44 | -------------------------------------------------------------------------------- /src/js/wx-jssdk.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 微信基本js接口 3 | */ 4 | (function (app, window) { 5 | app.factory('WuWxJsSdk',['$q', function ($q) { 6 | /** 7 | * 获取微信js接口对象 8 | * @param reject 如果没有js接口对象,调用通知方法 9 | * @returns {*} false 或 js接口对象 10 | */ 11 | function checkWxObj(reject) { 12 | if(!window.wx) { 13 | reject({ 14 | errMsg: '没有js接口对象,请确认是否引入微信js文件' 15 | }); 16 | return false; 17 | } 18 | return window.wx; 19 | } 20 | 21 | /** 22 | * 构建接口参数回调 23 | * @param params 参数 24 | * @param resolve 成功回调 25 | * @param reject 失败回调 26 | * @param config 失败回调 27 | * @returns {*} 28 | */ 29 | function builderParamsCb(params, resolve, reject) { 30 | params.success = function(res) { 31 | resolve(res); 32 | }; 33 | params.fail = function(res) { 34 | reject(res) 35 | }; 36 | params.complete = function (res) { 37 | 38 | }; 39 | params.cancel = function () { 40 | reject({ 41 | errMsg: '用户取消' 42 | }) 43 | }; 44 | params.trigger = function () { 45 | 46 | }; 47 | return params; 48 | } 49 | 50 | var __server = { 51 | // 权限验证配置 52 | config: function () { 53 | return $q(function (resolve, reject) { 54 | var wxObj = checkWxObj(reject); 55 | if(wxObj) { 56 | wxObj.config.apply(window, arguments); 57 | wxObj.ready(function(){ 58 | // 权限配置成功 59 | resolve({ 60 | errMsg: 'config:ok' 61 | }) 62 | }); 63 | wxObj.error(function(res){ 64 | // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 65 | reject(res) 66 | }); 67 | } 68 | }); 69 | } 70 | }; 71 | 72 | // 封装原有js接口 73 | var jsApiList = [ 74 | //openEnterpriseContact 75 | 'checkJsApi', 76 | 77 | 'onMenuShareTimeline', 78 | 'onMenuShareAppMessage', 79 | 'onMenuShareQQ', 80 | 'onMenuShareWeibo', 81 | 'onMenuShareWeibo', 82 | 83 | 'chooseImage', 84 | 'previewImage', 85 | 'uploadImage', 86 | 'downloadImage', 87 | 88 | 'startRecord', 89 | 'stopRecord', 90 | 'onVoiceRecordEnd', 91 | 'playVoice', 92 | 'pauseVoice', 93 | 'stopVoice', 94 | 'onVoicePlayEnd', 95 | 'uploadVoice', 96 | 'downloadVoice', 97 | 'translateVoice', 98 | 99 | 'getNetworkType', 100 | 101 | 'openLocation', 102 | 'getLocation', 103 | 104 | 'hideOptionMenu', 105 | 'showOptionMenu', 106 | 'closeWindow', 107 | 'hideMenuItems', 108 | 'showMenuItems', 109 | 'hideAllNonBaseMenuItem', 110 | 'showAllNonBaseMenuItem', 111 | 112 | 'scanQRCode', 113 | 114 | 'startSearchBeacons', //complete 115 | 'stopSearchBeacons', //complete 116 | 'onSearchBeacons', //complete 117 | 118 | 'openProductSpecificView', // 微小店商品页 119 | 120 | 'chooseCard', // 卡券 121 | 'addCard', 122 | 'openCard', 123 | 'consumeAndShareCard', 124 | 125 | 'chooseWXPay' // 支付 126 | 127 | ]; 128 | for(var i=0; i