PageSourceSearch

https://www.materiel-agricole-eurotek.fr/js/fileuploader.js

js materiel-agricole-eurotek.fr collected 2026-09-30 12:33:50 UTC 40,057 bytes, 999 lines download raw bytes

1/**
2 * http://github.com/Valums-File-Uploader/file-uploader
3 *
4 * Multiple file upload component with progress-bar, drag-and-drop.
5 *
6 * Have ideas for improving this JS for the general community?
7 * Submit your changes at: https://github.com/Valums-File-Uploader/file-uploader
8 *
9 * VERSION 2.0 beta
10 * Original version 1.0 © 2010 Andrew Valums ( andrew(at)valums.com )
11 *
12 * Licensed under MIT license, GNU GPL 2 or later, GNU LGPL 2 or later, see license.txt.
13 */
14var qq = qq || {};
15qq.extend = function (first, second) {
16    for (var prop in second) {
17        first[prop] = second[prop];
18    }
19};
20qq.indexOf = function (arr, elt, from) {
21    if (arr.indexOf) return arr.indexOf(elt, from);
22    from = from || 0;
23    var len = arr.length;
24    if (from < 0) from += len;
25    for (; from < len; from++) {
26        if (from in arr && arr[from] === elt) {
27            return from;
28        }
29    }
30    return -1;
31};
32qq.getUniqueId = (function () {
33    var id = 0;
34    return function () {
35        return id++;
36    };
37})();
38qq.ie = function () {
39    return navigator.userAgent.indexOf('MSIE') != -1;
40}
41qq.safari = function () {
42    return navigator.vendor != undefined && navigator.vendor.indexOf("Apple") != -1;
43}
44qq.chrome = function () {
45    return navigator.vendor != undefined && navigator.vendor.indexOf('Google') != -1;
46}
47qq.firefox = function () {
48    return (navigator.userAgent.indexOf('Mozilla') != -1 && navigator.vendor != undefined && navigator.vendor == '');
49}
50qq.windows = function () {
51    return navigator.platform == "Win32";
52}
53qq.attach = function (element, type, fn) {
54    if (element.addEventListener) {
55        element.addEventListener(type, fn, false);
56    } else if (element.attachEvent) {
57        element.attachEvent('on' + type, fn);
58    }
59    return function () {
60        qq.detach(element, type, fn)
61    }
62};
63qq.detach = function (element, type, fn) {
64    if (element.removeEventListener) {
65        element.removeEventListener(type, fn, false);
66    } else if (element.attachEvent) {
67        element.detachEvent('on' + type, fn);
68    }
69};
70qq.preventDefault = function (e) {
71    if (e.preventDefault) {
72        e.preventDefault();
73    } else {
74        e.returnValue = false;
75    }
76};
77qq.insertBefore = function (a, b) {
78    b.parentNode.insertBefore(a, b);
79};
80qq.remove = function (element) {
81    element.parentNode.removeChild(element);
82};
83qq.contains = function (parent, descendant) {
84    if (parent == descendant) return true;
85    if (parent.contains) {
86        return parent.contains(descendant);
87    } else {
88        return !!(descendant.compareDocumentPosition(parent) & 8);
89    }
90};
91qq.toElement = (function () {
92    var div = document.createElement('div');
93    return function (html) {
94        div.innerHTML = html;
95        var element = div.firstChild;
96        div.removeChild(element);
97        return element;
98    };
99})();
100qq.css = function (element, styles) {
101    if (styles.opacity != null) {
102        if (typeof element.style.opacity != 'string' && typeof(element.filters) != 'undefined') {
103            styles.filter = 'alpha(opacity=' + Math.round(100 * styles.opacity) + ')';
104        }
105    }
106    qq.extend(element.style, styles);
107};
108qq.hasClass = function (element, name) {
109    var re = new RegExp('(^| )' + name + '( |$)');
110    return re.test(element.className);
111};
112qq.addClass = function (element, name) {
113    if (!qq.hasClass(element, name)) {
114        element.className += ' ' + name;
115    }
116};
117qq.removeClass = function (element, name) {
118    var re = new RegExp('(^| )' + name + '( |$)');
119    element.className = element.className.replace(re, ' ').replace(/^\s+|\s+$/g, "");
120};
121qq.setText = function (element, text) {
122    element.innerText = text;
123    element.textContent = text;
124};
125qq.children = function (element) {
126    var children = [], child = element.firstChild;
127    while (child) {
128        if (child.nodeType == 1) {
129            children.push(child);
130        }
131        child = child.nextSibling;
132    }
133    return children;
134};
135qq.getByClass = function (element, className) {
136    if (element.querySelectorAll) {
137        return element.querySelectorAll('.' + className);
138    }
139    var result = [];
140    var candidates = element.getElementsByTagName("*");
141    var len = candidates.length;
142    for (var i = 0; i < len; i++) {
143        if (qq.hasClass(candidates[i], className)) {
144            result.push(candidates[i]);
145        }
146    }
147    return result;
148};
149qq.obj2url = function (obj, temp, prefixDone) {
150    var uristrings = [], prefix = '&', add = function (nextObj, i) {
151        var nextTemp = temp ? (/\[\]$/.test(temp)) ? temp : temp + '[' + i + ']' : i;
152        if ((nextTemp != 'undefined') && (i != 'undefined')) {
153            uristrings.push((typeof nextObj === 'object') ? qq.obj2url(nextObj, nextTemp, true) : (Object.prototype.toString.call(nextObj) === '[object Function]') ? encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj()) : encodeURIComponent(nextTemp) + '=' + encodeURIComponent(nextObj));
154        }
155    };
156    if (!prefixDone && temp) {
157        prefix = (/\?/.test(temp)) ? (/\?$/.test(temp)) ? '' : '&' : '?';
158        uristrings.push(temp);
159        uristrings.push(qq.obj2url(obj));
160    } else if ((Object.prototype.toString.call(obj) === '[object Array]') && (typeof obj != 'undefined')) {
161        for (var i = 0, len = obj.length; i < len; ++i) {
162            add(obj[i], i);
163        }
164    } else if ((typeof obj != 'undefined') && (obj !== null) && (typeof obj === "object")) {
165        for (var i in obj) {
166            add(obj[i], i);
167        }
168    } else {
169        uristrings.push(encodeURIComponent(temp) + '=' + encodeURIComponent(obj));
170    }
171    return uristrings.join(prefix).replace(/^&/, '').replace(/%20/g, '+');
172};
173var qq = qq || {};
174qq.FileUploaderBasic = function (o) {
175    var that = this;
176    this._options = {
177        debug: false,
178        action: '/server/upload',
179        params: {},
180        customHeaders: {},
181        button: null,
182        multiple: true,
183        maxConnections: 3,
184        disableCancelForFormUploads: false,
185        autoUpload: true,
186        allowedExtensions: [],
187        acceptFiles: null,
188        sizeLimit: 0,
189        minSizeLimit: 0,
190        onSubmit: function (id, fileName) {
191        },
192        onComplete: function (id, fileName, responseJSON) {
193        },
194        onCancel: function (id, fileName) {
195        },
196        onUpload: function (id, fileName, xhr) {
197        },
198        onProgress: function (id, fileName, loaded, total) {
199        },
200        onError: function (id, fileName, xhr) {
201        },
202        messages: {
203            typeError: "{file}
203 has an invalid extension. Only {extensions} {isAre} allowed.",
204            sizeError: "{file} is too large, maximum file size is {sizeLimit}.",
205            minSizeError: "{file} is too small, minimum file size is {minSizeLimit}.",
206            emptyError: "{file} is empty, please select files again without it.",
207            noFilesError: "No files to upload.",
208            onLeave: "The files are being uploaded, if you leave now the upload will be cancelled."
209        },
210        showMessage: function (message) {
211            alert(message);
212        },
213        inputName: 'qqfile',
214        extraDropzones: []
215    };
216    qq.extend(this._options, o);
217    qq.extend(this, qq.DisposeSupport);
218    this._filesInProgress = 0;
219    this._storedFileIds = [];
220    this._handler = this._createUploadHandler();
221    if (this._options.button) {
222        this._button = this._createUploadButton(this._options.button);
223    }
224    this._preventLeaveInProgress();
225};
226qq.FileUploaderBasic.prototype = {
227    setParams: function (params) {
228        this._options.params = params;
229    }, getInProgress: function () {
230        return this._filesInProgress;
231    }, uploadStoredFiles: function () {
232        for (var i = 0; i < this._storedFileIds.length; i++) {
233            this._filesInProgress++;
234            this._handler.upload(this._storedFileIds[i], this._options.params);
235        }
236    }, clearStoredFiles: function () {
237        this._storedFileIds = [];
238    }, _createUploadButton: function (element) {
239        var self = this;
240        var button = new qq.UploadButton({
241            element: element,
242            multiple: this._options.multiple && qq.UploadHandlerXhr.isSupported(),
243            acceptFiles: this._options.acceptFiles,
244            onChange: function (input) {
245                self._onInputChange(input);
246            }
247        });
248        this.addDisposer(function () {
249            button.dispose();
250        });
251        return button;
252    }, _createUploadHandler: function () {
253        var self = this, handlerClass;
254        if (qq.UploadHandlerXhr.isSupported()) {
255            handlerClass = 'UploadHandlerXhr';
256        } else {
257            handlerClass = 'UploadHandlerForm';
258        }
259        var handler = new qq[handlerClass]({
260            debug: this._options.debug,
261            action: this._options.action,
262            encoding: this._options.encoding,
263            maxConnections: this._options.maxConnections,
264            customHeaders: this._options.customHeaders,
265            inputName: this._options.inputName,
266            extraDropzones: this._options.extraDropzones,
267            demoMode: this._options.demoMode,
268            onProgress: function (id, fileName, loaded, total) {
269                self._onProgress(id, fileName, loaded, total);
270                self._options.onProgress(id, fileName, loaded, total);
271            },
272            onComplete: function (id, fileName, result) {
273                self._onComplete(id, fileName, result);
274                self._options.onComplete(id, fileName, result);
275            },
276            onCancel: function (id, fileName) {
277                var indexToRemove = self._storedFileIds.indexOf(id);
278                if (indexToRemove >= 0) {
279                    self._storedFileIds.splice(indexToRemove, 1);
280                }
281                self._onCancel(id, fileName);
282                self._options.onCancel(id, fileName);
283            },
284            onError: self._options.onError,
285            onUpload: function (id, fileName, xhr) {
286                self._onUpload(id, fileName, xhr);
287                self._options.onUpload(id, fileName, xhr);
288            }
289        });
290        return handler;
291    }, _preventLeaveInProgress: function () {
292        var self = this;
293        this._attach(window, 'beforeunload', function (e) {
294            if (!self._filesInProgress) {
295                return;
296            }
297            var e = e || window.event;
298            e.returnValue = self._options.messages.onLeave;
299            return self._options.messages.onLeave;
300        });
301    }, _onSubmit: function (id, fileName) {
302        if (this._options.autoUpload) {
303            this._filesInProgress++;
304        }
305    }, _onProgress: function (id, fileName, loaded, total) {
306    }, _onComplete: function (id, fileName, result) {
307        var indexToRemove = this._storedFileIds.indexOf(id);
308        if (indexToRemove >= 0) {
309            this._storedFileIds.splice(indexToRemove, 1);
310        }
311        this._filesInProgress--;
312        if (result.error) {
313            this._options.showMessage(result.error);
314        }
315    }, _onCancel: function (id, fileName) {
316        if (this._options.autoUpload) {
317            this._filesInProgress--;
318        }
319    }, _onUpload: function (id, fileName, xhr) {
320    }, _onInputChange: function (input) {
321        if (this._handler instanceof qq.UploadHandlerXhr) {
322            this._uploadFileList(input.files);
323        } else {
324            if (this._validateFile(input)) {
325                this._uploadFile(input);
326            }
327        }
328        this._button.reset();
329    }, _uploadFileList: function (files) {
330        if (files.length > 0) {
331            for (var i = 0; i < files.length; i++) {
332                if (!this._validateFile(files[i])) {
333                    return;
334                }
335            }
336            for (var i = 0; i < files.length; i++) {
337                this._uploadFile(files[i]);
338            }
339        }
340        else {
341            this._error('noFilesError', "");
342        }
343    }, _uploadFile: function (fileContainer) {
344        var id = this._handler.add(fileContainer);
345        var fileName = this._handler.getName(id);
346        if (this._options.onSubmit(id, fileName) !== false) {
347            this._onSubmit(id, fileName);
348            if (this._options.autoUpload) {
349                this._handler.upload(id, this._options.params);
350            }
351            else {
352                this._storeFileForLater(id);
353            }
354        }
355    }, _storeFileForLater: function (id) {
356        this._storedFileIds.push(id);
357    }, _validateFile: function (file) {
358        var name, size;
359        if (file.value) {
360            name = file.value.replace(/.*(\/|\\)/, "");
361        } else {
362            name = (file.fileName !== null && file.fileName !== undefined) ? file.fileName : file.name;
363            size = (file.fileSize !== null && file.fileSize !== undefined) ? file.fileSize : file.size;
364        }
365        if (!this._isAllowedExtension(name)) {
366            this._error('typeError', name);
367            return false;
368        } else if (size === 0) {
369            this._error('emptyError', name);
370            return false;
371        } else if (size && this._options.sizeLimit && size > this._options.sizeLimit) {
372            this._error('sizeError', name);
373            return false;
374        } else if (size && size < this._options.minSizeLimit) {
375            this._error('minSizeError', name);
376            return false;
377        }
378        return true;
379    }, _error: function (code, fileName) {
380        var message = this._options.messages[code];
381
382        function r(name, replacement) {
383            message = message.replace(name, replacement);
384        }
385
386        var extensions = this._options.allowedExtensions.join(', ');
387        r('{file}', this._formatFileName(fileName));
388        r('{extensions}', extensions);
389        r('{sizeLimit}', this._formatSize(this._options.sizeLimit));
390        r('{minSizeLimit}', this._formatSize(this._options.minSizeLimit));
391        r('{isAre}', extensions.indexOf(",") != -1 ? "are" : "is");
392        this._options.showMessage(message);
393    }, _formatFileName: function (name) {
394        if (name.length > 33) {
395            name = name.slice(0, 19) + '...' + name.slice(-13);
396        }
397        return name;
398    }, _isAllowedExtension: function (fileName) {
399        var ext = (-1 !== fileName.indexOf('.')) ? fileName.replace(/.*[.]/, '').toLowerCase() : '';
400        var allowed = this._options.allowedExtensions;
401        if (!allowed.length) {
402            return true;
403        }
404        for (var i = 0; i < allowed.length; i++) {
405            if (allowed[i].toLowerCase() == ext) {
406                return true;
407            }
408        }
409        return false;
410    }, _formatSize: function (bytes) {
411        var i = -1;
412        do {
413            bytes = bytes / 1024;
414            i++;
415        } while (bytes > 99);
416        return Math.max(bytes, 0.1).toFixed(1) + ['kB', 'MB', 'GB', 'TB', 'PB', 'EB'][i];
417    }
418};
419qq.FileUploader = function (o) {
420    qq.FileUploaderBasic.apply(this, arguments);
421    qq.extend(this._options, {
422        element: null,
423        listElement: null,
424        dragText: 'Drop files here to upload',
425        uploadButtonText: 'Upload a file',
426        cancelButtonText: 'Cancel',
427        failUploadText: 'Upload failed',
428        template: '<div class="qq-uploader">' + '<div class="qq-upload-drop-area"><span>{dragText}</span></div>' + '<div class="qq-upload-button">{uploadButtonText}</div>' + '<ul class="qq-upload-list"></ul>' + '</div>',
429        fileTemplate: '<li>' + '<span class="qq-progress-bar"></span>' + '<span class="qq-upload-spinner"></span>' + '<span class="qq-upload-finished"></span>' + '<span class="qq-upload-file"></span>' + '<span class="qq-upload-size"></span>' + '<a class="qq-upload-cancel" href="#">{cancelButtonText}</a>' + '<span class="qq-upload-failed-text">{failUploadtext}</span>' + '</li>',
430        classes: {
431            button: 'qq-upload-button',
432            drop: 'qq-upload-drop-area',
433            dropActive: 'qq-upload-drop-area-active',
434            dropDisabled: 'qq-upload-drop-area-disabled',
435            list: 'qq-upload-list',
436            progressBar: 'qq-progress-bar',
437            file: 'qq-upload-file',
438            spinner: 'qq-upload-spinner',
439            finished: 'qq-upload-finished',
440            size: 'qq-upload-size',
441            cancel: 'qq-upload-cancel',
442            success: 'qq-upload-success',
443            fail: 'qq-upload-fail',
444            successIcon: null,
445            failIcon: null
446        }
447    });
448    qq.extend(this._options, o);
449    this._options.template = this._options.template.replace(/\{dragText\}/g, this._options.dragText);
450    this._options.template = this._options.template.replace(/\{uploadButtonText\}/g, this._options.uploadButtonText);
451    this._options.fileTemplate = this._options.fileTemplate.replace(/\{cancelButtonText\}/g, this._options.cancelButtonText);
452    this._options.fileTemplate = this._options.fileTemplate.replace(/\{failUploadtext\}/g, this._options.failUploadText);
453    this._element = this._options.element;
454    this._element.innerHTML = this._options.template;
455    this._listElement = this._options.listElement || this._find(this._element, 'list');
456    this._classes = this._options.classes;
457    this._button = this._createUploadButton(this._find(this._element, 'button'));
458    this._bindCancelEvent();
459    this._setupDragDrop();
460};
461qq.extend(qq.FileUploader.prototype, qq.FileUploaderBasic.prototype);
462qq.extend(qq.FileUploader.prototype, {
463    clearStoredFiles: function () {
464        qq.FileUploaderBasic.prototype.clearStoredFiles.apply(this, arguments);
465        this._listElement.innerHTML = "";
466    }, addExtraDropzone: function (element) {
467        this._setupExtraDropzone(element);
468    }, removeExtraDropzone: function (element) {
469        var dzs = this._options.extraDropzones;
470        for (var i in dzs) if (dzs[i] === element) return this._options.extraDropzones.splice(i, 1);
471    }, _leaving_document_out: function (e) {
472        return ((qq.chrome() || (qq.safari() && qq.windows())) && e.clientX == 0 && e.clientY == 0) || (qq.firefox() && !e.relatedTarget);
473    }, _storeFileForLater: function (id) {
474        qq.FileUploaderBasic.prototype._storeFileForLater.apply(this, arguments);
475        var item = this._getItemByFileId(id);
476        this._find(item, 'spinner').style.display = "none";
477    }, _find: function (parent, type) {
478        var element = qq.getByClass(parent, this._options.classes[type])[0];
479        if (!element) {
480            throw new Error('element not found ' + type);
481        }
482        return element;
483    }, _setupExtraDropzone: function (element) {
484        this._options.extraDropzones.push(element);
485        this._setupDropzone(element);
486    }, _setupDropzone: function (dropArea) {
487        var self = this;
488        var dz = new qq.UploadDropZone({
489            element: dropArea, onEnter: function (e) {
490                qq.addClass(dropArea, self._classes.dropActive);
491                e.stopPropagation();
492            }, onLeave: function (e) {
493            }, onLeaveNotDescendants: function (e) {
494                qq.removeClass(dropArea, self._classes.dropActive);
495            }, onDrop: function (e) {
496                dropArea.style.display = 'none';
497                qq.removeClass(dropArea, self._classes.dropActive);
498                self._uploadFileList(e.dataTransfer.files);
499            }
500        });
501        this.addDisposer(function () {
502            dz.dispose();
503        });
504        dropArea.style.display = 'none';
505    }, _setupDragDrop: function () {
506        var dropArea = this._find(this._element, 'drop');
507        var self = this;
508        this._options.extraDropzones.push(dropArea);
509        var dropzones = this._options.extraDropzones;
510        var i;
511        for (i = 0; i < dropzones.length; i++) {
512            this._setupDropzone(dropzones[i]);
513        }
514        if (!qq.ie()) {
515            this._attach(document, 'dragenter', function (e) {
516                if (qq.hasClass(dropArea, self._classes.dropDisabled)) return;
517                dropArea.style.display = 'block';
518                for (i = 0; i < dropzones.length; i++) {
519                    dropzones[i].style.display = 'block';
520                }
521            });
522        }
523        this._attach(document, 'dragleave', function (e) {
524            var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
525            if (qq.FileUploader.prototype._leaving_document_out(e)) {
526                for (i = 0; i < dropzones.length; i++) {
527                    dropzones[i].style.display = 'none';
528                }
529            }
530        });
531        qq.attach(document, 'drop', function (e) {
532            for (i = 0; i < dropzones.length; i++) {
533                dropzones[i].style.display = 'none';
534            }
535            e.preventDefault();
536        });
537    }, _onSubmit: function (id, fileName) {
538        qq.FileUploaderBasic.prototype._onSubmit.apply(this, arguments);
539        this._addToList(id, fileName);
540    }, _onProgress: function (id, fileName, loaded, total) {
541        qq.FileUploaderBasic.prototype._onProgress.apply(this, arguments);
542        var item = this._getItemByFileId(id);
543        if (loaded === total) {
544            var cancelLink = this._find(item, 'cancel');
545            cancelLink.style.display = 'none';
546        }
547        var size = this._find(item, 'size');
548        size.style.display = 'inline';
549        var text;
550        var percent = Math.round(loaded / total * 100);
551        if (loaded != total) {
552            text = percent + '% from ' + this._formatSize(total);
553        } else {
554            text = this._formatSize(total);
555        }
556        this._find(item, 'progressBar').style.width = percent + '%';
557        qq.setText(size, text);
558    }, _onComplete: function (id, fileName, result) {
559        qq.FileUploaderBasic.prototype._onComplete.apply(this, arguments);
560        var item = this._getItemByFileId(id);
561        if (!this._options.disableCancelForFormUploads || qq.UploadHandlerXhr.isSupported()) {
562            qq.remove(this._find(item, 'cancel'));
563        }
564        qq.remove(this._find(item, 'spinner'));
565        if (result.success) {
566            qq.addClass(item, this._classes.success);
567            if (this._classes.successIcon) {
568                this._find(item, 'finished').style.display = "inline-block";
569                qq.addClass(item, this._classes.successIcon)
570            }
571        } else {
572            var errorReason = result.reason ? result.reason : "Unknown error";
573            qq.addClass(item, this._classes.fail);
574            if (this._classes.failIcon) {
575                this._find(item, 'finished').style.display = "inline-block";
576                qq.addClass(item, this._classes.failIcon)
577            }
578            item.title = errorReason;
579        }
580    }, _addToList: function (id, fileName) {
581        var item = qq.toElement(this._options.fileTemplate);
582        if (this._options.disableCancelForFormUploads && !qq.UploadHandlerXhr.isSupported()) {
583            var cancelLink = this._find(item, 'cancel');
584            qq.remove(cancelLink);
585        }
586        item.qqFileId = id;
587        var fileElement = this._find(item, 'file');
588        qq.setText(fileElement, this._formatFileName(fileName));
589        this._find(item, 'size').style.display = 'none';
590        if (!this._options.multiple) this._clearList();
591        this._listElement.appendChild(item);
592    }, _clearList: function () {
593        this._listElement.innerHTML = '';
594        this.clearStoredFiles();
595    }, _getItemByFileId: function (id) {
596        var item = this._listElement.firstChild;
597        while (item) {
598            if (item.qqFileId == id) return item;
599            item = item.nextSibling;
600        }
601    }, _bindCancelEvent: function () {
602        var self = this, list = this._listElement;
603        this._attach(list, 'click', function (e) {
604            e = e || window.event;
605            var target = e.target || e.srcElement;
606            if (qq.hasClass(target, self._classes.cancel)) {
607                qq.preventDefault(e);
608                var item = target.parentNode;
609                self._handler.cancel(item.qqFileId);
610                qq.remove(item);
611            }
612        });
613    }
614});
615qq.UploadDropZone = function (o) {
616    this._options = {
617        element: null, onEnter: function (e) {
618        }, onLeave: function (e) {
619        }, onLeaveNotDescendants: function (e) {
620        }, onDrop: function (e) {
621        }
622    };
623    qq.extend(this._options, o);
624    qq.extend(this, qq.DisposeSupport);
625    this._element = this._options.element;
626    this._disableDropOutside();
627    this._attachEvents();
628};
629qq.UploadDropZone.prototype = {
630    _dragover_should_be_canceled: function () {
631        return qq.safari() || (qq.firefox() && qq.windows());
632    }, _disableDropOutside: function (e) {
633        if (!qq.UploadDropZone.dropOutsideDisabled) {
634            if (this._dragover_should_be_canceled) {
635                qq.attach(document, 'dragover', function (e) {
636                    e.preventDefault();
637                });
638            } else {
639                qq.attach(document, 'dragover', function (e) {
640                    if (e.dataTransfer) {
641                        e.dataTransfer.dropEffect = 'none';
642                        e.preventDefault();
643                    }
644                });
645            }
646            qq.UploadDropZone.dropOutsideDisabled = true;
647        }
648    }, _attachEvents: function () {
649        var self = this;
650        self._attach(self._element, 'dragover', function (e) {
651            if (!self._isValidFileDrag(e)) return;
652            var effect = qq.ie() ? null : e.dataTransfer.effectAllowed;
653            if (effect == 'move' || effect == 'linkMove') {
654                e.dataTransfer.dropEffect = 'move';
655            } else {
656                e.dataTransfer.dropEffect = 'copy';
657            }
658            e.stopPropagation();
659            e.preventDefault();
660        });
661        self._attach(self._element, 'dragenter', function (e) {
662            if (!self._isValidFileDrag(e)) return;
663            self._options.onEnter(e);
664        });
665        self._attach(self._element, 'dragleave', function (e) {
666            if (!self._isValidFileDrag(e)) return;
667            self._options.onLeave(e);
668            var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
669            if (qq.contains(this, relatedTarget)) return;
670            self._options.onLeaveNotDescendants(e);
671        });
672        self._attach(self._element, 'drop', function (e) {
673            if (!self._isValidFileDrag(e)) return;
674            e.preventDefault();
675            self._options.onDrop(e);
676        });
677    }, _isValidFileDrag: function (e) {
678        if (qq.ie()) return false;
679        var dt = e.dataTransfer, isSafari = qq.safari();
680        return dt && dt.effectAllowed != 'none' && (dt.files || (!isSafari && dt.types.contains && dt.types.contains('Files')));
681    }
682};
683qq.UploadButton = function (o) {
684    this._options = {
685        element: null, multiple: false, acceptFiles: null, name: 'file', onChange: function (input) {
686        }, hoverClass: 'qq-upload-button-hover', focusClass: 'qq-upload-button-focus'
687    };
688    qq.extend(this._options, o);
689    qq.extend(this, qq.DisposeSupport);
690    this._element = this._options.element;
691    qq.css(this._element, {position: 'relative', overflow: 'hidden', direction: 'ltr'});
692    this._input = this._createInput();
693};
694qq.UploadButton.prototype = {
695    getInput: function () {
696        return this._input;
697    }, reset: function () {
698        if (this._input.parentNode) {
699            qq.remove(this._input);
700        }
701        qq.removeClass(this._element, this._options.focusClass);
702        this._input = this._createInput();
703    }, _createInput: function () {
704        var input = document.createElement("input");
705        if (this._options.multiple) {
706            input.setAttribute("multiple", "multiple");
707        }
708        if (this._options.acceptFiles) input.setAttribute("accept", this._options.acceptFiles);
709        input.setAttribute("type", "file");
710        input.setAttribute("name", this._options.name);
711        qq.css(input, {
712            position: 'absolute',
713            right: 0,
714            top: 0,
715            fontFamily: 'Arial',
716            fontSize: '118px',
717            margin: 0,
718            padding: 0,
719            cursor: 'pointer',
720            opacity: 0
721        });
722        this._element.appendChild(input);
723        var self = this;
724        this._attach(input, 'change', function () {
725            self._options.onChange(input);
726        });
727        this._attach(input, 'mouseover', function () {
728            qq.addClass(self._element, self._options.hoverClass);
729        });
730        this._attach(input, 'mouseout', function () {
731            qq.removeClass(self._element, self._options.hoverClass);
732        });
733        this._attach(input, 'focus', function () {
734            qq.addClass(self._element, self._options.focusClass);
735        });
736        this._attach(input, 'blur', function () {
737            qq.removeClass(self._element, self._options.focusClass);
738        });
739        if (window.attachEvent) {
740            input.setAttribute('tabIndex', "-1");
741        }
742        return input;
743    }
744};
745qq.UploadHandlerAbstract = function (o) {
746    this._options = {
747        debug: false,
748        action: '/upload.php',
749        maxConnections: 999,
750        onProgress: function (id, fileName, loaded, total) {
751        },
752        onComplete: function (id, fileName, response) {
753        },
754        onCancel: function (id, fileName) {
755        },
756        onUpload: function (id, fileName, xhr) {
757        }
758    };
759    qq.extend(this._options, o);
760    this._queue = [];
761    this._params = [];
762};
763qq.UploadHandlerAbstract.prototype = {
764    log: function (str) {
765        if (this._options.debug && window.console) console.log('[uploader] ' + str);
766    }, add: function (file) {
767    }, upload: function (id, params) {
768        var len = this._queue.push(id);
769        var copy = {};
770        qq.extend(copy, params);
771        this._params[id] = copy;
772        if (len <= this._options.maxConnections) {
773            this._upload(id, this._params[id]);
774        }
775    }, cancel: function (id) {
776        this._cancel(id);
777        this._dequeue(id);
778    }, cancelAll: function () {
779        for (var i = 0; i < this._queue.length; i++) {
780            this._cancel(this._queue[i]);
781        }
782        this._queue = [];
783    }, getName: function (id) {
784    }, getSize: function (id) {
785    }, getQueue: function () {
786        return this._queue;
787    }, _upload: function (id) {
788    }, _cancel: function (id) {
789    }, _dequeue: function (id) {
790        var i = qq.indexOf(this._queue, id);
791        this._queue.splice(i, 1);
792        var max = this._options.maxConnections;
793        if (this._queue.length >= max && i < max) {
794            var nextId = this._queue[max - 1];
795            this._upload(nextId, this._params[nextId]);
796        }
797    }
798};
799qq.UploadHandlerForm = function (o) {
800    qq.UploadHandlerAbstract.apply(this, arguments);
801    this._inputs = {};
802    this._detach_load_events = {};
803};
804qq.extend(qq.UploadHandlerForm.prototype, qq.UploadHandlerAbstract.prototype);
805qq.extend(qq.UploadHandlerForm.prototype, {
806    add: function (fileInput) {
807        fileInput.setAttribute('name', this._options.inputName);
808        var id = 'qq-upload-handler-iframe' + qq.getUniqueId();
809        this._inputs[id] = fileInput;
810        if (fileInput.parentNode) {
811            qq.remove(fileInput);
812        }
813        return id;
814    }, getName: function (id) {
815        return this._inputs[id].value.replace(/.*(\/|\\)/, "");
816    }, _cancel: function (id) {
817        this._options.onCancel(id, this.getName(id));
818        delete this._inputs[id];
819        delete this._detach_load_events[id];
820        var iframe = document.getElementById(id);
821        if (iframe) {
822            iframe.setAttribute('src', 'javascript:false;');
823            qq.remove(iframe);
824        }
825    }, _upload: function (id, params) {
826        this._options.onUpload(id, this.getName(id), false);
827        var input = this._inputs[id];
828        if (!input) {
829            throw new Error('file with passed id was not added, or already uploaded or cancelled');
830        }
831        var fileName = this.getName(id);
832        var iframe = this._createIframe(id);
833        var form = this._createForm(iframe, params);
834        form.appendChild(input);
835        var self = this;
836        this._attachLoadEvent(iframe, function () {
837            self.log('iframe loaded');
838            var response = self._getIframeContentJSON(iframe);
839            self._options.onComplete(id, fileName, response);
840            self._dequeue(id);
841            delete self._inputs[id];
842            setTimeout(function () {
843                self._detach_load_events[id]();
844                delete self._detach_load_events[id];
845                qq.remove(iframe);
846            }, 1);
847        });
848        form.submit();
849        qq.remove(form);
850        return id;
851    }, _attachLoadEvent: function (iframe, callback) {
852        this._detach_load_events[iframe.id] = qq.attach(iframe, 'load', function () {
853            if (!iframe.parentNode) {
854                return;
855            }
856            try {
857                if (iframe.contentDocument && iframe.contentDocument.body && iframe.contentDocument.body.innerHTML == "false") {
858                    return;
859                }
860            }
861            catch (error) {
862            }
863            callback();
864        });
865    }, _getIframeContentJSON: function (iframe) {
866        try {
867            var doc = iframe.contentDocument ? iframe.contentDocument : iframe.contentWindow.document, response;
868            var innerHTML = doc.body.innerHTML;
869            this.log("converting iframe's innerHTML to JSON");
870            this.log("innerHTML = " + innerHTML);
871            if (innerHTML.slice(0, 5).toLowerCase() == '<pre>' && innerHTML.slice(-6).toLowerCase() == '</pre>') {
872                innerHTML = doc.body.firstChild.firstChild.nodeValue;
873            }
874            response = eval("(" + innerHTML + ")");
875        } catch (err) {
876            response = {success: false};
877        }
878        return response;
879    }, _createIframe: function (id) {
880        var iframe = qq.toElement('<iframe src="javascript:false;" name="' + id + '" />');
881        iframe.setAttribute('id', id);
882        iframe.style.display = 'none';
883        document.body.appendChild(iframe);
884        return iframe;
885    }, _createForm: function (iframe, params) {
886        var protocol = this._options.demoMode ? "GET" : "POST"
887        var form = qq.toElement('<form method="' + protocol + '" enctype="multipart/form-data"></form>');
888        var queryString = qq.obj2url(params, this._options.action);
889        form.setAttribute('action', queryString);
890        form.setAttribute('target', iframe.name);
891        form.style.display = 'none';
892        document.body.appendChild(form);
893        return form;
894    }
895});
896qq.UploadHandlerXhr = function (o) {
897    qq.UploadHandlerAbstract.apply(this, arguments);
898    this._files = [];
899    this._xhrs = [];
900    this._loaded = [];
901};
902qq.UploadHandlerXhr.isSupported = function () {
903    var input = document.createElement('input');
904    input.type = 'file';
905    return ('multiple' in input && typeof File != "undefined" && typeof FormData != "undefined" && typeof(new XMLHttpRequest()).upload != "undefined");
906};
907qq.extend(qq.UploadHandlerXhr.prototype, qq.UploadHandlerAbstract.prototype)
908qq.extend(qq.UploadHandlerXhr.prototype, {
909    add: function (file) {
910        if (!(file instanceof File)) {
911            throw new Error('Passed obj in not a File (in qq.UploadHandlerXhr)');
912        }
913        return this._files.push(file) - 1;
914    }, getName: function (id) {
915        var file = this._files[id];
916        return (file.fileName !== null && file.fileName !== undefined) ? file.fileName : file.name;
917    }, getSize: function (id) {
918        var file = this._files[id];
919        return file.fileSize != null ? file.fileSize : file.size;
920    }, getLoaded: function (id) {
921        return this._loaded[id] || 0;
922    }, _upload: function (id, params) {
923        this._options.onUpload(id, this.getName(id), true);
924        var file = this._files[id], name = this.getName(id), size = this.get
924Size(id);
925        this._loaded[id] = 0;
926        var xhr = this._xhrs[id] = new XMLHttpRequest();
927        var self = this;
928        xhr.upload.onprogress = function (e) {
929            if (e.lengthComputable) {
930                self._loaded[id] = e.loaded;
931                self._options.onProgress(id, name, e.loaded, e.total);
932            }
933        };
934        xhr.onreadystatechange = function () {
935            if (xhr.readyState == 4) {
936                self._onComplete(id, xhr);
937            }
938        };
939        params = params || {};
940        params[this._options.inputName] = name;
941        var queryString = qq.obj2url(params, this._options.action);
942        var protocol = this._options.demoMode ? "GET" : "POST";
943        xhr.open(protocol, queryString, true);
944        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
945        xhr.setRequestHeader("X-File-Name", encodeURIComponent(name));
946        if (this._options.encoding == 'multipart') {
947            var formData = new FormData();
948            formData.append(this._options.inputName, file);
949            file = formData;
950        } else {
951            xhr.setRequestHeader("Content-Type", "application/octet-stream");
952            xhr.setRequestHeader("X-Mime-Type", file.type);
953        }
954        for (key in this._options.customHeaders) {
955            xhr.setRequestHeader(key, this._options.customHeaders[key]);
956        }
957        ;xhr.send(file);
958    }, _onComplete: function (id, xhr) {
959        if (!this._files[id]) return;
960        var name = this.getName(id);
961        var size = this.getSize(id);
962        this._options.onProgress(id, name, size, size);
963        if (xhr.status == 200) {
964            this.log("xhr - server response received");
965            this.log("responseText = " + xhr.responseText);
966            var response;
967            try {
968                response = eval("(" + xhr.responseText + ")");
969            } catch (err) {
970                response = {};
971            }
972            this._options.onComplete(id, name, response);
973        } else {
974            this._options.onError(id, name, xhr);
975            this._options.onComplete(id, name, {});
976        }
977        this._xhrs[id] = null;
978        this._dequeue(id);
979    }, _cancel: function (id) {
980        this._options.onCancel(id, this.getName(id));
981        this._files[id] = null;
982        if (this._xhrs[id]) {
983            this._xhrs[id].abort();
984            this._xhrs[id] = null;
985        }
986    }
987});
988qq.DisposeSupport = {
989    _disposers: [], dispose: function () {
990        var disposer;
991        while (disposer = this._disposers.shift()) {
992            disposer();
993        }
994    }, addDisposer: function (disposeFunction) {
995        this._disposers.push(disposeFunction);
996    }, _attach: function () {
997        this.addDisposer(qq.attach.apply(this, arguments));
998    }
999};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.