Rails Caching a Page Improperly - How to Stop? - ruby-on-rails

I have a very simple test case that explains the problem.
Here's the page that I'm displaying in Rails in an ERB file.
<div><%=rand%></div>
<p>Go</p>
To show the error, I load the page. I note the random number displayed as rand1. I click on the Google link. I click the browser's "Back" button. I note the random number displayed as rand2.
Here's the problem:
In Firefox and Chrome, rand1 != rand2 (always).
In Safari and IE, rand1 == rand2 (always).
Why the discrepancy in browsers? Why is Safari and IE caching the output from Rails while the other two browsers are not? How do I get Safari and IE to refresh the page?
(This is a simple test case to show the problem - this has implications in my Backbone application).

IE and Safari appear to be caching the response from the server, obviously; as long as your browsers are configured correctly, you can change this by changing the Cache-Control header in the response.
Another Stack Overflow post shows the appropriate way to do that, though in Rails 3 there's a shortcut method to accomplish this: you can invoke expires_now in the controller action to avoid manually setting all these headers.

WebKit in particular has an aggressive page caching strategy for handling exactly the case you're describing (clicking a link and then immediately clicking the back button). The idea is to make the back action happen almost instantaneously by caching not just the resources but also the DOM and other state of the page. You can read about it in these two articles:
WebKit Page Cache I — The Basics
WebKit Page Cache II — The unload Event
You may be able to use a combination of the load/unload and pageshow/pagehide events to accomplish what you need.
I'm not sure if IE implements something similar to WebKit, but maybe this will fix it too.

Related

Why don't jQuery Mobile prefetched "single-page" pages work exactly like "multi-page" pages

I have a website that consists of a bunch of single-page-template jQuery Mobile pages that are linked to each other using prefetching and caching. All pages exist in the DOM (after they are prefetched).
This works fine on my desktop browser. However, when I browse my site using my HTC EVO 3D Android phone (either the default browser or the Opera browser), switching between pages acts like I'm actually going to an external page. In other words, the browser's address bar appears momentarily, then the page turns white, then the new page loads, then the address bar goes away.
I would expect the behavior to be exactly that of a multi-page-template. For example, if you browse the multi-page-template in the jQuery Mobile documentation, you can switch from one page to another very smoothly. The browser address toolbar does not pop up, and there is no white flickering in between pages. However, if you browse the "persistent toolbar" example (which uses prefetching to load all the pages in the example), you will see the same behavior that my site is experiencing. The browser's address bar will appear, the page will turn white, the next page will render, then the address bar will go away.
So how do I make my prefetched pages act like the multi-page template without having to rewrite my site to use the multi-page-template?
For reference, here are the jQuery Mobile persistent toolbar demo and multi-page demo that I believe should work exactly the same (in regard to URL address bar appearing):
http://jquerymobile.com/demos/1.3.0-rc.1/docs/toolbars/footer-persist-a.html
http://jquerymobile.com/demos/1.3.0-rc.1/docs/pages/multipage-template.html
Unless your initial page links directly to all of your other pages with the data-prefetch attribute on your <a> link tags, those pages will not be prefetched and cached. I state this because your question implies that there is some chaining with your pages which is not supported. You can load also load and cache them via the API.
$.mobile.loadPage( pageUrl, { showLoadMsg: false } );
Are you able to actually inspect the DOM on your mobile Android device?
Is there any chance the pages are being flushed from the DOM based on a memory constraint? I am not aware of any specifics in the jQM docs on this scenario but at some point you will fill the cache.

Response.Redirect in MVC 4 Mobile Application

I am developing a mobile web application using ASP.NET mvc 4. I am facing problem with response.redirect to some other website (eg: http://www.google.com) from my controller,it is showing "Error Loading Page" message without redirect.
I have tried the following codes to redirect under "About" action on Home controller:
return Redirect("http://www.google.com");
return RedirectResult("http://www.google.com");
response.Redirect("http://www.google.com");
All the above produced the same error.
Note: the hyperlinks in view pages are working fine
Thanks
When you are setting up your link to the controller...you need to make sure the data-ajax attribute is set to false.
Redirect
My understanding is that jQuery mobile wraps all anchor request in ajax, unless otherwise specified, and your response.redirect is just being served to the jQuery .done function which can't handle it properly.
http://jquerymobile.com/demos/1.2.0/docs/pages/page-navmodel.html
Important: rel="external" and $.mobile.ajaxEnabled=false
Slightly different implementations of the replaceState API in various
browsers can cause odd behavior in specific scenarios. For example,
some browser implementations (including desktop browsers) implement
the popstate event differently when linking externally and moving back
to a page onto which state has already been pushed/replaced. When
building a jQuery Mobile application where the Ajax navigation is
being explicitly disabled, either through the frequent use of
rel="external" on links or by disabling Ajax navigation completely via
the $.mobile.ajaxEnabled=false, we recommend disabling the pushState
feature to fall back to the hash based navigation for more consistent
behavior.
I suspect your problem is that you are redirecting outside local site.
See this part of the documentation: http://jquerymobile.com/test/docs/pages/page-navmodel.html
Hash values created by jQuery Mobile are normalized as full paths
relative to the URL of the first "real" page that was loaded.
Then later it confirms the "local" requirement here:
When a link is clicked, jQuery Mobile will make sure that the link is
referencing a local URL
I think the solution is to not redirect users to other domains.
UPDATE
The above solution highlights the wrong part of the problem but the solution may still be the same. You should use javascript to do the redirection such as:
window.location = 'http://www.google.com/';
I believe you will run into issues if your JQM solution is attempting to make an ajax call that is then redirecting. One issue, specifically for google.com, could be if you are signed in to google. It will then redirect you to https for example. That could be interfering with the JQM / window.location.hash.

jquery slider with url changer [duplicate]

I am writing a complex AJAX application at the moment and the entire site has clean URLs. At the moment PHP creates the basic layout for each page however I don't want to have to navigate away from each page when the user clicks on a link, and I don't want to have a hash in the URL because it won't fit with the rest of the site. I know that this has cropped up loads before on the site and it seems to be quite commonly asked but I was wondering if there was a neat HTML5 way of just appearing to change the URL in the address bar even if it technically remains on the same page.
You can do it with history.pushState, but only in browsers that support it. Just try the following line in your browsers JavaScript-Console.
history.pushState({},"URL Rewrite Example","https://stackoverflow.com/example")
More on that in The pushState() method (Mozilla Developer)
Similar question How do I, with JavaScript, change the URL in the browser without loading the new page?
As others have stated, HTML5's history.pushstate is the way to go. Try browsing a repo on github to see it in action (https://github.com/visionmedia/express).
Trouble is the only version of IE that supports history.pushstate is IE10, which kinda sucks.
Plenty of sites use hashbang #! URL's such as Twitter (e.g. https://twitter.com/#!/Sironfoot ). The hashbang is a URL pattern agreed on by search engines so that they can still trawl and index a heavily Ajax powered website (more info here http://code.google.com/web/ajaxcrawling/docs/specification.html), so you could go that route.
The only other approach is to use history.pushstate for browsers that support it, and fall back to full-page refreshes for non-supporting browsers.

How is this URL modification possible?

Could anyone please tell how the site http://www.outsharked.com/imagemapster/default.aspx?what.html is working in such way? Modifying the url without loading/reloading the page. I think this is not done by html5. Because it works in IE6 which doesn't support html5.
I created that site. The commenter is correct, it uses Javascript to change the URL. There's nothing about how that navigation works that is different for IE6 - that browser supports the necessary client-side functionality to do this kind of thing. The basic functionality involves:
capturing click events on the nav, and loading the inner content via AJAX
update the URL to reflect a working direct URL to target.
The links also are valid anchor links that, in the absence of Javascript, would go to the same page (but load the whole thing). This is your basic AJAX web site setup with one minor difference. It's common practice to use a URLs like this in AJAX/single page web sites:
http://mysite.com/home#somepage
or even just
http://mysite.com/#somepage
Where the hashtag part represents the actual page a user has navigated to. If someone accessed that url directly, e.g. from outside the site, the site would use Javascript to load the correct content based on the hashtag, after the page had loaded. This means that there might be a little delay for the inner content to reflect the correct page, since it has to run another request after the initial page has loaded from the browser to get the inner content via AJAX.
I was trying to avoid that by creating a setup that worked completely with and without Javascript. If you go directly to a URL within the site such as http://www.outsharked.com/imagemapster/default.aspx?faq.html you will notice it loads the content directly. This URL will work even if Javascript is disabled. You can't actually do this using hashtags, since hashtag content is not sent to the server. Only the client knows what's after the hashtag in a URL. That's why I was using query strings to represent inner pages.
This site architecture was sort of an experiment at the time. It works pretty well but the code isn't fantastic, I didn't really do anything else with it, and I'm sure there are other better-fleshed-out/tested/full-featured frameworks out there to do much the same thing.
But it might not be a bad example of the nuts and bolts of creating a basic AJAX navigation setup, as a learning tool, since it's pretty concise, and also does HTML5 history navigation (e.g. so the back button works on modern browsers).

sifr3 - prefetch not working?

I am having a problem with the loading times/size of an sifr 3 enabled site, and found out the the font swf is requested several times in my application. This can be seen in the network tab of firebug, as well as in the apache logs.
On http://novemberborn.net/flash/prefetching-movies there are some instructions for prefetching. However that does not work, the prefetch Method is not available (still in the docu!). I understand that prefetching is done automatically, however that does not seem to work.
Even in the demo page of the sifr download package, with an empty browser cache I get several hits for rockwell.swf and cochin.swf! Both with Firefox 3 and IE7...
Any chance for an easy and quick fix?
Greetings,
Simon
Fundamentally, this is an issue between the browser and the Flash player. As sIFR inserts the Flash movies into the page, the browser initializes the Flash plugin with the path to the Flash movie. If the movie is not yet in a local cache, it's requested from the server. Since the movies are inserted within a few milliseconds, this would mean that a request is made for each inserted movie.
sIFR tries to prevent this by prefetching the Flash movies. It does this ones per browser session, based on a session cookie. This merely fires off a request for the movie file, and hopefully that file is in the cache by the time replacement starts. Therefore its important to load the sIFR JavaScript code as early as possible, and to activate sIFR properly by passing the Flash movies to the sIFR.activate() method.
In my experience the only way to reliably test this process is clearing browser cache, closing all browser instances (to get rid of the session cookie), then opening the browser and going straight to the page you want to test. I don't find the activity monitors within browsers reliable, so either check through an HTTP proxy or the server logs.
The one remaining improvement I could make is to try and detect the progress of the prefetch, and hold off on replacing elements until the prefetch is complete.
Do you have the option to move to Cufon? You'll find it much easier to use and isn't quirky.

Resources