JQuery selector validity/scope

Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 10:11

Hi,

I have tweaked my site to leverage rel=prefetch from HTML 5. Without going into all the intricacies involved, I want to use JQuery to get and cache the HTML of certain pages when a non Firefox browser is detected (handled by php elsewhere ... no issues with that).

Here is the code I have come up with:

    $(document).ready(function() {
        var my_url;
    	$('[rel=prefetch][href$=.html]')
    		.each(function() {
    			my_url = $(this).attr('href')
    			$.ajax({
    				url: my_url, 
    				dataType: 'text',
    				headers:{'X-Moz': 'prefetch'} 
    			});
    		});
    });

Basically, I have some links with 'rel=prefetch' in the head of the document and the code snippet above is inserted when the browser is not Firefox.

I have set G2 up to render things differently when the 'X-Moz: prefetch' header is detected so this is sent here as it is needed.

The code is supposed to just get the html and cache without evaluating scripts which I believe 'dataType: text' should take care of. Passing the required resources is handled by php elsewhere ... no issues with that.

I am trying to hook into JQuery 1.7.1 called using the google api.

Queries are:
1. Is the code above valid? If not what is the fix?
2. What do I need to change to limit the selector's scope to the < head > ... < /head > section? I have tried "$('head link[rel="prefetch"][href$=".html"]')" but not sure.

As might be apparent, JQuery is not my forte and will appreciate some eyes on this and suggestions (Wayne?).

Thanks.

--
dakanji.com

 
Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 13:29

Got it working. The issue was because the jquery snippet was not running when I linked to JQuery using the google api. When I serve it directly from my site, in which case all the js is combined into one file, it works.

I noticed this when I used the developer tool in Safari.

The full code is:

    (function ($) {
    	$(document).ready(function() {
    			var this_browser, my_url;
    			// Prefetch pages for non Firefox browsers
    			this_browser = new Browser();
    			
    			if ( this_browser.getBrowserName() != this_browser.BROWSER_FIREFOX ) {
    				// Asynchronously prefetch html as text strings
    				// I.E., do not process scripts in incoming html
    				// See: http://ernstdehaan.blogspot.com/2009/08/prefetching-files-using-jquery.html
    				$('link[rel="prefetch"][href$=".html"]')
    					.each(function() {
    						my_url = $(this).attr('href');
    						$.ajax({
    							url: my_url, 
    							dataType: 'text',
    							headers: {'X-Moz': 'prefetch'} 
    						});
    					});
    			}
    	});
    }(jQuery));

Safari alerted me that the "(jQuery)" bit was generating an error. Not sure why but things work as required so I will leave figuring that out so I can use the google api for later.

Now seeing the same instant loading on other browsers.
Sweet!

--
dakanji.com

 
suprsidr
suprsidr's picture

Joined: 2005-04-17
Posts: 8339
Posted: Tue, 2011-12-13 13:28

Ah yes HTML5 prefetch, I recently read Jean-Baptiste's article regarding the exciting possibilities.
And other tuts on the subject can be found on HTML5 Rocks and David Walsh's site.

So you're trying to create a kludge for unsupported browsers?

Quote:
Is the code above valid? If not what is the fix?

This looks possible the way you're attempting. you could also try loading a non-display element with whatever you are trying to prefetch.
Say you only want to fetch #gallery images from the next page:

$("#non-display-element").load("my_url #gallery img");

This way you would not need to send your headers.
In this example I'm loading just the images from /media/index.php?g2_itemId=32 #gsThumbMatrix w/:
$('#content').empty().load('/media/index.php?g2_itemId=32 #gsThumbMatrix img');
(view source)
if I added style="display:none;" to #content you would not even know It was there.

Quote:
What do I need to change to limit the selector's scope to the < head > ... < /head > section?

$('head link[rel="prefetch"][href$=".html"]') this would limit the selector engine to the <head />.

-s
FlashYourWeb and Your Gallery with The E2 XML Media Player for Gallery2

 
Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 13:49

Hi,

Yes, a hack for the other browsers (Go FireFox!).

Go it working fine now. Thanks for getting back.

I have been hacking my install for speed, particularly for perceived speed, over time.

I had been pushing six additional images with each photo page load for some time (using the window feature in G2 ... needed to hack the core a bit) so that a request for any of the pages in a seven page window around and including the current image would only load the html and the image would already be in the cache. This gives near instant loading with the only time needed to fetch the 4kb or so of html which is minified as well by G2.

I then later added the HTML rel = prefetch for FireFox (which has supported this since v3). So G2 pushes the images to the users as needed and FF dls the html. When clicked, it loads pretty much instantly ... just like hitting the back button.

When I started using chrome this year, I took at look at their prerender implementation but while they are trying to extend prefetch, I found that the Firefox prefetch implementation is far better so having a bit of time, I finally got around to trying to use JQuery to basically do the same for other browsers.

I also hacked the core code to combine my css and fixed some inefficiencies in the JS combination.

It's now flying on all browsers. Just need to go tweak my Nginx cache to take account of the setup.

--
dakanji.com

 
suprsidr
suprsidr's picture

Joined: 2005-04-17
Posts: 8339
Posted: Tue, 2011-12-13 13:58

My example would work for all browsers.
Layout elements, CSS and JS don't change from page to page they would already be cached.
So my method of only pre-loading the "heavy" elements(images) would work without the server-side fuss.

-s
FlashYourWeb and Your Gallery with The E2 XML Media Player for Gallery2

 
Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 14:18

Cheers.

I'll leave things are they are for now as it is within my comfort zone and does what I want.

I think I'll set G2 up to drop the rel attribute and just use $('head link[href$=".html"]') for all browsers.

In this way, I can drop the browser detection JS and use a common Nginx cache.

While I have your attention, Any ideas why the " }(jQuery));" triggers an error when calling JQuery using google but not when everything is combined into one file? BTW, the link to google comes after the combined JS when it is used. Not sure if this is relevant.

--
dakanji.com

 
suprsidr
suprsidr's picture

Joined: 2005-04-17
Posts: 8339
Posted: Tue, 2011-12-13 14:27

get your jQuery from google like this:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
leaving off the "http:" allows it to work regardless of whether the page is http or https - but it won't work locally.

-s
FlashYourWeb and Your Gallery with The E2 XML Media Player for Gallery2

 
Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 14:39

Leaving the scheme out will default to http on my site.

Actually, the jquery file was retrieved loaded OK (I used https as per google's instructions).

Anyway, I'll play around with it later. It may be that the "(jQuery)" just needs to be removed.

--
dakanji.com

 
Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 17:51

Jean-Baptiste's article linked above has a few inaccuracies in it. I had found the site while looking for answers and left him a comment to point of some of the issues but I suppose he hasn't had time to approve my comment.

1. Chrome's prerender is not the same thing as HTML5 prefetch (which FF implements).
When html is prefetched, it works as in my js code above. I.E., it downloads the html as text and does not evaluate the code (datatype: text). Other resources, such as images, css, js files and images have to be prefetched separately. since these other resources generally form the bulk of a page's size, Chrome's prerender tries to help by evaluating the html (equivalent to using datatype: html in the js code). Chrome will download the entire page in a hidden tab and when you select a link to go there, it swaps the tabs.

This however, I believe, is a flawed approach. In an attempt to stop run away scenarios, Chrome will only prerender one page max. The HTML 5 and FF approach is far better IMO. I can safely prefetch as many pages as I want, and I can prefetch the resources to go with them as a I want. The choice is mine. With prerender, the choice is made by the browser.

In any case, prerender is not simply Chrome's term for describing prefetch.

2. The section titled "Prefetching using jQuery" is misleading. He is not prefetching using JQuery in the true sense but simply creating a situation whereby prefetching may happen as long as the visitor happens to be on Firefox. It is more like "Using jQuery to Create Conditions where Prefetching May Sometimes Occur"

--
dakanji.com

 
Dayo

Joined: 2005-11-04
Posts: 1642
Posted: Tue, 2011-12-13 19:33

Solved the Google API issue.

It was because it was loading after the main JS file as I suspected. It fires after it finishes loading which was before the JQuery variable, defined in the main jquery file had been initialised.

Also leveraged the HTML 5 "defer" attribute (Again long supported by FF and surprisingly, IE) which allows asynchronous downloads of js files but fires them off in order (as opposed to the first come, first served "async" attribute).

Looking good!

--
dakanji.com