diff -r 9e172e4e50c7 -r f475f39713aa svghmi/gen_index_xhtml.xslt --- a/svghmi/gen_index_xhtml.xslt Tue Dec 15 13:43:21 2020 +0100 +++ b/svghmi/gen_index_xhtml.xslt Wed Dec 16 15:44:24 2020 +0100 @@ -3062,6 +3062,12 @@ + function numb_event(e) { + + e.stopPropagation(); + + } + class DropDownWidget extends Widget{ dispatch(value) { @@ -3082,11 +3088,11 @@ // Compute margins - let text_bbox = this.text_elt.getBBox(); - - let lmargin = text_bbox.x - this.box_bbox.x; - - let tmargin = text_bbox.y - this.box_bbox.y; + this.text_bbox = this.text_elt.getBBox(); + + let lmargin = this.text_bbox.x - this.box_bbox.x; + + let tmargin = this.text_bbox.y - this.box_bbox.y; this.margins = [lmargin, tmargin].map(x => Math.max(x,0)); @@ -3118,6 +3124,8 @@ this.opened = false; + this.clickables = []; + } on_button_click() { @@ -3180,13 +3188,13 @@ let count = 1; - let txt = this.text_elt; + let txt = this.text_elt; let first = txt.firstElementChild; // Real world (pixels) boundaries of current page - let bounds = svg_root.getBoundingClientRect(); + let bounds = svg_root.getBoundingClientRect(); this.lift = 0; @@ -3266,7 +3274,7 @@ // inhibit events not targetting spans (menu items) - if(e.target.parentNode !== this.text_elt){ + if([this.text_elt, this.element].indexOf(e.target.parentNode) == -1){ e.stopPropagation(); @@ -3284,12 +3292,18 @@ // Stop hogging all click events + svg_root.removeEventListener("pointerdown", numb_event, true); + + svg_root.removeEventListener("pointerup", numb_event, true); + svg_root.removeEventListener("click", this.bound_close_on_click_elsewhere, true); // Restore position and sixe of widget elements this.reset_text(); + this.reset_clickables(); + this.reset_box(); // Put the button back in place @@ -3306,11 +3320,55 @@ } + // Make item (text span) clickable by overlaying a rectangle on top of it + + make_clickable(span, func) { + + let txt = this.text_elt; + + let first = txt.firstElementChild; + + let original_text_y = this.text_bbox.y; + + let highlight = this.highlight_elt; + + let original_h_y = highlight.getBBox().y; + + let clickable = highlight.cloneNode(); + + let yoffset = span.getBBox().y - original_text_y; + + clickable.setAttribute("y", original_h_y + yoffset); + + clickable.style.pointerEvents = "bounding-box"; + + clickable.style.visibility = "hidden"; + + //clickable.onclick = () => alert("love JS"); + + clickable.onclick = func; + + this.element.appendChild(clickable); + + this.clickables.push(clickable) + + } + + reset_clickables() { + + while(this.clickables.length){ + + this.element.removeChild(this.clickables.pop()); + + } + + } + // Set text content when content is smaller than menu (no scrolling) set_complete_text(){ - let spans = this.text_elt.children; + let spans = this.text_elt.children; let c = 0; @@ -3320,7 +3378,9 @@ span.textContent = item; - span.onclick = (evt) => this.bound_on_selection_click(c); + let sel = c; + + this.make_clickable(span, (evt) => this.bound_on_selection_click(sel)); c++; @@ -3338,7 +3398,7 @@ let contentlength = this.content.length; - let spans = this.text_elt.children; + let spans = this.text_elt.children; let spanslength = spans.length; @@ -3352,7 +3412,7 @@ this.menu_offset = Math.min( - contentlength - spans.length + 1, + contentlength - spans.length + 1, this.menu_offset + spanslength); @@ -3360,12 +3420,14 @@ this.menu_offset = Math.max( - 0, + 0, this.menu_offset - spanslength); } + this.reset_clickables(); + this.set_partial_text(); } @@ -3376,7 +3438,7 @@ set_partial_text(){ - let spans = this.text_elt.children; + let spans = this.text_elt.children; let contentlength = this.content.length; @@ -3384,25 +3446,37 @@ let i = this.menu_offset, c = 0; + let m = this.box_bbox; + while(c < spanslength){ let span=spans[c]; + let onclickfunc; + // backward jump only present if not exactly at start if(c == 0 && i != 0){ - span.textContent = "↑ ↑ ↑"; - - span.onclick = this.bound_on_backward_click; + span.textContent = "▲"; + + onclickfunc = this.bound_on_backward_click; + + let o = span.getBBox(); + + span.setAttribute("dx", (m.width - o.width)/2); // presence of forward jump when not right at the end }else if(c == spanslength-1 && i < contentlength - 1){ - span.textContent = "↓ ↓ ↓"; - - span.onclick = this.bound_on_forward_click; + span.textContent = "▼"; + + onclickfunc = this.bound_on_forward_click; + + let o = span.getBBox(); + + span.setAttribute("dx", (m.width - o.width)/2); // otherwise normal content @@ -3412,12 +3486,16 @@ let sel = i; - span.onclick = (evt) => this.bound_on_selection_click(sel); + onclickfunc = (evt) => this.bound_on_selection_click(sel); + + span.removeAttribute("dx"); i++; } + this.make_clickable(span, onclickfunc); + c++; } @@ -3478,6 +3556,10 @@ // disable interaction with background + svg_root.addEventListener("pointerdown", numb_event, true); + + svg_root.addEventListener("pointerup", numb_event, true); + svg_root.addEventListener("click", this.bound_close_on_click_elsewhere, true); // mark as open @@ -3490,16 +3572,18 @@ reset_text(){ - let txt = this.text_elt; + let txt = this.text_elt; let first = txt.firstElementChild; // remove attribute eventually added to first text line while opening - first.removeAttribute("onclick"); + first.onclick = null; first.removeAttribute("dy"); + first.removeAttribute("dx"); + // keep only the first line of text for(let span of Array.from(txt.children).slice(1)){ @@ -3538,11 +3622,11 @@ let b = this.box_elt; - b.x.baseVal.value = m.x - lmargin; + // b.x.baseVal.value = m.x - lmargin; b.y.baseVal.value = m.y - tmargin; - b.width.baseVal.value = 2 * lmargin + m.width; + // b.width.baseVal.value = 2 * lmargin + m.width; b.height.baseVal.value = 2 * tmargin + m.height; @@ -3556,7 +3640,7 @@ - text box button + text box button highlight // It is assumed that list content conforms to Array interface.