annotate e2gallerypro/e2upload/Source/Uploader/Swiff.Uploader.js @ 20:1038db2374ec judyates

change address
author Robert McIntyre <rlm@mit.edu>
date Sun, 08 Sep 2013 00:47:09 -0400
parents 3f6b44aa6b35
children
rev   line source
rlm@3 1 /**
rlm@3 2 * Swiff.Uploader - Flash FileReference Control
rlm@3 3 *
rlm@3 4 * @version 3.0 rc1
rlm@3 5 *
rlm@3 6 * @license MIT License
rlm@3 7 *
rlm@3 8 * @author Harald Kirschner <mail [at] digitarald [dot] de>
rlm@3 9 * @copyright Authors
rlm@3 10 */
rlm@3 11
rlm@3 12 Swiff.Uploader = new Class({
rlm@3 13
rlm@3 14 Extends: Swiff,
rlm@3 15
rlm@3 16 Implements: Events,
rlm@3 17
rlm@3 18 options: {
rlm@3 19 path: 'Swiff.Uploader.swf',
rlm@3 20
rlm@3 21 target: null,
rlm@3 22 zIndex: 9999,
rlm@3 23
rlm@3 24 height: 30,
rlm@3 25 width: 100,
rlm@3 26 callBacks: null,
rlm@3 27 params: {
rlm@3 28 wMode: 'opaque',
rlm@3 29 menu: 'false',
rlm@3 30 allowScriptAccess: 'always'
rlm@3 31 },
rlm@3 32
rlm@3 33 typeFilter: null,
rlm@3 34 multiple: true,
rlm@3 35 queued: true,
rlm@3 36 verbose: false,
rlm@3 37
rlm@3 38 url: null,
rlm@3 39 method: null,
rlm@3 40 data: null,
rlm@3 41 mergeData: true,
rlm@3 42 fieldName: null,
rlm@3 43
rlm@3 44 fileSizeMin: 1,
rlm@3 45 fileSizeMax: null, // Official limit is 100 MB for FileReference!
rlm@3 46 allowDuplicates: false,
rlm@3 47
rlm@3 48 buttonImage: null,
rlm@3 49
rlm@3 50 fileListMax: 0,
rlm@3 51 fileListSizeMax: 0,
rlm@3 52
rlm@3 53 instantStart: false,
rlm@3 54 appendCookieData: false,
rlm@3 55
rlm@3 56 fileClass: null
rlm@3 57 /*
rlm@3 58 onLoad: $empty,
rlm@3 59 onFail: $empty,
rlm@3 60 onStart: $empty,
rlm@3 61 onQueue: $empty,
rlm@3 62 onComplete: $empty,
rlm@3 63 onBrowse: $empty,
rlm@3 64 onDisabledBrowse: $empty,
rlm@3 65 onCancel: $empty,
rlm@3 66 onSelect: $empty,
rlm@3 67 onSelectSuccess: $empty,
rlm@3 68 onSelectFail: $empty,
rlm@3 69
rlm@3 70 onButtonEnter: $empty,
rlm@3 71 onButtonLeave: $empty,
rlm@3 72 onButtonDown: $empty,
rlm@3 73 onButtonDisable: $empty,
rlm@3 74
rlm@3 75 onFileStart: $empty,
rlm@3 76 onFileStop: $empty,
rlm@3 77 onFileRequeue: $empty,
rlm@3 78 onFileOpen: $empty,
rlm@3 79 onFileProgress: $empty,
rlm@3 80 onFileComplete: $empty,
rlm@3 81 onFileRemove: $empty
rlm@3 82 */
rlm@3 83 },
rlm@3 84
rlm@3 85 initialize: function(options) {
rlm@3 86 // protected events to control the class, added
rlm@3 87 // before setting options (which adds own events)
rlm@3 88 this.addEvent('load', this.initializeSwiff, true)
rlm@3 89 .addEvent('select', this.processFiles, true)
rlm@3 90 .addEvent('complete', this.update, true)
rlm@3 91 .addEvent('fileRemove', function(file) {
rlm@3 92 this.fileList.erase(file);
rlm@3 93 }.bind(this), true);
rlm@3 94
rlm@3 95 this.setOptions(options);
rlm@3 96
rlm@3 97 // callbacks are no longer in the options, every callback
rlm@3 98 // is fired as event, this is just compat
rlm@3 99 if (this.options.callBacks) {
rlm@3 100 Hash.each(this.options.callBacks, function(fn, name) {
rlm@3 101 this.addEvent(name, fn);
rlm@3 102 }, this);
rlm@3 103 }
rlm@3 104
rlm@3 105 this.options.callBacks = {
rlm@3 106 fireCallback: this.fireCallback.bind(this)
rlm@3 107 };
rlm@3 108
rlm@3 109 var path = this.options.path;
rlm@3 110 if (!path.contains('?')) path += '?noCache=' + $time(); // cache in IE
rlm@3 111
rlm@3 112 // container options for Swiff class
rlm@3 113 this.options.container = this.box = new Element('span', {'class': 'swiff-uploader-box'}).inject($(this.options.container) || document.body);
rlm@3 114
rlm@3 115 // target
rlm@3 116 this.target = $(this.options.target);
rlm@3 117 if (this.target) {
rlm@3 118 var scroll = window.getScroll();
rlm@3 119 this.box.setStyles({
rlm@3 120 position: 'absolute',
rlm@3 121 visibility: 'visible',
rlm@3 122 zIndex: this.options.zIndex,
rlm@3 123 overflow: 'hidden',
rlm@3 124 height: 1, width: 1,
rlm@3 125 top: scroll.y, left: scroll.x
rlm@3 126 });
rlm@3 127
rlm@3 128 // we force wMode to transparent for the overlay effect
rlm@3 129 this.parent(path, {
rlm@3 130 params: {
rlm@3 131 wMode: 'transparent'
rlm@3 132 },
rlm@3 133 height: '100%',
rlm@3 134 width: '100%'
rlm@3 135 });
rlm@3 136
rlm@3 137 this.target.addEvent('mouseenter', this.reposition.bind(this, []));
rlm@3 138
rlm@3 139 // button interactions, relayed to to the target
rlm@3 140 this.addEvents({
rlm@3 141 buttonEnter: this.targetRelay.bind(this, ['mouseenter']),
rlm@3 142 buttonLeave: this.targetRelay.bind(this, ['mouseleave']),
rlm@3 143 buttonDown: this.targetRelay.bind(this, ['mousedown']),
rlm@3 144 buttonDisable: this.targetRelay.bind(this, ['disable'])
rlm@3 145 });
rlm@3 146
rlm@3 147 this.reposition();
rlm@3 148 window.addEvent('resize', this.reposition.bind(this, []));
rlm@3 149 } else {
rlm@3 150 this.parent(path);
rlm@3 151 }
rlm@3 152
rlm@3 153 this.inject(this.box);
rlm@3 154
rlm@3 155 this.fileList = [];
rlm@3 156
rlm@3 157 this.size = this.uploading = this.bytesLoaded = this.percentLoaded = 0;
rlm@3 158
rlm@3 159 if (Browser.Plugins.Flash.version < 9) {
rlm@3 160 this.fireEvent('fail', ['flash']);
rlm@3 161 } else {
rlm@3 162 this.verifyLoad.delay(500, this);
rlm@3 163 }
rlm@3 164 },
rlm@3 165
rlm@3 166 verifyLoad: function() {
rlm@3 167 if (this.loaded) return;
rlm@3 168 if (!this.object.parentNode) {
rlm@3 169 this.fireEvent('fail', ['disabled']);
rlm@3 170 } else if (this.object.style.display == 'none') {
rlm@3 171 this.fireEvent('fail', ['hidden']);
rlm@3 172 } else if (!this.object.offsetWidth) {
rlm@3 173 this.fireEvent('fail', ['empty']);
rlm@3 174 }
rlm@3 175 },
rlm@3 176
rlm@3 177 fireCallback: function(name, args) {
rlm@3 178 // file* callbacks are relayed to the specific file
rlm@3 179 if (name.substr(0, 4) == 'file') {
rlm@3 180 // updated queue data is the second argument
rlm@3 181 if (args.length > 1) this.update(args[1]);
rlm@3 182 var data = args[0];
rlm@3 183
rlm@3 184 var file = this.findFile(data.id);
rlm@3 185 this.fireEvent(name, file || data, 5);
rlm@3 186 if (file) {
rlm@3 187 var fire = name.replace(/^file([A-Z])/, function($0, $1) {
rlm@3 188 return $1.toLowerCase();
rlm@3 189 });
rlm@3 190 file.update(data).fireEvent(fire, [data], 10);
rlm@3 191 }
rlm@3 192 } else {
rlm@3 193 this.fireEvent(name, args, 5);
rlm@3 194 }
rlm@3 195 },
rlm@3 196
rlm@3 197 update: function(data) {
rlm@3 198 // the data is saved right to the instance
rlm@3 199 $extend(this, data);
rlm@3 200 this.fireEvent('queue', [this], 10);
rlm@3 201 return this;
rlm@3 202 },
rlm@3 203
rlm@3 204 findFile: function(id) {
rlm@3 205 for (var i = 0; i < this.fileList.length; i++) {
rlm@3 206 if (this.fileList[i].id == id) return this.fileList[i];
rlm@3 207 }
rlm@3 208 return null;
rlm@3 209 },
rlm@3 210
rlm@3 211 initializeSwiff: function() {
rlm@3 212 // extracted options for the swf
rlm@3 213 this.remote('initialize', {
rlm@3 214 width: this.options.width,
rlm@3 215 height: this.options.height,
rlm@3 216 typeFilter: this.options.typeFilter,
rlm@3 217 multiple: this.options.multiple,
rlm@3 218 queued: this.options.queued,
rlm@3 219 url: this.options.url,
rlm@3 220 method: this.options.method,
rlm@3 221 data: this.options.data,
rlm@3 222 mergeData: this.options.mergeData,
rlm@3 223 fieldName: this.options.fieldName,
rlm@3 224 verbose: this.options.verbose,
rlm@3 225 fileSizeMin: this.options.fileSizeMin,
rlm@3 226 fileSizeMax: this.options.fileSizeMax,
rlm@3 227 allowDuplicates: this.options.allowDuplicates,
rlm@3 228 buttonImage: this.options.buttonImage
rlm@3 229 });
rlm@3 230
rlm@3 231 this.loaded = true;
rlm@3 232
rlm@3 233 this.appendCookieData();
rlm@3 234 },
rlm@3 235
rlm@3 236 targetRelay: function(name) {
rlm@3 237 if (this.target) this.target.fireEvent(name);
rlm@3 238 },
rlm@3 239
rlm@3 240 reposition: function(coords) {
rlm@3 241 // update coordinates, manual or automatically
rlm@3 242 coords = coords || (this.target && this.target.offsetHeight)
rlm@3 243 ? this.target.getCoordinates(this.box.getOffsetParent())
rlm@3 244 : {top: window.getScrollTop(), left: 0, width: 40, height: 40}
rlm@3 245 this.box.setStyles(coords);
rlm@3 246 this.fireEvent('reposition', [coords, this.box, this.target]);
rlm@3 247 },
rlm@3 248
rlm@3 249 setOptions: function(options) {
rlm@3 250 if (options) {
rlm@3 251 if (options.url) options.url = Swiff.Uploader.qualifyPath(options.url);
rlm@3 252 if (options.buttonImage) options.buttonImage = Swiff.Uploader.qualifyPath(options.buttonImage);
rlm@3 253 this.parent(options);
rlm@3 254 if (this.loaded) this.remote('setOptions', options);
rlm@3 255 }
rlm@3 256 return this;
rlm@3 257 },
rlm@3 258
rlm@3 259 setEnabled: function(status) {
rlm@3 260 this.remote('setEnabled', status);
rlm@3 261 },
rlm@3 262
rlm@3 263 start: function() {
rlm@3 264 this.remote('start');
rlm@3 265 },
rlm@3 266
rlm@3 267 stop: function() {
rlm@3 268 this.remote('stop');
rlm@3 269 },
rlm@3 270
rlm@3 271 remove: function() {
rlm@3 272 this.remote('remove');
rlm@3 273 },
rlm@3 274
rlm@3 275 fileStart: function(file) {
rlm@3 276 this.remote('fileStart', file.id);
rlm@3 277 },
rlm@3 278
rlm@3 279 fileStop: function(file) {
rlm@3 280 this.remote('fileStop', file.id);
rlm@3 281 },
rlm@3 282
rlm@3 283 fileRemove: function(file) {
rlm@3 284 this.remote('fileRemove', file.id);
rlm@3 285 },
rlm@3 286
rlm@3 287 fileRequeue: function(file) {
rlm@3 288 this.remote('fileRequeue', file.id);
rlm@3 289 },
rlm@3 290
rlm@3 291 appendCookieData: function() {
rlm@3 292 var append = this.options.appendCookieData;
rlm@3 293 if (!append) return;
rlm@3 294
rlm@3 295 var hash = {};
rlm@3 296 document.cookie.split(/;\s*/).each(function(cookie) {
rlm@3 297 cookie = cookie.split('=');
rlm@3 298 if (cookie.length == 2) {
rlm@3 299 hash[decodeURIComponent(cookie[0])] = decodeURIComponent(cookie[1]);
rlm@3 300 }
rlm@3 301 });
rlm@3 302
rlm@3 303 var data = this.options.data || {};
rlm@3 304 if ($type(append) == 'string') data[append] = hash;
rlm@3 305 else $extend(data, hash);
rlm@3 306
rlm@3 307 this.setOptions({data: data});
rlm@3 308 },
rlm@3 309
rlm@3 310 processFiles: function(successraw, failraw, queue) {
rlm@3 311 var cls = this.options.fileClass || Swiff.Uploader.File;
rlm@3 312
rlm@3 313 var fail = [], success = [];
rlm@3 314
rlm@3 315 if (successraw) {
rlm@3 316 successraw.each(function(data) {
rlm@3 317 var ret = new cls(this, data);
rlm@3 318 if (!ret.validate()) {
rlm@3 319 ret.remove.delay(10, ret);
rlm@3 320 fail.push(ret);
rlm@3 321 } else {
rlm@3 322 this.size += data.size;
rlm@3 323 this.fileList.push(ret);
rlm@3 324 success.push(ret);
rlm@3 325 ret.render();
rlm@3 326 }
rlm@3 327 }, this);
rlm@3 328
rlm@3 329 this.fireEvent('selectSuccess', [success], 10);
rlm@3 330 }
rlm@3 331
rlm@3 332 if (failraw || fail.length) {
rlm@3 333 fail.extend((failraw) ? failraw.map(function(data) {
rlm@3 334 return new cls(this, data);
rlm@3 335 }, this) : []).each(function(file) {
rlm@3 336 file.invalidate().render();
rlm@3 337 });
rlm@3 338
rlm@3 339 this.fireEvent('selectFail', [fail], 10);
rlm@3 340 }
rlm@3 341
rlm@3 342 this.update(queue);
rlm@3 343
rlm@3 344 if (this.options.instantStart && success.length) this.start();
rlm@3 345 }
rlm@3 346
rlm@3 347 });
rlm@3 348
rlm@3 349 $extend(Swiff.Uploader, {
rlm@3 350
rlm@3 351 STATUS_QUEUED: 0,
rlm@3 352 STATUS_RUNNING: 1,
rlm@3 353 STATUS_ERROR: 2,
rlm@3 354 STATUS_COMPLETE: 3,
rlm@3 355 STATUS_STOPPED: 4,
rlm@3 356
rlm@3 357 log: function() {
rlm@3 358 if (window.console && console.info) console.info.apply(console, arguments);
rlm@3 359 },
rlm@3 360
rlm@3 361 unitLabels: {
rlm@3 362 b: [{min: 1, unit: 'B'}, {min: 1024, unit: 'kB'}, {min: 1048576, unit: 'MB'}, {min: 1073741824, unit: 'GB'}],
rlm@3 363 s: [{min: 1, unit: 's'}, {min: 60, unit: 'm'}, {min: 3600, unit: 'h'}, {min: 86400, unit: 'd'}]
rlm@3 364 },
rlm@3 365
rlm@3 366 formatUnit: function(base, type, join) {
rlm@3 367 var labels = Swiff.Uploader.unitLabels[(type == 'bps') ? 'b' : type];
rlm@3 368 var append = (type == 'bps') ? '/s' : '';
rlm@3 369 var i, l = labels.length, value;
rlm@3 370
rlm@3 371 if (base < 1) return '0 ' + labels[0].unit + append;
rlm@3 372
rlm@3 373 if (type == 's') {
rlm@3 374 var units = [];
rlm@3 375
rlm@3 376 for (i = l - 1; i >= 0; i--) {
rlm@3 377 value = Math.floor(base / labels[i].min);
rlm@3 378 if (value) {
rlm@3 379 units.push(value + ' ' + labels[i].unit);
rlm@3 380 base -= value * labels[i].min;
rlm@3 381 if (!base) break;
rlm@3 382 }
rlm@3 383 }
rlm@3 384
rlm@3 385 return (join === false) ? units : units.join(join || ', ');
rlm@3 386 }
rlm@3 387
rlm@3 388 for (i = l - 1; i >= 0; i--) {
rlm@3 389 value = labels[i].min;
rlm@3 390 if (base >= value) break;
rlm@3 391 }
rlm@3 392
rlm@3 393 return (base / value).toFixed(1) + ' ' + labels[i].unit + append;
rlm@3 394 }
rlm@3 395
rlm@3 396 });
rlm@3 397
rlm@3 398 Swiff.Uploader.qualifyPath = (function() {
rlm@3 399
rlm@3 400 var anchor;
rlm@3 401
rlm@3 402 return function(path) {
rlm@3 403 (anchor || (anchor = new Element('a'))).href = path;
rlm@3 404 return anchor.href;
rlm@3 405 };
rlm@3 406
rlm@3 407 })();
rlm@3 408
rlm@3 409 Swiff.Uploader.File = new Class({
rlm@3 410
rlm@3 411 Implements: Events,
rlm@3 412
rlm@3 413 initialize: function(base, data) {
rlm@3 414 this.base = base;
rlm@3 415 this.update(data);
rlm@3 416 },
rlm@3 417
rlm@3 418 update: function(data) {
rlm@3 419 return $extend(this, data);
rlm@3 420 },
rlm@3 421
rlm@3 422 validate: function() {
rlm@3 423 var options = this.base.options;
rlm@3 424
rlm@3 425 if (options.fileListMax && this.base.fileList.length >= options.fileListMax) {
rlm@3 426 this.validationError = 'fileListMax';
rlm@3 427 return false;
rlm@3 428 }
rlm@3 429
rlm@3 430 if (options.fileListSizeMax && (this.base.size + this.size) > options.fileListSizeMax) {
rlm@3 431 this.validationError = 'fileListSizeMax';
rlm@3 432 return false;
rlm@3 433 }
rlm@3 434
rlm@3 435 return true;
rlm@3 436 },
rlm@3 437
rlm@3 438 invalidate: function() {
rlm@3 439 this.invalid = true;
rlm@3 440 this.base.fireEvent('fileInvalid', this, 10);
rlm@3 441 return this.fireEvent('invalid', this, 10);
rlm@3 442 },
rlm@3 443
rlm@3 444 render: function() {
rlm@3 445 return this;
rlm@3 446 },
rlm@3 447
rlm@3 448 setOptions: function(options) {
rlm@3 449 if (options) {
rlm@3 450 if (options.url) options.url = Swiff.Uploader.qualifyPath(options.url);
rlm@3 451 this.base.remote('fileSetOptions', this.id, options);
rlm@3 452 this.options = $merge(this.options, options);
rlm@3 453 }
rlm@3 454 return this;
rlm@3 455 },
rlm@3 456
rlm@3 457 start: function() {
rlm@3 458 this.base.fileStart(this);
rlm@3 459 return this;
rlm@3 460 },
rlm@3 461
rlm@3 462 stop: function() {
rlm@3 463 this.base.fileStop(this);
rlm@3 464 return this;
rlm@3 465 },
rlm@3 466
rlm@3 467 remove: function() {
rlm@3 468 this.base.fileRemove(this);
rlm@3 469 return this;
rlm@3 470 },
rlm@3 471
rlm@3 472 requeue: function() {
rlm@3 473 this.base.fileRequeue(this);
rlm@3 474 }
rlm@3 475
rlm@3 476 });