Toggleable

by slicedtoad

HTML

<div id='PaddedContainer'>
    <div id='StartDate' class="datepicker">
        <input type="text" class="altfield"></input>
        <div class="picker"></div>
    </div>
</div>
<button type="button" id="toggle">Toggle</button>

CSS

.invisible {
    display:none;
}
.datepicker-toggleable.popup .picker {
    position:absolute;
}
.datepicker-toggleable.inline .picker {
}

#PaddedContainer{
    padding:20px;
}

JavaScript

/////////////////////
// Makes a datepicker toggleable between inline and an emulated popup mode.
// Returns: function that toggles the datepicker.
// Params:
//  - id of the container
//  - options.datepicker and options.altfield (class names)
//    ^ defaults are .picker and .altfield
// Author: Daniel Macdonald
var makeToggleable = function (container, options){
    options = typeof options !== 'undefined' ? options :
              {datepicker:".picker",altfield:".altfield"};
    var picker = options.datepicker;
    var altfield = options.altfield;
    var container = container; //in case selector refresh is needed
    var $node = $(container).addClass("datepicker-toggleable");
    var inline = false;
    var open = false;
    var bindOneOutsideMousedown = function(){ 
    // binds one mousedown, rebinds if click was on the picker or altfield
        $(document).one('mousedown',function closeOrBindAgain(e){
            if (inline) {return;}
            var $picker = $node.find(picker);
            if (!$picker.is($(e.target)) // if the target of the click isn't the picker
            && !$(e.target).parents(picker).length // nor a descendant of the picker
            && !$node.find(altfield).is($(e.target))) { // nor the altfield
                open = false;
                $picker.addClass('invisible');
            }else{
                bindOneOutsideMousedown();
            }
        });
    }
    var onAltFieldMousedown = function () { //open picker on altfield click
        if (open||inline) {return;}
        open = true;
        var $picker = $node.find(picker);
        $picker.removeClass("invisible");
        $picker.position({ //move it below the altfield
                my: "left top",
                at: "left bottom",
                of: $node.find(altfield),
                offset: "0 0",
                collision: "none"
        });
        $picker.datepicker('option', 'onSelect',function (e) { //close on date select           
           ...