How to bind to submit event in jQuery Mobile pages - javascript

Tried to bind submit event (or click or whatever) to an element within a jQuery mobile page. What I wanted to do is get the value from an input within an form element within a jQuery page and store it in cookies/localStorage. Every time I come back to this page I want to restore the input field.
Currently I ended up in using this script:
$('.pageClassSelector').live('pageinit', function (e) {
$('.classSelector').submit(function () {
var q = $('.inputClassSelector').val();
// store to localStorage ...
});
// load from localStorage ...
$('.q').val(lastSearchString);
});
This approach is documented there http://jquerymobile.com/test/docs/api/events.html
Since it seems possible that identical pages are hold in the DOM, ID selectors are not quite useful. My problem now is that everytime I navigate to this page the submit event is bound again and thus results in storing DIFFERENT (!) values. The submit event seems to be fired multiple times and much more interesting with the value before last.
Am I doing anything completly wrong? Any hints how to do scripting in jquery mobile properly?
TRY1:
I placed now the submit event binding within the pagebeforeshow event like so:
$('#PageId').on('pagebeforeshow', function (e) {
$('.classSelector').on('submit', function () {
var q = $('.q').val();
alert('stored: ' + q);
}
$('.q').val(lastSearchString);
}
But the value going to be stored is still the value before last, when I was navigating the page before. The first time it works as it should.
TRY2:
This is what I have now and it looks like it does that what I want. I select now the current page and select only the form which is a child of this page.
Is this good practice?
$('div:jqmData(id="PageId")').on('pagebeforeshow', function (e) {
$(this).find('#form').on('submit', function () {
var q = $(this).find('#input').val();
localStorage.setItem("key", q);
return true;
});
lastSearchString = localStorage.getItem("key");
$(this).find('#input').val(lastSearchString);
});

Your requirement to load from local storage and store on the page needs to be done by binding to the pagebeforeshow event (look at the section "Page transition events") and not the pageinit event like you are currently doing.
$('.pageClassSelector').on('pagebeforeshow', function (e) {
// load from localStorage ...
$('.q').val(lastSearchString);
});
Furthermore generally each page element (where you have data-role='page') should have a unique ID so you can use that instead of the CSS selector.

Multiple events firing when navigating pages sounds like multiple bindings to me, which is a known problem with jQuery Mobile. Bindings are not unbound when navigating pages, because everything is loaded through AJAX. See for example this StackOverflow Question: Jquery mobile .click firing multiple times on new page visit or my solution.

$('.classSelector').on('submit', function(){})
Try to use the constraction to bind your event to element.
Look likes some data was loaded through ajax request

Related

Custom jQuery not working on Wordpress Ninja Forms plugin

I am having some problems when I want to add custom jQuery code that affects the form.
For example when someone clicks an input or radio button another input or element to be hidden or shown.I tried to get a result like console.log('trigger'); when clicked or something else but nothing in dev. console appeared.Also, I tried the following methods:
To call the click event with .on('click', function()... or to call the event with .trigger('click');, or to change the event to change
To embed the script within a file from ninja forms or to put it inside the page at the ending of body tag in footer.php
To change the opening declaration of jQuery to work inside a function like this : (function($) {$(document).ready(function(){.....
I know that I could try another plugin, I tried one and the custom jQuery works but I really like this one and don't know why this is happening ...
Thanks
Not sure if you need help with this any more as it's been some time since you posted your question, but this may help others in the future. I had the same/similar issue with not being able to run JS/jQuery on the Ninja Forms and found that it's because Ninja Forms load their forms asynchronously. So, when your document.ready function runs, the form doesn't yet exist and it's not able to bind.
Ninja Forms have their own event ready state that can be used as follows:
jQuery(document).on( 'nfFormReady', function( e, layoutView ) {
// Your code goes here...
});
The event isn't registered simply because the elements you're trying to bind the event to do not exist yet at that moment (on document load). Ninja forms loads the form contents asynchronously, so you'll have to wait until the form is fully loaded and then add your event listeners.
This works for me:
var formExists = setInterval(function() {
if ($(".nf-form-cont").length) {
// Set your event listeners here, example:
$("#nf-field-1").click(function(e) {
console.log("click!");
}
clearInterval(formExists);
}
}, 100); // check every 100ms

jQuery click event handler attached to dom element

I am having hard time while building e-commerce cart module with jquery.
Lets say that if i write a tags in html like this:
<div class="add-to-cart">+</div>
and then target it in my app:
this.$products,
this.$pa,
this.$ip,
this.$products = $('.shopperProducts'),
this.$pa = this.$products.find('.shopperAdd');
var self = this;
this.$ip = function() {
var init = function(action, product) {
/.../
};
self.$pa.on('click', function(event) {
event.preventDefault();
init('add', this);
});
};
This method is possible while im displaying products because they are displayed by php on page refresh so i have all the + links generated by php on html.
The problem is on the checkout file, this is the page when i display entire cart filled with products, cart must be generated and handled in jQuery and AJAX.
And code that i showed you doesnt work in cart page beacuse those links are appended for each product via jQuery into the DOM.
I have been study possible methods and there are few, the most in favour is to do this:
$(document).on('click', self.$pa, function(event) {
The problem with that solution is that it also is considered practice to be avoided due to high resources drain, i can see the difference in execution time myselfe, it takes a lot longer on low end devices. Is there some neat trick that can be used or method that is considered good practice to do in that situation?
<--- EDIT (Solution) --->
Instead of calling:
this.$products = $('.shopperProducts'),
this.$pa = this.$products.find('.shopperAdd');
on the beginning, i have to call it after i load elements into DOM and then they became targetable, then i just have to use self.$ip(); and event handlers can be attached. Without using any sort of workarounds, the solution was just to change order of executing commands.
There are two main strategies that you can use for adding click handlers for elements that you dynamically add to the dom.
One, You can add click handlers to the DOM element each time you create one
var addToCartButton = $('<div class="add-to-cart">+</div>');
addToCartButton.on('click', function(){
init('add', this);
};
// then you add your DOM element to the page
$('.container').append(addToCartButton);
Two, you can have a master click event listener on the page listen for all clicks where your buttons fall, and in your click handler, figure out whether the user is clicking on your element or not. This is ultimately more efficient and you don't have to add or remove event handlers each time you add elements to your page. This pattern is called event delegation, and here's another post on Stack that probably explains it better than I can
What is DOM Event delegation?
$('.container').click(function(event){
if ($(event.target).is('.add-to-cart') || $(event.target).parents().is('.add-to-cart')) {
// handle add to cart
}
})
BTW, your use of the self variable doesn't actually do anything, and neither does declaring this.$pa. You're basically accessing the property "$pa" of your this object, but not doing anything it.

If an event fires a random amount of times, how do I capture the last one in Javascript/Jquery?

I have a function, that adjusts element width/height on a page. This function is triggered by a custom dimensionchange event.
I'm
$(window).trigger("dimensionchange")
whenever I'm loading content via AJAX or changing a page (I'm using jquery mobile).
My problem is on some pages, a bunch of Ajax requests get triggered (like a search page, which ajax loads criteria and intial results), so I'm ending up with several "dimensionchange" events, which all trigger my layout update function. This slows down the page considerably and is not necessary, because I only need to capture the last dimensionchange and then update the layout.
Question:
Is there a way to capture the last occurence of an event when the event fires a random amount of times? The only thing I could think of is to set a timeout on every event occurence and if there is no further event in ... 500ms... trigger the page update. But this seems pretty awkward, so I'm curious to know if there is a better way?
Thanks for help!
You want to use jQuery's Global Ajax Event Handlers ajaxStart() and ajaxStop() methods.
There is another recent post about Using AjaxStop and AjaxStart. The main thing you need to know is that you can be notified when the first ajax query begins, and when the last one ends. You could set a flag like this:
$(document).ready(function() {
var ajaxBusy = false;
$(document).ajaxStart( function() {
ajaxBusy = true;
}).ajaxStop( function() {
ajaxBusy = false;
});
});

jquery event added multiple times

I have a fairly large javascript class that generates an complete ajax-generated application. In one version of the ajax page there are a number of dropdown menus. These menus can get created and destroyed at various points during the life cycle of the application.
This is the behaviour I see:
User opens page version 1: no dropdowns
User goes to page version 2: dropdowns added with jQuery onchange event. Work as intended.
User returns to version 1 of page, dropdowns removed.
User returns to version 2 of page, dropdowns added again (using same element IDs)
dropdowns will now have 'double' event handling, triggering the event for each onchange.
The behaviour I'm struggling with is as follows.
On the initial page load, I add an onchange event:
function myClass(){
//Initiate once for current and future elements.
jQuery(document).on('change',".mydropdowns",
function(e){
self.submitDescriptionChange(this);
}
);
}
myClass.prototype.submitDescriptionChange = function (el){
doSomeAjaxStuff();
}
This works fine, except that each time the user goes to pages version 1 and returns to page version 2, the event gets multiplied. Very quickly you can end up with the event firing 20 times per change event, which in this case creates 20 ajax calls.
Logically, by using jQuery.off() I should be able to avoid this. But what happens instead is that the event is removed from both past and future elements, which means that when I recreate page version 2, the dropdowns won't work.
Every way I have tried this (and I've tried LOADS), I either end up with no event firing, or multiple events firing. I cannot seem to find a way to add/replace the elements whereby the event is only ever fired once.
Any ideas how I can solve this?
UPDATED
Yeah, so it turns out I misdiagnosed the problem. It actually came from repeatedly rebinding a 'hashchange' event, rather than rebinding the onchange event. Apologies for misdirection. Moving to bind() function to somewhere where it only executed once fixed the issue.
Since you do not want .off() to remove your events from other pages, I would suggest using namespaces for your events. For example, something like this:
function myClass(pageno) {
var pref_ev = 'mypage' + pageno + '.' + 'change';
$(document).off(pref_ev).on(pref_ev, ".mydropdowns", function(e) {
self.submitDescriptionChange(this);
});
}
This way, each page will have its own "change" event such as "mypage1.change". The event is still registered normally as a change event; the prefix namespace "mypage1" is used to only perform the .off() call on the right events.
I am not sure what plugin you are using for your dropdown menus but there should be a "destroy" method on that plugin. If you call that when removing the dropdowns that should work. Also, if you are only hiding the second page and not actually removing it from the DOM you dont have to re-invoke the plugin as the plugin will still be saved on the element.

Javascript for when AjaxControlToolkit TabContainer is ready?

I have a page with a TabContainer control (from the Ajax Control Toolkit), and I toggle the visibility of some elements on the page depending on the currently-selected tab. I'd been doing this in an event handler for OnClientActiveTabChanged (which works fine), but I discovered that it leaves the page in the wrong state after a postback. I tried adding some code to the document.ready event handler to get the index, but when I do the following:
$(document).ready(function () {
var index = $('#<%= TabContainer1.ClientID %>').[0].control.get_activeTabIndex();
// Do some stuff with the index
});
...I get a null reference exception on the .control property. Is there a way to hook a client-side "ready" event for the TabContainer?
I’m not familiar with the event lifecycle with normal DOM elements (it seems like there ought to be a general onload event, but I don’t see one). If there isn’t an event that can be easily handled, it seemed like it might work to add an UpdatePanel with UpdateMode=Conditional and an AsyncPostBackTrigger that pointed to a hidden button with an onclick event handler that would get the active tab index – but that seems like a lot of moving pieces for something that I’d expect the DOM to expose already.
Too late to be helpful, but I've had the same issue and found a workaround.
Change you code
$(document).ready(function () {
var index = $('#<%= TabContainer1.ClientID %>').[0].control.get_activeTabIndex();
// Do some stuff with the index
});
to
function pageLoad() {
var index = $('#<%= TabContainer1.ClientID %>').[0].control.get_activeTabIndex();
// Do some stuff with the index
};
Explanation here:
http://encosia.com/document-ready-and-pageload-are-not-the-same/
Basically, jQuery's ready event is "a bit early" and the TabContainer is not initialized yet, whereas the client side ASP.Net's pageLoad is late enough and the TabContainer has been initialized by then.
Check this post to save tab selection during postbacks. It works for normal post backs by saving the active tab index in hidden variable. Though its written for a JQuery plugin in the posted link, concept should be the same i.e., persisting the index of the selected tab.

Categories