svghmi/widget_jsontable.ysl2
author usveticic
Thu, 01 Oct 2020 14:23:27 +0200
branchsvghmi
changeset 3062 9ec338a99a18
parent 3048 d46d545ff7b7
child 3065 c369a742443d
permissions -rw-r--r--
Button fix if no active or inactive state,
Widget animate changed to use anitmateTransform and added option to change rotation
Widget circular slider fixed so it is working on got and reprogramed so it similar to normal slider
Widget slider added support for changing size still need some changes to work properly
Added slider to svghmi test project
Changed svg in svhgmi_v2 project
// widget_jsontable.ysl2

template "widget[@type='JsonTable']", mode="widget_class"
    ||
    class JsonTableWidget extends Widget{
        cache = [];
        do_http_request(...opt) {
            const query = {
                args: this.args,
                vars: this.cache,
                visible: this.visible,
                options: opt
            };

            const options = {
                 method: 'POST',
                 body: JSON.stringify(query),
                 headers: {'Content-Type': 'application/json'}
            };

            fetch(this.args[0], options)
                .then(res => res.json())
                .then(this.spread_json_data.bind(this));

        }
        dispatch(value, oldval, index) {
            this.cache[index] = value;
            this.do_http_request();
        }
        on_click(evt, ...options) {
            this.do_http_request(...options);
        }
    }
    ||

template "svg:*", mode="json_table_elt_render" {
    error > JsonTable Widget can't contain element of type «local-name()».
}


const "hmi_textstylelists_descs", "$parsed_widgets/widget[@type = 'TextStyleList']";
const "hmi_textstylelists", "$hmi_elements[@id = $hmi_textstylelists_descs/@id]";

const "textstylelist_related" foreach "$hmi_textstylelists" list {
    attrib "listid" value "@id";
    foreach "func:refered_elements(.)" elt {
        attrib "eltid" value "@id";
    }
}
const "textstylelist_related_ns", "exsl:node-set($textstylelist_related)";

def "func:json_expressions" {
    param "expressions";
    param "label";

    // compute javascript expressions to access JSON data
    // desscribed in given svg element's "label"
    // knowing that parent element already has given "expressions".

    choose {
        when "$label" {
            const "suffixes", "str:split($label)";
            const "res" foreach "$suffixes" expression {
                const "suffix",".";
                const "pos","position()";
                // take last available expression (i.e can have more suffixes than expressions)
                const "expr","$expressions[position() <= $pos][last()]/expression";
                choose {
                    when "contains($suffix,'=')" {
                        const "name", "substring-before($suffix,'=')";
                        if "$expr/@name[. != $name]"
                            error > JsonTable : missplaced '=' or inconsistent names in Json data expressions.
                        attrib "name" value "$name";
                        attrib "content" > «$expr/@content»«substring-after($suffix,'=')»
                    }
                    otherwise {
                        copy "$expr/@name";
                        attrib "content" > «$expr/@content»«$suffix»
                    }
                }
            }
            result "exsl:node-set($res)";
        }
        // Empty labels are ignored, expressions are then passed as-is.
        otherwise result "$expressions";
    }

}

const "initexpr" expression attrib "content" > jdata
const "initexpr_ns", "exsl:node-set($initexpr)";

template "svg:use", mode="json_table_elt_render" {
    param "expressions";
    // cloned element must be part of a HMI:List
    const "targetid", "substring-after(@xlink:href,'#')";
    const "from_list", "$hmi_lists[(@id | */@id) = $targetid]";

    choose {
        when "count($from_list) > 0" {
            |         id("«@id»").setAttribute("xlink:href", 
            // obtain new target id from HMI:List widget
            |             "#"+hmi_widgets["«$from_list/@id»"].items[«$expressions/expression[1]/@content»]);
        }
        otherwise
            warning > Clones (svg:use) in JsonTable Widget must point to a valid HMI:List widget or item. Reference "«@xlink:href»" is not valid and will not be updated.
    }
}

template "svg:text", mode="json_table_elt_render" {
    param "expressions";
    const "value_expr", "$expressions/expression[1]/@content";
    const "original", "@original";
    const "from_textstylelist", "$textstylelist_related_ns/list[elt/@eltid = $original]";
    choose {

        when "count($from_textstylelist) > 0" {
            const "content_expr", "$expressions/expression[2]/@content";
            if "string-length($content_expr) = 0 or $expressions/expression[2]/@name != 'textContent'"
                error > Clones (svg:use) in JsonTable Widget pointing to a HMI:TextStyleList widget or item must have a "textContent=.someVal" assignement following value expression in label.
            |         {
            |           let elt = id("«@id»");
            |           elt.textContent = String(«$content_expr»);
            |           elt.style = hmi_widgets["«$from_textstylelist/@listid»"].styles[«$value_expr»];
            |         }
        }
        otherwise {
            |         id("«@id»").textContent = String(«$value_expr»);
        }
    }
}


// only labels comming from Json widget are counted in
def "func:filter_non_widget_label" {
    param "elt";
    param "widget_elts";
    const "eltid" choose {
        when "$elt/@original" value "$elt/@original";
        otherwise value "$elt/@id";
    }
    result "$widget_elts[@id=$eltid]/@inkscape:label";
}

template "svg:*", mode="json_table_render_except_comments"{
    param "expressions";
    param "widget_elts";

    const "label", "func:filter_non_widget_label(., $widget_elts)";
    // filter out "# commented" elements
    if "not(starts-with($label,'#'))" 
        apply ".", mode="json_table_render"{
            with "expressions", "$expressions";
            with "widget_elts", "$widget_elts";
            with "label", "$label";
        }
}


template "svg:*", mode="json_table_render" {
    param "expressions";
    param "widget_elts";
    param "label";

    const "new_expressions", "func:json_expressions($expressions, $label)";

    const "elt",".";
    foreach "$new_expressions/expression[position() > 1][starts-with(@name,'onClick')]"
    |         id("«$elt/@id»").setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt, '«@name»', '"+«@content»+"')");

    apply ".", mode="json_table_elt_render"
        with "expressions", "$new_expressions";
}

template "svg:g", mode="json_table_render" {
    param "expressions";
    param "widget_elts";
    param "label";
    const "gid", "@id";

    // use intermediate variables for optimization
    const "varprefix" > obj_«$gid»_
    |         try {

    foreach "$expressions/expression"{
    |          let «$varprefix»«position()» = «@content»;
    |          if(«$varprefix»«position()» == undefined) {
    |               console.log("«$varprefix»«position()» = «@content»");
    |               throw null;
    |          }
    }

    // because we put values in a variables, we can replace corresponding expression with variable name
    const "new_expressions" foreach "$expressions/expression" xsl:copy {
        copy "@name";
        attrib "content" > «$varprefix»«position()»
    }

    // revert hiding in case it did happen before
    |           id("«@id»").setAttribute("style", "«@style»");

    apply "*", mode="json_table_render_except_comments" {
        with "expressions", "func:json_expressions(exsl:node-set($new_expressions), $label)";
        with "widget_elts", "$widget_elts";
    }
    |         } catch(err) {
    |           id("«$gid»").setAttribute("style", "display:none");
    |         }
}

template "widget[@type='JsonTable']", mode="widget_defs" {
    param "hmi_element";
    labels("data");
    optional_labels("forward backward cursor");
    const "data_elt", "$result_svg_ns//*[@id = $hmi_element/@id]/*[@inkscape:label = 'data']";
    |     visible: «count($data_elt/*[@inkscape:label])»,
    |     spread_json_data: function(janswer) {
    |         let [range,position,jdata] = janswer;
    |         this.apply_hmi_value(1, range);
    |         this.apply_hmi_value(2, position);
    |         console.log(range,position,jdata);
    apply "$data_elt", mode="json_table_render_except_comments" {
        with "expressions","$initexpr_ns";
        with "widget_elts","$hmi_element/*[@inkscape:label = 'data']/descendant::svg:*";
    }
    |     }
}