TranscriptionLanes

by Barry Carter

HTML

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
<div class='liveExample'>
  <div data-bind="with: rec">
    <span data-bind='text: totalLength'> </span>
    <div class="RecWrapper" data-bind="foreach: parties">
      <div class="party row">
          <div class="col-sm-1" data-bind="text: $root.getPartyName($data)">
          </div>
          <div class="col-sm-11">
            <div class="partyWrapper" data-bind="foreach: $root.getInstants($data.partyType), css: 'partyWrapper-' + $index()">
                <span class="instant" data-bind="css: 'instantType-' + $parent.partyType">
                  <p data-bind="style: { width: $root.elementWidth($data), left: $root.elementStart($data) }"></p>
                </span>
            </div>
        </div>
      </div>
  </div>
</div>
<div data-bind="with: rec">
    <div data-bind="foreach: instants">
      <div>
        <div data-bind="text: $root.formatTime($data.position())">
          
        </div>
        <span data-bind="text: text"></span>
      </div>
    </div>
  </div>
</div>

CSS

body { font-family: arial; font-size: 14px; }
.liveExample { padding: 1em; background-color: white; border: 1px solid #CCC; width:100%; max-width: 100%; position: relative; }
.instant p {
 position: absolute; 
 height:14px;
 background-color: #9ddcff;
 top: 2px;
 display:block;
 padding:0px;
 margin:0px;
}


.partyWrapper {
        height:20px;
  position: relative;
    margin-bottom: 15px;
}
.partyWrapper-0 {
  border-bottom: 1px solid #e8e8e8;
}

.partyWrapper-1 {
  border-top: 1px solid #e8e8e8;
}

.instantType-1 p {
  background-color: #a6e1bf;
}

JavaScript

//data

var PartyModel = function(id, partyType, name) {
	this.id = id;
	this.name = name;
  this.partyType = partyType; // 0 = agent, 1=customer, 2=coach, 3=other
}

var RecordingModel = function() {
		this.totalLength = 30000;    
    this.instants = ko.observableArray([]);
    this.parties = ko.observableArray([new PartyModel(1, 0, "Agent Smith"), new PartyModel(1, 1, "Customer Jane")]);
}

//data
var InstantModel = function(id, party, start, len, text) {
		this.instantId = id;
    this.party = party;
    this.position = ko.observable(start);
		this.totalInstantLength = ko.observable(len);
    this.text = text;
}

var recs = new RecordingModel();
recs.instants([
	new InstantModel(1, 0, 1000, 2000, "Hello, I am calling from your bank"),
  new InstantModel(2, 1, 4000, 3000, "Oh Hi Bank"),
  new InstantModel(2, 0, 8000, 1000, "Yeah it would seem that blah"),
  new InstantModel(2, 1, 9000, 1000, "Oh Noes!"),
  new InstantModel(2, 0, 12000, 1000, "Indeed. If you would just hand over your card details, that would be greeeaaat"),
  new InstantModel(2, 1, 14000, 1000, "Sure, theey are four five..."),
  new InstantModel(2, 0, 16000, 1000, "Thanks"),
  
]);

// Here's my data model
var ViewModel = function(recordingModel) {
	var self = this;
	this.rec = ko.observable(recordingModel);
  
  this.getInstants = function(partyId) {
    return ko.pureComputed(function() {
    	if (typeof(self.rec()) == 'undefined')
      	return;
        console.log(self.rec());
      return ko.utils.arrayFilter(self.rec().instants(), function(item) {
        return item.party == partyId;
      });
    });
  }
  
  this.getPartyName = function(data) {
  	if (data.partyType == 0)
    	return "Agent";
    else if (data.partyType == 1)
    	return "Customer";
    else
    	return "Other";
  }
  
  this.formatTime = function(ms) {
    var milliseconds = parseInt((ms % 1000) / 100),
      seconds = Math.floor((ms / 1000) % 60),
      minutes = Math.floor((ms / (1000 * 60)) % 60),
      hours =...