├── .gitignore
├── README.md
├── app.js
├── bower.json
├── config.example.js
├── front
├── js
│ ├── manager.js
│ └── uploader.js
└── scss
│ ├── base.scss
│ ├── home.scss
│ ├── index.scss
│ └── reset.scss
├── gulpfile.js
├── lib
└── genToken.js
├── package.json
└── public
├── css
└── index.css
├── index.html
└── js
├── lib
└── zepto.min.js
├── manager.js
└── uploader.js
/.gitignore:
--------------------------------------------------------------------------------
1 | config.js
2 | node_modules
3 | bower_components
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 小巧的前端七牛上传工具
2 | ----------------------
3 |
4 | 介绍
5 | ----
6 | `不依赖任何第三方库`
7 |
8 |
9 | 如何使用
10 | ---------
11 | **客户端**
12 | ```javascript
13 | var options = {
14 | //must
15 | domain: '七牛分配给你的域名',
16 |
17 | //must
18 | tokenUrl: '你的服务器上获取uptoken的访问地址',
19 | maxImgSize: '最大图片大小', //option
20 |
21 | // option , 比如: 'font-qn-uper/'. 访问地址就是:http:domain/prefix/filename
22 | prefix: '自定义的路径',
23 |
24 | //option, 默认5000ms
25 | timeout: '请求超时时间' ,
26 |
27 | //option, 默认480px
28 | maxMobileWidth: '在手机上最大显示宽度',
29 |
30 | //option, 默认960px
31 | maxPcWidth: '在pc端最大显示宽度',
32 |
33 | //option, 格式比如: "jpg, png, jpeg"
34 | imageType: "文件类型"
35 | }
36 | var ins = new fontQnUper(options);
37 | $('#upload').on('change', function() {
38 | var file = this.files[0];
39 |
40 | // 错误捕捉
41 | ins.errHandle = function(e) {
42 | console.log(e);
43 | }
44 |
45 | ins.post(file, function(result) {
46 | /*result datas
47 | {
48 | hash: "",
49 | key: "",
50 | fullImageUrl: "完整的上传图片",
51 | mobileImageUrl:"手机上显示的图片",
52 | pcImageUrl:"pc端显示的图片"
53 | }
54 | */
55 | });
56 | // 上传进度, total: 一共上传的数据, loaded: 已经上传的数据(bytes)
57 | ins.progress = function(total,loaded){
58 | //do something
59 | }
60 | });
61 | ```
62 |
63 | 案例
64 | ====
65 |
66 | 我自己的基于`Ghost`的博客系统的前端上传图片
67 | https://github.com/DgTechOrg/Customize-Ghost
68 |
69 | **配置文件说明**
70 |
71 | > 三个参数, 分别是: `BUCKET_NAME`, `ACCESS_KEY`, `SECRET_KEY`
72 | 就是你定义的空间以及七牛提供给你的访问秘钥
73 |
--------------------------------------------------------------------------------
/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const http = require('http');
4 | const url = require('url');
5 | const express = require('express');
6 | const app = express();
7 | const config = require('./config');
8 | const path = require('path');
9 | const genToken = require('./lib/genToken');
10 |
11 | app.use(express.static(path.join(__dirname, 'public')));
12 | // app.get('/', function(req, res) {
13 |
14 | // });
15 |
16 | app.get('/token', function(req, res) {
17 | res.writeHead(200, {
18 | 'Content-Type':'text/json',
19 | 'Expires': 0,
20 | 'Pragma': 'no-cache'
21 | });
22 | var retJson = {
23 | uptoken: genToken()
24 | }
25 | res.end(JSON.stringify(retJson));
26 | });
27 |
28 | http.createServer(app).listen(config.port, function() {
29 | console.log('server run at: ', config.port);
30 | });
31 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front-qn-uper",
3 | "version": "1.0.1",
4 | "homepage": "https://github.com/struCoder/front-qn-uper",
5 | "description": "",
6 | "main": "",
7 | "moduleType": [],
8 | "license": "MIT",
9 | "private": true,
10 | "ignore": [
11 | "**/.*",
12 | "node_modules",
13 | "bower_components",
14 | "test",
15 | "tests"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/config.example.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = {
4 | port: 9002,
5 | ACCESS_KEY: "your qiniu ACCESS_KEY",
6 | SECRET_KEY: 'your qiniu SECRET_KEY',
7 | BUCKET_NAME: 'your qiniu BUCKET_NAME'
8 | }
9 |
--------------------------------------------------------------------------------
/front/js/manager.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var $fileBtn = $('#file-btn');
3 | var $show = $('#result-show');
4 |
5 | var options = {
6 | domain: 'http://7xjbiz.com1.z0.glb.clouddn.com',
7 | tokenUrl: '/token',
8 | prefix: 'temp/'
9 | }
10 |
11 | var ins = new frontQnUper(options);
12 | $('#upload').on('change', function() {
13 | ins.prefix = $('#prefix').val() || 'temp/';
14 | var file = this.files[0];
15 | //process
16 | ins.progress = function(total, loaded) {
17 | $fileBtn.val('上传进度: ' + (loaded / total).toFixed(0) * 100 + '%');
18 | if (loaded === total) {
19 | $fileBtn.val('请稍等...');
20 | }
21 | }
22 | ins.errHandle = function(e) {
23 | alert(e)
24 | }
25 |
26 | ins.post(file, function(result) {
27 | var resultDOM = [];
28 |
29 | for(var i in result) {
30 | resultDOM.push([
31 | '
',
32 | '',
33 | result[i],
34 | '',
35 | '
'
36 | ].join(''))
37 | }
38 | $show.append(resultDOM.join(''));
39 | setTimeout(function() {
40 | $fileBtn.val('上传图片');
41 | }, 1500);
42 | });
43 | })
44 | })();
45 |
--------------------------------------------------------------------------------
/front/js/uploader.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | var STR_RAND = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
3 | var DEFAULT_IMG = ['jpg', 'jpeg', 'gif', 'png', 'bmp'];
4 | var DEFAULT_SIZE = 10 * 1024; // 10MB
5 |
6 | var genRand = function(len) {
7 | len = len || 16;
8 | var resultStr = '';
9 | var length = STR_RAND.length;
10 | var random = null;
11 | for (var i = 0; i < len; i++) {
12 | random = Math.floor(Math.random() * length);
13 | resultStr += STR_RAND.substring(random - 1, random);
14 | }
15 | return resultStr;
16 | }
17 |
18 | var createAjax = function() {
19 | var xmlhttp = {};
20 | if (window.XMLHttpRequest) {
21 | xmlhttp = new XMLHttpRequest();
22 | } else {
23 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
24 | }
25 | xmlhttp.timeout = this.timeout;
26 | return xmlhttp;
27 | }
28 |
29 | var request = function(options, cb) {
30 | var self = this;
31 | var xhr = createAjax();
32 | xhr.open(options.method, options.url, true);
33 | xhr.onload = function() {
34 | if (xhr.status === 200) {
35 | try {
36 | var jsonResult = JSON.parse(xhr.responseText);
37 | } catch (e) {
38 | e.msg = 'parse text to json error';
39 | cb(e);
40 | }
41 | cb(null, jsonResult);
42 | }
43 | }
44 |
45 | xhr.ontimeout = function() {
46 | cb('timeout');
47 | }
48 |
49 | xhr.onerror = function(e) {
50 | e.msg = 'network error not frontQnUper self error';
51 | cb(e);
52 | }
53 | if (options.onProgress) {
54 | xhr.upload.onprogress = function(e) {
55 | self.progress(e.total, e.loaded);
56 | }
57 | }
58 | xhr.send(options.method === 'POST' ? options.data : null);
59 | }
60 |
61 | var qnUpload = function(options) {
62 | if (Object.prototype.toString.call(options) !== '[object Object]') {
63 | throw new Error('options must be Object')
64 | }
65 | if (options.imageType) {
66 | this.imageTypeArr = options.imageType.split(',');
67 | } else {
68 | this.imageTypeArr = DEFAULT_IMG;
69 | }
70 |
71 | this.domain = options.domain; //must
72 | this.url = options.tokenUrl; // must
73 | this.prefix = options.prefix || 'font-qn-uper/';
74 | this.timeout = options.timeout || 5000; // By default 5000ms
75 | this.maxMobileWidth = options.maxWidth || 480;
76 | this.maxPcWidth = options.maxPcWidth || 960;
77 | this.defaultSize = parseInt(options.maxImgSize, 10) || 10 * 1024;
78 | this.uploadUrl = 'http://upload.qiniu.com/?token=';
79 | // this._getToken()
80 | }
81 |
82 | qnUpload.prototype.checkType = function(cb) {
83 | var errInfo;
84 | var fileName = this.file.name;
85 | var fileSize = this.file.size / 1024;
86 | var imgExt = fileName.substring(fileName.lastIndexOf('.') + 1).toLowerCase();
87 | if (this.imageTypeArr.indexOf(imgExt) === -1) {
88 | errInfo = '图片格式为下面的一种: ' + this.imageTypeArr.toString();
89 | cb(errInfo);
90 | } else if (fileSize > this.defaultSize) {
91 | errInfo = '图片大小因控制在' + this.defaultSize + ' 内';
92 | cb(errInfo);
93 | } else {
94 | cb();
95 | }
96 | };
97 |
98 | qnUpload.prototype._getToken = function(cb) {
99 | var self = this;
100 | var options = {
101 | method: 'GET',
102 | url: this.url
103 | }
104 | if (typeof cb === 'function') {
105 | request(options, cb);
106 | } else {
107 | throw new Error('when get uptoken the cb must be Function');
108 | }
109 | }
110 |
111 | qnUpload.prototype._postPrepare = function(cb) {
112 | var self = this;
113 | this.checkType(function(err) {
114 | if (err && typeof self.errHandle === 'function') {
115 | return self.errHandle(err);
116 | }
117 | self._getToken(function(err, tokenInfo) {
118 | if (err && typeof self.errHandle === 'function') {
119 | return self.errHandle(e);
120 | }
121 | self.token = tokenInfo;
122 | if (typeof cb === 'function') {
123 | cb();
124 | }
125 | });
126 | });
127 | }
128 |
129 | qnUpload.prototype.post = function(file, cb) {
130 | this.file = file;
131 | var self = this;
132 | var randName = genRand();
133 | this._postPrepare(function() {
134 | var data = new FormData();
135 | data.append('file', file);
136 | data.append('key', self.prefix + randName);
137 | var postUrl = self.uploadUrl + self.token.uptoken + '&rand=' + Math.random(); // avoid cache
138 | var options = {
139 | method: 'POST',
140 | url: postUrl,
141 | onProgress: true,
142 | data: data
143 | }
144 | request.call(self, options, function(err, returnObj) {
145 | if (err && typeof errHandle === 'function') {
146 | return errHandle(err);
147 | }
148 | var imageUrlInfo = {};
149 | imageUrlInfo.fullImageUrl = self.domain + '/' + returnObj.key;
150 | imageUrlInfo.mobileImageUrl = self.domain + '/' + returnObj.key + '?imageView2/0/w/' + self.maxMobileWidth
151 | imageUrlInfo.pcImageUrl = self.domain + '/' + returnObj.key + '?imageView2/2/w/' + self.maxPcWidth;
152 | cb(imageUrlInfo);
153 | });
154 | });
155 | }
156 | window.frontQnUper = qnUpload;
157 | })();
158 |
--------------------------------------------------------------------------------
/front/scss/base.scss:
--------------------------------------------------------------------------------
1 | input[type="text"], input[type="button"], input[type="file"] {
2 | font-weight: 400;
3 | width: 100%;
4 | font-size: 14px;
5 | padding: .75rem 0;
6 | line-height: inherit;
7 | border-radius: 0;
8 | text-indent: 8px;
9 | outline: none;
10 | border: 1px solid #41A6EF;
11 | }
12 |
13 | input[type="button"] {
14 | background-color: #41A6EF;
15 | }
16 |
17 |
--------------------------------------------------------------------------------
/front/scss/home.scss:
--------------------------------------------------------------------------------
1 | .container {
2 | width: 80%;
3 | height: auto;
4 | margin: 0 auto;
5 | margin-top: 10%;
6 | border: 4px dashed #aaa;
7 | padding: 20px;
8 |
9 | .margin-auto {
10 | position: relative;
11 | width: 95%;
12 | margin: 0 auto;
13 | }
14 | .upload-input {
15 | width: 50%;
16 | input {
17 | margin-bottom: 30px;
18 | }
19 | .select-prefix {
20 | input {
21 | display: inline-block;
22 | }
23 | .prefix-btn {
24 | width: 28%;
25 | color: #fff;
26 | }
27 | }
28 | // .upload-group {
29 | // opacity: 0;
30 | // &.show {
31 | // opacity: 1;
32 | // }
33 | // }
34 | .file {
35 | opacity: 0;
36 | z-index: 100;
37 | cursor: pointer;
38 | }
39 | .file-btn {
40 | position: absolute;
41 | top: 74px;
42 | z-index: -1;
43 | color: #fff;
44 | }
45 | }
46 |
47 | .result {
48 | .pic-url {
49 | padding: 4px;
50 | margin-bottom: 1px;
51 | border: 1px solid rgba(65, 166, 239, 0.48);
52 | width: 100%;
53 | height: auto;
54 | word-break: break-all;
55 | word-wrap: break-word;
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/front/scss/index.scss:
--------------------------------------------------------------------------------
1 | @import 'reset';
2 | @import 'base';
3 | @import 'home';
4 |
--------------------------------------------------------------------------------
/front/scss/reset.scss:
--------------------------------------------------------------------------------
1 | html, body { margin: 0; padding: 0; }
2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td { margin: 0; padding: 0; border: 0; font-weight: normal;font-style: normal; font-size: 100%; /*line-height: 1;*/ font-family: inherit; }
3 | table { border-collapse: collapse; border-spacing: 0;}
4 | //ol, ul { list-style: none; }
5 | q:before, q:after, blockquote:before, blockquote:after { content: ""; }
6 | //sd
7 |
8 | // Normalize.css
9 | // Pulling in select resets form the normalize.css project
10 | // --------------------------------------------------
11 |
12 | // Display in IE6-9 and FF3
13 | // -------------------------
14 | // Source: http://github.com/necolas/normalize.css
15 | html {
16 | font-size: 100%;
17 | -webkit-text-size-adjust: 100%;
18 | -ms-text-size-adjust: 100%;
19 | }
20 | // Focus states
21 | a:focus {
22 | outline: thin dotted;
23 | }
24 | // Hover & Active
25 | a:hover,
26 | a:active {
27 | outline: 0;
28 | }
29 |
30 | // Display in IE6-9 and FF3
31 | // -------------------------
32 | // Source: http://github.com/necolas/normalize.css
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | nav,
42 | section {
43 | display: block;
44 | }
45 |
46 | // Display block in IE6-9 and FF3
47 | // -------------------------
48 | // Source: http://github.com/necolas/normalize.css
49 | audio,
50 | canvas,
51 | video {
52 | display: inline-block;
53 | *display: inline;
54 | *zoom: 1;
55 | }
56 |
57 | // Prevents modern browsers from displaying 'audio' without controls
58 | // -------------------------
59 | // Source: http://github.com/necolas/normalize.css
60 | audio:not([controls]) {
61 | display: none;
62 | }
63 |
64 | // Prevents sub and sup affecting line-height in all browsers
65 | // -------------------------
66 | // Source: http://github.com/necolas/normalize.css
67 | sub,
68 | sup {
69 | font-size: 75%;
70 | line-height: 0;
71 | position: relative;
72 | vertical-align: baseline;
73 | }
74 | sup {
75 | top: -0.5em;
76 | }
77 | sub {
78 | bottom: -0.25em;
79 | }
80 |
81 | // Img border in a's and image quality
82 | // -------------------------
83 | // Source: http://github.com/necolas/normalize.css
84 | img {
85 | border: 0;
86 | -ms-interpolation-mode: bicubic;
87 | }
88 |
89 | // Forms
90 | // -------------------------
91 | // Source: http://github.com/necolas/normalize.css
92 |
93 | // Font size in all browsers, margin changes, misc consistency
94 | button,
95 | input,
96 | select,
97 | textarea {
98 | padding: 0;
99 | font-size: 100%;
100 | margin: 0;
101 | vertical-align: baseline;
102 | *vertical-align: middle;
103 | }
104 | button,
105 | input {
106 | line-height: normal; // FF3/4 have !important on line-height in UA stylesheet
107 | *overflow: visible; // Inner spacing ie IE6/7
108 | }
109 | button::-moz-focus-inner,
110 | input::-moz-focus-inner { // Inner padding and border oddities in FF3/4
111 | border: 0;
112 | padding: 0;
113 | }
114 | button,
115 | input[type="button"],
116 | input[type="reset"],
117 | input[type="submit"] {
118 | cursor: pointer; // Cursors on all buttons applied consistently
119 | -webkit-appearance: button; // Style clicable inputs in iOS
120 | }
121 | input[type="search"] { // Appearance in Safari/Chrome
122 | -webkit-appearance: textfield;
123 | -webkit-box-sizing: content-box;
124 | -moz-box-sizing: content-box;
125 | box-sizing: content-box;
126 | }
127 | input[type="search"]::-webkit-search-decoration {
128 | -webkit-appearance: none; // Inner-padding issues in Chrome OSX, Safari 5
129 | }
130 | textarea {
131 | overflow: auto; // Remove vertical scrollbar in IE6-9
132 | vertical-align: top; // Readability and alignment cross-browser
133 | }
134 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp');
2 | const changed = require('gulp-changed');
3 | const uglify = require('gulp-uglify');
4 | const sass = require('gulp-sass');
5 |
6 |
7 | gulp.task('copy-js', function() {
8 | return gulp.src('./front/js/*.js')
9 | .pipe(uglify())
10 | .pipe(gulp.dest('./public/js'))
11 | })
12 | gulp.task('copy-zepto', function() {
13 | return gulp.src('./bower_components/zepto/zepto.min.js')
14 | .pipe(changed('./public/js/lib'))
15 | .pipe(gulp.dest('./public/js/lib'))
16 | });
17 |
18 | gulp.task('sass', function() {
19 | return gulp.src('./front/scss/index.scss')
20 | .pipe(sass.sync())
21 | .pipe(gulp.dest('./public/css'))
22 | });
23 |
24 | gulp.task('watch-js', function() {
25 | return gulp.watch('./front/js/*.js', ['copy-js']);
26 | });
27 |
28 | gulp.task('watch-sass', function() {
29 | return gulp.watch('./front/scss/*.scss', ['sass']);
30 | });
31 |
32 | gulp.task('watch', ['watch-sass', 'watch-js']);
33 |
34 | gulp.task('copy', ['copy-zepto', 'copy-js']);
35 |
36 |
37 | gulp.task('default', ['copy', 'sass', 'watch']);
38 |
39 | gulp.task('pro', ['copy', 'sass']);
40 |
--------------------------------------------------------------------------------
/lib/genToken.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const crypto = require('crypto');
4 | const config = require('../config');
5 |
6 | function getFlags() {
7 | //对这个方法只做简单上传到bucket就好
8 | var returnObj = {
9 | scope: config.BUCKET_NAME,
10 | deadline: 3600 + Math.floor(Date.now() / 1000)
11 | }
12 | return returnObj;
13 | }
14 |
15 | function urlsafeBase64Encode (jsonFlags) {
16 | var encoded = new Buffer(jsonFlags).toString('base64');
17 | return base64ToUrlSafe(encoded);
18 | }
19 |
20 | function base64ToUrlSafe (val) {
21 | return val.replace(/\//g, '_').replace(/\+/g, '-');
22 | }
23 |
24 | function hmacSha1 (encodedFlags, secretKey) {
25 | var hmac = crypto.createHmac('sha1', secretKey);
26 | return hmac.update(encodedFlags).digest('base64');
27 | }
28 |
29 | module.exports = function() {
30 | var flags = getFlags();
31 | var encodedFlags = urlsafeBase64Encode(JSON.stringify(flags));
32 | var encoded = hmacSha1(encodedFlags, config.SECRET_KEY);
33 | var encodedSign = base64ToUrlSafe(encoded);
34 | var tokenInfo = config.ACCESS_KEY + ':' + encodedSign + ':' + encodedFlags;
35 | return tokenInfo;
36 | }
37 | // WebApp.connectHandlers.use('/cmeteor-token', function(req, res) {
38 | // var flags = getFlags();
39 | // var encodedFlags = urlsafeBase64Encode(JSON.stringify(flags));
40 | // var encoded = hmacSha1(encodedFlags, config.SECRET_KEY);
41 | // var encodedSign = base64ToUrlSafe(encoded);
42 | // var tokenInfo = {
43 | // uptoken: config.ACCESS_KEY + ':' + encodedSign + ':' + encodedFlags
44 | // }
45 | // res.writeHead(200, {
46 | // 'Content-Type':'text/json',
47 | // 'Expires': 0,
48 | // 'Pragma': 'no-cache'
49 | // });
50 | // res.end(JSON.stringify(tokenInfo));
51 | // });
52 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front-qn-uper",
3 | "version": "1.0.0",
4 | "description": "upload file",
5 | "main": "app.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/struCoder/front-qn-uper.git"
12 | },
13 | "author": "zdwloveschina@gmail.com",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/struCoder/front-qn-uper/issues"
17 | },
18 | "homepage": "https://github.com/struCoder/front-qn-uper#readme",
19 | "dependencies": {
20 | "express": "^4.13.3"
21 | },
22 | "devDependencies": {
23 | "gulp": "^3.9.0",
24 | "gulp-changed": "^1.3.0",
25 | "gulp-sass": "^2.1.0",
26 | "gulp-uglify": "^1.4.2"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/public/css/index.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | margin: 0;
3 | padding: 0; }
4 |
5 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, cite, code, del, dfn, em, img, q, s, samp, small, strike, strong, sub, sup, tt, var, dd, dl, dt, li, ol, ul, fieldset, form, label, legend, button, table, caption, tbody, tfoot, thead, tr, th, td {
6 | margin: 0;
7 | padding: 0;
8 | border: 0;
9 | font-weight: normal;
10 | font-style: normal;
11 | font-size: 100%;
12 | /*line-height: 1;*/
13 | font-family: inherit; }
14 |
15 | table {
16 | border-collapse: collapse;
17 | border-spacing: 0; }
18 |
19 | q:before, q:after, blockquote:before, blockquote:after {
20 | content: ""; }
21 |
22 | html {
23 | font-size: 100%;
24 | -webkit-text-size-adjust: 100%;
25 | -ms-text-size-adjust: 100%; }
26 |
27 | a:focus {
28 | outline: thin dotted; }
29 |
30 | a:hover,
31 | a:active {
32 | outline: 0; }
33 |
34 | article,
35 | aside,
36 | details,
37 | figcaption,
38 | figure,
39 | footer,
40 | header,
41 | hgroup,
42 | nav,
43 | section {
44 | display: block; }
45 |
46 | audio,
47 | canvas,
48 | video {
49 | display: inline-block;
50 | *display: inline;
51 | *zoom: 1; }
52 |
53 | audio:not([controls]) {
54 | display: none; }
55 |
56 | sub,
57 | sup {
58 | font-size: 75%;
59 | line-height: 0;
60 | position: relative;
61 | vertical-align: baseline; }
62 |
63 | sup {
64 | top: -0.5em; }
65 |
66 | sub {
67 | bottom: -0.25em; }
68 |
69 | img {
70 | border: 0;
71 | -ms-interpolation-mode: bicubic; }
72 |
73 | button,
74 | input,
75 | select,
76 | textarea {
77 | padding: 0;
78 | font-size: 100%;
79 | margin: 0;
80 | vertical-align: baseline;
81 | *vertical-align: middle; }
82 |
83 | button,
84 | input {
85 | line-height: normal;
86 | *overflow: visible; }
87 |
88 | button::-moz-focus-inner,
89 | input::-moz-focus-inner {
90 | border: 0;
91 | padding: 0; }
92 |
93 | button,
94 | input[type="button"],
95 | input[type="reset"],
96 | input[type="submit"] {
97 | cursor: pointer;
98 | -webkit-appearance: button; }
99 |
100 | input[type="search"] {
101 | -webkit-appearance: textfield;
102 | -webkit-box-sizing: content-box;
103 | -moz-box-sizing: content-box;
104 | box-sizing: content-box; }
105 |
106 | input[type="search"]::-webkit-search-decoration {
107 | -webkit-appearance: none; }
108 |
109 | textarea {
110 | overflow: auto;
111 | vertical-align: top; }
112 |
113 | input[type="text"], input[type="button"], input[type="file"] {
114 | font-weight: 400;
115 | width: 100%;
116 | font-size: 14px;
117 | padding: .75rem 0;
118 | line-height: inherit;
119 | border-radius: 0;
120 | text-indent: 8px;
121 | outline: none;
122 | border: 1px solid #41A6EF; }
123 |
124 | input[type="button"] {
125 | background-color: #41A6EF; }
126 |
127 | .container {
128 | width: 80%;
129 | height: auto;
130 | margin: 0 auto;
131 | margin-top: 10%;
132 | border: 4px dashed #aaa;
133 | padding: 20px; }
134 | .container .margin-auto {
135 | position: relative;
136 | width: 95%;
137 | margin: 0 auto; }
138 | .container .upload-input {
139 | width: 50%; }
140 | .container .upload-input input {
141 | margin-bottom: 30px; }
142 | .container .upload-input .select-prefix input {
143 | display: inline-block; }
144 | .container .upload-input .select-prefix .prefix-btn {
145 | width: 28%;
146 | color: #fff; }
147 | .container .upload-input .file {
148 | opacity: 0;
149 | z-index: 100;
150 | cursor: pointer; }
151 | .container .upload-input .file-btn {
152 | position: absolute;
153 | top: 74px;
154 | z-index: -1;
155 | color: #fff; }
156 | .container .result .pic-url {
157 | padding: 4px;
158 | margin-bottom: 1px;
159 | border: 1px solid rgba(65, 166, 239, 0.48);
160 | width: 100%;
161 | height: auto;
162 | word-break: break-all;
163 | word-wrap: break-word; }
164 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 图片上传自助工具
5 |
6 |
7 |
8 |
9 |
10 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/public/js/lib/zepto.min.js:
--------------------------------------------------------------------------------
1 | /* Zepto v1.1.6 - zepto event ajax form ie - zeptojs.com/license */
2 | var Zepto=function(){function L(t){return null==t?String(t):j[S.call(t)]||"object"}function Z(t){return"function"==L(t)}function _(t){return null!=t&&t==t.window}function $(t){return null!=t&&t.nodeType==t.DOCUMENT_NODE}function D(t){return"object"==L(t)}function M(t){return D(t)&&!_(t)&&Object.getPrototypeOf(t)==Object.prototype}function R(t){return"number"==typeof t.length}function k(t){return s.call(t,function(t){return null!=t})}function z(t){return t.length>0?n.fn.concat.apply([],t):t}function F(t){return t.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()}function q(t){return t in f?f[t]:f[t]=new RegExp("(^|\\s)"+t+"(\\s|$)")}function H(t,e){return"number"!=typeof e||c[F(t)]?e:e+"px"}function I(t){var e,n;return u[t]||(e=a.createElement(t),a.body.appendChild(e),n=getComputedStyle(e,"").getPropertyValue("display"),e.parentNode.removeChild(e),"none"==n&&(n="block"),u[t]=n),u[t]}function V(t){return"children"in t?o.call(t.children):n.map(t.childNodes,function(t){return 1==t.nodeType?t:void 0})}function B(n,i,r){for(e in i)r&&(M(i[e])||A(i[e]))?(M(i[e])&&!M(n[e])&&(n[e]={}),A(i[e])&&!A(n[e])&&(n[e]=[]),B(n[e],i[e],r)):i[e]!==t&&(n[e]=i[e])}function U(t,e){return null==e?n(t):n(t).filter(e)}function J(t,e,n,i){return Z(e)?e.call(t,n,i):e}function X(t,e,n){null==n?t.removeAttribute(e):t.setAttribute(e,n)}function W(e,n){var i=e.className||"",r=i&&i.baseVal!==t;return n===t?r?i.baseVal:i:void(r?i.baseVal=n:e.className=n)}function Y(t){try{return t?"true"==t||("false"==t?!1:"null"==t?null:+t+""==t?+t:/^[\[\{]/.test(t)?n.parseJSON(t):t):t}catch(e){return t}}function G(t,e){e(t);for(var n=0,i=t.childNodes.length;i>n;n++)G(t.childNodes[n],e)}var t,e,n,i,C,N,r=[],o=r.slice,s=r.filter,a=window.document,u={},f={},c={"column-count":1,columns:1,"font-weight":1,"line-height":1,opacity:1,"z-index":1,zoom:1},l=/^\s*<(\w+|!)[^>]*>/,h=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,p=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,d=/^(?:body|html)$/i,m=/([A-Z])/g,g=["val","css","html","text","data","width","height","offset"],v=["after","prepend","before","append"],y=a.createElement("table"),x=a.createElement("tr"),b={tr:a.createElement("tbody"),tbody:y,thead:y,tfoot:y,td:x,th:x,"*":a.createElement("div")},w=/complete|loaded|interactive/,E=/^[\w-]*$/,j={},S=j.toString,T={},O=a.createElement("div"),P={tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},A=Array.isArray||function(t){return t instanceof Array};return T.matches=function(t,e){if(!e||!t||1!==t.nodeType)return!1;var n=t.webkitMatchesSelector||t.mozMatchesSelector||t.oMatchesSelector||t.matchesSelector;if(n)return n.call(t,e);var i,r=t.parentNode,o=!r;return o&&(r=O).appendChild(t),i=~T.qsa(r,e).indexOf(t),o&&O.removeChild(t),i},C=function(t){return t.replace(/-+(.)?/g,function(t,e){return e?e.toUpperCase():""})},N=function(t){return s.call(t,function(e,n){return t.indexOf(e)==n})},T.fragment=function(e,i,r){var s,u,f;return h.test(e)&&(s=n(a.createElement(RegExp.$1))),s||(e.replace&&(e=e.replace(p,"<$1>$2>")),i===t&&(i=l.test(e)&&RegExp.$1),i in b||(i="*"),f=b[i],f.innerHTML=""+e,s=n.each(o.call(f.childNodes),function(){f.removeChild(this)})),M(r)&&(u=n(s),n.each(r,function(t,e){g.indexOf(t)>-1?u[t](e):u.attr(t,e)})),s},T.Z=function(t,e){return t=t||[],t.__proto__=n.fn,t.selector=e||"",t},T.isZ=function(t){return t instanceof T.Z},T.init=function(e,i){var r;if(!e)return T.Z();if("string"==typeof e)if(e=e.trim(),"<"==e[0]&&l.test(e))r=T.fragment(e,RegExp.$1,i),e=null;else{if(i!==t)return n(i).find(e);r=T.qsa(a,e)}else{if(Z(e))return n(a).ready(e);if(T.isZ(e))return e;if(A(e))r=k(e);else if(D(e))r=[e],e=null;else if(l.test(e))r=T.fragment(e.trim(),RegExp.$1,i),e=null;else{if(i!==t)return n(i).find(e);r=T.qsa(a,e)}}return T.Z(r,e)},n=function(t,e){return T.init(t,e)},n.extend=function(t){var e,n=o.call(arguments,1);return"boolean"==typeof t&&(e=t,t=n.shift()),n.forEach(function(n){B(t,n,e)}),t},T.qsa=function(t,e){var n,i="#"==e[0],r=!i&&"."==e[0],s=i||r?e.slice(1):e,a=E.test(s);return $(t)&&a&&i?(n=t.getElementById(s))?[n]:[]:1!==t.nodeType&&9!==t.nodeType?[]:o.call(a&&!i?r?t.getElementsByClassName(s):t.getElementsByTagName(e):t.querySelectorAll(e))},n.contains=a.documentElement.contains?function(t,e){return t!==e&&t.contains(e)}:function(t,e){for(;e&&(e=e.parentNode);)if(e===t)return!0;return!1},n.type=L,n.isFunction=Z,n.isWindow=_,n.isArray=A,n.isPlainObject=M,n.isEmptyObject=function(t){var e;for(e in t)return!1;return!0},n.inArray=function(t,e,n){return r.indexOf.call(e,t,n)},n.camelCase=C,n.trim=function(t){return null==t?"":String.prototype.trim.call(t)},n.uuid=0,n.support={},n.expr={},n.map=function(t,e){var n,r,o,i=[];if(R(t))for(r=0;r=0?e:e+this.length]},toArray:function(){return this.get()},size:function(){return this.length},remove:function(){return this.each(function(){null!=this.parentNode&&this.parentNode.removeChild(this)})},each:function(t){return r.every.call(this,function(e,n){return t.call(e,n,e)!==!1}),this},filter:function(t){return Z(t)?this.not(this.not(t)):n(s.call(this,function(e){return T.matches(e,t)}))},add:function(t,e){return n(N(this.concat(n(t,e))))},is:function(t){return this.length>0&&T.matches(this[0],t)},not:function(e){var i=[];if(Z(e)&&e.call!==t)this.each(function(t){e.call(this,t)||i.push(this)});else{var r="string"==typeof e?this.filter(e):R(e)&&Z(e.item)?o.call(e):n(e);this.forEach(function(t){r.indexOf(t)<0&&i.push(t)})}return n(i)},has:function(t){return this.filter(function(){return D(t)?n.contains(this,t):n(this).find(t).size()})},eq:function(t){return-1===t?this.slice(t):this.slice(t,+t+1)},first:function(){var t=this[0];return t&&!D(t)?t:n(t)},last:function(){var t=this[this.length-1];return t&&!D(t)?t:n(t)},find:function(t){var e,i=this;return e=t?"object"==typeof t?n(t).filter(function(){var t=this;return r.some.call(i,function(e){return n.contains(e,t)})}):1==this.length?n(T.qsa(this[0],t)):this.map(function(){return T.qsa(this,t)}):n()},closest:function(t,e){var i=this[0],r=!1;for("object"==typeof t&&(r=n(t));i&&!(r?r.indexOf(i)>=0:T.matches(i,t));)i=i!==e&&!$(i)&&i.parentNode;return n(i)},parents:function(t){for(var e=[],i=this;i.length>0;)i=n.map(i,function(t){return(t=t.parentNode)&&!$(t)&&e.indexOf(t)<0?(e.push(t),t):void 0});return U(e,t)},parent:function(t){return U(N(this.pluck("parentNode")),t)},children:function(t){return U(this.map(function(){return V(this)}),t)},contents:function(){return this.map(function(){return o.call(this.childNodes)})},siblings:function(t){return U(this.map(function(t,e){return s.call(V(e.parentNode),function(t){return t!==e})}),t)},empty:function(){return this.each(function(){this.innerHTML=""})},pluck:function(t){return n.map(this,function(e){return e[t]})},show:function(){return this.each(function(){"none"==this.style.display&&(this.style.display=""),"none"==getComputedStyle(this,"").getPropertyValue("display")&&(this.style.display=I(this.nodeName))})},replaceWith:function(t){return this.before(t).remove()},wrap:function(t){var e=Z(t);if(this[0]&&!e)var i=n(t).get(0),r=i.parentNode||this.length>1;return this.each(function(o){n(this).wrapAll(e?t.call(this,o):r?i.cloneNode(!0):i)})},wrapAll:function(t){if(this[0]){n(this[0]).before(t=n(t));for(var e;(e=t.children()).length;)t=e.first();n(t).append(this)}return this},wrapInner:function(t){var e=Z(t);return this.each(function(i){var r=n(this),o=r.contents(),s=e?t.call(this,i):t;o.length?o.wrapAll(s):r.append(s)})},unwrap:function(){return this.parent().each(function(){n(this).replaceWith(n(this).children())}),this},clone:function(){return this.map(function(){return this.cloneNode(!0)})},hide:function(){return this.css("display","none")},toggle:function(e){return this.each(function(){var i=n(this);(e===t?"none"==i.css("display"):e)?i.show():i.hide()})},prev:function(t){return n(this.pluck("previousElementSibling")).filter(t||"*")},next:function(t){return n(this.pluck("nextElementSibling")).filter(t||"*")},html:function(t){return 0 in arguments?this.each(function(e){var i=this.innerHTML;n(this).empty().append(J(this,t,e,i))}):0 in this?this[0].innerHTML:null},text:function(t){return 0 in arguments?this.each(function(e){var n=J(this,t,e,this.textContent);this.textContent=null==n?"":""+n}):0 in this?this[0].textContent:null},attr:function(n,i){var r;return"string"!=typeof n||1 in arguments?this.each(function(t){if(1===this.nodeType)if(D(n))for(e in n)X(this,e,n[e]);else X(this,n,J(this,i,t,this.getAttribute(n)))}):this.length&&1===this[0].nodeType?!(r=this[0].getAttribute(n))&&n in this[0]?this[0][n]:r:t},removeAttr:function(t){return this.each(function(){1===this.nodeType&&t.split(" ").forEach(function(t){X(this,t)},this)})},prop:function(t,e){return t=P[t]||t,1 in arguments?this.each(function(n){this[t]=J(this,e,n,this[t])}):this[0]&&this[0][t]},data:function(e,n){var i="data-"+e.replace(m,"-$1").toLowerCase(),r=1 in arguments?this.attr(i,n):this.attr(i);return null!==r?Y(r):t},val:function(t){return 0 in arguments?this.each(function(e){this.value=J(this,t,e,this.value)}):this[0]&&(this[0].multiple?n(this[0]).find("option").filter(function(){return this.selected}).pluck("value"):this[0].value)},offset:function(t){if(t)return this.each(function(e){var i=n(this),r=J(this,t,e,i.offset()),o=i.offsetParent().offset(),s={top:r.top-o.top,left:r.left-o.left};"static"==i.css("position")&&(s.position="relative"),i.css(s)});if(!this.length)return null;var e=this[0].getBoundingClientRect();return{left:e.left+window.pageXOffset,top:e.top+window.pageYOffset,width:Math.round(e.width),height:Math.round(e.height)}},css:function(t,i){if(arguments.length<2){var r,o=this[0];if(!o)return;if(r=getComputedStyle(o,""),"string"==typeof t)return o.style[C(t)]||r.getPropertyValue(t);if(A(t)){var s={};return n.each(t,function(t,e){s[e]=o.style[C(e)]||r.getPropertyValue(e)}),s}}var a="";if("string"==L(t))i||0===i?a=F(t)+":"+H(t,i):this.each(function(){this.style.removeProperty(F(t))});else for(e in t)t[e]||0===t[e]?a+=F(e)+":"+H(e,t[e])+";":this.each(function(){this.style.removeProperty(F(e))});return this.each(function(){this.style.cssText+=";"+a})},index:function(t){return t?this.indexOf(n(t)[0]):this.parent().children().indexOf(this[0])},hasClass:function(t){return t?r.some.call(this,function(t){return this.test(W(t))},q(t)):!1},addClass:function(t){return t?this.each(function(e){if("className"in this){i=[];var r=W(this),o=J(this,t,e,r);o.split(/\s+/g).forEach(function(t){n(this).hasClass(t)||i.push(t)},this),i.length&&W(this,r+(r?" ":"")+i.join(" "))}}):this},removeClass:function(e){return this.each(function(n){if("className"in this){if(e===t)return W(this,"");i=W(this),J(this,e,n,i).split(/\s+/g).forEach(function(t){i=i.replace(q(t)," ")}),W(this,i.trim())}})},toggleClass:function(e,i){return e?this.each(function(r){var o=n(this),s=J(this,e,r,W(this));s.split(/\s+/g).forEach(function(e){(i===t?!o.hasClass(e):i)?o.addClass(e):o.removeClass(e)})}):this},scrollTop:function(e){if(this.length){var n="scrollTop"in this[0];return e===t?n?this[0].scrollTop:this[0].pageYOffset:this.each(n?function(){this.scrollTop=e}:function(){this.scrollTo(this.scrollX,e)})}},scrollLeft:function(e){if(this.length){var n="scrollLeft"in this[0];return e===t?n?this[0].scrollLeft:this[0].pageXOffset:this.each(n?function(){this.scrollLeft=e}:function(){this.scrollTo(e,this.scrollY)})}},position:function(){if(this.length){var t=this[0],e=this.offsetParent(),i=this.offset(),r=d.test(e[0].nodeName)?{top:0,left:0}:e.offset();return i.top-=parseFloat(n(t).css("margin-top"))||0,i.left-=parseFloat(n(t).css("margin-left"))||0,r.top+=parseFloat(n(e[0]).css("border-top-width"))||0,r.left+=parseFloat(n(e[0]).css("border-left-width"))||0,{top:i.top-r.top,left:i.left-r.left}}},offsetParent:function(){return this.map(function(){for(var t=this.offsetParent||a.body;t&&!d.test(t.nodeName)&&"static"==n(t).css("position");)t=t.offsetParent;return t})}},n.fn.detach=n.fn.remove,["width","height"].forEach(function(e){var i=e.replace(/./,function(t){return t[0].toUpperCase()});n.fn[e]=function(r){var o,s=this[0];return r===t?_(s)?s["inner"+i]:$(s)?s.documentElement["scroll"+i]:(o=this.offset())&&o[e]:this.each(function(t){s=n(this),s.css(e,J(this,r,t,s[e]()))})}}),v.forEach(function(t,e){var i=e%2;n.fn[t]=function(){var t,o,r=n.map(arguments,function(e){return t=L(e),"object"==t||"array"==t||null==e?e:T.fragment(e)}),s=this.length>1;return r.length<1?this:this.each(function(t,u){o=i?u:u.parentNode,u=0==e?u.nextSibling:1==e?u.firstChild:2==e?u:null;var f=n.contains(a.documentElement,o);r.forEach(function(t){if(s)t=t.cloneNode(!0);else if(!o)return n(t).remove();o.insertBefore(t,u),f&&G(t,function(t){null==t.nodeName||"SCRIPT"!==t.nodeName.toUpperCase()||t.type&&"text/javascript"!==t.type||t.src||window.eval.call(window,t.innerHTML)})})})},n.fn[i?t+"To":"insert"+(e?"Before":"After")]=function(e){return n(e)[t](this),this}}),T.Z.prototype=n.fn,T.uniq=N,T.deserializeValue=Y,n.zepto=T,n}();window.Zepto=Zepto,void 0===window.$&&(window.$=Zepto),function(t){function l(t){return t._zid||(t._zid=e++)}function h(t,e,n,i){if(e=p(e),e.ns)var r=d(e.ns);return(s[l(t)]||[]).filter(function(t){return!(!t||e.e&&t.e!=e.e||e.ns&&!r.test(t.ns)||n&&l(t.fn)!==l(n)||i&&t.sel!=i)})}function p(t){var e=(""+t).split(".");return{e:e[0],ns:e.slice(1).sort().join(" ")}}function d(t){return new RegExp("(?:^| )"+t.replace(" "," .* ?")+"(?: |$)")}function m(t,e){return t.del&&!u&&t.e in f||!!e}function g(t){return c[t]||u&&f[t]||t}function v(e,i,r,o,a,u,f){var h=l(e),d=s[h]||(s[h]=[]);i.split(/\s/).forEach(function(i){if("ready"==i)return t(document).ready(r);var s=p(i);s.fn=r,s.sel=a,s.e in c&&(r=function(e){var n=e.relatedTarget;return!n||n!==this&&!t.contains(this,n)?s.fn.apply(this,arguments):void 0}),s.del=u;var l=u||r;s.proxy=function(t){if(t=j(t),!t.isImmediatePropagationStopped()){t.data=o;var i=l.apply(e,t._args==n?[t]:[t].concat(t._args));return i===!1&&(t.preventDefault(),t.stopPropagation()),i}},s.i=d.length,d.push(s),"addEventListener"in e&&e.addEventListener(g(s.e),s.proxy,m(s,f))})}function y(t,e,n,i,r){var o=l(t);(e||"").split(/\s/).forEach(function(e){h(t,e,n,i).forEach(function(e){delete s[o][e.i],"removeEventListener"in t&&t.removeEventListener(g(e.e),e.proxy,m(e,r))})})}function j(e,i){return(i||!e.isDefaultPrevented)&&(i||(i=e),t.each(E,function(t,n){var r=i[t];e[t]=function(){return this[n]=x,r&&r.apply(i,arguments)},e[n]=b}),(i.defaultPrevented!==n?i.defaultPrevented:"returnValue"in i?i.returnValue===!1:i.getPreventDefault&&i.getPreventDefault())&&(e.isDefaultPrevented=x)),e}function S(t){var e,i={originalEvent:t};for(e in t)w.test(e)||t[e]===n||(i[e]=t[e]);return j(i,t)}var n,e=1,i=Array.prototype.slice,r=t.isFunction,o=function(t){return"string"==typeof t},s={},a={},u="onfocusin"in window,f={focus:"focusin",blur:"focusout"},c={mouseenter:"mouseover",mouseleave:"mouseout"};a.click=a.mousedown=a.mouseup=a.mousemove="MouseEvents",t.event={add:v,remove:y},t.proxy=function(e,n){var s=2 in arguments&&i.call(arguments,2);if(r(e)){var a=function(){return e.apply(n,s?s.concat(i.call(arguments)):arguments)};return a._zid=l(e),a}if(o(n))return s?(s.unshift(e[n],e),t.proxy.apply(null,s)):t.proxy(e[n],e);throw new TypeError("expected function")},t.fn.bind=function(t,e,n){return this.on(t,e,n)},t.fn.unbind=function(t,e){return this.off(t,e)},t.fn.one=function(t,e,n,i){return this.on(t,e,n,i,1)};var x=function(){return!0},b=function(){return!1},w=/^([A-Z]|returnValue$|layer[XY]$)/,E={preventDefault:"isDefaultPrevented",stopImmediatePropagation:"isImmediatePropagationStopped",stopPropagation:"isPropagationStopped"};t.fn.delegate=function(t,e,n){return this.on(e,t,n)},t.fn.undelegate=function(t,e,n){return this.off(e,t,n)},t.fn.live=function(e,n){return t(document.body).delegate(this.selector,e,n),this},t.fn.die=function(e,n){return t(document.body).undelegate(this.selector,e,n),this},t.fn.on=function(e,s,a,u,f){var c,l,h=this;return e&&!o(e)?(t.each(e,function(t,e){h.on(t,s,a,e,f)}),h):(o(s)||r(u)||u===!1||(u=a,a=s,s=n),(r(a)||a===!1)&&(u=a,a=n),u===!1&&(u=b),h.each(function(n,r){f&&(c=function(t){return y(r,t.type,u),u.apply(this,arguments)}),s&&(l=function(e){var n,o=t(e.target).closest(s,r).get(0);return o&&o!==r?(n=t.extend(S(e),{currentTarget:o,liveFired:r}),(c||u).apply(o,[n].concat(i.call(arguments,1)))):void 0}),v(r,e,u,a,s,l||c)}))},t.fn.off=function(e,i,s){var a=this;return e&&!o(e)?(t.each(e,function(t,e){a.off(t,i,e)}),a):(o(i)||r(s)||s===!1||(s=i,i=n),s===!1&&(s=b),a.each(function(){y(this,e,s,i)}))},t.fn.trigger=function(e,n){return e=o(e)||t.isPlainObject(e)?t.Event(e):j(e),e._args=n,this.each(function(){e.type in f&&"function"==typeof this[e.type]?this[e.type]():"dispatchEvent"in this?this.dispatchEvent(e):t(this).triggerHandler(e,n)})},t.fn.triggerHandler=function(e,n){var i,r;return this.each(function(s,a){i=S(o(e)?t.Event(e):e),i._args=n,i.target=a,t.each(h(a,e.type||e),function(t,e){return r=e.proxy(i),i.isImmediatePropagationStopped()?!1:void 0})}),r},"focusin focusout focus blur load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select keydown keypress keyup error".split(" ").forEach(function(e){t.fn[e]=function(t){return 0 in arguments?this.bind(e,t):this.trigger(e)}}),t.Event=function(t,e){o(t)||(e=t,t=e.type);var n=document.createEvent(a[t]||"Events"),i=!0;if(e)for(var r in e)"bubbles"==r?i=!!e[r]:n[r]=e[r];return n.initEvent(t,i,!0),j(n)}}(Zepto),function(t){function h(e,n,i){var r=t.Event(n);return t(e).trigger(r,i),!r.isDefaultPrevented()}function p(t,e,i,r){return t.global?h(e||n,i,r):void 0}function d(e){e.global&&0===t.active++&&p(e,null,"ajaxStart")}function m(e){e.global&&!--t.active&&p(e,null,"ajaxStop")}function g(t,e){var n=e.context;return e.beforeSend.call(n,t,e)===!1||p(e,n,"ajaxBeforeSend",[t,e])===!1?!1:void p(e,n,"ajaxSend",[t,e])}function v(t,e,n,i){var r=n.context,o="success";n.success.call(r,t,o,e),i&&i.resolveWith(r,[t,o,e]),p(n,r,"ajaxSuccess",[e,n,t]),x(o,e,n)}function y(t,e,n,i,r){var o=i.context;i.error.call(o,n,e,t),r&&r.rejectWith(o,[n,e,t]),p(i,o,"ajaxError",[n,i,t||e]),x(e,n,i)}function x(t,e,n){var i=n.context;n.complete.call(i,e,t),p(n,i,"ajaxComplete",[e,n]),m(n)}function b(){}function w(t){return t&&(t=t.split(";",2)[0]),t&&(t==f?"html":t==u?"json":s.test(t)?"script":a.test(t)&&"xml")||"text"}function E(t,e){return""==e?t:(t+"&"+e).replace(/[&?]{1,2}/,"?")}function j(e){e.processData&&e.data&&"string"!=t.type(e.data)&&(e.data=t.param(e.data,e.traditional)),!e.data||e.type&&"GET"!=e.type.toUpperCase()||(e.url=E(e.url,e.data),e.data=void 0)}function S(e,n,i,r){return t.isFunction(n)&&(r=i,i=n,n=void 0),t.isFunction(i)||(r=i,i=void 0),{url:e,data:n,success:i,dataType:r}}function C(e,n,i,r){var o,s=t.isArray(n),a=t.isPlainObject(n);t.each(n,function(n,u){o=t.type(u),r&&(n=i?r:r+"["+(a||"object"==o||"array"==o?n:"")+"]"),!r&&s?e.add(u.name,u.value):"array"==o||!i&&"object"==o?C(e,u,i,n):e.add(n,u)})}var i,r,e=0,n=window.document,o=/