edouard@2994: // widget_jsontable.ysl2 edouard@2994: edouard@2994: template "widget[@type='JsonTable']", mode="widget_class" edouard@2994: || edouard@2994: class JsonTableWidget extends Widget{ Edouard@3065: cache = [100,50]; Edouard@3048: do_http_request(...opt) { edouard@2994: const query = { Edouard@3034: args: this.args, Edouard@3065: range: this.cache[1], Edouard@3065: position: this.cache[2], Edouard@3048: visible: this.visible, Edouard@3048: options: opt edouard@2994: }; edouard@2994: edouard@2994: const options = { edouard@2994: method: 'POST', edouard@2994: body: JSON.stringify(query), edouard@2994: headers: {'Content-Type': 'application/json'} Edouard@3034: }; edouard@2994: edouard@2994: fetch(this.args[0], options) edouard@2994: .then(res => res.json()) Edouard@3041: .then(this.spread_json_data.bind(this)); edouard@2994: edouard@2994: } Edouard@3034: dispatch(value, oldval, index) { Edouard@3034: this.cache[index] = value; edouard@2996: this.do_http_request(); edouard@2996: } Edouard@3048: on_click(evt, ...options) { Edouard@3048: this.do_http_request(...options); edouard@2994: } edouard@2994: } edouard@2994: || edouard@2996: edouard@2996: template "svg:*", mode="json_table_elt_render" { edouard@2997: error > JsonTable Widget can't contain element of type «local-name()». edouard@2996: } edouard@2996: edouard@3028: edouard@3028: const "hmi_textstylelists_descs", "$parsed_widgets/widget[@type = 'TextStyleList']"; edouard@3028: const "hmi_textstylelists", "$hmi_elements[@id = $hmi_textstylelists_descs/@id]"; edouard@3028: Edouard@3031: const "textstylelist_related" foreach "$hmi_textstylelists" list { Edouard@3031: attrib "listid" value "@id"; Edouard@3031: foreach "func:refered_elements(.)" elt { Edouard@3031: attrib "eltid" value "@id"; Edouard@3031: } Edouard@3031: } Edouard@3031: const "textstylelist_related_ns", "exsl:node-set($textstylelist_related)"; Edouard@3031: Edouard@3031: def "func:json_expressions" { Edouard@3031: param "expressions"; Edouard@3031: param "label"; Edouard@3031: Edouard@3031: // compute javascript expressions to access JSON data Edouard@3031: // desscribed in given svg element's "label" Edouard@3031: // knowing that parent element already has given "expressions". Edouard@3031: Edouard@3031: choose { Edouard@3031: when "$label" { Edouard@3031: const "suffixes", "str:split($label)"; Edouard@3031: const "res" foreach "$suffixes" expression { Edouard@3031: const "suffix","."; Edouard@3031: const "pos","position()"; Edouard@3031: // take last available expression (i.e can have more suffixes than expressions) Edouard@3031: const "expr","$expressions[position() <= $pos][last()]/expression"; Edouard@3031: choose { Edouard@3031: when "contains($suffix,'=')" { Edouard@3031: const "name", "substring-before($suffix,'=')"; Edouard@3043: if "$expr/@name[. != $name]" Edouard@3031: error > JsonTable : missplaced '=' or inconsistent names in Json data expressions. Edouard@3031: attrib "name" value "$name"; Edouard@3031: attrib "content" > «$expr/@content»«substring-after($suffix,'=')» Edouard@3031: } Edouard@3031: otherwise { Edouard@3031: copy "$expr/@name"; Edouard@3031: attrib "content" > «$expr/@content»«$suffix» Edouard@3031: } Edouard@3031: } Edouard@3031: } Edouard@3031: result "exsl:node-set($res)"; Edouard@3031: } Edouard@3031: // Empty labels are ignored, expressions are then passed as-is. Edouard@3031: otherwise result "$expressions"; Edouard@3031: } Edouard@3031: Edouard@3031: } Edouard@3031: Edouard@3031: const "initexpr" expression attrib "content" > jdata Edouard@3031: const "initexpr_ns", "exsl:node-set($initexpr)"; Edouard@3031: edouard@2996: template "svg:use", mode="json_table_elt_render" { Edouard@3031: param "expressions"; edouard@2997: // cloned element must be part of a HMI:List edouard@2997: const "targetid", "substring-after(@xlink:href,'#')"; edouard@2997: const "from_list", "$hmi_lists[(@id | */@id) = $targetid]"; edouard@2997: edouard@3028: choose { edouard@3028: when "count($from_list) > 0" { edouard@3028: | id("«@id»").setAttribute("xlink:href", edouard@3028: // obtain new target id from HMI:List widget Edouard@3031: | "#"+hmi_widgets["«$from_list/@id»"].items[«$expressions/expression[1]/@content»]); edouard@3028: } edouard@3028: otherwise Edouard@3031: 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. edouard@3028: } edouard@2996: } edouard@2996: edouard@2996: template "svg:text", mode="json_table_elt_render" { Edouard@3031: param "expressions"; Edouard@3031: const "value_expr", "$expressions/expression[1]/@content"; Edouard@3031: const "original", "@original"; Edouard@3031: const "from_textstylelist", "$textstylelist_related_ns/list[elt/@eltid = $original]"; Edouard@3031: choose { Edouard@3031: Edouard@3031: when "count($from_textstylelist) > 0" { Edouard@3031: const "content_expr", "$expressions/expression[2]/@content"; Edouard@3031: if "string-length($content_expr) = 0 or $expressions/expression[2]/@name != 'textContent'" Edouard@3031: 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. Edouard@3031: | { Edouard@3031: | let elt = id("«@id»"); Edouard@3031: | elt.textContent = String(«$content_expr»); Edouard@3031: | elt.style = hmi_widgets["«$from_textstylelist/@listid»"].styles[«$value_expr»]; Edouard@3031: | } Edouard@3031: } Edouard@3031: otherwise { Edouard@3031: | id("«@id»").textContent = String(«$value_expr»); Edouard@3031: } Edouard@3031: } Edouard@3031: } Edouard@3031: Edouard@3031: Edouard@3031: // only labels comming from Json widget are counted in Edouard@3031: def "func:filter_non_widget_label" { Edouard@3031: param "elt"; Edouard@3031: param "widget_elts"; Edouard@3031: const "eltid" choose { Edouard@3031: when "$elt/@original" value "$elt/@original"; Edouard@3031: otherwise value "$elt/@id"; Edouard@3031: } Edouard@3031: result "$widget_elts[@id=$eltid]/@inkscape:label"; edouard@2996: } edouard@2996: Edouard@3043: template "svg:*", mode="json_table_render_except_comments"{ Edouard@3043: param "expressions"; Edouard@3043: param "widget_elts"; Edouard@3043: Edouard@3043: const "label", "func:filter_non_widget_label(., $widget_elts)"; Edouard@3043: // filter out "# commented" elements Edouard@3043: if "not(starts-with($label,'#'))" Edouard@3043: apply ".", mode="json_table_render"{ Edouard@3043: with "expressions", "$expressions"; Edouard@3043: with "widget_elts", "$widget_elts"; Edouard@3043: with "label", "$label"; Edouard@3043: } Edouard@3043: } Edouard@3043: Edouard@3048: edouard@2996: template "svg:*", mode="json_table_render" { Edouard@3031: param "expressions"; Edouard@3031: param "widget_elts"; Edouard@3043: param "label"; Edouard@3048: Edouard@3048: const "new_expressions", "func:json_expressions($expressions, $label)"; Edouard@3048: Edouard@3048: const "elt","."; Edouard@3048: foreach "$new_expressions/expression[position() > 1][starts-with(@name,'onClick')]" Edouard@3048: | id("«$elt/@id»").setAttribute("onclick", "hmi_widgets['"+this.element_id+"'].on_click(evt, '«@name»', '"+«@content»+"')"); Edouard@3048: Edouard@3043: apply ".", mode="json_table_elt_render" Edouard@3048: with "expressions", "$new_expressions"; edouard@2996: } edouard@2996: edouard@2996: template "svg:g", mode="json_table_render" { Edouard@3031: param "expressions"; Edouard@3031: param "widget_elts"; Edouard@3043: param "label"; Edouard@3036: const "gid", "@id"; Edouard@3036: Edouard@3036: // use intermediate variables for optimization Edouard@3036: const "varprefix" > obj_«$gid»_ Edouard@3036: | try { Edouard@3036: Edouard@3036: foreach "$expressions/expression"{ Edouard@3036: | let «$varprefix»«position()» = «@content»; Edouard@3036: | if(«$varprefix»«position()» == undefined) { Edouard@3036: | console.log("«$varprefix»«position()» = «@content»"); Edouard@3036: | throw null; Edouard@3036: | } Edouard@3036: } Edouard@3036: Edouard@3036: // because we put values in a variables, we can replace corresponding expression with variable name Edouard@3036: const "new_expressions" foreach "$expressions/expression" xsl:copy { Edouard@3036: copy "@name"; Edouard@3036: attrib "content" > «$varprefix»«position()» Edouard@3036: } Edouard@3036: Edouard@3036: // revert hiding in case it did happen before Edouard@3036: | id("«@id»").setAttribute("style", "«@style»"); Edouard@3036: Edouard@3043: apply "*", mode="json_table_render_except_comments" { Edouard@3036: with "expressions", "func:json_expressions(exsl:node-set($new_expressions), $label)"; Edouard@3031: with "widget_elts", "$widget_elts"; Edouard@3031: } Edouard@3036: | } catch(err) { Edouard@3036: | id("«$gid»").setAttribute("style", "display:none"); Edouard@3036: | } edouard@2996: } edouard@2996: edouard@2996: template "widget[@type='JsonTable']", mode="widget_defs" { edouard@2996: param "hmi_element"; edouard@2996: labels("data"); edouard@2996: optional_labels("forward backward cursor"); edouard@2996: const "data_elt", "$result_svg_ns//*[@id = $hmi_element/@id]/*[@inkscape:label = 'data']"; Edouard@3036: | visible: «count($data_elt/*[@inkscape:label])», Edouard@3036: | spread_json_data: function(janswer) { Edouard@3036: | let [range,position,jdata] = janswer; Edouard@3041: | this.apply_hmi_value(1, range); Edouard@3041: | this.apply_hmi_value(2, position); Edouard@3036: | console.log(range,position,jdata); Edouard@3043: apply "$data_elt", mode="json_table_render_except_comments" { Edouard@3031: with "expressions","$initexpr_ns"; Edouard@3031: with "widget_elts","$hmi_element/*[@inkscape:label = 'data']/descendant::svg:*"; Edouard@3031: } edouard@2997: | } edouard@2996: }