[TASK] Remove breakOnError option from wizard
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Resources / Public / JavaScript / Wizard / Viewport / Left / Options / Forms / Validation / Rule.js
1 Ext.namespace('TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation');
2
3 /**
4 * The validation rules abstract
5 *
6 * @class TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule
7 * @extends Ext.FormPanel
8 */
9 TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule = Ext.extend(Ext.FormPanel, {
10 /**
11 * @cfg {Boolean} border
12 * True to display the borders of the panel's body element, false to hide
13 * them (defaults to true). By default, the border is a 2px wide inset
14 * border, but this can be further altered by setting bodyBorder to false.
15 */
16 border: false,
17
18 /**
19 * @cfg {Number/String} padding
20 * A shortcut for setting a padding style on the body element. The value can
21 * either be a number to be applied to all sides, or a normal css string
22 * describing padding.
23 */
24 padding: 0,
25
26 /**
27 * @cfg {String} defaultType
28 *
29 * The default xtype of child Components to create in this Container when
30 * a child item is specified as a raw configuration object,
31 * rather than as an instantiated Component.
32 *
33 * Defaults to 'panel', except Ext.menu.Menu which defaults to 'menuitem',
34 * and Ext.Toolbar and Ext.ButtonGroup which default to 'button'.
35 */
36 defaultType: 'textfield',
37
38 /**
39 * @cfg {String} rule
40 *
41 * The name of this rule
42 */
43 rule: '',
44
45 /**
46 * @cfg {Boolean} monitorValid If true, the form monitors its valid state client-side and
47 * regularly fires the clientvalidation event passing that state.
48 * When monitoring valid state, the FormPanel enables/disables any of its configured
49 * buttons which have been configured with formBind: true depending
50 * on whether the form is valid or not. Defaults to false
51 */
52 monitorValid: true,
53
54 /**
55 * Constructor
56 */
57 initComponent: function() {
58 var fields = this.getFieldsBySettings();
59 var formItems = new Array();
60
61 // Adds the specified events to the list of events which this Observable may fire.
62 this.addEvents({
63 'validation': true
64 });
65
66 Ext.iterate(fields, function(item, index, allItems) {
67 switch(item) {
68 case 'message':
69 formItems.push({
70 fieldLabel: TYPO3.l10n.localize('validation_properties_message'),
71 name: 'message',
72 allowBlank: false,
73 listeners: {
74 'triggerclick': {
75 scope: this,
76 fn: this.storeValue
77 }
78 }
79 });
80 break;
81 case 'error':
82 formItems.push({
83 fieldLabel: TYPO3.l10n.localize('validation_properties_error'),
84 name: 'error',
85 allowBlank: false,
86 listeners: {
87 'triggerclick': {
88 scope: this,
89 fn: this.storeValue
90 }
91 }
92 });
93 break;
94 case 'showMessage':
95 formItems.push({
96 xtype: 'checkbox',
97 fieldLabel: TYPO3.l10n.localize('validation_properties_showmessage'),
98 name: 'showMessage',
99 inputValue: '1',
100 listeners: {
101 'check': {
102 scope: this,
103 fn: this.storeValue
104 }
105 }
106 });
107 break;
108 case 'allowWhiteSpace':
109 formItems.push({
110 xtype: 'checkbox',
111 fieldLabel: TYPO3.l10n.localize('validation_properties_allowwhitespace'),
112 name: 'allowWhiteSpace',
113 inputValue: '1',
114 listeners: {
115 'check': {
116 scope: this,
117 fn: this.storeValue
118 }
119 }
120 });
121 break;
122 case 'minimum':
123 formItems.push({
124 xtype: 'spinnerfield',
125 fieldLabel: TYPO3.l10n.localize('validation_properties_minimum'),
126 name: 'minimum',
127 minValue: 0,
128 accelerate: true,
129 listeners: {
130 'spin': {
131 scope: this,
132 fn: this.storeValue
133 },
134 'blur': {
135 scope: this,
136 fn: this.storeValue
137 }
138 }
139 });
140 break;
141 case 'maximum':
142 formItems.push({
143 xtype: 'spinnerfield',
144 fieldLabel: TYPO3.l10n.localize('validation_properties_maximum'),
145 name: 'maximum',
146 minValue: 0,
147 accelerate: true,
148 listeners: {
149 'spin': {
150 scope: this,
151 fn: this.storeValue
152 },
153 'blur': {
154 scope: this,
155 fn: this.storeValue
156 }
157 }
158 });
159 break;
160 case 'inclusive':
161 formItems.push({
162 xtype: 'checkbox',
163 fieldLabel: TYPO3.l10n.localize('validation_properties_inclusive'),
164 name: 'inclusive',
165 inputValue: '1',
166 listeners: {
167 'check': {
168 scope: this,
169 fn: this.storeValue
170 }
171 }
172 });
173 break;
174 case 'format':
175 formItems.push({
176 fieldLabel: TYPO3.l10n.localize('validation_properties_format'),
177 name: 'format',
178 allowBlank: false,
179 listeners: {
180 'triggerclick': {
181 scope: this,
182 fn: this.storeValue
183 }
184 }
185 });
186 break;
187 case 'field':
188 formItems.push({
189 fieldLabel: TYPO3.l10n.localize('validation_properties_field'),
190 name: 'field',
191 allowBlank: false,
192 listeners: {
193 'triggerclick': {
194 scope: this,
195 fn: this.storeValue
196 }
197 }
198 });
199 break;
200 case 'array':
201 formItems.push({
202 fieldLabel: TYPO3.l10n.localize('validation_properties_array'),
203 name: 'array',
204 allowBlank: false,
205 listeners: {
206 'triggerclick': {
207 scope: this,
208 fn: this.storeValue
209 }
210 }
211 });
212 break;
213 case 'expression':
214 formItems.push({
215 fieldLabel: TYPO3.l10n.localize('validation_properties_expression'),
216 name: 'expression',
217 allowBlank: false,
218 listeners: {
219 'triggerclick': {
220 scope: this,
221 fn: this.storeValue
222 }
223 }
224 });
225 case 'types':
226 formItems.push({
227 fieldLabel: TYPO3.l10n.localize('validation_properties_types'),
228 name: 'types',
229 allowBlank: false,
230 listeners: {
231 'triggerclick': {
232 scope: this,
233 fn: this.storeValue
234 }
235 }
236 });
237 break;
238 }
239 }, this);
240
241 formItems.push({
242 xtype: 'button',
243 text: TYPO3.l10n.localize('button_remove'),
244 handler: this.removeRule,
245 scope: this
246 });
247
248 var config = {
249 items: [
250 {
251 xtype: 'fieldset',
252 title: TYPO3.l10n.localize('validation_' + this.rule),
253 autoHeight: true,
254 defaults: {
255 width: 128,
256 msgTarget: 'side'
257 },
258 defaultType: 'textfieldsubmit',
259 items: formItems
260 }
261 ]
262 };
263
264 // apply config
265 Ext.apply(this, Ext.apply(this.initialConfig, config));
266
267 // call parent
268 TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule.superclass.initComponent.apply(this, arguments);
269
270 // Initialize clientvalidation event
271 this.on('clientvalidation', this.validation, this);
272
273 // Strange, but we need to call doLayout() after render
274 this.on('afterrender', this.newOrExistingRule, this);
275 },
276
277 /**
278 * Decide whether this is a new or an existing one
279 *
280 * If new, the default configuration has to be added to the validation rules
281 * of the element, otherwise we can fill the form with the existing configuration
282 */
283 newOrExistingRule: function() {
284 this.doLayout();
285 // Existing rule
286 if (this.element.configuration.validation[this.rule]) {
287 this.fillForm();
288 // New rule
289 } else {
290 this.addRuleToElement();
291 }
292 },
293
294 /**
295 * Fill the form with the configuration of the element
296 *
297 * When filling, the events of all form elements should be suspended,
298 * otherwise the values are written back to the element, for instance on a
299 * check event on a checkbox.
300 */
301 fillForm: function() {
302 this.suspendEventsBeforeFilling();
303 this.getForm().setValues(this.element.configuration.validation[this.rule]);
304 this.resumeEventsAfterFilling();
305 },
306
307 /**
308 * Suspend the events on all items within this component
309 */
310 suspendEventsBeforeFilling: function() {
311 this.cascade(function(item) {
312 item.suspendEvents();
313 });
314 },
315
316 /**
317 * Resume the events on all items within this component
318 */
319 resumeEventsAfterFilling: function() {
320 this.cascade(function(item) {
321 item.resumeEvents();
322 });
323 },
324
325 /**
326 * Add this rule to the element
327 */
328 addRuleToElement: function() {
329 var formConfiguration = {validation: {}};
330 formConfiguration.validation[this.rule] = this.configuration;
331
332 this.element.setConfigurationValue(formConfiguration);
333
334 this.fillForm();
335 },
336
337 /**
338 * Store a changed value from the form in the element
339 *
340 * @param {Object} field The field which has changed
341 */
342 storeValue: function(field) {
343 if (field.isValid()) {
344 var fieldName = field.getName();
345
346 var formConfiguration = {validation: {}};
347 formConfiguration.validation[this.rule] = {};
348 formConfiguration.validation[this.rule][fieldName] = field.getValue();
349
350 this.element.setConfigurationValue(formConfiguration);
351 }
352 },
353
354 /**
355 * Remove the rule
356 *
357 * Called when the remove button of this rule has been clicked
358 */
359 removeRule: function() {
360 this.ownerCt.removeRule(this);
361 this.element.removeValidationRule(this.rule);
362 },
363
364 /**
365 * Get the fields for the element
366 *
367 * Based on the TSconfig general allowed fields
368 * and the TSconfig allowed fields for this type of element
369 *
370 * @returns object
371 */
372 getFieldsBySettings: function() {
373 var fields = [];
374 var ruleFields = this.configuration;
375 var elementType = this.element.xtype.split('-').pop();
376
377 var allowedGeneralFields = [];
378 try {
379 allowedGeneralFields = TYPO3.Form.Wizard.Settings.defaults.tabs.options.accordions.validation.rules[this.rule].showProperties.split(/[, ]+/);
380 } catch (error) {
381 // The object has not been found or constructed wrong
382 allowedGeneralFields = [
383 'message',
384 'error',
385 'showMessage',
386 'allowWhiteSpace',
387 'minimum',
388 'maximum',
389 'inclusive',
390 'format',
391 'field',
392 'array',
393 'strict',
394 'expression'
395 ];
396 }
397
398 var allowedElementFields = [];
399 try {
400 allowedElementFields = TYPO3.Form.Wizard.Settings.elements[elementType].accordions.validation.rules[this.rule].showProperties.split(/[, ]+/);
401 } catch (error) {
402 // The object has not been found or constructed wrong
403 allowedElementFields = allowedGeneralFields;
404 }
405
406 Ext.iterate(allowedElementFields, function(item, index, allItems) {
407 if (allowedGeneralFields.indexOf(item) > -1 && Ext.isDefined(ruleFields[item])) {
408 fields.push(item);
409 }
410 }, this);
411
412 return fields;
413 },
414
415 /**
416 * Called by the clientvalidation event
417 *
418 * Adds or removes the error class if the form is valid or not
419 *
420 * @param {Object} formPanel This formpanel
421 * @param {Boolean} valid True if the client validation is true
422 */
423 validation: function(formPanel, valid) {
424 if (this.el) {
425 if (valid && this.el.hasClass('validation-error')) {
426 this.removeClass('validation-error');
427 this.fireEvent('validation', this.rule, valid);
428 } else if (!valid && !this.el.hasClass('validation-error')) {
429 this.addClass('validation-error');
430 this.fireEvent('validation', this.rule, valid);
431 }
432 }
433 }
434 });
435
436 Ext.reg('typo3-form-wizard-viewport-left-options-forms-validation-rule', TYPO3.Form.Wizard.Viewport.Left.Options.Forms.Validation.Rule);