Modifying html of dom element that was created after page loaded - javascript

I have two separate AJAX calls. One that gets a list of items from a txt file and creates an HTML table out of them and one that talks to a database to find how much each item costs and then lists this in the corresponding table cell for each item (I know this may sound like a strange approach, but it's a good option in our case...).
The issue is that the price is not getting written to the table since the table is created (or to be precise, the rows of the table are created) after the page loads. I'm not sure how to fix this.
$(document).ready(function() {
makeItemTable();
listPrices();
...
});
function makeItemTable() {
$.ajax({
url: 'products.php',
type: 'GET'
})
.done(function(response) {
$('.price-table > tbody').html(response);
})
}
function listPrices() {
.ajax({
url: 'prices.php',
type: 'GET'
})
.done(function(response) {
priceData = $.parseJSON(response);
$('.price-table tr').each(function() {
var item = $(this).find('td:nth-child(1)').text();
if (priceData[item]) {
var price = priceData[item];
$(this).find('td:nth-child(2)').text(price);
}
})
}

You can try
Using setTimeout to check request to 'products.php' execute callback done (inside callback for request to 'prices.php')
Another way
var jqxhr1 = $.ajax("products.php");
var jqxhr2 = $.ajax("prices.php");
$.when(jqxhr1, jqxhr2).done(function(jqxhr1, jqxhr2) {
// Handle both XHR objects
alert("all complete");
});
Call function listPrices() inside callback request to 'products.php'
Hope to help

Related

Can't get value of <select> element in jQuery

I want to create a web app like google sheets in jQuery, but when I try to get a <select> value with $(select).val() I get `null.
I tried to put the code into $(button).click() and then it worked so I think the problem is that Javascript is executed before HTML, but I am not sure.
$(function() {
$.post("getTablesName.php", function(data) {
$("#tables_SCT").html(data);
});
var name = $("#tables_SCT").val();
$.get("getTable.php", { name: name }, function(data) {
$("#columns").html(data);
});
)};
I just want to get the $("#tables_SCT").val().
You will need to put the var name = $("#tables_SCT").val(); line inside the first AJAX callback. As it stands your code is trying to read content which doesn't yet exist in the DOM as the request which fills the option elements is asynchronous.
You will also need to make the second AJAX call from this point too, for the same reason. Try this:
$(function() {
$.post("getTablesName.php", function(data) {
$("#tables_SCT").html(data);
var name = $("#tables_SCT").val();
$.get("getTable.php", { name: name }, function(data) {
$("#columns").html(data);
});
});
)};

jquery ajax while loop in odd order

I cant understand what I'm doing wrong on this one. I've got a while loop running an AJAX function to get data from a PHP file for the amount of people selected from a dropdown.
$(document).on('change', '#attendingCount', function() {
$(".person-container").html("");
var amount = $(this).val();
var i = 0;
while (i < amount) {
getPerson(i);
i++;
}
});
getPerson(0);
function getPerson(e) {
$.ajax({
type: 'post',
url: './person.php',
data: {
"amount": e
},
success: function(data) {
$(".person-container").append(data);
},
error: function() {
console.log('error');
}
});
}
When the result gets pumped out though, the order of them is completely random.
What is it exactly I'm doing wrong?!
AJAX works in an asynchronous way, not necessarily the first request you send is going to return data first, that's the problem here. Doing an AJAX call in a while loop is not the best solution.

Is using jQuery clever to download multiple template-files?

I want to download and cache multiple mustache-templates and the only real way I know to do this is by downloading them via the jQuery.ajax()-method.
So my straightforward preload-init code looks a little ... ugly!
function getAllTemplatesUglyAndNotPerformant() {
//this is no longer valid, stays just for reference; look at the bottom for the solution
//easy - preload the template and execute it to the data
$.ajax({
url: 'fragments/employee.mustache',
success: function (employeeTpl) {
//uh-oh async process-handling forces me into digging this deeper
$.ajax({
url: 'fragments/employee_day.mustache',
success: function (dayTpl) {
//third level - now i am puzzled already
$.ajax({
url: 'fragments/employee_day_regular.mustache',
success: function (protodayTplRegular) {
//monologue: am i doing this right?
$.ajax({
url: 'fragments/employee_day_deleted.mustache',
success: function (protodayTplDeleted) {
//most probably not
var cachedTemplates = {
employee: employeeTpl,
day: dayTpl,
protoday: {
regular: protodayTplRegular,
deleted: protodayTplDeleted
}
};
//shoot, i also cannot return cachedTemplates, better bury my init-method in this!
init(cachedTemplates);
}
});
}
});
}
});
}
});
}
//initializes downloading and parsing data to what will be seen
function init(cachedTemplates) {
//get the data
$.ajax(
url: '_get_data.php',
success: function (data) {
if (data.success) {
$.each(data.employees, function (iEmployee, vEmployee) {
//this goes through a custom rendering for an employee and his sub-nodes stored in arrays (all rendered in Mustache)
var employee = parseEmployee(vEmployee);
var html_employee = employee.render(cachedTemplates);
$('#data-position').append(html_employee);
});
}
//ignore what may else happen for now
}
)
}
Is there a better way for downloading multiple files for caching in JS?
EDIT:
my rewrite of getAllTemplates() looks now more like this and is finally "more-understandable" and performant for the next one to touch "Peters Legacy":
function getAllTemplates() {
$.when(
$.get('fragments/employee.mustache'),
$.get('fragments/employee_day.mustache'),
$.get('fragments/employee_day_regular.mustache'),
$.get('fragments/employee_day_deleted.mustache')
)
.done(function (employeeTpl, acquisitionTpl, protodayTplRegular, protodayTplDeleted) {
var cachedTemplates = {
employee: employeeTpl[0],
acquisition: acquisitionTpl[0],
protoday: {
regular: protodayTplRegular[0],
deleted: protodayTplDeleted[0]
}
};
init(cachedTemplates);
});
}
You don't specify which version of jQuery you're using, so here's assuming you're using a somewhat current build;
You can use $.when() which is in jQuery 1.5+.
$.when() allows you to bundle (essentially) a bunch of async methods (ajax in this case) and wait until all of them have completed. In your example you are firign one request, waiting for the response and then firing another. With $.when(); if your connection allows it they can all fire simultaneously, saving a lot of time in your example!
something like:
$.when(
$.ajax( "fragments/employee.mustache" ),
$.ajax( "fragments/employee_day.mustache" ),
$.ajax( "..." )
)
.done(function( employeeRes, dayRes ) {
// the first item in array should be the data
var employeeTpl = employeeRes[0];
var dayTpl = dayRes [0];
// ...
});
There's loads of good examples at the jQuery Website

Search on keyup and document ready using Ajax

I am trying to make search function based on Ajax/Jquery.
My web app shows the data of service requests from the database. I want to make searchbar for my app as follows:
show all service request on the table initially.
If something is typed on the searchbar, it searches data and load those data to the table.
Finally if user deletes anyword from searchbar it will show all data as stated on No.1
I managed doing second and third function but I am having issues with the first one.
$(document).ready(function(){
$('#search_text').keyup(function(){
var txt = $(this).val();
if(txt != '') {
$.ajax({
url:"ajax/fetchRequests.php",
method:"post",
data:{search:txt},
dataType:"text",
success:function(data) {
$('#result').html(data);
}
});
}
else if(txt == '') {
$.get("ajax/readRequests.php", {}, function (data, status) {
$("#result").html(data);
});
}
});
});
Here is another script that i have worked on trying:
$(document).ready(function(){
var txt = $('#search_text').val();
if(txt != ''){
$.ajax({
url:"ajax/fetchRequests.php",
method:"post",
data:{search:txt},
dataType:"text",
success:function(data) {
$('#result').html(data);
}
});
}
else if(txt == '') {
$.get("ajax/readRequests.php", {}, function (data, status) {
$("#result").html(data);
});
}
});
All my features are working except for the search functions. Any tips or critics are welcome, thank you very much in advance.
I suggest you do two things, 1) use the suggested .on() and 2) use only one ajax function to simplify things. The idea is to funnel your calls through one function so that you know if something fails, it's not because you messed up the ajax part of the script:
// Create a generic ajax function so you can easily re-use it
function fetchResults($,path,method,data,func)
{
$.ajax({
url: path,
type: method,
data: data,
success:function(response) {
func(response);
}
});
}
// Create a simple function to return your proper path
function getDefaultPath(type)
{
return 'ajax/'+type+'Requests.php';
}
$(document).ready(function(){
// When the document is ready, run the read ajax
fetchResults($, getDefaultPath('read'), 'post', false, function(response) {
$('#result').html(response);
});
// On keyup
$(this).on('keyup','#search_text',function(){
// Get the value either way
var getText = $(this).val();
// If empty, use "read" else use "fetch"
var setPath = (!getText)? 'read' : 'fetch';
// Choose method, though I think post would be better to use in both instances...
var type = (!getText)? 'post' : 'get';
// Run the keyup function, this time with dynamic arguments
fetchResults($, getDefaultPath(setPath), type, { search: getText },function(response) {
$('#result').html(response);
});
});
});
To get initial results hook onto jQuery's document ready event.
var xhr;
var searchTypingTimer;
$(document).ready(function(){
// initial load of results
fetchResults([put your own params here]);
// apply on change event
$('#search_text').on('input', function() {
clearTimeout(typingTimer);
searchTypingTimer = setTimeout(fetchResults, 300);
});
});
function fetchResults($,path,method,data,func)
{
if (xhr && xhr.readyState != 4){
xhr.abort();
}
xhr = $.ajax({
url: path,
type: method,
data: data,
success:function(response) {
func(response);
}
});
}
As Rasclatt mentions you should use jQuery's on method to catch any changes.
Secondly I'd recommend disposing of previous requests when you make new ones, since if you are sending a new one on each character change then for one word many requests will be made. They won't necessarily arrive back in the order you send them. So for example as you type 'search term', the result for 'search ter' may arrive after and replace 'search term'. (welcome to async).
Thirdly since you will send many requests in quick succession I'd only call your fetchResults function after a short time out, so for example if a user types a five character word it doesn't fire until 300ms after the last character is typed. This will prevent 4 unnecessary requests that would just be ignored but put strain on your backend.

Appending item to list with Ajax after post - layout related

I have an activity stream for both users use, and site-wide view. Currently when a user posts an update, I have it displaying a default bootstrap success alert. I have seen other websites append the new post to the list by sliding down the existing items, and appending the newest post to the top of the list.
I am attempting to do just that, but I am not sure how to add it with all the proper styling. (code below). I am tried adding all the <div> tags that make up one activity item in my feed, but without success.
TL;DR - Is there a way to have ajax look at the current top activity item, clone it, and append it to the top? It would make the code more dynamic for my use, and avoid having to place CSS inside the .js file.
jQuery(document).ready(function ($) {
$('form#postActivity').submit(function (event) {
event.preventDefault();
$postActivityNow = (this);
var subject = $('#activity_subject').val();
var message = $('#activity_content').val();
var data = {
'action': 'postAnActivity',
'subject': subject,
'message': message,
}
$.ajax({
type: 'post',
url: postAnActivityAjax.ajaxurl,
data: data,
error: function (response, status) {
alert(response);
},
success: function (response) {
if (response.success) {
bootstrap_alert.success('Activity Added');
} else {
if (response.data.loggedIn == false) {
bootstrap_alert.warning('you are NOT logged in');
console.log('you are not logged in')
}
if (response.data.userExists == false) {
console.log(response);
bootstrap_alert.warning(response.data.alertMsg);
console.log(response.data.alertMsg)
}
}
}
});
});
});
you can also use .prependTo()
var newActivity = $( ".activity" ).first().clone();
newActivity.prependTo( ".parentDiv").hide().slideDown();
FIDDLE
To clone an element: jQuery.clone()
var newItem = $("#myDiv").clone();
To append it as first child: jQuery.prepend()
$("#parentDiv").prepend( newItem );
Regards,
hotzu
I have already done in the past using $.prepend()
Check this url for more information jquery append to front/top of list

Categories

Resources