1+ /*!
2+ * jQuery QueryBuilder Invert
3+ * Allows to invert a rule operator, a group condition or the entire builder.
4+ * Copyright 2014-2015 Damien "Mistic" Sorel (http://www.strangeplanet.fr)
5+ */
6+
7+ QueryBuilder . defaults ( {
8+ operatorOpposites : {
9+ 'equal' : 'not_equal' ,
10+ 'not_equal' : 'equal' ,
11+ 'in' : 'not_in' ,
12+ 'not_in' : 'in' ,
13+ 'less' : 'greater_or_equal' ,
14+ 'less_or_equal' : 'greater' ,
15+ 'greater' : 'less_or_equal' ,
16+ 'greater_or_equal' : 'less' ,
17+ 'between' : 'not_between' ,
18+ 'not_between' : 'between' ,
19+ 'begins_with' : 'not_begins_with' ,
20+ 'not_begins_with' : 'begins_with' ,
21+ 'contains' : 'not_contains' ,
22+ 'not_contains' : 'contains' ,
23+ 'ends_with' : 'not_ends_with' ,
24+ 'not_ends_with' : 'ends_with' ,
25+ 'is_empty' : 'is_not_empty' ,
26+ 'is_not_empty' : 'is_empty' ,
27+ 'is_null' : 'is_not_null' ,
28+ 'is_not_null' : 'is_null'
29+ } ,
30+
31+ conditionOpposites : {
32+ 'AND' : 'OR' ,
33+ 'OR' : 'AND'
34+ }
35+ } ) ;
36+
37+ QueryBuilder . define ( 'invert' , function ( options ) {
38+ var that = this ;
39+
40+ /**
41+ * Bind events
42+ */
43+ this . on ( 'afterInit' , function ( ) {
44+ that . $el . on ( 'click.queryBuilder' , '[data-invert=group]' , function ( ) {
45+ var $group = $ ( this ) . closest ( '.rules-group-container' ) ;
46+ that . invert ( Model ( $group ) , options . recursive , options . invert_rules ) ;
47+ } ) ;
48+
49+ if ( options . display_rules_button && options . invert_rules ) {
50+ that . $el . on ( 'click.queryBuilder' , '[data-invert=rule]' , function ( ) {
51+ var $rule = $ ( this ) . closest ( '.rule-container' ) ;
52+ that . invert ( Model ( $rule ) ) ;
53+ } ) ;
54+ }
55+ } ) ;
56+
57+ /**
58+ * Modify templates
59+ */
60+ this . on ( 'getGroupTemplate.filter' , function ( h , level ) {
61+ var $h = $ ( h . value ) ;
62+ $h . find ( '.group-conditions' ) . after ( '<button type="button" class="btn btn-xs btn-default" data-invert="group"><i class="' + options . icon + '"></i> ' + that . lang . invert + '</button>' ) ;
63+ h . value = $h . prop ( 'outerHTML' ) ;
64+ } ) ;
65+
66+ if ( options . display_rules_button && options . invert_rules ) {
67+ this . on ( 'getRuleTemplate.filter' , function ( h ) {
68+ var $h = $ ( h . value ) ;
69+ $h . find ( '.rule-actions' ) . prepend ( '<button type="button" class="btn btn-xs btn-default" data-invert="rule"><i class="' + options . icon + '"></i> ' + that . lang . invert + '</button>' ) ;
70+ h . value = $h . prop ( 'outerHTML' ) ;
71+ } ) ;
72+ }
73+ } , {
74+ icon : 'glyphicon glyphicon-random' ,
75+ recursive : true ,
76+ invert_rules : true ,
77+ display_rules_button : false
78+ } ) ;
79+
80+ QueryBuilder . extend ( {
81+ invert : function ( node , recursive , invert_rules ) {
82+ if ( typeof node != 'object' ) {
83+ if ( this . model . root ) {
84+ this . invert ( this . model . root , node , recursive ) ;
85+ }
86+ }
87+ else if ( node instanceof Group ) {
88+ if ( this . settings . conditionOpposites [ node . condition ] ) {
89+ node . condition = this . settings . conditionOpposites [ node . condition ] ;
90+ }
91+ else {
92+ error ( 'Unknown inverse of condition "{0}"' , node . condition ) ;
93+ }
94+
95+ if ( recursive === true || recursive === undefined ) {
96+ node . each ( function ( rule ) {
97+ if ( invert_rules === true || invert_rules === undefined ) {
98+ this . invert ( rule ) ;
99+ }
100+ } , function ( group ) {
101+ this . invert ( group , true ) ;
102+ } , this ) ;
103+ }
104+ }
105+ else if ( node instanceof Rule ) {
106+ if ( node . operator ) {
107+ if ( this . settings . operatorOpposites [ node . operator . type ] ) {
108+ node . operator = this . getOperatorByType ( this . settings . operatorOpposites [ node . operator . type ] ) ;
109+ }
110+ else {
111+ error ( 'Unknown inverse of operator "{0}"' , node . operator . type ) ;
112+ }
113+ }
114+ }
115+ }
116+ } ) ;
0 commit comments