-
Notifications
You must be signed in to change notification settings - Fork 492
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
325 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,4 +2,5 @@ | |
coverage | ||
lib | ||
node_modules | ||
npm-debug.log | ||
npm-debug.log | ||
.DS_Store |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
/** | ||
* Created by n7best | ||
*/ | ||
|
||
|
||
import React, { Component, PropTypes } from 'react'; | ||
import classNames from 'classnames'; | ||
|
||
export default class Uploader extends React.Component { | ||
static propTypes = { | ||
title: PropTypes.string, | ||
maxCount: PropTypes.number, | ||
maxWidth: PropTypes.number, | ||
onChange: PropTypes.func, | ||
onError: PropTypes.func, | ||
files: PropTypes.array, | ||
lang: PropTypes.object | ||
}; | ||
|
||
static defaultProps = { | ||
title: '图片上传', | ||
maxCount: 4, | ||
maxWidth: 500, | ||
files: [], | ||
onChange: undefined, | ||
onError: undefined, | ||
lang:{ | ||
maxError: maxCount => `最多只能上传${maxCount}张图片` | ||
} | ||
}; | ||
|
||
handleFile(file,cb) { | ||
let reader = new FileReader(); | ||
reader.onload = e => { | ||
let img = new Image(); | ||
img.onload = ()=>{ | ||
let w = Math.min(this.props.maxWidth, img.width); | ||
let h = img.height * (w / img.width); | ||
let canvas = document.createElement('canvas'); | ||
let ctx = canvas.getContext('2d'); | ||
canvas.width = w; | ||
canvas.height = h; | ||
ctx.drawImage(img, 0, 0, w, h); | ||
let base64 = canvas.toDataURL('image/png'); | ||
cb({ | ||
lastModified: file.lastModified, | ||
lastModifiedDate: file.lastModifiedDate, | ||
name: file.name, | ||
size: file.size, | ||
type: file.type, | ||
data: base64 | ||
}); | ||
}; | ||
img.src = e.target.result; | ||
} | ||
reader.readAsDataURL(file); | ||
} | ||
|
||
handleChange(e) { | ||
const langs = this.props.lang; | ||
let _files = e.target.files; | ||
|
||
if(_files.length === 0) return; | ||
|
||
if(this.props.files.length >= this.props.maxCount) { | ||
this.props.onError(langs.maxError(this.props.maxCount)); | ||
return; | ||
} | ||
|
||
for(let key in _files) { | ||
if (!_files.hasOwnProperty(key)) continue; | ||
let file = _files[key]; | ||
this.handleFile(file, _file=>{ | ||
if(this.props.onChange) this.props.onChange(_file, e); | ||
}); | ||
} | ||
} | ||
|
||
renderFiles(){ | ||
return this.props.files.map((file, idx)=>{ | ||
let {url, error, status, ...others} = file; | ||
let fileStyle = { | ||
backgroundImage: `url(${url})` | ||
}; | ||
let cls = classNames({ | ||
weui_uploader_file: true, | ||
weui_uploader_status: error || status | ||
}); | ||
|
||
return ( | ||
<li className={cls} key={idx} style={fileStyle} {...others}> | ||
{ | ||
error || status ? | ||
<div className="weui_uploader_status_content"> | ||
{ error ? <i className="weui_icon_warn"></i> : status } | ||
</div> | ||
: false | ||
} | ||
</li> | ||
); | ||
}); | ||
} | ||
|
||
render(){ | ||
const { className, title, maxCount, files, onChange, ...others } = this.props; | ||
const cls = classNames({ | ||
weui_uploader: true, | ||
[className]: className | ||
}); | ||
|
||
return ( | ||
<div className={cls}> | ||
<div className="weui_uploader_hd weui_cell"> | ||
<div className="weui_cell_bd weui_cell_primary">{title}</div> | ||
<div className="weui_cell_ft">{files.length}/{maxCount}</div> | ||
</div> | ||
<div className="weui_uploader_bd"> | ||
<ul className="weui_uploader_files"> | ||
{this.renderFiles()} | ||
</ul> | ||
<div className="weui_uploader_input_wrp"> | ||
<input | ||
className="weui_uploader_input" | ||
type="file" | ||
accept="image/jpg,image/jpeg,image/png,image/gif" | ||
onChange={this.handleChange.bind(this)} | ||
{...others} | ||
/> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/** | ||
* Created by n7best. | ||
*/ | ||
|
||
"use strict"; | ||
|
||
import React from 'react'; | ||
import { shallow } from 'enzyme'; | ||
import assert from 'assert'; | ||
import WeUI from '../src/index'; | ||
|
||
const {Uploader} = WeUI; | ||
const files = [ | ||
{ | ||
data: 'http://mmrmb.github.io/avatar/bear.jpg', | ||
onClick: e=>alert('事件测试') | ||
}, | ||
{ | ||
data: 'http://mmrmb.github.io/avatar/bear.jpg' | ||
}, | ||
{ | ||
data: 'http://mmrmb.github.io/avatar/bear.jpg' | ||
}, | ||
{ | ||
data: 'http://mmrmb.github.io/avatar/bear.jpg', | ||
error: true | ||
}, | ||
{ | ||
data: 'http://mmrmb.github.io/avatar/bear.jpg', | ||
status: '50%' | ||
} | ||
]; | ||
const title = '提示'; | ||
const enlang = { | ||
maxError: maxCount => `Max ${maxCount} photos allowed` | ||
}; | ||
describe('<Uploader></Uploader>', ()=> { | ||
[enlang, undefined].map(lang=> { | ||
[undefined, 5, 30].map(maxCount=> { | ||
[files, []].map(files=> { | ||
describe(`<Uploader lang=${lang} title=${title} files=${files} maxCount=${maxCount}></Uploader>`, ()=> { | ||
let verifyFiles = {}; | ||
let verifyErrors; | ||
const wrapper = shallow( | ||
<Uploader lang={lang} title={title} files={files} maxCount={maxCount} onError={msg=>verifyErrors=msg} onChange={_files=>verifyFiles=_files}/> | ||
); | ||
|
||
it('should render <Uploader></Uploader> component', () => { | ||
assert(wrapper.instance() instanceof Uploader); | ||
assert(wrapper.hasClass('weui_uploader')); | ||
}); | ||
|
||
it('should render header with class weui_uploader_hd, weui_cell', () => { | ||
assert(wrapper.children().first().hasClass('weui_uploader_hd')); | ||
assert(wrapper.children().first().hasClass('weui_cell')); | ||
}); | ||
|
||
it('should render body with class weui_uploader_bd', () => { | ||
assert(wrapper.children().last().hasClass('weui_uploader_bd')); | ||
}); | ||
|
||
let bd = wrapper.children().last().children(); | ||
|
||
it('should render lists container with weui_uploader_files', () => { | ||
assert(bd.find('ul').hasClass('weui_uploader_files')); | ||
}); | ||
|
||
it('should render input wrapper with weui_uploader_input_wrp', () => { | ||
assert(bd.last().hasClass('weui_uploader_input_wrp')); | ||
}); | ||
|
||
it('should render input with weui_uploader_input', () => { | ||
assert(bd.last().find('input').hasClass('weui_uploader_input')); | ||
}); | ||
|
||
it('should render file preview with weui_uploader_file', () => { | ||
if(files.length > 0){ | ||
assert(bd.first().find('ul').children().first().hasClass('weui_uploader_file')); | ||
} | ||
}); | ||
|
||
it('should render file preview with weui_uploader_status when error is true or status is set', () => { | ||
if(files.length > 0){ | ||
assert(bd.first().find('ul').children().at(3).hasClass('weui_uploader_status')); | ||
assert(bd.first().find('ul').children().at(4).hasClass('weui_uploader_status')); | ||
} | ||
}); | ||
|
||
it('should render div with weui_uploader_status_content when error is true or status is set', () => { | ||
if(files.length > 0){ | ||
assert(bd.first().find('ul').children().at(3).find('div').hasClass('weui_uploader_status_content')); | ||
assert(bd.first().find('ul').children().at(4).find('div').hasClass('weui_uploader_status_content')); | ||
} | ||
}); | ||
|
||
it('should render icon with weui_icon_warn when error is true', () => { | ||
if(files.length > 0){ | ||
assert(bd.first().find('ul').children().at(3).find('div').find('i').hasClass('weui_icon_warn')); | ||
} | ||
}); | ||
|
||
it('should render status when status is set', () => { | ||
if(files.length > 0){ | ||
assert.equal('50%',bd.first().find('ul').children().at(4).find('div').text()); | ||
} | ||
}); | ||
|
||
it('should render chinese error message', () => { | ||
let _maxCount = maxCount ? maxCount : 4; | ||
if(files.length > _maxCount && !lang){ | ||
verifyErrors = ''; | ||
let expectedmsg = `最多只能上传${_maxCount}张图片`; | ||
let input = assert(bd.last().find('input')); | ||
let changefiles = { 0: {name:'foo', size: 500001} }; | ||
bd.last().find('input').simulate('change',{target:{files:changefiles}}); | ||
assert.equal(expectedmsg,verifyErrors); | ||
} | ||
}); | ||
|
||
it('should render english error message', () => { | ||
let _maxCount = maxCount ? maxCount : 4; | ||
if(files.length > _maxCount && lang){ | ||
verifyErrors = ''; | ||
let expectedmsg = `Max ${_maxCount} photos allowed`; | ||
let input = assert(bd.last().find('input')); | ||
let changefiles = { 0: {name:'foo', size: 500001} }; | ||
bd.last().find('input').simulate('change',{target:{files:changefiles}}); | ||
assert.equal(expectedmsg,verifyErrors); | ||
} | ||
}); | ||
|
||
it('should render files', () => { | ||
//currently can't test filereaders | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |