rails-active-ui 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Rakefile +6 -0
- data/app/assets/stylesheets.css +73555 -0
- data/app/components/accordion_component.rb +34 -0
- data/app/components/ad_component.rb +28 -0
- data/app/components/api_component.rb +24 -0
- data/app/components/breadcrumb_component.rb +26 -0
- data/app/components/button_component.rb +49 -0
- data/app/components/calendar_component.rb +34 -0
- data/app/components/card_component.rb +56 -0
- data/app/components/checkbox_component.rb +41 -0
- data/app/components/column_component.rb +62 -0
- data/app/components/comment_component.rb +45 -0
- data/app/components/concerns/alignable.rb +21 -0
- data/app/components/concerns/attachable.rb +16 -0
- data/app/components/concerns/orientable.rb +21 -0
- data/app/components/concerns/positionable.rb +21 -0
- data/app/components/concerns/sizeable.rb +18 -0
- data/app/components/container_component.rb +23 -0
- data/app/components/dimmer_component.rb +30 -0
- data/app/components/divider_component.rb +30 -0
- data/app/components/dropdown_component.rb +63 -0
- data/app/components/embed_component.rb +32 -0
- data/app/components/emoji_component.rb +15 -0
- data/app/components/feed_component.rb +22 -0
- data/app/components/flag_component.rb +15 -0
- data/app/components/flyout_component.rb +41 -0
- data/app/components/form_component.rb +39 -0
- data/app/components/grid_component.rb +85 -0
- data/app/components/h_stack_component.rb +67 -0
- data/app/components/header_component.rb +60 -0
- data/app/components/icon_component.rb +41 -0
- data/app/components/image_component.rb +46 -0
- data/app/components/input_component.rb +52 -0
- data/app/components/item_component.rb +39 -0
- data/app/components/item_group_component.rb +30 -0
- data/app/components/label_component.rb +49 -0
- data/app/components/link_component.rb +23 -0
- data/app/components/list_component.rb +39 -0
- data/app/components/loader_component.rb +33 -0
- data/app/components/menu_component.rb +64 -0
- data/app/components/menu_item_component.rb +52 -0
- data/app/components/message_component.rb +54 -0
- data/app/components/modal_component.rb +50 -0
- data/app/components/nag_component.rb +25 -0
- data/app/components/overlay_component.rb +16 -0
- data/app/components/placeholder_component.rb +39 -0
- data/app/components/popup_component.rb +31 -0
- data/app/components/progress_component.rb +48 -0
- data/app/components/pusher_component.rb +18 -0
- data/app/components/rail_component.rb +31 -0
- data/app/components/rating_component.rb +41 -0
- data/app/components/reset_component.rb +12 -0
- data/app/components/reveal_component.rb +39 -0
- data/app/components/row_component.rb +39 -0
- data/app/components/search_component.rb +44 -0
- data/app/components/segment_component.rb +57 -0
- data/app/components/segment_group_component.rb +36 -0
- data/app/components/shape_component.rb +25 -0
- data/app/components/sidebar_component.rb +33 -0
- data/app/components/site_component.rb +12 -0
- data/app/components/slider_component.rb +46 -0
- data/app/components/state_component.rb +25 -0
- data/app/components/statistic_component.rb +43 -0
- data/app/components/step_component.rb +56 -0
- data/app/components/step_group_component.rb +38 -0
- data/app/components/sticky_component.rb +22 -0
- data/app/components/sub_header_component.rb +15 -0
- data/app/components/sub_menu_component.rb +24 -0
- data/app/components/tab_component.rb +24 -0
- data/app/components/table_cell_component.rb +60 -0
- data/app/components/table_component.rb +160 -0
- data/app/components/table_row_component.rb +43 -0
- data/app/components/text_component.rb +73 -0
- data/app/components/toast_component.rb +36 -0
- data/app/components/transition_component.rb +32 -0
- data/app/components/v_stack_component.rb +31 -0
- data/app/components/visibility_component.rb +22 -0
- data/app/helpers/component_helper.rb +109 -0
- data/app/helpers/fui_helper.rb +53 -0
- data/app/javascript/accordion.js +547 -0
- data/app/javascript/accordion.min.js +11 -0
- data/app/javascript/api.js +1112 -0
- data/app/javascript/api.min.js +11 -0
- data/app/javascript/calendar.js +1960 -0
- data/app/javascript/calendar.min.js +11 -0
- data/app/javascript/checkbox.js +819 -0
- data/app/javascript/checkbox.min.js +11 -0
- data/app/javascript/dimmer.js +686 -0
- data/app/javascript/dimmer.min.js +11 -0
- data/app/javascript/dropdown.js +4019 -0
- data/app/javascript/dropdown.min.js +11 -0
- data/app/javascript/embed.js +646 -0
- data/app/javascript/embed.min.js +11 -0
- data/app/javascript/flyout.js +1405 -0
- data/app/javascript/flyout.min.js +11 -0
- data/app/javascript/form.js +2070 -0
- data/app/javascript/form.min.js +11 -0
- data/app/javascript/jquery.js +10716 -0
- data/app/javascript/jquery.min.js +2 -0
- data/app/javascript/modal.js +1507 -0
- data/app/javascript/modal.min.js +11 -0
- data/app/javascript/nag.js +522 -0
- data/app/javascript/nag.min.js +11 -0
- data/app/javascript/popup.js +1457 -0
- data/app/javascript/popup.min.js +11 -0
- data/app/javascript/progress.js +922 -0
- data/app/javascript/progress.min.js +11 -0
- data/app/javascript/rating.js +496 -0
- data/app/javascript/rating.min.js +11 -0
- data/app/javascript/search.js +1519 -0
- data/app/javascript/search.min.js +11 -0
- data/app/javascript/shape.js +721 -0
- data/app/javascript/shape.min.js +11 -0
- data/app/javascript/sidebar.js +952 -0
- data/app/javascript/sidebar.min.js +11 -0
- data/app/javascript/site.js +415 -0
- data/app/javascript/site.min.js +11 -0
- data/app/javascript/slider.js +1449 -0
- data/app/javascript/slider.min.js +11 -0
- data/app/javascript/state.js +653 -0
- data/app/javascript/state.min.js +11 -0
- data/app/javascript/sticky.js +852 -0
- data/app/javascript/sticky.min.js +11 -0
- data/app/javascript/tab.js +867 -0
- data/app/javascript/tab.min.js +11 -0
- data/app/javascript/toast.js +916 -0
- data/app/javascript/toast.min.js +11 -0
- data/app/javascript/transition.js +955 -0
- data/app/javascript/transition.min.js +11 -0
- data/app/javascript/ui/controllers/fui_accordion_controller.js +45 -0
- data/app/javascript/ui/controllers/fui_api_controller.js +80 -0
- data/app/javascript/ui/controllers/fui_calendar_controller.js +66 -0
- data/app/javascript/ui/controllers/fui_checkbox_controller.js +48 -0
- data/app/javascript/ui/controllers/fui_dimmer_controller.js +45 -0
- data/app/javascript/ui/controllers/fui_dropdown_controller.js +68 -0
- data/app/javascript/ui/controllers/fui_embed_controller.js +49 -0
- data/app/javascript/ui/controllers/fui_flyout_controller.js +49 -0
- data/app/javascript/ui/controllers/fui_form_controller.js +62 -0
- data/app/javascript/ui/controllers/fui_modal_controller.js +61 -0
- data/app/javascript/ui/controllers/fui_nag_controller.js +52 -0
- data/app/javascript/ui/controllers/fui_popup_controller.js +58 -0
- data/app/javascript/ui/controllers/fui_progress_controller.js +60 -0
- data/app/javascript/ui/controllers/fui_rating_controller.js +49 -0
- data/app/javascript/ui/controllers/fui_search_controller.js +76 -0
- data/app/javascript/ui/controllers/fui_shape_controller.js +45 -0
- data/app/javascript/ui/controllers/fui_sidebar_controller.js +48 -0
- data/app/javascript/ui/controllers/fui_site_controller.js +29 -0
- data/app/javascript/ui/controllers/fui_slider_controller.js +53 -0
- data/app/javascript/ui/controllers/fui_state_controller.js +63 -0
- data/app/javascript/ui/controllers/fui_sticky_controller.js +50 -0
- data/app/javascript/ui/controllers/fui_tab_controller.js +57 -0
- data/app/javascript/ui/controllers/fui_toast_controller.js +60 -0
- data/app/javascript/ui/controllers/fui_transition_controller.js +60 -0
- data/app/javascript/ui/controllers/fui_visibility_controller.js +55 -0
- data/app/javascript/ui/index.js +114 -0
- data/app/javascript/visibility.js +1196 -0
- data/app/javascript/visibility.min.js +11 -0
- data/app/lib/component.rb +63 -0
- data/config/importmap.rb +27 -0
- data/config/initializers/ruby_template_handler.rb +31 -0
- data/config/routes.rb +2 -0
- data/lib/tasks/ui_tasks.rake +4 -0
- data/lib/ui/engine.rb +27 -0
- data/lib/ui/version.rb +3 -0
- data/lib/ui.rb +6 -0
- metadata +220 -0
|
@@ -0,0 +1,1112 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* # Fomantic-UI 2.9.4 - API
|
|
3
|
+
* https://github.com/fomantic/Fomantic-UI/
|
|
4
|
+
*
|
|
5
|
+
*
|
|
6
|
+
* Released under the MIT license
|
|
7
|
+
* https://opensource.org/licenses/MIT
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
(function ($, window, document) {
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
function isWindow(obj) {
|
|
15
|
+
return obj !== null && obj === obj.window;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function isFunction(obj) {
|
|
19
|
+
return typeof obj === 'function' && typeof obj.nodeType !== 'number';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
window = window !== undefined && window.Math === Math
|
|
23
|
+
? window
|
|
24
|
+
: globalThis;
|
|
25
|
+
|
|
26
|
+
$.fn.api = function (...args) {
|
|
27
|
+
// use window context if none specified
|
|
28
|
+
const $allModules = isFunction(this)
|
|
29
|
+
? $(window)
|
|
30
|
+
: $(this);
|
|
31
|
+
let time = Date.now();
|
|
32
|
+
let performance = [];
|
|
33
|
+
|
|
34
|
+
const parameters = args[0];
|
|
35
|
+
const methodInvoked = typeof parameters === 'string';
|
|
36
|
+
const queryArguments = args.slice(1);
|
|
37
|
+
const contextCheck = function (context, win) {
|
|
38
|
+
let $context;
|
|
39
|
+
if ([window, document].includes(context)) {
|
|
40
|
+
$context = $(context);
|
|
41
|
+
} else {
|
|
42
|
+
$context = $(win.document).find(context);
|
|
43
|
+
if ($context.length === 0) {
|
|
44
|
+
$context = win.frameElement ? contextCheck(context, win.parent) : window;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return $context;
|
|
49
|
+
};
|
|
50
|
+
let returnedValue;
|
|
51
|
+
|
|
52
|
+
$allModules.each(function () {
|
|
53
|
+
const settings = $.isPlainObject(parameters)
|
|
54
|
+
? $.extend(true, {}, $.fn.api.settings, parameters)
|
|
55
|
+
: $.extend({}, $.fn.api.settings);
|
|
56
|
+
|
|
57
|
+
// internal aliases
|
|
58
|
+
const regExp = settings.regExp;
|
|
59
|
+
const namespace = settings.namespace;
|
|
60
|
+
const metadata = settings.metadata;
|
|
61
|
+
const selector = settings.selector;
|
|
62
|
+
const error = settings.error;
|
|
63
|
+
const className = settings.className;
|
|
64
|
+
|
|
65
|
+
// define namespaces for modules
|
|
66
|
+
const eventNamespace = '.' + namespace;
|
|
67
|
+
const moduleNamespace = 'module-' + namespace;
|
|
68
|
+
|
|
69
|
+
// element that creates request
|
|
70
|
+
const $module = $(this);
|
|
71
|
+
const $form = $module.closest(selector.form);
|
|
72
|
+
|
|
73
|
+
// context used for state
|
|
74
|
+
const $context = settings.stateContext ? contextCheck(settings.stateContext, window) : $module;
|
|
75
|
+
|
|
76
|
+
// request details
|
|
77
|
+
let ajaxSettings;
|
|
78
|
+
let requestSettings;
|
|
79
|
+
let url;
|
|
80
|
+
let data;
|
|
81
|
+
let requestStartTime;
|
|
82
|
+
let originalData;
|
|
83
|
+
|
|
84
|
+
// standard module
|
|
85
|
+
const element = this;
|
|
86
|
+
const context = $context[0];
|
|
87
|
+
let instance = $module.data(moduleNamespace);
|
|
88
|
+
|
|
89
|
+
const module = {
|
|
90
|
+
|
|
91
|
+
initialize: function () {
|
|
92
|
+
if (!methodInvoked) {
|
|
93
|
+
originalData = settings.data;
|
|
94
|
+
module.bind.events();
|
|
95
|
+
}
|
|
96
|
+
module.instantiate();
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
instantiate: function () {
|
|
100
|
+
module.verbose('Storing instance of module', module);
|
|
101
|
+
instance = module;
|
|
102
|
+
$module
|
|
103
|
+
.data(moduleNamespace, instance);
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
destroy: function () {
|
|
107
|
+
module.verbose('Destroying previous module for', element);
|
|
108
|
+
$module
|
|
109
|
+
.removeData(moduleNamespace)
|
|
110
|
+
.off(eventNamespace);
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
bind: {
|
|
114
|
+
events: function () {
|
|
115
|
+
const triggerEvent = module.get.event();
|
|
116
|
+
if (triggerEvent) {
|
|
117
|
+
module.verbose('Attaching API events to element', triggerEvent);
|
|
118
|
+
$module
|
|
119
|
+
.on(triggerEvent + eventNamespace, module.event.trigger);
|
|
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 {
|
|
133
|
+
// isn't json string
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return response;
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
read: {
|
|
142
|
+
cachedResponse: function (url) {
|
|
143
|
+
let response = window.sessionStorage.getItem(url + module.get.normalizedData());
|
|
144
|
+
module.debug('Using cached response', url, settings.data, response);
|
|
145
|
+
response = module.decode.json(response);
|
|
146
|
+
|
|
147
|
+
return response;
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
write: {
|
|
151
|
+
cachedResponse: function (url, response) {
|
|
152
|
+
if ($.isPlainObject(response)) {
|
|
153
|
+
response = JSON.stringify(response);
|
|
154
|
+
}
|
|
155
|
+
window.sessionStorage.setItem(url + module.get.normalizedData(), response);
|
|
156
|
+
module.verbose('Storing cached response for url', url, settings.data, response);
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
query: function () {
|
|
161
|
+
if (module.is.disabled()) {
|
|
162
|
+
module.debug('Element is disabled API request aborted');
|
|
163
|
+
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (module.is.loading()) {
|
|
168
|
+
if (settings.interruptRequests) {
|
|
169
|
+
module.debug('Interrupting previous request');
|
|
170
|
+
module.abort();
|
|
171
|
+
} else {
|
|
172
|
+
module.debug('Cancelling request, previous request is still pending');
|
|
173
|
+
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// pass element metadata to url (value, text)
|
|
179
|
+
if (settings.defaultData) {
|
|
180
|
+
$.extend(true, settings.urlData, module.get.defaultData());
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Add form content
|
|
184
|
+
if (settings.serializeForm) {
|
|
185
|
+
settings.data = module.add.formData(originalData || settings.data);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// call beforesend and get any settings changes
|
|
189
|
+
requestSettings = module.get.settings();
|
|
190
|
+
|
|
191
|
+
// check if before send canceled request
|
|
192
|
+
if (requestSettings === false) {
|
|
193
|
+
module.cancelled = true;
|
|
194
|
+
module.error(error.beforeSend);
|
|
195
|
+
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
module.cancelled = false;
|
|
200
|
+
|
|
201
|
+
// get url
|
|
202
|
+
url = module.get.templatedURL();
|
|
203
|
+
|
|
204
|
+
if (!url && !module.is.mocked()) {
|
|
205
|
+
module.error(error.missingURL);
|
|
206
|
+
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// replace variables
|
|
211
|
+
url = module.add.urlData(url);
|
|
212
|
+
// missing url parameters
|
|
213
|
+
if (!url && !module.is.mocked()) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
requestSettings.url = settings.base + url;
|
|
218
|
+
|
|
219
|
+
// look for jQuery ajax parameters in settings
|
|
220
|
+
ajaxSettings = $.extend(true, {}, settings, {
|
|
221
|
+
type: settings.method || settings.type,
|
|
222
|
+
data: data,
|
|
223
|
+
url: settings.base + url,
|
|
224
|
+
beforeSend: settings.beforeXHR,
|
|
225
|
+
success: function () {},
|
|
226
|
+
failure: function () {},
|
|
227
|
+
complete: function () {},
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
module.debug('Querying URL', ajaxSettings.url);
|
|
231
|
+
module.verbose('Using AJAX settings', ajaxSettings);
|
|
232
|
+
if (settings.cache === 'local' && module.read.cachedResponse(url)) {
|
|
233
|
+
module.debug('Response returned from local cache');
|
|
234
|
+
module.request = module.create.request();
|
|
235
|
+
module.request.resolveWith(context, [module.read.cachedResponse(url)]);
|
|
236
|
+
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!settings.throttle) {
|
|
241
|
+
module.debug('Sending request', data, ajaxSettings.method);
|
|
242
|
+
module.send.request();
|
|
243
|
+
} else if (!settings.throttleFirstRequest && !module.timer) {
|
|
244
|
+
module.debug('Sending request', data, ajaxSettings.method);
|
|
245
|
+
module.send.request();
|
|
246
|
+
module.timer = setTimeout(function () {}, settings.throttle);
|
|
247
|
+
} else {
|
|
248
|
+
module.debug('Throttling request', settings.throttle);
|
|
249
|
+
clearTimeout(module.timer);
|
|
250
|
+
module.timer = setTimeout(function () {
|
|
251
|
+
if (module.timer) {
|
|
252
|
+
delete module.timer;
|
|
253
|
+
}
|
|
254
|
+
module.debug('Sending throttled request', data, ajaxSettings.method);
|
|
255
|
+
module.send.request();
|
|
256
|
+
}, settings.throttle);
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
should: {
|
|
261
|
+
removeError: function () {
|
|
262
|
+
return settings.hideError === true || (settings.hideError === 'auto' && !module.is.form());
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
is: {
|
|
267
|
+
disabled: function () {
|
|
268
|
+
return $module.filter(selector.disabled).length > 0;
|
|
269
|
+
},
|
|
270
|
+
expectingJSON: function () {
|
|
271
|
+
return settings.dataType === 'json' || settings.dataType === 'jsonp';
|
|
272
|
+
},
|
|
273
|
+
form: function () {
|
|
274
|
+
return $module.is('form') || $context.is('form');
|
|
275
|
+
},
|
|
276
|
+
mocked: function () {
|
|
277
|
+
return settings.mockResponse || settings.mockResponseAsync || settings.response || settings.responseAsync;
|
|
278
|
+
},
|
|
279
|
+
input: function () {
|
|
280
|
+
return $module.is('input');
|
|
281
|
+
},
|
|
282
|
+
loading: function () {
|
|
283
|
+
return module.request
|
|
284
|
+
? module.request.state() === 'pending'
|
|
285
|
+
: false;
|
|
286
|
+
},
|
|
287
|
+
abortedRequest: function (xhr) {
|
|
288
|
+
if (xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
|
|
289
|
+
module.verbose('XHR request determined to be aborted');
|
|
290
|
+
|
|
291
|
+
return true;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
module.verbose('XHR request was not aborted');
|
|
295
|
+
|
|
296
|
+
return false;
|
|
297
|
+
},
|
|
298
|
+
validResponse: function (response) {
|
|
299
|
+
if (!module.is.expectingJSON() || !isFunction(settings.successTest)) {
|
|
300
|
+
module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
|
|
301
|
+
|
|
302
|
+
return true;
|
|
303
|
+
}
|
|
304
|
+
module.debug('Checking JSON returned success', settings.successTest, response);
|
|
305
|
+
if (settings.successTest(response)) {
|
|
306
|
+
module.debug('Response passed success test', response);
|
|
307
|
+
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
module.debug('Response failed success test', response);
|
|
312
|
+
|
|
313
|
+
return false;
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
|
|
317
|
+
was: {
|
|
318
|
+
cancelled: function () {
|
|
319
|
+
return module.cancelled || false;
|
|
320
|
+
},
|
|
321
|
+
successful: function () {
|
|
322
|
+
return module.request && module.request.state() === 'resolved';
|
|
323
|
+
},
|
|
324
|
+
failure: function () {
|
|
325
|
+
return module.request && module.request.state() === 'rejected';
|
|
326
|
+
},
|
|
327
|
+
complete: function () {
|
|
328
|
+
return module.request && (module.request.state() === 'resolved' || module.request.state() === 'rejected');
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
add: {
|
|
333
|
+
urlData: function (url, urlData = settings.urlData) {
|
|
334
|
+
let requiredVariables;
|
|
335
|
+
let optionalVariables;
|
|
336
|
+
if (url) {
|
|
337
|
+
requiredVariables = url.match(regExp.required);
|
|
338
|
+
optionalVariables = url.match(regExp.optional);
|
|
339
|
+
if (requiredVariables) {
|
|
340
|
+
module.debug('Looking for required URL variables', requiredVariables);
|
|
341
|
+
$.each(requiredVariables, function (index, templatedString) {
|
|
342
|
+
const variable = templatedString.slice(1, -1);
|
|
343
|
+
let value = $.isPlainObject(urlData) && urlData[variable] !== undefined
|
|
344
|
+
? urlData[variable]
|
|
345
|
+
: ($module.data(variable) !== undefined
|
|
346
|
+
? $module.data(variable)
|
|
347
|
+
: ($context.data(variable) !== undefined // eslint-disable-line unicorn/no-nested-ternary
|
|
348
|
+
? $context.data(variable)
|
|
349
|
+
: urlData[variable]));
|
|
350
|
+
// remove value
|
|
351
|
+
if (value === undefined) {
|
|
352
|
+
module.error(error.requiredParameter, variable, url);
|
|
353
|
+
url = false;
|
|
354
|
+
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
module.verbose('Found required variable', variable, value);
|
|
359
|
+
value = settings.encodeParameters
|
|
360
|
+
? module.get.urlEncodedValue(value)
|
|
361
|
+
: value;
|
|
362
|
+
url = url.replace(templatedString, value);
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
if (optionalVariables) {
|
|
366
|
+
module.debug('Looking for optional URL variables', requiredVariables);
|
|
367
|
+
$.each(optionalVariables, function (index, templatedString) {
|
|
368
|
+
const variable = templatedString.slice(2, -1);
|
|
369
|
+
const value = $.isPlainObject(urlData) && urlData[variable] !== undefined
|
|
370
|
+
? urlData[variable]
|
|
371
|
+
: ($module.data(variable) !== undefined
|
|
372
|
+
? $module.data(variable)
|
|
373
|
+
: ($context.data(variable) !== undefined // eslint-disable-line unicorn/no-nested-ternary
|
|
374
|
+
? $context.data(variable)
|
|
375
|
+
: urlData[variable]));
|
|
376
|
+
// optional replacement
|
|
377
|
+
if (value !== undefined) {
|
|
378
|
+
module.verbose('Optional variable Found', variable, value);
|
|
379
|
+
url = url.replace(templatedString, value);
|
|
380
|
+
} else {
|
|
381
|
+
module.verbose('Optional variable not found', variable);
|
|
382
|
+
// remove preceding slash if set
|
|
383
|
+
url = url.includes('/' + templatedString)
|
|
384
|
+
? url.replace('/' + templatedString, '')
|
|
385
|
+
: url.replace(templatedString, '');
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return url;
|
|
392
|
+
},
|
|
393
|
+
formData: function (data = originalData || settings.data) {
|
|
394
|
+
let formData = {};
|
|
395
|
+
const useFormDataApi = settings.serializeForm === 'formdata';
|
|
396
|
+
const hasOtherData = $.isPlainObject(data);
|
|
397
|
+
|
|
398
|
+
if (useFormDataApi) {
|
|
399
|
+
formData = new FormData($form[0]);
|
|
400
|
+
settings.processData = settings.processData !== undefined ? settings.processData : false;
|
|
401
|
+
settings.contentType = settings.contentType !== undefined ? settings.contentType : false;
|
|
402
|
+
} else {
|
|
403
|
+
const formArray = $form.serializeArray();
|
|
404
|
+
const pushes = {};
|
|
405
|
+
const pushValues = {};
|
|
406
|
+
const build = function (base, key, value) {
|
|
407
|
+
base[key] = value;
|
|
408
|
+
|
|
409
|
+
return base;
|
|
410
|
+
};
|
|
411
|
+
// add files
|
|
412
|
+
$.each($('input[type="file"]', $form), function (i, tag) {
|
|
413
|
+
$.each($(tag)[0].files, function (j, file) {
|
|
414
|
+
formArray.push({ name: tag.name, value: file });
|
|
415
|
+
});
|
|
416
|
+
});
|
|
417
|
+
$.each(formArray, function (i, el) {
|
|
418
|
+
if (!regExp.validate.test(el.name)) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
const isCheckbox = $('[name="' + CSS.escape(el.name) + '"]', $form).attr('type') === 'checkbox';
|
|
422
|
+
const floatValue = Number.parseFloat(el.value);
|
|
423
|
+
let value = (isCheckbox && el.value === 'on')
|
|
424
|
+
|| el.value === 'true'
|
|
425
|
+
|| (String(floatValue) === el.value
|
|
426
|
+
? floatValue
|
|
427
|
+
: (el.value === 'false' ? false : el.value));
|
|
428
|
+
const nameKeys = el.name.match(regExp.key) || [];
|
|
429
|
+
const pushKey = el.name.replace(/\[]$/, '');
|
|
430
|
+
if (!(pushKey in pushes)) {
|
|
431
|
+
pushes[pushKey] = 0;
|
|
432
|
+
pushValues[pushKey] = value;
|
|
433
|
+
} else if (Array.isArray(pushValues[pushKey])) {
|
|
434
|
+
pushValues[pushKey].push(value);
|
|
435
|
+
} else {
|
|
436
|
+
pushValues[pushKey] = [pushValues[pushKey], value];
|
|
437
|
+
}
|
|
438
|
+
if (!pushKey.includes('[]')) {
|
|
439
|
+
value = pushValues[pushKey];
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
while (nameKeys.length > 0) {
|
|
443
|
+
const k = nameKeys.pop();
|
|
444
|
+
|
|
445
|
+
if (k === '' && !Array.isArray(value)) { // foo[]
|
|
446
|
+
value = build([], pushes[pushKey]++, value);
|
|
447
|
+
} else if (regExp.fixed.test(k)) { // foo[n]
|
|
448
|
+
value = build([], k, value);
|
|
449
|
+
} else if (regExp.named.test(k)) { // foo; foo[bar]
|
|
450
|
+
value = build({}, k, value);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
formData = $.extend(true, formData, value);
|
|
454
|
+
});
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (hasOtherData) {
|
|
458
|
+
module.debug('Extending existing data with form data', data, formData);
|
|
459
|
+
if (useFormDataApi) {
|
|
460
|
+
$.each(Object.keys(data), function (i, el) {
|
|
461
|
+
formData.append(el, data[el]);
|
|
462
|
+
});
|
|
463
|
+
data = formData;
|
|
464
|
+
} else {
|
|
465
|
+
data = $.extend(true, {}, data, formData);
|
|
466
|
+
}
|
|
467
|
+
} else {
|
|
468
|
+
module.debug('Adding form data', formData);
|
|
469
|
+
data = formData;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return data;
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
|
|
476
|
+
send: {
|
|
477
|
+
request: function () {
|
|
478
|
+
module.set.loading();
|
|
479
|
+
module.request = module.create.request();
|
|
480
|
+
if (module.is.mocked()) {
|
|
481
|
+
module.mockedXHR = module.create.mockedXHR();
|
|
482
|
+
} else {
|
|
483
|
+
module.xhr = module.create.xhr();
|
|
484
|
+
}
|
|
485
|
+
settings.onRequest.call(context, module.request, module.xhr);
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
|
|
489
|
+
event: {
|
|
490
|
+
trigger: function (event) {
|
|
491
|
+
module.query();
|
|
492
|
+
if (event.type === 'submit' || event.type === 'click') {
|
|
493
|
+
event.preventDefault();
|
|
494
|
+
}
|
|
495
|
+
},
|
|
496
|
+
xhr: {
|
|
497
|
+
always: function () {
|
|
498
|
+
// nothing special
|
|
499
|
+
},
|
|
500
|
+
done: function (response, textStatus, xhr) {
|
|
501
|
+
const context = this;
|
|
502
|
+
const elapsedTime = Date.now() - requestStartTime;
|
|
503
|
+
let timeLeft = settings.loadingDuration - elapsedTime;
|
|
504
|
+
const translatedResponse = isFunction(settings.onResponse)
|
|
505
|
+
? (module.is.expectingJSON() && !settings.rawResponse
|
|
506
|
+
? settings.onResponse.call(context, $.extend(true, {}, response))
|
|
507
|
+
: settings.onResponse.call(context, response))
|
|
508
|
+
: false;
|
|
509
|
+
timeLeft = Math.max(timeLeft, 0);
|
|
510
|
+
if (translatedResponse) {
|
|
511
|
+
module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
|
|
512
|
+
response = translatedResponse;
|
|
513
|
+
}
|
|
514
|
+
if (timeLeft > 0) {
|
|
515
|
+
module.debug('Response completed early delaying state change by', timeLeft);
|
|
516
|
+
}
|
|
517
|
+
setTimeout(function () {
|
|
518
|
+
if (module.is.validResponse(response)) {
|
|
519
|
+
module.request.resolveWith(context, [response, xhr]);
|
|
520
|
+
} else {
|
|
521
|
+
module.request.rejectWith(context, [xhr, 'invalid']);
|
|
522
|
+
}
|
|
523
|
+
}, timeLeft);
|
|
524
|
+
},
|
|
525
|
+
fail: function (xhr, status, httpMessage) {
|
|
526
|
+
const context = this;
|
|
527
|
+
const elapsedTime = Date.now() - requestStartTime;
|
|
528
|
+
let timeLeft = settings.loadingDuration - elapsedTime;
|
|
529
|
+
timeLeft = Math.max(timeLeft, 0);
|
|
530
|
+
if (timeLeft > 0) {
|
|
531
|
+
module.debug('Response completed early delaying state change by', timeLeft);
|
|
532
|
+
}
|
|
533
|
+
setTimeout(function () {
|
|
534
|
+
if (module.is.abortedRequest(xhr)) {
|
|
535
|
+
module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
|
|
536
|
+
} else {
|
|
537
|
+
module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
|
|
538
|
+
}
|
|
539
|
+
}, timeLeft);
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
request: {
|
|
543
|
+
done: function (response, xhr) {
|
|
544
|
+
module.debug('Successful API Response', response);
|
|
545
|
+
if (settings.cache === 'local' && url) {
|
|
546
|
+
module.write.cachedResponse(url, response);
|
|
547
|
+
module.debug('Saving server response locally', module.cache);
|
|
548
|
+
}
|
|
549
|
+
settings.onSuccess.call(context, response, $module, xhr);
|
|
550
|
+
},
|
|
551
|
+
complete: function (firstParameter, secondParameter) {
|
|
552
|
+
let xhr;
|
|
553
|
+
let response;
|
|
554
|
+
// have to guess callback parameters based on request success
|
|
555
|
+
if (module.was.successful()) {
|
|
556
|
+
response = firstParameter;
|
|
557
|
+
xhr = secondParameter;
|
|
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
|
+
// pull response from xhr if available
|
|
567
|
+
const response = module.get.responseFromXHR(xhr);
|
|
568
|
+
const errorMessage = module.get.errorFromRequest(response, status, httpMessage);
|
|
569
|
+
if (status === 'aborted') {
|
|
570
|
+
module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
|
|
571
|
+
settings.onAbort.call(context, status, $module, xhr);
|
|
572
|
+
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
if (status === 'invalid') {
|
|
576
|
+
module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
|
|
577
|
+
} else if (status === 'error' && xhr !== undefined) {
|
|
578
|
+
module.debug('XHR produced a server error', status, httpMessage);
|
|
579
|
+
// make sure we have an error to display to console
|
|
580
|
+
if ((xhr.status < 200 || xhr.status >= 300) && httpMessage !== undefined && httpMessage !== '') {
|
|
581
|
+
module.error(error.statusMessage + httpMessage, ajaxSettings.url);
|
|
582
|
+
}
|
|
583
|
+
settings.onError.call(context, errorMessage, $module, xhr);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (settings.errorDuration && status !== 'aborted') {
|
|
587
|
+
module.debug('Adding error state');
|
|
588
|
+
module.set.error();
|
|
589
|
+
if (module.should.removeError()) {
|
|
590
|
+
setTimeout(function () {
|
|
591
|
+
module.remove.error();
|
|
592
|
+
}, settings.errorDuration);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
module.debug('API Request failed', errorMessage, xhr);
|
|
596
|
+
settings.onFailure.call(context, response, $module, xhr);
|
|
597
|
+
},
|
|
598
|
+
},
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
create: {
|
|
602
|
+
|
|
603
|
+
request: function () {
|
|
604
|
+
// api request promise
|
|
605
|
+
return $.Deferred()
|
|
606
|
+
.always(module.event.request.complete)
|
|
607
|
+
.done(module.event.request.done)
|
|
608
|
+
.fail(module.event.request.fail);
|
|
609
|
+
},
|
|
610
|
+
|
|
611
|
+
mockedXHR: function () {
|
|
612
|
+
// xhr does not simulate these properties of xhr but must return them
|
|
613
|
+
const textStatus = false;
|
|
614
|
+
const status = false;
|
|
615
|
+
const httpMessage = false;
|
|
616
|
+
const responder = settings.mockResponse || settings.response;
|
|
617
|
+
const asyncResponder = settings.mockResponseAsync || settings.responseAsync;
|
|
618
|
+
let asyncCallback;
|
|
619
|
+
let response;
|
|
620
|
+
|
|
621
|
+
const mockedXHR = $.Deferred()
|
|
622
|
+
.always(module.event.xhr.complete)
|
|
623
|
+
.done(module.event.xhr.done)
|
|
624
|
+
.fail(module.event.xhr.fail);
|
|
625
|
+
|
|
626
|
+
if (responder) {
|
|
627
|
+
if (isFunction(responder)) {
|
|
628
|
+
module.debug('Using specified synchronous callback', responder);
|
|
629
|
+
response = responder.call(context, requestSettings);
|
|
630
|
+
} else {
|
|
631
|
+
module.debug('Using settings specified response', responder);
|
|
632
|
+
response = responder;
|
|
633
|
+
}
|
|
634
|
+
// simulating response
|
|
635
|
+
mockedXHR.resolveWith(context, [response, textStatus, { responseText: response }]);
|
|
636
|
+
} else if (isFunction(asyncResponder)) {
|
|
637
|
+
asyncCallback = function (response) {
|
|
638
|
+
module.debug('Async callback returned response', response);
|
|
639
|
+
|
|
640
|
+
if (response) {
|
|
641
|
+
mockedXHR.resolveWith(context, [response, textStatus, { responseText: response }]);
|
|
642
|
+
} else {
|
|
643
|
+
mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
module.debug('Using specified async response callback', asyncResponder);
|
|
647
|
+
asyncResponder.call(context, requestSettings, asyncCallback);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
return mockedXHR;
|
|
651
|
+
},
|
|
652
|
+
|
|
653
|
+
xhr: function () {
|
|
654
|
+
// ajax request promise
|
|
655
|
+
const xhr = $.ajax(ajaxSettings)
|
|
656
|
+
.always(module.event.xhr.always)
|
|
657
|
+
.done(module.event.xhr.done)
|
|
658
|
+
.fail(module.event.xhr.fail);
|
|
659
|
+
module.verbose('Created server request', xhr, ajaxSettings);
|
|
660
|
+
|
|
661
|
+
return xhr;
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
|
|
665
|
+
set: {
|
|
666
|
+
error: function () {
|
|
667
|
+
module.verbose('Adding error state to element', $context);
|
|
668
|
+
$context.addClass(className.error);
|
|
669
|
+
},
|
|
670
|
+
loading: function () {
|
|
671
|
+
module.verbose('Adding loading state to element', $context);
|
|
672
|
+
$context.addClass(className.loading);
|
|
673
|
+
requestStartTime = Date.now();
|
|
674
|
+
},
|
|
675
|
+
},
|
|
676
|
+
|
|
677
|
+
remove: {
|
|
678
|
+
error: function () {
|
|
679
|
+
module.verbose('Removing error state from element', $context);
|
|
680
|
+
$context.removeClass(className.error);
|
|
681
|
+
},
|
|
682
|
+
loading: function () {
|
|
683
|
+
module.verbose('Removing loading state from element', $context);
|
|
684
|
+
$context.removeClass(className.loading);
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
|
|
688
|
+
get: {
|
|
689
|
+
normalizedData: function () {
|
|
690
|
+
return typeof settings.data === 'string' ? settings.data : JSON.stringify(settings.data, Object.keys(settings.data).sort());
|
|
691
|
+
},
|
|
692
|
+
responseFromXHR: function (xhr) {
|
|
693
|
+
return $.isPlainObject(xhr)
|
|
694
|
+
? (module.is.expectingJSON()
|
|
695
|
+
? module.decode.json(xhr.responseText)
|
|
696
|
+
: xhr.responseText)
|
|
697
|
+
: false;
|
|
698
|
+
},
|
|
699
|
+
errorFromRequest: function (response, status, httpMessage) {
|
|
700
|
+
return $.isPlainObject(response) && response.error !== undefined
|
|
701
|
+
? response.error // use JSON error message
|
|
702
|
+
: (settings.error[status] !== undefined // use the server error message
|
|
703
|
+
? settings.error[status]
|
|
704
|
+
: httpMessage);
|
|
705
|
+
},
|
|
706
|
+
request: function () {
|
|
707
|
+
return module.request || false;
|
|
708
|
+
},
|
|
709
|
+
xhr: function () {
|
|
710
|
+
return module.xhr || false;
|
|
711
|
+
},
|
|
712
|
+
settings: function () {
|
|
713
|
+
const runSettings = settings.beforeSend.call(element, settings);
|
|
714
|
+
if (runSettings === undefined) {
|
|
715
|
+
module.error(error.noReturnedValue);
|
|
716
|
+
}
|
|
717
|
+
if (runSettings === false) {
|
|
718
|
+
return runSettings;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return runSettings !== undefined
|
|
722
|
+
? $.extend(true, {}, runSettings)
|
|
723
|
+
: $.extend(true, {}, settings);
|
|
724
|
+
},
|
|
725
|
+
urlEncodedValue: function (value) {
|
|
726
|
+
const decodedValue = window.decodeURIComponent(value);
|
|
727
|
+
const encodedValue = window.encodeURIComponent(value);
|
|
728
|
+
const alreadyEncoded = decodedValue !== value;
|
|
729
|
+
if (alreadyEncoded) {
|
|
730
|
+
module.debug('URL value is already encoded, avoiding double encoding', value);
|
|
731
|
+
|
|
732
|
+
return value;
|
|
733
|
+
}
|
|
734
|
+
module.verbose('Encoding value using encodeURIComponent', value, encodedValue);
|
|
735
|
+
|
|
736
|
+
return encodedValue;
|
|
737
|
+
},
|
|
738
|
+
defaultData: function () {
|
|
739
|
+
const data = {};
|
|
740
|
+
if (!isWindow(element)) {
|
|
741
|
+
if (module.is.input()) {
|
|
742
|
+
data.value = $module.val();
|
|
743
|
+
} else if (!module.is.form()) {
|
|
744
|
+
data.text = $module.text();
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
return data;
|
|
749
|
+
},
|
|
750
|
+
event: function () {
|
|
751
|
+
if (isWindow(element) || settings.on === 'now') {
|
|
752
|
+
module.debug('API called without element, no events attached');
|
|
753
|
+
|
|
754
|
+
return false;
|
|
755
|
+
}
|
|
756
|
+
if (settings.on === 'auto') {
|
|
757
|
+
if ($module.is('input')) {
|
|
758
|
+
return element.oninput !== undefined
|
|
759
|
+
? 'input'
|
|
760
|
+
: (element.onpropertychange !== undefined
|
|
761
|
+
? 'propertychange'
|
|
762
|
+
: 'keyup');
|
|
763
|
+
}
|
|
764
|
+
if ($module.is('form')) {
|
|
765
|
+
return 'submit';
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
return 'click';
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
return settings.on;
|
|
772
|
+
},
|
|
773
|
+
templatedURL: function (action = settings.action || $module.data(metadata.action) || false) {
|
|
774
|
+
url = settings.url || $module.data(metadata.url) || false;
|
|
775
|
+
if (url) {
|
|
776
|
+
module.debug('Using specified url', url);
|
|
777
|
+
|
|
778
|
+
return url;
|
|
779
|
+
}
|
|
780
|
+
if (action) {
|
|
781
|
+
module.debug('Looking up url for action', action, settings.api);
|
|
782
|
+
if (settings.api[action] === undefined && !module.is.mocked()) {
|
|
783
|
+
module.error(error.missingAction, settings.action, settings.api);
|
|
784
|
+
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
url = settings.api[action];
|
|
788
|
+
} else if (module.is.form()) {
|
|
789
|
+
url = $module.attr('action') || $context.attr('action') || false;
|
|
790
|
+
module.debug('No url or action specified, defaulting to form action', url);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
return url;
|
|
794
|
+
},
|
|
795
|
+
},
|
|
796
|
+
|
|
797
|
+
abort: function () {
|
|
798
|
+
const xhr = module.get.xhr();
|
|
799
|
+
if (xhr && xhr.state() !== 'resolved') {
|
|
800
|
+
module.debug('Cancelling API request');
|
|
801
|
+
xhr.abort();
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
|
|
805
|
+
// reset state
|
|
806
|
+
reset: function () {
|
|
807
|
+
module.remove.error();
|
|
808
|
+
module.remove.loading();
|
|
809
|
+
},
|
|
810
|
+
|
|
811
|
+
setting: function (name, value) {
|
|
812
|
+
module.debug('Changing setting', name, value);
|
|
813
|
+
if ($.isPlainObject(name)) {
|
|
814
|
+
$.extend(true, settings, name);
|
|
815
|
+
} else if (value !== undefined) {
|
|
816
|
+
if ($.isPlainObject(settings[name])) {
|
|
817
|
+
$.extend(true, settings[name], value);
|
|
818
|
+
} else {
|
|
819
|
+
settings[name] = value;
|
|
820
|
+
}
|
|
821
|
+
} else {
|
|
822
|
+
return settings[name];
|
|
823
|
+
}
|
|
824
|
+
},
|
|
825
|
+
internal: function (name, value) {
|
|
826
|
+
if ($.isPlainObject(name)) {
|
|
827
|
+
$.extend(true, module, name);
|
|
828
|
+
} else if (value !== undefined) {
|
|
829
|
+
module[name] = value;
|
|
830
|
+
} else {
|
|
831
|
+
return module[name];
|
|
832
|
+
}
|
|
833
|
+
},
|
|
834
|
+
debug: function (...args) {
|
|
835
|
+
if (!settings.silent && settings.debug) {
|
|
836
|
+
if (settings.performance) {
|
|
837
|
+
module.performance.log(args);
|
|
838
|
+
} else {
|
|
839
|
+
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
|
840
|
+
module.debug.apply(console, args);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
},
|
|
844
|
+
verbose: function (...args) {
|
|
845
|
+
if (!settings.silent && settings.verbose && settings.debug) {
|
|
846
|
+
if (settings.performance) {
|
|
847
|
+
module.performance.log(args);
|
|
848
|
+
} else {
|
|
849
|
+
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
|
|
850
|
+
module.verbose.apply(console, args);
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
error: function (...args) {
|
|
855
|
+
if (!settings.silent) {
|
|
856
|
+
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
|
|
857
|
+
module.error.apply(console, args);
|
|
858
|
+
}
|
|
859
|
+
},
|
|
860
|
+
performance: {
|
|
861
|
+
log: function (message) {
|
|
862
|
+
let currentTime;
|
|
863
|
+
let executionTime;
|
|
864
|
+
let previousTime;
|
|
865
|
+
if (settings.performance) {
|
|
866
|
+
currentTime = Date.now();
|
|
867
|
+
previousTime = time || currentTime;
|
|
868
|
+
executionTime = currentTime - previousTime;
|
|
869
|
+
time = currentTime;
|
|
870
|
+
performance.push({
|
|
871
|
+
Name: message[0],
|
|
872
|
+
Arguments: message.slice(1),
|
|
873
|
+
// 'Element' : element,
|
|
874
|
+
'Execution Time': executionTime,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
clearTimeout(module.performance.timer);
|
|
878
|
+
module.performance.timer = setTimeout(function () {
|
|
879
|
+
module.performance.display();
|
|
880
|
+
}, 500);
|
|
881
|
+
},
|
|
882
|
+
display: function () {
|
|
883
|
+
let title = settings.name + ':';
|
|
884
|
+
let totalTime = 0;
|
|
885
|
+
time = false;
|
|
886
|
+
clearTimeout(module.performance.timer);
|
|
887
|
+
$.each(performance, function (index, data) {
|
|
888
|
+
totalTime += data['Execution Time'];
|
|
889
|
+
});
|
|
890
|
+
title += ' ' + totalTime + 'ms';
|
|
891
|
+
if (performance.length > 0) {
|
|
892
|
+
console.groupCollapsed(title);
|
|
893
|
+
console.table(performance);
|
|
894
|
+
console.groupEnd();
|
|
895
|
+
}
|
|
896
|
+
performance = [];
|
|
897
|
+
},
|
|
898
|
+
},
|
|
899
|
+
invoke: function (query, passedArguments = queryArguments, context = element) {
|
|
900
|
+
let object = instance;
|
|
901
|
+
let maxDepth;
|
|
902
|
+
let found;
|
|
903
|
+
let response;
|
|
904
|
+
if (typeof query === 'string' && object !== undefined) {
|
|
905
|
+
query = query.split(/[ .]/);
|
|
906
|
+
maxDepth = query.length - 1;
|
|
907
|
+
$.each(query, function (depth, value) {
|
|
908
|
+
const camelCaseValue = depth !== maxDepth
|
|
909
|
+
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
|
|
910
|
+
: query;
|
|
911
|
+
if ($.isPlainObject(object[camelCaseValue]) && (depth !== maxDepth)) {
|
|
912
|
+
object = object[camelCaseValue];
|
|
913
|
+
} else if (object[camelCaseValue] !== undefined) {
|
|
914
|
+
found = object[camelCaseValue];
|
|
915
|
+
|
|
916
|
+
return false;
|
|
917
|
+
} else if ($.isPlainObject(object[value]) && (depth !== maxDepth)) {
|
|
918
|
+
object = object[value];
|
|
919
|
+
} else if (object[value] !== undefined) {
|
|
920
|
+
found = object[value];
|
|
921
|
+
|
|
922
|
+
return false;
|
|
923
|
+
} else {
|
|
924
|
+
module.error(error.method, query);
|
|
925
|
+
|
|
926
|
+
return false;
|
|
927
|
+
}
|
|
928
|
+
});
|
|
929
|
+
}
|
|
930
|
+
if (isFunction(found)) {
|
|
931
|
+
response = found.apply(context, passedArguments);
|
|
932
|
+
} else if (found !== undefined) {
|
|
933
|
+
response = found;
|
|
934
|
+
}
|
|
935
|
+
if (Array.isArray(returnedValue)) {
|
|
936
|
+
returnedValue.push(response);
|
|
937
|
+
} else if (returnedValue !== undefined) {
|
|
938
|
+
returnedValue = [returnedValue, response];
|
|
939
|
+
} else if (response !== undefined) {
|
|
940
|
+
returnedValue = response;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
return found;
|
|
944
|
+
},
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
if (methodInvoked) {
|
|
948
|
+
if (instance === undefined) {
|
|
949
|
+
module.initialize();
|
|
950
|
+
}
|
|
951
|
+
module.invoke(parameters);
|
|
952
|
+
} else {
|
|
953
|
+
if (instance !== undefined) {
|
|
954
|
+
instance.invoke('destroy');
|
|
955
|
+
}
|
|
956
|
+
module.initialize();
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
|
|
960
|
+
return returnedValue !== undefined
|
|
961
|
+
? returnedValue
|
|
962
|
+
: this;
|
|
963
|
+
};
|
|
964
|
+
$.api = $.fn.api;
|
|
965
|
+
|
|
966
|
+
$.api.settings = {
|
|
967
|
+
|
|
968
|
+
name: 'API',
|
|
969
|
+
namespace: 'api',
|
|
970
|
+
|
|
971
|
+
debug: false,
|
|
972
|
+
verbose: false,
|
|
973
|
+
performance: true,
|
|
974
|
+
|
|
975
|
+
// object containing all templates endpoints
|
|
976
|
+
api: {},
|
|
977
|
+
|
|
978
|
+
// whether to cache responses
|
|
979
|
+
cache: true,
|
|
980
|
+
|
|
981
|
+
// whether new requests should abort previous requests
|
|
982
|
+
interruptRequests: true,
|
|
983
|
+
|
|
984
|
+
// event binding
|
|
985
|
+
on: 'auto',
|
|
986
|
+
|
|
987
|
+
// context for applying state classes
|
|
988
|
+
stateContext: false,
|
|
989
|
+
|
|
990
|
+
// duration for loading state
|
|
991
|
+
loadingDuration: 0,
|
|
992
|
+
|
|
993
|
+
// whether to hide errors after a period of time
|
|
994
|
+
hideError: 'auto',
|
|
995
|
+
|
|
996
|
+
// duration for error state
|
|
997
|
+
errorDuration: 2000,
|
|
998
|
+
|
|
999
|
+
// whether parameters should be encoded with encodeURIComponent
|
|
1000
|
+
encodeParameters: true,
|
|
1001
|
+
|
|
1002
|
+
// API action to use
|
|
1003
|
+
action: false,
|
|
1004
|
+
|
|
1005
|
+
// templated URL to use
|
|
1006
|
+
url: false,
|
|
1007
|
+
|
|
1008
|
+
// base URL to apply to all endpoints
|
|
1009
|
+
base: '',
|
|
1010
|
+
|
|
1011
|
+
// data that will
|
|
1012
|
+
urlData: {},
|
|
1013
|
+
|
|
1014
|
+
// whether to add default data to url data
|
|
1015
|
+
defaultData: true,
|
|
1016
|
+
|
|
1017
|
+
// whether to serialize the closest form
|
|
1018
|
+
// use true to convert complex named keys like a[b][1][c][] into a nested object
|
|
1019
|
+
// use 'formdata' for formdata web api
|
|
1020
|
+
serializeForm: false,
|
|
1021
|
+
|
|
1022
|
+
// how long to wait before request should occur
|
|
1023
|
+
throttle: 0,
|
|
1024
|
+
|
|
1025
|
+
// whether to throttle first request or only repeated
|
|
1026
|
+
throttleFirstRequest: true,
|
|
1027
|
+
|
|
1028
|
+
// standard ajax settings
|
|
1029
|
+
method: 'get',
|
|
1030
|
+
data: {},
|
|
1031
|
+
dataType: 'json',
|
|
1032
|
+
|
|
1033
|
+
// mock response
|
|
1034
|
+
mockResponse: false,
|
|
1035
|
+
mockResponseAsync: false,
|
|
1036
|
+
|
|
1037
|
+
// aliases for mock
|
|
1038
|
+
response: false,
|
|
1039
|
+
responseAsync: false,
|
|
1040
|
+
|
|
1041
|
+
// whether onResponse should work with response value without force converting into an object
|
|
1042
|
+
rawResponse: true,
|
|
1043
|
+
|
|
1044
|
+
// callbacks before request
|
|
1045
|
+
beforeSend: function (settings) {
|
|
1046
|
+
return settings;
|
|
1047
|
+
},
|
|
1048
|
+
beforeXHR: function (xhr) {},
|
|
1049
|
+
onRequest: function (promise, xhr) {},
|
|
1050
|
+
|
|
1051
|
+
// after request
|
|
1052
|
+
onResponse: false, // function(response) { },
|
|
1053
|
+
|
|
1054
|
+
// response was successful if JSON passed validation
|
|
1055
|
+
onSuccess: function (response, $module) {},
|
|
1056
|
+
|
|
1057
|
+
// request finished without aborting
|
|
1058
|
+
onComplete: function (response, $module) {},
|
|
1059
|
+
|
|
1060
|
+
// failed JSON success test
|
|
1061
|
+
onFailure: function (response, $module) {},
|
|
1062
|
+
|
|
1063
|
+
// server error
|
|
1064
|
+
onError: function (errorMessage, $module) {},
|
|
1065
|
+
|
|
1066
|
+
// request aborted
|
|
1067
|
+
onAbort: function (errorMessage, $module) {},
|
|
1068
|
+
|
|
1069
|
+
successTest: false,
|
|
1070
|
+
|
|
1071
|
+
// errors
|
|
1072
|
+
error: {
|
|
1073
|
+
beforeSend: 'The before send function has aborted the request',
|
|
1074
|
+
error: 'There was an error with your request',
|
|
1075
|
+
exitConditions: 'API Request Aborted. Exit conditions met',
|
|
1076
|
+
JSONParse: 'JSON could not be parsed during error handling',
|
|
1077
|
+
method: 'The method you called is not defined',
|
|
1078
|
+
missingAction: 'API action used but no url was defined',
|
|
1079
|
+
missingURL: 'No URL specified for api event',
|
|
1080
|
+
noReturnedValue: 'The beforeSend callback must return a settings object, beforeSend ignored.',
|
|
1081
|
+
parseError: 'There was an error parsing your request',
|
|
1082
|
+
requiredParameter: 'Missing a required URL parameter: ',
|
|
1083
|
+
statusMessage: 'Server gave an error: ',
|
|
1084
|
+
timeout: 'Your request timed out',
|
|
1085
|
+
},
|
|
1086
|
+
|
|
1087
|
+
regExp: {
|
|
1088
|
+
required: /{[\da-z]+}/gi,
|
|
1089
|
+
optional: /{\/[\da-z]+}/gi,
|
|
1090
|
+
validate: /^[_a-z][\w-]*(?:\[[\w-]*])*$/i,
|
|
1091
|
+
key: /[\w-]+|(?=\[])/gi,
|
|
1092
|
+
push: /^$/,
|
|
1093
|
+
fixed: /^\d+$/,
|
|
1094
|
+
named: /^[\w-]+$/i,
|
|
1095
|
+
},
|
|
1096
|
+
|
|
1097
|
+
className: {
|
|
1098
|
+
loading: 'loading',
|
|
1099
|
+
error: 'error',
|
|
1100
|
+
},
|
|
1101
|
+
|
|
1102
|
+
selector: {
|
|
1103
|
+
disabled: '.disabled',
|
|
1104
|
+
form: 'form',
|
|
1105
|
+
},
|
|
1106
|
+
|
|
1107
|
+
metadata: {
|
|
1108
|
+
action: 'action',
|
|
1109
|
+
url: 'url',
|
|
1110
|
+
},
|
|
1111
|
+
};
|
|
1112
|
+
})(jQuery, window, document);
|