Skip to content

Commit

Permalink
working search-field
Browse files Browse the repository at this point in the history
  • Loading branch information
yongxu committed Oct 25, 2015
1 parent 1169058 commit 6832086
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 0 deletions.
2 changes: 2 additions & 0 deletions docs/src/app/app-routes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const Menus = require('./components/pages/components/menus');
const Paper = require('./components/pages/components/paper');
const Progress = require('./components/pages/components/progress');
const RefreshIndicator = require('./components/pages/components/refresh-indicator');
const SearchField = require('./components/pages/components/search-field');
const Sliders = require('./components/pages/components/sliders');
const Snackbar = require('./components/pages/components/snackbar');
const Switches = require('./components/pages/components/switches');
Expand Down Expand Up @@ -92,6 +93,7 @@ const AppRoutes = (
<Route path="paper" component={Paper} />
<Route path="progress" component={Progress} />
<Route path="refresh-indicator" component={RefreshIndicator} />
<Route path="search-field" component={SearchField} />
<Route path="sliders" component={Sliders} />
<Route path="switches" component={Switches} />
<Route path="snackbar" component={Snackbar} />
Expand Down
1 change: 1 addition & 0 deletions docs/src/app/components/pages/components.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default class Components extends React.Component {
{ route: '/components/paper', text: 'Paper'},
{ route: '/components/progress', text: 'Progress'},
{ route: '/components/refresh-indicator', text: 'Refresh Indicator'},
{ route: '/components/search-field', text: 'Search Field'},
{ route: '/components/sliders', text: 'Sliders'},
{ route: '/components/switches', text: 'Switches'},
{ route: '/components/snackbar', text: 'Snackbar'},
Expand Down
54 changes: 54 additions & 0 deletions docs/src/app/components/pages/components/search-field.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
let React = require('react');

let { SearchField } = require('material-ui');
let ComponentDoc = require('../../component-doc');

let Code = require('search-field-code');

class SearchFields extends React.Component {

constructor(props) {
super(props);
}

render() {

let desc = null;

return (
<ComponentDoc
name="Search Field"
code={Code}
desc={desc}
componentInfo={[{
name: 'Search Field',
infoArray: [],
}]}>

<br/>

<div>
<SearchField
onUpdateRequests={(t) => {console.log(t); return [t, t+t, t+t+t];}}
onNewRequest={(t) => {console.log('request:'+t);}} />
<SearchField
fullWidth = {true}
onUpdateRequests={(t) => {console.log(t); return [t, t+t, t+t+t];}}
onNewRequest={(t) => {console.log('request:'+t);}} />

<SearchField
fullWidth={true}
onUpdateRequests={(t) => {console.log(t); return [t, t+t, t+t+t];}}
onNewRequest={(t) => {console.log('request:'+t);}} />

</div>

</ComponentDoc>
);

}


}

module.exports = SearchFields;
8 changes: 8 additions & 0 deletions docs/src/app/components/raw-code/search-field-code.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<SearchField
onUpdateRequests={(t) => {console.log(t); return [t,t+t,t+t+t];}}
onNewRequest={(t) => {console.log('request:'+t);}} />

<SearchField
fullWidth={true}
onUpdateRequests={(t) => {console.log(t); return [t,t+t,t+t+t];}}
onNewRequest={(t) => {console.log('request:'+t);}} />
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ module.exports = {
RefreshIndicator: require('./refresh-indicator'),
Ripples: require('./ripples/'),
SelectField: require('./select-field'),
SearchField: require('./search-field'),
Slider: require('./slider'),
SvgIcon: require('./svg-icon'),
Icons: {
Expand Down
260 changes: 260 additions & 0 deletions src/search-field.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
const React = require('react');
const ReactTransitionGroup = require('react-addons-transition-group');
const StylePropable = require('./mixins/style-propable');
const ClickAwayable = require('./mixins/click-awayable');
const TextField = require('./text-field');
const Menu = require('./menus/menu');
const MenuItem = require('./menus/menu-item');

const SearchField = React.createClass({

mixins: [
StylePropable,
ClickAwayable,
],

contextTypes: {
muiTheme: React.PropTypes.object,
},

propTypes: {
errorText: React.PropTypes.string,
floatingLabelText: React.PropTypes.string,
errorStyle: React.PropTypes.object,
hintText: React.PropTypes.string,
id: React.PropTypes.string,
onChange: React.PropTypes.func,
autoWidth: React.PropTypes.bool,
menuStyle: React.PropTypes.object,
listStyle: React.PropTypes.object,
menuProps: React.PropTypes.object,
menuCloseDelay: React.PropTypes.number,
onUpdateRequests: React.PropTypes.func,
onNewSearchRequest: React.PropTypes.func,
},

getDefaultProps() {
return {
fullWidth: false,
open: false,
searchText: '',
menuCloseDelay: 100,

onChange: () => {},
onUpdateRequests: () => {},
onNewRequest: () => {},
};
},

getInitialState() {
return {
searchText: this.props.searchText,
requestsList: null,
open: this.props.open,
};
},

componentWillMount(){
this.focusOnInput = false;
},

componentClickAway() {
this.setState({open:false});
},

render() {
let {
style,
errorStyle,
floatingLabelText,
hintText,
fullWidth,
menuStyle,
menuProps,
listStyle,
...other,
} = this.props;

let requestsList = this.state.requestsList;

let styles = {
root: {
display: 'inline-block',
position: 'relative',
width: this.props.fullWidth ? '100%' : 256,
},
input: {
},
error: {
},
menu: {
top: 40,
left: 0,
width: '100%',
},
list: {
display: 'block',
width: this.props.fullWidth ? '100%' : 256,
},
};

let textFieldProps = {
style: this.mergeAndPrefix(styles.input, style),
floatingLabelText: floatingLabelText,
hintText: (!hintText && !floatingLabelText) ? '' : hintText,
fullWidth: true,
multiLine: false,
errorStyle: this.mergeAndPrefix(styles.error, errorStyle),
};

let mergedRootStyles = this.mergeAndPrefix(styles.root, style);
let mergedMenuStyles = this.mergeStyles(styles.menu, menuStyle);


let menu = this.state.open && this.state.searchText !== '' && requestsList ? (
<Menu
{...menuProps}
ref="menu"
key="dropDownMenu"
animated={true}
autoWidth={false}
initiallyKeyboardFocused={false}
onEscKeyDown={()=>this.setState({open:false})}
onItemTouchTap={this._handleItemTouchTap}
listStyle={this.mergeAndPrefix(styles.list, listStyle)}
openDirection="bottom-left"
style={mergedMenuStyles}>
{
requestsList.map((request, index) => {
switch(typeof request){
case 'string':
return (<MenuItem
disableFocusRipple={true}
key={index}
value={request}
primaryText={request}
/>);
case 'object':
return request;
default:
return null;
}
})
}
</Menu>
) : null;

return (
<div style={mergedRootStyles}
onKeyDown={(e)=>{
switch(e.keyCode){
case 27: //esc
this.setState({open:false});
break;
case 40: //down arrow
if(this.focusOnInput && this.state.open){
e.preventDefault();
this.focusOnInput = false;
this.setState({open:true});
}
break;
default:
break;
}
}}>
<div
style={{
widht:'100%',
}}>
<TextField
{...other}
ref="searchTextField"
value={this.state.searchText}
onEnterKeyDown={()=>{
setTimeout(() => {
this.state({open:false});
}, this.props.touchTapCloseDelay);
this.props.onNewRequest(this.state.searchText);
}}
onChange={
this._handleSearchTextChange
}
onBlur={()=>{
if(this.focusOnInput && this.state.open)
this.refs.searchTextField.focus();
}}
onFocus={()=>{
if(!this.state.open && this.searchText !== ''){
this.updateRequests(this.state.searchText);
}
this.focusOnInput = true;
}}

{...textFieldProps} />
</div>
<ReactTransitionGroup>{menu}</ReactTransitionGroup>
</div>
);
},

setValue(textValue) {
this.setState({
searchText: textValue,
});
},

getValue() {
return this.state.searchText;
},

_handleSearchTextChange(e){

let searchText = e.target.value;

this.updateRequests(searchText);
},

updateRequests(searchText){
let requestsListPromise = new Promise((resolve, reject) => {
let list = this.props.onUpdateRequests(searchText);
if(list){
resolve(list);
}
else{
reject();
}
});

requestsListPromise.then(list => {
this.focusOnInput = true;
this.setState({
searchText:searchText,
requestsList:list,
open: true,
});
}, ()=>{
this.setState({
searchText:searchText,
requestsList:null,
open: false,
});
});
},

_handleItemTouchTap(e, child) {
setTimeout(() => {
this.setState({open:false});
}, this.props.touchTapCloseDelay);

let index=parseInt(child.key, 10);

let chosenRequest=this.state.requestsList[index];
this.setState({searchText:typeof chosenRequest === 'string' ?
chosenRequest : chosenRequest.props.value});
this.props.onNewRequest(chosenRequest, index, this.state.requestsList);

},

});

module.exports = SearchField;

0 comments on commit 6832086

Please sign in to comment.