1678 </xsl:text> |
1765 </xsl:text> |
1679 <xsl:text> } |
1766 <xsl:text> } |
1680 </xsl:text> |
1767 </xsl:text> |
1681 <xsl:text> } |
1768 <xsl:text> } |
1682 </xsl:text> |
1769 </xsl:text> |
|
1770 <xsl:text> |
|
1771 </xsl:text> |
|
1772 <xsl:text> if(this.enable_expr){ |
|
1773 </xsl:text> |
|
1774 <xsl:text> this.enable_state = false; |
|
1775 </xsl:text> |
|
1776 <xsl:text> this.enable_displayed_state = false; |
|
1777 </xsl:text> |
|
1778 <xsl:text> for(let child of Array.from(this.element.children)){ |
|
1779 </xsl:text> |
|
1780 <xsl:text> let label = child.getAttribute("inkscape:label"); |
|
1781 </xsl:text> |
|
1782 <xsl:text> if(label!="disabled"){ |
|
1783 </xsl:text> |
|
1784 <xsl:text> this.enabled_elts.push(child); |
|
1785 </xsl:text> |
|
1786 <xsl:text> this.element.removeChild(child); |
|
1787 </xsl:text> |
|
1788 <xsl:text> } |
|
1789 </xsl:text> |
|
1790 <xsl:text> } |
|
1791 </xsl:text> |
|
1792 <xsl:text> } |
|
1793 </xsl:text> |
1683 <xsl:text> } |
1794 <xsl:text> } |
1684 </xsl:text> |
1795 </xsl:text> |
1685 <xsl:text> |
1796 <xsl:text> |
1686 </xsl:text> |
1797 </xsl:text> |
1687 <xsl:text> unsub(){ |
1798 <xsl:text> unsub(){ |
1688 </xsl:text> |
1799 </xsl:text> |
1689 <xsl:text> /* remove subsribers */ |
1800 <xsl:text> /* remove subsribers */ |
1690 </xsl:text> |
1801 </xsl:text> |
1691 <xsl:text> if(!this.unsubscribable) |
1802 <xsl:text> for(let i = 0; i < this.indexes_length; i++) { |
1692 </xsl:text> |
1803 </xsl:text> |
1693 <xsl:text> for(let i = 0; i < this.indexes.length; i++) { |
1804 <xsl:text> /* flush updates pending because of inhibition */ |
1694 </xsl:text> |
1805 </xsl:text> |
1695 <xsl:text> /* flush updates pending because of inhibition */ |
1806 <xsl:text> let inhibition = this.inhibit[i]; |
1696 </xsl:text> |
1807 </xsl:text> |
1697 <xsl:text> let inhibition = this.inhibit[i]; |
1808 <xsl:text> if(inhibition != undefined){ |
1698 </xsl:text> |
1809 </xsl:text> |
1699 <xsl:text> if(inhibition != undefined){ |
1810 <xsl:text> clearTimeout(inhibition); |
1700 </xsl:text> |
1811 </xsl:text> |
1701 <xsl:text> clearTimeout(inhibition); |
1812 <xsl:text> this.lastapply[i] = undefined; |
1702 </xsl:text> |
1813 </xsl:text> |
1703 <xsl:text> this.lastapply[i] = undefined; |
1814 <xsl:text> this.uninhibit(i); |
1704 </xsl:text> |
1815 </xsl:text> |
1705 <xsl:text> this.uninhibit(i); |
1816 <xsl:text> } |
|
1817 </xsl:text> |
|
1818 <xsl:text> let deafened = this.deafen[i]; |
|
1819 </xsl:text> |
|
1820 <xsl:text> if(deafened != undefined){ |
|
1821 </xsl:text> |
|
1822 <xsl:text> clearTimeout(deafened); |
|
1823 </xsl:text> |
|
1824 <xsl:text> this.lastdispatch[i] = undefined; |
|
1825 </xsl:text> |
|
1826 <xsl:text> this.undeafen(i); |
|
1827 </xsl:text> |
|
1828 <xsl:text> } |
|
1829 </xsl:text> |
|
1830 <xsl:text> let index = this.get_variable_index(i); |
|
1831 </xsl:text> |
|
1832 <xsl:text> subscribers(index).delete(this); |
|
1833 </xsl:text> |
|
1834 <xsl:text> } |
|
1835 </xsl:text> |
|
1836 <xsl:text> this.offset = 0; |
|
1837 </xsl:text> |
|
1838 <xsl:text> this.relativeness = undefined; |
|
1839 </xsl:text> |
|
1840 <xsl:text> } |
|
1841 </xsl:text> |
|
1842 <xsl:text> |
|
1843 </xsl:text> |
|
1844 <xsl:text> sub(new_offset=0, relativeness, container_id){ |
|
1845 </xsl:text> |
|
1846 <xsl:text> this.offset = new_offset; |
|
1847 </xsl:text> |
|
1848 <xsl:text> this.relativeness = relativeness; |
|
1849 </xsl:text> |
|
1850 <xsl:text> this.container_id = container_id ; |
|
1851 </xsl:text> |
|
1852 <xsl:text> /* add this's subsribers */ |
|
1853 </xsl:text> |
|
1854 <xsl:text> for(let i = 0; i < 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 < 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 && typeof new_val == "number") { |
|
1933 </xsl:text> |
|
1934 <xsl:text> let [min,max] = minmax; |
|
1935 </xsl:text> |
|
1936 <xsl:text> if(new_val < 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 > 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 > 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 < 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 && !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 && 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 && 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 > lastdispatch + min_interval){ |
|
2183 </xsl:text> |
|
2184 <xsl:text> this.lastdispatch[varnum] = now; |
|
2185 </xsl:text> |
|
2186 <xsl:text> this.do_dispatch(value, oldval, varnum) |
1706 </xsl:text> |
2187 </xsl:text> |
1707 <xsl:text> } |
2188 <xsl:text> } |
1708 </xsl:text> |
2189 </xsl:text> |
1709 <xsl:text> let deafened = this.deafen[i]; |
2190 <xsl:text> else { |
1710 </xsl:text> |
2191 </xsl:text> |
1711 <xsl:text> if(deafened != undefined){ |
2192 <xsl:text> let elapsed = now - lastdispatch; |
1712 </xsl:text> |
2193 </xsl:text> |
1713 <xsl:text> clearTimeout(deafened); |
2194 <xsl:text> this.incoming[varnum] = [value, oldval]; |
1714 </xsl:text> |
2195 </xsl:text> |
1715 <xsl:text> this.lastdispatch[i] = undefined; |
2196 <xsl:text> this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum); |
1716 </xsl:text> |
|
1717 <xsl:text> this.undeafen(i); |
|
1718 </xsl:text> |
2197 </xsl:text> |
1719 <xsl:text> } |
2198 <xsl:text> } |
1720 </xsl:text> |
2199 </xsl:text> |
1721 <xsl:text> let index = this.indexes[i]; |
|
1722 </xsl:text> |
|
1723 <xsl:text> if(this.relativeness[i]) |
|
1724 </xsl:text> |
|
1725 <xsl:text> index += this.offset; |
|
1726 </xsl:text> |
|
1727 <xsl:text> subscribers(index).delete(this); |
|
1728 </xsl:text> |
|
1729 <xsl:text> } |
2200 <xsl:text> } |
1730 </xsl:text> |
2201 </xsl:text> |
1731 <xsl:text> this.offset = 0; |
2202 <xsl:text> else { |
1732 </xsl:text> |
2203 </xsl:text> |
1733 <xsl:text> this.relativeness = undefined; |
2204 <xsl:text> this.incoming[varnum] = [value, oldval]; |
1734 </xsl:text> |
|
1735 <xsl:text> } |
|
1736 </xsl:text> |
|
1737 <xsl:text> |
|
1738 </xsl:text> |
|
1739 <xsl:text> sub(new_offset=0, relativeness, container_id){ |
|
1740 </xsl:text> |
|
1741 <xsl:text> this.offset = new_offset; |
|
1742 </xsl:text> |
|
1743 <xsl:text> this.relativeness = relativeness; |
|
1744 </xsl:text> |
|
1745 <xsl:text> this.container_id = container_id ; |
|
1746 </xsl:text> |
|
1747 <xsl:text> /* add this's subsribers */ |
|
1748 </xsl:text> |
|
1749 <xsl:text> if(!this.unsubscribable) |
|
1750 </xsl:text> |
|
1751 <xsl:text> for(let i = 0; i < this.indexes.length; i++) { |
|
1752 </xsl:text> |
|
1753 <xsl:text> let index = this.get_variable_index(i); |
|
1754 </xsl:text> |
|
1755 <xsl:text> if(index == undefined) continue; |
|
1756 </xsl:text> |
|
1757 <xsl:text> subscribers(index).add(this); |
|
1758 </xsl:text> |
2205 </xsl:text> |
1759 <xsl:text> } |
2206 <xsl:text> } |
1760 </xsl:text> |
2207 </xsl:text> |
1761 <xsl:text> need_cache_apply.push(this); |
|
1762 </xsl:text> |
|
1763 <xsl:text> } |
|
1764 </xsl:text> |
|
1765 <xsl:text> |
|
1766 </xsl:text> |
|
1767 <xsl:text> apply_cache() { |
|
1768 </xsl:text> |
|
1769 <xsl:text> if(!this.unsubscribable) for(let index in this.indexes){ |
|
1770 </xsl:text> |
|
1771 <xsl:text> /* dispatch current cache in newly opened page widgets */ |
|
1772 </xsl:text> |
|
1773 <xsl:text> let realindex = this.get_variable_index(index); |
|
1774 </xsl:text> |
|
1775 <xsl:text> if(realindex == undefined) continue; |
|
1776 </xsl:text> |
|
1777 <xsl:text> let cached_val = cache[realindex]; |
|
1778 </xsl:text> |
|
1779 <xsl:text> if(cached_val != undefined) |
|
1780 </xsl:text> |
|
1781 <xsl:text> this._dispatch(cached_val, cached_val, index); |
|
1782 </xsl:text> |
|
1783 <xsl:text> } |
2208 <xsl:text> } |
1784 </xsl:text> |
2209 </xsl:text> |
1785 <xsl:text> } |
2210 <xsl:text> } |
1786 </xsl:text> |
2211 </xsl:text> |
1787 <xsl:text> |
2212 <xsl:text> |
1788 </xsl:text> |
2213 </xsl:text> |
1789 <xsl:text> get_variable_index(varnum) { |
2214 <xsl:text> do_dispatch(value, oldval, varnum) { |
1790 </xsl:text> |
2215 </xsl:text> |
1791 <xsl:text> let index = this.indexes[varnum]; |
2216 <xsl:text> if(this.dispatch) try { |
1792 </xsl:text> |
2217 </xsl:text> |
1793 <xsl:text> if(typeof(index) == "string"){ |
2218 <xsl:text> this.dispatch(value, oldval, varnum); |
1794 </xsl:text> |
2219 </xsl:text> |
1795 <xsl:text> index = page_local_index(index, this.container_id); |
2220 <xsl:text> } catch(err) { |
1796 </xsl:text> |
2221 </xsl:text> |
1797 <xsl:text> } else { |
2222 <xsl:text> console.log(err); |
1798 </xsl:text> |
|
1799 <xsl:text> if(this.relativeness[varnum]){ |
|
1800 </xsl:text> |
|
1801 <xsl:text> index += this.offset; |
|
1802 </xsl:text> |
|
1803 <xsl:text> } |
|
1804 </xsl:text> |
2223 </xsl:text> |
1805 <xsl:text> } |
2224 <xsl:text> } |
1806 </xsl:text> |
2225 </xsl:text> |
1807 <xsl:text> return index; |
2226 <xsl:text> if(this.enable_expr) try { |
1808 </xsl:text> |
2227 </xsl:text> |
1809 <xsl:text> } |
2228 <xsl:text> this.compute_enable(value, oldval, varnum); |
1810 </xsl:text> |
2229 </xsl:text> |
1811 <xsl:text> |
2230 <xsl:text> } catch(err) { |
1812 </xsl:text> |
2231 </xsl:text> |
1813 <xsl:text> overshot(new_val, max) { |
2232 <xsl:text> console.log(err); |
1814 </xsl:text> |
|
1815 <xsl:text> } |
|
1816 </xsl:text> |
|
1817 <xsl:text> |
|
1818 </xsl:text> |
|
1819 <xsl:text> undershot(new_val, min) { |
|
1820 </xsl:text> |
|
1821 <xsl:text> } |
|
1822 </xsl:text> |
|
1823 <xsl:text> |
|
1824 </xsl:text> |
|
1825 <xsl:text> clip_min_max(index, new_val) { |
|
1826 </xsl:text> |
|
1827 <xsl:text> let minmax = this.minmaxes[index]; |
|
1828 </xsl:text> |
|
1829 <xsl:text> if(minmax !== undefined && typeof new_val == "number") { |
|
1830 </xsl:text> |
|
1831 <xsl:text> let [min,max] = minmax; |
|
1832 </xsl:text> |
|
1833 <xsl:text> if(new_val < min){ |
|
1834 </xsl:text> |
|
1835 <xsl:text> this.undershot(new_val, min); |
|
1836 </xsl:text> |
|
1837 <xsl:text> return min; |
|
1838 </xsl:text> |
|
1839 <xsl:text> } |
|
1840 </xsl:text> |
|
1841 <xsl:text> if(new_val > max){ |
|
1842 </xsl:text> |
|
1843 <xsl:text> this.overshot(new_val, max); |
|
1844 </xsl:text> |
|
1845 <xsl:text> return max; |
|
1846 </xsl:text> |
|
1847 <xsl:text> } |
|
1848 </xsl:text> |
2233 </xsl:text> |
1849 <xsl:text> } |
2234 <xsl:text> } |
1850 </xsl:text> |
2235 </xsl:text> |
1851 <xsl:text> return new_val; |
2236 <xsl:text> } |
1852 </xsl:text> |
2237 </xsl:text> |
1853 <xsl:text> } |
2238 <xsl:text> |
1854 </xsl:text> |
2239 </xsl:text> |
1855 <xsl:text> |
2240 <xsl:text> _animate(){ |
1856 </xsl:text> |
2241 </xsl:text> |
1857 <xsl:text> change_hmi_value(index, opstr) { |
2242 <xsl:text> if(this.enable_expr) |
1858 </xsl:text> |
2243 </xsl:text> |
1859 <xsl:text> let realindex = this.get_variable_index(index); |
2244 <xsl:text> this.animate_enable(); |
1860 </xsl:text> |
2245 </xsl:text> |
1861 <xsl:text> if(realindex == undefined) return undefined; |
2246 <xsl:text> // inhibit widget animation when disabled |
1862 </xsl:text> |
2247 </xsl:text> |
1863 <xsl:text> let old_val = cache[realindex]; |
2248 <xsl:text> if(!this.enable_expr || this.enable_state){ |
1864 </xsl:text> |
2249 </xsl:text> |
1865 <xsl:text> let new_val = eval_operation_string(old_val, opstr); |
2250 <xsl:text> if(this.has_activity) |
1866 </xsl:text> |
2251 </xsl:text> |
1867 <xsl:text> if(this.clip) |
2252 <xsl:text> this.animate_activity(); |
1868 </xsl:text> |
2253 </xsl:text> |
1869 <xsl:text> new_val = this.clip_min_max(index, new_val); |
2254 <xsl:text> if(this.animate != undefined) |
1870 </xsl:text> |
2255 </xsl:text> |
1871 <xsl:text> return apply_hmi_value(realindex, new_val); |
2256 <xsl:text> this.animate(); |
1872 </xsl:text> |
|
1873 <xsl:text> } |
|
1874 </xsl:text> |
|
1875 <xsl:text> |
|
1876 </xsl:text> |
|
1877 <xsl:text> _apply_hmi_value(index, new_val) { |
|
1878 </xsl:text> |
|
1879 <xsl:text> let realindex = this.get_variable_index(index); |
|
1880 </xsl:text> |
|
1881 <xsl:text> if(realindex == undefined) return undefined; |
|
1882 </xsl:text> |
|
1883 <xsl:text> if(this.clip) |
|
1884 </xsl:text> |
|
1885 <xsl:text> new_val = this.clip_min_max(index, new_val); |
|
1886 </xsl:text> |
|
1887 <xsl:text> return apply_hmi_value(realindex, new_val); |
|
1888 </xsl:text> |
|
1889 <xsl:text> } |
|
1890 </xsl:text> |
|
1891 <xsl:text> |
|
1892 </xsl:text> |
|
1893 <xsl:text> uninhibit(index){ |
|
1894 </xsl:text> |
|
1895 <xsl:text> this.inhibit[index] = undefined; |
|
1896 </xsl:text> |
|
1897 <xsl:text> let new_val = this.pending[index]; |
|
1898 </xsl:text> |
|
1899 <xsl:text> this.pending[index] = undefined; |
|
1900 </xsl:text> |
|
1901 <xsl:text> return this.apply_hmi_value(index, new_val); |
|
1902 </xsl:text> |
|
1903 <xsl:text> } |
|
1904 </xsl:text> |
|
1905 <xsl:text> |
|
1906 </xsl:text> |
|
1907 <xsl:text> apply_hmi_value(index, new_val) { |
|
1908 </xsl:text> |
|
1909 <xsl:text> if(this.inhibit[index] == undefined){ |
|
1910 </xsl:text> |
|
1911 <xsl:text> let now = Date.now(); |
|
1912 </xsl:text> |
|
1913 <xsl:text> let min_interval = 1000/this.frequency; |
|
1914 </xsl:text> |
|
1915 <xsl:text> let lastapply = this.lastapply[index]; |
|
1916 </xsl:text> |
|
1917 <xsl:text> if(lastapply == undefined || now > lastapply + min_interval){ |
|
1918 </xsl:text> |
|
1919 <xsl:text> this.lastapply[index] = now; |
|
1920 </xsl:text> |
|
1921 <xsl:text> return this._apply_hmi_value(index, new_val); |
|
1922 </xsl:text> |
|
1923 <xsl:text> } |
|
1924 </xsl:text> |
|
1925 <xsl:text> else { |
|
1926 </xsl:text> |
|
1927 <xsl:text> let elapsed = now - lastapply; |
|
1928 </xsl:text> |
|
1929 <xsl:text> this.pending[index] = new_val; |
|
1930 </xsl:text> |
|
1931 <xsl:text> this.inhibit[index] = setTimeout(this.bound_uninhibit, min_interval - elapsed, index); |
|
1932 </xsl:text> |
|
1933 <xsl:text> } |
|
1934 </xsl:text> |
2257 </xsl:text> |
1935 <xsl:text> } |
2258 <xsl:text> } |
1936 </xsl:text> |
2259 </xsl:text> |
1937 <xsl:text> else { |
2260 <xsl:text> this.pending_animate = false; |
1938 </xsl:text> |
2261 </xsl:text> |
1939 <xsl:text> this.pending[index] = new_val; |
2262 <xsl:text> } |
1940 </xsl:text> |
2263 </xsl:text> |
1941 <xsl:text> return new_val; |
2264 <xsl:text> |
|
2265 </xsl:text> |
|
2266 <xsl:text> request_animate(){ |
|
2267 </xsl:text> |
|
2268 <xsl:text> if(!this.pending_animate){ |
|
2269 </xsl:text> |
|
2270 <xsl:text> pending_widget_animates.push(this); |
|
2271 </xsl:text> |
|
2272 <xsl:text> this.pending_animate = true; |
|
2273 </xsl:text> |
|
2274 <xsl:text> requestHMIAnimation(); |
1942 </xsl:text> |
2275 </xsl:text> |
1943 <xsl:text> } |
2276 <xsl:text> } |
1944 </xsl:text> |
2277 </xsl:text> |
1945 <xsl:text> } |
2278 <xsl:text> } |
1946 </xsl:text> |
2279 </xsl:text> |
1947 <xsl:text> |
2280 <xsl:text> |
1948 </xsl:text> |
2281 </xsl:text> |
1949 <xsl:text> new_hmi_value(index, value, oldval) { |
2282 <xsl:text> animate_activity(){ |
1950 </xsl:text> |
2283 </xsl:text> |
1951 <xsl:text> // TODO avoid searching, store index at sub() |
2284 <xsl:text> if(this.activity_displayed_state != this.activity_state){ |
1952 </xsl:text> |
2285 </xsl:text> |
1953 <xsl:text> for(let i = 0; i < this.indexes.length; i++) { |
2286 <xsl:text> set_activity_state(this.activable_sub, this.activity_state); |
1954 </xsl:text> |
2287 </xsl:text> |
1955 <xsl:text> let refindex = this.get_variable_index(i); |
2288 <xsl:text> this.activity_displayed_state = this.activity_state; |
1956 </xsl:text> |
|
1957 <xsl:text> if(refindex == undefined) continue; |
|
1958 </xsl:text> |
|
1959 <xsl:text> |
|
1960 </xsl:text> |
|
1961 <xsl:text> if(index == refindex) { |
|
1962 </xsl:text> |
|
1963 <xsl:text> this._dispatch(value, oldval, i); |
|
1964 </xsl:text> |
|
1965 <xsl:text> break; |
|
1966 </xsl:text> |
|
1967 <xsl:text> } |
|
1968 </xsl:text> |
2289 </xsl:text> |
1969 <xsl:text> } |
2290 <xsl:text> } |
1970 </xsl:text> |
|
1971 <xsl:text> } |
|
1972 </xsl:text> |
|
1973 <xsl:text> |
|
1974 </xsl:text> |
|
1975 <xsl:text> undeafen(index){ |
|
1976 </xsl:text> |
|
1977 <xsl:text> this.deafen[index] = undefined; |
|
1978 </xsl:text> |
|
1979 <xsl:text> let [new_val, old_val] = this.incoming[index]; |
|
1980 </xsl:text> |
|
1981 <xsl:text> this.incoming[index] = undefined; |
|
1982 </xsl:text> |
|
1983 <xsl:text> this.dispatch(new_val, old_val, index); |
|
1984 </xsl:text> |
|
1985 <xsl:text> } |
|
1986 </xsl:text> |
|
1987 <xsl:text> |
|
1988 </xsl:text> |
|
1989 <xsl:text> _dispatch(value, oldval, varnum) { |
|
1990 </xsl:text> |
|
1991 <xsl:text> let dispatch = this.dispatch; |
|
1992 </xsl:text> |
|
1993 <xsl:text> if(dispatch != undefined){ |
|
1994 </xsl:text> |
|
1995 <xsl:text> if(this.deafen[varnum] == undefined){ |
|
1996 </xsl:text> |
|
1997 <xsl:text> let now = Date.now(); |
|
1998 </xsl:text> |
|
1999 <xsl:text> let min_interval = 1000/this.frequency; |
|
2000 </xsl:text> |
|
2001 <xsl:text> let lastdispatch = this.lastdispatch[varnum]; |
|
2002 </xsl:text> |
|
2003 <xsl:text> if(lastdispatch == undefined || now > lastdispatch + min_interval){ |
|
2004 </xsl:text> |
|
2005 <xsl:text> this.lastdispatch[varnum] = now; |
|
2006 </xsl:text> |
|
2007 <xsl:text> try { |
|
2008 </xsl:text> |
|
2009 <xsl:text> dispatch.call(this, value, oldval, varnum); |
|
2010 </xsl:text> |
|
2011 <xsl:text> } catch(err) { |
|
2012 </xsl:text> |
|
2013 <xsl:text> console.log(err); |
|
2014 </xsl:text> |
|
2015 <xsl:text> } |
|
2016 </xsl:text> |
|
2017 <xsl:text> } |
|
2018 </xsl:text> |
|
2019 <xsl:text> else { |
|
2020 </xsl:text> |
|
2021 <xsl:text> let elapsed = now - lastdispatch; |
|
2022 </xsl:text> |
|
2023 <xsl:text> this.incoming[varnum] = [value, oldval]; |
|
2024 </xsl:text> |
|
2025 <xsl:text> this.deafen[varnum] = setTimeout(this.bound_undeafen, min_interval - elapsed, varnum); |
|
2026 </xsl:text> |
|
2027 <xsl:text> } |
|
2028 </xsl:text> |
|
2029 <xsl:text> } |
|
2030 </xsl:text> |
|
2031 <xsl:text> else { |
|
2032 </xsl:text> |
|
2033 <xsl:text> this.incoming[varnum] = [value, oldval]; |
|
2034 </xsl:text> |
|
2035 <xsl:text> } |
|
2036 </xsl:text> |
|
2037 <xsl:text> } |
|
2038 </xsl:text> |
|
2039 <xsl:text> } |
|
2040 </xsl:text> |
|
2041 <xsl:text> |
|
2042 </xsl:text> |
|
2043 <xsl:text> _animate(){ |
|
2044 </xsl:text> |
|
2045 <xsl:text> this.animate(); |
|
2046 </xsl:text> |
|
2047 <xsl:text> this.pending_animate = false; |
|
2048 </xsl:text> |
|
2049 <xsl:text> } |
|
2050 </xsl:text> |
|
2051 <xsl:text> |
|
2052 </xsl:text> |
|
2053 <xsl:text> request_animate(){ |
|
2054 </xsl:text> |
|
2055 <xsl:text> if(!this.pending_animate){ |
|
2056 </xsl:text> |
|
2057 <xsl:text> pending_widget_animates.push(this); |
|
2058 </xsl:text> |
|
2059 <xsl:text> this.pending_animate = true; |
|
2060 </xsl:text> |
|
2061 <xsl:text> requestHMIAnimation(); |
|
2062 </xsl:text> |
|
2063 <xsl:text> } |
|
2064 </xsl:text> |
|
2065 <xsl:text> } |
|
2066 </xsl:text> |
|
2067 <xsl:text> |
|
2068 </xsl:text> |
|
2069 <xsl:text> set_activation_state(state){ |
|
2070 </xsl:text> |
|
2071 <xsl:text> set_activation_state(this.activable_sub, state); |
|
2072 </xsl:text> |
2291 </xsl:text> |
2073 <xsl:text> } |
2292 <xsl:text> } |
2074 </xsl:text> |
2293 </xsl:text> |
2075 <xsl:text>} |
2294 <xsl:text>} |
2076 </xsl:text> |
2295 </xsl:text> |
5528 <xsl:text>JumpWidget</xsl:text> |
5919 <xsl:text>JumpWidget</xsl:text> |
5529 <xsl:text> extends Widget{ |
5920 <xsl:text> extends Widget{ |
5530 </xsl:text> |
5921 </xsl:text> |
5531 <xsl:text> activable = false; |
5922 <xsl:text> activable = false; |
5532 </xsl:text> |
5923 </xsl:text> |
5533 <xsl:text> active = false; |
|
5534 </xsl:text> |
|
5535 <xsl:text> disabled = false; |
|
5536 </xsl:text> |
|
5537 <xsl:text> frequency = 2; |
5924 <xsl:text> frequency = 2; |
5538 </xsl:text> |
5925 </xsl:text> |
5539 <xsl:text> |
5926 <xsl:text> |
5540 </xsl:text> |
5927 </xsl:text> |
5541 <xsl:text> update_activity() { |
5928 <xsl:text> make_on_click() { |
5542 </xsl:text> |
5929 </xsl:text> |
5543 <xsl:text> if(this.active) { |
5930 <xsl:text> let that = this; |
5544 </xsl:text> |
5931 </xsl:text> |
5545 <xsl:text> /* show active */ |
5932 <xsl:text> const name = this.args[0]; |
5546 </xsl:text> |
5933 </xsl:text> |
5547 <xsl:text> this.active_elt.style.display = ""; |
5934 <xsl:text> return function(evt){ |
5548 </xsl:text> |
5935 </xsl:text> |
5549 <xsl:text> /* hide inactive */ |
5936 <xsl:text> /* TODO: in order to allow jumps to page selected through |
5550 </xsl:text> |
5937 </xsl:text> |
5551 <xsl:text> this.inactive_elt.style.display = "none"; |
5938 <xsl:text> for exemple a dropdown, support path pointing to local |
5552 </xsl:text> |
5939 </xsl:text> |
5553 <xsl:text> } else { |
5940 <xsl:text> variable whom value would be an HMI_TREE index and then |
5554 </xsl:text> |
5941 </xsl:text> |
5555 <xsl:text> /* show inactive */ |
5942 <xsl:text> jump to a relative page not hard-coded in advance |
5556 </xsl:text> |
5943 </xsl:text> |
5557 <xsl:text> this.inactive_elt.style.display = ""; |
5944 <xsl:text> */ |
5558 </xsl:text> |
5945 </xsl:text> |
5559 <xsl:text> /* hide active */ |
5946 <xsl:text> if(that.enable_state) { |
5560 </xsl:text> |
5947 </xsl:text> |
5561 <xsl:text> this.active_elt.style.display = "none"; |
5948 <xsl:text> const index = |
|
5949 </xsl:text> |
|
5950 <xsl:text> (that.is_relative && that.indexes.length > 0) ? |
|
5951 </xsl:text> |
|
5952 <xsl:text> that.indexes[0] + that.offset : undefined; |
|
5953 </xsl:text> |
|
5954 <xsl:text> fading_page_switch(name, index); |
|
5955 </xsl:text> |
|
5956 <xsl:text> that.notify(); |
|
5957 </xsl:text> |
|
5958 <xsl:text> } |
5562 </xsl:text> |
5959 </xsl:text> |
5563 <xsl:text> } |
5960 <xsl:text> } |
5564 </xsl:text> |
5961 </xsl:text> |
5565 <xsl:text> } |
5962 <xsl:text> } |
5566 </xsl:text> |
5963 </xsl:text> |
5567 <xsl:text> |
5964 <xsl:text> |
5568 </xsl:text> |
5965 </xsl:text> |
5569 <xsl:text> update_disability() { |
5966 <xsl:text> notify_page_change(page_name, index) { |
5570 </xsl:text> |
5967 </xsl:text> |
5571 <xsl:text> if(this.disabled) { |
5968 <xsl:text> // called from animate() |
5572 </xsl:text> |
5969 </xsl:text> |
5573 <xsl:text> /* show disabled */ |
5970 <xsl:text> if(this.activable) { |
5574 </xsl:text> |
5971 </xsl:text> |
5575 <xsl:text> this.disabled_elt.style.display = ""; |
5972 <xsl:text> const ref_index = this.indexes.length > 0 ? this.indexes[0] + this.offset : undefined; |
5576 </xsl:text> |
5973 </xsl:text> |
5577 <xsl:text> /* hide inactive */ |
5974 <xsl:text> const ref_name = this.args[0]; |
5578 </xsl:text> |
5975 </xsl:text> |
5579 <xsl:text> this.inactive_elt.style.display = "none"; |
5976 <xsl:text> this.activity_state = ((ref_name == undefined || ref_name == page_name) && index == ref_index); |
5580 </xsl:text> |
5977 </xsl:text> |
5581 <xsl:text> /* hide active */ |
5978 <xsl:text> // Since called from animate, update activity directly |
5582 </xsl:text> |
5979 </xsl:text> |
5583 <xsl:text> this.active_elt.style.display = "none"; |
5980 <xsl:text> if(this.enable_displayed_state && this.has_activity) { |
5584 </xsl:text> |
5981 </xsl:text> |
5585 <xsl:text> } else { |
5982 <xsl:text> this.animate_activity(); |
5586 </xsl:text> |
5983 </xsl:text> |
5587 <xsl:text> /* hide disabled */ |
5984 <xsl:text> } |
5588 </xsl:text> |
|
5589 <xsl:text> this.disabled_elt.style.display = "none"; |
|
5590 </xsl:text> |
|
5591 <xsl:text> this.update_activity(); |
|
5592 </xsl:text> |
5985 </xsl:text> |
5593 <xsl:text> } |
5986 <xsl:text> } |
5594 </xsl:text> |
5987 </xsl:text> |
5595 <xsl:text> } |
5988 <xsl:text> } |
5596 </xsl:text> |
5989 </xsl:text> |
5597 <xsl:text> |
|
5598 </xsl:text> |
|
5599 <xsl:text> make_on_click() { |
|
5600 </xsl:text> |
|
5601 <xsl:text> let that = this; |
|
5602 </xsl:text> |
|
5603 <xsl:text> const name = this.args[0]; |
|
5604 </xsl:text> |
|
5605 <xsl:text> return function(evt){ |
|
5606 </xsl:text> |
|
5607 <xsl:text> /* TODO: in order to allow jumps to page selected through for exemple a dropdown, |
|
5608 </xsl:text> |
|
5609 <xsl:text> support path pointing to local variable whom value |
|
5610 </xsl:text> |
|
5611 <xsl:text> would be an HMI_TREE index and then jump to a relative page not hard-coded in advance */ |
|
5612 </xsl:text> |
|
5613 <xsl:text> if(!that.disabled) { |
|
5614 </xsl:text> |
|
5615 <xsl:text> const index = that.indexes.length > 0 ? that.indexes[0] + that.offset : undefined; |
|
5616 </xsl:text> |
|
5617 <xsl:text> fading_page_switch(name, index); |
|
5618 </xsl:text> |
|
5619 <xsl:text> } |
|
5620 </xsl:text> |
|
5621 <xsl:text> } |
|
5622 </xsl:text> |
|
5623 <xsl:text> } |
|
5624 </xsl:text> |
|
5625 <xsl:text> |
|
5626 </xsl:text> |
|
5627 <xsl:text> notify_page_change(page_name, index) { |
|
5628 </xsl:text> |
|
5629 <xsl:text> if(this.activable) { |
|
5630 </xsl:text> |
|
5631 <xsl:text> const ref_index = this.indexes.length > 0 ? this.indexes[0] + this.offset : undefined; |
|
5632 </xsl:text> |
|
5633 <xsl:text> const ref_name = this.args[0]; |
|
5634 </xsl:text> |
|
5635 <xsl:text> this.active = ((ref_name == undefined || ref_name == page_name) && index == ref_index); |
|
5636 </xsl:text> |
|
5637 <xsl:text> this.update_state(); |
|
5638 </xsl:text> |
|
5639 <xsl:text> } |
|
5640 </xsl:text> |
|
5641 <xsl:text> } |
|
5642 </xsl:text> |
|
5643 <xsl:text> |
|
5644 </xsl:text> |
|
5645 <xsl:text> dispatch(value) { |
|
5646 </xsl:text> |
|
5647 <xsl:text> this.disabled = !Number(value); |
|
5648 </xsl:text> |
|
5649 <xsl:text> |
|
5650 </xsl:text> |
|
5651 <xsl:text> // TODO : use RequestAnimate and animate() |
|
5652 </xsl:text> |
|
5653 <xsl:text> |
|
5654 </xsl:text> |
|
5655 <xsl:text> this.update_state(); |
|
5656 </xsl:text> |
|
5657 <xsl:text> } |
|
5658 </xsl:text> |
|
5659 <xsl:text>} |
5990 <xsl:text>} |
5660 </xsl:text> |
5991 </xsl:text> |
5661 </xsl:template> |
5992 </xsl:template> |
|
5993 <func:function name="func:is_relative_jump"> |
|
5994 <xsl:param name="widget"/> |
|
5995 <func:result select="$widget/path and $widget/path[1]/@type='HMI_NODE' and not($widget/arg[position()>1 and @value = 'Absolute'])"/> |
|
5996 </func:function> |
5662 <xsl:template match="widget[@type='Jump']" mode="widget_defs"> |
5997 <xsl:template match="widget[@type='Jump']" mode="widget_defs"> |
5663 <xsl:param name="hmi_element"/> |
5998 <xsl:param name="hmi_element"/> |
|
5999 <xsl:variable name="disability"> |
|
6000 <xsl:call-template name="defs_by_labels"> |
|
6001 <xsl:with-param name="hmi_element" select="$hmi_element"/> |
|
6002 <xsl:with-param name="labels"> |
|
6003 <xsl:text>/disabled</xsl:text> |
|
6004 </xsl:with-param> |
|
6005 <xsl:with-param name="mandatory" select="'no'"/> |
|
6006 </xsl:call-template> |
|
6007 </xsl:variable> |
|
6008 <xsl:value-of select="$disability"/> |
|
6009 <xsl:variable name="has_disability" select="string-length($disability)>0"/> |
|
6010 <xsl:text> activable_sub:{ |
|
6011 </xsl:text> |
5664 <xsl:variable name="activity"> |
6012 <xsl:variable name="activity"> |
5665 <xsl:call-template name="defs_by_labels"> |
6013 <xsl:call-template name="defs_by_labels"> |
5666 <xsl:with-param name="hmi_element" select="$hmi_element"/> |
6014 <xsl:with-param name="hmi_element" select="$hmi_element"/> |
5667 <xsl:with-param name="labels"> |
6015 <xsl:with-param name="labels"> |
5668 <xsl:text>active inactive</xsl:text> |
6016 <xsl:text>/active /inactive</xsl:text> |
5669 </xsl:with-param> |
6017 </xsl:with-param> |
5670 <xsl:with-param name="mandatory" select="'no'"/> |
6018 <xsl:with-param name="mandatory"> |
|
6019 <xsl:text>no</xsl:text> |
|
6020 </xsl:with-param> |
5671 </xsl:call-template> |
6021 </xsl:call-template> |
5672 </xsl:variable> |
6022 </xsl:variable> |
5673 <xsl:variable name="have_activity" select="string-length($activity)>0"/> |
|
5674 <xsl:value-of select="$activity"/> |
6023 <xsl:value-of select="$activity"/> |
5675 <xsl:variable name="disability"> |
6024 <xsl:variable name="has_activity" select="string-length($activity)>0"/> |
5676 <xsl:call-template name="defs_by_labels"> |
6025 <xsl:text> }, |
5677 <xsl:with-param name="hmi_element" select="$hmi_element"/> |
6026 </xsl:text> |
5678 <xsl:with-param name="labels"> |
6027 <xsl:text> has_activity: </xsl:text> |
5679 <xsl:text>disabled</xsl:text> |
6028 <xsl:value-of select="$has_activity"/> |
5680 </xsl:with-param> |
6029 <xsl:text>, |
5681 <xsl:with-param name="mandatory" select="'no'"/> |
6030 </xsl:text> |
5682 </xsl:call-template> |
6031 <xsl:variable name="jump_disability" select="$has_activity and $has_disability"/> |
5683 </xsl:variable> |
|
5684 <xsl:variable name="have_disability" select="$have_activity and string-length($disability)>0"/> |
|
5685 <xsl:value-of select="$disability"/> |
|
5686 <xsl:text> init: function() { |
6032 <xsl:text> init: function() { |
5687 </xsl:text> |
6033 </xsl:text> |
5688 <xsl:text> this.element.onclick = this.make_on_click(); |
6034 <xsl:text> this.element.onclick = this.make_on_click(); |
5689 </xsl:text> |
6035 </xsl:text> |
5690 <xsl:if test="$have_activity"> |
6036 <xsl:if test="$has_activity"> |
5691 <xsl:text> this.activable = true; |
6037 <xsl:text> this.activable = true; |
5692 </xsl:text> |
6038 </xsl:text> |
5693 </xsl:if> |
6039 </xsl:if> |
5694 <xsl:if test="not($have_disability)"> |
6040 <xsl:text> this.is_relative = </xsl:text> |
5695 <xsl:text> this.unsubscribable = true; |
|
5696 </xsl:text> |
|
5697 </xsl:if> |
|
5698 <xsl:text> this.update_state = </xsl:text> |
|
5699 <xsl:choose> |
6041 <xsl:choose> |
5700 <xsl:when test="$have_disability"> |
6042 <xsl:when test="func:is_relative_jump(.)"> |
5701 <xsl:text>this.update_disability</xsl:text> |
6043 <xsl:text>true</xsl:text> |
5702 </xsl:when> |
|
5703 <xsl:when test="$have_activity"> |
|
5704 <xsl:text>this.update_activity</xsl:text> |
|
5705 </xsl:when> |
6044 </xsl:when> |
5706 <xsl:otherwise> |
6045 <xsl:otherwise> |
5707 <xsl:text>null</xsl:text> |
6046 <xsl:text>false</xsl:text> |
5708 </xsl:otherwise> |
6047 </xsl:otherwise> |
5709 </xsl:choose> |
6048 </xsl:choose> |
5710 <xsl:text>; |
6049 <xsl:text>; |
5711 </xsl:text> |
6050 </xsl:text> |
5712 <xsl:text> }, |
6051 <xsl:text> }, |
5713 </xsl:text> |
6052 </xsl:text> |
|
6053 <xsl:text> notify: function() { |
|
6054 </xsl:text> |
|
6055 <xsl:variable name="paths" select="path"/> |
|
6056 <xsl:for-each select="arg[position()>1 and contains(@value,'=')]"> |
|
6057 <xsl:variable name="name" select="substring-before(@value,'=')"/> |
|
6058 <xsl:variable name="value" select="substring-after(@value,'=')"/> |
|
6059 <xsl:variable name="index"> |
|
6060 <xsl:for-each select="$paths"> |
|
6061 <xsl:if test="@assign = $name"> |
|
6062 <xsl:value-of select="position()-1"/> |
|
6063 </xsl:if> |
|
6064 </xsl:for-each> |
|
6065 </xsl:variable> |
|
6066 <xsl:text> // </xsl:text> |
|
6067 <xsl:value-of select="@value"/> |
|
6068 <xsl:text> |
|
6069 </xsl:text> |
|
6070 <xsl:text> this.apply_hmi_value(</xsl:text> |
|
6071 <xsl:value-of select="$index"/> |
|
6072 <xsl:text>, </xsl:text> |
|
6073 <xsl:value-of select="$value"/> |
|
6074 <xsl:text>); |
|
6075 </xsl:text> |
|
6076 </xsl:for-each> |
|
6077 <xsl:text> }, |
|
6078 </xsl:text> |
5714 </xsl:template> |
6079 </xsl:template> |
5715 <xsl:template match="widget[@type='Jump']" mode="widget_page"> |
6080 <xsl:template match="widget[@type='Jump']" mode="widget_page"> |
5716 <xsl:param name="page_desc"/> |
6081 <xsl:param name="page_desc"/> |
5717 <xsl:param name="page_desc"/> |
6082 <xsl:param name="page_desc"/> |
5718 <xsl:if test="path"> |
6083 <xsl:if test="func:is_relative_jump(.)"> |
5719 <xsl:variable name="target_page_name"> |
6084 <xsl:variable name="target_page_name"> |
5720 <xsl:choose> |
6085 <xsl:choose> |
5721 <xsl:when test="arg"> |
6086 <xsl:when test="arg"> |
5722 <xsl:value-of select="arg[1]/@value"/> |
6087 <xsl:value-of select="arg[1]/@value"/> |
5723 </xsl:when> |
6088 </xsl:when> |
9446 </style> |
9965 </style> |
9447 </head> |
9966 </head> |
9448 <body style="margin:0;overflow:hidden;user-select:none;touch-action:none;"> |
9967 <body style="margin:0;overflow:hidden;user-select:none;touch-action:none;"> |
9449 <xsl:copy-of select="$result_svg"/> |
9968 <xsl:copy-of select="$result_svg"/> |
9450 <script> |
9969 <script> |
|
9970 <xsl:text>/* |
|
9971 </xsl:text> |
|
9972 <xsl:text> |
|
9973 </xsl:text> |
|
9974 <xsl:text>From https://github.com/keyvan-m-sadeghi/pythonic |
|
9975 </xsl:text> |
|
9976 <xsl:text> |
|
9977 </xsl:text> |
|
9978 <xsl:text>Slightly modified in order to be usable in browser (i.e. not as a node.js module) |
|
9979 </xsl:text> |
|
9980 <xsl:text> |
|
9981 </xsl:text> |
|
9982 <xsl:text>The MIT License (MIT) |
|
9983 </xsl:text> |
|
9984 <xsl:text> |
|
9985 </xsl:text> |
|
9986 <xsl:text>Copyright (c) 2016 Assister.Ai |
|
9987 </xsl:text> |
|
9988 <xsl:text> |
|
9989 </xsl:text> |
|
9990 <xsl:text>Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
9991 </xsl:text> |
|
9992 <xsl:text>this software and associated documentation files (the "Software"), to deal in |
|
9993 </xsl:text> |
|
9994 <xsl:text>the Software without restriction, including without limitation the rights to |
|
9995 </xsl:text> |
|
9996 <xsl:text>use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
|
9997 </xsl:text> |
|
9998 <xsl:text>the Software, and to permit persons to whom the Software is furnished to do so, |
|
9999 </xsl:text> |
|
10000 <xsl:text>subject to the following conditions: |
|
10001 </xsl:text> |
|
10002 <xsl:text> |
|
10003 </xsl:text> |
|
10004 <xsl:text>The above copyright notice and this permission notice shall be included in all |
|
10005 </xsl:text> |
|
10006 <xsl:text>copies or substantial portions of the Software. |
|
10007 </xsl:text> |
|
10008 <xsl:text> |
|
10009 </xsl:text> |
|
10010 <xsl:text>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
10011 </xsl:text> |
|
10012 <xsl:text>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
10013 </xsl:text> |
|
10014 <xsl:text>FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
10015 </xsl:text> |
|
10016 <xsl:text>COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
10017 </xsl:text> |
|
10018 <xsl:text>IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
10019 </xsl:text> |
|
10020 <xsl:text>CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
10021 </xsl:text> |
|
10022 <xsl:text>*/ |
|
10023 </xsl:text> |
|
10024 <xsl:text> |
|
10025 </xsl:text> |
|
10026 <xsl:text>class Iterator { |
|
10027 </xsl:text> |
|
10028 <xsl:text> constructor(generator) { |
|
10029 </xsl:text> |
|
10030 <xsl:text> this[Symbol.iterator] = generator; |
|
10031 </xsl:text> |
|
10032 <xsl:text> } |
|
10033 </xsl:text> |
|
10034 <xsl:text> |
|
10035 </xsl:text> |
|
10036 <xsl:text> async * [Symbol.asyncIterator]() { |
|
10037 </xsl:text> |
|
10038 <xsl:text> for (const element of this) { |
|
10039 </xsl:text> |
|
10040 <xsl:text> yield await element; |
|
10041 </xsl:text> |
|
10042 <xsl:text> } |
|
10043 </xsl:text> |
|
10044 <xsl:text> } |
|
10045 </xsl:text> |
|
10046 <xsl:text> |
|
10047 </xsl:text> |
|
10048 <xsl:text> forEach(callback) { |
|
10049 </xsl:text> |
|
10050 <xsl:text> for (const element of this) { |
|
10051 </xsl:text> |
|
10052 <xsl:text> callback(element); |
|
10053 </xsl:text> |
|
10054 <xsl:text> } |
|
10055 </xsl:text> |
|
10056 <xsl:text> } |
|
10057 </xsl:text> |
|
10058 <xsl:text> |
|
10059 </xsl:text> |
|
10060 <xsl:text> map(callback) { |
|
10061 </xsl:text> |
|
10062 <xsl:text> const result = []; |
|
10063 </xsl:text> |
|
10064 <xsl:text> for (const element of this) { |
|
10065 </xsl:text> |
|
10066 <xsl:text> result.push(callback(element)); |
|
10067 </xsl:text> |
|
10068 <xsl:text> } |
|
10069 </xsl:text> |
|
10070 <xsl:text> |
|
10071 </xsl:text> |
|
10072 <xsl:text> return result; |
|
10073 </xsl:text> |
|
10074 <xsl:text> } |
|
10075 </xsl:text> |
|
10076 <xsl:text> |
|
10077 </xsl:text> |
|
10078 <xsl:text> filter(callback) { |
|
10079 </xsl:text> |
|
10080 <xsl:text> const result = []; |
|
10081 </xsl:text> |
|
10082 <xsl:text> for (const element of this) { |
|
10083 </xsl:text> |
|
10084 <xsl:text> if (callback(element)) { |
|
10085 </xsl:text> |
|
10086 <xsl:text> result.push(element); |
|
10087 </xsl:text> |
|
10088 <xsl:text> } |
|
10089 </xsl:text> |
|
10090 <xsl:text> } |
|
10091 </xsl:text> |
|
10092 <xsl:text> |
|
10093 </xsl:text> |
|
10094 <xsl:text> return result; |
|
10095 </xsl:text> |
|
10096 <xsl:text> } |
|
10097 </xsl:text> |
|
10098 <xsl:text> |
|
10099 </xsl:text> |
|
10100 <xsl:text> reduce(callback, initialValue) { |
|
10101 </xsl:text> |
|
10102 <xsl:text> let empty = typeof initialValue === 'undefined'; |
|
10103 </xsl:text> |
|
10104 <xsl:text> let accumulator = initialValue; |
|
10105 </xsl:text> |
|
10106 <xsl:text> let index = 0; |
|
10107 </xsl:text> |
|
10108 <xsl:text> for (const currentValue of this) { |
|
10109 </xsl:text> |
|
10110 <xsl:text> if (empty) { |
|
10111 </xsl:text> |
|
10112 <xsl:text> accumulator = currentValue; |
|
10113 </xsl:text> |
|
10114 <xsl:text> empty = false; |
|
10115 </xsl:text> |
|
10116 <xsl:text> continue; |
|
10117 </xsl:text> |
|
10118 <xsl:text> } |
|
10119 </xsl:text> |
|
10120 <xsl:text> |
|
10121 </xsl:text> |
|
10122 <xsl:text> accumulator = callback(accumulator, currentValue, index, this); |
|
10123 </xsl:text> |
|
10124 <xsl:text> index++; |
|
10125 </xsl:text> |
|
10126 <xsl:text> } |
|
10127 </xsl:text> |
|
10128 <xsl:text> |
|
10129 </xsl:text> |
|
10130 <xsl:text> if (empty) { |
|
10131 </xsl:text> |
|
10132 <xsl:text> throw new TypeError('Reduce of empty Iterator with no initial value'); |
|
10133 </xsl:text> |
|
10134 <xsl:text> } |
|
10135 </xsl:text> |
|
10136 <xsl:text> |
|
10137 </xsl:text> |
|
10138 <xsl:text> return accumulator; |
|
10139 </xsl:text> |
|
10140 <xsl:text> } |
|
10141 </xsl:text> |
|
10142 <xsl:text> |
|
10143 </xsl:text> |
|
10144 <xsl:text> some(callback) { |
|
10145 </xsl:text> |
|
10146 <xsl:text> for (const element of this) { |
|
10147 </xsl:text> |
|
10148 <xsl:text> if (callback(element)) { |
|
10149 </xsl:text> |
|
10150 <xsl:text> return true; |
|
10151 </xsl:text> |
|
10152 <xsl:text> } |
|
10153 </xsl:text> |
|
10154 <xsl:text> } |
|
10155 </xsl:text> |
|
10156 <xsl:text> |
|
10157 </xsl:text> |
|
10158 <xsl:text> return false; |
|
10159 </xsl:text> |
|
10160 <xsl:text> } |
|
10161 </xsl:text> |
|
10162 <xsl:text> |
|
10163 </xsl:text> |
|
10164 <xsl:text> every(callback) { |
|
10165 </xsl:text> |
|
10166 <xsl:text> for (const element of this) { |
|
10167 </xsl:text> |
|
10168 <xsl:text> if (!callback(element)) { |
|
10169 </xsl:text> |
|
10170 <xsl:text> return false; |
|
10171 </xsl:text> |
|
10172 <xsl:text> } |
|
10173 </xsl:text> |
|
10174 <xsl:text> } |
|
10175 </xsl:text> |
|
10176 <xsl:text> |
|
10177 </xsl:text> |
|
10178 <xsl:text> return true; |
|
10179 </xsl:text> |
|
10180 <xsl:text> } |
|
10181 </xsl:text> |
|
10182 <xsl:text> |
|
10183 </xsl:text> |
|
10184 <xsl:text> static fromIterable(iterable) { |
|
10185 </xsl:text> |
|
10186 <xsl:text> return new Iterator(function * () { |
|
10187 </xsl:text> |
|
10188 <xsl:text> for (const element of iterable) { |
|
10189 </xsl:text> |
|
10190 <xsl:text> yield element; |
|
10191 </xsl:text> |
|
10192 <xsl:text> } |
|
10193 </xsl:text> |
|
10194 <xsl:text> }); |
|
10195 </xsl:text> |
|
10196 <xsl:text> } |
|
10197 </xsl:text> |
|
10198 <xsl:text> |
|
10199 </xsl:text> |
|
10200 <xsl:text> toArray() { |
|
10201 </xsl:text> |
|
10202 <xsl:text> return Array.from(this); |
|
10203 </xsl:text> |
|
10204 <xsl:text> } |
|
10205 </xsl:text> |
|
10206 <xsl:text> |
|
10207 </xsl:text> |
|
10208 <xsl:text> next() { |
|
10209 </xsl:text> |
|
10210 <xsl:text> if (!this.currentInvokedGenerator) { |
|
10211 </xsl:text> |
|
10212 <xsl:text> this.currentInvokedGenerator = this[Symbol.iterator](); |
|
10213 </xsl:text> |
|
10214 <xsl:text> } |
|
10215 </xsl:text> |
|
10216 <xsl:text> |
|
10217 </xsl:text> |
|
10218 <xsl:text> return this.currentInvokedGenerator.next(); |
|
10219 </xsl:text> |
|
10220 <xsl:text> } |
|
10221 </xsl:text> |
|
10222 <xsl:text> |
|
10223 </xsl:text> |
|
10224 <xsl:text> reset() { |
|
10225 </xsl:text> |
|
10226 <xsl:text> delete this.currentInvokedGenerator; |
|
10227 </xsl:text> |
|
10228 <xsl:text> } |
|
10229 </xsl:text> |
|
10230 <xsl:text>} |
|
10231 </xsl:text> |
|
10232 <xsl:text> |
|
10233 </xsl:text> |
|
10234 <xsl:text>function rangeSimple(stop) { |
|
10235 </xsl:text> |
|
10236 <xsl:text> return new Iterator(function * () { |
|
10237 </xsl:text> |
|
10238 <xsl:text> for (let i = 0; i < 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 < 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 < 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 => (...iterables) => { |
|
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] -> [[a],[b],[c]] |
|
10309 </xsl:text> |
|
10310 <xsl:text> // [a,b,c],[d,e,f] -> [[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 => Iterator.fromIterable(iterable)); |
|
10321 </xsl:text> |
|
10322 <xsl:text> while (true) { |
|
10323 </xsl:text> |
|
10324 <xsl:text> const row = iterators.map(iterator => 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 => 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 => next.value); |
|
10337 </xsl:text> |
|
10338 <xsl:text> } |
|
10339 </xsl:text> |
|
10340 <xsl:text> }); |
|
10341 </xsl:text> |
|
10342 <xsl:text>}; |
|
10343 </xsl:text> |
|
10344 <xsl:text> |
|
10345 </xsl:text> |
|
10346 <xsl:text>const zip = _zip(false), zipLongest= _zip(true); |
|
10347 </xsl:text> |
|
10348 <xsl:text> |
|
10349 </xsl:text> |
|
10350 <xsl:text>function items(obj) { |
|
10351 </xsl:text> |
|
10352 <xsl:text> let {keys, get} = obj; |
|
10353 </xsl:text> |
|
10354 <xsl:text> if (obj instanceof Map) { |
|
10355 </xsl:text> |
|
10356 <xsl:text> keys = keys.bind(obj); |
|
10357 </xsl:text> |
|
10358 <xsl:text> get = get.bind(obj); |
|
10359 </xsl:text> |
|
10360 <xsl:text> } else { |
|
10361 </xsl:text> |
|
10362 <xsl:text> keys = function () { |
|
10363 </xsl:text> |
|
10364 <xsl:text> return Object.keys(obj); |
|
10365 </xsl:text> |
|
10366 <xsl:text> }; |
|
10367 </xsl:text> |
|
10368 <xsl:text> |
|
10369 </xsl:text> |
|
10370 <xsl:text> get = function (key) { |
|
10371 </xsl:text> |
|
10372 <xsl:text> return obj[key]; |
|
10373 </xsl:text> |
|
10374 <xsl:text> }; |
|
10375 </xsl:text> |
|
10376 <xsl:text> } |
|
10377 </xsl:text> |
|
10378 <xsl:text> |
|
10379 </xsl:text> |
|
10380 <xsl:text> return new Iterator(function * () { |
|
10381 </xsl:text> |
|
10382 <xsl:text> for (const key of keys()) { |
|
10383 </xsl:text> |
|
10384 <xsl:text> yield [key, get(key)]; |
|
10385 </xsl:text> |
|
10386 <xsl:text> } |
|
10387 </xsl:text> |
|
10388 <xsl:text> }); |
|
10389 </xsl:text> |
|
10390 <xsl:text>} |
|
10391 </xsl:text> |
|
10392 <xsl:text> |
|
10393 </xsl:text> |
|
10394 <xsl:text>/* |
|
10395 </xsl:text> |
|
10396 <xsl:text>module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items}; |
|
10397 </xsl:text> |
|
10398 <xsl:text>*/ |
|
10399 </xsl:text> |
9451 <xsl:text> |
10400 <xsl:text> |
9452 // |
10401 // |
9453 // |
10402 // |
9454 // Early independent declarations |
10403 // Early independent declarations |
9455 // |
10404 // |
10044 </xsl:text> |
10993 </xsl:text> |
10045 <xsl:text> /* eslint-enable quote-props */ |
10994 <xsl:text> /* eslint-enable quote-props */ |
10046 </xsl:text> |
10995 </xsl:text> |
10047 <xsl:text>}(); // eslint-disable-line |
10996 <xsl:text>}(); // eslint-disable-line |
10048 </xsl:text> |
10997 </xsl:text> |
10049 <xsl:text>/* |
10998 <xsl:text>// svghmi.js |
10050 </xsl:text> |
10999 </xsl:text> |
10051 <xsl:text> |
11000 <xsl:text> |
10052 </xsl:text> |
11001 </xsl:text> |
10053 <xsl:text>From https://github.com/keyvan-m-sadeghi/pythonic |
11002 <xsl:text>function dispatch_value(index, value) { |
10054 </xsl:text> |
11003 </xsl:text> |
10055 <xsl:text> |
11004 <xsl:text> let widgets = subscribers(index); |
10056 </xsl:text> |
11005 </xsl:text> |
10057 <xsl:text>Slightly modified in order to be usable in browser (i.e. not as a node.js module) |
11006 <xsl:text> |
10058 </xsl:text> |
11007 </xsl:text> |
10059 <xsl:text> |
11008 <xsl:text> let oldval = cache[index]; |
10060 </xsl:text> |
11009 </xsl:text> |
10061 <xsl:text>The MIT License (MIT) |
11010 <xsl:text> cache[index] = value; |
10062 </xsl:text> |
11011 </xsl:text> |
10063 <xsl:text> |
11012 <xsl:text> |
10064 </xsl:text> |
11013 </xsl:text> |
10065 <xsl:text>Copyright (c) 2016 Assister.Ai |
11014 <xsl:text> if(widgets.size > 0) { |
10066 </xsl:text> |
11015 </xsl:text> |
10067 <xsl:text> |
11016 <xsl:text> for(let widget of widgets){ |
10068 </xsl:text> |
11017 </xsl:text> |
10069 <xsl:text>Permission is hereby granted, free of charge, to any person obtaining a copy of |
11018 <xsl:text> widget.new_hmi_value(index, value, oldval); |
10070 </xsl:text> |
11019 </xsl:text> |
10071 <xsl:text>this software and associated documentation files (the "Software"), to deal in |
11020 <xsl:text> } |
10072 </xsl:text> |
|
10073 <xsl:text>the Software without restriction, including without limitation the rights to |
|
10074 </xsl:text> |
|
10075 <xsl:text>use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
|
10076 </xsl:text> |
|
10077 <xsl:text>the Software, and to permit persons to whom the Software is furnished to do so, |
|
10078 </xsl:text> |
|
10079 <xsl:text>subject to the following conditions: |
|
10080 </xsl:text> |
|
10081 <xsl:text> |
|
10082 </xsl:text> |
|
10083 <xsl:text>The above copyright notice and this permission notice shall be included in all |
|
10084 </xsl:text> |
|
10085 <xsl:text>copies or substantial portions of the Software. |
|
10086 </xsl:text> |
|
10087 <xsl:text> |
|
10088 </xsl:text> |
|
10089 <xsl:text>THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
10090 </xsl:text> |
|
10091 <xsl:text>IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
10092 </xsl:text> |
|
10093 <xsl:text>FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
10094 </xsl:text> |
|
10095 <xsl:text>COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
10096 </xsl:text> |
|
10097 <xsl:text>IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
10098 </xsl:text> |
|
10099 <xsl:text>CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
10100 </xsl:text> |
|
10101 <xsl:text>*/ |
|
10102 </xsl:text> |
|
10103 <xsl:text> |
|
10104 </xsl:text> |
|
10105 <xsl:text>class Iterator { |
|
10106 </xsl:text> |
|
10107 <xsl:text> constructor(generator) { |
|
10108 </xsl:text> |
|
10109 <xsl:text> this[Symbol.iterator] = generator; |
|
10110 </xsl:text> |
11021 </xsl:text> |
10111 <xsl:text> } |
11022 <xsl:text> } |
10112 </xsl:text> |
11023 </xsl:text> |
10113 <xsl:text> |
11024 <xsl:text>}; |
10114 </xsl:text> |
11025 </xsl:text> |
10115 <xsl:text> async * [Symbol.asyncIterator]() { |
11026 <xsl:text> |
10116 </xsl:text> |
11027 </xsl:text> |
10117 <xsl:text> for (const element of this) { |
11028 <xsl:text>function init_widgets() { |
10118 </xsl:text> |
11029 </xsl:text> |
10119 <xsl:text> yield await element; |
11030 <xsl:text> Object.keys(hmi_widgets).forEach(function(id) { |
|
11031 </xsl:text> |
|
11032 <xsl:text> let widget = hmi_widgets[id]; |
|
11033 </xsl:text> |
|
11034 <xsl:text> widget.do_init(); |
|
11035 </xsl:text> |
|
11036 <xsl:text> }); |
|
11037 </xsl:text> |
|
11038 <xsl:text>}; |
|
11039 </xsl:text> |
|
11040 <xsl:text> |
|
11041 </xsl:text> |
|
11042 <xsl:text>// Open WebSocket to relative "/ws" address |
|
11043 </xsl:text> |
|
11044 <xsl:text>var has_watchdog = window.location.hash == "#watchdog"; |
|
11045 </xsl:text> |
|
11046 <xsl:text> |
|
11047 </xsl:text> |
|
11048 <xsl:text>var ws_url = |
|
11049 </xsl:text> |
|
11050 <xsl:text> window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws') |
|
11051 </xsl:text> |
|
11052 <xsl:text> + '?mode=' + (has_watchdog ? "watchdog" : "multiclient"); |
|
11053 </xsl:text> |
|
11054 <xsl:text> |
|
11055 </xsl:text> |
|
11056 <xsl:text>var ws = new WebSocket(ws_url); |
|
11057 </xsl:text> |
|
11058 <xsl:text>ws.binaryType = 'arraybuffer'; |
|
11059 </xsl:text> |
|
11060 <xsl:text> |
|
11061 </xsl:text> |
|
11062 <xsl:text>const dvgetters = { |
|
11063 </xsl:text> |
|
11064 <xsl:text> INT: (dv,offset) => [dv.getInt16(offset, true), 2], |
|
11065 </xsl:text> |
|
11066 <xsl:text> BOOL: (dv,offset) => [dv.getInt8(offset, true), 1], |
|
11067 </xsl:text> |
|
11068 <xsl:text> NODE: (dv,offset) => [dv.getInt8(offset, true), 1], |
|
11069 </xsl:text> |
|
11070 <xsl:text> REAL: (dv,offset) => [dv.getFloat32(offset, true), 4], |
|
11071 </xsl:text> |
|
11072 <xsl:text> STRING: (dv, offset) => { |
|
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) => { |
|
11099 </xsl:text> |
|
11100 <xsl:text> dispatch_value(index, value); |
|
11101 </xsl:text> |
|
11102 <xsl:text> }); |
|
11103 </xsl:text> |
|
11104 <xsl:text> updates.clear(); |
|
11105 </xsl:text> |
|
11106 <xsl:text>} |
|
11107 </xsl:text> |
|
11108 <xsl:text> |
|
11109 </xsl:text> |
|
11110 <xsl:text>// Called on requestAnimationFrame, modifies DOM |
|
11111 </xsl:text> |
|
11112 <xsl:text>var requestAnimationFrameID = null; |
|
11113 </xsl:text> |
|
11114 <xsl:text>function animate() { |
|
11115 </xsl:text> |
|
11116 <xsl:text> let rearm = true; |
|
11117 </xsl:text> |
|
11118 <xsl:text> do{ |
|
11119 </xsl:text> |
|
11120 <xsl:text> if(page_fading == "pending" || page_fading == "forced"){ |
|
11121 </xsl:text> |
|
11122 <xsl:text> if(page_fading == "pending") |
|
11123 </xsl:text> |
|
11124 <xsl:text> svg_root.classList.add("fade-out-page"); |
|
11125 </xsl:text> |
|
11126 <xsl:text> page_fading = "in_progress"; |
|
11127 </xsl:text> |
|
11128 <xsl:text> if(page_fading_args.length) |
|
11129 </xsl:text> |
|
11130 <xsl:text> setTimeout(function(){ |
|
11131 </xsl:text> |
|
11132 <xsl:text> switch_page(...page_fading_args); |
|
11133 </xsl:text> |
|
11134 <xsl:text> },1); |
|
11135 </xsl:text> |
|
11136 <xsl:text> break; |
10120 </xsl:text> |
11137 </xsl:text> |
10121 <xsl:text> } |
11138 <xsl:text> } |
10122 </xsl:text> |
11139 </xsl:text> |
|
11140 <xsl:text> |
|
11141 </xsl:text> |
|
11142 <xsl:text> // Do the page swith if pending |
|
11143 </xsl:text> |
|
11144 <xsl:text> if(page_switch_in_progress){ |
|
11145 </xsl:text> |
|
11146 <xsl:text> if(current_subscribed_page != current_visible_page){ |
|
11147 </xsl:text> |
|
11148 <xsl:text> switch_visible_page(current_subscribed_page); |
|
11149 </xsl:text> |
|
11150 <xsl:text> } |
|
11151 </xsl:text> |
|
11152 <xsl:text> |
|
11153 </xsl:text> |
|
11154 <xsl:text> page_switch_in_progress = false; |
|
11155 </xsl:text> |
|
11156 <xsl:text> |
|
11157 </xsl:text> |
|
11158 <xsl:text> if(page_fading == "in_progress"){ |
|
11159 </xsl:text> |
|
11160 <xsl:text> svg_root.classList.remove("fade-out-page"); |
|
11161 </xsl:text> |
|
11162 <xsl:text> page_fading = "off"; |
|
11163 </xsl:text> |
|
11164 <xsl:text> } |
|
11165 </xsl:text> |
|
11166 <xsl:text> } |
|
11167 </xsl:text> |
|
11168 <xsl:text> |
|
11169 </xsl:text> |
|
11170 <xsl:text> if(jumps_need_update) update_jumps(); |
|
11171 </xsl:text> |
|
11172 <xsl:text> |
|
11173 </xsl:text> |
|
11174 <xsl:text> |
|
11175 </xsl:text> |
|
11176 <xsl:text> pending_widget_animates.forEach(widget => widget._animate()); |
|
11177 </xsl:text> |
|
11178 <xsl:text> pending_widget_animates = []; |
|
11179 </xsl:text> |
|
11180 <xsl:text> rearm = false; |
|
11181 </xsl:text> |
|
11182 <xsl:text> } while(0); |
|
11183 </xsl:text> |
|
11184 <xsl:text> |
|
11185 </xsl:text> |
|
11186 <xsl:text> requestAnimationFrameID = null; |
|
11187 </xsl:text> |
|
11188 <xsl:text> |
|
11189 </xsl:text> |
|
11190 <xsl:text> if(rearm) requestHMIAnimation(); |
|
11191 </xsl:text> |
|
11192 <xsl:text>} |
|
11193 </xsl:text> |
|
11194 <xsl:text> |
|
11195 </xsl:text> |
|
11196 <xsl:text>function requestHMIAnimation() { |
|
11197 </xsl:text> |
|
11198 <xsl:text> if(requestAnimationFrameID == null){ |
|
11199 </xsl:text> |
|
11200 <xsl:text> requestAnimationFrameID = window.requestAnimationFrame(animate); |
|
11201 </xsl:text> |
10123 <xsl:text> } |
11202 <xsl:text> } |
10124 </xsl:text> |
11203 </xsl:text> |
10125 <xsl:text> |
11204 <xsl:text>} |
10126 </xsl:text> |
11205 </xsl:text> |
10127 <xsl:text> forEach(callback) { |
11206 <xsl:text> |
10128 </xsl:text> |
11207 </xsl:text> |
10129 <xsl:text> for (const element of this) { |
11208 <xsl:text>// Message reception handler |
10130 </xsl:text> |
11209 </xsl:text> |
10131 <xsl:text> callback(element); |
11210 <xsl:text>// Hash is verified and HMI values updates resulting from binary parsing |
|
11211 </xsl:text> |
|
11212 <xsl:text>// are stored until browser can compute next frame, DOM is left untouched |
|
11213 </xsl:text> |
|
11214 <xsl:text>ws.onmessage = function (evt) { |
|
11215 </xsl:text> |
|
11216 <xsl:text> |
|
11217 </xsl:text> |
|
11218 <xsl:text> let data = evt.data; |
|
11219 </xsl:text> |
|
11220 <xsl:text> let dv = new DataView(data); |
|
11221 </xsl:text> |
|
11222 <xsl:text> let i = 0; |
|
11223 </xsl:text> |
|
11224 <xsl:text> try { |
|
11225 </xsl:text> |
|
11226 <xsl:text> for(let hash_int of hmi_hash) { |
|
11227 </xsl:text> |
|
11228 <xsl:text> if(hash_int != dv.getUint8(i)){ |
|
11229 </xsl:text> |
|
11230 <xsl:text> throw new Error("Hash doesn't match"); |
|
11231 </xsl:text> |
|
11232 <xsl:text> }; |
|
11233 </xsl:text> |
|
11234 <xsl:text> i++; |
|
11235 </xsl:text> |
|
11236 <xsl:text> }; |
|
11237 </xsl:text> |
|
11238 <xsl:text> |
|
11239 </xsl:text> |
|
11240 <xsl:text> while(i < 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 > 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) => new Int16Array([number]), |
|
11315 </xsl:text> |
|
11316 <xsl:text> BOOL: (truth) => new Int16Array([truth]), |
|
11317 </xsl:text> |
|
11318 <xsl:text> NODE: (truth) => new Int16Array([truth]), |
|
11319 </xsl:text> |
|
11320 <xsl:text> REAL: (number) => new Float32Array([number]), |
|
11321 </xsl:text> |
|
11322 <xsl:text> STRING: (str) => { |
|
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 < str.length; i++){ |
|
11333 </xsl:text> |
|
11334 <xsl:text> binary[i+1] = str.charCodeAt(i); |
10132 </xsl:text> |
11335 </xsl:text> |
10133 <xsl:text> } |
11336 <xsl:text> } |
10134 </xsl:text> |
11337 </xsl:text> |
|
11338 <xsl:text> return binary; |
|
11339 </xsl:text> |
10135 <xsl:text> } |
11340 <xsl:text> } |
10136 </xsl:text> |
11341 </xsl:text> |
10137 <xsl:text> |
11342 <xsl:text> /* TODO */ |
10138 </xsl:text> |
11343 </xsl:text> |
10139 <xsl:text> map(callback) { |
11344 <xsl:text>}; |
10140 </xsl:text> |
11345 </xsl:text> |
10141 <xsl:text> const result = []; |
11346 <xsl:text> |
10142 </xsl:text> |
11347 </xsl:text> |
10143 <xsl:text> for (const element of this) { |
11348 <xsl:text>function send_reset() { |
10144 </xsl:text> |
11349 </xsl:text> |
10145 <xsl:text> result.push(callback(element)); |
11350 <xsl:text> send_blob(new Uint8Array([1])); /* reset = 1 */ |
|
11351 </xsl:text> |
|
11352 <xsl:text>}; |
|
11353 </xsl:text> |
|
11354 <xsl:text> |
|
11355 </xsl:text> |
|
11356 <xsl:text>var subscriptions = []; |
|
11357 </xsl:text> |
|
11358 <xsl:text> |
|
11359 </xsl:text> |
|
11360 <xsl:text>function subscribers(index) { |
|
11361 </xsl:text> |
|
11362 <xsl:text> let entry = subscriptions[index]; |
|
11363 </xsl:text> |
|
11364 <xsl:text> let res; |
|
11365 </xsl:text> |
|
11366 <xsl:text> if(entry == undefined){ |
|
11367 </xsl:text> |
|
11368 <xsl:text> res = new Set(); |
|
11369 </xsl:text> |
|
11370 <xsl:text> subscriptions[index] = [res,0]; |
|
11371 </xsl:text> |
|
11372 <xsl:text> }else{ |
|
11373 </xsl:text> |
|
11374 <xsl:text> [res, _ign] = entry; |
|
11375 </xsl:text> |
|
11376 <xsl:text> } |
|
11377 </xsl:text> |
|
11378 <xsl:text> return res |
|
11379 </xsl:text> |
|
11380 <xsl:text>} |
|
11381 </xsl:text> |
|
11382 <xsl:text> |
|
11383 </xsl:text> |
|
11384 <xsl:text>function get_subscription_period(index) { |
|
11385 </xsl:text> |
|
11386 <xsl:text> let entry = subscriptions[index]; |
|
11387 </xsl:text> |
|
11388 <xsl:text> if(entry == undefined) |
|
11389 </xsl:text> |
|
11390 <xsl:text> return 0; |
|
11391 </xsl:text> |
|
11392 <xsl:text> let [_ign, period] = entry; |
|
11393 </xsl:text> |
|
11394 <xsl:text> return period; |
|
11395 </xsl:text> |
|
11396 <xsl:text>} |
|
11397 </xsl:text> |
|
11398 <xsl:text> |
|
11399 </xsl:text> |
|
11400 <xsl:text>function set_subscription_period(index, period) { |
|
11401 </xsl:text> |
|
11402 <xsl:text> let entry = subscriptions[index]; |
|
11403 </xsl:text> |
|
11404 <xsl:text> if(entry == undefined){ |
|
11405 </xsl:text> |
|
11406 <xsl:text> subscriptions[index] = [new Set(), period]; |
|
11407 </xsl:text> |
|
11408 <xsl:text> } else { |
|
11409 </xsl:text> |
|
11410 <xsl:text> entry[1] = period; |
|
11411 </xsl:text> |
|
11412 <xsl:text> } |
|
11413 </xsl:text> |
|
11414 <xsl:text>} |
|
11415 </xsl:text> |
|
11416 <xsl:text> |
|
11417 </xsl:text> |
|
11418 <xsl:text>if(has_watchdog){ |
|
11419 </xsl:text> |
|
11420 <xsl:text> // artificially subscribe the watchdog widget to "/heartbeat" hmi variable |
|
11421 </xsl:text> |
|
11422 <xsl:text> // Since dispatch directly calls change_hmi_value, |
|
11423 </xsl:text> |
|
11424 <xsl:text> // PLC will periodically send variable at given frequency |
|
11425 </xsl:text> |
|
11426 <xsl:text> subscribers(heartbeat_index).add({ |
|
11427 </xsl:text> |
|
11428 <xsl:text> /* type: "Watchdog", */ |
|
11429 </xsl:text> |
|
11430 <xsl:text> frequency: 1, |
|
11431 </xsl:text> |
|
11432 <xsl:text> indexes: [heartbeat_index], |
|
11433 </xsl:text> |
|
11434 <xsl:text> new_hmi_value: function(index, value, oldval) { |
|
11435 </xsl:text> |
|
11436 <xsl:text> apply_hmi_value(heartbeat_index, value+1); |
10146 </xsl:text> |
11437 </xsl:text> |
10147 <xsl:text> } |
11438 <xsl:text> } |
10148 </xsl:text> |
11439 </xsl:text> |
10149 <xsl:text> |
11440 <xsl:text> }); |
10150 </xsl:text> |
11441 </xsl:text> |
10151 <xsl:text> return result; |
11442 <xsl:text>} |
|
11443 </xsl:text> |
|
11444 <xsl:text> |
|
11445 </xsl:text> |
|
11446 <xsl:text> |
|
11447 </xsl:text> |
|
11448 <xsl:text>var page_fading = "off"; |
|
11449 </xsl:text> |
|
11450 <xsl:text>var page_fading_args = "off"; |
|
11451 </xsl:text> |
|
11452 <xsl:text>function fading_page_switch(...args){ |
|
11453 </xsl:text> |
|
11454 <xsl:text> if(page_fading == "in_progress") |
|
11455 </xsl:text> |
|
11456 <xsl:text> page_fading = "forced"; |
|
11457 </xsl:text> |
|
11458 <xsl:text> else |
|
11459 </xsl:text> |
|
11460 <xsl:text> page_fading = "pending"; |
|
11461 </xsl:text> |
|
11462 <xsl:text> page_fading_args = args; |
|
11463 </xsl:text> |
|
11464 <xsl:text> |
|
11465 </xsl:text> |
|
11466 <xsl:text> requestHMIAnimation(); |
|
11467 </xsl:text> |
|
11468 <xsl:text> |
|
11469 </xsl:text> |
|
11470 <xsl:text>} |
|
11471 </xsl:text> |
|
11472 <xsl:text>document.body.style.backgroundColor = "black"; |
|
11473 </xsl:text> |
|
11474 <xsl:text> |
|
11475 </xsl:text> |
|
11476 <xsl:text>// subscribe to per instance current page hmi variable |
|
11477 </xsl:text> |
|
11478 <xsl:text>// PLC must prefix page name with "!" for page switch to happen |
|
11479 </xsl:text> |
|
11480 <xsl:text>subscribers(current_page_var_index).add({ |
|
11481 </xsl:text> |
|
11482 <xsl:text> frequency: 1, |
|
11483 </xsl:text> |
|
11484 <xsl:text> indexes: [current_page_var_index], |
|
11485 </xsl:text> |
|
11486 <xsl:text> new_hmi_value: function(index, value, oldval) { |
|
11487 </xsl:text> |
|
11488 <xsl:text> if(value.startsWith("!")) |
|
11489 </xsl:text> |
|
11490 <xsl:text> fading_page_switch(value.slice(1)); |
10152 </xsl:text> |
11491 </xsl:text> |
10153 <xsl:text> } |
11492 <xsl:text> } |
10154 </xsl:text> |
11493 </xsl:text> |
10155 <xsl:text> |
11494 <xsl:text>}); |
10156 </xsl:text> |
11495 </xsl:text> |
10157 <xsl:text> filter(callback) { |
11496 <xsl:text> |
10158 </xsl:text> |
11497 </xsl:text> |
10159 <xsl:text> const result = []; |
11498 <xsl:text>function svg_text_to_multiline(elt) { |
10160 </xsl:text> |
11499 </xsl:text> |
10161 <xsl:text> for (const element of this) { |
11500 <xsl:text> return(Array.prototype.map.call(elt.children, x=>x.textContent).join("\n")); |
10162 </xsl:text> |
11501 </xsl:text> |
10163 <xsl:text> if (callback(element)) { |
11502 <xsl:text>} |
10164 </xsl:text> |
11503 </xsl:text> |
10165 <xsl:text> result.push(element); |
11504 <xsl:text> |
|
11505 </xsl:text> |
|
11506 <xsl:text>function multiline_to_svg_text(elt, str, blank) { |
|
11507 </xsl:text> |
|
11508 <xsl:text> str.split('\n').map((line,i) => {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 > 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 && maxfreq < wf) |
|
11641 </xsl:text> |
|
11642 <xsl:text> maxfreq = wf; |
10166 </xsl:text> |
11643 </xsl:text> |
10167 <xsl:text> } |
11644 <xsl:text> } |
10168 </xsl:text> |
11645 </xsl:text> |
|
11646 <xsl:text> |
|
11647 </xsl:text> |
|
11648 <xsl:text> if(maxfreq != 0) |
|
11649 </xsl:text> |
|
11650 <xsl:text> new_period = 1000/maxfreq; |
|
11651 </xsl:text> |
10169 <xsl:text> } |
11652 <xsl:text> } |
10170 </xsl:text> |
11653 </xsl:text> |
10171 <xsl:text> |
11654 <xsl:text> |
10172 </xsl:text> |
11655 </xsl:text> |
10173 <xsl:text> return result; |
11656 <xsl:text> if(previous_period != new_period) { |
|
11657 </xsl:text> |
|
11658 <xsl:text> set_subscription_period(index, new_period); |
|
11659 </xsl:text> |
|
11660 <xsl:text> if(index <= last_remote_index){ |
|
11661 </xsl:text> |
|
11662 <xsl:text> delta.push( |
|
11663 </xsl:text> |
|
11664 <xsl:text> new Uint8Array([2]), /* subscribe = 2 */ |
|
11665 </xsl:text> |
|
11666 <xsl:text> new Uint32Array([index]), |
|
11667 </xsl:text> |
|
11668 <xsl:text> new Uint16Array([new_period])); |
|
11669 </xsl:text> |
|
11670 <xsl:text> } |
|
11671 </xsl:text> |
|
11672 <xsl:text> } |
10174 </xsl:text> |
11673 </xsl:text> |
10175 <xsl:text> } |
11674 <xsl:text> } |
10176 </xsl:text> |
11675 </xsl:text> |
10177 <xsl:text> |
11676 <xsl:text> send_blob(delta); |
10178 </xsl:text> |
11677 </xsl:text> |
10179 <xsl:text> reduce(callback, initialValue) { |
11678 <xsl:text>}; |
10180 </xsl:text> |
11679 </xsl:text> |
10181 <xsl:text> let empty = typeof initialValue === 'undefined'; |
11680 <xsl:text> |
10182 </xsl:text> |
11681 </xsl:text> |
10183 <xsl:text> let accumulator = initialValue; |
11682 <xsl:text>function send_hmi_value(index, value) { |
10184 </xsl:text> |
11683 </xsl:text> |
10185 <xsl:text> let index = 0; |
11684 <xsl:text> if(index > last_remote_index){ |
10186 </xsl:text> |
11685 </xsl:text> |
10187 <xsl:text> for (const currentValue of this) { |
11686 <xsl:text> dispatch_value(index, value); |
10188 </xsl:text> |
11687 </xsl:text> |
10189 <xsl:text> if (empty) { |
11688 <xsl:text> |
10190 </xsl:text> |
11689 </xsl:text> |
10191 <xsl:text> accumulator = currentValue; |
11690 <xsl:text> if(persistent_indexes.has(index)){ |
10192 </xsl:text> |
11691 </xsl:text> |
10193 <xsl:text> empty = false; |
11692 <xsl:text> let varname = persistent_indexes.get(index); |
10194 </xsl:text> |
11693 </xsl:text> |
10195 <xsl:text> continue; |
11694 <xsl:text> document.cookie = varname+"="+value+"; max-age=3153600000"; |
10196 </xsl:text> |
|
10197 <xsl:text> } |
|
10198 </xsl:text> |
|
10199 <xsl:text> |
|
10200 </xsl:text> |
|
10201 <xsl:text> accumulator = callback(accumulator, currentValue, index, this); |
|
10202 </xsl:text> |
|
10203 <xsl:text> index++; |
|
10204 </xsl:text> |
11695 </xsl:text> |
10205 <xsl:text> } |
11696 <xsl:text> } |
10206 </xsl:text> |
11697 </xsl:text> |
10207 <xsl:text> |
11698 <xsl:text> |
10208 </xsl:text> |
|
10209 <xsl:text> if (empty) { |
|
10210 </xsl:text> |
|
10211 <xsl:text> throw new TypeError('Reduce of empty Iterator with no initial value'); |
|
10212 </xsl:text> |
|
10213 <xsl:text> } |
|
10214 </xsl:text> |
|
10215 <xsl:text> |
|
10216 </xsl:text> |
|
10217 <xsl:text> return accumulator; |
|
10218 </xsl:text> |
|
10219 <xsl:text> } |
|
10220 </xsl:text> |
|
10221 <xsl:text> |
|
10222 </xsl:text> |
|
10223 <xsl:text> some(callback) { |
|
10224 </xsl:text> |
|
10225 <xsl:text> for (const element of this) { |
|
10226 </xsl:text> |
|
10227 <xsl:text> if (callback(element)) { |
|
10228 </xsl:text> |
|
10229 <xsl:text> return true; |
|
10230 </xsl:text> |
|
10231 <xsl:text> } |
|
10232 </xsl:text> |
|
10233 <xsl:text> } |
|
10234 </xsl:text> |
|
10235 <xsl:text> |
|
10236 </xsl:text> |
|
10237 <xsl:text> return false; |
|
10238 </xsl:text> |
|
10239 <xsl:text> } |
|
10240 </xsl:text> |
|
10241 <xsl:text> |
|
10242 </xsl:text> |
|
10243 <xsl:text> every(callback) { |
|
10244 </xsl:text> |
|
10245 <xsl:text> for (const element of this) { |
|
10246 </xsl:text> |
|
10247 <xsl:text> if (!callback(element)) { |
|
10248 </xsl:text> |
|
10249 <xsl:text> return false; |
|
10250 </xsl:text> |
|
10251 <xsl:text> } |
|
10252 </xsl:text> |
|
10253 <xsl:text> } |
|
10254 </xsl:text> |
|
10255 <xsl:text> |
|
10256 </xsl:text> |
|
10257 <xsl:text> return true; |
|
10258 </xsl:text> |
|
10259 <xsl:text> } |
|
10260 </xsl:text> |
|
10261 <xsl:text> |
|
10262 </xsl:text> |
|
10263 <xsl:text> static fromIterable(iterable) { |
|
10264 </xsl:text> |
|
10265 <xsl:text> return new Iterator(function * () { |
|
10266 </xsl:text> |
|
10267 <xsl:text> for (const element of iterable) { |
|
10268 </xsl:text> |
|
10269 <xsl:text> yield element; |
|
10270 </xsl:text> |
|
10271 <xsl:text> } |
|
10272 </xsl:text> |
|
10273 <xsl:text> }); |
|
10274 </xsl:text> |
|
10275 <xsl:text> } |
|
10276 </xsl:text> |
|
10277 <xsl:text> |
|
10278 </xsl:text> |
|
10279 <xsl:text> toArray() { |
|
10280 </xsl:text> |
|
10281 <xsl:text> return Array.from(this); |
|
10282 </xsl:text> |
|
10283 <xsl:text> } |
|
10284 </xsl:text> |
|
10285 <xsl:text> |
|
10286 </xsl:text> |
|
10287 <xsl:text> next() { |
|
10288 </xsl:text> |
|
10289 <xsl:text> if (!this.currentInvokedGenerator) { |
|
10290 </xsl:text> |
|
10291 <xsl:text> this.currentInvokedGenerator = this[Symbol.iterator](); |
|
10292 </xsl:text> |
|
10293 <xsl:text> } |
|
10294 </xsl:text> |
|
10295 <xsl:text> |
|
10296 </xsl:text> |
|
10297 <xsl:text> return this.currentInvokedGenerator.next(); |
|
10298 </xsl:text> |
|
10299 <xsl:text> } |
|
10300 </xsl:text> |
|
10301 <xsl:text> |
|
10302 </xsl:text> |
|
10303 <xsl:text> reset() { |
|
10304 </xsl:text> |
|
10305 <xsl:text> delete this.currentInvokedGenerator; |
|
10306 </xsl:text> |
|
10307 <xsl:text> } |
|
10308 </xsl:text> |
|
10309 <xsl:text>} |
|
10310 </xsl:text> |
|
10311 <xsl:text> |
|
10312 </xsl:text> |
|
10313 <xsl:text>function rangeSimple(stop) { |
|
10314 </xsl:text> |
|
10315 <xsl:text> return new Iterator(function * () { |
|
10316 </xsl:text> |
|
10317 <xsl:text> for (let i = 0; i < stop; i++) { |
|
10318 </xsl:text> |
|
10319 <xsl:text> yield i; |
|
10320 </xsl:text> |
|
10321 <xsl:text> } |
|
10322 </xsl:text> |
|
10323 <xsl:text> }); |
|
10324 </xsl:text> |
|
10325 <xsl:text>} |
|
10326 </xsl:text> |
|
10327 <xsl:text> |
|
10328 </xsl:text> |
|
10329 <xsl:text>function rangeOverload(start, stop, step = 1) { |
|
10330 </xsl:text> |
|
10331 <xsl:text> return new Iterator(function * () { |
|
10332 </xsl:text> |
|
10333 <xsl:text> for (let i = start; i < stop; i += step) { |
|
10334 </xsl:text> |
|
10335 <xsl:text> yield i; |
|
10336 </xsl:text> |
|
10337 <xsl:text> } |
|
10338 </xsl:text> |
|
10339 <xsl:text> }); |
|
10340 </xsl:text> |
|
10341 <xsl:text>} |
|
10342 </xsl:text> |
|
10343 <xsl:text> |
|
10344 </xsl:text> |
|
10345 <xsl:text>function range(...args) { |
|
10346 </xsl:text> |
|
10347 <xsl:text> if (args.length < 2) { |
|
10348 </xsl:text> |
|
10349 <xsl:text> return rangeSimple(...args); |
|
10350 </xsl:text> |
|
10351 <xsl:text> } |
|
10352 </xsl:text> |
|
10353 <xsl:text> |
|
10354 </xsl:text> |
|
10355 <xsl:text> return rangeOverload(...args); |
|
10356 </xsl:text> |
|
10357 <xsl:text>} |
|
10358 </xsl:text> |
|
10359 <xsl:text> |
|
10360 </xsl:text> |
|
10361 <xsl:text>function enumerate(iterable) { |
|
10362 </xsl:text> |
|
10363 <xsl:text> return new Iterator(function * () { |
|
10364 </xsl:text> |
|
10365 <xsl:text> let index = 0; |
|
10366 </xsl:text> |
|
10367 <xsl:text> for (const element of iterable) { |
|
10368 </xsl:text> |
|
10369 <xsl:text> yield [index, element]; |
|
10370 </xsl:text> |
|
10371 <xsl:text> index++; |
|
10372 </xsl:text> |
|
10373 <xsl:text> } |
|
10374 </xsl:text> |
|
10375 <xsl:text> }); |
|
10376 </xsl:text> |
|
10377 <xsl:text>} |
|
10378 </xsl:text> |
|
10379 <xsl:text> |
|
10380 </xsl:text> |
|
10381 <xsl:text>const _zip = longest => (...iterables) => { |
|
10382 </xsl:text> |
|
10383 <xsl:text> if (iterables.length < 2) { |
|
10384 </xsl:text> |
|
10385 <xsl:text> throw new TypeError("zip takes 2 iterables at least, "+iterables.length+" given"); |
|
10386 </xsl:text> |
|
10387 <xsl:text> } |
|
10388 </xsl:text> |
|
10389 <xsl:text> |
|
10390 </xsl:text> |
|
10391 <xsl:text> return new Iterator(function * () { |
|
10392 </xsl:text> |
|
10393 <xsl:text> const iterators = iterables.map(iterable => Iterator.fromIterable(iterable)); |
|
10394 </xsl:text> |
|
10395 <xsl:text> while (true) { |
|
10396 </xsl:text> |
|
10397 <xsl:text> const row = iterators.map(iterator => iterator.next()); |
|
10398 </xsl:text> |
|
10399 <xsl:text> const check = longest ? row.every.bind(row) : row.some.bind(row); |
|
10400 </xsl:text> |
|
10401 <xsl:text> if (check(next => next.done)) { |
|
10402 </xsl:text> |
|
10403 <xsl:text> return; |
|
10404 </xsl:text> |
|
10405 <xsl:text> } |
|
10406 </xsl:text> |
|
10407 <xsl:text> |
|
10408 </xsl:text> |
|
10409 <xsl:text> yield row.map(next => next.value); |
|
10410 </xsl:text> |
|
10411 <xsl:text> } |
|
10412 </xsl:text> |
|
10413 <xsl:text> }); |
|
10414 </xsl:text> |
|
10415 <xsl:text>}; |
|
10416 </xsl:text> |
|
10417 <xsl:text> |
|
10418 </xsl:text> |
|
10419 <xsl:text>const zip = _zip(false), zipLongest= _zip(true); |
|
10420 </xsl:text> |
|
10421 <xsl:text> |
|
10422 </xsl:text> |
|
10423 <xsl:text>function items(obj) { |
|
10424 </xsl:text> |
|
10425 <xsl:text> let {keys, get} = obj; |
|
10426 </xsl:text> |
|
10427 <xsl:text> if (obj instanceof Map) { |
|
10428 </xsl:text> |
|
10429 <xsl:text> keys = keys.bind(obj); |
|
10430 </xsl:text> |
|
10431 <xsl:text> get = get.bind(obj); |
|
10432 </xsl:text> |
|
10433 <xsl:text> } else { |
|
10434 </xsl:text> |
|
10435 <xsl:text> keys = function () { |
|
10436 </xsl:text> |
|
10437 <xsl:text> return Object.keys(obj); |
|
10438 </xsl:text> |
|
10439 <xsl:text> }; |
|
10440 </xsl:text> |
|
10441 <xsl:text> |
|
10442 </xsl:text> |
|
10443 <xsl:text> get = function (key) { |
|
10444 </xsl:text> |
|
10445 <xsl:text> return obj[key]; |
|
10446 </xsl:text> |
|
10447 <xsl:text> }; |
|
10448 </xsl:text> |
|
10449 <xsl:text> } |
|
10450 </xsl:text> |
|
10451 <xsl:text> |
|
10452 </xsl:text> |
|
10453 <xsl:text> return new Iterator(function * () { |
|
10454 </xsl:text> |
|
10455 <xsl:text> for (const key of keys()) { |
|
10456 </xsl:text> |
|
10457 <xsl:text> yield [key, get(key)]; |
|
10458 </xsl:text> |
|
10459 <xsl:text> } |
|
10460 </xsl:text> |
|
10461 <xsl:text> }); |
|
10462 </xsl:text> |
|
10463 <xsl:text>} |
|
10464 </xsl:text> |
|
10465 <xsl:text> |
|
10466 </xsl:text> |
|
10467 <xsl:text>/* |
|
10468 </xsl:text> |
|
10469 <xsl:text>module.exports = {Iterator, range, enumerate, zip: _zip(false), zipLongest: _zip(true), items}; |
|
10470 </xsl:text> |
|
10471 <xsl:text>*/ |
|
10472 </xsl:text> |
|
10473 <xsl:text>// svghmi.js |
|
10474 </xsl:text> |
|
10475 <xsl:text> |
|
10476 </xsl:text> |
|
10477 <xsl:text>var need_cache_apply = []; |
|
10478 </xsl:text> |
|
10479 <xsl:text> |
|
10480 </xsl:text> |
|
10481 <xsl:text>function dispatch_value(index, value) { |
|
10482 </xsl:text> |
|
10483 <xsl:text> let widgets = subscribers(index); |
|
10484 </xsl:text> |
|
10485 <xsl:text> |
|
10486 </xsl:text> |
|
10487 <xsl:text> let oldval = cache[index]; |
|
10488 </xsl:text> |
|
10489 <xsl:text> cache[index] = value; |
|
10490 </xsl:text> |
|
10491 <xsl:text> |
|
10492 </xsl:text> |
|
10493 <xsl:text> if(widgets.size > 0) { |
|
10494 </xsl:text> |
|
10495 <xsl:text> for(let widget of widgets){ |
|
10496 </xsl:text> |
|
10497 <xsl:text> widget.new_hmi_value(index, value, oldval); |
|
10498 </xsl:text> |
|
10499 <xsl:text> } |
|
10500 </xsl:text> |
|
10501 <xsl:text> } |
|
10502 </xsl:text> |
|
10503 <xsl:text>}; |
|
10504 </xsl:text> |
|
10505 <xsl:text> |
|
10506 </xsl:text> |
|
10507 <xsl:text>function init_widgets() { |
|
10508 </xsl:text> |
|
10509 <xsl:text> Object.keys(hmi_widgets).forEach(function(id) { |
|
10510 </xsl:text> |
|
10511 <xsl:text> let widget = hmi_widgets[id]; |
|
10512 </xsl:text> |
|
10513 <xsl:text> widget.do_init(); |
|
10514 </xsl:text> |
|
10515 <xsl:text> }); |
|
10516 </xsl:text> |
|
10517 <xsl:text>}; |
|
10518 </xsl:text> |
|
10519 <xsl:text> |
|
10520 </xsl:text> |
|
10521 <xsl:text>// Open WebSocket to relative "/ws" address |
|
10522 </xsl:text> |
|
10523 <xsl:text>var has_watchdog = window.location.hash == "#watchdog"; |
|
10524 </xsl:text> |
|
10525 <xsl:text> |
|
10526 </xsl:text> |
|
10527 <xsl:text>var ws_url = |
|
10528 </xsl:text> |
|
10529 <xsl:text> window.location.href.replace(/^http(s?:\/\/[^\/]*)\/.*$/, 'ws$1/ws') |
|
10530 </xsl:text> |
|
10531 <xsl:text> + '?mode=' + (has_watchdog ? "watchdog" : "multiclient"); |
|
10532 </xsl:text> |
|
10533 <xsl:text> |
|
10534 </xsl:text> |
|
10535 <xsl:text>var ws = new WebSocket(ws_url); |
|
10536 </xsl:text> |
|
10537 <xsl:text>ws.binaryType = 'arraybuffer'; |
|
10538 </xsl:text> |
|
10539 <xsl:text> |
|
10540 </xsl:text> |
|
10541 <xsl:text>const dvgetters = { |
|
10542 </xsl:text> |
|
10543 <xsl:text> INT: (dv,offset) => [dv.getInt16(offset, true), 2], |
|
10544 </xsl:text> |
|
10545 <xsl:text> BOOL: (dv,offset) => [dv.getInt8(offset, true), 1], |
|
10546 </xsl:text> |
|
10547 <xsl:text> NODE: (dv,offset) => [dv.getInt8(offset, true), 1], |
|
10548 </xsl:text> |
|
10549 <xsl:text> REAL: (dv,offset) => [dv.getFloat32(offset, true), 4], |
|
10550 </xsl:text> |
|
10551 <xsl:text> STRING: (dv, offset) => { |
|
10552 </xsl:text> |
|
10553 <xsl:text> const size = dv.getInt8(offset); |
|
10554 </xsl:text> |
|
10555 <xsl:text> return [ |
|
10556 </xsl:text> |
|
10557 <xsl:text> String.fromCharCode.apply(null, new Uint8Array( |
|
10558 </xsl:text> |
|
10559 <xsl:text> dv.buffer, /* original buffer */ |
|
10560 </xsl:text> |
|
10561 <xsl:text> offset + 1, /* string starts after size*/ |
|
10562 </xsl:text> |
|
10563 <xsl:text> size /* size of string */ |
|
10564 </xsl:text> |
|
10565 <xsl:text> )), size + 1]; /* total increment */ |
|
10566 </xsl:text> |
|
10567 <xsl:text> } |
|
10568 </xsl:text> |
|
10569 <xsl:text>}; |
|
10570 </xsl:text> |
|
10571 <xsl:text> |
|
10572 </xsl:text> |
|
10573 <xsl:text>// Apply updates recieved through ws.onmessage to subscribed widgets |
|
10574 </xsl:text> |
|
10575 <xsl:text>function apply_updates() { |
|
10576 </xsl:text> |
|
10577 <xsl:text> updates.forEach((value, index) => { |
|
10578 </xsl:text> |
|
10579 <xsl:text> dispatch_value(index, value); |
|
10580 </xsl:text> |
|
10581 <xsl:text> }); |
|
10582 </xsl:text> |
|
10583 <xsl:text> updates.clear(); |
|
10584 </xsl:text> |
|
10585 <xsl:text>} |
|
10586 </xsl:text> |
|
10587 <xsl:text> |
|
10588 </xsl:text> |
|
10589 <xsl:text>// Called on requestAnimationFrame, modifies DOM |
|
10590 </xsl:text> |
|
10591 <xsl:text>var requestAnimationFrameID = null; |
|
10592 </xsl:text> |
|
10593 <xsl:text>function animate() { |
|
10594 </xsl:text> |
|
10595 <xsl:text> let rearm = true; |
|
10596 </xsl:text> |
|
10597 <xsl:text> do{ |
|
10598 </xsl:text> |
|
10599 <xsl:text> if(page_fading == "pending" || page_fading == "forced"){ |
|
10600 </xsl:text> |
|
10601 <xsl:text> if(page_fading == "pending") |
|
10602 </xsl:text> |
|
10603 <xsl:text> svg_root.classList.add("fade-out-page"); |
|
10604 </xsl:text> |
|
10605 <xsl:text> page_fading = "in_progress"; |
|
10606 </xsl:text> |
|
10607 <xsl:text> if(page_fading_args.length) |
|
10608 </xsl:text> |
|
10609 <xsl:text> setTimeout(function(){ |
|
10610 </xsl:text> |
|
10611 <xsl:text> switch_page(...page_fading_args); |
|
10612 </xsl:text> |
|
10613 <xsl:text> },1); |
|
10614 </xsl:text> |
|
10615 <xsl:text> break; |
|
10616 </xsl:text> |
|
10617 <xsl:text> } |
|
10618 </xsl:text> |
|
10619 <xsl:text> |
|
10620 </xsl:text> |
|
10621 <xsl:text> // Do the page swith if pending |
|
10622 </xsl:text> |
|
10623 <xsl:text> if(page_switch_in_progress){ |
|
10624 </xsl:text> |
|
10625 <xsl:text> if(current_subscribed_page != current_visible_page){ |
|
10626 </xsl:text> |
|
10627 <xsl:text> switch_visible_page(current_subscribed_page); |
|
10628 </xsl:text> |
|
10629 <xsl:text> } |
|
10630 </xsl:text> |
|
10631 <xsl:text> |
|
10632 </xsl:text> |
|
10633 <xsl:text> page_switch_in_progress = false; |
|
10634 </xsl:text> |
|
10635 <xsl:text> |
|
10636 </xsl:text> |
|
10637 <xsl:text> if(page_fading == "in_progress"){ |
|
10638 </xsl:text> |
|
10639 <xsl:text> svg_root.classList.remove("fade-out-page"); |
|
10640 </xsl:text> |
|
10641 <xsl:text> page_fading = "off"; |
|
10642 </xsl:text> |
|
10643 <xsl:text> } |
|
10644 </xsl:text> |
|
10645 <xsl:text> } |
|
10646 </xsl:text> |
|
10647 <xsl:text> |
|
10648 </xsl:text> |
|
10649 <xsl:text> while(widget = need_cache_apply.pop()){ |
|
10650 </xsl:text> |
|
10651 <xsl:text> widget.apply_cache(); |
|
10652 </xsl:text> |
|
10653 <xsl:text> } |
|
10654 </xsl:text> |
|
10655 <xsl:text> |
|
10656 </xsl:text> |
|
10657 <xsl:text> if(jumps_need_update) update_jumps(); |
|
10658 </xsl:text> |
|
10659 <xsl:text> |
|
10660 </xsl:text> |
|
10661 <xsl:text> apply_updates(); |
|
10662 </xsl:text> |
|
10663 <xsl:text> |
|
10664 </xsl:text> |
|
10665 <xsl:text> pending_widget_animates.forEach(widget => widget._animate()); |
|
10666 </xsl:text> |
|
10667 <xsl:text> pending_widget_animates = []; |
|
10668 </xsl:text> |
|
10669 <xsl:text> rearm = false; |
|
10670 </xsl:text> |
|
10671 <xsl:text> } while(0); |
|
10672 </xsl:text> |
|
10673 <xsl:text> |
|
10674 </xsl:text> |
|
10675 <xsl:text> requestAnimationFrameID = null; |
|
10676 </xsl:text> |
|
10677 <xsl:text> |
|
10678 </xsl:text> |
|
10679 <xsl:text> if(rearm) requestHMIAnimation(); |
|
10680 </xsl:text> |
|
10681 <xsl:text>} |
|
10682 </xsl:text> |
|
10683 <xsl:text> |
|
10684 </xsl:text> |
|
10685 <xsl:text>function requestHMIAnimation() { |
|
10686 </xsl:text> |
|
10687 <xsl:text> if(requestAnimationFrameID == null){ |
|
10688 </xsl:text> |
|
10689 <xsl:text> requestAnimationFrameID = window.requestAnimationFrame(animate); |
|
10690 </xsl:text> |
|
10691 <xsl:text> } |
|
10692 </xsl:text> |
|
10693 <xsl:text>} |
|
10694 </xsl:text> |
|
10695 <xsl:text> |
|
10696 </xsl:text> |
|
10697 <xsl:text>// Message reception handler |
|
10698 </xsl:text> |
|
10699 <xsl:text>// Hash is verified and HMI values updates resulting from binary parsing |
|
10700 </xsl:text> |
|
10701 <xsl:text>// are stored until browser can compute next frame, DOM is left untouched |
|
10702 </xsl:text> |
|
10703 <xsl:text>ws.onmessage = function (evt) { |
|
10704 </xsl:text> |
|
10705 <xsl:text> |
|
10706 </xsl:text> |
|
10707 <xsl:text> let data = evt.data; |
|
10708 </xsl:text> |
|
10709 <xsl:text> let dv = new DataView(data); |
|
10710 </xsl:text> |
|
10711 <xsl:text> let i = 0; |
|
10712 </xsl:text> |
|
10713 <xsl:text> try { |
|
10714 </xsl:text> |
|
10715 <xsl:text> for(let hash_int of hmi_hash) { |
|
10716 </xsl:text> |
|
10717 <xsl:text> if(hash_int != dv.getUint8(i)){ |
|
10718 </xsl:text> |
|
10719 <xsl:text> throw new Error("Hash doesn't match"); |
|
10720 </xsl:text> |
|
10721 <xsl:text> }; |
|
10722 </xsl:text> |
|
10723 <xsl:text> i++; |
|
10724 </xsl:text> |
|
10725 <xsl:text> }; |
|
10726 </xsl:text> |
|
10727 <xsl:text> |
|
10728 </xsl:text> |
|
10729 <xsl:text> while(i < data.byteLength){ |
|
10730 </xsl:text> |
|
10731 <xsl:text> let index = dv.getUint32(i, true); |
|
10732 </xsl:text> |
|
10733 <xsl:text> i += 4; |
|
10734 </xsl:text> |
|
10735 <xsl:text> let iectype = hmitree_types[index]; |
|
10736 </xsl:text> |
|
10737 <xsl:text> if(iectype != undefined){ |
|
10738 </xsl:text> |
|
10739 <xsl:text> let dvgetter = dvgetters[iectype]; |
|
10740 </xsl:text> |
|
10741 <xsl:text> let [value, bytesize] = dvgetter(dv,i); |
|
10742 </xsl:text> |
|
10743 <xsl:text> updates.set(index, value); |
|
10744 </xsl:text> |
|
10745 <xsl:text> i += bytesize; |
|
10746 </xsl:text> |
|
10747 <xsl:text> } else { |
|
10748 </xsl:text> |
|
10749 <xsl:text> throw new Error("Unknown index "+index); |
|
10750 </xsl:text> |
|
10751 <xsl:text> } |
|
10752 </xsl:text> |
|
10753 <xsl:text> }; |
|
10754 </xsl:text> |
|
10755 <xsl:text> // register for rendering on next frame, since there are updates |
|
10756 </xsl:text> |
|
10757 <xsl:text> requestHMIAnimation(); |
|
10758 </xsl:text> |
|
10759 <xsl:text> } catch(err) { |
|
10760 </xsl:text> |
|
10761 <xsl:text> // 1003 is for "Unsupported Data" |
|
10762 </xsl:text> |
|
10763 <xsl:text> // ws.close(1003, err.message); |
|
10764 </xsl:text> |
|
10765 <xsl:text> |
|
10766 </xsl:text> |
|
10767 <xsl:text> // TODO : remove debug alert ? |
|
10768 </xsl:text> |
|
10769 <xsl:text> alert("Error : "+err.message+"\nHMI will be reloaded."); |
|
10770 </xsl:text> |
|
10771 <xsl:text> |
|
10772 </xsl:text> |
|
10773 <xsl:text> // force reload ignoring cache |
|
10774 </xsl:text> |
|
10775 <xsl:text> location.reload(true); |
|
10776 </xsl:text> |
|
10777 <xsl:text> } |
|
10778 </xsl:text> |
|
10779 <xsl:text>}; |
|
10780 </xsl:text> |
|
10781 <xsl:text> |
|
10782 </xsl:text> |
|
10783 <xsl:text>hmi_hash_u8 = new Uint8Array(hmi_hash); |
|
10784 </xsl:text> |
|
10785 <xsl:text> |
|
10786 </xsl:text> |
|
10787 <xsl:text>function send_blob(data) { |
|
10788 </xsl:text> |
|
10789 <xsl:text> if(data.length > 0) { |
|
10790 </xsl:text> |
|
10791 <xsl:text> ws.send(new Blob([hmi_hash_u8].concat(data))); |
|
10792 </xsl:text> |
|
10793 <xsl:text> }; |
|
10794 </xsl:text> |
|
10795 <xsl:text>}; |
|
10796 </xsl:text> |
|
10797 <xsl:text> |
|
10798 </xsl:text> |
|
10799 <xsl:text>const typedarray_types = { |
|
10800 </xsl:text> |
|
10801 <xsl:text> INT: (number) => new Int16Array([number]), |
|
10802 </xsl:text> |
|
10803 <xsl:text> BOOL: (truth) => new Int16Array([truth]), |
|
10804 </xsl:text> |
|
10805 <xsl:text> NODE: (truth) => new Int16Array([truth]), |
|
10806 </xsl:text> |
|
10807 <xsl:text> REAL: (number) => new Float32Array([number]), |
|
10808 </xsl:text> |
|
10809 <xsl:text> STRING: (str) => { |
|
10810 </xsl:text> |
|
10811 <xsl:text> // beremiz default string max size is 128 |
|
10812 </xsl:text> |
|
10813 <xsl:text> str = str.slice(0,128); |
|
10814 </xsl:text> |
|
10815 <xsl:text> binary = new Uint8Array(str.length + 1); |
|
10816 </xsl:text> |
|
10817 <xsl:text> binary[0] = str.length; |
|
10818 </xsl:text> |
|
10819 <xsl:text> for(let i = 0; i < str.length; i++){ |
|
10820 </xsl:text> |
|
10821 <xsl:text> binary[i+1] = str.charCodeAt(i); |
|
10822 </xsl:text> |
|
10823 <xsl:text> } |
|
10824 </xsl:text> |
|
10825 <xsl:text> return binary; |
|
10826 </xsl:text> |
|
10827 <xsl:text> } |
|
10828 </xsl:text> |
|
10829 <xsl:text> /* TODO */ |
|
10830 </xsl:text> |
|
10831 <xsl:text>}; |
|
10832 </xsl:text> |
|
10833 <xsl:text> |
|
10834 </xsl:text> |
|
10835 <xsl:text>function send_reset() { |
|
10836 </xsl:text> |
|
10837 <xsl:text> send_blob(new Uint8Array([1])); /* reset = 1 */ |
|
10838 </xsl:text> |
|
10839 <xsl:text>}; |
|
10840 </xsl:text> |
|
10841 <xsl:text> |
|
10842 </xsl:text> |
|
10843 <xsl:text>var subscriptions = []; |
|
10844 </xsl:text> |
|
10845 <xsl:text> |
|
10846 </xsl:text> |
|
10847 <xsl:text>function subscribers(index) { |
|
10848 </xsl:text> |
|
10849 <xsl:text> let entry = subscriptions[index]; |
|
10850 </xsl:text> |
|
10851 <xsl:text> let res; |
|
10852 </xsl:text> |
|
10853 <xsl:text> if(entry == undefined){ |
|
10854 </xsl:text> |
|
10855 <xsl:text> res = new Set(); |
|
10856 </xsl:text> |
|
10857 <xsl:text> subscriptions[index] = [res,0]; |
|
10858 </xsl:text> |
|
10859 <xsl:text> }else{ |
|
10860 </xsl:text> |
|
10861 <xsl:text> [res, _ign] = entry; |
|
10862 </xsl:text> |
|
10863 <xsl:text> } |
|
10864 </xsl:text> |
|
10865 <xsl:text> return res |
|
10866 </xsl:text> |
|
10867 <xsl:text>} |
|
10868 </xsl:text> |
|
10869 <xsl:text> |
|
10870 </xsl:text> |
|
10871 <xsl:text>function get_subscription_period(index) { |
|
10872 </xsl:text> |
|
10873 <xsl:text> let entry = subscriptions[index]; |
|
10874 </xsl:text> |
|
10875 <xsl:text> if(entry == undefined) |
|
10876 </xsl:text> |
|
10877 <xsl:text> return 0; |
|
10878 </xsl:text> |
|
10879 <xsl:text> let [_ign, period] = entry; |
|
10880 </xsl:text> |
|
10881 <xsl:text> return period; |
|
10882 </xsl:text> |
|
10883 <xsl:text>} |
|
10884 </xsl:text> |
|
10885 <xsl:text> |
|
10886 </xsl:text> |
|
10887 <xsl:text>function set_subscription_period(index, period) { |
|
10888 </xsl:text> |
|
10889 <xsl:text> let entry = subscriptions[index]; |
|
10890 </xsl:text> |
|
10891 <xsl:text> if(entry == undefined){ |
|
10892 </xsl:text> |
|
10893 <xsl:text> subscriptions[index] = [new Set(), period]; |
|
10894 </xsl:text> |
|
10895 <xsl:text> } else { |
|
10896 </xsl:text> |
|
10897 <xsl:text> entry[1] = period; |
|
10898 </xsl:text> |
|
10899 <xsl:text> } |
|
10900 </xsl:text> |
|
10901 <xsl:text>} |
|
10902 </xsl:text> |
|
10903 <xsl:text> |
|
10904 </xsl:text> |
|
10905 <xsl:text>if(has_watchdog){ |
|
10906 </xsl:text> |
|
10907 <xsl:text> // artificially subscribe the watchdog widget to "/heartbeat" hmi variable |
|
10908 </xsl:text> |
|
10909 <xsl:text> // Since dispatch directly calls change_hmi_value, |
|
10910 </xsl:text> |
|
10911 <xsl:text> // PLC will periodically send variable at given frequency |
|
10912 </xsl:text> |
|
10913 <xsl:text> subscribers(heartbeat_index).add({ |
|
10914 </xsl:text> |
|
10915 <xsl:text> /* type: "Watchdog", */ |
|
10916 </xsl:text> |
|
10917 <xsl:text> frequency: 1, |
|
10918 </xsl:text> |
|
10919 <xsl:text> indexes: [heartbeat_index], |
|
10920 </xsl:text> |
|
10921 <xsl:text> new_hmi_value: function(index, value, oldval) { |
|
10922 </xsl:text> |
|
10923 <xsl:text> apply_hmi_value(heartbeat_index, value+1); |
|
10924 </xsl:text> |
|
10925 <xsl:text> } |
|
10926 </xsl:text> |
|
10927 <xsl:text> }); |
|
10928 </xsl:text> |
|
10929 <xsl:text>} |
|
10930 </xsl:text> |
|
10931 <xsl:text> |
|
10932 </xsl:text> |
|
10933 <xsl:text> |
|
10934 </xsl:text> |
|
10935 <xsl:text>var page_fading = "off"; |
|
10936 </xsl:text> |
|
10937 <xsl:text>var page_fading_args = "off"; |
|
10938 </xsl:text> |
|
10939 <xsl:text>function fading_page_switch(...args){ |
|
10940 </xsl:text> |
|
10941 <xsl:text> if(page_fading == "in_progress") |
|
10942 </xsl:text> |
|
10943 <xsl:text> page_fading = "forced"; |
|
10944 </xsl:text> |
|
10945 <xsl:text> else |
|
10946 </xsl:text> |
|
10947 <xsl:text> page_fading = "pending"; |
|
10948 </xsl:text> |
|
10949 <xsl:text> page_fading_args = args; |
|
10950 </xsl:text> |
|
10951 <xsl:text> |
|
10952 </xsl:text> |
|
10953 <xsl:text> requestHMIAnimation(); |
|
10954 </xsl:text> |
|
10955 <xsl:text> |
|
10956 </xsl:text> |
|
10957 <xsl:text>} |
|
10958 </xsl:text> |
|
10959 <xsl:text>document.body.style.backgroundColor = "black"; |
|
10960 </xsl:text> |
|
10961 <xsl:text> |
|
10962 </xsl:text> |
|
10963 <xsl:text>// subscribe to per instance current page hmi variable |
|
10964 </xsl:text> |
|
10965 <xsl:text>// PLC must prefix page name with "!" for page switch to happen |
|
10966 </xsl:text> |
|
10967 <xsl:text>subscribers(current_page_var_index).add({ |
|
10968 </xsl:text> |
|
10969 <xsl:text> frequency: 1, |
|
10970 </xsl:text> |
|
10971 <xsl:text> indexes: [current_page_var_index], |
|
10972 </xsl:text> |
|
10973 <xsl:text> new_hmi_value: function(index, value, oldval) { |
|
10974 </xsl:text> |
|
10975 <xsl:text> if(value.startsWith("!")) |
|
10976 </xsl:text> |
|
10977 <xsl:text> fading_page_switch(value.slice(1)); |
|
10978 </xsl:text> |
|
10979 <xsl:text> } |
|
10980 </xsl:text> |
|
10981 <xsl:text>}); |
|
10982 </xsl:text> |
|
10983 <xsl:text> |
|
10984 </xsl:text> |
|
10985 <xsl:text>function svg_text_to_multiline(elt) { |
|
10986 </xsl:text> |
|
10987 <xsl:text> return(Array.prototype.map.call(elt.children, x=>x.textContent).join("\n")); |
|
10988 </xsl:text> |
|
10989 <xsl:text>} |
|
10990 </xsl:text> |
|
10991 <xsl:text> |
|
10992 </xsl:text> |
|
10993 <xsl:text>function multiline_to_svg_text(elt, str, blank) { |
|
10994 </xsl:text> |
|
10995 <xsl:text> str.split('\n').map((line,i) => {elt.children[i].textContent = blank?"":line;}); |
|
10996 </xsl:text> |
|
10997 <xsl:text>} |
|
10998 </xsl:text> |
|
10999 <xsl:text> |
|
11000 </xsl:text> |
|
11001 <xsl:text>function switch_langnum(langnum) { |
|
11002 </xsl:text> |
|
11003 <xsl:text> langnum = Math.max(0, Math.min(langs.length - 1, langnum)); |
|
11004 </xsl:text> |
|
11005 <xsl:text> |
|
11006 </xsl:text> |
|
11007 <xsl:text> for (let translation of translations) { |
|
11008 </xsl:text> |
|
11009 <xsl:text> let [objs, msgs] = translation; |
|
11010 </xsl:text> |
|
11011 <xsl:text> let msg = msgs[langnum]; |
|
11012 </xsl:text> |
|
11013 <xsl:text> for (let obj of objs) { |
|
11014 </xsl:text> |
|
11015 <xsl:text> multiline_to_svg_text(obj, msg); |
|
11016 </xsl:text> |
|
11017 <xsl:text> obj.setAttribute("lang",langnum); |
|
11018 </xsl:text> |
|
11019 <xsl:text> } |
|
11020 </xsl:text> |
|
11021 <xsl:text> } |
|
11022 </xsl:text> |
|
11023 <xsl:text> return langnum; |
|
11024 </xsl:text> |
|
11025 <xsl:text>} |
|
11026 </xsl:text> |
|
11027 <xsl:text> |
|
11028 </xsl:text> |
|
11029 <xsl:text>// backup original texts |
|
11030 </xsl:text> |
|
11031 <xsl:text>for (let translation of translations) { |
|
11032 </xsl:text> |
|
11033 <xsl:text> let [objs, msgs] = translation; |
|
11034 </xsl:text> |
|
11035 <xsl:text> msgs.unshift(svg_text_to_multiline(objs[0])); |
|
11036 </xsl:text> |
|
11037 <xsl:text>} |
|
11038 </xsl:text> |
|
11039 <xsl:text> |
|
11040 </xsl:text> |
|
11041 <xsl:text>var lang_local_index = hmi_local_index("lang"); |
|
11042 </xsl:text> |
|
11043 <xsl:text>var langcode_local_index = hmi_local_index("lang_code"); |
|
11044 </xsl:text> |
|
11045 <xsl:text>var langname_local_index = hmi_local_index("lang_name"); |
|
11046 </xsl:text> |
|
11047 <xsl:text>subscribers(lang_local_index).add({ |
|
11048 </xsl:text> |
|
11049 <xsl:text> indexes: [lang_local_index], |
|
11050 </xsl:text> |
|
11051 <xsl:text> new_hmi_value: function(index, value, oldval) { |
|
11052 </xsl:text> |
|
11053 <xsl:text> let current_lang = switch_langnum(value); |
|
11054 </xsl:text> |
|
11055 <xsl:text> let [langname,langcode] = langs[current_lang]; |
|
11056 </xsl:text> |
|
11057 <xsl:text> apply_hmi_value(langcode_local_index, langcode); |
|
11058 </xsl:text> |
|
11059 <xsl:text> apply_hmi_value(langname_local_index, langname); |
|
11060 </xsl:text> |
|
11061 <xsl:text> switch_page(); |
|
11062 </xsl:text> |
|
11063 <xsl:text> } |
|
11064 </xsl:text> |
|
11065 <xsl:text>}); |
|
11066 </xsl:text> |
|
11067 <xsl:text> |
|
11068 </xsl:text> |
|
11069 <xsl:text>// returns en_US, fr_FR or en_UK depending on selected language |
|
11070 </xsl:text> |
|
11071 <xsl:text>function get_current_lang_code(){ |
|
11072 </xsl:text> |
|
11073 <xsl:text> return cache[langcode_local_index]; |
|
11074 </xsl:text> |
|
11075 <xsl:text>} |
|
11076 </xsl:text> |
|
11077 <xsl:text> |
|
11078 </xsl:text> |
|
11079 <xsl:text>function setup_lang(){ |
|
11080 </xsl:text> |
|
11081 <xsl:text> let current_lang = cache[lang_local_index]; |
|
11082 </xsl:text> |
|
11083 <xsl:text> let new_lang = switch_langnum(current_lang); |
|
11084 </xsl:text> |
|
11085 <xsl:text> if(current_lang != new_lang){ |
|
11086 </xsl:text> |
|
11087 <xsl:text> apply_hmi_value(lang_local_index, new_lang); |
|
11088 </xsl:text> |
|
11089 <xsl:text> } |
|
11090 </xsl:text> |
|
11091 <xsl:text>} |
|
11092 </xsl:text> |
|
11093 <xsl:text> |
|
11094 </xsl:text> |
|
11095 <xsl:text>setup_lang(); |
|
11096 </xsl:text> |
|
11097 <xsl:text> |
|
11098 </xsl:text> |
|
11099 <xsl:text>function update_subscriptions() { |
|
11100 </xsl:text> |
|
11101 <xsl:text> let delta = []; |
|
11102 </xsl:text> |
|
11103 <xsl:text> for(let index in subscriptions){ |
|
11104 </xsl:text> |
|
11105 <xsl:text> let widgets = subscribers(index); |
|
11106 </xsl:text> |
|
11107 <xsl:text> |
|
11108 </xsl:text> |
|
11109 <xsl:text> // periods are in ms |
|
11110 </xsl:text> |
|
11111 <xsl:text> let previous_period = get_subscription_period(index); |
|
11112 </xsl:text> |
|
11113 <xsl:text> |
|
11114 </xsl:text> |
|
11115 <xsl:text> // subscribing with a zero period is unsubscribing |
|
11116 </xsl:text> |
|
11117 <xsl:text> let new_period = 0; |
|
11118 </xsl:text> |
|
11119 <xsl:text> if(widgets.size > 0) { |
|
11120 </xsl:text> |
|
11121 <xsl:text> let maxfreq = 0; |
|
11122 </xsl:text> |
|
11123 <xsl:text> for(let widget of widgets){ |
|
11124 </xsl:text> |
|
11125 <xsl:text> let wf = widget.frequency; |
|
11126 </xsl:text> |
|
11127 <xsl:text> if(wf != undefined && maxfreq < wf) |
|
11128 </xsl:text> |
|
11129 <xsl:text> maxfreq = wf; |
|
11130 </xsl:text> |
|
11131 <xsl:text> } |
|
11132 </xsl:text> |
|
11133 <xsl:text> |
|
11134 </xsl:text> |
|
11135 <xsl:text> if(maxfreq != 0) |
|
11136 </xsl:text> |
|
11137 <xsl:text> new_period = 1000/maxfreq; |
|
11138 </xsl:text> |
|
11139 <xsl:text> } |
|
11140 </xsl:text> |
|
11141 <xsl:text> |
|
11142 </xsl:text> |
|
11143 <xsl:text> if(previous_period != new_period) { |
|
11144 </xsl:text> |
|
11145 <xsl:text> set_subscription_period(index, new_period); |
|
11146 </xsl:text> |
|
11147 <xsl:text> if(index <= last_remote_index){ |
|
11148 </xsl:text> |
|
11149 <xsl:text> delta.push( |
|
11150 </xsl:text> |
|
11151 <xsl:text> new Uint8Array([2]), /* subscribe = 2 */ |
|
11152 </xsl:text> |
|
11153 <xsl:text> new Uint32Array([index]), |
|
11154 </xsl:text> |
|
11155 <xsl:text> new Uint16Array([new_period])); |
|
11156 </xsl:text> |
|
11157 <xsl:text> } |
|
11158 </xsl:text> |
|
11159 <xsl:text> } |
|
11160 </xsl:text> |
|
11161 <xsl:text> } |
|
11162 </xsl:text> |
|
11163 <xsl:text> send_blob(delta); |
|
11164 </xsl:text> |
|
11165 <xsl:text>}; |
|
11166 </xsl:text> |
|
11167 <xsl:text> |
|
11168 </xsl:text> |
|
11169 <xsl:text>function send_hmi_value(index, value) { |
|
11170 </xsl:text> |
|
11171 <xsl:text> if(index > last_remote_index){ |
|
11172 </xsl:text> |
|
11173 <xsl:text> updates.set(index, value); |
|
11174 </xsl:text> |
|
11175 <xsl:text> |
|
11176 </xsl:text> |
|
11177 <xsl:text> if(persistent_indexes.has(index)){ |
|
11178 </xsl:text> |
|
11179 <xsl:text> let varname = persistent_indexes.get(index); |
|
11180 </xsl:text> |
|
11181 <xsl:text> document.cookie = varname+"="+value+"; max-age=3153600000"; |
|
11182 </xsl:text> |
|
11183 <xsl:text> } |
|
11184 </xsl:text> |
|
11185 <xsl:text> |
|
11186 </xsl:text> |
|
11187 <xsl:text> requestHMIAnimation(); |
|
11188 </xsl:text> |
11699 </xsl:text> |
11189 <xsl:text> return; |
11700 <xsl:text> return; |
11190 </xsl:text> |
11701 </xsl:text> |
11191 <xsl:text> } |
11702 <xsl:text> } |
11192 </xsl:text> |
11703 </xsl:text> |