O'Reilly logo

JavaScript Cookbook by Shelley Powers

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

20.1. Attaching Persistent Information to URLs

Problem

You want to store a small fragment of information so that the information is available to anyone accessing the page.

Solution

Persisting a fragment of information in a web page for general access by everyone is dependent on the old school capability of attaching information to a URL. The information can be passed as a page fragment:

http://somecompany.com/firstpage.html#infoasfragment

Discussion

JavaScript can be used to add a page fragment, though this is more of a way to store a simple state than anything more complex:

http://somecompany.com/test.html#one

The data can also be encoded as parameters in a query string, which starts with a question mark, followed by the parameters passed as key/value pairs separated by equal signs, and separated from each other by ampersands:

http://somecompany.com?test=one&test=two

There are limits to lengths of URLs, and probably for numbers of GET pairs, but I would hope we wouldn’t ever approach these limits. This also isn’t an approach you would use in place of a cookie. For instance, if you want to capture user input into a form, in case the users have to leave before finishing the form entries (or they accidentally close their browser tab page), you should put this data into a cookie, which is more secure, and more specific to the person.

Data encoding in the URL is more of a way to capture page state so that a person can send a link to the page in that state to another person, or link it within a web page. Example 20-1 demonstrates how something like data persistence via URL can work. In the web page, there are three buttons and one div element controlled by the action of the buttons. One button moves the div element to the right, one button increases the size of the element, and one button changes its color. As each button is clicked, the div element is adjusted, and the newly applied CSS value is stored with the appropriate button.

When the state of the page is changed, a link within the page is updated to reflect the state of the page. Note that the actual window.location property and even the window.location.search property is not changed. The reason is that the page reloads as a security precaution when you update any component of window.location except the hash value.

Note

Allowing a person to change the URL in the location bar, which isn’t reflected in the actual page, introduces the threat of spoofing—one page masquerading as another in order to scam passwords and other confidential information.

Now you can reload the page and have the script restore the page to the state in the URL when it reloads—but that’s a lot of moving parts. In the example, we’ll just create a static state link, and leave it at that.

Example 20-1. Using the URL and the query string to preserve state

<!DOCTYPE html>
<head>
<title>Remember me?</title>
<style>
#square
{
  position: absolute;
  left: 0;
  top: 100px;
  width: 100px;
  height: 100px;
  border: 1px solid #333;
  background-color: #ffff00;
}
div p
{
  margin: 10px;
}
</style>
<script>

  // found at http://www.netlobo.com/url_query_string_javascript.html
  function getQueryParam( name ) {
        name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
        var regexS = "[\\?&]"+name+"=([^&#]*)";
        var regex = new RegExp( regexS );
        var results = regex.exec( window.location.href );
        if( results == null )
           return null;
        else
           return results[1];
   }

   window.onload=function() {

      // set up button
      document.getElementById("move").onclick=moveSquare;
      document.getElementById("size").onclick=resizeSquare;
      document.getElementById("color").onclick=changeColor;

      var move = getQueryParam("move");
      if (!move) return;

      var size = getQueryParam("size");
      var color = getQueryParam("color");

      // update element
      var square = document.getElementById("square");
      square.style.left=move + "px";
      square.style.height=size + "px";
      square.style.width=size + "px";
      square.style.backgroundColor="#" + color;

      // update data-state values
      document.getElementById("move").setAttribute("data-state",move);
      document.getElementById("size").setAttribute("data-state",size);
      document.getElementById("color").setAttribute("data-state",color);
   }

   function updateURL () {
      var move = document.getElementById("move").getAttribute("data-state");
      var color = document.getElementById("color").getAttribute("data-state");
      var size = document.getElementById("size").getAttribute("data-state");

      var link = document.getElementById("link");
      var path = location.protocol + "//" + location.hostname + location.pathname +
                "?move=" + move + "&size=" + size + "&color=" + color;
      link.innerHTML="<p><a href='" + path + "'>static state link</a></p>";

   }

   function moveSquare() {
      var move = parseInt(document.getElementById("move").getAttribute("data-
state"));
      move+=100;
      document.getElementById("square").style.left=move + "px";
      document.getElementById("move").setAttribute("data-state", move);
      updateURL();
   }

   function resizeSquare() {
      var size = parseInt(document.getElementById("size").getAttribute("data-
state"));
      size+=50;
      var square = document.getElementById("square");
      square.style.width=size + "px";
      square.style.height=size + "px";
      document.getElementById("size").setAttribute("data-state",size);
      updateURL();
    }

   function changeColor() {
     var color = document.getElementById("color").getAttribute("data-state");
     var hexcolor;
     if (color == "0000ff") {
       hexcolor="ffff00";
     } else {
       hexcolor = "0000ff";
     }
     document.getElementById("square").style.backgroundColor="#" +
hexcolor;
     document.getElementById("color").setAttribute("data-state",hexcolor);
     updateURL();
   }


</script>
</head>
<body>
  <button id="move" data-state="0">Move Square</button>
  <button id="size" data-state="100">Increase Square Size</button>
  <button id="color" data-state="#ffff00">Change Color</button>
  <div id="link"></div>
  <div id="square">
    <p>This is the object</p>
  </div>
</body>

Figure 20-1 shows the web page after several changes to the square element, and after the page is reloaded using the link.

Page after reloading and using persistence through URL

Figure 20-1. Page after reloading and using persistence through URL

See Also

Recipes 8.7 and 8.8 demonstrate how to use the location.hash property to store state in the URL and return to that state when the page is reloaded. The query string routine in the example is described at http://www.netlobo.com/url_query_string_javascript.html.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required