How to select menu item programmatically in Kendo menu - kendo-ui

I have a menu with values and I want to add a Key shortcut that will select that item.
I can demonstrate in this fiddle exactly what I am looking for
function onSelect(e) {
var item = $(e.item),
menuElement = item.closest(".k-menu"),
dataItem = this.options.dataSource,
index = item.parentsUntil(menuElement, ".k-item").map(function () {
return $(this).index();
}).get().reverse();
index.push(item.index());
for (var i = -1, len = index.length; ++i < len;) {
dataItem = dataItem[index[i]];
dataItem = i < len-1 ? dataItem.items : dataItem;
}
alert(dataItem.value);
}
$(document).ready(function() {
$("#menu").kendoMenu({
dataSource: [
{
text: "Item 1 (A)",
value: "A",
items: [
{
text: "Sub Item 1 (L)",
value: "L",
items: [
{
text: "Sub Sub Item 1 (D)",
value: "D"
},
{
text: "Sub Sub Item 2 (E)",
value: "E"
}
]
},
{
text: "Sub Item 2 (O)",
value: "O"
}
]
},
{
text: "Item 2 (F)",
value: "F"
},
{
text: "Item 3 (G)",
value: "G"
}
],
select: onSelect
});
$(document.body).keydown(function (e) {
var menu = $("#menu").kendoMenu().data("kendoMenu");
if (e.altKey && e.keyCode == 76) {
alert("select item with value L");
// Pseudocode:
// var item = find item with value L
// menu.select(item); (or trigger)
}
});
});
I couldn't find anywhere any resources that could accomplish that. Also I can't assign ids to the rendered "li" via the datasource which makes it hard to select a node of the menu.
Any ideas?

Not sure if Kendo API supports triggering select item but I was able to achieve click the menu items with keyboard shortcuts using JQuery.
Check this JSFiddle
function clickMenuSpan(keyCode){
var shortcut = String.fromCharCode(keyCode);
$('#menu span.k-link').each(function(){
var txt = $(this).text();
if(txt.substr(-3) === '(' + shortcut + ')')
{
$(this).click();
}
})
}
You can use the above function in your keydown event. And add some filters to call this only for your array of shortcuts.
$(document.body).keydown(function (e) {
var menu = $("#menu").kendoMenu().data("kendoMenu");
if (e.altKey) {
clickMenuSpan(e.keyCode);
}
});

Related

Filter Kendo Dropdownlist values within a kendo grid row based on value from another row

I have Kendo Grid, inside which I have dropdown input [editable]. Now I want to filter the values in dropdown based on value present in row next to it. For ex:
_________________________________________
Column 1 | Column 2 (this is a dropdown)
_________________________________________
A | Show only values relevant to A
__________________________________________
B | Show values relevant to B
_____________________________________________
C | Show values relevant to C
_________________________________________
you can do the following
On editing the row get the name from the first column
filter the second column based on the first column value
In the given sample below, I edited an existing sample provided by the Kendo UI for cascading dropdowns, so I wrote extra codes to get the Id of the first column, so in your case you can exclude the additional steps
The HTML needed
<div id="grid"></div>
The scripts needed
<script>
// array of all brands
var brands = [
{ brandId: 1, name: "Ford" },
{ brandId: 2, name: "BMW" }
];
// array of all models
var models = [
{ modelId: 1, name: "Explorer", brandId: 1},
{ modelId: 2, name: "Focus", brandId: 1},
{ modelId: 3, name: "X3", brandId: 2},
{ modelId: 4, name: "X5", brandId: 2}
];
$("#grid").kendoGrid({
dataSource: {
data: [
{ id: 1, brandId: 1, modelId: 2 }, // initial data item (Ford, Focus)
{ id: 2, brandId: 2, modelId: 3 } // initial data item (BMW, X3)
],
schema: {
model: {
id: "id",
fields: {
id: { editable: false }, // the id field is not editable
brandId: {editable: false}
}
}
}
},
editable: "inline", // use inline mode so both dropdownlists are visible (required for cascading)
columns: [
{ field: "id" },
{
// the brandId column
title: "Brand",
field: "brandId", // bound to the brandId field
template: "#= brandName(brandId) #", // the template shows the name corresponding to the brandId field
},
{
//The modelId column
title: "Model",
field: "modelId", // bound to the modelId field
template: "#= modelName(modelId) #", //the template shows the name corresponding to the modelId field
editor: function(container) { // use a dropdownlist as an editor
var input = $('<input id="modelId" name="modelId">');
input.appendTo(container);
input.kendoDropDownList({
dataTextField: "name",
dataValueField: "modelId",
//cascadeFrom: "brandId", // cascade from the brands dropdownlist
dataSource: filterModels() // bind it to the models array
}).appendTo(container);
}
},
{ command: "edit" }
]
});
function brandName(brandId) {
for (var i = 0; i < brands.length; i++) {
if (brands[i].brandId == brandId) {
return brands[i].name;
}
}
}
function brandId(brandName) {
for (var i = 0; i < brands.length; i++) {
if (brands[i].name == brandName) {
return brands[i].brandId;
}
}
}
function modelName(modelId) {
for (var i = 0; i < models.length; i++) {
if (models[i].modelId == modelId) {
return models[i].name;
}
}
}
// this function will be used by the drop down to filter the data based on the previous column value
function filterModels()
{
// bring the brand name from previous column
var brandName = $('#modelId').closest('td').prev('td').text();
// additional work in this sample to get the Id
var id = brandId(brandName);
// filter the data of the drop down list
var details= $.grep(models, function(n,i){
return n.brandId==id;
});
return details;
}
</script>
here a working demo
hope it will help you

pebble.js Selecting menuItem dont work

im trying to make a 3 - Step - menu. In the last step the user need the item information from first ui.menu(). I only get the last selected menu ItemIndex from menu3 so first select menu3=menu1 first select, and so on. Here my code:
var UI = require('ui');
var reciep = "";
var body = "";
// Make a list of menu items
var menu1 = [
{
title: "",
number: "465465465"
},
{
title: "",
number: "33333"
},
{
title: "",
number: "131321321"
}
];
// Create the Menu, supplying the list of menu1
var menuOne = new UI.Menu({
sections: [
{
title: 'Empfänger',
items: menu1
}
]
});
// Show the Menu
menuOne.show();
var menu2 = [
{
title: "MSG",
subtitle: ""
},
{
title: "",
subtitle: ""
},
{
title: "",
subtitle: ""
}
];
// Create the Menu, supplying the list of menu1
var menuTwo = new UI.Menu({
sections: [
{
title: 'Antwortart',
items: menu2
}
]
});
var menu3 = [
{
title: "Hallo",
subtitle: "Ich!"
},
{
title: "Keine Zeit",
subtitle: "bei dir!"
},
{
title: "Ja",
subtitle: "Ja"
},
{
title: "Nein",
subtitle: "Nein"
}
];
// Create the Menu, supplying the list of menu1
var menuTree = new UI.Menu({
sections: [
{
title: 'Antwortart',
items: menu3
}
]
});
// Add a click listener for select button click
menuOne.on('select', function (event) {
menuTree.show();
});
// Add a click listener for select button click
//menuTwo.on('select', function (event) {
// menuTree.show();
//});
// Add a click listener for select button click
menuTree.on('select', function (event) {
body = menu3[event.itemIndex].subtitle;
reciep = menu1[event.sectionIndex].number;
//console.log('Selected item #' + menu3[event.itemIndex].subtitle + ' of section #' + event.sectionIndex);
console.log('The item is titled "' + menu3[event.itemIndex].subtitle + '"');
// Show a card with clicked item details
var detailCard = new UI.Card({
title: menu3[event.itemIndex].title,
body: menu3[event.itemIndex].subtitle
});
// Show the new Card
detailCard.show();
You should save the index of the element that was selected in a variable that will be used later. For example:
var firstMenuSelection, secondMenuSelection;
menuOne.on('select', function(event) {
firstMenuSelection = event.itemIndex;
menuTree.show();
});
menuTree.on('select', function(event) {
console.log("Selection path is " + firstMenuSelection + " - " + event.itemIndex);
});

KendoUI Multiselect Remove Multiple

I am using Kendo UI Multiselect:
http://demos.kendoui.com/web/multiselect/events.html
I have this Data:
var data =
[
{ text: "Shirt-Black", value: "1" },
{ text: "Shirt-Brown", value: "2" },
{ text: "Shirt-Blue", value: "3" },
{ text: "Cap-Green", value: "4" },
{ text: "Cap-Red", value: "5" },
{ text: "Cap-White", value: "6" },
{ text: "Jacket-Denim", value: "7" }
];
Now I want that if I select "Shirt-Brown" then rest entries for shirt i.e. "Shirt-Black" and "Shirt-Blue" should not appear in the list which means that the user should not be able to choose the Shirt of two colors.
Similarly, If a "Cap" of any color has been chosen then user should not be able to choose the "Cap" of any other color.
Is there any way to achieve this?
This is not build-in functionality. You can't even use dataSource filter() method because it will remove selected items from list as well.
However, this code will do what you're asking:
$("#select").kendoMultiSelect({
...
change: function(e) {
var dataItems = e.sender.dataItems();
var categories = [];
for(var i = 0; i < dataItems.length; i++){
var category = dataItems[i].text.substring(0, dataItems[i].text.indexOf('-'));
categories.push(category);
}
e.sender.ul.find('li').each(function(index, value){
var $li = $(value);
var hidden = false;
for(var i = 0; i < categories.length; i++){
var category = categories[i];
if ($li.text().match("^" + category)){
$li.css('display', 'none');
hidden = true;
}
}
if(!hidden){
$li.css('display', 'list-item');
}
});
}
});
Working KendoUi Dojo: http://dojo.telerik.com/AGisi

Kendo Treeview Expand Node

I have this treeview wich can have a variable number of children (some nodes can have up to 3 generations of children, some may have only one etc)
What I'm trying to do is expand a certain node when the treeview is loaded. And I have 2 problems:
1) I can't find an event/callback so that I know when the treeview is ready
2) The expand function doesn't always work ( I'll explain )
This is my treeview:
function InitializeTreeview() {
var Children_Merchants = {
transport: {
read: {
url: function (options) {
return kendo.format(websiteRootUrl + '/Merchants/Merchants/?hasParents={0}', hasParent);
}
}
},
schema: {
model: {
model: {
id: "ID",
hasChildren: true,
children: Children_Merchants
}
}
}
};
var Brandowners = new kendo.data.HierarchicalDataSource({
transport: {
read: {
url: kendo.format(websiteRootUrl + '/Merchants/GetBrandowners?databaseID={0}', selectedDatabaseID)
}
},
//change: ExpandNode, - if I call expand node like this, it works.
schema: {
model: {
id: "ID",
hasChildren: true,
children: Children_Merchants
}
}
});
$('#treeview').kendoTreeView({
dataSource: Brandowners,
animation: {
collapse: {
duration: 200,
effects: "fadeOut"
},
expand: {
duration: 200,
effects: "fadeIn"
}
},
dataTextField: "Name",
complete: function () { alert('ok'); },
//dataBound : ExpandNode,
select: OnSelect,
expand: CheckIfHasParent
}).data('kendoTreeView');
}
function ExpandNode() {
var treeview;
treeview = $("#treeview").data("kendoTreeView");
var nodeToExpand = treeview.findByText('Adam'); //dummy txt, will have from parameter
treeview.expand(nodeToExpand);
}
The databind works ok, my controllers get called, everything's fine.
So what I tried is hook up the ExpandNode function to a click of a button. The function gets called but nothing happens. BUT if I hook it up to the change event of the parents datasource, it works. Another interesting thing is that the select works so if I replace treeview.expand(...) with treeview.select(...), it works on the click.
So my questions are:
1) What event should I use for loadEnd ( or smth like that ) - so I won't have to bind the function to button click (it's still ok but I preffer on load ended) - P.S. I tried all the ones I found on the kendo forums,like: change, requestEnd, success, dataBound and they don't work. I tried sending the JSON with the property "expanded" set to TRUE, for the node in question, but that only modifies the arrow to show like it's opened, but it doesn't call the controller and load the children.
2) Do you know why ExpandNode works only when binded to the change event? - the most important question to me.
3) If you have suggestions, or have I done something wrong in the initialiation of the treeview, please tell me.
I've copied your code with some free interpretations and the answer your questions is:
What event should I use for loadEnd => dataBound
Do you know why ExpandNode works only when binded to the change event? => No, it works without binding it to change event. If it does not then there is something else in your code.
Suggestions => There is some information missing about your code that might make the difference with what I've implemented.
What is CheckIfHasParent? => I have implemented it as a function that actually does nothing.
What is hasParent? => I've ignored it.
The code as I write it:
$(document).ready(function () {
function InitializeTreeview() {
var Children_Merchants = {
transport: {
read: function (op) {
var id = op.data.ID;
var data = [];
for (var i = 0; i < 10; i++) {
var aux = id * 100 + i;
data.push({ Name: "Name-" + aux, ID: aux});
}
op.success(data);
}
},
schema : {
model: {
model: {
id : "ID",
hasChildren: true,
children : Children_Merchants
}
}
}
};
var Brandowners = new kendo.data.HierarchicalDataSource({
transport: {
read: function (op) {
op.success([
{"Name": "Adam", "ID": 1},
{"Name": "Benjamin", "ID": 2},
{"Name": "Caleb", "ID": 3},
{"Name": "Daniel", "ID": 4},
{"Name": "Ephraim", "ID": 5},
{"Name": "Frank", "ID": 6},
{"Name": "Gideon", "ID": 7}
])
}
},
//change: ExpandNode, - if I call expand node like this, it works.
schema : {
model: {
id : "ID",
hasChildren: true,
children : Children_Merchants
}
}
});
$('#treeview').kendoTreeView({
dataSource : Brandowners,
animation : {
collapse: {
duration: 200,
effects : "fadeOut"
},
expand : {
duration: 200,
effects : "fadeIn"
}
},
dataTextField: "Name",
dataBound : ExpandNode,
expand : CheckIfHasParent
}).data('kendoTreeView');
}
function ExpandNode() {
var treeview;
treeview = $("#treeview").data("kendoTreeView");
var nodeToExpand = treeview.findByText('Adam'); //dummy txt, will have from parameter
treeview.expand(nodeToExpand);
}
function CheckIfHasParent(e) {
}
InitializeTreeview();
});
and you can play with it here : http://jsfiddle.net/OnaBai/dSt2h/
$("#treeview").kendoTreeView({
animation: {
expand: true
},
dataSource: dataSource,
dataBound: function (e) {
var tv = $("#treeview").data("kendoTreeView");
if (tv != null) {
tv.expand(".k-item");
}
},
dataTextField: "test",
dataValueField: "id"
});
For anyone who may be interested:
function ExpandNode() {
var treeview;
var node1;
treeview = $("#treeview").data("kendoTreeView");
var node2;
var myURL = kendo.format(websiteRootUrl + '/Merchants/GetPathForSelectedNode?databaseID={0}&merchantID={1}&brandownerID={2}', selectedDatabaseID,MerID,BowID);
node1 = treeview.dataSource.get(BowID);
node = treeview.findByUid(node1.uid);
var uid = node1.uid;
node.find('span:first-child').trigger('click'); //expand 1st level
$.ajax( {
url: myURL,
dataType: "json",
contentType: 'application/json; charset=utf-8',
success: function(result)
{
var length = result.length;
var lastVal = 1;
for (var i = 1; i < length-1; i++) {
$("#treeview li[data-uid=\'" + uid + "\'] ul.k-group").waitUntilExists (function
() {
i = lastVal; // have to reinitialize i because waitUntilExist's callback will find the i incermented, over the needed value
lastVal++;
node2 = node1.children.get(result[i]);
node = treeview.findByUid(node2.uid);
uid = node2.uid;
node1 = node2;
if(lastVal <= length-1)
node.find('span:first-child').trigger('click'); // keep expanding
else
{
treeview.select(node); // just select last node
currentSelectedNode = node;
}
});
}
if(length == 2) //select 1st child
{
$("#treeview li[data-uid=\'" + uid + "\'] ul.k-group").waitUntilExists (function
() {
node2 = node1.children.get(result[i]);
node = treeview.findByUid(node2.uid);
uid = node2.uid;
node1 = node2;
treeview.select(node); // just select last node
currentSelectedNode = node;
});
}
}
});
}
This is my method. The for loop starts at 1 because the 1st element in my array is the 1st node ID - wich I've already expanded. the .waitUntilExists is Ryan Lester's method (I put a link in the comments above). Many thanks to my colleague, to you OnaBai and, of courese, to Ryan Lester. I hope this helps someone. Cheers
ypu can easily find the treeview is ready for expand by following code which are expanding all the treeview nodes you can also find it by checking perticular id or text
hopw, following example will help you
Ex:
$("#treeview").kendoTreeView({
animation: {
expand: true
},
dataSource: dataSource,
dataBound: function (e) {
var tv = $("#treeview").data("kendoTreeView");
if (tv != null) {
tv.expand(".k-item");
}
},
dataTextField: "test",
dataValueField: "id"
});

How can I optimize datasource for Kendo UI Combobox with 5000 items?

In my test -> http://jsfiddle.net/olragon/642c4/12/, KendoUI Combobox cannot run with 5000 items, how can I make it work without calling severside data source or this is limit of KendoUI?
HTML
<h3>T-shirt Fabric</h3>
<input id="fabric" placeholder="Select fabric..." />
JS
/**
* Returns a random integer between min and max
* Using Math.round() will give you a non-uniform distribution!
*/
function getRandomInt (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
$(document).ready(function() {
var superData = []
, data = [
{ text: "Cotton", value: "1" },
{ text: "Polyester", value: "2" },
{ text: "Cotton/Polyester", value: "3" },
{ text: "Rib Knit", value: "4" }
];
for(var _i=0; _i<5000; _i++) {
var randomEntry = data[getRandomInt(0,data.length-1)];
randomEntry.text += '-' + _i;
randomEntry.value += _i;
superData.push(randomEntry);
}
// create ComboBox from input HTML element
$("#fabric").kendoComboBox({
dataTextField: "text",
dataValueField: "value",
dataSource: superData,
filter: "contains",
suggest: true,
index: 3
});
});
Update
Fiddle link was updated.
Virtual scrolling and paging for Combobox was not yet supported by KendoUI
The problem is not in Kendo UI ComboBox but in your loop. Did you check what it does (not what you want it to do)? I would say that there is an error since data[getRandomInt(0,data.length-1)] does not return a new element but a reference so you are appending "_i" to the same 5 elements many times building up a very long string.
Try this instead:
for (var _i = 0; _i < 5000; _i++) {
var randomEntry = data[getRandomInt(0, data.length - 1)];
var newEntry = {
text: randomEntry.text + '-' + _i,
value : randomEntry.value += _i
};
superData.push(newEntry);
}
Check the modified version of the Fiddle here: http://jsfiddle.net/OnaBai/642c4/14/

Resources