source: main/trunk/greenstone3/web/interfaces/default/js/utility_scripts.js@ 36904

Last change on this file since 36904 was 36904, checked in by kjdon, 19 months ago

some work for tk labels. now looks in site metadata folder for tk.mds if it can't find it in the collection. added choose-tklabels-single-field template - use this on instead of choose-tklabels when you have a comma separated list of tk labels in single field, rather than individual tk.xxx metadata fields. pass in the metadata field name that contains the csv as the label-metadata parameter

File size: 25.3 KB
Line 
1/** JavaScript file of utility functions.
2 * At present contains functions for sanitising of URLs,
3 * since tomcat 8+, being more compliant with URL/URI standards, is more strict about URLs.
4 */
5
6/*
7 Given a string consisting of a single character, returns the %hex (%XX)
8 https://www.w3resource.com/javascript-exercises/javascript-string-exercise-27.php
9 https://stackoverflow.com/questions/40100096/what-is-equivalent-php-chr-and-ord-functions-in-javascript
10 https://www.w3resource.com/javascript-exercises/javascript-string-exercise-27.php
11*/
12function urlEncodeChar(single_char_string) {
13 /*var hex = Number(single_char_string.charCodeAt(0)).toString(16);
14 var str = "" + hex;
15 str = "%" + str.toUpperCase();
16 return str;
17 */
18
19 var hex = "%" + Number(single_char_string.charCodeAt(0)).toString(16).toUpperCase();
20 return hex;
21}
22
23/*
24 Tomcat 8 appears to be stricter in requiring unsafe and reserved chars
25 in URLs to be escaped with URL encoding
26 See section "Character Encoding Chart of
27 https://perishablepress.com/stop-using-unsafe-characters-in-urls/
28 Reserved chars:
29 ; / ? : @ = &
30 -----> %3B %2F %3F %3A %40 %3D %26
31 [Now also reserved, but no special meaning yet in URLs (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent)
32 and not required to be enforced yet, so we're aren't at present dealing with these:
33 ! ' ( ) *
34 ]
35 Unsafe chars:
36 " < > # % { } | \ ^ ~ [ ] ` and SPACE/BLANK
37 ----> %22 %3C %3E %23 %25 %7B %7D %7C %5C %5E ~ %5B %5D %60 and %20
38 But the above conflicts with the reserved vs unreserved listings at
39 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
40 Possibly more info: https://stackoverflow.com/questions/1547899/which-characters-make-a-url-invalid
41
42 And the bottom of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
43 lists additional characters that have been reserved since and which need encoding when in a URL component.
44
45 Javascript already provides functions encodeURI() and encodeURIComponent(), see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI
46 However, the set of chars they deal with only partially overlap with the set of chars that need encoding as per the RFC3986 for URIs and RFC1738 for URLs discussed at
47 https://perishablepress.com/stop-using-unsafe-characters-in-urls/
48 We want to handle all the characters listed as unsafe and reserved at https://perishablepress.com/stop-using-unsafe-characters-in-urls/
49 so we define and use our own conceptually equivalent methods for both existing JavaScript methods:
50 - makeSafeURL() for Javascript's encodeURI() to make sure all unsafe characters in URLs are escaped by being URL encoded
51 - and makeSafeURLComponent() for JavaScript's encodeURIComponent to additionally make sure all reserved characters in a URL portion are escaped by being URL encoded too
52
53 Function makeSafeURL() is passed a string that represents a URL and therefore only deals with characters that are unsafe in a URL and which therefore require escaping.
54 Function makeSafeURLComponent() deals with portions of a URL that when decoded need not represent a URL at all, for example data like inline templates passed in as a
55 URL query string's parameter values. As such makeSafeURLComponent() should escape both unsafe URL characters and characters that are reserved in URLs since reserved
56 characters in the query string part (as query param values representing data) may take on a different meaning from their reserved meaning in a URL context.
57*/
58
59/* URL encodes both
60 - UNSAFE characters to make URL safe, by calling makeSafeURL()
61 - and RESERVED characters (characters that have reserved meanings within a URL) to make URL valid, since the url component parameter could use reserved characters
62 in a non-URL sense. For example, the inline template (ilt) parameter value of a URL could use '=' and '&' signs where these would have XSLT rather than URL meanings.
63
64 See end of https://www.w3schools.com/jsref/jsref_replace.asp to use a callback passing each captured element of a regex in str.replace()
65*/
66function makeURLComponentSafe(url_part, encode_percentages) {
67 // https://stackoverflow.com/questions/12797118/how-can-i-declare-optional-function-parameters-in-javascript
68 encode_percentages = encode_percentages || 1; // this method forces the URL-encoding of any % in url_part, e.g. do this for inline-templates that haven't ever been encoded
69
70 var url_encoded = makeURLSafe(url_part, encode_percentages);
71 //return url_encoded.replace(/;/g, "%3B").replace(/\//g, "%2F").replace(/\?/g, "%3F").replace(/\:/g, "%3A").replace(/\@/g, "%40").replace(/=/g, "%3D").replace(/\&/g,"%26");
72 url_encoded = url_encoded.replace(/[\;\/\?\:\@\=\&]/g, function(s) {
73 return urlEncodeChar(s);
74 });
75 return url_encoded;
76}
77
78/*
79 URL encode UNSAFE characters to make URL passed in safe.
80 Set encode_percentages to 1 (true) if you don't want % signs encoded: you'd do so if the url is already partly URL encoded.
81*/
82function makeURLSafe(url, encode_percentages) {
83 encode_percentages = encode_percentages || 0; // https://stackoverflow.com/questions/12797118/how-can-i-declare-optional-function-parameters-in-javascript
84
85 var url_encoded = url;
86 if(encode_percentages) { url_encoded = url_encoded.replace(/\%/g,"%25"); } // encode % first
87 //url_encoded = url_encoded.replace(/ /g, "%20").replace(/\"/g,"%22").replace(/\</g,"%3C").replace(/\>/g,"%3E").replace(/\#/g,"%23").replace(/\{/g,"%7B").replace(/\}/g,"%7D");
88 //url_encoded = url_encoded.replace(/\|/g,"%7C").replace(/\\/g,"%5C").replace(/\^/g,"%5E").replace(/\[/g,"%5B").replace(/\]/g,"%5D").replace(/\`/g,"%60");
89 // Should we handle ~, but then what is its URL encoded value? Because https://meyerweb.com/eric/tools/dencoder/ URLencodes ~ to ~.
90 //return url_encoded;
91 url_encoded = url_encoded.replace(/[\ \"\<\>\#\{\}\|\\^\~\[\]\`]/g, function(s) {
92 return urlEncodeChar(s);
93 });
94 return url_encoded;
95}
96
97/***************
98* MENU SCRIPTS *
99***************/
100function moveScroller() {
101 var move = function() {
102 var editbar = $("#editBar");
103 var st = $(window).scrollTop();
104 var fa = $("#float-anchor").offset().top;
105 if(st > fa) {
106
107 editbar.css({
108 position: "fixed",
109 top: "0px",
110 width: editbar.data("width"),
111 //width: "30%"
112 });
113 } else {
114 editbar.data("width", editbar.css("width"));
115 editbar.css({
116 position: "relative",
117 top: "",
118 width: ""
119 });
120 }
121 };
122 $(window).scroll(move);
123 move();
124}
125
126
127function floatMenu(enabled)
128{
129 var menu = $(".tableOfContentsContainer");
130 if(enabled)
131 {
132 menu.data("position", menu.css("position"));
133 menu.data("width", menu.css("width"));
134 menu.data("right", menu.css("right"));
135 menu.data("top", menu.css("top"));
136 menu.data("max-height", menu.css("max-height"));
137 menu.data("overflow", menu.css("overflow"));
138 menu.data("z-index", menu.css("z-index"));
139
140 menu.css("position", "fixed");
141 menu.css("width", "300px");
142 menu.css("right", "0px");
143 menu.css("top", "100px");
144 menu.css("max-height", "600px");
145 menu.css("overflow", "auto");
146 menu.css("z-index", "200");
147
148 $("#unfloatTOCButton").show();
149 }
150 else
151 {
152 menu.css("position", menu.data("position"));
153 menu.css("width", menu.data("width"));
154 menu.css("right", menu.data("right"));
155 menu.css("top", menu.data("top"));
156 menu.css("max-height", menu.data("max-height"));
157 menu.css("overflow", menu.data("overflow"));
158 menu.css("z-index", menu.data("z-index"));
159
160 $("#unfloatTOCButton").hide();
161 $("#floatTOCToggle").prop("checked", false);
162 }
163
164 var url = gs.xsltParams.library_name + "?a=d&ftoc=" + (enabled ? "1" : "0") + "&c=" + gs.cgiParams.c;
165
166 $.ajax(url);
167}
168
169// TK Label Scripts
170
171var tkMetadataSetStatus = "needs-to-be-loaded";
172var tkMetadataElements = null;
173
174
175function addTKLabelToImage(labelName, definition, name, comment) {
176 // lists of tkLabels and their corresponding codes, in order
177 let tkLabels = ["Attribution","Clan","Family","MultipleCommunities","CommunityVoice","Creative","Verified","NonVerified","Seasonal","WomenGeneral","MenGeneral",
178 "MenRestricted","WomenRestricted","CulturallySensitive","SecretSacred","OpenToCommercialization","NonCommercial","CommunityUseOnly","Outreach","OpenToCollaboration"];
179 let tkCodes = ["tk_a","tk_cl","tk_f","tk_mc","tk_cv","tk_cr","tk_v","tk_nv","tk_s","tk_wg","tk_mg","tk_mr","tk_wr","tk_cs","tk_ss","tk_oc","tk_nc","tk_co","tk_o","tk_cb"];
180 for (let i = 0; i < tkLabels.length; i++) {
181 if (labelName == tkLabels[i]) {
182 let labeldiv = document.querySelectorAll(".tklabels img");
183 for (image of labeldiv) {
184 let labelCode = image.src.substr(image.src.lastIndexOf("/") + 1).replace(".png", ""); // get tk label code from image file name
185 if (labelCode == tkCodes[i]) {
186 image.title = "TK " + name + ": " + definition + " Click for more details."; // set tooltip
187 if (image.parentElement.parentElement.parentElement.classList[0] != "tocSectionTitle") { // disable onclick event in favourites section
188 image.addEventListener("click", function(e) {
189 let currPopup = document.getElementsByClassName("tkPopup")[0];
190 if (currPopup == undefined || (currPopup != undefined && currPopup.id != labelCode)) {
191 let popup = document.createElement("div");
192 popup.classList.add("tkPopup");
193 popup.id = labelCode;
194 let popupText = document.createElement("span");
195 let heading = "<h1>Traditional Knowledge Label:<br><h2>" + name + "</h2></h1>";
196 let moreInformation = "<br> For more information about TK Labels, ";
197 let link = document.createElement("a");
198 link.innerHTML = "click here.";
199 link.href = "https://localcontexts.org/labels/traditional-knowledge-labels/";
200 link.target = "_blank";
201 popupText.innerHTML = heading + comment + moreInformation;
202 popupText.appendChild(link);
203 let closeButton = document.createElement("span");
204 closeButton.innerHTML = "&#215;";
205 closeButton.id = "tkCloseButton";
206 closeButton.title = "Click to close window."
207 closeButton.addEventListener("click", function(e) {
208 closeButton.parentElement.remove();
209 });
210 popup.appendChild(closeButton);
211 popup.appendChild(popupText);
212 e.target.parentElement.appendChild(popup);
213 }
214 if (currPopup) currPopup.remove(); // remove existing popup div
215 });
216 }
217 }
218 }
219 }
220 }
221}
222
223function addTKLabelsToImages(lang) {
224 if (tkMetadataElements == null) {
225 console.error("ajax call not yet loaded tk label metadata set");
226 } else {
227 for (label of tkMetadataElements) { // for each tklabel element in tk.mds
228 let tkLabelName = label.attributes.name.value; // Element name=""
229 let attributes = label.querySelectorAll("[code=" + lang + "] Attribute"); // gets attributes for selected language
230 let tkName = attributes[0].textContent; // name="label"
231 let tkDefinition = attributes[1].textContent; // name="definition"
232 let tkComment = attributes[2].textContent; // name="comment"
233 addTKLabelToImage(tkLabelName, tkDefinition, tkName, tkComment);
234 }
235 }
236}
237
238function loadTKMetadataSetOld(lang) {
239 tkMetadataSetStatus = "loading";
240 $.ajax({
241 url: gs.variables["tkMetadataURL"],
242 success: function(xml) {
243 tkMetadataSetStatus = "loaded";
244 let parser = new DOMParser();
245 let tkmds = parser.parseFromString(xml, "text/xml");
246 tkMetadataElements = tkmds.querySelectorAll("Element");
247 if (document.readyState === "complete") {
248 addTKLabelsToImages(lang);
249 } else {
250 window.onload = function() {
251 addTKLabelsToImages(lang);
252 }
253 }
254 },
255 error: function() {
256 tkMetadataSetStatus = "no-metadata-set-for-this-collection";
257 console.log("No TK Label Metadata-set found for this collection");
258 }
259 });
260};
261function loadTKMetadataSet(lang, type) {
262 tkMetadataSetStatus = "loading";
263 $.ajax({
264 url: gs.variables["tkMetadataURL_"+type],
265 async: false,
266 success: function(xml) {
267 tkMetadataSetStatus = "loaded";
268 let parser = new DOMParser();
269 let tkmds = parser.parseFromString(xml, "text/xml");
270 tkMetadataElements = tkmds.querySelectorAll("Element");
271 if (document.readyState === "complete") {
272 addTKLabelsToImages(lang);
273 } else {
274 window.onload = function() {
275 addTKLabelsToImages(lang);
276 }
277 }
278 },
279 error: function() {
280 tkMetadataSetStatus = "no-metadata-set-for-this-"+type;
281 console.log("No TK Label Metadata-set found for this "+type);
282 }
283 });
284};
285
286// Audio Scripts for Enriched Playback
287
288function loadAudio(audio, sectionData) {
289 var speakerObjects = [];
290 var uniqueSpeakers;
291 const inputFile = sectionData;
292 var itemType;
293
294 // var accentColour = "#4CA72D";
295 var accentColour = "#F8C537";
296 var regionTransparency = "59";
297
298 var waveformContainer = document.getElementById("waveform");
299
300 var wavesurfer = WaveSurfer.create({ // wavesurfer options
301 container: waveformContainer,
302 backend: "MediaElement",
303 backgroundColor: "rgb(54, 73, 78)",
304 waveColor: "white",
305 progressColor: accentColour,
306 barWidth: 2,
307 barHeight: 1.2,
308 barGap: 2,
309 barRadius: 1,
310 cursorColor: 'black',
311 plugins: [
312 WaveSurfer.regions.create(),
313 WaveSurfer.timeline.create({
314 container: "#wave-timeline",
315 secondaryColor: "white",
316 secondaryFontColor: "white",
317 notchPercentHeight: "0",
318 fontSize: "12"
319 }),
320 WaveSurfer.cursor.create({
321 showTime: true,
322 opacity: 1,
323 customShowTimeStyle: {
324 'background-color': '#000',
325 color: '#fff',
326 padding: '0.2em',
327 'font-size': '12px'
328 },
329 formatTimeCallback: (num) => { return minutize(num); }
330 }),
331 ],
332 });
333
334 wavesurfer.load(audio);
335
336 // wavesurfer events
337
338 wavesurfer.on('region-click', function(region, e) { // play region audio on click
339 e.stopPropagation();
340 handleRegionColours(region, true);
341 wavesurfer.play(region.start); // plays from start of region
342 // region.play(); // plays region only
343 });
344
345 wavesurfer.on('region-mouseenter', function(region) { handleRegionColours(region, true); });
346 wavesurfer.on('region-mouseleave', function(region) { if (!(wavesurfer.getCurrentTime() <= region.end && wavesurfer.getCurrentTime() >= region.start)) handleRegionColours(region, false); });
347 wavesurfer.on('region-in', function(region) {
348 handleRegionColours(region, true);
349 if (itemType == "chapter") {
350 document.getElementById("chapter" + region.id.replace("region", "")).scrollIntoView({
351 behavior: "smooth",
352 block: "nearest"
353 });
354 }
355 });
356 wavesurfer.on('region-out', function(region) { handleRegionColours(region, false); });
357
358 var loader = document.createElement("span"); // loading audio element
359 loader.innerHTML = "Loading audio";
360 loader.id = "waveform-loader";
361 document.querySelector("#waveform wave").prepend(loader);
362
363 wavesurfer.on('waveform-ready', function() { // retrieve regions once waveforms have loaded
364 if (inputFile.endsWith("csv")) { // diarization if csv
365 itemType = "chapter";
366 loadCSVFile(inputFile, ["speaker", "start", "end"]);
367 } else if (inputFile.endsWith("json")) { // transcription if json
368 itemType = "word";
369 loadJSONFile(inputFile);
370 } else {
371 console.log("Filetype of " + inputFile + " not supported.")
372 }
373 loader.remove(); // remove load text
374 });
375
376 function downloadURI(loc, name) {
377 var link = document.createElement("a");
378 link.download = name;
379 link.href = loc;
380 link.click();
381 }
382
383 // toolbar elements & event handlers
384 var chapters = document.getElementById("chapters");
385 var chapterButton = document.getElementById("chapterButton");
386 var backButton = document.getElementById("backButton");
387 var playPauseButton = document.getElementById("playPauseButton");
388 var forwardButton = document.getElementById("forwardButton");
389 var downloadButton = document.getElementById("downloadButton");
390 var muteButton = document.getElementById("muteButton");
391 var zoomSlider = document.getElementById("slider");
392 chapters.style.height = "0px";
393 chapterButton.addEventListener("click", function() { toggleChapters(); });
394 backButton.addEventListener("click", function() { wavesurfer.skipBackward(); });
395 playPauseButton.addEventListener("click", function() { wavesurfer.playPause() });
396 forwardButton.addEventListener("click", function() { wavesurfer.skipForward(); });
397 // audio = /greenstone3/library/sites/localsite/collect/tiriana-audio/index/assoc/HASHa6b7.dir/Te_Kakano_CH09_B.mp3
398 downloadButton.addEventListener("click", function() { downloadURI(audio, audio.split(".dir/")[1]) });
399 muteButton.addEventListener("click", function() { wavesurfer.toggleMute(); });
400 zoomSlider.style["accent-color"] = accentColour;
401
402 // path to toolbar images
403 var interface_bootstrap_images = "interfaces/" + gs.xsltParams.interface_name + "/images/bootstrap/";
404
405 wavesurfer.on("play", function() { playPauseButton.src = interface_bootstrap_images + "pause.svg"; });
406 wavesurfer.on("pause", function() { playPauseButton.src = interface_bootstrap_images + "play.svg"; });
407 wavesurfer.on("mute", function(mute) {
408 if (mute) {
409 muteButton.src = interface_bootstrap_images + "mute.svg";
410 muteButton.style.opacity = 0.6;
411 }
412 else {
413 muteButton.src = interface_bootstrap_images + "unmute.svg";
414 muteButton.style.opacity = 1;
415 }
416 });
417
418 zoomSlider.oninput = function () { // slider changes waveform zoom
419 wavesurfer.zoom(Number(this.value) / 4);
420 };
421 wavesurfer.zoom(zoomSlider.value / 4); // set default zoom point
422
423 var toggleChapters = function() { // show & hide chapter section
424 if (chapters.style.height == "0px") {
425 chapters.style.height = "30vh";
426 } else {
427 chapters.style.height = "0px";
428 }
429 }
430
431 function loadCSVFile(filename, manualHeader) { // based around: https://stackoverflow.com/questions/7431268/how-to-read-data-from-csv-file-using-javascript
432 $.ajax({
433 type: "GET",
434 url: filename,
435 dataType: "text",
436 }).then(function(data) {
437 var dataLines = data.split(/\r\n|\n/);
438 var headers;
439 var startIndex;
440 uniqueSpeakers = []; // used for obtaining unique colours
441 speakerObjects = []; // list of speaker items
442
443 if (manualHeader) { // headers for columns can be provided if not existent in csv
444 headers = manualHeader;
445 startIndex = 0;
446 } else {
447 headers = dataLines[0].split(',');
448 startIndex = 1;
449 }
450
451 for (var i = startIndex; i < dataLines.length; i++) {
452 var data = dataLines[i].split(',');
453 if (data.length == headers.length) {
454 var item = {};
455 for (var j = 0; j < headers.length; j++) {
456 item[headers[j]] = data[j];
457 if (j == 0) {
458 if (!uniqueSpeakers.includes(data[j])) {
459 uniqueSpeakers.push(data[j]);
460 }
461 }
462 }
463 speakerObjects.push(item);
464 }
465 }
466 populateChapters(speakerObjects);
467 });
468 }
469
470 function populateChapters(data) { // populates chapter section and adds regions to waveform
471 // colorbrewer is a web tool for guidance in choosing map colour schemes based on a variety of settings.
472 // this colour scheme is designed for qualitative data
473
474 if (uniqueSpeakers.length > 8) colourbrewerset = colorbrewer.Set2[8];
475 else if (uniqueSpeakers.length < 3) colourbrewerset = colorbrewer.Set2[3];
476 else colourbrewerset = colorbrewer.Set2[uniqueSpeakers.length];
477
478 for (var i = 0; i < data.length; i++) {
479 var chapter = document.createElement("div");
480 var speakerLetter = getLetter(data[i]);
481 chapter.id = "chapter" + i;
482 chapter.classList.add("chapter");
483 chapter.innerHTML = "Speaker " + speakerLetter + "<span class='speakerTime' id='" + "chapter" + i + "'>" + minutize(data[i].start) + " - " + minutize(data[i].end) + "</span>";
484 chapter.addEventListener("click", e => { chapterClicked(e.target.id) });
485 chapter.addEventListener("mouseover", e => { chapterEnter(e.target.id) });
486 chapter.addEventListener("mouseleave", e => { chapterLeave(e.target.id) });
487 chapters.appendChild(chapter);
488 // console.log("index: " + uniqueSpeakers.indexOf(data[i].speaker)%8);
489 // console.log("colour: " + colourbrewerset[uniqueSpeakers.indexOf(data[i].speaker)%8]);
490 wavesurfer.addRegion({
491 id: "region" + i,
492 start: data[i].start,
493 end: data[i].end,
494 drag: false,
495 resize: false,
496 color: colourbrewerset[uniqueSpeakers.indexOf(data[i].speaker)%8] + regionTransparency,
497 });
498 }
499 }
500
501 function loadJSONFile(filename) {
502 $.ajax({
503 type: "GET",
504 url: filename,
505 dataType: "text",
506 }).then(function(data){ populateWords(JSON.parse(data)) });
507 }
508
509 function populateWords(data) { // populates word section and adds regions to waveform
510 var transcription = data.transcription;
511 var words = data.words;
512 var wordContainer = document.createElement("div");
513 wordContainer.id = "word-container";
514 for (var i = 0; i < words.length; i++) {
515 var word = document.createElement("span");
516 word.id = "word" + i;
517 word.classList.add("word");
518 word.innerHTML = transcription.split(" ")[i];
519 word.addEventListener("click", e => { wordClicked(data, e.target.id) });
520 word.addEventListener("mouseover", e => { chapterEnter(e.target.id) });
521 word.addEventListener("mouseleave", e => { chapterLeave(e.target.id) });
522 wordContainer.appendChild(word);
523 wavesurfer.addRegion({
524 id: "region" + i,
525 start: words[i].startTime,
526 end: words[i].endTime,
527 drag: false,
528 resize: false,
529 color: "rgba(255, 255, 255, 0.1)",
530 });
531 }
532 chapters.appendChild(wordContainer);
533 }
534
535 var chapterClicked = function(id) { // plays audio from start of chapter
536 var index = id.replace("chapter", "");
537 var start = speakerObjects[index].start;
538 var end = speakerObjects[index].end;
539 // wavesurfer.play(start, end);
540 wavesurfer.play(start);
541 }
542
543 function wordClicked(data, id) { // plays audio from start of word
544 var index = id.replace("word", "");
545 var start = data.words[index].startTime;
546 var end = data.words[index].endTime;
547 // wavesurfer.play(start, end);
548 wavesurfer.play(start);
549 }
550
551 function chapterEnter(id) {
552 regionEnter(wavesurfer.regions.list["region" + id.replace(itemType, "")]);
553 }
554
555 function chapterLeave(id) {
556 regionLeave(wavesurfer.regions.list["region" + id.replace(itemType, "")]);
557 }
558
559 function handleRegionColours(region, highlight) { // handles region, chapter & word colours
560 var colour;
561 if (highlight) {
562 colour = "rgb(101, 116, 116)";
563 regionEnter(region);
564 } else {
565 colour = "";
566 regionLeave(region);
567 }
568 var regionIndex = region.id.replace("region","");
569 var corrItem = document.getElementById(itemType + regionIndex);
570 corrItem.style.backgroundColor = colour;
571 }
572
573 function regionEnter(region) {
574 region.update({ color: "rgba(255, 255, 255, 0.35)" });
575 }
576
577 function regionLeave(region) {
578 if (itemType == "chapter") {
579 if (!(wavesurfer.getCurrentTime() + 0.1 < region.end && wavesurfer.getCurrentTime() > region.start)) {
580 var index = region.id.replace("region", "");
581 region.update({ color: colourbrewerset[uniqueSpeakers.indexOf(speakerObjects[index].speaker)%8] + regionTransparency });
582 }
583 } else {
584 region.update({ color: "rgba(255, 255, 255, 0.1)" });
585 }
586 }
587
588 function minutize(num) { // converts seconds to m:ss for chapters & waveform hover
589 var seconds = Math.round(num % 60);
590 if (seconds.toString().length == 1) seconds = "0" + seconds;
591 return Math.floor(num / 60) + ":" + seconds;
592 }
593
594 function getLetter(val) {
595 var speakerNum = parseInt(val.speaker.replace("SPEAKER_",""));
596 return String.fromCharCode(65 + speakerNum); // 'A' == UTF-16 65
597 }
598}
599
600function formatAudioDuration(duration) {
601 console.log(duration);
602 var [hrs, mins, secs, ms] = duration.replace(".", ":").split(":");
603 return hrs + ":" + mins + ":" + secs;
604}
Note: See TracBrowser for help on using the repository browser.