Add scripts to create myops-getqueryview:
[myops.git] / web / query / vendor / couchapp / _attachments / jquery.pathbinder.js
diff --git a/web/query/vendor/couchapp/_attachments/jquery.pathbinder.js b/web/query/vendor/couchapp/_attachments/jquery.pathbinder.js
new file mode 100644 (file)
index 0000000..89f0dd4
--- /dev/null
@@ -0,0 +1,174 @@
+(function($) {
+  // functions for handling the path
+  // thanks sammy.js
+  var PATH_REPLACER = "([^\/]+)",
+      PATH_NAME_MATCHER = /:([\w\d]+)/g,
+      QUERY_STRING_MATCHER = /\?([^#]*)$/,
+      SPLAT_MATCHER = /(\*)/,
+      SPLAT_REPLACER = "(.+)",
+      _currentPath,
+      _lastPath,
+      _pathInterval;
+
+  function hashChanged() {
+    _currentPath = getPath();
+    // if path is actually changed from what we thought it was, then react
+    if (_lastPath != _currentPath) {
+      _lastPath = _currentPath;
+      return triggerOnPath(_currentPath);
+    }
+  }
+  
+  $.pathbinder = {
+    changeFuns : [],
+    paths : [],
+    begin : function(defaultPath) {
+      // this should trigger the defaultPath if there's not a path in the URL
+      // otherwise it should trigger the URL's path
+      $(function() {
+        var loadPath = getPath();
+        if (loadPath) {
+          triggerOnPath(loadPath);
+        } else {
+          goPath(defaultPath);          
+          triggerOnPath(defaultPath);
+        }
+      })
+    },
+    go : function(path) {
+      goPath(path);
+      triggerOnPath(path);
+    },
+    currentPath : function() {
+      return getPath();
+    },
+    onChange : function (fun) {
+      $.pathbinder.changeFuns.push(fun);
+    }
+  };
+
+  function pollPath(every) {
+    function hashCheck() {        
+      _currentPath = getPath();
+      // path changed if _currentPath != _lastPath
+      if (_lastPath != _currentPath) {
+        setTimeout(function() {
+          $(window).trigger('hashchange');
+        }, 1);
+      }
+    };
+    hashCheck();
+    _pathInterval = setInterval(hashCheck, every);
+    $(window).bind('unload', function() {
+      clearInterval(_pathInterval);
+    });
+  }
+
+  function triggerOnPath(path) {
+    path = path.replace(/^#/,'');
+    $.pathbinder.changeFuns.forEach(function(fun) {fun(path)});
+    var pathSpec, path_params, params = {}, param_name, param;
+    for (var i=0; i < $.pathbinder.paths.length; i++) {
+      pathSpec = $.pathbinder.paths[i];
+      // $.log("pathSpec", pathSpec);
+      if ((path_params = pathSpec.matcher.exec(path)) !== null) {
+        // $.log("path_params", path_params);
+        path_params.shift();
+        for (var j=0; j < path_params.length; j++) {
+          param_name = pathSpec.param_names[j];
+          param = decodeURIComponent(path_params[j]);
+          if (param_name) {
+            params[param_name] = param;
+          } else {
+            if (!params.splat) params.splat = [];
+            params.splat.push(param);
+          }
+        };
+        pathSpec.callback(params);
+        // return true; // removed this to allow for multi match
+      }
+    };
+  };
+
+  // bind the event
+  $(function() {
+    if ('onhashchange' in window) {
+      // we have a native event
+    } else {
+      pollPath(10);
+    }
+    // setTimeout(hashChanged,50);
+    $(window).bind('hashchange', hashChanged);
+  });
+
+  function registerPath(pathSpec) {
+    $.pathbinder.paths.push(pathSpec);
+  };
+
+  function setPath(pathSpec, params) {
+    var newPath = $.mustache(pathSpec.template, params);
+    goPath(newPath);
+  };
+  
+  function goPath(newPath) {
+    if (newPath) {
+      // $.log("goPath", newPath)
+      window.location = '#'+newPath;
+    }
+    _lastPath = getPath();
+  };
+  
+  function getPath() {
+    var matches = window.location.toString().match(/^[^#]*(#.+)$/);
+    return matches ? matches[1] : '';
+  };
+
+  function makePathSpec(path, callback) {
+    var param_names = [];
+    var template = "";
+    
+    PATH_NAME_MATCHER.lastIndex = 0;
+    
+    while ((path_match = PATH_NAME_MATCHER.exec(path)) !== null) {
+      param_names.push(path_match[1]);
+    }
+
+    return {
+      param_names : param_names,
+      matcher : new RegExp("^" + path.replace(
+        PATH_NAME_MATCHER, PATH_REPLACER).replace(
+        SPLAT_MATCHER, SPLAT_REPLACER) + "/?$"),
+      template : path.replace(PATH_NAME_MATCHER, function(a, b) {
+        return '{{'+b+'}}';
+      }).replace(SPLAT_MATCHER, '{{splat}}'),
+      callback : callback
+    };
+  };
+
+  $.fn.pathbinder = function(name, paths, options) {
+    options = options || {};
+    var self = $(this), pathList = paths.split(/\n/);
+    $.each(pathList, function() {
+      var path = this;
+      if (path) {
+        // $.log("bind path", path);
+        var pathSpec = makePathSpec(path, function(params) {
+          // $.log("path cb", name, path, self)
+          // $.log("trigger path: "+path+" params: ", params);
+          self.trigger(name, [params]);
+        });
+        // set the path when the event triggered through other means
+        if (options.bindPath) {
+          self.bind(name, function(ev, params) {
+            params = params || {};
+            // $.log("set path", name, pathSpec)
+            setPath(pathSpec, params);
+          });
+        }
+        // trigger when the path matches
+        registerPath(pathSpec);
+      }
+    });
+  };
+})(jQuery);
+  
\ No newline at end of file