Knockout - jQuery UI, dialogs, binding handlers

by johnpapa

HTML

<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/base/jquery-ui.css">
<script src="https://github.com/SteveSanderson/knockout.mapping/raw/master/build/output/knockout.mapping-latest.js"></script>
<div data-bind="template: {name: 'foldersTemplate' , foreach: folders}"></div>        

<script type="text/html" id="foldersTemplate"> 
    <div>
        <h2 data-bind='click: $parent.SelUnsel'>
            <a  href="#" data-bind='text: folderName'></a>       
        </h2>
        <div>     
            <a href="#" data-bind="click: function() { $root.editFolder($data) }" >edit Folder</a>
         </div>          
        <div  data-bind="if: $parent.selectedFolder()">
        <div  data-bind="if: $parent.selectedFolder().folderName == folderName">
             <ul data-bind=" template: {name:  'linksTemplate' , foreach:  links } " ></ul>
        </div>
        </div>
    </div>
</script>
 
 <script type="text/html" id="linksTemplate"> 
    <div>     
        <li><a href="#" data-bind='text: name' ></a></li>
        <li><a href="#" data-bind='text: url' ></a></li>
     </div> 
     <div>     
        <a href="#" data-bind="click: function() { $root.editLink($data) }" >edit Link</a>
     </div>     
</script>

<div id="details" data-bind="template: { name: 'editTmpl', if:selectedLink, data: selectedLink }, openDialog: selectedLink"> 
</div>

<script id="editTmpl" type="text/html">
    <p>
        <label>Name: </label>
        <input data-bind="value: name, valueUpdate: 'afterkeydown'  "/>  
        <label>URL: </label>
        <textarea data-bind="value: url, valueUpdate: 'afterkeydown'  "/>
       
    </p>       
</script>

<div id="folderdetails" data-bind="template: { name:...

CSS

#dialog-confirm { visibility: hidden; }

JavaScript

function Folder(id, name, isNew) {
    this.id = ko.observable(id);
    this.name = ko.observable(name);
    this.isNew = isNew;
    this.editId = ko.observable(id);
    this.editName = ko.observable(name);

    //persist edits to real values on accept
    this.accept = function() {
        this.id(this.editId()).name(this.editName());
    }.bind(this);

    //reset to originals on cancel
    this.cancel = function() {
        this.editId(this.id()).editName(this.name());
    }.bind(this);
}

$(function() {
    //set up dialog
    $("#details").dialog({
        autoOpen: false,
        resizable: false,
        modal: true,
        buttons: {
            "Accept": function() {
                foldersModel.accept();
                $(this).dialog("close");
            },
            Cancel: function() {
                foldersModel.cancel();
                $(this).dialog("close");
            }
        }
    });
});


$(function() {
    //set up dialog
    $("#folderdetails").dialog({
        autoOpen: false,
        resizable: false,
        modal: true,
        buttons: {
            "Accept": function() {
                foldersModel.acceptFolder();
                $(this).dialog("close");
            },
            Cancel: function() {
                foldersModel.cancelFolder();
                $(this).dialog("close");
            }
        }
    });
});

var FoldersModel = function(folders) {
    var self = this;

    self.folders = ko.mapping.fromJS(folders);

    //  self.folders = ko.observableArray(ko.utils.arrayMap(folders, function(folder) {
    //       return { folderName: folder.name, links: ko.observableArray(folder.links) };
    //   }));
    self.folderToEdit = ko.observable();

    self.selectedFolder = ko.observable();

    self.selectedLink = ko.observable();

    self.SelUnsel = function(e) {
        if (self.selectedFolder() == null || self.selectedFolder().folderName != e.folderName)
            self.selectedFolder(e);
        
       ...