Sencha Touch version tested:
  • 1.1.1

Platform tested against:
  • iOS 5
  • Chrome 17 on XP

  • Ext.urlDecode does not decode the + (plus sign) as a space.

    Let me back up and say I was a little torn on whether to file this as a bug or a feature request. If the purpose of urlDecode is to simply decode URLs (or more specifically, URIs), then there really is no "bug" because the URI standards don't say much on topic.

    However, if the purpose of urlDecode is to decode query parameters that are originally passed in via a URL, I'd consider this very lacking behavior. While it is also completely harmless to encode a space as %20, both the html4 and html5 specs for application/x-www-form-urlencoded data say that the "right" way to do it is to encode space as "+".

    Since that's the only defined way of building query params, that's the way a whole lot of applications are going to pass those params. Hence when interacting with other applications, you might get your parameters with +s instead of %20s.

    Now, if you're only EVER using Ext.urlDecode() to decode something that Ext.urlEncode() encoding (meaning you're not interacting with anything), you're completely safe.

    There's a pretty good discussion of all the issues here:

    He basically came to the same conclusions I did in the sections "2. Query String Standards (or the Lack Thereof)" and "3.1. The Built-In Functions Are Not Meant for Query Strings". He also suggested the same workaround I have. Basically, you just replace the +s with spaces before calling the underlying decodeURIComponent() function.

Test Case:

Steps to reproduce the problem:
  • Run the above code on the console

The result that was expected:
  • one two three

The result that occurs instead:
  • one+two+three

Possible fix:
  urlDecode : function(string, overwrite) {
      if (Ext.isEmpty(string)) {
          return {};

      var obj = {},
          pairs = string.replace(/\+/g, ' ').split('&'),
          d = decodeURIComponent,

      Ext.each(pairs, function(pair) {
          pair = pair.split('=');
          name = d(pair[0]);
          value = d(pair[1]);
          obj[name] = overwrite || !obj[name] ? value : [].concat(obj[name]).concat(value);

      return obj;