fomantic-ui-sass 2.8.8.1 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +4 -0
  3. data/app/assets/fonts/semantic-ui/Lato-Bold.woff +0 -0
  4. data/app/assets/fonts/semantic-ui/Lato-Bold.woff2 +0 -0
  5. data/app/assets/fonts/semantic-ui/Lato-BoldItalic.woff +0 -0
  6. data/app/assets/fonts/semantic-ui/Lato-BoldItalic.woff2 +0 -0
  7. data/app/assets/fonts/semantic-ui/Lato-Italic.woff +0 -0
  8. data/app/assets/fonts/semantic-ui/Lato-Italic.woff2 +0 -0
  9. data/app/assets/fonts/semantic-ui/Lato-Regular.woff +0 -0
  10. data/app/assets/fonts/semantic-ui/Lato-Regular.woff2 +0 -0
  11. data/app/assets/fonts/semantic-ui/LatoLatin-Bold.woff +0 -0
  12. data/app/assets/fonts/semantic-ui/LatoLatin-Bold.woff2 +0 -0
  13. data/app/assets/fonts/semantic-ui/LatoLatin-BoldItalic.woff +0 -0
  14. data/app/assets/fonts/semantic-ui/LatoLatin-BoldItalic.woff2 +0 -0
  15. data/app/assets/fonts/semantic-ui/LatoLatin-Italic.woff +0 -0
  16. data/app/assets/fonts/semantic-ui/LatoLatin-Italic.woff2 +0 -0
  17. data/app/assets/fonts/semantic-ui/LatoLatin-Regular.woff +0 -0
  18. data/app/assets/fonts/semantic-ui/LatoLatin-Regular.woff2 +0 -0
  19. data/app/assets/fonts/semantic-ui/brand-icons.eot +0 -0
  20. data/app/assets/fonts/semantic-ui/brand-icons.svg +41 -6
  21. data/app/assets/fonts/semantic-ui/brand-icons.ttf +0 -0
  22. data/app/assets/fonts/semantic-ui/brand-icons.woff +0 -0
  23. data/app/assets/fonts/semantic-ui/brand-icons.woff2 +0 -0
  24. data/app/assets/fonts/semantic-ui/icons.eot +0 -0
  25. data/app/assets/fonts/semantic-ui/icons.svg +245 -7
  26. data/app/assets/fonts/semantic-ui/icons.ttf +0 -0
  27. data/app/assets/fonts/semantic-ui/icons.woff +0 -0
  28. data/app/assets/fonts/semantic-ui/icons.woff2 +0 -0
  29. data/app/assets/fonts/semantic-ui/outline-icons.eot +0 -0
  30. data/app/assets/fonts/semantic-ui/outline-icons.svg +2 -2
  31. data/app/assets/fonts/semantic-ui/outline-icons.ttf +0 -0
  32. data/app/assets/fonts/semantic-ui/outline-icons.woff +0 -0
  33. data/app/assets/fonts/semantic-ui/outline-icons.woff2 +0 -0
  34. data/app/assets/javascripts/semantic-ui/accordion.js +569 -590
  35. data/app/assets/javascripts/semantic-ui/api.js +1153 -1116
  36. data/app/assets/javascripts/semantic-ui/calendar.js +1941 -1698
  37. data/app/assets/javascripts/semantic-ui/checkbox.js +862 -854
  38. data/app/assets/javascripts/semantic-ui/dimmer.js +697 -713
  39. data/app/assets/javascripts/semantic-ui/dropdown.js +4196 -4192
  40. data/app/assets/javascripts/semantic-ui/embed.js +646 -672
  41. data/app/assets/javascripts/semantic-ui/flyout.js +1579 -0
  42. data/app/assets/javascripts/semantic-ui/form.js +2024 -2000
  43. data/app/assets/javascripts/semantic-ui/modal.js +1546 -1384
  44. data/app/assets/javascripts/semantic-ui/nag.js +521 -527
  45. data/app/assets/javascripts/semantic-ui/popup.js +1457 -1463
  46. data/app/assets/javascripts/semantic-ui/progress.js +970 -995
  47. data/app/assets/javascripts/semantic-ui/rating.js +508 -520
  48. data/app/assets/javascripts/semantic-ui/search.js +1521 -1508
  49. data/app/assets/javascripts/semantic-ui/shape.js +784 -811
  50. data/app/assets/javascripts/semantic-ui/sidebar.js +1061 -1002
  51. data/app/assets/javascripts/semantic-ui/site.js +437 -477
  52. data/app/assets/javascripts/semantic-ui/slider.js +1311 -1297
  53. data/app/assets/javascripts/semantic-ui/state.js +639 -658
  54. data/app/assets/javascripts/semantic-ui/sticky.js +848 -891
  55. data/app/assets/javascripts/semantic-ui/tab.js +895 -941
  56. data/app/assets/javascripts/semantic-ui/toast.js +911 -851
  57. data/app/assets/javascripts/semantic-ui/transition.js +1049 -1073
  58. data/app/assets/javascripts/semantic-ui/visibility.js +1214 -1246
  59. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +7 -7
  60. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +389 -407
  61. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +203 -345
  62. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +372 -501
  63. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +154 -226
  64. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +2065 -880
  65. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +867 -1232
  66. data/app/assets/stylesheets/semantic-ui/elements/_container.scss +101 -6
  67. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +75 -93
  68. data/app/assets/stylesheets/semantic-ui/elements/_emoji.scss +11148 -9190
  69. data/app/assets/stylesheets/semantic-ui/elements/_flag.scss +1037 -929
  70. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +124 -146
  71. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +2728 -2759
  72. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +41 -65
  73. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +982 -163
  74. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +432 -479
  75. data/app/assets/stylesheets/semantic-ui/elements/_list.scss +80 -101
  76. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +452 -540
  77. data/app/assets/stylesheets/semantic-ui/elements/_placeholder.scss +56 -76
  78. data/app/assets/stylesheets/semantic-ui/elements/_rail.scss +17 -22
  79. data/app/assets/stylesheets/semantic-ui/elements/_reveal.scss +46 -85
  80. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +263 -255
  81. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +106 -179
  82. data/app/assets/stylesheets/semantic-ui/elements/_text.scss +33 -33
  83. data/app/assets/stylesheets/semantic-ui/globals/_reset.scss +14 -18
  84. data/app/assets/stylesheets/semantic-ui/globals/_site.scss +132 -48
  85. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +196 -74
  86. data/app/assets/stylesheets/semantic-ui/modules/_calendar.scss +43 -29
  87. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +210 -280
  88. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +78 -182
  89. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +339 -423
  90. data/app/assets/stylesheets/semantic-ui/modules/_embed.scss +24 -35
  91. data/app/assets/stylesheets/semantic-ui/modules/_flyout.scss +546 -0
  92. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +150 -153
  93. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +55 -65
  94. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +530 -310
  95. data/app/assets/stylesheets/semantic-ui/modules/_progress.scss +108 -213
  96. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +88 -168
  97. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +73 -102
  98. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +16 -32
  99. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +126 -215
  100. data/app/assets/stylesheets/semantic-ui/modules/_slider.scss +110 -138
  101. data/app/assets/stylesheets/semantic-ui/modules/_sticky.scss +3 -7
  102. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +16 -20
  103. data/app/assets/stylesheets/semantic-ui/modules/_toast.scss +111 -141
  104. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +371 -1282
  105. data/app/assets/stylesheets/semantic-ui/views/_ad.scss +39 -50
  106. data/app/assets/stylesheets/semantic-ui/views/_card.scss +949 -458
  107. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +44 -62
  108. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +50 -72
  109. data/app/assets/stylesheets/semantic-ui/views/_item.scss +89 -136
  110. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +78 -119
  111. data/lib/fomantic/ui/sass/version.rb +2 -2
  112. data/tasks/converter.rb +1 -1
  113. metadata +21 -3
@@ -1,1177 +1,1214 @@
1
1
  /*!
2
2
  * # Fomantic-UI - API
3
- * http://github.com/fomantic/Fomantic-UI/
3
+ * https://github.com/fomantic/Fomantic-UI/
4
4
  *
5
5
  *
6
6
  * Released under the MIT license
7
- * http://opensource.org/licenses/MIT
7
+ * https://opensource.org/licenses/MIT
8
8
  *
9
9
  */
10
10
 
11
- ;(function ($, window, document, undefined) {
12
-
13
- 'use strict';
14
-
15
- $.isWindow = $.isWindow || function(obj) {
16
- return obj != null && obj === obj.window;
17
- };
18
-
19
- window = (typeof window != 'undefined' && window.Math == Math)
20
- ? window
21
- : (typeof self != 'undefined' && self.Math == Math)
22
- ? self
23
- : Function('return this')()
24
- ;
25
-
26
- $.api = $.fn.api = function(parameters) {
27
-
28
- var
29
- // use window context if none specified
30
- $allModules = $.isFunction(this)
31
- ? $(window)
32
- : $(this),
33
- moduleSelector = $allModules.selector || '',
34
- time = new Date().getTime(),
35
- performance = [],
36
-
37
- query = arguments[0],
38
- methodInvoked = (typeof query == 'string'),
39
- queryArguments = [].slice.call(arguments, 1),
40
-
41
- returnedValue
42
- ;
43
-
44
- $allModules
45
- .each(function() {
46
- var
47
- settings = ( $.isPlainObject(parameters) )
48
- ? $.extend(true, {}, $.fn.api.settings, parameters)
49
- : $.extend({}, $.fn.api.settings),
50
-
51
- // internal aliases
52
- namespace = settings.namespace,
53
- metadata = settings.metadata,
54
- selector = settings.selector,
55
- error = settings.error,
56
- className = settings.className,
57
-
58
- // define namespaces for modules
59
- eventNamespace = '.' + namespace,
60
- moduleNamespace = 'module-' + namespace,
61
-
62
- // element that creates request
63
- $module = $(this),
64
- $form = $module.closest(selector.form),
65
-
66
- // context used for state
67
- $context = (settings.stateContext)
68
- ? $(settings.stateContext)
69
- : $module,
70
-
71
- // request details
72
- ajaxSettings,
73
- requestSettings,
74
- url,
75
- data,
76
- requestStartTime,
77
-
78
- // standard module
79
- element = this,
80
- context = $context[0],
81
- instance = $module.data(moduleNamespace),
82
- module
83
- ;
84
-
85
- module = {
86
-
87
- initialize: function() {
88
- if(!methodInvoked) {
89
- module.bind.events();
90
- }
91
- module.instantiate();
92
- },
11
+ (function ($, window, document) {
12
+ 'use strict';
93
13
 
94
- instantiate: function() {
95
- module.verbose('Storing instance of module', module);
96
- instance = module;
97
- $module
98
- .data(moduleNamespace, instance)
99
- ;
100
- },
14
+ function isWindow(obj) {
15
+ return obj !== null && obj === obj.window;
16
+ }
101
17
 
102
- destroy: function() {
103
- module.verbose('Destroying previous module for', element);
104
- $module
105
- .removeData(moduleNamespace)
106
- .off(eventNamespace)
107
- ;
108
- },
18
+ function isFunction(obj) {
19
+ return typeof obj === 'function' && typeof obj.nodeType !== 'number';
20
+ }
109
21
 
110
- bind: {
111
- events: function() {
112
- var
113
- triggerEvent = module.get.event()
114
- ;
115
- if( triggerEvent ) {
116
- module.verbose('Attaching API events to element', triggerEvent);
117
- $module
118
- .on(triggerEvent + eventNamespace, module.event.trigger)
119
- ;
120
- }
121
- else if(settings.on == 'now') {
122
- module.debug('Querying API endpoint immediately');
123
- module.query();
124
- }
125
- }
126
- },
22
+ window = window !== undefined && window.Math === Math
23
+ ? window
24
+ : globalThis;
127
25
 
128
- decode: {
129
- json: function(response) {
130
- if(response !== undefined && typeof response == 'string') {
131
- try {
132
- response = JSON.parse(response);
133
- }
134
- catch(e) {
135
- // isnt json string
136
- }
137
- }
138
- return response;
139
- }
140
- },
26
+ $.fn.api = function (parameters) {
27
+ var
28
+ // use window context if none specified
29
+ $allModules = isFunction(this)
30
+ ? $(window)
31
+ : $(this),
32
+ moduleSelector = $allModules.selector || '',
33
+ time = Date.now(),
34
+ performance = [],
35
+
36
+ query = arguments[0],
37
+ methodInvoked = typeof query === 'string',
38
+ queryArguments = [].slice.call(arguments, 1),
39
+
40
+ returnedValue
41
+ ;
141
42
 
142
- read: {
143
- cachedResponse: function(url) {
43
+ $allModules.each(function () {
144
44
  var
145
- response
45
+ settings = $.isPlainObject(parameters)
46
+ ? $.extend(true, {}, $.fn.api.settings, parameters)
47
+ : $.extend({}, $.fn.api.settings),
48
+
49
+ // internal aliases
50
+ namespace = settings.namespace,
51
+ metadata = settings.metadata,
52
+ selector = settings.selector,
53
+ error = settings.error,
54
+ className = settings.className,
55
+
56
+ // define namespaces for modules
57
+ eventNamespace = '.' + namespace,
58
+ moduleNamespace = 'module-' + namespace,
59
+
60
+ // element that creates request
61
+ $module = $(this),
62
+ $form = $module.closest(selector.form),
63
+
64
+ // context used for state
65
+ $context = settings.stateContext
66
+ ? ([window, document].indexOf(settings.stateContext) < 0 ? $(document).find(settings.stateContext) : $(settings.stateContext))
67
+ : $module,
68
+
69
+ // request details
70
+ ajaxSettings,
71
+ requestSettings,
72
+ url,
73
+ data,
74
+ requestStartTime,
75
+ originalData,
76
+
77
+ // standard module
78
+ element = this,
79
+ context = $context[0],
80
+ instance = $module.data(moduleNamespace),
81
+ module
146
82
  ;
147
- if(window.Storage === undefined) {
148
- module.error(error.noStorage);
149
- return;
150
- }
151
- response = sessionStorage.getItem(url);
152
- module.debug('Using cached response', url, response);
153
- response = module.decode.json(response);
154
- return response;
155
- }
156
- },
157
- write: {
158
- cachedResponse: function(url, response) {
159
- if(response && response === '') {
160
- module.debug('Response empty, not caching', response);
161
- return;
162
- }
163
- if(window.Storage === undefined) {
164
- module.error(error.noStorage);
165
- return;
166
- }
167
- if( $.isPlainObject(response) ) {
168
- response = JSON.stringify(response);
169
- }
170
- sessionStorage.setItem(url, response);
171
- module.verbose('Storing cached response for url', url, response);
172
- }
173
- },
174
83
 
175
- query: function() {
84
+ module = {
176
85
 
177
- if(module.is.disabled()) {
178
- module.debug('Element is disabled API request aborted');
179
- return;
180
- }
86
+ initialize: function () {
87
+ if (!methodInvoked) {
88
+ originalData = settings.data;
89
+ module.bind.events();
90
+ }
91
+ module.instantiate();
92
+ },
93
+
94
+ instantiate: function () {
95
+ module.verbose('Storing instance of module', module);
96
+ instance = module;
97
+ $module
98
+ .data(moduleNamespace, instance)
99
+ ;
100
+ },
181
101
 
182
- if(module.is.loading()) {
183
- if(settings.interruptRequests) {
184
- module.debug('Interrupting previous request');
185
- module.abort();
186
- }
187
- else {
188
- module.debug('Cancelling request, previous request is still pending');
189
- return;
190
- }
191
- }
192
-
193
- // pass element metadata to url (value, text)
194
- if(settings.defaultData) {
195
- $.extend(true, settings.urlData, module.get.defaultData());
196
- }
197
-
198
- // Add form content
199
- if(settings.serializeForm) {
200
- settings.data = module.add.formData(settings.data);
201
- }
202
-
203
- // call beforesend and get any settings changes
204
- requestSettings = module.get.settings();
205
-
206
- // check if before send cancelled request
207
- if(requestSettings === false) {
208
- module.cancelled = true;
209
- module.error(error.beforeSend);
210
- return;
211
- }
212
- else {
213
- module.cancelled = false;
214
- }
215
-
216
- // get url
217
- url = module.get.templatedURL();
218
-
219
- if(!url && !module.is.mocked()) {
220
- module.error(error.missingURL);
221
- return;
222
- }
223
-
224
- // replace variables
225
- url = module.add.urlData( url );
226
- // missing url parameters
227
- if( !url && !module.is.mocked()) {
228
- return;
229
- }
230
-
231
- requestSettings.url = settings.base + url;
232
-
233
- // look for jQuery ajax parameters in settings
234
- ajaxSettings = $.extend(true, {}, settings, {
235
- type : settings.method || settings.type,
236
- data : data,
237
- url : settings.base + url,
238
- beforeSend : settings.beforeXHR,
239
- success : function() {},
240
- failure : function() {},
241
- complete : function() {}
242
- });
243
-
244
- module.debug('Querying URL', ajaxSettings.url);
245
- module.verbose('Using AJAX settings', ajaxSettings);
246
- if(settings.cache === 'local' && module.read.cachedResponse(url)) {
247
- module.debug('Response returned from local cache');
248
- module.request = module.create.request();
249
- module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
250
- return;
251
- }
252
-
253
- if( !settings.throttle ) {
254
- module.debug('Sending request', data, ajaxSettings.method);
255
- module.send.request();
256
- }
257
- else {
258
- if(!settings.throttleFirstRequest && !module.timer) {
259
- module.debug('Sending request', data, ajaxSettings.method);
260
- module.send.request();
261
- module.timer = setTimeout(function(){}, settings.throttle);
262
- }
263
- else {
264
- module.debug('Throttling request', settings.throttle);
265
- clearTimeout(module.timer);
266
- module.timer = setTimeout(function() {
267
- if(module.timer) {
268
- delete module.timer;
269
- }
270
- module.debug('Sending throttled request', data, ajaxSettings.method);
271
- module.send.request();
272
- }, settings.throttle);
273
- }
274
- }
102
+ destroy: function () {
103
+ module.verbose('Destroying previous module for', element);
104
+ $module
105
+ .removeData(moduleNamespace)
106
+ .off(eventNamespace)
107
+ ;
108
+ },
109
+
110
+ bind: {
111
+ events: function () {
112
+ var
113
+ triggerEvent = module.get.event()
114
+ ;
115
+ if (triggerEvent) {
116
+ module.verbose('Attaching API events to element', triggerEvent);
117
+ $module
118
+ .on(triggerEvent + eventNamespace, module.event.trigger)
119
+ ;
120
+ } else if (settings.on === 'now') {
121
+ module.debug('Querying API endpoint immediately');
122
+ module.query();
123
+ }
124
+ },
125
+ },
126
+
127
+ decode: {
128
+ json: function (response) {
129
+ if (response !== undefined && typeof response === 'string') {
130
+ try {
131
+ response = JSON.parse(response);
132
+ } catch (e) {
133
+ // isn't json string
134
+ }
135
+ }
136
+
137
+ return response;
138
+ },
139
+ },
140
+
141
+ read: {
142
+ cachedResponse: function (url) {
143
+ var
144
+ response
145
+ ;
146
+ if (window.Storage === undefined) {
147
+ module.error(error.noStorage);
148
+
149
+ return;
150
+ }
151
+ response = sessionStorage.getItem(url + module.get.normalizedData());
152
+ module.debug('Using cached response', url, settings.data, response);
153
+ response = module.decode.json(response);
154
+
155
+ return response;
156
+ },
157
+ },
158
+ write: {
159
+ cachedResponse: function (url, response) {
160
+ if (window.Storage === undefined) {
161
+ module.error(error.noStorage);
162
+
163
+ return;
164
+ }
165
+ if ($.isPlainObject(response)) {
166
+ response = JSON.stringify(response);
167
+ }
168
+ sessionStorage.setItem(url + module.get.normalizedData(), response);
169
+ module.verbose('Storing cached response for url', url, settings.data, response);
170
+ },
171
+ },
172
+
173
+ query: function () {
174
+ if (module.is.disabled()) {
175
+ module.debug('Element is disabled API request aborted');
176
+
177
+ return;
178
+ }
275
179
 
276
- },
180
+ if (module.is.loading()) {
181
+ if (settings.interruptRequests) {
182
+ module.debug('Interrupting previous request');
183
+ module.abort();
184
+ } else {
185
+ module.debug('Cancelling request, previous request is still pending');
277
186
 
278
- should: {
279
- removeError: function() {
280
- return ( settings.hideError === true || (settings.hideError === 'auto' && !module.is.form()) );
281
- }
282
- },
187
+ return;
188
+ }
189
+ }
283
190
 
284
- is: {
285
- disabled: function() {
286
- return ($module.filter(selector.disabled).length > 0);
287
- },
288
- expectingJSON: function() {
289
- return settings.dataType === 'json' || settings.dataType === 'jsonp';
290
- },
291
- form: function() {
292
- return $module.is('form') || $context.is('form');
293
- },
294
- mocked: function() {
295
- return (settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync);
296
- },
297
- input: function() {
298
- return $module.is('input');
299
- },
300
- loading: function() {
301
- return (module.request)
302
- ? (module.request.state() == 'pending')
303
- : false
304
- ;
305
- },
306
- abortedRequest: function(xhr) {
307
- if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
308
- module.verbose('XHR request determined to be aborted');
309
- return true;
310
- }
311
- else {
312
- module.verbose('XHR request was not aborted');
313
- return false;
314
- }
315
- },
316
- validResponse: function(response) {
317
- if( (!module.is.expectingJSON()) || !$.isFunction(settings.successTest) ) {
318
- module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
319
- return true;
320
- }
321
- module.debug('Checking JSON returned success', settings.successTest, response);
322
- if( settings.successTest(response) ) {
323
- module.debug('Response passed success test', response);
324
- return true;
325
- }
326
- else {
327
- module.debug('Response failed success test', response);
328
- return false;
329
- }
330
- }
331
- },
191
+ // pass element metadata to url (value, text)
192
+ if (settings.defaultData) {
193
+ $.extend(true, settings.urlData, module.get.defaultData());
194
+ }
332
195
 
333
- was: {
334
- cancelled: function() {
335
- return (module.cancelled || false);
336
- },
337
- succesful: function() {
338
- module.verbose('This behavior will be deleted due to typo. Use "was successful" instead.');
339
- return module.was.successful();
340
- },
341
- successful: function() {
342
- return (module.request && module.request.state() == 'resolved');
343
- },
344
- failure: function() {
345
- return (module.request && module.request.state() == 'rejected');
346
- },
347
- complete: function() {
348
- return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
349
- }
350
- },
196
+ // Add form content
197
+ if (settings.serializeForm) {
198
+ settings.data = module.add.formData(originalData || settings.data);
199
+ }
351
200
 
352
- add: {
353
- urlData: function(url, urlData) {
354
- var
355
- requiredVariables,
356
- optionalVariables
357
- ;
358
- if(url) {
359
- requiredVariables = url.match(settings.regExp.required);
360
- optionalVariables = url.match(settings.regExp.optional);
361
- urlData = urlData || settings.urlData;
362
- if(requiredVariables) {
363
- module.debug('Looking for required URL variables', requiredVariables);
364
- $.each(requiredVariables, function(index, templatedString) {
365
- var
366
- // allow legacy {$var} style
367
- variable = (templatedString.indexOf('$') !== -1)
368
- ? templatedString.substr(2, templatedString.length - 3)
369
- : templatedString.substr(1, templatedString.length - 2),
370
- value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
371
- ? urlData[variable]
372
- : ($module.data(variable) !== undefined)
373
- ? $module.data(variable)
374
- : ($context.data(variable) !== undefined)
375
- ? $context.data(variable)
376
- : urlData[variable]
377
- ;
378
- // remove value
379
- if(value === undefined) {
380
- module.error(error.requiredParameter, variable, url);
381
- url = false;
382
- return false;
383
- }
384
- else {
385
- module.verbose('Found required variable', variable, value);
386
- value = (settings.encodeParameters)
387
- ? module.get.urlEncodedValue(value)
388
- : value
201
+ // call beforesend and get any settings changes
202
+ requestSettings = module.get.settings();
203
+
204
+ // check if before send cancelled request
205
+ if (requestSettings === false) {
206
+ module.cancelled = true;
207
+ module.error(error.beforeSend);
208
+
209
+ return;
210
+ }
211
+
212
+ module.cancelled = false;
213
+
214
+ // get url
215
+ url = module.get.templatedURL();
216
+
217
+ if (!url && !module.is.mocked()) {
218
+ module.error(error.missingURL);
219
+
220
+ return;
221
+ }
222
+
223
+ // replace variables
224
+ url = module.add.urlData(url);
225
+ // missing url parameters
226
+ if (!url && !module.is.mocked()) {
227
+ return;
228
+ }
229
+
230
+ requestSettings.url = settings.base + url;
231
+
232
+ // look for jQuery ajax parameters in settings
233
+ ajaxSettings = $.extend(true, {}, settings, {
234
+ type: settings.method || settings.type,
235
+ data: data,
236
+ url: settings.base + url,
237
+ beforeSend: settings.beforeXHR,
238
+ success: function () {},
239
+ failure: function () {},
240
+ complete: function () {},
241
+ });
242
+
243
+ module.debug('Querying URL', ajaxSettings.url);
244
+ module.verbose('Using AJAX settings', ajaxSettings);
245
+ if (settings.cache === 'local' && module.read.cachedResponse(url)) {
246
+ module.debug('Response returned from local cache');
247
+ module.request = module.create.request();
248
+ module.request.resolveWith(context, [module.read.cachedResponse(url)]);
249
+
250
+ return;
251
+ }
252
+
253
+ if (!settings.throttle) {
254
+ module.debug('Sending request', data, ajaxSettings.method);
255
+ module.send.request();
256
+ } else {
257
+ if (!settings.throttleFirstRequest && !module.timer) {
258
+ module.debug('Sending request', data, ajaxSettings.method);
259
+ module.send.request();
260
+ module.timer = setTimeout(function () {}, settings.throttle);
261
+ } else {
262
+ module.debug('Throttling request', settings.throttle);
263
+ clearTimeout(module.timer);
264
+ module.timer = setTimeout(function () {
265
+ if (module.timer) {
266
+ delete module.timer;
267
+ }
268
+ module.debug('Sending throttled request', data, ajaxSettings.method);
269
+ module.send.request();
270
+ }, settings.throttle);
271
+ }
272
+ }
273
+ },
274
+
275
+ should: {
276
+ removeError: function () {
277
+ return settings.hideError === true || (settings.hideError === 'auto' && !module.is.form());
278
+ },
279
+ },
280
+
281
+ is: {
282
+ disabled: function () {
283
+ return $module.filter(selector.disabled).length > 0;
284
+ },
285
+ expectingJSON: function () {
286
+ return settings.dataType === 'json' || settings.dataType === 'jsonp';
287
+ },
288
+ form: function () {
289
+ return $module.is('form') || $context.is('form');
290
+ },
291
+ mocked: function () {
292
+ return settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync;
293
+ },
294
+ input: function () {
295
+ return $module.is('input');
296
+ },
297
+ loading: function () {
298
+ return module.request
299
+ ? module.request.state() === 'pending'
300
+ : false;
301
+ },
302
+ abortedRequest: function (xhr) {
303
+ if (xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
304
+ module.verbose('XHR request determined to be aborted');
305
+
306
+ return true;
307
+ }
308
+
309
+ module.verbose('XHR request was not aborted');
310
+
311
+ return false;
312
+ },
313
+ validResponse: function (response) {
314
+ if (!module.is.expectingJSON() || !isFunction(settings.successTest)) {
315
+ module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
316
+
317
+ return true;
318
+ }
319
+ module.debug('Checking JSON returned success', settings.successTest, response);
320
+ if (settings.successTest(response)) {
321
+ module.debug('Response passed success test', response);
322
+
323
+ return true;
324
+ }
325
+
326
+ module.debug('Response failed success test', response);
327
+
328
+ return false;
329
+ },
330
+ },
331
+
332
+ was: {
333
+ cancelled: function () {
334
+ return module.cancelled || false;
335
+ },
336
+ successful: function () {
337
+ return module.request && module.request.state() === 'resolved';
338
+ },
339
+ failure: function () {
340
+ return module.request && module.request.state() === 'rejected';
341
+ },
342
+ complete: function () {
343
+ return module.request && (module.request.state() === 'resolved' || module.request.state() === 'rejected');
344
+ },
345
+ },
346
+
347
+ add: {
348
+ urlData: function (url, urlData) {
349
+ var
350
+ requiredVariables,
351
+ optionalVariables
352
+ ;
353
+ if (url) {
354
+ requiredVariables = url.match(settings.regExp.required);
355
+ optionalVariables = url.match(settings.regExp.optional);
356
+ urlData = urlData || settings.urlData;
357
+ if (requiredVariables) {
358
+ module.debug('Looking for required URL variables', requiredVariables);
359
+ $.each(requiredVariables, function (index, templatedString) {
360
+ var
361
+ // allow legacy {$var} style
362
+ variable = templatedString.indexOf('$') !== -1
363
+ ? templatedString.slice(2, -1)
364
+ : templatedString.slice(1, -1),
365
+ value = $.isPlainObject(urlData) && urlData[variable] !== undefined
366
+ ? urlData[variable]
367
+ : ($module.data(variable) !== undefined
368
+ ? $module.data(variable)
369
+ : ($context.data(variable) !== undefined // eslint-disable-line unicorn/no-nested-ternary
370
+ ? $context.data(variable)
371
+ : urlData[variable]))
372
+ ;
373
+ // remove value
374
+ if (value === undefined) {
375
+ module.error(error.requiredParameter, variable, url);
376
+ url = false;
377
+
378
+ return false;
379
+ }
380
+
381
+ module.verbose('Found required variable', variable, value);
382
+ value = settings.encodeParameters
383
+ ? module.get.urlEncodedValue(value)
384
+ : value;
385
+ url = url.replace(templatedString, value);
386
+ });
387
+ }
388
+ if (optionalVariables) {
389
+ module.debug('Looking for optional URL variables', requiredVariables);
390
+ $.each(optionalVariables, function (index, templatedString) {
391
+ var
392
+ // allow legacy {/$var} style
393
+ variable = templatedString.indexOf('$') !== -1
394
+ ? templatedString.slice(3, -1)
395
+ : templatedString.slice(2, -1),
396
+ value = $.isPlainObject(urlData) && urlData[variable] !== undefined
397
+ ? urlData[variable]
398
+ : ($module.data(variable) !== undefined
399
+ ? $module.data(variable)
400
+ : ($context.data(variable) !== undefined // eslint-disable-line unicorn/no-nested-ternary
401
+ ? $context.data(variable)
402
+ : urlData[variable]))
403
+ ;
404
+ // optional replacement
405
+ if (value !== undefined) {
406
+ module.verbose('Optional variable Found', variable, value);
407
+ url = url.replace(templatedString, value);
408
+ } else {
409
+ module.verbose('Optional variable not found', variable);
410
+ // remove preceding slash if set
411
+ url = url.indexOf('/' + templatedString) !== -1
412
+ ? url.replace('/' + templatedString, '')
413
+ : url.replace(templatedString, '');
414
+ }
415
+ });
416
+ }
417
+ }
418
+
419
+ return url;
420
+ },
421
+ formData: function (data) {
422
+ var
423
+ formData = {},
424
+ hasOtherData,
425
+ useFormDataApi = settings.serializeForm === 'formdata'
426
+ ;
427
+ data = data || originalData || settings.data;
428
+ hasOtherData = $.isPlainObject(data);
429
+
430
+ if (useFormDataApi) {
431
+ formData = new FormData($form[0]);
432
+ settings.processData = settings.processData !== undefined ? settings.processData : false;
433
+ settings.contentType = settings.contentType !== undefined ? settings.contentType : false;
434
+ } else {
435
+ var
436
+ formArray = $form.serializeArray(),
437
+ pushes = {},
438
+ pushValues = {},
439
+ build = function (base, key, value) {
440
+ base[key] = value;
441
+
442
+ return base;
443
+ }
444
+ ;
445
+ // add files
446
+ $.each($('input[type="file"]', $form), function (i, tag) {
447
+ $.each($(tag)[0].files, function (j, file) {
448
+ formArray.push({ name: tag.name, value: file });
449
+ });
450
+ });
451
+ $.each(formArray, function (i, el) {
452
+ if (!settings.regExp.validate.test(el.name)) {
453
+ return;
454
+ }
455
+ var
456
+ isCheckbox = $('[name="' + el.name + '"]', $form).attr('type') === 'checkbox',
457
+ floatValue = parseFloat(el.value),
458
+ value = (isCheckbox && el.value === 'on')
459
+ || el.value === 'true'
460
+ || (String(floatValue) === el.value
461
+ ? floatValue
462
+ : (el.value === 'false' ? false : el.value)),
463
+ nameKeys = el.name.match(settings.regExp.key) || [],
464
+ pushKey = el.name.replace(/\[]$/, '')
465
+ ;
466
+ if (!(pushKey in pushes)) {
467
+ pushes[pushKey] = 0;
468
+ pushValues[pushKey] = value;
469
+ } else if (Array.isArray(pushValues[pushKey])) {
470
+ pushValues[pushKey].push(value);
471
+ } else {
472
+ pushValues[pushKey] = [pushValues[pushKey], value];
473
+ }
474
+ if (pushKey.indexOf('[]') === -1) {
475
+ value = pushValues[pushKey];
476
+ }
477
+
478
+ while (nameKeys.length > 0) {
479
+ var k = nameKeys.pop();
480
+
481
+ if (k === '' && !Array.isArray(value)) { // foo[]
482
+ value = build([], pushes[pushKey]++, value);
483
+ } else if (settings.regExp.fixed.test(k)) { // foo[n]
484
+ value = build([], k, value);
485
+ } else if (settings.regExp.named.test(k)) { // foo; foo[bar]
486
+ value = build({}, k, value);
487
+ }
488
+ }
489
+ formData = $.extend(true, formData, value);
490
+ });
491
+ }
492
+
493
+ if (hasOtherData) {
494
+ module.debug('Extending existing data with form data', data, formData);
495
+ if (useFormDataApi) {
496
+ $.each(Object.keys(data), function (i, el) {
497
+ formData.append(el, data[el]);
498
+ });
499
+ data = formData;
500
+ } else {
501
+ data = $.extend(true, {}, data, formData);
502
+ }
503
+ } else {
504
+ module.debug('Adding form data', formData);
505
+ data = formData;
506
+ }
507
+
508
+ return data;
509
+ },
510
+ },
511
+
512
+ send: {
513
+ request: function () {
514
+ module.set.loading();
515
+ module.request = module.create.request();
516
+ if (module.is.mocked()) {
517
+ module.mockedXHR = module.create.mockedXHR();
518
+ } else {
519
+ module.xhr = module.create.xhr();
520
+ }
521
+ settings.onRequest.call(context, module.request, module.xhr);
522
+ },
523
+ },
524
+
525
+ event: {
526
+ trigger: function (event) {
527
+ module.query();
528
+ if (event.type === 'submit' || event.type === 'click') {
529
+ event.preventDefault();
530
+ }
531
+ },
532
+ xhr: {
533
+ always: function () {
534
+ // nothing special
535
+ },
536
+ done: function (response, textStatus, xhr) {
537
+ var
538
+ context = this,
539
+ elapsedTime = Date.now() - requestStartTime,
540
+ timeLeft = settings.loadingDuration - elapsedTime,
541
+ translatedResponse = isFunction(settings.onResponse)
542
+ ? (module.is.expectingJSON() && !settings.rawResponse
543
+ ? settings.onResponse.call(context, $.extend(true, {}, response))
544
+ : settings.onResponse.call(context, response))
545
+ : false
546
+ ;
547
+ timeLeft = timeLeft > 0
548
+ ? timeLeft
549
+ : 0;
550
+ if (translatedResponse) {
551
+ module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
552
+ response = translatedResponse;
553
+ }
554
+ if (timeLeft > 0) {
555
+ module.debug('Response completed early delaying state change by', timeLeft);
556
+ }
557
+ setTimeout(function () {
558
+ if (module.is.validResponse(response)) {
559
+ module.request.resolveWith(context, [response, xhr]);
560
+ } else {
561
+ module.request.rejectWith(context, [xhr, 'invalid']);
562
+ }
563
+ }, timeLeft);
564
+ },
565
+ fail: function (xhr, status, httpMessage) {
566
+ var
567
+ context = this,
568
+ elapsedTime = Date.now() - requestStartTime,
569
+ timeLeft = settings.loadingDuration - elapsedTime
570
+ ;
571
+ timeLeft = timeLeft > 0
572
+ ? timeLeft
573
+ : 0;
574
+ if (timeLeft > 0) {
575
+ module.debug('Response completed early delaying state change by', timeLeft);
576
+ }
577
+ setTimeout(function () {
578
+ if (module.is.abortedRequest(xhr)) {
579
+ module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
580
+ } else {
581
+ module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
582
+ }
583
+ }, timeLeft);
584
+ },
585
+ },
586
+ request: {
587
+ done: function (response, xhr) {
588
+ module.debug('Successful API Response', response);
589
+ if (settings.cache === 'local' && url) {
590
+ module.write.cachedResponse(url, response);
591
+ module.debug('Saving server response locally', module.cache);
592
+ }
593
+ settings.onSuccess.call(context, response, $module, xhr);
594
+ },
595
+ complete: function (firstParameter, secondParameter) {
596
+ var
597
+ xhr,
598
+ response
599
+ ;
600
+ // have to guess callback parameters based on request success
601
+ if (module.was.successful()) {
602
+ response = firstParameter;
603
+ xhr = secondParameter;
604
+ } else {
605
+ xhr = firstParameter;
606
+ response = module.get.responseFromXHR(xhr);
607
+ }
608
+ module.remove.loading();
609
+ settings.onComplete.call(context, response, $module, xhr);
610
+ },
611
+ fail: function (xhr, status, httpMessage) {
612
+ var
613
+ // pull response from xhr if available
614
+ response = module.get.responseFromXHR(xhr),
615
+ errorMessage = module.get.errorFromRequest(response, status, httpMessage)
616
+ ;
617
+ if (status === 'aborted') {
618
+ module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
619
+ settings.onAbort.call(context, status, $module, xhr);
620
+
621
+ return true;
622
+ }
623
+ if (status === 'invalid') {
624
+ module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
625
+ } else if (status === 'error') {
626
+ if (xhr !== undefined) {
627
+ module.debug('XHR produced a server error', status, httpMessage);
628
+ // make sure we have an error to display to console
629
+ if ((xhr.status < 200 || xhr.status >= 300) && httpMessage !== undefined && httpMessage !== '') {
630
+ module.error(error.statusMessage + httpMessage, ajaxSettings.url);
631
+ }
632
+ settings.onError.call(context, errorMessage, $module, xhr);
633
+ }
634
+ }
635
+
636
+ if (settings.errorDuration && status !== 'aborted') {
637
+ module.debug('Adding error state');
638
+ module.set.error();
639
+ if (module.should.removeError()) {
640
+ setTimeout(module.remove.error, settings.errorDuration);
641
+ }
642
+ }
643
+ module.debug('API Request failed', errorMessage, xhr);
644
+ settings.onFailure.call(context, response, $module, xhr);
645
+ },
646
+ },
647
+ },
648
+
649
+ create: {
650
+
651
+ request: function () {
652
+ // api request promise
653
+ return $.Deferred()
654
+ .always(module.event.request.complete)
655
+ .done(module.event.request.done)
656
+ .fail(module.event.request.fail)
657
+ ;
658
+ },
659
+
660
+ mockedXHR: function () {
661
+ var
662
+ // xhr does not simulate these properties of xhr but must return them
663
+ textStatus = false,
664
+ status = false,
665
+ httpMessage = false,
666
+ responder = settings.mockResponse || settings.response,
667
+ asyncResponder = settings.mockResponseAsync || settings.responseAsync,
668
+ asyncCallback,
669
+ response,
670
+ mockedXHR
671
+ ;
672
+
673
+ mockedXHR = $.Deferred()
674
+ .always(module.event.xhr.complete)
675
+ .done(module.event.xhr.done)
676
+ .fail(module.event.xhr.fail)
677
+ ;
678
+
679
+ if (responder) {
680
+ if (isFunction(responder)) {
681
+ module.debug('Using specified synchronous callback', responder);
682
+ response = responder.call(context, requestSettings);
683
+ } else {
684
+ module.debug('Using settings specified response', responder);
685
+ response = responder;
686
+ }
687
+ // simulating response
688
+ mockedXHR.resolveWith(context, [response, textStatus, { responseText: response }]);
689
+ } else if (isFunction(asyncResponder)) {
690
+ asyncCallback = function (response) {
691
+ module.debug('Async callback returned response', response);
692
+
693
+ if (response) {
694
+ mockedXHR.resolveWith(context, [response, textStatus, { responseText: response }]);
695
+ } else {
696
+ mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
697
+ }
698
+ };
699
+ module.debug('Using specified async response callback', asyncResponder);
700
+ asyncResponder.call(context, requestSettings, asyncCallback);
701
+ }
702
+
703
+ return mockedXHR;
704
+ },
705
+
706
+ xhr: function () {
707
+ var
708
+ xhr
709
+ ;
710
+ // ajax request promise
711
+ xhr = $.ajax(ajaxSettings)
712
+ .always(module.event.xhr.always)
713
+ .done(module.event.xhr.done)
714
+ .fail(module.event.xhr.fail)
715
+ ;
716
+ module.verbose('Created server request', xhr, ajaxSettings);
717
+
718
+ return xhr;
719
+ },
720
+ },
721
+
722
+ set: {
723
+ error: function () {
724
+ module.verbose('Adding error state to element', $context);
725
+ $context.addClass(className.error);
726
+ },
727
+ loading: function () {
728
+ module.verbose('Adding loading state to element', $context);
729
+ $context.addClass(className.loading);
730
+ requestStartTime = Date.now();
731
+ },
732
+ },
733
+
734
+ remove: {
735
+ error: function () {
736
+ module.verbose('Removing error state from element', $context);
737
+ $context.removeClass(className.error);
738
+ },
739
+ loading: function () {
740
+ module.verbose('Removing loading state from element', $context);
741
+ $context.removeClass(className.loading);
742
+ },
743
+ },
744
+
745
+ get: {
746
+ normalizedData: function () {
747
+ return typeof settings.data === 'string' ? settings.data : JSON.stringify(settings.data, Object.keys(settings.data).sort());
748
+ },
749
+ responseFromXHR: function (xhr) {
750
+ return $.isPlainObject(xhr)
751
+ ? (module.is.expectingJSON()
752
+ ? module.decode.json(xhr.responseText)
753
+ : xhr.responseText)
754
+ : false;
755
+ },
756
+ errorFromRequest: function (response, status, httpMessage) {
757
+ return $.isPlainObject(response) && response.error !== undefined
758
+ ? response.error // use json error message
759
+ : (settings.error[status] !== undefined // use server error message
760
+ ? settings.error[status]
761
+ : httpMessage);
762
+ },
763
+ request: function () {
764
+ return module.request || false;
765
+ },
766
+ xhr: function () {
767
+ return module.xhr || false;
768
+ },
769
+ settings: function () {
770
+ var
771
+ runSettings
772
+ ;
773
+ runSettings = settings.beforeSend.call($module, settings);
774
+ if (runSettings) {
775
+ if (runSettings.success !== undefined) {
776
+ module.debug('Legacy success callback detected', runSettings);
777
+ module.error(error.legacyParameters, runSettings.success);
778
+ runSettings.onSuccess = runSettings.success;
779
+ }
780
+ if (runSettings.failure !== undefined) {
781
+ module.debug('Legacy failure callback detected', runSettings);
782
+ module.error(error.legacyParameters, runSettings.failure);
783
+ runSettings.onFailure = runSettings.failure;
784
+ }
785
+ if (runSettings.complete !== undefined) {
786
+ module.debug('Legacy complete callback detected', runSettings);
787
+ module.error(error.legacyParameters, runSettings.complete);
788
+ runSettings.onComplete = runSettings.complete;
789
+ }
790
+ }
791
+ if (runSettings === undefined) {
792
+ module.error(error.noReturnedValue);
793
+ }
794
+ if (runSettings === false) {
795
+ return runSettings;
796
+ }
797
+
798
+ return runSettings !== undefined
799
+ ? $.extend(true, {}, runSettings)
800
+ : $.extend(true, {}, settings);
801
+ },
802
+ urlEncodedValue: function (value) {
803
+ var
804
+ decodedValue = window.decodeURIComponent(value),
805
+ encodedValue = window.encodeURIComponent(value),
806
+ alreadyEncoded = decodedValue !== value
807
+ ;
808
+ if (alreadyEncoded) {
809
+ module.debug('URL value is already encoded, avoiding double encoding', value);
810
+
811
+ return value;
812
+ }
813
+ module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
814
+
815
+ return encodedValue;
816
+ },
817
+ defaultData: function () {
818
+ var
819
+ data = {}
820
+ ;
821
+ if (!isWindow(element)) {
822
+ if (module.is.input()) {
823
+ data.value = $module.val();
824
+ } else if (!module.is.form()) {
825
+ data.text = $module.text();
826
+ }
827
+ }
828
+
829
+ return data;
830
+ },
831
+ event: function () {
832
+ if (isWindow(element) || settings.on === 'now') {
833
+ module.debug('API called without element, no events attached');
834
+
835
+ return false;
836
+ }
837
+ if (settings.on === 'auto') {
838
+ if ($module.is('input')) {
839
+ return element.oninput !== undefined
840
+ ? 'input'
841
+ : (element.onpropertychange !== undefined
842
+ ? 'propertychange'
843
+ : 'keyup');
844
+ }
845
+ if ($module.is('form')) {
846
+ return 'submit';
847
+ }
848
+
849
+ return 'click';
850
+ }
851
+
852
+ return settings.on;
853
+ },
854
+ templatedURL: function (action) {
855
+ action = action || settings.action || $module.data(metadata.action) || false;
856
+ url = settings.url || $module.data(metadata.url) || false;
857
+ if (url) {
858
+ module.debug('Using specified url', url);
859
+
860
+ return url;
861
+ }
862
+ if (action) {
863
+ module.debug('Looking up url for action', action, settings.api);
864
+ if (settings.api[action] === undefined && !module.is.mocked()) {
865
+ module.error(error.missingAction, settings.action, settings.api);
866
+
867
+ return;
868
+ }
869
+ url = settings.api[action];
870
+ } else if (module.is.form()) {
871
+ url = $module.attr('action') || $context.attr('action') || false;
872
+ module.debug('No url or action specified, defaulting to form action', url);
873
+ }
874
+
875
+ return url;
876
+ },
877
+ },
878
+
879
+ abort: function () {
880
+ var
881
+ xhr = module.get.xhr()
389
882
  ;
390
- url = url.replace(templatedString, value);
391
- }
392
- });
393
- }
394
- if(optionalVariables) {
395
- module.debug('Looking for optional URL variables', requiredVariables);
396
- $.each(optionalVariables, function(index, templatedString) {
397
- var
398
- // allow legacy {/$var} style
399
- variable = (templatedString.indexOf('$') !== -1)
400
- ? templatedString.substr(3, templatedString.length - 4)
401
- : templatedString.substr(2, templatedString.length - 3),
402
- value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
403
- ? urlData[variable]
404
- : ($module.data(variable) !== undefined)
405
- ? $module.data(variable)
406
- : ($context.data(variable) !== undefined)
407
- ? $context.data(variable)
408
- : urlData[variable]
409
- ;
410
- // optional replacement
411
- if(value !== undefined) {
412
- module.verbose('Optional variable Found', variable, value);
413
- url = url.replace(templatedString, value);
414
- }
415
- else {
416
- module.verbose('Optional variable not found', variable);
417
- // remove preceding slash if set
418
- if(url.indexOf('/' + templatedString) !== -1) {
419
- url = url.replace('/' + templatedString, '');
883
+ if (xhr && xhr.state() !== 'resolved') {
884
+ module.debug('Cancelling API request');
885
+ xhr.abort();
420
886
  }
421
- else {
422
- url = url.replace(templatedString, '');
887
+ },
888
+
889
+ // reset state
890
+ reset: function () {
891
+ module.remove.error();
892
+ module.remove.loading();
893
+ },
894
+
895
+ setting: function (name, value) {
896
+ module.debug('Changing setting', name, value);
897
+ if ($.isPlainObject(name)) {
898
+ $.extend(true, settings, name);
899
+ } else if (value !== undefined) {
900
+ if ($.isPlainObject(settings[name])) {
901
+ $.extend(true, settings[name], value);
902
+ } else {
903
+ settings[name] = value;
904
+ }
905
+ } else {
906
+ return settings[name];
907
+ }
908
+ },
909
+ internal: function (name, value) {
910
+ if ($.isPlainObject(name)) {
911
+ $.extend(true, module, name);
912
+ } else if (value !== undefined) {
913
+ module[name] = value;
914
+ } else {
915
+ return module[name];
916
+ }
917
+ },
918
+ debug: function () {
919
+ if (!settings.silent && settings.debug) {
920
+ if (settings.performance) {
921
+ module.performance.log(arguments);
922
+ } else {
923
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
924
+ module.debug.apply(console, arguments);
925
+ }
926
+ }
927
+ },
928
+ verbose: function () {
929
+ if (!settings.silent && settings.verbose && settings.debug) {
930
+ if (settings.performance) {
931
+ module.performance.log(arguments);
932
+ } else {
933
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
934
+ module.verbose.apply(console, arguments);
935
+ }
936
+ }
937
+ },
938
+ error: function () {
939
+ if (!settings.silent) {
940
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
941
+ module.error.apply(console, arguments);
942
+ }
943
+ },
944
+ performance: {
945
+ log: function (message) {
946
+ var
947
+ currentTime,
948
+ executionTime,
949
+ previousTime
950
+ ;
951
+ if (settings.performance) {
952
+ currentTime = Date.now();
953
+ previousTime = time || currentTime;
954
+ executionTime = currentTime - previousTime;
955
+ time = currentTime;
956
+ performance.push({
957
+ Name: message[0],
958
+ Arguments: [].slice.call(message, 1) || '',
959
+ // 'Element' : element,
960
+ 'Execution Time': executionTime,
961
+ });
962
+ }
963
+ clearTimeout(module.performance.timer);
964
+ module.performance.timer = setTimeout(module.performance.display, 500);
965
+ },
966
+ display: function () {
967
+ var
968
+ title = settings.name + ':',
969
+ totalTime = 0
970
+ ;
971
+ time = false;
972
+ clearTimeout(module.performance.timer);
973
+ $.each(performance, function (index, data) {
974
+ totalTime += data['Execution Time'];
975
+ });
976
+ title += ' ' + totalTime + 'ms';
977
+ if (moduleSelector) {
978
+ title += ' \'' + moduleSelector + '\'';
979
+ }
980
+ if (performance.length > 0) {
981
+ console.groupCollapsed(title);
982
+ if (console.table) {
983
+ console.table(performance);
984
+ } else {
985
+ $.each(performance, function (index, data) {
986
+ console.log(data.Name + ': ' + data['Execution Time'] + 'ms');
987
+ });
988
+ }
989
+ console.groupEnd();
990
+ }
991
+ performance = [];
992
+ },
993
+ },
994
+ invoke: function (query, passedArguments, context) {
995
+ var
996
+ object = instance,
997
+ maxDepth,
998
+ found,
999
+ response
1000
+ ;
1001
+ passedArguments = passedArguments || queryArguments;
1002
+ context = context || element;
1003
+ if (typeof query === 'string' && object !== undefined) {
1004
+ query = query.split(/[ .]/);
1005
+ maxDepth = query.length - 1;
1006
+ $.each(query, function (depth, value) {
1007
+ var camelCaseValue = depth !== maxDepth
1008
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
1009
+ : query
1010
+ ;
1011
+ if ($.isPlainObject(object[camelCaseValue]) && (depth !== maxDepth)) {
1012
+ object = object[camelCaseValue];
1013
+ } else if (object[camelCaseValue] !== undefined) {
1014
+ found = object[camelCaseValue];
1015
+
1016
+ return false;
1017
+ } else if ($.isPlainObject(object[value]) && (depth !== maxDepth)) {
1018
+ object = object[value];
1019
+ } else if (object[value] !== undefined) {
1020
+ found = object[value];
1021
+
1022
+ return false;
1023
+ } else {
1024
+ module.error(error.method, query);
1025
+
1026
+ return false;
1027
+ }
1028
+ });
1029
+ }
1030
+ if (isFunction(found)) {
1031
+ response = found.apply(context, passedArguments);
1032
+ } else if (found !== undefined) {
1033
+ response = found;
1034
+ }
1035
+ if (Array.isArray(returnedValue)) {
1036
+ returnedValue.push(response);
1037
+ } else if (returnedValue !== undefined) {
1038
+ returnedValue = [returnedValue, response];
1039
+ } else if (response !== undefined) {
1040
+ returnedValue = response;
423
1041
  }
424
- }
425
- });
426
- }
427
- }
428
- return url;
429
- },
430
- formData: function(data) {
431
- var
432
- canSerialize = ($.fn.serializeObject !== undefined),
433
- formData = (canSerialize)
434
- ? $form.serializeObject()
435
- : $form.serialize(),
436
- hasOtherData
437
- ;
438
- data = data || settings.data;
439
- hasOtherData = $.isPlainObject(data);
440
-
441
- if(hasOtherData) {
442
- if(canSerialize) {
443
- module.debug('Extending existing data with form data', data, formData);
444
- data = $.extend(true, {}, data, formData);
445
- }
446
- else {
447
- module.error(error.missingSerialize);
448
- module.debug('Cant extend data. Replacing data with form data', data, formData);
449
- data = formData;
450
- }
451
- }
452
- else {
453
- module.debug('Adding form data', formData);
454
- data = formData;
455
- }
456
- return data;
457
- }
458
- },
459
1042
 
460
- send: {
461
- request: function() {
462
- module.set.loading();
463
- module.request = module.create.request();
464
- if( module.is.mocked() ) {
465
- module.mockedXHR = module.create.mockedXHR();
466
- }
467
- else {
468
- module.xhr = module.create.xhr();
469
- }
470
- settings.onRequest.call(context, module.request, module.xhr);
471
- }
472
- },
1043
+ return found;
1044
+ },
1045
+ };
473
1046
 
474
- event: {
475
- trigger: function(event) {
476
- module.query();
477
- if(event.type == 'submit' || event.type == 'click') {
478
- event.preventDefault();
479
- }
480
- },
481
- xhr: {
482
- always: function() {
483
- // nothing special
484
- },
485
- done: function(response, textStatus, xhr) {
486
- var
487
- context = this,
488
- elapsedTime = (new Date().getTime() - requestStartTime),
489
- timeLeft = (settings.loadingDuration - elapsedTime),
490
- translatedResponse = ( $.isFunction(settings.onResponse) )
491
- ? module.is.expectingJSON() && !settings.rawResponse
492
- ? settings.onResponse.call(context, $.extend(true, {}, response))
493
- : settings.onResponse.call(context, response)
494
- : false
495
- ;
496
- timeLeft = (timeLeft > 0)
497
- ? timeLeft
498
- : 0
499
- ;
500
- if(translatedResponse) {
501
- module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
502
- response = translatedResponse;
503
- }
504
- if(timeLeft > 0) {
505
- module.debug('Response completed early delaying state change by', timeLeft);
506
- }
507
- setTimeout(function() {
508
- if( module.is.validResponse(response) ) {
509
- module.request.resolveWith(context, [response, xhr]);
510
- }
511
- else {
512
- module.request.rejectWith(context, [xhr, 'invalid']);
513
- }
514
- }, timeLeft);
515
- },
516
- fail: function(xhr, status, httpMessage) {
517
- var
518
- context = this,
519
- elapsedTime = (new Date().getTime() - requestStartTime),
520
- timeLeft = (settings.loadingDuration - elapsedTime)
521
- ;
522
- timeLeft = (timeLeft > 0)
523
- ? timeLeft
524
- : 0
525
- ;
526
- if(timeLeft > 0) {
527
- module.debug('Response completed early delaying state change by', timeLeft);
528
- }
529
- setTimeout(function() {
530
- if( module.is.abortedRequest(xhr) ) {
531
- module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
1047
+ if (methodInvoked) {
1048
+ if (instance === undefined) {
1049
+ module.initialize();
532
1050
  }
533
- else {
534
- module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
1051
+ module.invoke(query);
1052
+ } else {
1053
+ if (instance !== undefined) {
1054
+ instance.invoke('destroy');
535
1055
  }
536
- }, timeLeft);
1056
+ module.initialize();
537
1057
  }
538
- },
539
- request: {
540
- done: function(response, xhr) {
541
- module.debug('Successful API Response', response);
542
- if(settings.cache === 'local' && url) {
543
- module.write.cachedResponse(url, response);
544
- module.debug('Saving server response locally', module.cache);
545
- }
546
- settings.onSuccess.call(context, response, $module, xhr);
547
- },
548
- complete: function(firstParameter, secondParameter) {
549
- var
550
- xhr,
551
- response
552
- ;
553
- // have to guess callback parameters based on request success
554
- if( module.was.successful() ) {
555
- response = firstParameter;
556
- xhr = secondParameter;
557
- }
558
- else {
559
- xhr = firstParameter;
560
- response = module.get.responseFromXHR(xhr);
561
- }
562
- module.remove.loading();
563
- settings.onComplete.call(context, response, $module, xhr);
564
- },
565
- fail: function(xhr, status, httpMessage) {
566
- var
567
- // pull response from xhr if available
568
- response = module.get.responseFromXHR(xhr),
569
- errorMessage = module.get.errorFromRequest(response, status, httpMessage)
570
- ;
571
- if(status == 'aborted') {
572
- module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
573
- settings.onAbort.call(context, status, $module, xhr);
574
- return true;
575
- }
576
- else if(status == 'invalid') {
577
- module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
578
- }
579
- else if(status == 'error') {
580
- if(xhr !== undefined) {
581
- module.debug('XHR produced a server error', status, httpMessage);
582
- // make sure we have an error to display to console
583
- if( (xhr.status < 200 || xhr.status >= 300) && httpMessage !== undefined && httpMessage !== '') {
584
- module.error(error.statusMessage + httpMessage, ajaxSettings.url);
585
- }
586
- settings.onError.call(context, errorMessage, $module, xhr);
587
- }
588
- }
1058
+ });
589
1059
 
590
- if(settings.errorDuration && status !== 'aborted') {
591
- module.debug('Adding error state');
592
- module.set.error();
593
- if( module.should.removeError() ) {
594
- setTimeout(module.remove.error, settings.errorDuration);
595
- }
596
- }
597
- module.debug('API Request failed', errorMessage, xhr);
598
- settings.onFailure.call(context, response, $module, xhr);
599
- }
600
- }
601
- },
1060
+ return returnedValue !== undefined
1061
+ ? returnedValue
1062
+ : this;
1063
+ };
1064
+ $.api = $.fn.api;
602
1065
 
603
- create: {
1066
+ $.api.settings = {
604
1067
 
605
- request: function() {
606
- // api request promise
607
- return $.Deferred()
608
- .always(module.event.request.complete)
609
- .done(module.event.request.done)
610
- .fail(module.event.request.fail)
611
- ;
612
- },
1068
+ name: 'API',
1069
+ namespace: 'api',
613
1070
 
614
- mockedXHR: function () {
615
- var
616
- // xhr does not simulate these properties of xhr but must return them
617
- textStatus = false,
618
- status = false,
619
- httpMessage = false,
620
- responder = settings.mockResponse || settings.response,
621
- asyncResponder = settings.mockResponseAsync || settings.responseAsync,
622
- asyncCallback,
623
- response,
624
- mockedXHR
625
- ;
1071
+ debug: false,
1072
+ verbose: false,
1073
+ performance: true,
626
1074
 
627
- mockedXHR = $.Deferred()
628
- .always(module.event.xhr.complete)
629
- .done(module.event.xhr.done)
630
- .fail(module.event.xhr.fail)
631
- ;
1075
+ // object containing all templates endpoints
1076
+ api: {},
632
1077
 
633
- if(responder) {
634
- if( $.isFunction(responder) ) {
635
- module.debug('Using specified synchronous callback', responder);
636
- response = responder.call(context, requestSettings);
637
- }
638
- else {
639
- module.debug('Using settings specified response', responder);
640
- response = responder;
641
- }
642
- // simulating response
643
- mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
644
- }
645
- else if( $.isFunction(asyncResponder) ) {
646
- asyncCallback = function(response) {
647
- module.debug('Async callback returned response', response);
1078
+ // whether to cache responses
1079
+ cache: true,
648
1080
 
649
- if(response) {
650
- mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
651
- }
652
- else {
653
- mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
654
- }
655
- };
656
- module.debug('Using specified async response callback', asyncResponder);
657
- asyncResponder.call(context, requestSettings, asyncCallback);
658
- }
659
- return mockedXHR;
660
- },
1081
+ // whether new requests should abort previous requests
1082
+ interruptRequests: true,
661
1083
 
662
- xhr: function() {
663
- var
664
- xhr
665
- ;
666
- // ajax request promise
667
- xhr = $.ajax(ajaxSettings)
668
- .always(module.event.xhr.always)
669
- .done(module.event.xhr.done)
670
- .fail(module.event.xhr.fail)
671
- ;
672
- module.verbose('Created server request', xhr, ajaxSettings);
673
- return xhr;
674
- }
675
- },
1084
+ // event binding
1085
+ on: 'auto',
676
1086
 
677
- set: {
678
- error: function() {
679
- module.verbose('Adding error state to element', $context);
680
- $context.addClass(className.error);
681
- },
682
- loading: function() {
683
- module.verbose('Adding loading state to element', $context);
684
- $context.addClass(className.loading);
685
- requestStartTime = new Date().getTime();
686
- }
687
- },
1087
+ // context for applying state classes
1088
+ stateContext: false,
688
1089
 
689
- remove: {
690
- error: function() {
691
- module.verbose('Removing error state from element', $context);
692
- $context.removeClass(className.error);
693
- },
694
- loading: function() {
695
- module.verbose('Removing loading state from element', $context);
696
- $context.removeClass(className.loading);
697
- }
698
- },
1090
+ // duration for loading state
1091
+ loadingDuration: 0,
699
1092
 
700
- get: {
701
- responseFromXHR: function(xhr) {
702
- return $.isPlainObject(xhr)
703
- ? (module.is.expectingJSON())
704
- ? module.decode.json(xhr.responseText)
705
- : xhr.responseText
706
- : false
707
- ;
708
- },
709
- errorFromRequest: function(response, status, httpMessage) {
710
- return ($.isPlainObject(response) && response.error !== undefined)
711
- ? response.error // use json error message
712
- : (settings.error[status] !== undefined) // use server error message
713
- ? settings.error[status]
714
- : httpMessage
715
- ;
716
- },
717
- request: function() {
718
- return module.request || false;
719
- },
720
- xhr: function() {
721
- return module.xhr || false;
722
- },
723
- settings: function() {
724
- var
725
- runSettings
726
- ;
727
- runSettings = settings.beforeSend.call($module, settings);
728
- if(runSettings) {
729
- if(runSettings.success !== undefined) {
730
- module.debug('Legacy success callback detected', runSettings);
731
- module.error(error.legacyParameters, runSettings.success);
732
- runSettings.onSuccess = runSettings.success;
733
- }
734
- if(runSettings.failure !== undefined) {
735
- module.debug('Legacy failure callback detected', runSettings);
736
- module.error(error.legacyParameters, runSettings.failure);
737
- runSettings.onFailure = runSettings.failure;
738
- }
739
- if(runSettings.complete !== undefined) {
740
- module.debug('Legacy complete callback detected', runSettings);
741
- module.error(error.legacyParameters, runSettings.complete);
742
- runSettings.onComplete = runSettings.complete;
743
- }
744
- }
745
- if(runSettings === undefined) {
746
- module.error(error.noReturnedValue);
747
- }
748
- if(runSettings === false) {
749
- return runSettings;
750
- }
751
- return (runSettings !== undefined)
752
- ? $.extend(true, {}, runSettings)
753
- : $.extend(true, {}, settings)
754
- ;
755
- },
756
- urlEncodedValue: function(value) {
757
- var
758
- decodedValue = window.decodeURIComponent(value),
759
- encodedValue = window.encodeURIComponent(value),
760
- alreadyEncoded = (decodedValue !== value)
761
- ;
762
- if(alreadyEncoded) {
763
- module.debug('URL value is already encoded, avoiding double encoding', value);
764
- return value;
765
- }
766
- module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
767
- return encodedValue;
768
- },
769
- defaultData: function() {
770
- var
771
- data = {}
772
- ;
773
- if( !$.isWindow(element) ) {
774
- if( module.is.input() ) {
775
- data.value = $module.val();
776
- }
777
- else if( module.is.form() ) {
778
-
779
- }
780
- else {
781
- data.text = $module.text();
782
- }
783
- }
784
- return data;
785
- },
786
- event: function() {
787
- if( $.isWindow(element) || settings.on == 'now' ) {
788
- module.debug('API called without element, no events attached');
789
- return false;
790
- }
791
- else if(settings.on == 'auto') {
792
- if( $module.is('input') ) {
793
- return (element.oninput !== undefined)
794
- ? 'input'
795
- : (element.onpropertychange !== undefined)
796
- ? 'propertychange'
797
- : 'keyup'
798
- ;
799
- }
800
- else if( $module.is('form') ) {
801
- return 'submit';
802
- }
803
- else {
804
- return 'click';
805
- }
806
- }
807
- else {
808
- return settings.on;
809
- }
810
- },
811
- templatedURL: function(action) {
812
- action = action || $module.data(metadata.action) || settings.action || false;
813
- url = $module.data(metadata.url) || settings.url || false;
814
- if(url) {
815
- module.debug('Using specified url', url);
816
- return url;
817
- }
818
- if(action) {
819
- module.debug('Looking up url for action', action, settings.api);
820
- if(settings.api[action] === undefined && !module.is.mocked()) {
821
- module.error(error.missingAction, settings.action, settings.api);
822
- return;
823
- }
824
- url = settings.api[action];
825
- }
826
- else if( module.is.form() ) {
827
- url = $module.attr('action') || $context.attr('action') || false;
828
- module.debug('No url or action specified, defaulting to form action', url);
829
- }
830
- return url;
831
- }
832
- },
1093
+ // whether to hide errors after a period of time
1094
+ hideError: 'auto',
833
1095
 
834
- abort: function() {
835
- var
836
- xhr = module.get.xhr()
837
- ;
838
- if( xhr && xhr.state() !== 'resolved') {
839
- module.debug('Cancelling API request');
840
- xhr.abort();
841
- }
842
- },
1096
+ // duration for error state
1097
+ errorDuration: 2000,
843
1098
 
844
- // reset state
845
- reset: function() {
846
- module.remove.error();
847
- module.remove.loading();
848
- },
1099
+ // whether parameters should be encoded with encodeURIComponent
1100
+ encodeParameters: true,
849
1101
 
850
- setting: function(name, value) {
851
- module.debug('Changing setting', name, value);
852
- if( $.isPlainObject(name) ) {
853
- $.extend(true, settings, name);
854
- }
855
- else if(value !== undefined) {
856
- if($.isPlainObject(settings[name])) {
857
- $.extend(true, settings[name], value);
858
- }
859
- else {
860
- settings[name] = value;
861
- }
862
- }
863
- else {
864
- return settings[name];
865
- }
866
- },
867
- internal: function(name, value) {
868
- if( $.isPlainObject(name) ) {
869
- $.extend(true, module, name);
870
- }
871
- else if(value !== undefined) {
872
- module[name] = value;
873
- }
874
- else {
875
- return module[name];
876
- }
877
- },
878
- debug: function() {
879
- if(!settings.silent && settings.debug) {
880
- if(settings.performance) {
881
- module.performance.log(arguments);
882
- }
883
- else {
884
- module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
885
- module.debug.apply(console, arguments);
886
- }
887
- }
888
- },
889
- verbose: function() {
890
- if(!settings.silent && settings.verbose && settings.debug) {
891
- if(settings.performance) {
892
- module.performance.log(arguments);
893
- }
894
- else {
895
- module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
896
- module.verbose.apply(console, arguments);
897
- }
898
- }
899
- },
900
- error: function() {
901
- if(!settings.silent) {
902
- module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
903
- module.error.apply(console, arguments);
904
- }
905
- },
906
- performance: {
907
- log: function(message) {
908
- var
909
- currentTime,
910
- executionTime,
911
- previousTime
912
- ;
913
- if(settings.performance) {
914
- currentTime = new Date().getTime();
915
- previousTime = time || currentTime;
916
- executionTime = currentTime - previousTime;
917
- time = currentTime;
918
- performance.push({
919
- 'Name' : message[0],
920
- 'Arguments' : [].slice.call(message, 1) || '',
921
- //'Element' : element,
922
- 'Execution Time' : executionTime
923
- });
924
- }
925
- clearTimeout(module.performance.timer);
926
- module.performance.timer = setTimeout(module.performance.display, 500);
927
- },
928
- display: function() {
929
- var
930
- title = settings.name + ':',
931
- totalTime = 0
932
- ;
933
- time = false;
934
- clearTimeout(module.performance.timer);
935
- $.each(performance, function(index, data) {
936
- totalTime += data['Execution Time'];
937
- });
938
- title += ' ' + totalTime + 'ms';
939
- if(moduleSelector) {
940
- title += ' \'' + moduleSelector + '\'';
941
- }
942
- if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
943
- console.groupCollapsed(title);
944
- if(console.table) {
945
- console.table(performance);
946
- }
947
- else {
948
- $.each(performance, function(index, data) {
949
- console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
950
- });
951
- }
952
- console.groupEnd();
953
- }
954
- performance = [];
955
- }
956
- },
957
- invoke: function(query, passedArguments, context) {
958
- var
959
- object = instance,
960
- maxDepth,
961
- found,
962
- response
963
- ;
964
- passedArguments = passedArguments || queryArguments;
965
- context = element || context;
966
- if(typeof query == 'string' && object !== undefined) {
967
- query = query.split(/[\. ]/);
968
- maxDepth = query.length - 1;
969
- $.each(query, function(depth, value) {
970
- var camelCaseValue = (depth != maxDepth)
971
- ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
972
- : query
973
- ;
974
- if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
975
- object = object[camelCaseValue];
976
- }
977
- else if( object[camelCaseValue] !== undefined ) {
978
- found = object[camelCaseValue];
979
- return false;
980
- }
981
- else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
982
- object = object[value];
983
- }
984
- else if( object[value] !== undefined ) {
985
- found = object[value];
986
- return false;
987
- }
988
- else {
989
- module.error(error.method, query);
990
- return false;
991
- }
992
- });
993
- }
994
- if ( $.isFunction( found ) ) {
995
- response = found.apply(context, passedArguments);
996
- }
997
- else if(found !== undefined) {
998
- response = found;
999
- }
1000
- if(Array.isArray(returnedValue)) {
1001
- returnedValue.push(response);
1002
- }
1003
- else if(returnedValue !== undefined) {
1004
- returnedValue = [returnedValue, response];
1005
- }
1006
- else if(response !== undefined) {
1007
- returnedValue = response;
1008
- }
1009
- return found;
1010
- }
1011
- };
1012
-
1013
- if(methodInvoked) {
1014
- if(instance === undefined) {
1015
- module.initialize();
1016
- }
1017
- module.invoke(query);
1018
- }
1019
- else {
1020
- if(instance !== undefined) {
1021
- instance.invoke('destroy');
1022
- }
1023
- module.initialize();
1024
- }
1025
- })
1026
- ;
1027
-
1028
- return (returnedValue !== undefined)
1029
- ? returnedValue
1030
- : this
1031
- ;
1032
- };
1033
-
1034
- $.api.settings = {
1035
-
1036
- name : 'API',
1037
- namespace : 'api',
1038
-
1039
- debug : false,
1040
- verbose : false,
1041
- performance : true,
1042
-
1043
- // object containing all templates endpoints
1044
- api : {},
1045
-
1046
- // whether to cache responses
1047
- cache : true,
1048
-
1049
- // whether new requests should abort previous requests
1050
- interruptRequests : true,
1051
-
1052
- // event binding
1053
- on : 'auto',
1054
-
1055
- // context for applying state classes
1056
- stateContext : false,
1057
-
1058
- // duration for loading state
1059
- loadingDuration : 0,
1060
-
1061
- // whether to hide errors after a period of time
1062
- hideError : 'auto',
1063
-
1064
- // duration for error state
1065
- errorDuration : 2000,
1066
-
1067
- // whether parameters should be encoded with encodeURIComponent
1068
- encodeParameters : true,
1069
-
1070
- // API action to use
1071
- action : false,
1072
-
1073
- // templated URL to use
1074
- url : false,
1075
-
1076
- // base URL to apply to all endpoints
1077
- base : '',
1078
-
1079
- // data that will
1080
- urlData : {},
1081
-
1082
- // whether to add default data to url data
1083
- defaultData : true,
1084
-
1085
- // whether to serialize closest form
1086
- serializeForm : false,
1087
-
1088
- // how long to wait before request should occur
1089
- throttle : 0,
1090
-
1091
- // whether to throttle first request or only repeated
1092
- throttleFirstRequest : true,
1093
-
1094
- // standard ajax settings
1095
- method : 'get',
1096
- data : {},
1097
- dataType : 'json',
1098
-
1099
- // mock response
1100
- mockResponse : false,
1101
- mockResponseAsync : false,
1102
-
1103
- // aliases for mock
1104
- response : false,
1105
- responseAsync : false,
1106
-
1107
- // whether onResponse should work with response value without force converting into an object
1108
- rawResponse : false,
1102
+ // API action to use
1103
+ action: false,
1109
1104
 
1110
- // callbacks before request
1111
- beforeSend : function(settings) { return settings; },
1112
- beforeXHR : function(xhr) {},
1113
- onRequest : function(promise, xhr) {},
1105
+ // templated URL to use
1106
+ url: false,
1114
1107
 
1115
- // after request
1116
- onResponse : false, // function(response) { },
1108
+ // base URL to apply to all endpoints
1109
+ base: '',
1117
1110
 
1118
- // response was successful, if JSON passed validation
1119
- onSuccess : function(response, $module) {},
1111
+ // data that will
1112
+ urlData: {},
1120
1113
 
1121
- // request finished without aborting
1122
- onComplete : function(response, $module) {},
1114
+ // whether to add default data to url data
1115
+ defaultData: true,
1123
1116
 
1124
- // failed JSON success test
1125
- onFailure : function(response, $module) {},
1117
+ // whether to serialize closest form
1118
+ // use true to convert complex named keys like a[b][1][c][] into a nested object
1119
+ // use 'formdata' for formdata web api
1120
+ serializeForm: false,
1126
1121
 
1127
- // server error
1128
- onError : function(errorMessage, $module) {},
1122
+ // how long to wait before request should occur
1123
+ throttle: 0,
1129
1124
 
1130
- // request aborted
1131
- onAbort : function(errorMessage, $module) {},
1125
+ // whether to throttle first request or only repeated
1126
+ throttleFirstRequest: true,
1132
1127
 
1133
- successTest : false,
1128
+ // standard ajax settings
1129
+ method: 'get',
1130
+ data: {},
1131
+ dataType: 'json',
1134
1132
 
1135
- // errors
1136
- error : {
1137
- beforeSend : 'The before send function has aborted the request',
1138
- error : 'There was an error with your request',
1139
- exitConditions : 'API Request Aborted. Exit conditions met',
1140
- JSONParse : 'JSON could not be parsed during error handling',
1141
- legacyParameters : 'You are using legacy API success callback names',
1142
- method : 'The method you called is not defined',
1143
- missingAction : 'API action used but no url was defined',
1144
- missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
1145
- missingURL : 'No URL specified for api event',
1146
- noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
1147
- noStorage : 'Caching responses locally requires session storage',
1148
- parseError : 'There was an error parsing your request',
1149
- requiredParameter : 'Missing a required URL parameter: ',
1150
- statusMessage : 'Server gave an error: ',
1151
- timeout : 'Your request timed out'
1152
- },
1133
+ // mock response
1134
+ mockResponse: false,
1135
+ mockResponseAsync: false,
1153
1136
 
1154
- regExp : {
1155
- required : /\{\$*[A-z0-9]+\}/g,
1156
- optional : /\{\/\$*[A-z0-9]+\}/g,
1157
- },
1137
+ // aliases for mock
1138
+ response: false,
1139
+ responseAsync: false,
1158
1140
 
1159
- className: {
1160
- loading : 'loading',
1161
- error : 'error'
1162
- },
1141
+ // whether onResponse should work with response value without force converting into an object
1142
+ rawResponse: true,
1163
1143
 
1164
- selector: {
1165
- disabled : '.disabled',
1166
- form : 'form'
1167
- },
1144
+ // callbacks before request
1145
+ beforeSend: function (settings) {
1146
+ return settings;
1147
+ },
1148
+ beforeXHR: function (xhr) {},
1149
+ onRequest: function (promise, xhr) {},
1150
+
1151
+ // after request
1152
+ onResponse: false, // function(response) { },
1153
+
1154
+ // response was successful, if JSON passed validation
1155
+ onSuccess: function (response, $module) {},
1156
+
1157
+ // request finished without aborting
1158
+ onComplete: function (response, $module) {},
1159
+
1160
+ // failed JSON success test
1161
+ onFailure: function (response, $module) {},
1162
+
1163
+ // server error
1164
+ onError: function (errorMessage, $module) {},
1165
+
1166
+ // request aborted
1167
+ onAbort: function (errorMessage, $module) {},
1168
+
1169
+ successTest: false,
1170
+
1171
+ // errors
1172
+ error: {
1173
+ beforeSend: 'The before send function has aborted the request',
1174
+ error: 'There was an error with your request',
1175
+ exitConditions: 'API Request Aborted. Exit conditions met',
1176
+ JSONParse: 'JSON could not be parsed during error handling',
1177
+ legacyParameters: 'You are using legacy API success callback names',
1178
+ method: 'The method you called is not defined',
1179
+ missingAction: 'API action used but no url was defined',
1180
+ missingURL: 'No URL specified for api event',
1181
+ noReturnedValue: 'The beforeSend callback must return a settings object, beforeSend ignored.',
1182
+ noStorage: 'Caching responses locally requires session storage',
1183
+ parseError: 'There was an error parsing your request',
1184
+ requiredParameter: 'Missing a required URL parameter: ',
1185
+ statusMessage: 'Server gave an error: ',
1186
+ timeout: 'Your request timed out',
1187
+ },
1168
1188
 
1169
- metadata: {
1170
- action : 'action',
1171
- url : 'url'
1172
- }
1173
- };
1189
+ regExp: {
1190
+ required: /{\$*[\da-z]+}/gi,
1191
+ optional: /{\/\$*[\da-z]+}/gi,
1192
+ validate: /^[_a-z][\w-]*(?:\[[\w-]*])*$/i,
1193
+ key: /[\w-]+|(?=\[])/gi,
1194
+ push: /^$/,
1195
+ fixed: /^\d+$/,
1196
+ named: /^[\w-]+$/i,
1197
+ },
1174
1198
 
1199
+ className: {
1200
+ loading: 'loading',
1201
+ error: 'error',
1202
+ },
1175
1203
 
1204
+ selector: {
1205
+ disabled: '.disabled',
1206
+ form: 'form',
1207
+ },
1176
1208
 
1177
- })( jQuery, window, document );
1209
+ metadata: {
1210
+ action: 'action',
1211
+ url: 'url',
1212
+ },
1213
+ };
1214
+ })(jQuery, window, document);