semantic-ui-sass 0.19.3.1 → 1.7.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +5 -6
  4. data/app/assets/fonts/semantic-ui/icons.eot +0 -0
  5. data/app/assets/fonts/semantic-ui/icons.otf +0 -0
  6. data/app/assets/fonts/semantic-ui/icons.svg +472 -367
  7. data/app/assets/fonts/semantic-ui/icons.ttf +0 -0
  8. data/app/assets/fonts/semantic-ui/icons.woff +0 -0
  9. data/app/assets/images/semantic-ui/flags.png +0 -0
  10. data/app/assets/javascripts/semantic-ui.js +9 -5
  11. data/app/assets/javascripts/semantic-ui/accordion.js +169 -102
  12. data/app/assets/javascripts/semantic-ui/api.js +840 -0
  13. data/app/assets/javascripts/semantic-ui/checkbox.js +203 -46
  14. data/app/assets/javascripts/semantic-ui/{behavior/colorize.js → colorize.js} +4 -2
  15. data/app/assets/javascripts/semantic-ui/dimmer.js +110 -76
  16. data/app/assets/javascripts/semantic-ui/dropdown.js +897 -285
  17. data/app/assets/javascripts/semantic-ui/{behavior/form.js → form.js} +127 -42
  18. data/app/assets/javascripts/semantic-ui/modal.js +294 -219
  19. data/app/assets/javascripts/semantic-ui/nag.js +120 -186
  20. data/app/assets/javascripts/semantic-ui/popup.js +491 -223
  21. data/app/assets/javascripts/semantic-ui/progress.js +779 -0
  22. data/app/assets/javascripts/semantic-ui/rating.js +66 -22
  23. data/app/assets/javascripts/semantic-ui/search.js +219 -99
  24. data/app/assets/javascripts/semantic-ui/shape.js +72 -29
  25. data/app/assets/javascripts/semantic-ui/sidebar.js +678 -142
  26. data/app/assets/javascripts/semantic-ui/site.js +487 -0
  27. data/app/assets/javascripts/semantic-ui/{behavior/state.js → state.js} +116 -151
  28. data/app/assets/javascripts/semantic-ui/sticky.js +771 -0
  29. data/app/assets/javascripts/semantic-ui/tab.js +680 -603
  30. data/app/assets/javascripts/semantic-ui/transition.js +269 -158
  31. data/app/assets/javascripts/semantic-ui/video.js +113 -32
  32. data/app/assets/javascripts/semantic-ui/visibility.js +970 -0
  33. data/app/assets/javascripts/semantic-ui/visit.js +513 -0
  34. data/app/assets/stylesheets/semantic-ui.scss +2 -0
  35. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +58 -14
  36. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +464 -372
  37. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +1385 -533
  38. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +482 -655
  39. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +238 -139
  40. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +631 -280
  41. data/app/assets/stylesheets/semantic-ui/elements/_all.scss +3 -2
  42. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +1614 -657
  43. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +143 -80
  44. data/app/assets/stylesheets/semantic-ui/elements/_flag.scss +1018 -0
  45. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +302 -145
  46. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +1653 -1365
  47. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +160 -59
  48. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +247 -118
  49. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +501 -470
  50. data/app/assets/stylesheets/semantic-ui/elements/_list.scss +888 -0
  51. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +189 -98
  52. data/app/assets/stylesheets/semantic-ui/elements/_rail.scss +125 -0
  53. data/app/assets/stylesheets/semantic-ui/elements/_reveal.scss +147 -212
  54. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +328 -190
  55. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +261 -185
  56. data/app/assets/stylesheets/semantic-ui/globals/_all.scss +2 -0
  57. data/app/assets/stylesheets/semantic-ui/globals/_reset.scss +430 -0
  58. data/app/assets/stylesheets/semantic-ui/globals/_site.scss +128 -0
  59. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +190 -106
  60. data/app/assets/stylesheets/semantic-ui/modules/_all.scss +2 -1
  61. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +303 -201
  62. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +72 -63
  63. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +711 -331
  64. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +262 -140
  65. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +82 -71
  66. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +163 -119
  67. data/app/assets/stylesheets/semantic-ui/modules/_progress.scss +435 -0
  68. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +163 -68
  69. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +223 -150
  70. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +39 -40
  71. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +413 -147
  72. data/app/assets/stylesheets/semantic-ui/modules/_sticky.scss +80 -0
  73. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +49 -20
  74. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +542 -568
  75. data/app/assets/stylesheets/semantic-ui/modules/_video.scss +69 -37
  76. data/app/assets/stylesheets/semantic-ui/views/_ad.scss +265 -0
  77. data/app/assets/stylesheets/semantic-ui/views/_all.scss +1 -1
  78. data/app/assets/stylesheets/semantic-ui/views/_card.scss +758 -0
  79. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +133 -92
  80. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +200 -87
  81. data/app/assets/stylesheets/semantic-ui/views/_item.scss +298 -523
  82. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +390 -12
  83. data/lib/semantic/ui/sass/version.rb +2 -2
  84. data/tasks/converter.rb +99 -216
  85. metadata +22 -27
  86. data/app/assets/fonts/semantic-ui/basic.icons.eot +0 -0
  87. data/app/assets/fonts/semantic-ui/basic.icons.svg +0 -450
  88. data/app/assets/fonts/semantic-ui/basic.icons.ttf +0 -0
  89. data/app/assets/fonts/semantic-ui/basic.icons.woff +0 -0
  90. data/app/assets/images/semantic-ui/loader-large-inverted.gif +0 -0
  91. data/app/assets/images/semantic-ui/loader-large.gif +0 -0
  92. data/app/assets/images/semantic-ui/loader-medium-inverted.gif +0 -0
  93. data/app/assets/images/semantic-ui/loader-medium.gif +0 -0
  94. data/app/assets/images/semantic-ui/loader-mini-inverted.gif +0 -0
  95. data/app/assets/images/semantic-ui/loader-mini.gif +0 -0
  96. data/app/assets/images/semantic-ui/loader-small-inverted.gif +0 -0
  97. data/app/assets/images/semantic-ui/loader-small.gif +0 -0
  98. data/app/assets/javascripts/semantic-ui/behavior/api.js +0 -634
  99. data/app/assets/javascripts/semantic-ui/chatroom.js +0 -772
  100. data/app/assets/stylesheets/semantic-ui/depends/_basic.icon.scss +0 -4
  101. data/app/assets/stylesheets/semantic-ui/depends/_icon.scss +0 -4
  102. data/app/assets/stylesheets/semantic-ui/depends/_loader.scss +0 -8
  103. data/app/assets/stylesheets/semantic-ui/elements/_basic.icon.scss +0 -1124
  104. data/app/assets/stylesheets/semantic-ui/elements/_progress.scss +0 -280
  105. data/app/assets/stylesheets/semantic-ui/modules/_chatroom.scss +0 -299
  106. data/app/assets/stylesheets/semantic-ui/modules/_reveal.scss +0 -322
  107. data/app/assets/stylesheets/semantic-ui/views/_list.scss +0 -700
Binary file
@@ -1,19 +1,23 @@
1
+ //= require semantic-ui/api
2
+ //= require semantic-ui/colorize
3
+ //= require semantic-ui/form
4
+ //= require semantic-ui/state
5
+ //= require semantic-ui/visibility
6
+ //= require semantic-ui/visit
7
+ //= require semantic-ui/site
1
8
  //= require semantic-ui/accordion
2
- //= require semantic-ui/chatroom
3
9
  //= require semantic-ui/checkbox
4
10
  //= require semantic-ui/dimmer
5
11
  //= require semantic-ui/dropdown
6
12
  //= require semantic-ui/modal
7
13
  //= require semantic-ui/nag
8
14
  //= require semantic-ui/popup
15
+ //= require semantic-ui/progress
9
16
  //= require semantic-ui/rating
10
17
  //= require semantic-ui/search
11
18
  //= require semantic-ui/shape
12
19
  //= require semantic-ui/sidebar
20
+ //= require semantic-ui/sticky
13
21
  //= require semantic-ui/tab
14
22
  //= require semantic-ui/transition
15
23
  //= require semantic-ui/video
16
- //= require semantic-ui/behavior/api
17
- //= require semantic-ui/behavior/colorize
18
- //= require semantic-ui/behavior/form
19
- //= require semantic-ui/behavior/state
@@ -1,9 +1,9 @@
1
1
  /*
2
2
  * # Semantic - Accordion
3
- * http://github.com/jlukic/semantic-ui/
3
+ * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2014 Contributor
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
@@ -11,6 +11,8 @@
11
11
 
12
12
  ;(function ($, window, document, undefined) {
13
13
 
14
+ "use strict";
15
+
14
16
  $.fn.accordion = function(parameters) {
15
17
  var
16
18
  $allModules = $(this),
@@ -21,6 +23,13 @@ $.fn.accordion = function(parameters) {
21
23
  query = arguments[0],
22
24
  methodInvoked = (typeof query == 'string'),
23
25
  queryArguments = [].slice.call(arguments, 1),
26
+
27
+ requestAnimationFrame = window.requestAnimationFrame
28
+ || window.mozRequestAnimationFrame
29
+ || window.webkitRequestAnimationFrame
30
+ || window.msRequestAnimationFrame
31
+ || function(callback) { setTimeout(callback, 0); },
32
+
24
33
  returnedValue
25
34
  ;
26
35
  $allModules
@@ -45,6 +54,7 @@ $.fn.accordion = function(parameters) {
45
54
 
46
55
  element = this,
47
56
  instance = $module.data(moduleNamespace),
57
+ observer,
48
58
  module
49
59
  ;
50
60
 
@@ -52,10 +62,10 @@ $.fn.accordion = function(parameters) {
52
62
 
53
63
  initialize: function() {
54
64
  module.debug('Initializing accordion with bound events', $module);
55
- // initializing
56
- $title
57
- .on('click' + eventNamespace, module.event.click)
65
+ $module
66
+ .on('click' + eventNamespace, selector.title, module.event.click)
58
67
  ;
68
+ module.observeChanges();
59
69
  module.instantiate();
60
70
  },
61
71
 
@@ -76,88 +86,71 @@ $.fn.accordion = function(parameters) {
76
86
  ;
77
87
  },
78
88
 
89
+ refresh: function() {
90
+ $title = $module.find(selector.title);
91
+ $content = $module.find(selector.content);
92
+ },
93
+
94
+ observeChanges: function() {
95
+ if('MutationObserver' in window) {
96
+ observer = new MutationObserver(function(mutations) {
97
+ module.debug('DOM tree modified, updating selector cache');
98
+ module.refresh();
99
+ });
100
+ observer.observe(element, {
101
+ childList : true,
102
+ subtree : true
103
+ });
104
+ module.debug('Setting up mutation observer', observer);
105
+ }
106
+ },
107
+
108
+
79
109
  event: {
80
110
  click: function() {
81
- module.verbose('Title clicked', this);
82
- var
83
- $activeTitle = $(this),
84
- index = $title.index($activeTitle)
85
- ;
86
- module.toggle(index);
87
- },
88
- resetDisplay: function() {
89
- $(this).css('display', '');
90
- if( $(this).attr('style') == '') {
91
- $(this)
92
- .attr('style', '')
93
- .removeAttr('style')
94
- ;
95
- }
96
- },
97
- resetOpacity: function() {
98
- $(this).css('opacity', '');
99
- if( $(this).attr('style') == '') {
100
- $(this)
101
- .attr('style', '')
102
- .removeAttr('style')
103
- ;
104
- }
111
+ $.proxy(module.toggle, this)();
105
112
  }
106
113
  },
107
114
 
108
- toggle: function(index) {
109
- module.debug('Toggling content content at index', index);
115
+ toggle: function(query) {
110
116
  var
111
- $activeTitle = $title.eq(index),
117
+ $activeTitle = (query !== undefined)
118
+ ? (typeof query === 'number')
119
+ ? $title.eq(query)
120
+ : $(query)
121
+ : $(this),
112
122
  $activeContent = $activeTitle.next($content),
113
123
  contentIsOpen = $activeContent.is(':visible')
114
124
  ;
125
+ module.debug('Toggling visibility of content', $activeTitle);
115
126
  if(contentIsOpen) {
116
127
  if(settings.collapsible) {
117
- module.close(index);
128
+ $.proxy(module.close, $activeTitle)();
118
129
  }
119
130
  else {
120
131
  module.debug('Cannot close accordion content collapsing is disabled');
121
132
  }
122
133
  }
123
134
  else {
124
- module.open(index);
135
+ $.proxy(module.open, $activeTitle)();
125
136
  }
126
137
  },
127
138
 
128
- open: function(index) {
139
+ open: function(query) {
129
140
  var
130
- $activeTitle = $title.eq(index),
131
- $activeContent = $activeTitle.next($content),
132
- $otherSections = module.is.menu()
133
- ? $activeTitle.parent().siblings(selector.item).find(selector.title)
134
- : $activeTitle.siblings(selector.title),
135
- $previousTitle = $otherSections.filter('.' + className.active),
136
- $previousContent = $previousTitle.next($title),
137
- contentIsOpen = ($previousTitle.size() > 0)
141
+ $activeTitle = (query !== undefined)
142
+ ? (typeof query === 'number')
143
+ ? $title.eq(query)
144
+ : $(query)
145
+ : $(this),
146
+ $activeContent = $activeTitle.next($content),
147
+ currentlyAnimating = $activeContent.is(':animated'),
148
+ currentlyActive = $activeContent.hasClass(className.active)
138
149
  ;
139
- if( !$activeContent.is(':animated') ) {
150
+ if(!currentlyAnimating && !currentlyActive) {
140
151
  module.debug('Opening accordion content', $activeTitle);
141
- if(settings.exclusive && contentIsOpen) {
142
- $previousTitle
143
- .removeClass(className.active)
144
- ;
145
- $previousContent
146
- .stop()
147
- .children()
148
- .stop()
149
- .animate({
150
- opacity: 0
151
- }, settings.duration, module.event.resetOpacity)
152
- .end()
153
- .slideUp(settings.duration , settings.easing, function() {
154
- $previousContent
155
- .removeClass(className.active)
156
- .children()
157
- ;
158
- $.proxy(module.event.resetDisplay, this)();
159
- })
160
- ;
152
+ if(settings.exclusive) {
153
+ $.proxy(module.closeOthers, $activeTitle)();
161
154
  }
162
155
  $activeTitle
163
156
  .addClass(className.active)
@@ -168,52 +161,126 @@ $.fn.accordion = function(parameters) {
168
161
  .stop()
169
162
  .animate({
170
163
  opacity: 1
171
- }, settings.duration)
164
+ }, settings.duration, module.reset.display)
172
165
  .end()
173
166
  .slideDown(settings.duration, settings.easing, function() {
174
167
  $activeContent
175
168
  .addClass(className.active)
176
169
  ;
177
- $.proxy(module.event.resetDisplay, this)();
178
- $.proxy(settings.onOpen, $activeContent)();
179
- $.proxy(settings.onChange, $activeContent)();
170
+ $.proxy(module.reset.display, this)();
171
+ $.proxy(settings.onOpen, this)();
172
+ $.proxy(settings.onChange, this)();
180
173
  })
181
174
  ;
182
175
  }
183
176
  },
184
177
 
185
- close: function(index) {
178
+ close: function(query) {
186
179
  var
187
- $activeTitle = $title.eq(index),
188
- $activeContent = $activeTitle.next($content)
189
- ;
190
- module.debug('Closing accordion content', $activeContent);
191
- $activeTitle
192
- .removeClass(className.active)
180
+ $activeTitle = (query !== undefined)
181
+ ? (typeof query === 'number')
182
+ ? $title.eq(query)
183
+ : $(query)
184
+ : $(this),
185
+ $activeContent = $activeTitle.next($content),
186
+ isActive = $activeContent.hasClass(className.active)
193
187
  ;
194
- $activeContent
195
- .removeClass(className.active)
196
- .show()
197
- .stop()
198
- .children()
188
+ if(isActive) {
189
+ module.debug('Closing accordion content', $activeContent);
190
+ $activeTitle
191
+ .removeClass(className.active)
192
+ ;
193
+ $activeContent
194
+ .removeClass(className.active)
195
+ .show()
199
196
  .stop()
200
- .animate({
201
- opacity: 0
202
- }, settings.duration, module.event.resetOpacity)
203
- .end()
204
- .slideUp(settings.duration, settings.easing, function(){
205
- $.proxy(module.event.resetDisplay, this)();
206
- $.proxy(settings.onClose, $activeContent)();
207
- $.proxy(settings.onChange, $activeContent)();
208
- })
209
- ;
197
+ .children()
198
+ .stop()
199
+ .animate({
200
+ opacity: 0
201
+ }, settings.duration, module.reset.opacity)
202
+ .end()
203
+ .slideUp(settings.duration, settings.easing, function() {
204
+ $.proxy(module.reset.display, this)();
205
+ $.proxy(settings.onClose, this)();
206
+ $.proxy(settings.onChange, this)();
207
+ })
208
+ ;
209
+ }
210
210
  },
211
- is: {
212
- menu: function () {
213
- return $module.hasClass(className.menu);
211
+
212
+ closeOthers: function(index) {
213
+ var
214
+ $activeTitle = (index !== undefined)
215
+ ? $title.eq(index)
216
+ : $(this),
217
+ $parentTitles = $activeTitle.parents(selector.content).prev(selector.title),
218
+ $activeAccordion = $activeTitle.closest(selector.accordion),
219
+ activeSelector = selector.title + '.' + className.active + ':visible',
220
+ activeContent = selector.content + '.' + className.active + ':visible',
221
+ $openTitles,
222
+ $nestedTitles,
223
+ $openContents
224
+ ;
225
+ if(settings.closeNested) {
226
+ $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
227
+ $openContents = $openTitles.next($content);
214
228
  }
229
+ else {
230
+ $openTitles = $activeAccordion.find(activeSelector).not($parentTitles);
231
+ $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
232
+ $openTitles = $openTitles.not($nestedTitles);
233
+ $openContents = $openTitles.next($content);
234
+ }
235
+ if( ($openTitles.size() > 0) ) {
236
+ module.debug('Exclusive enabled, closing other content', $openTitles);
237
+ $openTitles
238
+ .removeClass(className.active)
239
+ ;
240
+ $openContents
241
+ .stop()
242
+ .children()
243
+ .stop()
244
+ .animate({
245
+ opacity: 0
246
+ }, settings.duration, module.resetOpacity)
247
+ .end()
248
+ .slideUp(settings.duration , settings.easing, function() {
249
+ $(this).removeClass(className.active);
250
+ $.proxy(module.reset.display, this)();
251
+ })
252
+ ;
253
+ }
254
+ },
255
+
256
+ reset: {
257
+
258
+ display: function() {
259
+ module.verbose('Removing inline display from element', this);
260
+ $(this).css('display', '');
261
+ if( $(this).attr('style') === '') {
262
+ $(this)
263
+ .attr('style', '')
264
+ .removeAttr('style')
265
+ ;
266
+ }
267
+ },
268
+
269
+ opacity: function() {
270
+ module.verbose('Removing inline opacity from element', this);
271
+ $(this).css('opacity', '');
272
+ if( $(this).attr('style') === '') {
273
+ $(this)
274
+ .attr('style', '')
275
+ .removeAttr('style')
276
+ ;
277
+ }
278
+ },
279
+
215
280
  },
281
+
216
282
  setting: function(name, value) {
283
+ module.debug('Changing setting', name, value);
217
284
  if( $.isPlainObject(name) ) {
218
285
  $.extend(true, settings, name);
219
286
  }
@@ -277,9 +344,9 @@ $.fn.accordion = function(parameters) {
277
344
  executionTime = currentTime - previousTime;
278
345
  time = currentTime;
279
346
  performance.push({
280
- 'Element' : element,
281
347
  'Name' : message[0],
282
348
  'Arguments' : [].slice.call(message, 1) || '',
349
+ 'Element' : element,
283
350
  'Execution Time' : executionTime
284
351
  });
285
352
  }
@@ -347,6 +414,7 @@ $.fn.accordion = function(parameters) {
347
414
  return false;
348
415
  }
349
416
  else {
417
+ module.error(error.method, query);
350
418
  return false;
351
419
  }
352
420
  });
@@ -390,6 +458,7 @@ $.fn.accordion = function(parameters) {
390
458
  };
391
459
 
392
460
  $.fn.accordion.settings = {
461
+
393
462
  name : 'Accordion',
394
463
  namespace : 'accordion',
395
464
 
@@ -399,6 +468,7 @@ $.fn.accordion.settings = {
399
468
 
400
469
  exclusive : true,
401
470
  collapsible : true,
471
+ closeNested : false,
402
472
 
403
473
  duration : 500,
404
474
  easing : 'easeInOutQuint',
@@ -408,22 +478,19 @@ $.fn.accordion.settings = {
408
478
  onChange : function(){},
409
479
 
410
480
  error: {
411
- method : 'The method you called is not defined'
481
+ method : 'The method you called is not defined'
412
482
  },
413
483
 
414
484
  className : {
415
- active : 'active',
416
- menu : 'menu',
485
+ active : 'active'
417
486
  },
418
487
 
419
488
  selector : {
420
- title : '.title',
421
- content : '.content',
422
- menu : '.menu',
423
- item : '.item',
489
+ accordion : '.accordion',
490
+ title : '.title',
491
+ content : '.content'
424
492
  }
425
493
 
426
-
427
494
  };
428
495
 
429
496
  // Adds easing
@@ -0,0 +1,840 @@
1
+ /*
2
+ * # Semantic - API
3
+ * http://github.com/semantic-org/semantic-ui/
4
+ *
5
+ *
6
+ * Copyright 2014 Contributor
7
+ * Released under the MIT license
8
+ * http://opensource.org/licenses/MIT
9
+ *
10
+ */
11
+
12
+ ;(function ( $, window, document, undefined ) {
13
+
14
+ $.api = $.fn.api = function(parameters) {
15
+
16
+ var
17
+ // use window context if none specified
18
+ $allModules = $.isFunction(this)
19
+ ? $(window)
20
+ : $(this),
21
+ moduleSelector = $allModules.selector || '',
22
+ time = new Date().getTime(),
23
+ performance = [],
24
+
25
+ query = arguments[0],
26
+ methodInvoked = (typeof query == 'string'),
27
+ queryArguments = [].slice.call(arguments, 1),
28
+
29
+ returnedValue
30
+ ;
31
+
32
+ $allModules
33
+ .each(function() {
34
+ var
35
+ settings = ( $.isPlainObject(parameters) )
36
+ ? $.extend(true, {}, $.fn.api.settings, parameters)
37
+ : $.extend({}, $.fn.api.settings),
38
+
39
+ // internal aliases
40
+ namespace = settings.namespace,
41
+ metadata = settings.metadata,
42
+ selector = settings.selector,
43
+ error = settings.error,
44
+ className = settings.className,
45
+
46
+ // define namespaces for modules
47
+ eventNamespace = '.' + namespace,
48
+ moduleNamespace = 'module-' + namespace,
49
+
50
+ // element that creates request
51
+ $module = $(this),
52
+ $form = $module.closest(selector.form),
53
+
54
+ // context used for state
55
+ $context = (settings.stateContext)
56
+ ? $(settings.stateContext)
57
+ : $module,
58
+
59
+ // request details
60
+ ajaxSettings,
61
+ requestSettings,
62
+ url,
63
+ data,
64
+
65
+ // standard module
66
+ element = this,
67
+ context = $context.get(),
68
+ instance = $module.data(moduleNamespace),
69
+ module
70
+ ;
71
+
72
+ module = {
73
+
74
+ initialize: function() {
75
+ var
76
+ triggerEvent = module.get.event()
77
+ ;
78
+ // bind events
79
+ if(!methodInvoked) {
80
+ if( triggerEvent ) {
81
+ module.debug('Attaching API events to element', triggerEvent);
82
+ $module
83
+ .on(triggerEvent + eventNamespace, module.event.trigger)
84
+ ;
85
+ }
86
+ else {
87
+ module.query();
88
+ }
89
+ }
90
+ module.instantiate();
91
+ },
92
+
93
+ instantiate: function() {
94
+ module.verbose('Storing instance of module', module);
95
+ instance = module;
96
+ $module
97
+ .data(moduleNamespace, instance)
98
+ ;
99
+ },
100
+
101
+ destroy: function() {
102
+ module.verbose('Destroying previous module for', element);
103
+ $module
104
+ .removeData(moduleNamespace)
105
+ .off(eventNamespace)
106
+ ;
107
+ },
108
+
109
+ query: function() {
110
+
111
+ if(module.is.disabled()) {
112
+ module.debug('Element is disabled API request aborted');
113
+ return;
114
+ }
115
+ // determine if an api event already occurred
116
+ if(module.is.loading() && settings.throttle === 0 ) {
117
+ module.debug('Cancelling request, previous request is still pending');
118
+ return;
119
+ }
120
+
121
+ // pass element metadata to url (value, text)
122
+ if(settings.defaultData) {
123
+ $.extend(true, settings.urlData, module.get.defaultData());
124
+ }
125
+
126
+ // Add form content
127
+ if(settings.serializeForm !== false || $context.is('form')) {
128
+ if(settings.serializeForm == 'json') {
129
+ $.extend(true, settings.data, module.get.formData());
130
+ }
131
+ else {
132
+ settings.data = module.get.formData();
133
+ }
134
+ }
135
+
136
+ // call beforesend and get any settings changes
137
+ requestSettings = module.get.settings();
138
+
139
+ // check if beforesend cancelled request
140
+ if(requestSettings === false) {
141
+ module.error(error.beforeSend);
142
+ return;
143
+ }
144
+
145
+ if(settings.url) {
146
+ // override with url if specified
147
+ module.debug('Using specified url', url);
148
+ url = module.add.urlData( settings.url );
149
+ }
150
+ else {
151
+ // otherwise find url from api endpoints
152
+ url = module.add.urlData( module.get.templateURL() );
153
+ module.debug('Added URL Data to url', url);
154
+ }
155
+
156
+ // exit conditions reached, missing url parameters
157
+ if( !url ) {
158
+ if($module.is('form')) {
159
+ module.debug('No url or action specified, defaulting to form action');
160
+ url = $module.attr('action');
161
+ }
162
+ else {
163
+ module.error(error.missingURL, settings.action);
164
+ return;
165
+ }
166
+ }
167
+
168
+ // add loading state
169
+ module.set.loading();
170
+
171
+ // look for jQuery ajax parameters in settings
172
+ ajaxSettings = $.extend(true, {}, settings, {
173
+ type : settings.method || settings.type,
174
+ data : data,
175
+ url : settings.base + url,
176
+ beforeSend : settings.beforeXHR,
177
+ success : function() {},
178
+ failure : function() {},
179
+ complete : function() {}
180
+ });
181
+
182
+ module.verbose('Creating AJAX request with settings', ajaxSettings);
183
+
184
+ if( !module.is.loading() ) {
185
+ module.request = module.create.request();
186
+ module.xhr = module.create.xhr();
187
+ }
188
+ else {
189
+ // throttle additional requests
190
+ module.timer = setTimeout(function() {
191
+ module.request = module.create.request();
192
+ module.xhr = module.create.xhr();
193
+ }, settings.throttle);
194
+ }
195
+
196
+ },
197
+
198
+
199
+ is: {
200
+ disabled: function() {
201
+ return ($module.filter(settings.filter).size() > 0);
202
+ },
203
+ loading: function() {
204
+ return (module.request && module.request.state() == 'pending');
205
+ }
206
+ },
207
+
208
+ was: {
209
+ succesful: function() {
210
+ return (module.request && module.request.state() == 'resolved');
211
+ },
212
+ failure: function() {
213
+ return (module.request && module.request.state() == 'rejected');
214
+ },
215
+ complete: function() {
216
+ return (module.request && (module.request.state() == 'resolved' || module.request.state() == 'rejected') );
217
+ }
218
+ },
219
+
220
+ add: {
221
+ urlData: function(url, urlData) {
222
+ var
223
+ requiredVariables,
224
+ optionalVariables
225
+ ;
226
+ if(url) {
227
+ requiredVariables = url.match(settings.regExp.required);
228
+ optionalVariables = url.match(settings.regExp.optional);
229
+ urlData = urlData || settings.urlData;
230
+ if(requiredVariables) {
231
+ module.debug('Looking for required URL variables', requiredVariables);
232
+ $.each(requiredVariables, function(index, templatedString) {
233
+ var
234
+ // allow legacy {$var} style
235
+ variable = (templatedString.indexOf('$') !== -1)
236
+ ? templatedString.substr(2, templatedString.length - 3)
237
+ : templatedString.substr(1, templatedString.length - 2),
238
+ value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
239
+ ? urlData[variable]
240
+ : ($module.data(variable) !== undefined)
241
+ ? $module.data(variable)
242
+ : ($context.data(variable) !== undefined)
243
+ ? $context.data(variable)
244
+ : urlData[variable]
245
+ ;
246
+ // remove value
247
+ if(value === undefined) {
248
+ module.error(error.requiredParameter, variable, url);
249
+ url = false;
250
+ return false;
251
+ }
252
+ else {
253
+ module.verbose('Found required variable', variable, value);
254
+ url = url.replace(templatedString, value);
255
+ }
256
+ });
257
+ }
258
+ if(optionalVariables) {
259
+ module.debug('Looking for optional URL variables', requiredVariables);
260
+ $.each(optionalVariables, function(index, templatedString) {
261
+ var
262
+ // allow legacy {/$var} style
263
+ variable = (templatedString.indexOf('$') !== -1)
264
+ ? templatedString.substr(3, templatedString.length - 4)
265
+ : templatedString.substr(2, templatedString.length - 3),
266
+ value = ($.isPlainObject(urlData) && urlData[variable] !== undefined)
267
+ ? urlData[variable]
268
+ : ($module.data(variable) !== undefined)
269
+ ? $module.data(variable)
270
+ : ($context.data(variable) !== undefined)
271
+ ? $context.data(variable)
272
+ : urlData[variable]
273
+ ;
274
+ // optional replacement
275
+ if(value !== undefined) {
276
+ module.verbose('Optional variable Found', variable, value);
277
+ url = url.replace(templatedString, value);
278
+ }
279
+ else {
280
+ module.verbose('Optional variable not found', variable);
281
+ // remove preceding slash if set
282
+ if(url.indexOf('/' + templatedString) !== -1) {
283
+ url = url.replace('/' + templatedString, '');
284
+ }
285
+ else {
286
+ url = url.replace(templatedString, '');
287
+ }
288
+ }
289
+ });
290
+ }
291
+ }
292
+ return url;
293
+ }
294
+ },
295
+
296
+ event: {
297
+ trigger: function(event) {
298
+ module.query();
299
+ if(event.type == 'submit' || event.type == 'click') {
300
+ event.preventDefault();
301
+ }
302
+ },
303
+ xhr: {
304
+ always: function() {
305
+ // calculate if loading time was below minimum threshold
306
+ },
307
+ done: function(response) {
308
+ var
309
+ context = this,
310
+ elapsedTime = (new Date().getTime() - time),
311
+ timeLeft = (settings.loadingDuration - elapsedTime)
312
+ ;
313
+ timeLeft = (timeLeft > 0)
314
+ ? timeLeft
315
+ : 0
316
+ ;
317
+ setTimeout(function() {
318
+ module.request.resolveWith(context, [response]);
319
+ }, timeLeft);
320
+ },
321
+ fail: function(xhr, status, httpMessage) {
322
+ var
323
+ context = this,
324
+ elapsedTime = (new Date().getTime() - time),
325
+ timeLeft = (settings.loadingDuration - elapsedTime)
326
+ ;
327
+ timeLeft = (timeLeft > 0)
328
+ ? timeLeft
329
+ : 0
330
+ ;
331
+ // page triggers abort on navigation, dont show error
332
+ setTimeout(function() {
333
+ if(status !== 'abort') {
334
+ module.request.rejectWith(context, [xhr, status, httpMessage]);
335
+ }
336
+ else {
337
+ module.reset();
338
+ }
339
+ }, timeLeft);
340
+ }
341
+ },
342
+ request: {
343
+ complete: function(response) {
344
+ module.remove.loading();
345
+ $.proxy(settings.onComplete, context)(response, $module);
346
+ },
347
+ done: function(response) {
348
+ module.debug('API Response Received', response);
349
+ if(settings.dataType == 'json') {
350
+ if( $.isFunction(settings.successTest) ) {
351
+ module.debug('Checking JSON returned success', settings.successTest, response);
352
+ if( settings.successTest(response) ) {
353
+ $.proxy(settings.onSuccess, context)(response, $module);
354
+ }
355
+ else {
356
+ module.debug('JSON test specified by user and response failed', response);
357
+ $.proxy(settings.onFailure, context)(response, $module);
358
+ }
359
+ }
360
+ else {
361
+ $.proxy(settings.onSuccess, context)(response, $module);
362
+ }
363
+ }
364
+ else {
365
+ $.proxy(settings.onSuccess, context)(response, $module);
366
+ }
367
+ },
368
+ error: function(xhr, status, httpMessage) {
369
+ var
370
+ errorMessage = (settings.error[status] !== undefined)
371
+ ? settings.error[status]
372
+ : httpMessage,
373
+ response
374
+ ;
375
+ // let em know unless request aborted
376
+ if(xhr !== undefined) {
377
+ // readyState 4 = done, anything less is not really sent
378
+ if(xhr.readyState !== undefined && xhr.readyState == 4) {
379
+
380
+ // if http status code returned and json returned error, look for it
381
+ if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
382
+ module.error(error.statusMessage + httpMessage);
383
+ }
384
+ else {
385
+ if(status == 'error' && settings.dataType == 'json') {
386
+ try {
387
+ response = $.parseJSON(xhr.responseText);
388
+ if(response && response.error !== undefined) {
389
+ errorMessage = response.error;
390
+ }
391
+ }
392
+ catch(e) {
393
+ module.error(error.JSONParse);
394
+ }
395
+ }
396
+ }
397
+ module.remove.loading();
398
+ module.set.error();
399
+ // show error state only for duration specified in settings
400
+ if(settings.errorDuration) {
401
+ setTimeout(module.remove.error, settings.errorDuration);
402
+ }
403
+ module.debug('API Request error:', errorMessage);
404
+ $.proxy(settings.onError, context)(errorMessage, context);
405
+ }
406
+ else {
407
+ $.proxy(settings.onAbort, context)(errorMessage, context);
408
+ module.debug('Request Aborted (Most likely caused by page change or CORS Policy)', status, httpMessage);
409
+ }
410
+ }
411
+ }
412
+ }
413
+ },
414
+
415
+ create: {
416
+ request: function() {
417
+ return $.Deferred()
418
+ .always(module.event.request.complete)
419
+ .done(module.event.request.done)
420
+ .fail(module.event.request.error)
421
+ ;
422
+ },
423
+ xhr: function() {
424
+ $.ajax(ajaxSettings)
425
+ .always(module.event.xhr.always)
426
+ .done(module.event.xhr.done)
427
+ .fail(module.event.xhr.fail)
428
+ ;
429
+ }
430
+ },
431
+
432
+ set: {
433
+ error: function() {
434
+ module.verbose('Adding error state to element', $context);
435
+ $context.addClass(className.error);
436
+ },
437
+ loading: function() {
438
+ module.verbose('Adding loading state to element', $context);
439
+ $context.addClass(className.loading);
440
+ }
441
+ },
442
+
443
+ remove: {
444
+ error: function() {
445
+ module.verbose('Removing error state from element', $context);
446
+ $context.removeClass(className.error);
447
+ },
448
+ loading: function() {
449
+ module.verbose('Removing loading state from element', $context);
450
+ $context.removeClass(className.loading);
451
+ }
452
+ },
453
+
454
+ get: {
455
+ request: function() {
456
+ return module.request || false;
457
+ },
458
+ xhr: function() {
459
+ return module.xhr || false;
460
+ },
461
+ settings: function() {
462
+ var
463
+ runSettings
464
+ ;
465
+ runSettings = $.proxy(settings.beforeSend, $module)(settings);
466
+ if(runSettings) {
467
+ if(runSettings.success !== undefined) {
468
+ module.debug('Legacy success callback detected', runSettings);
469
+ module.error(error.legacyParameters, runSettings.success);
470
+ runSettings.onSuccess = runSettings.success;
471
+ }
472
+ if(runSettings.failure !== undefined) {
473
+ module.debug('Legacy failure callback detected', runSettings);
474
+ module.error(error.legacyParameters, runSettings.failure);
475
+ runSettings.onFailure = runSettings.failure;
476
+ }
477
+ if(runSettings.complete !== undefined) {
478
+ module.debug('Legacy complete callback detected', runSettings);
479
+ module.error(error.legacyParameters, runSettings.complete);
480
+ runSettings.onComplete = runSettings.complete;
481
+ }
482
+ }
483
+ if(runSettings === undefined) {
484
+ module.error(error.noReturnedValue);
485
+ }
486
+ return (runSettings !== undefined)
487
+ ? runSettings
488
+ : settings
489
+ ;
490
+ },
491
+ defaultData: function() {
492
+ var
493
+ data = {}
494
+ ;
495
+ if( !$.isWindow(element) ) {
496
+ if( $module.is('input') ) {
497
+ data.value = $module.val();
498
+ }
499
+ else if( $module.is('form') ) {
500
+
501
+ }
502
+ else {
503
+ data.text = $module.text();
504
+ }
505
+ }
506
+ return data;
507
+ },
508
+ event: function() {
509
+ if( $.isWindow(element) || settings.on == 'now' ) {
510
+ module.debug('API called without element, no events attached');
511
+ return false;
512
+ }
513
+ else if(settings.on == 'auto') {
514
+ if( $module.is('input') ) {
515
+ return (element.oninput !== undefined)
516
+ ? 'input'
517
+ : (element.onpropertychange !== undefined)
518
+ ? 'propertychange'
519
+ : 'keyup'
520
+ ;
521
+ }
522
+ else if( $module.is('form') ) {
523
+ return 'submit';
524
+ }
525
+ else {
526
+ return 'click';
527
+ }
528
+ }
529
+ else {
530
+ return settings.on;
531
+ }
532
+ },
533
+ formData: function() {
534
+ var
535
+ formData
536
+ ;
537
+ if($(this).serializeObject() !== undefined) {
538
+ formData = $form.serializeObject();
539
+ }
540
+ else {
541
+ module.error(error.missingSerialize);
542
+ formData = $form.serialize();
543
+ }
544
+ module.debug('Retrieved form data', formData);
545
+ return formData;
546
+ },
547
+ templateURL: function(action) {
548
+ var
549
+ url
550
+ ;
551
+ action = action || $module.data(settings.metadata.action) || settings.action || false;
552
+ if(action) {
553
+ module.debug('Looking up url for action', action, settings.api);
554
+ if(settings.api[action] !== undefined) {
555
+ url = settings.api[action];
556
+ module.debug('Found template url', url);
557
+ }
558
+ else {
559
+ module.error(error.missingAction, settings.action, settings.api);
560
+ }
561
+ }
562
+ return url;
563
+ }
564
+ },
565
+
566
+ // reset state
567
+ reset: function() {
568
+ module.remove.error();
569
+ module.remove.loading();
570
+ },
571
+
572
+ setting: function(name, value) {
573
+ module.debug('Changing setting', name, value);
574
+ if( $.isPlainObject(name) ) {
575
+ $.extend(true, settings, name);
576
+ }
577
+ else if(value !== undefined) {
578
+ settings[name] = value;
579
+ }
580
+ else {
581
+ return settings[name];
582
+ }
583
+ },
584
+ internal: function(name, value) {
585
+ if( $.isPlainObject(name) ) {
586
+ $.extend(true, module, name);
587
+ }
588
+ else if(value !== undefined) {
589
+ module[name] = value;
590
+ }
591
+ else {
592
+ return module[name];
593
+ }
594
+ },
595
+ debug: function() {
596
+ if(settings.debug) {
597
+ if(settings.performance) {
598
+ module.performance.log(arguments);
599
+ }
600
+ else {
601
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
602
+ module.debug.apply(console, arguments);
603
+ }
604
+ }
605
+ },
606
+ verbose: function() {
607
+ if(settings.verbose && settings.debug) {
608
+ if(settings.performance) {
609
+ module.performance.log(arguments);
610
+ }
611
+ else {
612
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
613
+ module.verbose.apply(console, arguments);
614
+ }
615
+ }
616
+ },
617
+ error: function() {
618
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
619
+ module.error.apply(console, arguments);
620
+ },
621
+ performance: {
622
+ log: function(message) {
623
+ var
624
+ currentTime,
625
+ executionTime,
626
+ previousTime
627
+ ;
628
+ if(settings.performance) {
629
+ currentTime = new Date().getTime();
630
+ previousTime = time || currentTime;
631
+ executionTime = currentTime - previousTime;
632
+ time = currentTime;
633
+ performance.push({
634
+ 'Name' : message[0],
635
+ 'Arguments' : [].slice.call(message, 1) || '',
636
+ //'Element' : element,
637
+ 'Execution Time' : executionTime
638
+ });
639
+ }
640
+ clearTimeout(module.performance.timer);
641
+ module.performance.timer = setTimeout(module.performance.display, 100);
642
+ },
643
+ display: function() {
644
+ var
645
+ title = settings.name + ':',
646
+ totalTime = 0
647
+ ;
648
+ time = false;
649
+ clearTimeout(module.performance.timer);
650
+ $.each(performance, function(index, data) {
651
+ totalTime += data['Execution Time'];
652
+ });
653
+ title += ' ' + totalTime + 'ms';
654
+ if(moduleSelector) {
655
+ title += ' \'' + moduleSelector + '\'';
656
+ }
657
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
658
+ console.groupCollapsed(title);
659
+ if(console.table) {
660
+ console.table(performance);
661
+ }
662
+ else {
663
+ $.each(performance, function(index, data) {
664
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
665
+ });
666
+ }
667
+ console.groupEnd();
668
+ }
669
+ performance = [];
670
+ }
671
+ },
672
+ invoke: function(query, passedArguments, context) {
673
+ var
674
+ object = instance,
675
+ maxDepth,
676
+ found,
677
+ response
678
+ ;
679
+ passedArguments = passedArguments || queryArguments;
680
+ context = element || context;
681
+ if(typeof query == 'string' && object !== undefined) {
682
+ query = query.split(/[\. ]/);
683
+ maxDepth = query.length - 1;
684
+ $.each(query, function(depth, value) {
685
+ var camelCaseValue = (depth != maxDepth)
686
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
687
+ : query
688
+ ;
689
+ if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
690
+ object = object[camelCaseValue];
691
+ }
692
+ else if( object[camelCaseValue] !== undefined ) {
693
+ found = object[camelCaseValue];
694
+ return false;
695
+ }
696
+ else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
697
+ object = object[value];
698
+ }
699
+ else if( object[value] !== undefined ) {
700
+ found = object[value];
701
+ return false;
702
+ }
703
+ else {
704
+ module.error(error.method, query);
705
+ return false;
706
+ }
707
+ });
708
+ }
709
+ if ( $.isFunction( found ) ) {
710
+ response = found.apply(context, passedArguments);
711
+ }
712
+ else if(found !== undefined) {
713
+ response = found;
714
+ }
715
+ if($.isArray(returnedValue)) {
716
+ returnedValue.push(response);
717
+ }
718
+ else if(returnedValue !== undefined) {
719
+ returnedValue = [returnedValue, response];
720
+ }
721
+ else if(response !== undefined) {
722
+ returnedValue = response;
723
+ }
724
+ return found;
725
+ }
726
+ };
727
+
728
+ if(methodInvoked) {
729
+ if(instance === undefined) {
730
+ module.initialize();
731
+ }
732
+ module.invoke(query);
733
+ }
734
+ else {
735
+ if(instance !== undefined) {
736
+ module.destroy();
737
+ }
738
+ module.initialize();
739
+ }
740
+ })
741
+ ;
742
+
743
+ return (returnedValue !== undefined)
744
+ ? returnedValue
745
+ : this
746
+ ;
747
+ };
748
+
749
+ $.api.settings = {
750
+
751
+ name : 'API',
752
+ namespace : 'api',
753
+
754
+ debug : true,
755
+ verbose : true,
756
+ performance : true,
757
+
758
+ // event binding
759
+ on : 'auto',
760
+ filter : '.disabled',
761
+ stateContext : false,
762
+
763
+ // state
764
+ loadingDuration : 0,
765
+ errorDuration : 2000,
766
+
767
+ // templating
768
+ action : false,
769
+ url : false,
770
+ base : '',
771
+
772
+ // data
773
+ urlData : {},
774
+
775
+ // ui
776
+ defaultData : true,
777
+ serializeForm : false,
778
+ throttle : 0,
779
+
780
+ // jQ ajax
781
+ method : 'get',
782
+ data : {},
783
+ dataType : 'json',
784
+
785
+ // callbacks
786
+ beforeSend : function(settings) { return settings; },
787
+ beforeXHR : function(xhr) {},
788
+
789
+ onSuccess : function(response, $module) {},
790
+ onComplete : function(response, $module) {},
791
+ onFailure : function(errorMessage, $module) {},
792
+ onError : function(errorMessage, $module) {},
793
+ onAbort : function(errorMessage, $module) {},
794
+
795
+ successTest : false,
796
+
797
+ // errors
798
+ error : {
799
+ beforeSend : 'The before send function has aborted the request',
800
+ error : 'There was an error with your request',
801
+ exitConditions : 'API Request Aborted. Exit conditions met',
802
+ JSONParse : 'JSON could not be parsed during error handling',
803
+ legacyParameters : 'You are using legacy API success callback names',
804
+ method : 'The method you called is not defined',
805
+ missingAction : 'API action used but no url was defined',
806
+ missingSerialize : 'Required dependency jquery-serialize-object missing, using basic serialize',
807
+ missingURL : 'No URL specified for api event',
808
+ noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
809
+ parseError : 'There was an error parsing your request',
810
+ requiredParameter : 'Missing a required URL parameter: ',
811
+ statusMessage : 'Server gave an error: ',
812
+ timeout : 'Your request timed out'
813
+ },
814
+
815
+ regExp : {
816
+ required: /\{\$*[A-z0-9]+\}/g,
817
+ optional: /\{\/\$*[A-z0-9]+\}/g,
818
+ },
819
+
820
+ className: {
821
+ loading : 'loading',
822
+ error : 'error'
823
+ },
824
+
825
+ selector: {
826
+ form: 'form'
827
+ },
828
+
829
+ metadata: {
830
+ action : 'action',
831
+ request : 'request',
832
+ xhr : 'xhr'
833
+ }
834
+ };
835
+
836
+
837
+ $.api.settings.api = {};
838
+
839
+
840
+ })( jQuery, window , document );