diff --git a/select2.js b/select2.js index 572fac23..10bb75fc 100755 --- a/select2.js +++ b/select2.js @@ -20,7 +20,7 @@ return; } - var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, uid = 1;; + var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid; KEY = { TAB: 9, @@ -67,6 +67,8 @@ } }; + nextUid=(function() { var counter=1; return function() { return counter++; }}()); + function indexOf(value, array) { var i = 0, l = array.length, v; @@ -474,38 +476,58 @@ } opts = $.extend({}, { - formatList: function(results) { - var proc = function(results, depth) { - depth = depth || 0; - var parts = []; + populateResults: function(container, results) { + var uidToData={}, populate, markup=[], uid, data, result, children; - $.each(results, function() { - var result = this; - parts.push('
  • '); + populate=function(results, depth) { - parts.push('
    ' + result.text + '
    '); + var i, l, uid, result, selectable, compound; + for (i = 0, l = results.length; i < l; i = i + 1) { - if (result.children && result.children.length) { - parts.push(''); + result=results[i]; + selectable=("id" in result); // TODO switch to id() function + compound=("children" in result) && result.children.length > 0; + + markup.push("
  • '); - }); + markup.push(">
    "+opts.formatResult(result)+"
    "); + if (compound) { + markup.push(""); + } - return parts.join(''); + markup.push("
  • "); + } }; - 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) { if (data.fullText) { @@ -531,79 +553,26 @@ if (select) { opts.query = this.bind(function (query) { - var data = {results: [], map: {}, more: false}, + var data = { results: [], more: false }, term = query.term, - idx = 0, - placeholder = this.getPlaceholder(); + process; - element.find("> *").each(function() { - var el = $(this); - - if (el.is('optgroup')) { - var item = { - id: 'select2-group-' + (uid++), - uid: uid++, - text: el.attr('label'), - unselectable: true, - children: [] - }; - 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; - 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); - } + process=function(element, collection) { + var group; + if (element.is("option")) { + if (query.matcher(term, element.text())) { + collection.push({id:element.attr("value"), text:element.text()}); + } + } else if (element.is("optgroup")) { + group={text:element.attr("label"), children:[]}; + element.children().each(function() { process($(this), group.children); }); + if (group.children.length>0) { + collection.push(group); } - - return filtered; } + }; - data.results = filterDeep(data.results); - } + element.children().each(function() { process($(this), data.results); }); query.callback(data); }); @@ -796,10 +765,10 @@ 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 offset = -1, // index of first element without data - page = this.resultsPage + 1; + page = this.resultsPage + 1, + self=this; if (more.length === 0) return; - below = more.offset().top - results.offset().top - results.height(); if (below <= 0) { @@ -807,26 +776,21 @@ this.opts.query({ term: this.search.val(), page: page, - context: self.context, - matcher: self.opts.matcher, + context: this.context, + matcher: this.opts.matcher, callback: this.bind(function (data) { - var self = this; - var htmlResult = self.opts.formatList(data.results); - more.before(htmlResult); - results.find(".select2-result").each(function () { - var e = $(this); - if (e.data("select2-data") !== undefined) { - offset = i; - } else { - e.data("select2-data", data.map[e.data('select2-uid')]); - } - }); - if (data.more) { + console.log("load more callback", data); + + self.opts.populateResults(results, data.results); + + if (data.more===true) { + more.detach(); + results.children().filter(":last").append(more); more.removeClass("select2-active"); } else { more.remove(); } - this.resultsPage = page; + self.resultsPage = page; })}); } }, @@ -844,12 +808,16 @@ search.addClass("select2-active"); - function render(html) { - results.html(html); + function postRender() { results.scrollTop(0); search.removeClass("select2-active"); } + function render(html) { + results.html(html); + postRender(); + } + if (search.val().length < opts.minimumInputLength) { render("
  • " + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "
  • "); return; @@ -862,8 +830,7 @@ context: null, matcher: opts.matcher, callback: this.bind(function (data) { - var parts = [], // html parts - def; // default choice + var def; // default choice // create a default choice and prepend it to the list if (this.opts.createSearchChoice && search.val() !== "") { @@ -883,17 +850,14 @@ return; } - var htmlResult = self.opts.formatList(data.results); + results.empty(); + self.opts.populateResults(results, data.results); + postRender(); if (data.more === true) { - htmlResult += "
  • Loading more results...
  • "; + results.children().filter(":last").append("
  • Loading more results...
  • "); } - 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); })}); },