11 } |
11 } |
12 init() { |
12 init() { |
13 this.button_elt.onclick = this.on_button_click.bind(this); |
13 this.button_elt.onclick = this.on_button_click.bind(this); |
14 // Save original size of rectangle |
14 // Save original size of rectangle |
15 this.box_bbox = this.box_elt.getBBox() |
15 this.box_bbox = this.box_elt.getBBox() |
|
16 this.highlight_bbox = this.highlight_elt.getBBox() |
|
17 this.highlight_elt.style.visibility = "hidden"; |
16 |
18 |
17 // Compute margins |
19 // Compute margins |
18 this.text_bbox = this.text_elt.getBBox(); |
20 this.text_bbox = this.text_elt.getBBox(); |
19 let lmargin = this.text_bbox.x - this.box_bbox.x; |
21 let lmargin = this.text_bbox.x - this.box_bbox.x; |
20 let tmargin = this.text_bbox.y - this.box_bbox.y; |
22 let tmargin = this.text_bbox.y - this.box_bbox.y; |
83 // FIXME : exclude margins to be more accurate on box size |
85 // FIXME : exclude margins to be more accurate on box size |
84 let rect = txt.getBoundingClientRect(); |
86 let rect = txt.getBoundingClientRect(); |
85 if(rect.bottom > bounds.bottom){ |
87 if(rect.bottom > bounds.bottom){ |
86 // in case of overflow at the bottom, lift up one row |
88 // in case of overflow at the bottom, lift up one row |
87 let backup = first.getAttribute("dy"); |
89 let backup = first.getAttribute("dy"); |
88 // apply lift asr a dy added too first span (y attrib stays) |
90 // apply lift as a dy added too first span (y attrib stays) |
89 first.setAttribute("dy", "-"+String((this.lift+1)*1.1)+"em"); |
91 first.setAttribute("dy", "-"+String((this.lift+1)*1.1)+"em"); |
90 rect = txt.getBoundingClientRect(); |
92 rect = txt.getBoundingClientRect(); |
91 if(rect.top > bounds.top){ |
93 if(rect.top > bounds.top){ |
92 this.lift += 1; |
94 this.lift += 1; |
93 } else { |
95 } else { |
122 svg_root.removeEventListener("click", this.bound_close_on_click_elsewhere, true); |
124 svg_root.removeEventListener("click", this.bound_close_on_click_elsewhere, true); |
123 // Restore position and sixe of widget elements |
125 // Restore position and sixe of widget elements |
124 this.reset_text(); |
126 this.reset_text(); |
125 this.reset_clickables(); |
127 this.reset_clickables(); |
126 this.reset_box(); |
128 this.reset_box(); |
|
129 this.reset_highlight(); |
127 // Put the button back in place |
130 // Put the button back in place |
128 this.element.appendChild(this.button_elt); |
131 this.element.appendChild(this.button_elt); |
129 // Mark as closed (to allow dispatch) |
132 // Mark as closed (to allow dispatch) |
130 this.opened = false; |
133 this.opened = false; |
131 // Dispatch last cached value |
134 // Dispatch last cached value |
132 this.apply_cache(); |
135 this.apply_cache(); |
133 } |
136 } |
134 // Make item (text span) clickable by overlaying a rectangle on top of it |
137 // Make item (text span) clickable by overlaying a rectangle on top of it |
135 make_clickable(span, func) { |
138 make_clickable(span, func) { |
136 let txt = this.text_elt; |
139 let txt = this.text_elt; |
137 let first = txt.firstElementChild; |
|
138 let original_text_y = this.text_bbox.y; |
140 let original_text_y = this.text_bbox.y; |
139 let highlight = this.highlight_elt; |
141 let highlight = this.highlight_elt; |
140 let original_h_y = highlight.getBBox().y; |
142 let original_h_y = this.highlight_bbox.y; |
141 let clickable = highlight.cloneNode(); |
143 let clickable = highlight.cloneNode(); |
142 let yoffset = span.getBBox().y - original_text_y; |
144 let yoffset = span.getBBox().y - original_text_y; |
143 clickable.setAttribute("y", original_h_y + yoffset); |
145 clickable.y.baseVal.value = original_h_y + yoffset; |
144 clickable.style.pointerEvents = "bounding-box"; |
146 clickable.style.pointerEvents = "bounding-box"; |
145 clickable.style.visibility = "hidden"; |
147 //clickable.style.visibility = "hidden"; |
146 //clickable.onclick = () => alert("love JS"); |
148 //clickable.onclick = () => alert("love JS"); |
147 clickable.onclick = func; |
149 clickable.onclick = func; |
148 this.element.appendChild(clickable); |
150 this.element.appendChild(clickable); |
149 this.clickables.push(clickable) |
151 this.clickables.push(clickable) |
150 } |
152 } |
170 // true : downward, higher value |
172 // true : downward, higher value |
171 scroll(forward){ |
173 scroll(forward){ |
172 let contentlength = this.content.length; |
174 let contentlength = this.content.length; |
173 let spans = this.text_elt.children; |
175 let spans = this.text_elt.children; |
174 let spanslength = spans.length; |
176 let spanslength = spans.length; |
175 // reduce accounted menu size according to jumps |
177 // reduce accounted menu size according to prsence of scroll buttons |
176 if(this.menu_offset != 0) spanslength--; |
178 // since we scroll there is necessarly one button |
177 if(this.menu_offset < contentlength - 1) spanslength--; |
179 spanslength--; |
178 if(forward){ |
180 if(forward){ |
|
181 // reduce accounted menu size because of back button |
|
182 // in current view |
|
183 if(this.menu_offset > 0) spanslength--; |
179 this.menu_offset = Math.min( |
184 this.menu_offset = Math.min( |
180 contentlength - spans.length + 1, |
185 contentlength - spans.length + 1, |
181 this.menu_offset + spanslength); |
186 this.menu_offset + spanslength); |
182 }else{ |
187 }else{ |
|
188 // reduce accounted menu size because of back button |
|
189 // in view once scrolled |
|
190 if(this.menu_offset - spanslength > 0) spanslength--; |
183 this.menu_offset = Math.max( |
191 this.menu_offset = Math.max( |
184 0, |
192 0, |
185 this.menu_offset - spanslength); |
193 this.menu_offset - spanslength); |
186 } |
194 } |
|
195 if(this.menu_offset == 1) |
|
196 this.menu_offset = 0; |
|
197 |
|
198 this.reset_highlight(); |
|
199 |
187 this.reset_clickables(); |
200 this.reset_clickables(); |
188 this.set_partial_text(); |
201 this.set_partial_text(); |
|
202 |
|
203 this.highlight_selection(); |
189 } |
204 } |
190 // Setup partial view text content |
205 // Setup partial view text content |
191 // with jumps at first and last entry when appropriate |
206 // with jumps at first and last entry when appropriate |
192 set_partial_text(){ |
207 set_partial_text(){ |
193 let spans = this.text_elt.children; |
208 let spans = this.text_elt.children; |
250 this.element.parentNode.appendChild(this.element.parentNode.removeChild(this.element)); |
265 this.element.parentNode.appendChild(this.element.parentNode.removeChild(this.element)); |
251 // disable interaction with background |
266 // disable interaction with background |
252 svg_root.addEventListener("pointerdown", numb_event, true); |
267 svg_root.addEventListener("pointerdown", numb_event, true); |
253 svg_root.addEventListener("pointerup", numb_event, true); |
268 svg_root.addEventListener("pointerup", numb_event, true); |
254 svg_root.addEventListener("click", this.bound_close_on_click_elsewhere, true); |
269 svg_root.addEventListener("click", this.bound_close_on_click_elsewhere, true); |
|
270 this.highlight_selection(); |
|
271 |
255 // mark as open |
272 // mark as open |
256 this.opened = true; |
273 this.opened = true; |
257 } |
274 } |
258 // Put text element in normalized state |
275 // Put text element in normalized state |
259 reset_text(){ |
276 reset_text(){ |
275 b.x.baseVal.value = m.x; |
292 b.x.baseVal.value = m.x; |
276 b.y.baseVal.value = m.y; |
293 b.y.baseVal.value = m.y; |
277 b.width.baseVal.value = m.width; |
294 b.width.baseVal.value = m.width; |
278 b.height.baseVal.value = m.height; |
295 b.height.baseVal.value = m.height; |
279 } |
296 } |
|
297 highlight_selection(){ |
|
298 let highlighted_row = this.last_selection - this.menu_offset; |
|
299 if(highlighted_row < 0) return; |
|
300 let spans = this.text_elt.children; |
|
301 let spanslength = spans.length; |
|
302 let contentlength = this.content.length; |
|
303 if(this.menu_offset != 0) { |
|
304 spanslength--; |
|
305 highlighted_row++; |
|
306 } |
|
307 if(this.menu_offset + spanslength < contentlength - 1) spanslength--; |
|
308 if(highlighted_row > spanslength) return; |
|
309 let original_text_y = this.text_bbox.y; |
|
310 let highlight = this.highlight_elt; |
|
311 let span = spans[highlighted_row]; |
|
312 let yoffset = span.getBBox().y - original_text_y; |
|
313 highlight.y.baseVal.value = this.highlight_bbox.y + yoffset; |
|
314 highlight.style.visibility = "visible"; |
|
315 } |
|
316 reset_highlight(){ |
|
317 let highlight = this.highlight_elt; |
|
318 highlight.y.baseVal.value = this.highlight_bbox.y; |
|
319 highlight.style.visibility = "hidden"; |
|
320 } |
280 // Use margin and text size to compute box size |
321 // Use margin and text size to compute box size |
281 adjust_box_to_text(){ |
322 adjust_box_to_text(){ |
282 let [lmargin, tmargin] = this.margins; |
323 let [lmargin, tmargin] = this.margins; |
283 let m = this.text_elt.getBBox(); |
324 let m = this.text_elt.getBBox(); |
284 let b = this.box_elt; |
325 let b = this.box_elt; |