jQuery monitoring form field created by AJAX query - ajax

Preface: I am sure this is incredibly simple, but I have searched this site & the jQuery site and can't figure out the right search term to get an answer - please excuse my ignorance!
I am adding additional form fields using jQuery's ajax function and need to then apply additional ajax functions to those fields but can't seem to get jQuery to monitor these on the fly form fields.
How can I get jQuery to use these new fields?
$(document).ready(function() {
$('#formField').hide();
$('.lnk').click(function() {
var t = this.id;
$('#formField').show(400);
$('#form').load('loader.php?val=' + t);
});
//This works fine if the field is already present
var name = $('#name');
var email = $('#email');
$('#uid').keyup(function () {
var t = this;
if (this.value != this.lastValue) {
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(function () {
$.ajax({
url: 'loader.php',
data: 'action=getUser&uid=' + t.value,
type: 'get',
success: function (j) {
va = j.split("|");
displayname = va[1];
mail = va[2];
name.val(displayname);
email.val(mail);
}
});
}, 200);
this.lastValue = this.value;
}
});
});
So if the is present in the basic html page the function works, but if it arrives by the $.load function it doesn't - presumably because $(document).ready has already started.
I did try:
$(document).ready(function() {
$('#formField').hide();
$('.lnk').click(function() {
var t = this.id;
$('#formField').show(400);
$('#form').load('loader.php?val=' + t);
prepUid();
});
});
function prepUid(){
var name = $('#name');
var email = $('#email');
$('#uid').keyup(function () {
snip...........
But it didn't seem to work...

I think you are close. You need to add your keyup handler once the .load call is complete. Try changing this...
$('#form').load('loader.php?val=' + t);
prepUid();
To this...
$('#form').load('loader.php?val=' + t, null, prepUid);

What you are looking for is the jquery live function.
Attach a handler to the event for all elements which match the current selector, now or in the future
You can do something like this:
$('.clickme').live('click', function() {// Live handler called.});
and then add something using the DOM
$('body').append('<div class="clickme">Another target</div>');
When you click the div added above it will trigger the click handler as you expect with statically loaded dom nodes.
You can read more here: http://api.jquery.com/live/

Related

jquery/ajax load scripts - best practices

I'm trying to get the hang of using ajax loads (mostly via jquery) to make my site more efficient. Wondering if anyone can provide any suggestions re "best practices" for using ajax?
Is there a way to simplify a script for multiple ajax calls? For example, I currently have the working script:
$(document).ready(function() {
$('#dog').click(function () {
$('#body').load("dog.html");
});
$('#cat').click(function () {
$('#body').load("cat.html");
});
$('#bird').click(function () {
$('#body').load("bird.html");
});
$('#lizard').click(function () {
$('#body').load("lizard.html");
});
});
The script just gets longer and longer with each additional function. Is there a simpler, more efficient way to write this script to cover multiple load scripts?
Also, should I be using ajax loads to replace the majority of actual links?
Here is a suggestion, since the code you posted seems to have a pattern between the id and the filename:
$(document).ready(function () {
$(document).on('click', 'commonParentElementHere', function (e) {
$('#body').load(e.target.id + ".html");
});
});
This suggestion uses .on() and you just need to add a commonParentElementHere, a id or a class of the common parent of those elements.
Another option is to use a class on all elements that should be clickable, and then use the code passing the id to the html file name, like:
$(document).ready(function () {
$(document).on('click', '.theCOmmonClass', function () {
$('#body').load(this.id + ".html");
});
});
I'd say give all the elements you want to click on a class say ajax then.
$(document).ready(function() {
$('.ajax').click(function () {
$('#body').load(this.id + ".html");
});
});
Assuming that the id matches the file name the script can be simplified to:
$(document).ready(function() {
$('#dog,#cat,#bird,#lizard').click(function () {
var fileName = this.id + ".html";
$('#body').load(fileName);
});
});
This script simply specifies each id in a single selector that separates each id with a comma. This will calls the click function to be fired for each element. With the anonymous function attached to the click event, the id of each element is obtained and concatenated to create the file name which is then passed to the load function.
If the id doesn't always match the element you could use the following approach.
var mappings = [
{id: "fileName1", file:"file.html"},
{id: "fileName2", file:"file2.html"}
];
$(document).ready(function() {
for(var i = 0; i < mappings; i++){
createMapping(mappings[i]);
}
function createMapping(mapping){
$("#" + mapping.id).click(function(){
$('#body').load(mapping.file);
});
}
});

There must be an easier way

I am trying to create an JQM app and are doing so by getting a lot of data from database. When I click on a link from a ajax/json generated calendar list I should then be able to get the info for that event by calling the server and get the data. As it is now I do this in 2 steps like this.
My ajax generated event list:
$.each(groupcalendar, function (i, val) {
output += '<li><h2>' + val.matchformname + '</h2><p><strong>' + val.matchday + '</strong></p><p>' + val.coursename + '</p><p class="ui-li-aside"><strong>' + val.matchtime + '</strong></p></li>';
});
When I click on one of the links I want to goto a page called prematchdata.html and get the data fro that specific event. I do so by first calling the click and get the eventid from data-id like this:
$(document).on('click', '#gotoMatch', function () {
var matchid = $(this).attr("data-id");
$.get("http://mypage.com/json/getmatchinfo.php?matchid="+matchid, function(data) {
localStorage["matchinfo"] = JSON.stringify(data);
$.mobile.changePage( "prematchdata.html", { transition: "slide", changeHash: true} );
}, "json");
});
I save the returned data as localStorage and then uses this data in my pageinit like this:
$(document).on("pageinit", "#prematchdata", function() {
var matchinfo = {};
matchinfo = JSON.parse(localStorage["matchinfo"])
var content = '<h2>'+matchinfo["matchname"]+'</h2>';
$('.infoholder').html(content);
});
It works, although for me it seems like the last 2 steps should be done in one, but i am not sure how to do so? It seems a little bit wrong get data, save locally and then use it? Can't this be done without the $(document).on('click', '#gotoMatch', function () {});?
Hoping for some help and thanks in advance :-)
You could try sending it up using a query string. When you're using changePage, change your code like this :
$(document).on('click', '#gotoMatch', function () {
var matchid = $(this).attr("data-id");
$.get("http://mypage.com/json/getmatchinfo.php?matchid=" + matchid, function (data) {
paramData = data[0];
$.mobile.changePage("prematchdata.html", {
transition: "slide",
changeHash: true,
data: paramData //added this extra parameter which will pass data as a query string
});
}, "json");
});
When you're getting it back,
$(document).on("pageinit", "#prematchdata", function() {
var url = $.url(document.location);
var name= url.param("matchname");
var content = '<h2>'+ name +'</h2>';
$('.infoholder').html(content);
});
Another easy way would be use a singlepage template instead of a multi page template. Then, you could just use a global variable to get and set data.
That said, what you're doing right now is more secure than this query string method. By using this, anyone can see what you are sending over the URL. So I advise you keep using localStorage. For more info on this, look into this question.

jquery each on new elements not working

$('.collapse').each(function() {
var title= $(this).siblings('.accordion-heading').find('a');
$(this).on('show hide', function (e) {
if(!$(this).is(e.target))return;
title.parent().toggleClass('active', 300);
title.parent().hasClass('active') ? $('input.party').prop('value', '') : $('input.party').val(title.siblings('.delete').prop('id'));
var id = title.siblings('.delete').prop('id');
var data = {id: id};
$.post("times.php", data, function(result) {
if(title.parent().hasClass('active')){
$('.times').html('');
} else {
$('.times').html($.parseJSON(result));
}
})
})
})
So I am adding a new accordion-group to my html by adding a new party and I wan't all this to work on the newly added elements as well. I didn't find topics that could help me since it is a bit more specific than any random each function (I think).
This future elements thing is new to me, so I would appreciate some explanations or a good link to a place other that the jquery website which I already checked.
Thank you for your time!
Basically what I want to do this replace $(this).on('show hide', function (e) { with something like $(document).on('show hide', $(this), function (e) {. What I just wrote doesn't work though.
If it is just about the event handler, then you can use event delegation to capture the event on dynamically created elements as well.
There is not reason why you have to use .each here, so just omit it:
$(document.body).on('show hide', '.collapse', function() {
var title = $(this).siblings('.accordion-heading').find('a');
if(!$(this).is(e.target))return;
// rest of the code...
});
this will apply on any new objects matching selector
jQuery(document).on('show hide', '.accordion-heading a', function(event){
...
});

jqgrid setting page of grid

When a user selects a cell, I have the following code which goes to a window.location
beforeSelectRow: function (rowid, e) {
var $td = $(e.target).closest("td"),
iCol = $.jgrid.getCellIndex($td[0]);
if (this.p.colModel[iCol].name === 'FlSaved') {
var pagenum = $('#reportList').getGridParam('page');
var rownum = 200;
alert(pagenum);
alert(rownum);
window.location = "/Plt/FileUpload/" + '?id=' + encodeURIComponent(rowid) + '&pagenum=' + pagenum;
}
Note how I am passing the pagenum. The reason why I am passing the page number is because when the user finishes with what they need
to do at window.location, I need the user to go back to the grid page that they were at.
To do this, I am doing the loadComplete where I set the value of the page but does not seem to be working.
loadComplete: function (data) {
if ('#TempData["pageNum"]') {
$("#rpList").trigger("reloadGrid",[{page:pagenum}]);
}
Where is the best place of do the trigger reloadGrid at?
It's unclear for me when '#TempData["pageNum"]' will be set, when it will be cleared and whether the code will be hold in the cache of the web browser. If we forget about the questions I have one important remark to your code: if you use .trigger("reloadGrid", ...) inside of loadComplete you should place the call of trigger inside of setTimeout. It will allows to process till the end the current loadiong of the grid before starting the next loading initialized by .trigger("reloadGrid", ...). So the code could be about the following:
loadComplete: function (data) {
...
if (/*some condition*/) {
setTimeout(function () {
$(this).trigger("reloadGrid",[{page: pagenum}]);
}, 50);
}
...
}
Event the usage of 0 instead of 50 is not the same as the usage of .trigger("reloadGrid",...) without setTimeout.

ajax call not responding with $.post

What i am trying to do is to get the value of the selected elements by jquery selection. After that, those value are post to php script via ajax and then retrieve the data from the database and display it on the same page (something called autocompete).
var marvalue=$("input[name=m_status]:checked").val();
var fromhvalue=$("#fromheight").val();
var tohvalue=$("#toheight").val();
var value = $("#edu_det1").val();
alert (value);
var regvalue = $("#religion").val();
alert (regvalue);
var occvalue = $("#occupation").val();
alert (occvalue);
var convalue = $("#country").val();
alert (convalue);
Alert is there to check the correct values. As you see the code above this will get the values from the different input elements.
Below is the code i used to post to php
/*
$.post("regsearch.php", {queryString: ""+value+"",queryString1: ""+marvalue+"",queryStringfage: ""+fage+"",queryStringtage: ""+tage+""+queryStringfromh: ""+fromhvalue+""+queryStringtoh: ""+tohvalue+""+}, function(data) { // Do an AJAX call
$('#suggestions').fadeIn(); // Show the suggestions box
$('#suggestions').html(data); // Fill the suggestions box
});
*/
The problem :
when the comment is removed nor the alert popup and neither the result displayed. Ok about the result as no query is posted.
Major part is that when i use the below code which hold only m_status and edu_det1 it works.
marvalue=$("input[name=m_status]:checked").val();
alert (marvalue);
var value = $("#edu_det1").val();
alert (value);
The post code for above is
$.post("regsearch.php", {
queryString: ""+value+"",
queryString1: ""+marvalue+"",
queryStringfage: ""+fage+"",queryStringtage: ""+tage+""
}, function(data) {
// Do an AJAX call
$('#suggestions').fadeIn(); // Show the suggestions box
$('#suggestions').html(data); // Fill the suggestions box
});
The code for age and it verification is not added here. What is the problem and how to sort this out?
It will be better if you use jquery serialize() function. This will make your life easier to work with forms.
var querstring = $(form).serialize();
above will help
I guess using ajax post jQuery.ajax() will do the same thing and you can even serialize the fields in your page.
http://api.jquery.com/jQuery.ajax/#jQuery-ajax-settings
I have done similar type of code
UserName is the field Which I am passing
var data = $('#Username').serialize();
$('#usernameCheck').empty();
if (!$("form").validate().element("#Username"))
return;
$.ajax({
url: '/SignUp/CheckUsername',
type: 'POST',
data: data,
async: true,
success: function (result) {
if (result == 1) {
$('#usernameCheck').html('<font color=green>Username available</font>');
usernameOK = true;
}
else if (result == 2) {
$('#usernameCheck').html('<font color=red>Username not available</font>');
usernameOK = false;
}
else {
$('#usernameCheck').empty();
usernameOK = false;
}
}
});
First of all you should use your console to see Javascript errors, as I'm sure this will generate some. For example that querystring is undefined.
I'd also console.log instead of alert, it is less annoying and more informative.
Then: you dont need to use f.e. ""+marvalue+"" - just use marvalue. On the other hand f.e. queryString should be quoted...
$.post("regsearch.php", {'queryString':value,'queryString1': marvalue,'queryStringfage':fage,'queryStringtage':tage,'queryStringfromh': fromhvalue,'queryStringtoh':tohvalue}, function(data) {
$('#suggestions').fadeIn();
$('#suggestions').html(data);
});

Resources