拆分anot框架和UI库; 同时调整目录结构; 更新打包配置以支持next版
parent
8bf5c2d272
commit
742f3f0292
119
build.dev.js
119
build.dev.js
|
@ -28,104 +28,75 @@ const jsOpt = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
const cssOpt = {
|
const cssOpt = {
|
||||||
includePaths: ['src/css/'],
|
// includePaths: ['src/css/'],
|
||||||
outputStyle: 'compressed'
|
outputStyle: 'compressed'
|
||||||
}
|
}
|
||||||
|
|
||||||
const compileJs = (entry, output) => {
|
const compileJs = (entry, output) => {
|
||||||
if (/touch\.patch/.test(entry)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
if (/anot/.test(entry)) {
|
|
||||||
fs.cp(entry, output)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
let { code } = babel.transformFileSync(entry, jsOpt)
|
|
||||||
code = code.replace(/\.scss/g, '.css')
|
|
||||||
fs.echo(code, output)
|
|
||||||
} catch (err) {
|
|
||||||
return log(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
log('编译JS: %s', chalk.green(entry))
|
log('编译JS: %s', chalk.green(entry))
|
||||||
|
try {
|
||||||
|
let { code } = babel.transformFileSync(entry, jsOpt)
|
||||||
|
code = code.replace(/\.scss/g, '.css')
|
||||||
|
fs.echo(code, output)
|
||||||
|
} catch (err) {
|
||||||
|
return log(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const compileCss = (entry, output) => {
|
const compileCss = (entry, output) => {
|
||||||
setTimeout(() => {
|
|
||||||
try {
|
|
||||||
const { css } = scss.renderSync({ ...cssOpt, file: entry })
|
|
||||||
prefixer.process(css, { from: '', to: '' }).then(result => {
|
|
||||||
fs.echo(result.css, output)
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
log(err)
|
|
||||||
}
|
|
||||||
}, 100)
|
|
||||||
log('编译scss: %s', chalk.green(entry))
|
log('编译scss: %s', chalk.green(entry))
|
||||||
}
|
try {
|
||||||
|
const { css } = scss.renderSync({ ...cssOpt, file: entry })
|
||||||
const compileHtm = (entry, output) => {
|
prefixer.process(css, { from: '', to: '' }).then(result => {
|
||||||
setTimeout(() => {
|
fs.echo(result.css, output)
|
||||||
let htm = fs.cat(entry).toString('utf8')
|
})
|
||||||
htm = htm.replace(/[\r\n\t]+/g, ' ').replace(/\s{2,}/g, ' ')
|
} catch (err) {
|
||||||
fs.echo(htm, output)
|
log(err)
|
||||||
}, 100)
|
}
|
||||||
log('压缩HTML: %s', chalk.green(entry))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*=======================================================*/
|
/*=======================================================*/
|
||||||
/*===== ===*/
|
/*===== ===*/
|
||||||
/*=======================================================*/
|
/*=======================================================*/
|
||||||
|
|
||||||
const jsFiles = fs.ls('./src/js/', true)
|
|
||||||
const cssFiles = fs.ls('./src/css/', true)
|
|
||||||
|
|
||||||
// 字体文件直接复制
|
|
||||||
chokidar.watch(path.join(sourceDir, 'font/')).on('all', (act, file) => {
|
|
||||||
if (act === 'add' || act === 'change') {
|
|
||||||
let output = file.replace('src/font/', 'dist/font/')
|
|
||||||
fs.cp(file, output)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// css目录
|
|
||||||
chokidar.watch(path.resolve(sourceDir, 'css/')).on('all', (act, file) => {
|
|
||||||
if (act === 'add' || act === 'change') {
|
|
||||||
if (/\.scss$/.test(file)) {
|
|
||||||
let output = file
|
|
||||||
.replace('src/css/', 'dist/css/')
|
|
||||||
.replace('.scss', '.css')
|
|
||||||
|
|
||||||
compileCss(file, output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// js目录的处理要复杂一点
|
|
||||||
chokidar
|
chokidar
|
||||||
.watch(path.resolve(sourceDir, 'js/'))
|
.watch(sourceDir)
|
||||||
.on('all', (act, file) => {
|
.on('all', (act, file) => {
|
||||||
|
return
|
||||||
if (act === 'add' || act === 'change') {
|
if (act === 'add' || act === 'change') {
|
||||||
let output = file.replace('src/js/', 'dist/js/')
|
let entry = file
|
||||||
let ext = file.slice(file.lastIndexOf('.') + 1)
|
let output = file.replace('src/', 'dist/')
|
||||||
switch (ext) {
|
|
||||||
case 'js':
|
file = path.parse(entry)
|
||||||
compileJs(file, output)
|
if (!file.ext || file.base === '.DS_Store' || file.base === 'var.scss') {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (file.ext) {
|
||||||
|
case '.js':
|
||||||
|
compileJs(entry, output)
|
||||||
break
|
break
|
||||||
case 'scss':
|
case '.scss':
|
||||||
output = output.replace(/scss$/, 'css')
|
output = output.replace(/\.scss$/, '.css')
|
||||||
compileCss(file, output)
|
compileCss(entry, output)
|
||||||
break
|
|
||||||
case 'htm':
|
|
||||||
compileHtm(file, output)
|
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
fs.cp(file, output)
|
fs.cp(entry, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on('ready', () => {
|
.on('ready', () => {
|
||||||
log(chalk.red('预处理完成,监听文件变化中,请勿关闭本窗口...'))
|
log(chalk.red('预处理完成,监听文件变化中,请勿关闭本窗口...'))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
chokidar
|
||||||
|
.watch(path.resolve('./node_modules/anot/dist/'))
|
||||||
|
.on('all', (act, file) => {
|
||||||
|
if (act === 'add' || act === 'change') {
|
||||||
|
log('复制: %s', chalk.green(file))
|
||||||
|
fs.cp(file, path.resolve(buildDir, path.parse(file).base))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('ready', () => {
|
||||||
|
log('复制anot框架文件完成...')
|
||||||
|
})
|
||||||
|
|
|
@ -12,7 +12,7 @@ const sourceDir = path.resolve(__dirname, 'src')
|
||||||
const buildDir = path.resolve(__dirname, 'dist')
|
const buildDir = path.resolve(__dirname, 'dist')
|
||||||
|
|
||||||
const cssOpt = {
|
const cssOpt = {
|
||||||
includePaths: ['src/css/'],
|
// includePaths: ['src/css/'],
|
||||||
outputStyle: 'compressed'
|
outputStyle: 'compressed'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ const compileJs = (entry, output) => {
|
||||||
.replace(/\.scss/g, '.css')
|
.replace(/\.scss/g, '.css')
|
||||||
.replace(/import"([a-z0-9/.]*)(?<!\.css)"/g, 'import "$1.js"')
|
.replace(/import"([a-z0-9/.]*)(?<!\.css)"/g, 'import "$1.js"')
|
||||||
.replace(/import ([\w]*) from"([a-z0-9/.]*)"/g, 'import $1 from "$2.js"')
|
.replace(/import ([\w]*) from"([a-z0-9/.]*)"/g, 'import $1 from "$2.js"')
|
||||||
|
.replace(/import"(([a-z0-9/.]*\.css))"/g, 'importCss("/$1")')
|
||||||
log(
|
log(
|
||||||
'编译JS: %s, 耗时 %s ms',
|
'编译JS: %s, 耗时 %s ms',
|
||||||
chalk.green(entry),
|
chalk.green(entry),
|
||||||
|
@ -47,59 +48,52 @@ const compileCss = (entry, output) => {
|
||||||
fs.echo(css, output)
|
fs.echo(css, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
const compileHtm = (entry, output) => {
|
|
||||||
let t1 = Date.now()
|
|
||||||
let htm = fs.cat(entry).toString('utf8')
|
|
||||||
htm = htm.replace(/[\r\n\t]+/g, ' ').replace(/\s{2,}/g, ' ')
|
|
||||||
log(
|
|
||||||
'压缩HTML: %s, 耗时 %s ms',
|
|
||||||
chalk.green(entry),
|
|
||||||
chalk.yellow(Date.now() - t1)
|
|
||||||
)
|
|
||||||
fs.echo(htm, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=======================================================*/
|
/*=======================================================*/
|
||||||
/*===== ===*/
|
/*===== ===*/
|
||||||
/*=======================================================*/
|
/*=======================================================*/
|
||||||
|
|
||||||
const jsFiles = fs.ls('./src/js/', true)
|
|
||||||
const cssFiles = fs.ls('./src/css/', true)
|
|
||||||
|
|
||||||
if (fs.isdir(buildDir)) {
|
if (fs.isdir(buildDir)) {
|
||||||
fs.rm(buildDir, true)
|
fs.rm(buildDir, true)
|
||||||
log(chalk.cyan('清除旧目录 dist/'))
|
log(chalk.cyan('清除旧目录 dist/'))
|
||||||
}
|
}
|
||||||
|
fs.mkdir(buildDir)
|
||||||
|
|
||||||
// css目录
|
let list = fs.ls('./node_modules/anot/dist/')
|
||||||
cssFiles.forEach(file => {
|
list.forEach(it => {
|
||||||
if (/\.scss$/.test(file)) {
|
fs.cp(it, path.resolve(buildDir, path.parse(it).base))
|
||||||
let entry = file
|
|
||||||
let output = file.replace('src/css', 'dist/css').replace(/scss$/, 'css')
|
|
||||||
|
|
||||||
compileCss(entry, output)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// js目录的处理要复杂一点
|
log('复制anot框架文件完成...')
|
||||||
jsFiles.forEach(file => {
|
|
||||||
let entry = file
|
|
||||||
let output = file.replace(/src\/js/, 'dist/js').replace(/scss$/, 'css')
|
|
||||||
let ext = file.slice(file.lastIndexOf('.') + 1)
|
|
||||||
|
|
||||||
switch (ext) {
|
/*----------------------------------------------*/
|
||||||
case 'js':
|
/*----------------------------------------------*/
|
||||||
|
/*----------------------------------------------*/
|
||||||
|
|
||||||
|
let files = fs.ls(sourceDir, true)
|
||||||
|
files = files.map(it => {
|
||||||
|
let file = path.parse(it)
|
||||||
|
if (!file.ext || file.base === '.DS_Store' || file.base === 'var.scss') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return { path: it, ext: file.ext, name: file.base }
|
||||||
|
})
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
if (!file) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let entry = file.path
|
||||||
|
let output = file.path.replace('src/', 'dist/')
|
||||||
|
|
||||||
|
switch (file.ext) {
|
||||||
|
case '.js':
|
||||||
compileJs(entry, output)
|
compileJs(entry, output)
|
||||||
break
|
break
|
||||||
case 'scss':
|
case '.scss':
|
||||||
|
output = output.replace(/\.scss$/, '.css')
|
||||||
compileCss(entry, output)
|
compileCss(entry, output)
|
||||||
break
|
break
|
||||||
case 'htm':
|
|
||||||
compileHtm(entry, output)
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
if (!fs.isdir(entry)) {
|
fs.cp(entry, output)
|
||||||
fs.cp(entry, output)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -28,29 +28,25 @@ const jsOpt = {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
const cssOpt = {
|
const cssOpt = {
|
||||||
includePaths: ['src/css/'],
|
// includePaths: ['src/css/'],
|
||||||
outputStyle: 'compressed'
|
outputStyle: 'compressed'
|
||||||
}
|
}
|
||||||
|
|
||||||
const compileJs = (entry, output) => {
|
const compileJs = (entry, output) => {
|
||||||
if (/touch\.patch/.test(entry)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let t1 = Date.now()
|
let t1 = Date.now()
|
||||||
let tmpOpt = jsOpt
|
try {
|
||||||
let code = ''
|
let { code } = babel.transformFileSync(entry, jsOpt)
|
||||||
if (!/anot/.test(entry)) {
|
code = uglify.minify(code).code.replace(/\.scss/g, '.css')
|
||||||
code = babel.transformFileSync(entry, jsOpt).code
|
|
||||||
} else {
|
log(
|
||||||
code = fs.cat(entry).toString()
|
'编译JS: %s, 耗时 %s ms',
|
||||||
|
chalk.green(entry),
|
||||||
|
chalk.yellow(Date.now() - t1)
|
||||||
|
)
|
||||||
|
fs.echo(code, output)
|
||||||
|
} catch (err) {
|
||||||
|
return log(err)
|
||||||
}
|
}
|
||||||
code = uglify.minify(code).code.replace(/\.scss/g, '.css')
|
|
||||||
log(
|
|
||||||
'编译JS: %s, 耗时 %s ms',
|
|
||||||
chalk.green(entry),
|
|
||||||
chalk.yellow(Date.now() - t1)
|
|
||||||
)
|
|
||||||
fs.echo(code, output)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const compileCss = (entry, output) => {
|
const compileCss = (entry, output) => {
|
||||||
|
@ -66,59 +62,52 @@ const compileCss = (entry, output) => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const compileHtm = (entry, output) => {
|
|
||||||
let t1 = Date.now()
|
|
||||||
let htm = fs.cat(entry).toString('utf8')
|
|
||||||
htm = htm.replace(/[\r\n\t]+/g, ' ').replace(/\s{2,}/g, ' ')
|
|
||||||
log(
|
|
||||||
'压缩HTML: %s, 耗时 %s ms',
|
|
||||||
chalk.green(entry),
|
|
||||||
chalk.yellow(Date.now() - t1)
|
|
||||||
)
|
|
||||||
fs.echo(htm, output)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*=======================================================*/
|
/*=======================================================*/
|
||||||
/*===== ===*/
|
/*===== ===*/
|
||||||
/*=======================================================*/
|
/*=======================================================*/
|
||||||
|
|
||||||
const jsFiles = fs.ls('./src/js/', true)
|
|
||||||
const cssFiles = fs.ls('./src/css/', true)
|
|
||||||
|
|
||||||
if (fs.isdir(buildDir)) {
|
if (fs.isdir(buildDir)) {
|
||||||
fs.rm(buildDir, true)
|
fs.rm(buildDir, true)
|
||||||
log(chalk.cyan('清除旧目录 dist/'))
|
log(chalk.cyan('清除旧目录 dist/'))
|
||||||
}
|
}
|
||||||
|
fs.mkdir(buildDir)
|
||||||
|
|
||||||
// css目录
|
let list = fs.ls('./node_modules/anot/dist/')
|
||||||
cssFiles.forEach(file => {
|
list.forEach(it => {
|
||||||
if (/\.scss$/.test(file)) {
|
fs.cp(it, path.resolve(buildDir, path.parse(it).base))
|
||||||
let entry = file
|
|
||||||
let output = file.replace('src/css', 'dist/css').replace(/scss$/, 'css')
|
|
||||||
|
|
||||||
compileCss(entry, output)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// js目录的处理要复杂一点
|
log('复制anot框架文件完成...')
|
||||||
jsFiles.forEach(file => {
|
|
||||||
let entry = file
|
|
||||||
let output = file.replace(/src\/js/, 'dist/js').replace(/scss$/, 'css')
|
|
||||||
let ext = file.slice(file.lastIndexOf('.') + 1)
|
|
||||||
|
|
||||||
switch (ext) {
|
/*----------------------------------------------*/
|
||||||
case 'js':
|
/*----------------------------------------------*/
|
||||||
|
/*----------------------------------------------*/
|
||||||
|
|
||||||
|
let files = fs.ls(sourceDir, true)
|
||||||
|
files = files.map(it => {
|
||||||
|
let file = path.parse(it)
|
||||||
|
if (!file.ext || file.base === '.DS_Store' || file.base === 'var.scss') {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
return { path: it, ext: file.ext, name: file.base }
|
||||||
|
})
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
if (!file) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let entry = file.path
|
||||||
|
let output = file.path.replace('src/', 'dist/')
|
||||||
|
|
||||||
|
switch (file.ext) {
|
||||||
|
case '.js':
|
||||||
compileJs(entry, output)
|
compileJs(entry, output)
|
||||||
break
|
break
|
||||||
case 'scss':
|
case '.scss':
|
||||||
|
output = output.replace(/\.scss$/, '.css')
|
||||||
compileCss(entry, output)
|
compileCss(entry, output)
|
||||||
break
|
break
|
||||||
case 'htm':
|
|
||||||
compileHtm(entry, output)
|
|
||||||
break
|
|
||||||
default:
|
default:
|
||||||
if (!fs.isdir(entry)) {
|
fs.cp(entry, output)
|
||||||
fs.cp(entry, output)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
@ -1,3 +1,9 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @authors yutent (yutent@doui.cc)
|
||||||
|
* @date 2018-08-04 18:47:35
|
||||||
|
*/
|
||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
function CodeMirror(place, givenOptions) {
|
function CodeMirror(place, givenOptions) {
|
|
@ -1,5 +1,13 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @authors yutent (yutent@doui.cc)
|
||||||
|
* @date 2018-08-04 18:47:35
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
import CodeMirror from './codemirror'
|
import CodeMirror from './codemirror'
|
||||||
import './theme-dark.scss'
|
import 'css/codemirror-dark.scss'
|
||||||
|
|
||||||
CodeMirror.defineMode(
|
CodeMirror.defineMode(
|
||||||
'htmlmixed',
|
'htmlmixed',
|
||||||
|
@ -108,7 +116,9 @@ CodeMirror.defineMode(
|
||||||
var mode =
|
var mode =
|
||||||
state.token == html
|
state.token == html
|
||||||
? htmlMode
|
? htmlMode
|
||||||
: state.token == javascript ? jsMode : cssMode
|
: state.token == javascript
|
||||||
|
? jsMode
|
||||||
|
: cssMode
|
||||||
return {
|
return {
|
||||||
state: state.localState || state.htmlState,
|
state: state.localState || state.htmlState,
|
||||||
mode: mode
|
mode: mode
|
||||||
|
@ -120,11 +130,12 @@ CodeMirror.defineMode(
|
||||||
'javascript',
|
'javascript',
|
||||||
'css'
|
'css'
|
||||||
)
|
)
|
||||||
|
|
||||||
CodeMirror.defineMIME('text/html', 'htmlmixed')
|
CodeMirror.defineMIME('text/html', 'htmlmixed')
|
||||||
|
|
||||||
CodeMirror.defineMode('css', function(config) {
|
CodeMirror.defineMode('css', function(config) {
|
||||||
var indentUnit = config.indentUnit,
|
var indentUnit = config.indentUnit
|
||||||
type
|
var type
|
||||||
var atMediaTypes = keySet([
|
var atMediaTypes = keySet([
|
||||||
'all',
|
'all',
|
||||||
'aural',
|
'aural',
|
||||||
|
@ -909,7 +920,9 @@ CodeMirror.defineMode('css', function(config) {
|
||||||
|
|
||||||
function keySet(array) {
|
function keySet(array) {
|
||||||
var keys = {}
|
var keys = {}
|
||||||
for (var i = 0; i < array.length; ++i) keys[array[i]] = true
|
for (var i = 0; i < array.length; ++i) {
|
||||||
|
keys[array[i]] = true
|
||||||
|
}
|
||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,8 +979,8 @@ CodeMirror.defineMode('css', function(config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function tokenCComment(stream, state) {
|
function tokenCComment(stream, state) {
|
||||||
var maybeEnd = false,
|
var maybeEnd = false
|
||||||
ch
|
var ch
|
||||||
while ((ch = stream.next()) != null) {
|
while ((ch = stream.next()) != null) {
|
||||||
if (maybeEnd && ch == '/') {
|
if (maybeEnd && ch == '/') {
|
||||||
state.tokenize = tokenBase
|
state.tokenize = tokenBase
|
||||||
|
@ -993,13 +1006,17 @@ CodeMirror.defineMode('css', function(config) {
|
||||||
|
|
||||||
function tokenString(quote) {
|
function tokenString(quote) {
|
||||||
return function(stream, state) {
|
return function(stream, state) {
|
||||||
var escaped = false,
|
var escaped = false
|
||||||
ch
|
var ch
|
||||||
while ((ch = stream.next()) != null) {
|
while ((ch = stream.next()) != null) {
|
||||||
if (ch == quote && !escaped) break
|
if (ch == quote && !escaped) {
|
||||||
|
break
|
||||||
|
}
|
||||||
escaped = !escaped && ch == '\\'
|
escaped = !escaped && ch == '\\'
|
||||||
}
|
}
|
||||||
if (!escaped) state.tokenize = tokenBase
|
if (!escaped) {
|
||||||
|
state.tokenize = tokenBase
|
||||||
|
}
|
||||||
return ret('string', 'string')
|
return ret('string', 'string')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1103,10 +1120,11 @@ CodeMirror.defineMode('css', function(config) {
|
||||||
return style
|
return style
|
||||||
},
|
},
|
||||||
indent: function(state, textAfter) {
|
indent: function(state, textAfter) {
|
||||||
var n = state.stack.length
|
var len = state.stack.length
|
||||||
if (/^\}/.test(textAfter))
|
if (/^\}/.test(textAfter)) {
|
||||||
n -= state.stack[state.stack.length - 1] == 'propertyValue' ? 2 : 1
|
len -= state.stack[state.stack.length - 1] == 'propertyValue' ? 2 : 1
|
||||||
return state.baseIndent + n * indentUnit
|
}
|
||||||
|
return state.baseIndent + len * indentUnit
|
||||||
},
|
},
|
||||||
electricChars: '}'
|
electricChars: '}'
|
||||||
}
|
}
|
||||||
|
@ -1956,7 +1974,9 @@ CodeMirror.defineMode('xml', function(config, parserConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function popContext() {
|
function popContext() {
|
||||||
if (curState.context) curState.context = curState.context.prev
|
if (curState.context) {
|
||||||
|
curState.context = curState.context.prev
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function element(type) {
|
function element(type) {
|
||||||
|
@ -2114,9 +2134,10 @@ CodeMirror.defineMode('xml', function(config, parserConfig) {
|
||||||
})
|
})
|
||||||
CodeMirror.defineMIME('text/xml', 'xml')
|
CodeMirror.defineMIME('text/xml', 'xml')
|
||||||
CodeMirror.defineMIME('application/xml', 'xml')
|
CodeMirror.defineMIME('application/xml', 'xml')
|
||||||
if (!CodeMirror.mimeModes.hasOwnProperty('text/html'))
|
if (!CodeMirror.mimeModes.hasOwnProperty('text/html')) {
|
||||||
CodeMirror.defineMIME('text/html', {
|
CodeMirror.defineMIME('text/html', {
|
||||||
name: 'xml',
|
name: 'xml',
|
||||||
htmlMode: true
|
htmlMode: true
|
||||||
})
|
})
|
||||||
|
}
|
||||||
export default CodeMirror
|
export default CodeMirror
|
|
@ -0,0 +1,103 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @authors yutent (yutent@doui.cc)
|
||||||
|
* @date 2016-08-19 10:38:25
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
define(['avalon'], function(av) {
|
||||||
|
av.component('do:count', {
|
||||||
|
$replace: true,
|
||||||
|
$template:
|
||||||
|
'<ul class="do-ui-count"><li class="num-box" ms-repeat-obj="list" ms-class="split:obj.opt === 0"><span class="num" ms-repeat="obj.val">{{el}}</span></li></ul>',
|
||||||
|
maxLen: 8,
|
||||||
|
speed: 1,
|
||||||
|
update: av.noop,
|
||||||
|
list: [],
|
||||||
|
$list: [],
|
||||||
|
total: 0,
|
||||||
|
style: 2,
|
||||||
|
$construct: function(opt, a, b) {
|
||||||
|
var vm = av.mix(a, b)
|
||||||
|
document.head.insertAdjacentHTML(
|
||||||
|
'afterBegin',
|
||||||
|
'<style>' +
|
||||||
|
'.do-ui-count {width: 100%;height: 50px;text-align:center;}' +
|
||||||
|
'.do-ui-count li.num-box {overflow:hidden;display: inline-block;position: relative;width: 40px;height: 50px;margin:0 15px;line-height: 50px;background: #09f;font-size: 30px;}' +
|
||||||
|
'.do-ui-count li.num-box .num {display: block;width: 100%;height: 50px;margin-top: 0;transition: .3s ease-in-out}' +
|
||||||
|
'.do-ui-count li.num-box.split {width: auto;margin:0;background: none;}' +
|
||||||
|
'</style>'
|
||||||
|
)
|
||||||
|
|
||||||
|
vm.total = vm.total >> 0
|
||||||
|
vm.maxLen = vm.maxLen || 8
|
||||||
|
|
||||||
|
return av.mix(opt, vm)
|
||||||
|
},
|
||||||
|
$ready: function(vm, ele) {
|
||||||
|
function updateList(val) {
|
||||||
|
val = numberFormat(val, vm.maxLen)
|
||||||
|
|
||||||
|
vm.$list = []
|
||||||
|
vm.$list = val.split('')
|
||||||
|
if (vm.style === 2) {
|
||||||
|
vm.$list = vm.$list.reverse()
|
||||||
|
val = vm.$list.join('').replace(/([\d,]{3})/g, '$1,')
|
||||||
|
val = val.replace(/^,|,$/g, '')
|
||||||
|
vm.$list = val.split('').reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.$list.forEach(function(it, i) {
|
||||||
|
if (it === ',') {
|
||||||
|
if (!vm.list[i]) vm.list.push({ opt: 0, val: [it] })
|
||||||
|
} else {
|
||||||
|
if (vm.list[i]) {
|
||||||
|
if (it !== vm.list[i].last) {
|
||||||
|
vm.list[i].last = it
|
||||||
|
vm.list[i].val.push(it)
|
||||||
|
var curr = ele.querySelectorAll('.num-box')[i]
|
||||||
|
curr.querySelector('.num').style.marginTop =
|
||||||
|
vm.speed * 50 + 'px'
|
||||||
|
setTimeout(function() {
|
||||||
|
vm.list[i].val.shift()
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vm.list.push({ opt: 1, last: it, val: [it] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateList(vm.total)
|
||||||
|
|
||||||
|
vm.update = function(val) {
|
||||||
|
if (val < 0)
|
||||||
|
//确定滚动方向
|
||||||
|
vm.speed = 1
|
||||||
|
else vm.speed = -1
|
||||||
|
|
||||||
|
vm.total = vm.total - 0 + val
|
||||||
|
}
|
||||||
|
|
||||||
|
vm.$watch('total', function(n, o) {
|
||||||
|
if (n === o) return
|
||||||
|
|
||||||
|
updateList(n)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
//数字长度补全(前面加0)
|
||||||
|
function numberFormat(num, len) {
|
||||||
|
num += ''
|
||||||
|
if (num.length >= len) return num
|
||||||
|
|
||||||
|
while (num.length < len) num = '0' + num
|
||||||
|
return num
|
||||||
|
}
|
||||||
|
|
||||||
|
return av
|
||||||
|
})
|
|
@ -6,8 +6,7 @@
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import "../../../css/var.scss";
|
@import "var.scss";
|
||||||
// @import "../../../css/reset.scss";
|
|
||||||
|
|
||||||
.do-sliders {position: relative;height: 100%;width: 100%;
|
.do-sliders {position: relative;height: 100%;width: 100%;
|
||||||
.skin{height: 100%}
|
.skin{height: 100%}
|
|
@ -6,7 +6,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@import '../../css/var.scss';
|
@import 'var.scss';
|
||||||
|
|
||||||
|
|
||||||
.do-tree {overflow:hidden;overflow-y:auto;position:relative;display:block;width:100%;height:100%;line-height:30px;font-size:15px;color:nth($cd, 2);
|
.do-tree {overflow:hidden;overflow-y:auto;position:relative;display:block;width:100%;height:100%;line-height:30px;font-size:15px;color:nth($cd, 2);
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import './style.scss'
|
import 'css/datepicker.scss'
|
||||||
|
|
||||||
/**************** 公共函数 *****************/
|
/**************** 公共函数 *****************/
|
||||||
//计算日历数组
|
//计算日历数组
|
|
@ -5,7 +5,7 @@
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './style.scss'
|
import 'css/form.scss'
|
||||||
const log = console.log
|
const log = console.log
|
||||||
|
|
||||||
Anot.ui.form = '0.1.0'
|
Anot.ui.form = '0.1.0'
|
6923
src/js/anot-touch.js
6923
src/js/anot-touch.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
6333
src/js/anot.js
6333
src/js/anot.js
File diff suppressed because it is too large
Load Diff
7035
src/js/anot.shim.js
7035
src/js/anot.shim.js
File diff suppressed because it is too large
Load Diff
|
@ -1,153 +0,0 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @authors yutent (yutent@doui.cc)
|
|
||||||
* @date 2016-08-19 10:38:25
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
|
|
||||||
define(['avalon'], function(av){
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
av.component('do:count', {
|
|
||||||
$replace: true,
|
|
||||||
$template: '<ul class="do-ui-count"><li class="num-box" ms-repeat-obj="list" ms-class="split:obj.opt === 0"><span class="num" ms-repeat="obj.val">{{el}}</span></li></ul>',
|
|
||||||
maxLen: 8,
|
|
||||||
speed: 1,
|
|
||||||
update: av.noop,
|
|
||||||
list: [],
|
|
||||||
$list: [],
|
|
||||||
total: 0,
|
|
||||||
style: 2,
|
|
||||||
$construct: function(opt, a, b){
|
|
||||||
var vm = av.mix(a, b)
|
|
||||||
document.head.insertAdjacentHTML('afterBegin', '<style>' +
|
|
||||||
'.do-ui-count {width: 100%;height: 50px;text-align:center;}' +
|
|
||||||
'.do-ui-count li.num-box {overflow:hidden;display: inline-block;position: relative;width: 40px;height: 50px;margin:0 15px;line-height: 50px;background: #09f;font-size: 30px;}' +
|
|
||||||
'.do-ui-count li.num-box .num {display: block;width: 100%;height: 50px;margin-top: 0;transition: .3s ease-in-out}' +
|
|
||||||
'.do-ui-count li.num-box.split {width: auto;margin:0;background: none;}' +
|
|
||||||
'</style>')
|
|
||||||
|
|
||||||
vm.total = vm.total >> 0
|
|
||||||
vm.maxLen = vm.maxLen || 8
|
|
||||||
|
|
||||||
return av.mix(opt, vm)
|
|
||||||
},
|
|
||||||
$ready: function(vm, ele){
|
|
||||||
|
|
||||||
function updateList(val){
|
|
||||||
val = numberFormat(val, vm.maxLen)
|
|
||||||
|
|
||||||
vm.$list = []
|
|
||||||
vm.$list = val.split('')
|
|
||||||
if(vm.style === 2){
|
|
||||||
vm.$list = vm.$list.reverse()
|
|
||||||
val = vm.$list.join('').replace(/([\d,]{3})/g, '$1,')
|
|
||||||
val = val.replace(/^,|,$/g, '')
|
|
||||||
vm.$list = val.split('').reverse()
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.$list.forEach(function(it, i){
|
|
||||||
|
|
||||||
if(it === ','){
|
|
||||||
if(!vm.list[i])
|
|
||||||
vm.list.push({opt: 0, val: [it]})
|
|
||||||
|
|
||||||
}else{
|
|
||||||
if(vm.list[i]){
|
|
||||||
if(it !== vm.list[i].last){
|
|
||||||
vm.list[i].last = it
|
|
||||||
vm.list[i].val.push(it)
|
|
||||||
var curr = ele.querySelectorAll('.num-box')[i]
|
|
||||||
curr.querySelector('.num').style.marginTop = vm.speed * 50 + 'px'
|
|
||||||
setTimeout(function(){
|
|
||||||
vm.list[i].val.shift()
|
|
||||||
}, 300)
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
vm.list.push({opt: 1, last: it, val: [it]})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
updateList(vm.total)
|
|
||||||
|
|
||||||
vm.update = function(val){
|
|
||||||
if(val < 0) //确定滚动方向
|
|
||||||
vm.speed = 1
|
|
||||||
else
|
|
||||||
vm.speed = -1
|
|
||||||
|
|
||||||
|
|
||||||
vm.total = (vm.total - 0) + val
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vm.$watch('total', function(n, o){
|
|
||||||
|
|
||||||
if(n === o)
|
|
||||||
return
|
|
||||||
|
|
||||||
updateList(n)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//数字长度补全(前面加0)
|
|
||||||
function numberFormat(num, len){
|
|
||||||
num += ''
|
|
||||||
if(num.length >= len)
|
|
||||||
return num
|
|
||||||
|
|
||||||
while(num.length < len)
|
|
||||||
num = '0' + num
|
|
||||||
return num
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return av
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
|
@ -1,584 +0,0 @@
|
||||||
var ua = navigator.userAgent.toLowerCase()
|
|
||||||
//http://stackoverflow.com/questions/9038625/detect-if-device-is-ios
|
|
||||||
function iOSversion() {
|
|
||||||
//https://developer.apple.com/library/prerelease/mac/releasenotes/General/WhatsNewInSafari/Articles/Safari_9.html
|
|
||||||
//http://mp.weixin.qq.com/s?__biz=MzA3MDQ4MzQzMg==&mid=256900619&idx=1&sn=b29f84cff0b8d7b9742e5d8b3cd8f218&scene=1&srcid=1009F9l4gh9nZ7rcQJEhmf7Q#rd
|
|
||||||
if (/ipad|iphone|ipod/.test(ua) && !window.MSStream) {
|
|
||||||
if ('backdropFilter' in document.documentElement.style) {
|
|
||||||
return 9
|
|
||||||
}
|
|
||||||
if (!!window.indexedDB) {
|
|
||||||
return 8
|
|
||||||
}
|
|
||||||
if (!!window.SpeechSynthesisUtterance) {
|
|
||||||
return 7
|
|
||||||
}
|
|
||||||
if (!!window.webkitAudioContext) {
|
|
||||||
return 6
|
|
||||||
}
|
|
||||||
if (!!window.matchMedia) {
|
|
||||||
return 5
|
|
||||||
}
|
|
||||||
if (!!window.history && 'pushState' in window.history) {
|
|
||||||
return 4
|
|
||||||
}
|
|
||||||
return 3
|
|
||||||
}
|
|
||||||
return NaN
|
|
||||||
}
|
|
||||||
|
|
||||||
var deviceIsAndroid = ua.indexOf('android') > 0
|
|
||||||
var deviceIsIOS = iOSversion()
|
|
||||||
|
|
||||||
var Recognizer = (Anot.gestureHooks = {
|
|
||||||
pointers: {},
|
|
||||||
//以AOP切入touchstart, touchmove, touchend, touchcancel回调
|
|
||||||
start: function(event, callback) {
|
|
||||||
//touches是当前屏幕上所有触摸点的列表;
|
|
||||||
//targetTouches是当前对象上所有触摸点的列表;
|
|
||||||
//changedTouches是涉及当前事件的触摸点的列表。
|
|
||||||
for (var i = 0; i < event.changedTouches.length; i++) {
|
|
||||||
var touch = event.changedTouches[i],
|
|
||||||
id = touch.identifier,
|
|
||||||
pointer = {
|
|
||||||
startTouch: mixLocations({}, touch),
|
|
||||||
startTime: Date.now(),
|
|
||||||
status: 'tapping',
|
|
||||||
element: event.target,
|
|
||||||
pressingHandler:
|
|
||||||
Recognizer.pointers[id] && Recognizer.pointers[id].pressingHandler
|
|
||||||
}
|
|
||||||
Recognizer.pointers[id] = pointer
|
|
||||||
callback(pointer, touch)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
move: function(event, callback) {
|
|
||||||
for (var i = 0; i < event.changedTouches.length; i++) {
|
|
||||||
var touch = event.changedTouches[i]
|
|
||||||
var pointer = Recognizer.pointers[touch.identifier]
|
|
||||||
if (!pointer) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!('lastTouch' in pointer)) {
|
|
||||||
pointer.lastTouch = pointer.startTouch
|
|
||||||
pointer.lastTime = pointer.startTime
|
|
||||||
pointer.deltaX = pointer.deltaY = pointer.duration = pointer.distance = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var time = Date.now() - pointer.lastTime
|
|
||||||
|
|
||||||
if (time > 0) {
|
|
||||||
var RECORD_DURATION = 70
|
|
||||||
if (time > RECORD_DURATION) {
|
|
||||||
time = RECORD_DURATION
|
|
||||||
}
|
|
||||||
if (pointer.duration + time > RECORD_DURATION) {
|
|
||||||
pointer.duration = RECORD_DURATION - time
|
|
||||||
}
|
|
||||||
|
|
||||||
pointer.duration += time
|
|
||||||
pointer.lastTouch = mixLocations({}, touch)
|
|
||||||
|
|
||||||
pointer.lastTime = Date.now()
|
|
||||||
|
|
||||||
pointer.deltaX = touch.clientX - pointer.startTouch.clientX
|
|
||||||
pointer.deltaY = touch.clientY - pointer.startTouch.clientY
|
|
||||||
var x = pointer.deltaX * pointer.deltaX
|
|
||||||
var y = pointer.deltaY * pointer.deltaY
|
|
||||||
pointer.distance = Math.sqrt(x + y)
|
|
||||||
pointer.isVertical = x < y
|
|
||||||
|
|
||||||
callback(pointer, touch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
end: function(event, callback) {
|
|
||||||
for (var i = 0; i < event.changedTouches.length; i++) {
|
|
||||||
var touch = event.changedTouches[i],
|
|
||||||
id = touch.identifier,
|
|
||||||
pointer = Recognizer.pointers[id]
|
|
||||||
|
|
||||||
if (!pointer) continue
|
|
||||||
|
|
||||||
callback(pointer, touch)
|
|
||||||
|
|
||||||
delete Recognizer.pointers[id]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
//人工触发合成事件
|
|
||||||
fire: function(elem, type, props) {
|
|
||||||
if (elem) {
|
|
||||||
var event = document.createEvent('Events')
|
|
||||||
event.initEvent(type, true, true)
|
|
||||||
Anot.mix(event, props)
|
|
||||||
elem.dispatchEvent(event)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
//添加各种识别器
|
|
||||||
add: function(name, recognizer) {
|
|
||||||
function move(event) {
|
|
||||||
recognizer.touchmove(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
function end(event) {
|
|
||||||
recognizer.touchend(event)
|
|
||||||
|
|
||||||
document.removeEventListener('touchmove', move)
|
|
||||||
|
|
||||||
document.removeEventListener('touchend', end)
|
|
||||||
|
|
||||||
document.removeEventListener('touchcancel', cancel)
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel(event) {
|
|
||||||
recognizer.touchcancel(event)
|
|
||||||
|
|
||||||
document.removeEventListener('touchmove', move)
|
|
||||||
|
|
||||||
document.removeEventListener('touchend', end)
|
|
||||||
|
|
||||||
document.removeEventListener('touchcancel', cancel)
|
|
||||||
}
|
|
||||||
|
|
||||||
recognizer.events.forEach(function(eventName) {
|
|
||||||
Anot.eventHooks[eventName] = {
|
|
||||||
fix: function(el, fn) {
|
|
||||||
if (!el['touch-' + name]) {
|
|
||||||
el['touch-' + name] = '1'
|
|
||||||
el.addEventListener('touchstart', function(event) {
|
|
||||||
recognizer.touchstart(event)
|
|
||||||
|
|
||||||
document.addEventListener('touchmove', move)
|
|
||||||
|
|
||||||
document.addEventListener('touchend', end)
|
|
||||||
|
|
||||||
document.addEventListener('touchcancel', cancel)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
var locations = ['screenX', 'screenY', 'clientX', 'clientY', 'pageX', 'pageY']
|
|
||||||
|
|
||||||
// 复制 touch 对象上的有用属性到固定对象上
|
|
||||||
function mixLocations(target, source) {
|
|
||||||
if (source) {
|
|
||||||
locations.forEach(function(key) {
|
|
||||||
target[key] = source[key]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return target
|
|
||||||
}
|
|
||||||
|
|
||||||
var supportPointer = !!navigator.pointerEnabled || !!navigator.msPointerEnabled
|
|
||||||
|
|
||||||
if (supportPointer) {
|
|
||||||
// 支持pointer的设备可用样式来取消click事件的300毫秒延迟
|
|
||||||
root.style.msTouchAction = root.style.touchAction = 'none'
|
|
||||||
}
|
|
||||||
var tapRecognizer = {
|
|
||||||
events: ['tap'],
|
|
||||||
touchBoundary: 10,
|
|
||||||
tapDelay: 200,
|
|
||||||
needClick: function(target) {
|
|
||||||
//判定是否使用原生的点击事件, 否则使用sendClick方法手动触发一个人工的点击事件
|
|
||||||
switch (target.nodeName.toLowerCase()) {
|
|
||||||
case 'button':
|
|
||||||
case 'select':
|
|
||||||
case 'textarea':
|
|
||||||
if (target.disabled) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
case 'input':
|
|
||||||
// IOS6 pad 上选择文件,如果不是原生的click,弹出的选择界面尺寸错误
|
|
||||||
if ((deviceIsIOS && target.type === 'file') || target.disabled) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
|
||||||
case 'label':
|
|
||||||
case 'iframe':
|
|
||||||
case 'video':
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
needFocus: function(target) {
|
|
||||||
switch (target.nodeName.toLowerCase()) {
|
|
||||||
case 'textarea':
|
|
||||||
case 'select': //实测android下select也需要
|
|
||||||
return true
|
|
||||||
case 'input':
|
|
||||||
switch (target.type) {
|
|
||||||
case 'button':
|
|
||||||
case 'checkbox':
|
|
||||||
case 'file':
|
|
||||||
case 'image':
|
|
||||||
case 'radio':
|
|
||||||
case 'submit':
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
//如果是只读或disabled状态,就无须获得焦点了
|
|
||||||
return !target.disabled && !target.readOnly
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
focus: function(targetElement) {
|
|
||||||
var length
|
|
||||||
//在iOS7下, 对一些新表单元素(如date, datetime, time, month)调用focus方法会抛错,
|
|
||||||
//幸好的是,我们可以改用setSelectionRange获取焦点, 将光标挪到文字的最后
|
|
||||||
var type = targetElement.type
|
|
||||||
if (
|
|
||||||
deviceIsIOS &&
|
|
||||||
targetElement.setSelectionRange &&
|
|
||||||
type.indexOf('date') !== 0 &&
|
|
||||||
type !== 'time' &&
|
|
||||||
type !== 'month'
|
|
||||||
) {
|
|
||||||
length = targetElement.value.length
|
|
||||||
targetElement.setSelectionRange(length, length)
|
|
||||||
} else {
|
|
||||||
targetElement.focus()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
findControl: function(labelElement) {
|
|
||||||
// 获取label元素所对应的表单元素
|
|
||||||
// 可以能过control属性, getElementById, 或用querySelector直接找其内部第一表单元素实现
|
|
||||||
if (labelElement.control !== undefined) {
|
|
||||||
return labelElement.control
|
|
||||||
}
|
|
||||||
|
|
||||||
if (labelElement.htmlFor) {
|
|
||||||
return document.getElementById(labelElement.htmlFor)
|
|
||||||
}
|
|
||||||
|
|
||||||
return labelElement.querySelector(
|
|
||||||
'button, input:not([type=hidden]), keygen, meter, output, progress, select, textarea'
|
|
||||||
)
|
|
||||||
},
|
|
||||||
fixTarget: function(target) {
|
|
||||||
if (target.nodeType === 3) {
|
|
||||||
return target.parentNode
|
|
||||||
}
|
|
||||||
if (window.SVGElementInstance && target instanceof SVGElementInstance) {
|
|
||||||
return target.correspondingUseElement
|
|
||||||
}
|
|
||||||
|
|
||||||
return target
|
|
||||||
},
|
|
||||||
updateScrollParent: function(targetElement) {
|
|
||||||
//如果事件源元素位于某一个有滚动条的祖父元素中,那么保持其scrollParent与scrollTop值
|
|
||||||
var scrollParent = targetElement.tapScrollParent
|
|
||||||
|
|
||||||
if (!scrollParent || !scrollParent.contains(targetElement)) {
|
|
||||||
var parentElement = targetElement
|
|
||||||
do {
|
|
||||||
if (parentElement.scrollHeight > parentElement.offsetHeight) {
|
|
||||||
scrollParent = parentElement
|
|
||||||
targetElement.tapScrollParent = parentElement
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
parentElement = parentElement.parentElement
|
|
||||||
} while (parentElement)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scrollParent) {
|
|
||||||
scrollParent.lastScrollTop = scrollParent.scrollTop
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchHasMoved: function(event) {
|
|
||||||
//判定是否发生移动,其阀值是10px
|
|
||||||
var touch = event.changedTouches[0],
|
|
||||||
boundary = tapRecognizer.touchBoundary
|
|
||||||
return (
|
|
||||||
Math.abs(touch.pageX - tapRecognizer.pageX) > boundary ||
|
|
||||||
Math.abs(touch.pageY - tapRecognizer.pageY) > boundary
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
findType: function(targetElement) {
|
|
||||||
// 安卓chrome浏览器上,模拟的 click 事件不能让 select 打开,故使用 mousedown 事件
|
|
||||||
return deviceIsAndroid && targetElement.tagName.toLowerCase() === 'select'
|
|
||||||
? 'mousedown'
|
|
||||||
: 'click'
|
|
||||||
},
|
|
||||||
sendClick: function(targetElement, event) {
|
|
||||||
// 在click之前触发tap事件
|
|
||||||
Recognizer.fire(targetElement, 'tap', {
|
|
||||||
touchEvent: event
|
|
||||||
})
|
|
||||||
var clickEvent, touch
|
|
||||||
//某些安卓设备必须先移除焦点,之后模拟的click事件才能让新元素获取焦点
|
|
||||||
if (document.activeElement && document.activeElement !== targetElement) {
|
|
||||||
document.activeElement.blur()
|
|
||||||
}
|
|
||||||
|
|
||||||
touch = event.changedTouches[0]
|
|
||||||
// 手动触发点击事件,此时必须使用document.createEvent('MouseEvents')来创建事件
|
|
||||||
// 及使用initMouseEvent来初始化它
|
|
||||||
clickEvent = document.createEvent('MouseEvents')
|
|
||||||
clickEvent.initMouseEvent(
|
|
||||||
tapRecognizer.findType(targetElement),
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
window,
|
|
||||||
1,
|
|
||||||
touch.screenX,
|
|
||||||
touch.screenY,
|
|
||||||
touch.clientX,
|
|
||||||
touch.clientY,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
0,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
clickEvent.touchEvent = event
|
|
||||||
targetElement.dispatchEvent(clickEvent)
|
|
||||||
},
|
|
||||||
touchstart: function(event) {
|
|
||||||
//忽略多点触摸
|
|
||||||
if (event.targetTouches.length !== 1) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
//修正事件源对象
|
|
||||||
var targetElement = tapRecognizer.fixTarget(event.target)
|
|
||||||
var touch = event.targetTouches[0]
|
|
||||||
if (deviceIsIOS) {
|
|
||||||
// 判断是否是点击文字,进行选择等操作,如果是,不需要模拟click
|
|
||||||
var selection = window.getSelection()
|
|
||||||
if (selection.rangeCount && !selection.isCollapsed) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
var id = touch.identifier
|
|
||||||
//当 alert 或 confirm 时,点击其他地方,会触发touch事件,identifier相同,此事件应该被忽略
|
|
||||||
if (
|
|
||||||
id &&
|
|
||||||
isFinite(tapRecognizer.lastTouchIdentifier) &&
|
|
||||||
tapRecognizer.lastTouchIdentifier === id
|
|
||||||
) {
|
|
||||||
event.preventDefault()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
tapRecognizer.lastTouchIdentifier = id
|
|
||||||
|
|
||||||
tapRecognizer.updateScrollParent(targetElement)
|
|
||||||
}
|
|
||||||
//收集触摸点的信息
|
|
||||||
tapRecognizer.status = 'tapping'
|
|
||||||
tapRecognizer.startTime = Date.now()
|
|
||||||
tapRecognizer.element = targetElement
|
|
||||||
tapRecognizer.pageX = touch.pageX
|
|
||||||
tapRecognizer.pageY = touch.pageY
|
|
||||||
// 如果点击太快,阻止双击带来的放大收缩行为
|
|
||||||
if (
|
|
||||||
tapRecognizer.startTime - tapRecognizer.lastTime <
|
|
||||||
tapRecognizer.tapDelay
|
|
||||||
) {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchmove: function(event) {
|
|
||||||
if (tapRecognizer.status !== 'tapping') {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
// 如果事件源元素发生改变,或者发生了移动,那么就取消触发点击事件
|
|
||||||
if (
|
|
||||||
tapRecognizer.element !== tapRecognizer.fixTarget(event.target) ||
|
|
||||||
tapRecognizer.touchHasMoved(event)
|
|
||||||
) {
|
|
||||||
tapRecognizer.status = tapRecognizer.element = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchend: function(event) {
|
|
||||||
var targetElement = tapRecognizer.element
|
|
||||||
var now = Date.now()
|
|
||||||
//如果是touchstart与touchend相隔太久,可以认为是长按,那么就直接返回
|
|
||||||
//或者是在touchstart, touchmove阶段,判定其不该触发点击事件,也直接返回
|
|
||||||
if (
|
|
||||||
!targetElement ||
|
|
||||||
now - tapRecognizer.startTime > tapRecognizer.tapDelay
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
tapRecognizer.lastTime = now
|
|
||||||
|
|
||||||
var startTime = tapRecognizer.startTime
|
|
||||||
tapRecognizer.status = tapRecognizer.startTime = 0
|
|
||||||
|
|
||||||
targetTagName = targetElement.tagName.toLowerCase()
|
|
||||||
if (targetTagName === 'label') {
|
|
||||||
//尝试触发label上可能绑定的tap事件
|
|
||||||
Recognizer.fire(targetElement, 'tap', {
|
|
||||||
touchEvent: event
|
|
||||||
})
|
|
||||||
var forElement = tapRecognizer.findControl(targetElement)
|
|
||||||
if (forElement) {
|
|
||||||
tapRecognizer.focus(targetElement)
|
|
||||||
targetElement = forElement
|
|
||||||
}
|
|
||||||
} else if (tapRecognizer.needFocus(targetElement)) {
|
|
||||||
// 如果元素从touchstart到touchend经历时间过长,那么不应该触发点击事
|
|
||||||
// 或者此元素是iframe中的input元素,那么它也无法获点焦点
|
|
||||||
if (
|
|
||||||
now - startTime > 100 ||
|
|
||||||
(deviceIsIOS && window.top !== window && targetTagName === 'input')
|
|
||||||
) {
|
|
||||||
tapRecognizer.element = 0
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
tapRecognizer.focus(targetElement)
|
|
||||||
deviceIsAndroid && tapRecognizer.sendClick(targetElement, event)
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceIsIOS) {
|
|
||||||
//如果它的父容器的滚动条发生改变,那么应该识别为划动或拖动事件,不应该触发点击事件
|
|
||||||
var scrollParent = targetElement.tapScrollParent
|
|
||||||
if (
|
|
||||||
scrollParent &&
|
|
||||||
scrollParent.lastScrollTop !== scrollParent.scrollTop
|
|
||||||
) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//如果这不是一个需要使用原生click的元素,则屏蔽原生事件,避免触发两次click
|
|
||||||
if (!tapRecognizer.needClick(targetElement)) {
|
|
||||||
event.preventDefault()
|
|
||||||
// 触发一次模拟的click
|
|
||||||
tapRecognizer.sendClick(targetElement, event)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchcancel: function() {
|
|
||||||
tapRecognizer.startTime = tapRecognizer.element = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Recognizer.add('tap', tapRecognizer)
|
|
||||||
|
|
||||||
var pressRecognizer = {
|
|
||||||
events: ['longtap', 'doubletap'],
|
|
||||||
cancelPress: function(pointer) {
|
|
||||||
clearTimeout(pointer.pressingHandler)
|
|
||||||
pointer.pressingHandler = null
|
|
||||||
},
|
|
||||||
touchstart: function(event) {
|
|
||||||
Recognizer.start(event, function(pointer, touch) {
|
|
||||||
pointer.pressingHandler = setTimeout(function() {
|
|
||||||
if (pointer.status === 'tapping') {
|
|
||||||
Recognizer.fire(event.target, 'longtap', {
|
|
||||||
touch: touch,
|
|
||||||
touchEvent: event
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pressRecognizer.cancelPress(pointer)
|
|
||||||
}, 800)
|
|
||||||
if (event.changedTouches.length !== 1) {
|
|
||||||
pointer.status = 0
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
touchmove: function(event) {
|
|
||||||
Recognizer.move(event, function(pointer) {
|
|
||||||
if (pointer.distance > 10 && pointer.pressingHandler) {
|
|
||||||
pressRecognizer.cancelPress(pointer)
|
|
||||||
if (pointer.status === 'tapping') {
|
|
||||||
pointer.status = 'panning'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
touchend: function(event) {
|
|
||||||
Recognizer.end(event, function(pointer, touch) {
|
|
||||||
pressRecognizer.cancelPress(pointer)
|
|
||||||
if (pointer.status === 'tapping') {
|
|
||||||
pointer.lastTime = Date.now()
|
|
||||||
if (
|
|
||||||
pressRecognizer.lastTap &&
|
|
||||||
pointer.lastTime - pressRecognizer.lastTap.lastTime < 300
|
|
||||||
) {
|
|
||||||
Recognizer.fire(pointer.element, 'doubletap', {
|
|
||||||
touch: touch,
|
|
||||||
touchEvent: event
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pressRecognizer.lastTap = pointer
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
touchcancel: function(event) {
|
|
||||||
Recognizer.end(event, function(pointer) {
|
|
||||||
pressRecognizer.cancelPress(pointer)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Recognizer.add('press', pressRecognizer)
|
|
||||||
|
|
||||||
var swipeRecognizer = {
|
|
||||||
events: ['swipe', 'swipeleft', 'swiperight', 'swipeup', 'swipedown'],
|
|
||||||
getAngle: function(x, y) {
|
|
||||||
return Math.atan2(y, x) * 180 / Math.PI
|
|
||||||
},
|
|
||||||
getDirection: function(x, y) {
|
|
||||||
var angle = swipeRecognizer.getAngle(x, y)
|
|
||||||
if (angle < -45 && angle > -135) {
|
|
||||||
return 'up'
|
|
||||||
} else if (angle >= 45 && angle < 315) {
|
|
||||||
return 'down'
|
|
||||||
} else if (angle > -45 && angle <= 45) {
|
|
||||||
return 'right'
|
|
||||||
} else {
|
|
||||||
return 'left'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
touchstart: function(event) {
|
|
||||||
Recognizer.start(event, noop)
|
|
||||||
},
|
|
||||||
touchmove: function(event) {
|
|
||||||
Recognizer.move(event, noop)
|
|
||||||
},
|
|
||||||
touchend: function(event) {
|
|
||||||
if (event.changedTouches.length !== 1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Recognizer.end(event, function(pointer, touch) {
|
|
||||||
var isflick =
|
|
||||||
pointer.distance > 30 && pointer.distance / pointer.duration > 0.65
|
|
||||||
if (isflick) {
|
|
||||||
var extra = {
|
|
||||||
deltaX: pointer.deltaX,
|
|
||||||
deltaY: pointer.deltaY,
|
|
||||||
touch: touch,
|
|
||||||
touchEvent: event,
|
|
||||||
direction: swipeRecognizer.getDirection(
|
|
||||||
pointer.deltaX,
|
|
||||||
pointer.deltaY
|
|
||||||
),
|
|
||||||
isVertical: pointer.isVertical
|
|
||||||
}
|
|
||||||
var target = pointer.element
|
|
||||||
Recognizer.fire(target, 'swipe', extra)
|
|
||||||
Recognizer.fire(target, 'swipe' + extra.direction, extra)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
swipeRecognizer.touchcancel = swipeRecognizer.touchend
|
|
||||||
Recognizer.add('swipe', swipeRecognizer)
|
|
|
@ -1,137 +0,0 @@
|
||||||
/**
|
|
||||||
* Uploader 无刷新上传文件(next版)
|
|
||||||
* 只支持chrome/firefox/IE10+/opera12+
|
|
||||||
* @authors yutent (yutent@doui.cc)
|
|
||||||
* @date 2016-09-05 19:33:23
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
define(function(){
|
|
||||||
|
|
||||||
/* var isIE = !!window.VBArray
|
|
||||||
|
|
||||||
function IEVersion(){
|
|
||||||
if(document.documentMode)
|
|
||||||
return document.documentMode
|
|
||||||
|
|
||||||
return window.XMLHttpRequest ? 7 : 6
|
|
||||||
}*/
|
|
||||||
|
|
||||||
var Uploader = function(){
|
|
||||||
this.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
Uploader.prototype = {
|
|
||||||
init: function(){
|
|
||||||
this.xhr = new XMLHttpRequest()
|
|
||||||
this.form = new FormData()
|
|
||||||
this.field = {}
|
|
||||||
this.header = {}
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
setUrl: function(url){
|
|
||||||
if(!url || typeof url !== 'string')
|
|
||||||
return console.error('url不能为空且必须是字符串')
|
|
||||||
|
|
||||||
this.url = url
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
setField: function(key, val){
|
|
||||||
if(typeof key === 'object'){
|
|
||||||
for(var i in key){
|
|
||||||
this.field[i] = key[i]
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
this.field[key] = val
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
setHeader: function(key, val){
|
|
||||||
if(typeof key === 'object'){
|
|
||||||
for(var i in key){
|
|
||||||
this.header[i] = key[i]
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
this.header[key] = val
|
|
||||||
}
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
start: function(){
|
|
||||||
var _this = this
|
|
||||||
if(!this.url)
|
|
||||||
return console.error('请先设置url')
|
|
||||||
|
|
||||||
this.xhr.open('POST', this.url, true)
|
|
||||||
|
|
||||||
for(var i in this.field){
|
|
||||||
this.form.append(i, this.field[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
var startTime = Date.now()
|
|
||||||
|
|
||||||
this.xhr.upload.addEventListener('progress', function(evt){
|
|
||||||
|
|
||||||
if(evt.lengthComputable && _this.progress){
|
|
||||||
var now = Date.now()
|
|
||||||
var upSize = (evt.loaded * 1000) / 1024
|
|
||||||
var res = {loaded: evt.loaded, time: now - startTime}
|
|
||||||
res.speed = upSize / res.time
|
|
||||||
|
|
||||||
if(res.speed < 10){
|
|
||||||
res.speed = Math.floor(res.speed * 1024) + ' B/s'
|
|
||||||
}else{
|
|
||||||
res.speed = res.speed.toFixed(2) + ' KB/s'
|
|
||||||
}
|
|
||||||
|
|
||||||
res.progress = Math.round(evt.loaded * 100 / evt.total)
|
|
||||||
_this.progress(res)
|
|
||||||
}
|
|
||||||
|
|
||||||
}, false)
|
|
||||||
|
|
||||||
this.xhr.onreadystatechange = function(){
|
|
||||||
if(_this.xhr.readyState === 4 &&
|
|
||||||
_this.xhr.status === 200 &&
|
|
||||||
_this.xhr.responseText !== ''){
|
|
||||||
var res = _this.xhr.responseText
|
|
||||||
try{
|
|
||||||
res = JSON.parse(res)
|
|
||||||
}catch(err){}
|
|
||||||
_this.end && _this.end(res)
|
|
||||||
}else{
|
|
||||||
if(_this.xhr.status !== 200 && _this.xhr.responseText)
|
|
||||||
_this.error && _this.error(_this.xhr.responseText)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.xhr.send(this.form)
|
|
||||||
|
|
||||||
},
|
|
||||||
onProgress: function(fn){
|
|
||||||
this.progress = fn
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
onEnd: function(fn){
|
|
||||||
this.end = fn
|
|
||||||
return this
|
|
||||||
},
|
|
||||||
onError: function(fn){
|
|
||||||
this.error = fn
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(!window.Uploader)
|
|
||||||
window.Uploader = Uploader
|
|
||||||
|
|
||||||
|
|
||||||
return Uploader
|
|
||||||
|
|
||||||
})
|
|
|
@ -8,7 +8,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import 'drag/index'
|
import 'drag/index'
|
||||||
import './skin/normal.scss'
|
import 'css/layer-normal.scss'
|
||||||
|
|
||||||
Anot.ui.layer = '1.0.0-normal'
|
Anot.ui.layer = '1.0.0-normal'
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* https://github.com/chjj/marked
|
* https://github.com/chjj/marked
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './theme.scss'
|
import 'css/marked.scss'
|
||||||
/**
|
/**
|
||||||
* Block-Level Grammar
|
* Block-Level Grammar
|
||||||
*/
|
*/
|
|
@ -8,7 +8,7 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import 'layer/index'
|
import 'layer/index'
|
||||||
import './attach.scss'
|
import 'css/meditor__attach.scss'
|
||||||
|
|
||||||
const $doc = Anot(document)
|
const $doc = Anot(document)
|
||||||
const LANG = {
|
const LANG = {
|
|
@ -10,7 +10,7 @@
|
||||||
import 'prism/base'
|
import 'prism/base'
|
||||||
import 'marked/index'
|
import 'marked/index'
|
||||||
import addon from './addon/base'
|
import addon from './addon/base'
|
||||||
import './skin/main.scss'
|
import 'css/meditor.scss'
|
||||||
|
|
||||||
marked.setOptions({
|
marked.setOptions({
|
||||||
highlight: function(code, lang) {
|
highlight: function(code, lang) {
|
|
@ -1,6 +1,6 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
import './main.scss'
|
import 'css/pager.scss'
|
||||||
|
|
||||||
Anot.ui.pager = '1.0.0'
|
Anot.ui.pager = '1.0.0'
|
||||||
//计算页码列表
|
//计算页码列表
|
|
@ -5,7 +5,7 @@
|
||||||
* @version $Id$
|
* @version $Id$
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './highlight.scss'
|
import 'css/prism.scss'
|
||||||
|
|
||||||
var Prism = (function() {
|
var Prism = (function() {
|
||||||
// Private helper vars
|
// Private helper vars
|
|
@ -6,8 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
import 'css/tree.scss'
|
||||||
import './main.scss'
|
|
||||||
|
|
||||||
//储存版本信息
|
//储存版本信息
|
||||||
Anot.ui.tree = '1.0.0'
|
Anot.ui.tree = '1.0.0'
|
|
@ -0,0 +1,130 @@
|
||||||
|
/**
|
||||||
|
* Uploader 无刷新上传文件(next版)
|
||||||
|
* 只支持chrome/firefox/IE10+/opera12+
|
||||||
|
* @authors yutent (yutent@doui.cc)
|
||||||
|
* @date 2016-09-05 19:33:23
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
define(function() {
|
||||||
|
/* var isIE = !!window.VBArray
|
||||||
|
|
||||||
|
function IEVersion(){
|
||||||
|
if(document.documentMode)
|
||||||
|
return document.documentMode
|
||||||
|
|
||||||
|
return window.XMLHttpRequest ? 7 : 6
|
||||||
|
}*/
|
||||||
|
|
||||||
|
var Uploader = function() {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
Uploader.prototype = {
|
||||||
|
init: function() {
|
||||||
|
this.xhr = new XMLHttpRequest()
|
||||||
|
this.form = new FormData()
|
||||||
|
this.field = {}
|
||||||
|
this.header = {}
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
setUrl: function(url) {
|
||||||
|
if (!url || typeof url !== 'string')
|
||||||
|
return console.error('url不能为空且必须是字符串')
|
||||||
|
|
||||||
|
this.url = url
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
setField: function(key, val) {
|
||||||
|
if (typeof key === 'object') {
|
||||||
|
for (var i in key) {
|
||||||
|
this.field[i] = key[i]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.field[key] = val
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
setHeader: function(key, val) {
|
||||||
|
if (typeof key === 'object') {
|
||||||
|
for (var i in key) {
|
||||||
|
this.header[i] = key[i]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.header[key] = val
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
start: function() {
|
||||||
|
var _this = this
|
||||||
|
if (!this.url) return console.error('请先设置url')
|
||||||
|
|
||||||
|
this.xhr.open('POST', this.url, true)
|
||||||
|
|
||||||
|
for (var i in this.field) {
|
||||||
|
this.form.append(i, this.field[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime = Date.now()
|
||||||
|
|
||||||
|
this.xhr.upload.addEventListener(
|
||||||
|
'progress',
|
||||||
|
function(evt) {
|
||||||
|
if (evt.lengthComputable && _this.progress) {
|
||||||
|
var now = Date.now()
|
||||||
|
var upSize = evt.loaded * 1000 / 1024
|
||||||
|
var res = { loaded: evt.loaded, time: now - startTime }
|
||||||
|
res.speed = upSize / res.time
|
||||||
|
|
||||||
|
if (res.speed < 10) {
|
||||||
|
res.speed = Math.floor(res.speed * 1024) + ' B/s'
|
||||||
|
} else {
|
||||||
|
res.speed = res.speed.toFixed(2) + ' KB/s'
|
||||||
|
}
|
||||||
|
|
||||||
|
res.progress = Math.round(evt.loaded * 100 / evt.total)
|
||||||
|
_this.progress(res)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
|
this.xhr.onreadystatechange = function() {
|
||||||
|
if (
|
||||||
|
_this.xhr.readyState === 4 &&
|
||||||
|
_this.xhr.status === 200 &&
|
||||||
|
_this.xhr.responseText !== ''
|
||||||
|
) {
|
||||||
|
var res = _this.xhr.responseText
|
||||||
|
try {
|
||||||
|
res = JSON.parse(res)
|
||||||
|
} catch (err) {}
|
||||||
|
_this.end && _this.end(res)
|
||||||
|
} else {
|
||||||
|
if (_this.xhr.status !== 200 && _this.xhr.responseText)
|
||||||
|
_this.error && _this.error(_this.xhr.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.xhr.send(this.form)
|
||||||
|
},
|
||||||
|
onProgress: function(fn) {
|
||||||
|
this.progress = fn
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
onEnd: function(fn) {
|
||||||
|
this.end = fn
|
||||||
|
return this
|
||||||
|
},
|
||||||
|
onError: function(fn) {
|
||||||
|
this.error = fn
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window.Uploader) window.Uploader = Uploader
|
||||||
|
|
||||||
|
return Uploader
|
||||||
|
})
|
Reference in New Issue