.live .toggle (close) not working after ajax request - ajax

I have an ajax request which brings in new posts and each post has a toggle button to show and hide an element which is hidden by default.
The below code works, but with the inserted ajax data it only works the first time (open) and not the second (close)
$(".voice_btn").live( 'click', function(){
$(this).toggleClass('active voice_btn');
$(this).closest('.element').children('.voice_box').toggle(300);
$('.tipsy').hide();
$(this).attr("title", ($(this).hasClass("active")?"Close":"Open") + " voicebox");
return false;
});

If you remove the voice_btn class from the element, it will no longer trigger the click event because it no longer satisfies the selector.
change
$(this).toggleClass('active voice_btn');
to
$(this).toggleClass('active');

just update line 2 to only toggle the active class, because after the first time your code runs the voice_btn class is removed, and your live function is no longer attached to your element:
$(".voice_btn").live( 'click', function(){
$(this).toggleClass('active'); // <- notice the change in this line
$(this).closest('.element').children('.voice_box').toggle(300);
$('.tipsy').hide();
$(this).attr("title", ($(this).hasClass("active")?"Close":"Open") + " voicebox");
return false;
});

Related

jQuery Mobile 1.4+ pagecontainerbeforechange bug?

I am experimenting with the new way of handling page events in jqM and have run into a curious issue. When handling the pagecontainerbeforechange event
$(document).on('pagecontainerbeforechange',function(e,u){test(e,u,'changing');})
function test(e,u,msg){console.log($(u.toPage));}
Attempting to put a jQuery object wrapper around u.toPage - as done above - produces strange behavior.
Check out this fiddle to see what I mean
Click on the Second Page button and then view the console. Nothing will happen (the second page is not shown) and you will see a message along the lines of *Uncaught error:syntax error, unrecognized expression http://jsfiddle.net/egn7g5xb/1/show/#second
Now comment out Line 7 and run the fiddle again. No such issue this time and the second page gets shown.
Perhaps someone here might be able to explain what is going on here?
On initial run, jQuery Mobile creates a fake page before navigating to first page in DOM. At that stage, pagecontainerbeforechange fires twice and returns .toPage as an object.
Later on, upon navigating to other pages, it fires twice again; however, it returns a string first time (URL/hash) and second time it returns an object which is the page itself.
Therefore, when using that event, you have to determine whether .toPage is an object or a string.
$(document).on("pagecontainerbeforechange", function (e, data) {
if (typeof data.toPage == "string") {
/* parse url */
}
if (typeof data.toPage == "object") {
/* manipulate page navigating to */
}
});
Note that pagecontainerbeforetransition is similar to beforechange, however, it fires once and returns .toPage as an object.
First, create your pagecontainer events within $(document).on("pagecreate", "#first", function(){ .. }).
Then the selector for these events should be $(":mobile-pagecontainer") or $("body") NOT $(document).
function test(e,u,msg)
{
console.log(msg);
var IsJQ = u.toPage instanceof $;
console.log(IsJQ);
if (IsJQ){
console.log(u.toPage.data());
} else {
console.log(u.toPage);
}
console.log('---');
}
$(document).on("pagecreate", "#first", function(){
$(":mobile-pagecontainer").on('pagecontainerbeforechange', function (e, u) {
test(e,u,'changing');
});
$(":mobile-pagecontainer").on('pagecontainerchange',function(e,u){
test(e,u,'changed');
});
});
Updated FIDDLE

DOM element reappearing after empty() called

I have a button which when clicked the first time it will load another html page.
When it is clicked the second time it will empty a div of the loaded page.
However, for some reason the loaded content keeps reappearing after the second click....
CSS:
#boatdiv {
width: 100%;
}
.clicked {}
HTML
<button id="load"></button>
<div id="boatdiv"></div>
jQuery
$(document).ready(function() {
$.ajaxSetup ({
cache: false
});
var loadURL = "AjaxLoad_injection.html";
$("#load").on("click", function() {
if(!($(this).hasClass("clicked"))){ //checks if button has NOT been clicked
$("#boatdiv").html("<p>loading...</p>").load(loadURL);
}
else {
$("#boatdiv").empty();
}
$("#boatdiv").toggleClass("clicked");
}
);
}); // end ready
What's going on?
You test $(#load) but toggle $("boatdiv").
Try :
$("#load").on("click", function() {
if(!($(this).hasClass("clicked"))){ //checks if button has NOT been clicked
$("#boatdiv").html("<p>loading...</p>").load(loadURL);
}
else {
$("#boatdiv").empty();
}
$(this).toggleClass("clicked");
});
You are toggling class on wrong element. You want it to toggle on the element being clicked. Same as code I gave you in last post.
Simple to walk through it, you are testing this... so need to toglle the class on this
Use
$(this).togglClass('clicked')
Remember that ajax calls are asynchronous. You may be clicking the button a second time before the ajax call has returned.
You could disable the button during the ajax call, like this:
$('#load').on('click', function() {
if (!$(this).hasClass("clicked")) {
$('#load').attr('disabled', true);
$("#boatdiv").html("<p>loading...</p>").load(loadURL, function() {
$('#load').attr('disabled', false);
});
} else {
$('#boatdiv').empty();
}
//$('#boatdiv').toggleClass("clicked");
$('#load').toggleClass("clicked");
});
The button is disabled before the ajax call. A callback function is passed as a second parameter to the "load()" function. It will be called when the ajax call returns. It will re-enable the button.
EDIT: I missed that the wrong element was getting the class toggled, but I still think you want to disable the button during the ajax call or things can get messed up.

jQuery: toggleClass event handling function for ajax function

I was wondering if someone can help guide me how I can write a event when I'm using toggleClass in jQuery?
I have a list of items and when I click on an item, it highlights it, and when someone clicks another item from the list, the previous highlighted item goes away and highlights the current click. Also, if I click the same item that has been highlighted, it goes away.
Now I'm trying to write a function to call ajax when only its been highlighted. So it won't run the ajax function again when its being pressed again (when highlight is removed).
$(".media").on('click',function(){
var $this = $(this);
// highlighting the object
$this.toggleClass('selectMedia').siblings().removeClass('selectMedia');
// saving the id
var selId1 = $this.data('id');
$.post("ajax/ajax_sessions.php", {"sel_1":selId1}, function(data) {
alert(data); // alerts 'Updated'
});
});
Thank you for help!
Just check for the existance of the class before doing your AJAX request:
if ( ! $this.hasClass('selectMedia') ) return;
// Now do your AJAX request...

KendoUI Grid: row selection by jquery

I want to switch page and select a row on grid when page loaded. And in $(document).ready(function()) I write this:
$("#myGrid").data("kendoGrid").dataSource.page(17);
And it's working: the grid page is switched to 17. But right after that I write:
$("#myGrid").data("kendoGrid").select($("#myGrid").data("kendoGrid").tbody.find('>tr').find('>td').filter(function () {return $(this).text() == "#Model.ActionId";}).parent('tr:first'));
And it's not working. But when I run this command from browser's console, the row is selected. What should I do?
Probably your grid is bound to a remote service. In that case paging doesn't happen immediately. The grid's data source makes asynchronous request to the remote service and the grid is rebound when the response is received.
To make it work you need to call the selection code after response is received. The dataBound event of the grid is the proper place to call that code. Here is an example:
$("#myGrid").kendoGrid({
/* other configuration */
dataBound: function() {
this.select(this.tbody.find('>tr').find('>td').filter(function () {return $(this).text() == "#Model.ActionId";}).parent('tr:first'));
}
});

Ajax loader and events runs more than once

I have a website that pages' contents loaded by ajax. All of my pages are seperate files actually and when I need to call a page, I just passed the link to my "pageLoader" function.
pageLoader handle with content loading and re-ignite/re-define the necessary functions like close button.
Since the actual function have ~250 lines, I did re-write a short version;
var pageLoader = function(link){
var page = $(link).attr("href").replace('#','');
if(page != lastCalledURL){
// Load the page.
$.ajax({
beforeSend: function(){ /* remove previously loaded content; */ },
success: function(data){
// remove the loaded content if user clicked to close button.
$("a.close-button").live("click", function(){
$(this).parent().fadeOut().remove();
return false;
});
// load another page if user click another page's link.
$("a.content-loader-link").live("click",function(){
pageLoader(this);
});
// handle with tabs
$("a.tabs").live("click", function(){
var index = $("a.tabs").index(this);
console.log(index);
return false;
});
}
});
lastCalledURL = page;
}
return false;
OK. If I click a link in the page, It calls pageLoader. If I click one of the links just once, pageLoader called once. If I click another link, pageLoader called twice. If I click another link again, pageLoader called third times and so on.
Same things happen for the links that bind with "live" function in the code. If I click a.tabs, it write to console twite. If I clicked another .tabs link, it write to console four times and increasing double for every click.
I don't why it happens. Please let me know if you have any idea.
You can solve it by using the bind and unbind. Like this:
$("a.tabs").unbind('click').bind("click", function(){
var index = $("a.tabs").index(this);
console.log(index);
return false;
});
But i would prefer that you attach this events in your $(document).ready function instead of everytime you make an AJAX call.
$(document).ready(function() {
// Attach your events here.
});
Those live event handlers "Attach a handler to the event for all elements which match the current selector, now and in the future." so you shouldn't need them in your ajax call.

Resources