Passed
Push — master ( d286b7...24e4a5 )
by Jan
04:36
created

assets/js/jquery.tristate.js   B

Complexity

Total Complexity 45
Complexity/F 2.81

Size

Lines of Code 196
Function Count 16

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 124
c 0
b 0
f 0
dl 0
loc 196
rs 8.8
wmc 45
mnd 29
bc 29
fnc 16
bpm 1.8125
cpm 2.8125
noi 11

How to fix   Complexity   

Complexity

Complex classes like assets/js/jquery.tristate.js often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/*jslint devel: true, bitwise: true, regexp: true, browser: true, confusion: true, unparam: true, eqeq: true, white: true, nomen: true, plusplus: true, maxerr: 50, indent: 4 */
2
/*globals jQuery */
3
4
/*!
5
 * Tristate v1.2.1
6
 *
7
 * Copyright (c) 2013-2017 Martijn W. van der Lee
8
 * Licensed under the MIT.
9
 */
10
/* Based on work by:
11
 *  Chris Coyier (http://css-tricks.com/indeterminate-checkboxes/)
12
 *
13
 * Tristate checkbox with support features
14
 * pseudo selectors
15
 * val() overwrite
16
 */
17
18
;(function($, undefined) {   
19
	'use strict';
20
	
21
	var pluginName = 'tristate',
22
		defaults = {
23
			'change':			undefined,
24
			'checked':			undefined,
25
			'indeterminate':	undefined,
26
			'init':				undefined,
27
			'reverse':			false,
28
			'state':			undefined,
29
			'unchecked':		undefined,
30
			'value':			undefined	// one-way only!
31
		},
32
		valFunction	= $.fn.val;
33
34
    function Plugin(element, options) {
35
        if($(element).is(':checkbox')) {        
36
            this.element = $(element);
37
            this.settings = $.extend( {}, defaults, options );
38
            this._create();
39
        }
40
    }
41
42
    $.extend(Plugin.prototype, {
43
		_create: function() {					
44
			var that = this,
45
				state;
46
47
			// Fix for #1
48
			if (window.navigator.userAgent.indexOf('Trident') >= 0) {
49
				this.element.click(function(e) {
50
					that._change.call(that, e);			
51
					that.element.closest('form').change();
52
				});
53
			} else {
54
				this.element.change(function(e) {
55
					that._change.call(that, e);
56
				});
57
			}
58
59
			this.settings.checked		= this.element.attr('checkedvalue')		  || this.settings.checked;
60
			this.settings.unchecked		= this.element.attr('uncheckedvalue')	  || this.settings.unchecked;
61
			this.settings.indeterminate	= this.element.attr('indeterminatevalue') || this.settings.indeterminate;
62
63
			// Initially, set state based on option state or attributes
64
			if (typeof this.settings.state === 'undefined') {
65
				this.settings.state		= typeof this.element.attr('indeterminate') !== 'undefined'? null : this.element.is(':checked');
66
			}
67
68
			// If value specified, overwrite with value
69
			if (typeof this.settings.value !== 'undefined') {
70
				state = this._parseValue(this.settings.value);
71
				if (typeof state !== 'undefined') {
72
					this.settings.state = state;
73
				}
74
			}
75
76
			this._refresh(this.settings.init);
77
78
			return this;
79
		},
80
81
		_change: function(e) {
82
			if (e.isTrigger || !e.hasOwnProperty('which')) {
83
				e.preventDefault();
84
			}
85
			
86
			switch (this.settings.state) {
87
				case true:  this.settings.state = (this.settings.reverse ? false : null); break;
88
				case false: this.settings.state = (this.settings.reverse ? null : true); break;
89
				default:    this.settings.state = (this.settings.reverse ? true : false); break;
90
			}
91
92
			this._refresh(this.settings.change);								
93
		},
94
		
95
		_refresh: function(callback) {
96
			var value	= this.value();
97
98
			this.element.data("vanderlee." + pluginName, value);
99
100
			this.element[this.settings.state === null ? 'attr' : 'removeAttr']('indeterminate', 'indeterminate');
101
			this.element.prop('indeterminate', this.settings.state === null);
102
			this.element.get(0).indeterminate = this.settings.state === null;
103
104
			this.element[this.settings.state === true ? 'attr' : 'removeAttr']('checked', true);
105
			this.element.prop('checked', this.settings.state === true);
106
107
			if ($.isFunction(callback)) {
108
				callback.call(this.element, this.settings.state, this.value());
109
			}
110
		},
111
112
		state: function(value) {
113
			if (typeof value === 'undefined') {
114
				return this.settings.state;
115
			} else if (value === true || value === false || value === null) {
116
				this.settings.state = value;
117
118
				this._refresh(this.settings.change);
119
			}
120
			return this;
121
		},
122
123
		_parseValue: function(value) {
124
			if (value === this.settings.checked) {
125
				return true;
126
			} else if (value === this.settings.unchecked) {
127
				return false;
128
			} else if (value === this.settings.indeterminate) {
129
				return null;
130
			}
131
		},
132
133
		value: function(value) {
134
			if (typeof value === 'undefined') {
135
				var value;
136
				switch (this.settings.state) {
137
					case true:
138
						value = this.settings.checked;
139
						break;
140
141
					case false:
142
						value = this.settings.unchecked;
143
						break;
144
145
					case null:
146
						value = this.settings.indeterminate;
147
						break;
148
				}
149
				return typeof value === 'undefined'? this.element.attr('value') : value;
150
			} else {
151
				var state = this._parseValue(value);
152
				if (typeof state !== 'undefined') {
153
					this.settings.state = state;
154
					this._refresh(this.settings.change);
155
				}
156
			}
157
		}		
158
	});
159
160
	$.fn[pluginName] = function (options, value) {	
161
		var result = this;
162
		
163
		this.each(function() {
164
            if (!$.data(this, "plugin.vanderlee." + pluginName)) {
165
                $.data(this, "plugin.vanderlee." + pluginName, new Plugin(this, options));
166
            } else if (typeof options === 'string') {
167
				if (typeof value === 'undefined') {
168
					result = $(this).data("plugin.vanderlee." + pluginName)[options]();
169
					return false;
170
				} else {
171
					$(this).data("plugin.vanderlee." + pluginName)[options](value);
172
				}
173
			}
174
        });
175
176
		return result;
177
	};
178
	
179
	// Overwrite fn.val
180
    $.fn.val = function(value) {
181
        var data = this.data("vanderlee." + pluginName);
182
        if (typeof data === 'undefined') {
183
	        if (typeof value === 'undefined') {
184
	            return valFunction.call(this);
185
			} else {
186
				return valFunction.call(this, value);
187
			}
188
		} else {
189
	        if (typeof value === 'undefined') {
190
				return data;
191
			} else {
192
				this.data("vanderlee." + pluginName, value);
193
				return this;
194
			}
195
		}
196
    };
197
198
	// :indeterminate pseudo selector
199
    $.expr.filters.indeterminate = function(element) {
200
		var $element = $(element);
201
		return typeof $element.data("vanderlee." + pluginName) !== 'undefined' && $element.prop('indeterminate');
202
    };
203
204
	// :determinate pseudo selector
205
    $.expr.filters.determinate = function(element) {
206
		return !($.expr.filters.indeterminate(element));
207
    };
208
209
	// :tristate selector
210
    $.expr.filters.tristate = function(element) {
211
		return typeof $(element).data("vanderlee." + pluginName) !== 'undefined';
212
    };
213
})(jQuery);
214