ckeditor with knockout

by JonNorman

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/attrchange/2.0.1/attrchange.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.11.1/ckeditor.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
comment: <p id="comment" style="display:inline-block; margin:0" data-bind="text:$root.comment" ></p>
<div id="parameterLines" class="tab-pane fade in active">
  <table style="border: 1px solid">
    <thead>
      <tr class="side-margin">
        <th width="150px">Quality Parameter</th>
        <th width="150px">Method of Analysis</th>
        <th width="180px">Conditions of Analysis</th>
        <th width="200px">Specification Requirement</th>
        <th width="50px">UoM</th>
        <th width="40px">Tol</th>
        <th width="50px">UoT</th>
        <!-- ko if: $root.cofaMode() -->
        <th width="70px">Results</th>
        <th width="50px">UoR</th>
        <th width="40px">Tol</th>
        <th width="50px">UoT</th>
        <!-- /ko -->
        <!-- ko if: $root.editMode() && $root.specMode() -->
        <th></th>
        <!-- /ko -->
      </tr>
    </thead>
    <tbody data-bind="foreach: parameterData">
      <tr>
        <td valign="top" width="150px">
          <p style="display:inline-block; margin:0" class="v4QP" data-bind="attr: {id : 'qp_' + $index()} , ckeditor : QualityParameter, css: {disabledDv : !$root.canEditSpec(), editable: $root.specMode() }"></p>
        </td>
        <td valign="top" width="150px">
          <p style="display:inline-block; margin:0" class="v4MoA subsup" style="height:100%" data-bind="attr: {id : 'moa_' + $index()} , ckeditor: MethodOfAnalysis, css: {disabledDv : !$root.canEditSpec(), editable : $root.specMode()}"></p>
        </td>
        <td valign="top" width="180px">
          <p style="display:inline-block; margin:0" class="v4CoA subsup"...

CSS

th,
td {
  border: 1px solid
}

JavaScript

CKEDITOR.disableAutoInline = true;
$(document).ready(function() {
  CKEDITOR.disableAutoInline = true;
  ko.options.deferUpdates = true;
  ko.applyBindings(specCofaVM);
  $("#reload").click(function() {
    specCofaVM.display();
    $("#comment").attr("contenteditable","true");
  }).click();
  $("#debugbutton").click(function() {
    debug();
  });
});

function debug() { 
  specCofaVM.parameterData.valueHasMutated();
  //specCofaVM.parameterData[0].valueHasMutated();
}

function SpecCofAViewModel() {
  var self = this;
  self.parameterData = ko.observableArray([]);
  self.mode = ko.observable('spec');
  self.comment = ko.observable('');
  self.display = function() {
    var timeNow = Date.now();
    self.parameterData([]);
    lineArray = []
    $.each(specLines, function(i, val) {
      lineArray.push(new dataLine(val, self));
    });
    ko.utils.arrayPushAll(self.parameterData(), lineArray);
    self.parameterData.valueHasMutated();
    ko.tasks.runEarly();

    $("#debug").text((Date.now() - timeNow) + "ms");
  }
  self.specMode = ko.pureComputed(function() {
    if (self.mode() == 'spec') {
      return true;
    } else {
      return false;
    }
  });
  self.cofaMode = ko.pureComputed(function() {
    if (self.mode() == 'cofa') {
      return true;
    } else {
      return false;
    }
  });
  self.editMode = ko.observable(true);
  self.canEditSpec = ko.computed(function() {
    if ((self.editMode()) && (self.specMode())) {
      return true;
    } else {
      return false;
    }
  });
}

function dataLine(line, vm) {
  var self = this;
  // Common Data
  self.ID = line.ID || 0;
  self.QualityParameter = ko.observable(line.QualityParameter || "");
  self.MethodOfAnalysis = ko.observable(line.MethodOfAnalysis || "");
  self.ConditionsOfAnalysis = ko.observable(line.ConditionsOfAnalysis || "");
  self.SpecRequirement = ko.observable(line.SpecRequirement || "");
  self.UOM = ko.observable(line.UOM || "");
  self.Tolerance = ko.observable(line.Tolerance ||...