svghmi/gen_index_xhtml.xslt
changeset 3621 da020d88db0c
parent 3557 59158e360b8c
child 3629 f117526d41ba
equal deleted inserted replaced
3613:7af7a23e4adb 3621:da020d88db0c
   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">
       
   164     <xsl:text>
       
   165 </xsl:text>
       
   166   </xsl:variable>
       
   167   <xsl:variable name="twonewlines" select="concat($newline,$newline)"/>
   163   <xsl:template mode="parselabel" match="*">
   168   <xsl:template mode="parselabel" match="*">
   164     <xsl:variable name="label" select="@inkscape:label"/>
   169     <xsl:variable name="label" select="@inkscape:label"/>
       
   170     <xsl:variable name="desc" select="svg:desc"/>
       
   171     <xsl:variable name="len" select="string-length($label)"/>
       
   172     <xsl:variable name="has_continuation" select="substring($label,$len,1)='\'"/>
       
   173     <xsl:variable name="full_decl">
       
   174       <xsl:choose>
       
   175         <xsl:when test="$has_continuation">
       
   176           <xsl:variable name="_continuation" select="substring-before($desc, $twonewlines)"/>
       
   177           <xsl:variable name="continuation">
       
   178             <xsl:choose>
       
   179               <xsl:when test="$_continuation">
       
   180                 <xsl:value-of select="$_continuation"/>
       
   181               </xsl:when>
       
   182               <xsl:otherwise>
       
   183                 <xsl:value-of select="$desc"/>
       
   184               </xsl:otherwise>
       
   185             </xsl:choose>
       
   186           </xsl:variable>
       
   187           <xsl:value-of select="concat(substring($label,1,$len - 1),translate($continuation,$newline,''))"/>
       
   188         </xsl:when>
       
   189         <xsl:otherwise>
       
   190           <xsl:value-of select="$label"/>
       
   191         </xsl:otherwise>
       
   192       </xsl:choose>
       
   193     </xsl:variable>
   165     <xsl:variable name="id" select="@id"/>
   194     <xsl:variable name="id" select="@id"/>
   166     <xsl:variable name="description" select="substring-after($label,'HMI:')"/>
   195     <xsl:variable name="declaration" select="substring-after($full_decl,'HMI:')"/>
   167     <xsl:variable name="_args" select="substring-before($description,'@')"/>
   196     <xsl:variable name="_args" select="substring-before($declaration,'@')"/>
   168     <xsl:variable name="args">
   197     <xsl:variable name="args">
   169       <xsl:choose>
   198       <xsl:choose>
   170         <xsl:when test="$_args">
   199         <xsl:when test="$_args">
   171           <xsl:value-of select="$_args"/>
   200           <xsl:value-of select="$_args"/>
   172         </xsl:when>
   201         </xsl:when>
   173         <xsl:otherwise>
   202         <xsl:otherwise>
   174           <xsl:value-of select="$description"/>
   203           <xsl:value-of select="$declaration"/>
   175         </xsl:otherwise>
   204         </xsl:otherwise>
   176       </xsl:choose>
   205       </xsl:choose>
   177     </xsl:variable>
   206     </xsl:variable>
   178     <xsl:variable name="_typefreq" select="substring-before($args,':')"/>
   207     <xsl:variable name="_typefreq" select="substring-before($args,':')"/>
   179     <xsl:variable name="typefreq">
   208     <xsl:variable name="typefreq">
   210           <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]?'))">
   211             <xsl:message terminate="yes">
   240             <xsl:message terminate="yes">
   212               <xsl:text>Widget id:</xsl:text>
   241               <xsl:text>Widget id:</xsl:text>
   213               <xsl:value-of select="$id"/>
   242               <xsl:value-of select="$id"/>
   214               <xsl:text> label:</xsl:text>
   243               <xsl:text> label:</xsl:text>
   215               <xsl:value-of select="$label"/>
   244               <xsl:value-of select="$full_decl"/>
   216               <xsl:text> has wrong syntax of frequency forcing </xsl:text>
   245               <xsl:text> has wrong syntax of frequency forcing </xsl:text>
   217               <xsl:value-of select="$freq"/>
   246               <xsl:value-of select="$freq"/>
   218             </xsl:message>
   247             </xsl:message>
   219           </xsl:if>
   248           </xsl:if>
   220           <xsl:attribute name="freq">
   249           <xsl:attribute name="freq">
   221             <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"/>
   222           </xsl:attribute>
   270           </xsl:attribute>
   223         </xsl:if>
   271         </xsl:if>
   224         <xsl:for-each select="str:split(substring-after($args, ':'), ':')">
   272         <xsl:for-each select="str:split(substring-after($args, ':'), ':')">
   225           <arg>
   273           <arg>
   226             <xsl:attribute name="value">
   274             <xsl:attribute name="value">
   227               <xsl:value-of select="."/>
   275               <xsl:value-of select="."/>
   228             </xsl:attribute>
   276             </xsl:attribute>
   229           </arg>
   277           </arg>
   230         </xsl:for-each>
   278         </xsl:for-each>
   231         <xsl:variable name="paths" select="substring-after($description,'@')"/>
       
   232         <xsl:for-each select="str:split($paths, '@')">
   279         <xsl:for-each select="str:split($paths, '@')">
   233           <xsl:if test="string-length(.) &gt; 0">
   280           <xsl:if test="string-length(.) &gt; 0">
   234             <path>
   281             <path>
   235               <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],'=')"/>
   236               <xsl:variable name="pathminmax" select="str:split($path_match[4],',')"/>
   284               <xsl:variable name="pathminmax" select="str:split($path_match[4],',')"/>
   237               <xsl:variable name="path" select="$path_match[2]"/>
   285               <xsl:variable name="path" select="$path_match[3]"/>
   238               <xsl:variable name="path_accepts" select="$path_match[3]"/>
       
   239               <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>
   240               <xsl:attribute name="value">
   296               <xsl:attribute name="value">
   241                 <xsl:value-of select="$path"/>
   297                 <xsl:value-of select="$path"/>
   242               </xsl:attribute>
   298               </xsl:attribute>
   243               <xsl:if test="string-length($path_accepts)">
   299               <xsl:if test="$pathassign">
   244                 <xsl:attribute name="accepts">
   300                 <xsl:attribute name="assign">
   245                   <xsl:value-of select="$path_accepts"/>
   301                   <xsl:value-of select="$pathassign"/>
   246                 </xsl:attribute>
   302                 </xsl:attribute>
   247               </xsl:if>
   303               </xsl:if>
   248               <xsl:choose>
   304               <xsl:choose>
   249                 <xsl:when test="$pathminmaxcount = 2">
   305                 <xsl:when test="$pathminmaxcount = 2">
   250                   <xsl:attribute name="min">
   306                   <xsl:attribute name="min">
   257                 <xsl:when test="$pathminmaxcount = 1 or $pathminmaxcount &gt; 2">
   313                 <xsl:when test="$pathminmaxcount = 1 or $pathminmaxcount &gt; 2">
   258                   <xsl:message terminate="yes">
   314                   <xsl:message terminate="yes">
   259                     <xsl:text>Widget id:</xsl:text>
   315                     <xsl:text>Widget id:</xsl:text>
   260                     <xsl:value-of select="$id"/>
   316                     <xsl:value-of select="$id"/>
   261                     <xsl:text> label:</xsl:text>
   317                     <xsl:text> label:</xsl:text>
   262                     <xsl:value-of select="$label"/>
   318                     <xsl:value-of select="$full_decl"/>
   263                     <xsl:text> has wrong syntax of path section </xsl:text>
   319                     <xsl:text> has wrong syntax of path section </xsl:text>
   264                     <xsl:value-of select="$pathminmax"/>
   320                     <xsl:value-of select="$pathminmax"/>
   265                   </xsl:message>
   321                   </xsl:message>
   266                 </xsl:when>
   322                 </xsl:when>
   267               </xsl:choose>
   323               </xsl:choose>
   283                     <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')">
   284                       <xsl:message terminate="yes">
   340                       <xsl:message terminate="yes">
   285                         <xsl:text>Widget id:</xsl:text>
   341                         <xsl:text>Widget id:</xsl:text>
   286                         <xsl:value-of select="$id"/>
   342                         <xsl:value-of select="$id"/>
   287                         <xsl:text> label:</xsl:text>
   343                         <xsl:text> label:</xsl:text>
   288                         <xsl:value-of select="$label"/>
   344                         <xsl:value-of select="$full_decl"/>
   289                         <xsl:text> path section </xsl:text>
   345                         <xsl:text> path section </xsl:text>
   290                         <xsl:value-of select="$pathminmax"/>
   346                         <xsl:value-of select="$pathminmax"/>
   291                         <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>
   292                       </xsl:message>
   348                       </xsl:message>
   293                     </xsl:if>
   349                     </xsl:if>
   303                 </xsl:choose>
   359                 </xsl:choose>
   304               </xsl:if>
   360               </xsl:if>
   305             </path>
   361             </path>
   306           </xsl:if>
   362           </xsl:if>
   307         </xsl:for-each>
   363         </xsl:for-each>
   308         <xsl:if test="svg:desc">
   364         <xsl:choose>
   309           <desc>
   365           <xsl:when test="$has_continuation">
   310             <xsl:value-of select="svg:desc/text()"/>
   366             <xsl:variable name="_continuation" select="substring-after($desc, $twonewlines)"/>
   311           </desc>
   367             <xsl:if test="$_continuation">
   312         </xsl:if>
   368               <desc>
       
   369                 <xsl:value-of select="$_continuation"/>
       
   370               </desc>
       
   371             </xsl:if>
       
   372           </xsl:when>
       
   373           <xsl:otherwise>
       
   374             <xsl:if test="$desc">
       
   375               <desc>
       
   376                 <xsl:value-of select="$desc/text()"/>
       
   377               </desc>
       
   378             </xsl:if>
       
   379           </xsl:otherwise>
       
   380         </xsl:choose>
   313       </widget>
   381       </widget>
   314     </xsl:if>
   382     </xsl:if>
   315   </xsl:template>
   383   </xsl:template>
   316   <xsl:template mode="genlabel" match="arg">
   384   <xsl:template mode="genlabel" match="arg">
   317     <xsl:text>:</xsl:text>
   385     <xsl:text>:</xsl:text>
   369       <xsl:value-of select="."/>
   437       <xsl:value-of select="."/>
   370       <xsl:text>" </xsl:text>
   438       <xsl:text>" </xsl:text>
   371     </xsl:for-each>
   439     </xsl:for-each>
   372     <xsl:text>
   440     <xsl:text>
   373 </xsl:text>
   441 </xsl:text>
       
   442     <xsl:if test="text()">
       
   443       <xsl:value-of select="text()"/>
       
   444       <xsl:text>
       
   445 </xsl:text>
       
   446     </xsl:if>
   374     <xsl:apply-templates mode="testtree" select="*">
   447     <xsl:apply-templates mode="testtree" select="*">
   375       <xsl:with-param name="indent">
   448       <xsl:with-param name="indent">
   376         <xsl:value-of select="concat($indent,'&gt;')"/>
   449         <xsl:value-of select="concat($indent,'&gt;')"/>
   377       </xsl:with-param>
   450       </xsl:with-param>
   378     </xsl:apply-templates>
   451     </xsl:apply-templates>
  1198         </xsl:if>
  1271         </xsl:if>
  1199       </xsl:for-each>
  1272       </xsl:for-each>
  1200     </xsl:variable>
  1273     </xsl:variable>
  1201     <xsl:variable name="indexes">
  1274     <xsl:variable name="indexes">
  1202       <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>
  1203         <xsl:choose>
  1284         <xsl:choose>
  1204           <xsl:when test="not(@index)">
  1285           <xsl:when test="not(@index)">
  1205             <xsl:choose>
  1286             <xsl:choose>
  1206               <xsl:when test="not(@type)">
  1287               <xsl:when test="not(@type)">
  1207                 <xsl:message terminate="no">
  1288                 <xsl:message terminate="no">
  1234           </xsl:when>
  1315           </xsl:when>
  1235           <xsl:otherwise>
  1316           <xsl:otherwise>
  1236             <xsl:value-of select="@index"/>
  1317             <xsl:value-of select="@index"/>
  1237           </xsl:otherwise>
  1318           </xsl:otherwise>
  1238         </xsl:choose>
  1319         </xsl:choose>
  1239         <xsl:if test="position()!=last()">
  1320         <xsl:text>, {</xsl:text>
  1240           <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>
  1241         </xsl:if>
  1330         </xsl:if>
  1242       </xsl:for-each>
  1331         <xsl:if test="@assign">
  1243     </xsl:variable>
  1332           <xsl:text>assign:"</xsl:text>
  1244     <xsl:variable name="minmaxes">
  1333           <xsl:value-of select="@assign"/>
  1245       <xsl:for-each select="$widget/path">
  1334           <xsl:text>"</xsl:text>
  1246         <xsl:choose>
  1335         </xsl:if>
  1247           <xsl:when test="@min and @max">
  1336         <xsl:text>}]</xsl:text>
  1248             <xsl:text>[</xsl:text>
       
  1249             <xsl:value-of select="@min"/>
       
  1250             <xsl:text>,</xsl:text>
       
  1251             <xsl:value-of select="@max"/>
       
  1252             <xsl:text>]</xsl:text>
       
  1253           </xsl:when>
       
  1254           <xsl:otherwise>
       
  1255             <xsl:text>undefined</xsl:text>
       
  1256           </xsl:otherwise>
       
  1257         </xsl:choose>
       
  1258         <xsl:if test="position()!=last()">
  1337         <xsl:if test="position()!=last()">
  1259           <xsl:text>,</xsl:text>
  1338           <xsl:text>,</xsl:text>
  1260         </xsl:if>
  1339         </xsl:if>
  1261       </xsl:for-each>
  1340       </xsl:for-each>
  1262     </xsl:variable>
  1341     </xsl:variable>
  1270         <xsl:otherwise>
  1349         <xsl:otherwise>
  1271           <xsl:text>undefined</xsl:text>
  1350           <xsl:text>undefined</xsl:text>
  1272         </xsl:otherwise>
  1351         </xsl:otherwise>
  1273       </xsl:choose>
  1352       </xsl:choose>
  1274     </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>
  1275     <xsl:text>  "</xsl:text>
  1364     <xsl:text>  "</xsl:text>
  1276     <xsl:value-of select="@id"/>
  1365     <xsl:value-of select="@id"/>
  1277     <xsl:text>": new </xsl:text>
  1366     <xsl:text>": new </xsl:text>
  1278     <xsl:value-of select="$widget/@type"/>
  1367     <xsl:value-of select="$widget/@type"/>
  1279     <xsl:text>Widget ("</xsl:text>
  1368     <xsl:text>Widget ("</xsl:text>
  1281     <xsl:text>",</xsl:text>
  1370     <xsl:text>",</xsl:text>
  1282     <xsl:value-of select="$freq"/>
  1371     <xsl:value-of select="$freq"/>
  1283     <xsl:text>,[</xsl:text>
  1372     <xsl:text>,[</xsl:text>
  1284     <xsl:value-of select="$args"/>
  1373     <xsl:value-of select="$args"/>
  1285     <xsl:text>],[</xsl:text>
  1374     <xsl:text>],[</xsl:text>
  1286     <xsl:value-of select="$indexes"/>
  1375     <xsl:value-of select="$variables"/>
  1287     <xsl:text>],[</xsl:text>
  1376     <xsl:text>],</xsl:text>
  1288     <xsl:value-of select="$minmaxes"/>
  1377     <xsl:value-of select="$enable_expr"/>
  1289     <xsl:text>],{
  1378     <xsl:text>,{
  1290 </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>
  1291     <xsl:apply-templates mode="widget_defs" select="$widget">
  1426     <xsl:apply-templates mode="widget_defs" select="$widget">
  1292       <xsl:with-param name="hmi_element" select="."/>
  1427       <xsl:with-param name="hmi_element" select="."/>
  1293     </xsl:apply-templates>
  1428     </xsl:apply-templates>
  1294     <xsl:text>  })</xsl:text>
  1429     <xsl:text>  })</xsl:text>
  1295     <xsl:if test="position()!=last()">
  1430     <xsl:if test="position()!=last()">
  1472 </xsl:text>
  1607 </xsl:text>
  1473     <xsl:text>}
  1608     <xsl:text>}
  1474 </xsl:text>
  1609 </xsl:text>
  1475     <xsl:text>
  1610     <xsl:text>
  1476 </xsl:text>
  1611 </xsl:text>
  1477     <xsl:text>function set_activation_state(eltsub, state){
  1612     <xsl:text>function set_activity_state(eltsub, state){
  1478 </xsl:text>
  1613 </xsl:text>
  1479     <xsl:text>    if(eltsub.active_elt != undefined){
  1614     <xsl:text>    if(eltsub.active_elt != undefined){
  1480 </xsl:text>
  1615 </xsl:text>
  1481     <xsl:text>        if(eltsub.active_elt_placeholder == undefined){
  1616     <xsl:text>        if(eltsub.active_elt_placeholder == undefined){
  1482 </xsl:text>
  1617 </xsl:text>
  1506 </xsl:text>
  1641 </xsl:text>
  1507     <xsl:text>}
  1642     <xsl:text>}
  1508 </xsl:text>
  1643 </xsl:text>
  1509     <xsl:text>
  1644     <xsl:text>
  1510 </xsl:text>
  1645 </xsl:text>
  1511     <xsl:text>function activate_activable(eltsub) {
       
  1512 </xsl:text>
       
  1513     <xsl:text>    set_activation_state(eltsub, true);
       
  1514 </xsl:text>
       
  1515     <xsl:text>}
       
  1516 </xsl:text>
       
  1517     <xsl:text>
       
  1518 </xsl:text>
       
  1519     <xsl:text>function inactivate_activable(eltsub) {
       
  1520 </xsl:text>
       
  1521     <xsl:text>    set_activation_state(eltsub, false);
       
  1522 </xsl:text>
       
  1523     <xsl:text>}
       
  1524 </xsl:text>
       
  1525     <xsl:text>
       
  1526 </xsl:text>
       
  1527     <xsl:text>class Widget {
  1646     <xsl:text>class Widget {
  1528 </xsl:text>
  1647 </xsl:text>
  1529     <xsl:text>    offset = 0;
  1648     <xsl:text>    offset = 0;
  1530 </xsl:text>
  1649 </xsl:text>
  1531     <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 ? */
  1534 </xsl:text>
  1653 </xsl:text>
  1535     <xsl:text>    pending_animate = false;
  1654     <xsl:text>    pending_animate = false;
  1536 </xsl:text>
  1655 </xsl:text>
  1537     <xsl:text>
  1656     <xsl:text>
  1538 </xsl:text>
  1657 </xsl:text>
  1539     <xsl:text>    constructor(elt_id, freq, args, indexes, minmaxes, members){
  1658     <xsl:text>    constructor(elt_id, freq, args, variables, enable_expr, members){
  1540 </xsl:text>
  1659 </xsl:text>
  1541     <xsl:text>        this.element_id = elt_id;
  1660     <xsl:text>        this.element_id = elt_id;
  1542 </xsl:text>
  1661 </xsl:text>
  1543     <xsl:text>        this.element = id(elt_id);
  1662     <xsl:text>        this.element = id(elt_id);
  1544 </xsl:text>
  1663 </xsl:text>
  1545     <xsl:text>        this.args = args;
  1664     <xsl:text>        this.args = args;
  1546 </xsl:text>
  1665 </xsl:text>
  1547     <xsl:text>        this.indexes = indexes;
  1666     <xsl:text>        
  1548 </xsl:text>
  1667 </xsl:text>
  1549     <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>
  1550 </xsl:text>
  1683 </xsl:text>
  1551     <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]);
  1552 </xsl:text>
  1685 </xsl:text>
  1553     <xsl:text>        this.lastapply = indexes.map(() =&gt; undefined);
  1686     <xsl:text>        this.lastapply = this.indexes.map(() =&gt; undefined);
  1554 </xsl:text>
  1687 </xsl:text>
  1555     <xsl:text>        this.inhibit = indexes.map(() =&gt; undefined);
  1688     <xsl:text>        this.inhibit = this.indexes.map(() =&gt; undefined);
  1556 </xsl:text>
  1689 </xsl:text>
  1557     <xsl:text>        this.pending = indexes.map(() =&gt; undefined);
  1690     <xsl:text>        this.pending = this.indexes.map(() =&gt; undefined);
  1558 </xsl:text>
  1691 </xsl:text>
  1559     <xsl:text>        this.bound_uninhibit = this.uninhibit.bind(this);
  1692     <xsl:text>        this.bound_uninhibit = this.uninhibit.bind(this);
  1560 </xsl:text>
  1693 </xsl:text>
  1561     <xsl:text>
  1694     <xsl:text>
  1562 </xsl:text>
  1695 </xsl:text>
  1563     <xsl:text>        this.lastdispatch = indexes.map(() =&gt; undefined);
  1696     <xsl:text>        this.lastdispatch = this.indexes.map(() =&gt; undefined);
  1564 </xsl:text>
  1697 </xsl:text>
  1565     <xsl:text>        this.deafen = indexes.map(() =&gt; undefined);
  1698     <xsl:text>        this.deafen = this.indexes.map(() =&gt; undefined);
  1566 </xsl:text>
  1699 </xsl:text>
  1567     <xsl:text>        this.incoming = indexes.map(() =&gt; undefined);
  1700     <xsl:text>        this.incoming = this.indexes.map(() =&gt; undefined);
  1568 </xsl:text>
  1701 </xsl:text>
  1569     <xsl:text>        this.bound_undeafen = this.undeafen.bind(this);
  1702     <xsl:text>        this.bound_undeafen = this.undeafen.bind(this);
  1570 </xsl:text>
  1703 </xsl:text>
  1571     <xsl:text>
  1704     <xsl:text>
  1572 </xsl:text>
  1705 </xsl:text>
  1632 </xsl:text>
  1765 </xsl:text>
  1633     <xsl:text>            }
  1766     <xsl:text>            }
  1634 </xsl:text>
  1767 </xsl:text>
  1635     <xsl:text>        }
  1768     <xsl:text>        }
  1636 </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>
  1637     <xsl:text>    }
  1794     <xsl:text>    }
  1638 </xsl:text>
  1795 </xsl:text>
  1639     <xsl:text>
  1796     <xsl:text>
  1640 </xsl:text>
  1797 </xsl:text>
  1641     <xsl:text>    unsub(){
  1798     <xsl:text>    unsub(){
  1642 </xsl:text>
  1799 </xsl:text>
  1643     <xsl:text>        /* remove subsribers */
  1800     <xsl:text>        /* remove subsribers */
  1644 </xsl:text>
  1801 </xsl:text>
  1645     <xsl:text>        if(!this.unsubscribable)
  1802     <xsl:text>        for(let i = 0; i &lt; this.indexes_length; i++) {
  1646 </xsl:text>
  1803 </xsl:text>
  1647     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
  1804     <xsl:text>            /* flush updates pending because of inhibition */
  1648 </xsl:text>
  1805 </xsl:text>
  1649     <xsl:text>                /* flush updates pending because of inhibition */
  1806     <xsl:text>            let inhibition = this.inhibit[i];
  1650 </xsl:text>
  1807 </xsl:text>
  1651     <xsl:text>                let inhibition = this.inhibit[i];
  1808     <xsl:text>            if(inhibition != undefined){
  1652 </xsl:text>
  1809 </xsl:text>
  1653     <xsl:text>                if(inhibition != undefined){
  1810     <xsl:text>                clearTimeout(inhibition);
  1654 </xsl:text>
  1811 </xsl:text>
  1655     <xsl:text>                    clearTimeout(inhibition);
  1812     <xsl:text>                this.lastapply[i] = undefined;
  1656 </xsl:text>
  1813 </xsl:text>
  1657     <xsl:text>                    this.lastapply[i] = undefined;
  1814     <xsl:text>                this.uninhibit(i);
  1658 </xsl:text>
  1815 </xsl:text>
  1659     <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)
  1660 </xsl:text>
  2187 </xsl:text>
  1661     <xsl:text>                }
  2188     <xsl:text>                }
  1662 </xsl:text>
  2189 </xsl:text>
  1663     <xsl:text>                let deafened = this.deafen[i];
  2190     <xsl:text>                else {
  1664 </xsl:text>
  2191 </xsl:text>
  1665     <xsl:text>                if(deafened != undefined){
  2192     <xsl:text>                    let elapsed = now - lastdispatch;
  1666 </xsl:text>
  2193 </xsl:text>
  1667     <xsl:text>                    clearTimeout(deafened);
  2194     <xsl:text>                    this.incoming[varnum] = [value, oldval];
  1668 </xsl:text>
  2195 </xsl:text>
  1669     <xsl:text>                    this.lastdispatch[i] = undefined;
  2196     <xsl:text>                    this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum);
  1670 </xsl:text>
       
  1671     <xsl:text>                    this.undeafen(i);
       
  1672 </xsl:text>
  2197 </xsl:text>
  1673     <xsl:text>                }
  2198     <xsl:text>                }
  1674 </xsl:text>
  2199 </xsl:text>
  1675     <xsl:text>                let index = this.indexes[i];
       
  1676 </xsl:text>
       
  1677     <xsl:text>                if(this.relativeness[i])
       
  1678 </xsl:text>
       
  1679     <xsl:text>                    index += this.offset;
       
  1680 </xsl:text>
       
  1681     <xsl:text>                subscribers(index).delete(this);
       
  1682 </xsl:text>
       
  1683     <xsl:text>            }
  2200     <xsl:text>            }
  1684 </xsl:text>
  2201 </xsl:text>
  1685     <xsl:text>        this.offset = 0;
  2202     <xsl:text>            else {
  1686 </xsl:text>
  2203 </xsl:text>
  1687     <xsl:text>        this.relativeness = undefined;
  2204     <xsl:text>                this.incoming[varnum] = [value, oldval];
  1688 </xsl:text>
       
  1689     <xsl:text>    }
       
  1690 </xsl:text>
       
  1691     <xsl:text>
       
  1692 </xsl:text>
       
  1693     <xsl:text>    sub(new_offset=0, relativeness, container_id){
       
  1694 </xsl:text>
       
  1695     <xsl:text>        this.offset = new_offset;
       
  1696 </xsl:text>
       
  1697     <xsl:text>        this.relativeness = relativeness;
       
  1698 </xsl:text>
       
  1699     <xsl:text>        this.container_id = container_id ;
       
  1700 </xsl:text>
       
  1701     <xsl:text>        /* add this's subsribers */
       
  1702 </xsl:text>
       
  1703     <xsl:text>        if(!this.unsubscribable)
       
  1704 </xsl:text>
       
  1705     <xsl:text>            for(let i = 0; i &lt; this.indexes.length; i++) {
       
  1706 </xsl:text>
       
  1707     <xsl:text>                let index = this.get_variable_index(i);
       
  1708 </xsl:text>
       
  1709     <xsl:text>                if(index == undefined) continue;
       
  1710 </xsl:text>
       
  1711     <xsl:text>                subscribers(index).add(this);
       
  1712 </xsl:text>
  2205 </xsl:text>
  1713     <xsl:text>            }
  2206     <xsl:text>            }
  1714 </xsl:text>
  2207 </xsl:text>
  1715     <xsl:text>        need_cache_apply.push(this); 
       
  1716 </xsl:text>
       
  1717     <xsl:text>    }
       
  1718 </xsl:text>
       
  1719     <xsl:text>
       
  1720 </xsl:text>
       
  1721     <xsl:text>    apply_cache() {
       
  1722 </xsl:text>
       
  1723     <xsl:text>        if(!this.unsubscribable) for(let index in this.indexes){
       
  1724 </xsl:text>
       
  1725     <xsl:text>            /* dispatch current cache in newly opened page widgets */
       
  1726 </xsl:text>
       
  1727     <xsl:text>            let realindex = this.get_variable_index(index);
       
  1728 </xsl:text>
       
  1729     <xsl:text>            if(realindex == undefined) continue;
       
  1730 </xsl:text>
       
  1731     <xsl:text>            let cached_val = cache[realindex];
       
  1732 </xsl:text>
       
  1733     <xsl:text>            if(cached_val != undefined)
       
  1734 </xsl:text>
       
  1735     <xsl:text>                this._dispatch(cached_val, cached_val, index);
       
  1736 </xsl:text>
       
  1737     <xsl:text>        }
  2208     <xsl:text>        }
  1738 </xsl:text>
  2209 </xsl:text>
  1739     <xsl:text>    }
  2210     <xsl:text>    }
  1740 </xsl:text>
  2211 </xsl:text>
  1741     <xsl:text>
  2212     <xsl:text>
  1742 </xsl:text>
  2213 </xsl:text>
  1743     <xsl:text>    get_variable_index(varnum) {
  2214     <xsl:text>    do_dispatch(value, oldval, varnum) {
  1744 </xsl:text>
  2215 </xsl:text>
  1745     <xsl:text>        let index = this.indexes[varnum];
  2216     <xsl:text>        if(this.dispatch) try {
  1746 </xsl:text>
  2217 </xsl:text>
  1747     <xsl:text>        if(typeof(index) == "string"){
  2218     <xsl:text>            this.dispatch(value, oldval, varnum);
  1748 </xsl:text>
  2219 </xsl:text>
  1749     <xsl:text>            index = page_local_index(index, this.container_id);
  2220     <xsl:text>        } catch(err) {
  1750 </xsl:text>
  2221 </xsl:text>
  1751     <xsl:text>        } else {
  2222     <xsl:text>            console.log(err);
  1752 </xsl:text>
       
  1753     <xsl:text>            if(this.relativeness[varnum]){
       
  1754 </xsl:text>
       
  1755     <xsl:text>                index += this.offset;
       
  1756 </xsl:text>
       
  1757     <xsl:text>            }
       
  1758 </xsl:text>
  2223 </xsl:text>
  1759     <xsl:text>        }
  2224     <xsl:text>        }
  1760 </xsl:text>
  2225 </xsl:text>
  1761     <xsl:text>        return index;
  2226     <xsl:text>        if(this.enable_expr) try {
  1762 </xsl:text>
  2227 </xsl:text>
  1763     <xsl:text>    }
  2228     <xsl:text>            this.compute_enable(value, oldval, varnum);
  1764 </xsl:text>
  2229 </xsl:text>
  1765     <xsl:text>
  2230     <xsl:text>        } catch(err) {
  1766 </xsl:text>
  2231 </xsl:text>
  1767     <xsl:text>    overshot(new_val, max) {
  2232     <xsl:text>            console.log(err);
  1768 </xsl:text>
       
  1769     <xsl:text>    }
       
  1770 </xsl:text>
       
  1771     <xsl:text>
       
  1772 </xsl:text>
       
  1773     <xsl:text>    undershot(new_val, min) {
       
  1774 </xsl:text>
       
  1775     <xsl:text>    }
       
  1776 </xsl:text>
       
  1777     <xsl:text>
       
  1778 </xsl:text>
       
  1779     <xsl:text>    clip_min_max(index, new_val) {
       
  1780 </xsl:text>
       
  1781     <xsl:text>        let minmax = this.minmaxes[index];
       
  1782 </xsl:text>
       
  1783     <xsl:text>        if(minmax !== undefined &amp;&amp; typeof new_val == "number") {
       
  1784 </xsl:text>
       
  1785     <xsl:text>            let [min,max] = minmax;
       
  1786 </xsl:text>
       
  1787     <xsl:text>            if(new_val &lt; min){
       
  1788 </xsl:text>
       
  1789     <xsl:text>                this.undershot(new_val, min);
       
  1790 </xsl:text>
       
  1791     <xsl:text>                return min;
       
  1792 </xsl:text>
       
  1793     <xsl:text>            }
       
  1794 </xsl:text>
       
  1795     <xsl:text>            if(new_val &gt; max){
       
  1796 </xsl:text>
       
  1797     <xsl:text>                this.overshot(new_val, max);
       
  1798 </xsl:text>
       
  1799     <xsl:text>                return max;
       
  1800 </xsl:text>
       
  1801     <xsl:text>            }
       
  1802 </xsl:text>
  2233 </xsl:text>
  1803     <xsl:text>        }
  2234     <xsl:text>        }
  1804 </xsl:text>
  2235 </xsl:text>
  1805     <xsl:text>        return new_val;
  2236     <xsl:text>    }
  1806 </xsl:text>
  2237 </xsl:text>
  1807     <xsl:text>    }
  2238     <xsl:text>
  1808 </xsl:text>
  2239 </xsl:text>
  1809     <xsl:text>
  2240     <xsl:text>    _animate(){
  1810 </xsl:text>
  2241 </xsl:text>
  1811     <xsl:text>    change_hmi_value(index, opstr) {
  2242     <xsl:text>        if(this.enable_expr)
  1812 </xsl:text>
  2243 </xsl:text>
  1813     <xsl:text>        let realindex = this.get_variable_index(index);
  2244     <xsl:text>            this.animate_enable();
  1814 </xsl:text>
  2245 </xsl:text>
  1815     <xsl:text>        if(realindex == undefined) return undefined;
  2246     <xsl:text>        // inhibit widget animation when disabled
  1816 </xsl:text>
  2247 </xsl:text>
  1817     <xsl:text>        let old_val = cache[realindex];
  2248     <xsl:text>        if(!this.enable_expr || this.enable_state){
  1818 </xsl:text>
  2249 </xsl:text>
  1819     <xsl:text>        let new_val = eval_operation_string(old_val, opstr);
  2250     <xsl:text>            if(this.has_activity)
  1820 </xsl:text>
  2251 </xsl:text>
  1821     <xsl:text>        if(this.clip)
  2252     <xsl:text>                this.animate_activity();
  1822 </xsl:text>
  2253 </xsl:text>
  1823     <xsl:text>            new_val = this.clip_min_max(index, new_val);
  2254     <xsl:text>            if(this.animate != undefined)
  1824 </xsl:text>
  2255 </xsl:text>
  1825     <xsl:text>        return apply_hmi_value(realindex, new_val);
  2256     <xsl:text>                this.animate();
  1826 </xsl:text>
       
  1827     <xsl:text>    }
       
  1828 </xsl:text>
       
  1829     <xsl:text>
       
  1830 </xsl:text>
       
  1831     <xsl:text>    _apply_hmi_value(index, new_val) {
       
  1832 </xsl:text>
       
  1833     <xsl:text>        let realindex = this.get_variable_index(index);
       
  1834 </xsl:text>
       
  1835     <xsl:text>        if(realindex == undefined) return undefined;
       
  1836 </xsl:text>
       
  1837     <xsl:text>        if(this.clip)
       
  1838 </xsl:text>
       
  1839     <xsl:text>            new_val = this.clip_min_max(index, new_val);
       
  1840 </xsl:text>
       
  1841     <xsl:text>        return apply_hmi_value(realindex, new_val);
       
  1842 </xsl:text>
       
  1843     <xsl:text>    }
       
  1844 </xsl:text>
       
  1845     <xsl:text>
       
  1846 </xsl:text>
       
  1847     <xsl:text>    uninhibit(index){
       
  1848 </xsl:text>
       
  1849     <xsl:text>        this.inhibit[index] = undefined;
       
  1850 </xsl:text>
       
  1851     <xsl:text>        let new_val = this.pending[index];
       
  1852 </xsl:text>
       
  1853     <xsl:text>        this.pending[index] = undefined;
       
  1854 </xsl:text>
       
  1855     <xsl:text>        return this.apply_hmi_value(index, new_val);
       
  1856 </xsl:text>
       
  1857     <xsl:text>    }
       
  1858 </xsl:text>
       
  1859     <xsl:text>
       
  1860 </xsl:text>
       
  1861     <xsl:text>    apply_hmi_value(index, new_val) {
       
  1862 </xsl:text>
       
  1863     <xsl:text>        if(this.inhibit[index] == undefined){
       
  1864 </xsl:text>
       
  1865     <xsl:text>            let now = Date.now();
       
  1866 </xsl:text>
       
  1867     <xsl:text>            let min_interval = 1000/this.frequency;
       
  1868 </xsl:text>
       
  1869     <xsl:text>            let lastapply = this.lastapply[index];
       
  1870 </xsl:text>
       
  1871     <xsl:text>            if(lastapply == undefined || now &gt; lastapply + min_interval){
       
  1872 </xsl:text>
       
  1873     <xsl:text>                this.lastapply[index] = now;
       
  1874 </xsl:text>
       
  1875     <xsl:text>                return this._apply_hmi_value(index, new_val);
       
  1876 </xsl:text>
       
  1877     <xsl:text>            }
       
  1878 </xsl:text>
       
  1879     <xsl:text>            else {
       
  1880 </xsl:text>
       
  1881     <xsl:text>                let elapsed = now - lastapply;
       
  1882 </xsl:text>
       
  1883     <xsl:text>                this.pending[index] = new_val;
       
  1884 </xsl:text>
       
  1885     <xsl:text>                this.inhibit[index] = setTimeout(this.bound_uninhibit, min_interval - elapsed, index);
       
  1886 </xsl:text>
       
  1887     <xsl:text>            }
       
  1888 </xsl:text>
  2257 </xsl:text>
  1889     <xsl:text>        }
  2258     <xsl:text>        }
  1890 </xsl:text>
  2259 </xsl:text>
  1891     <xsl:text>        else {
  2260     <xsl:text>        this.pending_animate = false;
  1892 </xsl:text>
  2261 </xsl:text>
  1893     <xsl:text>            this.pending[index] = new_val;
  2262     <xsl:text>    }
  1894 </xsl:text>
  2263 </xsl:text>
  1895     <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();
  1896 </xsl:text>
  2275 </xsl:text>
  1897     <xsl:text>        }
  2276     <xsl:text>        }
  1898 </xsl:text>
  2277 </xsl:text>
  1899     <xsl:text>    }
  2278     <xsl:text>    }
  1900 </xsl:text>
  2279 </xsl:text>
  1901     <xsl:text>
  2280     <xsl:text>
  1902 </xsl:text>
  2281 </xsl:text>
  1903     <xsl:text>    new_hmi_value(index, value, oldval) {
  2282     <xsl:text>    animate_activity(){
  1904 </xsl:text>
  2283 </xsl:text>
  1905     <xsl:text>        // TODO avoid searching, store index at sub()
  2284     <xsl:text>        if(this.activity_displayed_state != this.activity_state){
  1906 </xsl:text>
  2285 </xsl:text>
  1907     <xsl:text>        for(let i = 0; i &lt; this.indexes.length; i++) {
  2286     <xsl:text>            set_activity_state(this.activable_sub, this.activity_state);
  1908 </xsl:text>
  2287 </xsl:text>
  1909     <xsl:text>            let refindex = this.get_variable_index(i);
  2288     <xsl:text>            this.activity_displayed_state = this.activity_state;
  1910 </xsl:text>
       
  1911     <xsl:text>            if(refindex == undefined) continue;
       
  1912 </xsl:text>
       
  1913     <xsl:text>
       
  1914 </xsl:text>
       
  1915     <xsl:text>            if(index == refindex) {
       
  1916 </xsl:text>
       
  1917     <xsl:text>                this._dispatch(value, oldval, i);
       
  1918 </xsl:text>
       
  1919     <xsl:text>                break;
       
  1920 </xsl:text>
       
  1921     <xsl:text>            }
       
  1922 </xsl:text>
  2289 </xsl:text>
  1923     <xsl:text>        }
  2290     <xsl:text>        }
  1924 </xsl:text>
       
  1925     <xsl:text>    }
       
  1926 </xsl:text>
       
  1927     <xsl:text>    
       
  1928 </xsl:text>
       
  1929     <xsl:text>    undeafen(index){
       
  1930 </xsl:text>
       
  1931     <xsl:text>        this.deafen[index] = undefined;
       
  1932 </xsl:text>
       
  1933     <xsl:text>        let [new_val, old_val] = this.incoming[index];
       
  1934 </xsl:text>
       
  1935     <xsl:text>        this.incoming[index] = undefined;
       
  1936 </xsl:text>
       
  1937     <xsl:text>        this.dispatch(new_val, old_val, index);
       
  1938 </xsl:text>
       
  1939     <xsl:text>    }
       
  1940 </xsl:text>
       
  1941     <xsl:text>
       
  1942 </xsl:text>
       
  1943     <xsl:text>    _dispatch(value, oldval, varnum) {
       
  1944 </xsl:text>
       
  1945     <xsl:text>        let dispatch = this.dispatch;
       
  1946 </xsl:text>
       
  1947     <xsl:text>        if(dispatch != undefined){
       
  1948 </xsl:text>
       
  1949     <xsl:text>            if(this.deafen[varnum] == undefined){
       
  1950 </xsl:text>
       
  1951     <xsl:text>                let now = Date.now();
       
  1952 </xsl:text>
       
  1953     <xsl:text>                let min_interval = 1000/this.frequency;
       
  1954 </xsl:text>
       
  1955     <xsl:text>                let lastdispatch = this.lastdispatch[varnum];
       
  1956 </xsl:text>
       
  1957     <xsl:text>                if(lastdispatch == undefined || now &gt; lastdispatch + min_interval){
       
  1958 </xsl:text>
       
  1959     <xsl:text>                    this.lastdispatch[varnum] = now;
       
  1960 </xsl:text>
       
  1961     <xsl:text>                    try {
       
  1962 </xsl:text>
       
  1963     <xsl:text>                        dispatch.call(this, value, oldval, varnum);
       
  1964 </xsl:text>
       
  1965     <xsl:text>                    } catch(err) {
       
  1966 </xsl:text>
       
  1967     <xsl:text>                        console.log(err);
       
  1968 </xsl:text>
       
  1969     <xsl:text>                    }
       
  1970 </xsl:text>
       
  1971     <xsl:text>                }
       
  1972 </xsl:text>
       
  1973     <xsl:text>                else {
       
  1974 </xsl:text>
       
  1975     <xsl:text>                    let elapsed = now - lastdispatch;
       
  1976 </xsl:text>
       
  1977     <xsl:text>                    this.incoming[varnum] = [value, oldval];
       
  1978 </xsl:text>
       
  1979     <xsl:text>                    this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum);
       
  1980 </xsl:text>
       
  1981     <xsl:text>                }
       
  1982 </xsl:text>
       
  1983     <xsl:text>            }
       
  1984 </xsl:text>
       
  1985     <xsl:text>            else {
       
  1986 </xsl:text>
       
  1987     <xsl:text>                this.incoming[varnum] = [value, oldval];
       
  1988 </xsl:text>
       
  1989     <xsl:text>            }
       
  1990 </xsl:text>
       
  1991     <xsl:text>        }
       
  1992 </xsl:text>
       
  1993     <xsl:text>    }
       
  1994 </xsl:text>
       
  1995     <xsl:text>
       
  1996 </xsl:text>
       
  1997     <xsl:text>    _animate(){
       
  1998 </xsl:text>
       
  1999     <xsl:text>        this.animate();
       
  2000 </xsl:text>
       
  2001     <xsl:text>        this.pending_animate = false;
       
  2002 </xsl:text>
       
  2003     <xsl:text>    }
       
  2004 </xsl:text>
       
  2005     <xsl:text>
       
  2006 </xsl:text>
       
  2007     <xsl:text>    request_animate(){
       
  2008 </xsl:text>
       
  2009     <xsl:text>        if(!this.pending_animate){
       
  2010 </xsl:text>
       
  2011     <xsl:text>            pending_widget_animates.push(this);
       
  2012 </xsl:text>
       
  2013     <xsl:text>            this.pending_animate = true;
       
  2014 </xsl:text>
       
  2015     <xsl:text>            requestHMIAnimation();
       
  2016 </xsl:text>
       
  2017     <xsl:text>        }
       
  2018 </xsl:text>
       
  2019     <xsl:text>    }
       
  2020 </xsl:text>
       
  2021     <xsl:text>
       
  2022 </xsl:text>
       
  2023     <xsl:text>    set_activation_state(state){
       
  2024 </xsl:text>
       
  2025     <xsl:text>        set_activation_state(this.activable_sub, state);
       
  2026 </xsl:text>
  2291 </xsl:text>
  2027     <xsl:text>    }
  2292     <xsl:text>    }
  2028 </xsl:text>
  2293 </xsl:text>
  2029     <xsl:text>}
  2294     <xsl:text>}
  2030 </xsl:text>
  2295 </xsl:text>
  2645     <xsl:apply-templates mode="actions" select="*"/>
  2910     <xsl:apply-templates mode="actions" select="*"/>
  2646     <xsl:text>    }
  2911     <xsl:text>    }
  2647 </xsl:text>
  2912 </xsl:text>
  2648   </xsl:template>
  2913   </xsl:template>
  2649   <xsl:template mode="actions" match="show">
  2914   <xsl:template mode="actions" match="show">
  2650     <xsl:text>        this.display = "</xsl:text>
  2915     <xsl:text>        this.activity_state = </xsl:text>
  2651     <xsl:value-of select="@eltname"/>
  2916     <xsl:value-of select="@eltname = 'active'"/>
  2652     <xsl:text>";
  2917     <xsl:text>;
  2653 </xsl:text>
  2918 </xsl:text>
  2654     <xsl:text>        this.request_animate();
  2919     <xsl:text>        this.request_animate();
  2655 </xsl:text>
  2920 </xsl:text>
  2656   </xsl:template>
  2921   </xsl:template>
  2657   <xsl:template mode="actions" match="hmi-value">
  2922   <xsl:template mode="actions" match="hmi-value">
  2660     <xsl:text>);
  2925     <xsl:text>);
  2661 </xsl:text>
  2926 </xsl:text>
  2662   </xsl:template>
  2927   </xsl:template>
  2663   <xsl:template name="generated_button_class">
  2928   <xsl:template name="generated_button_class">
  2664     <xsl:param name="fsm"/>
  2929     <xsl:param name="fsm"/>
  2665     <xsl:text>    display = "inactive";
       
  2666 </xsl:text>
       
  2667     <xsl:text>    state = "init";
  2930     <xsl:text>    state = "init";
  2668 </xsl:text>
  2931 </xsl:text>
  2669     <xsl:text>    dispatch(value) {
  2932     <xsl:text>    dispatch(value) {
  2670 </xsl:text>
  2933 </xsl:text>
  2671     <xsl:apply-templates mode="dispatch_transition" select="$fsm"/>
  2934     <xsl:apply-templates mode="dispatch_transition" select="$fsm"/>
  2688       <xsl:with-param name="position" select="'down'"/>
  2951       <xsl:with-param name="position" select="'down'"/>
  2689     </xsl:apply-templates>
  2952     </xsl:apply-templates>
  2690     <xsl:text>    }
  2953     <xsl:text>    }
  2691 </xsl:text>
  2954 </xsl:text>
  2692     <xsl:apply-templates mode="actions" select="$fsm"/>
  2955     <xsl:apply-templates mode="actions" select="$fsm"/>
  2693     <xsl:text>    animate(){
       
  2694 </xsl:text>
       
  2695     <xsl:text>        this.set_activation_state(this.display == "active");
       
  2696 </xsl:text>
       
  2697     <xsl:text>    }
       
  2698 </xsl:text>
       
  2699     <xsl:text>    init() {
  2956     <xsl:text>    init() {
  2700 </xsl:text>
  2957 </xsl:text>
  2701     <xsl:text>        this.bound_onmouseup = this.onmouseup.bind(this);
  2958     <xsl:text>        this.bound_onmouseup = this.onmouseup.bind(this);
  2702 </xsl:text>
  2959 </xsl:text>
  2703     <xsl:text>        this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
  2960     <xsl:text>        this.element.addEventListener("pointerdown", this.onmousedown.bind(this));
  2704 </xsl:text>
  2961 </xsl:text>
  2705     <xsl:text>        this.set_activation_state(undefined);
  2962     <xsl:text>        this.activity_state = undefined;
  2706 </xsl:text>
  2963 </xsl:text>
  2707     <xsl:text>    }
  2964     <xsl:text>    }
  2708 </xsl:text>
  2965 </xsl:text>
  2709   </xsl:template>
  2966   </xsl:template>
  2710   <xsl:template match="widget[@type='Button']" mode="widget_class">
  2967   <xsl:template match="widget[@type='Button']" mode="widget_class">
  2721     <xsl:text>}
  2978     <xsl:text>}
  2722 </xsl:text>
  2979 </xsl:text>
  2723   </xsl:template>
  2980   </xsl:template>
  2724   <xsl:template match="widget[@type='Button']" mode="widget_defs">
  2981   <xsl:template match="widget[@type='Button']" mode="widget_defs">
  2725     <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"/>
  2726     <xsl:text>    activable_sub:{
  2994     <xsl:text>    activable_sub:{
  2727 </xsl:text>
  2995 </xsl:text>
  2728     <xsl:call-template name="defs_by_labels">
  2996     <xsl:variable name="activity">
  2729       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2997       <xsl:call-template name="defs_by_labels">
  2730       <xsl:with-param name="labels">
  2998         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2731         <xsl:text>/active /inactive</xsl:text>
  2999         <xsl:with-param name="labels">
  2732       </xsl:with-param>
  3000           <xsl:text>/active /inactive</xsl:text>
  2733       <xsl:with-param name="mandatory" select="'warn'"/>
  3001         </xsl:with-param>
  2734     </xsl:call-template>
  3002         <xsl:with-param name="mandatory">
  2735     <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>,
  2736 </xsl:text>
  3014 </xsl:text>
  2737   </xsl:template>
  3015   </xsl:template>
  2738   <xsl:template match="widget[@type='PushButton']" mode="widget_class">
  3016   <xsl:template match="widget[@type='PushButton']" mode="widget_class">
  2739     <xsl:text>class </xsl:text>
  3017     <xsl:text>class </xsl:text>
  2740     <xsl:text>PushButtonWidget</xsl:text>
  3018     <xsl:text>PushButtonWidget</xsl:text>
  2749     <xsl:text>}
  3027     <xsl:text>}
  2750 </xsl:text>
  3028 </xsl:text>
  2751   </xsl:template>
  3029   </xsl:template>
  2752   <xsl:template match="widget[@type='PushButton']" mode="widget_defs">
  3030   <xsl:template match="widget[@type='PushButton']" mode="widget_defs">
  2753     <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"/>
  2754     <xsl:text>    activable_sub:{
  3043     <xsl:text>    activable_sub:{
  2755 </xsl:text>
  3044 </xsl:text>
  2756     <xsl:call-template name="defs_by_labels">
  3045     <xsl:variable name="activity">
  2757       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3046       <xsl:call-template name="defs_by_labels">
  2758       <xsl:with-param name="labels">
  3047         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2759         <xsl:text>/active /inactive</xsl:text>
  3048         <xsl:with-param name="labels">
  2760       </xsl:with-param>
  3049           <xsl:text>/active /inactive</xsl:text>
  2761       <xsl:with-param name="mandatory" select="'warn'"/>
  3050         </xsl:with-param>
  2762     </xsl:call-template>
  3051         <xsl:with-param name="mandatory">
  2763     <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>,
  2764 </xsl:text>
  3063 </xsl:text>
  2765   </xsl:template>
  3064   </xsl:template>
  2766   <xsl:template match="widget[@type='CircularBar']" mode="widget_desc">
  3065   <xsl:template match="widget[@type='CircularBar']" mode="widget_desc">
  2767     <type>
  3066     <type>
  2768       <xsl:value-of select="@type"/>
  3067       <xsl:value-of select="@type"/>
  2900     <xsl:text>}
  3199     <xsl:text>}
  2901 </xsl:text>
  3200 </xsl:text>
  2902   </xsl:template>
  3201   </xsl:template>
  2903   <xsl:template match="widget[@type='CircularBar']" mode="widget_defs">
  3202   <xsl:template match="widget[@type='CircularBar']" mode="widget_defs">
  2904     <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"/>
  2905     <xsl:call-template name="defs_by_labels">
  3215     <xsl:call-template name="defs_by_labels">
  2906       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3216       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  2907       <xsl:with-param name="labels">
  3217       <xsl:with-param name="labels">
  2908         <xsl:text>path</xsl:text>
  3218         <xsl:text>path</xsl:text>
  2909       </xsl:with-param>
  3219       </xsl:with-param>
  3415     <xsl:text>}
  3725     <xsl:text>}
  3416 </xsl:text>
  3726 </xsl:text>
  3417   </xsl:template>
  3727   </xsl:template>
  3418   <xsl:template match="widget[@type='CircularSlider']" mode="widget_defs">
  3728   <xsl:template match="widget[@type='CircularSlider']" mode="widget_defs">
  3419     <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"/>
  3420     <xsl:call-template name="defs_by_labels">
  3741     <xsl:call-template name="defs_by_labels">
  3421       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3742       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3422       <xsl:with-param name="labels">
  3743       <xsl:with-param name="labels">
  3423         <xsl:text>handle range</xsl:text>
  3744         <xsl:text>handle range</xsl:text>
  3424       </xsl:with-param>
  3745       </xsl:with-param>
  3495     <xsl:text>}
  3816     <xsl:text>}
  3496 </xsl:text>
  3817 </xsl:text>
  3497   </xsl:template>
  3818   </xsl:template>
  3498   <xsl:template match="widget[@type='CustomHtml']" mode="widget_defs">
  3819   <xsl:template match="widget[@type='CustomHtml']" mode="widget_defs">
  3499     <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"/>
  3500     <xsl:call-template name="defs_by_labels">
  3832     <xsl:call-template name="defs_by_labels">
  3501       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3833       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3502       <xsl:with-param name="labels">
  3834       <xsl:with-param name="labels">
  3503         <xsl:text>container code</xsl:text>
  3835         <xsl:text>container code</xsl:text>
  3504       </xsl:with-param>
  3836       </xsl:with-param>
  3566     <xsl:text>}
  3898     <xsl:text>}
  3567 </xsl:text>
  3899 </xsl:text>
  3568   </xsl:template>
  3900   </xsl:template>
  3569   <xsl:template match="widget[@type='Display']" mode="widget_defs">
  3901   <xsl:template match="widget[@type='Display']" mode="widget_defs">
  3570     <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"/>
  3571     <xsl:variable name="format">
  3914     <xsl:variable name="format">
  3572       <xsl:call-template name="defs_by_labels">
  3915       <xsl:call-template name="defs_by_labels">
  3573         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3916         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  3574         <xsl:with-param name="labels">
  3917         <xsl:with-param name="labels">
  3575           <xsl:text>format</xsl:text>
  3918           <xsl:text>format</xsl:text>
  4372     <xsl:text>}
  4715     <xsl:text>}
  4373 </xsl:text>
  4716 </xsl:text>
  4374   </xsl:template>
  4717   </xsl:template>
  4375   <xsl:template match="widget[@type='DropDown']" mode="widget_defs">
  4718   <xsl:template match="widget[@type='DropDown']" mode="widget_defs">
  4376     <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"/>
  4377     <xsl:call-template name="defs_by_labels">
  4731     <xsl:call-template name="defs_by_labels">
  4378       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  4732       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  4379       <xsl:with-param name="labels">
  4733       <xsl:with-param name="labels">
  4380         <xsl:text>box button highlight</xsl:text>
  4734         <xsl:text>box button highlight</xsl:text>
  4381       </xsl:with-param>
  4735       </xsl:with-param>
  4510       <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>
  4511     </path>
  4865     </path>
  4512   </xsl:template>
  4866   </xsl:template>
  4513   <xsl:template match="widget[@type='ForEach']" mode="widget_defs">
  4867   <xsl:template match="widget[@type='ForEach']" mode="widget_defs">
  4514     <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"/>
  4515     <xsl:if test="count(path) != 1">
  4880     <xsl:if test="count(path) != 1">
  4516       <xsl:message terminate="yes">
  4881       <xsl:message terminate="yes">
  4517         <xsl:text>ForEach widget </xsl:text>
  4882         <xsl:text>ForEach widget </xsl:text>
  4518         <xsl:value-of select="$hmi_element/@id"/>
  4883         <xsl:value-of select="$hmi_element/@id"/>
  4519         <xsl:text> must have one HMI path given.</xsl:text>
  4884         <xsl:text> must have one HMI path given.</xsl:text>
  4749 </xsl:text>
  5114 </xsl:text>
  4750     <xsl:text>        this.sub_items();
  5115     <xsl:text>        this.sub_items();
  4751 </xsl:text>
  5116 </xsl:text>
  4752     <xsl:text>        update_subscriptions();
  5117     <xsl:text>        update_subscriptions();
  4753 </xsl:text>
  5118 </xsl:text>
  4754     <xsl:text>        need_cache_apply.push(this);
  5119     <xsl:text>        this.apply_cache(); 
  4755 </xsl:text>
  5120 </xsl:text>
  4756     <xsl:text>        jumps_need_update = true;
  5121     <xsl:text>        jumps_need_update = true;
  4757 </xsl:text>
  5122 </xsl:text>
  4758     <xsl:text>        requestHMIAnimation();
  5123     <xsl:text>        requestHMIAnimation();
  4759 </xsl:text>
  5124 </xsl:text>
  4862     <xsl:text>}
  5227     <xsl:text>}
  4863 </xsl:text>
  5228 </xsl:text>
  4864   </xsl:template>
  5229   </xsl:template>
  4865   <xsl:template match="widget[@type='Input']" mode="widget_defs">
  5230   <xsl:template match="widget[@type='Input']" mode="widget_defs">
  4866     <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"/>
  4867     <xsl:variable name="value_elt">
  5243     <xsl:variable name="value_elt">
  4868       <xsl:call-template name="defs_by_labels">
  5244       <xsl:call-template name="defs_by_labels">
  4869         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5245         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  4870         <xsl:with-param name="labels">
  5246         <xsl:with-param name="labels">
  4871           <xsl:text>value</xsl:text>
  5247           <xsl:text>value</xsl:text>
  5393     <xsl:text>        }
  5769     <xsl:text>        }
  5394 </xsl:text>
  5770 </xsl:text>
  5395   </xsl:template>
  5771   </xsl:template>
  5396   <xsl:template match="widget[@type='JsonTable']" mode="widget_defs">
  5772   <xsl:template match="widget[@type='JsonTable']" mode="widget_defs">
  5397     <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"/>
  5398     <xsl:call-template name="defs_by_labels">
  5785     <xsl:call-template name="defs_by_labels">
  5399       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5786       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5400       <xsl:with-param name="labels">
  5787       <xsl:with-param name="labels">
  5401         <xsl:text>data</xsl:text>
  5788         <xsl:text>data</xsl:text>
  5402       </xsl:with-param>
  5789       </xsl:with-param>
  5442   <xsl:template match="widget[@type='Jump']" mode="widget_desc">
  5829   <xsl:template match="widget[@type='Jump']" mode="widget_desc">
  5443     <type>
  5830     <type>
  5444       <xsl:value-of select="@type"/>
  5831       <xsl:value-of select="@type"/>
  5445     </type>
  5832     </type>
  5446     <longdesc>
  5833     <longdesc>
  5447       <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
  5448 </xsl:text>
  5835 </xsl:text>
  5449       <xsl:text>gives name of the page.
  5836       <xsl:text>gives name of the page.
  5450 </xsl:text>
  5837 </xsl:text>
  5451       <xsl:text>
  5838       <xsl:text>
  5452 </xsl:text>
  5839 </xsl:text>
  5453       <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
  5454 </xsl:text>
  5841 </xsl:text>
  5455       <xsl:text>page, it must point to a HMI_NODE.
  5842       <xsl:text>when jumping to a relative page.
  5456 </xsl:text>
  5843 </xsl:text>
  5457       <xsl:text>
  5844       <xsl:text>
  5458 </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>
  5459       <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
  5460 </xsl:text>
  5859 </xsl:text>
  5461       <xsl:text>page being shown.
  5860       <xsl:text>page being shown.
  5462 </xsl:text>
  5861 </xsl:text>
  5463       <xsl:text>
  5862       <xsl:text>
  5464 </xsl:text>
  5863 </xsl:text>
  5465       <xsl:text>"disabled" labeled element, if provided, is shown instead of "active" or
  5864       <xsl:text>Exemples:
  5466 </xsl:text>
  5865 </xsl:text>
  5467       <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>
  5468 </xsl:text>
  5905 </xsl:text>
  5469     </longdesc>
  5906     </longdesc>
  5470     <shortdesc>
  5907     <shortdesc>
  5471       <xsl:text>Jump to given page</xsl:text>
  5908       <xsl:text>Jump to given page</xsl:text>
  5472     </shortdesc>
  5909     </shortdesc>
  5482     <xsl:text>JumpWidget</xsl:text>
  5919     <xsl:text>JumpWidget</xsl:text>
  5483     <xsl:text> extends Widget{
  5920     <xsl:text> extends Widget{
  5484 </xsl:text>
  5921 </xsl:text>
  5485     <xsl:text>        activable = false;
  5922     <xsl:text>        activable = false;
  5486 </xsl:text>
  5923 </xsl:text>
  5487     <xsl:text>        active = false;
       
  5488 </xsl:text>
       
  5489     <xsl:text>        disabled = false;
       
  5490 </xsl:text>
       
  5491     <xsl:text>        frequency = 2;
  5924     <xsl:text>        frequency = 2;
  5492 </xsl:text>
  5925 </xsl:text>
  5493     <xsl:text>
  5926     <xsl:text>
  5494 </xsl:text>
  5927 </xsl:text>
  5495     <xsl:text>        update_activity() {
  5928     <xsl:text>        make_on_click() {
  5496 </xsl:text>
  5929 </xsl:text>
  5497     <xsl:text>            if(this.active) {
  5930     <xsl:text>            let that = this;
  5498 </xsl:text>
  5931 </xsl:text>
  5499     <xsl:text>                 /* show active */ 
  5932     <xsl:text>            const name = this.args[0];
  5500 </xsl:text>
  5933 </xsl:text>
  5501     <xsl:text>                 this.active_elt.style.display = "";
  5934     <xsl:text>            return function(evt){
  5502 </xsl:text>
  5935 </xsl:text>
  5503     <xsl:text>                 /* hide inactive */ 
  5936     <xsl:text>                /* TODO: in order to allow jumps to page selected through
  5504 </xsl:text>
  5937 </xsl:text>
  5505     <xsl:text>                 this.inactive_elt.style.display = "none";
  5938     <xsl:text>                   for exemple a dropdown, support path pointing to local
  5506 </xsl:text>
  5939 </xsl:text>
  5507     <xsl:text>            } else {
  5940     <xsl:text>                   variable whom value would be an HMI_TREE index and then
  5508 </xsl:text>
  5941 </xsl:text>
  5509     <xsl:text>                 /* show inactive */ 
  5942     <xsl:text>                   jump to a relative page not hard-coded in advance
  5510 </xsl:text>
  5943 </xsl:text>
  5511     <xsl:text>                 this.inactive_elt.style.display = "";
  5944     <xsl:text>                */
  5512 </xsl:text>
  5945 </xsl:text>
  5513     <xsl:text>                 /* hide active */ 
  5946     <xsl:text>                if(that.enable_state) {
  5514 </xsl:text>
  5947 </xsl:text>
  5515     <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>                }
  5516 </xsl:text>
  5959 </xsl:text>
  5517     <xsl:text>            }
  5960     <xsl:text>            }
  5518 </xsl:text>
  5961 </xsl:text>
  5519     <xsl:text>        }
  5962     <xsl:text>        }
  5520 </xsl:text>
  5963 </xsl:text>
  5521     <xsl:text>
  5964     <xsl:text>
  5522 </xsl:text>
  5965 </xsl:text>
  5523     <xsl:text>        update_disability() {
  5966     <xsl:text>        notify_page_change(page_name, index) {
  5524 </xsl:text>
  5967 </xsl:text>
  5525     <xsl:text>            if(this.disabled) {
  5968     <xsl:text>            // called from animate()
  5526 </xsl:text>
  5969 </xsl:text>
  5527     <xsl:text>                /* show disabled */ 
  5970     <xsl:text>            if(this.activable) {
  5528 </xsl:text>
  5971 </xsl:text>
  5529     <xsl:text>                this.disabled_elt.style.display = "";
  5972     <xsl:text>                const ref_index = this.indexes.length &gt; 0 ? this.indexes[0] + this.offset : undefined;
  5530 </xsl:text>
  5973 </xsl:text>
  5531     <xsl:text>                /* hide inactive */ 
  5974     <xsl:text>                const ref_name = this.args[0];
  5532 </xsl:text>
  5975 </xsl:text>
  5533     <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);
  5534 </xsl:text>
  5977 </xsl:text>
  5535     <xsl:text>                /* hide active */ 
  5978     <xsl:text>                // Since called from animate, update activity directly
  5536 </xsl:text>
  5979 </xsl:text>
  5537     <xsl:text>                this.active_elt.style.display = "none";
  5980     <xsl:text>                if(this.enable_displayed_state &amp;&amp; this.has_activity) {
  5538 </xsl:text>
  5981 </xsl:text>
  5539     <xsl:text>            } else {
  5982     <xsl:text>                    this.animate_activity();
  5540 </xsl:text>
  5983 </xsl:text>
  5541     <xsl:text>                /* hide disabled */ 
  5984     <xsl:text>                }
  5542 </xsl:text>
       
  5543     <xsl:text>                this.disabled_elt.style.display = "none";
       
  5544 </xsl:text>
       
  5545     <xsl:text>                this.update_activity();
       
  5546 </xsl:text>
  5985 </xsl:text>
  5547     <xsl:text>            }
  5986     <xsl:text>            }
  5548 </xsl:text>
  5987 </xsl:text>
  5549     <xsl:text>        }
  5988     <xsl:text>        }
  5550 </xsl:text>
  5989 </xsl:text>
  5551     <xsl:text>
       
  5552 </xsl:text>
       
  5553     <xsl:text>        make_on_click() {
       
  5554 </xsl:text>
       
  5555     <xsl:text>            let that = this;
       
  5556 </xsl:text>
       
  5557     <xsl:text>            const name = this.args[0];
       
  5558 </xsl:text>
       
  5559     <xsl:text>            return function(evt){
       
  5560 </xsl:text>
       
  5561     <xsl:text>                /* TODO: in order to allow jumps to page selected through for exemple a dropdown,
       
  5562 </xsl:text>
       
  5563     <xsl:text>                   support path pointing to local variable whom value 
       
  5564 </xsl:text>
       
  5565     <xsl:text>                   would be an HMI_TREE index and then jump to a relative page not hard-coded in advance */
       
  5566 </xsl:text>
       
  5567     <xsl:text>                if(!that.disabled) {
       
  5568 </xsl:text>
       
  5569     <xsl:text>                    const index = that.indexes.length &gt; 0 ? that.indexes[0] + that.offset : undefined;
       
  5570 </xsl:text>
       
  5571     <xsl:text>                    fading_page_switch(name, index);
       
  5572 </xsl:text>
       
  5573     <xsl:text>                }
       
  5574 </xsl:text>
       
  5575     <xsl:text>            }
       
  5576 </xsl:text>
       
  5577     <xsl:text>        }
       
  5578 </xsl:text>
       
  5579     <xsl:text>
       
  5580 </xsl:text>
       
  5581     <xsl:text>        notify_page_change(page_name, index) {
       
  5582 </xsl:text>
       
  5583     <xsl:text>            if(this.activable) {
       
  5584 </xsl:text>
       
  5585     <xsl:text>                const ref_index = this.indexes.length &gt; 0 ? this.indexes[0] + this.offset : undefined;
       
  5586 </xsl:text>
       
  5587     <xsl:text>                const ref_name = this.args[0];
       
  5588 </xsl:text>
       
  5589     <xsl:text>                this.active = ((ref_name == undefined || ref_name == page_name) &amp;&amp; index == ref_index);
       
  5590 </xsl:text>
       
  5591     <xsl:text>                this.update_state();
       
  5592 </xsl:text>
       
  5593     <xsl:text>            }
       
  5594 </xsl:text>
       
  5595     <xsl:text>        }
       
  5596 </xsl:text>
       
  5597     <xsl:text>
       
  5598 </xsl:text>
       
  5599     <xsl:text>        dispatch(value) {
       
  5600 </xsl:text>
       
  5601     <xsl:text>            this.disabled = !Number(value);
       
  5602 </xsl:text>
       
  5603     <xsl:text>
       
  5604 </xsl:text>
       
  5605     <xsl:text>            // TODO : use RequestAnimate and animate()
       
  5606 </xsl:text>
       
  5607     <xsl:text>
       
  5608 </xsl:text>
       
  5609     <xsl:text>            this.update_state();
       
  5610 </xsl:text>
       
  5611     <xsl:text>        }
       
  5612 </xsl:text>
       
  5613     <xsl:text>}
  5990     <xsl:text>}
  5614 </xsl:text>
  5991 </xsl:text>
  5615   </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>
  5616   <xsl:template match="widget[@type='Jump']" mode="widget_defs">
  5997   <xsl:template match="widget[@type='Jump']" mode="widget_defs">
  5617     <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>
  5618     <xsl:variable name="activity">
  6012     <xsl:variable name="activity">
  5619       <xsl:call-template name="defs_by_labels">
  6013       <xsl:call-template name="defs_by_labels">
  5620         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6014         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  5621         <xsl:with-param name="labels">
  6015         <xsl:with-param name="labels">
  5622           <xsl:text>active inactive</xsl:text>
  6016           <xsl:text>/active /inactive</xsl:text>
  5623         </xsl:with-param>
  6017         </xsl:with-param>
  5624         <xsl:with-param name="mandatory" select="'no'"/>
  6018         <xsl:with-param name="mandatory">
       
  6019           <xsl:text>no</xsl:text>
       
  6020         </xsl:with-param>
  5625       </xsl:call-template>
  6021       </xsl:call-template>
  5626     </xsl:variable>
  6022     </xsl:variable>
  5627     <xsl:variable name="have_activity" select="string-length($activity)&gt;0"/>
       
  5628     <xsl:value-of select="$activity"/>
  6023     <xsl:value-of select="$activity"/>
  5629     <xsl:variable name="disability">
  6024     <xsl:variable name="has_activity" select="string-length($activity)&gt;0"/>
  5630       <xsl:call-template name="defs_by_labels">
  6025     <xsl:text>    },
  5631         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6026 </xsl:text>
  5632         <xsl:with-param name="labels">
  6027     <xsl:text>    has_activity: </xsl:text>
  5633           <xsl:text>disabled</xsl:text>
  6028     <xsl:value-of select="$has_activity"/>
  5634         </xsl:with-param>
  6029     <xsl:text>,
  5635         <xsl:with-param name="mandatory" select="'no'"/>
  6030 </xsl:text>
  5636       </xsl:call-template>
  6031     <xsl:variable name="jump_disability" select="$has_activity and $has_disability"/>
  5637     </xsl:variable>
       
  5638     <xsl:variable name="have_disability" select="$have_activity and string-length($disability)&gt;0"/>
       
  5639     <xsl:value-of select="$disability"/>
       
  5640     <xsl:text>    init: function() {
  6032     <xsl:text>    init: function() {
  5641 </xsl:text>
  6033 </xsl:text>
  5642     <xsl:text>        this.element.onclick = this.make_on_click();
  6034     <xsl:text>        this.element.onclick = this.make_on_click();
  5643 </xsl:text>
  6035 </xsl:text>
  5644     <xsl:if test="$have_activity">
  6036     <xsl:if test="$has_activity">
  5645       <xsl:text>        this.activable = true;
  6037       <xsl:text>        this.activable = true;
  5646 </xsl:text>
  6038 </xsl:text>
  5647     </xsl:if>
  6039     </xsl:if>
  5648     <xsl:if test="not($have_disability)">
  6040     <xsl:text>        this.is_relative = </xsl:text>
  5649       <xsl:text>        this.unsubscribable = true;
       
  5650 </xsl:text>
       
  5651     </xsl:if>
       
  5652     <xsl:text>        this.update_state = </xsl:text>
       
  5653     <xsl:choose>
  6041     <xsl:choose>
  5654       <xsl:when test="$have_disability">
  6042       <xsl:when test="func:is_relative_jump(.)">
  5655         <xsl:text>this.update_disability</xsl:text>
  6043         <xsl:text>true</xsl:text>
  5656       </xsl:when>
       
  5657       <xsl:when test="$have_activity">
       
  5658         <xsl:text>this.update_activity</xsl:text>
       
  5659       </xsl:when>
  6044       </xsl:when>
  5660       <xsl:otherwise>
  6045       <xsl:otherwise>
  5661         <xsl:text>null</xsl:text>
  6046         <xsl:text>false</xsl:text>
  5662       </xsl:otherwise>
  6047       </xsl:otherwise>
  5663     </xsl:choose>
  6048     </xsl:choose>
  5664     <xsl:text>;
  6049     <xsl:text>;
  5665 </xsl:text>
  6050 </xsl:text>
  5666     <xsl:text>    },
  6051     <xsl:text>    },
  5667 </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>
  5668   </xsl:template>
  6079   </xsl:template>
  5669   <xsl:template match="widget[@type='Jump']" mode="widget_page">
  6080   <xsl:template match="widget[@type='Jump']" mode="widget_page">
  5670     <xsl:param name="page_desc"/>
  6081     <xsl:param name="page_desc"/>
  5671     <xsl:param name="page_desc"/>
  6082     <xsl:param name="page_desc"/>
  5672     <xsl:if test="path">
  6083     <xsl:if test="func:is_relative_jump(.)">
  5673       <xsl:variable name="target_page_name">
  6084       <xsl:variable name="target_page_name">
  5674         <xsl:choose>
  6085         <xsl:choose>
  5675           <xsl:when test="arg">
  6086           <xsl:when test="arg">
  5676             <xsl:value-of select="arg[1]/@value"/>
  6087             <xsl:value-of select="arg[1]/@value"/>
  5677           </xsl:when>
  6088           </xsl:when>
  5752 </xsl:text>
  6163 </xsl:text>
  5753     <xsl:text>
  6164     <xsl:text>
  5754 </xsl:text>
  6165 </xsl:text>
  5755     <xsl:text>function update_jumps() {
  6166     <xsl:text>function update_jumps() {
  5756 </xsl:text>
  6167 </xsl:text>
       
  6168     <xsl:text>    // called from animate()
       
  6169 </xsl:text>
  5757     <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));
  5758 </xsl:text>
  6171 </xsl:text>
  5759     <xsl:text>    jumps_need_update = false;
  6172     <xsl:text>    jumps_need_update = false;
  5760 </xsl:text>
  6173 </xsl:text>
  5761     <xsl:text>};
  6174     <xsl:text>};
  6000 </xsl:text>
  6413 </xsl:text>
  6001     <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){
  6002 </xsl:text>
  6415 </xsl:text>
  6003     <xsl:text>             this._shift = this.shift;
  6416     <xsl:text>             this._shift = this.shift;
  6004 </xsl:text>
  6417 </xsl:text>
  6005     <xsl:text>             set_activation_state(this.Shift_sub, this.shift);
  6418     <xsl:text>             set_activity_state(this.Shift_sub, this.shift);
  6006 </xsl:text>
  6419 </xsl:text>
  6007     <xsl:text>         }
  6420     <xsl:text>         }
  6008 </xsl:text>
  6421 </xsl:text>
  6009     <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){
  6010 </xsl:text>
  6423 </xsl:text>
  6011     <xsl:text>             this._caps = this.caps;
  6424     <xsl:text>             this._caps = this.caps;
  6012 </xsl:text>
  6425 </xsl:text>
  6013     <xsl:text>             set_activation_state(this.CapsLock_sub, this.caps);
  6426     <xsl:text>             set_activity_state(this.CapsLock_sub, this.caps);
  6014 </xsl:text>
  6427 </xsl:text>
  6015     <xsl:text>         }
  6428     <xsl:text>         }
  6016 </xsl:text>
  6429 </xsl:text>
  6017     <xsl:text>     }
  6430     <xsl:text>     }
  6018 </xsl:text>
  6431 </xsl:text>
  6019     <xsl:text>}
  6432     <xsl:text>}
  6020 </xsl:text>
  6433 </xsl:text>
  6021   </xsl:template>
  6434   </xsl:template>
  6022   <xsl:template match="widget[@type='Keypad']" mode="widget_defs">
  6435   <xsl:template match="widget[@type='Keypad']" mode="widget_defs">
  6023     <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"/>
  6024     <xsl:call-template name="defs_by_labels">
  6448     <xsl:call-template name="defs_by_labels">
  6025       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6449       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6026       <xsl:with-param name="labels">
  6450       <xsl:with-param name="labels">
  6027         <xsl:text>Esc Enter BackSpace Keys Value</xsl:text>
  6451         <xsl:text>Esc Enter BackSpace Keys Value</xsl:text>
  6028       </xsl:with-param>
  6452       </xsl:with-param>
  6111     </shortdesc>
  6535     </shortdesc>
  6112     <arg name="listname"/>
  6536     <arg name="listname"/>
  6113   </xsl:template>
  6537   </xsl:template>
  6114   <xsl:template match="widget[@type='List']" mode="widget_defs">
  6538   <xsl:template match="widget[@type='List']" mode="widget_defs">
  6115     <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"/>
  6116     <xsl:text>    items: {
  6551     <xsl:text>    items: {
  6117 </xsl:text>
  6552 </xsl:text>
  6118     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  6553     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  6119       <xsl:text>        "</xsl:text>
  6554       <xsl:text>        "</xsl:text>
  6120       <xsl:value-of select="@inkscape:label"/>
  6555       <xsl:value-of select="@inkscape:label"/>
  6175     <xsl:text>}
  6610     <xsl:text>}
  6176 </xsl:text>
  6611 </xsl:text>
  6177   </xsl:template>
  6612   </xsl:template>
  6178   <xsl:template match="widget[@type='ListSwitch']" mode="widget_defs">
  6613   <xsl:template match="widget[@type='ListSwitch']" mode="widget_defs">
  6179     <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"/>
  6180     <xsl:variable name="targetid" select="substring-after($hmi_element/@xlink:href,'#')"/>
  6626     <xsl:variable name="targetid" select="substring-after($hmi_element/@xlink:href,'#')"/>
  6181     <xsl:variable name="from_list" select="$hmi_lists[(@id | */@id) = $targetid]"/>
  6627     <xsl:variable name="from_list" select="$hmi_lists[(@id | */@id) = $targetid]"/>
  6182     <xsl:text>    dispatch: function(value) {
  6628     <xsl:text>    dispatch: function(value) {
  6183 </xsl:text>
  6629 </xsl:text>
  6184     <xsl:text>        this.element.href.baseVal = "#"+hmi_widgets["</xsl:text>
  6630     <xsl:text>        this.element.href.baseVal = "#"+hmi_widgets["</xsl:text>
  6281     <xsl:text>}
  6727     <xsl:text>}
  6282 </xsl:text>
  6728 </xsl:text>
  6283   </xsl:template>
  6729   </xsl:template>
  6284   <xsl:template match="widget[@type='Meter']" mode="widget_defs">
  6730   <xsl:template match="widget[@type='Meter']" mode="widget_defs">
  6285     <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"/>
  6286     <xsl:call-template name="defs_by_labels">
  6743     <xsl:call-template name="defs_by_labels">
  6287       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6744       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6288       <xsl:with-param name="labels">
  6745       <xsl:with-param name="labels">
  6289         <xsl:text>needle range</xsl:text>
  6746         <xsl:text>needle range</xsl:text>
  6290       </xsl:with-param>
  6747       </xsl:with-param>
  6297       <xsl:with-param name="mandatory" select="'no'"/>
  6754       <xsl:with-param name="mandatory" select="'no'"/>
  6298     </xsl:call-template>
  6755     </xsl:call-template>
  6299   </xsl:template>
  6756   </xsl:template>
  6300   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6757   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6301     <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"/>
  6302     <longdesc>
  6770     <longdesc>
  6303       <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
  6304 </xsl:text>
  6772 </xsl:text>
  6305       <xsl:text>variable value representation. For exemple if given variable type
  6773       <xsl:text>variable value representation. For exemple if given variable type
  6306 </xsl:text>
  6774 </xsl:text>
  6412     <xsl:text>}
  6880     <xsl:text>}
  6413 </xsl:text>
  6881 </xsl:text>
  6414   </xsl:template>
  6882   </xsl:template>
  6415   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6883   <xsl:template match="widget[@type='MultiState']" mode="widget_defs">
  6416     <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"/>
  6417     <xsl:text>    choices: [
  6896     <xsl:text>    choices: [
  6418 </xsl:text>
  6897 </xsl:text>
  6419     <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)(#.*)?$'"/>
  6420     <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)]">
  6421       <xsl:variable name="literal" select="regexp:match(@inkscape:label,$regex)[2]"/>
  6900       <xsl:variable name="literal" select="regexp:match(@inkscape:label,$regex)[2]"/>
  6774     <xsl:text>}
  7253     <xsl:text>}
  6775 </xsl:text>
  7254 </xsl:text>
  6776   </xsl:template>
  7255   </xsl:template>
  6777   <xsl:template match="widget[@type='PathSlider']" mode="widget_defs">
  7256   <xsl:template match="widget[@type='PathSlider']" mode="widget_defs">
  6778     <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"/>
  6779     <xsl:call-template name="defs_by_labels">
  7269     <xsl:call-template name="defs_by_labels">
  6780       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7270       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6781       <xsl:with-param name="labels">
  7271       <xsl:with-param name="labels">
  6782         <xsl:text>cursor path</xsl:text>
  7272         <xsl:text>cursor path</xsl:text>
  6783       </xsl:with-param>
  7273       </xsl:with-param>
  6982     <xsl:text>}
  7472     <xsl:text>}
  6983 </xsl:text>
  7473 </xsl:text>
  6984   </xsl:template>
  7474   </xsl:template>
  6985   <xsl:template match="widget[@type='ScrollBar']" mode="widget_defs">
  7475   <xsl:template match="widget[@type='ScrollBar']" mode="widget_defs">
  6986     <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"/>
  6987     <xsl:call-template name="defs_by_labels">
  7488     <xsl:call-template name="defs_by_labels">
  6988       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7489       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  6989       <xsl:with-param name="labels">
  7490       <xsl:with-param name="labels">
  6990         <xsl:text>cursor range</xsl:text>
  7491         <xsl:text>cursor range</xsl:text>
  6991       </xsl:with-param>
  7492       </xsl:with-param>
  7709     <xsl:text>}
  8210     <xsl:text>}
  7710 </xsl:text>
  8211 </xsl:text>
  7711   </xsl:template>
  8212   </xsl:template>
  7712   <xsl:template match="widget[@type='Slider']" mode="widget_defs">
  8213   <xsl:template match="widget[@type='Slider']" mode="widget_defs">
  7713     <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"/>
  7714     <xsl:call-template name="defs_by_labels">
  8226     <xsl:call-template name="defs_by_labels">
  7715       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8227       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  7716       <xsl:with-param name="labels">
  8228       <xsl:with-param name="labels">
  7717         <xsl:text>handle range</xsl:text>
  8229         <xsl:text>handle range</xsl:text>
  7718       </xsl:with-param>
  8230       </xsl:with-param>
  7812     <xsl:text>}
  8324     <xsl:text>}
  7813 </xsl:text>
  8325 </xsl:text>
  7814   </xsl:template>
  8326   </xsl:template>
  7815   <xsl:template match="widget[@type='Switch']" mode="widget_defs">
  8327   <xsl:template match="widget[@type='Switch']" mode="widget_defs">
  7816     <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"/>
  7817     <xsl:text>    choices: [
  8340     <xsl:text>    choices: [
  7818 </xsl:text>
  8341 </xsl:text>
  7819     <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)(#.*)?$'"/>
  7820     <xsl:variable name="subelts" select="$result_widgets[@id = $hmi_element/@id]//*"/>
  8343     <xsl:variable name="subelts" select="$result_widgets[@id = $hmi_element/@id]//*"/>
  7821     <xsl:variable name="subwidgets" select="$subelts//*[@id = $hmi_widgets/@id]"/>
  8344     <xsl:variable name="subwidgets" select="$subelts//*[@id = $hmi_widgets/@id]"/>
  7885     </shortdesc>
  8408     </shortdesc>
  7886     <arg name="listname"/>
  8409     <arg name="listname"/>
  7887   </xsl:template>
  8410   </xsl:template>
  7888   <xsl:template match="widget[@type='TextList']" mode="widget_defs">
  8411   <xsl:template match="widget[@type='TextList']" mode="widget_defs">
  7889     <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"/>
  7890     <xsl:text>    texts: [
  8424     <xsl:text>    texts: [
  7891 </xsl:text>
  8425 </xsl:text>
  7892     <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]">
  7893       <xsl:text>        id("</xsl:text>
  8427       <xsl:text>        id("</xsl:text>
  7894       <xsl:value-of select="@id"/>
  8428       <xsl:value-of select="@id"/>
  7931     </shortdesc>
  8465     </shortdesc>
  7932     <arg name="listname"/>
  8466     <arg name="listname"/>
  7933   </xsl:template>
  8467   </xsl:template>
  7934   <xsl:template match="widget[@type='TextStyleList']" mode="widget_defs">
  8468   <xsl:template match="widget[@type='TextStyleList']" mode="widget_defs">
  7935     <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"/>
  7936     <xsl:text>    styles: {
  8481     <xsl:text>    styles: {
  7937 </xsl:text>
  8482 </xsl:text>
  7938     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  8483     <xsl:for-each select="$hmi_element/*[@inkscape:label]">
  7939       <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"/>
  7940       <xsl:text>        </xsl:text>
  8485       <xsl:text>        </xsl:text>
  7979     <xsl:text>ToggleButtonWidget</xsl:text>
  8524     <xsl:text>ToggleButtonWidget</xsl:text>
  7980     <xsl:text> extends Widget{
  8525     <xsl:text> extends Widget{
  7981 </xsl:text>
  8526 </xsl:text>
  7982     <xsl:text>    frequency = 5;
  8527     <xsl:text>    frequency = 5;
  7983 </xsl:text>
  8528 </xsl:text>
  7984     <xsl:text>    state = 0;
       
  7985 </xsl:text>
       
  7986     <xsl:text>    active_style = undefined;
  8529     <xsl:text>    active_style = undefined;
  7987 </xsl:text>
  8530 </xsl:text>
  7988     <xsl:text>    inactive_style = undefined;
  8531     <xsl:text>    inactive_style = undefined;
  7989 </xsl:text>
  8532 </xsl:text>
  7990     <xsl:text>
  8533     <xsl:text>
  7991 </xsl:text>
  8534 </xsl:text>
  7992     <xsl:text>    dispatch(value) {
  8535     <xsl:text>    dispatch(value) {
  7993 </xsl:text>
  8536 </xsl:text>
  7994     <xsl:text>        this.state = value;
  8537     <xsl:text>        this.activity_state = Boolean(value);
  7995 </xsl:text>
  8538 </xsl:text>
  7996     <xsl:text>        //redraw toggle button
  8539     <xsl:text>        //redraw toggle button
  7997 </xsl:text>
  8540 </xsl:text>
  7998     <xsl:text>        this.request_animate();
  8541     <xsl:text>        this.request_animate();
  7999 </xsl:text>
  8542 </xsl:text>
  8003 </xsl:text>
  8546 </xsl:text>
  8004     <xsl:text>    on_click(evt) {
  8547     <xsl:text>    on_click(evt) {
  8005 </xsl:text>
  8548 </xsl:text>
  8006     <xsl:text>        //toggle state and apply
  8549     <xsl:text>        //toggle state and apply
  8007 </xsl:text>
  8550 </xsl:text>
  8008     <xsl:text>        this.state = this.state ? false : true;
  8551     <xsl:text>        this.activity_state = this.activity_state ? false : true;
  8009 </xsl:text>
  8552 </xsl:text>
  8010     <xsl:text>        this.apply_hmi_value(0, this.state);
  8553     <xsl:text>        this.apply_hmi_value(0, this.activity_state);
  8011 </xsl:text>
  8554 </xsl:text>
  8012     <xsl:text>
  8555     <xsl:text>
  8013 </xsl:text>
  8556 </xsl:text>
  8014     <xsl:text>        //redraw toggle button
  8557     <xsl:text>        //redraw toggle button
  8015 </xsl:text>
  8558 </xsl:text>
  8017 </xsl:text>
  8560 </xsl:text>
  8018     <xsl:text>    }
  8561     <xsl:text>    }
  8019 </xsl:text>
  8562 </xsl:text>
  8020     <xsl:text>
  8563     <xsl:text>
  8021 </xsl:text>
  8564 </xsl:text>
  8022     <xsl:text>    animate(){
       
  8023 </xsl:text>
       
  8024     <xsl:text>        // redraw toggle button on screen refresh
       
  8025 </xsl:text>
       
  8026     <xsl:text>        this.set_activation_state(this.state);
       
  8027 </xsl:text>
       
  8028     <xsl:text>    }
       
  8029 </xsl:text>
       
  8030     <xsl:text>
       
  8031 </xsl:text>
       
  8032     <xsl:text>    init() {
  8565     <xsl:text>    init() {
  8033 </xsl:text>
  8566 </xsl:text>
  8034     <xsl:text>        this.element.onclick = (evt) =&gt; this.on_click(evt);
  8567     <xsl:text>        this.element.onclick = (evt) =&gt; this.on_click(evt);
  8035 </xsl:text>
  8568 </xsl:text>
  8036     <xsl:text>        this.set_activation_state(undefined);
  8569     <xsl:text>        this.activity_state = undefined;
  8037 </xsl:text>
  8570 </xsl:text>
  8038     <xsl:text>    }
  8571     <xsl:text>    }
  8039 </xsl:text>
  8572 </xsl:text>
  8040     <xsl:text>}
  8573     <xsl:text>}
  8041 </xsl:text>
  8574 </xsl:text>
  8042   </xsl:template>
  8575   </xsl:template>
  8043   <xsl:template match="widget[@type='ToggleButton']" mode="widget_defs">
  8576   <xsl:template match="widget[@type='ToggleButton']" mode="widget_defs">
  8044     <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"/>
  8045     <xsl:text>    activable_sub:{
  8589     <xsl:text>    activable_sub:{
  8046 </xsl:text>
  8590 </xsl:text>
  8047     <xsl:call-template name="defs_by_labels">
  8591     <xsl:variable name="activity">
  8048       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8592       <xsl:call-template name="defs_by_labels">
  8049       <xsl:with-param name="labels">
  8593         <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8050         <xsl:text>/active /inactive</xsl:text>
  8594         <xsl:with-param name="labels">
  8051       </xsl:with-param>
  8595           <xsl:text>/active /inactive</xsl:text>
  8052       <xsl:with-param name="mandatory" select="'warn'"/>
  8596         </xsl:with-param>
  8053     </xsl:call-template>
  8597         <xsl:with-param name="mandatory">
  8054     <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>,
  8055 </xsl:text>
  8609 </xsl:text>
  8056   </xsl:template>
  8610   </xsl:template>
  8057   <xsl:template match="widget[@type='XYGraph']" mode="widget_desc">
  8611   <xsl:template match="widget[@type='XYGraph']" mode="widget_desc">
  8058     <type>
  8612     <type>
  8059       <xsl:value-of select="@type"/>
  8613       <xsl:value-of select="@type"/>
  8523     </xsl:variable>
  9077     </xsl:variable>
  8524     <func:result select="$res"/>
  9078     <func:result select="$res"/>
  8525   </func:function>
  9079   </func:function>
  8526   <xsl:template match="widget[@type='XYGraph']" mode="widget_defs">
  9080   <xsl:template match="widget[@type='XYGraph']" mode="widget_defs">
  8527     <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"/>
  8528     <xsl:call-template name="defs_by_labels">
  9093     <xsl:call-template name="defs_by_labels">
  8529       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  9094       <xsl:with-param name="hmi_element" select="$hmi_element"/>
  8530       <xsl:with-param name="labels">
  9095       <xsl:with-param name="labels">
  8531         <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>
  8532       </xsl:with-param>
  9097       </xsl:with-param>
  9400         </style>
  9965         </style>
  9401       </head>
  9966       </head>
  9402       <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;">
  9403         <xsl:copy-of select="$result_svg"/>
  9968         <xsl:copy-of select="$result_svg"/>
  9404         <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>
  9405           <xsl:text>
 10400           <xsl:text>
  9406 //
 10401 //
  9407 //
 10402 //
  9408 // Early independent declarations 
 10403 // Early independent declarations 
  9409 //
 10404 //
  9998 </xsl:text>
 10993 </xsl:text>
  9999           <xsl:text>    /* eslint-enable quote-props */
 10994           <xsl:text>    /* eslint-enable quote-props */
 10000 </xsl:text>
 10995 </xsl:text>
 10001           <xsl:text>}(); // eslint-disable-line    
 10996           <xsl:text>}(); // eslint-disable-line    
 10002 </xsl:text>
 10997 </xsl:text>
 10003           <xsl:text>/*
 10998           <xsl:text>// svghmi.js
 10004 </xsl:text>
 10999 </xsl:text>
 10005           <xsl:text>
 11000           <xsl:text>
 10006 </xsl:text>
 11001 </xsl:text>
 10007           <xsl:text>From https://github.com/keyvan-m-sadeghi/pythonic
 11002           <xsl:text>function dispatch_value(index, value) {
 10008 </xsl:text>
 11003 </xsl:text>
 10009           <xsl:text>
 11004           <xsl:text>    let widgets = subscribers(index);
 10010 </xsl:text>
 11005 </xsl:text>
 10011           <xsl:text>Slightly modified in order to be usable in browser (i.e. not as a node.js module)
 11006           <xsl:text>
 10012 </xsl:text>
 11007 </xsl:text>
 10013           <xsl:text>
 11008           <xsl:text>    let oldval = cache[index];
 10014 </xsl:text>
 11009 </xsl:text>
 10015           <xsl:text>The MIT License (MIT)
 11010           <xsl:text>    cache[index] = value;
 10016 </xsl:text>
 11011 </xsl:text>
 10017           <xsl:text>
 11012           <xsl:text>
 10018 </xsl:text>
 11013 </xsl:text>
 10019           <xsl:text>Copyright (c) 2016 Assister.Ai
 11014           <xsl:text>    if(widgets.size &gt; 0) {
 10020 </xsl:text>
 11015 </xsl:text>
 10021           <xsl:text>
 11016           <xsl:text>        for(let widget of widgets){
 10022 </xsl:text>
 11017 </xsl:text>
 10023           <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);
 10024 </xsl:text>
 11019 </xsl:text>
 10025           <xsl:text>this software and associated documentation files (the "Software"), to deal in
 11020           <xsl:text>        }
 10026 </xsl:text>
       
 10027           <xsl:text>the Software without restriction, including without limitation the rights to
       
 10028 </xsl:text>
       
 10029           <xsl:text>use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
       
 10030 </xsl:text>
       
 10031           <xsl:text>the Software, and to permit persons to whom the Software is furnished to do so,
       
 10032 </xsl:text>
       
 10033           <xsl:text>subject to the following conditions:
       
 10034 </xsl:text>
       
 10035           <xsl:text>
       
 10036 </xsl:text>
       
 10037           <xsl:text>The above copyright notice and this permission notice shall be included in all
       
 10038 </xsl:text>
       
 10039           <xsl:text>copies or substantial portions of the Software.
       
 10040 </xsl:text>
       
 10041           <xsl:text>
       
 10042 </xsl:text>
       
 10043           <xsl:text>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
 10044 </xsl:text>
       
 10045           <xsl:text>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
       
 10046 </xsl:text>
       
 10047           <xsl:text>FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
       
 10048 </xsl:text>
       
 10049           <xsl:text>COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
       
 10050 </xsl:text>
       
 10051           <xsl:text>IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
       
 10052 </xsl:text>
       
 10053           <xsl:text>CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
       
 10054 </xsl:text>
       
 10055           <xsl:text>*/
       
 10056 </xsl:text>
       
 10057           <xsl:text>
       
 10058 </xsl:text>
       
 10059           <xsl:text>class Iterator {
       
 10060 </xsl:text>
       
 10061           <xsl:text>    constructor(generator) {
       
 10062 </xsl:text>
       
 10063           <xsl:text>        this[Symbol.iterator] = generator;
       
 10064 </xsl:text>
 11021 </xsl:text>
 10065           <xsl:text>    }
 11022           <xsl:text>    }
 10066 </xsl:text>
 11023 </xsl:text>
 10067           <xsl:text>
 11024           <xsl:text>};
 10068 </xsl:text>
 11025 </xsl:text>
 10069           <xsl:text>    async * [Symbol.asyncIterator]() {
 11026           <xsl:text>
 10070 </xsl:text>
 11027 </xsl:text>
 10071           <xsl:text>        for (const element of this) {
 11028           <xsl:text>function init_widgets() {
 10072 </xsl:text>
 11029 </xsl:text>
 10073           <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;
 10074 </xsl:text>
 11137 </xsl:text>
 10075           <xsl:text>        }
 11138           <xsl:text>        }
 10076 </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>
 10077           <xsl:text>    }
 11202           <xsl:text>    }
 10078 </xsl:text>
 11203 </xsl:text>
 10079           <xsl:text>
 11204           <xsl:text>}
 10080 </xsl:text>
 11205 </xsl:text>
 10081           <xsl:text>    forEach(callback) {
 11206           <xsl:text>
 10082 </xsl:text>
 11207 </xsl:text>
 10083           <xsl:text>        for (const element of this) {
 11208           <xsl:text>// Message reception handler
 10084 </xsl:text>
 11209 </xsl:text>
 10085           <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);
 10086 </xsl:text>
 11335 </xsl:text>
 10087           <xsl:text>        }
 11336           <xsl:text>        }
 10088 </xsl:text>
 11337 </xsl:text>
       
 11338           <xsl:text>        return binary;
       
 11339 </xsl:text>
 10089           <xsl:text>    }
 11340           <xsl:text>    }
 10090 </xsl:text>
 11341 </xsl:text>
 10091           <xsl:text>
 11342           <xsl:text>    /* TODO */
 10092 </xsl:text>
 11343 </xsl:text>
 10093           <xsl:text>    map(callback) {
 11344           <xsl:text>};
 10094 </xsl:text>
 11345 </xsl:text>
 10095           <xsl:text>        const result = [];
 11346           <xsl:text>
 10096 </xsl:text>
 11347 </xsl:text>
 10097           <xsl:text>        for (const element of this) {
 11348           <xsl:text>function send_reset() {
 10098 </xsl:text>
 11349 </xsl:text>
 10099           <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);
 10100 </xsl:text>
 11437 </xsl:text>
 10101           <xsl:text>        }
 11438           <xsl:text>        }
 10102 </xsl:text>
 11439 </xsl:text>
 10103           <xsl:text>
 11440           <xsl:text>    });
 10104 </xsl:text>
 11441 </xsl:text>
 10105           <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));
 10106 </xsl:text>
 11491 </xsl:text>
 10107           <xsl:text>    }
 11492           <xsl:text>    }
 10108 </xsl:text>
 11493 </xsl:text>
 10109           <xsl:text>
 11494           <xsl:text>});
 10110 </xsl:text>
 11495 </xsl:text>
 10111           <xsl:text>    filter(callback) {
 11496           <xsl:text>
 10112 </xsl:text>
 11497 </xsl:text>
 10113           <xsl:text>        const result = [];
 11498           <xsl:text>function svg_text_to_multiline(elt) {
 10114 </xsl:text>
 11499 </xsl:text>
 10115           <xsl:text>        for (const element of this) {
 11500           <xsl:text>    return(Array.prototype.map.call(elt.children, x=&gt;x.textContent).join("\n")); 
 10116 </xsl:text>
 11501 </xsl:text>
 10117           <xsl:text>            if (callback(element)) {
 11502           <xsl:text>}
 10118 </xsl:text>
 11503 </xsl:text>
 10119           <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;
 10120 </xsl:text>
 11643 </xsl:text>
 10121           <xsl:text>            }
 11644           <xsl:text>            }
 10122 </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>
 10123           <xsl:text>        }
 11652           <xsl:text>        }
 10124 </xsl:text>
 11653 </xsl:text>
 10125           <xsl:text>
 11654           <xsl:text>
 10126 </xsl:text>
 11655 </xsl:text>
 10127           <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>        }
 10128 </xsl:text>
 11673 </xsl:text>
 10129           <xsl:text>    }
 11674           <xsl:text>    }
 10130 </xsl:text>
 11675 </xsl:text>
 10131           <xsl:text>
 11676           <xsl:text>    send_blob(delta);
 10132 </xsl:text>
 11677 </xsl:text>
 10133           <xsl:text>    reduce(callback, initialValue) {
 11678           <xsl:text>};
 10134 </xsl:text>
 11679 </xsl:text>
 10135           <xsl:text>        let empty = typeof initialValue === 'undefined';
 11680           <xsl:text>
 10136 </xsl:text>
 11681 </xsl:text>
 10137           <xsl:text>        let accumulator = initialValue;
 11682           <xsl:text>function send_hmi_value(index, value) {
 10138 </xsl:text>
 11683 </xsl:text>
 10139           <xsl:text>        let index = 0;
 11684           <xsl:text>    if(index &gt; last_remote_index){
 10140 </xsl:text>
 11685 </xsl:text>
 10141           <xsl:text>        for (const currentValue of this) {
 11686           <xsl:text>        dispatch_value(index, value);
 10142 </xsl:text>
 11687 </xsl:text>
 10143           <xsl:text>            if (empty) {
 11688           <xsl:text>
 10144 </xsl:text>
 11689 </xsl:text>
 10145           <xsl:text>                accumulator = currentValue;
 11690           <xsl:text>        if(persistent_indexes.has(index)){
 10146 </xsl:text>
 11691 </xsl:text>
 10147           <xsl:text>                empty = false;
 11692           <xsl:text>            let varname = persistent_indexes.get(index);
 10148 </xsl:text>
 11693 </xsl:text>
 10149           <xsl:text>                continue;
 11694           <xsl:text>            document.cookie = varname+"="+value+"; max-age=3153600000";
 10150 </xsl:text>
       
 10151           <xsl:text>            }
       
 10152 </xsl:text>
       
 10153           <xsl:text>
       
 10154 </xsl:text>
       
 10155           <xsl:text>            accumulator = callback(accumulator, currentValue, index, this);
       
 10156 </xsl:text>
       
 10157           <xsl:text>            index++;
       
 10158 </xsl:text>
 11695 </xsl:text>
 10159           <xsl:text>        }
 11696           <xsl:text>        }
 10160 </xsl:text>
 11697 </xsl:text>
 10161           <xsl:text>
 11698           <xsl:text>
 10162 </xsl:text>
       
 10163           <xsl:text>        if (empty) {
       
 10164 </xsl:text>
       
 10165           <xsl:text>            throw new TypeError('Reduce of empty Iterator with no initial value');
       
 10166 </xsl:text>
       
 10167           <xsl:text>        }
       
 10168 </xsl:text>
       
 10169           <xsl:text>
       
 10170 </xsl:text>
       
 10171           <xsl:text>        return accumulator;
       
 10172 </xsl:text>
       
 10173           <xsl:text>    }
       
 10174 </xsl:text>
       
 10175           <xsl:text>
       
 10176 </xsl:text>
       
 10177           <xsl:text>    some(callback) {
       
 10178 </xsl:text>
       
 10179           <xsl:text>        for (const element of this) {
       
 10180 </xsl:text>
       
 10181           <xsl:text>            if (callback(element)) {
       
 10182 </xsl:text>
       
 10183           <xsl:text>                return true;
       
 10184 </xsl:text>
       
 10185           <xsl:text>            }
       
 10186 </xsl:text>
       
 10187           <xsl:text>        }
       
 10188 </xsl:text>
       
 10189           <xsl:text>
       
 10190 </xsl:text>
       
 10191           <xsl:text>        return false;
       
 10192 </xsl:text>
       
 10193           <xsl:text>    }
       
 10194 </xsl:text>
       
 10195           <xsl:text>
       
 10196 </xsl:text>
       
 10197           <xsl:text>    every(callback) {
       
 10198 </xsl:text>
       
 10199           <xsl:text>        for (const element of this) {
       
 10200 </xsl:text>
       
 10201           <xsl:text>            if (!callback(element)) {
       
 10202 </xsl:text>
       
 10203           <xsl:text>                return false;
       
 10204 </xsl:text>
       
 10205           <xsl:text>            }
       
 10206 </xsl:text>
       
 10207           <xsl:text>        }
       
 10208 </xsl:text>
       
 10209           <xsl:text>
       
 10210 </xsl:text>
       
 10211           <xsl:text>        return true;
       
 10212 </xsl:text>
       
 10213           <xsl:text>    }
       
 10214 </xsl:text>
       
 10215           <xsl:text>
       
 10216 </xsl:text>
       
 10217           <xsl:text>    static fromIterable(iterable) {
       
 10218 </xsl:text>
       
 10219           <xsl:text>        return new Iterator(function * () {
       
 10220 </xsl:text>
       
 10221           <xsl:text>            for (const element of iterable) {
       
 10222 </xsl:text>
       
 10223           <xsl:text>                yield element;
       
 10224 </xsl:text>
       
 10225           <xsl:text>            }
       
 10226 </xsl:text>
       
 10227           <xsl:text>        });
       
 10228 </xsl:text>
       
 10229           <xsl:text>    }
       
 10230 </xsl:text>
       
 10231           <xsl:text>
       
 10232 </xsl:text>
       
 10233           <xsl:text>    toArray() {
       
 10234 </xsl:text>
       
 10235           <xsl:text>        return Array.from(this);
       
 10236 </xsl:text>
       
 10237           <xsl:text>    }
       
 10238 </xsl:text>
       
 10239           <xsl:text>
       
 10240 </xsl:text>
       
 10241           <xsl:text>    next() {
       
 10242 </xsl:text>
       
 10243           <xsl:text>        if (!this.currentInvokedGenerator) {
       
 10244 </xsl:text>
       
 10245           <xsl:text>            this.currentInvokedGenerator = this[Symbol.iterator]();
       
 10246 </xsl:text>
       
 10247           <xsl:text>        }
       
 10248 </xsl:text>
       
 10249           <xsl:text>
       
 10250 </xsl:text>
       
 10251           <xsl:text>        return this.currentInvokedGenerator.next();
       
 10252 </xsl:text>
       
 10253           <xsl:text>    }
       
 10254 </xsl:text>
       
 10255           <xsl:text>
       
 10256 </xsl:text>
       
 10257           <xsl:text>    reset() {
       
 10258 </xsl:text>
       
 10259           <xsl:text>        delete this.currentInvokedGenerator;
       
 10260 </xsl:text>
       
 10261           <xsl:text>    }
       
 10262 </xsl:text>
       
 10263           <xsl:text>}
       
 10264 </xsl:text>
       
 10265           <xsl:text>
       
 10266 </xsl:text>
       
 10267           <xsl:text>function rangeSimple(stop) {
       
 10268 </xsl:text>
       
 10269           <xsl:text>    return new Iterator(function * () {
       
 10270 </xsl:text>
       
 10271           <xsl:text>        for (let i = 0; i &lt; stop; i++) {
       
 10272 </xsl:text>
       
 10273           <xsl:text>            yield i;
       
 10274 </xsl:text>
       
 10275           <xsl:text>        }
       
 10276 </xsl:text>
       
 10277           <xsl:text>    });
       
 10278 </xsl:text>
       
 10279           <xsl:text>}
       
 10280 </xsl:text>
       
 10281           <xsl:text>
       
 10282 </xsl:text>
       
 10283           <xsl:text>function rangeOverload(start, stop, step = 1) {
       
 10284 </xsl:text>
       
 10285           <xsl:text>    return new Iterator(function * () {
       
 10286 </xsl:text>
       
 10287           <xsl:text>        for (let i = start; i &lt; stop; i += step) {
       
 10288 </xsl:text>
       
 10289           <xsl:text>            yield i;
       
 10290 </xsl:text>
       
 10291           <xsl:text>        }
       
 10292 </xsl:text>
       
 10293           <xsl:text>    });
       
 10294 </xsl:text>
       
 10295           <xsl:text>}
       
 10296 </xsl:text>
       
 10297           <xsl:text>
       
 10298 </xsl:text>
       
 10299           <xsl:text>function range(...args) {
       
 10300 </xsl:text>
       
 10301           <xsl:text>    if (args.length &lt; 2) {
       
 10302 </xsl:text>
       
 10303           <xsl:text>        return rangeSimple(...args);
       
 10304 </xsl:text>
       
 10305           <xsl:text>    }
       
 10306 </xsl:text>
       
 10307           <xsl:text>
       
 10308 </xsl:text>
       
 10309           <xsl:text>    return rangeOverload(...args);
       
 10310 </xsl:text>
       
 10311           <xsl:text>}
       
 10312 </xsl:text>
       
 10313           <xsl:text>
       
 10314 </xsl:text>
       
 10315           <xsl:text>function enumerate(iterable) {
       
 10316 </xsl:text>
       
 10317           <xsl:text>    return new Iterator(function * () {
       
 10318 </xsl:text>
       
 10319           <xsl:text>        let index = 0;
       
 10320 </xsl:text>
       
 10321           <xsl:text>        for (const element of iterable) {
       
 10322 </xsl:text>
       
 10323           <xsl:text>            yield [index, element];
       
 10324 </xsl:text>
       
 10325           <xsl:text>            index++;
       
 10326 </xsl:text>
       
 10327           <xsl:text>        }
       
 10328 </xsl:text>
       
 10329           <xsl:text>    });
       
 10330 </xsl:text>
       
 10331           <xsl:text>}
       
 10332 </xsl:text>
       
 10333           <xsl:text>
       
 10334 </xsl:text>
       
 10335           <xsl:text>const _zip = longest =&gt; (...iterables) =&gt; {
       
 10336 </xsl:text>
       
 10337           <xsl:text>    if (iterables.length &lt; 2) {
       
 10338 </xsl:text>
       
 10339           <xsl:text>        throw new TypeError("zip takes 2 iterables at least, "+iterables.length+" given");
       
 10340 </xsl:text>
       
 10341           <xsl:text>    }
       
 10342 </xsl:text>
       
 10343           <xsl:text>
       
 10344 </xsl:text>
       
 10345           <xsl:text>    return new Iterator(function * () {
       
 10346 </xsl:text>
       
 10347           <xsl:text>        const iterators = iterables.map(iterable =&gt; Iterator.fromIterable(iterable));
       
 10348 </xsl:text>
       
 10349           <xsl:text>        while (true) {
       
 10350 </xsl:text>
       
 10351           <xsl:text>            const row = iterators.map(iterator =&gt; iterator.next());
       
 10352 </xsl:text>
       
 10353           <xsl:text>            const check = longest ? row.every.bind(row) : row.some.bind(row);
       
 10354 </xsl:text>
       
 10355           <xsl:text>            if (check(next =&gt; next.done)) {
       
 10356 </xsl:text>
       
 10357           <xsl:text>                return;
       
 10358 </xsl:text>
       
 10359           <xsl:text>            }
       
 10360 </xsl:text>
       
 10361           <xsl:text>
       
 10362 </xsl:text>
       
 10363           <xsl:text>            yield row.map(next =&gt; next.value);
       
 10364 </xsl:text>
       
 10365           <xsl:text>        }
       
 10366 </xsl:text>
       
 10367           <xsl:text>    });
       
 10368 </xsl:text>
       
 10369           <xsl:text>};
       
 10370 </xsl:text>
       
 10371           <xsl:text>
       
 10372 </xsl:text>
       
 10373           <xsl:text>const zip = _zip(false), zipLongest= _zip(true);
       
 10374 </xsl:text>
       
 10375           <xsl:text>
       
 10376 </xsl:text>
       
 10377           <xsl:text>function items(obj) {
       
 10378 </xsl:text>
       
 10379           <xsl:text>    let {keys, get} = obj;
       
 10380 </xsl:text>
       
 10381           <xsl:text>    if (obj instanceof Map) {
       
 10382 </xsl:text>
       
 10383           <xsl:text>        keys = keys.bind(obj);
       
 10384 </xsl:text>
       
 10385           <xsl:text>        get = get.bind(obj);
       
 10386 </xsl:text>
       
 10387           <xsl:text>    } else {
       
 10388 </xsl:text>
       
 10389           <xsl:text>        keys = function () {
       
 10390 </xsl:text>
       
 10391           <xsl:text>            return Object.keys(obj);
       
 10392 </xsl:text>
       
 10393           <xsl:text>        };
       
 10394 </xsl:text>
       
 10395           <xsl:text>
       
 10396 </xsl:text>
       
 10397           <xsl:text>        get = function (key) {
       
 10398 </xsl:text>
       
 10399           <xsl:text>            return obj[key];
       
 10400 </xsl:text>
       
 10401           <xsl:text>        };
       
 10402 </xsl:text>
       
 10403           <xsl:text>    }
       
 10404 </xsl:text>
       
 10405           <xsl:text>
       
 10406 </xsl:text>
       
 10407           <xsl:text>    return new Iterator(function * () {
       
 10408 </xsl:text>
       
 10409           <xsl:text>        for (const key of keys()) {
       
 10410 </xsl:text>
       
 10411           <xsl:text>            yield [key, get(key)];
       
 10412 </xsl:text>
       
 10413           <xsl:text>        }
       
 10414 </xsl:text>
       
 10415           <xsl:text>    });
       
 10416 </xsl:text>
       
 10417           <xsl:text>}
       
 10418 </xsl:text>
       
 10419           <xsl:text>
       
 10420 </xsl:text>
       
 10421           <xsl:text>/*
       
 10422 </xsl:text>
       
 10423           <xsl:text>module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items};
       
 10424 </xsl:text>
       
 10425           <xsl:text>*/
       
 10426 </xsl:text>
       
 10427           <xsl:text>// svghmi.js
       
 10428 </xsl:text>
       
 10429           <xsl:text>
       
 10430 </xsl:text>
       
 10431           <xsl:text>var need_cache_apply = [];
       
 10432 </xsl:text>
       
 10433           <xsl:text>
       
 10434 </xsl:text>
       
 10435           <xsl:text>function dispatch_value(index, value) {
       
 10436 </xsl:text>
       
 10437           <xsl:text>    let widgets = subscribers(index);
       
 10438 </xsl:text>
       
 10439           <xsl:text>
       
 10440 </xsl:text>
       
 10441           <xsl:text>    let oldval = cache[index];
       
 10442 </xsl:text>
       
 10443           <xsl:text>    cache[index] = value;
       
 10444 </xsl:text>
       
 10445           <xsl:text>
       
 10446 </xsl:text>
       
 10447           <xsl:text>    if(widgets.size &gt; 0) {
       
 10448 </xsl:text>
       
 10449           <xsl:text>        for(let widget of widgets){
       
 10450 </xsl:text>
       
 10451           <xsl:text>            widget.new_hmi_value(index, value, oldval);
       
 10452 </xsl:text>
       
 10453           <xsl:text>        }
       
 10454 </xsl:text>
       
 10455           <xsl:text>    }
       
 10456 </xsl:text>
       
 10457           <xsl:text>};
       
 10458 </xsl:text>
       
 10459           <xsl:text>
       
 10460 </xsl:text>
       
 10461           <xsl:text>function init_widgets() {
       
 10462 </xsl:text>
       
 10463           <xsl:text>    Object.keys(hmi_widgets).forEach(function(id) {
       
 10464 </xsl:text>
       
 10465           <xsl:text>        let widget = hmi_widgets[id];
       
 10466 </xsl:text>
       
 10467           <xsl:text>        widget.do_init();
       
 10468 </xsl:text>
       
 10469           <xsl:text>    });
       
 10470 </xsl:text>
       
 10471           <xsl:text>};
       
 10472 </xsl:text>
       
 10473           <xsl:text>
       
 10474 </xsl:text>
       
 10475           <xsl:text>// Open WebSocket to relative "/ws" address
       
 10476 </xsl:text>
       
 10477           <xsl:text>var has_watchdog = window.location.hash == "#watchdog";
       
 10478 </xsl:text>
       
 10479           <xsl:text>
       
 10480 </xsl:text>
       
 10481           <xsl:text>var ws_url = 
       
 10482 </xsl:text>
       
 10483           <xsl:text>    window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws')
       
 10484 </xsl:text>
       
 10485           <xsl:text>    + '?mode=' + (has_watchdog ? "watchdog" : "multiclient");
       
 10486 </xsl:text>
       
 10487           <xsl:text>
       
 10488 </xsl:text>
       
 10489           <xsl:text>var ws = new WebSocket(ws_url);
       
 10490 </xsl:text>
       
 10491           <xsl:text>ws.binaryType = 'arraybuffer';
       
 10492 </xsl:text>
       
 10493           <xsl:text>
       
 10494 </xsl:text>
       
 10495           <xsl:text>const dvgetters = {
       
 10496 </xsl:text>
       
 10497           <xsl:text>    INT: (dv,offset) =&gt; [dv.getInt16(offset, true), 2],
       
 10498 </xsl:text>
       
 10499           <xsl:text>    BOOL: (dv,offset) =&gt; [dv.getInt8(offset, true), 1],
       
 10500 </xsl:text>
       
 10501           <xsl:text>    NODE: (dv,offset) =&gt; [dv.getInt8(offset, true), 1],
       
 10502 </xsl:text>
       
 10503           <xsl:text>    REAL: (dv,offset) =&gt; [dv.getFloat32(offset, true), 4],
       
 10504 </xsl:text>
       
 10505           <xsl:text>    STRING: (dv, offset) =&gt; {
       
 10506 </xsl:text>
       
 10507           <xsl:text>        const size = dv.getInt8(offset);
       
 10508 </xsl:text>
       
 10509           <xsl:text>        return [
       
 10510 </xsl:text>
       
 10511           <xsl:text>            String.fromCharCode.apply(null, new Uint8Array(
       
 10512 </xsl:text>
       
 10513           <xsl:text>                dv.buffer, /* original buffer */
       
 10514 </xsl:text>
       
 10515           <xsl:text>                offset + 1, /* string starts after size*/
       
 10516 </xsl:text>
       
 10517           <xsl:text>                size /* size of string */
       
 10518 </xsl:text>
       
 10519           <xsl:text>            )), size + 1]; /* total increment */
       
 10520 </xsl:text>
       
 10521           <xsl:text>    }
       
 10522 </xsl:text>
       
 10523           <xsl:text>};
       
 10524 </xsl:text>
       
 10525           <xsl:text>
       
 10526 </xsl:text>
       
 10527           <xsl:text>// Apply updates recieved through ws.onmessage to subscribed widgets
       
 10528 </xsl:text>
       
 10529           <xsl:text>function apply_updates() {
       
 10530 </xsl:text>
       
 10531           <xsl:text>    updates.forEach((value, index) =&gt; {
       
 10532 </xsl:text>
       
 10533           <xsl:text>        dispatch_value(index, value);
       
 10534 </xsl:text>
       
 10535           <xsl:text>    });
       
 10536 </xsl:text>
       
 10537           <xsl:text>    updates.clear();
       
 10538 </xsl:text>
       
 10539           <xsl:text>}
       
 10540 </xsl:text>
       
 10541           <xsl:text>
       
 10542 </xsl:text>
       
 10543           <xsl:text>// Called on requestAnimationFrame, modifies DOM
       
 10544 </xsl:text>
       
 10545           <xsl:text>var requestAnimationFrameID = null;
       
 10546 </xsl:text>
       
 10547           <xsl:text>function animate() {
       
 10548 </xsl:text>
       
 10549           <xsl:text>    let rearm = true;
       
 10550 </xsl:text>
       
 10551           <xsl:text>    do{
       
 10552 </xsl:text>
       
 10553           <xsl:text>        if(page_fading == "pending" || page_fading == "forced"){
       
 10554 </xsl:text>
       
 10555           <xsl:text>            if(page_fading == "pending")
       
 10556 </xsl:text>
       
 10557           <xsl:text>                svg_root.classList.add("fade-out-page");
       
 10558 </xsl:text>
       
 10559           <xsl:text>            page_fading = "in_progress";
       
 10560 </xsl:text>
       
 10561           <xsl:text>            if(page_fading_args.length)
       
 10562 </xsl:text>
       
 10563           <xsl:text>                setTimeout(function(){
       
 10564 </xsl:text>
       
 10565           <xsl:text>                    switch_page(...page_fading_args);
       
 10566 </xsl:text>
       
 10567           <xsl:text>                },1);
       
 10568 </xsl:text>
       
 10569           <xsl:text>            break;
       
 10570 </xsl:text>
       
 10571           <xsl:text>        }
       
 10572 </xsl:text>
       
 10573           <xsl:text>
       
 10574 </xsl:text>
       
 10575           <xsl:text>        // Do the page swith if pending
       
 10576 </xsl:text>
       
 10577           <xsl:text>        if(page_switch_in_progress){
       
 10578 </xsl:text>
       
 10579           <xsl:text>            if(current_subscribed_page != current_visible_page){
       
 10580 </xsl:text>
       
 10581           <xsl:text>                switch_visible_page(current_subscribed_page);
       
 10582 </xsl:text>
       
 10583           <xsl:text>            }
       
 10584 </xsl:text>
       
 10585           <xsl:text>
       
 10586 </xsl:text>
       
 10587           <xsl:text>            page_switch_in_progress = false;
       
 10588 </xsl:text>
       
 10589           <xsl:text>
       
 10590 </xsl:text>
       
 10591           <xsl:text>            if(page_fading == "in_progress"){
       
 10592 </xsl:text>
       
 10593           <xsl:text>                svg_root.classList.remove("fade-out-page");
       
 10594 </xsl:text>
       
 10595           <xsl:text>                page_fading = "off";
       
 10596 </xsl:text>
       
 10597           <xsl:text>            }
       
 10598 </xsl:text>
       
 10599           <xsl:text>        }
       
 10600 </xsl:text>
       
 10601           <xsl:text>
       
 10602 </xsl:text>
       
 10603           <xsl:text>        while(widget = need_cache_apply.pop()){
       
 10604 </xsl:text>
       
 10605           <xsl:text>            widget.apply_cache();
       
 10606 </xsl:text>
       
 10607           <xsl:text>        }
       
 10608 </xsl:text>
       
 10609           <xsl:text>
       
 10610 </xsl:text>
       
 10611           <xsl:text>        if(jumps_need_update) update_jumps();
       
 10612 </xsl:text>
       
 10613           <xsl:text>
       
 10614 </xsl:text>
       
 10615           <xsl:text>        apply_updates();
       
 10616 </xsl:text>
       
 10617           <xsl:text>
       
 10618 </xsl:text>
       
 10619           <xsl:text>        pending_widget_animates.forEach(widget =&gt; widget._animate());
       
 10620 </xsl:text>
       
 10621           <xsl:text>        pending_widget_animates = [];
       
 10622 </xsl:text>
       
 10623           <xsl:text>        rearm = false;
       
 10624 </xsl:text>
       
 10625           <xsl:text>    } while(0);
       
 10626 </xsl:text>
       
 10627           <xsl:text>
       
 10628 </xsl:text>
       
 10629           <xsl:text>    requestAnimationFrameID = null;
       
 10630 </xsl:text>
       
 10631           <xsl:text>
       
 10632 </xsl:text>
       
 10633           <xsl:text>    if(rearm) requestHMIAnimation();
       
 10634 </xsl:text>
       
 10635           <xsl:text>}
       
 10636 </xsl:text>
       
 10637           <xsl:text>
       
 10638 </xsl:text>
       
 10639           <xsl:text>function requestHMIAnimation() {
       
 10640 </xsl:text>
       
 10641           <xsl:text>    if(requestAnimationFrameID == null){
       
 10642 </xsl:text>
       
 10643           <xsl:text>        requestAnimationFrameID = window.requestAnimationFrame(animate);
       
 10644 </xsl:text>
       
 10645           <xsl:text>    }
       
 10646 </xsl:text>
       
 10647           <xsl:text>}
       
 10648 </xsl:text>
       
 10649           <xsl:text>
       
 10650 </xsl:text>
       
 10651           <xsl:text>// Message reception handler
       
 10652 </xsl:text>
       
 10653           <xsl:text>// Hash is verified and HMI values updates resulting from binary parsing
       
 10654 </xsl:text>
       
 10655           <xsl:text>// are stored until browser can compute next frame, DOM is left untouched
       
 10656 </xsl:text>
       
 10657           <xsl:text>ws.onmessage = function (evt) {
       
 10658 </xsl:text>
       
 10659           <xsl:text>
       
 10660 </xsl:text>
       
 10661           <xsl:text>    let data = evt.data;
       
 10662 </xsl:text>
       
 10663           <xsl:text>    let dv = new DataView(data);
       
 10664 </xsl:text>
       
 10665           <xsl:text>    let i = 0;
       
 10666 </xsl:text>
       
 10667           <xsl:text>    try {
       
 10668 </xsl:text>
       
 10669           <xsl:text>        for(let hash_int of hmi_hash) {
       
 10670 </xsl:text>
       
 10671           <xsl:text>            if(hash_int != dv.getUint8(i)){
       
 10672 </xsl:text>
       
 10673           <xsl:text>                throw new Error("Hash doesn't match");
       
 10674 </xsl:text>
       
 10675           <xsl:text>            };
       
 10676 </xsl:text>
       
 10677           <xsl:text>            i++;
       
 10678 </xsl:text>
       
 10679           <xsl:text>        };
       
 10680 </xsl:text>
       
 10681           <xsl:text>
       
 10682 </xsl:text>
       
 10683           <xsl:text>        while(i &lt; data.byteLength){
       
 10684 </xsl:text>
       
 10685           <xsl:text>            let index = dv.getUint32(i, true);
       
 10686 </xsl:text>
       
 10687           <xsl:text>            i += 4;
       
 10688 </xsl:text>
       
 10689           <xsl:text>            let iectype = hmitree_types[index];
       
 10690 </xsl:text>
       
 10691           <xsl:text>            if(iectype != undefined){
       
 10692 </xsl:text>
       
 10693           <xsl:text>                let dvgetter = dvgetters[iectype];
       
 10694 </xsl:text>
       
 10695           <xsl:text>                let [value, bytesize] = dvgetter(dv,i);
       
 10696 </xsl:text>
       
 10697           <xsl:text>                updates.set(index, value);
       
 10698 </xsl:text>
       
 10699           <xsl:text>                i += bytesize;
       
 10700 </xsl:text>
       
 10701           <xsl:text>            } else {
       
 10702 </xsl:text>
       
 10703           <xsl:text>                throw new Error("Unknown index "+index);
       
 10704 </xsl:text>
       
 10705           <xsl:text>            }
       
 10706 </xsl:text>
       
 10707           <xsl:text>        };
       
 10708 </xsl:text>
       
 10709           <xsl:text>        // register for rendering on next frame, since there are updates
       
 10710 </xsl:text>
       
 10711           <xsl:text>        requestHMIAnimation();
       
 10712 </xsl:text>
       
 10713           <xsl:text>    } catch(err) {
       
 10714 </xsl:text>
       
 10715           <xsl:text>        // 1003 is for "Unsupported Data"
       
 10716 </xsl:text>
       
 10717           <xsl:text>        // ws.close(1003, err.message);
       
 10718 </xsl:text>
       
 10719           <xsl:text>
       
 10720 </xsl:text>
       
 10721           <xsl:text>        // TODO : remove debug alert ?
       
 10722 </xsl:text>
       
 10723           <xsl:text>        alert("Error : "+err.message+"\nHMI will be reloaded.");
       
 10724 </xsl:text>
       
 10725           <xsl:text>
       
 10726 </xsl:text>
       
 10727           <xsl:text>        // force reload ignoring cache
       
 10728 </xsl:text>
       
 10729           <xsl:text>        location.reload(true);
       
 10730 </xsl:text>
       
 10731           <xsl:text>    }
       
 10732 </xsl:text>
       
 10733           <xsl:text>};
       
 10734 </xsl:text>
       
 10735           <xsl:text>
       
 10736 </xsl:text>
       
 10737           <xsl:text>hmi_hash_u8 = new Uint8Array(hmi_hash);
       
 10738 </xsl:text>
       
 10739           <xsl:text>
       
 10740 </xsl:text>
       
 10741           <xsl:text>function send_blob(data) {
       
 10742 </xsl:text>
       
 10743           <xsl:text>    if(data.length &gt; 0) {
       
 10744 </xsl:text>
       
 10745           <xsl:text>        ws.send(new Blob([hmi_hash_u8].concat(data)));
       
 10746 </xsl:text>
       
 10747           <xsl:text>    };
       
 10748 </xsl:text>
       
 10749           <xsl:text>};
       
 10750 </xsl:text>
       
 10751           <xsl:text>
       
 10752 </xsl:text>
       
 10753           <xsl:text>const typedarray_types = {
       
 10754 </xsl:text>
       
 10755           <xsl:text>    INT: (number) =&gt; new Int16Array([number]),
       
 10756 </xsl:text>
       
 10757           <xsl:text>    BOOL: (truth) =&gt; new Int16Array([truth]),
       
 10758 </xsl:text>
       
 10759           <xsl:text>    NODE: (truth) =&gt; new Int16Array([truth]),
       
 10760 </xsl:text>
       
 10761           <xsl:text>    REAL: (number) =&gt; new Float32Array([number]),
       
 10762 </xsl:text>
       
 10763           <xsl:text>    STRING: (str) =&gt; {
       
 10764 </xsl:text>
       
 10765           <xsl:text>        // beremiz default string max size is 128
       
 10766 </xsl:text>
       
 10767           <xsl:text>        str = str.slice(0,128);
       
 10768 </xsl:text>
       
 10769           <xsl:text>        binary = new Uint8Array(str.length + 1);
       
 10770 </xsl:text>
       
 10771           <xsl:text>        binary[0] = str.length;
       
 10772 </xsl:text>
       
 10773           <xsl:text>        for(let i = 0; i &lt; str.length; i++){
       
 10774 </xsl:text>
       
 10775           <xsl:text>            binary[i+1] = str.charCodeAt(i);
       
 10776 </xsl:text>
       
 10777           <xsl:text>        }
       
 10778 </xsl:text>
       
 10779           <xsl:text>        return binary;
       
 10780 </xsl:text>
       
 10781           <xsl:text>    }
       
 10782 </xsl:text>
       
 10783           <xsl:text>    /* TODO */
       
 10784 </xsl:text>
       
 10785           <xsl:text>};
       
 10786 </xsl:text>
       
 10787           <xsl:text>
       
 10788 </xsl:text>
       
 10789           <xsl:text>function send_reset() {
       
 10790 </xsl:text>
       
 10791           <xsl:text>    send_blob(new Uint8Array([1])); /* reset = 1 */
       
 10792 </xsl:text>
       
 10793           <xsl:text>};
       
 10794 </xsl:text>
       
 10795           <xsl:text>
       
 10796 </xsl:text>
       
 10797           <xsl:text>var subscriptions = [];
       
 10798 </xsl:text>
       
 10799           <xsl:text>
       
 10800 </xsl:text>
       
 10801           <xsl:text>function subscribers(index) {
       
 10802 </xsl:text>
       
 10803           <xsl:text>    let entry = subscriptions[index];
       
 10804 </xsl:text>
       
 10805           <xsl:text>    let res;
       
 10806 </xsl:text>
       
 10807           <xsl:text>    if(entry == undefined){
       
 10808 </xsl:text>
       
 10809           <xsl:text>        res = new Set();
       
 10810 </xsl:text>
       
 10811           <xsl:text>        subscriptions[index] = [res,0];
       
 10812 </xsl:text>
       
 10813           <xsl:text>    }else{
       
 10814 </xsl:text>
       
 10815           <xsl:text>        [res, _ign] = entry;
       
 10816 </xsl:text>
       
 10817           <xsl:text>    }
       
 10818 </xsl:text>
       
 10819           <xsl:text>    return res
       
 10820 </xsl:text>
       
 10821           <xsl:text>}
       
 10822 </xsl:text>
       
 10823           <xsl:text>
       
 10824 </xsl:text>
       
 10825           <xsl:text>function get_subscription_period(index) {
       
 10826 </xsl:text>
       
 10827           <xsl:text>    let entry = subscriptions[index];
       
 10828 </xsl:text>
       
 10829           <xsl:text>    if(entry == undefined)
       
 10830 </xsl:text>
       
 10831           <xsl:text>        return 0;
       
 10832 </xsl:text>
       
 10833           <xsl:text>    let [_ign, period] = entry;
       
 10834 </xsl:text>
       
 10835           <xsl:text>    return period;
       
 10836 </xsl:text>
       
 10837           <xsl:text>}
       
 10838 </xsl:text>
       
 10839           <xsl:text>
       
 10840 </xsl:text>
       
 10841           <xsl:text>function set_subscription_period(index, period) {
       
 10842 </xsl:text>
       
 10843           <xsl:text>    let entry = subscriptions[index];
       
 10844 </xsl:text>
       
 10845           <xsl:text>    if(entry == undefined){
       
 10846 </xsl:text>
       
 10847           <xsl:text>        subscriptions[index] = [new Set(), period];
       
 10848 </xsl:text>
       
 10849           <xsl:text>    } else {
       
 10850 </xsl:text>
       
 10851           <xsl:text>        entry[1] = period;
       
 10852 </xsl:text>
       
 10853           <xsl:text>    }
       
 10854 </xsl:text>
       
 10855           <xsl:text>}
       
 10856 </xsl:text>
       
 10857           <xsl:text>
       
 10858 </xsl:text>
       
 10859           <xsl:text>if(has_watchdog){
       
 10860 </xsl:text>
       
 10861           <xsl:text>    // artificially subscribe the watchdog widget to "/heartbeat" hmi variable
       
 10862 </xsl:text>
       
 10863           <xsl:text>    // Since dispatch directly calls change_hmi_value,
       
 10864 </xsl:text>
       
 10865           <xsl:text>    // PLC will periodically send variable at given frequency
       
 10866 </xsl:text>
       
 10867           <xsl:text>    subscribers(heartbeat_index).add({
       
 10868 </xsl:text>
       
 10869           <xsl:text>        /* type: "Watchdog", */
       
 10870 </xsl:text>
       
 10871           <xsl:text>        frequency: 1,
       
 10872 </xsl:text>
       
 10873           <xsl:text>        indexes: [heartbeat_index],
       
 10874 </xsl:text>
       
 10875           <xsl:text>        new_hmi_value: function(index, value, oldval) {
       
 10876 </xsl:text>
       
 10877           <xsl:text>            apply_hmi_value(heartbeat_index, value+1);
       
 10878 </xsl:text>
       
 10879           <xsl:text>        }
       
 10880 </xsl:text>
       
 10881           <xsl:text>    });
       
 10882 </xsl:text>
       
 10883           <xsl:text>}
       
 10884 </xsl:text>
       
 10885           <xsl:text>
       
 10886 </xsl:text>
       
 10887           <xsl:text>
       
 10888 </xsl:text>
       
 10889           <xsl:text>var page_fading = "off";
       
 10890 </xsl:text>
       
 10891           <xsl:text>var page_fading_args = "off";
       
 10892 </xsl:text>
       
 10893           <xsl:text>function fading_page_switch(...args){
       
 10894 </xsl:text>
       
 10895           <xsl:text>    if(page_fading == "in_progress")
       
 10896 </xsl:text>
       
 10897           <xsl:text>        page_fading = "forced";
       
 10898 </xsl:text>
       
 10899           <xsl:text>    else
       
 10900 </xsl:text>
       
 10901           <xsl:text>        page_fading = "pending";
       
 10902 </xsl:text>
       
 10903           <xsl:text>    page_fading_args = args;
       
 10904 </xsl:text>
       
 10905           <xsl:text>
       
 10906 </xsl:text>
       
 10907           <xsl:text>    requestHMIAnimation();
       
 10908 </xsl:text>
       
 10909           <xsl:text>
       
 10910 </xsl:text>
       
 10911           <xsl:text>}
       
 10912 </xsl:text>
       
 10913           <xsl:text>document.body.style.backgroundColor = "black";
       
 10914 </xsl:text>
       
 10915           <xsl:text>
       
 10916 </xsl:text>
       
 10917           <xsl:text>// subscribe to per instance current page hmi variable
       
 10918 </xsl:text>
       
 10919           <xsl:text>// PLC must prefix page name with "!" for page switch to happen
       
 10920 </xsl:text>
       
 10921           <xsl:text>subscribers(current_page_var_index).add({
       
 10922 </xsl:text>
       
 10923           <xsl:text>    frequency: 1,
       
 10924 </xsl:text>
       
 10925           <xsl:text>    indexes: [current_page_var_index],
       
 10926 </xsl:text>
       
 10927           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
 10928 </xsl:text>
       
 10929           <xsl:text>        if(value.startsWith("!"))
       
 10930 </xsl:text>
       
 10931           <xsl:text>            fading_page_switch(value.slice(1));
       
 10932 </xsl:text>
       
 10933           <xsl:text>    }
       
 10934 </xsl:text>
       
 10935           <xsl:text>});
       
 10936 </xsl:text>
       
 10937           <xsl:text>
       
 10938 </xsl:text>
       
 10939           <xsl:text>function svg_text_to_multiline(elt) {
       
 10940 </xsl:text>
       
 10941           <xsl:text>    return(Array.prototype.map.call(elt.children, x=&gt;x.textContent).join("\n")); 
       
 10942 </xsl:text>
       
 10943           <xsl:text>}
       
 10944 </xsl:text>
       
 10945           <xsl:text>
       
 10946 </xsl:text>
       
 10947           <xsl:text>function multiline_to_svg_text(elt, str, blank) {
       
 10948 </xsl:text>
       
 10949           <xsl:text>    str.split('\n').map((line,i) =&gt; {elt.children[i].textContent = blank?"":line;});
       
 10950 </xsl:text>
       
 10951           <xsl:text>}
       
 10952 </xsl:text>
       
 10953           <xsl:text>
       
 10954 </xsl:text>
       
 10955           <xsl:text>function switch_langnum(langnum) {
       
 10956 </xsl:text>
       
 10957           <xsl:text>    langnum = Math.max(0, Math.min(langs.length - 1, langnum));
       
 10958 </xsl:text>
       
 10959           <xsl:text>
       
 10960 </xsl:text>
       
 10961           <xsl:text>    for (let translation of translations) {
       
 10962 </xsl:text>
       
 10963           <xsl:text>        let [objs, msgs] = translation;
       
 10964 </xsl:text>
       
 10965           <xsl:text>        let msg = msgs[langnum];
       
 10966 </xsl:text>
       
 10967           <xsl:text>        for (let obj of objs) {
       
 10968 </xsl:text>
       
 10969           <xsl:text>            multiline_to_svg_text(obj, msg);
       
 10970 </xsl:text>
       
 10971           <xsl:text>            obj.setAttribute("lang",langnum);
       
 10972 </xsl:text>
       
 10973           <xsl:text>        }
       
 10974 </xsl:text>
       
 10975           <xsl:text>    }
       
 10976 </xsl:text>
       
 10977           <xsl:text>    return langnum;
       
 10978 </xsl:text>
       
 10979           <xsl:text>}
       
 10980 </xsl:text>
       
 10981           <xsl:text>
       
 10982 </xsl:text>
       
 10983           <xsl:text>// backup original texts
       
 10984 </xsl:text>
       
 10985           <xsl:text>for (let translation of translations) {
       
 10986 </xsl:text>
       
 10987           <xsl:text>    let [objs, msgs] = translation;
       
 10988 </xsl:text>
       
 10989           <xsl:text>    msgs.unshift(svg_text_to_multiline(objs[0])); 
       
 10990 </xsl:text>
       
 10991           <xsl:text>}
       
 10992 </xsl:text>
       
 10993           <xsl:text>
       
 10994 </xsl:text>
       
 10995           <xsl:text>var lang_local_index = hmi_local_index("lang");
       
 10996 </xsl:text>
       
 10997           <xsl:text>var langcode_local_index = hmi_local_index("lang_code");
       
 10998 </xsl:text>
       
 10999           <xsl:text>var langname_local_index = hmi_local_index("lang_name");
       
 11000 </xsl:text>
       
 11001           <xsl:text>subscribers(lang_local_index).add({
       
 11002 </xsl:text>
       
 11003           <xsl:text>    indexes: [lang_local_index],
       
 11004 </xsl:text>
       
 11005           <xsl:text>    new_hmi_value: function(index, value, oldval) {
       
 11006 </xsl:text>
       
 11007           <xsl:text>        let current_lang =  switch_langnum(value);
       
 11008 </xsl:text>
       
 11009           <xsl:text>        let [langname,langcode] = langs[current_lang];
       
 11010 </xsl:text>
       
 11011           <xsl:text>        apply_hmi_value(langcode_local_index, langcode);
       
 11012 </xsl:text>
       
 11013           <xsl:text>        apply_hmi_value(langname_local_index, langname);
       
 11014 </xsl:text>
       
 11015           <xsl:text>        switch_page();
       
 11016 </xsl:text>
       
 11017           <xsl:text>    }
       
 11018 </xsl:text>
       
 11019           <xsl:text>});
       
 11020 </xsl:text>
       
 11021           <xsl:text>
       
 11022 </xsl:text>
       
 11023           <xsl:text>// returns en_US, fr_FR or en_UK depending on selected language
       
 11024 </xsl:text>
       
 11025           <xsl:text>function get_current_lang_code(){
       
 11026 </xsl:text>
       
 11027           <xsl:text>    return cache[langcode_local_index];
       
 11028 </xsl:text>
       
 11029           <xsl:text>}
       
 11030 </xsl:text>
       
 11031           <xsl:text>
       
 11032 </xsl:text>
       
 11033           <xsl:text>function setup_lang(){
       
 11034 </xsl:text>
       
 11035           <xsl:text>    let current_lang = cache[lang_local_index];
       
 11036 </xsl:text>
       
 11037           <xsl:text>    let new_lang = switch_langnum(current_lang);
       
 11038 </xsl:text>
       
 11039           <xsl:text>    if(current_lang != new_lang){
       
 11040 </xsl:text>
       
 11041           <xsl:text>        apply_hmi_value(lang_local_index, new_lang);
       
 11042 </xsl:text>
       
 11043           <xsl:text>    }
       
 11044 </xsl:text>
       
 11045           <xsl:text>}
       
 11046 </xsl:text>
       
 11047           <xsl:text>
       
 11048 </xsl:text>
       
 11049           <xsl:text>setup_lang();
       
 11050 </xsl:text>
       
 11051           <xsl:text>
       
 11052 </xsl:text>
       
 11053           <xsl:text>function update_subscriptions() {
       
 11054 </xsl:text>
       
 11055           <xsl:text>    let delta = [];
       
 11056 </xsl:text>
       
 11057           <xsl:text>    for(let index in subscriptions){
       
 11058 </xsl:text>
       
 11059           <xsl:text>        let widgets = subscribers(index);
       
 11060 </xsl:text>
       
 11061           <xsl:text>
       
 11062 </xsl:text>
       
 11063           <xsl:text>        // periods are in ms
       
 11064 </xsl:text>
       
 11065           <xsl:text>        let previous_period = get_subscription_period(index);
       
 11066 </xsl:text>
       
 11067           <xsl:text>
       
 11068 </xsl:text>
       
 11069           <xsl:text>        // subscribing with a zero period is unsubscribing
       
 11070 </xsl:text>
       
 11071           <xsl:text>        let new_period = 0;
       
 11072 </xsl:text>
       
 11073           <xsl:text>        if(widgets.size &gt; 0) {
       
 11074 </xsl:text>
       
 11075           <xsl:text>            let maxfreq = 0;
       
 11076 </xsl:text>
       
 11077           <xsl:text>            for(let widget of widgets){
       
 11078 </xsl:text>
       
 11079           <xsl:text>                let wf = widget.frequency;
       
 11080 </xsl:text>
       
 11081           <xsl:text>                if(wf != undefined &amp;&amp; maxfreq &lt; wf)
       
 11082 </xsl:text>
       
 11083           <xsl:text>                    maxfreq = wf;
       
 11084 </xsl:text>
       
 11085           <xsl:text>            }
       
 11086 </xsl:text>
       
 11087           <xsl:text>
       
 11088 </xsl:text>
       
 11089           <xsl:text>            if(maxfreq != 0)
       
 11090 </xsl:text>
       
 11091           <xsl:text>                new_period = 1000/maxfreq;
       
 11092 </xsl:text>
       
 11093           <xsl:text>        }
       
 11094 </xsl:text>
       
 11095           <xsl:text>
       
 11096 </xsl:text>
       
 11097           <xsl:text>        if(previous_period != new_period) {
       
 11098 </xsl:text>
       
 11099           <xsl:text>            set_subscription_period(index, new_period);
       
 11100 </xsl:text>
       
 11101           <xsl:text>            if(index &lt;= last_remote_index){
       
 11102 </xsl:text>
       
 11103           <xsl:text>                delta.push(
       
 11104 </xsl:text>
       
 11105           <xsl:text>                    new Uint8Array([2]), /* subscribe = 2 */
       
 11106 </xsl:text>
       
 11107           <xsl:text>                    new Uint32Array([index]),
       
 11108 </xsl:text>
       
 11109           <xsl:text>                    new Uint16Array([new_period]));
       
 11110 </xsl:text>
       
 11111           <xsl:text>            }
       
 11112 </xsl:text>
       
 11113           <xsl:text>        }
       
 11114 </xsl:text>
       
 11115           <xsl:text>    }
       
 11116 </xsl:text>
       
 11117           <xsl:text>    send_blob(delta);
       
 11118 </xsl:text>
       
 11119           <xsl:text>};
       
 11120 </xsl:text>
       
 11121           <xsl:text>
       
 11122 </xsl:text>
       
 11123           <xsl:text>function send_hmi_value(index, value) {
       
 11124 </xsl:text>
       
 11125           <xsl:text>    if(index &gt; last_remote_index){
       
 11126 </xsl:text>
       
 11127           <xsl:text>        updates.set(index, value);
       
 11128 </xsl:text>
       
 11129           <xsl:text>
       
 11130 </xsl:text>
       
 11131           <xsl:text>        if(persistent_indexes.has(index)){
       
 11132 </xsl:text>
       
 11133           <xsl:text>            let varname = persistent_indexes.get(index);
       
 11134 </xsl:text>
       
 11135           <xsl:text>            document.cookie = varname+"="+value+"; max-age=3153600000";
       
 11136 </xsl:text>
       
 11137           <xsl:text>        }
       
 11138 </xsl:text>
       
 11139           <xsl:text>
       
 11140 </xsl:text>
       
 11141           <xsl:text>        requestHMIAnimation();
       
 11142 </xsl:text>
 11699 </xsl:text>
 11143           <xsl:text>        return;
 11700           <xsl:text>        return;
 11144 </xsl:text>
 11701 </xsl:text>
 11145           <xsl:text>    }
 11702           <xsl:text>    }
 11146 </xsl:text>
 11703 </xsl:text>