1- import $ from "jquery" ;
21import parser from "./depends_parse" ;
32
4- function DependsHandler ( $el , expression ) {
5- var $context = $el . closest ( "form" ) ;
6- if ( ! $context . length ) $context = $ ( document ) ;
7- this . $el = $el ;
8- this . $context = $context ;
9- this . ast = parser . parse ( expression ) ; // TODO: handle parse exceptions here
10- }
3+ class DependsHandler {
4+ constructor ( el , expression ) {
5+ this . el = el ;
6+ this . context = el . closest ( "form" ) || document ;
7+ this . ast = parser . parse ( expression ) ; // TODO: handle parse exceptions here
8+ }
119
12- DependsHandler . prototype = {
13- _findInputs : function ( name ) {
14- var $input = this . $context . find ( ":input[name='" + name + "']" ) ;
15- if ( ! $input . length ) $input = $ ( "#" + name ) ;
16- return $input ;
17- } ,
10+ _findInputs ( name ) {
11+ // In case of radio buttons, there might be multiple inputs.
12+ // "name" in parentheses, because it can be any value. Common is:
13+ // `somename:list` for a radio input list.
14+ let inputs = this . context . querySelectorAll ( `
15+ input[name="${ name } "],
16+ select[name="${ name } "],
17+ textarea[name="${ name } "],
18+ button[name="${ name } "]
19+ ` ) ;
20+ if ( ! inputs . length ) {
21+ // This should really only find one instance.
22+ inputs = document . querySelectorAll ( `#${ name } ` ) ;
23+ }
24+ return inputs ;
25+ }
1826
19- _getValue : function ( name ) {
20- var $input = this . _findInputs ( name ) ;
21- if ( ! $input . length ) return null ;
27+ _getValue ( name ) {
28+ let inputs = this . _findInputs ( name ) ;
2229
23- if ( $input . attr ( "type" ) === "radio" || $input . attr ( "type" ) === "checkbox" )
24- return $input . filter ( ":checked" ) . val ( ) || null ;
25- else return $input . val ( ) ;
26- } ,
30+ inputs = [ ...inputs ] . filter ( ( input ) => {
31+ if ( input . type === "radio" && input . checked === false ) {
32+ return false ;
33+ }
34+ if ( input . type === "checkbox" && input . checked === false ) {
35+ return false ;
36+ }
37+ if ( input . disabled ) {
38+ return false ;
39+ }
40+ return true ;
41+ } ) ;
2742
28- getAllInputs : function ( ) {
29- var todo = [ this . ast ] ,
30- $inputs = $ ( ) ,
31- node ;
43+ if ( inputs . length === 0 ) {
44+ return null ;
45+ }
46+
47+ return inputs [ 0 ] . value ;
48+ }
49+
50+ getAllInputs ( ) {
51+ const todo = [ this . ast ] ;
52+ const all_inputs = new Set ( ) ;
3253
3354 while ( todo . length ) {
34- node = todo . shift ( ) ;
35- if ( node . input ) $inputs = $inputs . add ( this . _findInputs ( node . input ) ) ;
36- if ( node . children && node . children . length )
55+ const node = todo . shift ( ) ;
56+ if ( node . input ) {
57+ const inputs = this . _findInputs ( node . input ) ;
58+ for ( const input of inputs ) {
59+ all_inputs . add ( input ) ;
60+ }
61+ }
62+ if ( node . children && node . children . length ) {
3763 todo . push . apply ( todo , node . children ) ;
64+ }
3865 }
39- return $inputs ;
40- } ,
66+ return [ ... all_inputs ] ;
67+ }
4168
42- _evaluate : function ( node ) {
43- var value = node . input ? this . _getValue ( node . input ) : null ,
44- i ;
69+ _evaluate ( node ) {
70+ const value = node . input ? this . _getValue ( node . input ) : null ;
4571
4672 switch ( node . type ) {
4773 case "NOT" :
4874 return ! this . _evaluate ( node . children [ 0 ] ) ;
49- case "AND" :
50- for ( i = 0 ; i < node . children . length ; i ++ )
51- if ( ! this . _evaluate ( node . children [ i ] ) ) return false ;
52- return true ;
53- case "OR" :
54- for ( i = 0 ; i < node . children . length ; i ++ )
55- if ( this . _evaluate ( node . children [ i ] ) ) return true ;
56- return false ;
75+ case "AND" : {
76+ // As soon as one child evaluates to false, the AND expression is false.
77+ const is_false = node . children . some ( ( child ) => ! this . _evaluate ( child ) ) ;
78+ return ! is_false ;
79+ }
80+ case "OR" : {
81+ // As soon as one child evaluates to true, the OR expression is true.
82+ const is_true = node . children . some ( ( child ) => this . _evaluate ( child ) ) ;
83+ return is_true ;
84+ }
5785 case "comparison" :
5886 switch ( node . operator ) {
5987 case "=" :
@@ -69,21 +97,25 @@ DependsHandler.prototype = {
6997 case ">=" :
7098 return value >= node . value ;
7199 case "~=" :
72- if ( value === null ) return false ;
100+ if ( value === null ) {
101+ return false ;
102+ }
73103 return value . indexOf ( node . value ) != - 1 ;
74104 case "=~" :
75- if ( value === null || ! node . value ) return false ;
105+ if ( value === null || ! node . value ) {
106+ return false ;
107+ }
76108 return node . value . indexOf ( value ) != - 1 ;
77109 }
78110 break ;
79111 case "truthy" :
80112 return ! ! value ;
81113 }
82- } ,
114+ }
83115
84- evaluate : function ( ) {
116+ evaluate ( ) {
85117 return this . _evaluate ( this . ast ) ;
86- } ,
87- } ;
118+ }
119+ }
88120
89121export default DependsHandler ;
0 commit comments