I'm making a blog that takes markdown syntax. I would like to be able to provide an updated preview on every keystroke, just like Stackoverflow does when asking and answering questions. My current solution is incredibly laggy.
How does Stackoverflow implement their solution to provide an updated preview of markdown text without causing lag?
Currently, I make an AJAX call to the server on every keystroke in the post-content text area. The server sanitizes the content and returns HTML. The preview div is then updated with the new HTML:
$('#post-content').bind('input propertychange', (function() {
var content = {"content": this.value};
$.ajax({
...
success: function(data) {
$('#preview').html(data['content']);
}
...
});
}));
This isn't working well. If I type at full speed, the text area ends up missing about 1/3 of my characters. My server is a tiny 500MB RAM VM. I'm not sure if the server is bottle neck, but I don't understand why the textarea would be lagging because of a slow AJAX call - it seems to me that this line is the bottle neck:
$('#preview').html(data['content']);
But I don't know enough about front end development to speculate on this.
How does StackOverflow provide a preview of markdown text, without causing lag?
They store the text locally on your client browser, there is no server or database round-trip
This can be verified by inspecting the code
Don't send an AJAX call at every keystroke to the server! Make the preview use something client-side and only use the server when you submit the post/comment.
Creating the AJAX call is what is causing your lag. I haven't exactly looked but I can promise you that StackOverflow is not making a server call each time to validate and give you a preview of the markdown. They are just using Javascript to do it instead.
Stack Overflow renders the preview client-side, which is why some of the tags aren't sanitized. AJAX calls (especially lots of them) are not neccesary, because most computers can do it just as easily without the server's help.
If you notice, syntax highlighting is not triggered for a few seconds, because it is inefficient to do that every time a character is typed.
Currently, I make an AJAX call to the server on every keystroke
I will not paraphrase other answers and comments that have said it was a bad strategy. That said, if you cannot move your rendering to the client side and if you are ready to lower your expectations in term of speed you can use this solution (mentioned by user1106925 in comments):
define a timer of, say, 300ms
each keystroke resets the timer
when the timer does timeout, make the AJAX call to the server
That should drastically reduce the number of AJAX call. The user do not have to press a "render" button (he only has to stop typing) so it does modify your current UI.
This is the strategy that is used by Compiler Explorer (though not with markdown).
I have a main view function for my application. After logging in successfully this main view method is called and is expected to render the template.
But I have to perform some calculations in this view method [I am checking certain conditions about the user by making facebook graph api request.]
Thus it takes 2~4 seconds to load.
How do I show this loading scene since the template is rendered by return statement and thus is executed only when the process is complete.
Should I make 2 views , one for showing loading and the other one for calculating and keep making AJAX request to other view method to check if the process is complete or not ?
You should indeed make two views, one to only return the page showing the loading UI and one to perform the long task.
The second view will be called using an AJAX request made from the "loading" page. The response from the AJAX request will notify your "loading" page that it is time to move on.
You need to make sure the AJAX request's duration won't exceed the timeout of your server (with ~10 seconds, you should be fine).
You need to run your Graph API requests in a task executed asynchronously, allowing you to return a HttpResponse without waiting for the task to finish.
Celery will allow you to do just that.
You then need a way to notify your client that the asynchronous task has finished.
I see two ways to do that:
Making AJAX requests at regular intervals to a view that will check if the task is finished.
Using WebSockets.
The first approach is the simplest but has the drawback of making a lot of useless requests and of being less reactive.
Using WebSockets on the other side will require more configuration as an external app is required (ex: django-socketio or swampdragon).
If it is the only place where you need notifications from server to client, using WebSockets seems to be overkill.
I am working on a pure HTML website, all pages are HTML with no relation to any server side code.
Basically every request to the server is made using AJAX, I send data from forms, I process this data in Handlers, then I return a JSON string that will be processed back on the client side.
Let's say the page is loaded with parameters in the URL, something like question.html?id=1. Earlier, I used to read this query string on Page Load method, then read data from the database and so on...
Now, since its pure HTML pages, I'm trying to think of an approach that will allow me to do the same, I have an idea but its 99% a bad idea.
The idea is to read URL parameters using JS (after the page has loaded), and then make an AJAX request, and then fetch the data and show them on the page. I know that instead of having 1 request to the server (Web Forms), we are now having 2 Requests, the first request to get the page, and the second request is the AJAX request. And of course this has lots of delays, since the page will be loaded at the beginning without the actual data that I need inside it.
Is my goal impossible or there's a mature approach out there?
Is my goal impossible or there's a mature approach out there?
Lately there are a good handful of JavaScript frameworks designed around this very concept ("single page app") of having a page load up without any data pre-loaded in it, and accessing all of the data over AJAX. Some examples of such frameworks are AngularJS, Backbone.js, Ember.js, and Knockout. So no, this is not at all impossible. I recommend learning about these frameworks and others to find one that seems right for the site you are making.
The idea is to read URL parameters using JS (after the page has loaded), and then make an AJAX request, and then fetch the data and show them on the page.
This sounds like a fine idea.
Here is an example of how you can use JavaScript to extract the query parameters from the current page's URL.
I know that instead of having 1 request to the server (Web Forms), we are now having 2 Requests, the first request to get the page, and the second request is the AJAX request. And of course this has lots of delays, since the page will be loaded at the beginning without the actual data that I need inside it.
Here is why you should not worry about this:
A user's browser will generally cache the HTML file and associated JavaScript files, so the second time they visit your site, the browser will send requests to check whether the files have been modified. If not, the server will send back a short message simply saying that they have not been modified and the files will not need to be transmitted again.
The AJAX response will only contain the data that the page needs and none of the markup. So retrieving a page generated on the server would involve more data transfer than an approach that combines a cacheable .html file and an AJAX request.
So the total load time should be less even if you make two requests instead of one. If you are concerned that the user will see a page with no content while the AJAX data is loading, you can (a) have the page be completely blank while the data is loading (as long as it's not too slow, this should not be a problem), or (b) Throw up a splash screen to tell the user that the page is loading. Again, users should generally not have a problem with a small amount of load time at the beginning if the page is speedy after that.
I think you are overthinking it. I'd bet that the combined two calls that you are worried about are going to run in roughly the same amount of time as the single webforms page_load would if you coded otherwise - only difference now being that the initial page load is going to be really fast (because you are only loading a lightweight, html/css/images page with no slowdown for running any server code.
Common solution would be to then have a 'spinner' or some sort (an animated GIF) that gives the user an visual indication that the page isn't done loading while your ajax calls wait to complete.
Watch a typical page load done from almost any major website in any language, you are going to see many, many requests that make up a single page being loaded, wether it be pulling css/images from a CDN, js from a CDN, loading google analytics, advertisements from ad networks etc. Trying to get 100% of your page to load in a single call is not really a goal you should be worried about.
I don't think the 2-requests is a "bad idea" at all. In fact there is no other solution if you want to use only static HTML + AJAX (that is the moderm approach to web development since this allow to reuse AJAX request for other non-HTML clients like Android or iOS native apps). Also performance is very relative. If your client can cache the first static HTML it will be much faster compared to server-generated approach even if two requests are needed. Just use a network profiler to convince yourself.
What you can do if you don't want the user to notice any lag in the GUI is to use a generic script that shows a popup hiding/blocking all the full window (maybe with a "please wait") until the second request with the AJAX is received and a "data-received" (or similar) event is triggered in the AJAX callback.
EDIT:
I think that probably what you need is to convert your website into a webapp using a manifest to list "cacheable" static content. Then query your server only for dynamic (AJAX) data:
http://diveintohtml5.info/offline.html
(IE 10+ also support Webapp manifests)
Moderm browsers will read the manifest to know whether they need to reload static content or not. Using a webapp manifest will also allow to integrate your web site within the OS. For example, on Android it will be listed in the recent-task list (otherwise only your browser, not your app is shown) and the user can add a shorcut to the desktop.
So, you have static HTMLs and user server side code only in handlers? Why you can't have one ASP .Net page (generated on server side) to load initial data and all other data will be processed using AJAX requests?
if its possible to use any backed logic to determine what to load on server side, that will be easy to get the data.
say for example if you to load json a int he page cc.php by calling the page cc.php?json=a, you can determine from the PHP code to put a json into the page it self and use as object in your HTML page
if you are using query string to read and determine, what to load you have to make two calls.
The primary thing you appear to want is what is known as a router.
Since you seem to want to keep things fairly bare metal, the traditional answer would be Backbone.js. If you want even faster and leaner then the optimised Backbone fork ExoSkeleton might be just the ticket but it doesn't have the following that Backbone proper has. Certainly better than cooking your own thing.
There are some fine frameworks around, like Ember and Angular which have large user bases. I've been using Ember recently for a fairly complex application as it has a very sophisticated router, but based on my experiences I'm more aligned with the architecture available today in React/Flux (not just React but the architectural pattern of Flux).
React/Flux with one of the add-on router components will take you very far (Facebook/Instrgram) and in my view offers a superior architecture for web applications than traditional MVC; it is currently the fastest framework for updating the DOM and also allows isomorphic applications (run on both client and server). This represents the so called "holy grail" of web apps as it sends the initial rendered page from the server and avoids any delays due to framework loading, subsequent interactions then use ajax.
Above all, checkout some of the frameworks and find what works best for you. You may find some value comparing framework implementations over at TodoMVC but in my view the Todo app is far too simple and contrived to really show how the different frameworks shine.
My own evolution has been jQuery -> Backbone -> Backbone + Marionette -> Ember -> React/Flux so don't expect to get a good handle on what matters most to you until you have used a few frameworks in anger.
The main issue is from a UX / UI point of view.
Once you get your data from the server (in Ajax) after the page has been loaded - you'll get a "flickering" behavior, once the data is injected into the page.
You can solve this by presenting the page only after the data has arrived, OR use a pre-loader of some kind - to let the user know that the page is still getting its data, but then you'll have a performance issue as you already mentioned.
The ideal solution in this case is to get the "basic" data that the page needs (on the first request to the server), and manipulate it via the client - thus ease-in the "flickering" behavior.
It's the consideration between performance and "flickering" / pre-loading indication.
The most popular library for this SPA (Single Page Application) page - is angularJS
If I understand your inquiry correctly. You might want to look more about:
1) window.location.hash
Instead of using the "?", you can make use of the "#" to manipulate your page based on query string.
Reference: How to change the querystring on the same page without postback
2) hashchange event
This event fires whenever there's a changed in the fragment/hash("#") of the url. Also, you might want to track the hash to compare between the previous hash value and the current hash value.
e.g.
$(window).on('hashchange', function () {
//your manipulation for query string goes here...
prevHash = location.hash;
});
var prevHash = location.hash; //For tracking the previous hash.
Reference: On - window.location.hash - Change?
3) For client-side entry-point or similar to server-side PageLoad, you may make use of this,
e.g.
/* Appends a method - to be called after the page(from server) has been loaded. */
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function () {
if (oldonload) {
oldonload();
}
func();
}
}
}
function YourPage_PageLoad()
{
//your code goes here...
}
//Client entry-point
addLoadEvent(YourPage_PageLoad);
Since you're doing pure ajax, the benefit of this technique is you would be able to easily handle the previous/next button click events from the browser and present the proper data/page to the user.
I would prefer AngularJS. This will be a good technology and you can do pagination with one HTML. So i think this will be good framework for you as your using static content.
In AngularJS MVC concept is there please read the AngularJS Tutorial. So this framework will be worth for your new project. Happy coding
I'm doing some YouTube related stuff in a UIWebView on iOS. I'm using the mobile version of YouTube and they load things in the absolute strangest way (they make a bunch of AJAX calls to actually load the page while only loading basically a template first).
Something else strange: I'm logging the entire body of the page with this:
NSLog([webView stringByEvaluatingJavaScriptFromString:#"document.documentElement.innerHTML"]);
What's strange is that the logging doesn't happen until all AJAX is finished and the page is loaded. But I'd always thought that JavaScript doesn't wait for AJAX to finish before proceeding to execute the next line of code - this is contradicting that; it's actually waiting for AJAX to complete then returning the true, complete HTML of the page.
Any help? I'm confused.
XMLHttpRequests aren't necessarily asynchronous.
If we assume your AJAX is asynchronous, the page load order could affect what you're seeing.
Script tags in are executed first. The body is not available.
Script placed between are executed as they are encountered during page load, body is available up until the point the script is.
When all resources are loaded window.onload event is executed.
So depending on where your AJAX calls and where your logging call is this could affect the order you are seeing things.
Then depending on the finer implementation details of NSLog(), you may not see the output from a logging statement the very instant you are calling it. Many times there are buffers which are flushed now and then - perhaps only when the UI thread is not busy doing anything else.
Is is possible to intercept browser messages such as:
Firefox:
A script on this page may be busy, or
it may have stopped responding. You
can stop the script now, open the
script in the debugger, or let the
script continue.
I.E.
A script on this page is causing your
web browser to run slowly. If it
continues to run, your computer might
become unresponsive.
These messages are occuring due to the page having alot of javascript/jquery activity.
I appricate that the fact the these messages are appearing in the first place indicate a wider problem, but is there a way of intercerping this message/situation on the client side so that a more user friendly message can be shown?
No there's no way to do this, imagine a malicious user writing a script which slows down your browser until is completely unusable, now the "Slow Script" Warning may come to the rescue, but what if he could intercept it and prevent it from being shown?
You'll need to find a solution for the underlying problem, that is, in case that you're doing a lot of calculations(which I suppose you do), you need to split those of into chunks, put them into a queue and process them either asynchronously(if possible) or in order, but with a small timeout in between.
In pseudo code it may look like this:
var queue = []; // put your functions or the data in here
function() processQueue{
if (queue.length > 0) {
var item = queue.shift() // pop of the first item of the queue
item(); // call the function, or in case of data pass it to th processing function
setTimeout(processQueue, 100); // wait 100 ms before processing the next chunck
}
}
setTimeout(processQueue, 0);
No, there is no way to intercept these messages, they are are there at a lower level in the engine to protect the user. Instead look at what's taking so long, optimize as much as possible...possibly breaking your work up into chunks that have gaps in processing so you don't trigger the messages.