Skip to content

Instantly share code, notes, and snippets.

@togakangaroo
Last active December 20, 2015 07:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save togakangaroo/6096040 to your computer and use it in GitHub Desktop.
Save togakangaroo/6096040 to your computer and use it in GitHub Desktop.
dialog binding for doing dialogs in an mvvm manner.
// Elements with this binding will appear as a jquery ui dialog when the bound value exists
// This binding works similar to the 'with' data-binding in that its contents will only exist when its bound parameter is truthy.
// Also like with, it will start a new binding context.
// Unlike the 'with' binding, when the contents are visible this will not appear in place but instead be initialized in a
// jquery ui dialog. This dialog will close if the bounded value becomes falsy. Conversely, if the bound value is observable,
// closing the dialog will empty the observable.
var dialogDomDataKey = '__ko_dialogBindingData';
ko.bindingHandlers.dialog = {
init: function(el, valueAccessor) {
var $el = $(el)
,observable = ko.isObservable(valueAccessor()) && valueAccessor() //the observable itself or falsy
,clearObservable = function(){ observable && observable(null) }
,closeDialog = function(){ $el.dialog('close') }
;
//for unknown reasons, ko might call init twice so check that initialization has not occurred already
if( !$el.data(dialogDomDataKey) )
initializeVirtualElementCloning($el);
$el.dialog({ //jq ui widgets protect themselves against double initialization
close: clearObservable
,buttons: {"Ok": closeDialog }
});
return { 'controlsDescendantBindings': true };
},
update: function(el, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
var $el = $(el)
,val = ko.utils.unwrapObservable(valueAccessor()) //the value itself
,dialogContents = $el.data(dialogDomDataKey).savedNodes
;
if(!val) {
$el.dialog('close');
return ko.virtualElements.emptyNode(el);
}
ko.virtualElements.setDomNodeChildren(el, ko.utils.cloneNodes(dialogContents));
ko.applyBindingsToDescendants( bindingContext['createChildContext'](val) , el); //start context at to the value
return $el.dialog('open');
}
};
//This is the initalization required to make the binding work like a 'with'
function initializeVirtualElementCloning($el){
$el.data(dialogDomDataKey, {
savedNodes: ko.utils.cloneNodes(ko.virtualElements.childNodes($el[0]), true /*shouldCleanNodes*/) //record contents for later use
});
ko.virtualElements.emptyNode($el[0]); //because we're about to empty them
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment