svghmi/gen_index_xhtml.xslt
branchwxPython4
changeset 3615 5c983ead9db0
parent 3582 7dcd0de97e6f
child 3630 921f620577e8
equal deleted inserted replaced
3614:0e0252339e83 3615:5c983ead9db0
   157       <xsl:with-param name="parentpath">
   157       <xsl:with-param name="parentpath">
   158         <xsl:value-of select="$parentpath"/>
   158         <xsl:value-of select="$parentpath"/>
   159       </xsl:with-param>
   159       </xsl:with-param>
   160     </xsl:apply-templates>
   160     </xsl:apply-templates>
   161   </xsl:template>
   161   </xsl:template>
   162   <xsl:variable name="pathregex" select="'^([^\[,]+)(\[[^\]]+\])?([-.\d,]*)$'"/>
   162   <xsl:variable name="pathregex" select="'^(\w+=)?([^,=]+)([-.\d,]*)$'"/>
   163   <xsl:variable name="newline">
   163   <xsl:variable name="newline">
   164     <xsl:text>
   164     <xsl:text>
   165 </xsl:text>
   165 </xsl:text>
   166   </xsl:variable>
   166   </xsl:variable>
   167   <xsl:variable name="twonewlines" select="concat($newline,$newline)"/>
   167   <xsl:variable name="twonewlines" select="concat($newline,$newline)"/>
   168   <xsl:template mode="parselabel" match="*">
   168   <xsl:template mode="parselabel" match="*">
   169     <xsl:variable name="part" select="@inkscape:label"/>
   169     <xsl:variable name="label" select="@inkscape:label"/>
   170     <xsl:variable name="desc" select="svg:desc"/>
   170     <xsl:variable name="desc" select="svg:desc"/>
   171     <xsl:variable name="len" select="string-length($part)"/>
   171     <xsl:variable name="len" select="string-length($label)"/>
   172     <xsl:variable name="has_continuation" select="substring($part,$len,1)='\'"/>
   172     <xsl:variable name="has_continuation" select="substring($label,$len,1)='\'"/>
   173     <xsl:variable name="label">
   173     <xsl:variable name="full_decl">
   174       <xsl:choose>
   174       <xsl:choose>
   175         <xsl:when test="$has_continuation">
   175         <xsl:when test="$has_continuation">
   176           <xsl:variable name="_continuation" select="substring-before($desc, $twonewlines)"/>
   176           <xsl:variable name="_continuation" select="substring-before($desc, $twonewlines)"/>
   177           <xsl:variable name="continuation">
   177           <xsl:variable name="continuation">
   178             <xsl:choose>
   178             <xsl:choose>
   182               <xsl:otherwise>
   182               <xsl:otherwise>
   183                 <xsl:value-of select="$desc"/>
   183                 <xsl:value-of select="$desc"/>
   184               </xsl:otherwise>
   184               </xsl:otherwise>
   185             </xsl:choose>
   185             </xsl:choose>
   186           </xsl:variable>
   186           </xsl:variable>
   187           <xsl:value-of select="concat(substring($part,1,$len - 1),translate($continuation,$newline,''))"/>
   187           <xsl:value-of select="concat(substring($label,1,$len - 1),translate($continuation,$newline,''))"/>
   188         </xsl:when>
   188         </xsl:when>
   189         <xsl:otherwise>
   189         <xsl:otherwise>
   190           <xsl:value-of select="$part"/>
   190           <xsl:value-of select="$label"/>
   191         </xsl:otherwise>
   191         </xsl:otherwise>
   192       </xsl:choose>
   192       </xsl:choose>
   193     </xsl:variable>
   193     </xsl:variable>
   194     <xsl:variable name="id" select="@id"/>
   194     <xsl:variable name="id" select="@id"/>
   195     <xsl:variable name="description" select="substring-after($label,'HMI:')"/>
   195     <xsl:variable name="declaration" select="substring-after($full_decl,'HMI:')"/>
   196     <xsl:variable name="_args" select="substring-before($description,'@')"/>
   196     <xsl:variable name="_args" select="substring-before($declaration,'@')"/>
   197     <xsl:variable name="args">
   197     <xsl:variable name="args">
   198       <xsl:choose>
   198       <xsl:choose>
   199         <xsl:when test="$_args">
   199         <xsl:when test="$_args">
   200           <xsl:value-of select="$_args"/>
   200           <xsl:value-of select="$_args"/>
   201         </xsl:when>
   201         </xsl:when>
   202         <xsl:otherwise>
   202         <xsl:otherwise>
   203           <xsl:value-of select="$description"/>
   203           <xsl:value-of select="$declaration"/>
   204         </xsl:otherwise>
   204         </xsl:otherwise>
   205       </xsl:choose>
   205       </xsl:choose>
   206     </xsl:variable>
   206     </xsl:variable>
   207     <xsl:variable name="_typefreq" select="substring-before($args,':')"/>
   207     <xsl:variable name="_typefreq" select="substring-before($args,':')"/>
   208     <xsl:variable name="typefreq">
   208     <xsl:variable name="typefreq">
   239           <xsl:if test="not(regexp:test($freq,'^[0-9]*(\.[0-9]+)?[smh]?'))">
   239           <xsl:if test="not(regexp:test($freq,'^[0-9]*(\.[0-9]+)?[smh]?'))">
   240             <xsl:message terminate="yes">
   240             <xsl:message terminate="yes">
   241               <xsl:text>Widget id:</xsl:text>
   241               <xsl:text>Widget id:</xsl:text>
   242               <xsl:value-of select="$id"/>
   242               <xsl:value-of select="$id"/>
   243               <xsl:text> label:</xsl:text>
   243               <xsl:text> label:</xsl:text>
   244               <xsl:value-of select="$label"/>
   244               <xsl:value-of select="$full_decl"/>
   245               <xsl:text> has wrong syntax of frequency forcing </xsl:text>
   245               <xsl:text> has wrong syntax of frequency forcing </xsl:text>
   246               <xsl:value-of select="$freq"/>
   246               <xsl:value-of select="$freq"/>
   247             </xsl:message>
   247             </xsl:message>
   248           </xsl:if>
   248           </xsl:if>
   249           <xsl:attribute name="freq">
   249           <xsl:attribute name="freq">
   250             <xsl:value-of select="$freq"/>
   250             <xsl:value-of select="$freq"/>
       
   251           </xsl:attribute>
       
   252         </xsl:if>
       
   253         <xsl:variable name="tail" select="substring-after($declaration,'@')"/>
       
   254         <xsl:variable name="taillen" select="string-length($tail)"/>
       
   255         <xsl:variable name="has_enable" select="contains($tail, '#')"/>
       
   256         <xsl:variable name="paths">
       
   257           <xsl:choose>
       
   258             <xsl:when test="$has_enable">
       
   259               <xsl:value-of select="substring-before($tail,'#')"/>
       
   260             </xsl:when>
       
   261             <xsl:otherwise>
       
   262               <xsl:value-of select="$tail"/>
       
   263             </xsl:otherwise>
       
   264           </xsl:choose>
       
   265         </xsl:variable>
       
   266         <xsl:if test="$has_enable">
       
   267           <xsl:variable name="enable_expr" select="substring-after($tail,'#')"/>
       
   268           <xsl:attribute name="enable_expr">
       
   269             <xsl:value-of select="$enable_expr"/>
   251           </xsl:attribute>
   270           </xsl:attribute>
   252         </xsl:if>
   271         </xsl:if>
   253         <xsl:for-each select="str:split(substring-after($args, ':'), ':')">
   272         <xsl:for-each select="str:split(substring-after($args, ':'), ':')">
   254           <arg>
   273           <arg>
   255             <xsl:attribute name="value">
   274             <xsl:attribute name="value">
   256               <xsl:value-of select="."/>
   275               <xsl:value-of select="."/>
   257             </xsl:attribute>
   276             </xsl:attribute>
   258           </arg>
   277           </arg>
   259         </xsl:for-each>
   278         </xsl:for-each>
   260         <xsl:variable name="paths" select="substring-after($description,'@')"/>
       
   261         <xsl:for-each select="str:split($paths, '@')">
   279         <xsl:for-each select="str:split($paths, '@')">
   262           <xsl:if test="string-length(.) &gt; 0">
   280           <xsl:if test="string-length(.) &gt; 0">
   263             <path>
   281             <path>
   264               <xsl:variable name="path_match" select="regexp:match(.,$pathregex)"/>
   282               <xsl:variable name="path_match" select="regexp:match(.,$pathregex)"/>
       
   283               <xsl:variable name="pathassign" select="substring-before($path_match[2],'=')"/>
   265               <xsl:variable name="pathminmax" select="str:split($path_match[4],',')"/>
   284               <xsl:variable name="pathminmax" select="str:split($path_match[4],',')"/>
   266               <xsl:variable name="path" select="$path_match[2]"/>
   285               <xsl:variable name="path" select="$path_match[3]"/>
   267               <xsl:variable name="path_accepts" select="$path_match[3]"/>
       
   268               <xsl:variable name="pathminmaxcount" select="count($pathminmax)"/>
   286               <xsl:variable name="pathminmaxcount" select="count($pathminmax)"/>
       
   287               <xsl:if test="not($path)">
       
   288                 <xsl:message terminate="yes">
       
   289                   <xsl:text>Widget id:</xsl:text>
       
   290                   <xsl:value-of select="$id"/>
       
   291                   <xsl:text> label:</xsl:text>
       
   292                   <xsl:value-of select="$full_decl"/>
       
   293                   <xsl:text> has wrong syntax</xsl:text>
       
   294                 </xsl:message>
       
   295               </xsl:if>
   269               <xsl:attribute name="value">
   296               <xsl:attribute name="value">
   270                 <xsl:value-of select="$path"/>
   297                 <xsl:value-of select="$path"/>
   271               </xsl:attribute>
   298               </xsl:attribute>
   272               <xsl:if test="string-length($path_accepts)">
   299               <xsl:if test="$pathassign">
   273                 <xsl:attribute name="accepts">
   300                 <xsl:attribute name="assign">
   274                   <xsl:value-of select="$path_accepts"/>
   301                   <xsl:value-of select="$pathassign"/>
   275                 </xsl:attribute>
   302                 </xsl:attribute>
   276               </xsl:if>
   303               </xsl:if>
   277               <xsl:choose>
   304               <xsl:choose>
   278                 <xsl:when test="$pathminmaxcount = 2">
   305                 <xsl:when test="$pathminmaxcount = 2">
   279                   <xsl:attribute name="min">
   306                   <xsl:attribute name="min">
   286                 <xsl:when test="$pathminmaxcount = 1 or $pathminmaxcount &gt; 2">
   313                 <xsl:when test="$pathminmaxcount = 1 or $pathminmaxcount &gt; 2">
   287                   <xsl:message terminate="yes">
   314                   <xsl:message terminate="yes">
   288                     <xsl:text>Widget id:</xsl:text>
   315                     <xsl:text>Widget id:</xsl:text>
   289                     <xsl:value-of select="$id"/>
   316                     <xsl:value-of select="$id"/>
   290                     <xsl:text> label:</xsl:text>
   317                     <xsl:text> label:</xsl:text>
   291                     <xsl:value-of select="$label"/>
   318                     <xsl:value-of select="$full_decl"/>
   292                     <xsl:text> has wrong syntax of path section </xsl:text>
   319                     <xsl:text> has wrong syntax of path section </xsl:text>
   293                     <xsl:value-of select="$pathminmax"/>
   320                     <xsl:value-of select="$pathminmax"/>
   294                   </xsl:message>
   321                   </xsl:message>
   295                 </xsl:when>
   322                 </xsl:when>
   296               </xsl:choose>
   323               </xsl:choose>
   312                     <xsl:if test="$pathminmaxcount = 3 and not($pathtype = 'HMI_INT' or $pathtype = 'HMI_REAL')">
   339                     <xsl:if test="$pathminmaxcount = 3 and not($pathtype = 'HMI_INT' or $pathtype = 'HMI_REAL')">
   313                       <xsl:message terminate="yes">
   340                       <xsl:message terminate="yes">
   314                         <xsl:text>Widget id:</xsl:text>
   341                         <xsl:text>Widget id:</xsl:text>
   315                         <xsl:value-of select="$id"/>
   342                         <xsl:value-of select="$id"/>
   316                         <xsl:text> label:</xsl:text>
   343                         <xsl:text> label:</xsl:text>
   317                         <xsl:value-of select="$label"/>
   344                         <xsl:value-of select="$full_decl"/>
   318                         <xsl:text> path section </xsl:text>
   345                         <xsl:text> path section </xsl:text>
   319                         <xsl:value-of select="$pathminmax"/>
   346                         <xsl:value-of select="$pathminmax"/>
   320                         <xsl:text> use min and max on non mumeric value</xsl:text>
   347                         <xsl:text> use min and max on non mumeric value</xsl:text>
   321                       </xsl:message>
   348                       </xsl:message>
   322                     </xsl:if>
   349                     </xsl:if>
  1244         </xsl:if>
  1271         </xsl:if>
  1245       </xsl:for-each>
  1272       </xsl:for-each>
  1246     </xsl:variable>
  1273     </xsl:variable>
  1247     <xsl:variable name="indexes">
  1274     <xsl:variable name="indexes">
  1248       <xsl:for-each select="$widget/path">
  1275       <xsl:for-each select="$widget/path">
       
  1276         <xsl:if test="position()!=last()">
       
  1277           <xsl:text>,</xsl:text>
       
  1278         </xsl:if>
       
  1279       </xsl:for-each>
       
  1280     </xsl:variable>
       
  1281     <xsl:variable name="variables">
       
  1282       <xsl:for-each select="$widget/path">
       
  1283         <xsl:text>[</xsl:text>
  1249         <xsl:choose>
  1284         <xsl:choose>
  1250           <xsl:when test="not(@index)">
  1285           <xsl:when test="not(@index)">
  1251             <xsl:choose>
  1286             <xsl:choose>
  1252               <xsl:when test="not(@type)">
  1287               <xsl:when test="not(@type)">
  1253                 <xsl:message terminate="no">
  1288                 <xsl:message terminate="no">
  1280           </xsl:when>
  1315           </xsl:when>
  1281           <xsl:otherwise>
  1316           <xsl:otherwise>
  1282             <xsl:value-of select="@index"/>
  1317             <xsl:value-of select="@index"/>
  1283           </xsl:otherwise>
  1318           </xsl:otherwise>
  1284         </xsl:choose>
  1319         </xsl:choose>
  1285         <xsl:if test="position()!=last()">
  1320         <xsl:text>, {</xsl:text>
  1286           <xsl:text>,</xsl:text>
  1321         <xsl:if test="@min and @max">
       
  1322           <xsl:text>minmax:[</xsl:text>
       
  1323           <xsl:value-of select="@min"/>
       
  1324           <xsl:text>, </xsl:text>
       
  1325           <xsl:value-of select="@max"/>
       
  1326           <xsl:text>]</xsl:text>
       
  1327           <xsl:if test="@assign">
       
  1328             <xsl:text>,</xsl:text>
       
  1329           </xsl:if>
  1287         </xsl:if>
  1330         </xsl:if>
  1288       </xsl:for-each>
  1331         <xsl:if test="@assign">
  1289     </xsl:variable>
  1332           <xsl:text>assign:"</xsl:text>
  1290     <xsl:variable name="minmaxes">
  1333           <xsl:value-of select="@assign"/>
  1291       <xsl:for-each select="$widget/path">
  1334           <xsl:text>"</xsl:text>
  1292         <xsl:choose>
  1335         </xsl:if>
  1293           <xsl:when test="@min and @max">
  1336         <xsl:text>}]</xsl:text>
  1294             <xsl:text>[</xsl:text>
       
  1295             <xsl:value-of select="@min"/>
       
  1296             <xsl:text>,</xsl:text>
       
  1297             <xsl:value-of select="@max"/>
       
  1298             <xsl:text>]</xsl:text>
       
  1299           </xsl:when>
       
  1300           <xsl:otherwise>
       
  1301             <xsl:text>undefined</xsl:text>
       
  1302           </xsl:otherwise>
       
  1303         </xsl:choose>
       
  1304         <xsl:if test="position()!=last()">
  1337         <xsl:if test="position()!=last()">
  1305           <xsl:text>,</xsl:text>
  1338           <xsl:text>,</xsl:text>
  1306         </xsl:if>
  1339         </xsl:if>
  1307       </xsl:for-each>
  1340       </xsl:for-each>
  1308     </xsl:variable>
  1341     </xsl:variable>
  1316         <xsl:otherwise>
  1349         <xsl:otherwise>
  1317           <xsl:text>undefined</xsl:text>
  1350           <xsl:text>undefined</xsl:text>
  1318         </xsl:otherwise>
  1351         </xsl:otherwise>
  1319       </xsl:choose>
  1352       </xsl:choose>
  1320     </xsl:variable>
  1353     </xsl:variable>
       
  1354     <xsl:variable name="enable_expr">
       
  1355       <xsl:choose>
       
  1356         <xsl:when test="$widget/@enable_expr">
       
  1357           <xsl:text>true</xsl:text>
       
  1358         </xsl:when>
       
  1359         <xsl:otherwise>
       
  1360           <xsl:text>false</xsl:text>
       
  1361         </xsl:otherwise>
       
  1362       </xsl:choose>
       
  1363     </xsl:variable>
  1321     <xsl:text>  "</xsl:text>
  1364     <xsl:text>  "</xsl:text>
  1322     <xsl:value-of select="@id"/>
  1365     <xsl:value-of select="@id"/>
  1323     <xsl:text>": new </xsl:text>
  1366     <xsl:text>": new </xsl:text>
  1324     <xsl:value-of select="$widget/@type"/>
  1367     <xsl:value-of select="$widget/@type"/>
  1325     <xsl:text>Widget ("</xsl:text>
  1368     <xsl:text>Widget ("</xsl:text>
  1327     <xsl:text>",</xsl:text>
  1370     <xsl:text>",</xsl:text>
  1328     <xsl:value-of select="$freq"/>
  1371     <xsl:value-of select="$freq"/>
  1329     <xsl:text>,[</xsl:text>
  1372     <xsl:text>,[</xsl:text>
  1330     <xsl:value-of select="$args"/>
  1373     <xsl:value-of select="$args"/>
  1331     <xsl:text>],[</xsl:text>
  1374     <xsl:text>],[</xsl:text>
  1332     <xsl:value-of select="$indexes"/>
  1375     <xsl:value-of select="$variables"/>
  1333     <xsl:text>],[</xsl:text>
  1376     <xsl:text>],</xsl:text>
  1334     <xsl:value-of select="$minmaxes"/>
  1377     <xsl:value-of select="$enable_expr"/>
  1335     <xsl:text>],{
  1378     <xsl:text>,{
  1336 </xsl:text>
  1379 </xsl:text>
       
  1380     <xsl:if test="$widget/@enable_expr">
       
  1381       <xsl:text>      assignments: [],
       
  1382 </xsl:text>
       
  1383       <xsl:text>      compute_enable: function(value, oldval, varnum) {
       
  1384 </xsl:text>
       
  1385       <xsl:text>        let result = false;
       
  1386 </xsl:text>
       
  1387       <xsl:text>        do {
       
  1388 </xsl:text>
       
  1389       <xsl:for-each select="$widget/path">
       
  1390         <xsl:variable name="varid" select="generate-id()"/>
       
  1391         <xsl:variable name="varnum" select="position()-1"/>
       
  1392         <xsl:if test="@assign">
       
  1393           <xsl:for-each select="$widget/path[@assign]">
       
  1394             <xsl:if test="$varid = generate-id()">
       
  1395               <xsl:text>          if(varnum == </xsl:text>
       
  1396               <xsl:value-of select="$varnum"/>
       
  1397               <xsl:text>) this.assignments[</xsl:text>
       
  1398               <xsl:value-of select="position()-1"/>
       
  1399               <xsl:text>] = value;
       
  1400 </xsl:text>
       
  1401               <xsl:text>          let </xsl:text>
       
  1402               <xsl:value-of select="@assign"/>
       
  1403               <xsl:text> = this.assignments[</xsl:text>
       
  1404               <xsl:value-of select="position()-1"/>
       
  1405               <xsl:text>];
       
  1406 </xsl:text>
       
  1407               <xsl:text>          if(</xsl:text>
       
  1408               <xsl:value-of select="@assign"/>
       
  1409               <xsl:text> == undefined) break;
       
  1410 </xsl:text>
       
  1411             </xsl:if>
       
  1412           </xsl:for-each>
       
  1413         </xsl:if>
       
  1414       </xsl:for-each>
       
  1415       <xsl:text>          result = </xsl:text>
       
  1416       <xsl:value-of select="$widget/@enable_expr"/>
       
  1417       <xsl:text>;
       
  1418 </xsl:text>
       
  1419       <xsl:text>        } while(0);
       
  1420 </xsl:text>
       
  1421       <xsl:text>        this.enable(result);
       
  1422 </xsl:text>
       
  1423       <xsl:text>      },
       
  1424 </xsl:text>
       
  1425     </xsl:if>
  1337     <xsl:apply-templates mode="widget_defs" select="$widget">
  1426     <xsl:apply-templates mode="widget_defs" select="$widget">
  1338       <xsl:with-param name="hmi_element" select="."/>
  1427       <xsl:with-param name="hmi_element" select="."/>
  1339     </xsl:apply-templates>
  1428     </xsl:apply-templates>
  1340     <xsl:text>  })</xsl:text>
  1429     <xsl:text>  })</xsl:text>
  1341     <xsl:if test="position()!=last()">
  1430     <xsl:if test="position()!=last()">
  1518 </xsl:text>
  1607 </xsl:text>
  1519     <xsl:text>}
  1608     <xsl:text>}
  1520 </xsl:text>
  1609 </xsl:text>
  1521     <xsl:text>
  1610     <xsl:text>
  1522 </xsl:text>
  1611 </xsl:text>
  1523     <xsl:text>function set_activation_state(eltsub, state){
  1612     <xsl:text>function set_activity_state(eltsub, state){
  1524 </xsl:text>
  1613 </xsl:text>
  1525     <xsl:text>    if(eltsub.active_elt != undefined){
  1614     <xsl:text>    if(eltsub.active_elt != undefined){
  1526 </xsl:text>
  1615 </xsl:text>
  1527     <xsl:text>        if(eltsub.active_elt_placeholder == undefined){
  1616     <xsl:text>        if(eltsub.active_elt_placeholder == undefined){
  1528 </xsl:text>
  1617 </xsl:text>
  1552 </xsl:text>
  1641 </xsl:text>
  1553     <xsl:text>}
  1642     <xsl:text>}
  1554 </xsl:text>
  1643 </xsl:text>
  1555     <xsl:text>
  1644     <xsl:text>
  1556 </xsl:text>
  1645 </xsl:text>
  1557     <xsl:text>function activate_activable(eltsub) {
       
  1558 </xsl:text>
       
  1559     <xsl:text>    set_activation_state(eltsub, true);
       
  1560 </xsl:text>
       
  1561     <xsl:text>}
       
  1562 </xsl:text>
       
  1563     <xsl:text>
       
  1564 </xsl:text>
       
  1565     <xsl:text>function inactivate_activable(eltsub) {
       
  1566 </xsl:text>
       
  1567     <xsl:text>    set_activation_state(eltsub, false);
       
  1568 </xsl:text>
       
  1569     <xsl:text>}
       
  1570 </xsl:text>
       
  1571     <xsl:text>
       
  1572 </xsl:text>
       
  1573     <xsl:text>class Widget {
  1646     <xsl:text>class Widget {
  1574 </xsl:text>
  1647 </xsl:text>
  1575     <xsl:text>    offset = 0;
  1648     <xsl:text>    offset = 0;
  1576 </xsl:text>
  1649 </xsl:text>
  1577     <xsl:text>    frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */
  1650     <xsl:text>    frequency = 10; /* FIXME arbitrary default max freq. Obtain from config ? */
  1580 </xsl:text>
  1653 </xsl:text>
  1581     <xsl:text>    pending_animate = false;
  1654     <xsl:text>    pending_animate = false;
  1582 </xsl:text>
  1655 </xsl:text>
  1583     <xsl:text>
  1656     <xsl:text>
  1584 </xsl:text>
  1657 </xsl:text>
  1585     <xsl:text>    constructor(elt_id, freq, args, indexes, minmaxes, members){
  1658     <xsl:text>    constructor(elt_id, freq, args, variables, enable_expr, members){
  1586 </xsl:text>
  1659 </xsl:text>
  1587     <xsl:text>        this.element_id = elt_id;
  1660     <xsl:text>        this.element_id = elt_id;
  1588 </xsl:text>
  1661 </xsl:text>
  1589     <xsl:text>        this.element = id(elt_id);
  1662     <xsl:text>        this.element = id(elt_id);
  1590 </xsl:text>
  1663 </xsl:text>
  1591     <xsl:text>        this.args = args;
  1664     <xsl:text>        this.args = args;
  1592 </xsl:text>
  1665 </xsl:text>
  1593     <xsl:text>        this.indexes = indexes;
  1666     <xsl:text>        
  1594 </xsl:text>
  1667 </xsl:text>
  1595     <xsl:text>        this.minmaxes = minmaxes;
  1668     <xsl:text>        [this.indexes, this.variables_options] = (variables.length&gt;0) ? zip(...variables) : [[],[]];
       
  1669 </xsl:text>
       
  1670     <xsl:text>        this.indexes_length = this.indexes.length;
       
  1671 </xsl:text>
       
  1672     <xsl:text>
       
  1673 </xsl:text>
       
  1674     <xsl:text>        this.enable_expr = enable_expr;
       
  1675 </xsl:text>
       
  1676     <xsl:text>        this.enable_state = true;
       
  1677 </xsl:text>
       
  1678     <xsl:text>        this.enable_displayed_state = true;
       
  1679 </xsl:text>
       
  1680     <xsl:text>        this.enabled_elts = [];
       
  1681 </xsl:text>
       
  1682     <xsl:text>
  1596 </xsl:text>
  1683 </xsl:text>
  1597     <xsl:text>        Object.keys(members).forEach(prop =&gt; this[prop]=members[prop]);
  1684     <xsl:text>        Object.keys(members).forEach(prop =&gt; this[prop]=members[prop]);
  1598 </xsl:text>
  1685 </xsl:text>
  1599     <xsl:text>        this.lastapply = indexes.map(() =&gt; undefined);
  1686     <xsl:text>        this.lastapply = this.indexes.map(() =&gt; undefined);
  1600 </xsl:text>
  1687 </xsl:text>
  1601     <xsl:text>        this.inhibit = indexes.map(() =&gt; undefined);
  1688     <xsl:text>        this.inhibit = this.indexes.map(() =&gt; undefined);
  1602 </xsl:text>
  1689 </xsl:text>
  1603     <xsl:text>        this.pending = indexes.map(() =&gt; undefined);
  1690     <xsl:text>        this.pending = this.indexes.map(() =&gt; undefined);
  1604 </xsl:text>
  1691 </xsl:text>
  1605     <xsl:text>        this.bound_uninhibit = this.uninhibit.bind(this);
  1692     <xsl:text>        this.bound_uninhibit = this.uninhibit.bind(this);
  1606 </xsl:text>
  1693 </xsl:text>
  1607     <xsl:text>
  1694     <xsl:text>
  1608 </xsl:text>
  1695 </xsl:text>
  1609     <xsl:text>        this.lastdispatch = indexes.map(() =&gt; undefined);
  1696     <xsl:text>        this.lastdispatch = this.indexes.map(() =&gt; undefined);
  1610 </xsl:text>
  1697 </xsl:text>
  1611     <xsl:text>        this.deafen = indexes.map(() =&gt; undefined);
  1698     <xsl:text>        this.deafen = this.indexes.map(() =&gt; undefined);
  1612 </xsl:text>
  1699 </xsl:text>
  1613     <xsl:text>        this.incoming = indexes.map(() =&gt; undefined);
  1700     <xsl:text>        this.incoming = this.indexes.map(() =&gt; undefined);
  1614 </xsl:text>
  1701 </xsl:text>
  1615     <xsl:text>        this.bound_undeafen = this.undeafen.bind(this);
  1702     <xsl:text>        this.bound_undeafen = this.undeafen.bind(this);
  1616 </xsl:text>
  1703 </xsl:text>
  1617     <xsl:text>
  1704     <xsl:text>
  1618 </xsl:text>
  1705 </xsl:text>
  1678 </xsl:text>
  1765 </xsl:text>
  1679     <xsl:text>            }
  1766     <xsl:text>            }
  1680 </xsl:text>
  1767 </xsl:text>
  1681     <xsl:text>        }
  1768     <xsl:text>        }
  1682 </xsl:text>
  1769 </xsl:text>
       
  1770     <xsl:text>
       
  1771 </xsl:text>
       
  1772     <xsl:text>        if(this.enable_expr){
       
  1773 </xsl:text>
       
  1774     <xsl:text>            this.enable_state = false;
       
  1775 </xsl:text>
       
  1776     <xsl:text>            this.enable_displayed_state = false;
       
  1777 </xsl:text>
       
  1778     <xsl:text>            for(let child of Array.from(this.element.children)){
       
  1779 </xsl:text>
       
  1780     <xsl:text>                let label = child.getAttribute("inkscape:label");
       
  1781 </xsl:text>
       
  1782     <xsl:text>                if(label!="disabled"){
       
  1783 </xsl:text>
       
  1784     <xsl:text>                    this.enabled_elts.push(child);
       
  1785 </xsl:text>
       
  1786     <xsl:text>                    this.element.removeChild(child);
       
  1787 </xsl:text>
       
  1788     <xsl:text>                }
       
  1789 </xsl:text>
       
  1790     <xsl:text>            }
       
  1791 </xsl:text>
       
  1792     <xsl:text>        }
       
  1793 </xsl:text>
  1683     <xsl:text>    }
  1794     <xsl:text>    }
  1684 </xsl:text>
  1795 </xsl:text>
  1685     <xsl:text>
  1796     <xsl:text>
  1686 </xsl:text>
  1797 </xsl:text>
  1687     <xsl:text>    unsub(){
  1798     <xsl:text>    unsub(){
  1688 </xsl:text>
  1799 </xsl:text>
  1689     <xsl:text>        /* remove subsribers */
  1800     <xsl:text>        /* remove subsribers */
  1690 </xsl:text>
  1801 </xsl:text>
  1691     <xsl:text>        if(!this.unsubscribable)
  1802     <xsl:text>        for(let i = 0; i &lt; this.indexes_length; i++) {
  1692 </xsl:text>
  1803 </xsl:text>
  1693     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1804     <xsl:text>            /* flush updates pending because of inhibition */
  1694 </xsl:text>
  1805 </xsl:text>
  1695     <xsl:text>                /* flush updates pending because of inhibition */
  1806     <xsl:text>            let inhibition = this.inhibit[i];
  1696 </xsl:text>
  1807 </xsl:text>
  1697     <xsl:text>                let inhibition = this.inhibit[i];
  1808     <xsl:text>            if(inhibition != undefined){
  1698 </xsl:text>
  1809 </xsl:text>
  1699     <xsl:text>                if(inhibition != undefined){
  1810     <xsl:text>                clearTimeout(inhibition);
  1700 </xsl:text>
  1811 </xsl:text>
  1701     <xsl:text>                    clearTimeout(inhibition);
  1812     <xsl:text>                this.lastapply[i] = undefined;
  1702 </xsl:text>
  1813 </xsl:text>
  1703     <xsl:text>                    this.lastapply[i] = undefined;
  1814     <xsl:text>                this.uninhibit(i);
  1704 </xsl:text>
  1815 </xsl:text>
  1705     <xsl:text>                    this.uninhibit(i);
  1816     <xsl:text>            }
       
  1817 </xsl:text>
       
  1818     <xsl:text>            let deafened = this.deafen[i];
       
  1819 </xsl:text>
       
  1820     <xsl:text>            if(deafened != undefined){
       
  1821 </xsl:text>
       
  1822     <xsl:text>                clearTimeout(deafened);
       
  1823 </xsl:text>
       
  1824     <xsl:text>                this.lastdispatch[i] = undefined;
       
  1825 </xsl:text>
       
  1826     <xsl:text>                this.undeafen(i);
       
  1827 </xsl:text>
       
  1828     <xsl:text>            }
       
  1829 </xsl:text>
       
  1830     <xsl:text>            let index = this.get_variable_index(i);
       
  1831 </xsl:text>
       
  1832     <xsl:text>            subscribers(index).delete(this);
       
  1833 </xsl:text>
       
  1834     <xsl:text>        }
       
  1835 </xsl:text>
       
  1836     <xsl:text>        this.offset = 0;
       
  1837 </xsl:text>
       
  1838     <xsl:text>        this.relativeness = undefined;
       
  1839 </xsl:text>
       
  1840     <xsl:text>    }
       
  1841 </xsl:text>
       
  1842     <xsl:text>
       
  1843 </xsl:text>
       
  1844     <xsl:text>    sub(new_offset=0, relativeness, container_id){
       
  1845 </xsl:text>
       
  1846     <xsl:text>        this.offset = new_offset;
       
  1847 </xsl:text>
       
  1848     <xsl:text>        this.relativeness = relativeness;
       
  1849 </xsl:text>
       
  1850     <xsl:text>        this.container_id = container_id ;
       
  1851 </xsl:text>
       
  1852     <xsl:text>        /* add this's subsribers */
       
  1853 </xsl:text>
       
  1854     <xsl:text>        for(let i = 0; i &lt; this.indexes_length; i++) {
       
  1855 </xsl:text>
       
  1856     <xsl:text>            let index = this.get_variable_index(i);
       
  1857 </xsl:text>
       
  1858     <xsl:text>            if(index == undefined) continue;
       
  1859 </xsl:text>
       
  1860     <xsl:text>            subscribers(index).add(this);
       
  1861 </xsl:text>
       
  1862     <xsl:text>        }
       
  1863 </xsl:text>
       
  1864     <xsl:text>        this.apply_cache(); 
       
  1865 </xsl:text>
       
  1866     <xsl:text>    }
       
  1867 </xsl:text>
       
  1868     <xsl:text>
       
  1869 </xsl:text>
       
  1870     <xsl:text>    apply_cache() {
       
  1871 </xsl:text>
       
  1872     <xsl:text>        for(let i = 0; i &lt; this.indexes_length; i++) {
       
  1873 </xsl:text>
       
  1874     <xsl:text>            /* dispatch current cache in newly opened page widgets */
       
  1875 </xsl:text>
       
  1876     <xsl:text>            let realindex = this.get_variable_index(i);
       
  1877 </xsl:text>
       
  1878     <xsl:text>            if(realindex == undefined) continue;
       
  1879 </xsl:text>
       
  1880     <xsl:text>            let cached_val = cache[realindex];
       
  1881 </xsl:text>
       
  1882     <xsl:text>            if(cached_val != undefined)
       
  1883 </xsl:text>
       
  1884     <xsl:text>                this.feed_data_for_dispatch(cached_val, cached_val, i);
       
  1885 </xsl:text>
       
  1886     <xsl:text>        }
       
  1887 </xsl:text>
       
  1888     <xsl:text>    }
       
  1889 </xsl:text>
       
  1890     <xsl:text>
       
  1891 </xsl:text>
       
  1892     <xsl:text>    get_variable_index(varnum) {
       
  1893 </xsl:text>
       
  1894     <xsl:text>        let index = this.indexes[varnum];
       
  1895 </xsl:text>
       
  1896     <xsl:text>        if(typeof(index) == "string"){
       
  1897 </xsl:text>
       
  1898     <xsl:text>            index = page_local_index(index, this.container_id);
       
  1899 </xsl:text>
       
  1900     <xsl:text>        } else {
       
  1901 </xsl:text>
       
  1902     <xsl:text>            if(this.relativeness[varnum]){
       
  1903 </xsl:text>
       
  1904     <xsl:text>                index += this.offset;
       
  1905 </xsl:text>
       
  1906     <xsl:text>            }
       
  1907 </xsl:text>
       
  1908     <xsl:text>        }
       
  1909 </xsl:text>
       
  1910     <xsl:text>        return index;
       
  1911 </xsl:text>
       
  1912     <xsl:text>    }
       
  1913 </xsl:text>
       
  1914     <xsl:text>
       
  1915 </xsl:text>
       
  1916     <xsl:text>    overshot(new_val, max) {
       
  1917 </xsl:text>
       
  1918     <xsl:text>    }
       
  1919 </xsl:text>
       
  1920     <xsl:text>
       
  1921 </xsl:text>
       
  1922     <xsl:text>    undershot(new_val, min) {
       
  1923 </xsl:text>
       
  1924     <xsl:text>    }
       
  1925 </xsl:text>
       
  1926     <xsl:text>
       
  1927 </xsl:text>
       
  1928     <xsl:text>    clip_min_max(index, new_val) {
       
  1929 </xsl:text>
       
  1930     <xsl:text>        let minmax = this.variables_options[index].minmax;
       
  1931 </xsl:text>
       
  1932     <xsl:text>        if(minmax !== undefined &amp;&amp; typeof new_val == "number") {
       
  1933 </xsl:text>
       
  1934     <xsl:text>            let [min,max] = minmax;
       
  1935 </xsl:text>
       
  1936     <xsl:text>            if(new_val &lt; min){
       
  1937 </xsl:text>
       
  1938     <xsl:text>                this.undershot(new_val, min);
       
  1939 </xsl:text>
       
  1940     <xsl:text>                return min;
       
  1941 </xsl:text>
       
  1942     <xsl:text>            }
       
  1943 </xsl:text>
       
  1944     <xsl:text>            if(new_val &gt; max){
       
  1945 </xsl:text>
       
  1946     <xsl:text>                this.overshot(new_val, max);
       
  1947 </xsl:text>
       
  1948     <xsl:text>                return max;
       
  1949 </xsl:text>
       
  1950     <xsl:text>            }
       
  1951 </xsl:text>
       
  1952     <xsl:text>        }
       
  1953 </xsl:text>
       
  1954     <xsl:text>        return new_val;
       
  1955 </xsl:text>
       
  1956     <xsl:text>    }
       
  1957 </xsl:text>
       
  1958     <xsl:text>
       
  1959 </xsl:text>
       
  1960     <xsl:text>    change_hmi_value(index, opstr) {
       
  1961 </xsl:text>
       
  1962     <xsl:text>        let realindex = this.get_variable_index(index);
       
  1963 </xsl:text>
       
  1964     <xsl:text>        if(realindex == undefined) return undefined;
       
  1965 </xsl:text>
       
  1966     <xsl:text>        let old_val = cache[realindex];
       
  1967 </xsl:text>
       
  1968     <xsl:text>        let new_val = eval_operation_string(old_val, opstr);
       
  1969 </xsl:text>
       
  1970     <xsl:text>        if(this.clip)
       
  1971 </xsl:text>
       
  1972     <xsl:text>            new_val = this.clip_min_max(index, new_val);
       
  1973 </xsl:text>
       
  1974     <xsl:text>        return apply_hmi_value(realindex, new_val);
       
  1975 </xsl:text>
       
  1976     <xsl:text>    }
       
  1977 </xsl:text>
       
  1978     <xsl:text>
       
  1979 </xsl:text>
       
  1980     <xsl:text>    _apply_hmi_value(index, new_val) {
       
  1981 </xsl:text>
       
  1982     <xsl:text>        let realindex = this.get_variable_index(index);
       
  1983 </xsl:text>
       
  1984     <xsl:text>        if(realindex == undefined) return undefined;
       
  1985 </xsl:text>
       
  1986     <xsl:text>        if(this.clip)
       
  1987 </xsl:text>
       
  1988     <xsl:text>            new_val = this.clip_min_max(index, new_val);
       
  1989 </xsl:text>
       
  1990     <xsl:text>        return apply_hmi_value(realindex, new_val);
       
  1991 </xsl:text>
       
  1992     <xsl:text>    }
       
  1993 </xsl:text>
       
  1994     <xsl:text>
       
  1995 </xsl:text>
       
  1996     <xsl:text>    uninhibit(index){
       
  1997 </xsl:text>
       
  1998     <xsl:text>        this.inhibit[index] = undefined;
       
  1999 </xsl:text>
       
  2000     <xsl:text>        let new_val = this.pending[index];
       
  2001 </xsl:text>
       
  2002     <xsl:text>        this.pending[index] = undefined;
       
  2003 </xsl:text>
       
  2004     <xsl:text>        return this.apply_hmi_value(index, new_val);
       
  2005 </xsl:text>
       
  2006     <xsl:text>    }
       
  2007 </xsl:text>
       
  2008     <xsl:text>
       
  2009 </xsl:text>
       
  2010     <xsl:text>    apply_hmi_value(index, new_val) {
       
  2011 </xsl:text>
       
  2012     <xsl:text>        if(this.inhibit[index] == undefined){
       
  2013 </xsl:text>
       
  2014     <xsl:text>            let now = Date.now();
       
  2015 </xsl:text>
       
  2016     <xsl:text>            let min_interval = 1000/this.frequency;
       
  2017 </xsl:text>
       
  2018     <xsl:text>            let lastapply = this.lastapply[index];
       
  2019 </xsl:text>
       
  2020     <xsl:text>            if(lastapply == undefined || now &gt; lastapply + min_interval){
       
  2021 </xsl:text>
       
  2022     <xsl:text>                this.lastapply[index] = now;
       
  2023 </xsl:text>
       
  2024     <xsl:text>                return this._apply_hmi_value(index, new_val);
       
  2025 </xsl:text>
       
  2026     <xsl:text>            }
       
  2027 </xsl:text>
       
  2028     <xsl:text>            else {
       
  2029 </xsl:text>
       
  2030     <xsl:text>                let elapsed = now - lastapply;
       
  2031 </xsl:text>
       
  2032     <xsl:text>                this.pending[index] = new_val;
       
  2033 </xsl:text>
       
  2034     <xsl:text>                this.inhibit[index] = setTimeout(this.bound_uninhibit, min_interval - elapsed, index);
       
  2035 </xsl:text>
       
  2036     <xsl:text>            }
       
  2037 </xsl:text>
       
  2038     <xsl:text>        }
       
  2039 </xsl:text>
       
  2040     <xsl:text>        else {
       
  2041 </xsl:text>
       
  2042     <xsl:text>            this.pending[index] = new_val;
       
  2043 </xsl:text>
       
  2044     <xsl:text>            return new_val;
       
  2045 </xsl:text>
       
  2046     <xsl:text>        }
       
  2047 </xsl:text>
       
  2048     <xsl:text>    }
       
  2049 </xsl:text>
       
  2050     <xsl:text>
       
  2051 </xsl:text>
       
  2052     <xsl:text>    new_hmi_value(index, value, oldval) {
       
  2053 </xsl:text>
       
  2054     <xsl:text>        // TODO avoid searching, store index at sub()
       
  2055 </xsl:text>
       
  2056     <xsl:text>        for(let i = 0; i &lt; this.indexes_length; i++) {
       
  2057 </xsl:text>
       
  2058     <xsl:text>            let refindex = this.get_variable_index(i);
       
  2059 </xsl:text>
       
  2060     <xsl:text>            if(refindex == undefined) continue;
       
  2061 </xsl:text>
       
  2062     <xsl:text>
       
  2063 </xsl:text>
       
  2064     <xsl:text>            if(index == refindex) {
       
  2065 </xsl:text>
       
  2066     <xsl:text>                this.feed_data_for_dispatch(value, oldval, i);
       
  2067 </xsl:text>
       
  2068     <xsl:text>                break;
       
  2069 </xsl:text>
       
  2070     <xsl:text>            }
       
  2071 </xsl:text>
       
  2072     <xsl:text>        }
       
  2073 </xsl:text>
       
  2074     <xsl:text>    }
       
  2075 </xsl:text>
       
  2076     <xsl:text>    
       
  2077 </xsl:text>
       
  2078     <xsl:text>    undeafen(index){
       
  2079 </xsl:text>
       
  2080     <xsl:text>        this.deafen[index] = undefined;
       
  2081 </xsl:text>
       
  2082     <xsl:text>        let [new_val, old_val] = this.incoming[index];
       
  2083 </xsl:text>
       
  2084     <xsl:text>        this.incoming[index] = undefined;
       
  2085 </xsl:text>
       
  2086     <xsl:text>        this.do_dispatch(new_val, old_val, index);
       
  2087 </xsl:text>
       
  2088     <xsl:text>    }
       
  2089 </xsl:text>
       
  2090     <xsl:text>
       
  2091 </xsl:text>
       
  2092     <xsl:text>    enable(enabled){
       
  2093 </xsl:text>
       
  2094     <xsl:text>        if(this.enable_state != enabled){
       
  2095 </xsl:text>
       
  2096     <xsl:text>            this.enable_state = enabled;
       
  2097 </xsl:text>
       
  2098     <xsl:text>            this.request_animate();
       
  2099 </xsl:text>
       
  2100     <xsl:text>        }
       
  2101 </xsl:text>
       
  2102     <xsl:text>    }
       
  2103 </xsl:text>
       
  2104     <xsl:text>
       
  2105 </xsl:text>
       
  2106     <xsl:text>    animate_enable(){
       
  2107 </xsl:text>
       
  2108     <xsl:text>        if(this.enable_state &amp;&amp; !this.enable_displayed_state){
       
  2109 </xsl:text>
       
  2110     <xsl:text>            //show widget
       
  2111 </xsl:text>
       
  2112     <xsl:text>            for(let child of this.enabled_elts){
       
  2113 </xsl:text>
       
  2114     <xsl:text>                this.element.appendChild(child);
       
  2115 </xsl:text>
       
  2116     <xsl:text>            }
       
  2117 </xsl:text>
       
  2118     <xsl:text>
       
  2119 </xsl:text>
       
  2120     <xsl:text>            //hide disabled content
       
  2121 </xsl:text>
       
  2122     <xsl:text>            if(this.disabled_elt &amp;&amp; this.disabled_elt.parentNode != null)
       
  2123 </xsl:text>
       
  2124     <xsl:text>                this.element.removeChild(this.disabled_elt);
       
  2125 </xsl:text>
       
  2126     <xsl:text>
       
  2127 </xsl:text>
       
  2128     <xsl:text>            this.enable_displayed_state = true;
       
  2129 </xsl:text>
       
  2130     <xsl:text>
       
  2131 </xsl:text>
       
  2132     <xsl:text>        }else if(!this.enable_state &amp;&amp; this.enable_displayed_state){
       
  2133 </xsl:text>
       
  2134     <xsl:text>
       
  2135 </xsl:text>
       
  2136     <xsl:text>            //hide widget
       
  2137 </xsl:text>
       
  2138     <xsl:text>            for(let child of this.enabled_elts){
       
  2139 </xsl:text>
       
  2140     <xsl:text>                if(child.parentNode != null)
       
  2141 </xsl:text>
       
  2142     <xsl:text>                    this.element.removeChild(child);
       
  2143 </xsl:text>
       
  2144     <xsl:text>            }
       
  2145 </xsl:text>
       
  2146     <xsl:text>
       
  2147 </xsl:text>
       
  2148     <xsl:text>            //show disabled content
       
  2149 </xsl:text>
       
  2150     <xsl:text>            if(this.disabled_elt)
       
  2151 </xsl:text>
       
  2152     <xsl:text>                this.element.appendChild(this.disabled_elt);
       
  2153 </xsl:text>
       
  2154     <xsl:text>
       
  2155 </xsl:text>
       
  2156     <xsl:text>            this.enable_displayed_state = false;
       
  2157 </xsl:text>
       
  2158     <xsl:text>
       
  2159 </xsl:text>
       
  2160     <xsl:text>            // once disabled activity display is lost
       
  2161 </xsl:text>
       
  2162     <xsl:text>            this.activity_displayed_state = undefined;
       
  2163 </xsl:text>
       
  2164     <xsl:text>        }
       
  2165 </xsl:text>
       
  2166     <xsl:text>    }
       
  2167 </xsl:text>
       
  2168     <xsl:text>
       
  2169 </xsl:text>
       
  2170     <xsl:text>    feed_data_for_dispatch(value, oldval, varnum) {
       
  2171 </xsl:text>
       
  2172     <xsl:text>        if(this.dispatch || this.enable_expr){
       
  2173 </xsl:text>
       
  2174     <xsl:text>            if(this.deafen[varnum] == undefined){
       
  2175 </xsl:text>
       
  2176     <xsl:text>                let now = Date.now();
       
  2177 </xsl:text>
       
  2178     <xsl:text>                let min_interval = 1000/this.frequency;
       
  2179 </xsl:text>
       
  2180     <xsl:text>                let lastdispatch = this.lastdispatch[varnum];
       
  2181 </xsl:text>
       
  2182     <xsl:text>                if(lastdispatch == undefined || now &gt; lastdispatch + min_interval){
       
  2183 </xsl:text>
       
  2184     <xsl:text>                    this.lastdispatch[varnum] = now;
       
  2185 </xsl:text>
       
  2186     <xsl:text>                    this.do_dispatch(value, oldval, varnum)
  1706 </xsl:text>
  2187 </xsl:text>
  1707     <xsl:text>                }
  2188     <xsl:text>                }
  1708 </xsl:text>
  2189 </xsl:text>
  1709     <xsl:text>                let deafened = this.deafen[i];
  2190     <xsl:text>                else {
  1710 </xsl:text>
  2191 </xsl:text>
  1711     <xsl:text>                if(deafened != undefined){
  2192     <xsl:text>                    let elapsed = now - lastdispatch;
  1712 </xsl:text>
  2193 </xsl:text>
  1713     <xsl:text>                    clearTimeout(deafened);
  2194     <xsl:text>                    this.incoming[varnum] = [value, oldval];
  1714 </xsl:text>
  2195 </xsl:text>
  1715     <xsl:text>                    this.lastdispatch[i] = undefined;
  2196     <xsl:text>                    this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum);
  1716 </xsl:text>
       
  1717     <xsl:text>                    this.undeafen(i);
       
  1718 </xsl:text>
  2197 </xsl:text>
  1719     <xsl:text>                }
  2198     <xsl:text>                }
  1720 </xsl:text>
  2199 </xsl:text>
  1721     <xsl:text>                let index = this.indexes[i];
       
  1722 </xsl:text>
       
  1723     <xsl:text>                if(this.relativeness[i])
       
  1724 </xsl:text>
       
  1725     <xsl:text>                    index += this.offset;
       
  1726 </xsl:text>
       
  1727     <xsl:text>                subscribers(index).delete(this);
       
  1728 </xsl:text>
       
  1729     <xsl:text>            }
  2200     <xsl:text>            }
  1730 </xsl:text>
  2201 </xsl:text>
  1731     <xsl:text>        this.offset = 0;
  2202     <xsl:text>            else {
  1732 </xsl:text>
  2203 </xsl:text>
  1733     <xsl:text>        this.relativeness = undefined;
  2204     <xsl:text>                this.incoming[varnum] = [value, oldval];
  1734 </xsl:text>
       
  1735     <xsl:text>    }
       
  1736 </xsl:text>
       
  1737     <xsl:text>
       
  1738 </xsl:text>
       
  1739     <xsl:text>    sub(new_offset=0, relativeness, container_id){
       
  1740 </xsl:text>
       
  1741     <xsl:text>        this.offset = new_offset;
       
  1742 </xsl:text>
       
  1743     <xsl:text>        this.relativeness = relativeness;
       
  1744 </xsl:text>
       
  1745     <xsl:text>        this.container_id = container_id ;
       
  1746 </xsl:text>
       
  1747     <xsl:text>        /* add this's subsribers */
       
  1748 </xsl:text>
       
  1749     <xsl:text>        if(!this.unsubscribable)
       
  1750 </xsl:text>
       
  1751     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
       
  1752 </xsl:text>
       
  1753     <xsl:text>                let index = this.get_variable_index(i);
       
  1754 </xsl:text>
       
  1755     <xsl:text>                if(index == undefined) continue;
       
  1756 </xsl:text>
       
  1757     <xsl:text>                subscribers(index).add(this);
       
  1758 </xsl:text>
  2205 </xsl:text>
  1759     <xsl:text>            }
  2206     <xsl:text>            }
  1760 </xsl:text>
  2207 </xsl:text>
  1761     <xsl:text>        need_cache_apply.push(this); 
       
  1762 </xsl:text>
       
  1763     <xsl:text>    }
       
  1764 </xsl:text>
       
  1765     <xsl:text>
       
  1766 </xsl:text>
       
  1767     <xsl:text>    apply_cache() {
       
  1768 </xsl:text>
       
  1769     <xsl:text>        if(!this.unsubscribable) for(let index in this.indexes){
       
  1770 </xsl:text>
       
  1771     <xsl:text>            /* dispatch current cache in newly opened page widgets */
       
  1772 </xsl:text>
       
  1773     <xsl:text>            let realindex = this.get_variable_index(index);
       
  1774 </xsl:text>
       
  1775     <xsl:text>            if(realindex == undefined) continue;
       
  1776 </xsl:text>
       
  1777     <xsl:text>            let cached_val = cache[realindex];
       
  1778 </xsl:text>
       
  1779     <xsl:text>            if(cached_val != undefined)
       
  1780 </xsl:text>
       
  1781     <xsl:text>                this._dispatch(cached_val, cached_val, index);
       
  1782 </xsl:text>
       
  1783     <xsl:text>        }
  2208     <xsl:text>        }
  1784 </xsl:text>
  2209 </xsl:text>
  1785     <xsl:text>    }
  2210     <xsl:text>    }
  1786 </xsl:text>
  2211 </xsl:text>
  1787     <xsl:text>
  2212     <xsl:text>
  1788 </xsl:text>
  2213 </xsl:text>
  1789     <xsl:text>    get_variable_index(varnum) {
  2214     <xsl:text>    do_dispatch(value, oldval, varnum) {
  1790 </xsl:text>
  2215 </xsl:text>
  1791     <xsl:text>        let index = this.indexes[varnum];
  2216     <xsl:text>        if(this.dispatch) try {
  1792 </xsl:text>
  2217 </xsl:text>
  1793     <xsl:text>        if(typeof(index) == "string"){
  2218     <xsl:text>            this.dispatch(value, oldval, varnum);
  1794 </xsl:text>
  2219 </xsl:text>
  1795     <xsl:text>            index = page_local_index(index, this.container_id);
  2220     <xsl:text>        } catch(err) {
  1796 </xsl:text>
  2221 </xsl:text>
  1797     <xsl:text>        } else {
  2222     <xsl:text>            console.log(err);
  1798 </xsl:text>
       
  1799     <xsl:text>            if(this.relativeness[varnum]){
       
  1800 </xsl:text>
       
  1801     <xsl:text>                index += this.offset;
       
  1802 </xsl:text>
       
  1803     <xsl:text>            }
       
  1804 </xsl:text>
  2223 </xsl:text>
  1805     <xsl:text>        }
  2224     <xsl:text>        }
  1806 </xsl:text>
  2225 </xsl:text>
  1807     <xsl:text>        return index;
  2226     <xsl:text>        if(this.enable_expr) try {
  1808 </xsl:text>
  2227 </xsl:text>
  1809     <xsl:text>    }
  2228     <xsl:text>            this.compute_enable(value, oldval, varnum);
  1810 </xsl:text>
  2229 </xsl:text>
  1811     <xsl:text>
  2230     <xsl:text>        } catch(err) {
  1812 </xsl:text>
  2231 </xsl:text>
  1813     <xsl:text>    overshot(new_val, max) {
  2232     <xsl:text>            console.log(err);
  1814 </xsl:text>
       
  1815     <xsl:text>    }
       
  1816 </xsl:text>
       
  1817     <xsl:text>
       
  1818 </xsl:text>
       
  1819     <xsl:text>    undershot(new_val, min) {
       
  1820 </xsl:text>
       
  1821     <xsl:text>    }
       
  1822 </xsl:text>
       
  1823     <xsl:text>
       
  1824 </xsl:text>
       
  1825     <xsl:text>    clip_min_max(index, new_val) {
       
  1826 </xsl:text>
       
  1827     <xsl:text>        let minmax = this.minmaxes[index];
       
  1828 </xsl:text>
       
  1829     <xsl:text>        if(minmax !== undefined &amp;&amp; typeof new_val == "number") {
       
  1830 </xsl:text>
       
  1831     <xsl:text>            let [min,max] = minmax;
       
  1832 </xsl:text>
       
  1833     <xsl:text>            if(new_val &lt; min){
       
  1834 </xsl:text>
       
  1835     <xsl:text>                this.undershot(new_val, min);
       
  1836 </xsl:text>
       
  1837     <xsl:text>                return min;
       
  1838 </xsl:text>
       
  1839     <xsl:text>            }
       
  1840 </xsl:text>
       
  1841     <xsl:text>            if(new_val &gt; max){
       
  1842 </xsl:text>
       
  1843     <xsl:text>                this.overshot(new_val, max);
       
  1844 </xsl:text>
       
  1845     <xsl:text>                return max;
       
  1846 </xsl:text>
       
  1847     <xsl:text>            }
       
  1848 </xsl:text>
  2233 </xsl:text>
  1849     <xsl:text>        }
  2234     <xsl:text>        }
  1850 </xsl:text>
  2235 </xsl:text>
  1851     <xsl:text>        return new_val;
  2236     <xsl:text>    }
  1852 </xsl:text>
  2237 </xsl:text>
  1853     <xsl:text>    }
  2238     <xsl:text>
  1854 </xsl:text>
  2239 </xsl:text>
  1855     <xsl:text>
  2240     <xsl:text>    _animate(){
  1856 </xsl:text>
  2241 </xsl:text>
  1857     <xsl:text>    change_hmi_value(index, opstr) {
  2242     <xsl:text>        if(this.enable_expr)
  1858 </xsl:text>
  2243 </xsl:text>
  1859     <xsl:text>        let realindex = this.get_variable_index(index);
  2244     <xsl:text>            this.animate_enable();
  1860 </xsl:text>
  2245 </xsl:text>
  1861     <xsl:text>        if(realindex == undefined) return undefined;
  2246     <xsl:text>        // inhibit widget animation when disabled
  1862 </xsl:text>
  2247 </xsl:text>
  1863     <xsl:text>        let old_val = cache[realindex];
  2248     <xsl:text>        if(!this.enable_expr || this.enable_state){
  1864 </xsl:text>
  2249 </xsl:text>
  1865     <xsl:text>        let new_val = eval_operation_string(old_val, opstr);
  2250     <xsl:text>            if(this.has_activity)
  1866 </xsl:text>
  2251 </xsl:text>
  1867     <xsl:text>        if(this.clip)
  2252     <xsl:text>                this.animate_activity();
  1868 </xsl:text>
  2253 </xsl:text>
  1869     <xsl:text>            new_val = this.clip_min_max(index, new_val);
  2254     <xsl:text>            if(this.animate != undefined)
  1870 </xsl:text>
  2255 </xsl:text>
  1871     <xsl:text>        return apply_hmi_value(realindex, new_val);
  2256     <xsl:text>                this.animate();
  1872 </xsl:text>
       
  1873     <xsl:text>    }
       
  1874 </xsl:text>
       
  1875     <xsl:text>
       
  1876 </xsl:text>
       
  1877     <xsl:text>    _apply_hmi_value(index, new_val) {
       
  1878 </xsl:text>
       
  1879     <xsl:text>        let realindex = this.get_variable_index(index);
       
  1880 </xsl:text>
       
  1881     <xsl:text>        if(realindex == undefined) return undefined;
       
  1882 </xsl:text>
       
  1883     <xsl:text>        if(this.clip)
       
  1884 </xsl:text>
       
  1885     <xsl:text>            new_val = this.clip_min_max(index, new_val);
       
  1886 </xsl:text>
       
  1887     <xsl:text>        return apply_hmi_value(realindex, new_val);
       
  1888 </xsl:text>
       
  1889     <xsl:text>    }
       
  1890 </xsl:text>
       
  1891     <xsl:text>
       
  1892 </xsl:text>
       
  1893     <xsl:text>    uninhibit(index){
       
  1894 </xsl:text>
       
  1895     <xsl:text>        this.inhibit[index] = undefined;
       
  1896 </xsl:text>
       
  1897     <xsl:text>        let new_val = this.pending[index];
       
  1898 </xsl:text>
       
  1899     <xsl:text>        this.pending[index] = undefined;
       
  1900 </xsl:text>
       
  1901     <xsl:text>        return this.apply_hmi_value(index, new_val);
       
  1902 </xsl:text>
       
  1903     <xsl:text>    }
       
  1904 </xsl:text>
       
  1905     <xsl:text>
       
  1906 </xsl:text>
       
  1907     <xsl:text>    apply_hmi_value(index, new_val) {
       
  1908 </xsl:text>
       
  1909     <xsl:text>        if(this.inhibit[index] == undefined){
       
  1910 </xsl:text>
       
  1911     <xsl:text>            let now = Date.now();
       
  1912 </xsl:text>
       
  1913     <xsl:text>            let min_interval = 1000/this.frequency;
       
  1914 </xsl:text>
       
  1915     <xsl:text>            let lastapply = this.lastapply[index];
       
  1916 </xsl:text>
       
  1917     <xsl:text>            if(lastapply == undefined || now &gt; lastapply + min_interval){
       
  1918 </xsl:text>
       
  1919     <xsl:text>                this.lastapply[index] = now;
       
  1920 </xsl:text>
       
  1921     <xsl:text>                return this._apply_hmi_value(index, new_val);
       
  1922 </xsl:text>
       
  1923     <xsl:text>            }
       
  1924 </xsl:text>
       
  1925     <xsl:text>            else {
       
  1926 </xsl:text>
       
  1927     <xsl:text>                let elapsed = now - lastapply;
       
  1928 </xsl:text>
       
  1929     <xsl:text>                this.pending[index] = new_val;
       
  1930 </xsl:text>
       
  1931     <xsl:text>                this.inhibit[index] = setTimeout(this.bound_uninhibit, min_interval - elapsed, index);
       
  1932 </xsl:text>
       
  1933     <xsl:text>            }
       
  1934 </xsl:text>
  2257 </xsl:text>
  1935     <xsl:text>        }
  2258     <xsl:text>        }
  1936 </xsl:text>
  2259 </xsl:text>
  1937     <xsl:text>        else {
  2260     <xsl:text>        this.pending_animate = false;
  1938 </xsl:text>
  2261 </xsl:text>
  1939     <xsl:text>            this.pending[index] = new_val;
  2262     <xsl:text>    }
  1940 </xsl:text>
  2263 </xsl:text>
  1941     <xsl:text>            return new_val;
  2264     <xsl:text>
       
  2265 </xsl:text>
       
  2266     <xsl:text>    request_animate(){
       
  2267 </xsl:text>
       
  2268     <xsl:text>        if(!this.pending_animate){
       
  2269 </xsl:text>
       
  2270     <xsl:text>            pending_widget_animates.push(this);
       
  2271 </xsl:text>
       
  2272     <xsl:text>            this.pending_animate = true;
       
  2273 </xsl:text>
       
  2274     <xsl:text>            requestHMIAnimation();
  1942 </xsl:text>
  2275 </xsl:text>
  1943     <xsl:text>        }
  2276     <xsl:text>        }
  1944 </xsl:text>
  2277 </xsl:text>
  1945     <xsl:text>    }
  2278     <xsl:text>    }
  1946 </xsl:text>
  2279 </xsl:text>
  1947     <xsl:text>
  2280     <xsl:text>
  1948 </xsl:text>
  2281 </xsl:text>
  1949     <xsl:text>    new_hmi_value(index, value, oldval) {
  2282     <xsl:text>    animate_activity(){
  1950 </xsl:text>
  2283 </xsl:text>
  1951     <xsl:text>        // TODO avoid searching, store index at sub()
  2284     <xsl:text>        if(this.activity_displayed_state != this.activity_state){
  1952 </xsl:text>
  2285 </xsl:text>
  1953     <xsl:text>        for(let i = 0; i &lt; this.indexes.length; i++) {
  2286     <xsl:text>            set_activity_state(this.activable_sub, this.activity_state);
  1954 </xsl:text>
  2287 </xsl:text>
  1955     <xsl:text>            let refindex = this.get_variable_index(i);
  2288     <xsl:text>            this.activity_displayed_state = this.activity_state;
  1956 </xsl:text>
       
  1957     <xsl:text>            if(refindex == undefined) continue;
       
  1958 </xsl:text>
       
  1959     <xsl:text>
       
  1960 </xsl:text>
       
  1961     <xsl:text>            if(index == refindex) {
       
  1962 </xsl:text>
       
  1963     <xsl:text>                this._dispatch(value, oldval, i);
       
  1964 </xsl:text>
       
  1965     <xsl:text>                break;
       
  1966 </xsl:text>
       
  1967     <xsl:text>            }
       
  1968 </xsl:text>
  2289 </xsl:text>
  1969     <xsl:text>        }
  2290     <xsl:text>        }
  1970 </xsl:text>
       
  1971     <xsl:text>    }
       
  1972 </xsl:text>
       
  1973     <xsl:text>    
       
  1974 </xsl:text>
       
  1975     <xsl:text>    undeafen(index){
       
  1976 </xsl:text>
       
  1977     <xsl:text>        this.deafen[index] = undefined;
       
  1978 </xsl:text>
       
  1979     <xsl:text>        let [new_val, old_val] = this.incoming[index];
       
  1980 </xsl:text>
       
  1981     <xsl:text>        this.incoming[index] = undefined;
       
  1982 </xsl:text>
       
  1983     <xsl:text>        this.dispatch(new_val, old_val, index);
       
  1984 </xsl:text>
       
  1985     <xsl:text>    }
       
  1986 </xsl:text>
       
  1987     <xsl:text>
       
  1988 </xsl:text>
       
  1989     <xsl:text>    _dispatch(value, oldval, varnum) {
       
  1990 </xsl:text>
       
  1991     <xsl:text>        let dispatch = this.dispatch;
       
  1992 </xsl:text>
       
  1993     <xsl:text>        if(dispatch != undefined){
       
  1994 </xsl:text>
       
  1995     <xsl:text>            if(this.deafen[varnum] == undefined){
       
  1996 </xsl:text>
       
  1997     <xsl:text>                let now = Date.now();
       
  1998 </xsl:text>
       
  1999     <xsl:text>                let min_interval = 1000/this.frequency;
       
  2000 </xsl:text>
       
  2001     <xsl:text>                let lastdispatch = this.lastdispatch[varnum];
       
  2002 </xsl:text>
       
  2003     <xsl:text>                if(lastdispatch == undefined || now &gt; lastdispatch + min_interval){
       
  2004 </xsl:text>
       
  2005     <xsl:text>                    this.lastdispatch[varnum] = now;
       
  2006 </xsl:text>
       
  2007     <xsl:text>                    try {
       
  2008 </xsl:text>
       
  2009     <xsl:text>                        dispatch.call(this, value, oldval, varnum);
       
  2010 </xsl:text>
       
  2011     <xsl:text>                    } catch(err) {
       
  2012 </xsl:text>
       
  2013     <xsl:text>                        console.log(err);
       
  2014 </xsl:text>
       
  2015     <xsl:text>                    }
       
  2016 </xsl:text>
       
  2017     <xsl:text>                }
       
  2018 </xsl:text>
       
  2019     <xsl:text>                else {
       
  2020 </xsl:text>
       
  2021     <xsl:text>                    let elapsed = now - lastdispatch;
       
  2022 </xsl:text>
       
  2023     <xsl:text>                    this.incoming[varnum] = [value, oldval];
       
  2024 </xsl:text>
       
  2025     <xsl:text>                    this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum);
       
  2026 </xsl:text>
       
  2027     <xsl:text>                }
       
  2028 </xsl:text>
       
  2029     <xsl:text>            }
       
  2030 </xsl:text>
       
  2031     <xsl:text>            else {
       
  2032 </xsl:text>
       
  2033     <xsl:text>                this.incoming[varnum] = [value, oldval];
       
  2034 </xsl:text>
       
  2035     <xsl:text>            }
       
  2036 </xsl:text>
       
  2037     <xsl:text>        }
       
  2038 </xsl:text>
       
  2039     <xsl:text>    }
       
  2040 </xsl:text>
       
  2041     <xsl:text>
       
  2042 </xsl:text>
       
  2043     <xsl:text>    _animate(){
       
  2044 </xsl:text>
       
  2045     <xsl:text>        this.animate();
       
  2046 </xsl:text>
       
  2047     <xsl:text>        this.pending_animate = false;
       
  2048 </xsl:text>
       
  2049     <xsl:text>    }
       
  2050 </xsl:text>
       
  2051     <xsl:text>
       
  2052 </xsl:text>
       
  2053     <xsl:text>    request_animate(){
       
  2054 </xsl:text>
       
  2055     <xsl:text>        if(!this.pending_animate){
       
  2056 </xsl:text>
       
  2057     <xsl:text>            pending_widget_animates.push(this);
       
  2058 </xsl:text>
       
  2059     <xsl:text>            this.pending_animate = true;
       
  2060 </xsl:text>
       
  2061     <xsl:text>            requestHMIAnimation();
       
  2062 </xsl:text>
       
  2063     <xsl:text>        }
       
  2064 </xsl:text>
       
  2065     <xsl:text>    }
       
  2066 </xsl:text>
       
  2067     <xsl:text>
       
  2068 </xsl:text>
       
  2069     <xsl:text>    set_activation_state(state){
       
  2070 </xsl:text>
       
  2071     <xsl:text>        set_activation_state(this.activable_sub, state);
       
  2072 </xsl:text>
  2291 </xsl:text>
  2073     <xsl:text>    }
  2292     <xsl:text>    }
  2074 </xsl:text>
  2293 </xsl:text>
  2075     <xsl:text>}
  2294     <xsl:text>}
  2076 </xsl:text>
  2295 </xsl:text>
  2691     <xsl:apply-templates mode="actions" select="*"/>
  2910     <xsl:apply-templates mode="actions" select="*"/>
  2692     <xsl:text>    }
  2911     <xsl:text>    }
  2693 </xsl:text>
  2912 </xsl:text>
  2694   </xsl:template>
  2913   </xsl:template>
  2695   <xsl:template mode="actions" match="show">
  2914   <xsl:template mode="actions" match="show">
  2696     <xsl:text>        this.display = "</xsl:text>
  2915     <xsl:text>        this.activity_state = </xsl:text>
  2697     <xsl:value-of select="@eltname"/>
  2916     <xsl:value-of select="@eltname = 'active'"/>
  2698     <xsl:text>";
  2917     <xsl:text>;
  2699 </xsl:text>
  2918 </xsl:text>
  2700     <xsl:text>        this.request_animate();
  2919     <xsl:text>        this.request_animate();
  2701 </xsl:text>
  2920 </xsl:text>
  2702   </xsl:template>
  2921   </xsl:template>
  2703   <xsl:template mode="actions" match="hmi-value">
  2922   <xsl:template mode="actions" match="hmi-value">
  2706     <xsl:text>);
  2925     <xsl:text>);
  2707 </xsl:text>
  2926 </xsl:text>
  2708   </xsl:template>
  2927   </xsl:template>
  2709   <xsl:template name="generated_button_class">
  2928   <xsl:template name="generated_button_class">
  2710     <xsl:param name="fsm"/>
  2929     <xsl:param name="fsm"/>
  2711     <xsl:text>    display = "inactive";
       
  2712 </xsl:text>
       
  2713     <xsl:text>    state = "init";
  2930     <xsl:text>    state = "init";
  2714 </xsl:text>
  2931 </xsl:text>
  2715     <xsl:text>    dispatch(value) {
  2932     <xsl:text>    dispatch(value) {
  2716 </xsl:text>
  2933 </xsl:text>
  2717     <xsl:apply-templates mode="dispatch_transition" select="$fsm"/>
  2934     <xsl:apply-templates mode="dispatch_transition" select="$fsm"/>
  2734       <xsl:with-param name="position" select="'down'"/>
  2951       <xsl:with-param name="position" select="'down'"/>
  2735     </xsl:apply-templates>
  2952     </xsl:apply-templates>
  2736     <xsl:text>    }
  2953     <xsl:text>    }
  2737 </xsl:text>
  2954 </xsl:text>
  2738     <xsl:apply-templates mode="actions" select="$fsm"/>
  2955     <xsl:apply-templates mode="actions" select="$fsm"/>
  2739     <xsl:text>    animate(){
       
  2740 </xsl:text>
       
  2741     <xsl:text>        this.set_activation_state(this.display == "active");
       
  2742 </xsl:text>
       
  2743     <xsl:text>    }
       
  2744 </xsl:text>
       
  2745     <xsl:text>    init() {
  2956     <xsl:text>    init() {
  2746 </xsl:text>
  2957 </xsl:text>
  2747     <xsl:text>        this.bound_onmouseup = this.onmouseup.bind(this);
  2958     <xsl:text>        this.bound_onmouseup = this.onmouseup.bind(this);
  2748 </xsl:text>
  2959 </xsl:text>
  2749     <xsl:text>        this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
  2960     <xsl:text>        this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
  2750 </xsl:text>
  2961 </xsl:text>
  2751     <xsl:text>        this.set_activation_state(undefined);
  2962     <xsl:text>        this.activity_state = undefined;
  2752 </xsl:text>
  2963 </xsl:text>
  2753     <xsl:text>    }
  2964     <xsl:text>    }
  2754 </xsl:text>
  2965 </xsl:text>
  2755   </xsl:template>
  2966   </xsl:template>
  2756   <xsl:template match="widget[@type='Button']" mode="widget_class">
  2967   <xsl:template match="widget[@type='Button']" mode="widget_class">
  2767     <xsl:text>}
  2978     <xsl:text>}
  2768 </xsl:text>
  2979 </xsl:text>
  2769   </xsl:template>
  2980   </xsl:template>
  2770   <xsl:template match="widget[@type='Button']" mode="widget_defs">
  2981   <xsl:template match="widget[@type='Button']" mode="widget_defs">
  2771     <xsl:param name="hmi_element"/>
  2982     <xsl:param name="hmi_element"/>
       
  2983     <xsl:variable name="disability">
       
  2984       <xsl:call-template name="defs_by_labels">
       
  2985         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  2986         <xsl:with-param name="labels">
       
  2987           <xsl:text>/disabled</xsl:text>
       
  2988         </xsl:with-param>
       
  2989         <xsl:with-param name="mandatory" select="'no'"/>
       
  2990       </xsl:call-template>
       
  2991     </xsl:variable>
       
  2992     <xsl:value-of select="$disability"/>
       
  2993     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  2772     <xsl:text>    activable_sub:{
  2994     <xsl:text>    activable_sub:{
  2773 </xsl:text>
  2995 </xsl:text>
  2774     <xsl:call-template name="defs_by_labels">
  2996     <xsl:variable name="activity">
  2775       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2997       <xsl:call-template name="defs_by_labels">
  2776       <xsl:with-param name="labels">
  2998         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2777         <xsl:text>/active /inactive</xsl:text>
  2999         <xsl:with-param name="labels">
  2778       </xsl:with-param>
  3000           <xsl:text>/active /inactive</xsl:text>
  2779       <xsl:with-param name="mandatory" select="'warn'"/>
  3001         </xsl:with-param>
  2780     </xsl:call-template>
  3002         <xsl:with-param name="mandatory">
  2781     <xsl:text>    }
  3003           <xsl:text>warn</xsl:text>
       
  3004         </xsl:with-param>
       
  3005       </xsl:call-template>
       
  3006     </xsl:variable>
       
  3007     <xsl:value-of select="$activity"/>
       
  3008     <xsl:variable name="has_activity" select="string-length($activity)&gt;0"/>
       
  3009     <xsl:text>    },
       
  3010 </xsl:text>
       
  3011     <xsl:text>    has_activity: </xsl:text>
       
  3012     <xsl:value-of select="$has_activity"/>
       
  3013     <xsl:text>,
  2782 </xsl:text>
  3014 </xsl:text>
  2783   </xsl:template>
  3015   </xsl:template>
  2784   <xsl:template match="widget[@type='PushButton']" mode="widget_class">
  3016   <xsl:template match="widget[@type='PushButton']" mode="widget_class">
  2785     <xsl:text>class </xsl:text>
  3017     <xsl:text>class </xsl:text>
  2786     <xsl:text>PushButtonWidget</xsl:text>
  3018     <xsl:text>PushButtonWidget</xsl:text>
  2795     <xsl:text>}
  3027     <xsl:text>}
  2796 </xsl:text>
  3028 </xsl:text>
  2797   </xsl:template>
  3029   </xsl:template>
  2798   <xsl:template match="widget[@type='PushButton']" mode="widget_defs">
  3030   <xsl:template match="widget[@type='PushButton']" mode="widget_defs">
  2799     <xsl:param name="hmi_element"/>
  3031     <xsl:param name="hmi_element"/>
       
  3032     <xsl:variable name="disability">
       
  3033       <xsl:call-template name="defs_by_labels">
       
  3034         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  3035         <xsl:with-param name="labels">
       
  3036           <xsl:text>/disabled</xsl:text>
       
  3037         </xsl:with-param>
       
  3038         <xsl:with-param name="mandatory" select="'no'"/>
       
  3039       </xsl:call-template>
       
  3040     </xsl:variable>
       
  3041     <xsl:value-of select="$disability"/>
       
  3042     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  2800     <xsl:text>    activable_sub:{
  3043     <xsl:text>    activable_sub:{
  2801 </xsl:text>
  3044 </xsl:text>
  2802     <xsl:call-template name="defs_by_labels">
  3045     <xsl:variable name="activity">
  2803       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3046       <xsl:call-template name="defs_by_labels">
  2804       <xsl:with-param name="labels">
  3047         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2805         <xsl:text>/active /inactive</xsl:text>
  3048         <xsl:with-param name="labels">
  2806       </xsl:with-param>
  3049           <xsl:text>/active /inactive</xsl:text>
  2807       <xsl:with-param name="mandatory" select="'warn'"/>
  3050         </xsl:with-param>
  2808     </xsl:call-template>
  3051         <xsl:with-param name="mandatory">
  2809     <xsl:text>    }
  3052           <xsl:text>warn</xsl:text>
       
  3053         </xsl:with-param>
       
  3054       </xsl:call-template>
       
  3055     </xsl:variable>
       
  3056     <xsl:value-of select="$activity"/>
       
  3057     <xsl:variable name="has_activity" select="string-length($activity)&gt;0"/>
       
  3058     <xsl:text>    },
       
  3059 </xsl:text>
       
  3060     <xsl:text>    has_activity: </xsl:text>
       
  3061     <xsl:value-of select="$has_activity"/>
       
  3062     <xsl:text>,
  2810 </xsl:text>
  3063 </xsl:text>
  2811   </xsl:template>
  3064   </xsl:template>
  2812   <xsl:template match="widget[@type='CircularBar']" mode="widget_desc">
  3065   <xsl:template match="widget[@type='CircularBar']" mode="widget_desc">
  2813     <type>
  3066     <type>
  2814       <xsl:value-of select="@type"/>
  3067       <xsl:value-of select="@type"/>
  2946     <xsl:text>}
  3199     <xsl:text>}
  2947 </xsl:text>
  3200 </xsl:text>
  2948   </xsl:template>
  3201   </xsl:template>
  2949   <xsl:template match="widget[@type='CircularBar']" mode="widget_defs">
  3202   <xsl:template match="widget[@type='CircularBar']" mode="widget_defs">
  2950     <xsl:param name="hmi_element"/>
  3203     <xsl:param name="hmi_element"/>
       
  3204     <xsl:variable name="disability">
       
  3205       <xsl:call-template name="defs_by_labels">
       
  3206         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  3207         <xsl:with-param name="labels">
       
  3208           <xsl:text>/disabled</xsl:text>
       
  3209         </xsl:with-param>
       
  3210         <xsl:with-param name="mandatory" select="'no'"/>
       
  3211       </xsl:call-template>
       
  3212     </xsl:variable>
       
  3213     <xsl:value-of select="$disability"/>
       
  3214     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  2951     <xsl:call-template name="defs_by_labels">
  3215     <xsl:call-template name="defs_by_labels">
  2952       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3216       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2953       <xsl:with-param name="labels">
  3217       <xsl:with-param name="labels">
  2954         <xsl:text>path</xsl:text>
  3218         <xsl:text>path</xsl:text>
  2955       </xsl:with-param>
  3219       </xsl:with-param>
  3461     <xsl:text>}
  3725     <xsl:text>}
  3462 </xsl:text>
  3726 </xsl:text>
  3463   </xsl:template>
  3727   </xsl:template>
  3464   <xsl:template match="widget[@type='CircularSlider']" mode="widget_defs">
  3728   <xsl:template match="widget[@type='CircularSlider']" mode="widget_defs">
  3465     <xsl:param name="hmi_element"/>
  3729     <xsl:param name="hmi_element"/>
       
  3730     <xsl:variable name="disability">
       
  3731       <xsl:call-template name="defs_by_labels">
       
  3732         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  3733         <xsl:with-param name="labels">
       
  3734           <xsl:text>/disabled</xsl:text>
       
  3735         </xsl:with-param>
       
  3736         <xsl:with-param name="mandatory" select="'no'"/>
       
  3737       </xsl:call-template>
       
  3738     </xsl:variable>
       
  3739     <xsl:value-of select="$disability"/>
       
  3740     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  3466     <xsl:call-template name="defs_by_labels">
  3741     <xsl:call-template name="defs_by_labels">
  3467       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3742       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3468       <xsl:with-param name="labels">
  3743       <xsl:with-param name="labels">
  3469         <xsl:text>handle range</xsl:text>
  3744         <xsl:text>handle range</xsl:text>
  3470       </xsl:with-param>
  3745       </xsl:with-param>
  3541     <xsl:text>}
  3816     <xsl:text>}
  3542 </xsl:text>
  3817 </xsl:text>
  3543   </xsl:template>
  3818   </xsl:template>
  3544   <xsl:template match="widget[@type='CustomHtml']" mode="widget_defs">
  3819   <xsl:template match="widget[@type='CustomHtml']" mode="widget_defs">
  3545     <xsl:param name="hmi_element"/>
  3820     <xsl:param name="hmi_element"/>
       
  3821     <xsl:variable name="disability">
       
  3822       <xsl:call-template name="defs_by_labels">
       
  3823         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  3824         <xsl:with-param name="labels">
       
  3825           <xsl:text>/disabled</xsl:text>
       
  3826         </xsl:with-param>
       
  3827         <xsl:with-param name="mandatory" select="'no'"/>
       
  3828       </xsl:call-template>
       
  3829     </xsl:variable>
       
  3830     <xsl:value-of select="$disability"/>
       
  3831     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  3546     <xsl:call-template name="defs_by_labels">
  3832     <xsl:call-template name="defs_by_labels">
  3547       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3833       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3548       <xsl:with-param name="labels">
  3834       <xsl:with-param name="labels">
  3549         <xsl:text>container code</xsl:text>
  3835         <xsl:text>container code</xsl:text>
  3550       </xsl:with-param>
  3836       </xsl:with-param>
  3612     <xsl:text>}
  3898     <xsl:text>}
  3613 </xsl:text>
  3899 </xsl:text>
  3614   </xsl:template>
  3900   </xsl:template>
  3615   <xsl:template match="widget[@type='Display']" mode="widget_defs">
  3901   <xsl:template match="widget[@type='Display']" mode="widget_defs">
  3616     <xsl:param name="hmi_element"/>
  3902     <xsl:param name="hmi_element"/>
       
  3903     <xsl:variable name="disability">
       
  3904       <xsl:call-template name="defs_by_labels">
       
  3905         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  3906         <xsl:with-param name="labels">
       
  3907           <xsl:text>/disabled</xsl:text>
       
  3908         </xsl:with-param>
       
  3909         <xsl:with-param name="mandatory" select="'no'"/>
       
  3910       </xsl:call-template>
       
  3911     </xsl:variable>
       
  3912     <xsl:value-of select="$disability"/>
       
  3913     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  3617     <xsl:variable name="format">
  3914     <xsl:variable name="format">
  3618       <xsl:call-template name="defs_by_labels">
  3915       <xsl:call-template name="defs_by_labels">
  3619         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3916         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3620         <xsl:with-param name="labels">
  3917         <xsl:with-param name="labels">
  3621           <xsl:text>format</xsl:text>
  3918           <xsl:text>format</xsl:text>
  4418     <xsl:text>}
  4715     <xsl:text>}
  4419 </xsl:text>
  4716 </xsl:text>
  4420   </xsl:template>
  4717   </xsl:template>
  4421   <xsl:template match="widget[@type='DropDown']" mode="widget_defs">
  4718   <xsl:template match="widget[@type='DropDown']" mode="widget_defs">
  4422     <xsl:param name="hmi_element"/>
  4719     <xsl:param name="hmi_element"/>
       
  4720     <xsl:variable name="disability">
       
  4721       <xsl:call-template name="defs_by_labels">
       
  4722         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  4723         <xsl:with-param name="labels">
       
  4724           <xsl:text>/disabled</xsl:text>
       
  4725         </xsl:with-param>
       
  4726         <xsl:with-param name="mandatory" select="'no'"/>
       
  4727       </xsl:call-template>
       
  4728     </xsl:variable>
       
  4729     <xsl:value-of select="$disability"/>
       
  4730     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  4423     <xsl:call-template name="defs_by_labels">
  4731     <xsl:call-template name="defs_by_labels">
  4424       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  4732       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  4425       <xsl:with-param name="labels">
  4733       <xsl:with-param name="labels">
  4426         <xsl:text>box button highlight</xsl:text>
  4734         <xsl:text>box button highlight</xsl:text>
  4427       </xsl:with-param>
  4735       </xsl:with-param>
  4556       <xsl:text> where to find HMI_NODEs whose HMI_CLASS is class_name</xsl:text>
  4864       <xsl:text> where to find HMI_NODEs whose HMI_CLASS is class_name</xsl:text>
  4557     </path>
  4865     </path>
  4558   </xsl:template>
  4866   </xsl:template>
  4559   <xsl:template match="widget[@type='ForEach']" mode="widget_defs">
  4867   <xsl:template match="widget[@type='ForEach']" mode="widget_defs">
  4560     <xsl:param name="hmi_element"/>
  4868     <xsl:param name="hmi_element"/>
       
  4869     <xsl:variable name="disability">
       
  4870       <xsl:call-template name="defs_by_labels">
       
  4871         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  4872         <xsl:with-param name="labels">
       
  4873           <xsl:text>/disabled</xsl:text>
       
  4874         </xsl:with-param>
       
  4875         <xsl:with-param name="mandatory" select="'no'"/>
       
  4876       </xsl:call-template>
       
  4877     </xsl:variable>
       
  4878     <xsl:value-of select="$disability"/>
       
  4879     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  4561     <xsl:if test="count(path) != 1">
  4880     <xsl:if test="count(path) != 1">
  4562       <xsl:message terminate="yes">
  4881       <xsl:message terminate="yes">
  4563         <xsl:text>ForEach widget </xsl:text>
  4882         <xsl:text>ForEach widget </xsl:text>
  4564         <xsl:value-of select="$hmi_element/@id"/>
  4883         <xsl:value-of select="$hmi_element/@id"/>
  4565         <xsl:text> must have one HMI path given.</xsl:text>
  4884         <xsl:text> must have one HMI path given.</xsl:text>
  4795 </xsl:text>
  5114 </xsl:text>
  4796     <xsl:text>        this.sub_items();
  5115     <xsl:text>        this.sub_items();
  4797 </xsl:text>
  5116 </xsl:text>
  4798     <xsl:text>        update_subscriptions();
  5117     <xsl:text>        update_subscriptions();
  4799 </xsl:text>
  5118 </xsl:text>
  4800     <xsl:text>        need_cache_apply.push(this);
  5119     <xsl:text>        this.apply_cache(); 
  4801 </xsl:text>
  5120 </xsl:text>
  4802     <xsl:text>        jumps_need_update = true;
  5121     <xsl:text>        jumps_need_update = true;
  4803 </xsl:text>
  5122 </xsl:text>
  4804     <xsl:text>        requestHMIAnimation();
  5123     <xsl:text>        requestHMIAnimation();
  4805 </xsl:text>
  5124 </xsl:text>
  4908     <xsl:text>}
  5227     <xsl:text>}
  4909 </xsl:text>
  5228 </xsl:text>
  4910   </xsl:template>
  5229   </xsl:template>
  4911   <xsl:template match="widget[@type='Input']" mode="widget_defs">
  5230   <xsl:template match="widget[@type='Input']" mode="widget_defs">
  4912     <xsl:param name="hmi_element"/>
  5231     <xsl:param name="hmi_element"/>
       
  5232     <xsl:variable name="disability">
       
  5233       <xsl:call-template name="defs_by_labels">
       
  5234         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  5235         <xsl:with-param name="labels">
       
  5236           <xsl:text>/disabled</xsl:text>
       
  5237         </xsl:with-param>
       
  5238         <xsl:with-param name="mandatory" select="'no'"/>
       
  5239       </xsl:call-template>
       
  5240     </xsl:variable>
       
  5241     <xsl:value-of select="$disability"/>
       
  5242     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  4913     <xsl:variable name="value_elt">
  5243     <xsl:variable name="value_elt">
  4914       <xsl:call-template name="defs_by_labels">
  5244       <xsl:call-template name="defs_by_labels">
  4915         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5245         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  4916         <xsl:with-param name="labels">
  5246         <xsl:with-param name="labels">
  4917           <xsl:text>value</xsl:text>
  5247           <xsl:text>value</xsl:text>
  5439     <xsl:text>        }
  5769     <xsl:text>        }
  5440 </xsl:text>
  5770 </xsl:text>
  5441   </xsl:template>
  5771   </xsl:template>
  5442   <xsl:template match="widget[@type='JsonTable']" mode="widget_defs">
  5772   <xsl:template match="widget[@type='JsonTable']" mode="widget_defs">
  5443     <xsl:param name="hmi_element"/>
  5773     <xsl:param name="hmi_element"/>
       
  5774     <xsl:variable name="disability">
       
  5775       <xsl:call-template name="defs_by_labels">
       
  5776         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  5777         <xsl:with-param name="labels">
       
  5778           <xsl:text>/disabled</xsl:text>
       
  5779         </xsl:with-param>
       
  5780         <xsl:with-param name="mandatory" select="'no'"/>
       
  5781       </xsl:call-template>
       
  5782     </xsl:variable>
       
  5783     <xsl:value-of select="$disability"/>
       
  5784     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  5444     <xsl:call-template name="defs_by_labels">
  5785     <xsl:call-template name="defs_by_labels">
  5445       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5786       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5446       <xsl:with-param name="labels">
  5787       <xsl:with-param name="labels">
  5447         <xsl:text>data</xsl:text>
  5788         <xsl:text>data</xsl:text>
  5448       </xsl:with-param>
  5789       </xsl:with-param>
  5488   <xsl:template match="widget[@type='Jump']" mode="widget_desc">
  5829   <xsl:template match="widget[@type='Jump']" mode="widget_desc">
  5489     <type>
  5830     <type>
  5490       <xsl:value-of select="@type"/>
  5831       <xsl:value-of select="@type"/>
  5491     </type>
  5832     </type>
  5492     <longdesc>
  5833     <longdesc>
  5493       <xsl:text>Jump widget brings focus to a different page. Mandatory single argument
  5834       <xsl:text>Jump widget brings focus to a different page. Mandatory first argument
  5494 </xsl:text>
  5835 </xsl:text>
  5495       <xsl:text>gives name of the page.
  5836       <xsl:text>gives name of the page.
  5496 </xsl:text>
  5837 </xsl:text>
  5497       <xsl:text>
  5838       <xsl:text>
  5498 </xsl:text>
  5839 </xsl:text>
  5499       <xsl:text>Optional single path is used as new reference when jumping to a relative
  5840       <xsl:text>If first path is pointint to HMI_NODE variable is used as new reference
  5500 </xsl:text>
  5841 </xsl:text>
  5501       <xsl:text>page, it must point to a HMI_NODE.
  5842       <xsl:text>when jumping to a relative page.
  5502 </xsl:text>
  5843 </xsl:text>
  5503       <xsl:text>
  5844       <xsl:text>
  5504 </xsl:text>
  5845 </xsl:text>
       
  5846       <xsl:text>Additional arguments are unordered options:
       
  5847 </xsl:text>
       
  5848       <xsl:text>
       
  5849 </xsl:text>
       
  5850       <xsl:text>- Absolute: force page jump to be not relative even if first path is of type HMI_NODE
       
  5851 </xsl:text>
       
  5852       <xsl:text>
       
  5853 </xsl:text>
       
  5854       <xsl:text>- name=value: Notify PLC about jump by setting variable with path having same name assigned
       
  5855 </xsl:text>
       
  5856       <xsl:text>
       
  5857 </xsl:text>
  5505       <xsl:text>"active"+"inactive" labeled elements can be provided and reflect current
  5858       <xsl:text>"active"+"inactive" labeled elements can be provided and reflect current
  5506 </xsl:text>
  5859 </xsl:text>
  5507       <xsl:text>page being shown.
  5860       <xsl:text>page being shown.
  5508 </xsl:text>
  5861 </xsl:text>
  5509       <xsl:text>
  5862       <xsl:text>
  5510 </xsl:text>
  5863 </xsl:text>
  5511       <xsl:text>"disabled" labeled element, if provided, is shown instead of "active" or
  5864       <xsl:text>Exemples:
  5512 </xsl:text>
  5865 </xsl:text>
  5513       <xsl:text>"inactive" widget when pointed HMI_NODE is null.
  5866       <xsl:text>
       
  5867 </xsl:text>
       
  5868       <xsl:text>Relative jump:
       
  5869 </xsl:text>
       
  5870       <xsl:text>
       
  5871 </xsl:text>
       
  5872       <xsl:text>HMI:Jump:RelativePage@/PUMP9
       
  5873 </xsl:text>
       
  5874       <xsl:text>HMI:Jump:RelativePage@/PUMP9@role=.userrole#role=="admin"
       
  5875 </xsl:text>
       
  5876       <xsl:text>
       
  5877 </xsl:text>
       
  5878       <xsl:text>Absolute jump:
       
  5879 </xsl:text>
       
  5880       <xsl:text>
       
  5881 </xsl:text>
       
  5882       <xsl:text>HMI:Jump:AbsolutePage
       
  5883 </xsl:text>
       
  5884       <xsl:text>HMI:Jump:AbsolutePage@role=.userrole#role=="admin"
       
  5885 </xsl:text>
       
  5886       <xsl:text>
       
  5887 </xsl:text>
       
  5888       <xsl:text>Forced absolute jump:
       
  5889 </xsl:text>
       
  5890       <xsl:text>
       
  5891 </xsl:text>
       
  5892       <xsl:text>HMI:Jump:AbsolutePage:Absolute@/PUMP9
       
  5893 </xsl:text>
       
  5894       <xsl:text>HMI:Jump:AbsolutePage:Absolute:notify=1@notify=/PUMP9
       
  5895 </xsl:text>
       
  5896       <xsl:text>
       
  5897 </xsl:text>
       
  5898       <xsl:text>Jump with feedback
       
  5899 </xsl:text>
       
  5900       <xsl:text>
       
  5901 </xsl:text>
       
  5902       <xsl:text>HMI:Jump:AbsolutePage:notify=1@notify=.did_jump
       
  5903 </xsl:text>
       
  5904       <xsl:text>
  5514 </xsl:text>
  5905 </xsl:text>
  5515     </longdesc>
  5906     </longdesc>
  5516     <shortdesc>
  5907     <shortdesc>
  5517       <xsl:text>Jump to given page</xsl:text>
  5908       <xsl:text>Jump to given page</xsl:text>
  5518     </shortdesc>
  5909     </shortdesc>
  5528     <xsl:text>JumpWidget</xsl:text>
  5919     <xsl:text>JumpWidget</xsl:text>
  5529     <xsl:text> extends Widget{
  5920     <xsl:text> extends Widget{
  5530 </xsl:text>
  5921 </xsl:text>
  5531     <xsl:text>        activable = false;
  5922     <xsl:text>        activable = false;
  5532 </xsl:text>
  5923 </xsl:text>
  5533     <xsl:text>        active = false;
       
  5534 </xsl:text>
       
  5535     <xsl:text>        disabled = false;
       
  5536 </xsl:text>
       
  5537     <xsl:text>        frequency = 2;
  5924     <xsl:text>        frequency = 2;
  5538 </xsl:text>
  5925 </xsl:text>
  5539     <xsl:text>
  5926     <xsl:text>
  5540 </xsl:text>
  5927 </xsl:text>
  5541     <xsl:text>        update_activity() {
  5928     <xsl:text>        make_on_click() {
  5542 </xsl:text>
  5929 </xsl:text>
  5543     <xsl:text>            if(this.active) {
  5930     <xsl:text>            let that = this;
  5544 </xsl:text>
  5931 </xsl:text>
  5545     <xsl:text>                 /* show active */ 
  5932     <xsl:text>            const name = this.args[0];
  5546 </xsl:text>
  5933 </xsl:text>
  5547     <xsl:text>                 this.active_elt.style.display = "";
  5934     <xsl:text>            return function(evt){
  5548 </xsl:text>
  5935 </xsl:text>
  5549     <xsl:text>                 /* hide inactive */ 
  5936     <xsl:text>                /* TODO: in order to allow jumps to page selected through
  5550 </xsl:text>
  5937 </xsl:text>
  5551     <xsl:text>                 this.inactive_elt.style.display = "none";
  5938     <xsl:text>                   for exemple a dropdown, support path pointing to local
  5552 </xsl:text>
  5939 </xsl:text>
  5553     <xsl:text>            } else {
  5940     <xsl:text>                   variable whom value would be an HMI_TREE index and then
  5554 </xsl:text>
  5941 </xsl:text>
  5555     <xsl:text>                 /* show inactive */ 
  5942     <xsl:text>                   jump to a relative page not hard-coded in advance
  5556 </xsl:text>
  5943 </xsl:text>
  5557     <xsl:text>                 this.inactive_elt.style.display = "";
  5944     <xsl:text>                */
  5558 </xsl:text>
  5945 </xsl:text>
  5559     <xsl:text>                 /* hide active */ 
  5946     <xsl:text>                if(that.enable_state) {
  5560 </xsl:text>
  5947 </xsl:text>
  5561     <xsl:text>                 this.active_elt.style.display = "none";
  5948     <xsl:text>                    const index =
       
  5949 </xsl:text>
       
  5950     <xsl:text>                        (that.is_relative &amp;&amp; that.indexes.length &gt; 0) ?
       
  5951 </xsl:text>
       
  5952     <xsl:text>                        that.indexes[0] + that.offset : undefined;
       
  5953 </xsl:text>
       
  5954     <xsl:text>                    fading_page_switch(name, index);
       
  5955 </xsl:text>
       
  5956     <xsl:text>                    that.notify();
       
  5957 </xsl:text>
       
  5958     <xsl:text>                }
  5562 </xsl:text>
  5959 </xsl:text>
  5563     <xsl:text>            }
  5960     <xsl:text>            }
  5564 </xsl:text>
  5961 </xsl:text>
  5565     <xsl:text>        }
  5962     <xsl:text>        }
  5566 </xsl:text>
  5963 </xsl:text>
  5567     <xsl:text>
  5964     <xsl:text>
  5568 </xsl:text>
  5965 </xsl:text>
  5569     <xsl:text>        update_disability() {
  5966     <xsl:text>        notify_page_change(page_name, index) {
  5570 </xsl:text>
  5967 </xsl:text>
  5571     <xsl:text>            if(this.disabled) {
  5968     <xsl:text>            // called from animate()
  5572 </xsl:text>
  5969 </xsl:text>
  5573     <xsl:text>                /* show disabled */ 
  5970     <xsl:text>            if(this.activable) {
  5574 </xsl:text>
  5971 </xsl:text>
  5575     <xsl:text>                this.disabled_elt.style.display = "";
  5972     <xsl:text>                const ref_index = this.indexes.length &gt; 0 ? this.indexes[0] + this.offset : undefined;
  5576 </xsl:text>
  5973 </xsl:text>
  5577     <xsl:text>                /* hide inactive */ 
  5974     <xsl:text>                const ref_name = this.args[0];
  5578 </xsl:text>
  5975 </xsl:text>
  5579     <xsl:text>                this.inactive_elt.style.display = "none";
  5976     <xsl:text>                this.activity_state = ((ref_name == undefined || ref_name == page_name) &amp;&amp; index == ref_index);
  5580 </xsl:text>
  5977 </xsl:text>
  5581     <xsl:text>                /* hide active */ 
  5978     <xsl:text>                // Since called from animate, update activity directly
  5582 </xsl:text>
  5979 </xsl:text>
  5583     <xsl:text>                this.active_elt.style.display = "none";
  5980     <xsl:text>                if(this.enable_displayed_state &amp;&amp; this.has_activity) {
  5584 </xsl:text>
  5981 </xsl:text>
  5585     <xsl:text>            } else {
  5982     <xsl:text>                    this.animate_activity();
  5586 </xsl:text>
  5983 </xsl:text>
  5587     <xsl:text>                /* hide disabled */ 
  5984     <xsl:text>                }
  5588 </xsl:text>
       
  5589     <xsl:text>                this.disabled_elt.style.display = "none";
       
  5590 </xsl:text>
       
  5591     <xsl:text>                this.update_activity();
       
  5592 </xsl:text>
  5985 </xsl:text>
  5593     <xsl:text>            }
  5986     <xsl:text>            }
  5594 </xsl:text>
  5987 </xsl:text>
  5595     <xsl:text>        }
  5988     <xsl:text>        }
  5596 </xsl:text>
  5989 </xsl:text>
  5597     <xsl:text>
       
  5598 </xsl:text>
       
  5599     <xsl:text>        make_on_click() {
       
  5600 </xsl:text>
       
  5601     <xsl:text>            let that = this;
       
  5602 </xsl:text>
       
  5603     <xsl:text>            const name = this.args[0];
       
  5604 </xsl:text>
       
  5605     <xsl:text>            return function(evt){
       
  5606 </xsl:text>
       
  5607     <xsl:text>                /* TODO: in order to allow jumps to page selected through for exemple a dropdown,
       
  5608 </xsl:text>
       
  5609     <xsl:text>                   support path pointing to local variable whom value 
       
  5610 </xsl:text>
       
  5611     <xsl:text>                   would be an HMI_TREE index and then jump to a relative page not hard-coded in advance */
       
  5612 </xsl:text>
       
  5613     <xsl:text>                if(!that.disabled) {
       
  5614 </xsl:text>
       
  5615     <xsl:text>                    const index = that.indexes.length &gt; 0 ? that.indexes[0] + that.offset : undefined;
       
  5616 </xsl:text>
       
  5617     <xsl:text>                    fading_page_switch(name, index);
       
  5618 </xsl:text>
       
  5619     <xsl:text>                }
       
  5620 </xsl:text>
       
  5621     <xsl:text>            }
       
  5622 </xsl:text>
       
  5623     <xsl:text>        }
       
  5624 </xsl:text>
       
  5625     <xsl:text>
       
  5626 </xsl:text>
       
  5627     <xsl:text>        notify_page_change(page_name, index) {
       
  5628 </xsl:text>
       
  5629     <xsl:text>            if(this.activable) {
       
  5630 </xsl:text>
       
  5631     <xsl:text>                const ref_index = this.indexes.length &gt; 0 ? this.indexes[0] + this.offset : undefined;
       
  5632 </xsl:text>
       
  5633     <xsl:text>                const ref_name = this.args[0];
       
  5634 </xsl:text>
       
  5635     <xsl:text>                this.active = ((ref_name == undefined || ref_name == page_name) &amp;&amp; index == ref_index);
       
  5636 </xsl:text>
       
  5637     <xsl:text>                this.update_state();
       
  5638 </xsl:text>
       
  5639     <xsl:text>            }
       
  5640 </xsl:text>
       
  5641     <xsl:text>        }
       
  5642 </xsl:text>
       
  5643     <xsl:text>
       
  5644 </xsl:text>
       
  5645     <xsl:text>        dispatch(value) {
       
  5646 </xsl:text>
       
  5647     <xsl:text>            this.disabled = !Number(value);
       
  5648 </xsl:text>
       
  5649     <xsl:text>
       
  5650 </xsl:text>
       
  5651     <xsl:text>            // TODO : use RequestAnimate and animate()
       
  5652 </xsl:text>
       
  5653     <xsl:text>
       
  5654 </xsl:text>
       
  5655     <xsl:text>            this.update_state();
       
  5656 </xsl:text>
       
  5657     <xsl:text>        }
       
  5658 </xsl:text>
       
  5659     <xsl:text>}
  5990     <xsl:text>}
  5660 </xsl:text>
  5991 </xsl:text>
  5661   </xsl:template>
  5992   </xsl:template>
       
  5993   <func:function name="func:is_relative_jump">
       
  5994     <xsl:param name="widget"/>
       
  5995     <func:result select="$widget/path and $widget/path[1]/@type='HMI_NODE' and not($widget/arg[position()&gt;1 and @value = 'Absolute'])"/>
       
  5996   </func:function>
  5662   <xsl:template match="widget[@type='Jump']" mode="widget_defs">
  5997   <xsl:template match="widget[@type='Jump']" mode="widget_defs">
  5663     <xsl:param name="hmi_element"/>
  5998     <xsl:param name="hmi_element"/>
       
  5999     <xsl:variable name="disability">
       
  6000       <xsl:call-template name="defs_by_labels">
       
  6001         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6002         <xsl:with-param name="labels">
       
  6003           <xsl:text>/disabled</xsl:text>
       
  6004         </xsl:with-param>
       
  6005         <xsl:with-param name="mandatory" select="'no'"/>
       
  6006       </xsl:call-template>
       
  6007     </xsl:variable>
       
  6008     <xsl:value-of select="$disability"/>
       
  6009     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
       
  6010     <xsl:text>    activable_sub:{
       
  6011 </xsl:text>
  5664     <xsl:variable name="activity">
  6012     <xsl:variable name="activity">
  5665       <xsl:call-template name="defs_by_labels">
  6013       <xsl:call-template name="defs_by_labels">
  5666         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6014         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5667         <xsl:with-param name="labels">
  6015         <xsl:with-param name="labels">
  5668           <xsl:text>active inactive</xsl:text>
  6016           <xsl:text>/active /inactive</xsl:text>
  5669         </xsl:with-param>
  6017         </xsl:with-param>
  5670         <xsl:with-param name="mandatory" select="'no'"/>
  6018         <xsl:with-param name="mandatory">
       
  6019           <xsl:text>no</xsl:text>
       
  6020         </xsl:with-param>
  5671       </xsl:call-template>
  6021       </xsl:call-template>
  5672     </xsl:variable>
  6022     </xsl:variable>
  5673     <xsl:variable name="have_activity" select="string-length($activity)&gt;0"/>
       
  5674     <xsl:value-of select="$activity"/>
  6023     <xsl:value-of select="$activity"/>
  5675     <xsl:variable name="disability">
  6024     <xsl:variable name="has_activity" select="string-length($activity)&gt;0"/>
  5676       <xsl:call-template name="defs_by_labels">
  6025     <xsl:text>    },
  5677         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6026 </xsl:text>
  5678         <xsl:with-param name="labels">
  6027     <xsl:text>    has_activity: </xsl:text>
  5679           <xsl:text>disabled</xsl:text>
  6028     <xsl:value-of select="$has_activity"/>
  5680         </xsl:with-param>
  6029     <xsl:text>,
  5681         <xsl:with-param name="mandatory" select="'no'"/>
  6030 </xsl:text>
  5682       </xsl:call-template>
  6031     <xsl:variable name="jump_disability" select="$has_activity and $has_disability"/>
  5683     </xsl:variable>
       
  5684     <xsl:variable name="have_disability" select="$have_activity and string-length($disability)&gt;0"/>
       
  5685     <xsl:value-of select="$disability"/>
       
  5686     <xsl:text>    init: function() {
  6032     <xsl:text>    init: function() {
  5687 </xsl:text>
  6033 </xsl:text>
  5688     <xsl:text>        this.element.onclick = this.make_on_click();
  6034     <xsl:text>        this.element.onclick = this.make_on_click();
  5689 </xsl:text>
  6035 </xsl:text>
  5690     <xsl:if test="$have_activity">
  6036     <xsl:if test="$has_activity">
  5691       <xsl:text>        this.activable = true;
  6037       <xsl:text>        this.activable = true;
  5692 </xsl:text>
  6038 </xsl:text>
  5693     </xsl:if>
  6039     </xsl:if>
  5694     <xsl:if test="not($have_disability)">
  6040     <xsl:text>        this.is_relative = </xsl:text>
  5695       <xsl:text>        this.unsubscribable = true;
       
  5696 </xsl:text>
       
  5697     </xsl:if>
       
  5698     <xsl:text>        this.update_state = </xsl:text>
       
  5699     <xsl:choose>
  6041     <xsl:choose>
  5700       <xsl:when test="$have_disability">
  6042       <xsl:when test="func:is_relative_jump(.)">
  5701         <xsl:text>this.update_disability</xsl:text>
  6043         <xsl:text>true</xsl:text>
  5702       </xsl:when>
       
  5703       <xsl:when test="$have_activity">
       
  5704         <xsl:text>this.update_activity</xsl:text>
       
  5705       </xsl:when>
  6044       </xsl:when>
  5706       <xsl:otherwise>
  6045       <xsl:otherwise>
  5707         <xsl:text>null</xsl:text>
  6046         <xsl:text>false</xsl:text>
  5708       </xsl:otherwise>
  6047       </xsl:otherwise>
  5709     </xsl:choose>
  6048     </xsl:choose>
  5710     <xsl:text>;
  6049     <xsl:text>;
  5711 </xsl:text>
  6050 </xsl:text>
  5712     <xsl:text>    },
  6051     <xsl:text>    },
  5713 </xsl:text>
  6052 </xsl:text>
       
  6053     <xsl:text>    notify: function() {
       
  6054 </xsl:text>
       
  6055     <xsl:variable name="paths" select="path"/>
       
  6056     <xsl:for-each select="arg[position()&gt;1 and contains(@value,'=')]">
       
  6057       <xsl:variable name="name" select="substring-before(@value,'=')"/>
       
  6058       <xsl:variable name="value" select="substring-after(@value,'=')"/>
       
  6059       <xsl:variable name="index">
       
  6060         <xsl:for-each select="$paths">
       
  6061           <xsl:if test="@assign = $name">
       
  6062             <xsl:value-of select="position()-1"/>
       
  6063           </xsl:if>
       
  6064         </xsl:for-each>
       
  6065       </xsl:variable>
       
  6066       <xsl:text>        // </xsl:text>
       
  6067       <xsl:value-of select="@value"/>
       
  6068       <xsl:text>
       
  6069 </xsl:text>
       
  6070       <xsl:text>        this.apply_hmi_value(</xsl:text>
       
  6071       <xsl:value-of select="$index"/>
       
  6072       <xsl:text>, </xsl:text>
       
  6073       <xsl:value-of select="$value"/>
       
  6074       <xsl:text>);
       
  6075 </xsl:text>
       
  6076     </xsl:for-each>
       
  6077     <xsl:text>    },
       
  6078 </xsl:text>
  5714   </xsl:template>
  6079   </xsl:template>
  5715   <xsl:template match="widget[@type='Jump']" mode="widget_page">
  6080   <xsl:template match="widget[@type='Jump']" mode="widget_page">
  5716     <xsl:param name="page_desc"/>
  6081     <xsl:param name="page_desc"/>
  5717     <xsl:param name="page_desc"/>
  6082     <xsl:param name="page_desc"/>
  5718     <xsl:if test="path">
  6083     <xsl:if test="func:is_relative_jump(.)">
  5719       <xsl:variable name="target_page_name">
  6084       <xsl:variable name="target_page_name">
  5720         <xsl:choose>
  6085         <xsl:choose>
  5721           <xsl:when test="arg">
  6086           <xsl:when test="arg">
  5722             <xsl:value-of select="arg[1]/@value"/>
  6087             <xsl:value-of select="arg[1]/@value"/>
  5723           </xsl:when>
  6088           </xsl:when>
  5798 </xsl:text>
  6163 </xsl:text>
  5799     <xsl:text>
  6164     <xsl:text>
  5800 </xsl:text>
  6165 </xsl:text>
  5801     <xsl:text>function update_jumps() {
  6166     <xsl:text>function update_jumps() {
  5802 </xsl:text>
  6167 </xsl:text>
       
  6168     <xsl:text>    // called from animate()
       
  6169 </xsl:text>
  5803     <xsl:text>    page_desc[current_visible_page].jumps.map(w=&gt;w.notify_page_change(current_visible_page,current_page_index));
  6170     <xsl:text>    page_desc[current_visible_page].jumps.map(w=&gt;w.notify_page_change(current_visible_page,current_page_index));
  5804 </xsl:text>
  6171 </xsl:text>
  5805     <xsl:text>    jumps_need_update = false;
  6172     <xsl:text>    jumps_need_update = false;
  5806 </xsl:text>
  6173 </xsl:text>
  5807     <xsl:text>};
  6174     <xsl:text>};
  6046 </xsl:text>
  6413 </xsl:text>
  6047     <xsl:text>         if(this.Shift_sub &amp;&amp; this.shift != this._shift){
  6414     <xsl:text>         if(this.Shift_sub &amp;&amp; this.shift != this._shift){
  6048 </xsl:text>
  6415 </xsl:text>
  6049     <xsl:text>             this._shift = this.shift;
  6416     <xsl:text>             this._shift = this.shift;
  6050 </xsl:text>
  6417 </xsl:text>
  6051     <xsl:text>             set_activation_state(this.Shift_sub, this.shift);
  6418     <xsl:text>             set_activity_state(this.Shift_sub, this.shift);
  6052 </xsl:text>
  6419 </xsl:text>
  6053     <xsl:text>         }
  6420     <xsl:text>         }
  6054 </xsl:text>
  6421 </xsl:text>
  6055     <xsl:text>         if(this.CapsLock_sub &amp;&amp; this.caps != this._caps){
  6422     <xsl:text>         if(this.CapsLock_sub &amp;&amp; this.caps != this._caps){
  6056 </xsl:text>
  6423 </xsl:text>
  6057     <xsl:text>             this._caps = this.caps;
  6424     <xsl:text>             this._caps = this.caps;
  6058 </xsl:text>
  6425 </xsl:text>
  6059     <xsl:text>             set_activation_state(this.CapsLock_sub, this.caps);
  6426     <xsl:text>             set_activity_state(this.CapsLock_sub, this.caps);
  6060 </xsl:text>
  6427 </xsl:text>
  6061     <xsl:text>         }
  6428     <xsl:text>         }
  6062 </xsl:text>
  6429 </xsl:text>
  6063     <xsl:text>     }
  6430     <xsl:text>     }
  6064 </xsl:text>
  6431 </xsl:text>
  6065     <xsl:text>}
  6432     <xsl:text>}
  6066 </xsl:text>
  6433 </xsl:text>
  6067   </xsl:template>
  6434   </xsl:template>
  6068   <xsl:template match="widget[@type='Keypad']" mode="widget_defs">
  6435   <xsl:template match="widget[@type='Keypad']" mode="widget_defs">
  6069     <xsl:param name="hmi_element"/>
  6436     <xsl:param name="hmi_element"/>
       
  6437     <xsl:variable name="disability">
       
  6438       <xsl:call-template name="defs_by_labels">
       
  6439         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6440         <xsl:with-param name="labels">
       
  6441           <xsl:text>/disabled</xsl:text>
       
  6442         </xsl:with-param>
       
  6443         <xsl:with-param name="mandatory" select="'no'"/>
       
  6444       </xsl:call-template>
       
  6445     </xsl:variable>
       
  6446     <xsl:value-of select="$disability"/>
       
  6447     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6070     <xsl:call-template name="defs_by_labels">
  6448     <xsl:call-template name="defs_by_labels">
  6071       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6449       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6072       <xsl:with-param name="labels">
  6450       <xsl:with-param name="labels">
  6073         <xsl:text>Esc Enter BackSpace Keys Value</xsl:text>
  6451         <xsl:text>Esc Enter BackSpace Keys Value</xsl:text>
  6074       </xsl:with-param>
  6452       </xsl:with-param>
  6157     </shortdesc>
  6535     </shortdesc>
  6158     <arg name="listname"/>
  6536     <arg name="listname"/>
  6159   </xsl:template>
  6537   </xsl:template>
  6160   <xsl:template match="widget[@type='List']" mode="widget_defs">
  6538   <xsl:template match="widget[@type='List']" mode="widget_defs">
  6161     <xsl:param name="hmi_element"/>
  6539     <xsl:param name="hmi_element"/>
       
  6540     <xsl:variable name="disability">
       
  6541       <xsl:call-template name="defs_by_labels">
       
  6542         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6543         <xsl:with-param name="labels">
       
  6544           <xsl:text>/disabled</xsl:text>
       
  6545         </xsl:with-param>
       
  6546         <xsl:with-param name="mandatory" select="'no'"/>
       
  6547       </xsl:call-template>
       
  6548     </xsl:variable>
       
  6549     <xsl:value-of select="$disability"/>
       
  6550     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6162     <xsl:text>    items: {
  6551     <xsl:text>    items: {
  6163 </xsl:text>
  6552 </xsl:text>
  6164     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  6553     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  6165       <xsl:text>        "</xsl:text>
  6554       <xsl:text>        "</xsl:text>
  6166       <xsl:value-of select="@inkscape:label"/>
  6555       <xsl:value-of select="@inkscape:label"/>
  6221     <xsl:text>}
  6610     <xsl:text>}
  6222 </xsl:text>
  6611 </xsl:text>
  6223   </xsl:template>
  6612   </xsl:template>
  6224   <xsl:template match="widget[@type='ListSwitch']" mode="widget_defs">
  6613   <xsl:template match="widget[@type='ListSwitch']" mode="widget_defs">
  6225     <xsl:param name="hmi_element"/>
  6614     <xsl:param name="hmi_element"/>
       
  6615     <xsl:variable name="disability">
       
  6616       <xsl:call-template name="defs_by_labels">
       
  6617         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6618         <xsl:with-param name="labels">
       
  6619           <xsl:text>/disabled</xsl:text>
       
  6620         </xsl:with-param>
       
  6621         <xsl:with-param name="mandatory" select="'no'"/>
       
  6622       </xsl:call-template>
       
  6623     </xsl:variable>
       
  6624     <xsl:value-of select="$disability"/>
       
  6625     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6226     <xsl:variable name="targetid" select="substring-after($hmi_element/@xlink:href,'#')"/>
  6626     <xsl:variable name="targetid" select="substring-after($hmi_element/@xlink:href,'#')"/>
  6227     <xsl:variable name="from_list" select="$hmi_lists[(@id | */@id) = $targetid]"/>
  6627     <xsl:variable name="from_list" select="$hmi_lists[(@id | */@id) = $targetid]"/>
  6228     <xsl:text>    dispatch: function(value) {
  6628     <xsl:text>    dispatch: function(value) {
  6229 </xsl:text>
  6629 </xsl:text>
  6230     <xsl:text>        this.element.href.baseVal = "#"+hmi_widgets["</xsl:text>
  6630     <xsl:text>        this.element.href.baseVal = "#"+hmi_widgets["</xsl:text>
  6327     <xsl:text>}
  6727     <xsl:text>}
  6328 </xsl:text>
  6728 </xsl:text>
  6329   </xsl:template>
  6729   </xsl:template>
  6330   <xsl:template match="widget[@type='Meter']" mode="widget_defs">
  6730   <xsl:template match="widget[@type='Meter']" mode="widget_defs">
  6331     <xsl:param name="hmi_element"/>
  6731     <xsl:param name="hmi_element"/>
       
  6732     <xsl:variable name="disability">
       
  6733       <xsl:call-template name="defs_by_labels">
       
  6734         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6735         <xsl:with-param name="labels">
       
  6736           <xsl:text>/disabled</xsl:text>
       
  6737         </xsl:with-param>
       
  6738         <xsl:with-param name="mandatory" select="'no'"/>
       
  6739       </xsl:call-template>
       
  6740     </xsl:variable>
       
  6741     <xsl:value-of select="$disability"/>
       
  6742     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6332     <xsl:call-template name="defs_by_labels">
  6743     <xsl:call-template name="defs_by_labels">
  6333       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6744       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6334       <xsl:with-param name="labels">
  6745       <xsl:with-param name="labels">
  6335         <xsl:text>needle range</xsl:text>
  6746         <xsl:text>needle range</xsl:text>
  6336       </xsl:with-param>
  6747       </xsl:with-param>
  6343       <xsl:with-param name="mandatory" select="'no'"/>
  6754       <xsl:with-param name="mandatory" select="'no'"/>
  6344     </xsl:call-template>
  6755     </xsl:call-template>
  6345   </xsl:template>
  6756   </xsl:template>
  6346   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6757   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6347     <xsl:param name="hmi_element"/>
  6758     <xsl:param name="hmi_element"/>
       
  6759     <xsl:variable name="disability">
       
  6760       <xsl:call-template name="defs_by_labels">
       
  6761         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6762         <xsl:with-param name="labels">
       
  6763           <xsl:text>/disabled</xsl:text>
       
  6764         </xsl:with-param>
       
  6765         <xsl:with-param name="mandatory" select="'no'"/>
       
  6766       </xsl:call-template>
       
  6767     </xsl:variable>
       
  6768     <xsl:value-of select="$disability"/>
       
  6769     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6348     <longdesc>
  6770     <longdesc>
  6349       <xsl:text>Mutlistateh widget hides all subelements whose label do not match given
  6771       <xsl:text>Mutlistateh widget hides all subelements whose label do not match given
  6350 </xsl:text>
  6772 </xsl:text>
  6351       <xsl:text>variable value representation. For exemple if given variable type
  6773       <xsl:text>variable value representation. For exemple if given variable type
  6352 </xsl:text>
  6774 </xsl:text>
  6458     <xsl:text>}
  6880     <xsl:text>}
  6459 </xsl:text>
  6881 </xsl:text>
  6460   </xsl:template>
  6882   </xsl:template>
  6461   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6883   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6462     <xsl:param name="hmi_element"/>
  6884     <xsl:param name="hmi_element"/>
       
  6885     <xsl:variable name="disability">
       
  6886       <xsl:call-template name="defs_by_labels">
       
  6887         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  6888         <xsl:with-param name="labels">
       
  6889           <xsl:text>/disabled</xsl:text>
       
  6890         </xsl:with-param>
       
  6891         <xsl:with-param name="mandatory" select="'no'"/>
       
  6892       </xsl:call-template>
       
  6893     </xsl:variable>
       
  6894     <xsl:value-of select="$disability"/>
       
  6895     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6463     <xsl:text>    choices: [
  6896     <xsl:text>    choices: [
  6464 </xsl:text>
  6897 </xsl:text>
  6465     <xsl:variable name="regex" select="'^(&quot;[^&quot;].*&quot;|\-?[0-9]+|false|true)(#.*)?$'"/>
  6898     <xsl:variable name="regex" select="'^(&quot;[^&quot;].*&quot;|\-?[0-9]+|false|true)(#.*)?$'"/>
  6466     <xsl:for-each select="$result_svg_ns//*[@id = $hmi_element/@id]//*[regexp:test(@inkscape:label,$regex)]">
  6899     <xsl:for-each select="$result_svg_ns//*[@id = $hmi_element/@id]//*[regexp:test(@inkscape:label,$regex)]">
  6467       <xsl:variable name="literal" select="regexp:match(@inkscape:label,$regex)[2]"/>
  6900       <xsl:variable name="literal" select="regexp:match(@inkscape:label,$regex)[2]"/>
  6820     <xsl:text>}
  7253     <xsl:text>}
  6821 </xsl:text>
  7254 </xsl:text>
  6822   </xsl:template>
  7255   </xsl:template>
  6823   <xsl:template match="widget[@type='PathSlider']" mode="widget_defs">
  7256   <xsl:template match="widget[@type='PathSlider']" mode="widget_defs">
  6824     <xsl:param name="hmi_element"/>
  7257     <xsl:param name="hmi_element"/>
       
  7258     <xsl:variable name="disability">
       
  7259       <xsl:call-template name="defs_by_labels">
       
  7260         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  7261         <xsl:with-param name="labels">
       
  7262           <xsl:text>/disabled</xsl:text>
       
  7263         </xsl:with-param>
       
  7264         <xsl:with-param name="mandatory" select="'no'"/>
       
  7265       </xsl:call-template>
       
  7266     </xsl:variable>
       
  7267     <xsl:value-of select="$disability"/>
       
  7268     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  6825     <xsl:call-template name="defs_by_labels">
  7269     <xsl:call-template name="defs_by_labels">
  6826       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7270       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6827       <xsl:with-param name="labels">
  7271       <xsl:with-param name="labels">
  6828         <xsl:text>cursor path</xsl:text>
  7272         <xsl:text>cursor path</xsl:text>
  6829       </xsl:with-param>
  7273       </xsl:with-param>
  7028     <xsl:text>}
  7472     <xsl:text>}
  7029 </xsl:text>
  7473 </xsl:text>
  7030   </xsl:template>
  7474   </xsl:template>
  7031   <xsl:template match="widget[@type='ScrollBar']" mode="widget_defs">
  7475   <xsl:template match="widget[@type='ScrollBar']" mode="widget_defs">
  7032     <xsl:param name="hmi_element"/>
  7476     <xsl:param name="hmi_element"/>
       
  7477     <xsl:variable name="disability">
       
  7478       <xsl:call-template name="defs_by_labels">
       
  7479         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  7480         <xsl:with-param name="labels">
       
  7481           <xsl:text>/disabled</xsl:text>
       
  7482         </xsl:with-param>
       
  7483         <xsl:with-param name="mandatory" select="'no'"/>
       
  7484       </xsl:call-template>
       
  7485     </xsl:variable>
       
  7486     <xsl:value-of select="$disability"/>
       
  7487     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  7033     <xsl:call-template name="defs_by_labels">
  7488     <xsl:call-template name="defs_by_labels">
  7034       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7489       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7035       <xsl:with-param name="labels">
  7490       <xsl:with-param name="labels">
  7036         <xsl:text>cursor range</xsl:text>
  7491         <xsl:text>cursor range</xsl:text>
  7037       </xsl:with-param>
  7492       </xsl:with-param>
  7755     <xsl:text>}
  8210     <xsl:text>}
  7756 </xsl:text>
  8211 </xsl:text>
  7757   </xsl:template>
  8212   </xsl:template>
  7758   <xsl:template match="widget[@type='Slider']" mode="widget_defs">
  8213   <xsl:template match="widget[@type='Slider']" mode="widget_defs">
  7759     <xsl:param name="hmi_element"/>
  8214     <xsl:param name="hmi_element"/>
       
  8215     <xsl:variable name="disability">
       
  8216       <xsl:call-template name="defs_by_labels">
       
  8217         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  8218         <xsl:with-param name="labels">
       
  8219           <xsl:text>/disabled</xsl:text>
       
  8220         </xsl:with-param>
       
  8221         <xsl:with-param name="mandatory" select="'no'"/>
       
  8222       </xsl:call-template>
       
  8223     </xsl:variable>
       
  8224     <xsl:value-of select="$disability"/>
       
  8225     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  7760     <xsl:call-template name="defs_by_labels">
  8226     <xsl:call-template name="defs_by_labels">
  7761       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8227       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7762       <xsl:with-param name="labels">
  8228       <xsl:with-param name="labels">
  7763         <xsl:text>handle range</xsl:text>
  8229         <xsl:text>handle range</xsl:text>
  7764       </xsl:with-param>
  8230       </xsl:with-param>
  7858     <xsl:text>}
  8324     <xsl:text>}
  7859 </xsl:text>
  8325 </xsl:text>
  7860   </xsl:template>
  8326   </xsl:template>
  7861   <xsl:template match="widget[@type='Switch']" mode="widget_defs">
  8327   <xsl:template match="widget[@type='Switch']" mode="widget_defs">
  7862     <xsl:param name="hmi_element"/>
  8328     <xsl:param name="hmi_element"/>
       
  8329     <xsl:variable name="disability">
       
  8330       <xsl:call-template name="defs_by_labels">
       
  8331         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  8332         <xsl:with-param name="labels">
       
  8333           <xsl:text>/disabled</xsl:text>
       
  8334         </xsl:with-param>
       
  8335         <xsl:with-param name="mandatory" select="'no'"/>
       
  8336       </xsl:call-template>
       
  8337     </xsl:variable>
       
  8338     <xsl:value-of select="$disability"/>
       
  8339     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  7863     <xsl:text>    choices: [
  8340     <xsl:text>    choices: [
  7864 </xsl:text>
  8341 </xsl:text>
  7865     <xsl:variable name="regex" select="'^(&quot;[^&quot;].*&quot;|\-?[0-9]+|false|true)(#.*)?$'"/>
  8342     <xsl:variable name="regex" select="'^(&quot;[^&quot;].*&quot;|\-?[0-9]+|false|true)(#.*)?$'"/>
  7866     <xsl:variable name="subelts" select="$result_widgets[@id = $hmi_element/@id]//*"/>
  8343     <xsl:variable name="subelts" select="$result_widgets[@id = $hmi_element/@id]//*"/>
  7867     <xsl:variable name="subwidgets" select="$subelts//*[@id = $hmi_widgets/@id]"/>
  8344     <xsl:variable name="subwidgets" select="$subelts//*[@id = $hmi_widgets/@id]"/>
  7931     </shortdesc>
  8408     </shortdesc>
  7932     <arg name="listname"/>
  8409     <arg name="listname"/>
  7933   </xsl:template>
  8410   </xsl:template>
  7934   <xsl:template match="widget[@type='TextList']" mode="widget_defs">
  8411   <xsl:template match="widget[@type='TextList']" mode="widget_defs">
  7935     <xsl:param name="hmi_element"/>
  8412     <xsl:param name="hmi_element"/>
       
  8413     <xsl:variable name="disability">
       
  8414       <xsl:call-template name="defs_by_labels">
       
  8415         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  8416         <xsl:with-param name="labels">
       
  8417           <xsl:text>/disabled</xsl:text>
       
  8418         </xsl:with-param>
       
  8419         <xsl:with-param name="mandatory" select="'no'"/>
       
  8420       </xsl:call-template>
       
  8421     </xsl:variable>
       
  8422     <xsl:value-of select="$disability"/>
       
  8423     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  7936     <xsl:text>    texts: [
  8424     <xsl:text>    texts: [
  7937 </xsl:text>
  8425 </xsl:text>
  7938     <xsl:for-each select="func:refered_elements($hmi_element/*[@inkscape:label])[self::svg:text]">
  8426     <xsl:for-each select="func:refered_elements($hmi_element/*[@inkscape:label])[self::svg:text]">
  7939       <xsl:text>        id("</xsl:text>
  8427       <xsl:text>        id("</xsl:text>
  7940       <xsl:value-of select="@id"/>
  8428       <xsl:value-of select="@id"/>
  7977     </shortdesc>
  8465     </shortdesc>
  7978     <arg name="listname"/>
  8466     <arg name="listname"/>
  7979   </xsl:template>
  8467   </xsl:template>
  7980   <xsl:template match="widget[@type='TextStyleList']" mode="widget_defs">
  8468   <xsl:template match="widget[@type='TextStyleList']" mode="widget_defs">
  7981     <xsl:param name="hmi_element"/>
  8469     <xsl:param name="hmi_element"/>
       
  8470     <xsl:variable name="disability">
       
  8471       <xsl:call-template name="defs_by_labels">
       
  8472         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  8473         <xsl:with-param name="labels">
       
  8474           <xsl:text>/disabled</xsl:text>
       
  8475         </xsl:with-param>
       
  8476         <xsl:with-param name="mandatory" select="'no'"/>
       
  8477       </xsl:call-template>
       
  8478     </xsl:variable>
       
  8479     <xsl:value-of select="$disability"/>
       
  8480     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  7982     <xsl:text>    styles: {
  8481     <xsl:text>    styles: {
  7983 </xsl:text>
  8482 </xsl:text>
  7984     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  8483     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  7985       <xsl:variable name="style" select="func:refered_elements(.)[self::svg:text]/@style"/>
  8484       <xsl:variable name="style" select="func:refered_elements(.)[self::svg:text]/@style"/>
  7986       <xsl:text>        </xsl:text>
  8485       <xsl:text>        </xsl:text>
  8025     <xsl:text>ToggleButtonWidget</xsl:text>
  8524     <xsl:text>ToggleButtonWidget</xsl:text>
  8026     <xsl:text> extends Widget{
  8525     <xsl:text> extends Widget{
  8027 </xsl:text>
  8526 </xsl:text>
  8028     <xsl:text>    frequency = 5;
  8527     <xsl:text>    frequency = 5;
  8029 </xsl:text>
  8528 </xsl:text>
  8030     <xsl:text>    state = 0;
       
  8031 </xsl:text>
       
  8032     <xsl:text>    active_style = undefined;
  8529     <xsl:text>    active_style = undefined;
  8033 </xsl:text>
  8530 </xsl:text>
  8034     <xsl:text>    inactive_style = undefined;
  8531     <xsl:text>    inactive_style = undefined;
  8035 </xsl:text>
  8532 </xsl:text>
  8036     <xsl:text>
  8533     <xsl:text>
  8037 </xsl:text>
  8534 </xsl:text>
  8038     <xsl:text>    dispatch(value) {
  8535     <xsl:text>    dispatch(value) {
  8039 </xsl:text>
  8536 </xsl:text>
  8040     <xsl:text>        this.state = value;
  8537     <xsl:text>        this.activity_state = Boolean(value);
  8041 </xsl:text>
  8538 </xsl:text>
  8042     <xsl:text>        //redraw toggle button
  8539     <xsl:text>        //redraw toggle button
  8043 </xsl:text>
  8540 </xsl:text>
  8044     <xsl:text>        this.request_animate();
  8541     <xsl:text>        this.request_animate();
  8045 </xsl:text>
  8542 </xsl:text>
  8049 </xsl:text>
  8546 </xsl:text>
  8050     <xsl:text>    on_click(evt) {
  8547     <xsl:text>    on_click(evt) {
  8051 </xsl:text>
  8548 </xsl:text>
  8052     <xsl:text>        //toggle state and apply
  8549     <xsl:text>        //toggle state and apply
  8053 </xsl:text>
  8550 </xsl:text>
  8054     <xsl:text>        this.state = this.state ? false : true;
  8551     <xsl:text>        this.activity_state = this.activity_state ? false : true;
  8055 </xsl:text>
  8552 </xsl:text>
  8056     <xsl:text>        this.apply_hmi_value(0, this.state);
  8553     <xsl:text>        this.apply_hmi_value(0, this.activity_state);
  8057 </xsl:text>
  8554 </xsl:text>
  8058     <xsl:text>
  8555     <xsl:text>
  8059 </xsl:text>
  8556 </xsl:text>
  8060     <xsl:text>        //redraw toggle button
  8557     <xsl:text>        //redraw toggle button
  8061 </xsl:text>
  8558 </xsl:text>
  8063 </xsl:text>
  8560 </xsl:text>
  8064     <xsl:text>    }
  8561     <xsl:text>    }
  8065 </xsl:text>
  8562 </xsl:text>
  8066     <xsl:text>
  8563     <xsl:text>
  8067 </xsl:text>
  8564 </xsl:text>
  8068     <xsl:text>    animate(){
       
  8069 </xsl:text>
       
  8070     <xsl:text>        // redraw toggle button on screen refresh
       
  8071 </xsl:text>
       
  8072     <xsl:text>        this.set_activation_state(this.state);
       
  8073 </xsl:text>
       
  8074     <xsl:text>    }
       
  8075 </xsl:text>
       
  8076     <xsl:text>
       
  8077 </xsl:text>
       
  8078     <xsl:text>    init() {
  8565     <xsl:text>    init() {
  8079 </xsl:text>
  8566 </xsl:text>
  8080     <xsl:text>        this.element.onclick = (evt) =&gt; this.on_click(evt);
  8567     <xsl:text>        this.element.onclick = (evt) =&gt; this.on_click(evt);
  8081 </xsl:text>
  8568 </xsl:text>
  8082     <xsl:text>        this.set_activation_state(undefined);
  8569     <xsl:text>        this.activity_state = undefined;
  8083 </xsl:text>
  8570 </xsl:text>
  8084     <xsl:text>    }
  8571     <xsl:text>    }
  8085 </xsl:text>
  8572 </xsl:text>
  8086     <xsl:text>}
  8573     <xsl:text>}
  8087 </xsl:text>
  8574 </xsl:text>
  8088   </xsl:template>
  8575   </xsl:template>
  8089   <xsl:template match="widget[@type='ToggleButton']" mode="widget_defs">
  8576   <xsl:template match="widget[@type='ToggleButton']" mode="widget_defs">
  8090     <xsl:param name="hmi_element"/>
  8577     <xsl:param name="hmi_element"/>
       
  8578     <xsl:variable name="disability">
       
  8579       <xsl:call-template name="defs_by_labels">
       
  8580         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  8581         <xsl:with-param name="labels">
       
  8582           <xsl:text>/disabled</xsl:text>
       
  8583         </xsl:with-param>
       
  8584         <xsl:with-param name="mandatory" select="'no'"/>
       
  8585       </xsl:call-template>
       
  8586     </xsl:variable>
       
  8587     <xsl:value-of select="$disability"/>
       
  8588     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  8091     <xsl:text>    activable_sub:{
  8589     <xsl:text>    activable_sub:{
  8092 </xsl:text>
  8590 </xsl:text>
  8093     <xsl:call-template name="defs_by_labels">
  8591     <xsl:variable name="activity">
  8094       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8592       <xsl:call-template name="defs_by_labels">
  8095       <xsl:with-param name="labels">
  8593         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8096         <xsl:text>/active /inactive</xsl:text>
  8594         <xsl:with-param name="labels">
  8097       </xsl:with-param>
  8595           <xsl:text>/active /inactive</xsl:text>
  8098       <xsl:with-param name="mandatory" select="'warn'"/>
  8596         </xsl:with-param>
  8099     </xsl:call-template>
  8597         <xsl:with-param name="mandatory">
  8100     <xsl:text>    }
  8598           <xsl:text>warn</xsl:text>
       
  8599         </xsl:with-param>
       
  8600       </xsl:call-template>
       
  8601     </xsl:variable>
       
  8602     <xsl:value-of select="$activity"/>
       
  8603     <xsl:variable name="has_activity" select="string-length($activity)&gt;0"/>
       
  8604     <xsl:text>    },
       
  8605 </xsl:text>
       
  8606     <xsl:text>    has_activity: </xsl:text>
       
  8607     <xsl:value-of select="$has_activity"/>
       
  8608     <xsl:text>,
  8101 </xsl:text>
  8609 </xsl:text>
  8102   </xsl:template>
  8610   </xsl:template>
  8103   <xsl:template match="widget[@type='XYGraph']" mode="widget_desc">
  8611   <xsl:template match="widget[@type='XYGraph']" mode="widget_desc">
  8104     <type>
  8612     <type>
  8105       <xsl:value-of select="@type"/>
  8613       <xsl:value-of select="@type"/>
  8569     </xsl:variable>
  9077     </xsl:variable>
  8570     <func:result select="$res"/>
  9078     <func:result select="$res"/>
  8571   </func:function>
  9079   </func:function>
  8572   <xsl:template match="widget[@type='XYGraph']" mode="widget_defs">
  9080   <xsl:template match="widget[@type='XYGraph']" mode="widget_defs">
  8573     <xsl:param name="hmi_element"/>
  9081     <xsl:param name="hmi_element"/>
       
  9082     <xsl:variable name="disability">
       
  9083       <xsl:call-template name="defs_by_labels">
       
  9084         <xsl:with-param name="hmi_element" select="$hmi_element"/>
       
  9085         <xsl:with-param name="labels">
       
  9086           <xsl:text>/disabled</xsl:text>
       
  9087         </xsl:with-param>
       
  9088         <xsl:with-param name="mandatory" select="'no'"/>
       
  9089       </xsl:call-template>
       
  9090     </xsl:variable>
       
  9091     <xsl:value-of select="$disability"/>
       
  9092     <xsl:variable name="has_disability" select="string-length($disability)&gt;0"/>
  8574     <xsl:call-template name="defs_by_labels">
  9093     <xsl:call-template name="defs_by_labels">
  8575       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  9094       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8576       <xsl:with-param name="labels">
  9095       <xsl:with-param name="labels">
  8577         <xsl:text>/x_interval_minor_mark /x_axis_line /x_interval_major_mark /x_axis_label</xsl:text>
  9096         <xsl:text>/x_interval_minor_mark /x_axis_line /x_interval_major_mark /x_axis_label</xsl:text>
  8578       </xsl:with-param>
  9097       </xsl:with-param>
  9446         </style>
  9965         </style>
  9447       </head>
  9966       </head>
  9448       <body style="margin:0;overflow:hidden;user-select:none;touch-action:none;">
  9967       <body style="margin:0;overflow:hidden;user-select:none;touch-action:none;">
  9449         <xsl:copy-of select="$result_svg"/>
  9968         <xsl:copy-of select="$result_svg"/>
  9450         <script>
  9969         <script>
       
  9970           <xsl:text>/*
       
  9971 </xsl:text>
       
  9972           <xsl:text>
       
  9973 </xsl:text>
       
  9974           <xsl:text>From https://github.com/keyvan-m-sadeghi/pythonic
       
  9975 </xsl:text>
       
  9976           <xsl:text>
       
  9977 </xsl:text>
       
  9978           <xsl:text>Slightly modified in order to be usable in browser (i.e. not as a node.js module)
       
  9979 </xsl:text>
       
  9980           <xsl:text>
       
  9981 </xsl:text>
       
  9982           <xsl:text>The MIT License (MIT)
       
  9983 </xsl:text>
       
  9984           <xsl:text>
       
  9985 </xsl:text>
       
  9986           <xsl:text>Copyright (c) 2016 Assister.Ai
       
  9987 </xsl:text>
       
  9988           <xsl:text>
       
  9989 </xsl:text>
       
  9990           <xsl:text>Permission is hereby granted, free of charge, to any person obtaining a copy of
       
  9991 </xsl:text>
       
  9992           <xsl:text>this software and associated documentation files (the "Software"), to deal in
       
  9993 </xsl:text>
       
  9994           <xsl:text>the Software without restriction, including without limitation the rights to
       
  9995 </xsl:text>
       
  9996           <xsl:text>use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
       
  9997 </xsl:text>
       
  9998           <xsl:text>the Software, and to permit persons to whom the Software is furnished to do so,
       
  9999 </xsl:text>
       
 10000           <xsl:text>subject to the following conditions:
       
 10001 </xsl:text>
       
 10002           <xsl:text>
       
 10003 </xsl:text>
       
 10004           <xsl:text>The above copyright notice and this permission notice shall be included in all
       
 10005 </xsl:text>
       
 10006           <xsl:text>copies or substantial portions of the Software.
       
 10007 </xsl:text>
       
 10008           <xsl:text>
       
 10009 </xsl:text>
       
 10010           <xsl:text>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
 10011 </xsl:text>
       
 10012           <xsl:text>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
       
 10013 </xsl:text>
       
 10014           <xsl:text>FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
       
 10015 </xsl:text>
       
 10016           <xsl:text>COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
       
 10017 </xsl:text>
       
 10018           <xsl:text>IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
 10019 </xsl:text>
       
 10020           <xsl:text>CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
 10021 </xsl:text>
       
 10022           <xsl:text>*/
       
 10023 </xsl:text>
       
 10024           <xsl:text>
       
 10025 </xsl:text>
       
 10026           <xsl:text>class Iterator {
       
 10027 </xsl:text>
       
 10028           <xsl:text>    constructor(generator) {
       
 10029 </xsl:text>
       
 10030           <xsl:text>        this[Symbol.iterator] = generator;
       
 10031 </xsl:text>
       
 10032           <xsl:text>    }
       
 10033 </xsl:text>
       
 10034           <xsl:text>
       
 10035 </xsl:text>
       
 10036           <xsl:text>    async * [Symbol.asyncIterator]() {
       
 10037 </xsl:text>
       
 10038           <xsl:text>        for (const element of this) {
       
 10039 </xsl:text>
       
 10040           <xsl:text>            yield await element;
       
 10041 </xsl:text>
       
 10042           <xsl:text>        }
       
 10043 </xsl:text>
       
 10044           <xsl:text>    }
       
 10045 </xsl:text>
       
 10046           <xsl:text>
       
 10047 </xsl:text>
       
 10048           <xsl:text>    forEach(callback) {
       
 10049 </xsl:text>
       
 10050           <xsl:text>        for (const element of this) {
       
 10051 </xsl:text>
       
 10052           <xsl:text>            callback(element);
       
 10053 </xsl:text>
       
 10054           <xsl:text>        }
       
 10055 </xsl:text>
       
 10056           <xsl:text>    }
       
 10057 </xsl:text>
       
 10058           <xsl:text>
       
 10059 </xsl:text>
       
 10060           <xsl:text>    map(callback) {
       
 10061 </xsl:text>
       
 10062           <xsl:text>        const result = [];
       
 10063 </xsl:text>
       
 10064           <xsl:text>        for (const element of this) {
       
 10065 </xsl:text>
       
 10066           <xsl:text>            result.push(callback(element));
       
 10067 </xsl:text>
       
 10068           <xsl:text>        }
       
 10069 </xsl:text>
       
 10070           <xsl:text>
       
 10071 </xsl:text>
       
 10072           <xsl:text>        return result;
       
 10073 </xsl:text>
       
 10074           <xsl:text>    }
       
 10075 </xsl:text>
       
 10076           <xsl:text>
       
 10077 </xsl:text>
       
 10078           <xsl:text>    filter(callback) {
       
 10079 </xsl:text>
       
 10080           <xsl:text>        const result = [];
       
 10081 </xsl:text>
       
 10082           <xsl:text>        for (const element of this) {
       
 10083 </xsl:text>
       
 10084           <xsl:text>            if (callback(element)) {
       
 10085 </xsl:text>
       
 10086           <xsl:text>                result.push(element);
       
 10087 </xsl:text>
       
 10088           <xsl:text>            }
       
 10089 </xsl:text>
       
 10090           <xsl:text>        }
       
 10091 </xsl:text>
       
 10092           <xsl:text>
       
 10093 </xsl:text>
       
 10094           <xsl:text>        return result;
       
 10095 </xsl:text>
       
 10096           <xsl:text>    }
       
 10097 </xsl:text>
       
 10098           <xsl:text>
       
 10099 </xsl:text>
       
 10100           <xsl:text>    reduce(callback, initialValue) {
       
 10101 </xsl:text>
       
 10102           <xsl:text>        let empty = typeof initialValue === 'undefined';
       
 10103 </xsl:text>
       
 10104           <xsl:text>        let accumulator = initialValue;
       
 10105 </xsl:text>
       
 10106           <xsl:text>        let index = 0;
       
 10107 </xsl:text>
       
 10108           <xsl:text>        for (const currentValue of this) {
       
 10109 </xsl:text>
       
 10110           <xsl:text>            if (empty) {
       
 10111 </xsl:text>
       
 10112           <xsl:text>                accumulator = currentValue;
       
 10113 </xsl:text>
       
 10114           <xsl:text>                empty = false;
       
 10115 </xsl:text>
       
 10116           <xsl:text>                continue;
       
 10117 </xsl:text>
       
 10118           <xsl:text>            }
       
 10119 </xsl:text>
       
 10120           <xsl:text>
       
 10121 </xsl:text>
       
 10122           <xsl:text>            accumulator = callback(accumulator, currentValue, index, this);
       
 10123 </xsl:text>
       
 10124           <xsl:text>            index++;
       
 10125 </xsl:text>
       
 10126           <xsl:text>        }
       
 10127 </xsl:text>
       
 10128           <xsl:text>
       
 10129 </xsl:text>
       
 10130           <xsl:text>        if (empty) {
       
 10131 </xsl:text>
       
 10132           <xsl:text>            throw new TypeError('Reduce of empty Iterator with no initial value');
       
 10133 </xsl:text>
       
 10134           <xsl:text>        }
       
 10135 </xsl:text>
       
 10136           <xsl:text>
       
 10137 </xsl:text>
       
 10138           <xsl:text>        return accumulator;
       
 10139 </xsl:text>
       
 10140           <xsl:text>    }
       
 10141 </xsl:text>
       
 10142           <xsl:text>
       
 10143 </xsl:text>
       
 10144           <xsl:text>    some(callback) {
       
 10145 </xsl:text>
       
 10146           <xsl:text>        for (const element of this) {
       
 10147 </xsl:text>
       
 10148           <xsl:text>            if (callback(element)) {
       
 10149 </xsl:text>
       
 10150           <xsl:text>                return true;
       
 10151 </xsl:text>
       
 10152           <xsl:text>            }
       
 10153 </xsl:text>
       
 10154           <xsl:text>        }
       
 10155 </xsl:text>
       
 10156           <xsl:text>
       
 10157 </xsl:text>
       
 10158           <xsl:text>        return false;
       
 10159 </xsl:text>
       
 10160           <xsl:text>    }
       
 10161 </xsl:text>
       
 10162           <xsl:text>
       
 10163 </xsl:text>
       
 10164           <xsl:text>    every(callback) {
       
 10165 </xsl:text>
       
 10166           <xsl:text>        for (const element of this) {
       
 10167 </xsl:text>
       
 10168           <xsl:text>            if (!callback(element)) {
       
 10169 </xsl:text>
       
 10170           <xsl:text>                return false;
       
 10171 </xsl:text>
       
 10172           <xsl:text>            }
       
 10173 </xsl:text>
       
 10174           <xsl:text>        }
       
 10175 </xsl:text>
       
 10176           <xsl:text>
       
 10177 </xsl:text>
       
 10178           <xsl:text>        return true;
       
 10179 </xsl:text>
       
 10180           <xsl:text>    }
       
 10181 </xsl:text>
       
 10182           <xsl:text>
       
 10183 </xsl:text>
       
 10184           <xsl:text>    static fromIterable(iterable) {
       
 10185 </xsl:text>
       
 10186           <xsl:text>        return new Iterator(function * () {
       
 10187 </xsl:text>
       
 10188           <xsl:text>            for (const element of iterable) {
       
 10189 </xsl:text>
       
 10190           <xsl:text>                yield element;
       
 10191 </xsl:text>
       
 10192           <xsl:text>            }
       
 10193 </xsl:text>
       
 10194           <xsl:text>        });
       
 10195 </xsl:text>
       
 10196           <xsl:text>    }
       
 10197 </xsl:text>
       
 10198           <xsl:text>
       
 10199 </xsl:text>
       
 10200           <xsl:text>    toArray() {
       
 10201 </xsl:text>
       
 10202           <xsl:text>        return Array.from(this);
       
 10203 </xsl:text>
       
 10204           <xsl:text>    }
       
 10205 </xsl:text>
       
 10206           <xsl:text>
       
 10207 </xsl:text>
       
 10208           <xsl:text>    next() {
       
 10209 </xsl:text>
       
 10210           <xsl:text>        if (!this.currentInvokedGenerator) {
       
 10211 </xsl:text>
       
 10212           <xsl:text>            this.currentInvokedGenerator = this[Symbol.iterator]();
       
 10213 </xsl:text>
       
 10214           <xsl:text>        }
       
 10215 </xsl:text>
       
 10216           <xsl:text>
       
 10217 </xsl:text>
       
 10218           <xsl:text>        return this.currentInvokedGenerator.next();
       
 10219 </xsl:text>
       
 10220           <xsl:text>    }
       
 10221 </xsl:text>
       
 10222           <xsl:text>
       
 10223 </xsl:text>
       
 10224           <xsl:text>    reset() {
       
 10225 </xsl:text>
       
 10226           <xsl:text>        delete this.currentInvokedGenerator;
       
 10227 </xsl:text>
       
 10228           <xsl:text>    }
       
 10229 </xsl:text>
       
 10230           <xsl:text>}
       
 10231 </xsl:text>
       
 10232           <xsl:text>
       
 10233 </xsl:text>
       
 10234           <xsl:text>function rangeSimple(stop) {
       
 10235 </xsl:text>
       
 10236           <xsl:text>    return new Iterator(function * () {
       
 10237 </xsl:text>
       
 10238           <xsl:text>        for (let i = 0; i &lt; stop; i++) {
       
 10239 </xsl:text>
       
 10240           <xsl:text>            yield i;
       
 10241 </xsl:text>
       
 10242           <xsl:text>        }
       
 10243 </xsl:text>
       
 10244           <xsl:text>    });
       
 10245 </xsl:text>
       
 10246           <xsl:text>}
       
 10247 </xsl:text>
       
 10248           <xsl:text>
       
 10249 </xsl:text>
       
 10250           <xsl:text>function rangeOverload(start, stop, step = 1) {
       
 10251 </xsl:text>
       
 10252           <xsl:text>    return new Iterator(function * () {
       
 10253 </xsl:text>
       
 10254           <xsl:text>        for (let i = start; i &lt; stop; i += step) {
       
 10255 </xsl:text>
       
 10256           <xsl:text>            yield i;
       
 10257 </xsl:text>
       
 10258           <xsl:text>        }
       
 10259 </xsl:text>
       
 10260           <xsl:text>    });
       
 10261 </xsl:text>
       
 10262           <xsl:text>}
       
 10263 </xsl:text>
       
 10264           <xsl:text>
       
 10265 </xsl:text>
       
 10266           <xsl:text>function range(...args) {
       
 10267 </xsl:text>
       
 10268           <xsl:text>    if (args.length &lt; 2) {
       
 10269 </xsl:text>
       
 10270           <xsl:text>        return rangeSimple(...args);
       
 10271 </xsl:text>
       
 10272           <xsl:text>    }
       
 10273 </xsl:text>
       
 10274           <xsl:text>
       
 10275 </xsl:text>
       
 10276           <xsl:text>    return rangeOverload(...args);
       
 10277 </xsl:text>
       
 10278           <xsl:text>}
       
 10279 </xsl:text>
       
 10280           <xsl:text>
       
 10281 </xsl:text>
       
 10282           <xsl:text>function enumerate(iterable) {
       
 10283 </xsl:text>
       
 10284           <xsl:text>    return new Iterator(function * () {
       
 10285 </xsl:text>
       
 10286           <xsl:text>        let index = 0;
       
 10287 </xsl:text>
       
 10288           <xsl:text>        for (const element of iterable) {
       
 10289 </xsl:text>
       
 10290           <xsl:text>            yield [index, element];
       
 10291 </xsl:text>
       
 10292           <xsl:text>            index++;
       
 10293 </xsl:text>
       
 10294           <xsl:text>        }
       
 10295 </xsl:text>
       
 10296           <xsl:text>    });
       
 10297 </xsl:text>
       
 10298           <xsl:text>}
       
 10299 </xsl:text>
       
 10300           <xsl:text>
       
 10301 </xsl:text>
       
 10302           <xsl:text>const _zip = longest =&gt; (...iterables) =&gt; {
       
 10303 </xsl:text>
       
 10304           <xsl:text>    if (iterables.length == 0) {
       
 10305 </xsl:text>
       
 10306           <xsl:text>        // works starting with 1 iterable
       
 10307 </xsl:text>
       
 10308           <xsl:text>        // [a,b,c] -&gt; [[a],[b],[c]]
       
 10309 </xsl:text>
       
 10310           <xsl:text>        // [a,b,c],[d,e,f] -&gt; [[a,d],[b,e],[c,f]]
       
 10311 </xsl:text>
       
 10312           <xsl:text>        throw new TypeError("zip takes 1 iterables at least, "+iterables.length+" given");
       
 10313 </xsl:text>
       
 10314           <xsl:text>    }
       
 10315 </xsl:text>
       
 10316           <xsl:text>
       
 10317 </xsl:text>
       
 10318           <xsl:text>    return new Iterator(function * () {
       
 10319 </xsl:text>
       
 10320           <xsl:text>        const iterators = iterables.map(iterable =&gt; Iterator.fromIterable(iterable));
       
 10321 </xsl:text>
       
 10322           <xsl:text>        while (true) {
       
 10323 </xsl:text>
       
 10324           <xsl:text>            const row = iterators.map(iterator =&gt; iterator.next());
       
 10325 </xsl:text>
       
 10326           <xsl:text>            const check = longest ? row.every.bind(row) : row.some.bind(row);
       
 10327 </xsl:text>
       
 10328           <xsl:text>            if (check(next =&gt; next.done)) {
       
 10329 </xsl:text>
       
 10330           <xsl:text>                return;
       
 10331 </xsl:text>
       
 10332           <xsl:text>            }
       
 10333 </xsl:text>
       
 10334           <xsl:text>
       
 10335 </xsl:text>
       
 10336           <xsl:text>            yield row.map(next =&gt; next.value);
       
 10337 </xsl:text>
       
 10338           <xsl:text>        }
       
 10339 </xsl:text>
       
 10340           <xsl:text>    });
       
 10341 </xsl:text>
       
 10342           <xsl:text>};
       
 10343 </xsl:text>
       
 10344           <xsl:text>
       
 10345 </xsl:text>
       
 10346           <xsl:text>const zip = _zip(false), zipLongest= _zip(true);
       
 10347 </xsl:text>
       
 10348           <xsl:text>
       
 10349 </xsl:text>
       
 10350           <xsl:text>function items(obj) {
       
 10351 </xsl:text>
       
 10352           <xsl:text>    let {keys, get} = obj;
       
 10353 </xsl:text>
       
 10354           <xsl:text>    if (obj instanceof Map) {
       
 10355 </xsl:text>
       
 10356           <xsl:text>        keys = keys.bind(obj);
       
 10357 </xsl:text>
       
 10358           <xsl:text>        get = get.bind(obj);
       
 10359 </xsl:text>
       
 10360           <xsl:text>    } else {
       
 10361 </xsl:text>
       
 10362           <xsl:text>        keys = function () {
       
 10363 </xsl:text>
       
 10364           <xsl:text>            return Object.keys(obj);
       
 10365 </xsl:text>
       
 10366           <xsl:text>        };
       
 10367 </xsl:text>
       
 10368           <xsl:text>
       
 10369 </xsl:text>
       
 10370           <xsl:text>        get = function (key) {
       
 10371 </xsl:text>
       
 10372           <xsl:text>            return obj[key];
       
 10373 </xsl:text>
       
 10374           <xsl:text>        };
       
 10375 </xsl:text>
       
 10376           <xsl:text>    }
       
 10377 </xsl:text>
       
 10378           <xsl:text>
       
 10379 </xsl:text>
       
 10380           <xsl:text>    return new Iterator(function * () {
       
 10381 </xsl:text>
       
 10382           <xsl:text>        for (const key of keys()) {
       
 10383 </xsl:text>
       
 10384           <xsl:text>            yield [key, get(key)];
       
 10385 </xsl:text>
       
 10386           <xsl:text>        }
       
 10387 </xsl:text>
       
 10388           <xsl:text>    });
       
 10389 </xsl:text>
       
 10390           <xsl:text>}
       
 10391 </xsl:text>
       
 10392           <xsl:text>
       
 10393 </xsl:text>
       
 10394           <xsl:text>/*
       
 10395 </xsl:text>
       
 10396           <xsl:text>module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items};
       
 10397 </xsl:text>
       
 10398           <xsl:text>*/
       
 10399 </xsl:text>
  9451           <xsl:text>
 10400           <xsl:text>
  9452 //
 10401 //
  9453 //
 10402 //
  9454 // Early independent declarations 
 10403 // Early independent declarations 
  9455 //
 10404 //
 10044 </xsl:text>
 10993 </xsl:text>
 10045           <xsl:text>    /* eslint-enable quote-props */
 10994           <xsl:text>    /* eslint-enable quote-props */
 10046 </xsl:text>
 10995 </xsl:text>
 10047           <xsl:text>}(); // eslint-disable-line    
 10996           <xsl:text>}(); // eslint-disable-line    
 10048 </xsl:text>
 10997 </xsl:text>
 10049           <xsl:text>/*
 10998           <xsl:text>// svghmi.js
 10050 </xsl:text>
 10999 </xsl:text>
 10051           <xsl:text>
 11000           <xsl:text>
 10052 </xsl:text>
 11001 </xsl:text>
 10053           <xsl:text>From https://github.com/keyvan-m-sadeghi/pythonic
 11002           <xsl:text>function dispatch_value(index, value) {
 10054 </xsl:text>
 11003 </xsl:text>
 10055           <xsl:text>
 11004           <xsl:text>    let widgets = subscribers(index);
 10056 </xsl:text>
 11005 </xsl:text>
 10057           <xsl:text>Slightly modified in order to be usable in browser (i.e. not as a node.js module)
 11006           <xsl:text>
 10058 </xsl:text>
 11007 </xsl:text>
 10059           <xsl:text>
 11008           <xsl:text>    let oldval = cache[index];
 10060 </xsl:text>
 11009 </xsl:text>
 10061           <xsl:text>The MIT License (MIT)
 11010           <xsl:text>    cache[index] = value;
 10062 </xsl:text>
 11011 </xsl:text>
 10063           <xsl:text>
 11012           <xsl:text>
 10064 </xsl:text>
 11013 </xsl:text>
 10065           <xsl:text>Copyright (c) 2016 Assister.Ai
 11014           <xsl:text>    if(widgets.size &gt; 0) {
 10066 </xsl:text>
 11015 </xsl:text>
 10067           <xsl:text>
 11016           <xsl:text>        for(let widget of widgets){
 10068 </xsl:text>
 11017 </xsl:text>
 10069           <xsl:text>Permission is hereby granted, free of charge, to any person obtaining a copy of
 11018           <xsl:text>            widget.new_hmi_value(index, value, oldval);
 10070 </xsl:text>
 11019 </xsl:text>
 10071           <xsl:text>this software and associated documentation files (the "Software"), to deal in
 11020           <xsl:text>        }
 10072 </xsl:text>
       
 10073           <xsl:text>the Software without restriction, including without limitation the rights to
       
 10074 </xsl:text>
       
 10075           <xsl:text>use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
       
 10076 </xsl:text>
       
 10077           <xsl:text>the Software, and to permit persons to whom the Software is furnished to do so,
       
 10078 </xsl:text>
       
 10079           <xsl:text>subject to the following conditions:
       
 10080 </xsl:text>
       
 10081           <xsl:text>
       
 10082 </xsl:text>
       
 10083           <xsl:text>The above copyright notice and this permission notice shall be included in all
       
 10084 </xsl:text>
       
 10085           <xsl:text>copies or substantial portions of the Software.
       
 10086 </xsl:text>
       
 10087           <xsl:text>
       
 10088 </xsl:text>
       
 10089           <xsl:text>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
 10090 </xsl:text>
       
 10091           <xsl:text>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
       
 10092 </xsl:text>
       
 10093           <xsl:text>FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
       
 10094 </xsl:text>
       
 10095           <xsl:text>COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
       
 10096 </xsl:text>
       
 10097           <xsl:text>IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
 10098 </xsl:text>
       
 10099           <xsl:text>CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
 10100 </xsl:text>
       
 10101           <xsl:text>*/
       
 10102 </xsl:text>
       
 10103           <xsl:text>
       
 10104 </xsl:text>
       
 10105           <xsl:text>class Iterator {
       
 10106 </xsl:text>
       
 10107           <xsl:text>    constructor(generator) {
       
 10108 </xsl:text>
       
 10109           <xsl:text>        this[Symbol.iterator] = generator;
       
 10110 </xsl:text>
 11021 </xsl:text>
 10111           <xsl:text>    }
 11022           <xsl:text>    }
 10112 </xsl:text>
 11023 </xsl:text>
 10113           <xsl:text>
 11024           <xsl:text>};
 10114 </xsl:text>
 11025 </xsl:text>
 10115           <xsl:text>    async * [Symbol.asyncIterator]() {
 11026           <xsl:text>
 10116 </xsl:text>
 11027 </xsl:text>
 10117           <xsl:text>        for (const element of this) {
 11028           <xsl:text>function init_widgets() {
 10118 </xsl:text>
 11029 </xsl:text>
 10119           <xsl:text>            yield await element;
 11030           <xsl:text>    Object.keys(hmi_widgets).forEach(function(id) {
       
 11031 </xsl:text>
       
 11032           <xsl:text>        let widget = hmi_widgets[id];
       
 11033 </xsl:text>
       
 11034           <xsl:text>        widget.do_init();
       
 11035 </xsl:text>
       
 11036           <xsl:text>    });
       
 11037 </xsl:text>
       
 11038           <xsl:text>};
       
 11039 </xsl:text>
       
 11040           <xsl:text>
       
 11041 </xsl:text>
       
 11042           <xsl:text>// Open WebSocket to relative "/ws" address
       
 11043 </xsl:text>
       
 11044           <xsl:text>var has_watchdog = window.location.hash == "#watchdog";
       
 11045 </xsl:text>
       
 11046           <xsl:text>
       
 11047 </xsl:text>
       
 11048           <xsl:text>var ws_url = 
       
 11049 </xsl:text>
       
 11050           <xsl:text>    window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')
       
 11051 </xsl:text>
       
 11052           <xsl:text>    + '?mode=' + (has_watchdog ? "watchdog" : "multiclient");
       
 11053 </xsl:text>
       
 11054           <xsl:text>
       
 11055 </xsl:text>
       
 11056           <xsl:text>var ws = new WebSocket(ws_url);
       
 11057 </xsl:text>
       
 11058           <xsl:text>ws.binaryType = 'arraybuffer';
       
 11059 </xsl:text>
       
 11060           <xsl:text>
       
 11061 </xsl:text>
       
 11062           <xsl:text>const dvgetters = {
       
 11063 </xsl:text>
       
 11064           <xsl:text>    INT: (dv,offset) =&gt; [dv.getInt16(offset, true), 2],
       
 11065 </xsl:text>
       
 11066           <xsl:text>    BOOL: (dv,offset) =&gt; [dv.getInt8(offset, true), 1],
       
 11067 </xsl:text>
       
 11068           <xsl:text>    NODE: (dv,offset) =&gt; [dv.getInt8(offset, true), 1],
       
 11069 </xsl:text>
       
 11070           <xsl:text>    REAL: (dv,offset) =&gt; [dv.getFloat32(offset, true), 4],
       
 11071 </xsl:text>
       
 11072           <xsl:text>    STRING: (dv, offset) =&gt; {
       
 11073 </xsl:text>
       
 11074           <xsl:text>        const size = dv.getInt8(offset);
       
 11075 </xsl:text>
       
 11076           <xsl:text>        return [
       
 11077 </xsl:text>
       
 11078           <xsl:text>            String.fromCharCode.apply(null, new Uint8Array(
       
 11079 </xsl:text>
       
 11080           <xsl:text>                dv.buffer, /* original buffer */
       
 11081 </xsl:text>
       
 11082           <xsl:text>                offset + 1, /* string starts after size*/
       
 11083 </xsl:text>
       
 11084           <xsl:text>                size /* size of string */
       
 11085 </xsl:text>
       
 11086           <xsl:text>            )), size + 1]; /* total increment */
       
 11087 </xsl:text>
       
 11088           <xsl:text>    }
       
 11089 </xsl:text>
       
 11090           <xsl:text>};
       
 11091 </xsl:text>
       
 11092           <xsl:text>
       
 11093 </xsl:text>
       
 11094           <xsl:text>// Apply updates recieved through ws.onmessage to subscribed widgets
       
 11095 </xsl:text>
       
 11096           <xsl:text>function apply_updates() {
       
 11097 </xsl:text>
       
 11098           <xsl:text>    updates.forEach((value, index) =&gt; {
       
 11099 </xsl:text>
       
 11100           <xsl:text>        dispatch_value(index, value);
       
 11101 </xsl:text>
       
 11102           <xsl:text>    });
       
 11103 </xsl:text>
       
 11104           <xsl:text>    updates.clear();
       
 11105 </xsl:text>
       
 11106           <xsl:text>}
       
 11107 </xsl:text>
       
 11108           <xsl:text>
       
 11109 </xsl:text>
       
 11110           <xsl:text>// Called on requestAnimationFrame, modifies DOM
       
 11111 </xsl:text>
       
 11112           <xsl:text>var requestAnimationFrameID = null;
       
 11113 </xsl:text>
       
 11114           <xsl:text>function animate() {
       
 11115 </xsl:text>
       
 11116           <xsl:text>    let rearm = true;
       
 11117 </xsl:text>
       
 11118           <xsl:text>    do{
       
 11119 </xsl:text>
       
 11120           <xsl:text>        if(page_fading == "pending" || page_fading == "forced"){
       
 11121 </xsl:text>
       
 11122           <xsl:text>            if(page_fading == "pending")
       
 11123 </xsl:text>
       
 11124           <xsl:text>                svg_root.classList.add("fade-out-page");
       
 11125 </xsl:text>
       
 11126           <xsl:text>            page_fading = "in_progress";
       
 11127 </xsl:text>
       
 11128           <xsl:text>            if(page_fading_args.length)
       
 11129 </xsl:text>
       
 11130           <xsl:text>                setTimeout(function(){
       
 11131 </xsl:text>
       
 11132           <xsl:text>                    switch_page(...page_fading_args);
       
 11133 </xsl:text>
       
 11134           <xsl:text>                },1);
       
 11135 </xsl:text>
       
 11136           <xsl:text>            break;
 10120 </xsl:text>
 11137 </xsl:text>
 10121           <xsl:text>        }
 11138           <xsl:text>        }
 10122 </xsl:text>
 11139 </xsl:text>
       
 11140           <xsl:text>
       
 11141 </xsl:text>
       
 11142           <xsl:text>        // Do the page swith if pending
       
 11143 </xsl:text>
       
 11144           <xsl:text>        if(page_switch_in_progress){
       
 11145 </xsl:text>
       
 11146           <xsl:text>            if(current_subscribed_page != current_visible_page){
       
 11147 </xsl:text>
       
 11148           <xsl:text>                switch_visible_page(current_subscribed_page);
       
 11149 </xsl:text>
       
 11150           <xsl:text>            }
       
 11151 </xsl:text>
       
 11152           <xsl:text>
       
 11153 </xsl:text>
       
 11154           <xsl:text>            page_switch_in_progress = false;
       
 11155 </xsl:text>
       
 11156           <xsl:text>
       
 11157 </xsl:text>
       
 11158           <xsl:text>            if(page_fading == "in_progress"){
       
 11159 </xsl:text>
       
 11160           <xsl:text>                svg_root.classList.remove("fade-out-page");
       
 11161 </xsl:text>
       
 11162           <xsl:text>                page_fading = "off";
       
 11163 </xsl:text>
       
 11164           <xsl:text>            }
       
 11165 </xsl:text>
       
 11166           <xsl:text>        }
       
 11167 </xsl:text>
       
 11168           <xsl:text>
       
 11169 </xsl:text>
       
 11170           <xsl:text>        if(jumps_need_update) update_jumps();
       
 11171 </xsl:text>
       
 11172           <xsl:text>
       
 11173 </xsl:text>
       
 11174           <xsl:text>
       
 11175 </xsl:text>
       
 11176           <xsl:text>        pending_widget_animates.forEach(widget =&gt; widget._animate());
       
 11177 </xsl:text>
       
 11178           <xsl:text>        pending_widget_animates = [];
       
 11179 </xsl:text>
       
 11180           <xsl:text>        rearm = false;
       
 11181 </xsl:text>
       
 11182           <xsl:text>    } while(0);
       
 11183 </xsl:text>
       
 11184           <xsl:text>
       
 11185 </xsl:text>
       
 11186           <xsl:text>    requestAnimationFrameID = null;
       
 11187 </xsl:text>
       
 11188           <xsl:text>
       
 11189 </xsl:text>
       
 11190           <xsl:text>    if(rearm) requestHMIAnimation();
       
 11191 </xsl:text>
       
 11192           <xsl:text>}
       
 11193 </xsl:text>
       
 11194           <xsl:text>
       
 11195 </xsl:text>
       
 11196           <xsl:text>function requestHMIAnimation() {
       
 11197 </xsl:text>
       
 11198           <xsl:text>    if(requestAnimationFrameID == null){
       
 11199 </xsl:text>
       
 11200           <xsl:text>        requestAnimationFrameID = window.requestAnimationFrame(animate);
       
 11201 </xsl:text>
 10123           <xsl:text>    }
 11202           <xsl:text>    }
 10124 </xsl:text>
 11203 </xsl:text>
 10125           <xsl:text>
 11204           <xsl:text>}
 10126 </xsl:text>
 11205 </xsl:text>
 10127           <xsl:text>    forEach(callback) {
 11206           <xsl:text>
 10128 </xsl:text>
 11207 </xsl:text>
 10129           <xsl:text>        for (const element of this) {
 11208           <xsl:text>// Message reception handler
 10130 </xsl:text>
 11209 </xsl:text>
 10131           <xsl:text>            callback(element);
 11210           <xsl:text>// Hash is verified and HMI values updates resulting from binary parsing
       
 11211 </xsl:text>
       
 11212           <xsl:text>// are stored until browser can compute next frame, DOM is left untouched
       
 11213 </xsl:text>
       
 11214           <xsl:text>ws.onmessage = function (evt) {
       
 11215 </xsl:text>
       
 11216           <xsl:text>
       
 11217 </xsl:text>
       
 11218           <xsl:text>    let data = evt.data;
       
 11219 </xsl:text>
       
 11220           <xsl:text>    let dv = new DataView(data);
       
 11221 </xsl:text>
       
 11222           <xsl:text>    let i = 0;
       
 11223 </xsl:text>
       
 11224           <xsl:text>    try {
       
 11225 </xsl:text>
       
 11226           <xsl:text>        for(let hash_int of hmi_hash) {
       
 11227 </xsl:text>
       
 11228           <xsl:text>            if(hash_int != dv.getUint8(i)){
       
 11229 </xsl:text>
       
 11230           <xsl:text>                throw new Error("Hash doesn't match");
       
 11231 </xsl:text>
       
 11232           <xsl:text>            };
       
 11233 </xsl:text>
       
 11234           <xsl:text>            i++;
       
 11235 </xsl:text>
       
 11236           <xsl:text>        };
       
 11237 </xsl:text>
       
 11238           <xsl:text>
       
 11239 </xsl:text>
       
 11240           <xsl:text>        while(i &lt; data.byteLength){
       
 11241 </xsl:text>
       
 11242           <xsl:text>            let index = dv.getUint32(i, true);
       
 11243 </xsl:text>
       
 11244           <xsl:text>            i += 4;
       
 11245 </xsl:text>
       
 11246           <xsl:text>            let iectype = hmitree_types[index];
       
 11247 </xsl:text>
       
 11248           <xsl:text>            if(iectype != undefined){
       
 11249 </xsl:text>
       
 11250           <xsl:text>                let dvgetter = dvgetters[iectype];
       
 11251 </xsl:text>
       
 11252           <xsl:text>                let [value, bytesize] = dvgetter(dv,i);
       
 11253 </xsl:text>
       
 11254           <xsl:text>                updates.set(index, value);
       
 11255 </xsl:text>
       
 11256           <xsl:text>                i += bytesize;
       
 11257 </xsl:text>
       
 11258           <xsl:text>            } else {
       
 11259 </xsl:text>
       
 11260           <xsl:text>                throw new Error("Unknown index "+index);
       
 11261 </xsl:text>
       
 11262           <xsl:text>            }
       
 11263 </xsl:text>
       
 11264           <xsl:text>        };
       
 11265 </xsl:text>
       
 11266           <xsl:text>
       
 11267 </xsl:text>
       
 11268           <xsl:text>        apply_updates();
       
 11269 </xsl:text>
       
 11270           <xsl:text>        // register for rendering on next frame, since there are updates
       
 11271 </xsl:text>
       
 11272           <xsl:text>    } catch(err) {
       
 11273 </xsl:text>
       
 11274           <xsl:text>        // 1003 is for "Unsupported Data"
       
 11275 </xsl:text>
       
 11276           <xsl:text>        // ws.close(1003, err.message);
       
 11277 </xsl:text>
       
 11278           <xsl:text>
       
 11279 </xsl:text>
       
 11280           <xsl:text>        // TODO : remove debug alert ?
       
 11281 </xsl:text>
       
 11282           <xsl:text>        alert("Error : "+err.message+"\nHMI will be reloaded.");
       
 11283 </xsl:text>
       
 11284           <xsl:text>
       
 11285 </xsl:text>
       
 11286           <xsl:text>        // force reload ignoring cache
       
 11287 </xsl:text>
       
 11288           <xsl:text>        location.reload(true);
       
 11289 </xsl:text>
       
 11290           <xsl:text>    }
       
 11291 </xsl:text>
       
 11292           <xsl:text>};
       
 11293 </xsl:text>
       
 11294           <xsl:text>
       
 11295 </xsl:text>
       
 11296           <xsl:text>hmi_hash_u8 = new Uint8Array(hmi_hash);
       
 11297 </xsl:text>
       
 11298           <xsl:text>
       
 11299 </xsl:text>
       
 11300           <xsl:text>function send_blob(data) {
       
 11301 </xsl:text>
       
 11302           <xsl:text>    if(data.length &gt; 0) {
       
 11303 </xsl:text>
       
 11304           <xsl:text>        ws.send(new Blob([hmi_hash_u8].concat(data)));
       
 11305 </xsl:text>
       
 11306           <xsl:text>    };
       
 11307 </xsl:text>
       
 11308           <xsl:text>};
       
 11309 </xsl:text>
       
 11310           <xsl:text>
       
 11311 </xsl:text>
       
 11312           <xsl:text>const typedarray_types = {
       
 11313 </xsl:text>
       
 11314           <xsl:text>    INT: (number) =&gt; new Int16Array([number]),
       
 11315 </xsl:text>
       
 11316           <xsl:text>    BOOL: (truth) =&gt; new Int16Array([truth]),
       
 11317 </xsl:text>
       
 11318           <xsl:text>    NODE: (truth) =&gt; new Int16Array([truth]),
       
 11319 </xsl:text>
       
 11320           <xsl:text>    REAL: (number) =&gt; new Float32Array([number]),
       
 11321 </xsl:text>
       
 11322           <xsl:text>    STRING: (str) =&gt; {
       
 11323 </xsl:text>
       
 11324           <xsl:text>        // beremiz default string max size is 128
       
 11325 </xsl:text>
       
 11326           <xsl:text>        str = str.slice(0,128);
       
 11327 </xsl:text>
       
 11328           <xsl:text>        binary = new Uint8Array(str.length + 1);
       
 11329 </xsl:text>
       
 11330           <xsl:text>        binary[0] = str.length;
       
 11331 </xsl:text>
       
 11332           <xsl:text>        for(let i = 0; i &lt; str.length; i++){
       
 11333 </xsl:text>
       
 11334           <xsl:text>            binary[i+1] = str.charCodeAt(i);
 10132 </xsl:text>
 11335 </xsl:text>
 10133           <xsl:text>        }
 11336           <xsl:text>        }
 10134 </xsl:text>
 11337 </xsl:text>
       
 11338           <xsl:text>        return binary;
       
 11339 </xsl:text>
 10135           <xsl:text>    }
 11340           <xsl:text>    }
 10136 </xsl:text>
 11341 </xsl:text>
 10137           <xsl:text>
 11342           <xsl:text>    /* TODO */
 10138 </xsl:text>
 11343 </xsl:text>
 10139           <xsl:text>    map(callback) {
 11344           <xsl:text>};
 10140 </xsl:text>
 11345 </xsl:text>
 10141           <xsl:text>        const result = [];
 11346           <xsl:text>
 10142 </xsl:text>
 11347 </xsl:text>
 10143           <xsl:text>        for (const element of this) {
 11348           <xsl:text>function send_reset() {
 10144 </xsl:text>
 11349 </xsl:text>
 10145           <xsl:text>            result.push(callback(element));
 11350           <xsl:text>    send_blob(new Uint8Array([1])); /* reset = 1 */
       
 11351 </xsl:text>
       
 11352           <xsl:text>};
       
 11353 </xsl:text>
       
 11354           <xsl:text>
       
 11355 </xsl:text>
       
 11356           <xsl:text>var subscriptions = [];
       
 11357 </xsl:text>
       
 11358           <xsl:text>
       
 11359 </xsl:text>
       
 11360           <xsl:text>function subscribers(index) {
       
 11361 </xsl:text>
       
 11362           <xsl:text>    let entry = subscriptions[index];
       
 11363 </xsl:text>
       
 11364           <xsl:text>    let res;
       
 11365 </xsl:text>
       
 11366           <xsl:text>    if(entry == undefined){
       
 11367 </xsl:text>
       
 11368           <xsl:text>        res = new Set();
       
 11369 </xsl:text>
       
 11370           <xsl:text>        subscriptions[index] = [res,0];
       
 11371 </xsl:text>
       
 11372           <xsl:text>    }else{
       
 11373 </xsl:text>
       
 11374           <xsl:text>        [res, _ign] = entry;
       
 11375 </xsl:text>
       
 11376           <xsl:text>    }
       
 11377 </xsl:text>
       
 11378           <xsl:text>    return res
       
 11379 </xsl:text>
       
 11380           <xsl:text>}
       
 11381 </xsl:text>
       
 11382           <xsl:text>
       
 11383 </xsl:text>
       
 11384           <xsl:text>function get_subscription_period(index) {
       
 11385 </xsl:text>
       
 11386           <xsl:text>    let entry = subscriptions[index];
       
 11387 </xsl:text>
       
 11388           <xsl:text>    if(entry == undefined)
       
 11389 </xsl:text>
       
 11390           <xsl:text>        return 0;
       
 11391 </xsl:text>
       
 11392           <xsl:text>    let [_ign, period] = entry;
       
 11393 </xsl:text>
       
 11394           <xsl:text>    return period;
       
 11395 </xsl:text>
       
 11396           <xsl:text>}
       
 11397 </xsl:text>
       
 11398           <xsl:text>
       
 11399 </xsl:text>
       
 11400           <xsl:text>function set_subscription_period(index, period) {
       
 11401 </xsl:text>
       
 11402           <xsl:text>    let entry = subscriptions[index];
       
 11403 </xsl:text>
       
 11404           <xsl:text>    if(entry == undefined){
       
 11405 </xsl:text>
       
 11406           <xsl:text>        subscriptions[index] = [new Set(), period];
       
 11407 </xsl:text>
       
 11408           <xsl:text>    } else {
       
 11409 </xsl:text>
       
 11410           <xsl:text>        entry[1] = period;
       
 11411 </xsl:text>
       
 11412           <xsl:text>    }
       
 11413 </xsl:text>
       
 11414           <xsl:text>}
       
 11415 </xsl:text>
       
 11416           <xsl:text>
       
 11417 </xsl:text>
       
 11418           <xsl:text>if(has_watchdog){
       
 11419 </xsl:text>
       
 11420           <xsl:text>    // artificially subscribe the watchdog widget to "/heartbeat" hmi variable
       
 11421 </xsl:text>
       
 11422           <xsl:text>    // Since dispatch directly calls change_hmi_value,
       
 11423 </xsl:text>
       
 11424           <xsl:text>    // PLC will periodically send variable at given frequency
       
 11425 </xsl:text>
       
 11426           <xsl:text>    subscribers(heartbeat_index).add({
       
 11427 </xsl:text>
       
 11428           <xsl:text>        /* type: "Watchdog", */
       
 11429 </xsl:text>
       
 11430           <xsl:text>        frequency: 1,
       
 11431 </xsl:text>
       
 11432           <xsl:text>        indexes: [heartbeat_index],
       
 11433 </xsl:text>
       
 11434           <xsl:text>        new_hmi_value: function(index, value, oldval) {
       
 11435 </xsl:text>
       
 11436           <xsl:text>            apply_hmi_value(heartbeat_index, value+1);
 10146 </xsl:text>
 11437 </xsl:text>
 10147           <xsl:text>        }
 11438           <xsl:text>        }
 10148 </xsl:text>
 11439 </xsl:text>
 10149           <xsl:text>
 11440           <xsl:text>    });
 10150 </xsl:text>
 11441 </xsl:text>
 10151           <xsl:text>        return result;
 11442           <xsl:text>}
       
 11443 </xsl:text>
       
 11444           <xsl:text>
       
 11445 </xsl:text>
       
 11446           <xsl:text>
       
 11447 </xsl:text>
       
 11448           <xsl:text>var page_fading = "off";
       
 11449 </xsl:text>
       
 11450           <xsl:text>var page_fading_args = "off";
       
 11451 </xsl:text>
       
 11452           <xsl:text>function fading_page_switch(...args){
       
 11453 </xsl:text>
       
 11454           <xsl:text>    if(page_fading == "in_progress")
       
 11455 </xsl:text>
       
 11456           <xsl:text>        page_fading = "forced";
       
 11457 </xsl:text>
       
 11458           <xsl:text>    else
       
 11459 </xsl:text>
       
 11460           <xsl:text>        page_fading = "pending";
       
 11461 </xsl:text>
       
 11462           <xsl:text>    page_fading_args = args;
       
 11463 </xsl:text>
       
 11464           <xsl:text>
       
 11465 </xsl:text>
       
 11466           <xsl:text>    requestHMIAnimation();
       
 11467 </xsl:text>
       
 11468           <xsl:text>
       
 11469 </xsl:text>
       
 11470           <xsl:text>}
       
 11471 </xsl:text>
       
 11472           <xsl:text>document.body.style.backgroundColor = "black";
       
 11473 </xsl:text>
       
 11474           <xsl:text>
       
 11475 </xsl:text>
       
 11476           <xsl:text>// subscribe to per instance current page hmi variable
       
 11477 </xsl:text>
       
 11478           <xsl:text>// PLC must prefix page name with "!" for page switch to happen
       
 11479 </xsl:text>
       
 11480           <xsl:text>subscribers(current_page_var_index).add({
       
 11481 </xsl:text>
       
 11482           <xsl:text>    frequency: 1,
       
 11483 </xsl:text>
       
 11484           <xsl:text>    indexes: [current_page_var_index],
       
 11485 </xsl:text>
       
 11486           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
 11487 </xsl:text>
       
 11488           <xsl:text>        if(value.startsWith("!"))
       
 11489 </xsl:text>
       
 11490           <xsl:text>            fading_page_switch(value.slice(1));
 10152 </xsl:text>
 11491 </xsl:text>
 10153           <xsl:text>    }
 11492           <xsl:text>    }
 10154 </xsl:text>
 11493 </xsl:text>
 10155           <xsl:text>
 11494           <xsl:text>});
 10156 </xsl:text>
 11495 </xsl:text>
 10157           <xsl:text>    filter(callback) {
 11496           <xsl:text>
 10158 </xsl:text>
 11497 </xsl:text>
 10159           <xsl:text>        const result = [];
 11498           <xsl:text>function svg_text_to_multiline(elt) {
 10160 </xsl:text>
 11499 </xsl:text>
 10161           <xsl:text>        for (const element of this) {
 11500           <xsl:text>    return(Array.prototype.map.call(elt.children, x=&gt;x.textContent).join("\n")); 
 10162 </xsl:text>
 11501 </xsl:text>
 10163           <xsl:text>            if (callback(element)) {
 11502           <xsl:text>}
 10164 </xsl:text>
 11503 </xsl:text>
 10165           <xsl:text>                result.push(element);
 11504           <xsl:text>
       
 11505 </xsl:text>
       
 11506           <xsl:text>function multiline_to_svg_text(elt, str, blank) {
       
 11507 </xsl:text>
       
 11508           <xsl:text>    str.split('\n').map((line,i) =&gt; {elt.children[i].textContent = blank?"":line;});
       
 11509 </xsl:text>
       
 11510           <xsl:text>}
       
 11511 </xsl:text>
       
 11512           <xsl:text>
       
 11513 </xsl:text>
       
 11514           <xsl:text>function switch_langnum(langnum) {
       
 11515 </xsl:text>
       
 11516           <xsl:text>    langnum = Math.max(0, Math.min(langs.length - 1, langnum));
       
 11517 </xsl:text>
       
 11518           <xsl:text>
       
 11519 </xsl:text>
       
 11520           <xsl:text>    for (let translation of translations) {
       
 11521 </xsl:text>
       
 11522           <xsl:text>        let [objs, msgs] = translation;
       
 11523 </xsl:text>
       
 11524           <xsl:text>        let msg = msgs[langnum];
       
 11525 </xsl:text>
       
 11526           <xsl:text>        for (let obj of objs) {
       
 11527 </xsl:text>
       
 11528           <xsl:text>            multiline_to_svg_text(obj, msg);
       
 11529 </xsl:text>
       
 11530           <xsl:text>            obj.setAttribute("lang",langnum);
       
 11531 </xsl:text>
       
 11532           <xsl:text>        }
       
 11533 </xsl:text>
       
 11534           <xsl:text>    }
       
 11535 </xsl:text>
       
 11536           <xsl:text>    return langnum;
       
 11537 </xsl:text>
       
 11538           <xsl:text>}
       
 11539 </xsl:text>
       
 11540           <xsl:text>
       
 11541 </xsl:text>
       
 11542           <xsl:text>// backup original texts
       
 11543 </xsl:text>
       
 11544           <xsl:text>for (let translation of translations) {
       
 11545 </xsl:text>
       
 11546           <xsl:text>    let [objs, msgs] = translation;
       
 11547 </xsl:text>
       
 11548           <xsl:text>    msgs.unshift(svg_text_to_multiline(objs[0])); 
       
 11549 </xsl:text>
       
 11550           <xsl:text>}
       
 11551 </xsl:text>
       
 11552           <xsl:text>
       
 11553 </xsl:text>
       
 11554           <xsl:text>var lang_local_index = hmi_local_index("lang");
       
 11555 </xsl:text>
       
 11556           <xsl:text>var langcode_local_index = hmi_local_index("lang_code");
       
 11557 </xsl:text>
       
 11558           <xsl:text>var langname_local_index = hmi_local_index("lang_name");
       
 11559 </xsl:text>
       
 11560           <xsl:text>subscribers(lang_local_index).add({
       
 11561 </xsl:text>
       
 11562           <xsl:text>    indexes: [lang_local_index],
       
 11563 </xsl:text>
       
 11564           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
 11565 </xsl:text>
       
 11566           <xsl:text>        let current_lang =  switch_langnum(value);
       
 11567 </xsl:text>
       
 11568           <xsl:text>        let [langname,langcode] = langs[current_lang];
       
 11569 </xsl:text>
       
 11570           <xsl:text>        apply_hmi_value(langcode_local_index, langcode);
       
 11571 </xsl:text>
       
 11572           <xsl:text>        apply_hmi_value(langname_local_index, langname);
       
 11573 </xsl:text>
       
 11574           <xsl:text>        switch_page();
       
 11575 </xsl:text>
       
 11576           <xsl:text>    }
       
 11577 </xsl:text>
       
 11578           <xsl:text>});
       
 11579 </xsl:text>
       
 11580           <xsl:text>
       
 11581 </xsl:text>
       
 11582           <xsl:text>// returns en_US, fr_FR or en_UK depending on selected language
       
 11583 </xsl:text>
       
 11584           <xsl:text>function get_current_lang_code(){
       
 11585 </xsl:text>
       
 11586           <xsl:text>    return cache[langcode_local_index];
       
 11587 </xsl:text>
       
 11588           <xsl:text>}
       
 11589 </xsl:text>
       
 11590           <xsl:text>
       
 11591 </xsl:text>
       
 11592           <xsl:text>function setup_lang(){
       
 11593 </xsl:text>
       
 11594           <xsl:text>    let current_lang = cache[lang_local_index];
       
 11595 </xsl:text>
       
 11596           <xsl:text>    let new_lang = switch_langnum(current_lang);
       
 11597 </xsl:text>
       
 11598           <xsl:text>    if(current_lang != new_lang){
       
 11599 </xsl:text>
       
 11600           <xsl:text>        apply_hmi_value(lang_local_index, new_lang);
       
 11601 </xsl:text>
       
 11602           <xsl:text>    }
       
 11603 </xsl:text>
       
 11604           <xsl:text>}
       
 11605 </xsl:text>
       
 11606           <xsl:text>
       
 11607 </xsl:text>
       
 11608           <xsl:text>setup_lang();
       
 11609 </xsl:text>
       
 11610           <xsl:text>
       
 11611 </xsl:text>
       
 11612           <xsl:text>function update_subscriptions() {
       
 11613 </xsl:text>
       
 11614           <xsl:text>    let delta = [];
       
 11615 </xsl:text>
       
 11616           <xsl:text>    for(let index in subscriptions){
       
 11617 </xsl:text>
       
 11618           <xsl:text>        let widgets = subscribers(index);
       
 11619 </xsl:text>
       
 11620           <xsl:text>
       
 11621 </xsl:text>
       
 11622           <xsl:text>        // periods are in ms
       
 11623 </xsl:text>
       
 11624           <xsl:text>        let previous_period = get_subscription_period(index);
       
 11625 </xsl:text>
       
 11626           <xsl:text>
       
 11627 </xsl:text>
       
 11628           <xsl:text>        // subscribing with a zero period is unsubscribing
       
 11629 </xsl:text>
       
 11630           <xsl:text>        let new_period = 0;
       
 11631 </xsl:text>
       
 11632           <xsl:text>        if(widgets.size &gt; 0) {
       
 11633 </xsl:text>
       
 11634           <xsl:text>            let maxfreq = 0;
       
 11635 </xsl:text>
       
 11636           <xsl:text>            for(let widget of widgets){
       
 11637 </xsl:text>
       
 11638           <xsl:text>                let wf = widget.frequency;
       
 11639 </xsl:text>
       
 11640           <xsl:text>                if(wf != undefined &amp;&amp; maxfreq &lt; wf)
       
 11641 </xsl:text>
       
 11642           <xsl:text>                    maxfreq = wf;
 10166 </xsl:text>
 11643 </xsl:text>
 10167           <xsl:text>            }
 11644           <xsl:text>            }
 10168 </xsl:text>
 11645 </xsl:text>
       
 11646           <xsl:text>
       
 11647 </xsl:text>
       
 11648           <xsl:text>            if(maxfreq != 0)
       
 11649 </xsl:text>
       
 11650           <xsl:text>                new_period = 1000/maxfreq;
       
 11651 </xsl:text>
 10169           <xsl:text>        }
 11652           <xsl:text>        }
 10170 </xsl:text>
 11653 </xsl:text>
 10171           <xsl:text>
 11654           <xsl:text>
 10172 </xsl:text>
 11655 </xsl:text>
 10173           <xsl:text>        return result;
 11656           <xsl:text>        if(previous_period != new_period) {
       
 11657 </xsl:text>
       
 11658           <xsl:text>            set_subscription_period(index, new_period);
       
 11659 </xsl:text>
       
 11660           <xsl:text>            if(index &lt;= last_remote_index){
       
 11661 </xsl:text>
       
 11662           <xsl:text>                delta.push(
       
 11663 </xsl:text>
       
 11664           <xsl:text>                    new Uint8Array([2]), /* subscribe = 2 */
       
 11665 </xsl:text>
       
 11666           <xsl:text>                    new Uint32Array([index]),
       
 11667 </xsl:text>
       
 11668           <xsl:text>                    new Uint16Array([new_period]));
       
 11669 </xsl:text>
       
 11670           <xsl:text>            }
       
 11671 </xsl:text>
       
 11672           <xsl:text>        }
 10174 </xsl:text>
 11673 </xsl:text>
 10175           <xsl:text>    }
 11674           <xsl:text>    }
 10176 </xsl:text>
 11675 </xsl:text>
 10177           <xsl:text>
 11676           <xsl:text>    send_blob(delta);
 10178 </xsl:text>
 11677 </xsl:text>
 10179           <xsl:text>    reduce(callback, initialValue) {
 11678           <xsl:text>};
 10180 </xsl:text>
 11679 </xsl:text>
 10181           <xsl:text>        let empty = typeof initialValue === 'undefined';
 11680           <xsl:text>
 10182 </xsl:text>
 11681 </xsl:text>
 10183           <xsl:text>        let accumulator = initialValue;
 11682           <xsl:text>function send_hmi_value(index, value) {
 10184 </xsl:text>
 11683 </xsl:text>
 10185           <xsl:text>        let index = 0;
 11684           <xsl:text>    if(index &gt; last_remote_index){
 10186 </xsl:text>
 11685 </xsl:text>
 10187           <xsl:text>        for (const currentValue of this) {
 11686           <xsl:text>        dispatch_value(index, value);
 10188 </xsl:text>
 11687 </xsl:text>
 10189           <xsl:text>            if (empty) {
 11688           <xsl:text>
 10190 </xsl:text>
 11689 </xsl:text>
 10191           <xsl:text>                accumulator = currentValue;
 11690           <xsl:text>        if(persistent_indexes.has(index)){
 10192 </xsl:text>
 11691 </xsl:text>
 10193           <xsl:text>                empty = false;
 11692           <xsl:text>            let varname = persistent_indexes.get(index);
 10194 </xsl:text>
 11693 </xsl:text>
 10195           <xsl:text>                continue;
 11694           <xsl:text>            document.cookie = varname+"="+value+"; max-age=3153600000";
 10196 </xsl:text>
       
 10197           <xsl:text>            }
       
 10198 </xsl:text>
       
 10199           <xsl:text>
       
 10200 </xsl:text>
       
 10201           <xsl:text>            accumulator = callback(accumulator, currentValue, index, this);
       
 10202 </xsl:text>
       
 10203           <xsl:text>            index++;
       
 10204 </xsl:text>
 11695 </xsl:text>
 10205           <xsl:text>        }
 11696           <xsl:text>        }
 10206 </xsl:text>
 11697 </xsl:text>
 10207           <xsl:text>
 11698           <xsl:text>
 10208 </xsl:text>
       
 10209           <xsl:text>        if (empty) {
       
 10210 </xsl:text>
       
 10211           <xsl:text>            throw new TypeError('Reduce of empty Iterator with no initial value');
       
 10212 </xsl:text>
       
 10213           <xsl:text>        }
       
 10214 </xsl:text>
       
 10215           <xsl:text>
       
 10216 </xsl:text>
       
 10217           <xsl:text>        return accumulator;
       
 10218 </xsl:text>
       
 10219           <xsl:text>    }
       
 10220 </xsl:text>
       
 10221           <xsl:text>
       
 10222 </xsl:text>
       
 10223           <xsl:text>    some(callback) {
       
 10224 </xsl:text>
       
 10225           <xsl:text>        for (const element of this) {
       
 10226 </xsl:text>
       
 10227           <xsl:text>            if (callback(element)) {
       
 10228 </xsl:text>
       
 10229           <xsl:text>                return true;
       
 10230 </xsl:text>
       
 10231           <xsl:text>            }
       
 10232 </xsl:text>
       
 10233           <xsl:text>        }
       
 10234 </xsl:text>
       
 10235           <xsl:text>
       
 10236 </xsl:text>
       
 10237           <xsl:text>        return false;
       
 10238 </xsl:text>
       
 10239           <xsl:text>    }
       
 10240 </xsl:text>
       
 10241           <xsl:text>
       
 10242 </xsl:text>
       
 10243           <xsl:text>    every(callback) {
       
 10244 </xsl:text>
       
 10245           <xsl:text>        for (const element of this) {
       
 10246 </xsl:text>
       
 10247           <xsl:text>            if (!callback(element)) {
       
 10248 </xsl:text>
       
 10249           <xsl:text>                return false;
       
 10250 </xsl:text>
       
 10251           <xsl:text>            }
       
 10252 </xsl:text>
       
 10253           <xsl:text>        }
       
 10254 </xsl:text>
       
 10255           <xsl:text>
       
 10256 </xsl:text>
       
 10257           <xsl:text>        return true;
       
 10258 </xsl:text>
       
 10259           <xsl:text>    }
       
 10260 </xsl:text>
       
 10261           <xsl:text>
       
 10262 </xsl:text>
       
 10263           <xsl:text>    static fromIterable(iterable) {
       
 10264 </xsl:text>
       
 10265           <xsl:text>        return new Iterator(function * () {
       
 10266 </xsl:text>
       
 10267           <xsl:text>            for (const element of iterable) {
       
 10268 </xsl:text>
       
 10269           <xsl:text>                yield element;
       
 10270 </xsl:text>
       
 10271           <xsl:text>            }
       
 10272 </xsl:text>
       
 10273           <xsl:text>        });
       
 10274 </xsl:text>
       
 10275           <xsl:text>    }
       
 10276 </xsl:text>
       
 10277           <xsl:text>
       
 10278 </xsl:text>
       
 10279           <xsl:text>    toArray() {
       
 10280 </xsl:text>
       
 10281           <xsl:text>        return Array.from(this);
       
 10282 </xsl:text>
       
 10283           <xsl:text>    }
       
 10284 </xsl:text>
       
 10285           <xsl:text>
       
 10286 </xsl:text>
       
 10287           <xsl:text>    next() {
       
 10288 </xsl:text>
       
 10289           <xsl:text>        if (!this.currentInvokedGenerator) {
       
 10290 </xsl:text>
       
 10291           <xsl:text>            this.currentInvokedGenerator = this[Symbol.iterator]();
       
 10292 </xsl:text>
       
 10293           <xsl:text>        }
       
 10294 </xsl:text>
       
 10295           <xsl:text>
       
 10296 </xsl:text>
       
 10297           <xsl:text>        return this.currentInvokedGenerator.next();
       
 10298 </xsl:text>
       
 10299           <xsl:text>    }
       
 10300 </xsl:text>
       
 10301           <xsl:text>
       
 10302 </xsl:text>
       
 10303           <xsl:text>    reset() {
       
 10304 </xsl:text>
       
 10305           <xsl:text>        delete this.currentInvokedGenerator;
       
 10306 </xsl:text>
       
 10307           <xsl:text>    }
       
 10308 </xsl:text>
       
 10309           <xsl:text>}
       
 10310 </xsl:text>
       
 10311           <xsl:text>
       
 10312 </xsl:text>
       
 10313           <xsl:text>function rangeSimple(stop) {
       
 10314 </xsl:text>
       
 10315           <xsl:text>    return new Iterator(function * () {
       
 10316 </xsl:text>
       
 10317           <xsl:text>        for (let i = 0; i &lt; stop; i++) {
       
 10318 </xsl:text>
       
 10319           <xsl:text>            yield i;
       
 10320 </xsl:text>
       
 10321           <xsl:text>        }
       
 10322 </xsl:text>
       
 10323           <xsl:text>    });
       
 10324 </xsl:text>
       
 10325           <xsl:text>}
       
 10326 </xsl:text>
       
 10327           <xsl:text>
       
 10328 </xsl:text>
       
 10329           <xsl:text>function rangeOverload(start, stop, step = 1) {
       
 10330 </xsl:text>
       
 10331           <xsl:text>    return new Iterator(function * () {
       
 10332 </xsl:text>
       
 10333           <xsl:text>        for (let i = start; i &lt; stop; i += step) {
       
 10334 </xsl:text>
       
 10335           <xsl:text>            yield i;
       
 10336 </xsl:text>
       
 10337           <xsl:text>        }
       
 10338 </xsl:text>
       
 10339           <xsl:text>    });
       
 10340 </xsl:text>
       
 10341           <xsl:text>}
       
 10342 </xsl:text>
       
 10343           <xsl:text>
       
 10344 </xsl:text>
       
 10345           <xsl:text>function range(...args) {
       
 10346 </xsl:text>
       
 10347           <xsl:text>    if (args.length &lt; 2) {
       
 10348 </xsl:text>
       
 10349           <xsl:text>        return rangeSimple(...args);
       
 10350 </xsl:text>
       
 10351           <xsl:text>    }
       
 10352 </xsl:text>
       
 10353           <xsl:text>
       
 10354 </xsl:text>
       
 10355           <xsl:text>    return rangeOverload(...args);
       
 10356 </xsl:text>
       
 10357           <xsl:text>}
       
 10358 </xsl:text>
       
 10359           <xsl:text>
       
 10360 </xsl:text>
       
 10361           <xsl:text>function enumerate(iterable) {
       
 10362 </xsl:text>
       
 10363           <xsl:text>    return new Iterator(function * () {
       
 10364 </xsl:text>
       
 10365           <xsl:text>        let index = 0;
       
 10366 </xsl:text>
       
 10367           <xsl:text>        for (const element of iterable) {
       
 10368 </xsl:text>
       
 10369           <xsl:text>            yield [index, element];
       
 10370 </xsl:text>
       
 10371           <xsl:text>            index++;
       
 10372 </xsl:text>
       
 10373           <xsl:text>        }
       
 10374 </xsl:text>
       
 10375           <xsl:text>    });
       
 10376 </xsl:text>
       
 10377           <xsl:text>}
       
 10378 </xsl:text>
       
 10379           <xsl:text>
       
 10380 </xsl:text>
       
 10381           <xsl:text>const _zip = longest =&gt; (...iterables) =&gt; {
       
 10382 </xsl:text>
       
 10383           <xsl:text>    if (iterables.length &lt; 2) {
       
 10384 </xsl:text>
       
 10385           <xsl:text>        throw new TypeError("zip takes 2 iterables at least, "+iterables.length+" given");
       
 10386 </xsl:text>
       
 10387           <xsl:text>    }
       
 10388 </xsl:text>
       
 10389           <xsl:text>
       
 10390 </xsl:text>
       
 10391           <xsl:text>    return new Iterator(function * () {
       
 10392 </xsl:text>
       
 10393           <xsl:text>        const iterators = iterables.map(iterable =&gt; Iterator.fromIterable(iterable));
       
 10394 </xsl:text>
       
 10395           <xsl:text>        while (true) {
       
 10396 </xsl:text>
       
 10397           <xsl:text>            const row = iterators.map(iterator =&gt; iterator.next());
       
 10398 </xsl:text>
       
 10399           <xsl:text>            const check = longest ? row.every.bind(row) : row.some.bind(row);
       
 10400 </xsl:text>
       
 10401           <xsl:text>            if (check(next =&gt; next.done)) {
       
 10402 </xsl:text>
       
 10403           <xsl:text>                return;
       
 10404 </xsl:text>
       
 10405           <xsl:text>            }
       
 10406 </xsl:text>
       
 10407           <xsl:text>
       
 10408 </xsl:text>
       
 10409           <xsl:text>            yield row.map(next =&gt; next.value);
       
 10410 </xsl:text>
       
 10411           <xsl:text>        }
       
 10412 </xsl:text>
       
 10413           <xsl:text>    });
       
 10414 </xsl:text>
       
 10415           <xsl:text>};
       
 10416 </xsl:text>
       
 10417           <xsl:text>
       
 10418 </xsl:text>
       
 10419           <xsl:text>const zip = _zip(false), zipLongest= _zip(true);
       
 10420 </xsl:text>
       
 10421           <xsl:text>
       
 10422 </xsl:text>
       
 10423           <xsl:text>function items(obj) {
       
 10424 </xsl:text>
       
 10425           <xsl:text>    let {keys, get} = obj;
       
 10426 </xsl:text>
       
 10427           <xsl:text>    if (obj instanceof Map) {
       
 10428 </xsl:text>
       
 10429           <xsl:text>        keys = keys.bind(obj);
       
 10430 </xsl:text>
       
 10431           <xsl:text>        get = get.bind(obj);
       
 10432 </xsl:text>
       
 10433           <xsl:text>    } else {
       
 10434 </xsl:text>
       
 10435           <xsl:text>        keys = function () {
       
 10436 </xsl:text>
       
 10437           <xsl:text>            return Object.keys(obj);
       
 10438 </xsl:text>
       
 10439           <xsl:text>        };
       
 10440 </xsl:text>
       
 10441           <xsl:text>
       
 10442 </xsl:text>
       
 10443           <xsl:text>        get = function (key) {
       
 10444 </xsl:text>
       
 10445           <xsl:text>            return obj[key];
       
 10446 </xsl:text>
       
 10447           <xsl:text>        };
       
 10448 </xsl:text>
       
 10449           <xsl:text>    }
       
 10450 </xsl:text>
       
 10451           <xsl:text>
       
 10452 </xsl:text>
       
 10453           <xsl:text>    return new Iterator(function * () {
       
 10454 </xsl:text>
       
 10455           <xsl:text>        for (const key of keys()) {
       
 10456 </xsl:text>
       
 10457           <xsl:text>            yield [key, get(key)];
       
 10458 </xsl:text>
       
 10459           <xsl:text>        }
       
 10460 </xsl:text>
       
 10461           <xsl:text>    });
       
 10462 </xsl:text>
       
 10463           <xsl:text>}
       
 10464 </xsl:text>
       
 10465           <xsl:text>
       
 10466 </xsl:text>
       
 10467           <xsl:text>/*
       
 10468 </xsl:text>
       
 10469           <xsl:text>module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items};
       
 10470 </xsl:text>
       
 10471           <xsl:text>*/
       
 10472 </xsl:text>
       
 10473           <xsl:text>// svghmi.js
       
 10474 </xsl:text>
       
 10475           <xsl:text>
       
 10476 </xsl:text>
       
 10477           <xsl:text>var need_cache_apply = [];
       
 10478 </xsl:text>
       
 10479           <xsl:text>
       
 10480 </xsl:text>
       
 10481           <xsl:text>function dispatch_value(index, value) {
       
 10482 </xsl:text>
       
 10483           <xsl:text>    let widgets = subscribers(index);
       
 10484 </xsl:text>
       
 10485           <xsl:text>
       
 10486 </xsl:text>
       
 10487           <xsl:text>    let oldval = cache[index];
       
 10488 </xsl:text>
       
 10489           <xsl:text>    cache[index] = value;
       
 10490 </xsl:text>
       
 10491           <xsl:text>
       
 10492 </xsl:text>
       
 10493           <xsl:text>    if(widgets.size &gt; 0) {
       
 10494 </xsl:text>
       
 10495           <xsl:text>        for(let widget of widgets){
       
 10496 </xsl:text>
       
 10497           <xsl:text>            widget.new_hmi_value(index, value, oldval);
       
 10498 </xsl:text>
       
 10499           <xsl:text>        }
       
 10500 </xsl:text>
       
 10501           <xsl:text>    }
       
 10502 </xsl:text>
       
 10503           <xsl:text>};
       
 10504 </xsl:text>
       
 10505           <xsl:text>
       
 10506 </xsl:text>
       
 10507           <xsl:text>function init_widgets() {
       
 10508 </xsl:text>
       
 10509           <xsl:text>    Object.keys(hmi_widgets).forEach(function(id) {
       
 10510 </xsl:text>
       
 10511           <xsl:text>        let widget = hmi_widgets[id];
       
 10512 </xsl:text>
       
 10513           <xsl:text>        widget.do_init();
       
 10514 </xsl:text>
       
 10515           <xsl:text>    });
       
 10516 </xsl:text>
       
 10517           <xsl:text>};
       
 10518 </xsl:text>
       
 10519           <xsl:text>
       
 10520 </xsl:text>
       
 10521           <xsl:text>// Open WebSocket to relative "/ws" address
       
 10522 </xsl:text>
       
 10523           <xsl:text>var has_watchdog = window.location.hash == "#watchdog";
       
 10524 </xsl:text>
       
 10525           <xsl:text>
       
 10526 </xsl:text>
       
 10527           <xsl:text>var ws_url = 
       
 10528 </xsl:text>
       
 10529           <xsl:text>    window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')
       
 10530 </xsl:text>
       
 10531           <xsl:text>    + '?mode=' + (has_watchdog ? "watchdog" : "multiclient");
       
 10532 </xsl:text>
       
 10533           <xsl:text>
       
 10534 </xsl:text>
       
 10535           <xsl:text>var ws = new WebSocket(ws_url);
       
 10536 </xsl:text>
       
 10537           <xsl:text>ws.binaryType = 'arraybuffer';
       
 10538 </xsl:text>
       
 10539           <xsl:text>
       
 10540 </xsl:text>
       
 10541           <xsl:text>const dvgetters = {
       
 10542 </xsl:text>
       
 10543           <xsl:text>    INT: (dv,offset) =&gt; [dv.getInt16(offset, true), 2],
       
 10544 </xsl:text>
       
 10545           <xsl:text>    BOOL: (dv,offset) =&gt; [dv.getInt8(offset, true), 1],
       
 10546 </xsl:text>
       
 10547           <xsl:text>    NODE: (dv,offset) =&gt; [dv.getInt8(offset, true), 1],
       
 10548 </xsl:text>
       
 10549           <xsl:text>    REAL: (dv,offset) =&gt; [dv.getFloat32(offset, true), 4],
       
 10550 </xsl:text>
       
 10551           <xsl:text>    STRING: (dv, offset) =&gt; {
       
 10552 </xsl:text>
       
 10553           <xsl:text>        const size = dv.getInt8(offset);
       
 10554 </xsl:text>
       
 10555           <xsl:text>        return [
       
 10556 </xsl:text>
       
 10557           <xsl:text>            String.fromCharCode.apply(null, new Uint8Array(
       
 10558 </xsl:text>
       
 10559           <xsl:text>                dv.buffer, /* original buffer */
       
 10560 </xsl:text>
       
 10561           <xsl:text>                offset + 1, /* string starts after size*/
       
 10562 </xsl:text>
       
 10563           <xsl:text>                size /* size of string */
       
 10564 </xsl:text>
       
 10565           <xsl:text>            )), size + 1]; /* total increment */
       
 10566 </xsl:text>
       
 10567           <xsl:text>    }
       
 10568 </xsl:text>
       
 10569           <xsl:text>};
       
 10570 </xsl:text>
       
 10571           <xsl:text>
       
 10572 </xsl:text>
       
 10573           <xsl:text>// Apply updates recieved through ws.onmessage to subscribed widgets
       
 10574 </xsl:text>
       
 10575           <xsl:text>function apply_updates() {
       
 10576 </xsl:text>
       
 10577           <xsl:text>    updates.forEach((value, index) =&gt; {
       
 10578 </xsl:text>
       
 10579           <xsl:text>        dispatch_value(index, value);
       
 10580 </xsl:text>
       
 10581           <xsl:text>    });
       
 10582 </xsl:text>
       
 10583           <xsl:text>    updates.clear();
       
 10584 </xsl:text>
       
 10585           <xsl:text>}
       
 10586 </xsl:text>
       
 10587           <xsl:text>
       
 10588 </xsl:text>
       
 10589           <xsl:text>// Called on requestAnimationFrame, modifies DOM
       
 10590 </xsl:text>
       
 10591           <xsl:text>var requestAnimationFrameID = null;
       
 10592 </xsl:text>
       
 10593           <xsl:text>function animate() {
       
 10594 </xsl:text>
       
 10595           <xsl:text>    let rearm = true;
       
 10596 </xsl:text>
       
 10597           <xsl:text>    do{
       
 10598 </xsl:text>
       
 10599           <xsl:text>        if(page_fading == "pending" || page_fading == "forced"){
       
 10600 </xsl:text>
       
 10601           <xsl:text>            if(page_fading == "pending")
       
 10602 </xsl:text>
       
 10603           <xsl:text>                svg_root.classList.add("fade-out-page");
       
 10604 </xsl:text>
       
 10605           <xsl:text>            page_fading = "in_progress";
       
 10606 </xsl:text>
       
 10607           <xsl:text>            if(page_fading_args.length)
       
 10608 </xsl:text>
       
 10609           <xsl:text>                setTimeout(function(){
       
 10610 </xsl:text>
       
 10611           <xsl:text>                    switch_page(...page_fading_args);
       
 10612 </xsl:text>
       
 10613           <xsl:text>                },1);
       
 10614 </xsl:text>
       
 10615           <xsl:text>            break;
       
 10616 </xsl:text>
       
 10617           <xsl:text>        }
       
 10618 </xsl:text>
       
 10619           <xsl:text>
       
 10620 </xsl:text>
       
 10621           <xsl:text>        // Do the page swith if pending
       
 10622 </xsl:text>
       
 10623           <xsl:text>        if(page_switch_in_progress){
       
 10624 </xsl:text>
       
 10625           <xsl:text>            if(current_subscribed_page != current_visible_page){
       
 10626 </xsl:text>
       
 10627           <xsl:text>                switch_visible_page(current_subscribed_page);
       
 10628 </xsl:text>
       
 10629           <xsl:text>            }
       
 10630 </xsl:text>
       
 10631           <xsl:text>
       
 10632 </xsl:text>
       
 10633           <xsl:text>            page_switch_in_progress = false;
       
 10634 </xsl:text>
       
 10635           <xsl:text>
       
 10636 </xsl:text>
       
 10637           <xsl:text>            if(page_fading == "in_progress"){
       
 10638 </xsl:text>
       
 10639           <xsl:text>                svg_root.classList.remove("fade-out-page");
       
 10640 </xsl:text>
       
 10641           <xsl:text>                page_fading = "off";
       
 10642 </xsl:text>
       
 10643           <xsl:text>            }
       
 10644 </xsl:text>
       
 10645           <xsl:text>        }
       
 10646 </xsl:text>
       
 10647           <xsl:text>
       
 10648 </xsl:text>
       
 10649           <xsl:text>        while(widget = need_cache_apply.pop()){
       
 10650 </xsl:text>
       
 10651           <xsl:text>            widget.apply_cache();
       
 10652 </xsl:text>
       
 10653           <xsl:text>        }
       
 10654 </xsl:text>
       
 10655           <xsl:text>
       
 10656 </xsl:text>
       
 10657           <xsl:text>        if(jumps_need_update) update_jumps();
       
 10658 </xsl:text>
       
 10659           <xsl:text>
       
 10660 </xsl:text>
       
 10661           <xsl:text>        apply_updates();
       
 10662 </xsl:text>
       
 10663           <xsl:text>
       
 10664 </xsl:text>
       
 10665           <xsl:text>        pending_widget_animates.forEach(widget =&gt; widget._animate());
       
 10666 </xsl:text>
       
 10667           <xsl:text>        pending_widget_animates = [];
       
 10668 </xsl:text>
       
 10669           <xsl:text>        rearm = false;
       
 10670 </xsl:text>
       
 10671           <xsl:text>    } while(0);
       
 10672 </xsl:text>
       
 10673           <xsl:text>
       
 10674 </xsl:text>
       
 10675           <xsl:text>    requestAnimationFrameID = null;
       
 10676 </xsl:text>
       
 10677           <xsl:text>
       
 10678 </xsl:text>
       
 10679           <xsl:text>    if(rearm) requestHMIAnimation();
       
 10680 </xsl:text>
       
 10681           <xsl:text>}
       
 10682 </xsl:text>
       
 10683           <xsl:text>
       
 10684 </xsl:text>
       
 10685           <xsl:text>function requestHMIAnimation() {
       
 10686 </xsl:text>
       
 10687           <xsl:text>    if(requestAnimationFrameID == null){
       
 10688 </xsl:text>
       
 10689           <xsl:text>        requestAnimationFrameID = window.requestAnimationFrame(animate);
       
 10690 </xsl:text>
       
 10691           <xsl:text>    }
       
 10692 </xsl:text>
       
 10693           <xsl:text>}
       
 10694 </xsl:text>
       
 10695           <xsl:text>
       
 10696 </xsl:text>
       
 10697           <xsl:text>// Message reception handler
       
 10698 </xsl:text>
       
 10699           <xsl:text>// Hash is verified and HMI values updates resulting from binary parsing
       
 10700 </xsl:text>
       
 10701           <xsl:text>// are stored until browser can compute next frame, DOM is left untouched
       
 10702 </xsl:text>
       
 10703           <xsl:text>ws.onmessage = function (evt) {
       
 10704 </xsl:text>
       
 10705           <xsl:text>
       
 10706 </xsl:text>
       
 10707           <xsl:text>    let data = evt.data;
       
 10708 </xsl:text>
       
 10709           <xsl:text>    let dv = new DataView(data);
       
 10710 </xsl:text>
       
 10711           <xsl:text>    let i = 0;
       
 10712 </xsl:text>
       
 10713           <xsl:text>    try {
       
 10714 </xsl:text>
       
 10715           <xsl:text>        for(let hash_int of hmi_hash) {
       
 10716 </xsl:text>
       
 10717           <xsl:text>            if(hash_int != dv.getUint8(i)){
       
 10718 </xsl:text>
       
 10719           <xsl:text>                throw new Error("Hash doesn't match");
       
 10720 </xsl:text>
       
 10721           <xsl:text>            };
       
 10722 </xsl:text>
       
 10723           <xsl:text>            i++;
       
 10724 </xsl:text>
       
 10725           <xsl:text>        };
       
 10726 </xsl:text>
       
 10727           <xsl:text>
       
 10728 </xsl:text>
       
 10729           <xsl:text>        while(i &lt; data.byteLength){
       
 10730 </xsl:text>
       
 10731           <xsl:text>            let index = dv.getUint32(i, true);
       
 10732 </xsl:text>
       
 10733           <xsl:text>            i += 4;
       
 10734 </xsl:text>
       
 10735           <xsl:text>            let iectype = hmitree_types[index];
       
 10736 </xsl:text>
       
 10737           <xsl:text>            if(iectype != undefined){
       
 10738 </xsl:text>
       
 10739           <xsl:text>                let dvgetter = dvgetters[iectype];
       
 10740 </xsl:text>
       
 10741           <xsl:text>                let [value, bytesize] = dvgetter(dv,i);
       
 10742 </xsl:text>
       
 10743           <xsl:text>                updates.set(index, value);
       
 10744 </xsl:text>
       
 10745           <xsl:text>                i += bytesize;
       
 10746 </xsl:text>
       
 10747           <xsl:text>            } else {
       
 10748 </xsl:text>
       
 10749           <xsl:text>                throw new Error("Unknown index "+index);
       
 10750 </xsl:text>
       
 10751           <xsl:text>            }
       
 10752 </xsl:text>
       
 10753           <xsl:text>        };
       
 10754 </xsl:text>
       
 10755           <xsl:text>        // register for rendering on next frame, since there are updates
       
 10756 </xsl:text>
       
 10757           <xsl:text>        requestHMIAnimation();
       
 10758 </xsl:text>
       
 10759           <xsl:text>    } catch(err) {
       
 10760 </xsl:text>
       
 10761           <xsl:text>        // 1003 is for "Unsupported Data"
       
 10762 </xsl:text>
       
 10763           <xsl:text>        // ws.close(1003, err.message);
       
 10764 </xsl:text>
       
 10765           <xsl:text>
       
 10766 </xsl:text>
       
 10767           <xsl:text>        // TODO : remove debug alert ?
       
 10768 </xsl:text>
       
 10769           <xsl:text>        alert("Error : "+err.message+"\nHMI will be reloaded.");
       
 10770 </xsl:text>
       
 10771           <xsl:text>
       
 10772 </xsl:text>
       
 10773           <xsl:text>        // force reload ignoring cache
       
 10774 </xsl:text>
       
 10775           <xsl:text>        location.reload(true);
       
 10776 </xsl:text>
       
 10777           <xsl:text>    }
       
 10778 </xsl:text>
       
 10779           <xsl:text>};
       
 10780 </xsl:text>
       
 10781           <xsl:text>
       
 10782 </xsl:text>
       
 10783           <xsl:text>hmi_hash_u8 = new Uint8Array(hmi_hash);
       
 10784 </xsl:text>
       
 10785           <xsl:text>
       
 10786 </xsl:text>
       
 10787           <xsl:text>function send_blob(data) {
       
 10788 </xsl:text>
       
 10789           <xsl:text>    if(data.length &gt; 0) {
       
 10790 </xsl:text>
       
 10791           <xsl:text>        ws.send(new Blob([hmi_hash_u8].concat(data)));
       
 10792 </xsl:text>
       
 10793           <xsl:text>    };
       
 10794 </xsl:text>
       
 10795           <xsl:text>};
       
 10796 </xsl:text>
       
 10797           <xsl:text>
       
 10798 </xsl:text>
       
 10799           <xsl:text>const typedarray_types = {
       
 10800 </xsl:text>
       
 10801           <xsl:text>    INT: (number) =&gt; new Int16Array([number]),
       
 10802 </xsl:text>
       
 10803           <xsl:text>    BOOL: (truth) =&gt; new Int16Array([truth]),
       
 10804 </xsl:text>
       
 10805           <xsl:text>    NODE: (truth) =&gt; new Int16Array([truth]),
       
 10806 </xsl:text>
       
 10807           <xsl:text>    REAL: (number) =&gt; new Float32Array([number]),
       
 10808 </xsl:text>
       
 10809           <xsl:text>    STRING: (str) =&gt; {
       
 10810 </xsl:text>
       
 10811           <xsl:text>        // beremiz default string max size is 128
       
 10812 </xsl:text>
       
 10813           <xsl:text>        str = str.slice(0,128);
       
 10814 </xsl:text>
       
 10815           <xsl:text>        binary = new Uint8Array(str.length + 1);
       
 10816 </xsl:text>
       
 10817           <xsl:text>        binary[0] = str.length;
       
 10818 </xsl:text>
       
 10819           <xsl:text>        for(let i = 0; i &lt; str.length; i++){
       
 10820 </xsl:text>
       
 10821           <xsl:text>            binary[i+1] = str.charCodeAt(i);
       
 10822 </xsl:text>
       
 10823           <xsl:text>        }
       
 10824 </xsl:text>
       
 10825           <xsl:text>        return binary;
       
 10826 </xsl:text>
       
 10827           <xsl:text>    }
       
 10828 </xsl:text>
       
 10829           <xsl:text>    /* TODO */
       
 10830 </xsl:text>
       
 10831           <xsl:text>};
       
 10832 </xsl:text>
       
 10833           <xsl:text>
       
 10834 </xsl:text>
       
 10835           <xsl:text>function send_reset() {
       
 10836 </xsl:text>
       
 10837           <xsl:text>    send_blob(new Uint8Array([1])); /* reset = 1 */
       
 10838 </xsl:text>
       
 10839           <xsl:text>};
       
 10840 </xsl:text>
       
 10841           <xsl:text>
       
 10842 </xsl:text>
       
 10843           <xsl:text>var subscriptions = [];
       
 10844 </xsl:text>
       
 10845           <xsl:text>
       
 10846 </xsl:text>
       
 10847           <xsl:text>function subscribers(index) {
       
 10848 </xsl:text>
       
 10849           <xsl:text>    let entry = subscriptions[index];
       
 10850 </xsl:text>
       
 10851           <xsl:text>    let res;
       
 10852 </xsl:text>
       
 10853           <xsl:text>    if(entry == undefined){
       
 10854 </xsl:text>
       
 10855           <xsl:text>        res = new Set();
       
 10856 </xsl:text>
       
 10857           <xsl:text>        subscriptions[index] = [res,0];
       
 10858 </xsl:text>
       
 10859           <xsl:text>    }else{
       
 10860 </xsl:text>
       
 10861           <xsl:text>        [res, _ign] = entry;
       
 10862 </xsl:text>
       
 10863           <xsl:text>    }
       
 10864 </xsl:text>
       
 10865           <xsl:text>    return res
       
 10866 </xsl:text>
       
 10867           <xsl:text>}
       
 10868 </xsl:text>
       
 10869           <xsl:text>
       
 10870 </xsl:text>
       
 10871           <xsl:text>function get_subscription_period(index) {
       
 10872 </xsl:text>
       
 10873           <xsl:text>    let entry = subscriptions[index];
       
 10874 </xsl:text>
       
 10875           <xsl:text>    if(entry == undefined)
       
 10876 </xsl:text>
       
 10877           <xsl:text>        return 0;
       
 10878 </xsl:text>
       
 10879           <xsl:text>    let [_ign, period] = entry;
       
 10880 </xsl:text>
       
 10881           <xsl:text>    return period;
       
 10882 </xsl:text>
       
 10883           <xsl:text>}
       
 10884 </xsl:text>
       
 10885           <xsl:text>
       
 10886 </xsl:text>
       
 10887           <xsl:text>function set_subscription_period(index, period) {
       
 10888 </xsl:text>
       
 10889           <xsl:text>    let entry = subscriptions[index];
       
 10890 </xsl:text>
       
 10891           <xsl:text>    if(entry == undefined){
       
 10892 </xsl:text>
       
 10893           <xsl:text>        subscriptions[index] = [new Set(), period];
       
 10894 </xsl:text>
       
 10895           <xsl:text>    } else {
       
 10896 </xsl:text>
       
 10897           <xsl:text>        entry[1] = period;
       
 10898 </xsl:text>
       
 10899           <xsl:text>    }
       
 10900 </xsl:text>
       
 10901           <xsl:text>}
       
 10902 </xsl:text>
       
 10903           <xsl:text>
       
 10904 </xsl:text>
       
 10905           <xsl:text>if(has_watchdog){
       
 10906 </xsl:text>
       
 10907           <xsl:text>    // artificially subscribe the watchdog widget to "/heartbeat" hmi variable
       
 10908 </xsl:text>
       
 10909           <xsl:text>    // Since dispatch directly calls change_hmi_value,
       
 10910 </xsl:text>
       
 10911           <xsl:text>    // PLC will periodically send variable at given frequency
       
 10912 </xsl:text>
       
 10913           <xsl:text>    subscribers(heartbeat_index).add({
       
 10914 </xsl:text>
       
 10915           <xsl:text>        /* type: "Watchdog", */
       
 10916 </xsl:text>
       
 10917           <xsl:text>        frequency: 1,
       
 10918 </xsl:text>
       
 10919           <xsl:text>        indexes: [heartbeat_index],
       
 10920 </xsl:text>
       
 10921           <xsl:text>        new_hmi_value: function(index, value, oldval) {
       
 10922 </xsl:text>
       
 10923           <xsl:text>            apply_hmi_value(heartbeat_index, value+1);
       
 10924 </xsl:text>
       
 10925           <xsl:text>        }
       
 10926 </xsl:text>
       
 10927           <xsl:text>    });
       
 10928 </xsl:text>
       
 10929           <xsl:text>}
       
 10930 </xsl:text>
       
 10931           <xsl:text>
       
 10932 </xsl:text>
       
 10933           <xsl:text>
       
 10934 </xsl:text>
       
 10935           <xsl:text>var page_fading = "off";
       
 10936 </xsl:text>
       
 10937           <xsl:text>var page_fading_args = "off";
       
 10938 </xsl:text>
       
 10939           <xsl:text>function fading_page_switch(...args){
       
 10940 </xsl:text>
       
 10941           <xsl:text>    if(page_fading == "in_progress")
       
 10942 </xsl:text>
       
 10943           <xsl:text>        page_fading = "forced";
       
 10944 </xsl:text>
       
 10945           <xsl:text>    else
       
 10946 </xsl:text>
       
 10947           <xsl:text>        page_fading = "pending";
       
 10948 </xsl:text>
       
 10949           <xsl:text>    page_fading_args = args;
       
 10950 </xsl:text>
       
 10951           <xsl:text>
       
 10952 </xsl:text>
       
 10953           <xsl:text>    requestHMIAnimation();
       
 10954 </xsl:text>
       
 10955           <xsl:text>
       
 10956 </xsl:text>
       
 10957           <xsl:text>}
       
 10958 </xsl:text>
       
 10959           <xsl:text>document.body.style.backgroundColor = "black";
       
 10960 </xsl:text>
       
 10961           <xsl:text>
       
 10962 </xsl:text>
       
 10963           <xsl:text>// subscribe to per instance current page hmi variable
       
 10964 </xsl:text>
       
 10965           <xsl:text>// PLC must prefix page name with "!" for page switch to happen
       
 10966 </xsl:text>
       
 10967           <xsl:text>subscribers(current_page_var_index).add({
       
 10968 </xsl:text>
       
 10969           <xsl:text>    frequency: 1,
       
 10970 </xsl:text>
       
 10971           <xsl:text>    indexes: [current_page_var_index],
       
 10972 </xsl:text>
       
 10973           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
 10974 </xsl:text>
       
 10975           <xsl:text>        if(value.startsWith("!"))
       
 10976 </xsl:text>
       
 10977           <xsl:text>            fading_page_switch(value.slice(1));
       
 10978 </xsl:text>
       
 10979           <xsl:text>    }
       
 10980 </xsl:text>
       
 10981           <xsl:text>});
       
 10982 </xsl:text>
       
 10983           <xsl:text>
       
 10984 </xsl:text>
       
 10985           <xsl:text>function svg_text_to_multiline(elt) {
       
 10986 </xsl:text>
       
 10987           <xsl:text>    return(Array.prototype.map.call(elt.children, x=&gt;x.textContent).join("\n")); 
       
 10988 </xsl:text>
       
 10989           <xsl:text>}
       
 10990 </xsl:text>
       
 10991           <xsl:text>
       
 10992 </xsl:text>
       
 10993           <xsl:text>function multiline_to_svg_text(elt, str, blank) {
       
 10994 </xsl:text>
       
 10995           <xsl:text>    str.split('\n').map((line,i) =&gt; {elt.children[i].textContent = blank?"":line;});
       
 10996 </xsl:text>
       
 10997           <xsl:text>}
       
 10998 </xsl:text>
       
 10999           <xsl:text>
       
 11000 </xsl:text>
       
 11001           <xsl:text>function switch_langnum(langnum) {
       
 11002 </xsl:text>
       
 11003           <xsl:text>    langnum = Math.max(0, Math.min(langs.length - 1, langnum));
       
 11004 </xsl:text>
       
 11005           <xsl:text>
       
 11006 </xsl:text>
       
 11007           <xsl:text>    for (let translation of translations) {
       
 11008 </xsl:text>
       
 11009           <xsl:text>        let [objs, msgs] = translation;
       
 11010 </xsl:text>
       
 11011           <xsl:text>        let msg = msgs[langnum];
       
 11012 </xsl:text>
       
 11013           <xsl:text>        for (let obj of objs) {
       
 11014 </xsl:text>
       
 11015           <xsl:text>            multiline_to_svg_text(obj, msg);
       
 11016 </xsl:text>
       
 11017           <xsl:text>            obj.setAttribute("lang",langnum);
       
 11018 </xsl:text>
       
 11019           <xsl:text>        }
       
 11020 </xsl:text>
       
 11021           <xsl:text>    }
       
 11022 </xsl:text>
       
 11023           <xsl:text>    return langnum;
       
 11024 </xsl:text>
       
 11025           <xsl:text>}
       
 11026 </xsl:text>
       
 11027           <xsl:text>
       
 11028 </xsl:text>
       
 11029           <xsl:text>// backup original texts
       
 11030 </xsl:text>
       
 11031           <xsl:text>for (let translation of translations) {
       
 11032 </xsl:text>
       
 11033           <xsl:text>    let [objs, msgs] = translation;
       
 11034 </xsl:text>
       
 11035           <xsl:text>    msgs.unshift(svg_text_to_multiline(objs[0])); 
       
 11036 </xsl:text>
       
 11037           <xsl:text>}
       
 11038 </xsl:text>
       
 11039           <xsl:text>
       
 11040 </xsl:text>
       
 11041           <xsl:text>var lang_local_index = hmi_local_index("lang");
       
 11042 </xsl:text>
       
 11043           <xsl:text>var langcode_local_index = hmi_local_index("lang_code");
       
 11044 </xsl:text>
       
 11045           <xsl:text>var langname_local_index = hmi_local_index("lang_name");
       
 11046 </xsl:text>
       
 11047           <xsl:text>subscribers(lang_local_index).add({
       
 11048 </xsl:text>
       
 11049           <xsl:text>    indexes: [lang_local_index],
       
 11050 </xsl:text>
       
 11051           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
 11052 </xsl:text>
       
 11053           <xsl:text>        let current_lang =  switch_langnum(value);
       
 11054 </xsl:text>
       
 11055           <xsl:text>        let [langname,langcode] = langs[current_lang];
       
 11056 </xsl:text>
       
 11057           <xsl:text>        apply_hmi_value(langcode_local_index, langcode);
       
 11058 </xsl:text>
       
 11059           <xsl:text>        apply_hmi_value(langname_local_index, langname);
       
 11060 </xsl:text>
       
 11061           <xsl:text>        switch_page();
       
 11062 </xsl:text>
       
 11063           <xsl:text>    }
       
 11064 </xsl:text>
       
 11065           <xsl:text>});
       
 11066 </xsl:text>
       
 11067           <xsl:text>
       
 11068 </xsl:text>
       
 11069           <xsl:text>// returns en_US, fr_FR or en_UK depending on selected language
       
 11070 </xsl:text>
       
 11071           <xsl:text>function get_current_lang_code(){
       
 11072 </xsl:text>
       
 11073           <xsl:text>    return cache[langcode_local_index];
       
 11074 </xsl:text>
       
 11075           <xsl:text>}
       
 11076 </xsl:text>
       
 11077           <xsl:text>
       
 11078 </xsl:text>
       
 11079           <xsl:text>function setup_lang(){
       
 11080 </xsl:text>
       
 11081           <xsl:text>    let current_lang = cache[lang_local_index];
       
 11082 </xsl:text>
       
 11083           <xsl:text>    let new_lang = switch_langnum(current_lang);
       
 11084 </xsl:text>
       
 11085           <xsl:text>    if(current_lang != new_lang){
       
 11086 </xsl:text>
       
 11087           <xsl:text>        apply_hmi_value(lang_local_index, new_lang);
       
 11088 </xsl:text>
       
 11089           <xsl:text>    }
       
 11090 </xsl:text>
       
 11091           <xsl:text>}
       
 11092 </xsl:text>
       
 11093           <xsl:text>
       
 11094 </xsl:text>
       
 11095           <xsl:text>setup_lang();
       
 11096 </xsl:text>
       
 11097           <xsl:text>
       
 11098 </xsl:text>
       
 11099           <xsl:text>function update_subscriptions() {
       
 11100 </xsl:text>
       
 11101           <xsl:text>    let delta = [];
       
 11102 </xsl:text>
       
 11103           <xsl:text>    for(let index in subscriptions){
       
 11104 </xsl:text>
       
 11105           <xsl:text>        let widgets = subscribers(index);
       
 11106 </xsl:text>
       
 11107           <xsl:text>
       
 11108 </xsl:text>
       
 11109           <xsl:text>        // periods are in ms
       
 11110 </xsl:text>
       
 11111           <xsl:text>        let previous_period = get_subscription_period(index);
       
 11112 </xsl:text>
       
 11113           <xsl:text>
       
 11114 </xsl:text>
       
 11115           <xsl:text>        // subscribing with a zero period is unsubscribing
       
 11116 </xsl:text>
       
 11117           <xsl:text>        let new_period = 0;
       
 11118 </xsl:text>
       
 11119           <xsl:text>        if(widgets.size &gt; 0) {
       
 11120 </xsl:text>
       
 11121           <xsl:text>            let maxfreq = 0;
       
 11122 </xsl:text>
       
 11123           <xsl:text>            for(let widget of widgets){
       
 11124 </xsl:text>
       
 11125           <xsl:text>                let wf = widget.frequency;
       
 11126 </xsl:text>
       
 11127           <xsl:text>                if(wf != undefined &amp;&amp; maxfreq &lt; wf)
       
 11128 </xsl:text>
       
 11129           <xsl:text>                    maxfreq = wf;
       
 11130 </xsl:text>
       
 11131           <xsl:text>            }
       
 11132 </xsl:text>
       
 11133           <xsl:text>
       
 11134 </xsl:text>
       
 11135           <xsl:text>            if(maxfreq != 0)
       
 11136 </xsl:text>
       
 11137           <xsl:text>                new_period = 1000/maxfreq;
       
 11138 </xsl:text>
       
 11139           <xsl:text>        }
       
 11140 </xsl:text>
       
 11141           <xsl:text>
       
 11142 </xsl:text>
       
 11143           <xsl:text>        if(previous_period != new_period) {
       
 11144 </xsl:text>
       
 11145           <xsl:text>            set_subscription_period(index, new_period);
       
 11146 </xsl:text>
       
 11147           <xsl:text>            if(index &lt;= last_remote_index){
       
 11148 </xsl:text>
       
 11149           <xsl:text>                delta.push(
       
 11150 </xsl:text>
       
 11151           <xsl:text>                    new Uint8Array([2]), /* subscribe = 2 */
       
 11152 </xsl:text>
       
 11153           <xsl:text>                    new Uint32Array([index]),
       
 11154 </xsl:text>
       
 11155           <xsl:text>                    new Uint16Array([new_period]));
       
 11156 </xsl:text>
       
 11157           <xsl:text>            }
       
 11158 </xsl:text>
       
 11159           <xsl:text>        }
       
 11160 </xsl:text>
       
 11161           <xsl:text>    }
       
 11162 </xsl:text>
       
 11163           <xsl:text>    send_blob(delta);
       
 11164 </xsl:text>
       
 11165           <xsl:text>};
       
 11166 </xsl:text>
       
 11167           <xsl:text>
       
 11168 </xsl:text>
       
 11169           <xsl:text>function send_hmi_value(index, value) {
       
 11170 </xsl:text>
       
 11171           <xsl:text>    if(index &gt; last_remote_index){
       
 11172 </xsl:text>
       
 11173           <xsl:text>        updates.set(index, value);
       
 11174 </xsl:text>
       
 11175           <xsl:text>
       
 11176 </xsl:text>
       
 11177           <xsl:text>        if(persistent_indexes.has(index)){
       
 11178 </xsl:text>
       
 11179           <xsl:text>            let varname = persistent_indexes.get(index);
       
 11180 </xsl:text>
       
 11181           <xsl:text>            document.cookie = varname+"="+value+"; max-age=3153600000";
       
 11182 </xsl:text>
       
 11183           <xsl:text>        }
       
 11184 </xsl:text>
       
 11185           <xsl:text>
       
 11186 </xsl:text>
       
 11187           <xsl:text>        requestHMIAnimation();
       
 11188 </xsl:text>
 11699 </xsl:text>
 11189           <xsl:text>        return;
 11700           <xsl:text>        return;
 11190 </xsl:text>
 11701 </xsl:text>
 11191           <xsl:text>    }
 11702           <xsl:text>    }
 11192 </xsl:text>
 11703 </xsl:text>