alessandro trinca tornidor commited on
Commit
8244a47
·
1 Parent(s): c98ad9f

feat: refactor frontend, improve css style

Browse files
Files changed (3) hide show
  1. static/index.css +20 -2
  2. static/index.html +5 -4
  3. static/index.js +76 -60
static/index.css CHANGED
@@ -5,6 +5,21 @@ h1 {
5
  margin-block-start: 5px;
6
  margin-block-end: 5px;
7
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  .display-none {
9
  display: none;
10
  }
@@ -56,6 +71,9 @@ h1 {
56
  .margin5px-right {
57
  margin-right: 10px;
58
  }
 
 
 
59
  .background-color-lightgray {
60
  background-color: lightgray;
61
  }
@@ -65,8 +83,8 @@ h1 {
65
  .max-height-90vh {
66
  max-height: 90vh;
67
  }
68
- .max-height-85vh {
69
- max-height: 85vh;
70
  }
71
  .overflow-hidden {
72
  /* needed for scroll bar*/
 
5
  margin-block-start: 5px;
6
  margin-block-end: 5px;
7
  }
8
+ h4 {
9
+ font-size: 18px;
10
+ margin-block-start: 2px;
11
+ margin-block-end: 2px;
12
+ }
13
+ caption {
14
+ margin-left: 12px;
15
+ margin-top: 10px;
16
+ text-align: left;
17
+ font-weight: bold;
18
+ }
19
+ td {
20
+ padding-left: 10px;
21
+ padding-right: 10px;
22
+ }
23
  .display-none {
24
  display: none;
25
  }
 
71
  .margin5px-right {
72
  margin-right: 10px;
73
  }
74
+ .margin5px-top {
75
+ margin-top: 5px;
76
+ }
77
  .background-color-lightgray {
78
  background-color: lightgray;
79
  }
 
83
  .max-height-90vh {
84
  max-height: 90vh;
85
  }
86
+ .max-height-83vh {
87
+ max-height: 83vh;
88
  }
89
  .overflow-hidden {
90
  /* needed for scroll bar*/
static/index.html CHANGED
@@ -16,16 +16,17 @@
16
  </div>
17
  <div id="id-container-row-global-editor-frequency" class="display-flex">
18
  <div id="id-col1-editor" class="col-flex50 border-black padding10px margin10px overflow-hidden background-color-lightgray">
19
- <span>Text Editor</span>
20
- <div id="editor" contenteditable="true" class="max-height-85vh overflow-auto background-color-whitesmoke" aria-label="editor">
21
  Hi there, how are you? There are some pasties for you. Can you give me also... Take a pasty from the table there!
22
  </div>
23
  </div>
24
  <div id="id-col2-word-frequency" class="col-flex50 border-blue padding10px margin10px overflow-hidden background-color-lightgray">
25
- <span>Word Frequency Table</span>
 
26
  <span id="waiting-for-be" class="display-none">waiting for backend response...</span>
27
  <span id="waiting-for-be-error" class="display-none">Error!</span>
28
- <div id="words-frequency" class="max-height-85vh overflow-auto background-color-whitesmoke" aria-label="words-frequency"></div>
29
  </div>
30
  </div>
31
  </body>
 
16
  </div>
17
  <div id="id-container-row-global-editor-frequency" class="display-flex">
18
  <div id="id-col1-editor" class="col-flex50 border-black padding10px margin10px overflow-hidden background-color-lightgray">
19
+ <h4>Text Editor</h4>
20
+ <div id="editor" contenteditable="true" class="max-height-83vh overflow-auto background-color-whitesmoke" aria-label="editor">
21
  Hi there, how are you? There are some pasties for you. Can you give me also... Take a pasty from the table there!
22
  </div>
23
  </div>
24
  <div id="id-col2-word-frequency" class="col-flex50 border-blue padding10px margin10px overflow-hidden background-color-lightgray">
25
+ <h4 id="id-word-frequency-table-title">Word Frequency Table</h4>
26
+ <span id="id-n-total-rows" aria-label="id-n-total-rows" class="display-none"></span>
27
  <span id="waiting-for-be" class="display-none">waiting for backend response...</span>
28
  <span id="waiting-for-be-error" class="display-none">Error!</span>
29
+ <div id="words-frequency" class="max-height-83vh overflow-auto background-color-whitesmoke" aria-label="words-frequency"></div>
30
  </div>
31
  </div>
32
  </body>
static/index.js CHANGED
@@ -1,5 +1,6 @@
 
1
 
2
- function previewFile() {
3
  const editor = document.getElementById("editor");
4
  const [file] = document.querySelector("input[type=file]").files;
5
  const reader = new FileReader();
@@ -12,7 +13,21 @@ function previewFile() {
12
  reader.readAsText(file);
13
  }
14
  }
15
- function setCaret(line, offsetColumn, nTotalRows, negativeOffsetPerc=0.12) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  let editorElement = document.getElementById("editor");
17
  let validChildNodes = []
18
  // use a for loop because of better performance
@@ -31,18 +46,7 @@ function setCaret(line, offsetColumn, nTotalRows, negativeOffsetPerc=0.12) {
31
  sel.removeAllRanges();
32
  sel.addRange(rng);
33
  editorElement.focus();
34
- // try to scroll div to row... font-size on div is 12px
35
- let scrollHeight = parseFloat(editorElement.scrollHeight, 10)
36
- console.log("setCaret::updatedOffsetPosition:scroll to line/height position/int height position:", line, editorElement.scrollHeight, scrollHeight, "#")
37
- let offsetToScrollPerc = line / nTotalRows
38
- let offsetToScroll = scrollHeight * offsetToScrollPerc
39
- // if already at the end of the page, don't scroll anymore to avoid missing words in the upper side of the viewport
40
- if (offsetToScrollPerc < (1-negativeOffsetPerc)) {
41
- offsetToScroll -= offsetToScroll*negativeOffsetPerc
42
- }
43
- let offsetToScrollInt = parseInt(offsetToScroll, 10)
44
- console.log("setCaret::offsetToScroll:", offsetToScrollInt, "|", offsetToScroll, "#")
45
- editorElement.scrollTo(0, offsetToScrollInt)
46
  }
47
  const setElementCssClass = (elementId, currentClass) => {
48
  let spanWaitingFor = document.getElementById(elementId)
@@ -55,6 +59,8 @@ const getWordFrequency = async () => {
55
  let bodyRequest = {"text": text.innerText}
56
  setElementCssClass("waiting-for-be-error", "display-none")
57
  setElementCssClass("waiting-for-be", "display-block")
 
 
58
  let wordsFrequency = document.getElementById("words-frequency")
59
  wordsFrequency.innerHTML = ""
60
  try {
@@ -62,68 +68,78 @@ const getWordFrequency = async () => {
62
  method: "POST",
63
  body: JSON.stringify(bodyRequest)
64
  })
65
- console.log("getWordFreq::response.status:", response.status, "#")
66
  console.assert(response.status, 200)
67
  let bodyResponseJson = await response.json()
68
  setElementCssClass("waiting-for-be", "display-none")
69
- console.log("getWordFreq::body keys:", Object.keys(bodyResponseJson), "#")
70
  let freq = bodyResponseJson["words_frequency"]
71
  let nTotalRows = bodyResponseJson["n_total_rows"]
72
- console.log("getWordFreq::tot;:", nTotalRows, "#")
73
- populateWordFrequencyTable(freq, bodyResponseJson["n_total_rows"])
74
  } catch (err) {
75
  console.error("getWordFrequency::err:", err, "#")
76
  setElementCssClass("waiting-for-be", "display-none")
77
  setElementCssClass("waiting-for-be-error", "display-block")
78
  }
79
  }
80
- const populateWordFrequencyTable = (wordsFrequencyObj, nTotalRows) => {
81
  const wfo = JSON.parse(wordsFrequencyObj)
82
  const reduced = Object.values(wfo)
83
  let wordsFrequency = document.getElementById("words-frequency")
84
  wordsFrequency.innerHTML = ""
 
 
85
  for (let i=0; i<reduced.length; i++ ) {
86
- let iReduced = reduced[i]
87
- let currentTableWordFreq = document.createElement("table")
88
- currentTableWordFreq.setAttribute("class", "border-black")
89
- currentTableWordFreq.setAttribute("id", `id-table-${i}-nth`)
90
- currentTableWordFreq.setAttribute("aria-label", `id-table-${i}-nth`)
91
- currentTableWordFreq.createCaption(`count: ${iReduced["count"]}, word: '${iReduced["word_prefix"]}'`)
92
- let currentTHead = document.createElement("thead")
93
- let currentTHeadRow = currentTHead.insertRow()
94
- currentTHeadRow.insertCell().textContent = 'word'
95
- currentTHeadRow.insertCell().textContent = 'row nth'
96
- currentTHeadRow.insertCell().textContent = 'offsets'
97
 
98
- let currentTBody = document.createElement("tbody")
99
- let offsetsArray = iReduced.offsets_array
100
- for (let ii=0; ii < offsetsArray.length; ii++) {
101
- let nthOffset = offsetsArray[ii]
102
- let nthRowBody = currentTBody.insertRow()
103
- nthRowBody.setAttribute("id", `id-table-${i}-row-${ii}-nth`)
104
- nthRowBody.setAttribute("aria-label", `id-table-${i}-row-${ii}-nth`)
105
- let currentCell = nthRowBody.insertCell()
106
- let currentUrl = document.createElement("a")
107
- currentUrl.addEventListener("click", function() {
108
- let nRow = nthOffset["n_row"]
109
- let offsetWord = nthOffset["offsets"]
110
- setCaret(nRow, offsetWord, nTotalRows)
111
- try {
112
- let oldClassElement = document.getElementsByClassName('underlinedDarkViolet')
113
- oldClassElement[0].className = "underlinedBlue"
114
- } catch {
115
- console.log("first click...")
116
- }
117
- currentUrl.className = "underlinedDarkViolet"
118
- })
119
- currentUrl.className = "underlinedBlue"
120
- currentUrl.innerText = nthOffset["word"]
121
- currentCell.appendChild(currentUrl)
122
- nthRowBody.insertCell().textContent = nthOffset["n_row"]
123
- nthRowBody.insertCell().textContent = nthOffset["offsets"]
124
- }
125
- currentTableWordFreq.appendChild(currentTHead)
126
- currentTableWordFreq.appendChild(currentTBody)
127
- wordsFrequency.appendChild(currentTableWordFreq)
128
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
129
  }
 
1
+ const wordsFrequencyTableTitleText = "Word Frequency Table"
2
 
3
+ const previewFile = () => {
4
  const editor = document.getElementById("editor");
5
  const [file] = document.querySelector("input[type=file]").files;
6
  const reader = new FileReader();
 
13
  reader.readAsText(file);
14
  }
15
  }
16
+ const scrollToGivenPoint = (editorElement, line, nTotalRows, negativeOffsetPerc) => {
17
+ // try to scroll div to row... font-size on div is 12px
18
+ let scrollHeight = parseFloat(editorElement.scrollHeight, 10)
19
+ console.log("setCaret::updatedOffsetPosition:scroll to line/height position/int height position:", line, editorElement.scrollHeight, scrollHeight, "#")
20
+ let offsetToScrollPerc = line / nTotalRows
21
+ let offsetToScroll = scrollHeight * offsetToScrollPerc
22
+ // if already at the end of the page, don't scroll anymore to avoid missing words in the upper side of the viewport
23
+ if (offsetToScrollPerc < (1 - negativeOffsetPerc)) {
24
+ offsetToScroll -= offsetToScroll * negativeOffsetPerc
25
+ }
26
+ let offsetToScrollInt = parseInt(offsetToScroll, 10)
27
+ console.log("setCaret::offsetToScroll:", offsetToScrollInt, "|", offsetToScroll, "#")
28
+ editorElement.scrollTo(0, offsetToScrollInt)
29
+ }
30
+ const setCaret = (line, offsetColumn, nTotalRows, negativeOffsetPerc=0.12) => {
31
  let editorElement = document.getElementById("editor");
32
  let validChildNodes = []
33
  // use a for loop because of better performance
 
46
  sel.removeAllRanges();
47
  sel.addRange(rng);
48
  editorElement.focus();
49
+ scrollToGivenPoint(editorElement, line, nTotalRows, negativeOffsetPerc);
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
  const setElementCssClass = (elementId, currentClass) => {
52
  let spanWaitingFor = document.getElementById(elementId)
 
59
  let bodyRequest = {"text": text.innerText}
60
  setElementCssClass("waiting-for-be-error", "display-none")
61
  setElementCssClass("waiting-for-be", "display-block")
62
+ let wordsFrequencyTableTitleEl = document.getElementById("id-word-frequency-table-title")
63
+ wordsFrequencyTableTitleEl.innerText = wordsFrequencyTableTitleText
64
  let wordsFrequency = document.getElementById("words-frequency")
65
  wordsFrequency.innerHTML = ""
66
  try {
 
68
  method: "POST",
69
  body: JSON.stringify(bodyRequest)
70
  })
71
+ console.log(`getWordFreq::response.status: '${response.status}'`)
72
  console.assert(response.status, 200)
73
  let bodyResponseJson = await response.json()
74
  setElementCssClass("waiting-for-be", "display-none")
75
+ console.log(`getWordFreq::body keys: '${Object.keys(bodyResponseJson)}'`)
76
  let freq = bodyResponseJson["words_frequency"]
77
  let nTotalRows = bodyResponseJson["n_total_rows"]
78
+ console.log(`getWordFreq::tot: '${nTotalRows}'`)
79
+ populateWordFrequencyTables(freq, bodyResponseJson["n_total_rows"])
80
  } catch (err) {
81
  console.error("getWordFrequency::err:", err, "#")
82
  setElementCssClass("waiting-for-be", "display-none")
83
  setElementCssClass("waiting-for-be-error", "display-block")
84
  }
85
  }
86
+ const populateWordFrequencyTables = (wordsFrequencyObj, nTotalRows) => {
87
  const wfo = JSON.parse(wordsFrequencyObj)
88
  const reduced = Object.values(wfo)
89
  let wordsFrequency = document.getElementById("words-frequency")
90
  wordsFrequency.innerHTML = ""
91
+ let wordsFrequencyTableTitleEl = document.getElementById("id-word-frequency-table-title")
92
+ wordsFrequencyTableTitleEl.innerText = `${wordsFrequencyTableTitleText} (${reduced.length} word groups, ${nTotalRows} rows)`
93
  for (let i=0; i<reduced.length; i++ ) {
94
+ insertCurrentTable(i, reduced[i], nTotalRows, wordsFrequency);
95
+ }
96
+ }
97
+ const insertCurrentTable = (i, iReduced, nTotalRows, wordsFrequency) => {
98
+ let currentTableWordFreq = document.createElement("table")
99
+ currentTableWordFreq.setAttribute("class", "border-black")
100
+ currentTableWordFreq.setAttribute("id", `id-table-${i}-nth`)
101
+ currentTableWordFreq.setAttribute("aria-label", `id-table-${i}-nth`)
 
 
 
102
 
103
+ let currentCaption = currentTableWordFreq.createCaption()
104
+ currentCaption.setAttribute("aria-label", `id-table-${i}-caption`)
105
+ currentCaption.innerText = `${iReduced["word_prefix"]}: ${iReduced["count"]} repetitions`
106
+
107
+ let currentTHead = document.createElement("thead")
108
+ let currentTHeadRow = currentTHead.insertRow()
109
+ currentTHeadRow.insertCell().textContent = 'word'
110
+ currentTHeadRow.insertCell().textContent = 'row nth'
111
+ currentTHeadRow.insertCell().textContent = 'offsets'
112
+
113
+ let currentTBody = document.createElement("tbody")
114
+ let offsetsArray = iReduced.offsets_array
115
+ for (let ii = 0; ii < offsetsArray.length; ii++) {
116
+ insertCellIntoTRow(currentTBody, i, ii, offsetsArray[ii], nTotalRows)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  }
118
+ currentTableWordFreq.appendChild(currentTHead)
119
+ currentTableWordFreq.appendChild(currentTBody)
120
+ wordsFrequency.appendChild(currentTableWordFreq)
121
+ }
122
+ const insertCellIntoTRow = (currentTBody, i, ii, nthOffset, nTotalRows) => {
123
+ let nthRowBody = currentTBody.insertRow()
124
+ nthRowBody.setAttribute("id", `id-table-${i}-row-${ii}-nth`)
125
+ nthRowBody.setAttribute("aria-label", `id-table-${i}-row-${ii}-nth`)
126
+ let currentCell = nthRowBody.insertCell()
127
+ let currentUrl = document.createElement("a")
128
+ currentUrl.addEventListener("click", function() {
129
+ let nRow = nthOffset["n_row"]
130
+ let offsetWord = nthOffset["offsets"]
131
+ setCaret(nRow, offsetWord, nTotalRows)
132
+ try {
133
+ let oldClassElement = document.getElementsByClassName('underlinedDarkViolet')
134
+ oldClassElement[0].className = "underlinedBlue"
135
+ } catch {
136
+ console.log("first click...")
137
+ }
138
+ currentUrl.className = "underlinedDarkViolet"
139
+ })
140
+ currentUrl.className = "underlinedBlue"
141
+ currentUrl.innerText = nthOffset["word"]
142
+ currentCell.appendChild(currentUrl)
143
+ nthRowBody.insertCell().textContent = nthOffset["n_row"]
144
+ nthRowBody.insertCell().textContent = nthOffset["offsets"]
145
  }