From 8e40a69fcfe8bc799fee141fec953a2b0892dbd4 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期一, 09 十月 2023 15:54:26 +0800
Subject: [PATCH] 修改wifi扫描的交互

---
 src/pages/ai/FileUpload/common/uploader-simple.js | 1612 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 1,612 insertions(+), 0 deletions(-)

diff --git a/src/pages/ai/FileUpload/common/uploader-simple.js b/src/pages/ai/FileUpload/common/uploader-simple.js
new file mode 100644
index 0000000..b0a0d16
--- /dev/null
+++ b/src/pages/ai/FileUpload/common/uploader-simple.js
@@ -0,0 +1,1612 @@
+/*!
+ * Uploader - Uploader library implements html5 file upload and provides multiple simultaneous, stable, fault tolerant and resumable uploads
+ * @version v0.5.4
+ * @author dolymood <dolymood@gmail.com>
+ * @link https://github.com/simple-uploader/Uploader
+ * @license MIT
+ */
+!function(e){if("object"==typeof exports)module.exports=e();else if("function"==typeof define&&define.amd)define(e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Uploader=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
+    var utils = _dereq_('./utils')
+    
+    function Chunk (uploader, file, offset) {
+      utils.defineNonEnumerable(this, 'uploader', uploader)
+      utils.defineNonEnumerable(this, 'file', file)
+      utils.defineNonEnumerable(this, 'bytes', null)
+      this.offset = offset
+      this.tested = false
+      this.retries = 0
+      this.pendingRetry = false
+      this.preprocessState = 0
+      this.readState = 0
+      this.loaded = 0
+      this.total = 0
+      this.chunkSize = this.uploader.opts.chunkSize
+      this.startByte = this.offset * this.chunkSize
+      this.endByte = this.computeEndByte()
+      this.xhr = null
+    }
+    
+    var STATUS = Chunk.STATUS = {
+      PENDING: 'pending',
+      UPLOADING: 'uploading',
+      READING: 'reading',
+      SUCCESS: 'success',
+      ERROR: 'error',
+      COMPLETE: 'complete',
+      PROGRESS: 'progress',
+      RETRY: 'retry'
+    }
+    
+    utils.extend(Chunk.prototype, {
+    
+      _event: function (evt, args) {
+        args = utils.toArray(arguments)
+        args.unshift(this)
+        this.file._chunkEvent.apply(this.file, args)
+      },
+    
+      computeEndByte: function () {
+        var endByte = Math.min(this.file.size, (this.offset + 1) * this.chunkSize)
+        if (this.file.size - endByte < this.chunkSize && !this.uploader.opts.forceChunkSize) {
+          // The last chunk will be bigger than the chunk size,
+          // but less than 2 * this.chunkSize
+          endByte = this.file.size
+        }
+        return endByte
+      },
+    
+      getParams: function () {
+        return {
+          chunkNumber: this.offset + 1,
+          chunkSize: this.uploader.opts.chunkSize,
+          currentChunkSize: this.endByte - this.startByte,
+          totalSize: this.file.size,
+          identifier: this.file.uniqueIdentifier,
+          filename: this.file.name,
+          relativePath: this.file.relativePath,
+          totalChunks: this.file.chunks.length
+        }
+      },
+    
+      getTarget: function (target, params) {
+        if (!params.length) {
+          return target
+        }
+        if (target.indexOf('?') < 0) {
+          target += '?'
+        } else {
+          target += '&'
+        }
+        return target + params.join('&')
+      },
+    
+      test: function () {
+        this.xhr = new XMLHttpRequest()
+        this.xhr.addEventListener('load', testHandler, false)
+        this.xhr.addEventListener('error', testHandler, false)
+        var testMethod = utils.evalOpts(this.uploader.opts.testMethod, this.file, this)
+        var data = this.prepareXhrRequest(testMethod, true)
+        this.xhr.send(data)
+    
+        var $ = this
+        function testHandler (event) {
+          var status = $.status(true)
+          if (status === STATUS.ERROR) {
+            $._event(status, $.message())
+            $.uploader.uploadNextChunk()
+          } else if (status === STATUS.SUCCESS) {
+            $._event(status, $.message())
+            $.tested = true
+          } else if (!$.file.paused) {
+            // Error might be caused by file pause method
+            // Chunks does not exist on the server side
+            $.tested = true
+            $.send()
+          }
+        }
+      },
+    
+      preprocessFinished: function () {
+        // Compute the endByte after the preprocess function to allow an
+        // implementer of preprocess to set the fileObj size
+        this.endByte = this.computeEndByte()
+        this.preprocessState = 2
+        this.send()
+      },
+    
+      readFinished: function (bytes) {
+        this.readState = 2
+        this.bytes = bytes
+        this.send()
+      },
+    
+      send: function () {
+        var preprocess = this.uploader.opts.preprocess
+        var read = this.uploader.opts.readFileFn
+        if (utils.isFunction(preprocess)) {
+          switch (this.preprocessState) {
+            case 0:
+              this.preprocessState = 1
+              preprocess(this)
+              return
+            case 1:
+              return
+          }
+        }
+        switch (this.readState) {
+          case 0:
+            this.readState = 1
+            read(this.file, this.file.fileType, this.startByte, this.endByte, this)
+            return
+          case 1:
+            return
+        }
+        if (this.uploader.opts.testChunks && !this.tested) {
+          this.test()
+          return
+        }
+    
+        this.loaded = 0
+        this.total = 0
+        this.pendingRetry = false
+    
+        // Set up request and listen for event
+        this.xhr = new XMLHttpRequest()
+        this.xhr.upload.addEventListener('progress', progressHandler, false)
+        this.xhr.addEventListener('load', doneHandler, false)
+        this.xhr.addEventListener('error', doneHandler, false)
+    
+        var uploadMethod = utils.evalOpts(this.uploader.opts.uploadMethod, this.file, this)
+        var data = this.prepareXhrRequest(uploadMethod, false, this.uploader.opts.method, this.bytes)
+        this.xhr.send(data)
+    
+        var $ = this
+        function progressHandler (event) {
+          if (event.lengthComputable) {
+            $.loaded = event.loaded
+            $.total = event.total
+          }
+          $._event(STATUS.PROGRESS, event)
+        }
+    
+        function doneHandler (event) {
+          var msg = $.message()
+          $.processingResponse = true
+          $.uploader.opts.processResponse(msg, function (err, res) {
+            $.processingResponse = false
+            if (!$.xhr) {
+              return
+            }
+            $.processedState = {
+              err: err,
+              res: res
+            }
+            var status = $.status()
+            if (status === STATUS.SUCCESS || status === STATUS.ERROR) {
+              delete this.data
+              $._event(status, res)
+              status === STATUS.ERROR && $.uploader.uploadNextChunk()
+            } else {
+              $._event(STATUS.RETRY, res)
+              $.pendingRetry = true
+              $.abort()
+              $.retries++
+              var retryInterval = $.uploader.opts.chunkRetryInterval
+              if (retryInterval !== null) {
+                setTimeout(function () {
+                  $.send()
+                }, retryInterval)
+              } else {
+                $.send()
+              }
+            }
+          }, $.file, $)
+        }
+      },
+    
+      abort: function () {
+        var xhr = this.xhr
+        this.xhr = null
+        this.processingResponse = false
+        this.processedState = null
+        if (xhr) {
+          xhr.abort()
+        }
+      },
+    
+      status: function (isTest) {
+        if (this.readState === 1) {
+          return STATUS.READING
+        } else if (this.pendingRetry || this.preprocessState === 1) {
+          // if pending retry then that's effectively the same as actively uploading,
+          // there might just be a slight delay before the retry starts
+          return STATUS.UPLOADING
+        } else if (!this.xhr) {
+          return STATUS.PENDING
+        } else if (this.xhr.readyState < 4 || this.processingResponse) {
+          // Status is really 'OPENED', 'HEADERS_RECEIVED'
+          // or 'LOADING' - meaning that stuff is happening
+          return STATUS.UPLOADING
+        } else {
+          var _status
+          if (this.uploader.opts.successStatuses.indexOf(this.xhr.status) > -1) {
+            // HTTP 200, perfect
+            // HTTP 202 Accepted - The request has been accepted for processing, but the processing has not been completed.
+            _status = STATUS.SUCCESS
+          } else if (this.uploader.opts.permanentErrors.indexOf(this.xhr.status) > -1 ||
+              !isTest && this.retries >= this.uploader.opts.maxChunkRetries) {
+            // HTTP 415/500/501, permanent error
+            _status = STATUS.ERROR
+          } else {
+            // this should never happen, but we'll reset and queue a retry
+            // a likely case for this would be 503 service unavailable
+            this.abort()
+            _status = STATUS.PENDING
+          }
+          var processedState = this.processedState
+          if (processedState && processedState.err) {
+            _status = STATUS.ERROR
+          }
+          return _status
+        }
+      },
+    
+      message: function () {
+        return this.xhr ? this.xhr.responseText : ''
+      },
+    
+      progress: function () {
+        if (this.pendingRetry) {
+          return 0
+        }
+        var s = this.status()
+        if (s === STATUS.SUCCESS || s === STATUS.ERROR) {
+          return 1
+        } else if (s === STATUS.PENDING) {
+          return 0
+        } else {
+          return this.total > 0 ? this.loaded / this.total : 0
+        }
+      },
+    
+      sizeUploaded: function () {
+        var size = this.endByte - this.startByte
+        // can't return only chunk.loaded value, because it is bigger than chunk size
+        if (this.status() !== STATUS.SUCCESS) {
+          size = this.progress() * size
+        }
+        return size
+      },
+    
+      prepareXhrRequest: function (method, isTest, paramsMethod, blob) {
+        // Add data from the query options
+        var query = utils.evalOpts(this.uploader.opts.query, this.file, this, isTest)
+        query = utils.extend(this.getParams(), query)
+    
+        // processParams
+        query = this.uploader.opts.processParams(query, this.file, this, isTest)
+    
+        var target = utils.evalOpts(this.uploader.opts.target, this.file, this, isTest)
+        var data = null
+        if (method === 'GET' || paramsMethod === 'octet') {
+          // Add data from the query options
+          var params = []
+          utils.each(query, function (v, k) {
+            params.push([encodeURIComponent(k), encodeURIComponent(v)].join('='))
+          })
+          target = this.getTarget(target, params)
+          data = blob || null
+        } else {
+          // Add data from the query options
+          data = new FormData()
+          utils.each(query, function (v, k) {
+            data.append(k, v)
+          })
+          if (typeof blob !== 'undefined') {
+            data.append(this.uploader.opts.fileParameterName, blob, this.file.name)
+          }
+        }
+    
+        this.xhr.open(method, target, true)
+        this.xhr.withCredentials = this.uploader.opts.withCredentials
+    
+        // Add data from header options
+        utils.each(utils.evalOpts(this.uploader.opts.headers, this.file, this, isTest), function (v, k) {
+          this.xhr.setRequestHeader(k, v)
+        }, this)
+    
+        return data
+      }
+    
+    })
+    
+    module.exports = Chunk
+    
+    },{"./utils":5}],2:[function(_dereq_,module,exports){
+    var each = _dereq_('./utils').each
+    
+    var event = {
+    
+      _eventData: null,
+    
+      on: function (name, func) {
+        if (!this._eventData) this._eventData = {}
+        if (!this._eventData[name]) this._eventData[name] = []
+        var listened = false
+        each(this._eventData[name], function (fuc) {
+          if (fuc === func) {
+            listened = true
+            return false
+          }
+        })
+        if (!listened) {
+          this._eventData[name].push(func)
+        }
+      },
+    
+      off: function (name, func) {
+        if (!this._eventData) this._eventData = {}
+        if (!this._eventData[name] || !this._eventData[name].length) return
+        if (func) {
+          each(this._eventData[name], function (fuc, i) {
+            if (fuc === func) {
+              this._eventData[name].splice(i, 1)
+              return false
+            }
+          }, this)
+        } else {
+          this._eventData[name] = []
+        }
+      },
+    
+      trigger: function (name) {
+        if (!this._eventData) this._eventData = {}
+        if (!this._eventData[name]) return true
+        var args = this._eventData[name].slice.call(arguments, 1)
+        var preventDefault = false
+        each(this._eventData[name], function (fuc) {
+          preventDefault = fuc.apply(this, args) === false || preventDefault
+        }, this)
+        return !preventDefault
+      }
+    }
+    
+    module.exports = event
+    
+    },{"./utils":5}],3:[function(_dereq_,module,exports){
+    var utils = _dereq_('./utils')
+    var event = _dereq_('./event')
+    var File = _dereq_('./file')
+    var Chunk = _dereq_('./chunk')
+    
+    var version = '0.5.4'
+    
+    var isServer = typeof window === 'undefined'
+    
+    // ie10+
+    var ie10plus = isServer ? false : window.navigator.msPointerEnabled
+    var support = (function () {
+      if (isServer) {
+        return false
+      }
+      var sliceName = 'slice'
+      var _support = utils.isDefined(window.File) && utils.isDefined(window.Blob) &&
+                    utils.isDefined(window.FileList)
+      var bproto = null
+      if (_support) {
+        bproto = window.Blob.prototype
+        utils.each(['slice', 'webkitSlice', 'mozSlice'], function (n) {
+          if (bproto[n]) {
+            sliceName = n
+            return false
+          }
+        })
+        _support = !!bproto[sliceName]
+      }
+      if (_support) Uploader.sliceName = sliceName
+      bproto = null
+      return _support
+    })()
+    
+    var supportDirectory = (function () {
+      if (isServer) {
+        return false
+      }
+      var input = window.document.createElement('input')
+      input.type = 'file'
+      var sd = 'webkitdirectory' in input || 'directory' in input
+      input = null
+      return sd
+    })()
+    
+    function Uploader (opts) {
+      this.support = support
+      /* istanbul ignore if */
+      if (!this.support) {
+        return
+      }
+      this.supportDirectory = supportDirectory
+      utils.defineNonEnumerable(this, 'filePaths', {})
+      this.opts = utils.extend({}, Uploader.defaults, opts || {})
+    
+      this.preventEvent = utils.bind(this._preventEvent, this)
+    
+      File.call(this, this)
+    }
+    
+    /**
+     * Default read function using the webAPI
+     *
+     * @function webAPIFileRead(fileObj, fileType, startByte, endByte, chunk)
+     *
+     */
+    var webAPIFileRead = function (fileObj, fileType, startByte, endByte, chunk) {
+      chunk.readFinished(fileObj.file[Uploader.sliceName](startByte, endByte, fileType))
+    }
+    
+    Uploader.version = version
+    
+    Uploader.defaults = {
+      chunkSize: 1024 * 1024,
+      forceChunkSize: false,
+      simultaneousUploads: 3,
+      singleFile: false,
+      fileParameterName: 'file',
+      progressCallbacksInterval: 500,
+      speedSmoothingFactor: 0.1,
+      query: {},
+      headers: {},
+      withCredentials: false,
+      preprocess: null,
+      method: 'multipart',
+      testMethod: 'GET',
+      uploadMethod: 'POST',
+      prioritizeFirstAndLastChunk: false,
+      allowDuplicateUploads: false,
+      target: '/',
+      testChunks: true,
+      generateUniqueIdentifier: null,
+      maxChunkRetries: 0,
+      chunkRetryInterval: null,
+      permanentErrors: [404, 415, 500, 501],
+      successStatuses: [200, 201, 202],
+      onDropStopPropagation: false,
+      initFileFn: null,
+      readFileFn: webAPIFileRead,
+      checkChunkUploadedByResponse: null,
+      initialPaused: false,
+      processResponse: function (response, cb) {
+        cb(null, response)
+      },
+      processParams: function (params) {
+        return params
+      }
+    }
+    
+    Uploader.utils = utils
+    Uploader.event = event
+    Uploader.File = File
+    Uploader.Chunk = Chunk
+    
+    // inherit file
+    Uploader.prototype = utils.extend({}, File.prototype)
+    // inherit event
+    utils.extend(Uploader.prototype, event)
+    utils.extend(Uploader.prototype, {
+    
+      constructor: Uploader,
+    
+      _trigger: function (name) {
+        var args = utils.toArray(arguments)
+        var preventDefault = !this.trigger.apply(this, arguments)
+        if (name !== 'catchAll') {
+          args.unshift('catchAll')
+          preventDefault = !this.trigger.apply(this, args) || preventDefault
+        }
+        return !preventDefault
+      },
+    
+      _triggerAsync: function () {
+        var args = arguments
+        utils.nextTick(function () {
+          this._trigger.apply(this, args)
+        }, this)
+      },
+    
+      addFiles: function (files, evt) {
+        var _files = []
+        var oldFileListLen = this.fileList.length
+        utils.each(files, function (file) {
+          // Uploading empty file IE10/IE11 hangs indefinitely
+          // Directories have size `0` and name `.`
+          // Ignore already added files if opts.allowDuplicateUploads is set to false
+          if ((!ie10plus || ie10plus && file.size > 0) && !(file.size % 4096 === 0 && (file.name === '.' || file.fileName === '.'))) {
+            var uniqueIdentifier = this.generateUniqueIdentifier(file)
+            if (this.opts.allowDuplicateUploads || !this.getFromUniqueIdentifier(uniqueIdentifier)) {
+              var _file = new File(this, file, this)
+              _file.uniqueIdentifier = uniqueIdentifier
+              if (this._trigger('fileAdded', _file, evt)) {
+                _files.push(_file)
+              } else {
+                File.prototype.removeFile.call(this, _file)
+              }
+            }
+          }
+        }, this)
+        // get new fileList
+        var newFileList = this.fileList.slice(oldFileListLen)
+        if (this._trigger('filesAdded', _files, newFileList, evt)) {
+          utils.each(_files, function (file) {
+            if (this.opts.singleFile && this.files.length > 0) {
+              this.removeFile(this.files[0])
+            }
+            this.files.push(file)
+          }, this)
+          this._trigger('filesSubmitted', _files, newFileList, evt)
+        } else {
+          utils.each(newFileList, function (file) {
+            File.prototype.removeFile.call(this, file)
+          }, this)
+        }
+      },
+    
+      addFile: function (file, evt) {
+        this.addFiles([file], evt)
+      },
+    
+      cancel: function () {
+        for (var i = this.fileList.length - 1; i >= 0; i--) {
+          this.fileList[i].cancel()
+        }
+      },
+    
+      removeFile: function (file) {
+        File.prototype.removeFile.call(this, file)
+        this._trigger('fileRemoved', file)
+      },
+    
+      generateUniqueIdentifier: function (file) {
+        var custom = this.opts.generateUniqueIdentifier
+        if (utils.isFunction(custom)) {
+          return custom(file)
+        }
+        /* istanbul ignore next */
+        // Some confusion in different versions of Firefox
+        var relativePath = file.relativePath || file.webkitRelativePath || file.fileName || file.name
+        /* istanbul ignore next */
+        return file.size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, '')
+      },
+    
+      getFromUniqueIdentifier: function (uniqueIdentifier) {
+        var ret = false
+        utils.each(this.files, function (file) {
+          if (file.uniqueIdentifier === uniqueIdentifier) {
+            ret = file
+            return false
+          }
+        })
+        return ret
+      },
+    
+      uploadNextChunk: function (preventEvents) {
+        var found = false
+        var pendingStatus = Chunk.STATUS.PENDING
+        var checkChunkUploaded = this.uploader.opts.checkChunkUploadedByResponse
+        if (this.opts.prioritizeFirstAndLastChunk) {
+          utils.each(this.files, function (file) {
+            if (file.paused) {
+              return
+            }
+            if (checkChunkUploaded && !file._firstResponse && file.isUploading()) {
+              // waiting for current file's first chunk response
+              return
+            }
+            if (file.chunks.length && file.chunks[0].status() === pendingStatus) {
+              file.chunks[0].send()
+              found = true
+              return false
+            }
+            if (file.chunks.length > 1 && file.chunks[file.chunks.length - 1].status() === pendingStatus) {
+              file.chunks[file.chunks.length - 1].send()
+              found = true
+              return false
+            }
+          })
+          if (found) {
+            return found
+          }
+        }
+    
+        // Now, simply look for the next, best thing to upload
+        utils.each(this.files, function (file) {
+          if (!file.paused) {
+            if (checkChunkUploaded && !file._firstResponse && file.isUploading()) {
+              // waiting for current file's first chunk response
+              return
+            }
+            utils.each(file.chunks, function (chunk) {
+              if (chunk.status() === pendingStatus) {
+                chunk.send()
+                found = true
+                return false
+              }
+            })
+          }
+          if (found) {
+            return false
+          }
+        })
+        if (found) {
+          return true
+        }
+    
+        // The are no more outstanding chunks to upload, check is everything is done
+        var outstanding = false
+        utils.each(this.files, function (file) {
+          if (!file.isComplete()) {
+            outstanding = true
+            return false
+          }
+        })
+        // should check files now
+        // if now files in list
+        // should not trigger complete event
+        if (!outstanding && !preventEvents && this.files.length) {
+          // All chunks have been uploaded, complete
+          this._triggerAsync('complete')
+        }
+        return outstanding
+      },
+    
+      upload: function (preventEvents) {
+        // Make sure we don't start too many uploads at once
+        var ret = this._shouldUploadNext()
+        if (ret === false) {
+          return
+        }
+        !preventEvents && this._trigger('uploadStart')
+        var started = false
+        for (var num = 1; num <= this.opts.simultaneousUploads - ret; num++) {
+          started = this.uploadNextChunk(!preventEvents) || started
+          if (!started && preventEvents) {
+            // completed
+            break
+          }
+        }
+        if (!started && !preventEvents) {
+          this._triggerAsync('complete')
+        }
+      },
+    
+      /**
+       * should upload next chunk
+       * @function
+       * @returns {Boolean|Number}
+       */
+      _shouldUploadNext: function () {
+        var num = 0
+        var should = true
+        var simultaneousUploads = this.opts.simultaneousUploads
+        var uploadingStatus = Chunk.STATUS.UPLOADING
+        utils.each(this.files, function (file) {
+          utils.each(file.chunks, function (chunk) {
+            if (chunk.status() === uploadingStatus) {
+              num++
+              if (num >= simultaneousUploads) {
+                should = false
+                return false
+              }
+            }
+          })
+          return should
+        })
+        // if should is true then return uploading chunks's length
+        return should && num
+      },
+    
+      /**
+       * Assign a browse action to one or more DOM nodes.
+       * @function
+       * @param {Element|Array.<Element>} domNodes
+       * @param {boolean} isDirectory Pass in true to allow directories to
+       * @param {boolean} singleFile prevent multi file upload
+       * @param {Object} attributes set custom attributes:
+       *  http://www.w3.org/TR/html-markup/input.file.html#input.file-attributes
+       *  eg: accept: 'image/*'
+       * be selected (Chrome only).
+       */
+      assignBrowse: function (domNodes, isDirectory, singleFile, attributes) {
+        if (typeof domNodes.length === 'undefined') {
+          domNodes = [domNodes]
+        }
+    
+        utils.each(domNodes, function (domNode) {
+          var input
+          if (domNode.tagName === 'INPUT' && domNode.type === 'file') {
+            input = domNode
+          } else {
+            input = document.createElement('input')
+            input.setAttribute('type', 'file')
+            // display:none - not working in opera 12
+            utils.extend(input.style, {
+              visibility: 'hidden',
+              position: 'absolute',
+              width: '1px',
+              height: '1px'
+            })
+            // for opera 12 browser, input must be assigned to a document
+            Array.from(domNode.children).forEach(function(child){
+              if(child.type=='file'){
+                  console.log(child)
+                  domNode.removeChild(child)
+              }
+            })
+            domNode.appendChild(input)
+            // https://developer.mozilla.org/en/using_files_from_web_applications)
+            // event listener is executed two times
+            // first one - original mouse click event
+            // second - input.click(), input is inside domNode
+            domNode.addEventListener('click', function (e) {
+              if (domNode.tagName.toLowerCase() === 'label') {
+                return
+              }
+              input.click()
+            }, false)
+          }
+          if (!this.opts.singleFile && !singleFile) {
+            input.setAttribute('multiple', 'multiple')
+          }
+          if (isDirectory) {
+            input.setAttribute('webkitdirectory', 'webkitdirectory')
+          }
+          attributes && utils.each(attributes, function (value, key) {
+            input.setAttribute(key, value)
+          })
+          // When new files are added, simply append them to the overall list
+          var that = this
+          input.addEventListener('change', function (e) {
+            that._trigger(e.type, e)
+            if (e.target.value) {
+              that.addFiles(e.target.files, e)
+              e.target.value = ''
+            }
+          }, false)
+        }, this)
+      },
+    
+      onDrop: function (evt) {
+        this._trigger(evt.type, evt)
+        if (this.opts.onDropStopPropagation) {
+          evt.stopPropagation()
+        }
+        evt.preventDefault()
+        this._parseDataTransfer(evt.dataTransfer, evt)
+      },
+    
+      _parseDataTransfer: function (dataTransfer, evt) {
+        if (dataTransfer.items && dataTransfer.items[0] &&
+          dataTransfer.items[0].webkitGetAsEntry) {
+          this.webkitReadDataTransfer(dataTransfer, evt)
+        } else {
+          this.addFiles(dataTransfer.files, evt)
+        }
+      },
+    
+      webkitReadDataTransfer: function (dataTransfer, evt) {
+        var self = this
+        var queue = dataTransfer.items.length
+        var files = []
+        utils.each(dataTransfer.items, function (item) {
+          var entry = item.webkitGetAsEntry()
+          if (!entry) {
+            decrement()
+            return
+          }
+          if (entry.isFile) {
+            // due to a bug in Chrome's File System API impl - #149735
+            fileReadSuccess(item.getAsFile(), entry.fullPath)
+          } else {
+            readDirectory(entry.createReader())
+          }
+        })
+        function readDirectory (reader) {
+          reader.readEntries(function (entries) {
+            if (entries.length) {
+              queue += entries.length
+              utils.each(entries, function (entry) {
+                if (entry.isFile) {
+                  var fullPath = entry.fullPath
+                  entry.file(function (file) {
+                    fileReadSuccess(file, fullPath)
+                  }, readError)
+                } else if (entry.isDirectory) {
+                  readDirectory(entry.createReader())
+                }
+              })
+              readDirectory(reader)
+            } else {
+              decrement()
+            }
+          }, readError)
+        }
+        function fileReadSuccess (file, fullPath) {
+          // relative path should not start with "/"
+          file.relativePath = fullPath.substring(1)
+          files.push(file)
+          decrement()
+        }
+        function readError (fileError) {
+          throw fileError
+        }
+        function decrement () {
+          if (--queue === 0) {
+            self.addFiles(files, evt)
+          }
+        }
+      },
+    
+      _assignHelper: function (domNodes, handles, remove) {
+        if (typeof domNodes.length === 'undefined') {
+          domNodes = [domNodes]
+        }
+        var evtMethod = remove ? 'removeEventListener' : 'addEventListener'
+        utils.each(domNodes, function (domNode) {
+          utils.each(handles, function (handler, name) {
+            domNode[evtMethod](name, handler, false)
+          }, this)
+        }, this)
+      },
+    
+      _preventEvent: function (e) {
+        utils.preventEvent(e)
+        this._trigger(e.type, e)
+      },
+    
+      /**
+       * Assign one or more DOM nodes as a drop target.
+       * @function
+       * @param {Element|Array.<Element>} domNodes
+       */
+      assignDrop: function (domNodes) {
+        this._onDrop = utils.bind(this.onDrop, this)
+        this._assignHelper(domNodes, {
+          dragover: this.preventEvent,
+          dragenter: this.preventEvent,
+          dragleave: this.preventEvent,
+          drop: this._onDrop
+        })
+      },
+    
+      /**
+       * Un-assign drop event from DOM nodes
+       * @function
+       * @param domNodes
+       */
+      unAssignDrop: function (domNodes) {
+        this._assignHelper(domNodes, {
+          dragover: this.preventEvent,
+          dragenter: this.preventEvent,
+          dragleave: this.preventEvent,
+          drop: this._onDrop
+        }, true)
+        this._onDrop = null
+      }
+    })
+    
+    module.exports = Uploader
+    
+    },{"./chunk":1,"./event":2,"./file":4,"./utils":5}],4:[function(_dereq_,module,exports){
+    var utils = _dereq_('./utils')
+    var Chunk = _dereq_('./chunk')
+    
+    function File (uploader, file, parent) {
+      utils.defineNonEnumerable(this, 'uploader', uploader)
+      this.isRoot = this.isFolder = uploader === this
+      utils.defineNonEnumerable(this, 'parent', parent || null)
+      utils.defineNonEnumerable(this, 'files', [])
+      utils.defineNonEnumerable(this, 'fileList', [])
+      utils.defineNonEnumerable(this, 'chunks', [])
+      utils.defineNonEnumerable(this, '_errorFiles', [])
+      utils.defineNonEnumerable(this, 'file', null)
+      this.id = utils.uid()
+    
+      if (this.isRoot || !file) {
+        this.file = null
+      } else {
+        if (utils.isString(file)) {
+          // folder
+          this.isFolder = true
+          this.file = null
+          this.path = file
+          if (this.parent.path) {
+            file = file.substr(this.parent.path.length)
+          }
+          this.name = file.charAt(file.length - 1) === '/' ? file.substr(0, file.length - 1) : file
+        } else {
+          this.file = file
+          this.fileType = this.file.type
+          this.name = file.fileName || file.name
+          this.size = file.size
+          this.relativePath = file.relativePath || file.webkitRelativePath || this.name
+          this._parseFile()
+        }
+      }
+    
+      this.paused = uploader.opts.initialPaused
+      this.error = false
+      this.allError = false
+      this.aborted = false
+      this.completed = false
+      this.averageSpeed = 0
+      this.currentSpeed = 0
+      this._lastProgressCallback = Date.now()
+      this._prevUploadedSize = 0
+      this._prevProgress = 0
+    
+      this.bootstrap()
+    }
+    
+    utils.extend(File.prototype, {
+    
+      _parseFile: function () {
+        var ppaths = parsePaths(this.relativePath)
+        if (ppaths.length) {
+          var filePaths = this.uploader.filePaths
+          utils.each(ppaths, function (path, i) {
+            var folderFile = filePaths[path]
+            if (!folderFile) {
+              folderFile = new File(this.uploader, path, this.parent)
+              filePaths[path] = folderFile
+              this._updateParentFileList(folderFile)
+            }
+            this.parent = folderFile
+            folderFile.files.push(this)
+            if (!ppaths[i + 1]) {
+              folderFile.fileList.push(this)
+            }
+          }, this)
+        } else {
+          this._updateParentFileList()
+        }
+      },
+    
+      _updateParentFileList: function (file) {
+        if (!file) {
+          file = this
+        }
+        var p = this.parent
+        if (p) {
+          p.fileList.push(file)
+        }
+      },
+    
+      _eachAccess: function (eachFn, fileFn) {
+        if (this.isFolder) {
+          utils.each(this.files, function (f, i) {
+            return eachFn.call(this, f, i)
+          }, this)
+          return
+        }
+        fileFn.call(this, this)
+      },
+    
+      bootstrap: function () {
+        if (this.isFolder) return
+        var opts = this.uploader.opts
+        if (utils.isFunction(opts.initFileFn)) {
+          opts.initFileFn.call(this, this)
+        }
+    
+        this.abort(true)
+        this._resetError()
+        // Rebuild stack of chunks from file
+        this._prevProgress = 0
+        var round = opts.forceChunkSize ? Math.ceil : Math.floor
+        var chunks = Math.max(round(this.size / opts.chunkSize), 1)
+        for (var offset = 0; offset < chunks; offset++) {
+          this.chunks.push(new Chunk(this.uploader, this, offset))
+        }
+      },
+    
+      _measureSpeed: function () {
+        var smoothingFactor = this.uploader.opts.speedSmoothingFactor
+        var timeSpan = Date.now() - this._lastProgressCallback
+        if (!timeSpan) {
+          return
+        }
+        var uploaded = this.sizeUploaded()
+        // Prevent negative upload speed after file upload resume
+        this.currentSpeed = Math.max((uploaded - this._prevUploadedSize) / timeSpan * 1000, 0)
+        this.averageSpeed = smoothingFactor * this.currentSpeed + (1 - smoothingFactor) * this.averageSpeed
+        this._prevUploadedSize = uploaded
+        if (this.parent && this.parent._checkProgress()) {
+          this.parent._measureSpeed()
+        }
+      },
+    
+      _checkProgress: function (file) {
+        return Date.now() - this._lastProgressCallback >= this.uploader.opts.progressCallbacksInterval
+      },
+    
+      _chunkEvent: function (chunk, evt, message) {
+        var uploader = this.uploader
+        var STATUS = Chunk.STATUS
+        var that = this
+        var rootFile = this.getRoot()
+        var triggerProgress = function () {
+          that._measureSpeed()
+          uploader._trigger('fileProgress', rootFile, that, chunk)
+          that._lastProgressCallback = Date.now()
+        }
+        switch (evt) {
+          case STATUS.PROGRESS:
+            if (this._checkProgress()) {
+              triggerProgress()
+            }
+            break
+          case STATUS.ERROR:
+            this._error()
+            this.abort(true)
+            uploader._trigger('fileError', rootFile, this, message, chunk)
+            break
+          case STATUS.SUCCESS:
+            this._updateUploadedChunks(message, chunk)
+            if (this.error) {
+              return
+            }
+            clearTimeout(this._progeressId)
+            this._progeressId = 0
+            var timeDiff = Date.now() - this._lastProgressCallback
+            if (timeDiff < uploader.opts.progressCallbacksInterval) {
+              this._progeressId = setTimeout(triggerProgress, uploader.opts.progressCallbacksInterval - timeDiff)
+            }
+            if (this.isComplete()) {
+              clearTimeout(this._progeressId)
+              triggerProgress()
+              this.currentSpeed = 0
+              this.averageSpeed = 0
+              uploader._trigger('fileSuccess', rootFile, this, message, chunk)
+              if (rootFile.isComplete()) {
+                uploader._trigger('fileComplete', rootFile, this)
+              }
+            } else if (!this._progeressId) {
+              triggerProgress()
+            }
+            break
+          case STATUS.RETRY:
+            uploader._trigger('fileRetry', rootFile, this, chunk)
+            break
+        }
+      },
+    
+      _updateUploadedChunks: function (message, chunk) {
+        var checkChunkUploaded = this.uploader.opts.checkChunkUploadedByResponse
+        if (checkChunkUploaded) {
+          var xhr = chunk.xhr
+          utils.each(this.chunks, function (_chunk) {
+            if (!_chunk.tested) {
+              var uploaded = checkChunkUploaded.call(this, _chunk, message)
+              if (_chunk === chunk && !uploaded) {
+                // fix the first chunk xhr status
+                // treated as success but checkChunkUploaded is false
+                // so the current chunk should be uploaded again
+                _chunk.xhr = null
+              }
+              if (uploaded) {
+                // first success and other chunks are uploaded
+                // then set xhr, so the uploaded chunks
+                // will be treated as success too
+                _chunk.xhr = xhr
+              }
+              _chunk.tested = true
+            }
+          }, this)
+          if (!this._firstResponse) {
+            this._firstResponse = true
+            this.uploader.upload(true)
+          } else {
+            this.uploader.uploadNextChunk()
+          }
+        } else {
+          this.uploader.uploadNextChunk()
+        }
+      },
+    
+      _error: function () {
+        this.error = this.allError = true
+        var parent = this.parent
+        while (parent && parent !== this.uploader) {
+          parent._errorFiles.push(this)
+          parent.error = true
+          if (parent._errorFiles.length === parent.files.length) {
+            parent.allError = true
+          }
+          parent = parent.parent
+        }
+      },
+    
+      _resetError: function () {
+        this.error = this.allError = false
+        var parent = this.parent
+        var index = -1
+        while (parent && parent !== this.uploader) {
+          index = parent._errorFiles.indexOf(this)
+          parent._errorFiles.splice(index, 1)
+          parent.allError = false
+          if (!parent._errorFiles.length) {
+            parent.error = false
+          }
+          parent = parent.parent
+        }
+      },
+    
+      isComplete: function () {
+        if (!this.completed) {
+          var outstanding = false
+          this._eachAccess(function (file) {
+            if (!file.isComplete()) {
+              outstanding = true
+              return false
+            }
+          }, function () {
+            var STATUS = Chunk.STATUS
+            utils.each(this.chunks, function (chunk) {
+              var status = chunk.status()
+              if (status === STATUS.PENDING || status === STATUS.UPLOADING || status === STATUS.READING || chunk.preprocessState === 1 || chunk.readState === 1) {
+                outstanding = true
+                return false
+              }
+            })
+          })
+          this.completed = !outstanding
+        }
+        return this.completed
+      },
+    
+      isUploading: function () {
+        var uploading = false
+        this._eachAccess(function (file) {
+          if (file.isUploading()) {
+            uploading = true
+            return false
+          }
+        }, function () {
+          var uploadingStatus = Chunk.STATUS.UPLOADING
+          utils.each(this.chunks, function (chunk) {
+            if (chunk.status() === uploadingStatus) {
+              uploading = true
+              return false
+            }
+          })
+        })
+        return uploading
+      },
+    
+      resume: function () {
+        this._eachAccess(function (f) {
+          f.resume()
+        }, function () {
+          this.paused = false
+          this.aborted = false
+          this.uploader.upload()
+        })
+        this.paused = false
+        this.aborted = false
+      },
+    
+      pause: function () {
+        this._eachAccess(function (f) {
+          f.pause()
+        }, function () {
+          this.paused = true
+          this.abort()
+        })
+        this.paused = true
+      },
+    
+      cancel: function () {
+        this.uploader.removeFile(this)
+      },
+    
+      retry: function (file) {
+        var fileRetry = function (file) {
+          if (file.error) {
+            file.bootstrap()
+          }
+        }
+        if (file) {
+          file.bootstrap()
+        } else {
+          this._eachAccess(fileRetry, function () {
+            this.bootstrap()
+          })
+        }
+        this.uploader.upload()
+      },
+    
+      abort: function (reset) {
+        if (this.aborted) {
+          return
+        }
+        this.currentSpeed = 0
+        this.averageSpeed = 0
+        this.aborted = !reset
+        var chunks = this.chunks
+        if (reset) {
+          this.chunks = []
+        }
+        var uploadingStatus = Chunk.STATUS.UPLOADING
+        utils.each(chunks, function (c) {
+          if (c.status() === uploadingStatus) {
+            c.abort()
+            this.uploader.uploadNextChunk()
+          }
+        }, this)
+      },
+    
+      progress: function () {
+        var totalDone = 0
+        var totalSize = 0
+        var ret = 0
+        this._eachAccess(function (file, index) {
+          totalDone += file.progress() * file.size
+          totalSize += file.size
+          if (index === this.files.length - 1) {
+            ret = totalSize > 0 ? totalDone / totalSize : this.isComplete() ? 1 : 0
+          }
+        }, function () {
+          if (this.error) {
+            ret = 1
+            return
+          }
+          if (this.chunks.length === 1) {
+            this._prevProgress = Math.max(this._prevProgress, this.chunks[0].progress())
+            ret = this._prevProgress
+            return
+          }
+          // Sum up progress across everything
+          var bytesLoaded = 0
+          utils.each(this.chunks, function (c) {
+            // get chunk progress relative to entire file
+            bytesLoaded += c.progress() * (c.endByte - c.startByte)
+          })
+          var percent = bytesLoaded / this.size
+          // We don't want to lose percentages when an upload is paused
+          this._prevProgress = Math.max(this._prevProgress, percent > 0.9999 ? 1 : percent)
+          ret = this._prevProgress
+        })
+        return ret
+      },
+    
+      getSize: function () {
+        var size = 0
+        this._eachAccess(function (file) {
+          size += file.size
+        }, function () {
+          size += this.size
+        })
+        return size
+      },
+    
+      getFormatSize: function () {
+        var size = this.getSize()
+        return utils.formatSize(size)
+      },
+    
+      getRoot: function () {
+        if (this.isRoot) {
+          return this
+        }
+        var parent = this.parent
+        while (parent) {
+          if (parent.parent === this.uploader) {
+            // find it
+            return parent
+          }
+          parent = parent.parent
+        }
+        return this
+      },
+    
+      sizeUploaded: function () {
+        var size = 0
+        this._eachAccess(function (file) {
+          size += file.sizeUploaded()
+        }, function () {
+          utils.each(this.chunks, function (chunk) {
+            size += chunk.sizeUploaded()
+          })
+        })
+        return size
+      },
+    
+      timeRemaining: function () {
+        var ret = 0
+        var sizeDelta = 0
+        var averageSpeed = 0
+        this._eachAccess(function (file, i) {
+          if (!file.paused && !file.error) {
+            sizeDelta += file.size - file.sizeUploaded()
+            averageSpeed += file.averageSpeed
+          }
+          if (i === this.files.length - 1) {
+            ret = calRet(sizeDelta, averageSpeed)
+          }
+        }, function () {
+          if (this.paused || this.error) {
+            ret = 0
+            return
+          }
+          var delta = this.size - this.sizeUploaded()
+          ret = calRet(delta, this.averageSpeed)
+        })
+        return ret
+        function calRet (delta, averageSpeed) {
+          if (delta && !averageSpeed) {
+            return Number.POSITIVE_INFINITY
+          }
+          if (!delta && !averageSpeed) {
+            return 0
+          }
+          return Math.floor(delta / averageSpeed)
+        }
+      },
+    
+      removeFile: function (file) {
+        if (file.isFolder) {
+          while (file.files.length) {
+            var f = file.files[file.files.length - 1]
+            this._removeFile(f)
+          }
+        }
+        this._removeFile(file)
+      },
+    
+      _delFilePath: function (file) {
+        if (file.path && this.filePaths) {
+          delete this.filePaths[file.path]
+        }
+        utils.each(file.fileList, function (file) {
+          this._delFilePath(file)
+        }, this)
+      },
+    
+      _removeFile: function (file) {
+        if (!file.isFolder) {
+          utils.each(this.files, function (f, i) {
+            if (f === file) {
+              this.files.splice(i, 1)
+              return false
+            }
+          }, this)
+          file.abort()
+          var parent = file.parent
+          var newParent
+          while (parent && parent !== this) {
+            newParent = parent.parent
+            parent._removeFile(file)
+            parent = newParent
+          }
+        }
+        file.parent === this && utils.each(this.fileList, function (f, i) {
+          if (f === file) {
+            this.fileList.splice(i, 1)
+            return false
+          }
+        }, this)
+        if (!this.isRoot && this.isFolder && !this.files.length) {
+          this.parent._removeFile(this)
+          this.uploader._delFilePath(this)
+        }
+        file.parent = null
+      },
+    
+      getType: function () {
+        if (this.isFolder) {
+          return 'folder'
+        }
+        return this.file.type && this.file.type.split('/')[1]
+      },
+    
+      getExtension: function () {
+        if (this.isFolder) {
+          return ''
+        }
+        return this.name.substr((~-this.name.lastIndexOf('.') >>> 0) + 2).toLowerCase()
+      }
+    
+    })
+    
+    module.exports = File
+    
+    function parsePaths (path) {
+      var ret = []
+      var paths = path.split('/')
+      var len = paths.length
+      var i = 1
+      paths.splice(len - 1, 1)
+      len--
+      if (paths.length) {
+        while (i <= len) {
+          ret.push(paths.slice(0, i++).join('/') + '/')
+        }
+      }
+      return ret
+    }
+    
+    },{"./chunk":1,"./utils":5}],5:[function(_dereq_,module,exports){
+    var oproto = Object.prototype
+    var aproto = Array.prototype
+    var serialize = oproto.toString
+    
+    var isFunction = function (fn) {
+      return serialize.call(fn) === '[object Function]'
+    }
+    
+    var isArray = Array.isArray || /* istanbul ignore next */ function (ary) {
+      return serialize.call(ary) === '[object Array]'
+    }
+    
+    var isPlainObject = function (obj) {
+      return serialize.call(obj) === '[object Object]' && Object.getPrototypeOf(obj) === oproto
+    }
+    
+    var i = 0
+    var utils = {
+      uid: function () {
+        return ++i
+      },
+      noop: function () {},
+      bind: function (fn, context) {
+        return function () {
+          return fn.apply(context, arguments)
+        }
+      },
+      preventEvent: function (evt) {
+        evt.preventDefault()
+      },
+      stop: function (evt) {
+        evt.preventDefault()
+        evt.stopPropagation()
+      },
+      nextTick: function (fn, context) {
+        setTimeout(utils.bind(fn, context), 0)
+      },
+      toArray: function (ary, start, end) {
+        if (start === undefined) start = 0
+        if (end === undefined) end = ary.length
+        return aproto.slice.call(ary, start, end)
+      },
+    
+      isPlainObject: isPlainObject,
+      isFunction: isFunction,
+      isArray: isArray,
+      isObject: function (obj) {
+        return Object(obj) === obj
+      },
+      isString: function (s) {
+        return typeof s === 'string'
+      },
+      isUndefined: function (a) {
+        return typeof a === 'undefined'
+      },
+      isDefined: function (a) {
+        return typeof a !== 'undefined'
+      },
+    
+      each: function (ary, func, context) {
+        if (utils.isDefined(ary.length)) {
+          for (var i = 0, len = ary.length; i < len; i++) {
+            if (func.call(context, ary[i], i, ary) === false) {
+              break
+            }
+          }
+        } else {
+          for (var k in ary) {
+            if (func.call(context, ary[k], k, ary) === false) {
+              break
+            }
+          }
+        }
+      },
+    
+      /**
+       * If option is a function, evaluate it with given params
+       * @param {*} data
+       * @param {...} args arguments of a callback
+       * @returns {*}
+       */
+      evalOpts: function (data, args) {
+        if (utils.isFunction(data)) {
+          // `arguments` is an object, not array, in FF, so:
+          args = utils.toArray(arguments)
+          data = data.apply(null, args.slice(1))
+        }
+        return data
+      },
+    
+      extend: function () {
+        var options
+        var name
+        var src
+        var copy
+        var copyIsArray
+        var clone
+        var target = arguments[0] || {}
+        var i = 1
+        var length = arguments.length
+        var force = false
+    
+        // 濡傛灉绗竴涓弬鏁颁负甯冨皵,鍒ゅ畾鏄惁娣辨嫹璐�
+        if (typeof target === 'boolean') {
+          force = target
+          target = arguments[1] || {}
+          i++
+        }
+    
+        // 纭繚鎺ュ彈鏂逛负涓�涓鏉傜殑鏁版嵁绫诲瀷
+        if (typeof target !== 'object' && !isFunction(target)) {
+          target = {}
+        }
+    
+        // 濡傛灉鍙湁涓�涓弬鏁帮紝閭d箞鏂版垚鍛樻坊鍔犱簬 extend 鎵�鍦ㄧ殑瀵硅薄涓�
+        if (i === length) {
+          target = this
+          i--
+        }
+    
+        for (; i < length; i++) {
+          // 鍙鐞嗛潪绌哄弬鏁�
+          if ((options = arguments[i]) != null) {
+            for (name in options) {
+              src = target[name]
+              copy = options[name]
+    
+              // 闃叉鐜紩鐢�
+              if (target === copy) {
+                continue
+              }
+              if (force && copy && (isPlainObject(copy) || (copyIsArray = isArray(copy)))) {
+                if (copyIsArray) {
+                  copyIsArray = false
+                  clone = src && isArray(src) ? src : []
+                } else {
+                  clone = src && isPlainObject(src) ? src : {}
+                }
+                target[name] = utils.extend(force, clone, copy)
+              } else if (copy !== undefined) {
+                target[name] = copy
+              }
+            }
+          }
+        }
+        return target
+      },
+    
+      formatSize: function (size) {
+        if (size < 1024) {
+          return size.toFixed(0) + ' bytes'
+        } else if (size < 1024 * 1024) {
+          return (size / 1024.0).toFixed(0) + ' KB'
+        } else if (size < 1024 * 1024 * 1024) {
+          return (size / 1024.0 / 1024.0).toFixed(1) + ' MB'
+        } else {
+          return (size / 1024.0 / 1024.0 / 1024.0).toFixed(1) + ' GB'
+        }
+      },
+    
+      defineNonEnumerable: function (target, key, value) {
+        Object.defineProperty(target, key, {
+          enumerable: false,
+          configurable: true,
+          writable: true,
+          value: value
+        })
+      }
+    }
+    
+    module.exports = utils
+    
+    },{}]},{},[3])
+    (3)
+    });
\ No newline at end of file

--
Gitblit v1.8.0