-
Notifications
You must be signed in to change notification settings - Fork 167
fixes issue #84, for pasting with delimiters #90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
6ced8e0
27939c1
d364403
5fae01c
89b68b3
88a33b2
56b2d10
274fc81
4a6962c
52cad74
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,10 @@ class ReactTags extends React.Component { | |
}) | ||
} | ||
|
||
escapeForRegExp (query) { | ||
return query.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&') | ||
} | ||
|
||
handleChange (e) { | ||
const query = e.target.value | ||
|
||
|
@@ -56,6 +60,47 @@ class ReactTags extends React.Component { | |
this.setState({ query }) | ||
} | ||
|
||
handlePaste (e) { | ||
// allow over-ride, if there is a need | ||
if (this.props.handlePaste) { | ||
return this.props.handlePaste(e) | ||
} | ||
|
||
const { delimiterChars } = this.props | ||
|
||
e.preventDefault() | ||
|
||
// get the text data from the clipboard | ||
const data = e.clipboardData.getData('Text') | ||
|
||
if (data && delimiterChars.length > 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the expectation if delimiterChars.length is 0? Currently nothing is converted to tag. I am want to see if this is reasonable or whether we should treat it as one block? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there are no delimiterChars, then ReactTags can't do its job, I think? It needs a list to be able to chunk up input in the first place so if it does not have that list it can't convert string data into tags. Some options are to issue a warning ("no delimiter characters specified for onPaste handling by ReactTags") or to simply break out of the handler function before any code actually gets run. @i-like-robots is the idea that delimiterChars and delimiters are mutually exclusive (e.g. if you need real letters, don't use numbers, and vice versa) or are they complementary? (in which case I might try to build a map that can tell which key is which keyboard event code, because the difference between those two is still ridiculous =D) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would this be okay: else if (!delimiterChars || delimiterChars.length === 0) {
if (console) {
console.warn('no delimiterChars specified, so ignoring paste operation')
}
} For the evolution of delimiterChars and delimiters, could that be another ticket, given there is probably a lot of subtle use cases? For example the enter key can have two different values, depending on whether it is on the alphanumeric or num-pad section of the keyboard. I don't have a num-pad to test with. Should that unification work be done as part of issue #81? |
||
// split the string based on the delimiterChars as a regex, being sure | ||
// to escape chars, to prevent them being treated as special characters | ||
const tags = data.split(new RegExp('[' + this.escapeForRegExp(delimiterChars.join('')) + ']')) | ||
for (let i = 0; i < tags.length; i++) { | ||
// the logic here is similar to handleKeyDown, but subtly different, | ||
// due to the context of the operation | ||
if (tags[i].length > 0) { | ||
// look to see if the tag is already known | ||
const matchIdx = this.props.suggestions.findIndex((suggestion) => { | ||
return tags[i] === suggestion.name | ||
}) | ||
|
||
// if already known add it, otherwise add it only if we allow new tags | ||
if (matchIdx > -1) { | ||
this.addTag(this.props.suggestions[matchIdx]) | ||
} else if (this.props.allowNew) { | ||
this.addTag({ name: tags[i] }) | ||
} | ||
} | ||
} | ||
} else if (!delimiterChars || delimiterChars.length === 0) { | ||
if (console) { | ||
console.warn('no delimiterChars specified, so ignoring paste operation') | ||
} | ||
} | ||
} | ||
|
||
handleKeyDown (e) { | ||
const { query, selectedIndex } = this.state | ||
const { delimiters, delimiterChars } = this.props | ||
|
@@ -166,14 +211,16 @@ class ReactTags extends React.Component { | |
onBlur={this.handleBlur.bind(this)} | ||
onFocus={this.handleFocus.bind(this)} | ||
onChange={this.handleChange.bind(this)} | ||
onKeyDown={this.handleKeyDown.bind(this)}> | ||
onKeyDown={this.handleKeyDown.bind(this)} | ||
onPaste={this.handlePaste.bind(this)} > | ||
<Input {...this.state} | ||
ref={(c) => { this.input = c }} | ||
listboxId={listboxId} | ||
autofocus={this.props.autofocus} | ||
autoresize={this.props.autoresize} | ||
expandable={expandable} | ||
placeholder={this.props.placeholder} /> | ||
placeholder={this.props.placeholder} | ||
/> | ||
<Suggestions {...this.state} | ||
ref={(c) => { this.suggestions = c }} | ||
listboxId={listboxId} | ||
|
@@ -194,7 +241,7 @@ ReactTags.defaultProps = { | |
autofocus: true, | ||
autoresize: true, | ||
delimiters: [KEYS.TAB, KEYS.ENTER], | ||
delimiterChars: [], | ||
delimiterChars: ['\t', '\r\n', '\r', '\n'], | ||
minQueryLength: 2, | ||
maxSuggestionsLength: 6, | ||
allowNew: false, | ||
|
@@ -213,6 +260,7 @@ ReactTags.propTypes = { | |
handleDelete: PropTypes.func.isRequired, | ||
handleAddition: PropTypes.func.isRequired, | ||
handleInputChange: PropTypes.func, | ||
handlePaste: PropTypes.func, | ||
minQueryLength: PropTypes.number, | ||
maxSuggestionsLength: PropTypes.number, | ||
classNames: PropTypes.object, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd still advocate sticking with React conventions and calling this
onPaste
, but take that as just an opinion of a fellow react component dev rather than anything more than that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See issue #91