How to do proper URL Encoding in Javascript when using window.open()

In some cases you might want to do encoding of URL-parameters directly inside javascript, simply because you think it’s best to do it there or because you have no other options of getting the parameters encoded. But as I discovered when trying to do this myself, doing this in javascript is not like a walk in the park, or at least there are some important “black holes” you should be aware of.

In my example I use JSF, and I have a h:dataTable component which I build up programmatically in java. For each row I have a link that will open a new popup window that points to another page (jsp) passing some parameters. I needed to do javascript-encoding of parameters, because when I build my table I use expression language (EL – #{} ) and valueBindings (for those of you that are familiar with it). If you use expressions you don’t hold the value itself, but the expression will be “decoded” run-time when the page is rendered.

To show an example, I have a Java-class that has a hashmap called properties, an ordinary key-value thing. By using a get-method that returns the whole map it’s possible through EL to give an “input-parameter” on which property to get. My get-method:

public Map<String, Object> getProperties()
{
	return properties;
}

this would be the expression to get the url:

String url = "#{row.properties['"+SOME_KEY_THAT_POINTS_TO_OBJECT_WITH_URL+"']}";

And then I would create my link in java with value-binding like this:

HtmlOutputLink htmlOutputLink = new HtmlOutputLink();
ValueBinding vb = FacesContext.getCurrentInstance().getApplication().createValueBinding(
"popupWindow('"+ url +"','MY_POPUP_WINDOW', WIDTH,HEIGHT); return false;");
htmlOutputLink.setValueBinding("onclick",vb);

The “normal” way of doing encoding java-side would be something like this:

public String urlEncode(String urlToEncode)
{
	String encodedUrl = "";
	if(urlToEncode != null)
	{
		try
		{
 			encodedUrl = URLEncoder.encode(urlToEncode,"UTF-8");
		}
		catch (Exception e)
 		{
			log.error("Encode exception when encoding url: " + urlToEncode,e);
 			return urlToEncode; //Return unencodedUrl
		}

		return encodedUrl;
	}
}

But in my case, if I were to encode the url before passing it to the javascript, what I would encode would actually be my expression, not the value of it. The result of this encoding would be something like;

 %23%7Brow.properties%5B%27SOME_KEY_THAT_POINTS_TO_OBJECT_WITH_URL%27%5D%7D.

Thus, I was in the need of doing the encoding after the page has been rendered, and then I needed to do it inside the javascript.

I tried two different approaches for encoding the url, the first one which I expected would work, and the second one which I had to do to make it work. What you need to be aware of is that default encoding in javascript is the UTF-8 format, so if you try to decode “on the other side” you have to use UTF-8 in your decoder. I’ve also seen some examples around saying that the escape()-function does some sort of encoding, but this one just escapes (replaces) special characters, for example it converts white-spaces to %20%. Trying to use escape() on the URL and then decoding it with an URL-decoder would fail! Still, I found the need of using the escape()-function as well, and will explain this as I go.

The first function I tried uses the encodeURI()-function inside javascript directly:

function encodeUrl(url)
{
	return encodeURI(url);
}

And from my popupWindow()-function I call the encodeUrl() like this:

var newWindow = '';
function popupWindow(url, name, width, height)
{
	name = name.replace(/\/|\-|\./gi, "");
	var whitespace = new RegExp("\\s","g");
	name = name.replace(whitespace,"");
	if (!newWindow.closed && newWindow.location)
	{
		newWindow.location.href = encodeUrl(url);
	}
	else
	{
		newWindow = window.open(encodeUrl(url),name, "location=no, scrollbars=yes, resizable=yes, toolbar=no, menubar=no, width=" + width + ", height=" + height );
		if (!newWindow.opener)
			newWindow.opener = self;
	}
	if (window.focus)
	{
		newWindow.focus()
	}
}

But doing it like this the decoding seemed to fail, as I couldn’t get the proper value from the url on the receiving side (decodedValue != encodedValue). Having struggled with this one for some time, I discovered that the window.open()-function actually tries to do some sort of decoding of the url itself before it passes it on. So I created another method that encodes on parameter level, and which also uses the escape-method to “protect” the encoded parameters from the window.open()-function.

function encodeUrl(url)
{
 	if (url.indexOf("?")>0)
 	{
		encodedParams = "?";
 		parts = url.split("?");
 		params = parts[1].split("&");
 		for(i = 0; i < params.length; i++)
 		{
			if (i > 0)
	 		{
				encodedParams += "&";
			}
			if (params[i].indexOf("=")>0) //Avoid null values
			{
				p = params[i].split("=");
				encodedParams += (p[0] + "=" + escape(encodeURI(p[1])));
			}
			else
			{
				encodedParams += params[i];
			}
		}
		url = parts[0] + encodedParams;
	}
	return url;
}

One thing to mention in this function is that is uses the encodeURI()-function. This one doesn’t do anything with the reserved characters like ; , / ? : @ & = + $. If you for some reason need to encode these as well, you should use the encodeURIComponent()-function.I tried to do this function without the use of escape(), but then the parameters “arrived” wrongly encoded, and became “corrupted” after I decoded them. Wrapping the encodeURI() inside an escape() solved this problem:

encodedParams += (p[0] + "=" + escape(encodeURI(p[1])));

Finally, inside my receiving page, I managed to decode the parameters and get the values I actually submitted with a java decoding method like this:

public String urlDecode(String urlToDecode)
{
	String decodedUrl = "";
 	if(urlToDecode != null)
 	{
 		try
 		{
 			decodedUrl = URLDecoder.decode(urlToDecode,"UTF-8");
 		}
 		catch (Exception e)
 		{
 			log.error("INVALID URL: " + urlToDecode,e);
 			return "";
 		}
 	}
	return decodedUrl;
}

This way of doing it also works for special characters belonging to the ISO-8859-1 encoding, even if the encoding used is actually UTF-8. As a small reference I can list the proper UTF-8 encoding for the Scandinavian specific characters if you use those, in this way you should be able to check whether your URL is encoded correctly or not if you print it out before decoding it.

  • æ = %E6
  • ø = %F8
  • å = %E5
  • Æ = %C6
  • Ø = %D8
  • Å = %C5

You can also check out this page for a complete reference of encoded characters: http://www.w3schools.com/tags/ref_urlencode.asp

If you want to try an example of how encodeURI and encodeURIComponent works, copy and paste the following javascript and test with your own strings:


<script type="text/javascript">

                var unencodedText = "This is my text that contains whitespaces and characters like # and Ø";
                var encodedText = "";
                var decodedText = "";
                alert('unencodedText: ' + unencodedText);

                //To encode whitespaces and the 'Ø' character - use encodeURI
                encodedText = encodeURI(unencodedText);
                //We see that whitespaces and 'Ø' are encoded, but the '#' is still there:
                alert('encodedText: ' + encodedText);

                //If we decode it we should get our unencodedText back
                decodedText = decodeURI(encodedText);
                alert('decodedText: ' + decodedText);

                //To also encode the '#' we use the encodeURIComponent
                encodedText = encodeURIComponent(unencodedText);
                //Now all the characters have been encoded:
                alert('encodedText: ' + encodedText);

                //To get our unencodedText back we now need to use the decodeURIComponent
                decodedText = decodeURIComponent(encodedText);
                alert('decodedText: ' + decodedText);

            </script>

I hope that you might find this post useful, and that it might save you from some pain in the a** if you try to use the encoding capabilities of Javascript.

Advertisements

22 Responses to “How to do proper URL Encoding in Javascript when using window.open()”

  1. Open a popup window in Javascript with window.open - crossbrowser solution « Eivind’s Weblog Says:

    […] also use an encodeUrl()-function I created.I’ve talked about it in another post on this blog (How to do proper url encoding), but list it here for […]

  2. Rob Says:

    I have some problems with decodeUrl() function + javascript + URL containing unicode characters. Just a question: have I to convert those decoded URLs into escaped unicode javascript too? (\uXXXX format)

  3. roneiv Says:

    Hi!

    Unfortunately I’m not too familiar with unicode. But if you are trying to pass a url that contains character combinations like \u0001 I would use encodeURIComponent instead of encodeURI. encodeURIComponent (http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Functions:encodeURIComponent)
    escapes all characters except – _ . ! ~ * ‘ ( ) Then of course you would also have to decode using the decodeURIComponent. 🙂

    I’m not sure if I fully understand your question, but the information I provided here might help you a bit.

  4. ae Says:

    Hi, i have problems when escape character # (%23) and i have querystring with several #: %23%23%23..

    I call aspx page, and get querystring and decode it (UrlDecode) but character %23 (#) dissapears .

    any idea ?? thanks.

  5. roneiv Says:

    Hi ae!

    What function do you use to encode? Do you do it in java (or some other programming language) or do you do encoding in javascript?

    If you check my post again I’ve added a small javascript function at the bottom that might give you an idea of how things work and what you could do. 🙂

    My guess would be that either your ‘#’ is not encoded before it’s sent, or the application container/framework does some decoding by itself before the url reaches your decode method. This would cause characters like ‘#’ to be removed.

    Try to debug your querystring before sending it, check that all characters are encoded as you want it to be. Then debug on the other side before you pass it to the decode-method. The querystring should still be encoded at this point. If it is not, you could try to do a double encoding (encode your string, then encode the encoded string again) before you send it. When working with some frameworks I’ve been forced to do it like this to make sure that my parameters still are encoded when I get them on the other side.

    Good luck!

  6. Blossom Says:

    Hi,
    Your example is very useful to me, Thanks a lot =D

  7. Sean Says:

    Wow… you are the man. Thanks for this – it was a huge, huge help. 🙂

  8. name Says:

    Good day!,

  9. Peter Says:

    Thanks, man! You solved exactly the problem what I had today.

  10. Ugulino Says:

    WOW, it was great! Amazing solution! It was exactly what I was looking for. Great job!

  11. Suhas Says:

    Hi,

    Thanks for this useful information. I am using AJAX submission with UTF data. Your encode and decode methods are perfect.

  12. Selva Says:

    Hey thanks man … It was very usefull information . good post on Encode and Decode functions.

  13. name Says:

    really great sites, thank you,

  14. M Subrahmanyam Says:

    Thank alot for your explanation.
    I was having the same problem and had been trying to find the solution for this.
    Luckly I found this link. It solved my problem.

    Thanks again
    Subrahmanyam

    • Kim Says:

      Excellant! But what happens when the text to be sent itself has & or ? or = within it. These get seen as a separator and do not correctly arrive after posting.

  15. Diju Says:

    Hey thanks man………….It solved my problem by doing a small modification in JavaScript function
    encodedParams += (p[0] + “=” + encodeURI(p[1]));

    I have removed escape() from the above line.

    Thanks again……………….

  16. » Misc Programming Tips Ordinary Mind Says:

    […] How to do proper URL Encoding in Javascript when using window.open() […]

  17. Gozzie Says:

    Hi,

    Great post and very useful (a lifesaver especially in my case as a native speaker of a language with lots of special characters)

    One simple question though: When using the server-side url decoding function, which java libraries should I import?

  18. Stephane Says:

    Hi ,

    Thanks for your post !!

    Unfortunatly there is a problen in your function encodeUrl. If the input url contains an anchor (http://blah blah blah#anchor) the encodeurl function encodes the # character which is transformed in %23 (or something). That prevents the url to be correctly processed :
    – the anchor is not processed by the browser
    – in the case where the # anchor character is preceded by a param=value, on the web server the value of parameter param is not “value” as it should be but value#anchor which may lead to incorrect processing.

  19. flashflex Says:

    For URL encoding, to convert URL to safe format

    URL Encoding

  20. Yash Says:

    Hi ,
    My application is using newWin(url) java script function to open one search page. i am passing Unicode character as request parameter in url. i am getting correct value when i retrieve parameter in production environment However i am getting incorrect value in dev environment. I tried this in different different machine every where behavior is same.

    Ip – > “検証されない ステムが検証されない ” and o/p comes like “検証されない ステムが検証されない”

    Please help me.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: