I am using Slick JS to create a slider, adding slides to it using AJAX and the slickAdd method as follows:
$.getJSON(url, function(r) {
$.each(r, function(i, article) {
var html = 'HTML string created with data and ' + article.variables + ' from JSON';
$('.element').slick('slickAdd', html);
}
}
This AJAX works and the slides are successfully added to the slider after the browser has all the XHR data.
The fact that it's a Slick JS slider is simply context; I believe the question is more generic than that.
Main Question: Can I force the each loop to output the 'html' while the XHR data is still being loaded by AJAX, thus giving the user the experience of a more performant site as slides are added to the DOM as quickly as possible? If yes, how?
While the funciton is looping through the 'each', I can see discrete XHR data for each item returned, and I ideally wanted to start adding to the DOM (with a delay) before all the iterations are complete.
The site is primarily PHP, so if there isn't really a "clean" way to handle this in JS / jQuery on the front-end, I can do something server side with PHP ob_flush, but just wanted to beg some JS masters (opinionated) suggestions/criticisms first.
I don't necessarilly need a full code example, just a high-level explanation - I am just a bit noob with JS.
Many thanks ;P
TL:DR; Not with a single request.
If you were to use the underlying XMLHttpRequest object to perform the AJAX request you would be able to get updates as the data is coming back from the server and potentially perform updates while the data is being loaded.
However, the obvious problem with doing this, is that the JSON won't be valid until it has been completely loaded. Although you could parse it manually, it's unlikely to be worth the effort to do so.
The only work-around to do what you want would be to send separate requests for each block of data and process them separately.
Related
I have a website that loads mostly using AJAX calls. The javascript and CSS files are only loaded once when the page first loads.
My issue is that the javascript/CSS can get out of sync with the HTML and server-side code. The page can be using an old versions of the javascript file (from when the page first loaded) while the server-side code and ajax-loaded HTML files always use the latest code and files.
What are some strategies for dealing with this?
I have considered polling the server at set intervals and asking if there is a newer version of the JS. Then, if there is, reloading the page. But, it seems that this can get ugly, with the page suddenly reloading at awkward moments instead of, for example, as the result of a user-initiated call.
Also, there are some changes to the javascript that do not necessarily require that a page be reloaded. For example, the changes might affect a different page/module than the one that the user is on.
Re-loading the javascript with every Ajax call is not viable
I can imagine ugly solutions to this, but thought I'd ask first.
EDIT (in response to comments and suggested answers)
The only way to get the JS back into sync is to reload the page, which then loads the new JS. Adding new JS to an old page won't work as it doesn't get rid of any old functions, listeners, etc. I'm not asking how to reload a page or how to load javascript. I'm asking for a strategy of knowing WHEN to do it, especially in a way that does not seem awkward to the user. Do people incorporate polling to ask if there is a new JS version? Do they then suddenly (from the user's point of view) reload the page? Do they poll even when the tab is hidden? Is this a problem for the server? Where do they keep track of the latest required JS version? Or, do they ask with every AJAX request - hey, should I reload? Did they write a special function for that? Do they keep all new html/server code backwards compatible with the js?
Someone who has dealt with this, how do you do it?
Two possible solutions include
calling $.getScript() to retrieve, update variables at document from at server-side to match variables at document before calling $.ajax(/* settings */) ;
alternatively could use web workers to update original document variables to match server-side variables at beforeSend of $.ajax(/* settings */)
At result of first step of either approach, abort $.ajax() call, call error handlers, notify user, send message to server about error.
var head = document.getElementsByTagName("head")[0],
scripts = {};
function load_script(name){
var myscript = document.createElement('script');
myscript.setAttribute("type","text/javascript");
myscript.setAttribute("src", name);
if (scripts[name]) head.replaceChild(myscript, scripts[name]);
else head.appendChild(myscript);
scripts[name] = myscript;
}
// the first call to load the script code
// and then call if you decide to upgrade a newer version
load_script('js1.js');
load_script('js2.js');
today when I exploring Google API, I saw in their sample code, they simply request a url by doing
<script src="src="https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1.."></script>
Sad for me, my first thought before seeing this was ajax. Now I'm confused, the different with this 2. I can't do request as above as I need to add users' input within it.
like
"https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1&"'+user+'"
so if I use ajax, will achieve the same? sorry that I haven't try, but I'm still in confusion what's the diff btw them even I try.
Using <script src> to retrieve JSON data is a technique called JSONP. It gets around cross-site scripting limitations (your browser may block an AJAX request if it's to a different domain than the page it comes from; it won't block a script load that way). The disadvantage is that you can't do other HTTP methods (PUT, POST, DELETE, etc) - only GET. Also, as #FelixKing pointed out, the server has to support it - if you just drop a JSON blob as the contents of <script> element, that's not going to do you any good - it has to be sent to a callback. If the API supports JSONP, it will usually take a callback=functionName parameter, and the emitted script will be functionName({... JSON blob here ...}).
You can still make it dynamic to add things like your user parameter, however. You just need to use Javascript to add the <script> element to the page, instead of hard-coding it into the HTML:
var user = "someone";
var scriptTag = document.createElement('script');
scriptTag.src =
"https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1&user="+user
document.getElementsByTagName('html')[0].appendChild(scriptTag);
But I don't know what you're doing exactly, or if that call even supports JSONP; that's just an example of using Javascript to dynamically add a <script> element. Details are up to you.
Ajax will acchieve the same if you do something like this:
$.get("https://www.googleapis.com/customsearch/v1?key=AIzaSyCVAXiUzRYsML1Pv6RwSG1&"+user, function(response) {
// process the result here
});
As additional note: the "<script src=https://www.googleapis..." thing is a method used by ajax implementation if other methods fails (XMLHttpRequest, for example), so, you can (should) relay on ajax a let the library do what is better for your context (this is good for cross-browser support)
Currently I am creating a website which is completely JS driven. I don't use any HTML pages at all (except index page). Every query returns JSON and then I generate HTML inside JavaScript and insert into the DOM. Are there any disadvantages of doing this instead of creating HTML file with layout structure, then loading this file into the DOM and changing elements with new data from JSON?
EDIT:
All of my pages are loaded with AJAX calls. But I have a structure like this:
<nav></nav>
<div id="content"></div>
<footer></footer>
Basically, I never change nav or footer elements, they are only loaded once, when loading index.html file. Then on every page click I send an AJAX call to the server, it returns data in JSON and I generate HTML code with jQuery and insert like this $('#content').html(content);
Creating separate HTML files, and then for example using $('#someID').html(newContent) to change every element with JSON data, will use even more code and I will need 1 more request to server to load this file, so I thought I could just generate it in browser.
EDIT2:
SEO is not very important, because my website requires logging in so I will create all meta tags in index.html file.
In general, it's a nice way of doing things. I assume that you're updating the page with AJAX each time (although you didn't say that).
There are some things to look out for. If you always have the same URL, then your users can't come back to the same page. And they can't send links to their friends. To deal with this, you can use history.pushState() to update the URL without reloading the page.
Also, if you're sending more than one request per page and you don't have an HTML structure waiting for them, you may get them back in a different order each time. It's not a problem, just something to be aware of.
Returning HTML from the AJAX is a bad idea. It means that when you want to change the layout of the page, you need to edit all of your files. If you're returning JSON, it's much easier to make changes in one place.
One thing that definitly matters :
How long will it take you to develop a new system that will send data as JSON + code the JS required to inject it as HTML into the page ?
How long will it take to just return HTML ? And how long if you can re-use some of your already existing server-side code ?
and check how much is the server side interrection of your pages...
also some advantages of creating pure HTML :
1) It's simple markup, and often just as compact or actually more compact than JSON.
2) It's less error prone cause all you're getting is markup, and no code.
3) It will be faster to program in most cases cause you won't have to write code separately for the client end.
4) The HTML is the content, the JavaScript is the behavior. You're mixing both for absolutely no compelling reason.
in javascript or nay other scripting language .. if you encountered a problem in between the rest of the code will not work
and also it is easier to debug in pure html pages
my opinion ... use scriptiong code wherever necessary .. rest of the code you can do in html ...
it will save the triptime of going to server then fetch the data and then displaying it again.
Keep point No. 4 in your mind while coding.
I think that you can consider 3 methods:
Sending only JSON to the client and rendering according to a template (i.e.
handlerbar.js)
Creating the pages from the server-side, usually faster rendering also you can cache the page.
Or a mixture of this would be to generate partial views from the server and sending them to the client, for example it's like having a handlebar template on the client and applying the data from the JSON, but only having the same template on the server-side and rendering it on the server and sending it to the client in the final format, on the client you can just replace the partial views.
Also some things to think about determined by the use case of the applicaton, is that if you are targeting SEO you should consider ColBeseder advice, of if you are targeting mobile users, probably you would better go with the JSON only response, as this is a more lightweight response.
EDIT:
According to what you said you are creating a single page application, if this is correct, then probably you can go with either the JSON or a partial views like AngularJS has. But if your server-side logic is written to handle only JSON response, then probably you could better use a template engine on the client like handlerbar.js, underscore, or jquery templates, and you can define reusable portions of your HTML and apply to it the data from the JSON.
If you cared about SEO you'd want the HTML there at page load, which is closer to your second strategy than your first.
Update May 2014: Google claims to be getting better at executing Javascript: http://googlewebmastercentral.blogspot.com/2014/05/understanding-web-pages-better.html Still unclear what works and what does not.
Further updates probably belong here: Do Google or other search engines execute JavaScript?
I consistently come across this code smell where I am duplicating markup, and I'm not really sure how to fix it. Here's a typical use case scenario:
Let's say we'd like to post comments to some kind of article. Underneath the article, we see a bunch of comments. These are added with the original page request and are generated by the templating engine (Freemarker in my case, but it can be PHP or whatever).
Now, whenever a user adds a comment, we want to create a new li element and inject it in the current page's list of comments. Let's say this li contains a bunch of stuff like:
The user's avatar
Their name
A link to click to their profile or send them a private message
The text they wrote
The date they wrote the comment
Some "edit" and "delete" links/buttons if the currently logged in user has permission to do these actions.
Now, all of these things were already written in our template that originally generated the page... so now we have to duplicate it inside of Javascript!
Sure, we can use another templating language - like Jquery's Template plugin - to ease the pain generating and appending this new li block... but we still end up with duplicate html markup that is slightly different because we can't use macros or other conveniences provided to us by the templating language.
So how do we refactor out the duplication? Is it even possible, or do we just put up with it? What are the best practices being used to solve this problem?
This is a common problem and becomes more obvious as the UI complexity increases, and changes have to be done on both the server and client templates. This problem is fixable by using a the same template markup on both the client and server sides. The template processors must be written in both JavaScript and the server side language.
Two other solutions that are cleaner than the above approach, but both have their own problems:
Do everything client side
Do everything server side
If all markup generation is done on the client side, then the server acts more or less like a web service which only sends back data in whatever formats suits the application. JSON, and XML are really popular formats for most web services nowadays. The client always generates the necessary HTML and JS. If going with this approach, the boundary between the client and server must be well defined. Since the client has limited knowledge of what happens on the server, this means that proper error codes must be defined. State management will become harder since most/all server interaction will be happening asynchronously. An example of adding a comment with this approach may look like:
$('#add-comment').click(function() {
var comment = $('#comment-box').text();
$.ajax('http://example.com/add', {
success: function() {
addCommentRow(comment);
},
...
});
});
function addCommentRow(comment) {
var user = currentUser().name;
var html = "<li><b>{user}</b> says {comment}</li>";
html = html.replace("{user}", user).replace("{comment}", comment);
var item = $('<li>').html(html);
$('#comments').append(item);
}
The other approach is to do everything server side. Whenever a change happens, shoot a request to the server, and ask it for the updated view. With a fast backend, response times under a second, and proper indicators of network activity, the application should seem very responsive despite everything happening on the server. The above example would be simplified to:
$('#add-comment').click(function() {
$.ajax('http://example.com/add', {
success: function(response) {
$('#comments').html(response);
},
...
});
});
Although this seems a lot more cleaner on the client side than the previous approach, we have just moved the markup generation up to the server. However, if the application is not very AJAXy like Google Maps, then this approach may be easier to work with. Again, it's a matter of how complicated the application is, and perhaps maintaining state client side is a necessity for you, in which case you may want to go with the previous approach.
if im loading data for the markers from a database do i write the output queried from the db into a javascript file or is there a cleaner way of doing it?
thanks
Yeah, writing to a file is a good way to do it. Just write the data as JSON. Your file would look like:
var map = {waypoints:[...]};
And then you can do:
for(var i=o; i<map.waypoints.length; ++i) {
addWaypoint(map.waypoints[i]);
}
I actually do some static caching of nodes using this method: http://www.trailbehind.com/site_media/javascript/gen/national-parks.js
We use that set of National Parks a lot, so we cache it. But we also have urls where you can fetch JSON for a node on the fly, such as: http://www.trailbehind.com/map/node/7538973/632/735/
This URL gets the map for node 7538973, and specifies the dimensions of their map in pixels as well.
The needed Javascript can of course be wrapped in whatever language you prefer to use, see e.g. pymaps for a Python example. While pymaps is actualally inserting the JS code into an HTML template, if you're writing a web app you can perfectly well choose to serve that JS code on the fly at an appropriate URL and use that URL in a <script> tag in your pages.
Depending on the size of your application, you may want to consider printing out plain javascript.
I have a map that uses server-side clustering, so markers update frequently. I found that parsing JSON markers slowed the app significantly, and simply wasn't necessary.
If speed is an issue, I'd suggesting removing all of the unnecessary layers possible (JSON, AJAX, etc.). If it's not, you'll be just fine with JSON, which is cleaner.
I agree with Andrew's answer (+1).
I guess the only point I would add is that rather than including some server side generated JavaScript, you could use an AJAX request to grab that data. Something like:
var request = new Request.JSON (url: 'get_some_json.php',
onSuccess: function(data) {
// do stuff with the data
}).get ();
(This is a Mootools AJAX thing, but you could use any kind of AJAX request object).
Edit: ChrisB makes a good point about the performance of parsing JSON responses and re-reading my answer I certainly didn't make myself clear. I think AJAX requests are suitable for re-requesting data based on parameters generated by user interaction. I guess an example use case might be, a user filtering the data displayed on the map. You might grab the filtered data via an AJAX/SJON request rather than re-loading the page.