koda 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (161) hide show
  1. data/lib/helpers/app_helper.rb +40 -0
  2. data/lib/helpers/koda_helper.rb +105 -0
  3. data/lib/helpers/view_helper.rb +146 -0
  4. data/lib/koda.rb +123 -0
  5. data/lib/models/hash.rb +29 -0
  6. data/lib/models/mongo_collection.rb +144 -0
  7. data/lib/models/mongo_config.rb +22 -0
  8. data/lib/models/mongo_database.rb +136 -0
  9. data/lib/models/mongo_document.rb +124 -0
  10. data/lib/models/mongo_grid.rb +85 -0
  11. data/lib/models/mongo_media.rb +55 -0
  12. data/lib/models/user_access_provider.rb +135 -0
  13. data/lib/models/user_context.rb +19 -0
  14. data/lib/routes/koda_api.rb +392 -0
  15. data/lib/routes/koda_site.rb +57 -0
  16. data/lib/views/console.erb +139 -0
  17. data/lib/views/explorer.erb +119 -0
  18. data/lib/views/login.erb +77 -0
  19. data/lib/views/not_allowed.erb +75 -0
  20. data/public/koda/Help/DataTypes.txt +82 -0
  21. data/public/koda/Help/KodaType_Template.js +48 -0
  22. data/public/koda/apple-touch-icon-114x114-precomposed.png +0 -0
  23. data/public/koda/apple-touch-icon-144x144-precomposed.png +0 -0
  24. data/public/koda/apple-touch-icon-57x57-precomposed.png +0 -0
  25. data/public/koda/apple-touch-icon-72x72-precomposed.png +0 -0
  26. data/public/koda/apple-touch-icon-precomposed.png +0 -0
  27. data/public/koda/apple-touch-icon.png +0 -0
  28. data/public/koda/css/bootstrap-responsive.css +1058 -0
  29. data/public/koda/css/bootstrap.css +5774 -0
  30. data/public/koda/css/main.css +288 -0
  31. data/public/koda/favicon.ico +0 -0
  32. data/public/koda/fonts/angelina-webfont.eot +0 -0
  33. data/public/koda/fonts/angelina-webfont.svg +228 -0
  34. data/public/koda/fonts/angelina-webfont.ttf +0 -0
  35. data/public/koda/fonts/angelina-webfont.woff +0 -0
  36. data/public/koda/fonts/coolvetica_rg-webfont.eot +0 -0
  37. data/public/koda/fonts/coolvetica_rg-webfont.svg +232 -0
  38. data/public/koda/fonts/coolvetica_rg-webfont.ttf +0 -0
  39. data/public/koda/fonts/coolvetica_rg-webfont.woff +0 -0
  40. data/public/koda/fonts/ladyic__-webfont.eot +0 -0
  41. data/public/koda/fonts/ladyic__-webfont.svg +257 -0
  42. data/public/koda/fonts/ladyic__-webfont.ttf +0 -0
  43. data/public/koda/fonts/ladyic__-webfont.woff +0 -0
  44. data/public/koda/images/ajax-loader.gif +0 -0
  45. data/public/koda/images/back.png +0 -0
  46. data/public/koda/images/bg-table-thead.png +0 -0
  47. data/public/koda/images/big_folder.png +0 -0
  48. data/public/koda/images/box_file.png +0 -0
  49. data/public/koda/images/car_add.png +0 -0
  50. data/public/koda/images/compress.png +0 -0
  51. data/public/koda/images/database_table.png +0 -0
  52. data/public/koda/images/feed_add.png +0 -0
  53. data/public/koda/images/feed_link.png +0 -0
  54. data/public/koda/images/file.png +0 -0
  55. data/public/koda/images/folder.png +0 -0
  56. data/public/koda/images/folder_image.png +0 -0
  57. data/public/koda/images/glyphicons-halflings-white.png +0 -0
  58. data/public/koda/images/glyphicons-halflings.png +0 -0
  59. data/public/koda/images/group_add.png +0 -0
  60. data/public/koda/images/group_key.png +0 -0
  61. data/public/koda/images/image_add.png +0 -0
  62. data/public/koda/images/layout_add.png +0 -0
  63. data/public/koda/images/package.png +0 -0
  64. data/public/koda/images/page_white_edit.png +0 -0
  65. data/public/koda/images/page_white_text.png +0 -0
  66. data/public/koda/images/photo_add.png +0 -0
  67. data/public/koda/images/toggle-collapse-dark.png +0 -0
  68. data/public/koda/images/toggle-collapse-light.png +0 -0
  69. data/public/koda/images/toggle-expand-dark.png +0 -0
  70. data/public/koda/images/toggle-expand-light.png +0 -0
  71. data/public/koda/images/twitter.png +0 -0
  72. data/public/koda/koda-editors/KodaEditor.js +843 -0
  73. data/public/koda/koda-editors/collection-editor.html +56 -0
  74. data/public/koda/koda-editors/generic-editor.css +112 -0
  75. data/public/koda/koda-editors/generic-editor.html +74 -0
  76. data/public/koda/koda-editors/koda-editor.css +72 -0
  77. data/public/koda/koda-editors/twitterfeed-editor.html +90 -0
  78. data/public/koda/koda-types/_builtin_registration.json +62 -0
  79. data/public/koda/koda-types/koda-access.json +49 -0
  80. data/public/koda/koda-types/koda-collection.json +12 -0
  81. data/public/koda/koda-types/koda-generictext.json +50 -0
  82. data/public/koda/koda-types/koda-media.json +58 -0
  83. data/public/koda/koda-types/koda-twitterfeed.json +79 -0
  84. data/public/koda/koda-types/koda-user.json +71 -0
  85. data/public/koda/nicEditorIcons.gif +0 -0
  86. data/public/koda/scripts/Koda.js +1200 -0
  87. data/public/koda/scripts/lib/DOMAssistant.js +4 -0
  88. data/public/koda/scripts/lib/modernizr.js +4 -0
  89. data/public/koda/scripts/lib/respond.js +2 -0
  90. data/public/koda/scripts/lib/selectivizr.js +5 -0
  91. data/public/koda/scripts/plugins/bootstrap.js +2027 -0
  92. data/public/koda/scripts/plugins/box.js +8 -0
  93. data/public/koda/scripts/plugins/fancybox/blank.gif +0 -0
  94. data/public/koda/scripts/plugins/fancybox/fancy_close.png +0 -0
  95. data/public/koda/scripts/plugins/fancybox/fancy_loading.png +0 -0
  96. data/public/koda/scripts/plugins/fancybox/fancy_nav_left.png +0 -0
  97. data/public/koda/scripts/plugins/fancybox/fancy_nav_right.png +0 -0
  98. data/public/koda/scripts/plugins/fancybox/fancy_shadow_e.png +0 -0
  99. data/public/koda/scripts/plugins/fancybox/fancy_shadow_n.png +0 -0
  100. data/public/koda/scripts/plugins/fancybox/fancy_shadow_ne.png +0 -0
  101. data/public/koda/scripts/plugins/fancybox/fancy_shadow_nw.png +0 -0
  102. data/public/koda/scripts/plugins/fancybox/fancy_shadow_s.png +0 -0
  103. data/public/koda/scripts/plugins/fancybox/fancy_shadow_se.png +0 -0
  104. data/public/koda/scripts/plugins/fancybox/fancy_shadow_sw.png +0 -0
  105. data/public/koda/scripts/plugins/fancybox/fancy_shadow_w.png +0 -0
  106. data/public/koda/scripts/plugins/fancybox/fancy_title_left.png +0 -0
  107. data/public/koda/scripts/plugins/fancybox/fancy_title_main.png +0 -0
  108. data/public/koda/scripts/plugins/fancybox/fancy_title_over.png +0 -0
  109. data/public/koda/scripts/plugins/fancybox/fancy_title_right.png +0 -0
  110. data/public/koda/scripts/plugins/fancybox/fancybox-x.png +0 -0
  111. data/public/koda/scripts/plugins/fancybox/fancybox-y.png +0 -0
  112. data/public/koda/scripts/plugins/fancybox/fancybox.png +0 -0
  113. data/public/koda/scripts/plugins/fancybox/jquery.easing-1.3.pack.js +72 -0
  114. data/public/koda/scripts/plugins/fancybox/jquery.fancybox-1.3.4.css +359 -0
  115. data/public/koda/scripts/plugins/fancybox/jquery.fancybox-1.3.4.js +1155 -0
  116. data/public/koda/scripts/plugins/fancybox/jquery.fancybox-1.3.4.pack.js +46 -0
  117. data/public/koda/scripts/plugins/fancybox/jquery.mousewheel-3.0.4.pack.js +14 -0
  118. data/public/koda/scripts/plugins/fileuploader.js +1527 -0
  119. data/public/koda/scripts/plugins/jquery-class.js +7 -0
  120. data/public/koda/scripts/plugins/jquery.contextmenu/images/cut.png +0 -0
  121. data/public/koda/scripts/plugins/jquery.contextmenu/images/door.png +0 -0
  122. data/public/koda/scripts/plugins/jquery.contextmenu/images/page_white_copy.png +0 -0
  123. data/public/koda/scripts/plugins/jquery.contextmenu/images/page_white_delete.png +0 -0
  124. data/public/koda/scripts/plugins/jquery.contextmenu/images/page_white_edit.png +0 -0
  125. data/public/koda/scripts/plugins/jquery.contextmenu/images/page_white_paste.png +0 -0
  126. data/public/koda/scripts/plugins/jquery.contextmenu/jquery.contextMenu.css +63 -0
  127. data/public/koda/scripts/plugins/jquery.contextmenu/jquery.contextMenu.js +211 -0
  128. data/public/koda/scripts/plugins/jquery.js +2 -0
  129. data/public/koda/scripts/plugins/json2.js +277 -0
  130. data/public/koda/scripts/plugins/modernizr.js +2 -0
  131. data/public/koda/scripts/plugins/nicEdit.js +183 -0
  132. data/public/koda/scripts/plugins/qunit.js +1448 -0
  133. data/public/koda/scripts/plugins/spin.js +2 -0
  134. data/public/koda/scripts/plugins/uploader/README.md +77 -0
  135. data/public/koda/scripts/plugins/uploader/README.txt +89 -0
  136. data/public/koda/scripts/plugins/uploader/example/application.js +20 -0
  137. data/public/koda/scripts/plugins/uploader/example/index.html +109 -0
  138. data/public/koda/scripts/plugins/uploader/example/style.css +22 -0
  139. data/public/koda/scripts/plugins/uploader/example/upload.php +313 -0
  140. data/public/koda/scripts/plugins/uploader/jquery.fileupload-ui.css +100 -0
  141. data/public/koda/scripts/plugins/uploader/jquery.fileupload-ui.js +642 -0
  142. data/public/koda/scripts/plugins/uploader/jquery.fileupload.js +711 -0
  143. data/public/koda/scripts/plugins/uploader/jquery.iframe-transport.js +133 -0
  144. data/public/koda/scripts/plugins/uploader/pbar-ani.gif +0 -0
  145. data/public/koda/scripts/plugins/uploader/tests/index.html +115 -0
  146. data/public/koda/scripts/plugins/uploader/tests/tests.js +1008 -0
  147. data/public/koda/scripts/require.js +32 -0
  148. data/public/koda/scripts/specs.js +12 -0
  149. data/public/koda/scripts/specs/cd-command-spec.js +51 -0
  150. data/public/koda/scripts/specs/controller-spec.js +95 -0
  151. data/public/koda/scripts/specs/doubles/mock-command.js +21 -0
  152. data/public/koda/scripts/specs/doubles/mock-jamservice.js +33 -0
  153. data/public/koda/scripts/specs/doubles/mock-prompt.js +30 -0
  154. data/public/koda/scripts/specs/doubles/uiobject-double.js +15 -0
  155. data/public/koda/scripts/specs/edit-command-spec.js +76 -0
  156. data/public/koda/scripts/specs/ls-command-spec.js +61 -0
  157. data/public/koda/scripts/specs/mkdir-command-spec.js +40 -0
  158. data/public/koda/scripts/specs/peek-command-spec.js +24 -0
  159. data/public/koda/scripts/specs/remove-command-spec.js +37 -0
  160. data/public/koda/scripts/specs/service-spec.js +85 -0
  161. metadata +402 -0
@@ -0,0 +1,100 @@
1
+ @charset 'UTF-8';
2
+ /*
3
+ * jQuery File Upload UI Plugin CSS 5.0.5
4
+ * https://github.com/blueimp/jQuery-File-Upload
5
+ *
6
+ * Copyright 2010, Sebastian Tschan
7
+ * https://blueimp.net
8
+ *
9
+ * Licensed under the MIT license:
10
+ * http://creativecommons.org/licenses/MIT/
11
+ */
12
+
13
+ .ui-button input {
14
+ position: absolute;
15
+ top: 0;
16
+ right: 0;
17
+ margin: 0;
18
+ border: solid transparent;
19
+ border-width: 0 0 100px 200px;
20
+ opacity: 0;
21
+ filter: alpha(opacity=0);
22
+ -o-transform: translate(250px, -50px) scale(1);
23
+ -moz-transform: translate(-300px, 0) scale(4);
24
+ direction: ltr;
25
+ cursor: pointer;
26
+ }
27
+
28
+ .fileinput-button {
29
+ overflow: hidden;
30
+ }
31
+
32
+ /* Fix for IE 6: */
33
+ *html .fileinput-button {
34
+ padding: 2px 0;
35
+ }
36
+
37
+ /* Fix for IE 7: */
38
+ *+html .fileinput-button {
39
+ padding: 2px 0;
40
+ }
41
+
42
+ .fileupload-buttonbar {
43
+ padding: 0.2em 0.4em;
44
+ }
45
+
46
+ .fileupload-buttonbar .ui-button {
47
+ vertical-align: middle;
48
+ }
49
+
50
+ .fileupload-content {
51
+ padding: 0.2em 0.4em;
52
+ border-top-width: 0;
53
+ }
54
+
55
+ .ui-progressbar {
56
+ width: 200px;
57
+ height: 20px;
58
+ }
59
+
60
+ .ui-progressbar-value {
61
+ background: url(pbar-ani.gif);
62
+ }
63
+
64
+ .fileupload-progressbar {
65
+ width: 400px;
66
+ margin: 10px 0;
67
+ }
68
+
69
+ .files {
70
+ margin: 10px 0;
71
+ border-collapse: collapse;
72
+ }
73
+
74
+ .files td {
75
+ padding: 5px;
76
+ border-spacing: 5px;
77
+ }
78
+
79
+ .files img {
80
+ border: none;
81
+ }
82
+
83
+ .files .name {
84
+ padding: 0 10px;
85
+ }
86
+
87
+ .files .size {
88
+ padding: 0 10px 0 0;
89
+ text-align: right;
90
+ white-space: nowrap;
91
+ }
92
+
93
+ .ui-state-disabled .ui-state-disabled {
94
+ opacity: 1;
95
+ filter: alpha(opacity=100);
96
+ }
97
+
98
+ .ui-state-disabled input {
99
+ cursor: default;
100
+ }
@@ -0,0 +1,642 @@
1
+ /*
2
+ * jQuery File Upload User Interface Plugin 5.0.12
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2010, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://creativecommons.org/licenses/MIT/
10
+ */
11
+
12
+ /*jslint nomen: false, unparam: true, regexp: false */
13
+ /*global window, document, URL, webkitURL, FileReader, jQuery */
14
+
15
+ (function ($) {
16
+ 'use strict';
17
+
18
+ // The UI version extends the basic fileupload widget and adds
19
+ // a complete user interface based on the given upload/download
20
+ // templates.
21
+ $.widget('blueimpUI.fileupload', $.blueimp.fileupload, {
22
+
23
+ options: {
24
+ // By default, files added to the widget are uploaded as soon
25
+ // as the user clicks on the start buttons. To enable automatic
26
+ // uploads, set the following option to true:
27
+ autoUpload: false,
28
+ // The following option limits the number of files that are
29
+ // allowed to be uploaded using this widget:
30
+ maxNumberOfFiles: undefined,
31
+ // The maximum allowed file size:
32
+ maxFileSize: undefined,
33
+ // The minimum allowed file size:
34
+ minFileSize: 1,
35
+ // The regular expression for allowed file types, matches
36
+ // against either file type or file name:
37
+ acceptFileTypes: /.+$/i,
38
+ // The regular expression to define for which files a preview
39
+ // image is shown, matched against the file type:
40
+ previewFileTypes: /^image\/(gif|jpeg|png)$/,
41
+ // The maximum width of the preview images:
42
+ previewMaxWidth: 80,
43
+ // The maximum height of the preview images:
44
+ previewMaxHeight: 80,
45
+ // By default, preview images are displayed as canvas elements
46
+ // if supported by the browser. Set the following option to false
47
+ // to always display preview images as img elements:
48
+ previewAsCanvas: true,
49
+ // The file upload template that is given as first argument to the
50
+ // jQuery.tmpl method to render the file uploads:
51
+ uploadTemplate: $('#template-upload'),
52
+ // The file download template, that is given as first argument to the
53
+ // jQuery.tmpl method to render the file downloads:
54
+ downloadTemplate: $('#template-download'),
55
+ // The expected data type of the upload response, sets the dataType
56
+ // option of the $.ajax upload requests:
57
+ dataType: 'json',
58
+
59
+ // The add callback is invoked as soon as files are added to the fileupload
60
+ // widget (via file input selection, drag & drop or add API call).
61
+ // See the basic file upload widget for more information:
62
+ add: function (e, data) {
63
+ var that = $(this).data('fileupload');
64
+ that._adjustMaxNumberOfFiles(-data.files.length);
65
+ data.isAdjusted = true;
66
+ data.isValidated = that._validate(data.files);
67
+ data.context = that._renderUpload(data.files)
68
+ .appendTo($(this).find('.files')).fadeIn(function () {
69
+ // Fix for IE7 and lower:
70
+ $(this).show();
71
+ }).data('data', data);
72
+ if ((that.options.autoUpload || data.autoUpload) &&
73
+ data.isValidated) {
74
+ data.jqXHR = data.submit();
75
+ }
76
+ },
77
+ // Callback for the start of each file upload request:
78
+ send: function (e, data) {
79
+ if (!data.isValidated) {
80
+ var that = $(this).data('fileupload');
81
+ if (!data.isAdjusted) {
82
+ that._adjustMaxNumberOfFiles(-data.files.length);
83
+ }
84
+ if (!that._validate(data.files)) {
85
+ return false;
86
+ }
87
+ }
88
+ if (data.context && data.dataType &&
89
+ data.dataType.substr(0, 6) === 'iframe') {
90
+ // Iframe Transport does not support progress events.
91
+ // In lack of an indeterminate progress bar, we set
92
+ // the progress to 100%, showing the full animated bar:
93
+ data.context.find('.ui-progressbar').progressbar(
94
+ 'value',
95
+ parseInt(100, 10)
96
+ );
97
+ }
98
+ },
99
+ // Callback for successful uploads:
100
+ done: function (e, data) {
101
+ var that = $(this).data('fileupload');
102
+ if (data.context) {
103
+ data.context.each(function (index) {
104
+ var file = ($.isArray(data.result) &&
105
+ data.result[index]) || {error: 'emptyResult'};
106
+ if (file.error) {
107
+ that._adjustMaxNumberOfFiles(1);
108
+ }
109
+ $(this).fadeOut(function () {
110
+ that._renderDownload([file])
111
+ .css('display', 'none')
112
+ .replaceAll(this)
113
+ .fadeIn(function () {
114
+ // Fix for IE7 and lower:
115
+ $(this).show();
116
+ });
117
+ });
118
+ });
119
+ } else {
120
+ that._renderDownload(data.result)
121
+ .css('display', 'none')
122
+ .appendTo($(this).find('.files'))
123
+ .fadeIn(function () {
124
+ // Fix for IE7 and lower:
125
+ $(this).show();
126
+ });
127
+ }
128
+ },
129
+ // Callback for failed (abort or error) uploads:
130
+ fail: function (e, data) {
131
+ var that = $(this).data('fileupload');
132
+ that._adjustMaxNumberOfFiles(data.files.length);
133
+ if (data.context) {
134
+ data.context.each(function (index) {
135
+ $(this).fadeOut(function () {
136
+ if (data.errorThrown !== 'abort') {
137
+ var file = data.files[index];
138
+ file.error = file.error || data.errorThrown
139
+ || true;
140
+ that._renderDownload([file])
141
+ .css('display', 'none')
142
+ .replaceAll(this)
143
+ .fadeIn(function () {
144
+ // Fix for IE7 and lower:
145
+ $(this).show();
146
+ });
147
+ } else {
148
+ data.context.remove();
149
+ }
150
+ });
151
+ });
152
+ } else if (data.errorThrown !== 'abort') {
153
+ that._adjustMaxNumberOfFiles(-data.files.length);
154
+ data.context = that._renderUpload(data.files)
155
+ .css('display', 'none')
156
+ .appendTo($(this).find('.files'))
157
+ .fadeIn(function () {
158
+ // Fix for IE7 and lower:
159
+ $(this).show();
160
+ }).data('data', data);
161
+ }
162
+ },
163
+ // Callback for upload progress events:
164
+ progress: function (e, data) {
165
+ if (data.context) {
166
+ data.context.find('.ui-progressbar').progressbar(
167
+ 'value',
168
+ parseInt(data.loaded / data.total * 100, 10)
169
+ );
170
+ }
171
+ },
172
+ // Callback for global upload progress events:
173
+ progressall: function (e, data) {
174
+ $(this).find('.fileupload-progressbar').progressbar(
175
+ 'value',
176
+ parseInt(data.loaded / data.total * 100, 10)
177
+ );
178
+ },
179
+ // Callback for uploads start, equivalent to the global ajaxStart event:
180
+ start: function () {
181
+ $(this).find('.fileupload-progressbar')
182
+ .progressbar('value', 0).fadeIn();
183
+ },
184
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
185
+ stop: function () {
186
+ $(this).find('.fileupload-progressbar').fadeOut();
187
+ },
188
+ // Callback for file deletion:
189
+ destroy: function (e, data) {
190
+ var that = $(this).data('fileupload');
191
+ if (data.url) {
192
+ $.ajax(data)
193
+ .success(function () {
194
+ that._adjustMaxNumberOfFiles(1);
195
+ $(this).fadeOut(function () {
196
+ $(this).remove();
197
+ });
198
+ });
199
+ } else {
200
+ data.context.fadeOut(function () {
201
+ $(this).remove();
202
+ });
203
+ }
204
+ }
205
+ },
206
+
207
+ // Scales the given image (img HTML element)
208
+ // using the given options.
209
+ // Returns a canvas object if the canvas option is true
210
+ // and the browser supports canvas, else the scaled image:
211
+ _scaleImage: function (img, options) {
212
+ options = options || {};
213
+ var canvas = document.createElement('canvas'),
214
+ scale = Math.min(
215
+ (options.maxWidth || img.width) / img.width,
216
+ (options.maxHeight || img.height) / img.height
217
+ );
218
+ if (scale >= 1) {
219
+ scale = Math.max(
220
+ (options.minWidth || img.width) / img.width,
221
+ (options.minHeight || img.height) / img.height
222
+ );
223
+ }
224
+ img.width = parseInt(img.width * scale, 10);
225
+ img.height = parseInt(img.height * scale, 10);
226
+ if (!options.canvas || !canvas.getContext) {
227
+ return img;
228
+ }
229
+ canvas.width = img.width;
230
+ canvas.height = img.height;
231
+ canvas.getContext('2d')
232
+ .drawImage(img, 0, 0, img.width, img.height);
233
+ return canvas;
234
+ },
235
+
236
+ _createObjectURL: function (file) {
237
+ var undef = 'undefined',
238
+ urlAPI = (typeof window.createObjectURL !== undef && window) ||
239
+ (typeof URL !== undef && URL) ||
240
+ (typeof webkitURL !== undef && webkitURL);
241
+ return urlAPI ? urlAPI.createObjectURL(file) : false;
242
+ },
243
+
244
+ _revokeObjectURL: function (url) {
245
+ var undef = 'undefined',
246
+ urlAPI = (typeof window.revokeObjectURL !== undef && window) ||
247
+ (typeof URL !== undef && URL) ||
248
+ (typeof webkitURL !== undef && webkitURL);
249
+ return urlAPI ? urlAPI.revokeObjectURL(url) : false;
250
+ },
251
+
252
+ // Loads a given File object via FileReader interface,
253
+ // invokes the callback with a data url:
254
+ _loadFile: function (file, callback) {
255
+ if (typeof FileReader !== 'undefined' &&
256
+ FileReader.prototype.readAsDataURL) {
257
+ var fileReader = new FileReader();
258
+ fileReader.onload = function (e) {
259
+ callback(e.target.result);
260
+ };
261
+ fileReader.readAsDataURL(file);
262
+ return true;
263
+ }
264
+ return false;
265
+ },
266
+
267
+ // Loads an image for a given File object.
268
+ // Invokes the callback with an img or optional canvas
269
+ // element (if supported by the browser) as parameter:
270
+ _loadImage: function (file, callback, options) {
271
+ var that = this,
272
+ url,
273
+ img;
274
+ if (!options || !options.fileTypes ||
275
+ options.fileTypes.test(file.type)) {
276
+ url = this._createObjectURL(file);
277
+ img = $('<img>').bind('load', function () {
278
+ $(this).unbind('load');
279
+ that._revokeObjectURL(url);
280
+ callback(that._scaleImage(img[0], options));
281
+ }).prop('src', url);
282
+ if (!url) {
283
+ this._loadFile(file, function (url) {
284
+ img.prop('src', url);
285
+ });
286
+ }
287
+ }
288
+ },
289
+
290
+ // Link handler, that allows to download files
291
+ // by drag & drop of the links to the desktop:
292
+ _enableDragToDesktop: function () {
293
+ var link = $(this),
294
+ url = link.prop('href'),
295
+ name = decodeURIComponent(url.split('/').pop())
296
+ .replace(/:/g, '-'),
297
+ type = 'application/octet-stream';
298
+ link.bind('dragstart', function (e) {
299
+ try {
300
+ e.originalEvent.dataTransfer.setData(
301
+ 'DownloadURL',
302
+ [type, name, url].join(':')
303
+ );
304
+ } catch (err) {}
305
+ });
306
+ },
307
+
308
+ _adjustMaxNumberOfFiles: function (operand) {
309
+ if (typeof this.options.maxNumberOfFiles === 'number') {
310
+ this.options.maxNumberOfFiles += operand;
311
+ if (this.options.maxNumberOfFiles < 1) {
312
+ this._disableFileInputButton();
313
+ } else {
314
+ this._enableFileInputButton();
315
+ }
316
+ }
317
+ },
318
+
319
+ _formatFileSize: function (file) {
320
+ if (typeof file.size !== 'number') {
321
+ return '';
322
+ }
323
+ if (file.size >= 1000000000) {
324
+ return (file.size / 1000000000).toFixed(2) + ' GB';
325
+ }
326
+ if (file.size >= 1000000) {
327
+ return (file.size / 1000000).toFixed(2) + ' MB';
328
+ }
329
+ return (file.size / 1000).toFixed(2) + ' KB';
330
+ },
331
+
332
+ _hasError: function (file) {
333
+ if (file.error) {
334
+ return file.error;
335
+ }
336
+ // The number of added files is subtracted from
337
+ // maxNumberOfFiles before validation, so we check if
338
+ // maxNumberOfFiles is below 0 (instead of below 1):
339
+ if (this.options.maxNumberOfFiles < 0) {
340
+ return 'maxNumberOfFiles';
341
+ }
342
+ // Files are accepted if either the file type or the file name
343
+ // matches against the acceptFileTypes regular expression, as
344
+ // only browsers with support for the File API report the type:
345
+ if (!(this.options.acceptFileTypes.test(file.type) ||
346
+ this.options.acceptFileTypes.test(file.name))) {
347
+ return 'acceptFileTypes';
348
+ }
349
+ if (this.options.maxFileSize &&
350
+ file.size > this.options.maxFileSize) {
351
+ return 'maxFileSize';
352
+ }
353
+ if (typeof file.size === 'number' &&
354
+ file.size < this.options.minFileSize) {
355
+ return 'minFileSize';
356
+ }
357
+ return null;
358
+ },
359
+
360
+ _validate: function (files) {
361
+ var that = this,
362
+ valid;
363
+ $.each(files, function (index, file) {
364
+ file.error = that._hasError(file);
365
+ valid = !file.error;
366
+ });
367
+ return valid;
368
+ },
369
+
370
+ _uploadTemplateHelper: function (file) {
371
+ file.sizef = this._formatFileSize(file);
372
+ return file;
373
+ },
374
+
375
+ _renderUploadTemplate: function (files) {
376
+ var that = this;
377
+ return $.tmpl(
378
+ this.options.uploadTemplate,
379
+ $.map(files, function (file) {
380
+ return that._uploadTemplateHelper(file);
381
+ })
382
+ );
383
+ },
384
+
385
+ _renderUpload: function (files) {
386
+ var that = this,
387
+ options = this.options,
388
+ tmpl = this._renderUploadTemplate(files);
389
+ if (!(tmpl instanceof $)) {
390
+ return $();
391
+ }
392
+ tmpl.css('display', 'none');
393
+ // .slice(1).remove().end().first() removes all but the first
394
+ // element and selects only the first for the jQuery collection:
395
+ tmpl.find('.progress div').slice(1).remove().end().first()
396
+ .progressbar();
397
+ tmpl.find('.start button').slice(
398
+ this.options.autoUpload ? 0 : 1
399
+ ).remove().end().first()
400
+ .button({
401
+ text: false,
402
+ icons: {primary: 'ui-icon-circle-arrow-e'}
403
+ });
404
+ tmpl.find('.cancel button').slice(1).remove().end().first()
405
+ .button({
406
+ text: false,
407
+ icons: {primary: 'ui-icon-cancel'}
408
+ });
409
+ tmpl.find('.preview').each(function (index, node) {
410
+ that._loadImage(
411
+ files[index],
412
+ function (img) {
413
+ $(img).hide().appendTo(node).fadeIn();
414
+ },
415
+ {
416
+ maxWidth: options.previewMaxWidth,
417
+ maxHeight: options.previewMaxHeight,
418
+ fileTypes: options.previewFileTypes,
419
+ canvas: options.previewAsCanvas
420
+ }
421
+ );
422
+ });
423
+ return tmpl;
424
+ },
425
+
426
+ _downloadTemplateHelper: function (file) {
427
+ file.sizef = this._formatFileSize(file);
428
+ return file;
429
+ },
430
+
431
+ _renderDownloadTemplate: function (files) {
432
+ var that = this;
433
+ return $.tmpl(
434
+ this.options.downloadTemplate,
435
+ $.map(files, function (file) {
436
+ return that._downloadTemplateHelper(file);
437
+ })
438
+ );
439
+ },
440
+
441
+ _renderDownload: function (files) {
442
+ var tmpl = this._renderDownloadTemplate(files);
443
+ if (!(tmpl instanceof $)) {
444
+ return $();
445
+ }
446
+ tmpl.css('display', 'none');
447
+ tmpl.find('.delete button').button({
448
+ text: false,
449
+ icons: {primary: 'ui-icon-trash'}
450
+ });
451
+ tmpl.find('a').each(this._enableDragToDesktop);
452
+ return tmpl;
453
+ },
454
+
455
+ _startHandler: function (e) {
456
+ e.preventDefault();
457
+ var tmpl = $(this).closest('.template-upload'),
458
+ data = tmpl.data('data');
459
+ if (data && data.submit && !data.jqXHR) {
460
+ data.jqXHR = data.submit();
461
+ $(this).fadeOut();
462
+ }
463
+ },
464
+
465
+ _cancelHandler: function (e) {
466
+ e.preventDefault();
467
+ var tmpl = $(this).closest('.template-upload'),
468
+ data = tmpl.data('data') || {};
469
+ if (!data.jqXHR) {
470
+ data.errorThrown = 'abort';
471
+ e.data.fileupload._trigger('fail', e, data);
472
+ } else {
473
+ data.jqXHR.abort();
474
+ }
475
+ },
476
+
477
+ _deleteHandler: function (e) {
478
+ e.preventDefault();
479
+ var button = $(this);
480
+ e.data.fileupload._trigger('destroy', e, {
481
+ context: button.closest('.template-download'),
482
+ url: button.attr('data-url'),
483
+ type: button.attr('data-type'),
484
+ dataType: e.data.fileupload.options.dataType
485
+ });
486
+ },
487
+
488
+ _initEventHandlers: function () {
489
+ $.blueimp.fileupload.prototype._initEventHandlers.call(this);
490
+ var filesList = this.element.find('.files'),
491
+ eventData = {fileupload: this};
492
+ filesList.find('.start button')
493
+ .live(
494
+ 'click.' + this.options.namespace,
495
+ eventData,
496
+ this._startHandler
497
+ );
498
+ filesList.find('.cancel button')
499
+ .live(
500
+ 'click.' + this.options.namespace,
501
+ eventData,
502
+ this._cancelHandler
503
+ );
504
+ filesList.find('.delete button')
505
+ .live(
506
+ 'click.' + this.options.namespace,
507
+ eventData,
508
+ this._deleteHandler
509
+ );
510
+ },
511
+
512
+ _destroyEventHandlers: function () {
513
+ var filesList = this.element.find('.files');
514
+ filesList.find('.start button')
515
+ .die('click.' + this.options.namespace);
516
+ filesList.find('.cancel button')
517
+ .die('click.' + this.options.namespace);
518
+ filesList.find('.delete button')
519
+ .die('click.' + this.options.namespace);
520
+ $.blueimp.fileupload.prototype._destroyEventHandlers.call(this);
521
+ },
522
+
523
+ _initFileUploadButtonBar: function () {
524
+ var fileUploadButtonBar = this.element.find('.fileupload-buttonbar'),
525
+ filesList = this.element.find('.files'),
526
+ ns = this.options.namespace;
527
+ fileUploadButtonBar
528
+ .addClass('ui-widget-header ui-corner-top');
529
+ this.element.find('.fileinput-button').each(function () {
530
+ var fileInput = $(this).find('input:file').detach();
531
+ $(this).button({icons: {primary: 'ui-icon-plusthick'}})
532
+ .append(fileInput);
533
+ });
534
+ fileUploadButtonBar.find('.start')
535
+ .button({icons: {primary: 'ui-icon-circle-arrow-e'}})
536
+ .bind('click.' + ns, function (e) {
537
+ e.preventDefault();
538
+ filesList.find('.start button').click();
539
+ });
540
+ fileUploadButtonBar.find('.cancel')
541
+ .button({icons: {primary: 'ui-icon-cancel'}})
542
+ .bind('click.' + ns, function (e) {
543
+ e.preventDefault();
544
+ filesList.find('.cancel button').click();
545
+ });
546
+ fileUploadButtonBar.find('.delete')
547
+ .button({icons: {primary: 'ui-icon-trash'}})
548
+ .bind('click.' + ns, function (e) {
549
+ e.preventDefault();
550
+ filesList.find('.delete button').click();
551
+ });
552
+ },
553
+
554
+ _destroyFileUploadButtonBar: function () {
555
+ this.element.find('.fileupload-buttonbar')
556
+ .removeClass('ui-widget-header ui-corner-top');
557
+ this.element.find('.fileinput-button').each(function () {
558
+ var fileInput = $(this).find('input:file').detach();
559
+ $(this).button('destroy')
560
+ .append(fileInput);
561
+ });
562
+ this.element.find('.fileupload-buttonbar button')
563
+ .unbind('click.' + this.options.namespace)
564
+ .button('destroy');
565
+ },
566
+
567
+ _enableFileInputButton: function () {
568
+ this.element.find('.fileinput-button input:file:disabled')
569
+ .each(function () {
570
+ var fileInput = $(this),
571
+ button = fileInput.parent();
572
+ fileInput.detach().prop('disabled', false);
573
+ button.button('enable').append(fileInput);
574
+ });
575
+ },
576
+
577
+ _disableFileInputButton: function () {
578
+ this.element.find('.fileinput-button input:file:enabled')
579
+ .each(function () {
580
+ var fileInput = $(this),
581
+ button = fileInput.parent();
582
+ fileInput.detach().prop('disabled', true);
583
+ button.button('disable').append(fileInput);
584
+ });
585
+ },
586
+
587
+ _initTemplates: function () {
588
+ // Handle cases where the templates are defined
589
+ // after the widget library has been included:
590
+ if (this.options.uploadTemplate instanceof $ &&
591
+ !this.options.uploadTemplate.length) {
592
+ this.options.uploadTemplate = $(
593
+ this.options.uploadTemplate.selector
594
+ );
595
+ }
596
+ if (this.options.downloadTemplate instanceof $ &&
597
+ !this.options.downloadTemplate.length) {
598
+ this.options.downloadTemplate = $(
599
+ this.options.downloadTemplate.selector
600
+ );
601
+ }
602
+ },
603
+
604
+ _create: function () {
605
+ $.blueimp.fileupload.prototype._create.call(this);
606
+ this._initTemplates();
607
+ this.element
608
+ .addClass('ui-widget');
609
+ this._initFileUploadButtonBar();
610
+ this.element.find('.fileupload-content')
611
+ .addClass('ui-widget-content ui-corner-bottom');
612
+ this.element.find('.fileupload-progressbar')
613
+ .hide().progressbar();
614
+ },
615
+
616
+ destroy: function () {
617
+ this.element.find('.fileupload-progressbar')
618
+ .progressbar('destroy');
619
+ this.element.find('.fileupload-content')
620
+ .removeClass('ui-widget-content ui-corner-bottom');
621
+ this._destroyFileUploadButtonBar();
622
+ this.element.removeClass('ui-widget');
623
+ $.blueimp.fileupload.prototype.destroy.call(this);
624
+ },
625
+
626
+ enable: function () {
627
+ $.blueimp.fileupload.prototype.enable.call(this);
628
+ this.element.find(':ui-button').not('.fileinput-button')
629
+ .button('enable');
630
+ this._enableFileInputButton();
631
+ },
632
+
633
+ disable: function () {
634
+ this.element.find(':ui-button').not('.fileinput-button')
635
+ .button('disable');
636
+ this._disableFileInputButton();
637
+ $.blueimp.fileupload.prototype.disable.call(this);
638
+ }
639
+
640
+ });
641
+
642
+ }(jQuery));