(function(c){var e,l=/:([\w\d]+)/g,p=/\?([^#]*)$/,m=decodeURIComponent,h=function(a){return function(b,d){return this.route.apply(this,[a,b,d])}},q=[];e=function(){var a=c.makeArray(arguments),b,d;e.apps=e.apps||{};if(0===a.length||a[0]&&c.isFunction(a[0]))return e.apply(e,["body"].concat(a));if("string"==typeof(d=a.shift()))return b=e.apps[d]||new e.Application,b.element_selector=d,0<a.length&&c.each(a,function(a,d){b.use(d)}),b.element_selector!=d&&delete e.apps[d],e.apps[b.element_selector]=b};
e.VERSION="0.5.1";e.addLogger=function(a){q.push(a)};e.log=function(){var a=c.makeArray(arguments);a.unshift("["+Date()+"]");c.each(q,function(b,d){d.apply(e,a)})};"undefined"!=typeof window.console?c.isFunction(console.log.apply)?e.addLogger(function(){window.console.log.apply(console,arguments)}):e.addLogger(function(){window.console.log(arguments)}):"undefined"!=typeof console&&e.addLogger(function(){console.log.apply(console,arguments)});e.Object=function(a){return c.extend(this,a||{})};c.extend(e.Object.prototype,
{toHash:function(){var a={};c.each(this,function(b,d){c.isFunction(d)||(a[b]=d)});return a},toHTML:function(){var a="";c.each(this,function(b,d){c.isFunction(d)||(a+="<strong>"+b+"</strong> "+d+"<br />")});return a},uuid:function(){if("undefined"==typeof this._uuid||!this._uuid)this._uuid=(new Date).getTime()+"-"+parseInt(1E3*Math.random(),10);return this._uuid},keys:function(a){var b=[],d;for(d in this)(!c.isFunction(this[d])||!a)&&b.push(d);return b},has:function(a){return this[a]&&""!=c.trim(this[a].toString())},
join:function(){var a=c.makeArray(arguments),b=a.shift();return a.join(b)},log:function(){e.log.apply(e,arguments)},toString:function(a){var b=[];c.each(this,function(d,j){(!c.isFunction(j)||a)&&b.push('"'+d+'": '+j.toString())});return"Sammy.Object: {"+b.join(",")+"}"}});e.HashLocationProxy=function(a,b){this.app=a;"onhashchange"in window?(e.log("native hash change exists, using"),this.is_native=!0):(e.log("no native hash change, falling back to polling"),this.is_native=!1,this._startPolling(b))};
e.HashLocationProxy.prototype={bind:function(){var a=this.app;c(window).bind("hashchange."+this.app.eventNamespace(),function(){a.trigger("location-changed")})},unbind:function(){c(window).die("hashchange."+this.app.eventNamespace())},getLocation:function(){var a=window.location.toString().match(/^[^#]*(#.+)$/);return a?a[1]:""},setLocation:function(a){return window.location=a},_startPolling:function(a){var b=this;if(!e.HashLocationProxy._interval){a||(a=10);var d=function(){current_location=b.getLocation();
(!e.HashLocationProxy._last_location||current_location!=e.HashLocationProxy._last_location)&&setTimeout(function(){c(window).trigger("hashchange")},1);e.HashLocationProxy._last_location=current_location};d();e.HashLocationProxy._interval=setInterval(d,a);c(window).bind("beforeunload",function(){clearInterval(e.HashLocationProxy._interval)})}}};e.DataLocationProxy=function(a,b){this.app=a;this.data_name=b||"sammy-location"};e.DataLocationProxy.prototype={bind:function(){var a=this;this.app.$element().bind("setData",
function(b,d){d==a.data_name&&a.app.trigger("location-changed")})},unbind:function(){this.app.$element().die("setData")},getLocation:function(){return this.app.$element().data(this.data_name)},setLocation:function(a){return this.app.$element().data(this.data_name,a)}};e.Application=function(a){var b=this;this.routes={};this.listeners=new e.Object({});this.arounds=[];this.befores=[];this.namespace=this.uuid();this.context_prototype=function(){e.EventContext.apply(this,arguments)};this.context_prototype.prototype=
new e.EventContext;c.isFunction(a)&&a.apply(this,[this]);this.location_proxy||(this.location_proxy=new e.HashLocationProxy(b,this.run_interval_every));this.debug&&this.bindToAllEvents(function(a,c){b.log(b.toString(),a.cleaned_type,c||{})})};e.Application.prototype=c.extend({},e.Object.prototype,{ROUTE_VERBS:["get","post","put","delete"],APP_EVENTS:"run unload lookup-route run-route route-found event-context-before event-context-after changed error check-form-submission redirect".split(" "),_last_route:null,
_running:!1,element_selector:"body",debug:!1,raise_errors:!1,run_interval_every:50,location_proxy:null,template_engine:null,toString:function(){return"Sammy.Application:"+this.element_selector},$element:function(){return c(this.element_selector)},use:function(){var a=c.makeArray(arguments),b=a.shift();try{a.unshift(this),b.apply(this,a)}catch(d){"undefined"==typeof b?this.error("Plugin Error: called use() but plugin is not defined",d):c.isFunction(b)?this.error("Plugin Error",d):this.error("Plugin Error: called use() but '"+
b.toString()+"' is not a function",d)}return this},route:function(a,b,d){var j=this,e=[],g;!d&&c.isFunction(b)&&(d=b=a,a="any");a=a.toLowerCase();if(b.constructor==String){for(l.lastIndex=0;null!==(path_match=l.exec(b));)e.push(path_match[1]);b=RegExp("^"+b.replace(l,"([^/]+)")+"$")}"string"==typeof d&&(d=j[d]);g=function(a){var c={verb:a,path:b,callback:d,param_names:e};j.routes[a]=j.routes[a]||[];j.routes[a].push(c)};"any"===a?c.each(this.ROUTE_VERBS,function(a,b){g(b)}):g(a);return this},get:h("get"),
post:h("post"),put:h("put"),del:h("delete"),any:h("any"),mapRoutes:function(a){var b=this;c.each(a,function(a,c){b.route.apply(b,c)});return this},eventNamespace:function(){return["sammy-app",this.namespace].join("-")},bind:function(a,b,d){var c=this;"undefined"==typeof d&&(d=b);b=function(a,b){var e;b&&b.context?(e=b.context,delete b.context):e=new c.context_prototype(c,"bind",a.type,b);a.cleaned_type=a.type.replace(c.eventNamespace(),"");d.apply(e,[a,b])};this.listeners[a]||(this.listeners[a]=[]);
this.listeners[a].push(b);this.isRunning()&&this._listen(a,b);return this},trigger:function(a,b){this.$element().trigger([a,this.eventNamespace()].join("."),[b]);return this},refresh:function(){this.last_location=null;this.trigger("location-changed");return this},before:function(a,b){c.isFunction(a)&&(b=a,a={});this.befores.push([a,b]);return this},after:function(a){return this.bind("event-context-after",a)},around:function(a){this.arounds.push(a);return this},isRunning:function(){return this._running},
helpers:function(a){c.extend(this.context_prototype.prototype,a);return this},helper:function(a,b){this.context_prototype.prototype[a]=b;return this},run:function(a){if(this.isRunning())return!1;var b=this;c.each(this.listeners.toHash(),function(a,e){c.each(e,function(c,e){b._listen(a,e)})});this.trigger("run",{start_url:a});this._running=!0;this.last_location=null;""==this.getLocation()&&"undefined"!=typeof a&&this.setLocation(a);this._checkLocation();this.location_proxy.bind();this.bind("location-changed",
function(){b._checkLocation()});this.bind("submit",function(a){return!1===b._checkFormSubmission(c(a.target).closest("form"))?a.preventDefault():!1});c(window).bind("beforeunload",function(){b.unload()});return this.trigger("changed")},unload:function(){if(!this.isRunning())return!1;var a=this;this.trigger("unload");this.location_proxy.unbind();this.$element().unbind("submit").removeClass(a.eventNamespace());c.each(this.listeners.toHash(),function(b,d){c.each(d,function(d,c){a._unlisten(b,c)})});
this._running=!1;return this},bindToAllEvents:function(a){var b=this;c.each(this.APP_EVENTS,function(d,c){b.bind(c,a)});c.each(this.listeners.keys(!0),function(d,c){-1==b.APP_EVENTS.indexOf(c)&&b.bind(c,a)});return this},routablePath:function(a){return a.replace(p,"")},lookupRoute:function(a,b){var d=this,e=!1;this.trigger("lookup-route",{verb:a,path:b});"undefined"!=typeof this.routes[a]&&c.each(this.routes[a],function(a,c){if(d.routablePath(b).match(c.path))return e=c,!1});return e},runRoute:function(a,
b,d){var e=this,f=this.lookupRoute(a,b),g,k,i,n,o,r,h;this.log("runRoute",[a,b].join(" "));this.trigger("run-route",{verb:a,path:b,params:d});"undefined"==typeof d&&(d={});c.extend(d,this._parseQueryString(b));if(f){this.trigger("route-found",{route:f});if(null!==(path_params=f.path.exec(this.routablePath(b))))path_params.shift(),c.each(path_params,function(a,b){f.param_names[a]?d[f.param_names[a]]=m(b):(d.splat||(d.splat=[]),d.splat.push(m(b)))});g=new this.context_prototype(this,a,b,d);i=this.arounds.slice(0);
n=this.befores.slice(0);r=[g].concat(d.splat);k=function(){for(var a;0<n.length;)if(o=n.shift(),e.contextMatchesOptions(g,o[0])&&(a=o[1].apply(g,[g]),!1===a))return!1;e.last_route=f;g.trigger("event-context-before",{context:g});a=f.callback.apply(g,r);g.trigger("event-context-after",{context:g});return a};c.each(i.reverse(),function(a,b){var d=k;k=function(){return b.apply(g,[d])}});try{h=k()}catch(s){this.error(["500 Error",a,b].join(" "),s)}return h}return this.notFound(a,b)},contextMatchesOptions:function(a,
b,d){if("undefined"===typeof b||b=={})return!0;"undefined"===typeof d&&(d=!0);if("string"===typeof b||c.isFunction(b.test))b={path:b};if(b.only)return this.contextMatchesOptions(a,b.only,!0);if(b.except)return this.contextMatchesOptions(a,b.except,!1);var e=!0,f=!0;b.path&&(e=c.isFunction(b.path.test)?b.path.test(a.path):b.path.toString()===a.path);b.verb&&(f=b.verb===a.verb);return d?f&&e:!(f&&e)},getLocation:function(){return this.location_proxy.getLocation()},setLocation:function(a){return this.location_proxy.setLocation(a)},
swap:function(a){return this.$element().html(a)},notFound:function(a,b){var d=this.error(["404 Not Found",a,b].join(" "));return"get"===a?d:!0},error:function(a,b){b||(b=Error());b.message=[a,b.message].join(" ");this.trigger("error",{message:b.message,error:b});if(this.raise_errors)throw b;this.log(b.message,b)},_checkLocation:function(){var a,b;a=this.getLocation();a!=this.last_location&&(b=this.runRoute("get",a));this.last_location=a;return b},_checkFormSubmission:function(a){var b,d;this.trigger("check-form-submission",
{form:a});b=c(a);a=b.attr("action");d=c.trim(b.attr("method").toString().toLowerCase());if(!d||""==d)d="get";this.log("_checkFormSubmission",b,a,d);b=c.extend({},this._parseFormParams(b),{$form:b});a=this.runRoute(d,a,b);return"undefined"==typeof a?!1:a},_parseFormParams:function(a){var b={};c.each(a.serializeArray(),function(a,e){b[e.name]?c.isArray(b[e.name])?b[e.name].push(e.value):b[e.name]=[b[e.name],e.value]:b[e.name]=e.value});return b},_parseQueryString:function(a){var b={},d,c;if(a=a.match(p)){a=
a[1].split("&");for(c=0;c<a.length;c+=1)d=a[c].split("="),b[d[0]]=m(d[1])}return b},_listen:function(a,b){return this.$element().bind([a,this.eventNamespace()].join("."),b)},_unlisten:function(a,b){return this.$element().unbind([a,this.eventNamespace()].join("."),b)}});e.EventContext=function(a,b,c,j){this.app=a;this.verb=b;this.path=c;this.params=new e.Object(j)};e.EventContext.prototype=c.extend({},e.Object.prototype,{$element:function(){return this.app.$element()},partial:function(a,b,d){var e,
f,g,h="partial:"+a,i=this;if(f=a.match(/\.([^\.]+)$/))f=f[1];if((!f||!c.isFunction(i[f]))&&this.app.template_engine)f=this.app.template_engine;f&&(!c.isFunction(f)&&c.isFunction(i[f]))&&(f=i[f]);!d&&c.isFunction(b)&&(d=b,b={});g=c.isArray(b)?b:[b||{}];e=function(a){var b=a,e="";c.each(g,function(g,h){c.extend(h,i);c.isFunction(f)&&(b=f.apply(i,[a,h]));e=e+b;if(d)return d.apply(i,[b,g])});d||i.swap(e);i.trigger("changed")};this.app.cache_partials&&this.cache(h)?e.apply(i,[this.cache(h)]):c.get(a,function(a){i.app.cache_partials&&
i.cache(h,a);e.apply(i,[a])})},redirect:function(){var a;a=c.makeArray(arguments);var b=this.app.getLocation();1<a.length?(a.unshift("/"),a=this.join.apply(this,a)):a=a[0];this.trigger("redirect",{to:a});this.app.last_location=this.path;this.app.setLocation(a);b==a&&this.app.trigger("location-changed")},trigger:function(a,b){"undefined"==typeof b&&(b={});b.context||(b.context=this);return this.app.trigger(a,b)},eventNamespace:function(){return this.app.eventNamespace()},swap:function(a){return this.app.swap(a)},
notFound:function(){return this.app.notFound(this.verb,this.path)},toString:function(){return"Sammy.EventContext: "+[this.verb,this.path,this.params].join(" ")}});c.sammy=window.Sammy=e})(jQuery);