I am using Select2 to manage large lists of data. Users have expressed a desire to be able to paste a list to the Select2 field in order to select various items at once instead of manually entering and matching each item in the list.
I have attempted to use tokenSeparators
to separate the items in the list. This and the demo on tokens in the documentation lead me to believe that what I am hoping to do is possible, but so far I have had no joy.
The code I use to instantiate Select2 is:
$('input').select2({
width: 'element',
matcher: function (term, text) {
return text.toUpperCase().indexOf(term.toUpperCase()) === 0;
},
minimumInputLength: 3,
multiple: true,
data: tagList, // tagList is an array of objects with id & text parameters
placeholder: 'Manage List',
initSelection: function (element, callback) {
var data = [];
$.each(function () {
data.push({id: this, text: this});
});
callback(data);
},
tokenSeparators: [',', ', ', ' ']
});
Just to clarify, in all other respects the select2 field works. It's just that nothing is matched when a list is pasted into the field. I would like to test all the items in the pasted list. Is this possible and, if so, how?
Edit: I have tried the following code but it does not seem to work:
$('body').on('paste', '#s2id_list-unitids .select2-input', function () {
var that = this;
setTimeout(function () {
var tokens = that.value.split(/[\,\s]+/);
$('#list-unitids').val(tokens, true);console.log($('#list-unitids').select2('val'));
}, 1);
});
And here is a fiddle I've created: http://jsfiddle.net/KCZDu/.
select2 provides a tokenizer
option that lets you pre-process the input. here is a possible implementation for your particular usecase:
tokenizer: function(input, selection, callback) {
// no comma no need to tokenize
if (input.indexOf(',')<0) return;
var parts=input.split(",");
for (var i=0;i<parts.length;i++) {
var part=parts[i];
part=part.trim();
// todo: check for dupes (if part is already in [selection])
// check if the part is valid
// todo: you will need a better way of doing this
var valid=false;
for (var j=0;j<unitIds.length;j++) {
if (part===unitIds[j]) { valid=true; break; }
}
if (valid) callback({id:part,text:part});
}
}
here is a working fiddle: http://jsfiddle.net/XcCqg/38/
also note your original fiddle uses select2 3.2 which is very outdated and may not support the tokenizer.
Basically it overrides the default paste function to handle the new input text, this code will break the input based on the separators specified in the option 'tokenSeparators', then adds them all to the list separated, you only need to run this code at the end of your page:
$(document).on('paste', 'span.select2', function (e) {
e.preventDefault();
var select = $(e.target).closest('.select2').prev();
var clipboard = (e.originalEvent || e).clipboardData.getData('text/plain');
var createOption = function (value, selected) {
selected = typeof selected !== 'undefined' ? selected : true;
return $("<option></option>")
.attr("value", value)
.attr("selected", selected)
.text(value)[0]
};
$.each(
clipboard.split(new RegExp(select.data('select2').options.options.tokenSeparators.map(function (a) {
return (a).replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}).join('|'))),
function (key, value) {
if (value && (!select.val() || (select.val() && select.val().indexOf('' + value) == -1))) {
select.append(createOption(value));
}
});
select.trigger('change');
});
来源:https://stackoverflow.com/questions/17197223/is-it-possible-to-paste-a-list-to-a-select2-field-and-match-each-item-in-the-lis