|
20 | 20 | return; |
21 | 21 | } |
22 | 22 |
|
23 | | - var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, uid = 1;; |
| 23 | + var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid; |
24 | 24 |
|
25 | 25 | KEY = { |
26 | 26 | TAB: 9, |
|
67 | 67 | } |
68 | 68 | }; |
69 | 69 |
|
| 70 | + nextUid=(function() { var counter=1; return function() { return counter++; }}()); |
| 71 | + |
70 | 72 | function indexOf(value, array) { |
71 | 73 | var i = 0, l = array.length, v; |
72 | 74 |
|
|
474 | 476 | } |
475 | 477 |
|
476 | 478 | opts = $.extend({}, { |
477 | | - formatList: function(results) { |
478 | | - var proc = function(results, depth) { |
479 | | - depth = depth || 0; |
480 | | - var parts = []; |
481 | | - |
482 | | - $.each(results, function() { |
483 | | - var result = this; |
484 | | - parts.push('<li class="select2-result select2-result-uid-' + result.uid + ' select2-result-depth-' + depth); |
485 | | - if (result.unselectable) { |
486 | | - parts.push(' select2-result-unselectable'); |
487 | | - } |
488 | | - if (result.children && result.children.length) { |
489 | | - parts.push(' select2-result-with-children'); |
490 | | - } |
491 | | - parts.push('" data-select2-uid="' + result.uid + '">'); |
| 479 | + populateResults: function(container, results) { |
| 480 | + var uidToData={}, populate, markup=[], uid, data, result, children; |
| 481 | + |
| 482 | + populate=function(results, depth) { |
| 483 | + |
| 484 | + var i, l, uid, result, selectable, compound; |
| 485 | + for (i = 0, l = results.length; i < l; i = i + 1) { |
492 | 486 |
|
493 | | - parts.push('<div class="select2-result-label">' + result.text + '</div>'); |
| 487 | + result=results[i]; |
| 488 | + selectable=("id" in result); // TODO switch to id() function |
| 489 | + compound=("children" in result) && result.children.length > 0; |
494 | 490 |
|
495 | | - if (result.children && result.children.length) { |
496 | | - parts.push('<ul class="select2-result-sub">'); |
497 | | - parts.push(proc(result.children, depth + 1)) |
498 | | - parts.push('</ul>'); |
| 491 | + markup.push("<li class='select2-result-depth-"+depth); |
| 492 | + if (!selectable) { markup.push(" select2-result-unselectable"); } else { markup.push(" select2-result");} |
| 493 | + if (compound) { markup.push(" select2-result-with-children"); } |
| 494 | + |
| 495 | + markup.push("'"); |
| 496 | + |
| 497 | + if (selectable) { |
| 498 | + uid=nextUid(); |
| 499 | + markup.push(" id='select2-result-"+uid+"'"); |
| 500 | + uidToData[uid]=result; |
499 | 501 | } |
500 | 502 |
|
501 | | - parts.push('</li>'); |
502 | | - }); |
| 503 | + markup.push("><div class='select2-result-label'>"+opts.formatResult(result)+"</div>"); |
503 | 504 |
|
| 505 | + if (compound) { |
| 506 | + markup.push("<ul class='select2-result-sub'>"); |
| 507 | + populate(result.children, depth + 1); |
| 508 | + markup.push("</ul>"); |
| 509 | + } |
504 | 510 |
|
505 | | - return parts.join(''); |
| 511 | + markup.push("</li>"); |
| 512 | + } |
506 | 513 | }; |
507 | 514 |
|
508 | | - return proc(results, 0); |
| 515 | + populate(results, 0); |
| 516 | + |
| 517 | + children=container.children(); |
| 518 | + if (children.length==0) { |
| 519 | + container.html(markup.join("")); |
| 520 | + } else { |
| 521 | + $(children[children.length-1]).append(markup.join("")); |
| 522 | + } |
| 523 | + |
| 524 | + for (uid in uidToData) { |
| 525 | + $("#select2-result-"+uid).data("select2-data", uidToData[uid]); |
| 526 | + } |
| 527 | + |
| 528 | + }, |
| 529 | + formatResult: function(result) { |
| 530 | + return result.text; |
509 | 531 | }, |
510 | 532 | formatSelection: function (data) { |
511 | 533 | if (data.fullText) { |
|
531 | 553 |
|
532 | 554 | if (select) { |
533 | 555 | opts.query = this.bind(function (query) { |
534 | | - var data = {results: [], map: {}, more: false}, |
| 556 | + var data = { results: [], more: false }, |
535 | 557 | term = query.term, |
536 | | - idx = 0, |
537 | | - placeholder = this.getPlaceholder(); |
538 | | - |
539 | | - element.find("> *").each(function() { |
540 | | - var el = $(this); |
541 | | - |
542 | | - if (el.is('optgroup')) { |
543 | | - var item = { |
544 | | - id: 'select2-group-' + (uid++), |
545 | | - uid: uid++, |
546 | | - text: el.attr('label'), |
547 | | - unselectable: true, |
548 | | - children: [] |
549 | | - }; |
550 | | - data.map[item.uid] = item; |
551 | | - |
552 | | - el.find('> option').each(function() { |
553 | | - var sub = { |
554 | | - id: $(this).attr('value'), |
555 | | - uid: uid++, |
556 | | - text: $(this).text(), |
557 | | - unselectable: false, |
558 | | - fullText: el.attr('label') + ' > ' + $(this).text(), |
559 | | - children: [] |
560 | | - }; |
561 | | - |
562 | | - data.map[sub.uid] = sub; |
563 | | - item.children.push(sub); |
564 | | - }); |
565 | | - |
566 | | - data.results.push(item); |
567 | | - } else { |
568 | | - var item = { |
569 | | - id: $(this).attr('value'), |
570 | | - uid: uid++, |
571 | | - text: $(this).text(), |
572 | | - unselectable: false, |
573 | | - children: [] |
574 | | - }; |
575 | | - |
576 | | - data.map[item.uid] = item; |
577 | | - data.results.push(item); |
578 | | - } |
579 | | - }); |
| 558 | + process; |
580 | 559 |
|
581 | | - if (term !== "") { |
582 | | - var filterDeep = function(items, depth) { |
583 | | - var filtered = []; |
584 | | - for (var itemIdx = 0; itemIdx < items.length; itemIdx++) { |
585 | | - var newItem = $.extend(true, [], items[itemIdx]); |
586 | | - if (newItem.children) { |
587 | | - newItem.children = filterDeep(newItem.children); |
588 | | - } |
589 | | - |
590 | | - var isMatch = false; |
591 | | - if (newItem.children && newItem.children.length) { |
592 | | - isMatch = true; |
593 | | - } else if (!newItem.unselectable && query.matcher(term, newItem.text)) { |
594 | | - isMatch = true; |
595 | | - } |
596 | | - |
597 | | - if (isMatch) { |
598 | | - filtered.push(newItem); |
599 | | - } |
| 560 | + process=function(element, collection) { |
| 561 | + var group; |
| 562 | + if (element.is("option")) { |
| 563 | + if (query.matcher(term, element.text())) { |
| 564 | + collection.push({id:element.attr("value"), text:element.text()}); |
| 565 | + } |
| 566 | + } else if (element.is("optgroup")) { |
| 567 | + group={text:element.attr("label"), children:[]}; |
| 568 | + element.children().each(function() { process($(this), group.children); }); |
| 569 | + if (group.children.length>0) { |
| 570 | + collection.push(group); |
600 | 571 | } |
601 | | - |
602 | | - return filtered; |
603 | 572 | } |
| 573 | + }; |
604 | 574 |
|
605 | | - data.results = filterDeep(data.results); |
606 | | - } |
| 575 | + element.children().each(function() { process($(this), data.results); }); |
607 | 576 |
|
608 | 577 | query.callback(data); |
609 | 578 | }); |
|
796 | 765 | more = results.find("li.select2-more-results"), |
797 | 766 | below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible |
798 | 767 | offset = -1, // index of first element without data |
799 | | - page = this.resultsPage + 1; |
| 768 | + page = this.resultsPage + 1, |
| 769 | + self=this; |
800 | 770 |
|
801 | 771 | if (more.length === 0) return; |
802 | | - |
803 | 772 | below = more.offset().top - results.offset().top - results.height(); |
804 | 773 |
|
805 | 774 | if (below <= 0) { |
806 | 775 | more.addClass("select2-active"); |
807 | 776 | this.opts.query({ |
808 | 777 | term: this.search.val(), |
809 | 778 | page: page, |
810 | | - context: self.context, |
811 | | - matcher: self.opts.matcher, |
| 779 | + context: this.context, |
| 780 | + matcher: this.opts.matcher, |
812 | 781 | callback: this.bind(function (data) { |
813 | | - var self = this; |
814 | | - var htmlResult = self.opts.formatList(data.results); |
815 | | - more.before(htmlResult); |
816 | | - results.find(".select2-result").each(function () { |
817 | | - var e = $(this); |
818 | | - if (e.data("select2-data") !== undefined) { |
819 | | - offset = i; |
820 | | - } else { |
821 | | - e.data("select2-data", data.map[e.data('select2-uid')]); |
822 | | - } |
823 | | - }); |
824 | | - if (data.more) { |
| 782 | + console.log("load more callback", data); |
| 783 | + |
| 784 | + self.opts.populateResults(results, data.results); |
| 785 | + |
| 786 | + if (data.more===true) { |
| 787 | + more.detach(); |
| 788 | + results.children().filter(":last").append(more); |
825 | 789 | more.removeClass("select2-active"); |
826 | 790 | } else { |
827 | 791 | more.remove(); |
828 | 792 | } |
829 | | - this.resultsPage = page; |
| 793 | + self.resultsPage = page; |
830 | 794 | })}); |
831 | 795 | } |
832 | 796 | }, |
|
844 | 808 |
|
845 | 809 | search.addClass("select2-active"); |
846 | 810 |
|
847 | | - function render(html) { |
848 | | - results.html(html); |
| 811 | + function postRender() { |
849 | 812 | results.scrollTop(0); |
850 | 813 | search.removeClass("select2-active"); |
851 | 814 | } |
852 | 815 |
|
| 816 | + function render(html) { |
| 817 | + results.html(html); |
| 818 | + postRender(); |
| 819 | + } |
| 820 | + |
853 | 821 | if (search.val().length < opts.minimumInputLength) { |
854 | 822 | render("<li class='select2-no-results'>" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "</li>"); |
855 | 823 | return; |
|
862 | 830 | context: null, |
863 | 831 | matcher: opts.matcher, |
864 | 832 | callback: this.bind(function (data) { |
865 | | - var parts = [], // html parts |
866 | | - def; // default choice |
| 833 | + var def; // default choice |
867 | 834 |
|
868 | 835 | // create a default choice and prepend it to the list |
869 | 836 | if (this.opts.createSearchChoice && search.val() !== "") { |
|
883 | 850 | return; |
884 | 851 | } |
885 | 852 |
|
886 | | - var htmlResult = self.opts.formatList(data.results); |
| 853 | + results.empty(); |
| 854 | + self.opts.populateResults(results, data.results); |
| 855 | + postRender(); |
887 | 856 |
|
888 | 857 | if (data.more === true) { |
889 | | - htmlResult += "<li class='select2-more-results'>Loading more results...</li>"; |
| 858 | + results.children().filter(":last").append("<li class='select2-more-results'>Loading more results...</li>"); |
890 | 859 | } |
891 | 860 |
|
892 | | - render(htmlResult); |
893 | | - results.find(".select2-result").each(function () { |
894 | | - var d = data.map[$(this).data('select2-uid')]; |
895 | | - $(this).data("select2-data", d); |
896 | | - }); |
897 | 861 | this.postprocessResults(data, initial); |
898 | 862 | })}); |
899 | 863 | }, |
|
0 commit comments