diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_js.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_js.xml
index 583b2318a38f1b15e9b04e902668799774cd0a95..256778d2d0726cfcf60a20c859567e5fb7703bd0 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_js.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_js.xml
@@ -501,8 +501,8 @@
         declared_method_list.push(item);\n
       }  \n
       return RSVP.all([\n
-        declared_method_list,\n
-        gadget.getDeclaredMethodList()\n
+        declared_method_list //,\n
+        // gadget.getDeclaredMethodList()\n
       ]); \n
     })\n
 \n
@@ -896,7 +896,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.46204.46630.51746</string> </value>
+                <value> <string>946.46289.58152.58624</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -914,7 +914,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445960753.22</float>
+                        <float>1446475754.4</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_form_js.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_form_js.xml
index f1f357534c1544acbc3b25ebe80b3d5b51feeabb..cd788412c574026cecc901ed98b278d09ad9d90f 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_form_js.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_form_js.xml
@@ -205,12 +205,16 @@
             if(gadget_list.length > 0) {\n
               var page_type = fetchPageType(gadget_list[0]);\n
               return gadget.redirect({\n
-                page: page_type,\n
-                appcache_url: appcache_url\n
+                command: \'change\',\n
+                options: {\n
+                  page: page_type,\n
+                  appcache_url: appcache_url\n
+                }\n
               });\n
             } else {\n
               return gadget.redirect({\n
-                found: false\n
+                command: \'change\',\n
+                options: {found: false}\n
               });\n
             }\n
           });\n
@@ -361,7 +365,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.46360.38047.28279</string> </value>
+                <value> <string>946.46361.42674.38161</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -379,7 +383,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445965059.05</float>
+                        <float>1446476000.92</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_report_js.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_report_js.xml
index 2810b58b7ef2a089d53523074fcc9afe8af160e9..8994cd1ea07cd5c45a48585e49a66770af95a7f4 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_report_js.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_page_report_js.xml
@@ -200,7 +200,7 @@
   }\n
 \n
   function updateReportData(gadget, report_data) {\n
-    var id = "#" + report_data.id,\n
+    var id = "#" + report_data.id.replace(\'/\',\'\\\\/\'),\n
       update_element = gadget.props.content_element.querySelector(id),\n
       interface_data = \'\',\n
       validation_status = report_data.validation_status,\n
@@ -299,7 +299,8 @@
           return validateAppGadgetList(gadget, gadget_list);\n
         }, function(error) {\n
           return gadget.redirect({\n
-            found: false\n
+            command: \'change\',\n
+            options: {found: false, page: \'form\'}\n
           });\n
         });\n
     })\n
@@ -472,7 +473,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.46341.46226.26060</string> </value>
+                <value> <string>946.49108.59205.8413</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -490,7 +491,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445965003.93</float>
+                        <float>1446476069.46</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_html.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_html.xml
index 1263d5ffb0f8268c7867a77ed39204cdbb2bc52e..9cf69f51322b7e5789c5db619afced4e0598ddf4 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_html.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_html.xml
@@ -140,7 +140,7 @@
     <script id="panel-template-body" type="text/x-handlebars-template">\n
       <div class="ui-content">\n
         <ul data-role="listview" class="ui-listview">\n
-          <li><a href="#page=form" data-i18n="Interface Validation Form">Interface Validation Form</a></li>\n
+          <li><a href="#/?page=form" data-i18n="Interface Validation Form">Interface Validation Form</a></li>\n
         </ul>\n
       </div>\n
     </script>\n
@@ -289,7 +289,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.44766.36269.12373</string> </value>
+                <value> <string>946.44825.62507.52206</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -307,7 +307,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445872917.21</float>
+                        <float>1446476148.07</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_js.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_js.xml
index 14b426f200ff908ed0053bb20cae76601e4f09a2..5e94173b9d112db094d4d4b6ec865d307c90e02d 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_js.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_panel_js.xml
@@ -156,6 +156,10 @@
     .declareMethod(\'toggle\', function () {\n
       this.props.jelement.panel("toggle");\n
     })\n
+\n
+    .declareMethod(\'close\', function () {\n
+      this.props.jelement.panel("close");\n
+    })\n
 \n
     .declareMethod(\'render\', function () {\n
       return;\n
@@ -334,7 +338,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.44742.21501.55296</string> </value>
+                <value> <string>946.44742.30838.38775</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -352,7 +356,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445867908.17</float>
+                        <float>1446476219.73</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_html.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_html.xml
index 3cc31c9d4d3c82fdcaf339c1193976390964c453..92e4605a2ab3a5908882d6e9687fa989fe6edbfd 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_html.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_html.xml
@@ -121,6 +121,7 @@
 \n
   </head>\n
   <body>\n
+    <div data-gadget-url="gadget_jio.html" data-gadget-scope="jio_selection"></div>\n
   </body>\n
 </html>
 
@@ -259,7 +260,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.44747.45157.45653</string> </value>
+                <value> <string>946.44766.54929.30600</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -277,7 +278,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445869370.23</float>
+                        <float>1446476270.36</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_js.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_js.xml
index 5b129bb75c338389b2d39300bc52c4447bfc7d37..0091140631d412d84ecf618b138d7dc1b37ca137 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_js.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_page_module/gadget_interface_validator_router_js.xml
@@ -101,60 +101,567 @@
             <key> <string>text_content</string> </key>
             <value> <string encoding="cdata"><![CDATA[
 
-/*global window, rJS */\n
-/*jslint nomen: true, indent: 2, maxerr: 3*/\n
-(function (window, rJS) {\n
+/*global window, rJS, RSVP, loopEventListener, document, jIO */\n
+/*jslint nomen: true, indent: 2 */\n
+(function (window, rJS, RSVP, loopEventListener, document, jIO) {\n
   "use strict";\n
 \n
-  var gadget_klass = rJS(window),\n
-    MAIN_PAGE_PREFIX = "gadget_interface_validator_",\n
-    DEFAULT_PAGE = "form";\n
+  // Keep reference of the latest allDocs params which reach to this view\n
+  // var SELECTION_KEY = "s",\n
+  // Keep reference in the global navigation pattern\n
+  // HISTORY KEY = "h"\n
+  // Current display parameter\n
+  // DISPLAY KEY = "d"\n
+  var PREVIOUS_KEY = "p",\n
+    NEXT_KEY = "n",\n
+    PREFIX_DISPLAY = "/",\n
+    PREFIX_COMMAND = "!",\n
+    // PREFIX_ERROR = "?",\n
+    COMMAND_DISPLAY_STATE = "display",\n
+    COMMAND_CHANGE_STATE = "change",\n
+    COMMAND_INDEX_STATE = "index",\n
+    COMMAND_SELECTION_PREVIOUS = "selection_previous",\n
+    COMMAND_SELECTION_NEXT = "selection_next",\n
+    COMMAND_HISTORY_PREVIOUS = "history_previous",\n
+    COMMAND_PUSH_HISTORY = "push_history",\n
+    VALID_URL_COMMAND_DICT = {},\n
+    DEFAULT_PAGE = \'form\';\n
+  VALID_URL_COMMAND_DICT[COMMAND_DISPLAY_STATE] = null;\n
+  VALID_URL_COMMAND_DICT[COMMAND_CHANGE_STATE] = null;\n
+  VALID_URL_COMMAND_DICT[COMMAND_INDEX_STATE] = null;\n
+  VALID_URL_COMMAND_DICT[COMMAND_SELECTION_PREVIOUS] = null;\n
+  VALID_URL_COMMAND_DICT[COMMAND_SELECTION_NEXT] = null;\n
+  VALID_URL_COMMAND_DICT[COMMAND_HISTORY_PREVIOUS] = null;\n
+  VALID_URL_COMMAND_DICT[COMMAND_PUSH_HISTORY] = null;\n
 \n
-  gadget_klass\n
-    .declareAcquiredMethod(\'pleaseRedirectMyHash\', \'pleaseRedirectMyHash\')\n
-    .declareAcquiredMethod(\'jio_get\', \'jio_get\')\n
+  //////////////////////////////////////////////////////////////////\n
+  // Change URL functions\n
+  //////////////////////////////////////////////////////////////////\n
+  function changeState(hash) {\n
+    // window.location = hash;\n
+    return window.location.replace(hash);\n
+  }\n
 \n
-    .ready(function (gadget) {\n
-      gadget.props = {};\n
-    })\n
-    .declareMethod(\'route\', function (options) {\n
-      var gadget = this;\n
-      gadget.options = options;\n
-      if (options.jio_key === undefined || options.jio_key === \'\') {\n
-        if (options.page === undefined || options.page === \'\' || options.page === "document_list") {\n
-          options.page = DEFAULT_PAGE;\n
+  function synchronousChangeState(hash) {\n
+    changeState(hash);\n
+    // prevent returning unexpected response\n
+    // wait for the hash change to occur\n
+    // fail if nothing happens\n
+    return RSVP.timeout(\'5000\');\n
+  }\n
+\n
+  //////////////////////////////////////////////////////////////////\n
+  // Selection functions\n
+  //////////////////////////////////////////////////////////////////\n
+  function getSelection(gadget, selection_id) {\n
+    return gadget.props.jio_gadget.get(selection_id)\n
+      .push(function (result) {\n
+        return result.data;\n
+      });\n
+  }\n
+\n
+  function getHistory(gadget, history_id) {\n
+    var previous_id;\n
+    return gadget.props.jio_gadget.get(history_id)\n
+      .push(function (history) {\n
+        previous_id = history.previous_history_id;\n
+        return gadget.props.jio_gadget.get(history.options_id);\n
+      })\n
+      .push(function (result) {\n
+        return [result, previous_id];\n
+      }, function (error) {\n
+        // XXX Check if 404\n
+        if ((error instanceof jIO.util.jIOError) &&\n
+            (error.status_code === 404)) {\n
+          return [{data: {}}, undefined];\n
         }\n
-        return {\n
-          url: MAIN_PAGE_PREFIX + "page_" + options.page + ".html",\n
-          options: options\n
+        throw error;\n
+      });\n
+  }\n
+\n
+  function addHistory(gadget, options, previous_selection_id) {\n
+    var options_blob = {\n
+      type: "options",\n
+      data: options\n
+    },\n
+      blob_id;\n
+\n
+    return gadget.props.jio_gadget.post(options_blob)\n
+      .push(function (result) {\n
+        blob_id = result;\n
+        return gadget.props.jio_gadget.get(previous_selection_id)\n
+          .push(undefined, function () {\n
+            previous_selection_id = undefined;\n
+          });\n
+      })\n
+      .push(function () {\n
+        var data_history = {\n
+          type: "history",\n
+          options_id: blob_id,\n
+          previous_history_id: previous_selection_id\n
         };\n
+        return gadget.props.jio_gadget.post(data_history);\n
+      })\n
+      .push(function (id) {\n
+        return id;\n
+      });\n
+  }\n
+\n
+  function addSelection(gadget, options) {\n
+    var data_blob = {\n
+      type: "selection",\n
+      data: options\n
+    };\n
+    return gadget.props.jio_gadget.post(data_blob);\n
+  }\n
+\n
+  //////////////////////////////////////////////////////////////////\n
+  // Build URL functions\n
+  //////////////////////////////////////////////////////////////////\n
+  function getCommandUrlFor(gadget, command, options) {\n
+    var result = "#" + PREFIX_COMMAND + (command || ""),\n
+      prefix = "?",\n
+      key,\n
+      tmp_dict;\n
+    tmp_dict = gadget.props.options;\n
+    for (key in tmp_dict) {\n
+      if (tmp_dict.hasOwnProperty(key)) {\n
+        if (tmp_dict[key] === undefined) {\n
+          tmp_dict[key] = \'\';\n
+        }\n
+        result += prefix + PREVIOUS_KEY + "." + encodeURIComponent(key) + "=" + encodeURIComponent(tmp_dict[key]);\n
+        prefix = "&";\n
+      }\n
+    }\n
+    for (key in options) {\n
+      if (options.hasOwnProperty(key)) {\n
+        if (options[key] === undefined) {\n
+          options[key] = \'\';\n
+        }\n
+        result += prefix + NEXT_KEY + "." + encodeURIComponent(key) + "=" + encodeURIComponent(options[key]);\n
+        prefix = "&";\n
+      }\n
+    }\n
+    return result;\n
+  }\n
+\n
+  function getDisplayUrlFor(jio_key, options) {\n
+    var prefix = \'?\',\n
+      result,\n
+      key;\n
+    result = "#" + PREFIX_DISPLAY + (jio_key || "");\n
+    for (key in options) {\n
+      if (options.hasOwnProperty(key) && options[key] !== undefined) {\n
+        // Don\'t keep empty values\n
+        result += prefix + encodeURIComponent(key) + "=" + encodeURIComponent(options[key]);\n
+        prefix = \'&\';\n
+      }\n
+    }\n
+    return result;\n
+  }\n
+\n
+  //////////////////////////////////////////////////////////////////\n
+  // exec command functions\n
+  //////////////////////////////////////////////////////////////////\n
+  function execDisplayCommand(next_options) {\n
+    // console.warn(command_options);\n
+    var jio_key = next_options.jio_key;\n
+    delete next_options.jio_key;\n
+    // XXX Implement history management\n
+    return synchronousChangeState(\n
+      getDisplayUrlFor(jio_key, next_options)\n
+    );\n
+  }\n
+\n
+  function execChangeCommand(previous_options, next_options) {\n
+    var key,\n
+      jio_key;\n
+    for (key in previous_options) {\n
+      if (previous_options.hasOwnProperty(key)) {\n
+        if (!next_options.hasOwnProperty(key)) {\n
+          next_options[key] = previous_options[key];\n
+        }\n
+      }\n
+    }\n
+    for (key in next_options) {\n
+      if (next_options.hasOwnProperty(key)) {\n
+        if (!next_options[key]) {\n
+          delete next_options[key];\n
+        }\n
       }\n
-      return gadget.jio_get(options.jio_key)\n
-        .push(function (doc) {\n
-          var sub_options = {},\n
-            base_portal_type = doc.portal_type.toLowerCase().replace(/\\s/g, "_");\n
-          sub_options = {\n
-            doc: doc,\n
-            jio_key: options.jio_key,\n
-            search: options.search\n
-          };\n
-          if (base_portal_type.search(/_temp$/) >= 0) {\n
-            //Remove "_temp"\n
-            base_portal_type = base_portal_type.substr(\n
-              0,\n
-              base_portal_type.length - 5\n
+    }\n
+    jio_key = next_options.jio_key;\n
+    delete next_options.jio_key;\n
+    return synchronousChangeState(\n
+      getDisplayUrlFor(jio_key, next_options)\n
+    );\n
+  }\n
+\n
+  function execIndexCommand(gadget, previous_options, next_options) {\n
+    var jio_key = next_options.jio_key,\n
+      selection_options = {};\n
+    delete next_options.jio_key;\n
+    // selection_options.index = next_options.index;\n
+    selection_options.query = next_options.query;\n
+    selection_options.list_method_template = next_options.list_method_template;\n
+    // Store selection in local DB\n
+    return addSelection(gadget, selection_options)\n
+      .push(function (id) {\n
+        next_options.selection = id;\n
+        // XXX Implement history management\n
+        return addHistory(gadget, previous_options);\n
+      })\n
+      .push(function (id) {\n
+        next_options.history = id;\n
+        return synchronousChangeState(\n
+          getDisplayUrlFor(jio_key, next_options)\n
+        );\n
+      });\n
+  }\n
+\n
+  function execPushHistoryCommand(gadget, previous_options, next_options) {\n
+    var jio_key = next_options.jio_key;\n
+    delete next_options.jio_key;\n
+    // XXX Hack to support create dialog\n
+    delete previous_options.view;\n
+    delete previous_options.page;\n
+    return addHistory(gadget, previous_options)\n
+      .push(function (id) {\n
+        next_options.history = id;\n
+        return synchronousChangeState(\n
+          getDisplayUrlFor(jio_key, next_options)\n
+        );\n
+      });\n
+  }\n
+\n
+  function execSelectionNextCommand(gadget, previous_options) {\n
+    // Get the selection parameters\n
+    // Query all docs with those parameters + expected index\n
+    // Redirect to the result document\n
+    return getSelection(gadget, previous_options.selection)\n
+      .push(function (selection) {\n
+        return gadget.jio_allDocs({\n
+          "query": selection.query,\n
+          "list_method_template": selection.list_method_template,\n
+          "limit": [parseInt(previous_options.selection_index, 10) + 1, 1]\n
+        })\n
+          .push(function (result) {\n
+            if (result.data.rows.length === 0) {\n
+              return synchronousChangeState(\n
+                getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)\n
+              );\n
+            }\n
+            return synchronousChangeState(\n
+              getDisplayUrlFor(result.data.rows[0].id, {\n
+                selection: previous_options.selection,\n
+                selection_index: parseInt(previous_options.selection_index, 10) + 1,\n
+                history: previous_options.history\n
+              })\n
+            );\n
+          });\n
+      }, function (error) {\n
+        if ((error instanceof jIO.util.jIOError) &&\n
+            (error.status_code === 404)) {\n
+          return synchronousChangeState(\n
+            getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)\n
+          );        \n
+        }\n
+        throw error;\n
+      });\n
+  }\n
+\n
+  function execSelectionPreviousCommand(gadget, previous_options) {\n
+    // Get the selection parameters\n
+    // Query all docs with those parameters + expected index\n
+    // Redirect to the result document\n
+    return getSelection(gadget, previous_options.selection)\n
+      .push(function (selection) {\n
+        if (parseInt(previous_options.selection_index, 10) < 1) {\n
+          return synchronousChangeState(\n
+            getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)\n
+          );\n
+        }\n
+        return gadget.jio_allDocs({\n
+          "query": selection.query,\n
+          "list_method_template": selection.list_method_template,\n
+          "limit": [parseInt(previous_options.selection_index, 10) - 1, 1]\n
+        })\n
+          .push(function (result) {\n
+            if (result.data.rows.length === 0) {\n
+              return synchronousChangeState(\n
+                getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)\n
+              );\n
+            }\n
+            return synchronousChangeState(\n
+              getDisplayUrlFor(result.data.rows[0].id, {\n
+                selection: previous_options.selection,\n
+                selection_index: parseInt(previous_options.selection_index, 10) - 1,\n
+                history: previous_options.history\n
+              })\n
             );\n
+          });\n
+      }, function (error) {\n
+        if ((error instanceof jIO.util.jIOError) &&\n
+            (error.status_code === 404)) {\n
+          return synchronousChangeState(\n
+            getCommandUrlFor(gadget, COMMAND_HISTORY_PREVIOUS, previous_options)\n
+          );        \n
+        }\n
+        throw error;\n
+      });\n
+  }\n
+\n
+\n
+  function execHistoryPreviousCommand(gadget, previous_options) {\n
+    var history = previous_options.history;\n
+    if (history === undefined) {\n
+      return synchronousChangeState(\n
+        getDisplayUrlFor(undefined, {page: DEFAULT_PAGE})\n
+      );\n
+    }\n
+    return getHistory(gadget, previous_options.history)\n
+      .push(function (result_list) {\n
+        var options = result_list[0].data,\n
+          jio_key = options.jio_key;\n
+        delete options.jio_key;\n
+        return synchronousChangeState(\n
+          getDisplayUrlFor(jio_key, options)\n
+        );\n
+      });\n
+  }\n
+\n
+  //////////////////////////////////////////////////////////////////\n
+  // Command URL functions\n
+  //////////////////////////////////////////////////////////////////\n
+  function routeMethodLess() {\n
+    // Nothing. Go to front page\n
+    return synchronousChangeState(\n
+      getDisplayUrlFor(undefined, {page: DEFAULT_PAGE})\n
+    );\n
+  }\n
+\n
+  function routeDisplay(gadget, command_options) {\n
+    if (command_options.path) {\n
+      if (command_options.args.page === undefined) {\n
+        return synchronousChangeState(\n
+          getDisplayUrlFor(command_options.path, {\n
+            page: \'form\',\n
+            editable: command_options.args.editable,\n
+            view: command_options.args.view || \'view\',\n
+            selection: command_options.args.selection,\n
+            selection_index: command_options.args.selection_index,\n
+            history: command_options.args.history\n
+          })\n
+        );\n
+      }\n
+    }\n
+\n
+    if (command_options.args.page === undefined) {\n
+      return synchronousChangeState(\n
+        getDisplayUrlFor(undefined, {\n
+          page: DEFAULT_PAGE\n
+        })\n
+      );\n
+    }\n
+\n
+    command_options.args.jio_key = command_options.path;\n
+\n
+    // Store current options to handle navigation\n
+    gadget.props.options = JSON.parse(JSON.stringify(command_options.args));\n
+\n
+    return {\n
+      url: "gadget_interface_validator_page_" + command_options.args.page + ".html",\n
+      // XXX Drop this options thing.\n
+      // Implement a "getSelection" method \n
+      options: command_options.args\n
+      // options: {}\n
+    };\n
+\n
+  }\n
+\n
+  function routeCommand(gadget, command_options) {\n
+    var args = command_options.args,\n
+      key,\n
+      split_list,\n
+      previous_options = {},\n
+      next_options = {},\n
+      valid = true;\n
+    // Rebuild the previous and next parameter dict\n
+    for (key in args) {\n
+      if (args.hasOwnProperty(key)) {\n
+        split_list = key.split(\'.\', 2);\n
+        if (split_list.length !== 2) {\n
+          valid = false;\n
+          break;\n
+        }\n
+        if (split_list[0] === PREVIOUS_KEY) {\n
+          previous_options[split_list[1]] = args[key];\n
+        } else if (split_list[0] === NEXT_KEY) {\n
+          next_options[split_list[1]] = args[key];\n
+        } else {\n
+          valid = false;\n
+          break;\n
+        }\n
+      }\n
+    }\n
+    if (!valid) {\n
+      throw new Error(\'Unsupported parameters: \' + key);\n
+    }\n
+\n
+    if (command_options.path === COMMAND_DISPLAY_STATE) {\n
+      return execDisplayCommand(next_options);\n
+    }\n
+    if (command_options.path === COMMAND_INDEX_STATE) {\n
+      return execIndexCommand(gadget, previous_options, next_options);\n
+    }\n
+    if (command_options.path === COMMAND_CHANGE_STATE) {\n
+      return execChangeCommand(previous_options, next_options);\n
+    }\n
+    if (command_options.path === COMMAND_SELECTION_NEXT) {\n
+      return execSelectionNextCommand(gadget, previous_options, next_options);\n
+    }\n
+    if (command_options.path === COMMAND_SELECTION_PREVIOUS) {\n
+      return execSelectionPreviousCommand(gadget, previous_options, next_options);\n
+    }\n
+    if (command_options.path === COMMAND_HISTORY_PREVIOUS) {\n
+      return execHistoryPreviousCommand(gadget, previous_options);\n
+    }\n
+    if (command_options.path === COMMAND_PUSH_HISTORY) {\n
+      return execPushHistoryCommand(gadget, previous_options, next_options);\n
+    }\n
+    throw new Error(\'Unsupported command \' + command_options.path);\n
+\n
+  }\n
+\n
+  function listenHashChange(gadget) {\n
+    // Handle hash in this format: #$path1/path2?a=b&c=d\n
+    function extractHashAndDispatch(evt) {\n
+      var hash = (evt.newURL || window.location.toString()).split(\'#\')[1],\n
+        split,\n
+        command = "",\n
+        query = "",\n
+        subhashes,\n
+        subhash,\n
+        keyvalue,\n
+        index,\n
+        args = {};\n
+      if (hash !== undefined) {\n
+        split = hash.split(\'?\');\n
+        command = split[0] || "";\n
+        query = split[1] || "";\n
+      }\n
+      subhashes = query.split(\'&\');\n
+      for (index in subhashes) {\n
+        if (subhashes.hasOwnProperty(index)) {\n
+          subhash = subhashes[index];\n
+          if (subhash !== \'\') {\n
+            keyvalue = subhash.split(\'=\');\n
+            if (keyvalue.length === 2) {\n
+              args[decodeURIComponent(keyvalue[0])] = decodeURIComponent(keyvalue[1]);\n
+            }\n
           }\n
-          return {\n
-            url: MAIN_PAGE_PREFIX + "jio_"\n
-              + base_portal_type\n
-              + "_" + options.page + ".html",\n
-            options: sub_options\n
-          };\n
+        }\n
+      }\n
+\n
+      return gadget.renderApplication({\n
+        method: command[0],\n
+        path: command.substr(1),\n
+        args: args\n
+      });\n
+\n
+    }\n
+\n
+    var result = loopEventListener(window, \'hashchange\', false,\n
+                                   extractHashAndDispatch),\n
+      event = document.createEvent("Event");\n
+    event.initEvent(\'hashchange\', true, true);\n
+    event.newURL = window.location.toString();\n
+    window.dispatchEvent(event);\n
+    return result;\n
+  }\n
+\n
+\n
+  rJS(window)\n
+    .ready(function (gadget) {\n
+      gadget.props = {\n
+        options: {},\n
+        start_deferred: RSVP.defer()\n
+      };\n
+    })\n
+\n
+    .ready(function (gadget) {\n
+      return gadget.getDeclaredGadget("jio_selection")\n
+        .push(function (jio_gadget) {\n
+          gadget.props.jio_gadget = jio_gadget;\n
+          return jio_gadget.createJio({\n
+            type: "sha",\n
+            sub_storage: {\n
+              type: "indexeddb",\n
+              database: "selection"\n
+            }\n
+          });\n
+        });\n
+    })\n
+\n
+    .declareMethod(\'getCommandUrlFor\', function (options) {\n
+      var command = options.command,\n
+        args = options.options,\n
+        valid = true,\n
+        key;\n
+      // Only authorize \'command\' and \'options\' keys\n
+      // Drop all other kind of parameters, to detect issue more easily\n
+      for (key in options) {\n
+        if (options.hasOwnProperty(key)) {\n
+          if ((key !== \'command\') && (key !== \'options\')) {\n
+            valid = false;\n
+          }\n
+        }\n
+      }\n
+      if (valid && (options.command) && (VALID_URL_COMMAND_DICT.hasOwnProperty(options.command))) {\n
+        return getCommandUrlFor(this, command, args);\n
+      }\n
+      return getCommandUrlFor(this, \'error\', options);\n
+    })\n
+\n
+    .declareMethod(\'getUrlParameter\', function (key) {\n
+      return this.props.options[key];\n
+    })\n
+\n
+    .declareMethod(\'route\', function (command_options) {\n
+      var gadget = this;\n
+\n
+      if (command_options.method === PREFIX_DISPLAY) {\n
+        return routeDisplay(gadget, command_options);\n
+      }\n
+      if (command_options.method === PREFIX_COMMAND) {\n
+        return routeCommand(gadget, command_options);\n
+      }\n
+      if (command_options.method) {\n
+        throw new Error(\'Unsupported hash method: \' + command_options.method);\n
+      }\n
+      return routeMethodLess();\n
+    })\n
+\n
+    .declareMethod(\'start\', function () {\n
+      this.props.start_deferred.resolve();\n
+    })\n
+\n
+    .declareAcquiredMethod(\'renderApplication\', \'renderApplication\')\n
+    .declareAcquiredMethod(\'jio_allDocs\', \'jio_allDocs\')\n
+\n
+    .declareService(function () {\n
+      var gadget = this;\n
+      return new RSVP.Queue()\n
+        .push(function () {\n
+          return gadget.props.start_deferred.promise;\n
+        })\n
+        .push(function () {\n
+          // console.info(\'router service: listen to hash change\');\n
+          return listenHashChange(gadget);\n
         });\n
     });\n
 \n
-}(window, rJS));
+}(window, rJS, RSVP, loopEventListener, document, jIO));
 
 ]]></string> </value>
         </item>
@@ -291,7 +798,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.44744.45719.49203</string> </value>
+                <value> <string>946.44747.61190.22391</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -309,7 +816,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445868235.97</float>
+                        <float>1446476363.31</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_site_module/gadget_interface_validator.xml b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_site_module/gadget_interface_validator.xml
index bbe704f78a6e420bb0fefe036ae4921c0dba37e5..302a69aba27409d4492f6bb490cf4fc4faef1256 100644
--- a/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_site_module/gadget_interface_validator.xml
+++ b/bt5/erp5_gadget_interface_validator/PathTemplateItem/web_site_module/gadget_interface_validator.xml
@@ -426,7 +426,7 @@
         </item>
         <item>
             <key> <string>configuration_jio_gadget_url</string> </key>
-            <value> <string>gadget_officejs_jio.html</string> </value>
+            <value> <string>gadget_erp5_jio.html</string> </value>
         </item>
         <item>
             <key> <string>configuration_manifest_url</string> </key>
@@ -442,7 +442,7 @@
         </item>
         <item>
             <key> <string>configuration_translation_gadget_url</string> </key>
-            <value> <string>gadget_officejs_translation.html</string> </value>
+            <value> <string>gadget_translation.html</string> </value>
         </item>
         <item>
             <key> <string>configuration_view_action_category</string> </key>
@@ -741,7 +741,7 @@
             </item>
             <item>
                 <key> <string>serial</string> </key>
-                <value> <string>946.44750.63239.42905</string> </value>
+                <value> <string>946.44751.34537.43673</string> </value>
             </item>
             <item>
                 <key> <string>state</string> </key>
@@ -759,7 +759,7 @@
                     </tuple>
                     <state>
                       <tuple>
-                        <float>1445868451.61</float>
+                        <float>1446476438.92</float>
                         <string>UTC</string>
                       </tuple>
                     </state>
diff --git a/bt5/erp5_gadget_interface_validator_ui_test/PathTemplateItem/portal_tests/gadget_interface_validator_ui_zuite/testGadgetInterfaceVerification.xml b/bt5/erp5_gadget_interface_validator_ui_test/PathTemplateItem/portal_tests/gadget_interface_validator_ui_zuite/testGadgetInterfaceVerification.xml
index e867ed3fbca975d8dba829bad856584788aa1c56..b82b8ac30eaddb14a8946cf3ced63a36c7c81956 100644
--- a/bt5/erp5_gadget_interface_validator_ui_test/PathTemplateItem/portal_tests/gadget_interface_validator_ui_zuite/testGadgetInterfaceVerification.xml
+++ b/bt5/erp5_gadget_interface_validator_ui_test/PathTemplateItem/portal_tests/gadget_interface_validator_ui_zuite/testGadgetInterfaceVerification.xml
@@ -44,7 +44,7 @@
 </head>\n
 <body>\n
 <table cellpadding="1" cellspacing="1" border="1">\n
-<thead>in\n
+<thead>\n
 <tr><td rowspan="1" colspan="3">Test Gadget Interface Validation UI</td></tr>\n
 </thead><tbody>\n
 <tal:block metal:use-macro="here/Zuite_CommonTemplate/macros/init" />\n
@@ -80,7 +80,7 @@
 </tr>\n
 <tr>\n
   <td>click</td>\n
-  <td>//input[@name=\'Submit\']</td>t\n
+  <td>//input[@name=\'Submit\']</td>\n
   <td></td>\n
 </tr>\n
 <tr>\n
@@ -160,7 +160,7 @@
 </tr>\n
 <tr>\n
   <td>click</td>\n
-  <td>//a[@data-i18n=\'Interface Validation Form\']</td>inp\n
+  <td>//a[@data-i18n=\'Interface Validation Form\']</td>\n
   <td></td>\n
 </tr>\n
 <tr>\n
@@ -168,11 +168,6 @@
   <td>//form[@class=\'interface-validation-form\']</td>\n
   <td></td>\n
 </tr>\n
-<tr>\n
-  <td>click</td>\n
-  <td>//input[@data-i18n=\'[value]Close\']</td>\n
-  <td></td>\n
-</tr>\n
 <tr>\n
   <td>type</td>\n
   <td>name=appcache_url</td>\n
@@ -180,7 +175,7 @@
 </tr>\n
 <tr>\n
   <td>click</td>\n
-  <td>//input[@name=\'Submit\']</td>t\n
+  <td>//input[@name=\'Submit\']</td>\n
   <td></td>\n
 </tr>\n
 <tr>\n
@@ -205,7 +200,7 @@
 </tr>\n
 <tr>\n
   <td>click</td>\n
-  <td>//a[@data-i18n=\'Home\']</td>inp\n
+  <td>//a[@data-i18n=\'Home\']</td>\n
   <td></td>\n
 </tr>\n
 <tr>\n
@@ -213,11 +208,6 @@
   <td>//form[@class=\'interface-validation-form\']</td>\n
   <td></td>\n
 </tr>\n
-<tr>\n
-  <td>click</td>\n
-  <td>//input[@data-i18n=\'[value]Close\']</td>\n
-  <td></td>\n
-</tr>\n
 </tbody></table>\n
 </body>\n
 </html>