Grasping Knockout

I need to grasp it from the ground up

by db_dev

HTML

<script src="//code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<!-- 
  Bootstrap docs: https://getbootstrap.com/docs
-->

<div class="container">
    <h2>Your seat reservations (<span data-bind="text: seats().length"></span>)</h2>
    <div class="row">
        <div class="col">
            <table class="table">
                <thead>
                    <tr>
                        <th>Passenger Name</th>
                        <th>Meal</th>
                        <th>Surcharge</th>
                    </tr>
                </thead>
                <!-- Gen Table Body -->
                <tbody data-bind="foreach:seats">
                    <tr>
                        <td> <input type="text" data-bind="value: name" /></td>
                        <td> <select data-bind="options:$root.availableMeals, value: meal, optionsText:'mealName'"></select></td>
                        <td data-bind="text:formattedPrice"></td>
                        <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td>
                    </tr>
                </tbody>
            </table>
            <h3 data-bind="visible: totalSurcharge() > 0">
                Total Surcharge: $<span data-bind="text:totalSurcharge().toFixed(2)"></span>
            </h3>
        </div>
    </div>
    <div class="row">
        <button class="btn btn-info" data-bind="click:addSeat, enable: seats().length < 5">Reserve another seat</button>
    </div>


    <h2 class="mt-5">Simple</h2>
    <div class="row">

        <div class="col">
            <p>First Name: <span data-bind="text:firstName"></span></p>
 ...

JavaScript

// Class to represent a row in the seat reservations grid
   function SeatReservation(name, initialMeal) {
       var self = this;

       self.name = name;
       self.meal = ko.observable(initialMeal);

       self.formattedPrice = ko.computed(function() {
           var price = self.meal().price;
           return price ? "$" + price.toFixed(2) : "None";
       })
   }

   function viewModel() {
       var self = this;

       // Simple Text 
       self.firstName = ko.observable("Berry");
       self.lastName = ko.observable("Berrymore");

       // Simple Obervables
       self.middleName = ko.observable("Kimberly");
       self.title = ko.observable("Ms");

       // Simple Computed
       self.fullName = ko.computed(function() {
           return self.title() + ". " + self.firstName() + " " + self.middleName() + " " + self.lastName();
       });

       // Updating the ViewModel
       self.capitalizeLastName = function() {
           var currentVal = self.lastName();
           self.lastName(currentVal.toUpperCase());
       }

       // Lists and Collections---------------------------------

       // Overall VM for this screen, along with intial state
       self.availableMeals = [{
               mealName: "Standard (sandwich)",
               price: 0
           },
           {
               mealName: "Premium (lobster)",
               price: 34.95
           },
           {
               mealName: "Ultimate (whole zebra)",
               price: 290
           }
       ];

       // Editable Data
       self.seats = ko.observableArray([
           new SeatReservation("Berry", self.availableMeals[1]),
           new SeatReservation("Cherry", self.availableMeals[2]),
           new SeatReservation("Raspberry", self.availableMeals[1]),
           new SeatReservation("Banana", self.availableMeals[2]),
           new SeatReservation("Blueberry", self.availableMeals[1])
       ]);

       // Add Button
       self.addSeat = function() {
          ...