svghmi/widget_dropdown.ysl2
branchsvghmi
changeset 3092 96ffd8b1b016
parent 3091 f475f39713aa
child 3107 ee0704cc6dc8
equal deleted inserted replaced
3091:f475f39713aa 3092:96ffd8b1b016
    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;