simplify optgroup querying and rendering code. provide a more powerful populateResults() function fixes #58. fixes #105. fixes #84
This commit is contained in:
parent
9fc18a9ca8
commit
55fd00169e
206
select2.js
206
select2.js
@ -20,7 +20,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, uid = 1;;
|
var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid;
|
||||||
|
|
||||||
KEY = {
|
KEY = {
|
||||||
TAB: 9,
|
TAB: 9,
|
||||||
@ -67,6 +67,8 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
nextUid=(function() { var counter=1; return function() { return counter++; }}());
|
||||||
|
|
||||||
function indexOf(value, array) {
|
function indexOf(value, array) {
|
||||||
var i = 0, l = array.length, v;
|
var i = 0, l = array.length, v;
|
||||||
|
|
||||||
@ -474,38 +476,58 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts = $.extend({}, {
|
opts = $.extend({}, {
|
||||||
formatList: function(results) {
|
populateResults: function(container, results) {
|
||||||
var proc = function(results, depth) {
|
var uidToData={}, populate, markup=[], uid, data, result, children;
|
||||||
depth = depth || 0;
|
|
||||||
var parts = [];
|
|
||||||
|
|
||||||
$.each(results, function() {
|
populate=function(results, depth) {
|
||||||
var result = this;
|
|
||||||
parts.push('<li class="select2-result select2-result-uid-' + result.uid + ' select2-result-depth-' + depth);
|
|
||||||
if (result.unselectable) {
|
|
||||||
parts.push(' select2-result-unselectable');
|
|
||||||
}
|
|
||||||
if (result.children && result.children.length) {
|
|
||||||
parts.push(' select2-result-with-children');
|
|
||||||
}
|
|
||||||
parts.push('" data-select2-uid="' + result.uid + '">');
|
|
||||||
|
|
||||||
parts.push('<div class="select2-result-label">' + result.text + '</div>');
|
var i, l, uid, result, selectable, compound;
|
||||||
|
for (i = 0, l = results.length; i < l; i = i + 1) {
|
||||||
|
|
||||||
if (result.children && result.children.length) {
|
result=results[i];
|
||||||
parts.push('<ul class="select2-result-sub">');
|
selectable=("id" in result); // TODO switch to id() function
|
||||||
parts.push(proc(result.children, depth + 1))
|
compound=("children" in result) && result.children.length > 0;
|
||||||
parts.push('</ul>');
|
|
||||||
|
markup.push("<li class='select2-result-depth-"+depth);
|
||||||
|
if (!selectable) { markup.push(" select2-result-unselectable"); } else { markup.push(" select2-result");}
|
||||||
|
if (compound) { markup.push(" select2-result-with-children"); }
|
||||||
|
|
||||||
|
markup.push("'");
|
||||||
|
|
||||||
|
if (selectable) {
|
||||||
|
uid=nextUid();
|
||||||
|
markup.push(" id='select2-result-"+uid+"'");
|
||||||
|
uidToData[uid]=result;
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.push('</li>');
|
markup.push("><div class='select2-result-label'>"+opts.formatResult(result)+"</div>");
|
||||||
});
|
|
||||||
|
|
||||||
|
if (compound) {
|
||||||
|
markup.push("<ul class='select2-result-sub'>");
|
||||||
|
populate(result.children, depth + 1);
|
||||||
|
markup.push("</ul>");
|
||||||
|
}
|
||||||
|
|
||||||
return parts.join('');
|
markup.push("</li>");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return proc(results, 0);
|
populate(results, 0);
|
||||||
|
|
||||||
|
children=container.children();
|
||||||
|
if (children.length==0) {
|
||||||
|
container.html(markup.join(""));
|
||||||
|
} else {
|
||||||
|
$(children[children.length-1]).append(markup.join(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uid in uidToData) {
|
||||||
|
$("#select2-result-"+uid).data("select2-data", uidToData[uid]);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
formatResult: function(result) {
|
||||||
|
return result.text;
|
||||||
},
|
},
|
||||||
formatSelection: function (data) {
|
formatSelection: function (data) {
|
||||||
if (data.fullText) {
|
if (data.fullText) {
|
||||||
@ -531,79 +553,26 @@
|
|||||||
|
|
||||||
if (select) {
|
if (select) {
|
||||||
opts.query = this.bind(function (query) {
|
opts.query = this.bind(function (query) {
|
||||||
var data = {results: [], map: {}, more: false},
|
var data = { results: [], more: false },
|
||||||
term = query.term,
|
term = query.term,
|
||||||
idx = 0,
|
process;
|
||||||
placeholder = this.getPlaceholder();
|
|
||||||
|
|
||||||
element.find("> *").each(function() {
|
process=function(element, collection) {
|
||||||
var el = $(this);
|
var group;
|
||||||
|
if (element.is("option")) {
|
||||||
if (el.is('optgroup')) {
|
if (query.matcher(term, element.text())) {
|
||||||
var item = {
|
collection.push({id:element.attr("value"), text:element.text()});
|
||||||
id: 'select2-group-' + (uid++),
|
}
|
||||||
uid: uid++,
|
} else if (element.is("optgroup")) {
|
||||||
text: el.attr('label'),
|
group={text:element.attr("label"), children:[]};
|
||||||
unselectable: true,
|
element.children().each(function() { process($(this), group.children); });
|
||||||
children: []
|
if (group.children.length>0) {
|
||||||
};
|
collection.push(group);
|
||||||
data.map[item.uid] = item;
|
}
|
||||||
|
}
|
||||||
el.find('> option').each(function() {
|
|
||||||
var sub = {
|
|
||||||
id: $(this).attr('value'),
|
|
||||||
uid: uid++,
|
|
||||||
text: $(this).text(),
|
|
||||||
unselectable: false,
|
|
||||||
fullText: el.attr('label') + ' > ' + $(this).text(),
|
|
||||||
children: []
|
|
||||||
};
|
};
|
||||||
|
|
||||||
data.map[sub.uid] = sub;
|
element.children().each(function() { process($(this), data.results); });
|
||||||
item.children.push(sub);
|
|
||||||
});
|
|
||||||
|
|
||||||
data.results.push(item);
|
|
||||||
} else {
|
|
||||||
var item = {
|
|
||||||
id: $(this).attr('value'),
|
|
||||||
uid: uid++,
|
|
||||||
text: $(this).text(),
|
|
||||||
unselectable: false,
|
|
||||||
children: []
|
|
||||||
};
|
|
||||||
|
|
||||||
data.map[item.uid] = item;
|
|
||||||
data.results.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (term !== "") {
|
|
||||||
var filterDeep = function(items, depth) {
|
|
||||||
var filtered = [];
|
|
||||||
for (var itemIdx = 0; itemIdx < items.length; itemIdx++) {
|
|
||||||
var newItem = $.extend(true, [], items[itemIdx]);
|
|
||||||
if (newItem.children) {
|
|
||||||
newItem.children = filterDeep(newItem.children);
|
|
||||||
}
|
|
||||||
|
|
||||||
var isMatch = false;
|
|
||||||
if (newItem.children && newItem.children.length) {
|
|
||||||
isMatch = true;
|
|
||||||
} else if (!newItem.unselectable && query.matcher(term, newItem.text)) {
|
|
||||||
isMatch = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMatch) {
|
|
||||||
filtered.push(newItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filtered;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.results = filterDeep(data.results);
|
|
||||||
}
|
|
||||||
|
|
||||||
query.callback(data);
|
query.callback(data);
|
||||||
});
|
});
|
||||||
@ -796,10 +765,10 @@
|
|||||||
more = results.find("li.select2-more-results"),
|
more = results.find("li.select2-more-results"),
|
||||||
below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
|
below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
|
||||||
offset = -1, // index of first element without data
|
offset = -1, // index of first element without data
|
||||||
page = this.resultsPage + 1;
|
page = this.resultsPage + 1,
|
||||||
|
self=this;
|
||||||
|
|
||||||
if (more.length === 0) return;
|
if (more.length === 0) return;
|
||||||
|
|
||||||
below = more.offset().top - results.offset().top - results.height();
|
below = more.offset().top - results.offset().top - results.height();
|
||||||
|
|
||||||
if (below <= 0) {
|
if (below <= 0) {
|
||||||
@ -807,26 +776,21 @@
|
|||||||
this.opts.query({
|
this.opts.query({
|
||||||
term: this.search.val(),
|
term: this.search.val(),
|
||||||
page: page,
|
page: page,
|
||||||
context: self.context,
|
context: this.context,
|
||||||
matcher: self.opts.matcher,
|
matcher: this.opts.matcher,
|
||||||
callback: this.bind(function (data) {
|
callback: this.bind(function (data) {
|
||||||
var self = this;
|
console.log("load more callback", data);
|
||||||
var htmlResult = self.opts.formatList(data.results);
|
|
||||||
more.before(htmlResult);
|
self.opts.populateResults(results, data.results);
|
||||||
results.find(".select2-result").each(function () {
|
|
||||||
var e = $(this);
|
if (data.more===true) {
|
||||||
if (e.data("select2-data") !== undefined) {
|
more.detach();
|
||||||
offset = i;
|
results.children().filter(":last").append(more);
|
||||||
} else {
|
|
||||||
e.data("select2-data", data.map[e.data('select2-uid')]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (data.more) {
|
|
||||||
more.removeClass("select2-active");
|
more.removeClass("select2-active");
|
||||||
} else {
|
} else {
|
||||||
more.remove();
|
more.remove();
|
||||||
}
|
}
|
||||||
this.resultsPage = page;
|
self.resultsPage = page;
|
||||||
})});
|
})});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -844,12 +808,16 @@
|
|||||||
|
|
||||||
search.addClass("select2-active");
|
search.addClass("select2-active");
|
||||||
|
|
||||||
function render(html) {
|
function postRender() {
|
||||||
results.html(html);
|
|
||||||
results.scrollTop(0);
|
results.scrollTop(0);
|
||||||
search.removeClass("select2-active");
|
search.removeClass("select2-active");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function render(html) {
|
||||||
|
results.html(html);
|
||||||
|
postRender();
|
||||||
|
}
|
||||||
|
|
||||||
if (search.val().length < opts.minimumInputLength) {
|
if (search.val().length < opts.minimumInputLength) {
|
||||||
render("<li class='select2-no-results'>" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "</li>");
|
render("<li class='select2-no-results'>" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "</li>");
|
||||||
return;
|
return;
|
||||||
@ -862,8 +830,7 @@
|
|||||||
context: null,
|
context: null,
|
||||||
matcher: opts.matcher,
|
matcher: opts.matcher,
|
||||||
callback: this.bind(function (data) {
|
callback: this.bind(function (data) {
|
||||||
var parts = [], // html parts
|
var def; // default choice
|
||||||
def; // default choice
|
|
||||||
|
|
||||||
// create a default choice and prepend it to the list
|
// create a default choice and prepend it to the list
|
||||||
if (this.opts.createSearchChoice && search.val() !== "") {
|
if (this.opts.createSearchChoice && search.val() !== "") {
|
||||||
@ -883,17 +850,14 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var htmlResult = self.opts.formatList(data.results);
|
results.empty();
|
||||||
|
self.opts.populateResults(results, data.results);
|
||||||
|
postRender();
|
||||||
|
|
||||||
if (data.more === true) {
|
if (data.more === true) {
|
||||||
htmlResult += "<li class='select2-more-results'>Loading more results...</li>";
|
results.children().filter(":last").append("<li class='select2-more-results'>Loading more results...</li>");
|
||||||
}
|
}
|
||||||
|
|
||||||
render(htmlResult);
|
|
||||||
results.find(".select2-result").each(function () {
|
|
||||||
var d = data.map[$(this).data('select2-uid')];
|
|
||||||
$(this).data("select2-data", d);
|
|
||||||
});
|
|
||||||
this.postprocessResults(data, initial);
|
this.postprocessResults(data, initial);
|
||||||
})});
|
})});
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user