PageSourceSearch

https://www.soundgym.co/js/app/yiiactiveform.js

js soundgym.co collected 2026-09-24 18:48:58 UTC 14,540 bytes, 438 lines download raw bytes

1/**
2 * jQuery yiiactiveform plugin file.
3 *
4 * @author Qiang Xue <[email protected]>
5 * @link http://www.yiiframework.com/
6 * @copyright 2008-2010 Yii Software LLC
7 * @license http://www.yiiframework.com/license/
8 * @since 1.1.1
9 */
10
11(function ($) {
12	/*
13	 * returns the value of the CActiveForm input field
14	 * performs additional checks to get proper values for checkbox / radiobutton / checkBoxList / radioButtonList
15	 * @param o object the jQuery object of the input element
16	 */
17	var getAFValue = function (o) {
18		var type,
19			c = [];
20		if (!o.length) {
21			return undefined;
22		}
23		if (o[0].tagName.toLowerCase() === 'span') {
24			o.find(':checked').each(function () {
25				c.push(this.value);
26			});
27			return c.join(',');
28		}
29		type = o.attr('type');
30		if (type === 'checkbox' || type === 'radio') {
31			return o.filter(':checked').val();
32		} else {
33			return o.val();
34		}
35	};
36
37	/**
38	 * yiiactiveform set function.
39	 * @param options map settings for the active form plugin. Please see {@link CActiveForm::options} for availablel options.
40	 */
41	$.fn.yiiactiveform = function (options) {
42		return this.each(function () {
43			var settings = $.extend({}, $.fn.yiiactiveform.defaults, options || {}),
44				$form = $(this);
45
46			if (settings.validationUrl === undefined) {
47				settings.validationUrl = $form.attr('action');
48			}
49			$.each(settings.attributes, function (i) {
50				this.value = getAFValue($form.find('#' + this.inputID));
51				settings.attributes[i] = $.extend({}, {
52					validationDelay: settings.validationDelay,
53					validateOnChange: settings.validateOnChange,
54					validateOnType: settings.validateOnType,
55					hideErrorMessage: settings.hideErrorMessage,
56					inputContainer: settings.inputContainer,
57					errorCssClass: settings.errorCssClass,
58					successCssClass: settings.successCssClass,
59					beforeValidateAttribute: settings.beforeValidateAttribute,
60					afterValidateAttribute: settings.afterValidateAttribute,
61					validatingCssClass: settings.validatingCssClass
62				}, this);
63			});
64			$form.data('settings', settings);
65
66			settings.submitting = false;  // whether it is waiting for ajax submission result
67			var validate = function (attribute, forceValidate) {
68				if (forceValidate) {
69					attribute.status = 2;
70				}
71				$.each(settings.attributes, function () {
72					if (this.value !== getAFValue($form.find('#' + this.inputID))) {
73						this.status = 2;
74						forceValidate = true;
75					}
76				});
77				if (!forceValidate) {
78					return;
79				}
80
81				if (settings.timer !== undefined) {
82					clearTimeout(settings.timer);
83				}
84				settings.timer = setTimeout(function () {
85					if (settings.submitting || $form.is(':hidden')) {
86						return;
87					}
88					if (attribute.beforeValidateAttribute === undefined || attribute.beforeValidateAttribute($form, attribute)) {
89						$.each(settings.attributes, function () {
90							if (this.status === 2) {
91								this.status = 3;
92								$.fn.yiiactiveform.getInputContainer(this, $form).addClass(this.validatingCssClass);
93							}
94						});
95						$.fn.yiiactiveform.validate($form, function (data) {
96							var hasError = false;
97							$.each(settings.attributes, function () {
98								if (this.status === 2 || this.status === 3) {
99									hasError = $.fn.yiiactiveform.updateInput(this, data, $form) || hasError;
100								}
101							});
102							if (attribute.afterValidateAttribute !== undefined) {
103								attribute.afterValidateAttribute($form, attribute, data, hasError);
104							}
105						});
106					}
107				}, attribute.validationDelay);
108			};
109
110			$.each(settings.attributes, function (i, attribute) {
111				if (this.validateOnChange) {
112					$form.find('#' + this.inputID).change(function () {
113						validate(attribute, false);
114					}).blur(function () {
115						if (attribute.status !== 2 && attribute.status !== 3) {
116							validate(attribute, !attribute.status);
117						}
118					});
119				}
120				if (this.validateOnType) {
121					$form.find('#' + this.inputID).keyup(function () {
122						if (attribute.value !== getAFValue($(this))) {
123							validate(attribute, false);
124						}
125					});
126				}
127			});
128
129			if (settings.validateOnSubmit) {
130				$form.on('mouseup keyup', ':submit', function () {
131					$form.data('submitObject', $(this));
132				});
133				var validated = false;
134				$form.submit(function () {
135					if (validated) {
136						validated = false;
137						return true;
138					}
139					if (settings.timer !== undefined) {
140						clearTimeout(settings.timer);
141					}
142					settings.submitting = true;
143					if (settings.beforeValidate === undefined || settings.beforeValidate($form)) {
144						$.fn.yiiactiveform.validate($form, function (data) {
145							var hasError = false;
146							$.each(settings.attributes, function () {
147								hasError = $.fn.yiiactiveform.updateInput(this, data, $form) || hasError;
148							});
149							$.fn.yiiactiveform.updateSummary($form, data);
150							if (settings.afterValidate === undefined || settings.afterValidate($form, data, hasError)) {
151								if (!hasError) {
152									validated = true;
153									var $button = $form.data('submitObject') || $form.find(':submit:first');
154									// TODO: if the submission is caused by "change" event, it will not work
155									if ($button.length) {
156										$button.click();
157									} else {  // no submit button in the form
158										$form.submit();
159									}
160									return;
161								}
162							}
163							settings.submitting = false;
164						});
165					} else {
166						settings.submitting = false;
167					}
168					return false;
169				});
170			}
171
172			/*
173			 * In case of reseting the form we need to reset error messages
174			 * NOTE1: $form.reset - does not exist
175			 * NOTE2: $form.on('reset', ...) does not work
176			 */
177			$form.bind('reset', function () {
178				/*
179				 * because we bind directly to a form reset event, not to a reset button (that could or could not exist),
180				 * when this function is executed form elements values have not been reset yet,
181				 * because of that we use the setTimeout
182				 */
183				setTimeout(function () {
184					$.each(settings.attributes, function () {
185						this.status = 0;
186						var $error = $form.find('#' + this.errorID),
187							$container = $.fn.yiiactiveform.getInputContainer(this, $form);
188
189						$container.removeClass(
190							this.validatingCssClass + ' ' +
191							this.errorCssClass + ' ' +
192							this.successCssClass
193						);
194
195						$error.html('').hide();
196
197						/*
198						 * without the setTimeout() we would get here the current entered value before the reset instead of the reseted value
199						 */
200						this.value = getAFValue($form.find('#' + this.inputID));
201					});
202					/*
203					 * If the form is submited (non ajax) with errors, labels and input gets the class 'error'
204					 */
205					$form.find('label, :input').each(function () {
206						$(this).removeClass(settings.errorCss);
207					});
208					$('#' + settings.summaryID).hide().find('ul').html('');
209					//.. set to initial focus on reset
210					if (settings.focus !== undefined && !window.location.hash) {
211						$form.find(settings.focus).focus();
212					}
213				}, 1);
214			});
215
216			/*
217			 * set to initial focus
218			 */
219			if (settings.focus !== undefined && !window.location.hash) {
220				$form.find(settings.focus).focus();
221			}
222		});
223	};
224
225	/**
226	 * Returns the container element of the specified attribute.
227	 * @param attribute object the configuration for a particular attribute.
228	 * @param form the form jQuery object
229	 * @return jQuery the jQuery representation of the container
230	 */
231	$.fn.yiiactiveform.getInputContainer = function (attribute, form) {
232		if (attribute.inputContainer === undefined) {
233			return form.find('#' + attribute.inputID).closest('div');
234		} else {
235			return form.find(attribute.inputContainer).filter(':has("#' + attribute.inputID + '")');
236		}
237	};
238
239	/**
240	 * updates the error message and the input container for a particular attribute.
241	 * @param attribute object the configuration for a particular attribute.
242	 * @param messages array the json data obtained from the ajax validation request
243	 * @param form the form jQuery object
244	 * @return boolean whether there is a validation error for the specified attribute
245	 */
246	$.fn.yiiactiveform.updateInput = function (attribute, messages, form) {
247		attribute.status = 1;
248		var $error, $container,
249			hasError = false,
250			$el = form.find('#' + attribute.inputID),
251			errorCss = form.data('settings').errorCss;
252
253		if ($el.length) {
254			hasError = messages !== null && $.isArray(messages[attribute.id]) && messages[attribute.id].length > 0;
255			$error = form.find('#' + attribute.errorID);
256			$container = $.fn.yiiactiveform.getInputContainer(attribute, form);
257
258			$container.removeClass(
259				attribute.validatingCssClass + ' ' +
260				attribute.errorCssClass + ' ' +
261				attribute.successCssClass
262			);
263			$container.find('label, :input').each(function () {
264				$(this).removeClass(errorCss);
265			});
266
267			if (hasError) {
268				$error.html(messages[attribute.id][0]);
269				$container.addClass(attribute.errorCssClass);
270			} else if (attribute.enableAjaxValidation || attribute.clientValidation) {
271				$container.addClass(attribute.successCssClass);
272			}
273			if (!attribute.hideErrorMessage) {
274				$error.toggle(hasError);
275			}
276
277			attribute.value = getAFValue($el);
278		}
279		return hasError;
280	};
281
282	/**
283	 * updates the error summary, if any.
284	 * @param form jquery the jquery representation of the form
285	 * @param messages array the json data obtained from the ajax validation request
286	 */
287	$.fn.yiiactiveform.updateSummary = function (form, messages) {
288		var settings = $(form).data('settings'),
289			content = '';
290		if (settings.summaryID === undefined) {
291			return;
292		}
293		if (messages) {
294			var summaryAttributes = [];
295			for (var i in settings.attributes) {
296				if (settings.attributes[i].summary) {
297					summaryAttributes.push(settings.attributes[i].id);
298				}
299			}
300			$.each(settings.attributes, function () {
301				if ($.inArray(this.id, summaryAttributes) !== -1 && $.isArray(messages[this.id])) {
302					$.each(messages[this.id], function (j, message) {
303						content = content + '<li>' + message + '</li>';
304					});
305				}
306			});
307		}
308		$('#' + settings.summaryID).toggle(content !== '').find('ul').html(content);
309	};
310
311	/**
312	 * Performs the ajax validation request.
313	 * This method is invoked internally to trigger the ajax validation.
314	 * @param form jquery the jquery representation of the form
315	 * @param successCallback function the function to be invoked if the ajax request succeeds
316	 * @param errorCallback function the function to be invoked if the ajax request fails
317	 */
318	$.fn.yiiactiveform.validate = function (form, successCallback, errorCallback) {
319		var $form = $(form),
320			settings = $form.data('settings'),
321			needAjaxValidation = false,
322			messages = {};
323		$.each(settings.attributes, function () {
324			var value,
325				msg = [];
326			if (this.clientValidation !== undefined && (settings.submitting || this.status === 2 || this.status === 3)) {
327				value = getAFValue($form.find('#' + this.inputID));
328				this.clientValidation(value, msg, this);
329				if (msg.length) {
330					messages[this.id] = msg;
331				}
332			}
333			if (this.enableAjaxValidation && !msg.length && (settings.submitting || this.status === 2 || this.status === 3)) {
334				needAjaxValidation = true;
335			}
336		});
337
338		if (!needAjaxValidation || settings.submitting && !$.isEmptyObject(messages)) {
339			if (settings.submitting) {
340				// delay callback so that the form can be submitted without problem
341				setTimeout(function () {
342					successCallback(messages);
343				}, 200);
344			} else {
345				successCallback(messages);
346			}
347			return;
348		}
349
350		var $button = $form.data('submitObject'),
351			extData = '&' + settings.ajaxVar + '=' + $form.attr('id');
352		if ($button && $button.length) {
353			extData += '&' + $button.attr('name') + '=' + $button.attr('value');
354		}
355
356		$.ajax({
357			url: settings.validationUrl,
358			type: $form.attr('method'),
359			data: $form.serialize() + extData,
360			dataType: 'json',
361			success: function (data) {
362				if (data !== null && typeof data === 'object') {
363					$.each(settings.attributes, function () {
364						if (!this.enableAjaxValidation) {
365							delete data[this.id];
366						}
367					});
368					successCallback($.extend({}, messages, data));
369				} else {
370					successCallback(messages);
371				}
372			},
373			error: function () {
374				if (errorCallback !== undefined) {
375					errorCallback();
376				}
377			}
378		});
379	};
380
381	/**
382	 * Returns the configuration for the specified form.
383	 * The configuration contains all needed information to perform ajax-based validation.
384	 * @param form jquery the jquery representation of the form
385	 * @return object the configuration for the specified form.
386	 */
387	$.fn.yiiactiveform.getSettings = function (form) {
388		return $(form).data('settings');
389	};
390
391	$.fn.yiiactiveform.defaults = {
392		ajaxVar: 'ajax',
393		validationUrl: undefined,
394		validationDelay: 200,
395		validateOnSubmit: false,
396		validateOnChange: true,
397		validateOnType: false,
398		hideErrorMessage: false,
399		inputContainer: undefined,
400		errorCss: 'error',
401		errorCssClass: 'error',
402		successCssClass: 'success',
403		validatingCssClass: 'validating',
404		summaryID: undefined,
405		timer: undefined,
406		beforeValidateAttribute: undefined, // function (form, attribute) | boolean
407		afterValidateAttribute: undefined,  // function (form, attribute, data, hasError)
408		beforeValidate: undefined, // function (form) | boolean
409		afterValidate: undefined,  // function (form, data, hasError) | boolean
410		focus: undefined,  // jquery selector that indicates which element to receive input focus initially
411		/**
412		 * list of attributes to be validated. Each array element is of the following structure:
413		 * {
414		 *     id: 'ModelClass_attribute', // the unique attribute ID
415		 *     model: 'ModelClass', // the model class name
416		 *     name: 'name', // attribute name
417		 *     inputID: 'input-tag-id',
418		 *     errorID: 'error-tag-id',
419		 *     value: undefined,
420		 *     status: 0,  // 0: empty, not entered before,  1: validated, 2: pending validation, 3: validating
421		 *     validationDelay: 200,
422		 *     validateOnChange: true,
423		 *     validateOnType: false,
424		 *     hideErrorMessage: false,
425		 *     inputContainer: undefined,
426		 *     errorCssClass: 'error',
427		 *     successCssClass: 'success',
428		 *     validatingCssClass: 'validating',
429		 *     enableAjaxValidation: true,
430		 *     enableClientValidation: true,
431		 *     clientValidation: undefined, // function (value, messages, attribute) | client-side validation
432		 *     beforeValidateAttribute: undefined, // function (form, attribute) | boolean
433		 *     afterValidateAttribute: undefined,  // function (form, attribute, data, hasError)
434		 * }
435		 */
436		attributes: []
437	};
438})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.