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)