knockout and tinymce

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/knockout/3.4.2/knockout-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tinymce/4.8.5/tinymce.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/attrchange/2.0.1/attrchange.min.js"></script>
<div id="parameterLines" class="tab-pane fade in active">
  <!--<div style="margin:5px">
    <input type="button" class="btn btn-primary" id="addLine" value="Add Row" data-bind="click: $root.addLine, visible: $root.editMode() && $root.specMode()" />
    <input type="button" class="btn btn-primary" id="arrangeRows" value="Arrange Rows" data-bind="visible: $root.editMode(), disable: $root.linesSorted()" />
    <input type="button" class="btn btn-primary" id="publish" value="Publish" data-bind="visible: $root.editMode()" />
    <input type="button" class="btn btn-primary" id="newFrom" data-bind="value: 'Create New '+$root.modeTitle()+' from this Data', visible: !$root.editMode()" />
    <input type="button" class="btn btn-primary" id="openPdf" value="Open PDF" data-bind="visible: !$root.editMode(), click: $root.openPDFCurrent, enable: $root.pdfExists()" />
  </div>-->
  <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...

JavaScript

$(document).ready(function() {
  ko.options.deferUpdates = true;
  ko.applyBindings(specCofaVM);
  $("#reload").click(function() {
    specCofaVM.display();
  }).click();
});

function SpecCofAViewModel() {
  var self = this;
  self.parameterData = ko.observableArray([]);
  self.mode = ko.observable('spec');
  self.display = function() {
    var timeNow = Date.now();
    $.each(tinymce.get(), function(i, editor) {
      $.each(editor.notificationManager.getNotifications(), function(i, notification) {
        editor.notificationManager.close();
      });
      editor.undoManager.clear();
      editor.destroy();
      editor=null;
    });
    tinymce.editors=[];
    self.parameterData([]);
    var lineArray = []
    $.each(specLines, function(i, val) {
      lineArray.push(new dataLine(val, self));
    });
    ko.utils.arrayPushAll(self.parameterData(), lineArray);
    self.parameterData.valueHasMutated();
    ko.tasks.runEarly();
    $(".tinymceSupSubEdit,.tinymceEdit").tinymce(ko.bindingHandlers['wysiwyg'].defaults);
    $("#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 ||...