svghmi/widget_jsontable.ysl2
author Edouard Tisserant
Mon, 24 Aug 2020 09:48:35 +0200
branchsvghmi
changeset 3035 d1fc8c55c1d3
parent 3034 793ce2117258
child 3036 4930455428df
permissions -rw-r--r--
SVGHMI: removed debug code forgotten here and there.
// widget_jsontable.ysl2

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

            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, oldval, index) {
            this.cache[index] = 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:*";
    }
    |     }
}