joosy 1.1.2 → 1.2.0.alpha.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +6 -7
  3. data/Gemfile +1 -11
  4. data/Gruntfile.coffee +138 -0
  5. data/README.md +65 -24
  6. data/bin/joosy +21 -0
  7. data/bower.json +23 -0
  8. data/joosy.gemspec +6 -12
  9. data/lib/joosy.js +3754 -0
  10. data/lib/joosy.rb +8 -9
  11. data/package.json +37 -0
  12. data/spec/{javascripts/helpers/spec_helper.js.coffee → helpers/helper.coffee} +0 -0
  13. data/spec/{javascripts/joosy/core/application_spec.js.coffee → joosy/core/application_spec.coffee} +0 -0
  14. data/spec/{javascripts/joosy/core/form_spec.js.coffee → joosy/core/form_spec.coffee} +30 -30
  15. data/spec/{javascripts/joosy/core/helpers/forms_spec.js.coffee → joosy/core/helpers/forms_spec.coffee} +0 -0
  16. data/spec/{javascripts/joosy/core/helpers/view_spec.js.coffee → joosy/core/helpers/view_spec.coffee} +0 -0
  17. data/spec/{javascripts/joosy/core/helpers/widgets_spec.js.coffee → joosy/core/helpers/widgets_spec.coffee} +0 -0
  18. data/spec/{javascripts/joosy/core/joosy_spec.js.coffee → joosy/core/joosy_spec.coffee} +0 -0
  19. data/spec/{javascripts/joosy/core/layout_spec.js.coffee → joosy/core/layout_spec.coffee} +0 -0
  20. data/spec/{javascripts/joosy/core/modules/container_spec.js.coffee → joosy/core/modules/container_spec.coffee} +1 -1
  21. data/spec/{javascripts/joosy/core/modules/events_spec.js.coffee → joosy/core/modules/events_spec.coffee} +0 -0
  22. data/spec/{javascripts/joosy/core/modules/filters_spec.js.coffee → joosy/core/modules/filters_spec.coffee} +0 -0
  23. data/spec/{javascripts/joosy/core/modules/log_spec.js.coffee → joosy/core/modules/log_spec.coffee} +0 -0
  24. data/spec/{javascripts/joosy/core/modules/module_spec.js.coffee → joosy/core/modules/module_spec.coffee} +0 -0
  25. data/spec/{javascripts/joosy/core/modules/renderer_spec.js.coffee → joosy/core/modules/renderer_spec.coffee} +35 -0
  26. data/spec/{javascripts/joosy/core/modules/time_manager_spec.js.coffee → joosy/core/modules/time_manager_spec.coffee} +0 -0
  27. data/spec/{javascripts/joosy/core/modules/widget_manager_spec.js.coffee → joosy/core/modules/widget_manager_spec.coffee} +0 -0
  28. data/spec/{javascripts/joosy/core/page_spec.js.coffee → joosy/core/page_spec.coffee} +0 -0
  29. data/spec/{javascripts/joosy/core/resource/collection_spec.js.coffee → joosy/core/resource/collection_spec.coffee} +0 -0
  30. data/spec/{javascripts/joosy/core/resource/generic_spec.js.coffee → joosy/core/resource/generic_spec.coffee} +0 -0
  31. data/spec/{javascripts/joosy/core/resource/rest_collection_spec.js.coffee → joosy/core/resource/rest_collection_spec.coffee} +0 -0
  32. data/spec/{javascripts/joosy/core/resource/rest_spec.js.coffee → joosy/core/resource/rest_spec.coffee} +0 -8
  33. data/spec/{javascripts/joosy/core/router_spec.js.coffee → joosy/core/router_spec.coffee} +19 -22
  34. data/spec/{javascripts/joosy/core/templaters/rails_jst_spec.js.coffee → joosy/core/templaters/rails_jst_spec.coffee} +0 -0
  35. data/spec/{javascripts/joosy/core/widget_spec.js.coffee → joosy/core/widget_spec.coffee} +0 -0
  36. data/spec/{javascripts/joosy/preloaders/caching_spec.js.coffee → joosy/preloaders/caching_spec.coffee} +2 -2
  37. data/spec/{javascripts/joosy/preloaders/inline_spec.js.coffee → joosy/preloaders/inline_spec.coffee} +1 -1
  38. data/spec/support/test.js +1 -0
  39. data/{app/assets/javascripts/joosy/core/application.js.coffee → src/joosy/core/application.coffee} +0 -0
  40. data/{app/assets/javascripts/joosy/core/form.js.coffee → src/joosy/core/form.coffee} +5 -5
  41. data/{app/assets/javascripts/joosy/core/helpers/form.js.coffee → src/joosy/core/helpers/form.coffee} +0 -0
  42. data/{app/assets/javascripts/joosy/core/helpers/view.js.coffee → src/joosy/core/helpers/view.coffee} +0 -0
  43. data/{app/assets/javascripts/joosy/core/helpers/widgets.js.coffee → src/joosy/core/helpers/widgets.coffee} +0 -0
  44. data/{app/assets/javascripts/joosy/core/joosy.js.coffee → src/joosy/core/joosy.coffee} +1 -1
  45. data/{app/assets/javascripts/joosy/core/layout.js.coffee → src/joosy/core/layout.coffee} +0 -0
  46. data/{app/assets/javascripts/joosy/core/modules/container.js.coffee → src/joosy/core/modules/container.coffee} +1 -1
  47. data/{app/assets/javascripts/joosy/core/modules/events.js.coffee → src/joosy/core/modules/events.coffee} +4 -6
  48. data/{app/assets/javascripts/joosy/core/modules/filters.js.coffee → src/joosy/core/modules/filters.coffee} +0 -0
  49. data/{app/assets/javascripts/joosy/core/modules/log.js.coffee → src/joosy/core/modules/log.coffee} +0 -0
  50. data/{app/assets/javascripts/joosy/core/modules/module.js.coffee → src/joosy/core/modules/module.coffee} +0 -0
  51. data/{app/assets/javascripts/joosy/core/modules/renderer.js.coffee → src/joosy/core/modules/renderer.coffee} +1 -1
  52. data/{app/assets/javascripts/joosy/core/modules/time_manager.js.coffee → src/joosy/core/modules/time_manager.coffee} +0 -0
  53. data/{app/assets/javascripts/joosy/core/modules/widgets_manager.js.coffee → src/joosy/core/modules/widgets_manager.coffee} +0 -0
  54. data/{app/assets/javascripts/joosy/core/page.js.coffee → src/joosy/core/page.coffee} +0 -1
  55. data/{app/assets/javascripts/joosy/core/preloader.js.coffee → src/joosy/core/preloader.coffee} +0 -0
  56. data/{app/assets/javascripts/joosy/core/resource/collection.js.coffee → src/joosy/core/resource/collection.coffee} +0 -0
  57. data/{app/assets/javascripts/joosy/core/resource/generic.js.coffee → src/joosy/core/resource/generic.coffee} +5 -5
  58. data/{app/assets/javascripts/joosy/core/resource/rest.js.coffee → src/joosy/core/resource/rest.coffee} +5 -5
  59. data/{app/assets/javascripts/joosy/core/resource/rest_collection.js.coffee → src/joosy/core/resource/rest_collection.coffee} +0 -0
  60. data/src/joosy/core/resource/watcher.coffee +50 -0
  61. data/{app/assets/javascripts/joosy/core/router.js.coffee → src/joosy/core/router.coffee} +28 -30
  62. data/{app/assets/javascripts/joosy/core/templaters/rails_jst.js.coffee → src/joosy/core/templaters/rails_jst.coffee} +12 -2
  63. data/{app/assets/javascripts/joosy/core/widget.js.coffee → src/joosy/core/widget.coffee} +0 -0
  64. data/src/joosy/generators/command.coffee +49 -0
  65. data/src/joosy/generators/generator.coffee +93 -0
  66. data/src/joosy/generators/layout.coffee +20 -0
  67. data/src/joosy/generators/page.coffee +20 -0
  68. data/src/joosy/generators/project/base.coffee +28 -0
  69. data/src/joosy/generators/project/standalone.coffee +25 -0
  70. data/src/joosy/generators/project.coffee +16 -0
  71. data/src/joosy/generators/widget.coffee +20 -0
  72. data/{app/assets/javascripts/joosy/preloaders/caching.js.coffee → src/joosy/preloaders/caching.coffee} +0 -0
  73. data/{app/assets/javascripts/joosy/preloaders/inline.js.coffee → src/joosy/preloaders/inline.coffee} +0 -0
  74. data/src/joosy.coffee +2 -0
  75. data/src/vendor/metamorph.coffee +410 -0
  76. data/tasks/joosy.coffee +63 -0
  77. data/templates/application/base/application.coffee +11 -0
  78. data/{lib/rails/generators/joosy/templates/app/helpers/application.js.coffee → templates/application/base/helpers/application.coffee} +0 -0
  79. data/{lib/rails/generators/joosy/templates/app/layouts/application.js.coffee → templates/application/base/layouts/application.coffee} +0 -0
  80. data/{lib/rails/generators/joosy/templates/app/pages/application.js.coffee → templates/application/base/pages/application.coffee} +0 -0
  81. data/{lib/rails/generators/joosy/templates/app/pages/welcome/index.js.coffee → templates/application/base/pages/welcome/index.coffee} +3 -3
  82. data/templates/application/base/routes.coffee +3 -0
  83. data/{lib/rails/generators/joosy/templates/app → templates/application/base}/templates/layouts/application.jst.hamlc +0 -0
  84. data/{lib/rails/generators/joosy/templates/app → templates/application/base}/templates/pages/welcome/index.jst.hamlc +1 -2
  85. data/templates/application/standalone/.gitignore +5 -0
  86. data/templates/application/standalone/Gruntfile.coffee +40 -0
  87. data/templates/application/standalone/Procfile +1 -0
  88. data/templates/application/standalone/bower.json +7 -0
  89. data/templates/application/standalone/package.json +24 -0
  90. data/templates/application/standalone/source/index.haml +7 -0
  91. data/templates/application/standalone/stylesheets/application.styl +2 -0
  92. data/templates/layout/basic.coffee +2 -0
  93. data/templates/layout/namespaced.coffee +4 -0
  94. data/templates/page/basic.coffee +3 -0
  95. data/templates/page/namespaced.coffee +5 -0
  96. data/templates/widget/basic.coffee +2 -0
  97. data/templates/widget/namespaced.coffee +4 -0
  98. metadata +98 -179
  99. data/.codoopts +0 -5
  100. data/Gemfile.lock +0 -157
  101. data/Guardfile +0 -32
  102. data/LICENSE +0 -22
  103. data/MIT-LICENSE +0 -21
  104. data/Rakefile +0 -14
  105. data/app/assets/javascripts/joosy.js.coffee +0 -5
  106. data/app/helpers/joosy/sprockets_helper.rb +0 -41
  107. data/app/views/layouts/json_wrapper.json.erb +0 -1
  108. data/lib/joosy/rails/engine.rb +0 -24
  109. data/lib/joosy/version.rb +0 -3
  110. data/lib/rails/generators/joosy/application_generator.rb +0 -43
  111. data/lib/rails/generators/joosy/joosy_base.rb +0 -30
  112. data/lib/rails/generators/joosy/layout_generator.rb +0 -30
  113. data/lib/rails/generators/joosy/page_generator.rb +0 -42
  114. data/lib/rails/generators/joosy/preloader_generator.rb +0 -30
  115. data/lib/rails/generators/joosy/resource_generator.rb +0 -40
  116. data/lib/rails/generators/joosy/templates/app/layouts/template.js.coffee +0 -2
  117. data/lib/rails/generators/joosy/templates/app/pages/template.js.coffee +0 -5
  118. data/lib/rails/generators/joosy/templates/app/resources/template.js.coffee +0 -2
  119. data/lib/rails/generators/joosy/templates/app/resources/template_with_namespace.js.coffee +0 -4
  120. data/lib/rails/generators/joosy/templates/app/routes.js.coffee +0 -8
  121. data/lib/rails/generators/joosy/templates/app/widgets/template.js.coffee +0 -2
  122. data/lib/rails/generators/joosy/templates/app.js.coffee +0 -11
  123. data/lib/rails/generators/joosy/templates/app_controller.rb +0 -9
  124. data/lib/rails/generators/joosy/templates/app_preloader.js.coffee.erb +0 -13
  125. data/lib/rails/generators/joosy/templates/app_railties.js.coffee.erb +0 -11
  126. data/lib/rails/generators/joosy/templates/preload.html.erb +0 -26
  127. data/lib/rails/generators/joosy/templates/preload.html.haml +0 -19
  128. data/lib/rails/generators/joosy/templates/preload.html.slim +0 -19
  129. data/lib/rails/generators/joosy/widget_generator.rb +0 -30
  130. data/lib/rails/resources_with_joosy.rb +0 -11
  131. data/spec/javascripts/support/assets/coolface.jpg +0 -0
  132. data/spec/javascripts/support/assets/okay.jpg +0 -0
  133. data/spec/javascripts/support/assets/test.js +0 -1
  134. data/spec/javascripts/support/jasmine.yml +0 -74
  135. data/spec/javascripts/support/jasmine_config.rb +0 -23
  136. data/spec/javascripts/support/jasmine_runner.rb +0 -32
  137. data/spec/javascripts/support/sinon-1.3.1.js +0 -3469
  138. data/spec/javascripts/support/sinon-ie-1.3.1.js.skip +0 -82
  139. data/vendor/assets/javascripts/jquery.form.js +0 -1190
  140. data/vendor/assets/javascripts/jquery.hashchange.js +0 -390
  141. data/vendor/assets/javascripts/metamorph.js +0 -409
  142. data/vendor/assets/javascripts/sugar.js +0 -8637
@@ -1,1190 +0,0 @@
1
- /*!
2
- * jQuery Form Plugin
3
- * version: 3.36.0-2013.06.16
4
- * @requires jQuery v1.5 or later
5
- * Copyright (c) 2013 M. Alsup
6
- * Examples and documentation at: http://malsup.com/jquery/form/
7
- * Project repository: https://github.com/malsup/form
8
- * Dual licensed under the MIT and GPL licenses.
9
- * https://github.com/malsup/form#copyright-and-license
10
- */
11
- /*global ActiveXObject */
12
- ;(function($) {
13
- "use strict";
14
-
15
- /*
16
- Usage Note:
17
- -----------
18
- Do not use both ajaxSubmit and ajaxForm on the same form. These
19
- functions are mutually exclusive. Use ajaxSubmit if you want
20
- to bind your own submit handler to the form. For example,
21
-
22
- $(document).ready(function() {
23
- $('#myForm').on('submit', function(e) {
24
- e.preventDefault(); // <-- important
25
- $(this).ajaxSubmit({
26
- target: '#output'
27
- });
28
- });
29
- });
30
-
31
- Use ajaxForm when you want the plugin to manage all the event binding
32
- for you. For example,
33
-
34
- $(document).ready(function() {
35
- $('#myForm').ajaxForm({
36
- target: '#output'
37
- });
38
- });
39
-
40
- You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
41
- form does not have to exist when you invoke ajaxForm:
42
-
43
- $('#myForm').ajaxForm({
44
- delegation: true,
45
- target: '#output'
46
- });
47
-
48
- When using ajaxForm, the ajaxSubmit function will be invoked for you
49
- at the appropriate time.
50
- */
51
-
52
- /**
53
- * Feature detection
54
- */
55
- var feature = {};
56
- feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
57
- feature.formdata = window.FormData !== undefined;
58
-
59
- var hasProp = !!$.fn.prop;
60
-
61
- // attr2 uses prop when it can but checks the return type for
62
- // an expected string. this accounts for the case where a form
63
- // contains inputs with names like "action" or "method"; in those
64
- // cases "prop" returns the element
65
- $.fn.attr2 = function() {
66
- if ( ! hasProp )
67
- return this.attr.apply(this, arguments);
68
- var val = this.prop.apply(this, arguments);
69
- if ( ( val && val.jquery ) || typeof val === 'string' )
70
- return val;
71
- return this.attr.apply(this, arguments);
72
- };
73
-
74
- /**
75
- * ajaxSubmit() provides a mechanism for immediately submitting
76
- * an HTML form using AJAX.
77
- */
78
- $.fn.ajaxSubmit = function(options) {
79
- /*jshint scripturl:true */
80
-
81
- // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
82
- if (!this.length) {
83
- log('ajaxSubmit: skipping submit process - no element selected');
84
- return this;
85
- }
86
-
87
- var method, action, url, $form = this;
88
-
89
- if (typeof options == 'function') {
90
- options = { success: options };
91
- }
92
-
93
- method = options.type || this.attr2('method');
94
- action = options.url || this.attr2('action');
95
-
96
- url = (typeof action === 'string') ? $.trim(action) : '';
97
- url = url || window.location.href || '';
98
- if (url) {
99
- // clean url (don't include hash vaue)
100
- url = (url.match(/^([^#]+)/)||[])[1];
101
- }
102
-
103
- options = $.extend(true, {
104
- url: url,
105
- success: $.ajaxSettings.success,
106
- type: method || 'GET',
107
- iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
108
- }, options);
109
-
110
- // hook for manipulating the form data before it is extracted;
111
- // convenient for use with rich editors like tinyMCE or FCKEditor
112
- var veto = {};
113
- this.trigger('form-pre-serialize', [this, options, veto]);
114
- if (veto.veto) {
115
- log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
116
- return this;
117
- }
118
-
119
- // provide opportunity to alter form data before it is serialized
120
- if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
121
- log('ajaxSubmit: submit aborted via beforeSerialize callback');
122
- return this;
123
- }
124
-
125
- var traditional = options.traditional;
126
- if ( traditional === undefined ) {
127
- traditional = $.ajaxSettings.traditional;
128
- }
129
-
130
- var elements = [];
131
- var qx, a = this.formToArray(options.semantic, elements);
132
- if (options.data) {
133
- options.extraData = options.data;
134
- qx = $.param(options.data, traditional);
135
- }
136
-
137
- // give pre-submit callback an opportunity to abort the submit
138
- if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
139
- log('ajaxSubmit: submit aborted via beforeSubmit callback');
140
- return this;
141
- }
142
-
143
- // fire vetoable 'validate' event
144
- this.trigger('form-submit-validate', [a, this, options, veto]);
145
- if (veto.veto) {
146
- log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
147
- return this;
148
- }
149
-
150
- var q = $.param(a, traditional);
151
- if (qx) {
152
- q = ( q ? (q + '&' + qx) : qx );
153
- }
154
- if (options.type.toUpperCase() == 'GET') {
155
- options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
156
- options.data = null; // data is null for 'get'
157
- }
158
- else {
159
- options.data = q; // data is the query string for 'post'
160
- }
161
-
162
- var callbacks = [];
163
- if (options.resetForm) {
164
- callbacks.push(function() { $form.resetForm(); });
165
- }
166
- if (options.clearForm) {
167
- callbacks.push(function() { $form.clearForm(options.includeHidden); });
168
- }
169
-
170
- // perform a load on the target only if dataType is not provided
171
- if (!options.dataType && options.target) {
172
- var oldSuccess = options.success || function(){};
173
- callbacks.push(function(data) {
174
- var fn = options.replaceTarget ? 'replaceWith' : 'html';
175
- $(options.target)[fn](data).each(oldSuccess, arguments);
176
- });
177
- }
178
- else if (options.success) {
179
- callbacks.push(options.success);
180
- }
181
-
182
- options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
183
- var context = options.context || this ; // jQuery 1.4+ supports scope context
184
- for (var i=0, max=callbacks.length; i < max; i++) {
185
- callbacks[i].apply(context, [data, status, xhr || $form, $form]);
186
- }
187
- };
188
-
189
- if (options.error) {
190
- var oldError = options.error;
191
- options.error = function(xhr, status, error) {
192
- var context = options.context || this;
193
- oldError.apply(context, [xhr, status, error, $form]);
194
- };
195
- }
196
-
197
- if (options.complete) {
198
- var oldComplete = options.complete;
199
- options.complete = function(xhr, status) {
200
- var context = options.context || this;
201
- oldComplete.apply(context, [xhr, status, $form]);
202
- };
203
- }
204
-
205
- // are there files to upload?
206
-
207
- // [value] (issue #113), also see comment:
208
- // https://github.com/malsup/form/commit/588306aedba1de01388032d5f42a60159eea9228#commitcomment-2180219
209
- var fileInputs = $('input[type=file]:enabled[value!=""]', this);
210
-
211
- var hasFileInputs = fileInputs.length > 0;
212
- var mp = 'multipart/form-data';
213
- var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
214
-
215
- var fileAPI = feature.fileapi && feature.formdata;
216
- log("fileAPI :" + fileAPI);
217
- var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
218
-
219
- var jqxhr;
220
-
221
- // options.iframe allows user to force iframe mode
222
- // 06-NOV-09: now defaulting to iframe mode if file input is detected
223
- if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
224
- // hack to fix Safari hang (thanks to Tim Molendijk for this)
225
- // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
226
- if (options.closeKeepAlive) {
227
- $.get(options.closeKeepAlive, function() {
228
- jqxhr = fileUploadIframe(a);
229
- });
230
- }
231
- else {
232
- jqxhr = fileUploadIframe(a);
233
- }
234
- }
235
- else if ((hasFileInputs || multipart) && fileAPI) {
236
- jqxhr = fileUploadXhr(a);
237
- }
238
- else {
239
- jqxhr = $.ajax(options);
240
- }
241
-
242
- $form.removeData('jqxhr').data('jqxhr', jqxhr);
243
-
244
- // clear element array
245
- for (var k=0; k < elements.length; k++)
246
- elements[k] = null;
247
-
248
- // fire 'notify' event
249
- this.trigger('form-submit-notify', [this, options]);
250
- return this;
251
-
252
- // utility fn for deep serialization
253
- function deepSerialize(extraData){
254
- var serialized = $.param(extraData, options.traditional).split('&');
255
- var len = serialized.length;
256
- var result = [];
257
- var i, part;
258
- for (i=0; i < len; i++) {
259
- // #252; undo param space replacement
260
- serialized[i] = serialized[i].replace(/\+/g,' ');
261
- part = serialized[i].split('=');
262
- // #278; use array instead of object storage, favoring array serializations
263
- result.push([decodeURIComponent(part[0]), decodeURIComponent(part[1])]);
264
- }
265
- return result;
266
- }
267
-
268
- // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
269
- function fileUploadXhr(a) {
270
- var formdata = new FormData();
271
-
272
- for (var i=0; i < a.length; i++) {
273
- formdata.append(a[i].name, a[i].value);
274
- }
275
-
276
- if (options.extraData) {
277
- var serializedData = deepSerialize(options.extraData);
278
- for (i=0; i < serializedData.length; i++)
279
- if (serializedData[i])
280
- formdata.append(serializedData[i][0], serializedData[i][1]);
281
- }
282
-
283
- options.data = null;
284
-
285
- var s = $.extend(true, {}, $.ajaxSettings, options, {
286
- contentType: false,
287
- processData: false,
288
- cache: false,
289
- type: method || 'POST'
290
- });
291
-
292
- if (options.uploadProgress) {
293
- // workaround because jqXHR does not expose upload property
294
- s.xhr = function() {
295
- var xhr = $.ajaxSettings.xhr();
296
- if (xhr.upload) {
297
- xhr.upload.addEventListener('progress', function(event) {
298
- var percent = 0;
299
- var position = event.loaded || event.position; /*event.position is deprecated*/
300
- var total = event.total;
301
- if (event.lengthComputable) {
302
- percent = Math.ceil(position / total * 100);
303
- }
304
- options.uploadProgress(event, position, total, percent);
305
- }, false);
306
- }
307
- return xhr;
308
- };
309
- }
310
-
311
- s.data = null;
312
- var beforeSend = s.beforeSend;
313
- s.beforeSend = function(xhr, o) {
314
- o.data = formdata;
315
- if(beforeSend)
316
- beforeSend.call(this, xhr, o);
317
- };
318
- return $.ajax(s);
319
- }
320
-
321
- // private function for handling file uploads (hat tip to YAHOO!)
322
- function fileUploadIframe(a) {
323
- var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
324
- var deferred = $.Deferred();
325
-
326
- if (a) {
327
- // ensure that every serialized input is still enabled
328
- for (i=0; i < elements.length; i++) {
329
- el = $(elements[i]);
330
- if ( hasProp )
331
- el.prop('disabled', false);
332
- else
333
- el.removeAttr('disabled');
334
- }
335
- }
336
-
337
- s = $.extend(true, {}, $.ajaxSettings, options);
338
- s.context = s.context || s;
339
- id = 'jqFormIO' + (new Date().getTime());
340
- if (s.iframeTarget) {
341
- $io = $(s.iframeTarget);
342
- n = $io.attr2('name');
343
- if (!n)
344
- $io.attr2('name', id);
345
- else
346
- id = n;
347
- }
348
- else {
349
- $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
350
- $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
351
- }
352
- io = $io[0];
353
-
354
-
355
- xhr = { // mock object
356
- aborted: 0,
357
- responseText: null,
358
- responseXML: null,
359
- status: 0,
360
- statusText: 'n/a',
361
- getAllResponseHeaders: function() {},
362
- getResponseHeader: function() {},
363
- setRequestHeader: function() {},
364
- abort: function(status) {
365
- var e = (status === 'timeout' ? 'timeout' : 'aborted');
366
- log('aborting upload... ' + e);
367
- this.aborted = 1;
368
-
369
- try { // #214, #257
370
- if (io.contentWindow.document.execCommand) {
371
- io.contentWindow.document.execCommand('Stop');
372
- }
373
- }
374
- catch(ignore) {}
375
-
376
- $io.attr('src', s.iframeSrc); // abort op in progress
377
- xhr.error = e;
378
- if (s.error)
379
- s.error.call(s.context, xhr, e, status);
380
- if (g)
381
- $.event.trigger("ajaxError", [xhr, s, e]);
382
- if (s.complete)
383
- s.complete.call(s.context, xhr, e);
384
- }
385
- };
386
-
387
- g = s.global;
388
- // trigger ajax global events so that activity/block indicators work like normal
389
- if (g && 0 === $.active++) {
390
- $.event.trigger("ajaxStart");
391
- }
392
- if (g) {
393
- $.event.trigger("ajaxSend", [xhr, s]);
394
- }
395
-
396
- if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
397
- if (s.global) {
398
- $.active--;
399
- }
400
- deferred.reject();
401
- return deferred;
402
- }
403
- if (xhr.aborted) {
404
- deferred.reject();
405
- return deferred;
406
- }
407
-
408
- // add submitting element to data if we know it
409
- sub = form.clk;
410
- if (sub) {
411
- n = sub.name;
412
- if (n && !sub.disabled) {
413
- s.extraData = s.extraData || {};
414
- s.extraData[n] = sub.value;
415
- if (sub.type == "image") {
416
- s.extraData[n+'.x'] = form.clk_x;
417
- s.extraData[n+'.y'] = form.clk_y;
418
- }
419
- }
420
- }
421
-
422
- var CLIENT_TIMEOUT_ABORT = 1;
423
- var SERVER_ABORT = 2;
424
-
425
- function getDoc(frame) {
426
- /* it looks like contentWindow or contentDocument do not
427
- * carry the protocol property in ie8, when running under ssl
428
- * frame.document is the only valid response document, since
429
- * the protocol is know but not on the other two objects. strange?
430
- * "Same origin policy" http://en.wikipedia.org/wiki/Same_origin_policy
431
- */
432
-
433
- var doc = null;
434
-
435
- // IE8 cascading access check
436
- try {
437
- if (frame.contentWindow) {
438
- doc = frame.contentWindow.document;
439
- }
440
- } catch(err) {
441
- // IE8 access denied under ssl & missing protocol
442
- log('cannot get iframe.contentWindow document: ' + err);
443
- }
444
-
445
- if (doc) { // successful getting content
446
- return doc;
447
- }
448
-
449
- try { // simply checking may throw in ie8 under ssl or mismatched protocol
450
- doc = frame.contentDocument ? frame.contentDocument : frame.document;
451
- } catch(err) {
452
- // last attempt
453
- log('cannot get iframe.contentDocument: ' + err);
454
- doc = frame.document;
455
- }
456
- return doc;
457
- }
458
-
459
- // Rails CSRF hack (thanks to Yvan Barthelemy)
460
- var csrf_token = $('meta[name=csrf-token]').attr('content');
461
- var csrf_param = $('meta[name=csrf-param]').attr('content');
462
- if (csrf_param && csrf_token) {
463
- s.extraData = s.extraData || {};
464
- s.extraData[csrf_param] = csrf_token;
465
- }
466
-
467
- // take a breath so that pending repaints get some cpu time before the upload starts
468
- function doSubmit() {
469
- // make sure form attrs are set
470
- var t = $form.attr2('target'), a = $form.attr2('action');
471
-
472
- // update form attrs in IE friendly way
473
- form.setAttribute('target',id);
474
- if (!method) {
475
- form.setAttribute('method', 'POST');
476
- }
477
- if (a != s.url) {
478
- form.setAttribute('action', s.url);
479
- }
480
-
481
- // ie borks in some cases when setting encoding
482
- if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
483
- $form.attr({
484
- encoding: 'multipart/form-data',
485
- enctype: 'multipart/form-data'
486
- });
487
- }
488
-
489
- // support timout
490
- if (s.timeout) {
491
- timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
492
- }
493
-
494
- // look for server aborts
495
- function checkState() {
496
- try {
497
- var state = getDoc(io).readyState;
498
- log('state = ' + state);
499
- if (state && state.toLowerCase() == 'uninitialized')
500
- setTimeout(checkState,50);
501
- }
502
- catch(e) {
503
- log('Server abort: ' , e, ' (', e.name, ')');
504
- cb(SERVER_ABORT);
505
- if (timeoutHandle)
506
- clearTimeout(timeoutHandle);
507
- timeoutHandle = undefined;
508
- }
509
- }
510
-
511
- // add "extra" data to form if provided in options
512
- var extraInputs = [];
513
- try {
514
- if (s.extraData) {
515
- for (var n in s.extraData) {
516
- if (s.extraData.hasOwnProperty(n)) {
517
- // if using the $.param format that allows for multiple values with the same name
518
- if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
519
- extraInputs.push(
520
- $('<input type="hidden" name="'+s.extraData[n].name+'">').val(s.extraData[n].value)
521
- .appendTo(form)[0]);
522
- } else {
523
- extraInputs.push(
524
- $('<input type="hidden" name="'+n+'">').val(s.extraData[n])
525
- .appendTo(form)[0]);
526
- }
527
- }
528
- }
529
- }
530
-
531
- if (!s.iframeTarget) {
532
- // add iframe to doc and submit the form
533
- $io.appendTo('body');
534
- if (io.attachEvent)
535
- io.attachEvent('onload', cb);
536
- else
537
- io.addEventListener('load', cb, false);
538
- }
539
- setTimeout(checkState,15);
540
-
541
- try {
542
- form.submit();
543
- } catch(err) {
544
- // just in case form has element with name/id of 'submit'
545
- var submitFn = document.createElement('form').submit;
546
- submitFn.apply(form);
547
- }
548
- }
549
- finally {
550
- // reset attrs and remove "extra" input elements
551
- form.setAttribute('action',a);
552
- if(t) {
553
- form.setAttribute('target', t);
554
- } else {
555
- $form.removeAttr('target');
556
- }
557
- $(extraInputs).remove();
558
- }
559
- }
560
-
561
- if (s.forceSync) {
562
- doSubmit();
563
- }
564
- else {
565
- setTimeout(doSubmit, 10); // this lets dom updates render
566
- }
567
-
568
- var data, doc, domCheckCount = 50, callbackProcessed;
569
-
570
- function cb(e) {
571
- if (xhr.aborted || callbackProcessed) {
572
- return;
573
- }
574
-
575
- doc = getDoc(io);
576
- if(!doc) {
577
- log('cannot access response document');
578
- e = SERVER_ABORT;
579
- }
580
- if (e === CLIENT_TIMEOUT_ABORT && xhr) {
581
- xhr.abort('timeout');
582
- deferred.reject(xhr, 'timeout');
583
- return;
584
- }
585
- else if (e == SERVER_ABORT && xhr) {
586
- xhr.abort('server abort');
587
- deferred.reject(xhr, 'error', 'server abort');
588
- return;
589
- }
590
-
591
- if (!doc || doc.location.href == s.iframeSrc) {
592
- // response not received yet
593
- if (!timedOut)
594
- return;
595
- }
596
- if (io.detachEvent)
597
- io.detachEvent('onload', cb);
598
- else
599
- io.removeEventListener('load', cb, false);
600
-
601
- var status = 'success', errMsg;
602
- try {
603
- if (timedOut) {
604
- throw 'timeout';
605
- }
606
-
607
- var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
608
- log('isXml='+isXml);
609
- if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
610
- if (--domCheckCount) {
611
- // in some browsers (Opera) the iframe DOM is not always traversable when
612
- // the onload callback fires, so we loop a bit to accommodate
613
- log('requeing onLoad callback, DOM not available');
614
- setTimeout(cb, 250);
615
- return;
616
- }
617
- // let this fall through because server response could be an empty document
618
- //log('Could not access iframe DOM after mutiple tries.');
619
- //throw 'DOMException: not available';
620
- }
621
-
622
- //log('response detected');
623
- var docRoot = doc.body ? doc.body : doc.documentElement;
624
- xhr.responseText = docRoot ? docRoot.innerHTML : null;
625
- xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
626
- if (isXml)
627
- s.dataType = 'xml';
628
- xhr.getResponseHeader = function(header){
629
- var headers = {'content-type': s.dataType};
630
- return headers[header];
631
- };
632
- // support for XHR 'status' & 'statusText' emulation :
633
- if (docRoot) {
634
- xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
635
- xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
636
- }
637
-
638
- var dt = (s.dataType || '').toLowerCase();
639
- var scr = /(json|script|text)/.test(dt);
640
- if (scr || s.textarea) {
641
- // see if user embedded response in textarea
642
- var ta = doc.getElementsByTagName('textarea')[0];
643
- if (ta) {
644
- xhr.responseText = ta.value;
645
- // support for XHR 'status' & 'statusText' emulation :
646
- xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
647
- xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
648
- }
649
- else if (scr) {
650
- // account for browsers injecting pre around json response
651
- var pre = doc.getElementsByTagName('pre')[0];
652
- var b = doc.getElementsByTagName('body')[0];
653
- if (pre) {
654
- xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
655
- }
656
- else if (b) {
657
- xhr.responseText = b.textContent ? b.textContent : b.innerText;
658
- }
659
- }
660
- }
661
- else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
662
- xhr.responseXML = toXml(xhr.responseText);
663
- }
664
-
665
- try {
666
- data = httpData(xhr, dt, s);
667
- }
668
- catch (err) {
669
- status = 'parsererror';
670
- xhr.error = errMsg = (err || status);
671
- }
672
- }
673
- catch (err) {
674
- log('error caught: ',err);
675
- status = 'error';
676
- xhr.error = errMsg = (err || status);
677
- }
678
-
679
- if (xhr.aborted) {
680
- log('upload aborted');
681
- status = null;
682
- }
683
-
684
- if (xhr.status) { // we've set xhr.status
685
- status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
686
- }
687
-
688
- // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
689
- if (status === 'success') {
690
- if (s.success)
691
- s.success.call(s.context, data, 'success', xhr);
692
- deferred.resolve(xhr.responseText, 'success', xhr);
693
- if (g)
694
- $.event.trigger("ajaxSuccess", [xhr, s]);
695
- }
696
- else if (status) {
697
- if (errMsg === undefined)
698
- errMsg = xhr.statusText;
699
- if (s.error)
700
- s.error.call(s.context, xhr, status, errMsg);
701
- deferred.reject(xhr, 'error', errMsg);
702
- if (g)
703
- $.event.trigger("ajaxError", [xhr, s, errMsg]);
704
- }
705
-
706
- if (g)
707
- $.event.trigger("ajaxComplete", [xhr, s]);
708
-
709
- if (g && ! --$.active) {
710
- $.event.trigger("ajaxStop");
711
- }
712
-
713
- if (s.complete)
714
- s.complete.call(s.context, xhr, status);
715
-
716
- callbackProcessed = true;
717
- if (s.timeout)
718
- clearTimeout(timeoutHandle);
719
-
720
- // clean up
721
- setTimeout(function() {
722
- if (!s.iframeTarget)
723
- $io.remove();
724
- xhr.responseXML = null;
725
- }, 100);
726
- }
727
-
728
- var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
729
- if (window.ActiveXObject) {
730
- doc = new ActiveXObject('Microsoft.XMLDOM');
731
- doc.async = 'false';
732
- doc.loadXML(s);
733
- }
734
- else {
735
- doc = (new DOMParser()).parseFromString(s, 'text/xml');
736
- }
737
- return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
738
- };
739
- var parseJSON = $.parseJSON || function(s) {
740
- /*jslint evil:true */
741
- return window['eval']('(' + s + ')');
742
- };
743
-
744
- var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
745
-
746
- var ct = xhr.getResponseHeader('content-type') || '',
747
- xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
748
- data = xml ? xhr.responseXML : xhr.responseText;
749
-
750
- if (xml && data.documentElement.nodeName === 'parsererror') {
751
- if ($.error)
752
- $.error('parsererror');
753
- }
754
- if (s && s.dataFilter) {
755
- data = s.dataFilter(data, type);
756
- }
757
- if (typeof data === 'string') {
758
- if (type === 'json' || !type && ct.indexOf('json') >= 0) {
759
- data = parseJSON(data);
760
- } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
761
- $.globalEval(data);
762
- }
763
- }
764
- return data;
765
- };
766
-
767
- return deferred;
768
- }
769
- };
770
-
771
- /**
772
- * ajaxForm() provides a mechanism for fully automating form submission.
773
- *
774
- * The advantages of using this method instead of ajaxSubmit() are:
775
- *
776
- * 1: This method will include coordinates for <input type="image" /> elements (if the element
777
- * is used to submit the form).
778
- * 2. This method will include the submit element's name/value data (for the element that was
779
- * used to submit the form).
780
- * 3. This method binds the submit() method to the form for you.
781
- *
782
- * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
783
- * passes the options argument along after properly binding events for submit elements and
784
- * the form itself.
785
- */
786
- $.fn.ajaxForm = function(options) {
787
- options = options || {};
788
- options.delegation = options.delegation && $.isFunction($.fn.on);
789
-
790
- // in jQuery 1.3+ we can fix mistakes with the ready state
791
- if (!options.delegation && this.length === 0) {
792
- var o = { s: this.selector, c: this.context };
793
- if (!$.isReady && o.s) {
794
- log('DOM not ready, queuing ajaxForm');
795
- $(function() {
796
- $(o.s,o.c).ajaxForm(options);
797
- });
798
- return this;
799
- }
800
- // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
801
- log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
802
- return this;
803
- }
804
-
805
- if ( options.delegation ) {
806
- $(document)
807
- .off('submit.form-plugin', this.selector, doAjaxSubmit)
808
- .off('click.form-plugin', this.selector, captureSubmittingElement)
809
- .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
810
- .on('click.form-plugin', this.selector, options, captureSubmittingElement);
811
- return this;
812
- }
813
-
814
- return this.ajaxFormUnbind()
815
- .bind('submit.form-plugin', options, doAjaxSubmit)
816
- .bind('click.form-plugin', options, captureSubmittingElement);
817
- };
818
-
819
- // private event handlers
820
- function doAjaxSubmit(e) {
821
- /*jshint validthis:true */
822
- var options = e.data;
823
- if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
824
- e.preventDefault();
825
- $(this).ajaxSubmit(options);
826
- }
827
- }
828
-
829
- function captureSubmittingElement(e) {
830
- /*jshint validthis:true */
831
- var target = e.target;
832
- var $el = $(target);
833
- if (!($el.is("[type=submit],[type=image]"))) {
834
- // is this a child element of the submit el? (ex: a span within a button)
835
- var t = $el.closest('[type=submit]');
836
- if (t.length === 0) {
837
- return;
838
- }
839
- target = t[0];
840
- }
841
- var form = this;
842
- form.clk = target;
843
- if (target.type == 'image') {
844
- if (e.offsetX !== undefined) {
845
- form.clk_x = e.offsetX;
846
- form.clk_y = e.offsetY;
847
- } else if (typeof $.fn.offset == 'function') {
848
- var offset = $el.offset();
849
- form.clk_x = e.pageX - offset.left;
850
- form.clk_y = e.pageY - offset.top;
851
- } else {
852
- form.clk_x = e.pageX - target.offsetLeft;
853
- form.clk_y = e.pageY - target.offsetTop;
854
- }
855
- }
856
- // clear form vars
857
- setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
858
- }
859
-
860
-
861
- // ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
862
- $.fn.ajaxFormUnbind = function() {
863
- return this.unbind('submit.form-plugin click.form-plugin');
864
- };
865
-
866
- /**
867
- * formToArray() gathers form element data into an array of objects that can
868
- * be passed to any of the following ajax functions: $.get, $.post, or load.
869
- * Each object in the array has both a 'name' and 'value' property. An example of
870
- * an array for a simple login form might be:
871
- *
872
- * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
873
- *
874
- * It is this array that is passed to pre-submit callback functions provided to the
875
- * ajaxSubmit() and ajaxForm() methods.
876
- */
877
- $.fn.formToArray = function(semantic, elements) {
878
- var a = [];
879
- if (this.length === 0) {
880
- return a;
881
- }
882
-
883
- var form = this[0];
884
- var els = semantic ? form.getElementsByTagName('*') : form.elements;
885
- if (!els) {
886
- return a;
887
- }
888
-
889
- var i,j,n,v,el,max,jmax;
890
- for(i=0, max=els.length; i < max; i++) {
891
- el = els[i];
892
- n = el.name;
893
- if (!n || el.disabled) {
894
- continue;
895
- }
896
-
897
- if (semantic && form.clk && el.type == "image") {
898
- // handle image inputs on the fly when semantic == true
899
- if(form.clk == el) {
900
- a.push({name: n, value: $(el).val(), type: el.type });
901
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
902
- }
903
- continue;
904
- }
905
-
906
- v = $.fieldValue(el, true);
907
- if (v && v.constructor == Array) {
908
- if (elements)
909
- elements.push(el);
910
- for(j=0, jmax=v.length; j < jmax; j++) {
911
- a.push({name: n, value: v[j]});
912
- }
913
- }
914
- else if (feature.fileapi && el.type == 'file') {
915
- if (elements)
916
- elements.push(el);
917
- var files = el.files;
918
- if (files.length) {
919
- for (j=0; j < files.length; j++) {
920
- a.push({name: n, value: files[j], type: el.type});
921
- }
922
- }
923
- else {
924
- // #180
925
- a.push({ name: n, value: '', type: el.type });
926
- }
927
- }
928
- else if (v !== null && typeof v != 'undefined') {
929
- if (elements)
930
- elements.push(el);
931
- a.push({name: n, value: v, type: el.type, required: el.required});
932
- }
933
- }
934
-
935
- if (!semantic && form.clk) {
936
- // input type=='image' are not found in elements array! handle it here
937
- var $input = $(form.clk), input = $input[0];
938
- n = input.name;
939
- if (n && !input.disabled && input.type == 'image') {
940
- a.push({name: n, value: $input.val()});
941
- a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
942
- }
943
- }
944
- return a;
945
- };
946
-
947
- /**
948
- * Serializes form data into a 'submittable' string. This method will return a string
949
- * in the format: name1=value1&amp;name2=value2
950
- */
951
- $.fn.formSerialize = function(semantic) {
952
- //hand off to jQuery.param for proper encoding
953
- return $.param(this.formToArray(semantic));
954
- };
955
-
956
- /**
957
- * Serializes all field elements in the jQuery object into a query string.
958
- * This method will return a string in the format: name1=value1&amp;name2=value2
959
- */
960
- $.fn.fieldSerialize = function(successful) {
961
- var a = [];
962
- this.each(function() {
963
- var n = this.name;
964
- if (!n) {
965
- return;
966
- }
967
- var v = $.fieldValue(this, successful);
968
- if (v && v.constructor == Array) {
969
- for (var i=0,max=v.length; i < max; i++) {
970
- a.push({name: n, value: v[i]});
971
- }
972
- }
973
- else if (v !== null && typeof v != 'undefined') {
974
- a.push({name: this.name, value: v});
975
- }
976
- });
977
- //hand off to jQuery.param for proper encoding
978
- return $.param(a);
979
- };
980
-
981
- /**
982
- * Returns the value(s) of the element in the matched set. For example, consider the following form:
983
- *
984
- * <form><fieldset>
985
- * <input name="A" type="text" />
986
- * <input name="A" type="text" />
987
- * <input name="B" type="checkbox" value="B1" />
988
- * <input name="B" type="checkbox" value="B2"/>
989
- * <input name="C" type="radio" value="C1" />
990
- * <input name="C" type="radio" value="C2" />
991
- * </fieldset></form>
992
- *
993
- * var v = $('input[type=text]').fieldValue();
994
- * // if no values are entered into the text inputs
995
- * v == ['','']
996
- * // if values entered into the text inputs are 'foo' and 'bar'
997
- * v == ['foo','bar']
998
- *
999
- * var v = $('input[type=checkbox]').fieldValue();
1000
- * // if neither checkbox is checked
1001
- * v === undefined
1002
- * // if both checkboxes are checked
1003
- * v == ['B1', 'B2']
1004
- *
1005
- * var v = $('input[type=radio]').fieldValue();
1006
- * // if neither radio is checked
1007
- * v === undefined
1008
- * // if first radio is checked
1009
- * v == ['C1']
1010
- *
1011
- * The successful argument controls whether or not the field element must be 'successful'
1012
- * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
1013
- * The default value of the successful argument is true. If this value is false the value(s)
1014
- * for each element is returned.
1015
- *
1016
- * Note: This method *always* returns an array. If no valid value can be determined the
1017
- * array will be empty, otherwise it will contain one or more values.
1018
- */
1019
- $.fn.fieldValue = function(successful) {
1020
- for (var val=[], i=0, max=this.length; i < max; i++) {
1021
- var el = this[i];
1022
- var v = $.fieldValue(el, successful);
1023
- if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
1024
- continue;
1025
- }
1026
- if (v.constructor == Array)
1027
- $.merge(val, v);
1028
- else
1029
- val.push(v);
1030
- }
1031
- return val;
1032
- };
1033
-
1034
- /**
1035
- * Returns the value of the field element.
1036
- */
1037
- $.fieldValue = function(el, successful) {
1038
- var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
1039
- if (successful === undefined) {
1040
- successful = true;
1041
- }
1042
-
1043
- if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
1044
- (t == 'checkbox' || t == 'radio') && !el.checked ||
1045
- (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
1046
- tag == 'select' && el.selectedIndex == -1)) {
1047
- return null;
1048
- }
1049
-
1050
- if (tag == 'select') {
1051
- var index = el.selectedIndex;
1052
- if (index < 0) {
1053
- return null;
1054
- }
1055
- var a = [], ops = el.options;
1056
- var one = (t == 'select-one');
1057
- var max = (one ? index+1 : ops.length);
1058
- for(var i=(one ? index : 0); i < max; i++) {
1059
- var op = ops[i];
1060
- if (op.selected) {
1061
- var v = op.value;
1062
- if (!v) { // extra pain for IE...
1063
- v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
1064
- }
1065
- if (one) {
1066
- return v;
1067
- }
1068
- a.push(v);
1069
- }
1070
- }
1071
- return a;
1072
- }
1073
- return $(el).val();
1074
- };
1075
-
1076
- /**
1077
- * Clears the form data. Takes the following actions on the form's input fields:
1078
- * - input text fields will have their 'value' property set to the empty string
1079
- * - select elements will have their 'selectedIndex' property set to -1
1080
- * - checkbox and radio inputs will have their 'checked' property set to false
1081
- * - inputs of type submit, button, reset, and hidden will *not* be effected
1082
- * - button elements will *not* be effected
1083
- */
1084
- $.fn.clearForm = function(includeHidden) {
1085
- return this.each(function() {
1086
- $('input,select,textarea', this).clearFields(includeHidden);
1087
- });
1088
- };
1089
-
1090
- /**
1091
- * Clears the selected form elements.
1092
- */
1093
- $.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
1094
- var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
1095
- return this.each(function() {
1096
- var t = this.type, tag = this.tagName.toLowerCase();
1097
- if (re.test(t) || tag == 'textarea') {
1098
- this.value = '';
1099
- }
1100
- else if (t == 'checkbox' || t == 'radio') {
1101
- this.checked = false;
1102
- }
1103
- else if (tag == 'select') {
1104
- this.selectedIndex = -1;
1105
- }
1106
- else if (t == "file") {
1107
- if (/MSIE/.test(navigator.userAgent)) {
1108
- $(this).replaceWith($(this).clone(true));
1109
- } else {
1110
- $(this).val('');
1111
- }
1112
- }
1113
- else if (includeHidden) {
1114
- // includeHidden can be the value true, or it can be a selector string
1115
- // indicating a special test; for example:
1116
- // $('#myForm').clearForm('.special:hidden')
1117
- // the above would clean hidden inputs that have the class of 'special'
1118
- if ( (includeHidden === true && /hidden/.test(t)) ||
1119
- (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
1120
- this.value = '';
1121
- }
1122
- });
1123
- };
1124
-
1125
- /**
1126
- * Resets the form data. Causes all form elements to be reset to their original value.
1127
- */
1128
- $.fn.resetForm = function() {
1129
- return this.each(function() {
1130
- // guard against an input with the name of 'reset'
1131
- // note that IE reports the reset function as an 'object'
1132
- if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
1133
- this.reset();
1134
- }
1135
- });
1136
- };
1137
-
1138
- /**
1139
- * Enables or disables any matching elements.
1140
- */
1141
- $.fn.enable = function(b) {
1142
- if (b === undefined) {
1143
- b = true;
1144
- }
1145
- return this.each(function() {
1146
- this.disabled = !b;
1147
- });
1148
- };
1149
-
1150
- /**
1151
- * Checks/unchecks any matching checkboxes or radio buttons and
1152
- * selects/deselects and matching option elements.
1153
- */
1154
- $.fn.selected = function(select) {
1155
- if (select === undefined) {
1156
- select = true;
1157
- }
1158
- return this.each(function() {
1159
- var t = this.type;
1160
- if (t == 'checkbox' || t == 'radio') {
1161
- this.checked = select;
1162
- }
1163
- else if (this.tagName.toLowerCase() == 'option') {
1164
- var $sel = $(this).parent('select');
1165
- if (select && $sel[0] && $sel[0].type == 'select-one') {
1166
- // deselect all other options
1167
- $sel.find('option').selected(false);
1168
- }
1169
- this.selected = select;
1170
- }
1171
- });
1172
- };
1173
-
1174
- // expose debug var
1175
- $.fn.ajaxSubmit.debug = false;
1176
-
1177
- // helper fn for console logging
1178
- function log() {
1179
- if (!$.fn.ajaxSubmit.debug)
1180
- return;
1181
- var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
1182
- if (window.console && window.console.log) {
1183
- window.console.log(msg);
1184
- }
1185
- else if (window.opera && window.opera.postError) {
1186
- window.opera.postError(msg);
1187
- }
1188
- }
1189
-
1190
- })(jQuery);