Saturday, July 14, 2012

A Knockout History.js ajaxify bindingHandler

I've been playing around with balupton's History.js and Ajaxify scripts for my current project. I had tried both a year or so ago and, while they worked well at first I ran into some problems here and there. I'm making a second attempt and so far it's going well.

However, balupon's ajaxify code is run once on the initial page load or the return of the ajax load event so it does not catch template fragments that are loaded or bound after the load completes.

As I am using Knockout extensively with a lot of dynamically loaded content, I wanted extend balupton's ajaxify function to my dynamically loaded content using a knockout bindingHandler:

This is the helper function:


// Ajaxify Helper
$.fn.ajaxify = function(){
    // Prepare
    var $this = $(this);

    // Ajaxify
    $this.find('a:internal:not(.no-ajaxy)').click(function(event){
        // Prepare
 var
     $this = $(this),
     url = $this.attr('href'),
     title = $this.attr('title')||null;

 // Continue as normal for cmd clicks etc
 if ( event.which == 2 || event.metaKey ) { return true; }
            // Ajaxify this link
     History.pushState(null,title,url);
     event.preventDefault();
     return false;
 });

 // Chain
 return $this;
};

And here it is, amd style:


define(['jquery', 'ko'], function($, ko) {
    "use strict";
    ko.bindingHandlers.ajaxify = {
        update: function(element) {
            // Prepare
            var $this = $(element);
            // Ajaxify
            $this.find('a:internal:not(.no-ajaxy)').click(function(event) {
                // Prepare
                var $this = $(this),
                    url = $this.attr('href'),
                    title = $this.attr('title') || null;

                // Continue as normal for cmd clicks etc
                if (event.which == 2 || event.metaKey) {
                    return true;
                }

                // Ajaxify this link
                History.pushState(null, title, url);
                event.preventDefault();
                return false;
            });
        }
    };
});

This assumes you have the other 5000 scripts already on the page (JQuery, History, ScrollTo, Ajaxify, Knockout, Require to name a few) of course. After which usage is simple (well after all that pretty much anything is simple):

<div data-bind="foreach: item, ajaxify: true">
   //any links loaded here will get ajaxified
</a>

Now this works well when I'm loading the content from the ko native template and the html is already on the page. When trying to do this when loading the html from templates, no dice. However, by putting the 'ajaxify' binding on the template element being bound, it worked nicely.

2 comments:

  1. Actual URLs for History.js and the Ajaxify.js gist:

    https://github.com/browserstate/history.js

    https://github.com/browserstate/ajaxify

    ReplyDelete
  2. Note that there’s no limit to the amount of practice you need to|you should|you have to} better your video poker technique. The good factor, online gambling, is authorized plenty of} countries. Do not draw any cards if you have a straight, flush, full home, straight flush, or royal straight flush. You will win more the higher your hand is, so make sure you|ensure you|be positive to} know the ranking of 다파벳 poker palms.

    ReplyDelete