svghmi/widget_dropdown.ysl2
author Edouard Tisserant <edouard.tisserant@gmail.com>
Tue, 23 Mar 2021 05:11:23 +0100
branchsvghmi
changeset 3193 8006bb60a4dd
parent 3133 450cd01324ad
child 3232 7bdb766c2a4d
permissions -rw-r--r--
SVGHMI: Added SVG widget library browser. Supports browsing and previewing widgets. Widget validation and drag'n'drop are still to be implemented.
2922
ddce4ebdf010 SVGHMI: intermediate commit while working on dropdown widget.
Edouard Tisserant
parents:
diff changeset
     1
// widget_dropdown.ysl2
ddce4ebdf010 SVGHMI: intermediate commit while working on dropdown widget.
Edouard Tisserant
parents:
diff changeset
     2
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
     3
template "widget[@type='DropDown']", mode="widget_class"{
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
     4
||
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
     5
    function numb_event(e) {
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
     6
        e.stopPropagation();
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
     7
    }
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
     8
    class DropDownWidget extends Widget{
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
     9
        dispatch(value) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    10
            if(!this.opened) this.set_selection(value);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    11
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    12
        init() {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    13
            this.button_elt.onclick = this.on_button_click.bind(this);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    14
            // Save original size of rectangle
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    15
            this.box_bbox = this.box_elt.getBBox()
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
    16
            this.highlight_bbox = this.highlight_elt.getBBox()
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
    17
            this.highlight_elt.style.visibility = "hidden";
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    18
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    19
            // Compute margins
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
    20
            this.text_bbox = this.text_elt.getBBox();
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
    21
            let lmargin = this.text_bbox.x - this.box_bbox.x;
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
    22
            let tmargin = this.text_bbox.y - this.box_bbox.y;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    23
            this.margins = [lmargin, tmargin].map(x => Math.max(x,0));
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    24
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    25
            // Index of first visible element in the menu, when opened
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    26
            this.menu_offset = 0;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    27
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    28
            // How mutch to lift the menu vertically so that it does not cross bottom border
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    29
            this.lift = 0;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    30
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    31
            // Event handlers cannot be object method ('this' is unknown)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    32
            // as a workaround, handler given to addEventListener is bound in advance.
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    33
            this.bound_close_on_click_elsewhere = this.close_on_click_elsewhere.bind(this);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    34
            this.bound_on_selection_click = this.on_selection_click.bind(this);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    35
            this.bound_on_backward_click = this.on_backward_click.bind(this);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    36
            this.bound_on_forward_click = this.on_forward_click.bind(this);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    37
            this.opened = false;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
    38
            this.clickables = [];
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    39
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    40
        on_button_click() {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    41
            this.open();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    42
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    43
        // Called when a menu entry is clicked
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    44
        on_selection_click(selection) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    45
            this.close();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    46
            this.apply_hmi_value(0, selection);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    47
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    48
        on_backward_click(){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    49
            this.scroll(false);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    50
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    51
        on_forward_click(){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    52
            this.scroll(true);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    53
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    54
        set_selection(value) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    55
            let display_str;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    56
            if(value >= 0 && value < this.content.length){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    57
                // if valid selection resolve content
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    58
                display_str = this.content[value];
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    59
                this.last_selection = value;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    60
            } else {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    61
                // otherwise show problem
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    62
                display_str = "?"+String(value)+"?";
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    63
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    64
            // It is assumed that first span always stays,
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    65
            // and contains selection when menu is closed
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    66
            this.text_elt.firstElementChild.textContent = display_str;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    67
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    68
        grow_text(up_to) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    69
            let count = 1;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
    70
            let txt = this.text_elt;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    71
            let first = txt.firstElementChild;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    72
            // Real world (pixels) boundaries of current page
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
    73
            let bounds = svg_root.getBoundingClientRect();
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    74
            this.lift = 0;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    75
            while(count < up_to) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    76
                let next = first.cloneNode();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    77
                // relative line by line text flow instead of absolute y coordinate
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    78
                next.removeAttribute("y");
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    79
                next.setAttribute("dy", "1.1em");
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    80
                // default content to allow computing text element bbox
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    81
                next.textContent = "...";
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    82
                // append new span to text element
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    83
                txt.appendChild(next);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    84
                // now check if text extended by one row fits to page
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    85
                // FIXME : exclude margins to be more accurate on box size
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    86
                let rect = txt.getBoundingClientRect();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    87
                if(rect.bottom > bounds.bottom){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    88
                    // in case of overflow at the bottom, lift up one row
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    89
                    let backup = first.getAttribute("dy");
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
    90
                    // apply lift as a dy added too first span (y attrib stays)
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    91
                    first.setAttribute("dy", "-"+String((this.lift+1)*1.1)+"em");
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    92
                    rect = txt.getBoundingClientRect();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    93
                    if(rect.top > bounds.top){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    94
                        this.lift += 1;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    95
                    } else {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    96
                        // if it goes over the top, then backtrack
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    97
                        // restore dy attribute on first span
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    98
                        if(backup)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
    99
                            first.setAttribute("dy", backup);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   100
                        else
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   101
                            first.removeAttribute("dy");
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   102
                        // remove unwanted child
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   103
                        txt.removeChild(next);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   104
                        return count;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   105
                    }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   106
                }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   107
                count++;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   108
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   109
            return count;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   110
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   111
        close_on_click_elsewhere(e) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   112
            // inhibit events not targetting spans (menu items)
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   113
            if([this.text_elt, this.element].indexOf(e.target.parentNode) == -1){
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   114
                e.stopPropagation();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   115
                // close menu in case click is outside box
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   116
                if(e.target !== this.box_elt)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   117
                    this.close();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   118
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   119
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   120
        close(){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   121
            // Stop hogging all click events
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   122
            svg_root.removeEventListener("pointerdown", numb_event, true);
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   123
            svg_root.removeEventListener("pointerup", numb_event, true);
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   124
            svg_root.removeEventListener("click", this.bound_close_on_click_elsewhere, true);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   125
            // Restore position and sixe of widget elements
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   126
            this.reset_text();
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   127
            this.reset_clickables();
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   128
            this.reset_box();
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   129
            this.reset_highlight();
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   130
            // Put the button back in place
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   131
            this.element.appendChild(this.button_elt);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   132
            // Mark as closed (to allow dispatch)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   133
            this.opened = false;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   134
            // Dispatch last cached value
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   135
            this.apply_cache();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   136
        }
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   137
        // Make item (text span) clickable by overlaying a rectangle on top of it
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   138
        make_clickable(span, func) {
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   139
            let txt = this.text_elt;
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   140
            let original_text_y = this.text_bbox.y;
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   141
            let highlight = this.highlight_elt;
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   142
            let original_h_y = this.highlight_bbox.y;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   143
            let clickable = highlight.cloneNode();
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   144
            let yoffset = span.getBBox().y - original_text_y;
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   145
            clickable.y.baseVal.value = original_h_y + yoffset;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   146
            clickable.style.pointerEvents = "bounding-box";
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   147
            //clickable.style.visibility = "hidden";
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   148
            //clickable.onclick = () => alert("love JS");
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   149
            clickable.onclick = func;
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   150
            this.element.appendChild(clickable);
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   151
            this.clickables.push(clickable)
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   152
        }
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   153
        reset_clickables() {
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   154
            while(this.clickables.length){
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   155
                this.element.removeChild(this.clickables.pop());
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   156
            }
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   157
        }
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   158
        // Set text content when content is smaller than menu (no scrolling)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   159
        set_complete_text(){
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   160
            let spans = this.text_elt.children;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   161
            let c = 0;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   162
            for(let item of this.content){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   163
                let span=spans[c];
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   164
                span.textContent = item;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   165
                let sel = c;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   166
                this.make_clickable(span, (evt) => this.bound_on_selection_click(sel));
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   167
                c++;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   168
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   169
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   170
        // Move partial view :
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   171
        // false : upward, lower value
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   172
        // true  : downward, higher value
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   173
        scroll(forward){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   174
            let contentlength = this.content.length;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   175
            let spans = this.text_elt.children;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   176
            let spanslength = spans.length;
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   177
            // reduce accounted menu size according to prsence of scroll buttons
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   178
            // since we scroll there is necessarly one button
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   179
            spanslength--;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   180
            if(forward){
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   181
                // reduce accounted menu size because of back button
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   182
                // in current view
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   183
                if(this.menu_offset > 0) spanslength--;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   184
                this.menu_offset = Math.min(
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   185
                    contentlength - spans.length + 1,
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   186
                    this.menu_offset + spanslength);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   187
            }else{
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   188
                // reduce accounted menu size because of back button
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   189
                // in view once scrolled
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   190
                if(this.menu_offset - spanslength > 0) spanslength--;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   191
                this.menu_offset = Math.max(
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   192
                    0,
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   193
                    this.menu_offset - spanslength);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   194
            }
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   195
            if(this.menu_offset == 1)
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   196
                this.menu_offset = 0;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   197
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   198
            this.reset_highlight();
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   199
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   200
            this.reset_clickables();
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   201
            this.set_partial_text();
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   202
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   203
            this.highlight_selection();
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   204
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   205
        // Setup partial view text content
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   206
        // with jumps at first and last entry when appropriate
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   207
        set_partial_text(){
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   208
            let spans = this.text_elt.children;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   209
            let contentlength = this.content.length;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   210
            let spanslength = spans.length;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   211
            let i = this.menu_offset, c = 0;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   212
            let m = this.box_bbox;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   213
            while(c < spanslength){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   214
                let span=spans[c];
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   215
                let onclickfunc;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   216
                // backward jump only present if not exactly at start
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   217
                if(c == 0 && i != 0){
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   218
                    span.textContent = "▲";
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   219
                    onclickfunc = this.bound_on_backward_click;
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   220
                    let o = span.getBBox();
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   221
                    span.setAttribute("dx", (m.width - o.width)/2);
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   222
                // presence of forward jump when not right at the end
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   223
                }else if(c == spanslength-1 && i < contentlength - 1){
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   224
                    span.textContent = "▼";
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   225
                    onclickfunc = this.bound_on_forward_click;
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   226
                    let o = span.getBBox();
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   227
                    span.setAttribute("dx", (m.width - o.width)/2);
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   228
                // otherwise normal content
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   229
                }else{
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   230
                    span.textContent = this.content[i];
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   231
                    let sel = i;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   232
                    onclickfunc = (evt) => this.bound_on_selection_click(sel);
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   233
                    span.removeAttribute("dx");
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   234
                    i++;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   235
                }
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   236
                this.make_clickable(span, onclickfunc);
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   237
                c++;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   238
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   239
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   240
        open(){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   241
            let length = this.content.length;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   242
            // systematically reset text, to strip eventual whitespace spans
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   243
            this.reset_text();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   244
            // grow as much as needed or possible
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   245
            let slots = this.grow_text(length);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   246
            // Depending on final size
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   247
            if(slots == length) {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   248
                // show all at once
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   249
                this.set_complete_text();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   250
            } else {
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   251
                // eventualy align menu to current selection, compensating for lift
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   252
                let offset = this.last_selection - this.lift;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   253
                if(offset > 0)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   254
                    this.menu_offset = Math.min(offset + 1, length - slots + 1);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   255
                else
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   256
                    this.menu_offset = 0;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   257
                // show surrounding values
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   258
                this.set_partial_text();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   259
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   260
            // Now that text size is known, we can set the box around it
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   261
            this.adjust_box_to_text();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   262
            // Take button out until menu closed
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   263
            this.element.removeChild(this.button_elt);
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   264
            // Rise widget to top by moving it to last position among siblings
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   265
            this.element.parentNode.appendChild(this.element.parentNode.removeChild(this.element));
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   266
            // disable interaction with background
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   267
            svg_root.addEventListener("pointerdown", numb_event, true);
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   268
            svg_root.addEventListener("pointerup", numb_event, true);
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   269
            svg_root.addEventListener("click", this.bound_close_on_click_elsewhere, true);
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   270
            this.highlight_selection();
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   271
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   272
            // mark as open
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   273
            this.opened = true;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   274
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   275
        // Put text element in normalized state
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   276
        reset_text(){
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   277
            let txt = this.text_elt;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   278
            let first = txt.firstElementChild;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   279
            // remove attribute eventually added to first text line while opening
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   280
            first.onclick = null;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   281
            first.removeAttribute("dy");
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   282
            first.removeAttribute("dx");
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   283
            // keep only the first line of text
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   284
            for(let span of Array.from(txt.children).slice(1)){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   285
                txt.removeChild(span)
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   286
            }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   287
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   288
        // Put rectangle element in saved original state
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   289
        reset_box(){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   290
            let m = this.box_bbox;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   291
            let b = this.box_elt;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   292
            b.x.baseVal.value = m.x;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   293
            b.y.baseVal.value = m.y;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   294
            b.width.baseVal.value = m.width;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   295
            b.height.baseVal.value = m.height;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   296
        }
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   297
        highlight_selection(){
3131
2d750e38a4c6 SVGHMI: Prevent Dropdown widget to mak exception whe value out of range
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3107
diff changeset
   298
            if(this.last_selection == undefined) return;
3092
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   299
            let highlighted_row = this.last_selection - this.menu_offset;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   300
            if(highlighted_row < 0) return;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   301
            let spans = this.text_elt.children;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   302
            let spanslength = spans.length;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   303
            let contentlength = this.content.length;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   304
            if(this.menu_offset != 0) {
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   305
                spanslength--;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   306
                highlighted_row++;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   307
            }
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   308
            if(this.menu_offset + spanslength < contentlength - 1) spanslength--;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   309
            if(highlighted_row > spanslength) return;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   310
            let original_text_y = this.text_bbox.y;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   311
            let highlight = this.highlight_elt;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   312
            let span = spans[highlighted_row];
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   313
            let yoffset = span.getBBox().y - original_text_y;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   314
            highlight.y.baseVal.value = this.highlight_bbox.y + yoffset;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   315
            highlight.style.visibility = "visible";
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   316
        }
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   317
        reset_highlight(){
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   318
            let highlight = this.highlight_elt;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   319
            highlight.y.baseVal.value = this.highlight_bbox.y;
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   320
            highlight.style.visibility = "hidden";
96ffd8b1b016 SVGHMI: added dropdown selection highlighting and fixed scrolling so that it doesn't miss any entry while jumping from one page to the other.
Edouard Tisserant
parents: 3091
diff changeset
   321
        }
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   322
        // Use margin and text size to compute box size
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   323
        adjust_box_to_text(){
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   324
            let [lmargin, tmargin] = this.margins;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   325
            let m = this.text_elt.getBBox();
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   326
            let b = this.box_elt;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   327
            // b.x.baseVal.value = m.x - lmargin;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   328
            b.y.baseVal.value = m.y - tmargin;
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   329
            // b.width.baseVal.value = 2 * lmargin + m.width;
3090
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   330
            b.height.baseVal.value = 2 * tmargin + m.height;
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   331
        }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   332
    }
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   333
||
9e172e4e50c7 SVGHMI: DropDown widget now using new class based style
Edouard Tisserant
parents: 3035
diff changeset
   334
}
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   335
2922
ddce4ebdf010 SVGHMI: intermediate commit while working on dropdown widget.
Edouard Tisserant
parents:
diff changeset
   336
template "widget[@type='DropDown']", mode="widget_defs" {
ddce4ebdf010 SVGHMI: intermediate commit while working on dropdown widget.
Edouard Tisserant
parents:
diff changeset
   337
    param "hmi_element";
3091
f475f39713aa SVGHMI: change scroll buttons into single unicode triangle and center them. Use highlight rectangle duplicated and hidden to catch selection clicks so that the whole row is clickable.
Edouard Tisserant
parents: 3090
diff changeset
   338
    labels("text box button highlight");
3107
ee0704cc6dc8 SVGHMI: Jump widget: switch to class based declaraion, and add some TODO comments to prepare for jump to relative page being selected through a DropDown widget.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3092
diff changeset
   339
    // It is assumed that list content conforms to Array interface.
3133
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   340
    >   content:
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   341
    choose{
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   342
        // special case when used for language selection
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   343
        when "count(arg) = 1 and arg[1]/@value = '#langs'" {
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   344
            > langs
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   345
        }
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   346
        otherwise {
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   347
            > [\n
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   348
            foreach "arg" | "«@value»",
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   349
            >   ]
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   350
        }
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   351
    }
450cd01324ad SVGHMI: HMI:DropDown:#langs@lang now automatically shows human readable list of languages. tests/svghmi_i18n updated accordingly.
Edouard Tisserant <edouard.tisserant@gmail.com>
parents: 3131
diff changeset
   352
    > ,\n
2922
ddce4ebdf010 SVGHMI: intermediate commit while working on dropdown widget.
Edouard Tisserant
parents:
diff changeset
   353
}