WWW FAQs: How do I pass data between JavaScript pages?

2007-02-09: Your JavaScript page has retrieved some information from the user. Now you want to display another JavaScript page, which should also use that information. How do you pass it from the first page to the second? There are three simple solutions. The first two are safe and effective, with advantages and disadvantages to each. The third appears ideal but has a very serious security problem and should be avoided.

1. Submitting form data to a server-side script that then outputs a new JavaScript page containing the data. This is simple and reliable and works in all browsers, but requires support for server-side scripting of some kind (PHP, ASP, etc).

2. Passing form-style data in a URL to a new JavaScript page, without using any server-side scripts. This works in all browsers but supports a limited amount of data. It is the traditional way of solving the problem without server-side scripting.

3. Passing data via the window.name property. Although this is not the intended purpose of window.name, it seems to work quite well and supports larger amounts of data than the second method. And it works in Safari, Firefox, and Internet Explorer. So why not use it? Because it is highly insecure! If the user follows a link to another website that doesn't belong to you, that other website can still see the data stored in window.name, which was never meant to be a secure, site-specific property. So I strongly discourage the use of this method.

When possible, it's best to use the first method, because the amount of data you can pass is essentially unlimited. I'll demonstrate the first two methods and give an overview of the third, but as I said, the third is unsafe and you should not use it.

1. Using a Server-Side Script

When server-side scripting is available, this is the best approach. Let's assume you have a JavaScript array of strings you'd like to pass to a new web page:

<script>
var data = new Array();
data[0] = "one, a datum";
data[1] = "two, a deer";
data[2] = "three, a slash: \\";
data[3] = "four has quotes: \"I forget what four was for\"";
</script>

To pass this array to a script on a new page without packing it into a long URL (remember, URLs are limited to a practical maximum of 2,083 characters in the most popular web browser, and long URLs don't look very pretty either), we can use a hidden form in the first page, and submit this form to a PHP script on the server using the POST method. The GET and POST methods differ in that a GET-method form submission packs everything in the URL, which is nice for bookmarkable searches but a poor choice for large amounts of data. The POST method submits the data outside of the URL, without a length limit.

You could call the sendData function from any JavaScript code. Calling it when a link is clicked is simply one example.
We'll use a hidden field in the hidden form to pass the information. A hidden form field is a single string, so we'll pack the array into it by using a comma to separate elements of the array. And since the data might also contain commas, we'll use JavaScript's escape() function to encode these, so that they can't be confused with our separators. We'll name both the form and the hidden field within it data. When we do this, we access set the contents of the hidden field using the JavaScript syntax document.data.data.value (read from right to left: the value of the field named data, in the form named data, in the document).
Want to test this technique on your own computer? You'll need a web server with PHP support on your computer. PHP can't be tested on your local hard drive, because PHP is a server side solution. See How do I test PHP, ASP, server side include and CGI pages offline or at home?
The two listings that follow are passdata1a.html and passdata1b.php. passdata1a.html passes an array of JavaScript data to passdata1b.php when a link is clicked.

passdata1a.html

<script>
var data = new Array();
data[0] = "one, a datum";
data[1] = "two, a deer";
data[2] = "three, a slash: \\";
data[3] = "four has quotes: \"I forget what four was for\"";
</script>
<form name="data" method="POST" action="passdata1b.php">
<input type="hidden" name="data">
</form>
<script>
function sendData()
{
  // Initialize packed or we get the word 'undefined'
  var packed = "";
  for (i = 0; (i < data.length); i++) {
    if (i > 0) {
      packed += ",";
    }
    packed += escape(data[i]);
  }
  document.data.data.value = packed;
  document.data.submit();
}
</script>
<h1>This is what the array contains:</h1>
<ul>
<script>
  for (i = 0; (i < data.length); i++) {
    document.write("<li>" + data[i] + "</li>\n");
  }
</script>
</ul>
<a href="javascript:sendData();">Go to passdata1b.php</a>

passdata1b.php

<?php
  $packed = $_POST['data'];
  $data = split(",", $packed);
  for ($i = 0; ($i < count($data)); $i++) {
    # Undo what JavaScript's escape() function did
    $data[$i] = rawurldecode($data[$i]);
    # Slashes need escaping when they appear in code
    $data[$i] = str_replace("\\", "\\\\", $data[$i]);
    # Quotes need escaping too
    $data[$i] = str_replace("\"", "\\\"", $data[$i]);
  }
?>
<script>
  var data = new Array (
<?php
  for ($i = 0; ($i < count($data)); $i++) {
    if ($i > 0) {
      echo ",\n";
    }
    echo "    \"";
    echo $data[$i];
    echo "\"";
  }
?>

  );
</script>
<h1>This is what the data contains:</h1>
<ul>
<script>
  for (i = 0; (i < data.length); i++) {
    document.write("<li>" + data[i] + "</li>\n");
  }
</script>
</ul>

2. Using JavaScript Only: Data in the URL

When server-side scripting is not available, it is still possible to pass data between web pages, either via the "query string" (the portion of the URL after the ?) or the window.name property. First we'll look at how to do it via the query string.

The main problem with the query string approach is that the amount of data you can pass is limited. The maximum total safe length of a URL is 2,083 characters, and "escaping" of data like whitespace and punctuation will consume quite a bit of this space. So this technique should be used only for small amounts of information. For larger amounts, use the PHP technique demonstrated above a similar technique based on ASP or Perl, or the window.name technique at the end of this article. Just keep in mind that server-side scripting is always preferable for passing large amounts of data.

Implementing the Query String Solution

When web servers see a URL that specifies an ordinary HTML web page, followed by a ? character, followed by additional data, like this:

http://www.example.com/page.html?this%20is%20some%20data

They deliver the file /page.html to the browser and ignore the ? and the data beyond it. However, this data is available to JavaScript code in page.html, in the variable window.location.search.

Even though this technique uses only JavaScript, you cannot test this using two HTML pages on your own hard drive in Internet Explorer unless you have a web server on your own computer -- a simple and useful thing to have, and I recommend setting one up for testing purposes. Test this technique with your pages on a web server, not just your hard drive. Or test it in Firefox, which allows URLs with a ? to work correctly for JavaScript pages on the local hard drive.
Again, let's assume you have a JavaScript array of strings you'd like to pass to a new web page:

<script>
var data = new Array();
data[0] = "one, a datum";
data[1] = "two, a deer";
data[2] = "three, a slash: \\";
data[3] = "four has quotes: \"I forget what four was for\"";
</script>

We can pass this data to a second page by packing the array into a single string, "escaping" each of the array elements with JavaScript's escape() function and then separating them with commas. We then send the browser to a new page by setting window.location to passdata2b.html (the name of the new page), followed by a ? character, followed by our packed string. In the second page, we'll find the data in window.location.search and break it back into separate array elements with the split() function, and then use unescape() to restore each of these elements to their normal appearance.

The two listings that follow are passdata2a.html and passdata2b.html. passdata2a.html passes an array of JavaScript data to passdata2b.html when a link is clicked.

passdata2a.html

<script>
var data = new Array();
data[0] = "one, a datum";
data[1] = "two, a deer";
data[2] = "three, a slash: \\";
data[3] = "four has quotes: \"I forget what four was for\"";
</script>
<script>
function sendData()
{
  // Initialize packed or we get the word 'undefined'
  var packed = "";
  for (i = 0; (i < data.length); i++) {
    if (i > 0) {
      packed += ",";
    }
    packed += escape(data[i]);
  }
  window.location = "passdata2b.html?" + packed;
}
</script>
<h1>This is what the array contains:</h1>
<ul>
<script>
  for (i = 0; (i < data.length); i++) {
    document.write("<li>" + data[i] + "</li>\n");
  }
</script>
</ul>
<a href="javascript:sendData();">Go to Page Two</a>

passdata2b.html

<script>
  var query = window.location.search;
  // Skip the leading ?, which should always be there,
  // but be careful anyway
  if (query.substring(0, 1) == '?') {
    query = query.substring(1);
  }
  var data = query.split(',');
  for (i = 0; (i < data.length); i++) {
    data[i] = unescape(data[i]);
  }
</script>
<h1>This is what the array contains:</h1>
<ul>
<script>
  for (i = 0; (i < data.length); i++) {
    document.write("<li>" + data[i] + "</li>\n");
  }
</script>
</ul>

3. Using JavaScript Only: window.name

The query string solution is the traditional way to pass data without server side scripting, but it supports a limited amount of data. Recently another alternative has gained popularity: the window.name property.

The original purpose of window.name is not to pass data between pages. The idea is that a browser window (or tab) can be given a name that can then be used to refer to that window later. For instance, the window.open function can be used to open a new page in an existing popup window by specifying its name.

However, clever programmers have noticed that the window.name property can be changed by JavaScript code and has no apparent fixed length limit. So why not use it to pass data between pages?

There are three downsides to this approach. The first two have simple workarounds, but the third is a fatal security flaw:

A. Internet Explorer rejects special characters in window.name. So you can't trust line breaks (carriage returns) or binary data to stick around in window.name. We handle this issue the same way we handle it for the query string: by "escaping" our data.

B. If you are using window.name to pass data around, then you no longer have the option of using it to refer to the window in window.open calls and so on. You could work around this by removing the data from window.name after you parse it, but then the data is no longer available if the user reloads the page. Depending on your needs, this may or may not be a serious issue for your purposes.

C. Once the data is in window.name, it stays there even if the user follows a link to a completely different website. This is extremely dangerous - especially if there is personal information included in the data! Please do not use this method.

A few developers may feel that window.name is safe for use in their application because there will never be any personal information passed. This is almost always a mistake - you don't know how users will choose to use your web application, and what they will hold you responsible for if things go badly wrong.

If you do choose to use window.name to pass data, note that the window.name property is not available to JavaScript code that executes while the page is still loading. You will need to access it from a function called by the onLoad handler of the body element.

Share |

Legal Note: yes, you may use sample HTML, Javascript, PHP and other code presented above in your own projects. You may not reproduce large portions of the text of the article without our express permission.

Got a LiveJournal account? Keep up with the latest articles in this FAQ by adding our syndicated feed to your friends list!


Follow us on Twitter | Contact Us

Copyright 1994-2014 Boutell.Com, Inc. All Rights Reserved.