jQuery URL Utils: Query String, Fragment and more

| 15

This plugin has been superseded by both the jQuery BBQ plugin and the jQuery urlInternal plugins. Be sure to check those out, because they’re newer and way cooler! And also because this plugin is no longer getting any updates or support!

The URL Utils jQuery plugin provides some very useful methods around three major areas of URL handling:

First, the Query String / Fragment methods allow you to very easily serialize or deserialize data objects and param strings, including merging either into existing URLs or even elements with URLs. Second, the urlInternal and urlExternal methods allow you to determine the internal- or external-ness of URLs or elements with URLs and filter them using either methods or selectors. Finally, the fragmentChange event allows for very easy-to-implement cross-browser history, even on IE6/7, using the onhashchange event where available.

  • Release v1.11
  • Tested with jQuery 1.3.2 in Internet Explorer 6-8, Firefox 2-3.6a, Safari 3-4, Chrome, Opera 9.
  • Download Source, Minified (4.0kb)
  • Because this plugin has been deprecated, all documentation and examples are offline. Please try the jQuery BBQ and jQuery urlInternal plugins instead!

15 Comments

  • This looks fantastic! Appears to be exactly what I was looking for.

  • I had already decided to use the hash fragment to store data, since it respects history without sacrificing a cache hit; I started to write my own jQuery plug-in, but I figured that there must be one already available. One look at the tab UI example (with history), and I knew that I had found exactly what we needed.

    Thanks!

  • hi, i try to create a site which drops to a normal link behaviour instead of the history-enabled ajax-links if no js is enabled. eg: www.example.net/path/to/use/wihout/js#fragmentforajax_usage a simple clickevent which returns false, also stops the functionality of the history plugin. a solution would be to strip the part before the fragment via js on pageload. is there a more elegant aproach for that?

    greets and thanks for your great work peter

  • Peter, what about using query string parameters by default, but then changing all query string parameters to fragments via JavaScript?

    Links rendered into the page like <a href="?a=1&b=2">click</a> would get changed to <a href="#a=1&b=2">click</a> by your JavaScript on DOM ready. Your server-side code would handle any query strings that were passed through, otherwise the client-side JavaScript code would handle the fragments (and generate only fragments), and you’d have the best of both worlds.

  • Thank you so much for this.

    I’ve been creating custom scripts for each project to do stuff like this.

    Now I have it all in one (easier to use) package.

    Awesome!

  • Ii was forced to do in my code :

    setTimeout(function(){
        jQuery.setFragment(hash, 2);
    }, 0);
    

    just calling jQuery.setFragment wasn’t sufficient, hash was updated BUT there wasn’t any history entry in Firefox, i guess there’s something wrong elsewhere in my code but there’s so much lines .. :) big project ! Thank you !

  • Vincent, I’m not sure what the problem was.. as long as you’re using the fragmentChange event, it shouldn’t matter whether you set the fragment synchronously or asynchronously (as you’ve done here).. Are you making a lot of rapid, sequential setFragment changes? If that’s the case, be sure to allow for a delay between them (at least as large as the fragmentChange IE polling loop delay).

  • Hi Ben, thanks for your incredible helpful plugin! One more question is, if it is possible to set the fragment to a ‘pure’ string instead of key-value pairs? I’d like to do some ‘REStful fragments’ like "www.domain.org/en/#/posts/id/comments". Do you have some advices how to do this? Thanks and regards, Joe

  • Joe, I didn’t bother providing a convenience method for this because JavaScript already lets you do this, just change the hash directly with document.location.hash = "#/posts/id/comments";

    $.setFragment() exists as an easy way to merge new params into the hash or change existing hash params. For example, if you already have a fragment like #a=1&b=2, and want to merge {c: 3} or even {a: 2} in, $.setFragment() makes this easy, keeping the params orthogonal (unless you don’t want that, of course).

    Let me illustrate one instance where you might want to use $.setFragment() and the query string param-style hash, instead of just a single string value.

    Right now, you have just one variable you want to store in the hash, let’s call it path. You configure your hash to look like #/posts/id/comment which works perfectly.. until you realize, down the road, that you also want to store another variable in the hash, let’s call it user. Now, you basically need to figure out a backwards-compatible way to store the object { path: "/posts/id/comment", user: "cowboy" } in the hash.

    There are many ways to do this. One way: you come up with an arbitrary param delimiter (which is, of course, dependent on the values you’re trying to join.. let’s say for this example that you know __ won’t exist in any path or user string), which might make your hash look something like #/posts/id/comment__cowboy, and when you’re reading that string, you split it into an array, and then map each array value into an object, so you can access both path and user separately.

    But the problem here isn’t getting the values as much as setting them. In this example, in order to update the hash with a new user or path value, you’d need to look at the entire hash string, parse out everything you don’t want to change, add in the stuff you do want to change, and set everything again. You’d basically have to write your own hash encoder/decoder to do this…

    Or maybe you think a little more generally, and do $.setFragment({ path: "/posts/id/comment" }) which, while making your initial hash slightly more ugly as #path=/posts/id/comment, allows you to very easily add any other number of parameters in the future.. for example $.setFragment({ user: "cowboy" }) would change the hash to #path=/posts/id/comment&user=cowboy but then $.setFragment({ path: "/some/other/path" }) would change the hash to #path=/some/other/path&user=cowboy without even having to think about whether user was set, or what its value was.

    This “one instance” I’ve suggested could really apply to all instances if you think generally enough. Of course, your needs might be much simpler or more specific.. I just wanted to provide a different viewpoint. I hope this helps!

  • Hello !

    Just to answer quickly your last question : no we do not make a lot of setFragment calls but i think our code is a little buggy sometimes :) …

    I think i really found a bug this time !

    When we have an hash with quote in it like this : http://site.com/#d=h’ello

    The fragment change gives this fragment : #d=h%27ello

    BUT ! If we use the jQuery.queryString functions to let’s say, compare this value with another we have in a variable :

    if (fragment === jQuery.queryString({d: "h'ello'}))
    {
       alert('wonderfull !');
    }
    

    This does not work in FF ! Yes and it’s very easy to understand why : in your script you retrieve document.location.href wich has the quotes encoded (escaped to be exact !) But then jQuery.queryString uses jQuery.param wich do not encode quotes (has defined on the mozilla mdc site).

    So the hash an the object you initially used to modify the hash are now different from one character : the quote !

    We added a little fix, when we retrieve the fragment change, we do this :

    fragment = fragment.replace(“%27”, “’”);

    Here we go ! Can you confirm this bug ? Can you think of a solution ?

    thank you your plugin is so nice !

  • Vincent, instead of comparing fragment to jQuery.queryString({d: "h'ello'})), take any potential URI encoding issues out of the equation by comparing $.fragment().d to "h'ello". You’ll find that this is easier to do and far more reliable.

  • Hi Ben, your plugin is great, I’m using it in a website that will also be burned to a CD, therefore I can’t use any server-side language.

    I’m having a problem with this. Consider this URL:

    http://website/2008/english/01.htm

    Id like to store “01.htm” to a variable. I can’t seem to understand how to do it with your URL parser, can you shed some light, please?

    Thanks in advance.

  • Rodrigo, URL Utils won’t really help you there.. but fortunately all you need to do is use a simple RegExp. In your example, document.location.href.replace( /.*\//, '' ); should return 01.htm.

  • Hi,

    It would be wonderful if all of your plugins would have support for Visual Studio documentation & autocomplete. That is already done for jquery which works marvless.

    What do you think?

    -Laurentiu, DotNetWise

  • Laurentiu, I think that’s a great idea. I’ll be honest, since I don’t use Visual Studio, I’m not the best person to write the IntelliSense documentation.. but if someone else were to do the work, I’d be happy to include it here.