svghmi/widget_jsontable.ysl2
author Edouard Tisserant
Thu, 20 Aug 2020 13:56:21 +0200
branchsvghmi
changeset 3031 440d74319a74
parent 3028 72ee99635db7
child 3034 793ce2117258
permissions -rw-r--r--
SVGHMI: Refactor the way JsonTable generate javascript code to access json data. Now support multiple assignments, used in the case of text to change both content and style on the same element.
// widget_jsontable.ysl2

template "widget[@type='JsonTable']", mode="widget_class"
    ||
    class JsonTableWidget extends Widget{
        do_http_request() {
            const query = {
                 offset: '42',
                 filter: '*powerloss*',
                 args: this.args
            };

            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);

        }
        dispatch(value) {
            this.do_http_request();
        }
        on_click(evt) {
            this.do_http_request();
        }
        init() {
            this.element.setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt)");
        }
    }
    ||

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" {
    param "expressions";
    param "widget_elts";
    const "label", "func:filter_non_widget_label(., $widget_elts)";
    apply ".", mode="json_table_elt_render" {
        with "expressions", "func:json_expressions($expressions, $label)";
    }
}

template "svg:g", mode="json_table_render" {
    param "expressions";
    param "widget_elts";
    /* TODO : use intermediate variables for optimization
    foreach "$new_expressions"
    |         let obj_«@id»_«position()» = «.»;
    */
    const "label", "func:filter_non_widget_label(., $widget_elts)";
    apply "*", mode="json_table_render" {
        with "expressions", "func:json_expressions($expressions, $label)";
        with "widget_elts", "$widget_elts";
    }
}

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']";
    |     spread_json_data: function(jdata) {
    apply "$data_elt/*", mode="json_table_render" {
        with "expressions","$initexpr_ns";
        with "widget_elts","$hmi_element/*[@inkscape:label = 'data']/descendant::svg:*";
    }
    |     }
}