How to refactor this repetitive jquery ajax pattern? - javascript

I received this complicated jquery based ajax structure.
$.ajax({
url: ("example/example.php"),
type: "post",
data: {
data1 = datafromphp_1;
data2 = datafromphp_2;
}
dataType: "json",
},
success: function (datafromphp_2){
return function(datafromphp_2){
$.ajax({
// Same structure as outer structure
success: function (){
$.ajax({
// same structure as outer structure. The structure is recursively repeating.
success: function(){
// The structure is recursively repeating..
// Some complicated embedded html strings with jquery.
// Each ajax makes cells dynamically. Further inner ajax codes make smaller cells in each cells made by outer ajax codes.
}
});
}
});
};
}(datafromphp_2)
});
What customers should see on browsers like this.
And each cells have to be generated by dynamically. If there is no data on server, browser have to show nothing. To generate cells dynamically, jquery codes are implemented like this.
$("<label>").text("this is label example),$(input type = 'text' name='cell0' style = blablabla...), ("other html codes to decorate cell"), ... , ...
So even CSS, php, html and javascript(.js) files are divided, javascript files are too big and It seems like other html codes! Extremely, one js file for implementing this view has 20 times of tabs and nested block structure.
Is there any way to simplify these structure? I can't find the proper solutions to refactor this.

Related

Best strategy when filling HTML page via javascript and ajax

I have this HTML page that is filled via javascript with multiple ajax calls. I have this dictionary that is filled with some JSON text grabbed via ajax calls like in this example: (The actual code is over 1k lines)
var dict = {}
$.ajax({async: false, type: 'GET', url: '/page/1', success: function(data)
{
dict = JSON.parse(data);
// {'name': 'foo', 'image': '42', 'user': 'bar_user'}
$.ajax({async: false, type: 'GET', url: '/image/'+dict.image,
success: function(data)
{
dict.image = JSON.parse(data);
// {'low_res': 'l.jpg', 'high_res': 'h.jpg'}
}
$.ajax({async: false, type: 'GET', url: '/user/'+dict.user,
success: function(data)
{
dict.user = JSON.parse(data);
// {'email': 'bar#bar.com', 'image': '69'}
$.ajax({async: false, type: 'GET', url: '/image/'+dict.user.image,
success: function(data)
{
dict.user.image = JSON.parse(data);
// {'low_res': 'l_2.jpg', 'high_res': 'h_2.jpg'}
}
}
}
This dictionary is used to fill the page using some functions like so:
function fillImageDiv(img)
{
$('div#image_container > img').attr('src',img.high_res)
}
function fillUserDiv(user)
{
$('div#user_container > span').html(user.email);
$('div#user_container > img').attr('src', user.image.low_res);
}
fillImageDiv(dict.image);
fillUserDiv(dict.user);
Having this in mind, what would be the best way to fill the page?
Would it be better to fill the whole dictionary and then fill the divs, or to fill each div as soon as the JSON was loaded into the dictionary?
Making the ajax calls asynchronous would make the dict fill faster, even when there is no multi-threading in javascript?
What about calling fillImageDiv and fillUserDiv asynchronously?
Thank you!
In terms of performance, it would be best if you could just make one AJAX call to fill up your dictionary, and then fill in your <div> elements all in one go. Those synchronous AJAX calls are going to hurt the responsiveness of your site more than anything else.
If you can't combine the AJAX calls, and your site won't have its interface affected by not having each of the separate components (image and user) together, then it would definitely be better to have them separately updated asynchronously.
If you do need to have both of them together, then you can use an asynchronous control flow library such as caolan's async.js to more elegantly manage your parallel AJAX calls, and then update the DOM element in one go once the results are available.
In general, when you're talking about web and JavaScript performance, do the following things in order:
Minimize HTTP requests
Make your AJAX results cacheable
Minimize access to the DOM
The HTTP requests will generally be the bottleneck, and DOM manipulation right after that.

How to load new content to DIV without refreshing [duplicate]

This question already has answers here:
how to reload DIV content without refreshing whole page
(8 answers)
Closed 9 years ago.
I want to load new content from the server to the DIV without refreshing the whole page.
I tried the following
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData +"&relationship="+ forData +"#",
success: function (response) {
$("#testDIV").html(response);
}
});
But the problem is the whole page is loading in <DIV id="testDIV">. I want to replace the old DIV with New DIV content returned from the server not with the whole page.
You can keep your same process sense you are interested in using AJAX directly and want to manage your done function (instead of success because .done() will replace it). Here is how...
.done(function(data) {
...
}
Inside of that done function, you can filter the page content to what you want. Simply request what you want to filter with jquery like this...
var $response = $(data);
var response_title = $response.filter(".title").html(); //I'm assuming you are trying to pull just the title (perhaps an < h1 > tag, in this little example, from the entire external page!
THEN!...
$("#testDIV").html(response_title);
With the done function, based on jQuery's API, you can use this format...
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
So your final code may look something like this...
$.ajax({
type: "GET",
url: "ht.tp://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+ occasionData +"&relationship="+ forData +"#"})
.done(function(response) {
var $response = $(response);
var response_title = $response.filter(".title").html();
$("#testDIV").html(response_title);
});
I like the answer by blackhawk. It uses the existing code with slight modification.
I would just condense it to a one line change like this:
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData+"&relationship="+ forData +"#",
success: function (response) {
$("testDIV").html($(data).filter(".title").html());
}
});
The code you are displaying is actually correct.
The problem comes from what your server is providing.
What you are doing here is GETing a whole page via an AJAX call, and replacing the content of One div with that whole page.
Your server should not render the whole page for that call, but only the content of the div you wish to replace. If you are using framework like rails or symfony, they often provide an easy way to detect if the query is a normal GET request, or an AJAX call.
Basically you have 4 strategies at your disposal :
Make the requests to a specific endpoint that is used only for the ajax call and that returns the content of the div you wish to replace. And not the whole page.
Make the request to the same page, and detect if the request is a normal HTTP request or an AJAX call. Based on that, return the whole page or just the content of the div. You'll probably have to look for the helpers in your framework / toolbox documentation.
Make the AJAX request but ask for a JSON object. Transform your JSON in HTML on the client side to replace the content of the div. This is the "my app is just an API" approach. This is my personal favorite as this JSON endpoint can be used for other purposes (eg: a mobile app) since it carries only content, and not presentation. This also tends to be the fastest way in terms of performance since a significant part of the computation is done on the client side. On the con side, this requires you to write more JS.
Always render the whole page, and filter only what you need on the client side. This is balchawk approach. Benefit is that you don't have to modify your server, but you will waste processing time and bandwidth by returning a whole page, when only a subset is necessary.
$(function(){
$('.classloader.').on('click', function(e){
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData +"&relationship="+ forData +"#",
beforeSend: function() {
$("#testDIV").hide();
$('div#loading').show();
},
success: function(html){
$("#testDIV").html($(html).filter("#mainContent").html()).show();
$('div#loading').hide();
}
});
return false;
});
})

jQuery AJAX : How to query an returned HTML document

My question is as follows: I have started using the $.ajax function with jQuery and I am wondering how I work with the return of an HTML page. The request completes and I can console.log the returned HTML page however I would now like to select a single element from that page. I have had several attempts which included:
$(data).find('p');
$('button').click(function() {
$.ajax(funciton() {
dataType: 'html',.
url: 'localhost/sw',
success: function(data) {
// This is where I would like to select a element or node from the complete
// returned html document
});
});
I know i can simply use .load() which you can provide select criteria but .ajax is the root function to begin with and I would like to learn that way as well for more complicated queries. Second half of this would be should I not be trying to select elements this way and just serve up json or a single key phrase instead of the entire html page? All help is appreciated.
Just pass the returned HTML to jQuery, and treat it like a regular jQuery collection:
$.ajax({
dataType: 'html',.
url: 'localhost/sw',
success: function (html) {
var paragraphs = $(html).find('p');
// Manipulate `paragraphs` however you like. For example:
$(document.body).append( paragraphs );
}
});
Joseph's answer above is correct if you just want to get the objects.But if you want to load the content of that element, you may change this:
var paragraphs = $(html).find('p');
to
var paragraphs = $(html).find('p').html();
Hope it helps.

Enumerating through Yahoo Pipes generated JSON with jQuery fails

I'm trying to lessen manual update work by using Yahoo Pipes and jQuery to update a table with upcoming events from a different domain. I have created this Pipe to gather the data, and it seems to work.
Now I am reading the JSON file with the following jQuery Script taken from this tutorial:
$.ajax({
type: "GET",
url: "http://pipes.yahoo.com/pipes/pipe.run?_id=57aa32bf3481c8dca0c07afcf9b9dc29&_render=json",
async: false,
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/j-son;charset=UTF-8");
}
},
dataType: "json",
success: function(data){
$('body').append(data.query.results.a.content);
}
});
The jQuery append failes, I guess because 'data.query.results.a.content' does not relate well to the JSON structure created by the pipe.
I've tried altering both the pipe and the append in several ways and am just short of giving up, I'd be very grateful for your Input.
Think you are parsing the json result incorrectly.
On viewing the json object here http://jsonviewer.stack.hu/
You will observe content node for each item is at value.items[0].a.content
i.e. try something like this :
$('body').append(data.value.items[0].a.content);
You will need to iterate the items array like this
$.each(data.value.items, function(index,element) {
$('body').append(element.a.content);
});
Try it on fiddle : http://jsfiddle.net/EFvJf/

javascript async woes

This is a newbie JavaScript question, but something I'm not quite sure how to google for help because I'm not sure how to describe the problem in an easy way.
I have a large, somewhat complex JSON that I need to manipulate so that I could reshape the JSON in a way that I get a list of only countries, cities, and sales.
The JSON itself isn't the issue for me, it's what I would like to do with it once I've received it. Basically, I'd like to create 3 separate objects/arrays from a large received JSON and have those 3 separate objects/arrays accessible for usage OUTSIDE of the $.ajax call. Yes, I think I could do all of this inside of the $.ajax success callback, but I'd rather have all the JSON processing done elsewhere. My pseudo JavaScript looks something like this:
var model = {
countries: [],
cities: [],
sales: [],
set: function(data) {
//manipulate data here so that model.countries, model.cities, model.sales are populated
}
};
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data); //is this the right way to do this?
}
});
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
But because JavaScript executes asynchronously, the last 3 lines are always blank because the JSON hasn't been received yet.
So I guess my question is, how do I bind the results of my received JSON to a variable outside of the $.ajax scope so that I could use it wherever on the page?
The simple solution is this:
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data);
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
}
});
If you want something more frameworky, then you could look at a something like Backbone.js.
Populate your HTML (i.e. update your view) in the AJAX success callback. i.e.
function updateView() {
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
}
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data); //is this the right way to do this?
updateView();
}
});
Just put those 3 line in the success callback (you can also separate it into a function) and skip the model population.
There are frameworks that allow you to bind DOM elements to JS objects and their data, bu in this case it might be an overkill.

Categories

Resources