Fiddle is here: http://jsfiddle.net/bDvkQ/
The reason for using check boxes is so that the user may select many items in one pass. The default behavior of other types of multi-select drop-downs (e.g. Chosen) requires 2*n clicks for n selections; one click to open the drop down, and a second click to make a selection, then the popup closes again. This is fine for infrequently used forms, but when the user hits the same form dozens of times a day, minimizing user clicks is important. This drop-down requires n+2 clicks for n selections.
This could benefit from Select All and Clear actions as well, but I ran out of time. Feel free to hack on this further to suit your needs. As-is, no warranties, and all that.
Kasey
56 Answers, 1 is accepted
Thank you for the sharing. The implementation looks very well and the widget can be very helpful for those who need multi-select component. I updated your Telerik points, because of the sharing.
As a side note, I just want to mention that the "multi-select" widget is planned for the next (Q1 2013) release of KendoUI.
Georgi Krustev
the Telerik team
I'd much rather have the official Kendo control, and I'll be looking forward to its release.
:-)
Thanks
Here is a fork with the option label.
http://jsfiddle.net/xgVpX/
However, there are still a lot of things missing from this example.
- Select/Clear All buttons
- Clicking text should also toggle the text box
- Auto-resize when data-bound (still a mystery why the drop-down list does not do this)
- Change icon to differentiate between this and a normal drop-down
- Accessor should return an observable array, otherwise Kendo framework converts array with single value to (non-array) plain value in bound view model
- value function should set checkbox values even when input array is empty (equivalent to clearing all checkboxes)
- when value is changed (through value function or popup close event), this should trigger the change event on kendo control (to update MVVM model) and it's original element (in case any other event listeners are attached to the input element)
Thanks for the quick reply it worked, but the only issue I have is that the optionLabel is being added to the list of selection options. Is there a way to not include it in the selectlist?
Other than that great work around!
http://jsfiddle.net/MNqaT/
I can't really devote any more time to this, so good luck with future changes.
Kasey
Works perfect. Thanks for taking the time, but like you I'm hoping Telerik comes out with this functionality soon. I would think its a very common scenario.
Thanks again!
This version includes the fix:
http://jsfiddle.net/MNqaT/19/
When is the official release happening for Q1 2013? Do you have a date?
Thanks!
The official release is slated for the second half of March, while a public Beta release (including the new Kendo UI Web widgets) is due in the middle of next week. I encourage you to try it out and share your feedback with us, which will help us polish the multi-select widget for the formal release in March.
Best regards,
Sebastian
the Telerik team
Where will the Beta be announced?
Best regards,
Sebastian
the Telerik team
I'm looking forward to trying it out.
It is based on my own requirments and built on 2012.3.1114 which I know needs a tweak for the latest version of 2012.3.1315.
This has taken quite some time to implement and I hope that the Telerik devs can take some of the ideas forward as I would love to have simlar functionality built into the new multi-select for Kendo. Meaning I can then delete mine :)
http://jsfiddle.net/draunkin/kfQDg/14/
Let me know what you think or any questions you have
Thank you for your input and for the jsFiddle demo. We decided to take a different approach where selected values are shown as tags. Thus the end user is able to see what is selected and modified it with ease. Hence the widget will not use checkboxes as the suggested demo. The MultiSelect widget uses <select multiple> element and it also allows to filter the list.
Georgi Krustev
the Telerik team
I'm really happy with the implementation direction you guys went with.
There is, however, one issue I noticed in the download... when constructing the float wrapper div, the BETA download uses the class floatWrap instead of k-floatwrap
This occurs in both the kendo.all.min.js and the kendo.multiselect.min.js
I am glad to hear that you are happy with the chosen direction.
This is a known issue, which we addressed and the widget will use the correct css class for the official release of Kendo UI. Thank you for the involvement.
Georgi Krustev
the Telerik team
- You can now select a checkbox by clicking on the label as well.
- The control now works on a <select multiple="multiple"> to be consistent with the official kendo ui multiselect.
Also what Kasey said in the first post: this control with checkboxes works faster as you only have to click n+2 times in stead of 2*n times in the official one.
I hope telerik will include this as well in the official release one day, either as a separate control, or as an option on the existing multiselect.
I have a multiselectbox on a form with an optionlabel specified. When the form is posted back, the first option is sent back as selected option for that input, in stead of an empty value.
I'm not sure on how to solve this. Anybody has some more insight. This would be greatly appreciated!
I also tried to upgrade, but ran into different problems. In my particular case, I figured out that the binding code was changed in a way that breaks this drop-down-list-based multi-select control. Specifically, I was trying to set a view model value to an array of simple ids like [1,2,3] bound to my control. But the new code expects an object array like [{Id: 1}, {Id: 2}, {Id: 3}] and throws. However, it works fine if you set the Kendo multi-select control to an array of simple values. So, it's pretty annoying that they broke this for me but allow it to work in their widget.
I ultimately had to abandon the upgrade until such time that a 1-pass multi-selection is added to the framework, either with checkboxes or Ctrl-clicking multiple items in one pass. This is a requirement for my users which the new Kendo widget does not meet, and therefore I can't use it.
Kasey
After some research I found that the value of the select was wrongly set to the first item of the list after the widget was databound, so when catching that event and setting the value again there, the problem was solved.
I added the following code right after the init of the dropdownlist in the MultiSelectBox widget:
me.bind('dataBound', function() {
me.element.val(me.value());
});
Regards,
fretje
That looks like it might solve my issue too. Thanks.
Kasey
I have the following markup and code and only the first item in the markup is initialized, I can switch the order in the html and the other will show.
<
div
id
=
"ViewModelModel"
class
=
'dealer-filter'
>
<
select
id
=
"oemFilterItems"
multiple
=
"multiple"
data-role
=
"multiselectbox"
data-option-label
=
"OEM..."
data-text-field
=
"Name"
data-value-field
=
"ID"
data-bind
=
"source: oemFilterItemSource, value: oemFilterItems"
/>
<
select
id
=
"networkFilterItems"
multiple
=
"multiple"
data-role
=
"multiselectbox"
data-option-label
=
"Network..."
data-text-field
=
"Text"
data-value-field
=
"Value"
data-bind
=
"source: networkFilterItemSource, value: networkFilterItems"
/>
</
div
>
01.
<
script
>
02.
var viewModel = kendo.observable({
03.
networkFilterItems: [],
04.
networkFilterItemSource: new kendo.data.DataSource({
05.
data: [
06.
{ Value: 1, Text: "Facebook" },
07.
{ Value: 2, Text: "Twitter" },
08.
{ Value: 3, Text: "Google" },
09.
{ Value: 4, Text: "Blooger" }
10.
]
11.
}),
12.
oemFilterItems: [],
13.
oemFilterItemSource: new kendo.data.DataSource({
14.
transport: { read: { url: "/Reputation/Reputation/OEMListFiltered", dataType: "json" } },
15.
schema: { data: "Data" }
16.
})
17.
});
18.
19.
$(function () {
20.
21.
kendo.bind($("#ViewModelModel"), viewModel);
22.
});
23.
</
script
>
I really like this implementation, it best represents the functionality I've been looking for with built-in Select All functionality and a count of selected items. Implemented as-is I've experienced a couple of issues and I wondered if you could provide any insight into these. First in the latest version of kendo (all) I get the following error: Uncaught TypeError: Object [object Object] has no method '_valueOnFetch'. This seems to happen in the kendo framework itself where it interprets the nodes as numbers and not as li items. The second error, which doesn't throw any kind of exception is that after selecting all/deselect all the checkboxes no longer show checked. The values are selected correctly, but it appears a toggle count may be off by 1. The one difference between my implementation and your JSFiddle example is that my control is loaded dynamically via AJAX. I was wondering if you had encountered either of these issues or could offer some insight as to why they might be happening. Also if you have any recent enhancements I'd love to see them.
Thanks
Jason
Thank you for your feedback, appreciate knowing it suits your needs.
This jsfiddle and my custom extension runs on Kendo 2012.3.1114. It has not yet been updated to the latest version and I realise when I tested an upgrade that there are breaking changes. I do intend to spend time to do it as I am running behind on running the latest kendo which is something I'd like to change. However it has not been my priority to date. I'll take a quick look at the points you've made. If they prove to take too long to fix I will be parking it until I have time.
Cheers,
Rob.
This jsFiddle uses the new version of kendo. I have not tested this extensively, but everything I've seen so far indicates is works as per the previous version I submitted.
http://jsfiddle.net/draunkin/8caNL/2/
Cheers,
Rob.
This is working perfectly. This extension is going to be a big help for our project. Thanks again for your help and insight!
Regards
Jason
This is probably a bit of a long-shot, but would you happen to have an example of how to apply this extension to a Razor/CSHTML Kendo Multiselect box?
I'm trying duplicate the functionality of the old RadControls Multiselect and your implementation would work perfectly.
Thanks,
Landon
i just found this thread, and i also require a checked list box for our web projects.
i would rather not resort to copying the code from fiddle, unless i have to.
are there any plans to include such a control as an official part of Kendo UI ?
Thanks
Menahem
This plugin / extension of the kendo dropdownlist will not be supported by the Kendo MVC wrappers, basically because it is my own customisation which the wrappers could not know about.
We have a view model which has a string property that stores the comma separated values used by the value() method of the multiselect.
The data soure comes from another property on our view model which as you can tell is a IDictionary
Essentially you will need to build the multiselect via javascript yourself rather than with the wrappers
Here is a modified snippet of our binding which I have not run, so you may find syntax issues.
@{
var fieldName = ViewData.TemplateInfo.GetFullHtmlFieldName("PropertyName");
// clean up property name to use as an element Id
var fieldId = fieldName.Replace(".", "_");
}
<input id="@(fieldId)" name="@(fieldName)" style="width: 280px" />
<script type="text/javascript">
$(document).ready(function() {
$('#@(fieldId)').kendoMultiSelectBox({
dataTextField: "Text",
dataValueField: "Value",
dataSource: @Html.Raw(Json.Encode(Model.FieldLookupData.Select(x => new { Value = x.Key, Text = x.Value }))),
emptySelectionLabel: "Please select...",
value: @Html.Raw(Json.Encode(string.Format("{0}", Model.PropertyName).Split(new []{','})))
});
});
</script>
Its working perfect in your updated js fiddle http://jsfiddle.net/8caNL/10/ if i change jquery version to 1.9.1 but, the same if i tried to copy the code in my local it is not working. Functionality are working fine but when it is chosen it popups like modal window. could you please reply on this.
For Your info : I have attached the image .
I took a look at the Kendo official MultiSelect and it didn't quite serve the purpose that we needed. I've used this checkbox MultiSelectBox widget instead and updated it to work within a grid popup, and using MVVM binding. I had to override / implement the _accessor function for that.
Just now, I've updated the Kendo version to 2013.3.1119 and I'm noticing some really strange behaviour. I thought I'd post a fiddle based on the last one that was posted in this thread, you can find it at http://jsfiddle.net/timweightman/vzX8m/4/.
If anyone has some ideas about what might be causing this weird stuff, please don't hesitate to let me know!
I managed to track the issue down to the new _textAccessor function which is in the v2013.3.1119 DropDownList widget.
I've made the necessary changes to preserve the expected functionality from this MultiSelectBox.
See this JsFiddle: http://jsfiddle.net/timweightman/vzX8m/5/
Thanks so much for the you great efforts on this very much needed widget !
The guys at Telerik should take a page out of your book.
a question: i am trying to post the selected items to the server in a from. but i only get the first item that is selected , rather than all of the selected items.
any idea why that is ? (its all based on the fiddle you posted)
the regular multiselect does post all selections.
Thanks,
Menahem
This is a great additional to the basic multiselect functionality. I've been looking for something just like this for some time now.
However the above fiddle does not seem to be working - any chance you could provide an updated link?
Best Regards
I tested the jsfiddle linked in the first post of this thread under different browsers and it seems to operate a as expected.
Can you try it on a different machine/device to see whether it works? You may also check whether there are any javascript errors when the page is loaded which prevent the proper functioning of the sample.
Regards,
Sebastian
Telerik
Here a plunker with the later version included (script.js)
http://plnkr.co/edit/OVPTCV?p=preview
I found this lately, and I'm trying to use this plugin now, I have a question: how can i clear all selections in javascript?
Thanks a lot
Tiffany
You can send an empty array or value to the .value() function. This would wipe existing values.
e.g. $('#elementId').data("kendoMultiSelectBox").value([]);
Cheers,
Rob.
It works for me.
Thank you!
Tiffany
Thanks so much for putting this extension together, it's almost exactly what I was looking for. I just have 2 questions. How can I set multiple default values? I used the code from your last post and just added values, but only one was recognized and I need to set 2 or 3. Also, I would much prefer the box to show the comma delimited values that are selected as the selected value, than just how many. Is this easily possible? Thank you.
I was using the older version that you had posted before and it started acting weird when I updated Kendo UI libraries. I happened to visit this thread again and was delightfully surprised to see the updated example. This works perfectly even on 2014.2.716.
A very valuable custom extension to the drop down list element; I've fairly easily implemented it as the filter UI for one of my kendo grid columns, however it isn't immediately apparent to me how to listen for a change to the element values; I know how to apply changes to the kendo grid filter, once I have access to those values. In your Plunker example, you've just got the standalone element wrapped in a DIV, then you're binding the selectionChanged event to a jQuery listener on that DIV's ID. I thought selecting multiple values in my dropdown, then simply pressing the Filter button, would auto-magically apply the filters, as the out-of-the-box drop down does when you select one item. Nothing is happening, however, so I'm unsure how to proceed.
To assign multiple default values you just provide an array of the values either in the options object when creating or afterwards using the value() function. If you look at this example I have 2 values assigned. http://plnkr.co/edit/OVPTCV?p=preview
You can increase the number of items to display before turning into a count by assigning a value to preSummaryCount in your options object when you create the control. For example { preSummaryCount: 999 }
Hope that helps.
No problem, as I had to update it to work for me I thought it best to share :)
Cheers,
Rob.
From what I understand (haven't tried it myself), the built in filter menu will expect a single value and the multi select provides an array. I don't think the two will be compatible, if kendo supports its own multiselect as a filter ui then perhaps I am wrong.
You could always try and perform the filtering yourself. You can handle the apply button click on the filter menu and then create filter objects to apply to the datasource.filter function directly. You can even read the existing filters already applied to pre-populate the multiselect next time the menu is shown. Take a look at the datasource api documentation on that one.
Sorry can be of more help, best of luck with it.
Cheers,
Rob.
Here's my issue: The drop down filter still displays the Kendo "logic" box for selecting "is equal to", which I don't want. I'm not sure how to hide this box without affecting all the other filters in column headers since Kendo (I think) doesn't put an ID on them. Also, the Filter and Cancel buttons get blocked by the drop down when the user clicks in the "---Select Value(s)---" block, which means they have to click their selections, then click back above the drop down to close it, thereby making the buttons visible again.
Best case scenario is I would like to hide the "logic" box, for only this column, and move the submit buttons above the drop down box (in effect, where the logic box was, so they are visible while the dropdown list is open.
Any help would be greatly appreciated!
I'm pretty new to telerik and was looking at the custom Multiselect Dropdownlist from Robert which is great and i hope Telerik incorporate this feature in their controls as well. I am curious on how you add filtering to the custom multiselect. Can you please share some insight on that. Thanks.
In my case, my custom multi-select widget represents statuses: I call the function applyStatusFilter when the selectionChanged property of my custom element is fired. Here's what my function looks like:
// Apply the status filters from the multi-select drop down
function
applyStatusFilter(statusValues) {
var
grid = $(
"#grid"
).data(
"kendoGrid"
);
var
dataSource = grid.dataSource;
var
filter = dataSource.filter() || { filters:[], logic:
"and"
};
var
statusFilters = { logic:
"or"
, filters: [] };
var
statusArray = statusValues.split(
','
);
// Convert status selections to array
// Strip out any status related filters so we can rebuild and apply new ones
removeFiltersForField(filter,
"status"
);
// Only build status filter array if selections were made in the dropdown...
if
(statusArray[0].length > 0) {
// Spin through all the statuses chosen
$.each(statusArray,
function
(key, value) {
statusFilters.filters.push({
field:
"status"
,
operator:
"eq"
,
value: value
});
});
}
// Add the status filter to the current filters, if we built any
if
(statusFilters.filters.length > 0) {
filter.filters.push(statusFilters);
}
// Apply new filters to grid
dataSource.filter(filter);
}
function
removeFiltersForField(expression, field) {
if
(expression.filters) {
expression.filters = $.grep(expression.filters,
function
(filter) {
removeFiltersForField(filter, field);
if
(filter.filters) {
return
filter.filters.length;
}
else
{
return
filter.field != field;
}
});
}
}
Hopefully this helps with your situation.
I was mistaken, i thought you were adding the filter feature onto the custom multiselect dropdownlist making it similar to the kendo combobox but with multiselect which is what i want to achieve. Was looking at the script.js file that extends the dropdownlist, do you know if i can do the same with the combobox?
I'm sure your code to manual filter the grid datasource will come in handy as well.
http://www.erichynds.com/examples/jquery-ui-multiselect-widget/demos/#filter
I might use this custom control since it incorporates filtering in the dropdownlist.
// Create the custom status multi-select dropdwon
var
statusDropdown = $(
'#statusMultiSelect'
);
statusDropdown.kendoMultiSelectBox({
dataTextField:
'text'
,
dataValueField:
'value'
,
dataSource: {
transport: {
read: {
dataType:
'json'
,
url:
'/home/ajax/getstatuses'
}
},
},
showSelectAll: false,
emptySelectionLabel:
"Status"
,
selectionChanged:
function
() {
$(
"#statusMultiSelect-list"
).css(
'display'
,
'none'
);
// Close the dropdown right away
applyStatusFilter(this.value());
}
});
And here is the custom extension of Kendo's dropdownlist that I got from one of the previous posts:
//MultiSelect - A user extension of KendoUI DropDownList widget.
(
function
($) {
// shorten references to variables
var
kendo = window.kendo,
ui = kendo.ui,
DropDownList = ui.DropDownList,
keys = kendo.keys,
SELECT =
"select"
,
SELECTIONCHANGED =
"selectionChanged"
,
SELECTED =
"k-state-selected"
,
HIGHLIGHTED =
"k-state-active"
,
CHECKBOX =
"custom-multiselect-check-item"
,
SELECTALLITEM =
"custom-multiselect-selectAll-item"
,
MULTISELECTPOPUP =
"custom-multiselect-popup"
,
EMPTYSELECTION =
"custom-multiselect-summary-empty"
;
var
lineTemplate =
'<input type="checkbox" name="#= {1} #" value="#= {0} #" class="'
+ CHECKBOX +
'" />'
+
'<span data-value="#= {0} #">#= {1} #</span>'
;
var
MultiSelectBox = DropDownList.extend({
init:
function
(element, options) {
options.template = kendo.template(kendo.format(lineTemplate, options.dataValueField, options.dataTextField));
// base call to widget initialization
DropDownList.fn.init.call(
this
, element, options);
},
options: {
name:
"MultiSelectBox"
,
index: -1,
showSelectAll:
null
,
preSummaryCount: 1,
// number of items to show before summarising
emptySelectionLabel:
null
,
// what to show when no items are selected
selectionChanged:
null
,
// provide callback to invoke when selection has changed
},
events: [
SELECTIONCHANGED
],
refresh:
function
() {
// base call
DropDownList.fn.refresh.call(
this
);
this
._updateSummary();
$(
this
.popup.element).addClass(MULTISELECTPOPUP);
},
current:
function
(candidate) {
return
this
._current;
},
open:
function
() {
this
._removeSelectAllItem();
this
._addSelectAllItem();
DropDownList.fn.open.call(
this
);
//hook on to popup event because dropdown close does not
//fire consistently when user clicks on some other elements
//like a dataviz chart graphic
this
.popup.one(
'close'
, $.proxy(
this
._onPopupClosed,
this
));
},
_onPopupClosed:
function
() {
this
._removeSelectAllItem();
this
._current =
null
;
//this._highlightCurrent();
this
._raiseSelectionChanged();
},
_raiseSelectionChanged:
function
() {
var
currentValue =
this
.value();
var
currentValues = $.map((currentValue.length > 0 ? currentValue.split(
","
) : []).sort(),
function
(item) {
return
item.toString(); });
var
oldValues = $.map((
this
._oldValue || []).sort(),
function
(item) {
return
item.toString(); });
// store for next pass
this
._oldValue = $.map(currentValues,
function
(item) {
return
item.toString(); });
var
changedArgs = { newValue: currentValues, oldValue: oldValues };
if
(oldValues) {
var
hasChanged = ($(oldValues).not(currentValues).length == 0 && $(currentValues).not(oldValues).length == 0) !==
true
;
if
(hasChanged) {
//if (this.options.selectionChanged)
// this.options.selectionChanged(changedArgs);
this
.trigger(SELECTIONCHANGED, changedArgs);
}
}
else
if
(currentValue.length > 0) {
//if (this.options.selectionChanged)
// this.options.selectionChanged(changedArgs);
this
.trigger(SELECTIONCHANGED, changedArgs);
}
},
_addSelectAllItem:
function
() {
if
(!
this
.options.showSelectAll)
return
;
var
firstListItem =
this
.ul.children(
'li:first'
);
if
(firstListItem.length > 0) {
this
.selectAllListItem = $(
'<li tabindex="-1" role="option" unselectable="on" class="k-item '
+ SELECTALLITEM +
'"></li>'
).insertBefore(firstListItem);
// fake a data object to use for the template binding below
var
selectAllData = {};
selectAllData[
this
.options.dataValueField] =
'*'
;
selectAllData[
this
.options.dataTextField] =
'All'
;
this
.selectAllListItem.html(
this
.options.template(selectAllData));
this
._updateSelectAllItem();
this
._makeUnselectable();
// required for IE8
}
},
_removeSelectAllItem:
function
() {
if
(
this
.selectAllListItem) {
this
.selectAllListItem.remove();
}
this
.selectAllListItem =
null
;
},
_focus:
function
(li) {
if
(
this
.popup.visible() && li &&
this
.trigger(SELECT, { item: li })) {
this
.close();
return
;
}
this
.select(li);
},
//_highlightCurrent: function () {
// $('li', this.ul).removeClass(HIGHLIGHTED);
// $(this._current).addClass(HIGHLIGHTED);
//},
_keydown:
function
(e) {
// currently ignore Home and End keys
// can be added later
if
(e.keyCode == kendo.keys.HOME ||
e.keyCode == kendo.keys.END) {
e.preventDefault();
return
;
}
DropDownList.fn._keydown.call(
this
, e);
},
_keypress:
function
(e) {
// disable existing function
},
_move:
function
(e) {
var
that =
this
,
key = e.keyCode,
ul = that.ul[0],
down = key === keys.DOWN,
pressed;
if
(key === keys.UP || down) {
if
(down) {
if
(!that.popup.visible()) {
that.toggle(down);
}
if
(!that._current) {
that._current = ul.firstChild;
}
else
{
that._current = ($(that._current)[0].nextSibling || that._current);
}
}
else
{
//up
// only if anything is highlighted
if
(that._current) {
that._current = ($(that._current)[0].previousSibling || ul.firstChild);
}
}
if
(that._current) {
that._scroll(that._current);
}
that._highlightCurrent();
e.preventDefault();
pressed =
true
;
}
else
{
pressed = DropDownList.fn._move.call(
this
, e);
}
return
pressed;
},
selectAll:
function
() {
var
unselectedItems =
this
._getUnselectedListItems();
this
._selectItems(unselectedItems);
// todo: raise custom event
},
unselectAll:
function
() {
var
selectedItems =
this
._getSelectedListItems();
this
._selectItems(selectedItems);
// will invert the selection
// todo: raise custom event
},
_selectItems:
function
(listItems) {
var
that =
this
;
$.each(listItems,
function
(i, item) {
var
idx = ui.List.inArray(item, that.ul[0]);
that.select(idx);
// select OR unselect
});
},
_selectItem:
function
() {
// method override to prevent default selection of first item, done by normal dropdown
var
that =
this
,
options = that.options,
useOptionIndex,
value;
useOptionIndex = that._isSelect && !that._initial && !options.value && options.index && !that._bound;
if
(!useOptionIndex) {
value = that._selectedValue || options.value || that._accessor();
}
if
(value) {
that.value(value);
}
else
if
(that._bound === undefined) {
that.select(options.index);
}
},
_select:
function
(li) {
var
that =
this
,
value,
text,
idx;
li = that._get(li);
if
(li && li[0]) {
idx = ui.List.inArray(li[0], that.ul[0]);
if
(idx > -1) {
if
(li.hasClass(SELECTED)) {
li.removeClass(SELECTED);
that._uncheckItem(li);
if
(
this
.selectAllListItem && li[0] ===
this
.selectAllListItem[0]) {
this
.unselectAll();
}
}
else
{
li.addClass(SELECTED);
that._checkItem(li);
if
(
this
.selectAllListItem && li[0] ===
this
.selectAllListItem[0]) {
this
.selectAll();
}
}
if
(
this
._open) {
that._current(li);
that._highlightCurrent();
}
var
selecteditems =
this
._getSelectedListItems();
value = [];
text = [];
$.each(selecteditems,
function
(indx, item) {
var
obj = $(item).children(
"span"
).first();
value.push(obj.attr(
"data-value"
));
text.push(obj.text());
});
that._updateSummary(text);
that._updateSelectAllItem();
that._accessor(value, idx);
// todo: raise change event (add support for selectedIndex) if required
}
}
},
_getAllValueListItems:
function
() {
if
(
this
.selectAllListItem) {
return
this
.ul.children(
"li"
).not(
this
.selectAllListItem[0]);
}
else
{
return
this
.ul.children(
"li"
);
}
},
_getSelectedListItems:
function
() {
return
this
._getAllValueListItems().filter(
"."
+ SELECTED);
},
_getUnselectedListItems:
function
() {
return
this
._getAllValueListItems().filter(
":not(."
+ SELECTED +
")"
);
},
_getSelectedItemsText:
function
() {
var
text = [];
var
selecteditems =
this
._getSelectedListItems();
$.each(selecteditems,
function
(indx, item) {
var
obj = $(item).children(
"span"
).first();
text.push(obj.text());
});
return
text;
},
_updateSelectAllItem:
function
() {
if
(!
this
.selectAllListItem)
return
;
// are all items selected?
if
(
this
._getAllValueListItems().length ==
this
._getSelectedListItems().length) {
this
._checkItem(
this
.selectAllListItem);
this
.selectAllListItem.addClass(SELECTED);
}
else
{
this
._uncheckItem(
this
.selectAllListItem);
this
.selectAllListItem.removeClass(SELECTED);
}
},
_updateSummary:
function
(itemsText) {
if
(!itemsText) {
itemsText =
this
._getSelectedItemsText();
}
if
(itemsText.length == 0) {
this
._inputWrapper.addClass(EMPTYSELECTION);
this
.text(
this
.options.emptySelectionLabel);
return
;
}
else
{
this
._inputWrapper.removeClass(EMPTYSELECTION);
}
if
(itemsText.length <=
this
.options.preSummaryCount) {
this
._textAccessor(itemsText.join(
", "
));
}
else
{
this
._textAccessor(itemsText.length +
' selected'
);
}
},
_checkItem:
function
(itemContainer) {
if
(!itemContainer)
return
;
itemContainer.children(
"input"
).prop(
"checked"
,
true
);
},
_uncheckItem:
function
(itemContainer) {
if
(!itemContainer)
return
;
itemContainer.children(
"input"
).removeAttr(
"checked"
);
},
_isItemChecked:
function
(itemContainer) {
return
itemContainer.children(
"input:checked"
).length > 0;
},
value:
function
(value) {
var
that =
this
,
idx,
valuesList = [];
if
(value !== undefined) {
if
(!$.isArray(value)) {
valuesList.push(value);
this
._oldValue = valuesList;
// to allow for selectionChanged event
}
else
{
valuesList = value;
this
._oldValue = value;
// to allow for selectionChanged event
}
// clear all selections first
$(that.ul[0]).children(
"li"
).removeClass(SELECTED);
$(
"input"
, that.ul[0]).removeAttr(
"checked"
);
$.each(valuesList,
function
(indx, item) {
var
hasValue;
if
(item !==
null
) {
item = item.toString();
}
that._selectedValue = item;
hasValue = value || (that.options.optionLabel && !that.element[0].disabled && value ===
""
);
if
(hasValue && that._fetchItems(value)) {
return
;
}
idx = that._index(item);
if
(idx > -1) {
that.select(idx);
}
});
that._updateSummary();
}
else
{
var
selecteditems =
this
._getSelectedListItems();
return
$.map(selecteditems,
function
(item) {
var
obj = $(item).children(
"span"
).first();
return
obj.attr(
"data-value"
);
}).join();
}
},
});
ui.plugin(MultiSelectBox);
})(jQuery);
Any time you need a multi-select with an amount of options that cause the tags to wrap, the control is quite ugly and using checkboxes makes much more sense.
Currently, we do not have any specific plans for providing combobox/dropdownlist widgets with multi-select support including the checkboxes in this case. For now, our solution for widget providing multiple selection is Kendo UI MultiSelect.
I encourage every interested in this thread to open/comment in our Feedback portal or send us a pull request (Kendo UI Core is an open-source library).
I will close this thread. If any one would like to share his/her implementation, I would suggest Kendo UI Labs.
Regards,
Georgi Krustev
Telerik