alessandro trinca tornidor commited on
Commit
0c4660b
·
1 Parent(s): 7a541c8

feat: UI change, now it shows some text around the selected word

Browse files
Files changed (3) hide show
  1. static/index-dark.css +4 -1
  2. static/index.css +4 -1
  3. static/index.js +94 -22
static/index-dark.css CHANGED
@@ -9,7 +9,7 @@
9
  text-align: left;
10
  font-weight: bold;
11
  }
12
- #words-frequency > table > thead > tr > td, #words-frequency > table > tbody > tr > td {
13
  padding-left: 10px;
14
  padding-right: 10px;
15
  }
@@ -17,6 +17,9 @@
17
  height: 30px;
18
  width: 100%;
19
  }
 
 
 
20
  .display-none {
21
  display: none;
22
  }
 
9
  text-align: left;
10
  font-weight: bold;
11
  }
12
+ #words-frequency > div > table > thead > tr > td, #words-frequency > div > table > tbody > tr > td {
13
  padding-left: 10px;
14
  padding-right: 10px;
15
  }
 
17
  height: 30px;
18
  width: 100%;
19
  }
20
+ .font-weight-bold {
21
+ font-weight: bolder;
22
+ }
23
  .display-none {
24
  display: none;
25
  }
static/index.css CHANGED
@@ -16,10 +16,13 @@
16
  text-align: left;
17
  font-weight: bold;
18
  }
19
- #words-frequency > table > thead > tr > td, #words-frequency > table > tbody > tr > td {
20
  padding-left: 10px;
21
  padding-right: 10px;
22
  }
 
 
 
23
  .display-none {
24
  display: none;
25
  }
 
16
  text-align: left;
17
  font-weight: bold;
18
  }
19
+ #words-frequency > div > table > thead > tr > td, #words-frequency > div > table > tbody > tr > td {
20
  padding-left: 10px;
21
  padding-right: 10px;
22
  }
23
+ .font-weight-bold {
24
+ font-weight: bolder;
25
+ }
26
  .display-none {
27
  display: none;
28
  }
static/index.js CHANGED
@@ -1,7 +1,8 @@
1
  const wordsFrequencyTableTitleText = "Words Frequency Stats"
2
  let wfo = {
3
  "words_frequency": {},
4
- "nTotalRows": null
 
5
  }
6
  const editorFieldLabel = "editor"
7
  const remoteWebServer = "http://localhost:7860"
@@ -42,7 +43,7 @@ const wordsFrequencyAnalyzers = {
42
  let freq = bodyResponseJson["words_frequency"]
43
  let nTotalRows = bodyResponseJson["n_total_rows"]
44
  console.log(`wordsFrequencyAnalyzers::nTotalRows: '${nTotalRows}'`)
45
- populateWordsFrequencyTables(freq, nTotalRows)
46
  } catch (err) {
47
  console.error("wordsFrequencyAnalyzers::err on webserver request/response:", err, "#")
48
  console.log(`wordsFrequencyAnalyzers::wordsFrequencyURL: ${typeof wordsFrequencyURL}:`, wordsFrequencyURL, "#")
@@ -64,7 +65,7 @@ const wordsFrequencyAnalyzers = {
64
  let freq = bodyResponseJson["wordsStemsDict"]
65
  let nTotalRows = bodyResponseJson["nTotalRows"]
66
  console.log(`getWordsFreq::nTotalRows: '${nTotalRows}', populateWordsFrequencyTables...`)
67
- populateWordsFrequencyTables(freq, nTotalRows)
68
  // temp until we have the new UI
69
  let hiddenOutputSpan = document.getElementById("id-hidden-editor")
70
  hiddenOutputSpan.textContent = JSON.stringify(freq, null, 2)
@@ -362,7 +363,6 @@ function getFormDataByKey(formId, key) {
362
  *
363
  * @function previewFile
364
  * @description Displays the contents of a selected text file within an element with id 'editor'.
365
- * @param {none}
366
  */
367
  function previewFile() {
368
  const editor = document.getElementById(editorFieldLabel);
@@ -437,8 +437,8 @@ function setCaret(line, offsetColumn, nRowChild, nRowParent) {
437
  editorElement.focus();
438
 
439
  const offsetsEditor = getOffsetsWithElement(editorElement)
440
- const yBase = parseInt(offsetsEditor.top, 10)
441
- const y = parseInt(getBoundingClientRect(rng).y, 10)
442
  const yClientOffset = y - yBase
443
 
444
  scrollToGivenPoint(editorElement, yClientOffset)
@@ -596,7 +596,7 @@ function arrayFilterNestedValue(array, nestedValue) {
596
  /**
597
  * Updates the words frequency tables with new data.
598
  *
599
- * Called whenever a change in form input fields or the uploaded text file affects the words frequency table's content.
600
  * Sorts and filters the word groups based on user preferences, and updates the HTML elements containing these tables.
601
  *
602
  * @function updateWordsFrequencyTables
@@ -634,17 +634,19 @@ function updateWordsFrequencyTables() {
634
  }
635
 
636
  /**
637
- * Populate the words frequency tables in the UI with data from the provided object or JSON string.
638
  *
639
  * @param {Object|string} wordsFrequencyObj - The object or JSON string containing word frequencies.
640
  * @param {number} nTotalRows - The total number of lines/rows to display for each word group.
 
641
  */
642
- function populateWordsFrequencyTables(wordsFrequencyObj, nTotalRows) {
643
  wfo["words_frequency"] = wordsFrequencyObj
644
  if (typeof wordsFrequencyObj === "string") {
645
  wfo["words_frequency"] = JSON.parse(wordsFrequencyObj)
646
  }
647
  wfo["nTotalRows"] = nTotalRows
 
648
  updateWordsFrequencyTables()
649
  }
650
 
@@ -665,18 +667,11 @@ function insertCurrentTable(i, iReduced, currentTableOfWords) {
665
  currentCaption.setAttribute("aria-label", `id-table-${i}-caption`)
666
  currentCaption.innerText = `${iReduced["word_prefix"]}: ${iReduced["count"]} repetitions`
667
 
668
- let currentTHead = document.createElement("thead")
669
- let currentTHeadRow = currentTHead.insertRow()
670
- currentTHeadRow.insertCell().textContent = 'word'
671
- currentTHeadRow.insertCell().textContent = 'row nth'
672
- currentTHeadRow.insertCell().textContent = 'offsets'
673
-
674
  let currentTBody = document.createElement("tbody")
675
  let offsetsArray = iReduced.offsets_array
676
  for (let ii = 0; ii < offsetsArray.length; ii++) {
677
  insertCellIntoTRow(currentTBody, i, ii, offsetsArray[ii])
678
  }
679
- currentTableWordsFreq.appendChild(currentTHead)
680
  currentTableWordsFreq.appendChild(currentTBody)
681
  currentTableOfWords.appendChild(currentTableWordsFreq)
682
  }
@@ -713,13 +708,15 @@ function insertListOfWords(i, iReduced, wordListElement, currentTableOfWords) {
713
  * @param {Object} nthOffset - An object containing information about a single offset word, including its row number and word text.
714
  */
715
  function insertCellIntoTRow(currentTBody, i, ii, nthOffset) {
 
716
  let nthRowBody = currentTBody.insertRow()
717
  nthRowBody.setAttribute("id", `id-table-${i}-row-${ii}-nth`)
718
  nthRowBody.setAttribute("aria-label", `id-table-${i}-row-${ii}-nth`)
 
719
  let currentCell = nthRowBody.insertCell()
720
  let currentUrl = document.createElement("a")
721
  currentUrl.addEventListener("click", function() {
722
- let nRow = nthOffset["n_row"]
723
  let nRowChild = nthOffset["n_row_child"]
724
  let nRowParent = nthOffset["n_row_parent"]
725
  let offsetWord = nthOffset["offsets"]
@@ -728,16 +725,91 @@ function insertCellIntoTRow(currentTBody, i, ii, nthOffset) {
728
  currentUrl.className = underlinedClickedTable
729
  })
730
  currentUrl.className = underlinedPrimary
731
- currentUrl.innerText = nthOffset["word"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
732
  currentCell.appendChild(currentUrl)
733
- nthRowBody.insertCell().textContent = nthOffset["n_row"]
734
- nthRowBody.insertCell().textContent = nthOffset["offsets"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
735
  }
736
 
737
  /**
738
- * Updates the words frequency tables with new data if enter key is pressed.
739
  * If the event target has a value (i.e., it's an input field) and the event key is "Enter",
740
- * call the updateWordsFrequencyTables function to update the words frequency tables.
741
  *
742
  * @returns {void}
743
  */
 
1
  const wordsFrequencyTableTitleText = "Words Frequency Stats"
2
  let wfo = {
3
  "words_frequency": {},
4
+ "nTotalRows": null,
5
+ "rowArray": []
6
  }
7
  const editorFieldLabel = "editor"
8
  const remoteWebServer = "http://localhost:7860"
 
43
  let freq = bodyResponseJson["words_frequency"]
44
  let nTotalRows = bodyResponseJson["n_total_rows"]
45
  console.log(`wordsFrequencyAnalyzers::nTotalRows: '${nTotalRows}'`)
46
+ populateWordsFrequencyTables(freq, nTotalRows, arrayOfValidTextChildWithNrow)
47
  } catch (err) {
48
  console.error("wordsFrequencyAnalyzers::err on webserver request/response:", err, "#")
49
  console.log(`wordsFrequencyAnalyzers::wordsFrequencyURL: ${typeof wordsFrequencyURL}:`, wordsFrequencyURL, "#")
 
65
  let freq = bodyResponseJson["wordsStemsDict"]
66
  let nTotalRows = bodyResponseJson["nTotalRows"]
67
  console.log(`getWordsFreq::nTotalRows: '${nTotalRows}', populateWordsFrequencyTables...`)
68
+ populateWordsFrequencyTables(freq, nTotalRows, inputText)
69
  // temp until we have the new UI
70
  let hiddenOutputSpan = document.getElementById("id-hidden-editor")
71
  hiddenOutputSpan.textContent = JSON.stringify(freq, null, 2)
 
363
  *
364
  * @function previewFile
365
  * @description Displays the contents of a selected text file within an element with id 'editor'.
 
366
  */
367
  function previewFile() {
368
  const editor = document.getElementById(editorFieldLabel);
 
437
  editorElement.focus();
438
 
439
  const offsetsEditor = getOffsetsWithElement(editorElement)
440
+ const yBase = offsetsEditor.top
441
+ const {y} = getBoundingClientRect(rng)
442
  const yClientOffset = y - yBase
443
 
444
  scrollToGivenPoint(editorElement, yClientOffset)
 
596
  /**
597
  * Updates the words frequency tables with new data.
598
  *
599
+ * Called whenever a change in form input fields or the uploaded text file affects the word frequency table's content.
600
  * Sorts and filters the word groups based on user preferences, and updates the HTML elements containing these tables.
601
  *
602
  * @function updateWordsFrequencyTables
 
634
  }
635
 
636
  /**
637
+ * Populate the word frequency tables in the UI with data from the provided object or JSON string.
638
  *
639
  * @param {Object|string} wordsFrequencyObj - The object or JSON string containing word frequencies.
640
  * @param {number} nTotalRows - The total number of lines/rows to display for each word group.
641
+ * @param rowArray - An array of objects representing the rows of text, each containing the text and its corresponding index.
642
  */
643
+ function populateWordsFrequencyTables(wordsFrequencyObj, nTotalRows, rowArray) {
644
  wfo["words_frequency"] = wordsFrequencyObj
645
  if (typeof wordsFrequencyObj === "string") {
646
  wfo["words_frequency"] = JSON.parse(wordsFrequencyObj)
647
  }
648
  wfo["nTotalRows"] = nTotalRows
649
+ wfo["rowArray"] = Object.values(rowArray)
650
  updateWordsFrequencyTables()
651
  }
652
 
 
667
  currentCaption.setAttribute("aria-label", `id-table-${i}-caption`)
668
  currentCaption.innerText = `${iReduced["word_prefix"]}: ${iReduced["count"]} repetitions`
669
 
 
 
 
 
 
 
670
  let currentTBody = document.createElement("tbody")
671
  let offsetsArray = iReduced.offsets_array
672
  for (let ii = 0; ii < offsetsArray.length; ii++) {
673
  insertCellIntoTRow(currentTBody, i, ii, offsetsArray[ii])
674
  }
 
675
  currentTableWordsFreq.appendChild(currentTBody)
676
  currentTableOfWords.appendChild(currentTableWordsFreq)
677
  }
 
708
  * @param {Object} nthOffset - An object containing information about a single offset word, including its row number and word text.
709
  */
710
  function insertCellIntoTRow(currentTBody, i, ii, nthOffset) {
711
+ let rowArray = wfo["rowArray"]
712
  let nthRowBody = currentTBody.insertRow()
713
  nthRowBody.setAttribute("id", `id-table-${i}-row-${ii}-nth`)
714
  nthRowBody.setAttribute("aria-label", `id-table-${i}-row-${ii}-nth`)
715
+ const nthRowIdx = nthOffset["n_row"]
716
  let currentCell = nthRowBody.insertCell()
717
  let currentUrl = document.createElement("a")
718
  currentUrl.addEventListener("click", function() {
719
+ let nRow = nthRowIdx
720
  let nRowChild = nthOffset["n_row_child"]
721
  let nRowParent = nthOffset["n_row_parent"]
722
  let offsetWord = nthOffset["offsets"]
 
725
  currentUrl.className = underlinedClickedTable
726
  })
727
  currentUrl.className = underlinedPrimary
728
+ const wfoContainerWidth = getStylePropertyById("id-col2-words-frequency", "width", "int")
729
+ const listOfWordsWidth = getStylePropertyById("id-list-of-words", "width", "int")
730
+ const sentencesContainerWidth = wfoContainerWidth - listOfWordsWidth
731
+ const nCharsMore = Math.floor(sentencesContainerWidth / 20)
732
+ console.log(`insertCellIntoTRow::sentencesContainerWidth: ${sentencesContainerWidth}px, nCharsMore: ${nCharsMore}.`)
733
+ const {substring0, substringWord, substring2} = getSubstringForTextWithGivenOffset(rowArray, nthRowIdx, nthOffset, nCharsMore)
734
+
735
+ const span0 = document.createElement("span").innerText = substring0
736
+ const spanWord = document.createElement("span")
737
+ spanWord.setAttribute("class", "font-weight-bold")
738
+ spanWord.innerText = substringWord
739
+ const span2 = document.createElement("span").innerText = substring2
740
+ currentUrl.append(span0)
741
+ currentUrl.append(spanWord)
742
+ currentUrl.append(span2)
743
  currentCell.appendChild(currentUrl)
744
+ }
745
+
746
+ function getSubstringForTextWithGivenOffset(rowArray, nthRowIdx, nthOffset, nCharsMore = 30) {
747
+ try {
748
+ const currentRowArr = rowArray.filter(item => {
749
+ if (item.idxRowChild !== null) {
750
+ return item.idxRow === nthRowIdx && item.idxRowChild === nthOffset["n_row_child"] && item.idxRowParent === nthOffset["n_row_parent"]
751
+ }
752
+ return item.idxRow === nthRowIdx
753
+ })
754
+ const currentRow = currentRowArr[0]
755
+ const text = currentRow.text
756
+ let offset = nthOffset["offsets"]
757
+ let start = offset[0]
758
+ let end = offset[1]
759
+ let currentWord = nthOffset["word"]
760
+ let startOffset = Math.max(0, start - nCharsMore)
761
+ let endOffset = Math.min(text.length, end + nCharsMore)
762
+ let substringWord = text.substring(start, end)
763
+
764
+ // Prune incomplete word at the start
765
+ let substring0 = text.substring(startOffset, start)
766
+ substring0 = substring0.replace(/^\S*\s?/, '') // remove partial word at the start
767
+
768
+ // Prune incomplete word at the end
769
+ let substring2 = text.substring(end, endOffset)
770
+ substring2 = substring2.replace(/\s?\S*$/, '') // remove partial word at the end
771
+
772
+ // Rebuild substring for validation
773
+ let substring = substring0 + substringWord + substring2
774
+
775
+ if (substringWord !== currentWord || substring !== substring0 + substringWord + substring2) {
776
+ console.assert(substringWord === currentWord,
777
+ `text.substring(${start}, ${end}) !== currentWord: '${substringWord}', '${currentWord}'.`
778
+ )
779
+ console.assert(substring === substring0 + substringWord + substring2,
780
+ `## text.substring(${startOffset}, ${endOffset}) !== text.substring(${startOffset}, ${start}) + currentWord + text.substring(${end}, ${endOffset}).`
781
+ )
782
+ throw Error(`text.substring(${start}, ${end}): (${substringWord}) !== currentWord (${currentWord}).`)
783
+ }
784
+ return {substring0, substringWord, substring2};
785
+ } catch (e) {
786
+ console.error(`getSubstringForTextWithGivenOffset::error:`, e, ` #`)
787
+ throw e
788
+ }
789
+ }
790
+
791
+ function getStylePropertyById(id, property, parsing="") {
792
+ const element = document.getElementById(id)
793
+ return getStylePropertyWithElement(element, property, parsing)
794
+ }
795
+
796
+ function getStylePropertyWithElement(element, property, parsing="") {
797
+ const howToParse = {
798
+ "int": parseInt,
799
+ "float": parseFloat
800
+ }
801
+ const elementStyle = window.getComputedStyle(element)
802
+ let value = elementStyle.getPropertyValue(property)
803
+ if (howToParse[parsing] !== undefined) {
804
+ value = howToParse[parsing](value, 10)
805
+ }
806
+ return value
807
  }
808
 
809
  /**
810
+ * Updates the word frequency tables with new data if enter key is pressed.
811
  * If the event target has a value (i.e., it's an input field) and the event key is "Enter",
812
+ * call the updateWordsFrequencyTables function to update the word frequency tables.
813
  *
814
  * @returns {void}
815
  */