1
0
mirror of synced 2024-11-29 16:16:02 +03:00

Add support for hierarchies and unselectable items. issue #58

Signed-off-by: Igor Vaynberg <igor.vaynberg@gmail.com>
This commit is contained in:
Christopher Nadeau 2012-06-12 12:35:56 +01:00 committed by Igor Vaynberg
parent efccc62510
commit 6151ddbb0d
2 changed files with 145 additions and 37 deletions

View File

@ -236,13 +236,25 @@ Version: @@ver@@ Timestamp: @@timestamp@@
overflow-y: auto; overflow-y: auto;
max-height: 200px; max-height: 200px;
} }
.select2-results ul.select2-result-sub {
margin: 0 0 0 15px;
}
.select2-results li { .select2-results li {
list-style: none;
display: list-item;
}
.select2-results li.select2-result-with-children > .select2-result-label {
font-weight: bold;
}
.select2-results .select2-result-label {
line-height: 80%; line-height: 80%;
padding: 7px 7px 8px; padding: 7px 7px 8px;
margin: 0; margin: 0;
list-style: none;
cursor: pointer; cursor: pointer;
display: list-item;
} }
.select2-results .select2-highlighted { .select2-results .select2-highlighted {

View File

@ -20,7 +20,7 @@
return; return;
} }
var KEY, AbstractSelect2, SingleSelect2, MultiSelect2; var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, uid = 1;;
KEY = { KEY = {
TAB: 9, TAB: 9,
@ -475,8 +475,46 @@
} }
opts = $.extend({}, { opts = $.extend({}, {
formatResult: function (data) { return data.text; }, formatList: function(results) {
formatSelection: function (data) { return data.text; }, var proc = function(results, depth) {
depth = depth || 0;
var parts = [];
$.each(results, function() {
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>');
if (result.children && result.children.length) {
parts.push('<ul class="select2-result-sub">');
parts.push(proc(result.children, depth + 1))
parts.push('</ul>');
}
parts.push('</li>');
});
return parts.join('');
};
return proc(results, 0);
},
formatSelection: function (data) {
if (data.fullText) {
return data.fullText;
} else {
return data.text;
}
},
formatNoMatches: function () { return "No matches found"; }, formatNoMatches: function () { return "No matches found"; },
formatInputTooShort: function (input, min) { return "Please enter " + (min - input.length) + " more characters"; }, formatInputTooShort: function (input, min) { return "Please enter " + (min - input.length) + " more characters"; },
minimumResultsForSearch: 0, minimumResultsForSearch: 0,
@ -494,19 +532,80 @@
if (select) { if (select) {
opts.query = this.bind(function (query) { opts.query = this.bind(function (query) {
var data = {results: [], more: false}, var data = {results: [], map: {}, more: false},
term = query.term, term = query.term,
idx = 0,
placeholder = this.getPlaceholder(); placeholder = this.getPlaceholder();
element.find("option").each(function (i) {
var e = $(this),
text = e.text();
if (i === 0 && placeholder !== undefined && text === "") return true; element.find("> *").each(function() {
var el = $(this);
if (query.matcher(term, text)) { if (el.is('optgroup')) {
data.results.push({id: e.attr("value"), text: text}); 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);
}
}
return filtered;
}
data.results = filterDeep(data.results);
}
query.callback(data); query.callback(data);
}); });
// this is needed because inside val() we construct choices from options and there id is hardcoded // this is needed because inside val() we construct choices from options and there id is hardcoded
@ -622,7 +721,7 @@
ensureHighlightVisible: function () { ensureHighlightVisible: function () {
var results = this.results, children, index, child, hb, rb, y, more; var results = this.results, children, index, child, hb, rb, y, more;
children = results.children(".select2-result"); children = results.find(".select2-result");
index = this.highlight(); index = this.highlight();
if (index < 0) return; if (index < 0) return;
@ -652,7 +751,7 @@
}, },
moveHighlight: function (delta) { moveHighlight: function (delta) {
var choices = this.results.children(".select2-result"), var choices = this.results.find(".select2-result"),
index = this.highlight(); index = this.highlight();
while (index > -1 && index < choices.length) { while (index > -1 && index < choices.length) {
@ -665,17 +764,21 @@
}, },
highlight: function (index) { highlight: function (index) {
var choices = this.results.children(".select2-result"); var choices = this.results.find(".select2-result .select2-result-label");
if (arguments.length === 0) { if (arguments.length === 0) {
return indexOf(choices.filter(".select2-highlighted")[0], choices.get()); return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
} }
choices.removeClass("select2-highlighted");
if (index >= choices.length) index = choices.length - 1; if (index >= choices.length) index = choices.length - 1;
if (index < 0) index = 0; if (index < 0) index = 0;
if ($(choices[index]).parent().is('.select2-result-unselectable')) {
return;
}
choices.removeClass("select2-highlighted");
$(choices[index]).addClass("select2-highlighted"); $(choices[index]).addClass("select2-highlighted");
this.ensureHighlightVisible(); this.ensureHighlightVisible();
@ -684,8 +787,9 @@
highlightUnderEvent: function (event) { highlightUnderEvent: function (event) {
var el = $(event.target).closest(".select2-result"); var el = $(event.target).closest(".select2-result");
var choices = this.results.find('.select2-result');
if (el.length > 0) { if (el.length > 0) {
this.highlight(el.index()); this.highlight(choices.index(el));
} }
}, },
@ -708,19 +812,15 @@
context: self.context, context: self.context,
matcher: self.opts.matcher, matcher: self.opts.matcher,
callback: this.bind(function (data) { callback: this.bind(function (data) {
var parts = [], self = this; var self = this;
$(data.results).each(function () { var htmlResult = self.opts.formatList(data.results);
parts.push("<li class='select2-result'>"); more.before(htmlResult);
parts.push(self.opts.formatResult(this)); results.find(".select2-result").each(function () {
parts.push("</li>");
});
more.before(parts.join(""));
results.find(".select2-result").each(function (i) {
var e = $(this); var e = $(this);
if (e.data("select2-data") !== undefined) { if (e.data("select2-data") !== undefined) {
offset = i; offset = i;
} else { } else {
e.data("select2-data", data.results[i - offset - 1]); e.data("select2-data", data.map[e.data('select2-uid')]);
} }
}); });
if (data.more) { if (data.more) {
@ -785,19 +885,15 @@
return; return;
} }
$(data.results).each(function () { var htmlResult = self.opts.formatList(data.results);
parts.push("<li class='select2-result'>");
parts.push(opts.formatResult(this));
parts.push("</li>");
});
if (data.more === true) { if (data.more === true) {
parts.push("<li class='select2-more-results'>Loading more results...</li>"); htmlResult += "<li class='select2-more-results'>Loading more results...</li>";
} }
render(parts.join("")); render(htmlResult);
results.children(".select2-result").each(function (i) { results.find(".select2-result").each(function () {
var d = data.results[i]; var d = data.map[$(this).data('select2-uid')];
$(this).data("select2-data", d); $(this).data("select2-data", d);
}); });
this.postprocessResults(data, initial); this.postprocessResults(data, initial);
@ -830,7 +926,7 @@
}, },
selectHighlighted: function () { selectHighlighted: function () {
var data = this.results.find(".select2-highlighted:not(.select2-disabled)").data("select2-data"); var data = this.results.find(".select2-highlighted").not(".select2-disabled").closest('.select2-result').not('.select2-result-unselectable').data("select2-data");
if (data) { if (data) {
this.onSelect(data); this.onSelect(data);
} }