condo_interface 0.0.1

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 (54) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.textile +5 -0
  3. data/Rakefile +40 -0
  4. data/app/assets/images/condo_interface/close.png +0 -0
  5. data/app/assets/images/condo_interface/close.svg +71 -0
  6. data/app/assets/images/condo_interface/document.png +0 -0
  7. data/app/assets/images/condo_interface/document.svg +108 -0
  8. data/app/assets/images/condo_interface/pause.png +0 -0
  9. data/app/assets/images/condo_interface/pause.svg +75 -0
  10. data/app/assets/images/condo_interface/play.png +0 -0
  11. data/app/assets/images/condo_interface/play.svg +79 -0
  12. data/app/assets/javascripts/condo_interface/directives.js +308 -0
  13. data/app/assets/javascripts/condo_interface.js +1 -0
  14. data/app/assets/stylesheets/condo_interface/images.css.erb +51 -0
  15. data/app/assets/stylesheets/condo_interface/uploads.css +475 -0
  16. data/app/assets/stylesheets/condo_interface.css +16 -0
  17. data/app/assets/templates/_upload.html +59 -0
  18. data/app/views/condo_interface/_upload.html +4 -0
  19. data/lib/condo_interface/engine.rb +5 -0
  20. data/lib/condo_interface/version.rb +3 -0
  21. data/lib/condo_interface.rb +4 -0
  22. data/lib/tasks/condo_interface_tasks.rake +4 -0
  23. data/test/condo_interface_test.rb +7 -0
  24. data/test/dummy/README.rdoc +261 -0
  25. data/test/dummy/Rakefile +7 -0
  26. data/test/dummy/app/assets/javascripts/application.js +15 -0
  27. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  28. data/test/dummy/app/controllers/application_controller.rb +3 -0
  29. data/test/dummy/app/helpers/application_helper.rb +2 -0
  30. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/test/dummy/config/application.rb +59 -0
  32. data/test/dummy/config/boot.rb +10 -0
  33. data/test/dummy/config/database.yml +25 -0
  34. data/test/dummy/config/environment.rb +5 -0
  35. data/test/dummy/config/environments/development.rb +37 -0
  36. data/test/dummy/config/environments/production.rb +67 -0
  37. data/test/dummy/config/environments/test.rb +37 -0
  38. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  39. data/test/dummy/config/initializers/inflections.rb +15 -0
  40. data/test/dummy/config/initializers/mime_types.rb +5 -0
  41. data/test/dummy/config/initializers/secret_token.rb +7 -0
  42. data/test/dummy/config/initializers/session_store.rb +8 -0
  43. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  44. data/test/dummy/config/locales/en.yml +5 -0
  45. data/test/dummy/config/routes.rb +4 -0
  46. data/test/dummy/config.ru +4 -0
  47. data/test/dummy/public/404.html +26 -0
  48. data/test/dummy/public/422.html +26 -0
  49. data/test/dummy/public/500.html +25 -0
  50. data/test/dummy/public/favicon.ico +0 -0
  51. data/test/dummy/script/rails +6 -0
  52. data/test/integration/navigation_test.rb +10 -0
  53. data/test/test_helper.rb +15 -0
  54. metadata +161 -0
@@ -0,0 +1,308 @@
1
+ /**
2
+ * CoTag Condo
3
+ * Direct to cloud resumable uploads
4
+ *
5
+ * Copyright (c) 2012 CoTag Media.
6
+ *
7
+ * @author Stephen von Takach <steve@cotag.me>
8
+ * @copyright 2012 cotag.me
9
+ *
10
+ *
11
+ * References:
12
+ * * https://github.com/umdjs/umd
13
+ * * https://github.com/addyosmani/jquery-plugin-patterns
14
+ * * http://ie.microsoft.com/testdrive/ieblog/2011/oct/PointerDraw.js.source.html (detect click, touch etc on all platforms)
15
+ * * http://docs.angularjs.org/guide/directive
16
+ * * http://stackoverflow.com/questions/3758606/how-to-convert-byte-size-into-human-readable-format-in-java/3758880
17
+ *
18
+ **/
19
+
20
+ (function (factory) {
21
+ if (typeof define === 'function' && define.amd) {
22
+ // AMD
23
+ define(['jquery', 'condo_uploader'], factory);
24
+ } else {
25
+ // Browser globals
26
+ factory(jQuery, window.CondoUploader);
27
+ }
28
+ }(function ($, uploads, undefined) {
29
+ 'use strict';
30
+
31
+
32
+ var safeApply = function(scope, fn) {
33
+ var phase = scope.$root.$$phase;
34
+ if(phase == '$apply' || phase == '$digest') {
35
+ fn();
36
+ } else {
37
+ scope.$apply(fn);
38
+ }
39
+ };
40
+
41
+
42
+ //
43
+ // Allow for both mobile and desktop events or both
44
+ // Overkill?
45
+ //
46
+ uploads.directive('coTap', function() {
47
+
48
+
49
+ //
50
+ // Opera doesn't have Object.keys so we use this wrapper
51
+ //
52
+ var NumberOfKeys = function(theObject) {
53
+ if (Object.keys)
54
+ return Object.keys(theObject).length;
55
+
56
+ var n = 0;
57
+ for (var key in theObject)
58
+ ++n;
59
+
60
+ return n;
61
+ };
62
+
63
+ return function(scope, element, attrs) {
64
+ var tracker = {},
65
+
66
+ // common event handler for the mouse/pointer/touch models and their down/start, move, up/end, and cancel events
67
+ DoEvent = function(event) {
68
+
69
+ //
70
+ // Optimise rejecting clicks (iOS) that are most likely triggered by a touch
71
+ //
72
+ if (event.originalEvent.type == "click" && NumberOfKeys(tracker) == 0)
73
+ return;
74
+
75
+ var theEvtObj = event.originalEvent,
76
+ pointerList = theEvtObj.changedTouches ? theEvtObj.changedTouches : [theEvtObj];
77
+ for (var i = 0; i < pointerList.length; ++i) {
78
+ var pointerObj = pointerList[i],
79
+ pointerId = (typeof pointerObj.identifier != 'undefined') ? pointerObj.identifier : (typeof pointerObj.pointerId != 'undefined') ? pointerObj.pointerId : 1;
80
+
81
+ if (theEvtObj.type.match(/(start|down)$/i)) {
82
+ // clause for processing MSPointerDown, touchstart, and mousedown
83
+
84
+ //
85
+ // Track the element the event started on and if we should execute the attached action
86
+ //
87
+ tracker[pointerId] = {element: this, execute: true};
88
+
89
+ //
90
+ // in the Microsoft pointer model, set the capture for this pointer
91
+ // in the mouse model, set the capture or add a document-level event handlers if this is our first down point
92
+ // nothing is required for the iOS touch model because capture is implied on touchstart
93
+ //
94
+ if (this.msSetPointerCapture)
95
+ this.msSetPointerCapture(pointerId);
96
+
97
+
98
+ } else if (theEvtObj.type.match(/move$/i)) {
99
+ // clause handles MSPointerMove and touchmove
100
+
101
+ if(tracker[pointerId])
102
+ tracker[pointerId].execute = false;
103
+
104
+
105
+ } else if (tracker[pointerId] && theEvtObj.type.match(/(up|end|cancel|click)$/i)) {
106
+ // clause handles up/end/cancel/click
107
+ var target = tracker[pointerId].element;
108
+
109
+ if (!theEvtObj.type.match(/cancel$/i) && tracker[pointerId].execute === true)
110
+ safeApply(scope, attrs['coTap']); // Apply the click, touch, point event
111
+
112
+ delete tracker[pointerId];
113
+
114
+ //
115
+ // in the Microsoft pointer model, release the capture for this pointer
116
+ // in the mouse model, release the capture or remove document-level event handlers if there are no down points
117
+ // nothing is required for the iOS touch model because capture is implied on touchstart
118
+ //
119
+ if (target.msReleasePointerCapture)
120
+ target.msReleasePointerCapture(pointerId);
121
+ }
122
+ }
123
+ };
124
+
125
+ if (window.navigator.msPointerEnabled) {
126
+ // Microsoft pointer model
127
+ element.on('MSPointerDown.condo MSPointerMove.condo MSPointerUp.condo MSPointerCancel.condo', DoEvent);
128
+ } else {
129
+ // iOS touch model & mouse model
130
+ element.on('touchstart.condo touchmove.condo touchend.condo touchcancel.condo mousedown.condo click.condo', DoEvent);
131
+ }
132
+
133
+
134
+ //
135
+ // Clean up any event handlers
136
+ //
137
+ scope.$on('$destroy', function() {
138
+ element.off('.condo');
139
+ });
140
+
141
+
142
+ };
143
+ });
144
+
145
+ //
146
+ // create a directive for attaching the input events
147
+ //
148
+ uploads.directive('coUploads', ['Condo.Broadcast', function(broadcast) {
149
+ return function(scope, element, attrs) {
150
+ var options = {
151
+ delegate: attrs['coDelegate'] || element,
152
+ drop_targets: attrs['coTargets'] || element,
153
+ hover_class: attrs['coHoverClass'] || 'drag-hover',
154
+ pre_check: attrs['coAccepts'] || '/./i',
155
+ size_limit: attrs['coLimit'] || 0
156
+ };
157
+
158
+
159
+ if(!!attrs['coEndpoint'])
160
+ scope.endpoint = attrs['coEndpoint'];
161
+
162
+
163
+ scope.options = options;
164
+
165
+
166
+ //
167
+ // Determine how to draw the element
168
+ //
169
+ if(document.implementation.hasFeature("org.w3c.svg", "1.0")) {
170
+ element.addClass('supports-svg');
171
+ } else {
172
+ element.addClass('no-svg');
173
+ }
174
+
175
+
176
+ //
177
+ // Detect file drops
178
+ //
179
+ options.drop_targets = $(options.drop_targets);
180
+ options.delegate = $(options.delegate).on('drop.condo', options.drop_targets, function(event) {
181
+ options.drop_targets.removeClass(options.hover_class);
182
+
183
+ //
184
+ // Prevent propagation early (so any errors don't cause unwanted behaviour)
185
+ //
186
+ event.preventDefault();
187
+ event.stopPropagation();
188
+
189
+ safeApply(scope, function() {
190
+ scope.add(event.originalEvent.dataTransfer.files);
191
+ });
192
+ }).on('dragover.condo', options.drop_targets, function(event) {
193
+ $(this).addClass(options.hover_class);
194
+
195
+ return false;
196
+ }).on('dragleave.condo', options.drop_targets, function(event) {
197
+ $(this).removeClass(options.hover_class);
198
+
199
+ return false;
200
+ }).
201
+
202
+
203
+ //
204
+ // Detect manual file uploads
205
+ //
206
+ on('change.condo', ':file', function(event) {
207
+ var self = $(this);
208
+ safeApply(scope, function() {
209
+ scope.add(self[0].files);
210
+ self.parents('form')[0].reset();
211
+ });
212
+ });
213
+
214
+
215
+ //
216
+ // Clean up any event handlers
217
+ //
218
+ scope.$on('$destroy', function() {
219
+ options.drop_targets.off('.condo');
220
+ options.delegate.off('.condo');
221
+ element.removeClass('supports-svg').removeClass('no-svg');
222
+ });
223
+
224
+
225
+ scope.$on('coFileAddFailed', function() {
226
+ alert('Failed to add file: ' + broadcast.message.reason);
227
+ });
228
+
229
+
230
+ scope.humanReadableByteCount = function(bytes, si) {
231
+ var unit = si ? 1000.0 : 1024.0;
232
+ if (bytes < unit) return bytes + (si ? ' iB' : ' B');
233
+ var exp = Math.floor(Math.log(bytes) / Math.log(unit)),
234
+ pre = (si ? 'kMGTPE' : 'KMGTPE').charAt(exp-1) + (si ? 'iB' : 'B');
235
+ return (bytes / Math.pow(unit, exp)).toFixed(1) + ' ' + pre;
236
+ }
237
+ }
238
+ }]);
239
+
240
+
241
+ //
242
+ // The individual upload events
243
+ // Triggers the pause, resume, abort functions
244
+ //
245
+ uploads.directive('coUpload', function() {
246
+ var PENDING = 0,
247
+ STARTED = 1,
248
+ PAUSED = 2,
249
+ UPLOADING = 3,
250
+ COMPLETED = 4,
251
+ ABORTED = 5;
252
+
253
+ return function(scope, element, attrs) {
254
+
255
+ scope.size = scope.humanReadableByteCount(scope.upload.size, false);
256
+ scope.progress = 0;
257
+ scope.paused = true;
258
+
259
+ scope.$watch('upload.state', function(newValue, oldValue) {
260
+ switch(newValue) {
261
+ case STARTED:
262
+ scope.paused = false;
263
+ scope.upload.message = 'starting...';
264
+ break;
265
+
266
+ case UPLOADING:
267
+ element.find('div.bar').addClass('animate');
268
+ scope.upload.message = undefined;
269
+ scope.paused = false;
270
+ break;
271
+
272
+ case COMPLETED:
273
+ scope.upload.message = 'complete';
274
+ element.find('td.controls').replaceWith( '<td class="blank" />' );
275
+ element.find('div.bar').removeClass('animate');
276
+
277
+ scope.check_autostart();
278
+ break;
279
+
280
+ case PAUSED:
281
+ element.find('div.bar').removeClass('animate');
282
+ if (scope.upload.message === undefined)
283
+ scope.upload.message = 'paused';
284
+
285
+ scope.paused = true;
286
+ // No need for break
287
+ }
288
+ });
289
+
290
+ scope.$watch('upload.progress', function(newValue, oldValue) {
291
+ scope.progress = newValue / scope.upload.size * 100;
292
+ });
293
+
294
+
295
+ scope.animate_remove = function() {
296
+ scope.abort(scope.upload);
297
+
298
+ element.fadeOut(800, function() {
299
+ safeApply(scope, function() {
300
+ scope.remove(scope.upload);
301
+ });
302
+ });
303
+ };
304
+
305
+ };
306
+ });
307
+
308
+ }));
@@ -0,0 +1 @@
1
+ //= require condo_interface/directives
@@ -0,0 +1,51 @@
1
+
2
+
3
+
4
+ .supports-svg div.condo-upload > div.description td.icon {
5
+ background: url(<%= asset_path('condo_interface/document.svg') %>) no-repeat center center;
6
+ }
7
+
8
+ .supports-svg div.condo-upload > div.stats td.controls.paused {
9
+ background: url(<%= asset_path('condo_interface/play.svg') %>) no-repeat center center;
10
+ }
11
+
12
+ .supports-svg div.condo-upload > div.stats td.controls.uploading {
13
+ background: url(<%= asset_path('condo_interface/pause.svg') %>) no-repeat center center;
14
+ }
15
+
16
+ .supports-svg div.condo-upload > div.stats td.abort {
17
+ background: url(<%= asset_path('condo_interface/close.svg') %>) no-repeat center center;
18
+ }
19
+
20
+
21
+
22
+
23
+
24
+ .no-svg div.condo-upload > div.description td.icon {
25
+ background: url(<%= asset_path('condo_interface/document.png') %>) no-repeat center center;
26
+ }
27
+
28
+ .no-svg div.condo-upload > div.stats td.controls.paused {
29
+ background: url(<%= asset_path('condo_interface/play.png') %>) no-repeat center center;
30
+ }
31
+
32
+ .no-svg div.condo-upload > div.stats td.controls.uploading {
33
+ background: url(<%= asset_path('condo_interface/pause.png') %>) no-repeat center center;
34
+ }
35
+
36
+ .no-svg div.condo-upload > div.stats td.abort {
37
+ background: url(<%= asset_path('condo_interface/close.png') %>) no-repeat center center;
38
+ }
39
+
40
+
41
+
42
+
43
+ div.condo-upload td.image {
44
+ -webkit-background-size: contain !important;
45
+ -moz-background-size: contain !important;
46
+ -ms-background-size: contain !important;
47
+ -o-background-size: contain !important;
48
+ background-size: contain !important;
49
+ }
50
+
51
+