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
Related
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.
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.
I have an issue, do not know if it possible or not, how to check if my container is already loaded or not, because sometimes it is being loaded faster, sometimes slower and if it does not succeed in time getting an error in javaScript where gridview some functions are not recognizable(because the gridview is not loaded fast enough). Hope it is clear. Thanks for Your time.
Code:
function LoadPartial(partialUrl, container) {
$.ajax({
type: 'POST',
url: partialUrl,
success: function (returnData) {
$(container).html(returnData);
}
});
//.done(function () {
// return;
//});
}
you can use something like this.
$(".container").load(function (){
alert("Loaded :)");
});
Let me know in-case this doesn't work.
You can try using .data()
if ($('#mycontainer').data('loaded')) {
// your code
}
If you mean to find event when data received use "complete" function:
$.ajax({
type: 'POST',
url: partialUrl,
success: function (returnData) {
$(container).html(returnData);
},
complete: function() {
console.log('container filled with data');
}
});
I've played around with creating my own jquery functions, this done via the
$.fn.extend({
myFunc: function () {
}
});
However, after scouring the web and SO for an answer, I would like to ask:
How can I extend $.ajax()
The new implementation of $.ajax can be used by running
$.ajax({
}).done(function (e) {
}).fail(function (e) {
});
What I would like to do is to add a .progress() so that I don't always have to write
$.ajax({
url: path,
xhrFields: {
onprogress: function (e) {
if (e.lengthComputable) {
console.log(e.loaded /e.total * 100 + '%');
}
}
}
});
each time I want to monitor the progress. e.g.
$.ajax({
url: '/somewhereorother',
type: 'post',
dataType: 'json'
}).progress(function (e) {
updateProgressBar(e.percentage + '%');
}).done(function (e) {
}).fail(function (e) {
});
$.ajax is a function attached to $ object.
As such, to extend it you would have to store the reference to it somewhere, and call it when needed, something like:
var ajax = $.ajax;
$.ajax = function()
{
if (!arguments[0].success)
arguments[0].success = function()
{
window.alert('done!');
}
ajax.apply(ajax, arguments);
}
This is a concept (I'm not sure of this scope in apply - would have to actually run it) ;) Also, I'd say it's ugly as hell way of doing things.
If you want your $.ajax function to differ from official function, I'd still separate it. Either via $.my_ajax or by separate namespace (take a look at http://api.jquery.com/jquery.sub/)
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