semantic-ui-sass 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +51 -0
  6. data/Rakefile +5 -0
  7. data/app/assets/fonts/semantic-ui/basic.icons.eot +0 -0
  8. data/app/assets/fonts/semantic-ui/basic.icons.svg +450 -0
  9. data/app/assets/fonts/semantic-ui/basic.icons.ttf +0 -0
  10. data/app/assets/fonts/semantic-ui/basic.icons.woff +0 -0
  11. data/app/assets/fonts/semantic-ui/icons.eot +0 -0
  12. data/app/assets/fonts/semantic-ui/icons.otf +0 -0
  13. data/app/assets/fonts/semantic-ui/icons.svg +399 -0
  14. data/app/assets/fonts/semantic-ui/icons.ttf +0 -0
  15. data/app/assets/fonts/semantic-ui/icons.woff +0 -0
  16. data/app/assets/images/semantic-ui/loader-large-inverted.gif +0 -0
  17. data/app/assets/images/semantic-ui/loader-large.gif +0 -0
  18. data/app/assets/images/semantic-ui/loader-medium-inverted.gif +0 -0
  19. data/app/assets/images/semantic-ui/loader-medium.gif +0 -0
  20. data/app/assets/images/semantic-ui/loader-mini-inverted.gif +0 -0
  21. data/app/assets/images/semantic-ui/loader-mini.gif +0 -0
  22. data/app/assets/images/semantic-ui/loader-small-inverted.gif +0 -0
  23. data/app/assets/images/semantic-ui/loader-small.gif +0 -0
  24. data/app/assets/javascripts/semantic-ui.js +20 -0
  25. data/app/assets/javascripts/semantic-ui/accordion.js +419 -0
  26. data/app/assets/javascripts/semantic-ui/behavior/api.js +638 -0
  27. data/app/assets/javascripts/semantic-ui/behavior/colorize.js +270 -0
  28. data/app/assets/javascripts/semantic-ui/behavior/form.js +702 -0
  29. data/app/assets/javascripts/semantic-ui/behavior/state.js +725 -0
  30. data/app/assets/javascripts/semantic-ui/chatroom.js +769 -0
  31. data/app/assets/javascripts/semantic-ui/checkbox.js +344 -0
  32. data/app/assets/javascripts/semantic-ui/dimmer.js +564 -0
  33. data/app/assets/javascripts/semantic-ui/dropdown.js +724 -0
  34. data/app/assets/javascripts/semantic-ui/modal.js +553 -0
  35. data/app/assets/javascripts/semantic-ui/nag.js +545 -0
  36. data/app/assets/javascripts/semantic-ui/popup.js +727 -0
  37. data/app/assets/javascripts/semantic-ui/rating.js +403 -0
  38. data/app/assets/javascripts/semantic-ui/search.js +772 -0
  39. data/app/assets/javascripts/semantic-ui/shape.js +778 -0
  40. data/app/assets/javascripts/semantic-ui/sidebar.js +490 -0
  41. data/app/assets/javascripts/semantic-ui/tab.js +689 -0
  42. data/app/assets/javascripts/semantic-ui/transition.js +654 -0
  43. data/app/assets/javascripts/semantic-ui/video.js +457 -0
  44. data/app/assets/stylesheets/semantic-ui.scss +4 -0
  45. data/app/assets/stylesheets/semantic-ui/collections/_all.scss +6 -0
  46. data/app/assets/stylesheets/semantic-ui/collections/_breadcrumb.scss +77 -0
  47. data/app/assets/stylesheets/semantic-ui/collections/_form.scss +569 -0
  48. data/app/assets/stylesheets/semantic-ui/collections/_grid.scss +643 -0
  49. data/app/assets/stylesheets/semantic-ui/collections/_menu.scss +1767 -0
  50. data/app/assets/stylesheets/semantic-ui/collections/_message.scss +347 -0
  51. data/app/assets/stylesheets/semantic-ui/collections/_table.scss +524 -0
  52. data/app/assets/stylesheets/semantic-ui/elements/_all.scss +12 -0
  53. data/app/assets/stylesheets/semantic-ui/elements/_basic.icon.scss +479 -0
  54. data/app/assets/stylesheets/semantic-ui/elements/_button.scss +1187 -0
  55. data/app/assets/stylesheets/semantic-ui/elements/_divider.scss +199 -0
  56. data/app/assets/stylesheets/semantic-ui/elements/_header.scss +342 -0
  57. data/app/assets/stylesheets/semantic-ui/elements/_icon.scss +772 -0
  58. data/app/assets/stylesheets/semantic-ui/elements/_image.scss +181 -0
  59. data/app/assets/stylesheets/semantic-ui/elements/_input.scss +338 -0
  60. data/app/assets/stylesheets/semantic-ui/elements/_label.scss +827 -0
  61. data/app/assets/stylesheets/semantic-ui/elements/_loader.scss +185 -0
  62. data/app/assets/stylesheets/semantic-ui/elements/_progress.scss +352 -0
  63. data/app/assets/stylesheets/semantic-ui/elements/_segment.scss +464 -0
  64. data/app/assets/stylesheets/semantic-ui/elements/_step.scss +293 -0
  65. data/app/assets/stylesheets/semantic-ui/modules/_accordion.scss +199 -0
  66. data/app/assets/stylesheets/semantic-ui/modules/_all.scss +16 -0
  67. data/app/assets/stylesheets/semantic-ui/modules/_chatroom.scss +281 -0
  68. data/app/assets/stylesheets/semantic-ui/modules/_checkbox.scss +481 -0
  69. data/app/assets/stylesheets/semantic-ui/modules/_dimmer.scss +236 -0
  70. data/app/assets/stylesheets/semantic-ui/modules/_dropdown.scss +548 -0
  71. data/app/assets/stylesheets/semantic-ui/modules/_modal.scss +217 -0
  72. data/app/assets/stylesheets/semantic-ui/modules/_nag.scss +173 -0
  73. data/app/assets/stylesheets/semantic-ui/modules/_popup.scss +255 -0
  74. data/app/assets/stylesheets/semantic-ui/modules/_rating.scss +179 -0
  75. data/app/assets/stylesheets/semantic-ui/modules/_reveal.scss +365 -0
  76. data/app/assets/stylesheets/semantic-ui/modules/_search.scss +273 -0
  77. data/app/assets/stylesheets/semantic-ui/modules/_shape.scss +113 -0
  78. data/app/assets/stylesheets/semantic-ui/modules/_sidebar.scss +150 -0
  79. data/app/assets/stylesheets/semantic-ui/modules/_tab.scss +63 -0
  80. data/app/assets/stylesheets/semantic-ui/modules/_transition.scss +1096 -0
  81. data/app/assets/stylesheets/semantic-ui/modules/_video.scss +98 -0
  82. data/app/assets/stylesheets/semantic-ui/views/_all.scss +5 -0
  83. data/app/assets/stylesheets/semantic-ui/views/_comment.scss +221 -0
  84. data/app/assets/stylesheets/semantic-ui/views/_feed.scss +152 -0
  85. data/app/assets/stylesheets/semantic-ui/views/_item.scss +651 -0
  86. data/app/assets/stylesheets/semantic-ui/views/_list.scss +555 -0
  87. data/app/assets/stylesheets/semantic-ui/views/_statistic.scss +27 -0
  88. data/lib/semantic/ui/sass.rb +10 -0
  89. data/lib/semantic/ui/sass/engine.rb +13 -0
  90. data/lib/semantic/ui/sass/version.rb +8 -0
  91. data/semantic-ui-sass.gemspec +24 -0
  92. data/tasks/converter.rb +237 -0
  93. metadata +177 -0
@@ -0,0 +1,419 @@
1
+ /*
2
+ * # Semantic - Accordion
3
+ * http://github.com/jlukic/semantic-ui/
4
+ *
5
+ *
6
+ * Copyright 2013 Contributors
7
+ * Released under the MIT license
8
+ * http://opensource.org/licenses/MIT
9
+ *
10
+ */
11
+
12
+ ;(function ($, window, document, undefined) {
13
+
14
+ $.fn.accordion = function(parameters) {
15
+ var
16
+ $allModules = $(this),
17
+
18
+ settings = ( $.isPlainObject(parameters) )
19
+ ? $.extend(true, {}, $.fn.accordion.settings, parameters)
20
+ : $.fn.accordion.settings,
21
+
22
+ className = settings.className,
23
+ namespace = settings.namespace,
24
+ selector = settings.selector,
25
+ error = settings.error,
26
+
27
+ eventNamespace = '.' + namespace,
28
+ moduleNamespace = 'module-' + namespace,
29
+ moduleSelector = $allModules.selector || '',
30
+
31
+ time = new Date().getTime(),
32
+ performance = [],
33
+
34
+ query = arguments[0],
35
+ methodInvoked = (typeof query == 'string'),
36
+ queryArguments = [].slice.call(arguments, 1),
37
+ invokedResponse
38
+ ;
39
+ $allModules
40
+ .each(function() {
41
+ var
42
+ $module = $(this),
43
+ $title = $module.find(selector.title),
44
+ $content = $module.find(selector.content),
45
+
46
+ element = this,
47
+ instance = $module.data(moduleNamespace),
48
+ module
49
+ ;
50
+
51
+ module = {
52
+
53
+ initialize: function() {
54
+ module.debug('Initializing accordion with bound events', $module);
55
+ // initializing
56
+ $title
57
+ .on('click' + eventNamespace, module.event.click)
58
+ ;
59
+ module.instantiate();
60
+ },
61
+
62
+ instantiate: function() {
63
+ $module
64
+ .data(moduleNamespace, module)
65
+ ;
66
+ },
67
+
68
+ destroy: function() {
69
+ module.debug('Destroying previous accordion for', $module);
70
+ $module
71
+ .removeData(moduleNamespace)
72
+ ;
73
+ $title
74
+ .off(eventNamespace)
75
+ ;
76
+ },
77
+
78
+ event: {
79
+ click: function() {
80
+ module.verbose('Title clicked', this);
81
+ var
82
+ $activeTitle = $(this),
83
+ index = $title.index($activeTitle)
84
+ ;
85
+ module.toggle(index);
86
+ },
87
+ resetStyle: function() {
88
+ module.verbose('Resetting styles on element', this);
89
+ $(this)
90
+ .attr('style', '')
91
+ .removeAttr('style')
92
+ .children()
93
+ .attr('style', '')
94
+ .removeAttr('style')
95
+ ;
96
+ }
97
+ },
98
+
99
+ toggle: function(index) {
100
+ module.debug('Toggling content content at index', index);
101
+ var
102
+ $activeTitle = $title.eq(index),
103
+ $activeContent = $activeTitle.next($content),
104
+ contentIsOpen = $activeContent.is(':visible')
105
+ ;
106
+ if(contentIsOpen) {
107
+ if(settings.collapsible) {
108
+ module.close(index);
109
+ }
110
+ else {
111
+ module.debug('Cannot close accordion content collapsing is disabled');
112
+ }
113
+ }
114
+ else {
115
+ module.open(index);
116
+ }
117
+ },
118
+
119
+ open: function(index) {
120
+ var
121
+ $activeTitle = $title.eq(index),
122
+ $activeContent = $activeTitle.next($content),
123
+ $previousTitle = $title.filter('.' + className.active),
124
+ $previousContent = $previousTitle.next($title),
125
+ contentIsOpen = ($previousTitle.size() > 0)
126
+ ;
127
+ if( !$activeContent.is(':animated') ) {
128
+ module.debug('Opening accordion content', $activeTitle);
129
+ if(settings.exclusive && contentIsOpen) {
130
+ $previousTitle
131
+ .removeClass(className.active)
132
+ ;
133
+ $previousContent
134
+ .stop()
135
+ .children()
136
+ .animate({
137
+ opacity: 0
138
+ }, settings.duration, module.event.resetStyle)
139
+ .end()
140
+ .slideUp(settings.duration , settings.easing, function() {
141
+ $previousContent
142
+ .removeClass(className.active)
143
+ .attr('style', '')
144
+ .removeAttr('style')
145
+ .children()
146
+ .attr('style', '')
147
+ .removeAttr('style')
148
+ ;
149
+ })
150
+ ;
151
+ }
152
+ $activeTitle
153
+ .addClass(className.active)
154
+ ;
155
+ $activeContent
156
+ .stop()
157
+ .children()
158
+ .attr('style', '')
159
+ .removeAttr('style')
160
+ .end()
161
+ .slideDown(settings.duration, settings.easing, function() {
162
+ $activeContent
163
+ .addClass(className.active)
164
+ .attr('style', '')
165
+ .removeAttr('style')
166
+ ;
167
+ $.proxy(settings.onOpen, $activeContent)();
168
+ $.proxy(settings.onChange, $activeContent)();
169
+ })
170
+ ;
171
+ }
172
+ },
173
+
174
+ close: function(index) {
175
+ var
176
+ $activeTitle = $title.eq(index),
177
+ $activeContent = $activeTitle.next($content)
178
+ ;
179
+ module.debug('Closing accordion content', $activeTitle);
180
+ $activeTitle
181
+ .removeClass(className.active)
182
+ ;
183
+ $activeContent
184
+ .removeClass(className.active)
185
+ .show()
186
+ .stop()
187
+ .children()
188
+ .animate({
189
+ opacity: 0
190
+ }, settings.duration, module.event.resetStyle)
191
+ .end()
192
+ .slideUp(settings.duration, settings.easing, function(){
193
+ $activeContent
194
+ .attr('style', '')
195
+ .removeAttr('style')
196
+ ;
197
+ $.proxy(settings.onClose, $activeContent)();
198
+ $.proxy(settings.onChange, $activeContent)();
199
+ })
200
+ ;
201
+ },
202
+
203
+ setting: function(name, value) {
204
+ module.debug('Changing setting', name, value);
205
+ if(value !== undefined) {
206
+ if( $.isPlainObject(name) ) {
207
+ $.extend(true, settings, name);
208
+ }
209
+ else {
210
+ settings[name] = value;
211
+ }
212
+ }
213
+ else {
214
+ return settings[name];
215
+ }
216
+ },
217
+ internal: function(name, value) {
218
+ module.debug('Changing internal', name, value);
219
+ if(value !== undefined) {
220
+ if( $.isPlainObject(name) ) {
221
+ $.extend(true, module, name);
222
+ }
223
+ else {
224
+ module[name] = value;
225
+ }
226
+ }
227
+ else {
228
+ return module[name];
229
+ }
230
+ },
231
+ debug: function() {
232
+ if(settings.debug) {
233
+ if(settings.performance) {
234
+ module.performance.log(arguments);
235
+ }
236
+ else {
237
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
238
+ module.debug.apply(console, arguments);
239
+ }
240
+ }
241
+ },
242
+ verbose: function() {
243
+ if(settings.verbose && settings.debug) {
244
+ if(settings.performance) {
245
+ module.performance.log(arguments);
246
+ }
247
+ else {
248
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
249
+ module.verbose.apply(console, arguments);
250
+ }
251
+ }
252
+ },
253
+ error: function() {
254
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
255
+ module.error.apply(console, arguments);
256
+ },
257
+ performance: {
258
+ log: function(message) {
259
+ var
260
+ currentTime,
261
+ executionTime,
262
+ previousTime
263
+ ;
264
+ if(settings.performance) {
265
+ currentTime = new Date().getTime();
266
+ previousTime = time || currentTime;
267
+ executionTime = currentTime - previousTime;
268
+ time = currentTime;
269
+ performance.push({
270
+ 'Element' : element,
271
+ 'Name' : message[0],
272
+ 'Arguments' : [].slice.call(message, 1) || '',
273
+ 'Execution Time' : executionTime
274
+ });
275
+ }
276
+ clearTimeout(module.performance.timer);
277
+ module.performance.timer = setTimeout(module.performance.display, 100);
278
+ },
279
+ display: function() {
280
+ var
281
+ title = settings.name + ':',
282
+ totalTime = 0
283
+ ;
284
+ time = false;
285
+ clearTimeout(module.performance.timer);
286
+ $.each(performance, function(index, data) {
287
+ totalTime += data['Execution Time'];
288
+ });
289
+ title += ' ' + totalTime + 'ms';
290
+ if(moduleSelector) {
291
+ title += ' \'' + moduleSelector + '\'';
292
+ }
293
+ if($allModules.size() > 1) {
294
+ title += ' ' + '(' + $allModules.size() + ')';
295
+ }
296
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
297
+ console.groupCollapsed(title);
298
+ if(console.table) {
299
+ console.table(performance);
300
+ }
301
+ else {
302
+ $.each(performance, function(index, data) {
303
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
304
+ });
305
+ }
306
+ console.groupEnd();
307
+ }
308
+ performance = [];
309
+ }
310
+ },
311
+ invoke: function(query, passedArguments, context) {
312
+ var
313
+ maxDepth,
314
+ found,
315
+ response
316
+ ;
317
+ passedArguments = passedArguments || queryArguments;
318
+ context = element || context;
319
+ if(typeof query == 'string' && instance !== undefined) {
320
+ query = query.split(/[\. ]/);
321
+ maxDepth = query.length - 1;
322
+ $.each(query, function(depth, value) {
323
+ var camelCaseValue = (depth != maxDepth)
324
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
325
+ : query
326
+ ;
327
+ if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
328
+ instance = instance[value];
329
+ }
330
+ else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) {
331
+ instance = instance[camelCaseValue];
332
+ }
333
+ else if( instance[value] !== undefined ) {
334
+ found = instance[value];
335
+ return false;
336
+ }
337
+ else if( instance[camelCaseValue] !== undefined ) {
338
+ found = instance[camelCaseValue];
339
+ return false;
340
+ }
341
+ else {
342
+ module.error(error.method);
343
+ return false;
344
+ }
345
+ });
346
+ }
347
+ if ( $.isFunction( found ) ) {
348
+ response = found.apply(context, passedArguments);
349
+ }
350
+ else if(found !== undefined) {
351
+ response = found;
352
+ }
353
+ if($.isArray(invokedResponse)) {
354
+ invokedResponse.push(response);
355
+ }
356
+ else if(typeof invokedResponse == 'string') {
357
+ invokedResponse = [invokedResponse, response];
358
+ }
359
+ else if(response !== undefined) {
360
+ invokedResponse = response;
361
+ }
362
+ return found;
363
+ }
364
+ };
365
+ if(methodInvoked) {
366
+ if(instance === undefined) {
367
+ module.initialize();
368
+ }
369
+ module.invoke(query);
370
+ }
371
+ else {
372
+ if(instance !== undefined) {
373
+ module.destroy();
374
+ }
375
+ module.initialize();
376
+ }
377
+ })
378
+ ;
379
+ return (invokedResponse !== undefined)
380
+ ? invokedResponse
381
+ : this
382
+ ;
383
+ };
384
+
385
+ $.fn.accordion.settings = {
386
+ name : 'Accordion',
387
+ namespace : 'accordion',
388
+
389
+ debug : true,
390
+ verbose : true,
391
+ performance : true,
392
+
393
+ exclusive : true,
394
+ collapsible : true,
395
+
396
+ duration : 300,
397
+ easing : 'linear',
398
+
399
+ onOpen : function(){},
400
+ onClose : function(){},
401
+ onChange : function(){},
402
+
403
+ error: {
404
+ method : 'The method you called is not defined'
405
+ },
406
+
407
+ className : {
408
+ active : 'active'
409
+ },
410
+
411
+ selector : {
412
+ title : '.title',
413
+ content : '.content'
414
+ },
415
+
416
+
417
+ };
418
+
419
+ })( jQuery, window , document );
@@ -0,0 +1,638 @@
1
+ /*
2
+ * # Semantic - API
3
+ * http://github.com/jlukic/semantic-ui/
4
+ *
5
+ *
6
+ * Copyright 2013 Contributors
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
+ settings = $.extend(true, {}, $.api.settings, parameters),
18
+
19
+ // if this keyword isn't a jQuery object, create one
20
+ context = (typeof this != 'function')
21
+ ? this
22
+ : $('<div/>'),
23
+ // context defines the element used for loading/error state
24
+ $context = (settings.stateContext)
25
+ ? $(settings.stateContext)
26
+ : $(context),
27
+ // module is the thing that initiates the api action, can be independent of context
28
+ $module = typeof this == 'object'
29
+ ? $(context)
30
+ : $context,
31
+
32
+ element = this,
33
+ time = new Date().getTime(),
34
+ performance = [],
35
+
36
+ moduleSelector = $module.selector || '',
37
+ moduleNamespace = settings.namespace + '-module',
38
+
39
+ className = settings.className,
40
+ metadata = settings.metadata,
41
+ error = settings.error,
42
+
43
+ instance = $module.data(moduleNamespace),
44
+
45
+ query = arguments[0],
46
+ methodInvoked = (instance !== undefined && typeof query == 'string'),
47
+ queryArguments = [].slice.call(arguments, 1),
48
+
49
+ module,
50
+ invokedResponse
51
+ ;
52
+
53
+ module = {
54
+ initialize: function() {
55
+ var
56
+ runSettings,
57
+
58
+ loadingTimer = new Date().getTime(),
59
+ loadingDelay,
60
+
61
+ promise,
62
+ url,
63
+
64
+ formData = {},
65
+ data,
66
+
67
+ ajaxSettings = {},
68
+ xhr
69
+ ;
70
+
71
+ // serialize parent form if requested!
72
+ if(settings.serializeForm && $(this).toJSON() !== undefined) {
73
+ formData = module.get.formData();
74
+ module.debug('Adding form data to API Request', formData);
75
+ $.extend(true, settings.data, formData);
76
+ }
77
+
78
+ // let beforeSend change settings object
79
+ runSettings = $.proxy(settings.beforeSend, $module)(settings);
80
+
81
+ // check for exit conditions
82
+ if(runSettings !== undefined && !runSettings) {
83
+ module.error(error.beforeSend);
84
+ module.reset();
85
+ return;
86
+ }
87
+
88
+ // get real url from template
89
+ url = module.get.url( module.get.templateURL() );
90
+
91
+ // exit conditions reached from missing url parameters
92
+ if( !url ) {
93
+ module.error(error.missingURL);
94
+ module.reset();
95
+ return;
96
+ }
97
+
98
+ // promise handles notification on api request, so loading min. delay can occur for all notifications
99
+ promise =
100
+ $.Deferred()
101
+ .always(function() {
102
+ if(settings.stateContext) {
103
+ $context
104
+ .removeClass(className.loading)
105
+ ;
106
+ }
107
+ $.proxy(settings.complete, $module)();
108
+ })
109
+ .done(function(response) {
110
+ module.debug('API request successful');
111
+ // take a stab at finding success state if json
112
+ if(settings.dataType == 'json') {
113
+ if (response.error !== undefined) {
114
+ $.proxy(settings.failure, $context)(response.error, settings, $module);
115
+ }
116
+ else if ($.isArray(response.errors)) {
117
+ $.proxy(settings.failure, $context)(response.errors[0], settings, $module);
118
+ }
119
+ else {
120
+ $.proxy(settings.success, $context)(response, settings, $module);
121
+ }
122
+ }
123
+ // otherwise
124
+ else {
125
+ $.proxy(settings.success, $context)(response, settings, $module);
126
+ }
127
+ })
128
+ .fail(function(xhr, status, httpMessage) {
129
+ var
130
+ errorMessage = (settings.error[status] !== undefined)
131
+ ? settings.error[status]
132
+ : httpMessage,
133
+ response
134
+ ;
135
+ // let em know unless request aborted
136
+ if(xhr !== undefined) {
137
+ // readyState 4 = done, anything less is not really sent
138
+ if(xhr.readyState !== undefined && xhr.readyState == 4) {
139
+
140
+ // if http status code returned and json returned error, look for it
141
+ if( xhr.status != 200 && httpMessage !== undefined && httpMessage !== '') {
142
+ module.error(error.statusMessage + httpMessage);
143
+ }
144
+ else {
145
+ if(status == 'error' && settings.dataType == 'json') {
146
+ try {
147
+ response = $.parseJSON(xhr.responseText);
148
+ if(response && response.error !== undefined) {
149
+ errorMessage = response.error;
150
+ }
151
+ }
152
+ catch(error) {
153
+ module.error(error.JSONParse);
154
+ }
155
+ }
156
+ }
157
+ $context
158
+ .removeClass(className.loading)
159
+ .addClass(className.error)
160
+ ;
161
+ // show error state only for duration specified in settings
162
+ if(settings.errorLength > 0) {
163
+ setTimeout(function(){
164
+ $context
165
+ .removeClass(className.error)
166
+ ;
167
+ }, settings.errorLength);
168
+ }
169
+ module.debug('API Request error:', errorMessage);
170
+ $.proxy(settings.failure, $context)(errorMessage, settings, this);
171
+ }
172
+ else {
173
+ module.debug('Request Aborted (Most likely caused by page change)');
174
+ }
175
+ }
176
+ })
177
+ ;
178
+
179
+ // look for params in data
180
+ $.extend(true, ajaxSettings, settings, {
181
+ success : function(){},
182
+ failure : function(){},
183
+ complete : function(){},
184
+ type : settings.method || settings.type,
185
+ data : data,
186
+ url : url,
187
+ beforeSend : settings.beforeXHR
188
+ });
189
+
190
+ if(settings.stateContext) {
191
+ $context
192
+ .addClass(className.loading)
193
+ ;
194
+ }
195
+
196
+ if(settings.progress) {
197
+ module.verbose('Adding progress events');
198
+ $.extend(true, ajaxSettings, {
199
+ xhr: function() {
200
+ var
201
+ xhr = new window.XMLHttpRequest()
202
+ ;
203
+ xhr.upload.addEventListener('progress', function(event) {
204
+ var
205
+ percentComplete
206
+ ;
207
+ if (event.lengthComputable) {
208
+ percentComplete = Math.round(event.loaded / event.total * 10000) / 100 + '%';
209
+ $.proxy(settings.progress, $context)(percentComplete, event);
210
+ }
211
+ }, false);
212
+ xhr.addEventListener('progress', function(event) {
213
+ var
214
+ percentComplete
215
+ ;
216
+ if (event.lengthComputable) {
217
+ percentComplete = Math.round(event.loaded / event.total * 10000) / 100 + '%';
218
+ $.proxy(settings.progress, $context)(percentComplete, event);
219
+ }
220
+ }, false);
221
+ return xhr;
222
+ }
223
+ });
224
+ }
225
+
226
+ module.verbose('Creating AJAX request with settings: ', ajaxSettings);
227
+ xhr =
228
+ $.ajax(ajaxSettings)
229
+ .always(function() {
230
+ // calculate if loading time was below minimum threshold
231
+ loadingDelay = ( settings.loadingLength - (new Date().getTime() - loadingTimer) );
232
+ settings.loadingDelay = loadingDelay < 0
233
+ ? 0
234
+ : loadingDelay
235
+ ;
236
+ })
237
+ .done(function(response) {
238
+ var
239
+ context = this
240
+ ;
241
+ setTimeout(function(){
242
+ promise.resolveWith(context, [response]);
243
+ }, settings.loadingDelay);
244
+ })
245
+ .fail(function(xhr, status, httpMessage) {
246
+ var
247
+ context = this
248
+ ;
249
+ // page triggers abort on navigation, dont show error
250
+ if(status != 'abort') {
251
+ setTimeout(function(){
252
+ promise.rejectWith(context, [xhr, status, httpMessage]);
253
+ }, settings.loadingDelay);
254
+ }
255
+ else {
256
+ $context
257
+ .removeClass(className.error)
258
+ .removeClass(className.loading)
259
+ ;
260
+ }
261
+ })
262
+ ;
263
+ if(settings.stateContext) {
264
+ $module
265
+ .data(metadata.promise, promise)
266
+ .data(metadata.xhr, xhr)
267
+ ;
268
+ }
269
+ },
270
+
271
+ get: {
272
+ formData: function() {
273
+ return $module
274
+ .closest('form')
275
+ .toJSON()
276
+ ;
277
+ },
278
+ templateURL: function() {
279
+ var
280
+ action = $module.data(settings.metadata.action) || settings.action || false,
281
+ url
282
+ ;
283
+ if(action) {
284
+ module.debug('Creating url for: ', action);
285
+ if(settings.api[action] !== undefined) {
286
+ url = settings.api[action];
287
+ }
288
+ else {
289
+ module.error(error.missingAction);
290
+ }
291
+ }
292
+ // override with url if specified
293
+ if(settings.url) {
294
+ url = settings.url;
295
+ module.debug('Getting url', url);
296
+ }
297
+ return url;
298
+ },
299
+ url: function(url, urlData) {
300
+ var
301
+ urlVariables
302
+ ;
303
+ if(url) {
304
+ urlVariables = url.match(settings.regExpTemplate);
305
+ urlData = urlData || settings.urlData;
306
+
307
+ if(urlVariables) {
308
+ module.debug('Looking for URL variables', urlVariables);
309
+ $.each(urlVariables, function(index, templateValue){
310
+ var
311
+ term = templateValue.substr( 2, templateValue.length - 3),
312
+ termValue = ($.isPlainObject(urlData) && urlData[term] !== undefined)
313
+ ? urlData[term]
314
+ : ($module.data(term) !== undefined)
315
+ ? $module.data(term)
316
+ : urlData[term]
317
+ ;
318
+ module.verbose('Looking for variable', term, $module, $module.data(term), urlData[term]);
319
+ // remove optional value
320
+ if(termValue === false) {
321
+ module.debug('Removing variable from URL', urlVariables);
322
+ url = url.replace('/' + templateValue, '');
323
+ }
324
+ // undefined condition
325
+ else if(termValue === undefined || !termValue) {
326
+ module.error(error.missingParameter + term);
327
+ url = false;
328
+ return false;
329
+ }
330
+ else {
331
+ url = url.replace(templateValue, termValue);
332
+ }
333
+ });
334
+ }
335
+ }
336
+ return url;
337
+ }
338
+ },
339
+
340
+ // reset api request
341
+ reset: function() {
342
+ $module
343
+ .data(metadata.promise, false)
344
+ .data(metadata.xhr, false)
345
+ ;
346
+ $context
347
+ .removeClass(className.error)
348
+ .removeClass(className.loading)
349
+ ;
350
+ },
351
+
352
+ setting: function(name, value) {
353
+ if(value !== undefined) {
354
+ if( $.isPlainObject(name) ) {
355
+ $.extend(true, settings, name);
356
+ }
357
+ else {
358
+ settings[name] = value;
359
+ }
360
+ }
361
+ else {
362
+ return settings[name];
363
+ }
364
+ },
365
+ internal: function(name, value) {
366
+ if(value !== undefined) {
367
+ if( $.isPlainObject(name) ) {
368
+ $.extend(true, module, name);
369
+ }
370
+ else {
371
+ module[name] = value;
372
+ }
373
+ }
374
+ else {
375
+ return module[name];
376
+ }
377
+ },
378
+ debug: function() {
379
+ if(settings.debug) {
380
+ if(settings.performance) {
381
+ module.performance.log(arguments);
382
+ }
383
+ else {
384
+ module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
385
+ module.debug.apply(console, arguments);
386
+ }
387
+ }
388
+ },
389
+ verbose: function() {
390
+ if(settings.verbose && settings.debug) {
391
+ if(settings.performance) {
392
+ module.performance.log(arguments);
393
+ }
394
+ else {
395
+ module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
396
+ module.verbose.apply(console, arguments);
397
+ }
398
+ }
399
+ },
400
+ error: function() {
401
+ module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
402
+ module.error.apply(console, arguments);
403
+ },
404
+ performance: {
405
+ log: function(message) {
406
+ var
407
+ currentTime,
408
+ executionTime,
409
+ previousTime
410
+ ;
411
+ if(settings.performance) {
412
+ currentTime = new Date().getTime();
413
+ previousTime = time || currentTime;
414
+ executionTime = currentTime - previousTime;
415
+ time = currentTime;
416
+ performance.push({
417
+ 'Element' : element,
418
+ 'Name' : message[0],
419
+ 'Arguments' : [].slice.call(message, 1) || '',
420
+ 'Execution Time' : executionTime
421
+ });
422
+ }
423
+ clearTimeout(module.performance.timer);
424
+ module.performance.timer = setTimeout(module.performance.display, 100);
425
+ },
426
+ display: function() {
427
+ var
428
+ title = settings.name + ':',
429
+ totalTime = 0
430
+ ;
431
+ time = false;
432
+ clearTimeout(module.performance.timer);
433
+ $.each(performance, function(index, data) {
434
+ totalTime += data['Execution Time'];
435
+ });
436
+ title += ' ' + totalTime + 'ms';
437
+ if(moduleSelector) {
438
+ title += ' \'' + moduleSelector + '\'';
439
+ }
440
+ if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
441
+ console.groupCollapsed(title);
442
+ if(console.table) {
443
+ console.table(performance);
444
+ }
445
+ else {
446
+ $.each(performance, function(index, data) {
447
+ console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
448
+ });
449
+ }
450
+ console.groupEnd();
451
+ }
452
+ performance = [];
453
+ }
454
+ },
455
+ invoke: function(query, passedArguments, context) {
456
+ var
457
+ maxDepth,
458
+ found,
459
+ response
460
+ ;
461
+ passedArguments = passedArguments || queryArguments;
462
+ context = element || context;
463
+ if(typeof query == 'string' && instance !== undefined) {
464
+ query = query.split(/[\. ]/);
465
+ maxDepth = query.length - 1;
466
+ $.each(query, function(depth, value) {
467
+ var camelCaseValue = (depth != maxDepth)
468
+ ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
469
+ : query
470
+ ;
471
+ if( $.isPlainObject( instance[value] ) && (depth != maxDepth) ) {
472
+ instance = instance[value];
473
+ }
474
+ else if( $.isPlainObject( instance[camelCaseValue] ) && (depth != maxDepth) ) {
475
+ instance = instance[camelCaseValue];
476
+ }
477
+ else if( instance[value] !== undefined ) {
478
+ found = instance[value];
479
+ return false;
480
+ }
481
+ else if( instance[camelCaseValue] !== undefined ) {
482
+ found = instance[camelCaseValue];
483
+ return false;
484
+ }
485
+ else {
486
+ module.error(error.method);
487
+ return false;
488
+ }
489
+ });
490
+ }
491
+ if ( $.isFunction( found ) ) {
492
+ response = found.apply(context, passedArguments);
493
+ }
494
+ else if(found !== undefined) {
495
+ response = found;
496
+ }
497
+ if($.isArray(invokedResponse)) {
498
+ invokedResponse.push(response);
499
+ }
500
+ else if(typeof invokedResponse == 'string') {
501
+ invokedResponse = [invokedResponse, response];
502
+ }
503
+ else if(response !== undefined) {
504
+ invokedResponse = response;
505
+ }
506
+ return found;
507
+ }
508
+ };
509
+
510
+ if(methodInvoked) {
511
+ if(instance === undefined) {
512
+ module.initialize();
513
+ }
514
+ module.invoke(query);
515
+ }
516
+ else {
517
+ if(instance !== undefined) {
518
+ module.destroy();
519
+ }
520
+ module.initialize();
521
+ }
522
+
523
+ return (invokedResponse !== undefined)
524
+ ? invokedResponse
525
+ : this
526
+ ;
527
+ };
528
+
529
+ // handle DOM attachment to API functionality
530
+ $.fn.apiButton = function(parameters) {
531
+ $(this)
532
+ .each(function(){
533
+ var
534
+ // if only function passed it is success callback
535
+ $module = $(this),
536
+ selector = $(this).selector || '',
537
+
538
+ settings = ( $.isFunction(parameters) )
539
+ ? $.extend(true, {}, $.api.settings, $.fn.apiButton.settings, { stateContext: this, success: parameters })
540
+ : $.extend(true, {}, $.api.settings, $.fn.apiButton.settings, { stateContext: this}, parameters),
541
+ module
542
+ ;
543
+ module = {
544
+ initialize: function() {
545
+ if(settings.context && selector !== '') {
546
+ $(settings.context)
547
+ .on(selector, 'click.' + settings.namespace, module.click)
548
+ ;
549
+ }
550
+ else {
551
+ $module
552
+ .on('click.' + settings.namespace, module.click)
553
+ ;
554
+ }
555
+ },
556
+ click: function() {
557
+ if(!settings.filter || $(this).filter(settings.filter).size() === 0) {
558
+ $.proxy( $.api, this )(settings);
559
+ }
560
+ }
561
+ };
562
+ module.initialize();
563
+ })
564
+ ;
565
+ return this;
566
+ };
567
+
568
+ $.api.settings = {
569
+
570
+ name : 'API',
571
+ namespace : 'api',
572
+
573
+ debug : true,
574
+ verbose : true,
575
+ performance : true,
576
+
577
+ api : {},
578
+
579
+ beforeSend : function(settings) {
580
+ return settings;
581
+ },
582
+ beforeXHR : function(xhr) {},
583
+ success : function(response) {},
584
+ complete : function(response) {},
585
+ failure : function(errorCode) {},
586
+ progress : false,
587
+
588
+ error : {
589
+ missingAction : 'API action used but no url was defined',
590
+ missingURL : 'URL not specified for the API action',
591
+ missingParameter : 'Missing an essential URL parameter: ',
592
+
593
+ timeout : 'Your request timed out',
594
+ error : 'There was an error with your request',
595
+ parseError : 'There was an error parsing your request',
596
+ JSONParse : 'JSON could not be parsed during error handling',
597
+ statusMessage : 'Server gave an error: ',
598
+ beforeSend : 'The before send function has aborted the request',
599
+ exitConditions : 'API Request Aborted. Exit conditions met'
600
+ },
601
+
602
+ className: {
603
+ loading : 'loading',
604
+ error : 'error'
605
+ },
606
+
607
+ metadata: {
608
+ action : 'action',
609
+ promise : 'promise',
610
+ xhr : 'xhr'
611
+ },
612
+
613
+ regExpTemplate: /\{\$([A-z]+)\}/g,
614
+
615
+ action : false,
616
+ url : false,
617
+ urlData : false,
618
+ serializeForm : false,
619
+
620
+ stateContext : false,
621
+
622
+ method : 'get',
623
+ data : {},
624
+ dataType : 'json',
625
+ cache : true,
626
+
627
+ loadingLength : 200,
628
+ errorLength : 2000
629
+
630
+ };
631
+
632
+ $.fn.apiButton.settings = {
633
+ filter : '.disabled, .loading',
634
+ context : false,
635
+ stateContext : false
636
+ };
637
+
638
+ })( jQuery, window , document );