Tuesday,
28 Apr 2009
Introducing jQuery Address
I'm happy to announce our first contribution to the jQuery ecosystem. Our brand new project called jQuery Address brings the deep linking functionality to jQuery and hopefully is going to simplify one of the most common tasks for JavaScript developers. In other words it provides an API for creating direct links to specific Ajax states and enables the Back and Forward buttons of the browser.
jQuery Address is a direct port of the SWFAddress library which has become a standard in the Flash world and has been used on many high profile websites. It supports all the major browsers and degrades flawlessly in a small percent of unsupported versions. This first release ships with 2 samples that showcase the different ways to utilize the plugin (API sample) and how to use with jQuery UI (Tabs sample). The next steps we're planning include documentation, SEO samples and integration with the SWFObject plugin.
The work on the plugin started a few months ago but so far I wasn't able to find the time to release it. It's my first serious work that involves jQuery and I'm open for suggestions, critiques and comments. I had great time learning the library and writing the most expressive code ever. The good thing about the plugin is that it has much smaller file size compared to SWFAddress but it also does not target Flash content at this point.
I hope that our experience in this field will be valuable to many jQuery users. The plugin already contains all the improvements included in the upcoming SWFAddress 2.3 which is we're planning to release tomorrow.
Comments:
One note/comment/heads up:
There is an embedded bit of logic in the library that will call the Google Analytics functions, trackPageview or urchinTracker. While this makes sense in many cases, it didn't in ours and actually artificially lowered our bounce rate for the page and increased our page view count.
We simply commented out the calls to the Analytics functions.
Is it possible to deep link using #foo instead of #/foo ?
Thanks
btw, I haven't tested it but considering what happened to the code I posted this comment system might be slightly xss vulnerable. (pasting a youtube embed link at least shows up in live comment preview).
Regards,
gwk
I even copied the exact format from the example pages, inserting my own functions, to now avail.
Thanks for this gorgeous plugin!
I had an issue with links coming in by AJAX. The magic didn't want to work on those new links.
Changing:
<code> $.fn.address = function (fn) { $(this).click(function() { ...
to
<code> $.fn.address = function (fn) { $(this).live('click',function() { ...
did the trick for me.
I hope it doen't break too much of the magic...
Cheers,
Georg
var bindBehaviors = function(scope) {
$(function () {
$('a').address();
});
};
bindBehaviors(this);
_d.body.innerHTML = '<iframe id="' + ID + '" src="javascript:false;" width="0" height="0"></iframe>' + _d.body.innerHTML;
Into this:
$("body").append('<iframe id="' + ID + '" src="javascript:false;" width="0" height="0"></iframe>');
Basicaly i moved iframe from begining to the end of body (and after the troublesome form)
I'd like to know if it's possible to use the plugin only if the user click on "previous" or "next" button.
I'd like to manage the site like GMAIL: when you click on a link, it's loading the page, and then the URL change. But when you click on previous or next, the URL change and then the page is loading.
Thx
First, instead of adding "#..." to the address it can replace part of the string. So, for instance, I could use a REGEX expression to replace "/value1/" with "/value2/".
Second, and this might just be simpler, to replace the entire URL.
Either of these would remove the "#..." from the URL, which would be quite handy. I could possibly work around it if necessary but given the option I'd rather keep my clean URLs.
refering the the post before:
the init() excuts only if it's in the <head> of the page, and I'm trying to call it inside a Object, is ther any solution for that please?
.ab
Thanks for the patch. I will try to include it in the next release.
There is known IE loading issue that has been fixed months ago but I haven't found the time to release. Hopefully this will happen very soon.
The only reason we wanted to disable it was because it seemed to be calling trackPageview when the page initially loaded, which we don't want. But, we do want it to call trackPageview whenever the $.address.change() is fired, after the initial page load.
Any thoughts?
http://localhost/seo/
to simulate the experience of an iPhone or Search robot. When I click on a link to About I get this error:
"The requested URL /swfaddress/samples/seo/index.php was not found on this server."
However when I put the seo example in the folder structure:
http://localhost/swfaddress/samples/seo/
Everything works just fine. So my question is, when using
http://localhost/seo/ where is swfaddress/samples/ coming from? What code is setting that?
Thank you!
Thanks for noticing that. There was a problem with the tabs initialization which should be fixed now and the code became even simpler.
@Mark
Probably you have received my response on Twitter. It's totally up to you to distinguish the external links.
@Yusuf
The plugin should work for forms that create GET queries and I will try to prepare a sample for the next release.
I congratulate you.
Do you plan to add same functionalty for forms?
Best regards...
(also there needs to be a support forum)
Thanks for reporting this! We will release an update soon and hopefully this will be fixed.
After working with this wonderful solution for a bit, I realized that the problem jb mentioned above was happening on my site as well. It turns out the fix Left by Rostislav at Sun, 24 May 2:43 PM isn't included in the downloadable project zip.
Copy pasting the jquery from the example page ( http://www.asual.com/jquery/address/samples/tabs/ ) should fix any remaining issues.
Thanks for a fantastic addition to the jQuery plugins :)
<a href="/deep-link" rel="address:/deep-link">Deep link</a>
James
You should adjust the RewriteBase path in the .htaccess file which is often hidden in OSX. Please, post SWFAddress questions in the appropriate posts.
thanks for coding this jQuery plugin. May be I've got an issue. When I use it with jQuery 1.3.2 and Firebug in Firefox 3.0.10 I get the error "accesext_consoleDump is not defined - if ( !handler.guid )" in line 2447.
I didn't get the error in the examples above, but in the examples of the download package.
Does anyone knows the error? What could I do?
Thank you for this plugin.
It has a weird bug, on IE browsers if you include jquery.address AFTER other javascript files, the code in these files don't work.
did any one had the same problem?
Thanks
Thanks. You're making a good feature request. Please, implement the functionality in your code for now because there are some other features with higher priority. One of them is the ability to distinguish between internal (link click) or external (back button, direct access) change events.
Thanks a lot !
I have a problem with IE 7. (the plugin works great in Firefox 3.5 and IE 8). In IE 7, it fails with no javascript error. Firebug in Firefox gives an error "H is undefined" (in jquery code) and seems to happen when trying to bind "init" and "change" event (line 400 of jquery-address js file). Firefox seems to ignore the error and continue, but IE7 breaks on it.
Firebug gives the same error on the "Tab" example too.
I'm using this great plugin on my current project and it works fine on all browsers -- except Safari v4.0.530.17 (Windows XP Pro SP2).
On a page I have few tabs that display different portion of the same page. In address bar links look like:
help.html#/#tab1
help.html#/#tab2
But in Safari v4 they look a bit different and therefore plugin does not work (the second hash symbol got converted into hex code %23):
help.html#/%23tab1
help.html#/%23tab2
Even if I copy-paste the whole correct url into address bar, Safari "fixing" it before requesting the page.
Is there something that can be done to fix this ?
Any help would be appreciated.
I have an issue though - when clicking on a link whose href is to a named anchor on the same page, an externalChange event is triggered. This isn't what I was expecting, was expecting change and internalChange only. Perhaps this is by design, but I'm having a difficult time accommodating it, as the event's value (the href) as received by my handler doesn't include the '#', so I'm not sure how to distinguish that type of situation without resorting to some ugly hacks.
Your feedback would be greatly appreciated, and again, thanks for your efforts here!
Thank you very much for this port :)
in my page I've put:
$.address.init(function(event){
//do somthing
}).change(function(event){
//do somthing
});
the change() works fine but init() don't excut at all, did any body have the smae problem? or I'm missing something?
thank you for your help
Thanks for the feedback! The tracking functionality can be a little tricky. The recommended way to disable it is to include the script using "jquery.address-1.1.min.js?tracker=null" or to call $.address.tracker(null).
This looks like an error caused by an extension.
@Olivvv
I think I saw bind(name, fn || data, fn && data) in the jQuery code and the rest is improvisation.
@ab
Thanks for reporting. I will put it on the list.
@Ioannis
The slash is automatically added when the plugin works in strict mode. You have two ways to disable it and they're described in the docs.
where did you learn about this ? :
$.each(('init,change').split(','), function(i, name){
_api[name] = function(data, fn){
$($.address).bind(name, fn || data, fn && data);
return this;
};
});
This is really cool !
Say that you have an application on Facebook
e.g.: http://apps.facebook.com/myapp
this app has an iframe for your domain
e.g.: http://www.mysite.com
the plugin fails on _getWindow function when calling top.document.
Firefox & Explorer goes to the catch(e) , but Chrome does not.
Solution:
chaning the _getWindow function to check whether top.document is UNDEFINED instead of just calling it.
Complete code:
var _getWindow = function() {
try {
if(top.document!=undefined)
return top;
else
return window;
} catch (e) {
return window;
}
};
Try the development copy of the plugin what can be found in the Source section of the site. Recently we improved the IE8 support by detecting the cases where it works like IE7.
_d.body.innerHTML = '<iframe id="' + ID + '" src="javascript:false;" width="0" height="0"></iframe>' + _d.body.innerHTML;
into this:
_d.body.innerHTML = '<iframe id="' + ID + '" src="javascript:false;" width="0" height="0" style="position:absolute;top:0px;"></iframe>' + _d.body.innerHTML;
The result might not be satisfying for all cases because position:absolute; but it worked in mine..
$j.address.change(function(event) {
//i need some parameters here
});
how do i do that?
$.address.autoUpdate() - autoupdate of what?
$.address.crawling() - in what ways can this plugin affect crawling?
$.address.strict() - aside from the "/" not being present in the fragment, what else will turning this off disable?
$.address.tracker() - in what ways can this plugin affect tracking?
$.address.value() - how does this differ from the hash property?
$.address.wrap() - wrapping of what?!
Also aside from using the automatic way of adding the functionality to links (using links of this structure: Deep link) how else can I manually add this functionality to specific links?
Finally how is the Address function used, is it used to set the fragment manually or called as an event?
Sorry there are a lot of questions but I'm more used to procedural coding and the $ syntax of JQuery is a little different to what I'm used to.
Thanks for your help.
P.S. It might be worth throwing the responses in the documentation too.
Add a listener for the init event only and inside of it add one for the change event with a slight timeout of 100ms.
The plugin is about having a nice navigation in Ajax websites and it can help you create this Gmail like functionality.
Thanks! The patch is already applied and will ship with 1.2.
this plugin is very elegantly written (IMO deserves a blog post on the coding patterns used).
Would it be possible to distinguish between the loading of new content and the loading of content already visited ?
I tried quickly to explore that with some console.log s in your code, but it could not find this information.
So it seems to me that I have to use an array of the hash s of the visited contents to know if its an already visited content but that there is to no direct way to know if the user has clicked the back button.
If html page has SELECT element, there is a problem that IE6 is flashing on the screen
To solve this problem, I changed this line:
Before:
_d.body.innerHTML = '<iframe id="' + ID + '" src="javascript:false;" width="0" height="0"></iframe>' + _d.body.innerHTML;
After:
$(_d.body).prepend('<iframe id="' + ID + '" src="javascript:false;" width="0" height="0"></iframe>');
Why did you use body.innerHTML not jQuery's prepend method?
I think that you had to use body.innerHTML because of another reason.
Very nice plug-in, but I have a problem with lightbox. It doesn't work in a tabs.
(there is no conflict with jquery because it works only in Overview when refreshing)
Is there a solution ?
thx
One quick question.
I have the following event attached to a div.
On click of div, its ID is updated in the address and the address change callback makes an ajax request.
Now if I click the div again, nothing will happen. This is a bit annoying. I want the callback to be fired every time I click the div.
Is there a way to achieve this? Am I missing something?
Add a click event to your div and change the address manually. Something like:
$('#container').click(function(e) {
$.address.value('/container');
});
I use the plug-in to page through search results but I am having issues with IE7.
For example I can have 3 pages of search results. When I click on a record that is on the 3rd page of results I go to the record details page. When I click back button I go back to page 3 of the search results. When I click back button again I go to the 2nd page of search results. This is the behavior I want.
For some reason in Internet Explorer 7 (IE7) when I click back to the search results I go to page 3 but when I click back button again I go to the previous page and not page 2 of search results.
Am I doing something wrong? And am I the only one that dislikes IE?
on all browsers but