svghmi/gen_index_xhtml.xslt
branchsvghmi
changeset 3147 910290aec533
parent 3141 6d4c1e6560ac
child 3150 5a1bb6ec48a0
equal deleted inserted replaced
3146:b18f78582f8c 3147:910290aec533
     1 <?xml version="1.0"?>
     1 <?xml version="1.0"?>
     2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exsl="http://exslt.org/common" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:str="http://exslt.org/strings" xmlns:func="http://exslt.org/functions" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:debug="debug" xmlns:preamble="preamble" xmlns:declarations="declarations" xmlns:definitions="definitions" xmlns:epilogue="epilogue" xmlns:ns="beremiz" version="1.0" extension-element-prefixes="ns func exsl regexp str dyn" exclude-result-prefixes="ns func exsl regexp str dyn debug preamble epilogue declarations definitions">
     2 <xsl:stylesheet xmlns:ns="beremiz" xmlns:definitions="definitions" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:func="http://exslt.org/functions" xmlns:epilogue="epilogue" xmlns:preamble="preamble" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:svg="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:str="http://exslt.org/strings" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:exsl="http://exslt.org/common" xmlns:declarations="declarations" xmlns:debug="debug" exclude-result-prefixes="ns func exsl regexp str dyn debug preamble epilogue declarations definitions" extension-element-prefixes="ns func exsl regexp str dyn" version="1.0">
     3   <xsl:output cdata-section-elements="xhtml:script" method="xml"/>
     3   <xsl:output method="xml" cdata-section-elements="xhtml:script"/>
     4   <xsl:variable name="svg" select="/svg:svg"/>
     4   <xsl:variable name="svg" select="/svg:svg"/>
     5   <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/>
     5   <xsl:variable name="hmi_elements" select="//svg:*[starts-with(@inkscape:label, 'HMI:')]"/>
     6   <xsl:variable name="hmitree" select="ns:GetHMITree()"/>
     6   <xsl:variable name="hmitree" select="ns:GetHMITree()"/>
     7   <xsl:variable name="_categories">
     7   <xsl:variable name="_categories">
     8     <noindex>
     8     <noindex>
  1133     <xsl:value-of select="local-name()"/>
  1133     <xsl:value-of select="local-name()"/>
  1134     <xsl:text> */
  1134     <xsl:text> */
  1135 </xsl:text>
  1135 </xsl:text>
  1136     <xsl:text>
  1136     <xsl:text>
  1137 </xsl:text>
  1137 </xsl:text>
       
  1138     <xsl:text>
       
  1139 </xsl:text>
  1138     <xsl:text>let hmi_locals = {};
  1140     <xsl:text>let hmi_locals = {};
  1139 </xsl:text>
  1141 </xsl:text>
  1140     <xsl:text>var last_remote_index = hmitree_types.length - 1;
  1142     <xsl:text>var last_remote_index = hmitree_types.length - 1;
  1141 </xsl:text>
  1143 </xsl:text>
  1142     <xsl:text>var next_available_index = hmitree_types.length;
  1144     <xsl:text>var next_available_index = hmitree_types.length;
  1204 </xsl:text>
  1206 </xsl:text>
  1205     <xsl:text>var persistent_indexes = new Map();
  1207     <xsl:text>var persistent_indexes = new Map();
  1206 </xsl:text>
  1208 </xsl:text>
  1207     <xsl:text>var cache = hmitree_types.map(_ignored =&gt; undefined);
  1209     <xsl:text>var cache = hmitree_types.map(_ignored =&gt; undefined);
  1208 </xsl:text>
  1210 </xsl:text>
       
  1211     <xsl:text>var updates = {};
       
  1212 </xsl:text>
  1209     <xsl:text>
  1213     <xsl:text>
  1210 </xsl:text>
  1214 </xsl:text>
  1211     <xsl:text>function page_local_index(varname, pagename){
  1215     <xsl:text>function page_local_index(varname, pagename){
  1212 </xsl:text>
  1216 </xsl:text>
  1213     <xsl:text>    let pagevars = hmi_locals[pagename];
  1217     <xsl:text>    let pagevars = hmi_locals[pagename];
  1327 </xsl:text>
  1331 </xsl:text>
  1328     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1332     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1329 </xsl:text>
  1333 </xsl:text>
  1330     <xsl:text>                /* flush updates pending because of inhibition */
  1334     <xsl:text>                /* flush updates pending because of inhibition */
  1331 </xsl:text>
  1335 </xsl:text>
  1332     <xsl:text>                let inhibition = this.inhibit[index];
  1336     <xsl:text>                let inhibition = this.inhibit[i];
  1333 </xsl:text>
  1337 </xsl:text>
  1334     <xsl:text>                if(inhibition != undefined){
  1338     <xsl:text>                if(inhibition != undefined){
  1335 </xsl:text>
  1339 </xsl:text>
  1336     <xsl:text>                    clearTimeout(inhibition);
  1340     <xsl:text>                    clearTimeout(inhibition);
  1337 </xsl:text>
  1341 </xsl:text>
  1338     <xsl:text>                    this.lastapply[index] = undefined;
  1342     <xsl:text>                    this.lastapply[i] = undefined;
  1339 </xsl:text>
  1343 </xsl:text>
  1340     <xsl:text>                    this.unhinibit(index);
  1344     <xsl:text>                    this.unhinibit(i);
  1341 </xsl:text>
  1345 </xsl:text>
  1342     <xsl:text>                }
  1346     <xsl:text>                }
  1343 </xsl:text>
  1347 </xsl:text>
  1344     <xsl:text>                let index = this.indexes[i];
  1348     <xsl:text>                let index = this.indexes[i];
  1345 </xsl:text>
  1349 </xsl:text>
  1663 </xsl:text>
  1667 </xsl:text>
  1664     <xsl:text>
  1668     <xsl:text>
  1665 </xsl:text>
  1669 </xsl:text>
  1666   </xsl:template>
  1670   </xsl:template>
  1667   <xsl:variable name="excluded_types" select="str:split('Page VarInit VarInitPersistent')"/>
  1671   <xsl:variable name="excluded_types" select="str:split('Page VarInit VarInitPersistent')"/>
  1668   <xsl:key name="TypesKey" match="widget" use="@type"/>
  1672   <xsl:key use="@type" name="TypesKey" match="widget"/>
  1669   <declarations:hmi-classes/>
  1673   <declarations:hmi-classes/>
  1670   <xsl:template match="declarations:hmi-classes">
  1674   <xsl:template match="declarations:hmi-classes">
  1671     <xsl:text>
  1675     <xsl:text>
  1672 </xsl:text>
  1676 </xsl:text>
  1673     <xsl:text>/* </xsl:text>
  1677     <xsl:text>/* </xsl:text>
  2874 </xsl:text>
  2878 </xsl:text>
  2875     <xsl:text>    dispatch(value, oldval, index) {
  2879     <xsl:text>    dispatch(value, oldval, index) {
  2876 </xsl:text>
  2880 </xsl:text>
  2877     <xsl:text>        this.fields[index] = value;    
  2881     <xsl:text>        this.fields[index] = value;    
  2878 </xsl:text>
  2882 </xsl:text>
  2879     <xsl:text>        this.element.textContent = this.args.length == 1 ? vsprintf(this.args[0],this.fields) : this.fields.join(' ');
  2883     <xsl:text>        this.request_animate();
  2880 </xsl:text>
  2884 </xsl:text>
  2881     <xsl:text>    }
  2885     <xsl:text>    }
  2882 </xsl:text>
  2886 </xsl:text>
  2883     <xsl:text>}
  2887     <xsl:text>}
  2884 </xsl:text>
  2888 </xsl:text>
  2885   </xsl:template>
  2889   </xsl:template>
  2886   <xsl:template mode="widget_defs" match="widget[@type='Display']">
  2890   <xsl:template mode="widget_defs" match="widget[@type='Display']">
  2887     <xsl:param name="hmi_element"/>
  2891     <xsl:param name="hmi_element"/>
  2888     <xsl:if test="$hmi_element[not(self::svg:text)]">
  2892     <xsl:variable name="format">
       
  2893       <xsl:call-template name="defs_by_labels">
       
  2894         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  2895         <xsl:with-param name="labels">
       
  2896           <xsl:text>format</xsl:text>
       
  2897         </xsl:with-param>
       
  2898         <xsl:with-param name="mandatory" select="'no'"/>
       
  2899       </xsl:call-template>
       
  2900     </xsl:variable>
       
  2901     <xsl:variable name="has_format" select="string-length($format)&gt;0"/>
       
  2902     <xsl:value-of select="$format"/>
       
  2903     <xsl:if test="$hmi_element[not(self::svg:text)] and not($has_format)">
  2889       <xsl:message terminate="yes">
  2904       <xsl:message terminate="yes">
  2890         <xsl:text>Display Widget id="</xsl:text>
  2905         <xsl:text>Display Widget id="</xsl:text>
  2891         <xsl:value-of select="$hmi_element/@id"/>
  2906         <xsl:value-of select="$hmi_element/@id"/>
  2892         <xsl:text>" is not a svg::text element</xsl:text>
  2907         <xsl:text>" must be a svg::text element itself or a group containing a svg:text element labelled "format"</xsl:text>
  2893       </xsl:message>
  2908       </xsl:message>
  2894     </xsl:if>
  2909     </xsl:if>
  2895     <xsl:variable name="field_initializer">
  2910     <xsl:variable name="field_initializer">
  2896       <xsl:for-each select="path">
  2911       <xsl:for-each select="path">
  2897         <xsl:choose>
  2912         <xsl:choose>
  2909     </xsl:variable>
  2924     </xsl:variable>
  2910     <xsl:text>    fields: [</xsl:text>
  2925     <xsl:text>    fields: [</xsl:text>
  2911     <xsl:value-of select="$field_initializer"/>
  2926     <xsl:value-of select="$field_initializer"/>
  2912     <xsl:text>],
  2927     <xsl:text>],
  2913 </xsl:text>
  2928 </xsl:text>
       
  2929     <xsl:text>    animate: function(){
       
  2930 </xsl:text>
       
  2931     <xsl:choose>
       
  2932       <xsl:when test="$has_format">
       
  2933         <xsl:text>      if(this.format_elt.getAttribute("lang")) {
       
  2934 </xsl:text>
       
  2935         <xsl:text>          this.format = svg_text_to_multiline(this.format_elt);
       
  2936 </xsl:text>
       
  2937         <xsl:text>          this.format_elt.removeAttribute("lang");
       
  2938 </xsl:text>
       
  2939         <xsl:text>      }
       
  2940 </xsl:text>
       
  2941         <xsl:text>      let str = vsprintf(this.format,this.fields);
       
  2942 </xsl:text>
       
  2943         <xsl:text>      multiline_to_svg_text(this.format_elt, str);
       
  2944 </xsl:text>
       
  2945       </xsl:when>
       
  2946       <xsl:otherwise>
       
  2947         <xsl:text>      let str = this.args.length == 1 ? vsprintf(this.args[0],this.fields) : this.fields.join(' ');
       
  2948 </xsl:text>
       
  2949         <xsl:text>      multiline_to_svg_text(this.element, str);
       
  2950 </xsl:text>
       
  2951       </xsl:otherwise>
       
  2952     </xsl:choose>
       
  2953     <xsl:text>    },
       
  2954 </xsl:text>
       
  2955     <xsl:text>    
       
  2956 </xsl:text>
       
  2957     <xsl:if test="$has_format">
       
  2958       <xsl:text>    init: function() {
       
  2959 </xsl:text>
       
  2960       <xsl:text>      this.format = svg_text_to_multiline(this.format_elt);
       
  2961 </xsl:text>
       
  2962       <xsl:text>    },
       
  2963 </xsl:text>
       
  2964     </xsl:if>
  2914   </xsl:template>
  2965   </xsl:template>
  2915   <preamble:display/>
  2966   <preamble:display/>
  2916   <xsl:template match="preamble:display">
  2967   <xsl:template match="preamble:display">
  2917     <xsl:text>
  2968     <xsl:text>
  2918 </xsl:text>
  2969 </xsl:text>
  5600 </xsl:text>
  5651 </xsl:text>
  5601     <xsl:text>        switch(index) {
  5652     <xsl:text>        switch(index) {
  5602 </xsl:text>
  5653 </xsl:text>
  5603     <xsl:text>            case 0:
  5654     <xsl:text>            case 0:
  5604 </xsl:text>
  5655 </xsl:text>
  5605     <xsl:text>                if (Math.round(this.position) != value)
  5656     <xsl:text>                this.position = value;
  5606 </xsl:text>
       
  5607     <xsl:text>                    this.position = value;
       
  5608 </xsl:text>
  5657 </xsl:text>
  5609     <xsl:text>                break;
  5658     <xsl:text>                break;
  5610 </xsl:text>
  5659 </xsl:text>
  5611     <xsl:text>            case 1:
  5660     <xsl:text>            case 1:
  5612 </xsl:text>
  5661 </xsl:text>
  5613     <xsl:text>                this.range = value;
  5662     <xsl:text>                this.range = Math.max(1,value);
  5614 </xsl:text>
  5663 </xsl:text>
  5615     <xsl:text>                break;
  5664     <xsl:text>                break;
  5616 </xsl:text>
  5665 </xsl:text>
  5617     <xsl:text>            case 2:
  5666     <xsl:text>            case 2:
  5618 </xsl:text>
  5667 </xsl:text>
  5686 </xsl:text>
  5735 </xsl:text>
  5687     <xsl:text>
  5736     <xsl:text>
  5688 </xsl:text>
  5737 </xsl:text>
  5689     <xsl:text>    apply_position(position){
  5738     <xsl:text>    apply_position(position){
  5690 </xsl:text>
  5739 </xsl:text>
  5691     <xsl:text>        this.position = Math.max(Math.min(position, this.range), 0);
  5740     <xsl:text>        this.position = Math.round(Math.max(Math.min(position, this.range), 0));
  5692 </xsl:text>
  5741 </xsl:text>
  5693     <xsl:text>        this.apply_hmi_value(0, Math.round(this.position));
  5742     <xsl:text>        this.apply_hmi_value(0, this.position);
  5694 </xsl:text>
  5743 </xsl:text>
  5695     <xsl:text>    }
  5744     <xsl:text>    }
  5696 </xsl:text>
  5745 </xsl:text>
  5697     <xsl:text>
  5746     <xsl:text>
  5698 </xsl:text>
  5747 </xsl:text>
  5724 </xsl:text>
  5773 </xsl:text>
  5725     <xsl:text>        svg_root.addEventListener("pointerup", this.bound_drop, true);
  5774     <xsl:text>        svg_root.addEventListener("pointerup", this.bound_drop, true);
  5726 </xsl:text>
  5775 </xsl:text>
  5727     <xsl:text>        svg_root.addEventListener("pointermove", this.bound_drag, true);
  5776     <xsl:text>        svg_root.addEventListener("pointermove", this.bound_drag, true);
  5728 </xsl:text>
  5777 </xsl:text>
       
  5778     <xsl:text>        this.dragpos = this.position;
       
  5779 </xsl:text>
  5729     <xsl:text>    }
  5780     <xsl:text>    }
  5730 </xsl:text>
  5781 </xsl:text>
  5731     <xsl:text>
  5782     <xsl:text>
  5732 </xsl:text>
  5783 </xsl:text>
  5733     <xsl:text>    drop(e) {
  5784     <xsl:text>    drop(e) {
  5748 </xsl:text>
  5799 </xsl:text>
  5749     <xsl:text>        let point = new DOMPoint(e.movementX, e.movementY);
  5800     <xsl:text>        let point = new DOMPoint(e.movementX, e.movementY);
  5750 </xsl:text>
  5801 </xsl:text>
  5751     <xsl:text>        let movement = point.matrixTransform(this.invctm).y;
  5802     <xsl:text>        let movement = point.matrixTransform(this.invctm).y;
  5752 </xsl:text>
  5803 </xsl:text>
  5753     <xsl:text>        this.apply_position(this.position + movement * units / pixels);
  5804     <xsl:text>        this.dragpos += movement * units / pixels;
       
  5805 </xsl:text>
       
  5806     <xsl:text>        this.apply_position(this.dragpos);
  5754 </xsl:text>
  5807 </xsl:text>
  5755     <xsl:text>    }
  5808     <xsl:text>    }
  5756 </xsl:text>
  5809 </xsl:text>
  5757     <xsl:text>}
  5810     <xsl:text>}
  5758 </xsl:text>
  5811 </xsl:text>
  6651       <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
  6704       <xsl:text>Made with SVGHMI. https://beremiz.org</xsl:text>
  6652     </xsl:comment>
  6705     </xsl:comment>
  6653     <xsl:comment>
  6706     <xsl:comment>
  6654       <xsl:apply-templates select="document('')/*/debug:*"/>
  6707       <xsl:apply-templates select="document('')/*/debug:*"/>
  6655     </xsl:comment>
  6708     </xsl:comment>
  6656     <html xmlns="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
  6709     <html xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/1999/xhtml">
  6657       <head/>
  6710       <head/>
  6658       <body style="margin:0;overflow:hidden;user-select:none;touch-action:none;">
  6711       <body style="margin:0;overflow:hidden;user-select:none;touch-action:none;">
  6659         <xsl:copy-of select="$result_svg"/>
  6712         <xsl:copy-of select="$result_svg"/>
  6660         <script>
  6713         <script>
  6661           <xsl:text>
  6714           <xsl:text>
  6692           <xsl:apply-templates select="document('')/*/epilogue:*"/>
  6745           <xsl:apply-templates select="document('')/*/epilogue:*"/>
  6693           <xsl:text>// svghmi.js
  6746           <xsl:text>// svghmi.js
  6694 </xsl:text>
  6747 </xsl:text>
  6695           <xsl:text>
  6748           <xsl:text>
  6696 </xsl:text>
  6749 </xsl:text>
  6697           <xsl:text>var updates = {};
       
  6698 </xsl:text>
       
  6699           <xsl:text>var need_cache_apply = [];
  6750           <xsl:text>var need_cache_apply = [];
  6700 </xsl:text>
  6751 </xsl:text>
  6701           <xsl:text>
  6752           <xsl:text>
  6702 </xsl:text>
  6753 </xsl:text>
  6703           <xsl:text>
       
  6704 </xsl:text>
       
  6705           <xsl:text>function dispatch_value(index, value) {
  6754           <xsl:text>function dispatch_value(index, value) {
  6706 </xsl:text>
  6755 </xsl:text>
  6707           <xsl:text>    let widgets = subscribers(index);
  6756           <xsl:text>    let widgets = subscribers(index);
  6708 </xsl:text>
  6757 </xsl:text>
  6709           <xsl:text>
  6758           <xsl:text>
  6980 </xsl:text>
  7029 </xsl:text>
  6981           <xsl:text>    BOOL: (truth) =&gt; new Int16Array([truth]),
  7030           <xsl:text>    BOOL: (truth) =&gt; new Int16Array([truth]),
  6982 </xsl:text>
  7031 </xsl:text>
  6983           <xsl:text>    NODE: (truth) =&gt; new Int16Array([truth]),
  7032           <xsl:text>    NODE: (truth) =&gt; new Int16Array([truth]),
  6984 </xsl:text>
  7033 </xsl:text>
       
  7034           <xsl:text>    REAL: (number) =&gt; new Float32Array([number]),
       
  7035 </xsl:text>
  6985           <xsl:text>    STRING: (str) =&gt; {
  7036           <xsl:text>    STRING: (str) =&gt; {
  6986 </xsl:text>
  7037 </xsl:text>
  6987           <xsl:text>        // beremiz default string max size is 128
  7038           <xsl:text>        // beremiz default string max size is 128
  6988 </xsl:text>
  7039 </xsl:text>
  6989           <xsl:text>        str = str.slice(0,128);
  7040           <xsl:text>        str = str.slice(0,128);
  7100 </xsl:text>
  7151 </xsl:text>
  7101           <xsl:text>});
  7152           <xsl:text>});
  7102 </xsl:text>
  7153 </xsl:text>
  7103           <xsl:text>
  7154           <xsl:text>
  7104 </xsl:text>
  7155 </xsl:text>
  7105           <xsl:text>var translated = false;
  7156           <xsl:text>function svg_text_to_multiline(elt) {
       
  7157 </xsl:text>
       
  7158           <xsl:text>    return(Array.prototype.map.call(elt.children, x=&gt;x.textContent).join("\n")); 
       
  7159 </xsl:text>
       
  7160           <xsl:text>}
       
  7161 </xsl:text>
       
  7162           <xsl:text>
       
  7163 </xsl:text>
       
  7164           <xsl:text>function multiline_to_svg_text(elt, str) {
       
  7165 </xsl:text>
       
  7166           <xsl:text>    str.split('\n').map((line,i) =&gt; {elt.children[i].textContent = line;});
       
  7167 </xsl:text>
       
  7168           <xsl:text>}
  7106 </xsl:text>
  7169 </xsl:text>
  7107           <xsl:text>
  7170           <xsl:text>
  7108 </xsl:text>
  7171 </xsl:text>
  7109           <xsl:text>function switch_langnum(langnum) {
  7172           <xsl:text>function switch_langnum(langnum) {
  7110 </xsl:text>
  7173 </xsl:text>
  7114 </xsl:text>
  7177 </xsl:text>
  7115           <xsl:text>    }
  7178           <xsl:text>    }
  7116 </xsl:text>
  7179 </xsl:text>
  7117           <xsl:text>
  7180           <xsl:text>
  7118 </xsl:text>
  7181 </xsl:text>
  7119           <xsl:text>    if (!translated) {
  7182           <xsl:text>    for (let translation of translations) {
  7120 </xsl:text>
  7183 </xsl:text>
  7121           <xsl:text>        translated = true;
  7184           <xsl:text>        let [objs, msgs, orig] = translation;
  7122 </xsl:text>
  7185 </xsl:text>
  7123           <xsl:text>        for (let translation of translations) {
  7186           <xsl:text>        let msg = langnum == 0 ? orig : msgs[langnum - 1];
  7124 </xsl:text>
  7187 </xsl:text>
  7125           <xsl:text>            let [objs] = translation;
  7188           <xsl:text>        for (let obj of objs) {
  7126 </xsl:text>
  7189 </xsl:text>
  7127           <xsl:text>            translation.push(Array.prototype.map.call(objs[0].children, x=&gt;x.textContent).join("\n")); 
  7190           <xsl:text>            multiline_to_svg_text(obj, msg);
       
  7191 </xsl:text>
       
  7192           <xsl:text>            obj.setAttribute("lang",langnum);
  7128 </xsl:text>
  7193 </xsl:text>
  7129           <xsl:text>        }
  7194           <xsl:text>        }
  7130 </xsl:text>
  7195 </xsl:text>
  7131           <xsl:text>    }
  7196           <xsl:text>    }
  7132 </xsl:text>
  7197 </xsl:text>
  7133           <xsl:text>
  7198           <xsl:text>    current_lang = langnum;
  7134 </xsl:text>
  7199 </xsl:text>
  7135           <xsl:text>    for (let translation of translations) {
  7200           <xsl:text>}
  7136 </xsl:text>
  7201 </xsl:text>
  7137           <xsl:text>        let [objs, msgs, orig] = translation;
  7202           <xsl:text>
  7138 </xsl:text>
  7203 </xsl:text>
  7139           <xsl:text>        let msg = langnum == 0 ? orig : msgs[langnum - 1];
  7204           <xsl:text>// backup original texts
  7140 </xsl:text>
  7205 </xsl:text>
  7141           <xsl:text>        for (let obj of objs) {
  7206           <xsl:text>for (let translation of translations) {
  7142 </xsl:text>
  7207 </xsl:text>
  7143           <xsl:text>            msg.split('\n').map((line,i) =&gt; {obj.children[i].textContent = line;});
  7208           <xsl:text>    let [objs] = translation;
       
  7209 </xsl:text>
       
  7210           <xsl:text>    translation.push(svg_text_to_multiline(objs[0])); 
       
  7211 </xsl:text>
       
  7212           <xsl:text>}
       
  7213 </xsl:text>
       
  7214           <xsl:text>
       
  7215 </xsl:text>
       
  7216           <xsl:text>var lang_local_index = hmi_local_index("lang");
       
  7217 </xsl:text>
       
  7218           <xsl:text>subscribers(lang_local_index).add({
       
  7219 </xsl:text>
       
  7220           <xsl:text>    indexes: [lang_local_index],
       
  7221 </xsl:text>
       
  7222           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
  7223 </xsl:text>
       
  7224           <xsl:text>        switch_langnum(value);
       
  7225 </xsl:text>
       
  7226           <xsl:text>        switch_page();
       
  7227 </xsl:text>
       
  7228           <xsl:text>    }
       
  7229 </xsl:text>
       
  7230           <xsl:text>});
       
  7231 </xsl:text>
       
  7232           <xsl:text>var current_lang = 0;
       
  7233 </xsl:text>
       
  7234           <xsl:text>switch_langnum(cache[lang_local_index]);
       
  7235 </xsl:text>
       
  7236           <xsl:text>
       
  7237 </xsl:text>
       
  7238           <xsl:text>function update_subscriptions() {
       
  7239 </xsl:text>
       
  7240           <xsl:text>    let delta = [];
       
  7241 </xsl:text>
       
  7242           <xsl:text>    for(let index in subscriptions){
       
  7243 </xsl:text>
       
  7244           <xsl:text>        let widgets = subscribers(index);
       
  7245 </xsl:text>
       
  7246           <xsl:text>
       
  7247 </xsl:text>
       
  7248           <xsl:text>        // periods are in ms
       
  7249 </xsl:text>
       
  7250           <xsl:text>        let previous_period = get_subscription_period(index);
       
  7251 </xsl:text>
       
  7252           <xsl:text>
       
  7253 </xsl:text>
       
  7254           <xsl:text>        // subscribing with a zero period is unsubscribing
       
  7255 </xsl:text>
       
  7256           <xsl:text>        let new_period = 0;
       
  7257 </xsl:text>
       
  7258           <xsl:text>        if(widgets.size &gt; 0) {
       
  7259 </xsl:text>
       
  7260           <xsl:text>            let maxfreq = 0;
       
  7261 </xsl:text>
       
  7262           <xsl:text>            for(let widget of widgets){
       
  7263 </xsl:text>
       
  7264           <xsl:text>                let wf = widget.frequency;
       
  7265 </xsl:text>
       
  7266           <xsl:text>                if(wf != undefined &amp;&amp; maxfreq &lt; wf)
       
  7267 </xsl:text>
       
  7268           <xsl:text>                    maxfreq = wf;
       
  7269 </xsl:text>
       
  7270           <xsl:text>            }
       
  7271 </xsl:text>
       
  7272           <xsl:text>
       
  7273 </xsl:text>
       
  7274           <xsl:text>            if(maxfreq != 0)
       
  7275 </xsl:text>
       
  7276           <xsl:text>                new_period = 1000/maxfreq;
  7144 </xsl:text>
  7277 </xsl:text>
  7145           <xsl:text>        }
  7278           <xsl:text>        }
  7146 </xsl:text>
  7279 </xsl:text>
       
  7280           <xsl:text>
       
  7281 </xsl:text>
       
  7282           <xsl:text>        if(previous_period != new_period) {
       
  7283 </xsl:text>
       
  7284           <xsl:text>            set_subscription_period(index, new_period);
       
  7285 </xsl:text>
       
  7286           <xsl:text>            if(index &lt;= last_remote_index){
       
  7287 </xsl:text>
       
  7288           <xsl:text>                delta.push(
       
  7289 </xsl:text>
       
  7290           <xsl:text>                    new Uint8Array([2]), /* subscribe = 2 */
       
  7291 </xsl:text>
       
  7292           <xsl:text>                    new Uint32Array([index]),
       
  7293 </xsl:text>
       
  7294           <xsl:text>                    new Uint16Array([new_period]));
       
  7295 </xsl:text>
       
  7296           <xsl:text>            }
       
  7297 </xsl:text>
       
  7298           <xsl:text>        }
       
  7299 </xsl:text>
  7147           <xsl:text>    }
  7300           <xsl:text>    }
  7148 </xsl:text>
  7301 </xsl:text>
  7149           <xsl:text>    current_lang = langnum;
  7302           <xsl:text>    send_blob(delta);
       
  7303 </xsl:text>
       
  7304           <xsl:text>};
       
  7305 </xsl:text>
       
  7306           <xsl:text>
       
  7307 </xsl:text>
       
  7308           <xsl:text>function send_hmi_value(index, value) {
       
  7309 </xsl:text>
       
  7310           <xsl:text>    if(index &gt; last_remote_index){
       
  7311 </xsl:text>
       
  7312           <xsl:text>        updates[index] = value;
       
  7313 </xsl:text>
       
  7314           <xsl:text>
       
  7315 </xsl:text>
       
  7316           <xsl:text>        if(persistent_indexes.has(index)){
       
  7317 </xsl:text>
       
  7318           <xsl:text>            let varname = persistent_indexes.get(index);
       
  7319 </xsl:text>
       
  7320           <xsl:text>            document.cookie = varname+"="+value+"; max-age=3153600000";
       
  7321 </xsl:text>
       
  7322           <xsl:text>        }
       
  7323 </xsl:text>
       
  7324           <xsl:text>
       
  7325 </xsl:text>
       
  7326           <xsl:text>        requestHMIAnimation();
       
  7327 </xsl:text>
       
  7328           <xsl:text>        return;
       
  7329 </xsl:text>
       
  7330           <xsl:text>    }
       
  7331 </xsl:text>
       
  7332           <xsl:text>
       
  7333 </xsl:text>
       
  7334           <xsl:text>    let iectype = hmitree_types[index];
       
  7335 </xsl:text>
       
  7336           <xsl:text>    let tobinary = typedarray_types[iectype];
       
  7337 </xsl:text>
       
  7338           <xsl:text>    send_blob([
       
  7339 </xsl:text>
       
  7340           <xsl:text>        new Uint8Array([0]),  /* setval = 0 */
       
  7341 </xsl:text>
       
  7342           <xsl:text>        new Uint32Array([index]),
       
  7343 </xsl:text>
       
  7344           <xsl:text>        tobinary(value)]);
       
  7345 </xsl:text>
       
  7346           <xsl:text>
       
  7347 </xsl:text>
       
  7348           <xsl:text>    // DON'T DO THAT unless read_iterator in svghmi.c modifies wbuf as well, not only rbuf
       
  7349 </xsl:text>
       
  7350           <xsl:text>    // cache[index] = value;
       
  7351 </xsl:text>
       
  7352           <xsl:text>};
       
  7353 </xsl:text>
       
  7354           <xsl:text>
       
  7355 </xsl:text>
       
  7356           <xsl:text>function apply_hmi_value(index, new_val) {
       
  7357 </xsl:text>
       
  7358           <xsl:text>    let old_val = cache[index]
       
  7359 </xsl:text>
       
  7360           <xsl:text>    if(new_val != undefined &amp;&amp; old_val != new_val)
       
  7361 </xsl:text>
       
  7362           <xsl:text>        send_hmi_value(index, new_val);
       
  7363 </xsl:text>
       
  7364           <xsl:text>    return new_val;
  7150 </xsl:text>
  7365 </xsl:text>
  7151           <xsl:text>}
  7366           <xsl:text>}
  7152 </xsl:text>
  7367 </xsl:text>
  7153           <xsl:text>var lang_local_index = hmi_local_index("lang");
  7368           <xsl:text>
  7154 </xsl:text>
  7369 </xsl:text>
  7155           <xsl:text>subscribers(lang_local_index).add({
  7370           <xsl:text>const quotes = {"'":null, '"':null};
  7156 </xsl:text>
  7371 </xsl:text>
  7157           <xsl:text>    indexes: [lang_local_index],
  7372           <xsl:text>
  7158 </xsl:text>
  7373 </xsl:text>
  7159           <xsl:text>    new_hmi_value: function(index, value, oldval) {
  7374           <xsl:text>function eval_operation_string(old_val, opstr) {
  7160 </xsl:text>
  7375 </xsl:text>
  7161           <xsl:text>        switch_langnum(value);
  7376           <xsl:text>    let op = opstr[0];
       
  7377 </xsl:text>
       
  7378           <xsl:text>    let given_val;
       
  7379 </xsl:text>
       
  7380           <xsl:text>    if(opstr.length &lt; 2) 
       
  7381 </xsl:text>
       
  7382           <xsl:text>        return undefined;
       
  7383 </xsl:text>
       
  7384           <xsl:text>    if(opstr[1] in quotes){
       
  7385 </xsl:text>
       
  7386           <xsl:text>        if(opstr.length &lt; 3) 
       
  7387 </xsl:text>
       
  7388           <xsl:text>            return undefined;
       
  7389 </xsl:text>
       
  7390           <xsl:text>        if(opstr[opstr.length-1] == opstr[1]){
       
  7391 </xsl:text>
       
  7392           <xsl:text>            given_val = opstr.slice(2,opstr.length-1);
       
  7393 </xsl:text>
       
  7394           <xsl:text>        }
       
  7395 </xsl:text>
       
  7396           <xsl:text>    } else {
       
  7397 </xsl:text>
       
  7398           <xsl:text>        given_val = Number(opstr.slice(1));
  7162 </xsl:text>
  7399 </xsl:text>
  7163           <xsl:text>    }
  7400           <xsl:text>    }
  7164 </xsl:text>
  7401 </xsl:text>
  7165           <xsl:text>});
  7402           <xsl:text>    let new_val;
  7166 </xsl:text>
  7403 </xsl:text>
  7167           <xsl:text>var current_lang = 0;
  7404           <xsl:text>    switch(op){
  7168 </xsl:text>
  7405 </xsl:text>
  7169           <xsl:text>switch_langnum(cache[lang_local_index]);
  7406           <xsl:text>      case "=":
  7170 </xsl:text>
  7407 </xsl:text>
  7171           <xsl:text>
  7408           <xsl:text>        new_val = given_val;
  7172 </xsl:text>
  7409 </xsl:text>
  7173           <xsl:text>function update_subscriptions() {
  7410           <xsl:text>        break;
  7174 </xsl:text>
  7411 </xsl:text>
  7175           <xsl:text>    let delta = [];
  7412           <xsl:text>      case "+":
  7176 </xsl:text>
  7413 </xsl:text>
  7177           <xsl:text>    for(let index in subscriptions){
  7414           <xsl:text>        new_val = old_val + given_val;
  7178 </xsl:text>
  7415 </xsl:text>
  7179           <xsl:text>        let widgets = subscribers(index);
  7416           <xsl:text>        break;
  7180 </xsl:text>
  7417 </xsl:text>
  7181           <xsl:text>
  7418           <xsl:text>      case "-":
  7182 </xsl:text>
  7419 </xsl:text>
  7183           <xsl:text>        // periods are in ms
  7420           <xsl:text>        new_val = old_val - given_val;
  7184 </xsl:text>
  7421 </xsl:text>
  7185           <xsl:text>        let previous_period = get_subscription_period(index);
  7422           <xsl:text>        break;
  7186 </xsl:text>
  7423 </xsl:text>
  7187           <xsl:text>
  7424           <xsl:text>      case "*":
  7188 </xsl:text>
  7425 </xsl:text>
  7189           <xsl:text>        // subscribing with a zero period is unsubscribing
  7426           <xsl:text>        new_val = old_val * given_val;
  7190 </xsl:text>
  7427 </xsl:text>
  7191           <xsl:text>        let new_period = 0;
  7428           <xsl:text>        break;
  7192 </xsl:text>
  7429 </xsl:text>
  7193           <xsl:text>        if(widgets.size &gt; 0) {
  7430           <xsl:text>      case "/":
  7194 </xsl:text>
  7431 </xsl:text>
  7195           <xsl:text>            let maxfreq = 0;
  7432           <xsl:text>        new_val = old_val / given_val;
  7196 </xsl:text>
  7433 </xsl:text>
  7197           <xsl:text>            for(let widget of widgets){
  7434           <xsl:text>        break;
  7198 </xsl:text>
       
  7199           <xsl:text>                let wf = widget.frequency;
       
  7200 </xsl:text>
       
  7201           <xsl:text>                if(wf != undefined &amp;&amp; maxfreq &lt; wf)
       
  7202 </xsl:text>
       
  7203           <xsl:text>                    maxfreq = wf;
       
  7204 </xsl:text>
       
  7205           <xsl:text>            }
       
  7206 </xsl:text>
       
  7207           <xsl:text>
       
  7208 </xsl:text>
       
  7209           <xsl:text>            if(maxfreq != 0)
       
  7210 </xsl:text>
       
  7211           <xsl:text>                new_period = 1000/maxfreq;
       
  7212 </xsl:text>
       
  7213           <xsl:text>        }
       
  7214 </xsl:text>
       
  7215           <xsl:text>
       
  7216 </xsl:text>
       
  7217           <xsl:text>        if(previous_period != new_period) {
       
  7218 </xsl:text>
       
  7219           <xsl:text>            set_subscription_period(index, new_period);
       
  7220 </xsl:text>
       
  7221           <xsl:text>            if(index &lt;= last_remote_index){
       
  7222 </xsl:text>
       
  7223           <xsl:text>                delta.push(
       
  7224 </xsl:text>
       
  7225           <xsl:text>                    new Uint8Array([2]), /* subscribe = 2 */
       
  7226 </xsl:text>
       
  7227           <xsl:text>                    new Uint32Array([index]),
       
  7228 </xsl:text>
       
  7229           <xsl:text>                    new Uint16Array([new_period]));
       
  7230 </xsl:text>
       
  7231           <xsl:text>            }
       
  7232 </xsl:text>
       
  7233           <xsl:text>        }
       
  7234 </xsl:text>
  7435 </xsl:text>
  7235           <xsl:text>    }
  7436           <xsl:text>    }
  7236 </xsl:text>
  7437 </xsl:text>
  7237           <xsl:text>    send_blob(delta);
  7438           <xsl:text>    return new_val;
       
  7439 </xsl:text>
       
  7440           <xsl:text>}
       
  7441 </xsl:text>
       
  7442           <xsl:text>
       
  7443 </xsl:text>
       
  7444           <xsl:text>var current_visible_page;
       
  7445 </xsl:text>
       
  7446           <xsl:text>var current_subscribed_page;
       
  7447 </xsl:text>
       
  7448           <xsl:text>var current_page_index;
       
  7449 </xsl:text>
       
  7450           <xsl:text>
       
  7451 </xsl:text>
       
  7452           <xsl:text>function prepare_svg() {
       
  7453 </xsl:text>
       
  7454           <xsl:text>    // prevents context menu from appearing on right click and long touch
       
  7455 </xsl:text>
       
  7456           <xsl:text>    document.body.addEventListener('contextmenu', e =&gt; {
       
  7457 </xsl:text>
       
  7458           <xsl:text>        e.preventDefault();
       
  7459 </xsl:text>
       
  7460           <xsl:text>    });
       
  7461 </xsl:text>
       
  7462           <xsl:text>
       
  7463 </xsl:text>
       
  7464           <xsl:text>    for(let eltid in detachable_elements){
       
  7465 </xsl:text>
       
  7466           <xsl:text>        let [element,parent] = detachable_elements[eltid];
       
  7467 </xsl:text>
       
  7468           <xsl:text>        parent.removeChild(element);
       
  7469 </xsl:text>
       
  7470           <xsl:text>    }
  7238 </xsl:text>
  7471 </xsl:text>
  7239           <xsl:text>};
  7472           <xsl:text>};
  7240 </xsl:text>
  7473 </xsl:text>
  7241           <xsl:text>
  7474           <xsl:text>
  7242 </xsl:text>
  7475 </xsl:text>
  7243           <xsl:text>function send_hmi_value(index, value) {
  7476           <xsl:text>function switch_page(page_name, page_index) {
  7244 </xsl:text>
  7477 </xsl:text>
  7245           <xsl:text>    if(index &gt; last_remote_index){
  7478           <xsl:text>    if(current_subscribed_page != current_visible_page){
  7246 </xsl:text>
  7479 </xsl:text>
  7247           <xsl:text>        updates[index] = value;
  7480           <xsl:text>        /* page switch already going */
  7248 </xsl:text>
  7481 </xsl:text>
  7249           <xsl:text>
  7482           <xsl:text>        /* TODO LOG ERROR */
  7250 </xsl:text>
  7483 </xsl:text>
  7251           <xsl:text>        if(persistent_indexes.has(index)){
  7484           <xsl:text>        return false;
  7252 </xsl:text>
       
  7253           <xsl:text>            let varname = persistent_indexes.get(index);
       
  7254 </xsl:text>
       
  7255           <xsl:text>            document.cookie = varname+"="+value+"; max-age=3153600000";
       
  7256 </xsl:text>
       
  7257           <xsl:text>        }
       
  7258 </xsl:text>
       
  7259           <xsl:text>
       
  7260 </xsl:text>
       
  7261           <xsl:text>        requestHMIAnimation();
       
  7262 </xsl:text>
       
  7263           <xsl:text>        return;
       
  7264 </xsl:text>
  7485 </xsl:text>
  7265           <xsl:text>    }
  7486           <xsl:text>    }
  7266 </xsl:text>
  7487 </xsl:text>
  7267           <xsl:text>
  7488           <xsl:text>
  7268 </xsl:text>
  7489 </xsl:text>
  7269           <xsl:text>    let iectype = hmitree_types[index];
  7490           <xsl:text>    if(page_name == undefined)
  7270 </xsl:text>
  7491 </xsl:text>
  7271           <xsl:text>    let tobinary = typedarray_types[iectype];
  7492           <xsl:text>        page_name = current_subscribed_page;
  7272 </xsl:text>
  7493 </xsl:text>
  7273           <xsl:text>    send_blob([
  7494           <xsl:text>
  7274 </xsl:text>
  7495 </xsl:text>
  7275           <xsl:text>        new Uint8Array([0]),  /* setval = 0 */
  7496           <xsl:text>
  7276 </xsl:text>
  7497 </xsl:text>
  7277           <xsl:text>        new Uint32Array([index]),
  7498           <xsl:text>    let old_desc = page_desc[current_subscribed_page];
  7278 </xsl:text>
  7499 </xsl:text>
  7279           <xsl:text>        tobinary(value)]);
  7500           <xsl:text>    let new_desc = page_desc[page_name];
  7280 </xsl:text>
  7501 </xsl:text>
  7281           <xsl:text>
  7502           <xsl:text>
  7282 </xsl:text>
  7503 </xsl:text>
  7283           <xsl:text>    // DON'T DO THAT unless read_iterator in svghmi.c modifies wbuf as well, not only rbuf
  7504           <xsl:text>    if(new_desc == undefined){
  7284 </xsl:text>
  7505 </xsl:text>
  7285           <xsl:text>    // cache[index] = value;
  7506           <xsl:text>        /* TODO LOG ERROR */
  7286 </xsl:text>
  7507 </xsl:text>
  7287           <xsl:text>};
  7508           <xsl:text>        return false;
  7288 </xsl:text>
       
  7289           <xsl:text>
       
  7290 </xsl:text>
       
  7291           <xsl:text>function apply_hmi_value(index, new_val) {
       
  7292 </xsl:text>
       
  7293           <xsl:text>    let old_val = cache[index]
       
  7294 </xsl:text>
       
  7295           <xsl:text>    if(new_val != undefined &amp;&amp; old_val != new_val)
       
  7296 </xsl:text>
       
  7297           <xsl:text>        send_hmi_value(index, new_val);
       
  7298 </xsl:text>
       
  7299           <xsl:text>    return new_val;
       
  7300 </xsl:text>
       
  7301           <xsl:text>}
       
  7302 </xsl:text>
       
  7303           <xsl:text>
       
  7304 </xsl:text>
       
  7305           <xsl:text>const quotes = {"'":null, '"':null};
       
  7306 </xsl:text>
       
  7307           <xsl:text>
       
  7308 </xsl:text>
       
  7309           <xsl:text>function eval_operation_string(old_val, opstr) {
       
  7310 </xsl:text>
       
  7311           <xsl:text>    let op = opstr[0];
       
  7312 </xsl:text>
       
  7313           <xsl:text>    let given_val;
       
  7314 </xsl:text>
       
  7315           <xsl:text>    if(opstr.length &lt; 2) 
       
  7316 </xsl:text>
       
  7317           <xsl:text>        return undefined;
       
  7318 </xsl:text>
       
  7319           <xsl:text>    if(opstr[1] in quotes){
       
  7320 </xsl:text>
       
  7321           <xsl:text>        if(opstr.length &lt; 3) 
       
  7322 </xsl:text>
       
  7323           <xsl:text>            return undefined;
       
  7324 </xsl:text>
       
  7325           <xsl:text>        if(opstr[opstr.length-1] == opstr[1]){
       
  7326 </xsl:text>
       
  7327           <xsl:text>            given_val = opstr.slice(2,opstr.length-1);
       
  7328 </xsl:text>
       
  7329           <xsl:text>        }
       
  7330 </xsl:text>
       
  7331           <xsl:text>    } else {
       
  7332 </xsl:text>
       
  7333           <xsl:text>        given_val = Number(opstr.slice(1));
       
  7334 </xsl:text>
  7509 </xsl:text>
  7335           <xsl:text>    }
  7510           <xsl:text>    }
  7336 </xsl:text>
  7511 </xsl:text>
  7337           <xsl:text>    let new_val;
  7512           <xsl:text>
  7338 </xsl:text>
  7513 </xsl:text>
  7339           <xsl:text>    switch(op){
  7514           <xsl:text>    if(page_index == undefined){
  7340 </xsl:text>
  7515 </xsl:text>
  7341           <xsl:text>      case "=":
  7516           <xsl:text>        page_index = new_desc.page_index;
  7342 </xsl:text>
       
  7343           <xsl:text>        new_val = given_val;
       
  7344 </xsl:text>
       
  7345           <xsl:text>        break;
       
  7346 </xsl:text>
       
  7347           <xsl:text>      case "+":
       
  7348 </xsl:text>
       
  7349           <xsl:text>        new_val = old_val + given_val;
       
  7350 </xsl:text>
       
  7351           <xsl:text>        break;
       
  7352 </xsl:text>
       
  7353           <xsl:text>      case "-":
       
  7354 </xsl:text>
       
  7355           <xsl:text>        new_val = old_val - given_val;
       
  7356 </xsl:text>
       
  7357           <xsl:text>        break;
       
  7358 </xsl:text>
       
  7359           <xsl:text>      case "*":
       
  7360 </xsl:text>
       
  7361           <xsl:text>        new_val = old_val * given_val;
       
  7362 </xsl:text>
       
  7363           <xsl:text>        break;
       
  7364 </xsl:text>
       
  7365           <xsl:text>      case "/":
       
  7366 </xsl:text>
       
  7367           <xsl:text>        new_val = old_val / given_val;
       
  7368 </xsl:text>
       
  7369           <xsl:text>        break;
       
  7370 </xsl:text>
  7517 </xsl:text>
  7371           <xsl:text>    }
  7518           <xsl:text>    }
  7372 </xsl:text>
  7519 </xsl:text>
  7373           <xsl:text>    return new_val;
  7520           <xsl:text>
  7374 </xsl:text>
  7521 </xsl:text>
  7375           <xsl:text>}
  7522           <xsl:text>    if(old_desc){
  7376 </xsl:text>
  7523 </xsl:text>
  7377           <xsl:text>
  7524           <xsl:text>        old_desc.widgets.map(([widget,relativeness])=&gt;widget.unsub());
  7378 </xsl:text>
       
  7379           <xsl:text>var current_visible_page;
       
  7380 </xsl:text>
       
  7381           <xsl:text>var current_subscribed_page;
       
  7382 </xsl:text>
       
  7383           <xsl:text>var current_page_index;
       
  7384 </xsl:text>
       
  7385           <xsl:text>
       
  7386 </xsl:text>
       
  7387           <xsl:text>function prepare_svg() {
       
  7388 </xsl:text>
       
  7389           <xsl:text>    // prevents context menu from appearing on right click and long touch
       
  7390 </xsl:text>
       
  7391           <xsl:text>    document.body.addEventListener('contextmenu', e =&gt; {
       
  7392 </xsl:text>
       
  7393           <xsl:text>        e.preventDefault();
       
  7394 </xsl:text>
       
  7395           <xsl:text>    });
       
  7396 </xsl:text>
       
  7397           <xsl:text>
       
  7398 </xsl:text>
       
  7399           <xsl:text>    for(let eltid in detachable_elements){
       
  7400 </xsl:text>
       
  7401           <xsl:text>        let [element,parent] = detachable_elements[eltid];
       
  7402 </xsl:text>
       
  7403           <xsl:text>        parent.removeChild(element);
       
  7404 </xsl:text>
  7525 </xsl:text>
  7405           <xsl:text>    }
  7526           <xsl:text>    }
  7406 </xsl:text>
  7527 </xsl:text>
  7407           <xsl:text>};
       
  7408 </xsl:text>
       
  7409           <xsl:text>
       
  7410 </xsl:text>
       
  7411           <xsl:text>function switch_page(page_name, page_index) {
       
  7412 </xsl:text>
       
  7413           <xsl:text>    if(current_subscribed_page != current_visible_page){
       
  7414 </xsl:text>
       
  7415           <xsl:text>        /* page switch already going */
       
  7416 </xsl:text>
       
  7417           <xsl:text>        /* TODO LOG ERROR */
       
  7418 </xsl:text>
       
  7419           <xsl:text>        return false;
       
  7420 </xsl:text>
       
  7421           <xsl:text>    }
       
  7422 </xsl:text>
       
  7423           <xsl:text>
       
  7424 </xsl:text>
       
  7425           <xsl:text>    if(page_name == undefined)
       
  7426 </xsl:text>
       
  7427           <xsl:text>        page_name = current_subscribed_page;
       
  7428 </xsl:text>
       
  7429           <xsl:text>
       
  7430 </xsl:text>
       
  7431           <xsl:text>
       
  7432 </xsl:text>
       
  7433           <xsl:text>    let old_desc = page_desc[current_subscribed_page];
       
  7434 </xsl:text>
       
  7435           <xsl:text>    let new_desc = page_desc[page_name];
       
  7436 </xsl:text>
       
  7437           <xsl:text>
       
  7438 </xsl:text>
       
  7439           <xsl:text>    if(new_desc == undefined){
       
  7440 </xsl:text>
       
  7441           <xsl:text>        /* TODO LOG ERROR */
       
  7442 </xsl:text>
       
  7443           <xsl:text>        return false;
       
  7444 </xsl:text>
       
  7445           <xsl:text>    }
       
  7446 </xsl:text>
       
  7447           <xsl:text>
       
  7448 </xsl:text>
       
  7449           <xsl:text>    if(page_index == undefined){
       
  7450 </xsl:text>
       
  7451           <xsl:text>        page_index = new_desc.page_index;
       
  7452 </xsl:text>
       
  7453           <xsl:text>    }
       
  7454 </xsl:text>
       
  7455           <xsl:text>
       
  7456 </xsl:text>
       
  7457           <xsl:text>    if(old_desc){
       
  7458 </xsl:text>
       
  7459           <xsl:text>        old_desc.widgets.map(([widget,relativeness])=&gt;widget.unsub());
       
  7460 </xsl:text>
       
  7461           <xsl:text>    }
       
  7462 </xsl:text>
       
  7463           <xsl:text>    const new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
  7528           <xsl:text>    const new_offset = page_index == undefined ? 0 : page_index - new_desc.page_index;
  7464 </xsl:text>
  7529 </xsl:text>
  7465           <xsl:text>
  7530           <xsl:text>
  7466 </xsl:text>
  7531 </xsl:text>
  7467           <xsl:text>    const container_id = page_name + (page_index != undefined ? page_index : "");
  7532           <xsl:text>    const container_id = page_name + (page_index != undefined ? page_index : "");
  7485           <xsl:text>    jumps_need_update = true;
  7550           <xsl:text>    jumps_need_update = true;
  7486 </xsl:text>
  7551 </xsl:text>
  7487           <xsl:text>
  7552           <xsl:text>
  7488 </xsl:text>
  7553 </xsl:text>
  7489           <xsl:text>    requestHMIAnimation();
  7554           <xsl:text>    requestHMIAnimation();
  7490 </xsl:text>
       
  7491           <xsl:text>
       
  7492 </xsl:text>
  7555 </xsl:text>
  7493           <xsl:text>    jump_history.push([page_name, page_index]);
  7556           <xsl:text>    jump_history.push([page_name, page_index]);
  7494 </xsl:text>
  7557 </xsl:text>
  7495           <xsl:text>    if(jump_history.length &gt; 42)
  7558           <xsl:text>    if(jump_history.length &gt; 42)
  7496 </xsl:text>
  7559 </xsl:text>