I am using Kendo UI MVC and i have a kendoTabStrip on acshtml page. By default I am selecting the first tab on page load. All other tabs are loaded dynamically using AJAX.
Issue: I am trying to find the selected tab so i can find its children?
one way to find active tab is by calling select() method without parameter, or anotherway is by checking classname 'k-state-active' however both methods doesnt work
<section class="tpt-tabstrip">
#(Html.Kendo().TabStrip()
.Name("MyTabStrip")
.Animation(false)
.Items(items =>
{
foreach (var revision in Model.MyCollection)
{
items.Add()
.Text(revision.Name)
.LoadContentFrom("MyActionMethod", "MyController", Model.ID);
}
})
)
</section>
<script src="~/Scripts/MyScript.js"></script>
Note that above in cshtml that the script tag is at the end of the page.
Below is the script code
$(function(){
var tabStrip = $("#MyTabStrip").getKendoTabStrip();
if (tabStrip != null && tabStrip.tabGroup.length > 0) {
tabStrip.select(0); // this line is getting executed for sure
}
// the line below returns -1 here why?????
var index = tabStrip.select().index();
// another way to find active tab is by checkikng class name 'k-state-active' however it didnt work either.
// jQuery couldnt find any element with class 'k-state-active'
$('.k-state-active')
})
UPDATE1
The activate event of tabstrip would not work for me because it get fired each time i select tab. I need an event which gets fired only once. Ultimately i want to find NumericTextBox controls on selected tab and attach 'change' event handlers to those controls. like below
$(function(){
var tabStrip = $('#MyTabStrip').data("kendoTabStrip");
tabStrip.bind('activate', function (e) {
$('[data-role="numerictextbox"]').each(function(){
$(this).getKendoNumericTextBox().bind("change",function(e){
alert('changed');
})
})
});
})
here the change event handler will get attach to NumericTextBox everytime i select the tab
$('.k-state-active') works fine it will return the two elements from DOM. You are trying to select element in $(document).ready that's the reason you are not getting element as tab control is not rendered yet.
Try to write your code onActivate event of kendo tab strip control.
OnActivate event is triggered after a tab is being made visible and its animation complete. Before Q2 2014 this event was invoked after tab show, but before the end of the animation. This event is triggered only for tabs with associated content.
See more at http://docs.telerik.com/kendo-ui/api/javascript/ui/tabstrip#events-activate
1st Tab name
<li class="k-item k-state-default k-first k-tab-on-top k-state-active" role="tab" aria-controls="RoleTabs-1" style="" aria-selected="true">
<span class="k-loading k-complete k-progress"></span>
<a class="k-link">Tab Name</a>
2nd Tab Content
<div class="k-content k-state-active" id="RoleTabs-1" style="display: block; height: auto; overflow: auto; opacity: 1;" role="tabpanel" aria-expanded="true">
Related
I am trying to integrate Yammer share button https://developer.yammer.com/docs/share-button, I successfully implemented as instructed, but the only catch is first time it requires two click to fire up, later on single click seems to do the job. Here is the code below.
function clickSaveShare(){
var options = {
customButton : true, //false by default. Pass true if you are providing your own button to trigger the share popup
classSelector: 'homeBtn',//if customButton is true, you must pass the css class name of your button (so we can bind the click event for you)
defaultMessage: 'My custom Message', //optionally pass a message to prepopulate your post
pageUrl: 'www.microsoft.com' //current browser url is used by default. You can pass your own url if you want to generate the OG object from a different URL.
};
yam.platform.yammerShare(options);
}
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<span href="#" class="homeBtn" onclick="clickSaveShare(339,'Reverse KT')"> Click here to share</a>
<script>
</script>
<script type="text/javascript" src="https://s0.assets-yammer.com/assets/platform_social_buttons.min.js"></script>
<script type="text/javascript">yam.platform.yammerShare();</script>
</body>
</html>
Calling yam.platform.yammerShare() doesn't actually call the share to Yammer function despite its name. What it does is apply a click event to the specified DOM element so that when that element is clicked the Yammer popup will appear.
The reason you have to click the button twice is that the first time clickSaveShare is called, it calls yam.platform.yammerShare() which sets up a click event on the specified DOM element. The next time the button is clicked your click event has been replaced with the Yammer one so it works as expected.
One simple way to fix it given that you are including jQuery would be to use jQuery's document.ready event:
$(document).ready(function() {
var options = {
customButton : true,
classSelector: 'homeBtn',
defaultMessage: 'My custom Message',
pageUrl: 'www.microsoft.com'
};
yam.platform.yammerShare(options);
});
Here is a CodePen example of the above.
I would like to have a button and when the user clicks on it a filter form pops down just below the button. I would like to utilize Kendo UI controls to achieve the effect.
In fact, what I need is almost exactly the 'filtering' that can be found on this example:
http://demos.telerik.com/kendo-ui/grid/filter-menu-customization
However, I'm not dealing with a grid of data so I can't use that example above.
There are different possible implementations. Here I will describe one based on kendoWindow since then you have a lot of possible customizations for that filtering form.
This is the HTML that includes the button:
<div>
This is the container that includes a
<button id="filter" class="k-button">Filter</button>
that is used to display a form
</div>
And then you define the HTML form. Example:
<div id="form">
<div>Filtering value:<input data-role="autocomplete"/></div>
<button class="k-button">Filter</button>
</div>
Doing the form initialization is:
var form = $("#form").kendoWindow({
title : "Filter",
visible : false,
modal : false,
draggable: false
}).data("kendoWindow");
Where initially we set the form as not visible.
You can define it as modal, draggable or even define the opening and closing effect.
Finally, for opening and placing the form just bellow the button you should:
$("#filter").on("click", function(e) {
// Find clicked button
var button = $(e.currentTarget);
// and get its position
var pos = button.offset();
// shift down the form to open by the height of the button + 5px (margin)
pos.top += button.outerHeight() + 5;
// Apply positioning to the form
form.wrapper.css(pos);
// display form
form.open();
});
You can see this here : http://jsfiddle.net/OnaBai/mpq6k/
I am trying to use Kendo's Mobile widgets inside of my PhoneGap Durandal project.
See sample source project here: https://github.com/rodneyjoyce/DurandalKendoMobile/tree/master/App
I don't understand where to put the Kendo initilisation code (the widgets do not render without this):
window.kendoMobileApplication = new kendo.mobile.Application($(document.body), {
skin: "flat"
});
I have tried to put it into the Index.html, shell.html and into a particular Durandal page view (x.html), shell.js, main,js and x.js but none of these work.
My Index page has these links in it:
<script src="css/telerik/js/kendo.all.min.js"></script>
<link href="css/telerik/styles/kendo.mobile.flat.min.css" rel="stylesheet" />
My Durandal View has the following HTML with Kendo Mobile widgets:
<section>
1
<div id="kendoindex">
<div data-kendo-role="view" data-kendo-title="View">
<header data-kendo-role="header">
<div data-kendo-role="navbar">
<span data-kendo-role="view-title">Title</span>
</div>
</header>
<ul data-kendo-role="listview">
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
</div>
2
</section>
and my ViewModel for this View:
define(function (require)
{
function viewModel()
{
var self = this;
self.activate = activate;
function activate()
{
//window.kendoMobileApplication = new kendo.mobile.Application($("#kendoindex"), {
// skin: "flat"
//});
}
}
var vm = new viewModel();
return vm;
});
If I don't call kendoMobileApplication then the Kendo Mobile widgets are not rendered (it just shows "1 Title 2" with no CSS (ie. Kendo is not transforming them).
Everything seems to be keyed on where to call this: kendoMobileApplication in Durandal.
I followed the Durandal guidelines to give the Kendo bindings their own namespace: http://durandaljs.com/documentation/KendoUI/
UPDATE 1
I have created a simple Durandal 1.2 project which highlights the problem with Kendo Mobile and Durandal (and PhoneGap, but irrelevant here)), namely:
The only way to get the Mobile controls to render properly is to call kendo.mobile.Application. However this cannot find the right HTML element if it is put into a different file and loaded with Durandal.
I cannot find the right place to put this init code as it throws this error: “Uncaught Error: Your kendo mobile application element does not contain any direct child elements with data-role="view" attribute set. Make sure that you instantiate the mobile application using the correct container.”
kendoIndex.html is NOT Durandal but shows how it should be rendered if the kendo.mobile.Application is called correctly (Run this first to see what we are trying to achieve)
Shell : Has the Kendo Layout which does not get rendered.
Home View: Has the simple Kendo Mobile view – this does not get rendered.
About: A simple HTML page without Kendo
Source is on Guthub – if anyone can get Kendo Mobile working with Durandal I would appreciate it (or at least confirm if it is impossible (Telerik are no help at all on this)).
https://github.com/rodneyjoyce/DurandalKendoMobile/tree/master/App
Here's a working demo, which shows the correct start screen, but doesn't show the about view on navigation click. There's probably some extra work required to either remove kendo's or Durandal's router functionality.
http://rainerat.spirit.de/DurandalKendoMobile/App/#/
There were a couple of things required to make it work.
https://github.com/RainerAtSpirit/DurandalKendoMobile/commits/master
Kendo requires that the host element and all 'view' and 'layout' elements are in the DOM and that 'view' and 'layout' are child of the container element. After updating the view html to reflect this the right place to create the kendo app would be home.js
define(function( require ) {
var ctor = function() {
};
ctor.prototype.activate = function() {
console.log("Home activate");
};
ctor.prototype.viewAttached = function() {
var $kendoHost = $('#kendoHost');
// Workaround for height = 0.
// Additional code required to calculate on windows.resize
$kendoHost.height($(window).height());
this.app = new kendo.mobile.Application($kendoHost, {
skin: "flat"
});
console.log("Home viewAttached", this.app, $kendoHost.height());
};
return ctor;
});
Last kendo determines kendoHost height as 0, which prevents that the correctly rendered view show up. As a workaound I'm using $kendoHost.height($(window).height()); right before creating the app addresses.
As said in my comment above I'm still not sure if I'd recommend combining those two SPA frameworks as you might encounter more glitches like that while building your app. That said I'd love to hear about your progress :).
Setup
I've got a Telerik Kendo UI TabStrip with multiple tabs inside of an UpdatePanel...
<asp:UpdatePanel ID="DataDetails_Panel" UpdateMode="Conditional" runat="server">
<div id="ABIOptions_TabContainer">
<ul>
<li>Attendance</li>
<li>Grades</li>
<li>Gradebook</li>
<li>PFT</li>
<li>Scheduling</li>
<li>Miscellaneous</li>
<li>Parent Data Changing</li>
</ul>
</div>
</asp:UpdatePanel>
...which I then wire up in javascript later...
var optionTabContainer = $("#ABIOptions_TabContainer").kendoTabStrip({
animation: {
open: {
effects: "fadeIn"
}
},
select: onMainTabSelect
}).data("kendoTabStrip");
Scenario
The users will click on the various tabs and inside of each tab are settings for our portal. When they are in a tab and they make a change to a setting, the expectation is that they'll click on the 'Save' button, which will perform a postback to the server via ajax, because it is in the update panel.
Current Behavior
After the post back happens and the ul content comes back, I reapply the kendoTabStrip setup function call, which makes none of the tabs selected. This appears to the user like the page is now empty, when it just had content.
Desired Result
What I want to do, is after the partial postback happens and the UpdatePanel sends back the ul, I want to reselect the tab that the user previously selected.
What Already Works
I already have a way to preserve the tab that the user clicked on:
var onMainTabSelect = function (e) {
tabToSelect = e.item;
console.log("onTabSelect --> ", e.item.textContent);
}
and a function to reset the selected tab whenever it is called:
function setMainTab() {
if (!jQuery.isEmptyObject(tabToSelect)) {
var tabStrip = $('#ABIOptions_TabContainer').data("kendoTabStrip");
console.log("Attempt to set tab to ", tabToSelect.textContent);
tabStrip.select(tabToSelect);
} else {
console.log("tabToSelect was empty");
}
}
What Doesn't Work
My hypothesis is that the Kendo TabStrip says, "Hey, that tab is already selected" when I call the setMainTab after my postback:
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
BindControlEvents();
setMainTab();
});
...and therefore, doesn't set my tab back. If I click on the tab, then Poof, all my content is there just like I expect.
Any ideas what I may be doing wrong?
I ended up changing the onMainTabSelect method to:
var onMainTabSelect = function (e) {
tabToSelect = $(e.item).data("tabindex");
}
which gets me the data-tabindex value for each li in my ul. I couldn't get the tab index from kendo, so I had to role my own. Once I got that value, then I was able to set the selected tab via an index rather than the tab object reference itself.
I'm making a project where a whole div with buttons is being inserted dynamically when user click a button, and inside that div there's a button, which when the user click on it, it does something else, like alerting something for example.
The problem is when i press on that button in the dynamically added div, nothing happens. The event doesn't fire at all.
I tried to add that div inside the HTML and try again, the event worked. So i guess it's because the div is dynamically added.
The added div has a class mainTaskWrapper, and the button has a class checkButton.
The event is attached using .on() at the end of script.js file below.
Here's my code :
helper_main_task.js : (that's the object that adds the div, you don't have to read it, as i think it's all about that div being dynamically added, but i'll put it in case you needed to)
var MainUtil = {
tasksArr : [],
catArr : ["all"],
add : function(){
var MTLabel = $("#mainTaskInput").val(), //task label
MTCategory = $("#mainCatInput").val(), //task category
MTPriority = $("#prioritySlider").slider("value"), //task priority
MTContents = $('<div class="wholeTask">\
<div class="mainTaskWrapper clearfix">\
<div class="mainMarker"></div>\
<label class="mainTaskLabel"></label>\
<div class="holder"></div>\
<div class="subTrigger"></div>\
<div class="checkButton"></div>\
<div class="optTrigger"></div>\
<div class="addSubButton"></div>\
<div class="mainOptions">\
<ul>\
<li id="mainInfo">Details</li>\
<li id="mainEdit">Edit</li>\
<li id="mainDelete">Delete</li>\
</ul>\
</div>\
</div>\
</div>');
this.tasksArr.push(MTLabel);
//setting label
MTContents.find(".mainTaskLabel").text(MTLabel);
//setting category
if(MTCategory == ""){
MTCategory = "uncategorized";
}
MTContents.attr('data-cat', MTCategory);
if(this.catArr.indexOf(MTCategory) == -1){
this.catArr.push(MTCategory);
$("#categories ul").append("<li>" + MTCategory +"</li>");
}
$("#mainCatInput").autocomplete("option", "source",this.catArr);
//setting priority marker color
if(MTPriority == 2){
MTContents.find(".mainMarker").css("background-color", "red");
} else if(MTPriority == 1){
MTContents.find(".mainMarker").css("background-color", "black");
} else if(MTPriority == 0){
MTContents.find(".mainMarker").css("background-color", "blue");
}
MTContents.hide();
$("#tasksWrapper").prepend(MTContents);
MTContents.slideDown(100);
$("#tasksWrapper").sortable({
axis: "y",
scroll: "true",
scrollSpeed : 10,
scrollSensitivity: 10,
handle: $(".holder")
});
}
};
script.js : (the file where the .on() function resides at the bottom)
$(function(){
$("#addMain, #mainCatInput").on('click keypress', function(evt){
if(evt.type == "click" || evt.type =="keypress"){
if((evt.type =="click" && evt.target.id == "addMain") ||
(evt.which == 13 && evt.target.id=="mainCatInput")){
MainUtil.add();
}
}
});
//Here's the event i'm talking about :
$("div.mainTaskWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
});
It does not look like div.mainTaskWrapper exist.
From the documentation (yes, it is actually bold):
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page.
[...]
By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers.
You might want to bind it to #tasksWrapper instead:
$("#tasksWrapper").on('click', '.checkButton' , function(){
alert("test text");
});
You need to specify a selector with on (as a parameter) to make it behave like the old delegate method. If you don't do that, the event will only be linked to the elements that currenly match div.mainTaskWrapper (which do not exists yet). You need to either re-assign the event after you added the new elements, or add the event to an element that already exists, like #tasksWrapper or the document itself.
See 'Direct and delegate events' on this page.
I know this is an old post but might be useful for anyone else who comes across...
You could try:
jQuery('body')on.('DOMNodeInserted', '#yourdynamicallyaddeddiv', function () {
//Your button click event
});
Here's a quick example - https://jsfiddle.net/8b0e2auu/