
  basis.require('basis.ua');
  basis.require('basis.dom.event');


 /**
  * @namespace basis.router
  */

  var namespace = this.path;


  var location = global.location;
  var document = global.document;
  var docMode = document.documentMode;
  var buggyIE = basis.ua.is('IE') && (!docMode || docMode <= 7);
  var eventSupport = 'onhashchange' in global && !buggyIE;

  var CHECK_INTERVAL = 50;
  var NAMED_PARAM = /:\w+/g;
  var SPLAT_PARAM = /\\\*\w+/g;


  function pathToRegExp(route){
    return new RegExp(
      '^' +
      String(route)
        .forRegExp()
        .replace(NAMED_PARAM, '([^\/]+)')
        .replace(SPLAT_PARAM, '(.*?)') +
      '$',
    'i');
  }

  var routes = {};
  var started = false;
  var currentPath;
  var timer;


 /**
  * Start router
  */
  function start(){
    if (!started)
    {
      if (eventSupport)
        basis.dom.event.addHandler(global, 'hashchange', checkUrl);
      else
        timer = setInterval(checkUrl, 50);

      ;;;basis.dev.log(namespace + ' started');
      started = true;

      checkUrl();      
    }
  }

 /**
  * Stop router
  */
  function stop(){
    if (eventSupport)
      basis.dom.event.removeHandler(global, 'hashchange', checkUrl);
    else
      clearInterval(timer);

    ;;;basis.dev.log(namespace + ' stopped');
    started = false;
  }

 /**
  * Process current location
  */
  function checkUrl(){
    var newPath = location.hash.substr(1) || '/';

    if (newPath != currentPath)
    {
      ;;;basis.dev.log(namespace + ' hash changed:', newPath);
      currentPath = newPath;

      for (var path in routes)
      {
        var route = routes[path];
        var match = newPath.match(route.regexp);
        if (match)
        {
          var args = basis.array.from(match, 1);
          var callbacks = basis.array.from(route.callbacks);
          for (var i = 0, item; item = callbacks[i]; i++)
            item.callback.apply(item.context, args);

          ;;;basis.dev.log(namespace + ' hash match:', route.source, args);
        }
      }
    }
  }

 /**
  * Add path to be handled
  */
  function add(path, callback, context){
    var route = routes[path];

    if (!route)
    {
      route = {
        source: path,
        callbacks: [],
        regexp: Object.prototype.toString.call(path) != '[object RegExp]'
          ? pathToRegExp(path)
          : path
      };
      routes[path] = route;
    }
    
    route.callbacks.push({
      callback: callback,
      context: context
    });

    if (currentPath)
    {
      var match = currentPath.match(route.regexp);
      if (match)
        callback.apply(context, basis.array.from(match, 1));
    }
  }

 /**
  * Navigate to specified path
  */
  function navigate(path, replace){
    if (replace)
      location.replace(location.pathname + '#' + path);
    else
      location.hash = path;

    if (started)
      checkUrl();
  }

  //
  // export names
  //

  module.exports = {
    add: add,
    stop: stop,
    start: start,
    checkUrl: checkUrl,
    navigate: navigate
  };

@@ -131,16 +131,42 @@
 path;%0A%0A%0A
+  //%0A  // main part%0A  //%0A%0A
   var lo
@@ -478,16 +478,104 @@
 %5Cw+/g;%0A%0A
+  var routes = %7B%7D;%0A  var started = false;%0A  var currentPath;%0A  var timer;%0A  var match;%0A%0A
 %0A  funct
@@ -755,24 +755,24 @@
 '(.*?)')
- +
 %0A     
+ +
  '$',%0A  
@@ -790,108 +790,184 @@
 %0A%0A  
-var routes = %7B%7D;%0A  var started = fa
+function startWatch()%7B%0A    if (eventSupport)%0A      basis.dom.event.addHandler(global, 'hashchange', checkUrl);%0A    e
 lse
-;
 %0A  
-var currentPath;%0A  var timer;%0A%0A%0A /**%0A  * Start router%0A  */
+    timer = setInterval(checkUrl, CHECK_INTERVAL);%0A  %7D
 %0A  f
@@ -980,41 +980,19 @@
 n st
-art
+opWatch
 ()%7B%0A
-    if (!started)%0A    %7B%0A  
     
@@ -1005,26 +1005,24 @@
 entSupport)%0A
-  
       basis.
@@ -1023,35 +1023,38 @@
 basis.dom.event.
-add
+remove
 Handler(global, 
@@ -1082,18 +1082,16 @@
 l);%0A    
-  
 else%0A   
@@ -1097,42 +1097,124 @@
     
-  timer = setInterval(checkUrl, 50
+clearInterval(timer);%0A  %7D%0A%0A%0A /**%0A  * Start router%0A  */%0A  function start()%7B%0A    if (!started)%0A    %7B%0A      startWatch(
 );%0A%0A
@@ -1376,129 +1376,45 @@
 if (
-eventSupport)%0A      basis.dom.event.removeHandler(global, 'hashchange', checkUrl);
+started)
 %0A    
-else
+%7B
 %0A      
-clearInterval(timer
+stopWatch(
 );%0A%0A
+  
     
@@ -1455,24 +1455,26 @@
 pped');%0A    
+  
 started = fa
@@ -1478,16 +1478,22 @@
  false;%0A
+    %7D%0A
   %7D%0A%0A /*
@@ -2817,32 +2817,364 @@
 1));%0A    %7D%0A  %7D%0A%0A
+ /**%0A  * Remove handler for path%0A  */ %0A  function remove(path, callback, context)%7B%0A    var route = routes%5Bpath%5D;%0A%0A    if (route)%0A      for (var i = 0, cb; cb = route.callbacks%5Bi%5D; i++)%0A        if (cb.callback === callback && cb.context === context)%0A        %7B%0A          route.callbacks.splice(i, 1);%0A          return;%0A        %7D%0A  %7D%0A%0A
  /**%0A  * Navigat
@@ -3449,16 +3449,36 @@
 d: add,%0A
+    remove: remove,%0A
     stop

remove callback function implemented, small code refactoring