lightwalker01
3/5/2014 - 1:11 AM

Knockout.js Custom Utility Bindings

Knockout.js Custom Utility Bindings from https://gist.github.com/lelandrichardson/9359228

(function (ko, handlers, unwrap, extend) {
    "use strict";
    extend(handlers, {
        href: {
            update: function (element, valueAccessor) {
                handlers.attr.update(element, function () {
                    return { href: valueAccessor() };
                });
            }
        },
        src: {
            update: function (element, valueAccessor) {
                handlers.attr.update(element, function () {
                    return { src: valueAccessor() };
                });
            }
        },
        hidden: {
            update: function (element, valueAccessor) {
                var value = unwrap(valueAccessor());
                handlers.visible.update(element, function () { return !value; });
            }
        },
        instantValue: {
            init: function (element, valueAccessor, allBindingsAccessor) {
                handlers.value.init(element, valueAccessor,
                    ko.observable(extend(allBindingsAccessor(), {valueUpdate: 'afterkeydown'}))
                    );
            },
            update: handlers.value.update
        },
        toggle: {
            init: function (element, valueAccessor) {
                var value = valueAccessor();
                ko.applyBindingsToNode(element, {
                    click: function () {
                        value(!value());
                    }
                });
            }
        },
        currency: {
          symbol: ko.observable('$'),
          numberToCurrency: function (value, symbol) {
              return symbol + value.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1,");
          },
          update: function (element, valueAccessor, allBindingsAccessor) {
              return handlers.text.update(element, function () {
                  var value = +(unwrap(valueAccessor()) || 0),
                      symbol = unwrap(allBindingsAccessor().symbol === undefined
                                  ? handlers.currency.symbol
                                  : allBindingsAccessor().symbol);
                  return handlers.currency.numberToCurrency(value, symbol);
              });
          }
      },
        stopBinding: {
            init: function () {
                return { controlsDescendantBindings: true };
            }
        },
        toJSON: {
            update: function (element, valueAccessor) {
                return handlers.text.update(element, function () {
                    return ko.toJSON(valueAccessor(), null, 2);
                });
            }
        },
        timeAgo: {
            dateToTimeAgo: function (dt) {
                var secs = (((new Date()).getTime() - dt.getTime()) / 1000),
                    days = Math.floor(secs / 86400);
            
                return days === 0 && (
                    secs < 60 && "just now" ||
                        secs < 120 && "a minute ago" ||
                        secs < 3600 && Math.floor(secs / 60) + " minutes ago" ||
                        secs < 7200 && "an hour ago" ||
                        secs < 86400 && Math.floor(secs / 3600) + " hours ago") ||
                    days === 1 && "yesterday" ||
                    days < 31 && days + " days ago" ||
                    days < 60 && "one month ago" ||
                    days < 365 && Math.ceil(days / 30) + " months ago" ||
                    days < 730 && "one year ago" ||
                    Math.ceil(days / 365) + " years ago";
            },
            update: function (element, valueAccessor) {
                var val = unwrap(valueAccessor()),
                    date = new Date(val), // WARNING: this is not compatibile with IE8
                    timeAgo = handlers.timeAgo.toTimeAgo(date);
                return handlers.html.update(element, function () {
                    return '<time datetime="' + encodeURIComponent(val) + '">' + timeAgo + '</time>';
                });
            }
        }
    });

    ko.virtualElements.allowedBindings.stopBinding = true;
}(ko, ko.bindingHandlers, ko.utils.unwrapObservable, ko.utils.extend));
(function(e,t,n,r){"use strict";r(t,{href:{update:function(e,n){t.attr.update(e,function(){return{href:n()}})}},src:{update:function(e,n){t.attr.update(e,function(){return{src:n()}})}},hidden:{update:function(e,r){var i=n(r());t.visible.update(e,function(){return!i})}},instantValue:{init:function(n,i,s){t.value.init(n,i,e.observable(r(s(),{valueUpdate:"afterkeydown"})))},update:t.value.update},toggle:{init:function(t,n){var r=n();e.applyBindingsToNode(t,{click:function(){r(!r())}})}},currency:{symbol:e.observable("$"),numberToCurrency:function(e,t){return t+e.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g,"$1,")},update:function(e,r,i){return t.text.update(e,function(){var e=+(n(r())||0),s=n(i().symbol===undefined?i().symbol:t.currency.symbol);return t.currency.numberToCurrency(e,s)})}},stopBinding:{init:function(){return{controlsDescendantBindings:true}}},toJSON:{update:function(n,r){return t.text.update(n,function(){return e.toJSON(r(),null,2)})}},timeAgo:{dateToTimeAgo:function(e){var t=((new Date).getTime()-e.getTime())/1e3,n=Math.floor(t/86400);return n===0&&(t<60&&"just now"||t<120&&"a minute ago"||t<3600&&Math.floor(t/60)+" minutes ago"||t<7200&&"an hour ago"||t<86400&&Math.floor(t/3600)+" hours ago")||n===1&&"yesterday"||n<31&&n+" days ago"||n<60&&"one month ago"||n<365&&Math.ceil(n/30)+" months ago"||n<730&&"one year ago"||Math.ceil(n/365)+" years ago"},update:function(e,r){var i=n(r()),s=new Date(i),o=t.timeAgo.toTimeAgo(s);return t.html.update(e,function(){return'<time datetime="'+encodeURIComponent(i)+'">'+o+"</time>"})}}});e.virtualElements.allowedBindings.stopBinding=true})(ko,ko.bindingHandlers,ko.utils.unwrapObservable,ko.utils.extend)