less-rails-semantic_ui 1.12.3.0 → 2.0.0.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 (197) hide show
  1. checksums.yaml +4 -4
  2. data/assets/javascripts/semantic_ui/definitions/behaviors/api.js +394 -188
  3. data/assets/javascripts/semantic_ui/definitions/behaviors/colorize.js +4 -2
  4. data/assets/javascripts/semantic_ui/definitions/behaviors/form.js +263 -125
  5. data/assets/javascripts/semantic_ui/definitions/behaviors/state.js +3 -3
  6. data/assets/javascripts/semantic_ui/definitions/behaviors/visibility.js +213 -96
  7. data/assets/javascripts/semantic_ui/definitions/behaviors/visit.js +6 -4
  8. data/assets/javascripts/semantic_ui/definitions/globals/site.js +4 -4
  9. data/assets/javascripts/semantic_ui/definitions/modules/accordion.js +66 -52
  10. data/assets/javascripts/semantic_ui/definitions/modules/checkbox.js +309 -112
  11. data/assets/javascripts/semantic_ui/definitions/modules/dimmer.js +24 -26
  12. data/assets/javascripts/semantic_ui/definitions/modules/dropdown.js +2005 -590
  13. data/assets/javascripts/semantic_ui/definitions/modules/embed.js +662 -0
  14. data/assets/javascripts/semantic_ui/definitions/modules/modal.js +106 -79
  15. data/assets/javascripts/semantic_ui/definitions/modules/nag.js +7 -8
  16. data/assets/javascripts/semantic_ui/definitions/modules/popup.js +323 -194
  17. data/assets/javascripts/semantic_ui/definitions/modules/progress.js +111 -103
  18. data/assets/javascripts/semantic_ui/definitions/modules/rating.js +78 -54
  19. data/assets/javascripts/semantic_ui/definitions/modules/search.js +304 -122
  20. data/assets/javascripts/semantic_ui/definitions/modules/shape.js +93 -47
  21. data/assets/javascripts/semantic_ui/definitions/modules/sidebar.js +83 -149
  22. data/assets/javascripts/semantic_ui/definitions/modules/sticky.js +99 -29
  23. data/assets/javascripts/semantic_ui/definitions/modules/tab.js +219 -124
  24. data/assets/javascripts/semantic_ui/definitions/modules/transition.js +202 -171
  25. data/assets/stylesheets/semantic_ui/definitions/collections/breadcrumb.less +2 -1
  26. data/assets/stylesheets/semantic_ui/definitions/collections/form.less +135 -58
  27. data/assets/stylesheets/semantic_ui/definitions/collections/grid.less +366 -383
  28. data/assets/stylesheets/semantic_ui/definitions/collections/menu.less +838 -631
  29. data/assets/stylesheets/semantic_ui/definitions/collections/message.less +89 -71
  30. data/assets/stylesheets/semantic_ui/definitions/collections/table.less +183 -131
  31. data/assets/stylesheets/semantic_ui/definitions/elements/button.less +1097 -300
  32. data/assets/stylesheets/semantic_ui/definitions/elements/container.less +135 -0
  33. data/assets/stylesheets/semantic_ui/definitions/elements/divider.less +31 -30
  34. data/assets/stylesheets/semantic_ui/definitions/elements/flag.less +1 -1
  35. data/assets/stylesheets/semantic_ui/definitions/elements/header.less +209 -121
  36. data/assets/stylesheets/semantic_ui/definitions/elements/icon.less +201 -96
  37. data/assets/stylesheets/semantic_ui/definitions/elements/image.less +26 -11
  38. data/assets/stylesheets/semantic_ui/definitions/elements/input.less +49 -14
  39. data/assets/stylesheets/semantic_ui/definitions/elements/label.less +391 -221
  40. data/assets/stylesheets/semantic_ui/definitions/elements/list.less +107 -68
  41. data/assets/stylesheets/semantic_ui/definitions/elements/loader.less +3 -1
  42. data/assets/stylesheets/semantic_ui/definitions/elements/rail.less +34 -25
  43. data/assets/stylesheets/semantic_ui/definitions/elements/reveal.less +25 -10
  44. data/assets/stylesheets/semantic_ui/definitions/elements/segment.less +261 -173
  45. data/assets/stylesheets/semantic_ui/definitions/elements/step.less +169 -70
  46. data/assets/stylesheets/semantic_ui/definitions/globals/reset.less +1 -1
  47. data/assets/stylesheets/semantic_ui/definitions/globals/site.less +3 -1
  48. data/assets/stylesheets/semantic_ui/definitions/modules/accordion.less +1 -2
  49. data/assets/stylesheets/semantic_ui/definitions/modules/checkbox.less +175 -103
  50. data/assets/stylesheets/semantic_ui/definitions/modules/dimmer.less +26 -15
  51. data/assets/stylesheets/semantic_ui/definitions/modules/dropdown.less +349 -80
  52. data/assets/stylesheets/semantic_ui/definitions/modules/embed.less +174 -0
  53. data/assets/stylesheets/semantic_ui/definitions/modules/modal.less +83 -36
  54. data/assets/stylesheets/semantic_ui/definitions/modules/nag.less +1 -1
  55. data/assets/stylesheets/semantic_ui/definitions/modules/popup.less +48 -7
  56. data/assets/stylesheets/semantic_ui/definitions/modules/progress.less +160 -107
  57. data/assets/stylesheets/semantic_ui/definitions/modules/rating.less +57 -54
  58. data/assets/stylesheets/semantic_ui/definitions/modules/search.less +55 -10
  59. data/assets/stylesheets/semantic_ui/definitions/modules/shape.less +5 -6
  60. data/assets/stylesheets/semantic_ui/definitions/modules/sidebar.less +9 -5
  61. data/assets/stylesheets/semantic_ui/definitions/modules/sticky.less +1 -1
  62. data/assets/stylesheets/semantic_ui/definitions/modules/tab.less +1 -1
  63. data/assets/stylesheets/semantic_ui/definitions/modules/transition.less +3 -4
  64. data/assets/stylesheets/semantic_ui/definitions/views/card.less +240 -130
  65. data/assets/stylesheets/semantic_ui/definitions/views/comment.less +1 -1
  66. data/assets/stylesheets/semantic_ui/definitions/views/feed.less +15 -8
  67. data/assets/stylesheets/semantic_ui/definitions/views/item.less +13 -13
  68. data/assets/stylesheets/semantic_ui/definitions/views/statistic.less +230 -86
  69. data/assets/stylesheets/semantic_ui/theme.less +22 -15
  70. data/assets/stylesheets/semantic_ui/themes/amazon/elements/button.overrides +5 -5
  71. data/assets/stylesheets/semantic_ui/themes/amazon/elements/button.variables +5 -4
  72. data/assets/stylesheets/semantic_ui/themes/basic/collections/table.variables +1 -0
  73. data/assets/stylesheets/semantic_ui/themes/basic/views/card.variables +6 -4
  74. data/assets/stylesheets/semantic_ui/themes/bookish/elements/header.variables +4 -4
  75. data/assets/stylesheets/semantic_ui/themes/bootstrap3/elements/button.variables +1 -1
  76. data/assets/stylesheets/semantic_ui/themes/chubby/collections/form.overrides +8 -0
  77. data/assets/stylesheets/semantic_ui/themes/chubby/collections/menu.overrides +0 -0
  78. data/assets/stylesheets/semantic_ui/themes/chubby/collections/menu.variables +40 -0
  79. data/assets/stylesheets/semantic_ui/themes/classic/modules/progress.variables +1 -0
  80. data/assets/stylesheets/semantic_ui/themes/classic/views/card.overrides +1 -1
  81. data/assets/stylesheets/semantic_ui/themes/colored/modules/checkbox.overrides +0 -0
  82. data/assets/stylesheets/semantic_ui/themes/colored/modules/checkbox.variables +17 -0
  83. data/assets/stylesheets/semantic_ui/themes/default/collections/breadcrumb.overrides +0 -0
  84. data/assets/stylesheets/semantic_ui/themes/default/collections/breadcrumb.variables +5 -15
  85. data/assets/stylesheets/semantic_ui/themes/default/collections/form.overrides +0 -0
  86. data/assets/stylesheets/semantic_ui/themes/default/collections/form.variables +31 -35
  87. data/assets/stylesheets/semantic_ui/themes/default/collections/grid.overrides +0 -0
  88. data/assets/stylesheets/semantic_ui/themes/default/collections/grid.variables +34 -28
  89. data/assets/stylesheets/semantic_ui/themes/default/collections/menu.overrides +0 -0
  90. data/assets/stylesheets/semantic_ui/themes/default/collections/menu.variables +259 -163
  91. data/assets/stylesheets/semantic_ui/themes/default/collections/message.overrides +0 -0
  92. data/assets/stylesheets/semantic_ui/themes/default/collections/message.variables +42 -19
  93. data/assets/stylesheets/semantic_ui/themes/default/collections/table.overrides +0 -3
  94. data/assets/stylesheets/semantic_ui/themes/default/collections/table.variables +63 -59
  95. data/assets/stylesheets/semantic_ui/themes/default/elements/button.overrides +0 -0
  96. data/assets/stylesheets/semantic_ui/themes/default/elements/button.variables +90 -50
  97. data/assets/stylesheets/semantic_ui/themes/default/elements/container.overrides +3 -0
  98. data/assets/stylesheets/semantic_ui/themes/default/elements/container.variables +45 -0
  99. data/assets/stylesheets/semantic_ui/themes/default/elements/divider.overrides +15 -0
  100. data/assets/stylesheets/semantic_ui/themes/default/elements/divider.variables +3 -4
  101. data/assets/stylesheets/semantic_ui/themes/default/elements/flag.overrides +0 -0
  102. data/assets/stylesheets/semantic_ui/themes/default/elements/header.overrides +0 -0
  103. data/assets/stylesheets/semantic_ui/themes/default/elements/header.variables +40 -36
  104. data/assets/stylesheets/semantic_ui/themes/default/elements/icon.overrides +4 -3
  105. data/assets/stylesheets/semantic_ui/themes/default/elements/icon.variables +29 -12
  106. data/assets/stylesheets/semantic_ui/themes/default/elements/image.overrides +0 -0
  107. data/assets/stylesheets/semantic_ui/themes/default/elements/image.variables +5 -3
  108. data/assets/stylesheets/semantic_ui/themes/default/elements/input.overrides +0 -0
  109. data/assets/stylesheets/semantic_ui/themes/default/elements/input.variables +10 -24
  110. data/assets/stylesheets/semantic_ui/themes/default/elements/label.overrides +0 -0
  111. data/assets/stylesheets/semantic_ui/themes/default/elements/label.variables +88 -35
  112. data/assets/stylesheets/semantic_ui/themes/default/elements/list.overrides +0 -0
  113. data/assets/stylesheets/semantic_ui/themes/default/elements/list.variables +53 -34
  114. data/assets/stylesheets/semantic_ui/themes/default/elements/loader.overrides +0 -0
  115. data/assets/stylesheets/semantic_ui/themes/default/elements/loader.variables +9 -10
  116. data/assets/stylesheets/semantic_ui/themes/default/elements/rail.overrides +0 -0
  117. data/assets/stylesheets/semantic_ui/themes/default/elements/rail.variables +13 -5
  118. data/assets/stylesheets/semantic_ui/themes/default/elements/reveal.overrides +0 -0
  119. data/assets/stylesheets/semantic_ui/themes/default/elements/reveal.variables +6 -4
  120. data/assets/stylesheets/semantic_ui/themes/default/elements/segment.overrides +0 -0
  121. data/assets/stylesheets/semantic_ui/themes/default/elements/segment.variables +66 -28
  122. data/assets/stylesheets/semantic_ui/themes/default/elements/step.overrides +0 -0
  123. data/assets/stylesheets/semantic_ui/themes/default/elements/step.variables +60 -31
  124. data/assets/stylesheets/semantic_ui/themes/default/globals/reset.overrides +0 -0
  125. data/assets/stylesheets/semantic_ui/themes/default/globals/site.variables +477 -303
  126. data/assets/stylesheets/semantic_ui/themes/default/modules/accordion.overrides +0 -0
  127. data/assets/stylesheets/semantic_ui/themes/default/modules/accordion.variables +6 -7
  128. data/assets/stylesheets/semantic_ui/themes/default/modules/chatroom.overrides +0 -0
  129. data/assets/stylesheets/semantic_ui/themes/default/modules/checkbox.overrides +19 -16
  130. data/assets/stylesheets/semantic_ui/themes/default/modules/checkbox.variables +71 -43
  131. data/assets/stylesheets/semantic_ui/themes/default/modules/dimmer.overrides +0 -0
  132. data/assets/stylesheets/semantic_ui/themes/default/modules/dimmer.variables +12 -9
  133. data/assets/stylesheets/semantic_ui/themes/default/modules/dropdown.overrides +0 -5
  134. data/assets/stylesheets/semantic_ui/themes/default/modules/dropdown.variables +146 -64
  135. data/assets/stylesheets/semantic_ui/themes/default/modules/{video.overrides → embed.overrides} +0 -0
  136. data/assets/stylesheets/semantic_ui/themes/default/modules/embed.variables +53 -0
  137. data/assets/stylesheets/semantic_ui/themes/default/modules/modal.overrides +0 -0
  138. data/assets/stylesheets/semantic_ui/themes/default/modules/modal.variables +24 -18
  139. data/assets/stylesheets/semantic_ui/themes/default/modules/nag.overrides +0 -0
  140. data/assets/stylesheets/semantic_ui/themes/default/modules/popup.overrides +0 -0
  141. data/assets/stylesheets/semantic_ui/themes/default/modules/popup.variables +3 -9
  142. data/assets/stylesheets/semantic_ui/themes/default/modules/progress.variables +13 -7
  143. data/assets/stylesheets/semantic_ui/themes/default/modules/rating.overrides +0 -0
  144. data/assets/stylesheets/semantic_ui/themes/default/modules/rating.variables +71 -33
  145. data/assets/stylesheets/semantic_ui/themes/default/modules/search.overrides +0 -0
  146. data/assets/stylesheets/semantic_ui/themes/default/modules/search.variables +36 -34
  147. data/assets/stylesheets/semantic_ui/themes/default/modules/shape.overrides +0 -0
  148. data/assets/stylesheets/semantic_ui/themes/default/modules/shape.variables +7 -2
  149. data/assets/stylesheets/semantic_ui/themes/default/modules/sidebar.overrides +0 -0
  150. data/assets/stylesheets/semantic_ui/themes/default/modules/sidebar.variables +2 -5
  151. data/assets/stylesheets/semantic_ui/themes/default/modules/sticky.overrides +0 -0
  152. data/assets/stylesheets/semantic_ui/themes/default/modules/sticky.variables +2 -7
  153. data/assets/stylesheets/semantic_ui/themes/default/modules/tab.variables +1 -3
  154. data/assets/stylesheets/semantic_ui/themes/default/modules/transition.overrides +8 -9
  155. data/assets/stylesheets/semantic_ui/themes/default/views/ad.variables +2 -2
  156. data/assets/stylesheets/semantic_ui/themes/default/views/card.variables +33 -23
  157. data/assets/stylesheets/semantic_ui/themes/default/views/comment.overrides +0 -0
  158. data/assets/stylesheets/semantic_ui/themes/default/views/feed.overrides +0 -0
  159. data/assets/stylesheets/semantic_ui/themes/default/views/feed.variables +15 -23
  160. data/assets/stylesheets/semantic_ui/themes/default/views/item.overrides +0 -0
  161. data/assets/stylesheets/semantic_ui/themes/default/views/item.variables +12 -11
  162. data/assets/stylesheets/semantic_ui/themes/default/views/statistic.overrides +0 -0
  163. data/assets/stylesheets/semantic_ui/themes/default/views/statistic.variables +25 -24
  164. data/assets/stylesheets/semantic_ui/themes/flat/collections/form.overrides +4 -0
  165. data/assets/stylesheets/semantic_ui/themes/flat/collections/form.variables +1 -2
  166. data/assets/stylesheets/semantic_ui/themes/flat/globals/site.variables +1 -0
  167. data/assets/stylesheets/semantic_ui/themes/github/collections/form.variables +1 -1
  168. data/assets/stylesheets/semantic_ui/themes/github/collections/menu.variables +10 -15
  169. data/assets/stylesheets/semantic_ui/themes/github/elements/button.variables +2 -2
  170. data/assets/stylesheets/semantic_ui/themes/github/elements/step.variables +2 -2
  171. data/assets/stylesheets/semantic_ui/themes/instagram/views/card.overrides +12 -0
  172. data/assets/stylesheets/semantic_ui/themes/instagram/views/card.variables +23 -0
  173. data/assets/stylesheets/semantic_ui/themes/material/collections/menu.overrides +1 -0
  174. data/assets/stylesheets/semantic_ui/themes/material/collections/menu.variables +10 -0
  175. data/assets/stylesheets/semantic_ui/themes/material/elements/button.overrides +1 -0
  176. data/assets/stylesheets/semantic_ui/themes/material/elements/button.variables +14 -6
  177. data/assets/stylesheets/semantic_ui/themes/material/globals/site.variables +3 -2
  178. data/assets/stylesheets/semantic_ui/themes/material/modules/dropdown.overrides +5 -0
  179. data/assets/stylesheets/semantic_ui/themes/material/modules/dropdown.variables +20 -0
  180. data/assets/stylesheets/semantic_ui/themes/raised/elements/button.variables +5 -5
  181. data/assets/stylesheets/semantic_ui/themes/round/elements/button.variables +1 -1
  182. data/assets/stylesheets/semantic_ui/themes/timeline/views/feed.overrides +4 -12
  183. data/assets/stylesheets/semantic_ui/themes/timeline/views/feed.variables +3 -7
  184. data/lib/generators/semantic_ui/install/templates/config/elements/container.overrides +3 -0
  185. data/lib/generators/semantic_ui/install/templates/config/elements/container.variables +3 -0
  186. data/lib/generators/semantic_ui/install/templates/config/modules/embed.overrides +3 -0
  187. data/lib/generators/semantic_ui/install/templates/config/modules/embed.variables +0 -0
  188. data/lib/generators/semantic_ui/install/templates/semantic_ui.css +2 -1
  189. data/lib/generators/semantic_ui/install/templates/semantic_ui.js +1 -1
  190. data/lib/generators/semantic_ui/install/templates/theme.config +5 -3
  191. data/lib/less/rails/semantic_ui/version.rb +1 -1
  192. data/tasks/update.rake +21 -6
  193. metadata +23 -7
  194. data/assets/fonts/semantic_ui/themes/default/assets/fonts/icons.otf +0 -0
  195. data/assets/javascripts/semantic_ui/definitions/modules/video.js +0 -540
  196. data/assets/stylesheets/semantic_ui/definitions/modules/video.less +0 -135
  197. data/assets/stylesheets/semantic_ui/themes/default/modules/video.variables +0 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4e4343980ee8e7b79009d25aaf6ec3f47e800fc2
4
- data.tar.gz: 5897d1bb42e3a4902f92ee9e1f13aa57faaeb300
3
+ metadata.gz: ae7af5f161f9cf436de8c0a4a2b2b1b8a8f538a3
4
+ data.tar.gz: c1ecc46fb62fcea92e8de9a02a1eb07e5f7897ca
5
5
  SHA512:
6
- metadata.gz: bfd3d585acf357b0d4f0f572d7646a0199deef4fe4181cbaf2b74f6d33e23412fecdffde2261bcafdf9d8649edc8aec6c4034beec4cdcd1d3d9ed8ca95050b62
7
- data.tar.gz: 147569b9c3ff924ec9c0982914205d815340d99e956c92670a5eaa9b33e961213a6c16be148ac6bbb708765f498f40c0d24dfe3fc24b7bd8f2031a722a88096d
6
+ metadata.gz: 013cb7dbb6a031ddc75fb39b0c9be1817cf1d80d88cf6945e86d2354497235263f185ad0365d00e506d9e9900f9309e3f64df3936f4c74df003f88aad5a82218
7
+ data.tar.gz: 1d39a800271be04c61c8edcccdc9a46c42b65c400ba2fb6f087d6c34a7544990c2f00f79271b95d2ed9230b34783b6b40806d02df23ee402961751a257e31350
@@ -3,7 +3,7 @@
3
3
  * http://github.com/semantic-org/semantic-ui/
4
4
  *
5
5
  *
6
- * Copyright 2014 Contributors
6
+ * Copyright 2015 Contributors
7
7
  * Released under the MIT license
8
8
  * http://opensource.org/licenses/MIT
9
9
  *
@@ -63,10 +63,11 @@ $.api = $.fn.api = function(parameters) {
63
63
  requestSettings,
64
64
  url,
65
65
  data,
66
+ requestStartTime,
66
67
 
67
68
  // standard module
68
69
  element = this,
69
- context = $context.get(),
70
+ context = $context[0],
70
71
  instance = $module.data(moduleNamespace),
71
72
  module
72
73
  ;
@@ -74,21 +75,8 @@ $.api = $.fn.api = function(parameters) {
74
75
  module = {
75
76
 
76
77
  initialize: function() {
77
- var
78
- triggerEvent = module.get.event()
79
- ;
80
- // bind events
81
78
  if(!methodInvoked) {
82
- if( triggerEvent ) {
83
- module.debug('Attaching API events to element', triggerEvent);
84
- $module
85
- .on(triggerEvent + eventNamespace, module.event.trigger)
86
- ;
87
- }
88
- else if(settings.on == 'now') {
89
- module.debug('Querying API now', triggerEvent);
90
- module.query();
91
- }
79
+ module.bind.events();
92
80
  }
93
81
  module.instantiate();
94
82
  },
@@ -109,16 +97,81 @@ $.api = $.fn.api = function(parameters) {
109
97
  ;
110
98
  },
111
99
 
100
+ bind: {
101
+ events: function() {
102
+ var
103
+ triggerEvent = module.get.event()
104
+ ;
105
+ if( triggerEvent ) {
106
+ module.verbose('Attaching API events to element', triggerEvent);
107
+ $module
108
+ .on(triggerEvent + eventNamespace, module.event.trigger)
109
+ ;
110
+ }
111
+ else if(settings.on == 'now') {
112
+ module.debug('Querying API now', triggerEvent);
113
+ module.query();
114
+ }
115
+ }
116
+ },
117
+
118
+ read: {
119
+ cachedResponse: function(url) {
120
+ var
121
+ response
122
+ ;
123
+ if(window.Storage === undefined) {
124
+ module.error(error.noStorage);
125
+ return;
126
+ }
127
+ response = sessionStorage.getItem(url);
128
+ module.debug('Using cached response', url, response);
129
+ if(response !== undefined) {
130
+ try {
131
+ response = JSON.parse(response);
132
+ }
133
+ catch(e) {
134
+ // didnt store object
135
+ }
136
+ return response;
137
+ }
138
+ return false;
139
+ }
140
+ },
141
+ write: {
142
+ cachedResponse: function(url, response) {
143
+ if(response && response === '') {
144
+ module.debug('Response empty, not caching', response);
145
+ return;
146
+ }
147
+ if(window.Storage === undefined) {
148
+ module.error(error.noStorage);
149
+ return;
150
+ }
151
+ if( $.isPlainObject(response) ) {
152
+ response = JSON.stringify(response);
153
+ }
154
+ sessionStorage.setItem(url, response);
155
+ module.verbose('Storing cached response for url', url, response);
156
+ }
157
+ },
158
+
112
159
  query: function() {
113
160
 
114
161
  if(module.is.disabled()) {
115
162
  module.debug('Element is disabled API request aborted');
116
163
  return;
117
164
  }
118
- // determine if an api event already occurred
119
- if(module.is.loading() && settings.throttle === 0 ) {
120
- module.debug('Cancelling request, previous request is still pending');
121
- return;
165
+
166
+ if(module.is.loading()) {
167
+ if(settings.interruptRequests) {
168
+ module.debug('Interrupting previous request');
169
+ module.abort();
170
+ }
171
+ else {
172
+ module.debug('Cancelling request, previous request is still pending');
173
+ return;
174
+ }
122
175
  }
123
176
 
124
177
  // pass element metadata to url (value, text)
@@ -127,17 +180,12 @@ $.api = $.fn.api = function(parameters) {
127
180
  }
128
181
 
129
182
  // Add form content
130
- if(settings.serializeForm !== false || $context.is('form')) {
131
- if(settings.serializeForm == 'json') {
132
- $.extend(true, settings.data, module.get.formData());
133
- }
134
- else {
135
- settings.data = module.get.formData();
136
- }
183
+ if(settings.serializeForm) {
184
+ settings.data = module.add.formData(settings.data);
137
185
  }
138
186
 
139
187
  // call beforesend and get any settings changes
140
- requestSettings = module.get.settings();
188
+ requestSettings = module.get.settings();
141
189
 
142
190
  // check if before send cancelled request
143
191
  if(requestSettings === false) {
@@ -149,31 +197,22 @@ $.api = $.fn.api = function(parameters) {
149
197
  module.cancelled = false;
150
198
  }
151
199
 
152
- if(settings.url) {
153
- // override with url if specified
154
- module.debug('Using specified url', url);
155
- url = module.add.urlData( settings.url );
156
- }
157
- else {
158
- // otherwise find url from api endpoints
159
- url = module.add.urlData( module.get.templateURL() );
160
- module.debug('Added URL Data to url', url);
200
+ // get url
201
+ url = module.get.templatedURL();
202
+
203
+ if(!url && !module.is.mocked()) {
204
+ module.error(error.missingURL);
205
+ return;
161
206
  }
162
207
 
163
- // exit conditions reached, missing url parameters
164
- if( !url ) {
165
- if( module.is.form() ) {
166
- url = $module.attr('action') || '';
167
- module.debug('No url or action specified, defaulting to form action', url);
168
- }
169
- else {
170
- module.error(error.missingURL, settings.action);
171
- return;
172
- }
208
+ // replace variables
209
+ url = module.add.urlData( url );
210
+
211
+ // missing url parameters
212
+ if( !url && !module.is.mocked()) {
213
+ return;
173
214
  }
174
215
 
175
- // add loading state
176
- module.set.loading();
177
216
 
178
217
  // look for jQuery ajax parameters in settings
179
218
  ajaxSettings = $.extend(true, {}, settings, {
@@ -187,39 +226,80 @@ $.api = $.fn.api = function(parameters) {
187
226
  });
188
227
 
189
228
  module.debug('Querying URL', ajaxSettings.url);
190
- module.debug('Sending data', data, ajaxSettings.method);
191
229
  module.verbose('Using AJAX settings', ajaxSettings);
192
230
 
193
- if( module.is.loading() ) {
194
- // throttle additional requests
195
- module.timer = setTimeout(function() {
196
- module.request = module.create.request();
197
- module.xhr = module.create.xhr();
198
- settings.onRequest.call(context, module.request, module.xhr);
199
- }, settings.throttle);
231
+ if(settings.cache === 'local' && module.read.cachedResponse(url)) {
232
+ module.debug('Response returned from local cache');
233
+ module.request = module.create.request();
234
+ module.request.resolveWith(context, [ module.read.cachedResponse(url) ]);
235
+ return;
236
+ }
237
+
238
+ if( !settings.throttle ) {
239
+ module.debug('Sending request', data, ajaxSettings.method);
240
+ module.send.request();
200
241
  }
201
242
  else {
202
- // immediately on first request
203
- module.request = module.create.request();
204
- module.xhr = module.create.xhr();
205
- settings.onRequest.call(context, module.request, module.xhr);
243
+ if(!settings.throttleFirstRequest && !module.timer) {
244
+ module.debug('Sending request', data, ajaxSettings.method);
245
+ module.send.request();
246
+ module.timer = setTimeout(function(){}, settings.throttle);
247
+ }
248
+ else {
249
+ module.debug('Throttling request', settings.throttle);
250
+ clearTimeout(module.timer);
251
+ module.timer = setTimeout(function() {
252
+ if(module.timer) {
253
+ delete module.timer;
254
+ }
255
+ module.debug('Sending throttled request', data, ajaxSettings.method);
256
+ module.send.request();
257
+ }, settings.throttle);
258
+ }
206
259
  }
207
260
 
208
261
  },
209
262
 
210
-
211
263
  is: {
212
264
  disabled: function() {
213
- return ($module.filter(settings.filter).length > 0);
265
+ return ($module.filter(selector.disabled).length > 0);
214
266
  },
215
267
  form: function() {
216
268
  return $module.is('form');
217
269
  },
270
+ mocked: function() {
271
+ return (settings.mockResponse || settings.mockResponseAsync);
272
+ },
218
273
  input: function() {
219
274
  return $module.is('input');
220
275
  },
221
276
  loading: function() {
222
277
  return (module.request && module.request.state() == 'pending');
278
+ },
279
+ abortedRequest: function(xhr) {
280
+ if(xhr && xhr.readyState !== undefined && xhr.readyState === 0) {
281
+ module.verbose('XHR request determined to be aborted');
282
+ return true;
283
+ }
284
+ else {
285
+ module.verbose('XHR request was not aborted');
286
+ return false;
287
+ }
288
+ },
289
+ validResponse: function(response) {
290
+ if( settings.dataType !== 'json' || !$.isFunction(settings.successTest) ) {
291
+ module.verbose('Response is not JSON, skipping validation', settings.successTest, response);
292
+ return true;
293
+ }
294
+ module.debug('Checking JSON returned success', settings.successTest, response);
295
+ if( settings.successTest(response) ) {
296
+ module.debug('Response passed success test', response);
297
+ return true;
298
+ }
299
+ else {
300
+ module.debug('Response failed success test', response);
301
+ return false;
302
+ }
223
303
  }
224
304
  },
225
305
 
@@ -311,6 +391,48 @@ $.api = $.fn.api = function(parameters) {
311
391
  }
312
392
  }
313
393
  return url;
394
+ },
395
+ formData: function(data) {
396
+ var
397
+ canSerialize = ($.fn.serializeObject !== undefined),
398
+ formData = (canSerialize)
399
+ ? $form.serializeObject()
400
+ : $form.serialize(),
401
+ hasOtherData
402
+ ;
403
+ data = data || settings.data;
404
+ hasOtherData = $.isPlainObject(data);
405
+
406
+ if(hasOtherData) {
407
+ if(canSerialize) {
408
+ module.debug('Extending existing data with form data', data, formData);
409
+ data = $.extend(true, {}, data, formData);
410
+ }
411
+ else {
412
+ module.error(error.missingSerialize);
413
+ module.debug('Cant extend data. Replacing data with form data', data, formData);
414
+ data = formData;
415
+ }
416
+ }
417
+ else {
418
+ module.debug('Adding form data', formData);
419
+ data = formData;
420
+ }
421
+ return data;
422
+ }
423
+ },
424
+
425
+ send: {
426
+ request: function() {
427
+ module.set.loading();
428
+ module.request = module.create.request();
429
+ if( module.is.mocked() ) {
430
+ module.mockedXHR = module.create.mockedXHR();
431
+ }
432
+ else {
433
+ module.xhr = module.create.xhr();
434
+ }
435
+ settings.onRequest.call(context, module.request, module.xhr);
314
436
  }
315
437
  },
316
438
 
@@ -325,37 +447,54 @@ $.api = $.fn.api = function(parameters) {
325
447
  always: function() {
326
448
  // calculate if loading time was below minimum threshold
327
449
  },
328
- done: function(response) {
450
+ done: function(response, textStatus, xhr) {
329
451
  var
330
452
  context = this,
331
- elapsedTime = (new Date().getTime() - time),
332
- timeLeft = (settings.loadingDuration - elapsedTime)
453
+ elapsedTime = (new Date().getTime() - requestStartTime),
454
+ timeLeft = (settings.loadingDuration - elapsedTime),
455
+ translatedResponse = ( $.isFunction(settings.onResponse) )
456
+ ? settings.onResponse.call(context, $.extend(true, {}, response))
457
+ : false
333
458
  ;
334
459
  timeLeft = (timeLeft > 0)
335
460
  ? timeLeft
336
461
  : 0
337
462
  ;
463
+ if(translatedResponse) {
464
+ module.debug('Modified API response in onResponse callback', settings.onResponse, translatedResponse, response);
465
+ response = translatedResponse;
466
+ }
467
+ if(timeLeft > 0) {
468
+ module.debug('Response completed early delaying state change by', timeLeft);
469
+ }
338
470
  setTimeout(function() {
339
- module.request.resolveWith(context, [response]);
471
+ if( module.is.validResponse(response) ) {
472
+ module.request.resolveWith(context, [response]);
473
+ }
474
+ else {
475
+ module.request.rejectWith(context, [xhr, 'invalid']);
476
+ }
340
477
  }, timeLeft);
341
478
  },
342
479
  fail: function(xhr, status, httpMessage) {
343
480
  var
344
481
  context = this,
345
- elapsedTime = (new Date().getTime() - time),
482
+ elapsedTime = (new Date().getTime() - requestStartTime),
346
483
  timeLeft = (settings.loadingDuration - elapsedTime)
347
484
  ;
348
485
  timeLeft = (timeLeft > 0)
349
486
  ? timeLeft
350
487
  : 0
351
488
  ;
352
- // page triggers abort on navigation, dont show error
489
+ if(timeLeft > 0) {
490
+ module.debug('Response completed early delaying state change by', timeLeft);
491
+ }
353
492
  setTimeout(function() {
354
- if(status !== 'abort') {
355
- module.request.rejectWith(context, [xhr, status, httpMessage]);
493
+ if( module.is.abortedRequest(xhr) ) {
494
+ module.request.rejectWith(context, [xhr, 'aborted', httpMessage]);
356
495
  }
357
496
  else {
358
- module.reset();
497
+ module.request.rejectWith(context, [xhr, 'error', status, httpMessage]);
359
498
  }
360
499
  }, timeLeft);
361
500
  }
@@ -366,87 +505,124 @@ $.api = $.fn.api = function(parameters) {
366
505
  settings.onComplete.call(context, response, $module);
367
506
  },
368
507
  done: function(response) {
369
- module.debug('API Response Received', response);
370
- if(settings.dataType == 'json') {
371
- if( $.isFunction(settings.successTest) ) {
372
- module.debug('Checking JSON returned success', settings.successTest, response);
373
- if( settings.successTest(response) ) {
374
- settings.onSuccess.call(context, response, $module);
375
- }
376
- else {
377
- module.debug('JSON test specified by user and response failed', response);
378
- settings.onFailure.call(context, response, $module);
379
- }
380
- }
381
- else {
382
- settings.onSuccess.call(context, response, $module);
383
- }
384
- }
385
- else {
386
- settings.onSuccess.call(context, response, $module);
508
+ module.debug('Successful API Response', response);
509
+ if(settings.cache === 'local' && url) {
510
+ module.write.cachedResponse(url, response);
511
+ module.debug('Saving server response locally', module.cache);
387
512
  }
513
+ settings.onSuccess.call(context, response, $module);
388
514
  },
389
- error: function(xhr, status, httpMessage) {
515
+ fail: function(xhr, status, httpMessage) {
390
516
  var
391
- errorMessage = (settings.error[status] !== undefined)
392
- ? settings.error[status]
393
- : httpMessage,
394
- response
517
+ // pull response from xhr if available
518
+ response = $.isPlainObject(xhr)
519
+ ? (xhr.responseText)
520
+ : false,
521
+ errorMessage = ($.isPlainObject(response) && response.error !== undefined)
522
+ ? response.error // use json error message
523
+ : (settings.error[status] !== undefined) // use server error message
524
+ ? settings.error[status]
525
+ : httpMessage
395
526
  ;
396
- // let em know unless request aborted
397
- if(xhr !== undefined) {
398
- // readyState 4 = done, anything less is not really sent
399
- if(xhr.readyState !== undefined && xhr.readyState == 4) {
527
+ if(status == 'aborted') {
528
+ module.debug('XHR Aborted (Most likely caused by page navigation or CORS Policy)', status, httpMessage);
529
+ settings.onAbort.call(context, status, $module);
530
+ }
531
+ else if(status == 'invalid') {
532
+ module.debug('JSON did not pass success test. A server-side error has most likely occurred', response);
533
+ }
534
+ else if(status == 'error') {
400
535
 
401
- // if http status code returned and json returned error, look for it
536
+ if(xhr !== undefined) {
537
+ module.debug('XHR produced a server error', status, httpMessage);
538
+ // make sure we have an error to display to console
402
539
  if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
403
540
  module.error(error.statusMessage + httpMessage, ajaxSettings.url);
404
541
  }
405
- else {
406
- if(status == 'error' && settings.dataType == 'json') {
407
- try {
408
- response = $.parseJSON(xhr.responseText);
409
- if(response && response.error !== undefined) {
410
- errorMessage = response.error;
411
- }
412
- }
413
- catch(e) {
414
- module.error(error.JSONParse);
415
- }
416
- }
417
- }
418
- module.remove.loading();
419
- module.set.error();
420
- // show error state only for duration specified in settings
421
- if(settings.errorDuration) {
422
- setTimeout(module.remove.error, settings.errorDuration);
423
- }
424
- module.debug('API Request error:', errorMessage);
425
542
  settings.onError.call(context, errorMessage, $module);
426
543
  }
427
- else {
428
- settings.onAbort.call(context, errorMessage, $module);
429
- module.debug('Request Aborted (Most likely caused by page change or CORS Policy)', status, httpMessage);
430
- }
431
544
  }
545
+
546
+ if(settings.errorDuration && status !== 'aborted') {
547
+ module.debug('Adding error state');
548
+ module.set.error();
549
+ setTimeout(module.remove.error, settings.errorDuration);
550
+ }
551
+ module.debug('API Request failed', errorMessage, xhr);
552
+ settings.onFailure.call(context, response, $module);
432
553
  }
433
554
  }
434
555
  },
435
556
 
436
557
  create: {
558
+
437
559
  request: function() {
560
+ // api request promise
438
561
  return $.Deferred()
439
562
  .always(module.event.request.complete)
440
563
  .done(module.event.request.done)
441
- .fail(module.event.request.error)
564
+ .fail(module.event.request.fail)
442
565
  ;
443
566
  },
567
+
568
+ mockedXHR: function () {
569
+ var
570
+ // xhr does not simulate these properties of xhr but must return them
571
+ textStatus = false,
572
+ status = false,
573
+ httpMessage = false,
574
+ asyncCallback,
575
+ response,
576
+ mockedXHR
577
+ ;
578
+
579
+ mockedXHR = $.Deferred()
580
+ .always(module.event.xhr.complete)
581
+ .done(module.event.xhr.done)
582
+ .fail(module.event.xhr.fail)
583
+ ;
584
+
585
+ if(settings.mockResponse) {
586
+ if( $.isFunction(settings.mockResponse) ) {
587
+ module.debug('Using mocked callback returning response', settings.mockResponse);
588
+ response = settings.mockResponse.call(context, settings);
589
+ }
590
+ else {
591
+ module.debug('Using specified response', settings.mockResponse);
592
+ response = settings.mockResponse;
593
+ }
594
+ // simulating response
595
+ mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
596
+ }
597
+ else if( $.isFunction(settings.mockResponseAsync) ) {
598
+ asyncCallback = function(response) {
599
+ module.debug('Async callback returned response', response);
600
+
601
+ if(response) {
602
+ mockedXHR.resolveWith(context, [ response, textStatus, { responseText: response }]);
603
+ }
604
+ else {
605
+ mockedXHR.rejectWith(context, [{ responseText: response }, status, httpMessage]);
606
+ }
607
+ };
608
+ module.debug('Using async mocked response', settings.mockResponseAsync);
609
+ settings.mockResponseAsync.call(context, settings, asyncCallback);
610
+ }
611
+ return mockedXHR;
612
+ },
613
+
444
614
  xhr: function() {
445
- return $.ajax(ajaxSettings)
615
+ var
616
+ xhr
617
+ ;
618
+ // ajax request promise
619
+ xhr = $.ajax(ajaxSettings)
446
620
  .always(module.event.xhr.always)
447
621
  .done(module.event.xhr.done)
448
622
  .fail(module.event.xhr.fail)
449
623
  ;
624
+ module.verbose('Created server request', xhr);
625
+ return xhr;
450
626
  }
451
627
  },
452
628
 
@@ -458,6 +634,7 @@ $.api = $.fn.api = function(parameters) {
458
634
  loading: function() {
459
635
  module.verbose('Adding loading state to element', $context);
460
636
  $context.addClass(className.loading);
637
+ requestStartTime = new Date().getTime();
461
638
  }
462
639
  },
463
640
 
@@ -483,7 +660,7 @@ $.api = $.fn.api = function(parameters) {
483
660
  var
484
661
  runSettings
485
662
  ;
486
- runSettings = settings.beforeSend.call($module, settings);
663
+ runSettings = settings.beforeSend.call(context, settings);
487
664
  if(runSettings) {
488
665
  if(runSettings.success !== undefined) {
489
666
  module.debug('Legacy success callback detected', runSettings);
@@ -551,34 +728,24 @@ $.api = $.fn.api = function(parameters) {
551
728
  return settings.on;
552
729
  }
553
730
  },
554
- formData: function() {
555
- var
556
- formData
557
- ;
558
- if($module.serializeObject !== undefined) {
559
- formData = $form.serializeObject();
560
- }
561
- else {
562
- module.error(error.missingSerialize);
563
- formData = $form.serialize();
564
- }
565
- module.debug('Retrieved form data', formData);
566
- return formData;
567
- },
568
- templateURL: function(action) {
569
- var
570
- url
571
- ;
731
+ templatedURL: function(action) {
572
732
  action = action || $module.data(metadata.action) || settings.action || false;
733
+ url = $module.data(metadata.url) || settings.url || false;
734
+ if(url) {
735
+ module.debug('Using specified url', url);
736
+ return url;
737
+ }
573
738
  if(action) {
574
739
  module.debug('Looking up url for action', action, settings.api);
575
- if(settings.api[action] !== undefined) {
576
- url = settings.api[action];
577
- module.debug('Found template url', url);
578
- }
579
- else if( !module.is.form() ) {
740
+ if(settings.api[action] === undefined && !module.is.mocked()) {
580
741
  module.error(error.missingAction, settings.action, settings.api);
742
+ return;
581
743
  }
744
+ url = settings.api[action];
745
+ }
746
+ else if( module.is.form() ) {
747
+ url = $module.attr('action') || false;
748
+ module.debug('No url or action specified, defaulting to form action', url);
582
749
  }
583
750
  return url;
584
751
  }
@@ -591,7 +758,6 @@ $.api = $.fn.api = function(parameters) {
591
758
  if( xhr && xhr.state() !== 'resolved') {
592
759
  module.debug('Cancelling API request');
593
760
  xhr.abort();
594
- module.request.rejectWith(settings.apiSettings);
595
761
  }
596
762
  },
597
763
 
@@ -670,7 +836,7 @@ $.api = $.fn.api = function(parameters) {
670
836
  });
671
837
  }
672
838
  clearTimeout(module.performance.timer);
673
- module.performance.timer = setTimeout(module.performance.display, 100);
839
+ module.performance.timer = setTimeout(module.performance.display, 500);
674
840
  },
675
841
  display: function() {
676
842
  var
@@ -780,49 +946,88 @@ $.api = $.fn.api = function(parameters) {
780
946
 
781
947
  $.api.settings = {
782
948
 
783
- name : 'API',
784
- namespace : 'api',
949
+ name : 'API',
950
+ namespace : 'api',
951
+
952
+ debug : true,
953
+ verbose : false,
954
+ performance : true,
955
+
956
+ // object containing all templates endpoints
957
+ api : {},
785
958
 
786
- debug : true,
787
- verbose : false,
788
- performance : true,
959
+ // whether to cache responses
960
+ cache : true,
961
+
962
+ // whether new requests should abort previous requests
963
+ interruptRequests : true,
789
964
 
790
965
  // event binding
791
- on : 'auto',
792
- filter : '.disabled',
793
- stateContext : false,
966
+ on : 'auto',
967
+
968
+ // context for applying state classes
969
+ stateContext : false,
970
+
971
+ // duration for loading state
972
+ loadingDuration : 0,
973
+
974
+ // duration for error state
975
+ errorDuration : 2000,
976
+
977
+ // API action to use
978
+ action : false,
979
+
980
+ // templated URL to use
981
+ url : false,
794
982
 
795
- // state
796
- loadingDuration : 0,
797
- errorDuration : 2000,
983
+ // base URL to apply to all endpoints
984
+ base : '',
798
985
 
799
- // templating
800
- action : false,
801
- url : false,
802
- base : '',
986
+ // data that will
987
+ urlData : {},
803
988
 
804
- // data
805
- urlData : {},
989
+ // whether to add default data to url data
990
+ defaultData : true,
806
991
 
807
- // ui
808
- defaultData : true,
809
- serializeForm : false,
810
- throttle : 0,
992
+ // whether to serialize closest form
993
+ serializeForm : false,
811
994
 
812
- // jQ ajax
813
- method : 'get',
814
- data : {},
815
- dataType : 'json',
995
+ // how long to wait before request should occur
996
+ throttle : 0,
816
997
 
817
- // callbacks
998
+ // whether to throttle first request or only repeated
999
+ throttleFirstRequest : true,
1000
+
1001
+ // standard ajax settings
1002
+ method : 'get',
1003
+ data : {},
1004
+ dataType : 'json',
1005
+
1006
+ // mock response
1007
+ mockResponse : false,
1008
+ mockResponseAsync : false,
1009
+
1010
+ // callbacks before request
818
1011
  beforeSend : function(settings) { return settings; },
819
1012
  beforeXHR : function(xhr) {},
820
-
821
1013
  onRequest : function(promise, xhr) {},
1014
+
1015
+ // after request
1016
+ onResponse : false, // function(response) { },
1017
+
1018
+ // response was successful, if JSON passed validation
822
1019
  onSuccess : function(response, $module) {},
1020
+
1021
+ // request finished without aborting
823
1022
  onComplete : function(response, $module) {},
824
- onFailure : function(errorMessage, $module) {},
1023
+
1024
+ // failed JSON success test
1025
+ onFailure : function(response, $module) {},
1026
+
1027
+ // server error
825
1028
  onError : function(errorMessage, $module) {},
1029
+
1030
+ // request aborted
826
1031
  onAbort : function(errorMessage, $module) {},
827
1032
 
828
1033
  successTest : false,
@@ -836,9 +1041,10 @@ $.api.settings = {
836
1041
  legacyParameters : 'You are using legacy API success callback names',
837
1042
  method : 'The method you called is not defined',
838
1043
  missingAction : 'API action used but no url was defined',
839
- missingSerialize : 'Required dependency jquery-serialize-object missing, using basic serialize',
1044
+ missingSerialize : 'jquery-serialize-object is required to add form data to an existing data object',
840
1045
  missingURL : 'No URL specified for api event',
841
1046
  noReturnedValue : 'The beforeSend callback must return a settings object, beforeSend ignored.',
1047
+ noStorage : 'Caching respopnses locally requires session storage',
842
1048
  parseError : 'There was an error parsing your request',
843
1049
  requiredParameter : 'Missing a required URL parameter: ',
844
1050
  statusMessage : 'Server gave an error: ',
@@ -846,8 +1052,8 @@ $.api.settings = {
846
1052
  },
847
1053
 
848
1054
  regExp : {
849
- required: /\{\$*[A-z0-9]+\}/g,
850
- optional: /\{\/\$*[A-z0-9]+\}/g,
1055
+ required : /\{\$*[A-z0-9]+\}/g,
1056
+ optional : /\{\/\$*[A-z0-9]+\}/g,
851
1057
  },
852
1058
 
853
1059
  className: {
@@ -856,16 +1062,16 @@ $.api.settings = {
856
1062
  },
857
1063
 
858
1064
  selector: {
859
- form: 'form'
1065
+ disabled : '.disabled',
1066
+ form : 'form'
860
1067
  },
861
1068
 
862
1069
  metadata: {
863
- action : 'action'
1070
+ action : 'action',
1071
+ url : 'url'
864
1072
  }
865
1073
  };
866
1074
 
867
1075
 
868
- $.api.settings.api = {};
869
-
870
1076
 
871
- })( jQuery, window , document );
1077
+ })( jQuery, window , document );