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.
Files changed (167) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +6 -0
  3. data/app/assets/stylesheets.css +73555 -0
  4. data/app/components/accordion_component.rb +34 -0
  5. data/app/components/ad_component.rb +28 -0
  6. data/app/components/api_component.rb +24 -0
  7. data/app/components/breadcrumb_component.rb +26 -0
  8. data/app/components/button_component.rb +49 -0
  9. data/app/components/calendar_component.rb +34 -0
  10. data/app/components/card_component.rb +56 -0
  11. data/app/components/checkbox_component.rb +41 -0
  12. data/app/components/column_component.rb +62 -0
  13. data/app/components/comment_component.rb +45 -0
  14. data/app/components/concerns/alignable.rb +21 -0
  15. data/app/components/concerns/attachable.rb +16 -0
  16. data/app/components/concerns/orientable.rb +21 -0
  17. data/app/components/concerns/positionable.rb +21 -0
  18. data/app/components/concerns/sizeable.rb +18 -0
  19. data/app/components/container_component.rb +23 -0
  20. data/app/components/dimmer_component.rb +30 -0
  21. data/app/components/divider_component.rb +30 -0
  22. data/app/components/dropdown_component.rb +63 -0
  23. data/app/components/embed_component.rb +32 -0
  24. data/app/components/emoji_component.rb +15 -0
  25. data/app/components/feed_component.rb +22 -0
  26. data/app/components/flag_component.rb +15 -0
  27. data/app/components/flyout_component.rb +41 -0
  28. data/app/components/form_component.rb +39 -0
  29. data/app/components/grid_component.rb +85 -0
  30. data/app/components/h_stack_component.rb +67 -0
  31. data/app/components/header_component.rb +60 -0
  32. data/app/components/icon_component.rb +41 -0
  33. data/app/components/image_component.rb +46 -0
  34. data/app/components/input_component.rb +52 -0
  35. data/app/components/item_component.rb +39 -0
  36. data/app/components/item_group_component.rb +30 -0
  37. data/app/components/label_component.rb +49 -0
  38. data/app/components/link_component.rb +23 -0
  39. data/app/components/list_component.rb +39 -0
  40. data/app/components/loader_component.rb +33 -0
  41. data/app/components/menu_component.rb +64 -0
  42. data/app/components/menu_item_component.rb +52 -0
  43. data/app/components/message_component.rb +54 -0
  44. data/app/components/modal_component.rb +50 -0
  45. data/app/components/nag_component.rb +25 -0
  46. data/app/components/overlay_component.rb +16 -0
  47. data/app/components/placeholder_component.rb +39 -0
  48. data/app/components/popup_component.rb +31 -0
  49. data/app/components/progress_component.rb +48 -0
  50. data/app/components/pusher_component.rb +18 -0
  51. data/app/components/rail_component.rb +31 -0
  52. data/app/components/rating_component.rb +41 -0
  53. data/app/components/reset_component.rb +12 -0
  54. data/app/components/reveal_component.rb +39 -0
  55. data/app/components/row_component.rb +39 -0
  56. data/app/components/search_component.rb +44 -0
  57. data/app/components/segment_component.rb +57 -0
  58. data/app/components/segment_group_component.rb +36 -0
  59. data/app/components/shape_component.rb +25 -0
  60. data/app/components/sidebar_component.rb +33 -0
  61. data/app/components/site_component.rb +12 -0
  62. data/app/components/slider_component.rb +46 -0
  63. data/app/components/state_component.rb +25 -0
  64. data/app/components/statistic_component.rb +43 -0
  65. data/app/components/step_component.rb +56 -0
  66. data/app/components/step_group_component.rb +38 -0
  67. data/app/components/sticky_component.rb +22 -0
  68. data/app/components/sub_header_component.rb +15 -0
  69. data/app/components/sub_menu_component.rb +24 -0
  70. data/app/components/tab_component.rb +24 -0
  71. data/app/components/table_cell_component.rb +60 -0
  72. data/app/components/table_component.rb +160 -0
  73. data/app/components/table_row_component.rb +43 -0
  74. data/app/components/text_component.rb +73 -0
  75. data/app/components/toast_component.rb +36 -0
  76. data/app/components/transition_component.rb +32 -0
  77. data/app/components/v_stack_component.rb +31 -0
  78. data/app/components/visibility_component.rb +22 -0
  79. data/app/helpers/component_helper.rb +109 -0
  80. data/app/helpers/fui_helper.rb +53 -0
  81. data/app/javascript/accordion.js +547 -0
  82. data/app/javascript/accordion.min.js +11 -0
  83. data/app/javascript/api.js +1112 -0
  84. data/app/javascript/api.min.js +11 -0
  85. data/app/javascript/calendar.js +1960 -0
  86. data/app/javascript/calendar.min.js +11 -0
  87. data/app/javascript/checkbox.js +819 -0
  88. data/app/javascript/checkbox.min.js +11 -0
  89. data/app/javascript/dimmer.js +686 -0
  90. data/app/javascript/dimmer.min.js +11 -0
  91. data/app/javascript/dropdown.js +4019 -0
  92. data/app/javascript/dropdown.min.js +11 -0
  93. data/app/javascript/embed.js +646 -0
  94. data/app/javascript/embed.min.js +11 -0
  95. data/app/javascript/flyout.js +1405 -0
  96. data/app/javascript/flyout.min.js +11 -0
  97. data/app/javascript/form.js +2070 -0
  98. data/app/javascript/form.min.js +11 -0
  99. data/app/javascript/jquery.js +10716 -0
  100. data/app/javascript/jquery.min.js +2 -0
  101. data/app/javascript/modal.js +1507 -0
  102. data/app/javascript/modal.min.js +11 -0
  103. data/app/javascript/nag.js +522 -0
  104. data/app/javascript/nag.min.js +11 -0
  105. data/app/javascript/popup.js +1457 -0
  106. data/app/javascript/popup.min.js +11 -0
  107. data/app/javascript/progress.js +922 -0
  108. data/app/javascript/progress.min.js +11 -0
  109. data/app/javascript/rating.js +496 -0
  110. data/app/javascript/rating.min.js +11 -0
  111. data/app/javascript/search.js +1519 -0
  112. data/app/javascript/search.min.js +11 -0
  113. data/app/javascript/shape.js +721 -0
  114. data/app/javascript/shape.min.js +11 -0
  115. data/app/javascript/sidebar.js +952 -0
  116. data/app/javascript/sidebar.min.js +11 -0
  117. data/app/javascript/site.js +415 -0
  118. data/app/javascript/site.min.js +11 -0
  119. data/app/javascript/slider.js +1449 -0
  120. data/app/javascript/slider.min.js +11 -0
  121. data/app/javascript/state.js +653 -0
  122. data/app/javascript/state.min.js +11 -0
  123. data/app/javascript/sticky.js +852 -0
  124. data/app/javascript/sticky.min.js +11 -0
  125. data/app/javascript/tab.js +867 -0
  126. data/app/javascript/tab.min.js +11 -0
  127. data/app/javascript/toast.js +916 -0
  128. data/app/javascript/toast.min.js +11 -0
  129. data/app/javascript/transition.js +955 -0
  130. data/app/javascript/transition.min.js +11 -0
  131. data/app/javascript/ui/controllers/fui_accordion_controller.js +45 -0
  132. data/app/javascript/ui/controllers/fui_api_controller.js +80 -0
  133. data/app/javascript/ui/controllers/fui_calendar_controller.js +66 -0
  134. data/app/javascript/ui/controllers/fui_checkbox_controller.js +48 -0
  135. data/app/javascript/ui/controllers/fui_dimmer_controller.js +45 -0
  136. data/app/javascript/ui/controllers/fui_dropdown_controller.js +68 -0
  137. data/app/javascript/ui/controllers/fui_embed_controller.js +49 -0
  138. data/app/javascript/ui/controllers/fui_flyout_controller.js +49 -0
  139. data/app/javascript/ui/controllers/fui_form_controller.js +62 -0
  140. data/app/javascript/ui/controllers/fui_modal_controller.js +61 -0
  141. data/app/javascript/ui/controllers/fui_nag_controller.js +52 -0
  142. data/app/javascript/ui/controllers/fui_popup_controller.js +58 -0
  143. data/app/javascript/ui/controllers/fui_progress_controller.js +60 -0
  144. data/app/javascript/ui/controllers/fui_rating_controller.js +49 -0
  145. data/app/javascript/ui/controllers/fui_search_controller.js +76 -0
  146. data/app/javascript/ui/controllers/fui_shape_controller.js +45 -0
  147. data/app/javascript/ui/controllers/fui_sidebar_controller.js +48 -0
  148. data/app/javascript/ui/controllers/fui_site_controller.js +29 -0
  149. data/app/javascript/ui/controllers/fui_slider_controller.js +53 -0
  150. data/app/javascript/ui/controllers/fui_state_controller.js +63 -0
  151. data/app/javascript/ui/controllers/fui_sticky_controller.js +50 -0
  152. data/app/javascript/ui/controllers/fui_tab_controller.js +57 -0
  153. data/app/javascript/ui/controllers/fui_toast_controller.js +60 -0
  154. data/app/javascript/ui/controllers/fui_transition_controller.js +60 -0
  155. data/app/javascript/ui/controllers/fui_visibility_controller.js +55 -0
  156. data/app/javascript/ui/index.js +114 -0
  157. data/app/javascript/visibility.js +1196 -0
  158. data/app/javascript/visibility.min.js +11 -0
  159. data/app/lib/component.rb +63 -0
  160. data/config/importmap.rb +27 -0
  161. data/config/initializers/ruby_template_handler.rb +31 -0
  162. data/config/routes.rb +2 -0
  163. data/lib/tasks/ui_tasks.rake +4 -0
  164. data/lib/ui/engine.rb +27 -0
  165. data/lib/ui/version.rb +3 -0
  166. data/lib/ui.rb +6 -0
  167. metadata +220 -0
@@ -0,0 +1,922 @@
1
+ /*!
2
+ * # Fomantic-UI 2.9.4 - Progress
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 isFunction(obj) {
15
+ return typeof obj === 'function' && typeof obj.nodeType !== 'number';
16
+ }
17
+
18
+ window = window !== undefined && window.Math === Math
19
+ ? window
20
+ : globalThis;
21
+
22
+ $.fn.progress = function (...args) {
23
+ const $allModules = $(this);
24
+
25
+ let time = Date.now();
26
+ let performance = [];
27
+
28
+ const parameters = args[0];
29
+ const methodInvoked = typeof parameters === 'string';
30
+ const queryArguments = args.slice(1);
31
+
32
+ let returnedValue;
33
+
34
+ $allModules.each(function () {
35
+ const settings = $.isPlainObject(parameters)
36
+ ? $.extend(true, {}, $.fn.progress.settings, parameters)
37
+ : $.extend({}, $.fn.progress.settings);
38
+
39
+ const className = settings.className;
40
+ const metadata = settings.metadata;
41
+ const namespace = settings.namespace;
42
+ const selector = settings.selector;
43
+ const error = settings.error;
44
+
45
+ const eventNamespace = '.' + namespace;
46
+ const moduleNamespace = 'module-' + namespace;
47
+
48
+ const $module = $(this);
49
+ const $bars = $(this).find(selector.bar);
50
+ const $progresses = $(this).find(selector.progress);
51
+ const $label = $(this).find(selector.label);
52
+
53
+ const element = this;
54
+ let instance = $module.data(moduleNamespace);
55
+
56
+ let animating = false;
57
+ const module = {
58
+ helper: {
59
+ sum: function (nums) {
60
+ return Array.isArray(nums) ? nums.reduce(function (left, right) {
61
+ return left + Number(right);
62
+ }, 0) : 0;
63
+ },
64
+ /**
65
+ * Derive precision for multiple progress with total and values.
66
+ *
67
+ * This helper dervices a precision that is large enough to show the minimum value of multiple progress.
68
+ *
69
+ * Example1
70
+ * - total: 1122
71
+ * - values: [325, 111, 74, 612]
72
+ * - min ratio: 74/1122 = 0.0659...
73
+ * - required precision: 100
74
+ *
75
+ * Example2
76
+ * - total: 10541
77
+ * - values: [3235, 1111, 74, 6121]
78
+ * - min ratio: 74/10541 = 0.0070...
79
+ * - required precision: 1000
80
+ *
81
+ * @param min A minimum value within multiple values
82
+ * @param total A total amount of multiple values
83
+ * @returns {number} A precision. Could be 1, 10, 100, ... 1e+10.
84
+ */
85
+ derivePrecision: function (min, total) {
86
+ let precisionPower = 0;
87
+ let precision = 1;
88
+ let ratio = min / total;
89
+ while (precisionPower < 10) {
90
+ ratio *= precision;
91
+ if (ratio > 1) {
92
+ break;
93
+ }
94
+ precision = 10 ** precisionPower++;
95
+ }
96
+
97
+ return precision;
98
+ },
99
+ forceArray: function (element) {
100
+ return Array.isArray(element)
101
+ ? element
102
+ : (!Number.isNaN(Number(element))
103
+ ? [element]
104
+ : (typeof element === 'string' ? element.split(',') : [])); // eslint-disable-line unicorn/no-nested-ternary
105
+ },
106
+ },
107
+
108
+ initialize: function () {
109
+ module.set.duration();
110
+ module.debug(element);
111
+
112
+ module.read.metadata();
113
+ module.read.settings();
114
+
115
+ module.instantiate();
116
+ },
117
+
118
+ instantiate: function () {
119
+ module.verbose('Storing instance of progress', module);
120
+ instance = module;
121
+ $module
122
+ .data(moduleNamespace, module);
123
+ },
124
+ destroy: function () {
125
+ module.verbose('Destroying previous progress for', $module);
126
+ clearInterval(instance.interval);
127
+ module.remove.state();
128
+ $module.removeData(moduleNamespace);
129
+ instance = undefined;
130
+ },
131
+
132
+ reset: function () {
133
+ module.remove.nextValue();
134
+ module.update.progress(0);
135
+ },
136
+
137
+ complete: function (keepState) {
138
+ if (module.percent === undefined || module.percent < 100) {
139
+ module.remove.progressPoll();
140
+ if (keepState !== true) {
141
+ module.set.percent(100);
142
+ }
143
+ }
144
+ },
145
+
146
+ read: {
147
+ metadata: function () {
148
+ const data = {
149
+ percent: module.helper.forceArray($module.data(metadata.percent)),
150
+ total: $module.data(metadata.total),
151
+ value: module.helper.forceArray($module.data(metadata.value)),
152
+ };
153
+ if (data.total !== undefined) {
154
+ module.debug('Total value set from metadata', data.total);
155
+ module.set.total(data.total);
156
+ }
157
+ if (data.value.length > 0) {
158
+ module.debug('Current value set from metadata', data.value);
159
+ module.set.value(data.value);
160
+ module.set.progress(data.value);
161
+ }
162
+ if (data.percent.length > 0) {
163
+ module.debug('Current percent value set from metadata', data.percent);
164
+ module.set.percent(data.percent);
165
+ }
166
+ },
167
+ settings: function () {
168
+ if (settings.total !== false) {
169
+ module.debug('Current total set in settings', settings.total);
170
+ module.set.total(settings.total);
171
+ }
172
+ if (settings.value !== false) {
173
+ module.debug('Current value set in settings', settings.value);
174
+ module.set.value(settings.value);
175
+ module.set.progress(module.value);
176
+ }
177
+ if (settings.percent !== false) {
178
+ module.debug('Current percent set in settings', settings.percent);
179
+ module.set.percent(settings.percent);
180
+ }
181
+ },
182
+ },
183
+
184
+ bind: {
185
+ transitionEnd: function (callback) {
186
+ $bars
187
+ .one('transitionend' + eventNamespace, function (event) {
188
+ clearTimeout(module.failSafeTimer);
189
+ callback.call(this, event);
190
+ });
191
+ module.failSafeTimer = setTimeout(function () {
192
+ $bars.triggerHandler('transitionend');
193
+ }, settings.duration + settings.failSafeDelay);
194
+ module.verbose('Adding fail safe timer', module.timer);
195
+ },
196
+ },
197
+
198
+ increment: function (incrementValue) {
199
+ let startValue;
200
+ let newValue;
201
+ if (module.has.total()) {
202
+ startValue = module.get.value();
203
+ incrementValue = incrementValue || 1;
204
+ } else {
205
+ startValue = module.get.percent();
206
+ incrementValue = incrementValue || module.get.randomValue();
207
+ }
208
+ newValue = startValue + incrementValue;
209
+ module.debug('Incrementing percentage by', startValue, newValue, incrementValue);
210
+ newValue = module.get.normalizedValue(newValue);
211
+ module.set.progress(newValue);
212
+ },
213
+ decrement: function (decrementValue) {
214
+ const total = module.get.total();
215
+ let startValue;
216
+ let newValue;
217
+ if (total) {
218
+ startValue = module.get.value();
219
+ decrementValue = decrementValue || 1;
220
+ newValue = startValue - decrementValue;
221
+ module.debug('Decrementing value by', decrementValue, startValue);
222
+ } else {
223
+ startValue = module.get.percent();
224
+ decrementValue = decrementValue || module.get.randomValue();
225
+ newValue = startValue - decrementValue;
226
+ module.debug('Decrementing percentage by', decrementValue, startValue);
227
+ }
228
+ newValue = module.get.normalizedValue(newValue);
229
+ module.set.progress(newValue);
230
+ },
231
+
232
+ has: {
233
+ progressPoll: function () {
234
+ return module.progressPoll;
235
+ },
236
+ total: function () {
237
+ return module.get.total() !== false;
238
+ },
239
+ },
240
+
241
+ get: {
242
+ text: function (templateText = '', index = 0) {
243
+ const value = module.get.value(index);
244
+ const total = module.get.total();
245
+ const percent = animating
246
+ ? module.get.displayPercent(index)
247
+ : module.get.percent(index);
248
+ const left = total !== false
249
+ ? Math.max(0, total - value)
250
+ : 100 - percent;
251
+ templateText = templateText
252
+ .replace('{value}', value)
253
+ .replace('{total}', total || 0)
254
+ .replace('{left}', left)
255
+ .replace('{percent}', percent)
256
+ .replace('{bar}', settings.text.bars[index] || '');
257
+ module.verbose('Adding variables to progress bar text', templateText);
258
+
259
+ return templateText;
260
+ },
261
+
262
+ normalizedValue: function (value) {
263
+ if (value < 0) {
264
+ module.debug('Value cannot decrement below 0');
265
+
266
+ return 0;
267
+ }
268
+ if (module.has.total()) {
269
+ if (value > module.total) {
270
+ module.debug('Value cannot increment above total', module.total);
271
+
272
+ return module.total;
273
+ }
274
+ } else if (value > 100) {
275
+ module.debug('Value cannot increment above 100 percent');
276
+
277
+ return 100;
278
+ }
279
+
280
+ return value;
281
+ },
282
+
283
+ updateInterval: function () {
284
+ if (settings.updateInterval === 'auto') {
285
+ return settings.duration;
286
+ }
287
+
288
+ return settings.updateInterval;
289
+ },
290
+
291
+ randomValue: function () {
292
+ module.debug('Generating random increment percentage');
293
+
294
+ return Math.floor((Math.random() * settings.random.max) + settings.random.min);
295
+ },
296
+
297
+ numericValue: function (value) {
298
+ return typeof value === 'string'
299
+ ? (value.replace(/[^\d.]/g, '') !== ''
300
+ ? +value.replace(/[^\d.]/g, '')
301
+ : false)
302
+ : value;
303
+ },
304
+
305
+ // gets current displayed percentage (if animating values, this is the intermediary value)
306
+ displayPercent: function (index) {
307
+ const $bar = $($bars[index]);
308
+ const barWidth = $bar.width();
309
+ const totalWidth = $module.width();
310
+ const minDisplay = Number.parseInt($bar.css('min-width'), 10);
311
+ const displayPercent = barWidth > minDisplay
312
+ ? (barWidth / totalWidth) * 100
313
+ : module.percent;
314
+
315
+ return settings.precision > 0
316
+ ? Math.round(displayPercent * (10 * settings.precision)) / (10 * settings.precision)
317
+ : Math.round(displayPercent);
318
+ },
319
+
320
+ percent: function (index) {
321
+ return (module.percent && module.percent[index || 0]) || 0;
322
+ },
323
+ value: function (index) {
324
+ return module.nextValue || (module.value && module.value[index || 0]) || 0;
325
+ },
326
+ total: function () {
327
+ return module.total !== undefined ? module.total : false;
328
+ },
329
+ },
330
+
331
+ create: {
332
+ progressPoll: function () {
333
+ module.progressPoll = setTimeout(function () {
334
+ module.update.toNextValue();
335
+ module.remove.progressPoll();
336
+ }, module.get.updateInterval());
337
+ },
338
+ },
339
+
340
+ is: {
341
+ complete: function () {
342
+ return module.is.success() || module.is.warning() || module.is.error();
343
+ },
344
+ success: function () {
345
+ return $module.hasClass(className.success);
346
+ },
347
+ warning: function () {
348
+ return $module.hasClass(className.warning);
349
+ },
350
+ error: function () {
351
+ return $module.hasClass(className.error);
352
+ },
353
+ active: function () {
354
+ return $module.hasClass(className.active);
355
+ },
356
+ visible: function () {
357
+ return $module.is(':visible');
358
+ },
359
+ },
360
+
361
+ remove: {
362
+ progressPoll: function () {
363
+ module.verbose('Removing progress poll timer');
364
+ if (module.progressPoll) {
365
+ clearTimeout(module.progressPoll);
366
+ delete module.progressPoll;
367
+ }
368
+ },
369
+ nextValue: function () {
370
+ module.verbose('Removing progress value stored for next update');
371
+ delete module.nextValue;
372
+ },
373
+ state: function () {
374
+ module.verbose('Removing stored state');
375
+ delete module.total;
376
+ delete module.percent;
377
+ delete module.value;
378
+ },
379
+ active: function () {
380
+ module.verbose('Removing active state');
381
+ $module.removeClass(className.active);
382
+ },
383
+ success: function () {
384
+ module.verbose('Removing success state');
385
+ $module.removeClass(className.success);
386
+ },
387
+ warning: function () {
388
+ module.verbose('Removing warning state');
389
+ $module.removeClass(className.warning);
390
+ },
391
+ error: function () {
392
+ module.verbose('Removing error state');
393
+ $module.removeClass(className.error);
394
+ },
395
+ },
396
+
397
+ set: {
398
+ barWidth: function (values) {
399
+ module.debug('set bar width with ', values);
400
+ values = module.helper.forceArray(values);
401
+ let firstNonZeroIndex = -1;
402
+ let lastNonZeroIndex = -1;
403
+ const valuesSum = module.helper.sum(values);
404
+ const barCounts = $bars.length;
405
+ const isMultiple = barCounts > 1;
406
+ const percents = values.map(function (value, index) {
407
+ const allZero = index === barCounts - 1 && valuesSum === 0;
408
+ const $bar = $($bars[index]);
409
+ if (value === 0 && isMultiple && !allZero) {
410
+ $bar.css('display', 'none');
411
+ } else {
412
+ if (isMultiple && allZero) {
413
+ $bar.css('background', 'transparent');
414
+ }
415
+ if (firstNonZeroIndex === -1) {
416
+ firstNonZeroIndex = index;
417
+ }
418
+ lastNonZeroIndex = index;
419
+ $bar.css({
420
+ display: 'block',
421
+ width: value + '%',
422
+ });
423
+ }
424
+
425
+ return Number.parseFloat(value);
426
+ });
427
+ for (const [index, _] of values.entries()) {
428
+ const $bar = $($bars[index]);
429
+ $bar.css({
430
+ borderTopLeftRadius: index === firstNonZeroIndex ? '' : '0',
431
+ borderBottomLeftRadius: index === firstNonZeroIndex ? '' : '0',
432
+ borderTopRightRadius: index === lastNonZeroIndex ? '' : '0',
433
+ borderBottomRightRadius: index === lastNonZeroIndex ? '' : '0',
434
+ });
435
+ }
436
+ $module
437
+ .attr('data-percent', percents);
438
+ },
439
+ duration: function (duration = settings.duration) {
440
+ duration = typeof duration === 'number'
441
+ ? duration + 'ms'
442
+ : duration;
443
+ module.verbose('Setting progress bar transition duration', duration);
444
+ $bars
445
+ .css({
446
+ 'transition-duration': duration,
447
+ });
448
+ },
449
+ percent: function (percents) {
450
+ percents = module.helper.forceArray(percents).map(function (percent) {
451
+ percent = typeof percent === 'string'
452
+ ? +percent.replace('%', '')
453
+ : percent;
454
+
455
+ return settings.limitValues
456
+ ? Math.max(0, Math.min(100, percent))
457
+ : percent;
458
+ });
459
+ const hasTotal = module.has.total();
460
+ const totalPercent = module.helper.sum(percents);
461
+ const isMultipleValues = percents.length > 1 && hasTotal;
462
+ const sumTotal = module.helper.sum(module.helper.forceArray(module.value));
463
+ if (isMultipleValues && sumTotal > module.total) {
464
+ // Sum values instead of percents to avoid precision issues when summing floats
465
+ module.error(error.sumExceedsTotal, sumTotal, module.total);
466
+ } else if (!isMultipleValues && totalPercent > 100) {
467
+ // Sum before rounding, since sum of rounded may have error though sum of actual is fine
468
+ module.error(error.tooHigh, totalPercent);
469
+ } else if (totalPercent < 0) {
470
+ module.error(error.tooLow, totalPercent);
471
+ } else {
472
+ const autoPrecision = settings.precision > 0
473
+ ? settings.precision
474
+ : (isMultipleValues
475
+ ? module.helper.derivePrecision(Math.min.apply(null, module.value), module.total)
476
+ : 0);
477
+
478
+ // round display percentage
479
+ const roundedPercents = percents.map(function (percent) {
480
+ return autoPrecision > 0
481
+ ? Math.round(percent * (10 * autoPrecision)) / (10 * autoPrecision)
482
+ : Math.round(percent);
483
+ });
484
+ module.percent = roundedPercents;
485
+ if (hasTotal) {
486
+ module.value = percents.map(function (percent) {
487
+ return autoPrecision > 0
488
+ ? Math.round((percent / 100) * module.total * (10 * autoPrecision)) / (10 * autoPrecision)
489
+ : Math.round((percent / 100) * module.total * 10) / 10;
490
+ });
491
+ }
492
+ module.set.barWidth(percents);
493
+ module.set.labelInterval();
494
+ }
495
+ settings.onChange.call(element, percents, module.value, module.total);
496
+ },
497
+ labelInterval: function () {
498
+ const animationCallback = function () {
499
+ module.verbose('Bar finished animating, removing continuous label updates');
500
+ clearInterval(module.interval);
501
+ animating = false;
502
+ module.set.labels();
503
+ };
504
+ clearInterval(module.interval);
505
+ module.bind.transitionEnd(animationCallback);
506
+ animating = true;
507
+ module.interval = setInterval(function () {
508
+ const isInDOM = document.documentElement.contains(element);
509
+ if (!isInDOM) {
510
+ clearInterval(module.interval);
511
+ animating = false;
512
+ }
513
+ module.set.labels();
514
+ }, settings.framerate);
515
+ },
516
+ labels: function () {
517
+ module.verbose('Setting both bar progress and outer label text');
518
+ module.set.barLabel();
519
+ module.set.state();
520
+ },
521
+ label: function (text) {
522
+ if (text) {
523
+ text = module.get.text(text);
524
+ module.verbose('Setting label to text', text);
525
+ $label.text(text);
526
+ }
527
+ },
528
+ state: function (percent = module.helper.sum(module.percent)) {
529
+ if (percent === 100) {
530
+ if (settings.autoSuccess && $bars.length === 1 && !(module.is.warning() || module.is.error() || module.is.success())) {
531
+ module.set.success();
532
+ module.debug('Automatically triggering success at 100%');
533
+ } else {
534
+ module.verbose('Reached 100% removing active state');
535
+ module.remove.active();
536
+ module.remove.progressPoll();
537
+ }
538
+ } else if (percent > 0) {
539
+ module.verbose('Adjusting active progress bar label', percent);
540
+ module.set.active();
541
+ } else {
542
+ module.remove.active();
543
+ module.remove.warning();
544
+ module.remove.error();
545
+ module.remove.success();
546
+ module.set.label(settings.text.active);
547
+ }
548
+ },
549
+ barLabel: function (text) {
550
+ $progresses.each(function (index, element) {
551
+ const $progress = $(element);
552
+ if (text !== undefined) {
553
+ $progress.text(module.get.text(text, index));
554
+ } else if (settings.label === 'ratio' && module.has.total()) {
555
+ module.verbose('Adding ratio to bar label');
556
+ $progress.text(module.get.text(settings.text.ratio, index));
557
+ } else if (settings.label === 'percent') {
558
+ module.verbose('Adding percentage to bar label');
559
+ $progress.text(module.get.text(settings.text.percent, index));
560
+ }
561
+ });
562
+ },
563
+ active: function (text = settings.text.active) {
564
+ module.debug('Setting active state');
565
+ if (settings.showActivity && !module.is.active()) {
566
+ $module.addClass(className.active);
567
+ }
568
+ module.remove.warning();
569
+ module.remove.error();
570
+ module.remove.success();
571
+ text = settings.onLabelUpdate('active', text, module.value, module.total);
572
+ if (text) {
573
+ module.set.label(text);
574
+ }
575
+ module.bind.transitionEnd(function () {
576
+ settings.onActive.call(element, module.value, module.total);
577
+ });
578
+ },
579
+ success: function (text = settings.text.success || settings.text.active, keepState = false) {
580
+ module.debug('Setting success state');
581
+ $module.addClass(className.success);
582
+ module.remove.active();
583
+ module.remove.warning();
584
+ module.remove.error();
585
+ module.complete(keepState);
586
+ if (settings.text.success) {
587
+ text = settings.onLabelUpdate('success', text, module.value, module.total);
588
+ module.set.label(text);
589
+ } else {
590
+ text = settings.onLabelUpdate('active', text, module.value, module.total);
591
+ module.set.label(text);
592
+ }
593
+ module.bind.transitionEnd(function () {
594
+ settings.onSuccess.call(element, module.total);
595
+ });
596
+ },
597
+ warning: function (text = settings.text.warning, keepState = false) {
598
+ module.debug('Setting warning state');
599
+ $module.addClass(className.warning);
600
+ module.remove.active();
601
+ module.remove.success();
602
+ module.remove.error();
603
+ module.complete(keepState);
604
+ text = settings.onLabelUpdate('warning', text, module.value, module.total);
605
+ if (text) {
606
+ module.set.label(text);
607
+ }
608
+ module.bind.transitionEnd(function () {
609
+ settings.onWarning.call(element, module.value, module.total);
610
+ });
611
+ },
612
+ error: function (text = settings.text.error, keepState = false) {
613
+ module.debug('Setting error state');
614
+ $module.addClass(className.error);
615
+ module.remove.active();
616
+ module.remove.success();
617
+ module.remove.warning();
618
+ module.complete(keepState);
619
+ text = settings.onLabelUpdate('error', text, module.value, module.total);
620
+ if (text) {
621
+ module.set.label(text);
622
+ }
623
+ module.bind.transitionEnd(function () {
624
+ settings.onError.call(element, module.value, module.total);
625
+ });
626
+ },
627
+ total: function (totalValue) {
628
+ module.total = totalValue;
629
+ },
630
+ value: function (value) {
631
+ module.value = module.helper.forceArray(value);
632
+ },
633
+ progress: function (value) {
634
+ if (!module.has.progressPoll()) {
635
+ module.debug('First update in progress update interval, immediately updating', value);
636
+ module.update.progress(value);
637
+ module.create.progressPoll();
638
+ } else {
639
+ module.debug('Updated within interval, setting next update to use new value', value);
640
+ module.set.nextValue(value);
641
+ }
642
+ },
643
+ nextValue: function (value) {
644
+ module.nextValue = value;
645
+ },
646
+ },
647
+
648
+ update: {
649
+ toNextValue: function () {
650
+ const nextValue = module.nextValue;
651
+ if (nextValue) {
652
+ module.debug('Update interval complete using last updated value', nextValue);
653
+ module.update.progress(nextValue);
654
+ module.remove.nextValue();
655
+ }
656
+ },
657
+ progress: function (values) {
658
+ const hasTotal = module.has.total();
659
+ if (hasTotal) {
660
+ module.set.value(values);
661
+ }
662
+ const percentCompletes = module.helper.forceArray(values).map(function (value) {
663
+ let percentComplete;
664
+ value = module.get.numericValue(value);
665
+ if (value === false) {
666
+ module.error(error.nonNumeric, value);
667
+ }
668
+ value = module.get.normalizedValue(value);
669
+ if (hasTotal) {
670
+ percentComplete = module.total > 0 ? (value / module.total) * 100 : 100;
671
+ module.debug('Calculating percent complete from total', percentComplete);
672
+ } else {
673
+ percentComplete = value;
674
+ module.debug('Setting value to exact percentage value', percentComplete);
675
+ }
676
+
677
+ return percentComplete;
678
+ });
679
+ module.set.percent(percentCompletes);
680
+ },
681
+ },
682
+
683
+ setting: function (name, value) {
684
+ module.debug('Changing setting', name, value);
685
+ if ($.isPlainObject(name)) {
686
+ $.extend(true, settings, name);
687
+ } else if (value !== undefined) {
688
+ if ($.isPlainObject(settings[name])) {
689
+ $.extend(true, settings[name], value);
690
+ } else {
691
+ settings[name] = value;
692
+ }
693
+ } else {
694
+ return settings[name];
695
+ }
696
+ },
697
+ internal: function (name, value) {
698
+ if ($.isPlainObject(name)) {
699
+ $.extend(true, module, name);
700
+ } else if (value !== undefined) {
701
+ module[name] = value;
702
+ } else {
703
+ return module[name];
704
+ }
705
+ },
706
+ debug: function (...args) {
707
+ if (!settings.silent && settings.debug) {
708
+ if (settings.performance) {
709
+ module.performance.log(args);
710
+ } else {
711
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
712
+ module.debug.apply(console, args);
713
+ }
714
+ }
715
+ },
716
+ verbose: function (...args) {
717
+ if (!settings.silent && settings.verbose && settings.debug) {
718
+ if (settings.performance) {
719
+ module.performance.log(args);
720
+ } else {
721
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
722
+ module.verbose.apply(console, args);
723
+ }
724
+ }
725
+ },
726
+ error: function (...args) {
727
+ if (!settings.silent) {
728
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
729
+ module.error.apply(console, args);
730
+ }
731
+ },
732
+ performance: {
733
+ log: function (message) {
734
+ let currentTime;
735
+ let executionTime;
736
+ let previousTime;
737
+ if (settings.performance) {
738
+ currentTime = Date.now();
739
+ previousTime = time || currentTime;
740
+ executionTime = currentTime - previousTime;
741
+ time = currentTime;
742
+ performance.push({
743
+ Name: message[0],
744
+ Arguments: message.slice(1),
745
+ Element: element,
746
+ 'Execution Time': executionTime,
747
+ });
748
+ }
749
+ clearTimeout(module.performance.timer);
750
+ module.performance.timer = setTimeout(function () {
751
+ module.performance.display();
752
+ }, 500);
753
+ },
754
+ display: function () {
755
+ let title = settings.name + ':';
756
+ let totalTime = 0;
757
+ time = false;
758
+ clearTimeout(module.performance.timer);
759
+ $.each(performance, function (index, data) {
760
+ totalTime += data['Execution Time'];
761
+ });
762
+ title += ' ' + totalTime + 'ms';
763
+ if (performance.length > 0) {
764
+ console.groupCollapsed(title);
765
+ console.table(performance);
766
+ console.groupEnd();
767
+ }
768
+ performance = [];
769
+ },
770
+ },
771
+ invoke: function (query, passedArguments = queryArguments, context = element) {
772
+ let object = instance;
773
+ let maxDepth;
774
+ let found;
775
+ let response;
776
+ if (typeof query === 'string' && object !== undefined) {
777
+ query = query.split(/[ .]/);
778
+ maxDepth = query.length - 1;
779
+ $.each(query, function (depth, value) {
780
+ const camelCaseValue = depth !== maxDepth
781
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
782
+ : query;
783
+ if ($.isPlainObject(object[camelCaseValue]) && (depth !== maxDepth)) {
784
+ object = object[camelCaseValue];
785
+ } else if (object[camelCaseValue] !== undefined) {
786
+ found = object[camelCaseValue];
787
+
788
+ return false;
789
+ } else if ($.isPlainObject(object[value]) && (depth !== maxDepth)) {
790
+ object = object[value];
791
+ } else if (object[value] !== undefined) {
792
+ found = object[value];
793
+
794
+ return false;
795
+ } else {
796
+ module.error(error.method, query);
797
+
798
+ return false;
799
+ }
800
+ });
801
+ }
802
+ if (isFunction(found)) {
803
+ response = found.apply(context, passedArguments);
804
+ } else if (found !== undefined) {
805
+ response = found;
806
+ }
807
+ if (Array.isArray(returnedValue)) {
808
+ returnedValue.push(response);
809
+ } else if (returnedValue !== undefined) {
810
+ returnedValue = [returnedValue, response];
811
+ } else if (response !== undefined) {
812
+ returnedValue = response;
813
+ }
814
+
815
+ return found;
816
+ },
817
+ };
818
+
819
+ if (methodInvoked) {
820
+ if (instance === undefined) {
821
+ module.initialize();
822
+ }
823
+ module.invoke(parameters);
824
+ } else {
825
+ if (instance !== undefined) {
826
+ instance.invoke('destroy');
827
+ }
828
+ module.initialize();
829
+ }
830
+ });
831
+
832
+ return returnedValue !== undefined
833
+ ? returnedValue
834
+ : this;
835
+ };
836
+
837
+ $.fn.progress.settings = {
838
+
839
+ name: 'Progress',
840
+ namespace: 'progress',
841
+
842
+ silent: false,
843
+ debug: false,
844
+ verbose: false,
845
+ performance: true,
846
+
847
+ random: {
848
+ min: 2,
849
+ max: 5,
850
+ },
851
+
852
+ duration: 300,
853
+
854
+ updateInterval: 'auto',
855
+
856
+ autoSuccess: true,
857
+ showActivity: true,
858
+ limitValues: true,
859
+
860
+ label: 'percent',
861
+ precision: 0,
862
+ framerate: 1000 / 30, /// 30 fps
863
+
864
+ percent: false,
865
+ total: false,
866
+ value: false,
867
+
868
+ // delay in ms for fail-safe animation callback
869
+ failSafeDelay: 100,
870
+
871
+ onLabelUpdate: function (state, text, value, total) {
872
+ return text;
873
+ },
874
+ onChange: function (percent, value, total) {},
875
+ onSuccess: function (total) {},
876
+ onActive: function (value, total) {},
877
+ onError: function (value, total) {},
878
+ onWarning: function (value, total) {},
879
+
880
+ error: {
881
+ method: 'The method you called is not defined.',
882
+ nonNumeric: 'Progress value is non numeric',
883
+ tooHigh: 'Value specified is above 100%',
884
+ tooLow: 'Value specified is below 0%',
885
+ sumExceedsTotal: 'Sum of multiple values exceed total',
886
+ },
887
+
888
+ regExp: {
889
+ variable: /{\$*[\da-z]+}/gi,
890
+ },
891
+
892
+ metadata: {
893
+ percent: 'percent',
894
+ total: 'total',
895
+ value: 'value',
896
+ },
897
+
898
+ selector: {
899
+ bar: '> .bar',
900
+ label: '> .label',
901
+ progress: '.bar > .progress',
902
+ },
903
+
904
+ text: {
905
+ active: false,
906
+ error: false,
907
+ success: false,
908
+ warning: false,
909
+ percent: '{percent}%',
910
+ ratio: '{value} of {total}',
911
+ bars: [''],
912
+ },
913
+
914
+ className: {
915
+ active: 'active',
916
+ error: 'error',
917
+ success: 'success',
918
+ warning: 'warning',
919
+ },
920
+
921
+ };
922
+ })(jQuery, window, document);