Completed
Push — master ( 598cbd...912844 )
by wiese
432:38 queued 367:30
created

SelectComponent.elementAndContentAreEmpty   A

Complexity

Conditions 1
Paths 2

Size

Total Lines 5

Duplication

Lines 5
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 5
loc 5
rs 9.4285
cc 1
nc 2
nop 1
1 View Code Duplication
'use strict';
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
2
3
var objectAssign = require( 'object-assign' ),
4
	_ = require( 'underscore' ),
5
	actions = require( './actions' ),
6
	NumericInputHandler = require( './numeric_input_handler' ),
7
8
	/**
9
	 * Wrapper around underscore debounce function with a delay of 300 milliseconds
10
	 *
11
	 * @param {function} f
12
	 * @param {Number} milliseconds
13
	 * @return {Function}
14
	 */
15
	defaultDebounce = function ( f, milliseconds ) {
16
		return _.debounce( f, milliseconds || 300 );
17
	},
18
19
	createDefaultChangeHandler = function ( store, contentName ) {
20
		return function ( evt ) {
21
			store.dispatch( actions.newChangeContentAction( contentName, evt.target.value ) );
22
		};
23
	},
24
25
	createRegexValidator = function ( store, contentName ) {
26
		return function ( evt ) {
27
			store.dispatch( actions.newValidateInputAction(
28
				contentName,
29
				evt.target.value,
30
				evt.target.getAttribute( 'data-pattern' )
31
			) );
32
		};
33
	},
34
35
	createNoEmptyStringValidator = function ( store, contentName ) {
36
		return function ( evt ) {
37
			store.dispatch( actions.newValidateInputAction(
38
				contentName,
39
				evt.target.value
40
			) );
41
		};
42
	},
43
44
	RadioComponent = {
45
		element: null,
46
		contentName: '',
47
		onChange: null,
48
		render: function ( formContent ) {
49
			this.element.val( [ formContent[ this.contentName ] ] ); // Needs to be an array
50
		}
51
	},
52
53
	SelectComponent = {
54
		element: null,
55
		contentName: '',
56
		onChange: null,
57
		render: function ( formContent ) {
58
59
			if ( this.element.val() === formContent[ this.contentName ]  || this.elementAndContentAreEmpty( formContent ) ) {
60
				return;
61
			}
62
63
			this.element.val( [ formContent[ this.contentName ] ] );
64
			this.element.change();
65
		},
66
		elementAndContentAreEmpty: function( formContent ) {
67
			// calling this.element.val( '' ) leads to this.element.val() === null in some cases,
68
			// so we need to compare different types
69
			return this.element.val() === null && formContent[ this.contentName ] === '';
70
		}
71
	},
72
73
	CheckboxComponent = {
74
		element: null,
75
		contentName: '',
76
		onChange: null,
77
		render: function ( formContent ) {
78
			this.element.prop( 'checked', !!formContent[ this.contentName ] ); // !! converts to boolean
79
		}
80
	},
81
82
	TextComponent = {
83
		element: null,
84
		contentName: '',
85
		onChange: null,
86
		validator: null,
87
		render: function ( formContent ) {
88
			if ( this.element.val() !== formContent[ this.contentName ] ) {
89
				// Avoid changing value while element is edited by the user
90
				if ( !this.element.is( ':focus' ) ) {
91
					this.element.val( formContent[ this.contentName ] );
92
					this.element.change();
93
				}
94
			}
95
		}
96
	},
97
98
	AmountComponent = {
99
		inputElement: null,
100
		selectElement: null,
101
		hiddenElement: null,
102
		numberFormatter: null,
103
		render: function ( formContent ) {
104
			this.hiddenElement.val( this.numberFormatter.format( formContent.amount ) );
105
			if ( formContent.isCustomAmount ) {
106
				this.inputElement.parent().addClass( 'filled' );
107
				this.selectElement.prop( 'checked', false );
108
				this.inputElement.val( this.numberFormatter.format( formContent.amount ) );
109
			} else {
110
				this.inputElement.parent().removeClass( 'filled' );
111
				this.selectElement.val( [ String( formContent.amount ) ] );
112
				this.inputElement.val( '' );
113
			}
114
		}
115
	},
116
117
	BankDataComponent = {
118
		ibanElement: null,
119
		bicElement: null,
120
		accountNumberElement: null,
121
		bankCodeElement: null,
122
		bankNameFieldElement: null,
123
		bankNameDisplayElement: null,
124
		render: function ( formContent ) {
125
			this.ibanElement.val( formContent.iban );
126
			this.bicElement.val( formContent.bic );
127
			this.accountNumberElement.val( formContent.accountNumber );
128
			this.bankCodeElement.val( formContent.bankCode );
129
			this.bankNameFieldElement.val( formContent.bankName );
130
			this.bankNameDisplayElement.text( formContent.bankName );
131
		}
132
	};
133
134
module.exports = {
135
136
	createRadioComponent: function ( store, element, contentName ) {
137
		var component = objectAssign( Object.create( RadioComponent ), {
138
			element: element,
139
			contentName: contentName,
140
			onChange: createDefaultChangeHandler( store, contentName )
141
		} );
142
		element.on( 'change', component.onChange );
143
		return component;
144
	},
145
146
	createSelectMenuComponent: function ( store, element, contentName ) {
147
		var component = objectAssign( Object.create( SelectComponent ), {
148
			element: element,
149
			contentName: contentName,
150
			onChange: createDefaultChangeHandler( store, contentName )
151
		} );
152
		element.on( 'selectmenuchange, change', component.onChange );
153
		return component;
154
	},
155
156
	createCheckboxComponent: function ( store, element, contentName ) {
157
		var component = objectAssign( Object.create( CheckboxComponent ), {
158
			element: element,
159
			contentName: contentName,
160
			onChange: function () {
161
				store.dispatch( actions.newChangeContentAction( contentName, !!element.prop( 'checked' ) ) );
162
			}
163
		} );
164
		element.on( 'change', component.onChange );
165
		return component;
166
	},
167
168
	createValidatingCheckboxComponent: function ( store, element, contentName ) {
169
		var component = objectAssign( this.createCheckboxComponent( store, element, contentName ), {
170
			validator: createNoEmptyStringValidator( store, contentName )
171
		} );
172
		element.on( 'change', component.validator );
173
		return component;
174
	},
175
176
	createTextComponent: function ( store, element, contentName ) {
177
		var component = objectAssign( Object.create( TextComponent ), {
178
			element: element,
179
			contentName: contentName,
180
			onChange: createDefaultChangeHandler( store, contentName )
181
		} );
182
		element.on( 'change', component.onChange );
183
		return component;
184
	},
185
186
	createValidatingTextComponent: function ( store, element, contentName ) {
187
		var component = objectAssign( this.createTextComponent( store, element, contentName ), {
188
			validator: createRegexValidator( store, contentName )
189
		} );
190
		element.on( 'change', component.validator );
191
		return component;
192
	},
193
194
	/**
195
	 * @param store
196
	 * @param {jQuery} inputElement
197
	 * @param {jQuery} selectElement
198
	 * @param {jQuery} hiddenElement
199
	 * @param {CurrencyParser} numberParser
200
	 * @param {CurrencyFormatter} numberFormatter
201
	 * @return {AmountComponent}
202
	 */
203
	createAmountComponent: function ( store, inputElement, selectElement, hiddenElement, numberParser, numberFormatter ) {
204
		var component = objectAssign( Object.create( AmountComponent ), {
205
			inputElement: inputElement,
206
			selectElement: selectElement,
207
			hiddenElement: hiddenElement,
208
			numberFormatter: numberFormatter
209
		} );
210
		NumericInputHandler.createNumericInputHandler( inputElement, numberParser.getDecimalDelimiter() );
211
		inputElement.on( 'change', function ( evt ) {
212
			var amount;
213
			try {
214
				amount = numberParser.parse( evt.target.value );
215
			} catch ( e ) {
216
				amount = 0;
217
				inputElement.val( '0' );
218
			}
219
			store.dispatch( actions.newInputAmountAction( amount ) );
220
		} );
221
		selectElement.on( 'change', function ( evt ) {
222
			store.dispatch( actions.newSelectAmountAction( evt.target.value ) );
223
		} );
224
		return component;
225
	},
226
227
	createBankDataComponent: function ( store, bankDataElements ) {
228
		var component = objectAssign( Object.create( BankDataComponent ), bankDataElements );
229
		bankDataElements.ibanElement.on( 'change', createDefaultChangeHandler( store, 'iban' ) );
230
		bankDataElements.bicElement.on( 'change', createDefaultChangeHandler( store, 'bic' ) );
231
		bankDataElements.bicElement.on( 'change', createRegexValidator( store, 'bic' ) );
232
		bankDataElements.accountNumberElement.on( 'change', createDefaultChangeHandler( store, 'accountNumber' ) );
233
		bankDataElements.bankCodeElement.on( 'change', createDefaultChangeHandler( store, 'bankCode' ) );
234
		return component;
235
	},
236
237
	addEagerChangeBehavior: function( textComponent, debouncingFunction ) {
238
		debouncingFunction = debouncingFunction || defaultDebounce;
239
		textComponent.element.on( 'keypress', debouncingFunction( function ( evt ) {
240
			textComponent.onChange( evt );
241
			if ( textComponent.validator ) {
242
				textComponent.validator( evt );
243
			}
244
		} ) );
245
		return textComponent;
246
	},
247
248
	SelectComponent: SelectComponent
249
};
250