knockout-sortable - seating chart

https://github.com/rniemeyer/knockout-sortable

by pj_js15

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.3.0.js"></script>
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>


<div id="main" data-bind="foreach: itemsTable">
    <!-- ko if: $index() == 0 -->        
        <div class="table">
            <span data-bind="text: agendaSPItems.Id"></span>
            <div class="seats" data-bind="sortable: { data: agendaSPItems, allowDrop: $root.isTableFull }">
                <div class="student" data-bind="text: ME"></div>
            </div>            
        </div>    
     <!-- /ko -->
</div>

<div id="anotherMain" data-bind="foreach: itemsTable">
    <!-- ko if: $index() == 1 -->
       <div class="table">
            <span data-bind="text: agendaSPItems.Id"></span>
            <div class="seats" data-bind="sortable: { data: agendaSPItems, allowDrop: $root.isTableFull }">
                <div class="student" data-bind="text: ME"></div>
            </div>            
        </div>    
     <!-- /ko -->
</div>




<div id="extra">
    <div>Available</div>
    <div class="new" data-bind="sortable: availableStudents">
        <div class="student" data-bind="text: name"></div>
    </div>
</div>

<div id="message" data-bind="flash: lastAction"></div>
<div id="error" data-bind="flash: lastError"></div>

<div id="master">
    <div>Master List</div>
    <table>
        <tr>
            <th></th>
            <th>Seat One</th>
            <th>Seat Two</th>
            <th>Seat Three</th>
            <th>Seat Four</th>
        </tr>
        <tbody data-bind="foreach: itemsTable">
            <tr>
                <th data-bind="text: agendaSPItems.Id"></th>
                <!-- ko foreach: agendaSPItems -->
                <td data-bind="text: ME"></td>
                <!-- /ko -->
            </tr>
        </tbody>
        <tr>
            <th>Available</th>
            <!-- ko foreach: availableStudents -->
            <td data-bind="text: ME"></td>
           ...

CSS

body {
    font-family: arial;
}

.table {
    float: left;
    text-align: center;
    margin-right: 5px;
}

.table span {
    font-size: .75em;
}

.seats {
    border: solid 3px #666;
    width: 75px;
    height: 100px;
    background-color: #666;
    margin: 5px;
    padding: 2px;
    border-radius: 5px;
    box-shadow: 2px 2px 2px #999;
}

.ko_container {
    border: solid 3px green;
}

.student {
    background-color: #444;
    color: #fff;
    border-radius: 3px;
    margin: 2px;
    padding: 1px;
    text-align: center;
    width: 70px;
    cursor: move;
}

.new {
    border: solid 1px #444;
    background-color: #ccc;
    height: 25px;
    width: 500px;
    padding: 2px;
    border-radius: 5px;
}

.new div {
    float: left;
}

.note {
    font-style: italic;
    font-size: .75em;
    color: #888;
    margin-bottom: 10px;
}

.count {
    color: #666;
}

.ready {
    color: green;
}

#extra {
    clear: both;
    padding-top: 20px;
}

#master {
    margin-top: 40px;
}


#master td, th {
    font-size: .75em;
    text-align: center;
    padding: 1px;
    border: solid 1px black;
}

#master th {
    color: #666;
}

#message, #error {
    font-size: .75em;
    margin-top: 10px;
    background-color: orange;
    color: #444;
    padding: 2px;
    width: 500px;
    text-align: center;
    border-radius: 5px;
    box-shadow: 2px 2px 2px #999;
    position: absolute;
}

#error {
    background-color: #ff3333;
    color: #ddd;
}

JavaScript

ko.bindingHandlers.flash = {
    init: function(element) {
        //$(element).hide();
    },
    update: function(element, valueAccessor) {        
        var value = ko.utils.unwrapObservable(valueAccessor());
        /*
        if (value) {
            $(element).stop().hide().text(value).fadeIn(function() {
                clearTimeout($(element).data("timeout"));
                $(element).data("timeout", setTimeout(function() {
                    $(element).fadeOut();
                    valueAccessor()(null);
                }, 3000));
            });
        }
        */
    },
    timeout: null
};

/********** MeetingSetup ***************************/
var AgendaSPItem = function(Id, ME) {
    this.Id = Id;
    this.ME = ME;            
}

var ItemsTable = function(Id, agendaSPItems) {
    this.agendaSPItems = ko.observableArray(agendaSPItems);
    this.agendaSPItems.Id = Id;
}
/********** End of MeetingSetup *******************/


var Student = function(id, name, gender) {
    this.id = id;
    this.name = ko.observable(name);
    this.gender = gender;
};

var Table = function(id, students) {
    this.students = ko.observableArray(students);
    this.students.id = id;
};

var SeatingChartModel = function(tables, availableStudents) {
    var self = this;
    /* Meeting Setup */
    var testTable2 = [
    new ItemsTable("Agenda",  [
        new AgendaSPItem(1, "Ones"),
        new AgendaSPItem(2, "Twos"),
        new AgendaSPItem(3, "Threes")
    ]),
    new ItemsTable("Sub Pres", [
        new AgendaSPItem(4, "Fours"),
        new AgendaSPItem(5, "Fives"),
        new AgendaSPItem(6, "Sixs")
    ])
];
    this.itemsTable = ko.observableArray(testTable2);
    
    this.tables = ko.observableArray(tables);
    this.availableStudents = ko.observableArray(availableStudents);
    this.availableStudents.id = "Available Students";
    this.lastAction = ko.observable();
    this.lastError = ko.observable();
    this.maximumStudents = 4;
    this.isTableFull =...