Onsen UI PostPush event callback fires multiple times - javascript

I am working on an OnsenUI powered app.
It is having multiple pages.
I am using postpush event to fire my ajax requests for data.
Like below.
$scope.navi.on('postpush', function () {
//ajax code here
});
Now the issue is, my complete code looks like below.
$scope.navi.pushPage('linkone.html');
$scope.navi.on('postpush', function () {
//ajax 1
});
$scope.navi.pushPage('linktwo.html');
$scope.navi.on('postpush', function () {
//ajax 2
});
If I navigate to linkone.html page it fires the ajax1.
After that if I navigate to linktwo.html it fires ajax1 and ajax2 both.
I want only relevant ajax to be fired. But both the events are getting fired. And if I keep on browsing pages, eventually too many requests starts getting fired.
Can anyone help me regarding this?

What you are explaining is actually the expected behaviour. The on method adds a listener to be executed whenever the event becomes triggered. You seem to be adding more listeners without removing them.
Alternatives:
A simple alternative would be the once method which will be executed only once and then it will remove the listener automatically.
Instead of adding listeners you can just queue the ajax as a callback to the pushPage - either of these:
$scope.navi.pushPage('linkone.html', {callback: ajax1});
$scope.navi.pushPage('linkone.html').then(ajax1);
should be fine.
You can add one listener which does different things depending on your page:
$scope.navi.pushPage('linkone.html');
$scope.navi.on('postpush', function(ev){
if (ev.enterPage.id === 'page1') {
ajax1();
} else if (ev.enterPage.id === 'page2') {
ajax2();
}
});
The same thing can probably also be achieved with the page's init event.
document.addEventListener('init', function(ev) {
if (ev.target.id === 'page1') {
ajax1();
} else if (ev.target.id === 'page2') {
ajax2();
}
});
However do note that in this third alternative page1 and page2 must be the ids of the ons-page elements, not the templates'.

Related

Ajax sends request more than once

I have a huge problem with working with AJAX:
After the AJAX request on my page is send the next request are send multiple times, and buttons think that they are pressed multiple times.
Now I searched around here and the internet, but I can't solve it. So far, following corrections are made in the code:
All code is in an own function called AjaxInit()
AjaxInit() is called upon $(window).load and on $(document).ajaxStop
All Element have their binder to body (e.g. $("body").on("click","#btn-main", function)
Now I have tried unbinding all events using $("body").find("*").off(), but that did not help either.
I know that I do something wrong, I just don't know what.
How can I properly rebind everythink after the Ajax call is done? How can I make shure that object bindings (e.g. $("#news").sortable({})) will work properly after the first ajax call? I would love to use AJAX for all the callbacks on my page, but currently the best solution seems to be just reloading the entire page after every ajax call, which would be rather bad.
Any help is appreciated.
EDIT: Code added
$(window).load(function() {
AjaxInit();
});
$(document).ajaxStop(function() {
AjaxInit();
});
function AjaxInit() {
$("body").on("click", "#btn-admin-main", function(e) {
console.log("Admin clicked");
e.handled = true;
e.preventDefault();
LoadDynamicContent("/Edit/");
});
}
function LoadDynamicContent(path) {
//Nach oben Scrollen
$('html,body').scrollTop(0);
$.ajax({
type: 'GET',
url: path,
success: function(response) {
var html_response = $(response).find('#dynamic_content').html();
$("#dynamic_content").html(html_response);
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<a class="sidebutton-full" id="btn-main">Edit</a>
<div id="dynamic_content"></div>
You can unbind the click event from button
$(document).unbind('click').on("click", "#btn-main", function () {
//do stuff here
});
OR
$(document).off("click", "#btn-news").on("click", "#btn-news", function () {
});
If your form submission hitting twice then you need to change your code little bit
$("#form_news_sort").submit(function(e){
e.preventDefault()
// do stuffer here
.
.
.
.
return false;
})
if you are still facing error , please comment below
The problem is that when your ajaxStop handler calls AjaxInit(), it adds another click handler to the body.
In your example code, it looks like you don't need ajaxStop at all. All it will do is add another click handler, which is the problem. Or if your real code does some more complex initialization that needs to run whenever all Ajax requests are complete, you should factor out the click handler assignment from whatever else needs to happen.

Meteor + Bootstrap - Alert closed.bs.alert does not trigger

I'm using Meteor and Bootstrap, with the nemo64:bootstrap package. In custom.bootstrap.json I have "alerts" and "alert" on.
I'm trying to capture the closed.bs.alert event in a Template events. For some reason, it won't capture.
Template.alert.events({
'closed.bs.alert .alert': function () {
console.log('closed'); // does not trigger
}
});
Oddly, close.bs.alert does work:
Template.alert.events({
'close.bs.alert .alert': function () {
console.log('closed'); // triggers
}
});
Also, if I add the event via jQuery, I can capture closed.bs.alert:
$('.alert').on('closed.bs.alert', function () {
console.log('closed'); // triggers
});
So, I know I have my events formatted correctly and I know the closed.bs.alert event is triggering... but for some reason I can't catch it with Template.alert.events.
Any ideas?
I dove in to the Bootstrap code and found where it triggered this event: alert.js, line 50
First, the technique that I got to work:
Templates.alert.onRendered({
$('.alert').on('closed.bs.alert', function (e) {
console.log('closed'); // triggers =D
});
});
I think the problem lies in the fact that Bootstrap detaches the alert before triggering the event, so things like $(document).on('closed.bs.alert', '.alert') can't work. I don't know 100% for sure, but I suspect Meteor's Template.my_template.events() trigger using a very similar method as well.
Normally this would work:
$(function () {
$('.alert').on('closed.bs.alert', function () {
console.log('closed'); // doesn't trigger
});
});
However, Meteor throws a wrench in to that plan because I'm loading the alerts from data, they aren't there when that would trigger.
However, by putting a jQuery-style on() in a Template.my_template.onRender() seems to do the trick.
Also, Bootstrap doesn't throw the event unless the alert has the "fade" class. You can assign the fade class without including the "transition" module. If you leave it off, you just won't get the effect, but the event can fire regardless.

Onload fires no matter where I place it

Right, I'm getting quite aggitated with this. I'm probably doing something wrong, but here's what I'm doing:
$(document).ready(function () {
$('#somebutton').click(function () {
openPage1();
});
$('#someotherbutton').click(function () {
openPage2();
});
});
var openPage1 = function () {
$('#iframe').attr('src', 'someurl');
$('#iframe').load(function () {
$('#button').click();
});
};
var openPage2 = function () {
$('#iframe').attr('src', 'anotherurl');
$('#iframe').load(function () {
$('#anotherbutton').click();
});
}
Whenever I click somebutton everything goes as expected. However when I click someotherbutton. The .load() from openPage1() is called first and I can't find a way to stop that. The .load() from openPage1() has a button with the same name, however on openPage2() I need to modify the contents before clicking the buttons.
I need to use .load() because I can't click the buttons before the document is ready.
Basically what I need is two seperate .load() instances on the same iframe, that don't fire off on each other.
Besides that, maybe my understanding of jQuery/JS is wrong, but shouldn't the .load() events only be listening after clicking the corresponding button?
Can someone help me out, this has been keeping me busy all afternoon.
Try using on, and once loaded, unbind
$("#iframe").on("load", function(){
$(this).off("load");
$('#button').click();
});
That way you remove the handler you put up before the second button is clicked?
By writing : $('#iframe').load(function (){ $('#button').click(); });, you are adding a listener on the load event, which will stay and be re-executed on each subsequent reload of the iframe.
Here is a jsfiddle to demonstrate this : click on the "reload" button, and see how many times the "loaded" message appears in your console.
in your case, if you click on #somebutton, then on #someotherbutton, after the second click, you will have two handlers bound on the load event, and both will be triggered.
If you click 5 times on #somebutton, you should end up calling 5 times $('#button').click().
If you want to execute it once, you can follow Fred's suggestion, or use jQuery .one() binder :
$('#iframe').one('load', function(){ $('#button').click() });
Here is the updated jsfiddle : 'loaded' should be displayed only once per click.
Maybe try and replace the lines in both functions like this:
$('#iframe').load(function() {
$('#anotherbutton').click();
};
$('#iframe').attr('src', 'anotherurl');
Otherwise it might be firing the event before the new event-handler has been set.
This isn't really an answer to your problem Now it is an answer, but I think utilizing functions as they were intended could be beneficial here, i.e.:
//Utilize a single function that takes arguments
var openPage = function (frame, src, eventEl) {
frame.attr('src', src); // If you pass frame as a jQuery object, you don't
frame.on("load", function(){ // need to do it again
$(this).off("load");
evEl.click(); //Same for your buttons
});
}
//Simplify other code
$(document).ready(function () {
$('#somebutton').click(function () {
openPage($("#iframe"),somehref,$("#buttonelement"));
});
$('#someotherbutton').click(function () {
openPage($("#iframe"),anotherhref,$("#someotherbuttonelement"));
});
});

Prevent calling a function

I have two parts of scripts.
Part 1 :
$("mySelector").click(function() {
alert('you call me');
})
Part 2 :
$("mySelector").click(function() {
if(myCondition) {
//how can i prevent calling the first function from here ???
}
})
The whole problem, is that i have no access to part1. So i need to unbind the event allready specified in part 1, if myCondition is true, but otherwise i need to call the first function.
Thanks
UPDATE:
Thank you. I didn't know about stopImmediatePropagation(). But i feel, that there must be something like that :)
But actually in my case it doesn't work :(
Please have a look at my site
http://www.tours.am/en/outgoing/tours/%D5%80%D5%B6%D5%A4%D5%AF%D5%A1%D5%BD%D5%BF%D5%A1%D5%B6/Park-Hyatt-Goa/
Under the hotel description tab i have cloud carousel, when i click on not active image (not the front image), as you can see i'm consoling that i stopImmediatePropagation() there, but the event however calls :(
If your handler is registered first, then you can use event.stopImmediatePropagation like this:
$("mySelector").click(function(event) {
if(myCondition) {
event.stopImmediatePropagation();
}
})
Be aware that this will also stop event bubbling, so it will also prevent click handlers on parent elements from being invoked.
Update: If this does not work, then your handler is attached after the one you want to control. This is a problem that makes the solution much more difficult. I suggest seeing if you can bind "before the other guy", otherwise you will have to unbind the existing handler and then conditionally invoke it from within your own by retaining a reference to it. See jQuery find events handlers registered with an object.
No access:
$("#mySelector").click(function() {
alert('you call me');
})
Access:
var myCondition = true, //try false too
fFirstFunction = $("#mySelector").data("events").click[0].handler;
$("#mySelector").unbind("click");
$("#mySelector").click(function() {
if(myCondition) {
alert(myCondition);
} else {
$("#mySelector").click(fFirstFunction);
}
});
Look at this example
You can call
$('mySelector').unbind('click');
to get rid of all the click handlers. If your script is loaded after the other one (which appears to be the case), then that should do it. However note that it does unbind all "click" handlers, so make sure you call that before you add your own handler.
If you can't ensure your handler is attached first, try the following code:
var events = $('mySelector').data("events"); //all handlers bound to the element
var clickEvents = events ? events.click : null;//all click handlers bound to the element
$('mySelector').unbind('click'); //unbind all click handlers
//bind your handler
$("mySelector").click(function(e) {
if (myCondition) {
//do what you want
} else {
//call other handlers
if (clickEvents) {
for (var prop in clickEvents)
clickEvents[prop].call(this, e);
}
}
})
Update:
Above code is for jQuery 1.3.2
Above code is based on internal implementation of jQuery 1.3.2, so please check it carefully once you update jQuery.
return false;
-or-
event.preventDefault();

jquery function not getting called inside of an ajax function

So im trying do disable links on some <li> ellements that have been loaded in from another page using an .load() function, but for some reason i'm not able to effect those list items.
var from_post = false;
$(document).ready(function() {
//so this is the function that loads in data from another page
$("#gallery").load('http://localhost/index.php/site/gallerys_avalible/ #gallerys_avalible'), function() {
console.log('hello');
// sense there are no other li elliments on the page i thought this
// would be okay. but this function never gets called, i've moved it
// all over i just recently attached it to the load function thinking
// that maybe if the load was not complete it would not run, but i
// have had no luck.
$('li').click(function (e) {
e.preventDefault();
console.log("I have been clicked!");
return false;
});
};
$('#addNew').click(function () {
console.log('i got called');
$('#new_form').fadeIn(1000);
});
$('form').submit(function() {
if(from_post) {
//submit form
return true;
} else {
//dont submit form.
return false;
}
});
any help would be greatly appreciated, oh and the other thing is that i can run this function through firebug, and it works 100% fine. so im stumped.
You are closing your call to .load() too early. You have:
$("#gallery").load('http://...'), function() {
That just calls load and then declares a function. But, that function is not bound to the success handler and it will never be executed. You need the ) to be on the other side of the function declaration so that the function is included as a parameter to your call to load:
$("#gallery").load('http://...', function() {
...
});
Fix that and your code works: http://jsfiddle.net/gilly3/WdqDY/
Try a future-proof event observer like live or delegate:
$('li').live('click', function(){})
or, this method is preferred if you know the parent:
$('#gallery').delegate('li','click',function(){})
The reason for needing this is your click events are being bound to elements that are on the page at the time of the binding. Any li's added later will not see that binding which is how live or delegate works. They bind to the parent and traverse the child nodes every (click in this case) event to see if the event applies to an existing child.
Use .live('click', ...) or .delegate() instead of .click(...).

Categories

Resources