rails-active-ui 0.3.0 → 0.3.2

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 (197) hide show
  1. checksums.yaml +4 -4
  2. data/app/javascript/ui/controllers/turbo_modal_controller.js +36 -0
  3. data/config/importmap.rb +1 -0
  4. data/formantic-ui/components/accordion.css +369 -0
  5. data/formantic-ui/components/accordion.js +595 -0
  6. data/formantic-ui/components/accordion.min.css +9 -0
  7. data/formantic-ui/components/accordion.min.js +11 -0
  8. data/formantic-ui/components/ad.css +264 -0
  9. data/formantic-ui/components/ad.min.css +10 -0
  10. data/formantic-ui/components/api.js +1225 -0
  11. data/formantic-ui/components/api.min.js +11 -0
  12. data/formantic-ui/components/breadcrumb.css +135 -0
  13. data/formantic-ui/components/breadcrumb.min.css +9 -0
  14. data/formantic-ui/components/button.css +4058 -0
  15. data/formantic-ui/components/button.min.css +9 -0
  16. data/formantic-ui/components/calendar.css +327 -0
  17. data/formantic-ui/components/calendar.js +2045 -0
  18. data/formantic-ui/components/calendar.min.css +9 -0
  19. data/formantic-ui/components/calendar.min.js +11 -0
  20. data/formantic-ui/components/card.css +1881 -0
  21. data/formantic-ui/components/card.min.css +9 -0
  22. data/formantic-ui/components/checkbox.css +785 -0
  23. data/formantic-ui/components/checkbox.js +888 -0
  24. data/formantic-ui/components/checkbox.min.css +9 -0
  25. data/formantic-ui/components/checkbox.min.js +11 -0
  26. data/formantic-ui/components/comment.css +283 -0
  27. data/formantic-ui/components/comment.min.css +9 -0
  28. data/formantic-ui/components/container.css +300 -0
  29. data/formantic-ui/components/container.min.css +9 -0
  30. data/formantic-ui/components/dimmer.css +367 -0
  31. data/formantic-ui/components/dimmer.js +732 -0
  32. data/formantic-ui/components/dimmer.min.css +9 -0
  33. data/formantic-ui/components/dimmer.min.js +11 -0
  34. data/formantic-ui/components/divider.css +287 -0
  35. data/formantic-ui/components/divider.min.css +9 -0
  36. data/formantic-ui/components/dropdown.css +2087 -0
  37. data/formantic-ui/components/dropdown.js +4432 -0
  38. data/formantic-ui/components/dropdown.min.css +9 -0
  39. data/formantic-ui/components/dropdown.min.js +11 -0
  40. data/formantic-ui/components/embed.css +155 -0
  41. data/formantic-ui/components/embed.js +688 -0
  42. data/formantic-ui/components/embed.min.css +9 -0
  43. data/formantic-ui/components/embed.min.js +11 -0
  44. data/formantic-ui/components/emoji.css +15311 -0
  45. data/formantic-ui/components/emoji.min.css +9 -0
  46. data/formantic-ui/components/feed.css +799 -0
  47. data/formantic-ui/components/feed.min.css +9 -0
  48. data/formantic-ui/components/flag.css +1149 -0
  49. data/formantic-ui/components/flag.min.css +9 -0
  50. data/formantic-ui/components/flyout.css +546 -0
  51. data/formantic-ui/components/flyout.js +1551 -0
  52. data/formantic-ui/components/flyout.min.css +9 -0
  53. data/formantic-ui/components/flyout.min.js +11 -0
  54. data/formantic-ui/components/form.css +1885 -0
  55. data/formantic-ui/components/form.js +2199 -0
  56. data/formantic-ui/components/form.min.css +9 -0
  57. data/formantic-ui/components/form.min.js +11 -0
  58. data/formantic-ui/components/grid.css +1952 -0
  59. data/formantic-ui/components/grid.min.css +9 -0
  60. data/formantic-ui/components/header.css +778 -0
  61. data/formantic-ui/components/header.min.css +9 -0
  62. data/formantic-ui/components/icon.css +7066 -0
  63. data/formantic-ui/components/icon.min.css +9 -0
  64. data/formantic-ui/components/image.css +315 -0
  65. data/formantic-ui/components/image.min.css +9 -0
  66. data/formantic-ui/components/input.css +1566 -0
  67. data/formantic-ui/components/input.min.css +9 -0
  68. data/formantic-ui/components/item.css +534 -0
  69. data/formantic-ui/components/item.min.css +9 -0
  70. data/formantic-ui/components/label.css +2114 -0
  71. data/formantic-ui/components/label.min.css +9 -0
  72. data/formantic-ui/components/list.css +955 -0
  73. data/formantic-ui/components/list.min.css +9 -0
  74. data/formantic-ui/components/loader.css +787 -0
  75. data/formantic-ui/components/loader.min.css +9 -0
  76. data/formantic-ui/components/menu.css +2131 -0
  77. data/formantic-ui/components/menu.min.css +9 -0
  78. data/formantic-ui/components/message.css +619 -0
  79. data/formantic-ui/components/message.min.css +9 -0
  80. data/formantic-ui/components/modal.css +779 -0
  81. data/formantic-ui/components/modal.js +1637 -0
  82. data/formantic-ui/components/modal.min.css +9 -0
  83. data/formantic-ui/components/modal.min.js +11 -0
  84. data/formantic-ui/components/nag.css +290 -0
  85. data/formantic-ui/components/nag.js +566 -0
  86. data/formantic-ui/components/nag.min.css +9 -0
  87. data/formantic-ui/components/nag.min.js +11 -0
  88. data/formantic-ui/components/placeholder.css +228 -0
  89. data/formantic-ui/components/placeholder.min.css +9 -0
  90. data/formantic-ui/components/popup.css +1184 -0
  91. data/formantic-ui/components/popup.js +1561 -0
  92. data/formantic-ui/components/popup.min.css +9 -0
  93. data/formantic-ui/components/popup.min.js +11 -0
  94. data/formantic-ui/components/progress.css +761 -0
  95. data/formantic-ui/components/progress.js +979 -0
  96. data/formantic-ui/components/progress.min.css +9 -0
  97. data/formantic-ui/components/progress.min.js +11 -0
  98. data/formantic-ui/components/rail.css +147 -0
  99. data/formantic-ui/components/rail.min.css +9 -0
  100. data/formantic-ui/components/rating.css +414 -0
  101. data/formantic-ui/components/rating.js +540 -0
  102. data/formantic-ui/components/rating.min.css +9 -0
  103. data/formantic-ui/components/rating.min.js +11 -0
  104. data/formantic-ui/components/reset.css +386 -0
  105. data/formantic-ui/components/reset.min.css +9 -0
  106. data/formantic-ui/components/reveal.css +277 -0
  107. data/formantic-ui/components/reveal.min.css +9 -0
  108. data/formantic-ui/components/search.css +541 -0
  109. data/formantic-ui/components/search.js +1641 -0
  110. data/formantic-ui/components/search.min.css +9 -0
  111. data/formantic-ui/components/search.min.js +11 -0
  112. data/formantic-ui/components/segment.css +1053 -0
  113. data/formantic-ui/components/segment.min.css +9 -0
  114. data/formantic-ui/components/shape.css +144 -0
  115. data/formantic-ui/components/shape.js +797 -0
  116. data/formantic-ui/components/shape.min.css +9 -0
  117. data/formantic-ui/components/shape.min.js +11 -0
  118. data/formantic-ui/components/sidebar.css +539 -0
  119. data/formantic-ui/components/sidebar.js +1054 -0
  120. data/formantic-ui/components/sidebar.min.css +9 -0
  121. data/formantic-ui/components/sidebar.min.js +11 -0
  122. data/formantic-ui/components/site.css +286 -0
  123. data/formantic-ui/components/site.js +455 -0
  124. data/formantic-ui/components/site.min.css +9 -0
  125. data/formantic-ui/components/site.min.js +11 -0
  126. data/formantic-ui/components/slider.css +926 -0
  127. data/formantic-ui/components/slider.js +1546 -0
  128. data/formantic-ui/components/slider.min.css +9 -0
  129. data/formantic-ui/components/slider.min.js +11 -0
  130. data/formantic-ui/components/state.js +697 -0
  131. data/formantic-ui/components/state.min.js +11 -0
  132. data/formantic-ui/components/statistic.css +586 -0
  133. data/formantic-ui/components/statistic.min.css +9 -0
  134. data/formantic-ui/components/step.css +1538 -0
  135. data/formantic-ui/components/step.min.css +9 -0
  136. data/formantic-ui/components/sticky.css +73 -0
  137. data/formantic-ui/components/sticky.js +917 -0
  138. data/formantic-ui/components/sticky.min.css +9 -0
  139. data/formantic-ui/components/sticky.min.js +11 -0
  140. data/formantic-ui/components/tab.css +84 -0
  141. data/formantic-ui/components/tab.js +967 -0
  142. data/formantic-ui/components/tab.min.css +9 -0
  143. data/formantic-ui/components/tab.min.js +11 -0
  144. data/formantic-ui/components/table.css +3473 -0
  145. data/formantic-ui/components/table.min.css +9 -0
  146. data/formantic-ui/components/text.css +155 -0
  147. data/formantic-ui/components/text.min.css +9 -0
  148. data/formantic-ui/components/toast.css +751 -0
  149. data/formantic-ui/components/toast.js +964 -0
  150. data/formantic-ui/components/toast.min.css +9 -0
  151. data/formantic-ui/components/toast.min.js +11 -0
  152. data/formantic-ui/components/transition.css +1148 -0
  153. data/formantic-ui/components/transition.js +1034 -0
  154. data/formantic-ui/components/transition.min.css +9 -0
  155. data/formantic-ui/components/transition.min.js +11 -0
  156. data/formantic-ui/components/visibility.js +1292 -0
  157. data/formantic-ui/components/visibility.min.js +11 -0
  158. data/formantic-ui/semantic.css +78485 -0
  159. data/formantic-ui/semantic.js +31036 -0
  160. data/formantic-ui/semantic.min.css +11 -0
  161. data/formantic-ui/semantic.min.js +11 -0
  162. data/formantic-ui/themes/basic/assets/fonts/LICENSE.txt +91 -0
  163. data/formantic-ui/themes/basic/assets/fonts/icons.woff +0 -0
  164. data/formantic-ui/themes/basic/assets/fonts/icons.woff2 +0 -0
  165. data/formantic-ui/themes/default/assets/fonts/LICENSE_Lato.txt +94 -0
  166. data/formantic-ui/themes/default/assets/fonts/LICENSE_icons.txt +165 -0
  167. data/formantic-ui/themes/default/assets/fonts/Lato-Bold.woff +0 -0
  168. data/formantic-ui/themes/default/assets/fonts/Lato-Bold.woff2 +0 -0
  169. data/formantic-ui/themes/default/assets/fonts/Lato-BoldItalic.woff +0 -0
  170. data/formantic-ui/themes/default/assets/fonts/Lato-BoldItalic.woff2 +0 -0
  171. data/formantic-ui/themes/default/assets/fonts/Lato-Italic.woff +0 -0
  172. data/formantic-ui/themes/default/assets/fonts/Lato-Italic.woff2 +0 -0
  173. data/formantic-ui/themes/default/assets/fonts/Lato-Regular.woff +0 -0
  174. data/formantic-ui/themes/default/assets/fonts/Lato-Regular.woff2 +0 -0
  175. data/formantic-ui/themes/default/assets/fonts/LatoLatin-Bold.woff +0 -0
  176. data/formantic-ui/themes/default/assets/fonts/LatoLatin-Bold.woff2 +0 -0
  177. data/formantic-ui/themes/default/assets/fonts/LatoLatin-BoldItalic.woff +0 -0
  178. data/formantic-ui/themes/default/assets/fonts/LatoLatin-BoldItalic.woff2 +0 -0
  179. data/formantic-ui/themes/default/assets/fonts/LatoLatin-Italic.woff +0 -0
  180. data/formantic-ui/themes/default/assets/fonts/LatoLatin-Italic.woff2 +0 -0
  181. data/formantic-ui/themes/default/assets/fonts/LatoLatin-Regular.woff +0 -0
  182. data/formantic-ui/themes/default/assets/fonts/LatoLatin-Regular.woff2 +0 -0
  183. data/formantic-ui/themes/default/assets/fonts/brand-icons.woff +0 -0
  184. data/formantic-ui/themes/default/assets/fonts/brand-icons.woff2 +0 -0
  185. data/formantic-ui/themes/default/assets/fonts/icons.woff +0 -0
  186. data/formantic-ui/themes/default/assets/fonts/icons.woff2 +0 -0
  187. data/formantic-ui/themes/default/assets/fonts/outline-icons.woff +0 -0
  188. data/formantic-ui/themes/default/assets/fonts/outline-icons.woff2 +0 -0
  189. data/formantic-ui/themes/famfamfam/assets/images/flags.png +0 -0
  190. data/formantic-ui/themes/github/assets/fonts/LICENSE.txt +94 -0
  191. data/formantic-ui/themes/github/assets/fonts/octicons.woff +0 -0
  192. data/formantic-ui/themes/github/assets/fonts/octicons.woff2 +0 -0
  193. data/formantic-ui/themes/material/assets/fonts/LICENSE.txt +202 -0
  194. data/formantic-ui/themes/material/assets/fonts/icons.woff +0 -0
  195. data/formantic-ui/themes/material/assets/fonts/icons.woff2 +0 -0
  196. data/lib/ui/version.rb +1 -1
  197. metadata +194 -1
@@ -0,0 +1,967 @@
1
+ /*!
2
+ * # Fomantic-UI 2.9.4 - Tab
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.tab = function (parameters) {
27
+ var
28
+ // use window context if none specified
29
+ $allModules = isFunction(this)
30
+ ? $(window)
31
+ : $(this),
32
+ $document = $(document),
33
+ time = Date.now(),
34
+ performance = [],
35
+
36
+ query = arguments[0],
37
+ methodInvoked = typeof query === 'string',
38
+ queryArguments = [].slice.call(arguments, 1),
39
+ contextCheck = function (context, win) {
40
+ var $context;
41
+ if ([window, document].indexOf(context) >= 0) {
42
+ $context = $(context);
43
+ } else {
44
+ $context = $(win.document).find(context);
45
+ if ($context.length === 0) {
46
+ $context = win.frameElement ? contextCheck(context, win.parent) : window;
47
+ }
48
+ }
49
+
50
+ return $context;
51
+ },
52
+ initializedHistory = false,
53
+ returnedValue
54
+ ;
55
+
56
+ $allModules.each(function () {
57
+ var
58
+ settings = $.isPlainObject(parameters)
59
+ ? $.extend(true, {}, $.fn.tab.settings, parameters)
60
+ : $.extend({}, $.fn.tab.settings),
61
+
62
+ className = settings.className,
63
+ metadata = settings.metadata,
64
+ selector = settings.selector,
65
+ error = settings.error,
66
+ regExp = settings.regExp,
67
+
68
+ eventNamespace = '.' + settings.namespace,
69
+ moduleNamespace = 'module-' + settings.namespace,
70
+
71
+ $module = $(this),
72
+ $context,
73
+ $tabs,
74
+
75
+ cache = {},
76
+ firstLoad = true,
77
+ recursionDepth = 0,
78
+ element = this,
79
+ instance = $module.data(moduleNamespace),
80
+
81
+ activeTabPath,
82
+ parameterArray,
83
+ module,
84
+
85
+ historyEvent
86
+ ;
87
+
88
+ module = {
89
+
90
+ initialize: function () {
91
+ module.debug('Initializing tab menu item', $module);
92
+ module.determineTabs();
93
+
94
+ module.debug('Determining tabs', settings.context, $tabs);
95
+ // set up automatic routing
96
+ if (settings.auto) {
97
+ module.set.auto();
98
+ }
99
+ module.bind.events();
100
+
101
+ if (settings.history && !initializedHistory) {
102
+ settings.history = module.initializeHistory();
103
+ initializedHistory = true;
104
+ }
105
+
106
+ var activeTab = module.determine.activeTab();
107
+ if (settings.autoTabActivation && instance === undefined && activeTab === null) {
108
+ activeTab = settings.autoTabActivation === true ? module.get.initialPath() : settings.autoTabActivation;
109
+ module.debug('No active tab detected, setting tab active', activeTab);
110
+ module.changeTab(activeTab);
111
+ }
112
+ if (activeTab !== null && settings.history && settings.historyType === 'state') {
113
+ var autoUpdate = $.address.autoUpdate();
114
+ $.address.autoUpdate(false);
115
+ $.address.value(activeTab);
116
+ $.address.autoUpdate(autoUpdate);
117
+ }
118
+
119
+ module.instantiate();
120
+ },
121
+
122
+ instantiate: function () {
123
+ module.verbose('Storing instance of module', module);
124
+ instance = module;
125
+ $module
126
+ .data(moduleNamespace, module)
127
+ ;
128
+ },
129
+
130
+ destroy: function () {
131
+ module.debug('Destroying tabs', $module);
132
+ $module
133
+ .removeData(moduleNamespace)
134
+ .off(eventNamespace)
135
+ ;
136
+ },
137
+
138
+ bind: {
139
+ events: function () {
140
+ // if using $.tab don't add events
141
+ if (!isWindow(element)) {
142
+ module.debug('Attaching tab activation events to element', $module);
143
+ $module
144
+ .on('click' + eventNamespace, module.event.click)
145
+ ;
146
+ }
147
+ },
148
+ },
149
+
150
+ determineTabs: function () {
151
+ var
152
+ $reference
153
+ ;
154
+
155
+ // determine tab context
156
+ if (settings.context === 'parent') {
157
+ if ($module.closest(selector.ui).length > 0) {
158
+ $reference = $module.closest(selector.ui);
159
+ module.verbose('Using closest UI element as parent', $reference);
160
+ } else {
161
+ $reference = $module;
162
+ }
163
+ $context = $reference.parent();
164
+ module.verbose('Determined parent element for creating context', $context);
165
+ } else if (settings.context) {
166
+ $context = contextCheck(settings.context, window);
167
+ module.verbose('Using selector for tab context', settings.context, $context);
168
+ } else {
169
+ $context = $('body');
170
+ }
171
+ // find tabs
172
+ if (settings.childrenOnly) {
173
+ $tabs = $context.children(selector.tabs);
174
+ module.debug('Searching tab context children for tabs', $context, $tabs);
175
+ } else {
176
+ $tabs = $context.find(selector.tabs);
177
+ module.debug('Searching tab context for tabs', $context, $tabs);
178
+ }
179
+ },
180
+
181
+ initializeHistory: function () {
182
+ module.debug('Initializing page state');
183
+ if ($.address === undefined) {
184
+ module.error(error.state);
185
+
186
+ return false;
187
+ }
188
+ if (settings.historyType === 'state') {
189
+ module.debug('Using HTML5 to manage state');
190
+ if (settings.path !== false) {
191
+ $.address
192
+ .history(true)
193
+ .state(settings.path)
194
+ ;
195
+ $(window).trigger('popstate');
196
+ } else {
197
+ module.error(error.path);
198
+
199
+ return false;
200
+ }
201
+ }
202
+ $.address
203
+ .bind('change', module.event.history.change)
204
+ ;
205
+
206
+ return true;
207
+ },
208
+
209
+ event: {
210
+ click: function (event) {
211
+ var
212
+ tabPath = $(this).data(metadata.tab)
213
+ ;
214
+ if (tabPath !== undefined) {
215
+ if (settings.history) {
216
+ module.verbose('Updating page state', event);
217
+ $.address.value(tabPath);
218
+ } else {
219
+ module.verbose('Changing tab', event);
220
+ module.changeTab(tabPath);
221
+ }
222
+ event.preventDefault();
223
+ } else {
224
+ module.debug('No tab specified');
225
+ }
226
+ },
227
+ history: {
228
+ change: function (event) {
229
+ var
230
+ tabPath = event.pathNames.join('/') || module.get.initialPath(),
231
+ pageTitle = settings.templates.determineTitle(tabPath) || false
232
+ ;
233
+ module.performance.display();
234
+ module.debug('History change event', tabPath, event);
235
+ historyEvent = event;
236
+ if (tabPath !== undefined) {
237
+ module.changeTab(tabPath);
238
+ }
239
+ if (pageTitle) {
240
+ $.address.title(pageTitle);
241
+ }
242
+ },
243
+ },
244
+ },
245
+
246
+ refresh: function () {
247
+ if (activeTabPath) {
248
+ module.debug('Refreshing tab', activeTabPath);
249
+ module.changeTab(activeTabPath);
250
+ }
251
+ },
252
+
253
+ cache: {
254
+
255
+ read: function (cacheKey) {
256
+ return cacheKey !== undefined
257
+ ? cache[cacheKey]
258
+ : false;
259
+ },
260
+ add: function (cacheKey, content) {
261
+ cacheKey = cacheKey || activeTabPath;
262
+ module.debug('Adding cached content for', cacheKey);
263
+ cache[cacheKey] = content;
264
+ },
265
+ remove: function (cacheKey) {
266
+ cacheKey = cacheKey || activeTabPath;
267
+ module.debug('Removing cached content for', cacheKey);
268
+ delete cache[cacheKey];
269
+ },
270
+ },
271
+
272
+ escape: {
273
+ string: function (text) {
274
+ text = String(text);
275
+
276
+ return text.replace(regExp.escape, '\\$&');
277
+ },
278
+ },
279
+
280
+ set: {
281
+ auto: function () {
282
+ var
283
+ url = typeof settings.path === 'string'
284
+ ? settings.path.replace(/\/$/, '') + '/{$tab}'
285
+ : '/{$tab}'
286
+ ;
287
+ module.verbose('Setting up automatic tab retrieval from server', url);
288
+ if ($.isPlainObject(settings.apiSettings)) {
289
+ settings.apiSettings.url = url;
290
+ } else {
291
+ settings.apiSettings = {
292
+ url: url,
293
+ };
294
+ }
295
+ },
296
+ loading: function (tabPath) {
297
+ var
298
+ $tab = module.get.tabElement(tabPath),
299
+ isLoading = $tab.hasClass(className.loading)
300
+ ;
301
+ if (!isLoading) {
302
+ module.verbose('Setting loading state for', $tab);
303
+ $tab
304
+ .addClass(className.loading)
305
+ .siblings($tabs)
306
+ .removeClass(className.active + ' ' + className.loading)
307
+ ;
308
+ if ($tab.length > 0) {
309
+ settings.onRequest.call($tab[0], tabPath);
310
+ }
311
+ }
312
+ },
313
+ state: function (state) {
314
+ $.address.value(state);
315
+ },
316
+ },
317
+
318
+ changeTab: function (tabPath) {
319
+ var
320
+ pushStateAvailable = window.history && window.history.pushState,
321
+ shouldIgnoreLoad = pushStateAvailable && settings.ignoreFirstLoad && firstLoad,
322
+ remoteContent = settings.auto || $.isPlainObject(settings.apiSettings),
323
+ // only add default path if not remote content
324
+ pathArray = remoteContent && !shouldIgnoreLoad
325
+ ? module.utilities.pathToArray(tabPath)
326
+ : module.get.defaultPathArray(tabPath)
327
+ ;
328
+ tabPath = module.utilities.arrayToPath(pathArray);
329
+ $.each(pathArray, function (index, tab) {
330
+ var
331
+ currentPathArray = pathArray.slice(0, index + 1),
332
+ currentPath = module.utilities.arrayToPath(currentPathArray),
333
+
334
+ isTab = module.is.tab(currentPath),
335
+ isLastIndex = index + 1 === pathArray.length,
336
+
337
+ $tab = module.get.tabElement(currentPath),
338
+ $anchor,
339
+ nextPathArray,
340
+ nextPath,
341
+ isLastTab
342
+ ;
343
+ module.verbose('Looking for tab', tab);
344
+ if (isTab) {
345
+ module.verbose('Tab was found', tab);
346
+ // scope up
347
+ activeTabPath = currentPath;
348
+ parameterArray = module.utilities.filterArray(pathArray, currentPathArray);
349
+
350
+ if (isLastIndex) {
351
+ isLastTab = true;
352
+ } else {
353
+ nextPathArray = pathArray.slice(0, index + 2);
354
+ nextPath = module.utilities.arrayToPath(nextPathArray);
355
+ isLastTab = !module.is.tab(nextPath);
356
+ if (isLastTab) {
357
+ module.verbose('Tab parameters found', nextPathArray);
358
+ }
359
+ }
360
+ if (settings.onBeforeChange.call(element, currentPath) === false) {
361
+ module.debug('onBeforeChange returned false, cancelling tab change', $tab);
362
+
363
+ return false;
364
+ }
365
+ if (isLastTab && remoteContent) {
366
+ if (!shouldIgnoreLoad) {
367
+ module.activate.navigation(currentPath);
368
+ module.fetch.content(currentPath, tabPath);
369
+ } else {
370
+ module.debug('Ignoring remote content on first tab load', currentPath);
371
+ firstLoad = false;
372
+ module.cache.add(tabPath, $tab.html());
373
+ module.activate.all(currentPath);
374
+ settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
375
+ settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
376
+ }
377
+
378
+ return false;
379
+ }
380
+
381
+ module.debug('Opened local tab', currentPath);
382
+ module.activate.all(currentPath);
383
+ if (!module.cache.read(currentPath)) {
384
+ module.cache.add(currentPath, true);
385
+ module.debug('First time tab loaded calling tab init');
386
+ settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
387
+ }
388
+ settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
389
+ } else if (tabPath.search('/') === -1 && tabPath !== '') {
390
+ // look for in page anchor
391
+ tabPath = module.escape.string(tabPath);
392
+ $anchor = $('#' + tabPath + ', a[name="' + tabPath + '"]');
393
+ currentPath = $anchor.closest('[data-tab]').data(metadata.tab);
394
+ $tab = module.get.tabElement(currentPath);
395
+ // if anchor exists use parent tab
396
+ if ($anchor && $anchor.length > 0 && currentPath) {
397
+ module.debug('Anchor link used, opening parent tab', $tab, $anchor);
398
+ if (settings.onBeforeChange.call(element, currentPath) === false) {
399
+ module.debug('onBeforeChange returned false, cancelling tab change', $tab);
400
+
401
+ return false;
402
+ }
403
+ if (!$tab.hasClass(className.active)) {
404
+ setTimeout(function () {
405
+ module.scrollTo($anchor);
406
+ }, 0);
407
+ }
408
+ module.activate.all(currentPath);
409
+ if (!module.cache.read(currentPath)) {
410
+ module.cache.add(currentPath, true);
411
+ module.debug('First time tab loaded calling tab init');
412
+ settings.onFirstLoad.call($tab[0], currentPath, parameterArray, historyEvent);
413
+ }
414
+ settings.onLoad.call($tab[0], currentPath, parameterArray, historyEvent);
415
+
416
+ return false;
417
+ }
418
+ } else {
419
+ module.error(error.missingTab, $module, $context, currentPath);
420
+
421
+ return false;
422
+ }
423
+ });
424
+ },
425
+
426
+ scrollTo: function ($element) {
427
+ var
428
+ scrollOffset = $element && $element.length > 0
429
+ ? $element.offset().top
430
+ : false
431
+ ;
432
+ if (scrollOffset !== false) {
433
+ module.debug('Forcing scroll to an in-page link in a hidden tab', scrollOffset, $element);
434
+ $document.scrollTop(scrollOffset);
435
+ }
436
+ },
437
+
438
+ update: {
439
+ content: function (tabPath, html, evaluateScripts) {
440
+ var
441
+ $tab = module.get.tabElement(tabPath),
442
+ tab = $tab[0]
443
+ ;
444
+ evaluateScripts = evaluateScripts !== undefined
445
+ ? evaluateScripts
446
+ : settings.evaluateScripts;
447
+ if (typeof settings.cacheType === 'string' && settings.cacheType.toLowerCase() === 'dom' && typeof html !== 'string') {
448
+ $tab
449
+ .empty()
450
+ .append($(html).clone(true))
451
+ ;
452
+ } else {
453
+ if (evaluateScripts) {
454
+ module.debug('Updating HTML and evaluating inline scripts', tabPath, html);
455
+ $tab.html(html);
456
+ } else {
457
+ module.debug('Updating HTML', tabPath, html);
458
+ tab.innerHTML = html;
459
+ }
460
+ }
461
+ },
462
+ },
463
+
464
+ fetch: {
465
+
466
+ content: function (tabPath, fullTabPath) {
467
+ var
468
+ $tab = module.get.tabElement(tabPath),
469
+ apiSettings = {
470
+ dataType: 'html',
471
+ encodeParameters: false,
472
+ on: 'now',
473
+ cache: settings.alwaysRefresh,
474
+ headers: {
475
+ 'X-Remote': true,
476
+ },
477
+ onSuccess: function (response) {
478
+ if (settings.cacheType === 'response') {
479
+ module.cache.add(fullTabPath, response);
480
+ }
481
+ module.update.content(tabPath, response);
482
+ if (tabPath == activeTabPath) {
483
+ module.debug('Content loaded', tabPath);
484
+ module.activate.tab(tabPath);
485
+ } else {
486
+ module.debug('Content loaded in background', tabPath);
487
+ }
488
+ settings.onFirstLoad.call($tab[0], tabPath, parameterArray, historyEvent);
489
+ settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
490
+
491
+ if (settings.loadOnce) {
492
+ module.cache.add(fullTabPath, true);
493
+ } else if (typeof settings.cacheType === 'string' && settings.cacheType.toLowerCase() === 'dom' && $tab.children().length > 0) {
494
+ setTimeout(function () {
495
+ var
496
+ $clone = $tab.children().clone(true)
497
+ ;
498
+ $clone = $clone.not('script');
499
+ module.cache.add(fullTabPath, $clone);
500
+ }, 0);
501
+ } else {
502
+ module.cache.add(fullTabPath, $tab.html());
503
+ }
504
+ },
505
+ urlData: {
506
+ tab: fullTabPath,
507
+ },
508
+ },
509
+ request = $tab.api('get request') || false,
510
+ existingRequest = request && request.state() === 'pending',
511
+ requestSettings,
512
+ cachedContent
513
+ ;
514
+
515
+ fullTabPath = fullTabPath || tabPath;
516
+ cachedContent = module.cache.read(fullTabPath);
517
+
518
+ if (settings.cache && cachedContent) {
519
+ module.activate.tab(tabPath);
520
+ module.debug('Adding cached content', fullTabPath);
521
+ if (!settings.loadOnce) {
522
+ if (settings.evaluateScripts === 'once') {
523
+ module.update.content(tabPath, cachedContent, false);
524
+ } else {
525
+ module.update.content(tabPath, cachedContent);
526
+ }
527
+ }
528
+ settings.onLoad.call($tab[0], tabPath, parameterArray, historyEvent);
529
+ } else if (existingRequest) {
530
+ module.set.loading(tabPath);
531
+ module.debug('Content is already loading', fullTabPath);
532
+ } else if ($.api !== undefined) {
533
+ requestSettings = $.extend(true, {}, settings.apiSettings, apiSettings);
534
+ module.debug('Retrieving remote content', fullTabPath, requestSettings);
535
+ module.set.loading(tabPath);
536
+ $tab.api(requestSettings);
537
+ } else {
538
+ module.error(error.api);
539
+ }
540
+ },
541
+ },
542
+
543
+ activate: {
544
+ all: function (tabPath) {
545
+ module.activate.tab(tabPath);
546
+ module.activate.navigation(tabPath);
547
+ },
548
+ tab: function (tabPath) {
549
+ var
550
+ $tab = module.get.tabElement(tabPath),
551
+ $deactiveTabs = settings.deactivate === 'siblings'
552
+ ? $tab.siblings($tabs)
553
+ : $tabs.not($tab),
554
+ isActive = $tab.hasClass(className.active)
555
+ ;
556
+ module.verbose('Showing tab content for', $tab);
557
+ if (!isActive) {
558
+ $tab
559
+ .addClass(className.active)
560
+ ;
561
+ $deactiveTabs
562
+ .removeClass(className.active + ' ' + className.loading)
563
+ ;
564
+ if ($tab.length > 0) {
565
+ settings.onVisible.call($tab[0], tabPath);
566
+ }
567
+ }
568
+ },
569
+ navigation: function (tabPath) {
570
+ var
571
+ $navigation = module.get.navElement(tabPath),
572
+ $deactiveNavigation = settings.deactivate === 'siblings'
573
+ ? $navigation.siblings($allModules)
574
+ : $allModules.not($navigation),
575
+ isActive = $navigation.hasClass(className.active)
576
+ ;
577
+ module.verbose('Activating tab navigation for', $navigation, tabPath);
578
+ if (!isActive) {
579
+ $navigation
580
+ .addClass(className.active)
581
+ ;
582
+ $deactiveNavigation
583
+ .removeClass(className.active + ' ' + className.loading)
584
+ ;
585
+ }
586
+ },
587
+ },
588
+
589
+ deactivate: {
590
+ all: function () {
591
+ module.deactivate.navigation();
592
+ module.deactivate.tabs();
593
+ },
594
+ navigation: function () {
595
+ $allModules
596
+ .removeClass(className.active)
597
+ ;
598
+ },
599
+ tabs: function () {
600
+ $tabs
601
+ .removeClass(className.active + ' ' + className.loading)
602
+ ;
603
+ },
604
+ },
605
+
606
+ is: {
607
+ tab: function (tabName) {
608
+ return tabName !== undefined
609
+ ? module.get.tabElement(tabName).length > 0
610
+ : false;
611
+ },
612
+ },
613
+
614
+ get: {
615
+ initialPath: function () {
616
+ return $allModules.eq(0).data(metadata.tab) || $tabs.eq(0).data(metadata.tab);
617
+ },
618
+ path: function () {
619
+ return $.address.value();
620
+ },
621
+ // adds default tabs to tab path
622
+ defaultPathArray: function (tabPath) {
623
+ return module.utilities.pathToArray(module.get.defaultPath(tabPath));
624
+ },
625
+ defaultPath: function (tabPath) {
626
+ var
627
+ $defaultNav = $allModules.filter('[data-' + metadata.tab + '^="' + module.escape.string(tabPath) + '/"]').eq(0),
628
+ defaultTab = $defaultNav.data(metadata.tab) || false
629
+ ;
630
+ if (defaultTab) {
631
+ module.debug('Found default tab', defaultTab);
632
+ if (recursionDepth < settings.maxDepth) {
633
+ recursionDepth++;
634
+
635
+ return module.get.defaultPath(defaultTab);
636
+ }
637
+ module.error(error.recursion);
638
+ } else {
639
+ module.debug('No default tabs found for', tabPath, $tabs);
640
+ }
641
+ recursionDepth = 0;
642
+
643
+ return tabPath;
644
+ },
645
+ navElement: function (tabPath) {
646
+ tabPath = tabPath || activeTabPath;
647
+
648
+ return $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
649
+ },
650
+ tabElement: function (tabPath) {
651
+ var
652
+ $fullPathTab,
653
+ $simplePathTab,
654
+ tabPathArray,
655
+ lastTab
656
+ ;
657
+ tabPath = tabPath || activeTabPath;
658
+ tabPathArray = module.utilities.pathToArray(tabPath);
659
+ lastTab = module.utilities.last(tabPathArray);
660
+ $fullPathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]');
661
+ $simplePathTab = $tabs.filter('[data-' + metadata.tab + '="' + module.escape.string(lastTab) + '"]');
662
+
663
+ return $fullPathTab.length > 0
664
+ ? $fullPathTab
665
+ : $simplePathTab;
666
+ },
667
+ tab: function () {
668
+ return activeTabPath;
669
+ },
670
+ },
671
+
672
+ determine: {
673
+ activeTab: function () {
674
+ var activeTab = null;
675
+
676
+ $tabs.each(function (_index, tab) {
677
+ var $tab = $(tab);
678
+
679
+ if ($tab.hasClass(className.active)) {
680
+ var
681
+ tabPath = $(this).data(metadata.tab),
682
+ $anchor = $allModules.filter('[data-' + metadata.tab + '="' + module.escape.string(tabPath) + '"]')
683
+ ;
684
+
685
+ if ($anchor.hasClass(className.active)) {
686
+ activeTab = tabPath;
687
+ }
688
+ }
689
+ });
690
+
691
+ return activeTab;
692
+ },
693
+ },
694
+
695
+ utilities: {
696
+ filterArray: function (keepArray, removeArray) {
697
+ return $.grep(keepArray, function (keepValue) {
698
+ return $.inArray(keepValue, removeArray) === -1;
699
+ });
700
+ },
701
+ last: function (array) {
702
+ return Array.isArray(array)
703
+ ? array[array.length - 1]
704
+ : false;
705
+ },
706
+ pathToArray: function (pathName) {
707
+ if (pathName === undefined) {
708
+ pathName = activeTabPath;
709
+ }
710
+
711
+ return typeof pathName === 'string'
712
+ ? pathName.split('/')
713
+ : [pathName];
714
+ },
715
+ arrayToPath: function (pathArray) {
716
+ return Array.isArray(pathArray)
717
+ ? pathArray.join('/')
718
+ : false;
719
+ },
720
+ },
721
+
722
+ setting: function (name, value) {
723
+ module.debug('Changing setting', name, value);
724
+ if ($.isPlainObject(name)) {
725
+ $.extend(true, settings, name);
726
+ } else if (value !== undefined) {
727
+ if ($.isPlainObject(settings[name])) {
728
+ $.extend(true, settings[name], value);
729
+ } else {
730
+ settings[name] = value;
731
+ }
732
+ } else {
733
+ return settings[name];
734
+ }
735
+ },
736
+ internal: function (name, value) {
737
+ if ($.isPlainObject(name)) {
738
+ $.extend(true, module, name);
739
+ } else if (value !== undefined) {
740
+ module[name] = value;
741
+ } else {
742
+ return module[name];
743
+ }
744
+ },
745
+ debug: function () {
746
+ if (!settings.silent && settings.debug) {
747
+ if (settings.performance) {
748
+ module.performance.log(arguments);
749
+ } else {
750
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
751
+ module.debug.apply(console, arguments);
752
+ }
753
+ }
754
+ },
755
+ verbose: function () {
756
+ if (!settings.silent && settings.verbose && settings.debug) {
757
+ if (settings.performance) {
758
+ module.performance.log(arguments);
759
+ } else {
760
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
761
+ module.verbose.apply(console, arguments);
762
+ }
763
+ }
764
+ },
765
+ error: function () {
766
+ if (!settings.silent) {
767
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
768
+ module.error.apply(console, arguments);
769
+ }
770
+ },
771
+ performance: {
772
+ log: function (message) {
773
+ var
774
+ currentTime,
775
+ executionTime,
776
+ previousTime
777
+ ;
778
+ if (settings.performance) {
779
+ currentTime = Date.now();
780
+ previousTime = time || currentTime;
781
+ executionTime = currentTime - previousTime;
782
+ time = currentTime;
783
+ performance.push({
784
+ Name: message[0],
785
+ Arguments: [].slice.call(message, 1) || '',
786
+ Element: element,
787
+ 'Execution Time': executionTime,
788
+ });
789
+ }
790
+ clearTimeout(module.performance.timer);
791
+ module.performance.timer = setTimeout(function () {
792
+ module.performance.display();
793
+ }, 500);
794
+ },
795
+ display: function () {
796
+ var
797
+ title = settings.name + ':',
798
+ totalTime = 0
799
+ ;
800
+ time = false;
801
+ clearTimeout(module.performance.timer);
802
+ $.each(performance, function (index, data) {
803
+ totalTime += data['Execution Time'];
804
+ });
805
+ title += ' ' + totalTime + 'ms';
806
+ if (performance.length > 0) {
807
+ console.groupCollapsed(title);
808
+ if (console.table) {
809
+ console.table(performance);
810
+ } else {
811
+ $.each(performance, function (index, data) {
812
+ console.log(data.Name + ': ' + data['Execution Time'] + 'ms');
813
+ });
814
+ }
815
+ console.groupEnd();
816
+ }
817
+ performance = [];
818
+ },
819
+ },
820
+ invoke: function (query, passedArguments, context) {
821
+ var
822
+ object = instance,
823
+ maxDepth,
824
+ found,
825
+ response
826
+ ;
827
+ passedArguments = passedArguments || queryArguments;
828
+ context = context || element;
829
+ if (typeof query === 'string' && object !== undefined) {
830
+ query = query.split(/[ .]/);
831
+ maxDepth = query.length - 1;
832
+ $.each(query, function (depth, value) {
833
+ var camelCaseValue = depth !== maxDepth
834
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
835
+ : query
836
+ ;
837
+ if ($.isPlainObject(object[camelCaseValue]) && (depth !== maxDepth)) {
838
+ object = object[camelCaseValue];
839
+ } else if (object[camelCaseValue] !== undefined) {
840
+ found = object[camelCaseValue];
841
+
842
+ return false;
843
+ } else if ($.isPlainObject(object[value]) && (depth !== maxDepth)) {
844
+ object = object[value];
845
+ } else if (object[value] !== undefined) {
846
+ found = object[value];
847
+
848
+ return false;
849
+ } else {
850
+ module.error(error.method, query);
851
+
852
+ return false;
853
+ }
854
+ });
855
+ }
856
+ if (isFunction(found)) {
857
+ response = found.apply(context, passedArguments);
858
+ } else if (found !== undefined) {
859
+ response = found;
860
+ }
861
+ if (Array.isArray(returnedValue)) {
862
+ returnedValue.push(response);
863
+ } else if (returnedValue !== undefined) {
864
+ returnedValue = [returnedValue, response];
865
+ } else if (response !== undefined) {
866
+ returnedValue = response;
867
+ }
868
+
869
+ return found;
870
+ },
871
+ };
872
+ if (methodInvoked) {
873
+ if (instance === undefined) {
874
+ module.initialize();
875
+ }
876
+ module.invoke(query);
877
+ } else {
878
+ if (instance !== undefined) {
879
+ instance.invoke('destroy');
880
+ }
881
+ module.initialize();
882
+ }
883
+ });
884
+
885
+ return returnedValue !== undefined
886
+ ? returnedValue
887
+ : this;
888
+ };
889
+
890
+ // shortcut for tabbed content with no defined navigation
891
+ $.tab = function () {
892
+ $(window).tab.apply(this, arguments);
893
+ };
894
+
895
+ $.fn.tab.settings = {
896
+
897
+ name: 'Tab',
898
+ namespace: 'tab',
899
+
900
+ silent: false,
901
+ debug: false,
902
+ verbose: false,
903
+ performance: true,
904
+
905
+ auto: false, // uses pjax style endpoints fetching content from same url with remote-content headers
906
+ history: false, // use browser history
907
+ historyType: 'hash', // #/ or html5 state
908
+ path: false, // base path of url
909
+
910
+ context: false, // specify a context that tabs must appear inside
911
+ childrenOnly: false, // use only tabs that are children of context
912
+ maxDepth: 25, // max depth a tab can be nested
913
+
914
+ deactivate: 'siblings', // whether tabs should deactivate sibling menu elements or all elements initialized together
915
+
916
+ alwaysRefresh: false, // load tab content new every tab click
917
+ cache: true, // cache the content requests to pull locally
918
+ loadOnce: false, // Whether tab data should only be loaded once when using remote content
919
+ cacheType: 'response', // Whether to cache exact response, or to html cache contents after scripts execute
920
+ ignoreFirstLoad: false, // don't load remote content on first load
921
+
922
+ apiSettings: false, // settings for api call
923
+ evaluateScripts: 'once', // whether inline scripts should be parsed (true/false/once). Once will not re-evaluate on cached content
924
+ autoTabActivation: true, // whether a non existing active tab will auto activate the first available tab
925
+
926
+ onFirstLoad: function (tabPath, parameterArray, historyEvent) {}, // called first time loaded
927
+ onLoad: function (tabPath, parameterArray, historyEvent) {}, // called on every load
928
+ onVisible: function (tabPath, parameterArray, historyEvent) {}, // called every time tab visible
929
+ onRequest: function (tabPath, parameterArray, historyEvent) {}, // called ever time a tab beings loading remote content
930
+ onBeforeChange: function (tabPath) {}, // called before a tab is about to be changed. Returning false will cancel the tab change
931
+
932
+ templates: {
933
+ determineTitle: function (tabArray) {}, // returns page title for path
934
+ },
935
+
936
+ error: {
937
+ api: 'You attempted to load content without API module',
938
+ method: 'The method you called is not defined',
939
+ missingTab: 'Activated tab cannot be found. Tabs are case-sensitive.',
940
+ noContent: 'The tab you specified is missing a content url.',
941
+ path: 'History enabled, but no path was specified',
942
+ recursion: 'Max recursive depth reached',
943
+ state: 'History requires Asual\'s Address library <https://github.com/asual/jquery-address>',
944
+ },
945
+
946
+ regExp: {
947
+ escape: /[\s#$()*+,.:=?@[\\\]^{|}-]/g,
948
+ },
949
+
950
+ metadata: {
951
+ tab: 'tab',
952
+ loaded: 'loaded',
953
+ promise: 'promise',
954
+ },
955
+
956
+ className: {
957
+ loading: 'loading',
958
+ active: 'active',
959
+ },
960
+
961
+ selector: {
962
+ tabs: '.ui.tab',
963
+ ui: '.ui',
964
+ },
965
+
966
+ };
967
+ })(jQuery, window, document);