Knockout.js application routing with Sammy.js and history with html4 support

I just started playing with sammy.js, and the first thing I want to do is check how the history changes work. And it works as expected, even better, but as soon as I open IE10 and switch to IE9 browser mode, everything crashes. If I don't set up hash links, IE9 just keeps following the links. Same problem with IE8, of course.

At this point, I only have this bit of code related to sammy

App.sm = $.sammy('#content', function() { this.get('/', function(context) { console.log('Yo yo yo') }); this.get('/landing', function(context) { console.log('landing page') }); this.get('/:user', function(context) { console.log(context) }); }); 

And the initiator

 $(function() { App.sm.run('/'); }); 

I also looked at this example , which contains three types of links, normal, hash and normal again, but it works correctly on IE9 and IE8. which makes me think that somehow it should be possible to make sammy.js support html5 history and html4 at the same time.

So my question will be, how can I achieve this?

Update

I found a way to make it work with IE

I just added this snippet:

 this.bind('run', function(e) { var ctx = this; $('body').on('click', 'a', function(e) { e.preventDefault(); ctx.redirect($(e.target).attr('href')); return false; }); }); 

Anyway, I still have a problem logging into the site, html5, which supports browsers, is always redirected to the .com domain, regardless of what the starting URL was.

It is so interesting how should I configure sammy.js to work peroperly. Or maybe someone can recommend another router that will work well with knockout.js.

+4
source share
1 answer

For a number of reasons, including search engine spiders and link exchange; Your site should work without a history API. If the user sees http://example.org/poodles/red and wants to show someone else the red poodles on your website, they will copy the link. Another visitor should be able to see the same content at the same URL; even if they do not start on the main page.

For this reason, I suggest using the History API as a progressive improvement. Where available, you should use it to provide a better UX. If it is not available, links should work as usual.

Here is an example of a Router (e.g. Sammy) that just allows default navigation if history.pushState is not available.

And about the knockout part; I used this in a KnockoutJS project and it works well.

 (function($){ function Route(path, callback) { function escapeRegExp(str) { return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); } // replace "/:something" with a regular expression fragment var expression = escapeRegExp(path).replace(/\/:(\w+)+/g, "/(\\w+)*"); this.regex = new RegExp(expression); this.callback = callback; } Route.prototype.test = function (path) { this.regex.lastIndex = 0; var match = this.regex.exec(path); if (match !== null && match[0].length === path.length) { // call it, passing any matching groups this.callback.apply(this, match.slice(1)); return false; } }; function Router(paths) { var self = this; self.routes = []; $.each(paths, function (path, callback) { self.routes.push(new Route(path, callback)); }); self.listen(); self.doCallbacks(location.pathname); } Router.prototype.listen = function () { var self = this, $document = $(document); // watch for clicks on links // does AJAX when ctrl is not down // nor the href ends in .html // nor the href is blank // nor the href is / $document.ready(function(e){ $document.on("click", "[href]", function(e){ var href = this.getAttribute("href"); if ( !e.ctrlKey && (href.indexOf(".html") !== href.length - 5) && (href.indexOf(".zip") !== href.length - 4) && href.length > 0 && href !== "/") { e.preventDefault(); self.navigate(href); } }); }); window.addEventListener("popstate", function(e) { self.doCallbacks(location.pathname); }); }; Router.prototype.navigate = function(url) { if (window.history && window.history.pushState) { history.pushState(null, null, url); this.doCallbacks(location.pathname); } }; Router.prototype.doCallbacks = function(url) { var routes = this.routes; for (var i=0; i<routes.length; i++){ var route = routes[i]; // it returns false when there a match if (route.test(url) === false) { console.log("nav matched " + route.regex); return; } } if (typeof this.fourOhFour === "function") { this.fourOhFour(url); } else { console.log("404 at ", url); } }; window.Router = Router; }).call(this, jQuery); 

Usage example:

 router = new Router({ "/": function () { }, "/category/:which": function (category) { }, "/search/:query": function(query) { }, "/search/:category/:query": function(category, query) { }, "/:foo/:bar": function(foo, bar) { } }); router.fourOhFour = function(requestURL){ }; 
0
source

All Articles