11'use strict' ;
2- function $ ( selector ) {
3- return document . querySelector ( selector ) ;
4- }
5- function $$ ( selector ) {
6- return document . querySelectorAll ( selector ) ;
2+
3+ function _eval ( e ) {
4+ return eval ( e ) ;
75}
6+ // _eval won't access local variables
87
9- $ ( '#expr' ) . addEventListener ( 'keydown' , function ( e ) {
10- if ( e . keyCode === 32 ) {
11- e . preventDefault ( ) ;
8+ ( function ( ) {
9+ function $ ( selector ) {
10+ return document . querySelector ( selector ) ;
1211 }
13- } ) ;
14- $ ( '#expr' ) . addEventListener ( 'focus' , function ( ) {
15- $ ( '#expr' ) . placeholder = '' ;
16- } ) ;
17- $ ( '#expr' ) . addEventListener ( 'input' , function ( ) {
18- var oldValue = $ ( '#expr' ) . value ;
19- var expr = $ ( '#expr' ) . value . replace ( / \s / g, '' ) ;
20- if ( oldValue !== expr ) {
21- $ ( '#expr' ) . value = expr ;
12+ function $$ ( selector ) {
13+ return document . querySelectorAll ( selector ) ;
2214 }
2315
24- var rules = $$ ( '#rules li' ) ;
25- for ( var i = 0 , l = rules . length ; i < l ; i ++ ) {
26- rules [ i ] . className = '' ;
27- }
28- switch ( expr . toLowerCase ( ) ) {
29- case '' :
30- $ ( '#result' ) . innerHTML = '' ;
31- return ;
32- case 's' :
33- $ ( '#result' ) . innerHTML = '~ is useful' ;
34- return ;
35- case 'sk' :
36- $ ( '#result' ) . innerHTML = 'x<<y is x*2<sup>y</sup>' ;
37- return ;
38- case 'ski' :
39- $ ( '#result' ) . innerHTML = 'try & | ^' ;
40- return ;
41- case 'skip' :
42- localStorage . total = + localStorage . total + 1 ;
43- refresh ( ) ;
44- $ ( '#stats' ) . className = 'hover' ;
45- setTimeout ( function ( ) {
46- $ ( '#stats' ) . className = '' ;
47- } , 1500 ) ;
48- $ ( '#result' ) . innerHTML = '' ;
49- return ;
50- default :
51- try {
52- var result = eval ( $ ( '#expr' ) . value ) ;
53- if ( result === null ) {
54- $ ( '#result' ) . innerHTML = 'null' ;
55- } else {
56- $ ( '#result' ) . innerHTML = result ;
16+ $ ( '#expr' ) . addEventListener ( 'keydown' , function ( e ) {
17+ if ( e . keyCode === 32 ) {
18+ e . preventDefault ( ) ;
19+ }
20+ } ) ;
21+ $ ( '#expr' ) . addEventListener ( 'focus' , function ( ) {
22+ $ ( '#expr' ) . placeholder = '' ;
23+ } ) ;
24+ $ ( '#expr' ) . addEventListener ( 'input' , function ( ) {
25+ var oldValue = $ ( '#expr' ) . value ;
26+ var expr = $ ( '#expr' ) . value . replace ( / \s / g, '' ) ;
27+ if ( oldValue !== expr ) {
28+ $ ( '#expr' ) . value = expr ;
29+ }
30+
31+ var rules = $$ ( '#rules li' ) ;
32+ for ( var i = 0 , l = rules . length ; i < l ; i ++ ) {
33+ rules [ i ] . className = '' ;
34+ }
35+ switch ( expr . toLowerCase ( ) ) {
36+ case '' :
37+ $ ( '#result' ) . innerHTML = '' ;
38+ return ;
39+ case 's' :
40+ $ ( '#result' ) . innerHTML = '~ is useful' ;
41+ return ;
42+ case 'sk' :
43+ $ ( '#result' ) . innerHTML = 'x<<y is x*2<sup>y</sup>' ;
44+ return ;
45+ case 'ski' :
46+ $ ( '#result' ) . innerHTML = 'try & | ^' ;
47+ return ;
48+ case 'skip' :
49+ localStorage . total = + localStorage . total + 1 ;
50+ refresh ( ) ;
51+ $ ( '#stats' ) . className = 'hover' ;
52+ setTimeout ( function ( ) {
53+ $ ( '#stats' ) . className = '' ;
54+ } , 1500 ) ;
55+ $ ( '#result' ) . innerHTML = '' ;
56+ return ;
57+ default :
58+ try {
59+ var result = _eval ( $ ( '#expr' ) . value ) ;
60+ if ( result === null ) {
61+ $ ( '#result' ) . innerHTML = 'null' ;
62+ } else {
63+ $ ( '#result' ) . innerHTML = result ;
64+ }
65+ check ( result ) ;
66+ } catch ( e ) {
67+ $ ( '#result' ) . innerHTML = expr ;
68+ rules [ 0 ] . className = 'bad' ;
5769 }
58- check ( result ) ;
59- } catch ( e ) {
60- $ ( '#result' ) . innerHTML = expr ;
61- rules [ 0 ] . className = 'bad' ;
70+ }
71+ } ) ;
72+ function check ( result ) {
73+ var rules = $$ ( '#rules li' ) ;
74+ var expr = $ ( '#expr' ) . value ;
75+ var e = expr . replace ( / ( \d | \) ) - / g, / $ 1 / ) . replace ( / & & | \| \| / g, '#' ) . replace ( / > > | < < | [ + * \/ % ~ ^ & | ( ) ] / g, '' ) . replace ( / 0 x / ig, '0' ) . replace ( / 0 o / ig, '0' ) ;
76+ var digitsAppeared = 0 ;
77+ for ( var i = 0 ; i < 4 ; i ++ ) {
78+ if ( e . match ( localStorage . digits [ i ] ) ) {
79+ e = e . replace ( localStorage . digits [ i ] , '' ) ;
80+ digitsAppeared += 1 ;
6281 }
63- }
64- } ) ;
65- function check ( result ) {
66- var rules = $$ ( '#rules li' ) ;
67- var expr = $ ( '#expr' ) . value ;
68- var e = expr . replace ( / ( \d | \) ) - / g, / $ 1 / ) . replace ( / & & | \| \| / g, '#' ) . replace ( / > > | < < | [ + * \/ % ~ ^ & | ( ) ] / g, '' ) . replace ( / 0 x / ig, '0' ) . replace ( / 0 o / ig, '0' ) ;
69- var digitsAppeared = 0 ;
70- for ( var i = 0 ; i < 4 ; i ++ ) {
71- if ( e . match ( localStorage . digits [ i ] ) ) {
72- e = e . replace ( localStorage . digits [ i ] , '' ) ;
73- digitsAppeared += 1 ;
82+ }
83+ var valid = true ;
84+ if ( result !== 24 ) {
85+ rules [ 1 ] . className = 'bad' ;
86+ valid = false ;
87+ }
88+ if ( digitsAppeared !== 4 || e . match ( / \d / ) ) {
89+ rules [ 2 ] . className = 'bad' ;
90+ e = e . replace ( / \d / g, '' ) ;
91+ valid = false ;
92+ }
93+ if ( e . match ( / - / ) ) {
94+ rules [ 4 ] . className = 'bad' ;
95+ e = e . replace ( / - / g, '' ) ;
96+ valid = false ;
97+ }
98+ if ( e ) {
99+ rules [ 3 ] . className = 'bad' ;
100+ valid = false ;
101+ }
102+ if ( valid ) {
103+ success ( ) ;
74104 }
75105 }
76- var valid = true ;
77- if ( result !== 24 ) {
78- rules [ 1 ] . className = 'bad' ;
79- valid = false ;
80- }
81- if ( digitsAppeared !== 4 || e . match ( / \d / ) ) {
82- rules [ 2 ] . className = 'bad' ;
83- e = e . replace ( / \d / g, '' ) ;
84- valid = false ;
85- }
86- if ( e . match ( / - / ) ) {
87- rules [ 4 ] . className = 'bad' ;
88- e = e . replace ( / - / g, '' ) ;
89- valid = false ;
90- }
91- if ( e ) {
92- rules [ 3 ] . className = 'bad' ;
93- valid = false ;
106+ function success ( ) {
107+ localStorage . averageLength = ( localStorage . averageLength * localStorage . won + $ ( '#expr' ) . value . length ) / ( + localStorage . won + 1 ) ;
108+ localStorage . won = + localStorage . won + 1 ;
109+ localStorage . total = + localStorage . total + 1 ;
110+
111+ $ ( '#result' ) . className = 'animate' ;
112+ $ ( '#solution' ) . className = 'animate' ;
113+ $ ( '#solution' ) . innerHTML = ' = ' + $ ( '#expr' ) . value ;
114+ $ ( '#expr' ) . setAttribute ( 'disabled' , '' ) ;
115+ setTimeout ( function ( ) {
116+ showStats ( ) ;
117+ $ ( '#stats' ) . className = 'hover' ;
118+ } , 250 ) ;
119+ setTimeout ( function ( ) {
120+ $ ( '#stats' ) . className = '' ;
121+ } , 1750 ) ;
122+ setTimeout ( function ( ) {
123+ $ ( '#result' ) . className = '' ;
124+ $ ( '#result' ) . innerHTML = '' ;
125+ refresh ( ) ;
126+ } , 2250 ) ;
127+ setTimeout ( function ( ) {
128+ $ ( '#solution' ) . className = '' ;
129+ $ ( '#solution' ) . innerHTML = '' ;
130+ } , 2500 ) ;
94131 }
95- if ( valid ) {
96- success ( ) ;
132+ function refresh ( ) {
133+ localStorage . digits = ( Math . random ( ) + '' ) . substr ( 2 , 4 ) ;
134+ show ( ) ;
135+
136+ $ ( '#expr' ) . value = '' ;
137+ $ ( '#expr' ) . removeAttribute ( 'disabled' ) ;
138+ $ ( '#expr' ) . focus ( ) ;
97139 }
98- }
99- function success ( ) {
100- localStorage . averageLength = ( localStorage . averageLength * localStorage . won + $ ( '#expr' ) . value . length ) / ( + localStorage . won + 1 ) ;
101- localStorage . won = + localStorage . won + 1 ;
102- localStorage . total = + localStorage . total + 1 ;
140+ function show ( ) {
141+ var digits = $$ ( '#digits li' ) ;
142+ for ( var i = 0 ; i < 4 ; i ++ ) {
143+ var digit = document . createElement ( 'div' ) ;
144+ digit . className = 'style-' + Math . floor ( Math . random ( ) * 4 ) ;
145+ digit . innerHTML = localStorage . digits [ i ] ;
146+ digits [ i ] . className = 'animation-' + Math . floor ( Math . random ( ) * 6 ) ;
147+ digits [ i ] . appendChild ( digit ) ;
148+ }
149+ setTimeout ( removeOldDigits , 1250 ) ;
103150
104- $ ( '#result' ) . className = 'animate' ;
105- $ ( '#solution' ) . className = 'animate' ;
106- $ ( '#solution' ) . innerHTML = ' = ' + $ ( '#expr' ) . value ;
107- $ ( '#expr' ) . setAttribute ( 'disabled' , '' ) ;
108- setTimeout ( function ( ) {
109151 showStats ( ) ;
110- $ ( '#stats' ) . className = 'hover' ;
111- } , 250 ) ;
112- setTimeout ( function ( ) {
113- $ ( '#stats' ) . className = '' ;
114- } , 1750 ) ;
115- setTimeout ( function ( ) {
116- $ ( '#result' ) . className = '' ;
117- $ ( '#result' ) . innerHTML = '' ;
118- refresh ( ) ;
119- } , 2250 ) ;
120- setTimeout ( function ( ) {
121- $ ( '#solution' ) . className = '' ;
122- $ ( '#solution' ) . innerHTML = '' ;
123- } , 2500 ) ;
124- }
125- function refresh ( ) {
126- localStorage . digits = ( Math . random ( ) + '' ) . substr ( 2 , 4 ) ;
127- show ( ) ;
128-
129- $ ( '#expr' ) . value = '' ;
130- $ ( '#expr' ) . removeAttribute ( 'disabled' ) ;
131- $ ( '#expr' ) . focus ( ) ;
132- }
133- function show ( ) {
134- var digits = $$ ( '#digits li' ) ;
135- for ( var i = 0 ; i < 4 ; i ++ ) {
136- var digit = document . createElement ( 'div' ) ;
137- digit . className = 'style-' + Math . floor ( Math . random ( ) * 4 ) ;
138- digit . innerHTML = localStorage . digits [ i ] ;
139- digits [ i ] . className = 'animation-' + Math . floor ( Math . random ( ) * 6 ) ;
140- digits [ i ] . appendChild ( digit ) ;
141152 }
142- setTimeout ( removeOldDigits , 1250 ) ;
143-
144- showStats ( ) ;
145- }
146- function showStats ( ) {
147- $ ( '#won' ) . innerHTML = localStorage . won ;
148- $ ( '#total' ) . innerHTML = localStorage . total ;
149- $ ( '#average-length' ) . innerHTML = localStorage . averageLength . substr ( 0 , 4 ) ;
150- }
151- function removeOldDigits ( ) {
152- var digits = $$ ( '#digits li' ) ;
153- for ( var i = 0 ; i < 4 ; i ++ ) {
154- while ( digits [ i ] . children . length > 1 ) {
155- digits [ i ] . removeChild ( digits [ i ] . children [ 0 ] ) ;
153+ function showStats ( ) {
154+ $ ( '#won' ) . innerHTML = localStorage . won ;
155+ $ ( '#total' ) . innerHTML = localStorage . total ;
156+ $ ( '#average-length' ) . innerHTML = localStorage . averageLength . substr ( 0 , 4 ) ;
157+ }
158+ function removeOldDigits ( ) {
159+ var digits = $$ ( '#digits li' ) ;
160+ for ( var i = 0 ; i < 4 ; i ++ ) {
161+ while ( digits [ i ] . children . length > 1 ) {
162+ digits [ i ] . removeChild ( digits [ i ] . children [ 0 ] ) ;
163+ }
156164 }
157165 }
158- }
159- function resize ( ) {
160- parent . postMessage ( {
161- height : document . body . clientHeight ,
162- } , '*' ) ;
163- }
164- function init ( ) {
165- localStorage . won = localStorage . won || 0 ;
166- localStorage . total = localStorage . total || 0 ;
167- localStorage . averageLength = localStorage . averageLength || 0 ;
168- localStorage . digits = localStorage . digits || ( Math . random ( ) + '' ) . substr ( 2 , 4 ) ;
169- if ( parent !== window ) {
170- window . addEventListener ( 'resize' , resize ) ;
171- resize ( ) ;
166+ function resize ( ) {
167+ parent . postMessage ( {
168+ height : document . body . clientHeight ,
169+ } , '*' ) ;
170+ }
171+ function init ( ) {
172+ localStorage . won = localStorage . won || 0 ;
173+ localStorage . total = localStorage . total || 0 ;
174+ localStorage . averageLength = localStorage . averageLength || 0 ;
175+ localStorage . digits = localStorage . digits || ( Math . random ( ) + '' ) . substr ( 2 , 4 ) ;
176+ if ( parent !== window ) {
177+ window . addEventListener ( 'resize' , resize ) ;
178+ resize ( ) ;
179+ }
180+ show ( ) ;
181+ setInterval ( function ( ) {
182+ $ ( '#expr' ) . placeholder = document . activeElement === $ ( '#expr' ) || $ ( '#expr' ) . placeholder ?
183+ '' : '█' ;
184+ } , 500 ) ;
172185 }
173- show ( ) ;
174- setInterval ( function ( ) {
175- $ ( '#expr' ) . placeholder = document . activeElement === $ ( '#expr' ) || $ ( '#expr' ) . placeholder ?
176- '' : '█' ;
177- } , 500 ) ;
178- }
179186
180- if ( typeof localStorage === 'object' ) {
181- /* global Storage:false */
182- try {
183- localStorage . setItem ( 'localStorage' , 1 ) ;
184- localStorage . removeItem ( 'localStorage' ) ;
185- } catch ( e ) {
186- Storage . prototype . _setItem = Storage . prototype . setItem ;
187- Storage . prototype . setItem = function ( ) { } ;
188- alert ( 'Your web browser does not support storing settings locally. In Safari, the most common cause of this is using "Private Browsing Mode". Some settings may not save or some features may not work properly for you.' ) ;
187+ if ( typeof localStorage === 'object' ) {
188+ /* global Storage:false */
189+ try {
190+ localStorage . setItem ( 'localStorage' , 1 ) ;
191+ localStorage . removeItem ( 'localStorage' ) ;
192+ } catch ( e ) {
193+ Storage . prototype . _setItem = Storage . prototype . setItem ;
194+ Storage . prototype . setItem = function ( ) { } ;
195+ alert ( 'Your web browser does not support storing settings locally. In Safari, the most common cause of this is using "Private Browsing Mode". Some settings may not save or some features may not work properly for you.' ) ;
196+ }
189197 }
190- }
191- init ( ) ;
198+ init ( ) ;
199+ } ) ( ) ;
0 commit comments