PageSourceSearch

https://www.lca.org.tw/modules/civicrm/packages/jquery/plugins/jquery.form.js?tm7z1m

js lca.org.tw collected 2026-10-02 10:47:36 UTC 22,309 bytes, 781 lines download raw bytes

1/*!
2 * jQuery Form Plugin
3 * version: 2.47 (04-SEP-2010)
4 * @requires jQuery v1.3.2 or later
5 *
6 * Examples and documentation at: http://malsup.com/jquery/form/
7 * Dual licensed under the MIT and GPL licenses:
8 *   http://www.opensource.org/licenses/mit-license.php
9 *   http://www.gnu.org/licenses/gpl.html
10 */
11;(function($) {
12
13/*
14	Usage Note:
15	-----------
16	Do not use both ajaxSubmit and ajaxForm on the same form.  These
17	functions are intended to be exclusive.  Use ajaxSubmit if you want
18	to bind your own submit handler to the form.  For example,
19
20	$(document).ready(function() {
21		$('#myForm').bind('submit', function() {
22			$(this).ajaxSubmit({
23				target: '#output'
24			});
25			return false; // <-- important!
26		});
27	});
28
29	Use ajaxForm when you want the plugin to manage all the event binding
30	for you.  For example,
31
32	$(document).ready(function() {
33		$('#myForm').ajaxForm({
34			target: '#output'
35		});
36	});
37
38	When using ajaxForm, the ajaxSubmit function will be invoked for you
39	at the appropriate time.
40*/
41
42/**
43 * ajaxSubmit() provides a mechanism for immediately submitting
44 * an HTML form using AJAX.
45 */
46$.fn.ajaxSubmit = function(options) {
47	// fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
48	if (!this.length) {
49		log('ajaxSubmit: skipping submit process - no element selected');
50		return this;
51	}
52
53	if (typeof options == 'function') {
54		options = { success: options };
55	}
56
57	var url = $.trim(this.attr('action'));
58	if (url) {
59		// clean url (don't include hash vaue)
60		url = (url.match(/^([^#]+)/)||[])[1];
61	}
62	url = url || window.location.href || '';
63
64	options = $.extend(true, {
65		url:  url,
66		type: this.attr('method') || 'GET',
67		iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
68	}, options);
69
70	// hook for manipulating the form data before it is extracted;
71	// convenient for use with rich editors like tinyMCE or FCKEditor
72	var veto = {};
73	this.trigger('form-pre-serialize', [this, options, veto]);
74	if (veto.veto) {
75		log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
76		return this;
77	}
78
79	// provide opportunity to alter form data before it is serialized
80	if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
81		log('ajaxSubmit: submit aborted via beforeSerialize callback');
82		return this;
83	}
84
85	var n,v,a = this.formToArray(options.semantic);
86	if (options.data) {
87		options.extraData = options.data;
88		for (n in options.data) {
89			if(options.data[n] instanceof Array) {
90				for (var k in options.data[n]) {
91					a.push( { name: n, value: options.data[n][k] } );
92				}
93			}
94			else {
95				v = options.data[n];
96				v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
97				a.push( { name: n, value: v } );
98			}
99		}
100	}
101
102	// give pre-submit callback an opportunity to abort the submit
103	if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
104		log('ajaxSubmit: submit aborted via beforeSubmit callback');
105		return this;
106	}
107
108	// fire vetoable 'validate' event
109	this.trigger('form-submit-validate', [a, this, options, veto]);
110	if (veto.veto) {
111		log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
112		return this;
113	}
114
115	var q = $.param(a);
116
117	if (options.type.toUpperCase() == 'GET') {
118		options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
119		options.data = null;  // data is null for 'get'
120	}
121	else {
122		options.data = q; // data is the query string for 'post'
123	}
124
125	var $form = this, callbacks = [];
126	if (options.resetForm) {
127		callbacks.push(function() { $form.resetForm(); });
128	}
129	if (options.clearForm) {
130		callbacks.push(function() { $form.clearForm(); });
131	}
132
133	// perform a load on the target only if dataType is not provided
134	if (!options.dataType && options.target) {
135		var oldSuccess = options.success || function(){};
136		callbacks.push(function(data) {
137			var fn = options.replaceTarget ? 'replaceWith' : 'html';
138			$(options.target)[fn](data).each(oldSuccess, arguments);
139		});
140	}
141	else if (options.success) {
142		callbacks.push(options.success);
143	}
144
145	options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
146		var context = options.context || options;   // jQuery 1.4+ supports scope context
147		for (var i=0, max=callbacks.length; i < max; i++) {
148			callbacks[i].apply(context, [data, status, xhr || $form, $form]);
149		}
150	};
151
152	// are there files to upload?
153	var fileInputs = $('input:file', this).length > 0;
154	var mp = 'multipart/form-data';
155	var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
156
157	// options.iframe allows user to force iframe mode
158	// 06-NOV-09: now defaulting to iframe mode if file input is detected
159   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
160	   // hack to fix Safari hang (thanks to Tim Molendijk for this)
161	   // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
162	   if (options.closeKeepAlive) {
163		   $.get(options.closeKeepAlive, fileUpload);
164		}
165	   else {
166		   fileUpload();
167		}
168   }
169   else {
170	   $.ajax(options);
171   }
172
173	// fire 'notify' event
174	this.trigger('form-submit-notify', [this, options]);
175	return this;
176
177
178	// private function for handling file uploads (hat tip to YAHOO!)
179	function fileUpload() {
180		var form = $form[0];
181
182		if ($(':input[name=submit],:input[id=submit]', form).length) {
183			// if there is an input with a name or id of 'submit' then we won't be
184			// able to invoke the submit fn on the form (at least not x-browser)
185			alert('Error: Form elements must not have name or id of "submit".');
186			return;
187		}
188
189		var s = $.extend(true, {}, $.ajaxSettings, options);
190		s.context = s.context || s;
191		var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
192		window[fn] = function() {
193			var f = $io.data('form-plugin-onload');
194			if (f) {
195				f();
196				window[fn] = undefined;
197				try { delete window[fn]; } catch(e){}
198			}
199		}
200		var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" onload="window[\'_\'+this.id]()" />');
201		var io = $io[0];
202
203		$io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
204
205		var xhr = { // mock object
206			aborted: 0,
207			responseText: null,
208			responseXML: null,
209			status: 0,
210			statusText: 'n/a',
211			getAllResponseHeaders: function() {},
212			getResponseHeader: function() {},
213			setRequestHeader: function() {},
214			abort: function() {
215				this.aborted = 1;
216				$io.attr('src', s.iframeSrc); // abort op in progress
217			}
218		};
219
220		var g = s.global;
221		// trigger ajax global events so that activity/block indicators work like normal
222		if (g && ! $.active++) {
223			$.event.trigger("ajaxStart");
224		}
225		if (g) {
226			$.event.trigger("ajaxSend", [xhr, s]);
227		}
228
229		if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
230			if (s.global) {
231				$.active--;
232			}
233			return;
234		}
235		if (xhr.aborted) {
236			return;
237		}
238
239		var cbInvoked = false;
240		var timedOut = 0;
241
242		// add submitting element to data if we know it
243		var sub = form.clk;
244		if (sub) {
245			var n = sub.name;
246			if (n && !sub.disabled) {
247				s.extraData = s.extraData || {};
248				s.extraData[n] = sub.value;
249				if (sub.type == "image") {
250					s.extraData[n+'.x'] = form.clk_x;
251					s.extraData[n+'.y'] = form.clk_y;
252				}
253			}
254		}
255
256		// take a breath so that pending repaints get some cpu time before the upload starts
257		function doSubmit() {
258			// make sure form attrs are set
259			var t = $form.attr('target'), a = $form.attr('action');
260
261			// update form attrs in IE friendly way
262			form.setAttribute('target',id);
263			if (form.getAttribute('method') != 'POST') {
264				form.setAttribute('method', 'POST');
265			}
266			if (form.getAttribute('action') != s.url) {
267				form.setAttribute('action', s.url);
268			}
269
270			// ie borks in some cases when setting encoding
271			if (! s.skipEncodingOverride) {
272				$form.attr({
273					encoding: 'multipart/form-data',
274					enctype:  'multipart/form-data'
275				});
276			}
277
278			// support timout
279			if (s.timeout) {
280				setTimeout(function() { timedOut = true; cb(); }, s.timeout);
281			}
282
283			// add "extra" data to form if provided in options
284			var extraInputs = [];
285			try {
286				if (s.extraData) {
287					for (var n in s.extraData) {
288						extraInputs.push(
289							$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
290								.appendTo(form)[0]);
291					}
292				}
293
294				// add iframe to doc and submit the form
295				$io.appendTo('body');
296				$io.data('form-plugin-onload', cb);
297				form.submit();
298			}
299			finally {
300				// reset attrs and remove "extra" input elements
301				form.setAttribute('action',a);
302				if(t) {
303					form.setAttribute('target', t);
304				} else {
305					$form.removeAttr('target');
306				}
307				$(extraInputs).remove();
308			}
309		}
310
311		if (s.forceSync) {
312			doSubmit();
313		}
314		else {
315			setTimeout(doSubmit, 10); // this lets dom updates render
316		}
317
318		var data, doc, domCheckCount = 50;
319
320		function cb() {
321			if (cbInvoked) {
322				return;
323			}
324
325			$io.removeData('form-plugin-onload');
326
327			var ok = true;
328			try {
329				if (timedOut) {
330					throw 'timeout';
331				}
332				// extract the server response from the iframe
333				doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
334
335				var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
336				log('isXml='+isXml);
337				if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
338					if (--domCheckCount) {
339						// in some browsers (Opera) the iframe DOM is not always traversable when
340						// the onload callback fires, so we loop a bit to accommodate
341						log('requeing onLoad callback, DOM not available');
342						setTimeout(cb, 250);
343						return;
344					}
345					// let this fall through because server response could be an empty document
346					//log('Could not access iframe DOM after mutiple tries.');
347					//throw 'DOMException: not available';
348				}
349
350				//log('response detected');
351				cbInvoked = true;
352				xhr.responseText = doc.documentElement ? doc.documentElement.innerHTML : null;
353				xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
354				xhr.getResponseHeader = function(header){
355					var headers = {'content-type': s.dataType};
356					return headers[header];
357				};
358
359				var scr = /(json|script)/.test(s.dataType);
360				if (scr || s.textarea) {
361					// see if user embedded response in textarea
362					var ta = doc.getElementsByTagName('textarea')[0];
363					if (ta) {
364						xhr.responseText = ta.value;
365					}
366					else if (scr) {
367						// account for browsers injecting pre around json response
368						var pre = doc.getElementsByTagName('pre')[0];
369						if (pre) {
370							xhr.responseText = pre.innerHTML;
371						}
372					}
373				}
374				else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
375					xhr.responseXML = toXml(xhr.responseText);
376				}
377				data = $.httpData(xhr, s.dataType);
378			}
379			catch(e){
380				log('error caught:',e);
381				ok = false;
382				xhr.error = e;
383				$.handleError(s, xhr, 'error', e);
384			}
385
386			// ordering of these callbacks/triggers is odd, but that's how $.ajax does it
387			if (ok) {
388				s.success.call(s.context, data, 'success', xhr);
389				if (g) {
390					$.event.trigger("ajaxSuccess", [xhr, s]);
391				}
392			}
393			if (g) {
394				$.event.trigger("ajaxComplete", [xhr, s]);
395			}
396			if (g && ! --$.active) {
397				$.event.trigger("ajaxStop");
398			}
399			if (s.complete) {
400				s.complete.call(s.context, xhr, ok ? 'success' : 'error');
401			}
402
403			// clean up
404			setTimeout(function() {
405				$io.removeData('form-plugin-onload');
406				$io.remove();
407				xhr.responseXML = null;
408			}, 100);
409		}
410
411		function toXml(s, doc) {
412			if (window.ActiveXObject) {
413				doc = new ActiveXObject('Microsoft.XMLDOM');
414				doc.async = 'false';
415				doc.loadXML(s);
416			}
417			else {
418				doc = (new DOMParser()).parseFromString(s, 'text/xml');
419			}
420			return (doc && doc.documentElement && doc.documentElement.tagName != 'parsererror') ? doc : null;
421		}
422	}
423};
424
425/**
426 * ajaxForm() provides a mechanism for fully automating form submission.
427 *
428 * The advantages of using this method instead of ajaxSubmit() are:
429 *
430 * 1: This method will include coordinates for <input type="image" /> elements (if the element
431 *	is used to submit the form).
432 * 2. This method will include the submit element's name/value data (for the element that was
433 *	used to submit the form).
434 * 3. This method binds the submit() method to the form for you.
435 *
436 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
437 * passes the options argument along after properly binding events for submit elements and
438 * the form itself.
439 */
440$.fn.ajaxForm = function(options) {
441	// in jQuery 1.3+ we can fix mistakes with the ready state
442	if (this.length === 0) {
443		var o = { s: this.selector, c: this.context };
444		if (!$.isReady && o.s) {
445			log('DOM not ready, queuing ajaxForm');
446			$(function() {
447				$(o.s,o.c).ajaxForm(options);
448			});
449			return this;
450		}
451		// is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
452		log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
453		return this;
454	}
455
456	return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
457		if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
458			e.preventDefault();
459			$(this).ajaxSubmit(options);
460		}
461	}).bind('click.form-plugin', function(e) {
462		var target = e.target;
463		var $el = $(target);
464		if (!($el.is(":submit,input:image"))) {
465			// is this a child element of the submit el?  (ex: a span within a button)
466			var t = $el.closest(':submit');
467			if (t.length == 0) {
468				return;
469			}
470			target = t[0];
471		}
472		var form = this;
473		form.clk = target;
474		if (target.type == 'image') {
475			if (e.offsetX != undefined) {
476				form.clk_x = e.offsetX;
477				form.clk_y = e.offsetY;
478			} else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
479				var offset = $el.offset();
480				form.clk_x = e.pageX - offset.left;
481				form.clk_y = e.pageY - offset.top;
482			} else {
483				form.clk_x = e.pageX - target.offsetLeft;
484				form.clk_y = e.pageY - target.offsetTop;
485			}
486		}
487		// clear form vars
488		setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
489	});
490};
491
492// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
493$.fn.ajaxFormUnbind = function() {
494	return this.unbind('submit.form-plugin click.form-plugin');
495};
496
497/**
498 * formToArray() gathers form element data into an array of objects that can
499 * be passed to any of the following ajax functions: $.get, $.post, or load.
500 * Each object in the array has both a 'name' and 'value' property.  An example of
501 * an array for a simple login form might be:
502 *
503 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
504 *
505 * It is this array that is passed to pre-submit callback functions provided to the
506 * ajaxSubmit() and ajaxForm() methods.
507 */
508$.fn.formToArray = function(semantic) {
509	var a = [];
510	if (this.length === 0) {
511		return a;
512	}
513
514	var form = this[0];
515	var els = semantic ? form.getElementsByTagName('*') : form.elements;
516	if (!els) {
517		return a;
518	}
519
520	var i,j,n,v,el;
521	for(i=0, max=els.length; i < max; i++) {
522		el = els[i];
523		n = el.name;
524		if (!n) {
525			continue;
526		}
527
528		if (semantic && form.clk && el.type == "image") {
529			// handle image inputs on the fly when semantic == true
530			if(!el.disabled && form.clk == el) {
531				a.push({name: n, value: $(el).val()});
532				a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
533			}
534			continue;
535		}
536
537		v = $.fieldValue(el, true);
538		if (v && v.constructor == Array) {
539			for(j=0, jmax=v.length; j < jmax; j++) {
540				a.push({name: n, value: v[j]});
541			}
542		}
543		else if (v !== null && typeof v != 'undefined') {
544			a.push({name: n, value: v});
545		}
546	}
547
548	if (!semantic && form.clk) {
549		// input type=='image' are not found in elements array! handle it here
550		var $input = $(form.clk), input = $input[0];
551		n = input.name;
552		if (n && !input.disabled && input.type == 'image') {
553			a.push({name: n, value: $input.val()});
554			a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
555		}
556	}
557	return a;
558};
559
560/**
561 * Serializes form data into a 'submittable' string. This method will return a string
562 * in the format: name1=value1&amp;name2=value2
563 */
564$.fn.formSerialize = function(semantic) {
565	//hand off to jQuery.param for proper encoding
566	return $.param(this.formToArray(semantic));
567};
568
569/**
570 * Serializes all field elements in the jQuery object into a query string.
571 * This method will return a string in the format: name1=value1&amp;name2=value2
572 */
573$.fn.fieldSerialize = function(successful) {
574	var a = [];
575	this.each(function() {
576		var n = this.name;
577		if (!n) {
578			return;
579		}
580		var v = $.fieldValue(this, successful);
581		if (v && v.constructor == Array) {
582			for (var i=0,max=v.length; i < max; i++) {
583				a.push({name: n, value: v[i]});
584			}
585		}
586		else if (v !== null && typeof v != 'undefined') {
587			a.push({name: this.name, value: v});
588		}
589	});
590	//hand off to jQuery.param for proper encoding
591	return $.param(a);
592};
593
594/**
595 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
596 *
597 *  <form><fieldset>
598 *	  <input name="A" type="text" />
599 *	  <input name="A" type="text" />
600 *	  <input name="B" type="checkbox" value="B1" />
601 *	  <input name="B" type="checkbox" value="B2"/>
602 *	  <input name="C" type="radio" value="C1" />
603 *	  <input name="C" type="radio" value="C2" />
604 *  </fieldset></form>
605 *
606 *  var v = $(':text').fieldValue();
607 *  // if no values are entered into the text inputs
608 *  v == ['','']
609 *  // if values entered into the text inputs are 'foo' and 'bar'
610 *  v == ['foo','bar']
611 *
612 *  var v = $(':checkbox').fieldValue();
613 *  // if neither checkbox is checked
614 *  v === undefined
615 *  // if both checkboxes are checked
616 *  v == ['B1', 'B2']
617 *
618 *  var v = $(':radio').fieldValue();
619 *  // if neither radio is checked
620 *  v === undefined
621 *  // if first radio is checked
622 *  v == ['C1']
623 *
624 * The successful argument controls whether or not the field element must be 'successful'
625 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
626 * The default value of the successful argument is true.  If this value is false the value(s)
627 * for each element is returned.
628 *
629 * Note: This method *always* returns an array.  If no valid value can be determined the
630 *	   array will be empty, otherwise it will contain one or more values.
631 */
632$.fn.fieldValue = function(successful) {
633	for (var val=[], i=0, max=this.length; i < max; i++) {
634		var el = this[i];
635		var v = $.fieldValue(el, successful);
636		if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
637			continue;
638		}
639		v.constructor == Array ? $.merge(val, v) : val.push(v);
640	}
641	return val;
642};
643
644/**
645 * Returns the value of the field element.
646 */
647$.fieldValue = function(el, successful) {
648	var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
649	if (successful === undefined) {
650		successful = true;
651	}
652
653	if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
654		(t == 'checkbox' || t == 'radio') && !el.checked ||
655		(t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
656		tag == 'select' && el.selectedIndex == -1)) {
657			return null;
658	}
659
660	if (tag == 'select') {
661		var index = el.selectedIndex;
662		if (index < 0) {
663			return null;
664		}
665		var a = [], ops = el.options;
666		var one = (t == 'select-one');
667		var max = (one ? index+1 : ops.length);
668		for(var i=(one ? index : 0); i < max; i++) {
669			var op = ops[i];
670			if (op.selected) {
671				var v = op.value;
672				if (!v) { // extra pain for IE...
673					v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
674				}
675				if (one) {
676					return v;
677				}
678				a.push(v);
679			}
680		}
681		return a;
682	}
683	return $(el).val();
684};
685
686/**
687 * Clears the form data.  Takes the following actions on the form's input fields:
688 *  - input text fields will have their 'value' property set to the empty string
689 *  - select elements will have their 'selectedIndex' property set to -1
690 *  - checkbox and radio inputs will have their 'checked' property set to false
691 *  - inputs of type submit, button, reset, and hidden will *not* be effected
692 *  - button elements will *not* be effected
693 */
694$.fn.clearForm = function() {
695	return this.each(function() {
696		$('input,select,textarea', this).clearFields();
697	});
698};
699
700/**
701 * Clears the selected form elements.
702 */
703$.fn.clearFields = $.fn.clearInputs = function() {
704	return this.each(function() {
705		var t = this.type, tag = this.tagName.toLowerCase();
706		if (t == 'text' || t == 'password' || tag == 'textarea') {
707			this.value = '';
708		}
709		else if (t == 'checkbox' || t == 'radio') {
710			this.checked = false;
711		}
712		else if (tag == 'select') {
713			this.selectedIndex = -1;
714		}
715	});
716};
717
718/**
719 * Resets the form data.  Causes all form elements to be reset to their original value.
720 */
721$.fn.resetForm = function() {
722	return this.each(function() {
723		// guard against an input with the name of 'reset'
724		// note that IE reports the reset function as an 'object'
725		if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
726			this.reset();
727		}
728	});
729};
730
731/**
732 * Enables or disables any matching elements.
733 */
734$.fn.enable = function(b) {
735	if (b === undefined) {
736		b = true;
737	}
738	return this.each(function() {
739		this.disabled = !b;
740	});
741};
742
743/**
744 * Checks/unchecks any matching checkboxes or radio buttons and
745 * selects/deselects and matching option elements.
746 */
747$.fn.selected = function(select) {
748	if (select === undefined) {
749		select = true;
750	}
751	return this.each(function() {
752		var t = this.type;
753		if (t == 'checkbox' || t == 'radio') {
754			this.checked = select;
755		}
756		else if (this.tagName.toLowerCase() == 'option') {
757			var $sel = $(this).parent('select');
758			if (select && $sel[0] && $sel[0].type == 'select-one') {
759				// deselect all other options
760				$sel.find('option').selected(false);
761			}
762			this.selected = select;
763		}
764	});
765};
766
767// helper fn for console logging
768// set $.fn.ajaxSubmit.debug to true to enable debug logging
769function log() {
770	if ($.fn.ajaxSubmit.debug) {
771		var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
772		if (window.console && window.console.log) {
773			window.console.log(msg);
774		}
775		else if (window.opera && window.opera.postError) {
776			window.opera.postError(msg);
777		}
778	}
779};
780
781})(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.