Knockout jQuery UI Widget Binding

Demonstrates using Knockout with custom jQuery UI Widget binding. Custom binding at https://gist.github.com/889400

by craigcav

HTML

<script src="https://github.com/downloads/SteveSanderson/knockout/jquery.tmpl.js"></script>
<script src="https://github.com/SteveSanderson/knockout/raw/master/build/output/knockout-latest.debug.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/ui-lightness/jquery-ui.css">
<script src="http://dl.dropbox.com/u/16870890/knockout-jquery-ui-widget.js"></script>
<script src="http://www.datejs.com/build/date.js"></script>
<h2>Knockout with jQuery UI Widget Bindings</h2>

<div>
  <label for='start'>start:</label>
  <input id='end' type='text' data-bind='jqueryui: {  "widget": "datepicker",  options : { minDate: offset(end, -1), maxDate: offset(end,0) } }, value: start' />
  <small>(with datepicker)</small>
</div>
<div>
  <label for='x'>end:</label>
  <input id='x' type='text' 
    data-bind='jqueryui: {  "widget": "datepicker",  options : { minDate: offset(start, 0), maxDate: offset(start,1) } },
               value: end' />
  <small>(with datepicker)</small>
</div>

CSS

html {
    font-size: 80%;
}

body > div {
    margin-top: 1em;
}

body > div > label {
    display: inline-block;
    width: 8em;
    margin-right: 0.2em;
    text-align: right;
}

small {
    font-size: 0.8em;
    color: #999999;
}

#quantity_slider {
    margin-left: 0.5em;
    display: inline-block;
    width: 6em;
}

#summary {
    display: inline-block;
    padding: 0.5em;
}

img.ui-datepicker-trigger {
    margin-left: 3px;
}

JavaScript

var viewModel = {
    start: ko.observable(),
    end: ko.observable()
};

function daysBetween(date1, date2) {
    var ONE_DAY = 1000 * 60 * 60 * 24;
    var date1_ms = date1.getTime();
    var date2_ms = date2.getTime();
    var difference_ms = Math.abs(date1_ms - date2_ms);    
    var result = Math.round(difference_ms/ONE_DAY);    
    if(date1_ms > date2_ms)
        return -result + 1;    
    return result + 1;
}

viewModel.offset = function(observable, value){
    return ko.dependentObservable(function() {
        if(observable()){
            return daysBetween(new Date(),Date.parse(observable()) || new Date()) + value;
        }
        return null;
    }, viewModel)();
};

ko.applyBindings(viewModel);