function (domNodes, isDirectory, singleFile, attributes) {
      if (domNodes instanceof Element) {
        domNodes = [domNodes];
      }

      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
          extend(input.style, {
            visibility: 'hidden',
            position: 'absolute',
            width: '1px',
            height: '1px'
          });
          // for opera 12 browser, input must be assigned to a document
          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() {
            input.click();
          }, false);
        }
        if (!this.opts.singleFile && !singleFile) {
          input.setAttribute('multiple', 'multiple');
        }
        if (isDirectory) {
          input.setAttribute('webkitdirectory', 'webkitdirectory');
        }
        each(attributes, function (value, key) {
          input.setAttribute(key, value);
        });
        // When new files are added, simply append them to the overall list
        var $ = this;
        input.addEventListener('change', function (e) {
       	  if (e.target.value) {
            $.addFiles(e.target.files, e);
            e.target.value = '';
       	  }
        }, false);
      }, this);
    }

function ( domNodes , isDirectory , singleFile , attributes ) { if ( domNodes instanceof Element ) { domNodes = [ domNodes ] ; } each ( domNodes , function ( domNode ) { var input ; if ( domNode . tagName === 'INPUT' && domNode . type === 'file' ) { input = domNode ; } else { input = document . createElement ( 'input' ) ; input . setAttribute ( 'type' , 'file' ) ; extend ( input . style , { visibility : 'hidden' , position : 'absolute' , width : '1px' , height : '1px' } ) ; domNode . appendChild ( input ) ; domNode . addEventListener ( 'click' , function ( ) { input . click ( ) ; } , false ) ; } if ( ! this . opts . singleFile && ! singleFile ) { input . setAttribute ( 'multiple' , 'multiple' ) ; } if ( isDirectory ) { input . setAttribute ( 'webkitdirectory' , 'webkitdirectory' ) ; } each ( attributes , function ( value , key ) { input . setAttribute ( key , value ) ; } ) ; var $ = this ; input . addEventListener ( 'change' , function ( e ) { if ( e . target . value ) { $ . addFiles ( e . target . files , e ) ; e . target . value = '' ; } } , false ) ; } , this ) ; }

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).

Assign a browse action to one or more DOM nodes .


function (domNodes) {
      if (typeof domNodes.length === 'undefined') {
        domNodes = [domNodes];
      }
      each(domNodes, function (domNode) {
        domNode.addEventListener('dragover', this.preventEvent, false);
        domNode.addEventListener('dragenter', this.preventEvent, false);
        domNode.addEventListener('drop', this.onDrop, false);
      }, this);
    }

function ( domNodes ) { if ( typeof domNodes . length === 'undefined' ) { domNodes = [ domNodes ] ; } each ( domNodes , function ( domNode ) { domNode . addEventListener ( 'dragover' , this . preventEvent , false ) ; domNode . addEventListener ( 'dragenter' , this . preventEvent , false ) ; domNode . addEventListener ( 'drop' , this . onDrop , false ) ; } , this ) ; }

Assign one or more DOM nodes as a drop target.
@function
@param {Element|Array.<Element>} domNodes

Assign one or more DOM nodes as a drop target .


function (domNodes) {
      if (typeof domNodes.length === 'undefined') {
        domNodes = [domNodes];
      }
      each(domNodes, function (domNode) {
        domNode.removeEventListener('dragover', this.preventEvent);
        domNode.removeEventListener('dragenter', this.preventEvent);
        domNode.removeEventListener('drop', this.onDrop);
      }, this);
    }

function ( domNodes ) { if ( typeof domNodes . length === 'undefined' ) { domNodes = [ domNodes ] ; } each ( domNodes , function ( domNode ) { domNode . removeEventListener ( 'dragover' , this . preventEvent ) ; domNode . removeEventListener ( 'dragenter' , this . preventEvent ) ; domNode . removeEventListener ( 'drop' , this . onDrop ) ; } , this ) ; }

Un-assign drop event from DOM nodes
@function
@param domNodes


function () {
      var uploading = false;
      each(this.files, function (file) {
        if (file.isUploading()) {
          uploading = true;
          return false;
        }
      });
      return uploading;
    }

function ( ) { var uploading = false ; each ( this . files , function ( file ) { if ( file . isUploading ( ) ) { uploading = true ; return false ; } } ) ; return uploading ; }

Returns a boolean indicating whether or not the instance is currently
uploading anything.
@function
@returns {boolean}

Returns a boolean indicating whether or not the instance is currently uploading anything .


function () {
      var num = 0;
      var should = true;
      var simultaneousUploads = this.opts.simultaneousUploads;
      each(this.files, function (file) {
        each(file.chunks, function(chunk) {
          if (chunk.status() === 'uploading') {
            num++;
            if (num >= simultaneousUploads) {
              should = false;
              return false;
            }
          }
        });
      });
      // if should is true then return uploading chunks's length
      return should && num;
    }

function ( ) { var num = 0 ; var should = true ; var simultaneousUploads = this . opts . simultaneousUploads ; each ( this . files , function ( file ) { each ( file . chunks , function ( chunk ) { if ( chunk . status ( ) === 'uploading' ) { num ++ ; if ( num >= simultaneousUploads ) { should = false ; return false ; } } } ) ; } ) ; return should && num ; }

should upload next chunk
@function
@returns {boolean|number}


function () {
      // Make sure we don't start too many uploads at once
      var ret = this._shouldUploadNext();
      if (ret === false) {
        return;
      }
      // Kick off the queue
      this.fire('uploadStart');
      var started = false;
      for (var num = 1; num <= this.opts.simultaneousUploads - ret; num++) {
        started = this.uploadNextChunk(true) || started;
      }
      if (!started) {
        async(function () {
          this.fire('complete');
        }, this);
      }
    }

function ( ) { var ret = this . _shouldUploadNext ( ) ; if ( ret === false ) { return ; } this . fire ( 'uploadStart' ) ; var started = false ; for ( var num = 1 ; num <= this . opts . simultaneousUploads - ret ; num ++ ) { started = this . uploadNextChunk ( true ) || started ; } if ( ! started ) { async ( function ( ) { this . fire ( 'complete' ) ; } , this ) ; } }


function (fileList, event) {
      var files = [];
      each(fileList, function (file) {
        // https://github.com/flowjs/flow.js/issues/55
        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 f = new FlowFile(this, file, uniqueIdentifier);
            if (this.fire('fileAdded', f, event)) {
              files.push(f);
            }
          }
        }
      }, this);
      if (this.fire('filesAdded', files, event)) {
        each(files, function (file) {
          if (this.opts.singleFile && this.files.length > 0) {
            this.removeFile(this.files[0]);
          }
          this.files.push(file);
        }, this);
        this.fire('filesSubmitted', files, event);
      }
    }

function ( fileList , event ) { var files = [ ] ; each ( fileList , function ( file ) { 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 f = new FlowFile ( this , file , uniqueIdentifier ) ; if ( this . fire ( 'fileAdded' , f , event ) ) { files . push ( f ) ; } } } } , this ) ; if ( this . fire ( 'filesAdded' , files , event ) ) { each ( files , function ( file ) { if ( this . opts . singleFile && this . files . length > 0 ) { this . removeFile ( this . files [ 0 ] ) ; } this . files . push ( file ) ; } , this ) ; this . fire ( 'filesSubmitted' , files , event ) ; } }

Add a HTML5 File object to the list of files.
@function
@param {FileList|Array} fileList
@param {Event} [event] event is optional

Add a HTML5 File object to the list of files .


function (file) {
      for (var i = this.files.length - 1; i >= 0; i--) {
        if (this.files[i] === file) {
          this.files.splice(i, 1);
          file.abort();
          this.fire('fileRemoved', file);
        }
      }
    }

function ( file ) { for ( var i = this . files . length - 1 ; i >= 0 ; i -- ) { if ( this . files [ i ] === file ) { this . files . splice ( i , 1 ) ; file . abort ( ) ; this . fire ( 'fileRemoved' , file ) ; } } }

Cancel upload of a specific FlowFile object from the list.
@function
@param {FlowFile} file

Cancel upload of a specific FlowFile object from the list .


function (uniqueIdentifier) {
      var ret = false;
      each(this.files, function (file) {
        if (file.uniqueIdentifier === uniqueIdentifier) {
          ret = file;
        }
      });
      return ret;
    }

function ( uniqueIdentifier ) { var ret = false ; each ( this . files , function ( file ) { if ( file . uniqueIdentifier === uniqueIdentifier ) { ret = file ; } } ) ; return ret ; }

Look up a FlowFile object by its unique identifier.
@function
@param {string} uniqueIdentifier
@returns {boolean|FlowFile} false if file was not found

Look up a FlowFile object by its unique identifier .


function () {
      var sizeDelta = 0;
      var averageSpeed = 0;
      each(this.files, function (file) {
        if (!file.paused && !file.error) {
          sizeDelta += file.size - file.sizeUploaded();
          averageSpeed += file.averageSpeed;
        }
      });
      if (sizeDelta && !averageSpeed) {
        return Number.POSITIVE_INFINITY;
      }
      if (!sizeDelta && !averageSpeed) {
        return 0;
      }
      return Math.floor(sizeDelta / averageSpeed);
    }

function ( ) { var sizeDelta = 0 ; var averageSpeed = 0 ; each ( this . files , function ( file ) { if ( ! file . paused && ! file . error ) { sizeDelta += file . size - file . sizeUploaded ( ) ; averageSpeed += file . averageSpeed ; } } ) ; if ( sizeDelta && ! averageSpeed ) { return Number . POSITIVE_INFINITY ; } if ( ! sizeDelta && ! averageSpeed ) { return 0 ; } return Math . floor ( sizeDelta / averageSpeed ) ; }

Returns remaining time to upload all files in seconds. Accuracy is based on average speed.
If speed is zero, time remaining will be equal to positive infinity `Number.POSITIVE_INFINITY`
@function
@returns {number}

Returns remaining time to upload all files in seconds . Accuracy is based on average speed . If speed is zero time remaining will be equal to positive infinity Number . POSITIVE_INFINITY


function () {
      var timeSpan = Date.now() - this._lastProgressCallback;
      if (!timeSpan) {
        return ;
      }
      var smoothingFactor = this.flowObj.opts.speedSmoothingFactor;
      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;
    }

function ( ) { var timeSpan = Date . now ( ) - this . _lastProgressCallback ; if ( ! timeSpan ) { return ; } var smoothingFactor = this . flowObj . opts . speedSmoothingFactor ; var uploaded = this . sizeUploaded ( ) ; this . currentSpeed = Math . max ( ( uploaded - this . _prevUploadedSize ) / timeSpan * 1000 , 0 ) ; this . averageSpeed = smoothingFactor * this . currentSpeed + ( 1 - smoothingFactor ) * this . averageSpeed ; this . _prevUploadedSize = uploaded ; }

Update speed parameters
@link http://stackoverflow.com/questions/2779600/how-to-estimate-download-time-remaining-accurately
@function


function (chunk, event, message) {
      switch (event) {
        case 'progress':
          if (Date.now() - this._lastProgressCallback <
            this.flowObj.opts.progressCallbacksInterval) {
            break;
          }
          this.measureSpeed();
          this.flowObj.fire('fileProgress', this, chunk);
          this.flowObj.fire('progress');
          this._lastProgressCallback = Date.now();
          break;
        case 'error':
          this.error = true;
          this.abort(true);
          this.flowObj.fire('fileError', this, message, chunk);
          this.flowObj.fire('error', message, this, chunk);
          break;
        case 'success':
          if (this.error) {
            return;
          }
          this.measureSpeed();
          this.flowObj.fire('fileProgress', this, chunk);
          this.flowObj.fire('progress');
          this._lastProgressCallback = Date.now();
          if (this.isComplete()) {
            this.currentSpeed = 0;
            this.averageSpeed = 0;
            this.flowObj.fire('fileSuccess', this, message, chunk);
          }
          break;
        case 'retry':
          this.flowObj.fire('fileRetry', this, chunk);
          break;
      }
    }

function ( chunk , event , message ) { switch ( event ) { case 'progress' : if ( Date . now ( ) - this . _lastProgressCallback < this . flowObj . opts . progressCallbacksInterval ) { break ; } this . measureSpeed ( ) ; this . flowObj . fire ( 'fileProgress' , this , chunk ) ; this . flowObj . fire ( 'progress' ) ; this . _lastProgressCallback = Date . now ( ) ; break ; case 'error' : this . error = true ; this . abort ( true ) ; this . flowObj . fire ( 'fileError' , this , message , chunk ) ; this . flowObj . fire ( 'error' , message , this , chunk ) ; break ; case 'success' : if ( this . error ) { return ; } this . measureSpeed ( ) ; this . flowObj . fire ( 'fileProgress' , this , chunk ) ; this . flowObj . fire ( 'progress' ) ; this . _lastProgressCallback = Date . now ( ) ; if ( this . isComplete ( ) ) { this . currentSpeed = 0 ; this . averageSpeed = 0 ; this . flowObj . fire ( 'fileSuccess' , this , message , chunk ) ; } break ; case 'retry' : this . flowObj . fire ( 'fileRetry' , this , chunk ) ; break ; } }

For internal usage only.
Callback when something happens within the chunk.
@function
@param {FlowChunk} chunk
@param {string} event can be 'progress', 'success', 'error' or 'retry'
@param {string} [message]

For internal usage only . Callback when something happens within the chunk .


function (reset) {
      this.currentSpeed = 0;
      this.averageSpeed = 0;
      var chunks = this.chunks;
      if (reset) {
        this.chunks = [];
      }
      each(chunks, function (c) {
        if (c.status() === 'uploading') {
          c.abort();
          this.flowObj.uploadNextChunk();
        }
      }, this);
    }

function ( reset ) { this . currentSpeed = 0 ; this . averageSpeed = 0 ; var chunks = this . chunks ; if ( reset ) { this . chunks = [ ] ; } each ( chunks , function ( c ) { if ( c . status ( ) === 'uploading' ) { c . abort ( ) ; this . flowObj . uploadNextChunk ( ) ; } } , this ) ; }


function () {
      if (typeof this.flowObj.opts.initFileFn === "function") {
        this.flowObj.opts.initFileFn(this);
      }

      this.abort(true);
      this.error = false;
      // Rebuild stack of chunks from file
      this._prevProgress = 0;
      var round = this.flowObj.opts.forceChunkSize ? Math.ceil : Math.floor;
      var chunks = Math.max(
        round(this.size / this.flowObj.opts.chunkSize), 1
      );
      for (var offset = 0; offset < chunks; offset++) {
        this.chunks.push(
          new FlowChunk(this.flowObj, this, offset)
        );
      }
    }

function ( ) { if ( typeof this . flowObj . opts . initFileFn === "function" ) { this . flowObj . opts . initFileFn ( this ) ; } this . abort ( true ) ; this . error = false ; this . _prevProgress = 0 ; var round = this . flowObj . opts . forceChunkSize ? Math . ceil : Math . floor ; var chunks = Math . max ( round ( this . size / this . flowObj . opts . chunkSize ) , 1 ) ; for ( var offset = 0 ; offset < chunks ; offset ++ ) { this . chunks . push ( new FlowChunk ( this . flowObj , this , offset ) ) ; } }

Clear current chunks and slice file again
@function


function () {
      if (this.error) {
        return 1;
      }
      if (this.chunks.length === 1) {
        this._prevProgress = Math.max(this._prevProgress, this.chunks[0].progress());
        return this._prevProgress;
      }
      // Sum up progress across everything
      var bytesLoaded = 0;
      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);
      return this._prevProgress;
    }

function ( ) { if ( this . error ) { return 1 ; } if ( this . chunks . length === 1 ) { this . _prevProgress = Math . max ( this . _prevProgress , this . chunks [ 0 ] . progress ( ) ) ; return this . _prevProgress ; } var bytesLoaded = 0 ; each ( this . chunks , function ( c ) { bytesLoaded += c . progress ( ) * ( c . endByte - c . startByte ) ; } ) ; var percent = bytesLoaded / this . size ; this . _prevProgress = Math . max ( this . _prevProgress , percent > 0.9999 ? 1 : percent ) ; return this . _prevProgress ; }

Get current upload progress status
@function
@returns {number} from 0 to 1


function () {
      var outstanding = false;
      each(this.chunks, function (chunk) {
        var status = chunk.status();
        if (status === 'pending' || status === 'uploading' || status === 'reading' || chunk.preprocessState === 1 || chunk.readState === 1) {
          outstanding = true;
          return false;
        }
      });
      return !outstanding;
    }

function ( ) { var outstanding = false ; each ( this . chunks , function ( chunk ) { var status = chunk . status ( ) ; if ( status === 'pending' || status === 'uploading' || status === 'reading' || chunk . preprocessState === 1 || chunk . readState === 1 ) { outstanding = true ; return false ; } } ) ; return ! outstanding ; }

Indicates if file is has finished uploading and received a response
@function
@returns {boolean}


function () {
      if (this.paused || this.error) {
        return 0;
      }
      var delta = this.size - this.sizeUploaded();
      if (delta && !this.averageSpeed) {
        return Number.POSITIVE_INFINITY;
      }
      if (!delta && !this.averageSpeed) {
        return 0;
      }
      return Math.floor(delta / this.averageSpeed);
    }

function ( ) { if ( this . paused || this . error ) { return 0 ; } var delta = this . size - this . sizeUploaded ( ) ; if ( delta && ! this . averageSpeed ) { return Number . POSITIVE_INFINITY ; } if ( ! delta && ! this . averageSpeed ) { return 0 ; } return Math . floor ( delta / this . averageSpeed ) ; }

Returns remaining time to finish upload file in seconds. Accuracy is based on average speed.
If speed is zero, time remaining will be equal to positive infinity `Number.POSITIVE_INFINITY`
@function
@returns {number}

Returns remaining time to finish upload file in seconds . Accuracy is based on average speed . If speed is zero time remaining will be equal to positive infinity Number . POSITIVE_INFINITY


function webAPIFileRead(fileObj, startByte, endByte, fileType, chunk) {
    var function_name = 'slice';

    if (fileObj.file.slice)
      function_name =  'slice';
    else if (fileObj.file.mozSlice)
      function_name = 'mozSlice';
    else if (fileObj.file.webkitSlice)
      function_name = 'webkitSlice';

    chunk.readFinished(fileObj.file[function_name](startByte, endByte, fileType));
  }

function webAPIFileRead ( fileObj , startByte , endByte , fileType , chunk ) { var function_name = 'slice' ; if ( fileObj . file . slice ) function_name = 'slice' ; else if ( fileObj . file . mozSlice ) function_name = 'mozSlice' ; else if ( fileObj . file . webkitSlice ) function_name = 'webkitSlice' ; chunk . readFinished ( fileObj . file [ function_name ] ( startByte , endByte , fileType ) ) ; }

Default read function using the webAPI

@function webAPIFileRead(fileObj, startByte, endByte, fileType, chunk)


function () {
      // Set up request and listen for event
      this.xhr = new XMLHttpRequest();
      this.xhr.addEventListener("load", this.testHandler, false);
      this.xhr.addEventListener("error", this.testHandler, false);
      var testMethod = evalOpts(this.flowObj.opts.testMethod, this.fileObj, this);
      var data = this.prepareXhrRequest(testMethod, true);
      this.xhr.send(data);
    }

function ( ) { this . xhr = new XMLHttpRequest ( ) ; this . xhr . addEventListener ( "load" , this . testHandler , false ) ; this . xhr . addEventListener ( "error" , this . testHandler , false ) ; var testMethod = evalOpts ( this . flowObj . opts . testMethod , this . fileObj , this ) ; var data = this . prepareXhrRequest ( testMethod , true ) ; this . xhr . send ( data ) ; }

Makes a GET request without any data to see if the chunk has already
been uploaded in a previous session
@function


function () {
      var preprocess = this.flowObj.opts.preprocess;
      var read = this.flowObj.opts.readFileFn;
      if (typeof preprocess === 'function') {
        switch (this.preprocessState) {
          case 0:
            this.preprocessState = 1;
            preprocess(this);
            return;
          case 1:
            return;
        }
      }
      switch (this.readState) {
        case 0:
          this.readState = 1;
          read(this.fileObj, this.startByte, this.endByte, this.fileObj.file.type, this);
          return;
        case 1:
          return;
      }
      if (this.flowObj.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', this.progressHandler, false);
      this.xhr.addEventListener("load", this.doneHandler, false);
      this.xhr.addEventListener("error", this.doneHandler, false);

      var uploadMethod = evalOpts(this.flowObj.opts.uploadMethod, this.fileObj, this);
      var data = this.prepareXhrRequest(uploadMethod, false, this.flowObj.opts.method, this.bytes);
      this.xhr.send(data);
    }

function ( ) { var preprocess = this . flowObj . opts . preprocess ; var read = this . flowObj . opts . readFileFn ; if ( typeof preprocess === 'function' ) { switch ( this . preprocessState ) { case 0 : this . preprocessState = 1 ; preprocess ( this ) ; return ; case 1 : return ; } } switch ( this . readState ) { case 0 : this . readState = 1 ; read ( this . fileObj , this . startByte , this . endByte , this . fileObj . file . type , this ) ; return ; case 1 : return ; } if ( this . flowObj . opts . testChunks && ! this . tested ) { this . test ( ) ; return ; } this . loaded = 0 ; this . total = 0 ; this . pendingRetry = false ; this . xhr = new XMLHttpRequest ( ) ; this . xhr . upload . addEventListener ( 'progress' , this . progressHandler , false ) ; this . xhr . addEventListener ( "load" , this . doneHandler , false ) ; this . xhr . addEventListener ( "error" , this . doneHandler , false ) ; var uploadMethod = evalOpts ( this . flowObj . opts . uploadMethod , this . fileObj , this ) ; var data = this . prepareXhrRequest ( uploadMethod , false , this . flowObj . opts . method , this . bytes ) ; this . xhr . send ( data ) ; }

Uploads the actual data in a POST call
@function


function (isTest) {
      if (this.readState === 1) {
        return '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 'uploading';
      } else if (!this.xhr) {
        return 'pending';
      } else if (this.xhr.readyState < 4) {
        // Status is really 'OPENED', 'HEADERS_RECEIVED'
        // or 'LOADING' - meaning that stuff is happening
        return 'uploading';
      } else {
        if (this.flowObj.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.
          return 'success';
        } else if (this.flowObj.opts.permanentErrors.indexOf(this.xhr.status) > -1 ||
            !isTest && this.retries >= this.flowObj.opts.maxChunkRetries) {
          // HTTP 413/415/500/501, permanent error
          return '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();
          return 'pending';
        }
      }
    }

function ( isTest ) { if ( this . readState === 1 ) { return 'reading' ; } else if ( this . pendingRetry || this . preprocessState === 1 ) { return 'uploading' ; } else if ( ! this . xhr ) { return 'pending' ; } else if ( this . xhr . readyState < 4 ) { return 'uploading' ; } else { if ( this . flowObj . opts . successStatuses . indexOf ( this . xhr . status ) > - 1 ) { return 'success' ; } else if ( this . flowObj . opts . permanentErrors . indexOf ( this . xhr . status ) > - 1 || ! isTest && this . retries >= this . flowObj . opts . maxChunkRetries ) { return 'error' ; } else { this . abort ( ) ; return 'pending' ; } } }

Retrieve current chunk upload status
@function
@returns {string} 'pending', 'uploading', 'success', 'error'


function(method, isTest, paramsMethod, blob) {
      // Add data from the query options
      var query = evalOpts(this.flowObj.opts.query, this.fileObj, this, isTest);
      query = extend(query || {}, this.getParams());

      var target = evalOpts(this.flowObj.opts.target, this.fileObj, this, isTest);
      var data = null;
      if (method === 'GET' || paramsMethod === 'octet') {
        // Add data from the query options
        var params = [];
        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();
        each(query, function (v, k) {
          data.append(k, v);
        });
        if (typeof blob !== "undefined") data.append(this.flowObj.opts.fileParameterName, blob, this.fileObj.file.name);
      }

      this.xhr.open(method, target, true);
      this.xhr.withCredentials = this.flowObj.opts.withCredentials;

      // Add data from header options
      each(evalOpts(this.flowObj.opts.headers, this.fileObj, this, isTest), function (v, k) {
        this.xhr.setRequestHeader(k, v);
      }, this);

      return data;
    }

function ( method , isTest , paramsMethod , blob ) { var query = evalOpts ( this . flowObj . opts . query , this . fileObj , this , isTest ) ; query = extend ( query || { } , this . getParams ( ) ) ; var target = evalOpts ( this . flowObj . opts . target , this . fileObj , this , isTest ) ; var data = null ; if ( method === 'GET' || paramsMethod === 'octet' ) { var params = [ ] ; each ( query , function ( v , k ) { params . push ( [ encodeURIComponent ( k ) , encodeURIComponent ( v ) ] . join ( '=' ) ) ; } ) ; target = this . getTarget ( target , params ) ; data = blob || null ; } else { data = new FormData ( ) ; each ( query , function ( v , k ) { data . append ( k , v ) ; } ) ; if ( typeof blob !== "undefined" ) data . append ( this . flowObj . opts . fileParameterName , blob , this . fileObj . file . name ) ; } this . xhr . open ( method , target , true ) ; this . xhr . withCredentials = this . flowObj . opts . withCredentials ; each ( evalOpts ( this . flowObj . opts . headers , this . fileObj , this , isTest ) , function ( v , k ) { this . xhr . setRequestHeader ( k , v ) ; } , this ) ; return data ; }

Prepare Xhr request. Set query, headers and data
@param {string} method GET or POST
@param {bool} isTest is this a test request
@param {string} [paramsMethod] octet or form
@param {Blob} [blob] to send
@returns {FormData|Blob|Null} data to send

Prepare Xhr request . Set query headers and data


function evalOpts(data, args) {
    if (typeof data === "function") {
      // `arguments` is an object, not array, in FF, so:
      args = Array.prototype.slice.call(arguments);
      data = data.apply(null, args.slice(1));
    }
    return data;
  }

function evalOpts ( data , args ) { if ( typeof data === "function" ) { args = Array . prototype . slice . call ( arguments ) ; data = data . apply ( null , args . slice ( 1 ) ) ; } return data ; }

If option is a function, evaluate it with given params
@param {*} data
@param {...} args arguments of a callback
@returns {*}

If option is a function evaluate it with given params


function each(obj, callback, context) {
    if (!obj) {
      return ;
    }
    var key;
    // Is Array?
    // Array.isArray won't work, not only arrays can be iterated by index https://github.com/flowjs/ng-flow/issues/236#
    if (typeof(obj.length) !== 'undefined') {
      for (key = 0; key < obj.length; key++) {
        if (callback.call(context, obj[key], key) === false) {
          return ;
        }
      }
    } else {
      for (key in obj) {
        if (obj.hasOwnProperty(key) && callback.call(context, obj[key], key) === false) {
          return ;
        }
      }
    }
  }

function each ( obj , callback , context ) { if ( ! obj ) { return ; } var key ; if ( typeof ( obj . length ) !== 'undefined' ) { for ( key = 0 ; key < obj . length ; key ++ ) { if ( callback . call ( context , obj [ key ] , key ) === false ) { return ; } } } else { for ( key in obj ) { if ( obj . hasOwnProperty ( key ) && callback . call ( context , obj [ key ] , key ) === false ) { return ; } } } }

Iterate each element of an object
@function
@param {Array|Object} obj object or an array to iterate
@param {Function} callback first argument is a value and second is a key.
@param {Object=} context Object to become context (`this`) for the iterator function.


function createTable() {
    tableName = arguments[0];
    var fname = '';
    var callback;
    if (arguments.length === 2) {

        callback = arguments[1];
        fname = path.join(userData, tableName + '.json');
    } else if (arguments.length === 3) {
        fname = path.join(arguments[1], arguments[0] + '.json');
        callback = arguments[2];
    }

    // Check if the file with the tablename.json exists
    let exists = fs.existsSync(fname);

    if (exists) {
        // The file exists, do not recreate the table/json file
        callback(false, tableName + '.json already exists!');
        return;
    } else {
        // Create an empty object and pass an empty array as value
        let obj = new Object();
        obj[tableName] = [];

        // Write the object to json file
        try {
            fs.writeFileSync(fname, JSON.stringify(obj, null, 2), (err) => {

            })
            callback(true, "Success!")
            return;
        } catch (e) {
            callback(false, e.toString());
            return;
        }

    }
}

function
createTable
(
)
{
tableName
=
arguments
[
0
]
;
var
fname
=
''
;
var
callback
;
if
(
arguments
.
length
===
2
)
{
callback
=
arguments
[
1
]
;
fname
=
path
.
join
(
userData
,
tableName
+
'.json'
)
;
}
else
if
(
arguments
.
length
===
3
)
{
fname
=
path
.
join
(
arguments
[
1
]
,
arguments
[
0
]
+
'.json'
)
;
callback
=
arguments
[
2
]
;
}
let
exists
=
fs
.
existsSync
(
fname
)
;
if
(
exists
)
{
callback
(
false
,
tableName
+
'.json already exists!'
)
;
return
;
}
else
{
let
obj
=
new
Object
(
)
;
obj
[
tableName
]
=
[
]
;
try
{
fs
.
writeFileSync
(
fname
,
JSON
.
stringify
(
obj
,
,
2
)
,
(
err
)
=>
{
}
)
callback
(
true
,
"Success!"
)
return
;
}
catch
(
e
)
{
callback
(
false
,
e
.
toString
(
)
)
;
return
;
}
}
}

Create a table | a json file
The second argument is optional, if ommitted, the file
will be created at the default location.
@param  {[string]} arguments[0] [Table name]
@param {[string]} arguments[1] [Location of the database file] (Optional)
@param {[function]} arguments[2] [Callbak ]
 function createTable(tableName, callback) {

Create a table | a json file The second argument is optional if ommitted the file will be created at the default location .


function valid() {
    var fName = ''
    if (arguments.length == 2) {
        // Given the database name and location
        const dbName = arguments[0]
        const dbLocation = arguments[1]
        var fName = path.join(dbLocation, dbName + '.json')
    } else if (arguments.length == 1) {
        const dbName = arguments[0]
        fname = path.join(userData, dbName + '.json')
    }

    const content = fs.readFileSync(fName, 'utf-8')
    try {
        JSON.parse(content)
    } catch (e) {
        return false
    }
    return true
}

function valid ( ) { var fName = '' if ( arguments . length == 2 ) { const dbName = arguments [ 0 ] const dbLocation = arguments [ 1 ] var fName = path . join ( dbLocation , dbName + '.json' ) } else if ( arguments . length == 1 ) { const dbName = arguments [ 0 ] fname = path . join ( userData , dbName + '.json' ) } const content = fs . readFileSync ( fName , 'utf-8' ) try { JSON . parse ( content ) } catch ( e ) { return false } return true }

Checks if a json file contains valid JSON string


function insertTableContent() {
    let tableName = arguments[0];
    var fname = '';
    var callback;
    var tableRow;
    if (arguments.length === 3) {
        callback = arguments[2];
        fname = path.join(userData, arguments[0] + '.json');
        tableRow = arguments[1];
    } else if (arguments.length === 4) {
        fname = path.join(arguments[1], arguments[0] + '.json');
        callback = arguments[3];
        tableRow = arguments[2];
    }

    let exists = fs.existsSync(fname);

    if (exists) {
        // Table | json parsed
        let table = JSON.parse(fs.readFileSync(fname));

        let date = new Date();
        let id = date.getTime();
        tableRow['id'] = id;

        table[tableName].push(tableRow);

        try {
            fs.writeFileSync(fname, JSON.stringify(table, null, 2), (err) => {

            })

            callback(true, "Object written successfully!");
            return;
        } catch (e) {
            callback(false, "Error writing object.");
            return;
        }
    }
    callback(false, "Table/json file doesn't exist!");
    return;
}

function
insertTableContent
(
)
{
let
tableName
=
arguments
[
0
]
;
var
fname
=
''
;
var
callback
;
var
tableRow
;
if
(
arguments
.
length
===
3
)
{
callback
=
arguments
[
2
]
;
fname
=
path
.
join
(
userData
,
arguments
[
0
]
+
'.json'
)
;
tableRow
=
arguments
[
1
]
;
}
else
if
(
arguments
.
length
===
4
)
{
fname
=
path
.
join
(
arguments
[
1
]
,
arguments
[
0
]
+
'.json'
)
;
callback
=
arguments
[
3
]
;
tableRow
=
arguments
[
2
]
;
}
let
exists
=
fs
.
existsSync
(
fname
)
;
if
(
exists
)
{
let
table
=
JSON
.
parse
(
fs
.
readFileSync
(
fname
)
)
;
let
date
=
new
Date
(
)
;
let
id
=
date
.
getTime
(
)
;
tableRow
[
'id'
]
=
id
;
table
[
tableName
]
.
push
(
tableRow
)
;
try
{
fs
.
writeFileSync
(
fname
,
JSON
.
stringify
(
table
,
,
2
)
,
(
err
)
=>
{
}
)
callback
(
true
,
"Object written successfully!"
)
;
return
;
}
catch
(
e
)
{
callback
(
false
,
"Error writing object."
)
;
return
;
}
}
callback
(
false
,
"Table/json file doesn't exist!"
)
;
return
;
}

Insert object to table. The object will be appended with the property, id
which uses timestamp as value.
There are 3 required arguments.
@param  {string} arguments[0]  [Table name]
@param  {string} arguments[1] [Location of the database file] (Optional)
@param  {string} arguments[2] [Row object]
@param  {Function} arguments[3] [Callback function]
 function insertTableContent(tableName, tableRow, callback) {

Insert object to table . The object will be appended with the property id which uses timestamp as value . There are 3 required arguments .


function count() {
    let tableName = arguments[0]
    let callback
    if (arguments.length === 2) {
        callback = arguments[1]
        getAll(tableName, (succ, data) => {
            if (succ) {
                callback(true, data.length)
                return
            } else {
                callback(false, data)
                return
            }
        })
    } else if (arguments.length === 3) {
        callback = arguments[2]
        getAll(tableName, arguments[1], (succ, data) => {
            if (succ) {
                callback(true, data.length)
                return
            } else {
                callback(false, data)
                return
            }
        })
    } else {
        callback(false,'Wrong number of arguments. Must be either 2 or 3 arguments including callback function.')
        return
    }
}

Count the number of rows for a given table.
@param {string} FirstArgument Table name
@param {string} SecondArgument Location of the database file (Optional)
@param {callback} ThirdArgument Function callback

Count the number of rows for a given table .


function updateRow() {
    let tableName = arguments[0];
    var fname = '';
    var where;
    var set;
    var callback;

    if (arguments.length === 4) {
        fname = path.join(userData, tableName + '.json');
        where = arguments[1];
        set = arguments[2];
        callback = arguments[3];
    } else if (arguments.length === 5) {
        fname = path.join(arguments[1], arguments[0] + '.json');
        where = arguments[2];
        set = arguments[3];
        callback = arguments[4];
    }

    let exists = fs.existsSync(fname);

    let whereKeys = Object.keys(where);
    let setKeys = Object.keys(set);

    if (exists) {
        let table = JSON.parse(fs.readFileSync(fname));
        let rows = table[tableName];

        let matched = 0; // Number of matched complete where clause
        let matchedIndex = 0;

        for (var i = 0; i < rows.length; i++) {

            for (var j = 0; j < whereKeys.length; j++) {
                // Test if there is a matched key with where clause and single row of table
                if (rows[i].hasOwnProperty(whereKeys[j])) {
                    if (rows[i][whereKeys[j]] === where[whereKeys[j]]) {
                        matched++;
                        matchedIndex = i;
                    }
                }
            }
        }

        if (matched === whereKeys.length) {
            // All field from where clause are present in this particular
            // row of the database table
            try {
                for (var k = 0; k < setKeys.length; k++) {
                    // rows[i][setKeys[k]] = set[setKeys[k]];
                    rows[matchedIndex][setKeys[k]] = set[setKeys[k]];
                }

                // Create a new object and pass the rows
                let obj = new Object();
                obj[tableName] = rows;

                // Write the object to json file
                try {
                    fs.writeFileSync(fname, JSON.stringify(obj, null, 2), (err) => {

                    })

                    callback(true, "Success!")
                    return;
                } catch (e) {
                    callback(false, e.toString());
                    return;
                }

                callback(true, rows);
            } catch (e) {
                callback(false, e.toString());
                return;
            }
        } else {
            callback(false, "Cannot find the specified record.");
            return;
        }

    } else {
        callback(false, 'Table file does not exist!');
        return;
    }
}

function
updateRow
(
)
{
let
tableName
=
arguments
[
0
]
;
var
fname
=
''
;
var
where
;
var
set
;
var
callback
;
if
(
arguments
.
length
===
4
)
{
fname
=
path
.
join
(
userData
,
tableName
+
'.json'
)
;
where
=
arguments
[
1
]
;
set
=
arguments
[
2
]
;
callback
=
arguments
[
3
]
;
}
else
if
(
arguments
.
length
===
5
)
{
fname
=
path
.
join
(
arguments
[
1
]
,
arguments
[
0
]
+
'.json'
)
;
where
=
arguments
[
2
]
;
set
=
arguments
[
3
]
;
callback
=
arguments
[
4
]
;
}
let
exists
=
fs
.
existsSync
(
fname
)
;
let
whereKeys
=
Object
.
keys
(
where
)
;
let
setKeys
=
Object
.
keys
(
set
)
;
if
(
exists
)
{
let
table
=
JSON
.
parse
(
fs
.
readFileSync
(
fname
)
)
;
let
rows
=
table
[
tableName
]
;
let
matched
=
0
;
let
matchedIndex
=
0
;
for
(
var
i
=
0
;
i
<
rows
.
length
;
i
++
)
{
for
(
var
j
=
0
;
j
<
whereKeys
.
length
;
j
++
)
{
if
(
rows
[
i
]
.
hasOwnProperty
(
whereKeys
[
j
]
)
)
{
if
(
rows
[
i
]
[
whereKeys
[
j
]
]
===
where
[
whereKeys
[
j
]
]
)
{
matched
++
;
matchedIndex
=
i
;
}
}
}
}
if
(
matched
===
whereKeys
.
length
)
{
try
{
for
(
var
k
=
0
;
k
<
setKeys
.
length
;
k
++
)
{
rows
[
matchedIndex
]
[
setKeys
[
k
]
]
=
set
[
setKeys
[
k
]
]
;
}
let
obj
=
new
Object
(
)
;
obj
[
tableName
]
=
rows
;
try
{
fs
.
writeFileSync
(
fname
,
JSON
.
stringify
(
obj
,
,
2
)
,
(
err
)
=>
{
}
)
callback
(
true
,
"Success!"
)
return
;
}
catch
(
e
)
{
callback
(
false
,
e
.
toString
(
)
)
;
return
;
}
callback
(
true
,
rows
)
;
}
catch
(
e
)
{
callback
(
false
,
e
.
toString
(
)
)
;
return
;
}
}
else
{
callback
(
false
,
"Cannot find the specified record."
)
;
return
;
}
}
else
{
callback
(
false
,
'Table file does not exist!'
)
;
return
;
}
}

Update a row or record which satisfies the where clause
@param  {[string]} arguments[0] [Table name]
@param {string} arguments[1] [Location of the database file] (Optional)
@param  {[object]} arguments[2]     [Objet for WHERE clause]
@param  {[object]} arguments[3]       [Object for SET clause]
@param  {Function} arguments[4]  [Callback function]
 function updateRow(tableName, where, set, callback) {


function createHeaderGetter (str) {
  var name = str.toLowerCase()

  return function (req, res) {
    // set appropriate Vary header
    vary(res, str)

    // get header
    var header = req.headers[name]

    if (!header) {
      return undefined
    }

    // multiple headers get joined with comma by node.js core
    var index = header.indexOf(',')

    // return first value
    return index !== -1
      ? header.substr(0, index).trim()
      : header.trim()
  }
}

function createHeaderGetter ( str ) { var name = str . toLowerCase ( ) return function ( req , res ) { vary ( res , str ) var header = req . headers [ name ] if ( ! header ) { return undefined } var index = header . indexOf ( ',' ) return index !== - 1 ? header . substr ( 0 , index ) . trim ( ) : header . trim ( ) } }

Create a getter for the given header name.

Create a getter for the given header name .


function Param(name, shortName, process) {
      if (process == null) {
        process = cloudinary.Util.identity;
      }

      /**
       * The name of the parameter in snake_case
       * @member {string} Param#name
       */
      this.name = name;

      /**
       * The name of the serialized form of the parameter
       * @member {string} Param#shortName
       */
      this.shortName = shortName;

      /**
       * Manipulate origValue when value is called
       * @member {function} Param#process
       */
      this.process = process;
    }

function Param ( name , shortName , process ) { if ( process == null ) { process = cloudinary . Util . identity ; } this . name = name ; this . shortName = shortName ; this . process = process ; }

Represents a single parameter
@class Param
@param {string} name - The name of the parameter in snake_case
@param {string} shortName - The name of the serialized form of the parameter.
If a value is not provided, the parameter will not be serialized.
@param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called
@ignore


function ArrayParam(name, shortName, sep, process) {
      if (sep == null) {
        sep = '.';
      }
      this.sep = sep;
      ArrayParam.__super__.constructor.call(this, name, shortName, process);
    }

function ArrayParam ( name , shortName , sep , process ) { if ( sep == null ) { sep = '.' ; } this . sep = sep ; ArrayParam . __super__ . constructor . call ( this , name , shortName , process ) ; }

A parameter that represents an array
@param {string} name - The name of the parameter in snake_case
@param {string} shortName - The name of the serialized form of the parameter
If a value is not provided, the parameter will not be serialized.
@param {string} [sep='.'] - The separator to use when joining the array elements together
@param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called
@class ArrayParam
@extends Param
@ignore


function TransformationParam(name, shortName, sep, process) {
      if (shortName == null) {
        shortName = "t";
      }
      if (sep == null) {
        sep = '.';
      }
      this.sep = sep;
      TransformationParam.__super__.constructor.call(this, name, shortName, process);
    }

function TransformationParam ( name , shortName , sep , process ) { if ( shortName == null ) { shortName = "t" ; } if ( sep == null ) { sep = '.' ; } this . sep = sep ; TransformationParam . __super__ . constructor . call ( this , name , shortName , process ) ; }

A parameter that represents a transformation
@param {string} name - The name of the parameter in snake_case
@param {string} [shortName='t'] - The name of the serialized form of the parameter
@param {string} [sep='.'] - The separator to use when joining the array elements together
@param {function} [process=cloudinary.Util.identity ] - Manipulate origValue when value is called
@class TransformationParam
@extends Param
@ignore


function RangeParam(name, shortName, process) {
      if (process == null) {
        process = this.norm_range_value;
      }
      RangeParam.__super__.constructor.call(this, name, shortName, process);
    }

function RangeParam ( name , shortName , process ) { if ( process == null ) { process = this . norm_range_value ; } RangeParam . __super__ . constructor . call ( this , name , shortName , process ) ; }

A parameter that represents a range
@param {string} name - The name of the parameter in snake_case
@param {string} shortName - The name of the serialized form of the parameter
If a value is not provided, the parameter will not be serialized.
@param {function} [process=norm_range_value ] - Manipulate origValue when value is called
@class RangeParam
@extends Param
@ignore


function Configuration(options) {
      if (options == null) {
        options = {};
      }
      this.configuration = Util.cloneDeep(options);
      Util.defaults(this.configuration, DEFAULT_CONFIGURATION_PARAMS);
    }

function Configuration ( options ) { if ( options == null ) { options = { } ; } this . configuration = Util . cloneDeep ( options ) ; Util . defaults ( this . configuration , DEFAULT_CONFIGURATION_PARAMS ) ; }

Cloudinary configuration class
@constructor Configuration
@param {Object} options - configuration parameters


function Cloudinary(options) {
      var configuration;
      this.devicePixelRatioCache = {};
      this.responsiveConfig = {};
      this.responsiveResizeInitialized = false;
      configuration = new Configuration(options);
      this.config = function(newConfig, newValue) {
        return configuration.config(newConfig, newValue);
      };

      /**
       * Use \<meta\> tags in the document to configure this Cloudinary instance.
       * @return {Cloudinary} this for chaining
       */
      this.fromDocument = function() {
        configuration.fromDocument();
        return this;
      };

      /**
       * Use environment variables to configure this Cloudinary instance.
       * @return {Cloudinary} this for chaining
       */
      this.fromEnvironment = function() {
        configuration.fromEnvironment();
        return this;
      };

      /**
       * Initialize configuration.
       * @function Cloudinary#init
       * @see Configuration#init
       * @return {Cloudinary} this for chaining
       */
      this.init = function() {
        configuration.init();
        return this;
      };
    }

function Cloudinary ( options ) { var configuration ; this . devicePixelRatioCache = { } ; this . responsiveConfig = { } ; this . responsiveResizeInitialized = false ; configuration = new Configuration ( options ) ; this . config = function ( newConfig , newValue ) { return configuration . config ( newConfig , newValue ) ; } ; this . fromDocument = function ( ) { configuration . fromDocument ( ) ; return this ; } ; this . fromEnvironment = function ( ) { configuration . fromEnvironment ( ) ; return this ; } ; this . init = function ( ) { configuration . init ( ) ; return this ; } ; }

Main Cloudinary class
@class Cloudinary
@param {Object} options - options to configure Cloudinary
@see Configuration for more details
@example
var cl = new cloudinary.Cloudinary( { cloud_name: "mycloud"});
var imgTag = cl.image("myPicID");


function getMode(env, argv) {
  // When running from parallel-webpack, grab the cli parameters
  argv = Object.keys(argv).length ? argv : require('minimist')(process.argv.slice(2));
  var isProd = (argv.mode || env.mode) === 'production' || env === 'prod' || env.prod;
  return isProd ? 'production' : 'development';
}

function getMode ( env , argv ) { argv = Object . keys ( argv ) . length ? argv : require ( 'minimist' ) ( process . argv . slice ( 2 ) ) ; var isProd = ( argv . mode || env . mode ) === 'production' || env === 'prod' || env . prod ; return isProd ? 'production' : 'development' ; }

Determine the build mode.
@param {object} env - webpack environment
@param {boolean} [env.production] - when true, set mode to production
@param {boolean} [env.development] - when true, set mode to development
@param {object} argv - webpack options
@param {string} [argv.mode] - the build mode


function resolveLodash(context, request, callback) {
  if (/^lodash\//.test(request)) {
    callback(null, {
      commonjs: request,
      commonjs2: request,
      amd: request,
      root: ['_', request.split('/')[1]]
    });
  } else {
    callback();
  }
}

function resolveLodash ( context , request , callback ) { if ( / ^lodash\/ / . test ( request ) ) { callback ( null , { commonjs : request , commonjs2 : request , amd : request , root : [ '_' , request . split ( '/' ) [ 1 ] ] } ) ; } else { callback ( ) ; } }

This function is used by webpack to resolve individual lodash modules
@param context
@param request
@param callback


function baseConfig(name, mode) {
  const config = {
    name: `${name}-${mode}`,
    mode,
    output: {
      library: 'cloudinary',
      libraryTarget: 'umd',
      globalObject: "this",
      pathinfo: false
    },
    optimization: {
      concatenateModules: true,
      moduleIds: 'named',
      usedExports: true,
      minimizer: [new TerserPlugin({
        terserOptions: {
          mangle: {
            keep_classnames: true,
            reserved: reserved,
            ie8: true
          }
        },
      })]
    },
    resolve: {
      extensions: ['.js']
    },
    externals: [
      {
        jquery: 'jQuery'
      }
    ],
    node: {
      Buffer: false,
      process: false
    },
    devtool: "source-map",
    module: {
      rules: [
        {
          test: /\.m?js$/,
          exclude: /(node_modules|bower_components)/,
          use: {loader: 'babel-loader'}
        }
      ]
    },
    plugins: [
      new webpack.BannerPlugin({
        banner: `/**
   * cloudinary-[name].js
   * Cloudinary's JavaScript library - Version ${version}
   * Copyright Cloudinary
   * see https://github.com/cloudinary/cloudinary_js
   *
   */`, // the banner as string or function, it will be wrapped in a comment
        raw: true, // if true, banner will not be wrapped in a comment
        entryOnly: true, // if true, the banner will only be added to the entry chunks
      })
    ]
  };

  let filename = `cloudinary-${name}`;
  if(mode === 'production') { filename += '.min';}

  const util = name.startsWith('jquery') ? 'jquery' : 'lodash';
  const utilPath = path.resolve(__dirname, `src/util/${util}`);

  config.output.filename = `./${filename}.js`;
  config.entry = `./src/namespace/cloudinary-${name}.js`;
  config.resolve.alias = {
    "../util$": utilPath,
    "./util$": utilPath
  };
  // Add reference to each lodash function as a separate module.
  if (name === 'core') {
    config.externals.push(resolveLodash);
  }
  config.plugins.push(
    new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      reportFilename: `./${filename}-visualizer.html`,
      openAnalyzer: false
    })
  );
  return config;
}

function baseConfig ( name , mode ) { const config = { name : ` ${ name } ${ mode } ` , mode , output : { library : 'cloudinary' , libraryTarget : 'umd' , globalObject : "this" , pathinfo : false } , optimization : { concatenateModules : true , moduleIds : 'named' , usedExports : true , minimizer : [ new TerserPlugin ( { terserOptions : { mangle : { keep_classnames : true , reserved : reserved , ie8 : true } } , } ) ] } , resolve : { extensions : [ '.js' ] } , externals : [ { jquery : 'jQuery' } ] , node : { Buffer : false , process : false } , devtool : "source-map" , module : { rules : [ { test : / \.m?js$ / , exclude : / (node_modules|bower_components) / , use : { loader : 'babel-loader' } } ] } , plugins : [ new webpack . BannerPlugin ( { banner : ` ${ version } ` , raw : true , entryOnly : true , } ) ] } ; let filename = ` ${ name } ` ; if ( mode === 'production' ) { filename += '.min' ; } const util = name . startsWith ( 'jquery' ) ? 'jquery' : 'lodash' ; const utilPath = path . resolve ( __dirname , ` ${ util } ` ) ; config . output . filename = ` ${ filename } ` ; config . entry = ` ${ name } ` ; config . resolve . alias = { "../util$" : utilPath , "./util$" : utilPath } ; if ( name === 'core' ) { config . externals . push ( resolveLodash ) ; } config . plugins . push ( new BundleAnalyzerPlugin ( { analyzerMode : 'static' , reportFilename : ` ${ filename } ` , openAnalyzer : false } ) ) ; return config ; }

Generate a webpack configuration
@param {string} name the name of the package
@param {string} mode either development or production
@return {object} webpack configuration


function finalizeResourceType(resourceType = "image", type = "upload", urlSuffix, useRootPath, shorten) {
  var options;
  resourceType = resourceType == null ? "image" : resourceType;
  type = type == null ? "upload" : type;
  if (isPlainObject(resourceType)) {
    options = resourceType;
    resourceType = options.resource_type;
    type = options.type;
    urlSuffix = options.url_suffix;
    useRootPath = options.use_root_path;
    shorten = options.shorten;
  }
  if (type == null) {
    type = 'upload';
  }
  if (urlSuffix != null) {
    resourceType = SEO_TYPES[`${resourceType}/${type}`];
    type = null;
    if (resourceType == null) {
      throw new Error(`URL Suffix only supported for ${Object.keys(SEO_TYPES).join(', ')}`);
    }
  }
  if (useRootPath) {
    if (resourceType === 'image' && type === 'upload' || resourceType === "images") {
      resourceType = null;
      type = null;
    } else {
      throw new Error("Root path only supported for image/upload");
    }
  }
  if (shorten && resourceType === 'image' && type === 'upload') {
    resourceType = 'iu';
    type = null;
  }
  return [resourceType, type].join("/");
}

Return the resource type and action type based on the given configuration
@function Cloudinary#finalizeResourceType
@param {Object|string} resourceType
@param {string} [type='upload']
@param {string} [urlSuffix]
@param {boolean} [useRootPath]
@param {boolean} [shorten]
@returns {string} resource_type/type
@ignore


function Drag(parent, options) {
        _classCallCheck(this, Drag);

        options = options || {};

        var _this = _possibleConstructorReturn(this, (Drag.__proto__ || Object.getPrototypeOf(Drag)).call(this, parent));

        _this.moved = false;
        _this.wheelActive = utils.defaults(options.wheel, true);
        _this.wheelScroll = options.wheelScroll || 1;
        _this.reverse = options.reverse ? 1 : -1;
        _this.clampWheel = options.clampWheel;
        _this.factor = options.factor || 1;
        _this.xDirection = !options.direction || options.direction === 'all' || options.direction === 'x';
        _this.yDirection = !options.direction || options.direction === 'all' || options.direction === 'y';
        _this.parseUnderflow(options.underflow || 'center');
        _this.mouseButtons(options.mouseButtons);
        return _this;
    }

function Drag ( parent , options ) { _classCallCheck ( this , Drag ) ; options = options || { } ; var _this = _possibleConstructorReturn ( this , ( Drag . __proto__ || Object . getPrototypeOf ( Drag ) ) . call ( this , parent ) ) ; _this . moved = false ; _this . wheelActive = utils . defaults ( options . wheel , true ) ; _this . wheelScroll = options . wheelScroll || 1 ; _this . reverse = options . reverse ? 1 : - 1 ; _this . clampWheel = options . clampWheel ; _this . factor = options . factor || 1 ; _this . xDirection = ! options . direction || options . direction === 'all' || options . direction === 'x' ; _this . yDirection = ! options . direction || options . direction === 'all' || options . direction === 'y' ; _this . parseUnderflow ( options . underflow || 'center' ) ; _this . mouseButtons ( options . mouseButtons ) ; return _this ; }

enable one-finger touch to drag
@private
@param {Viewport} parent
@param {object} [options]
@param {string} [options.direction=all] direction to drag (all, x, or y)
@param {boolean} [options.wheel=true] use wheel to scroll in y direction (unless wheel plugin is active)
@param {number} [options.wheelScroll=1] number of pixels to scroll with each wheel spin
@param {boolean} [options.reverse] reverse the direction of the wheel scroll
@param {boolean|string} [options.clampWheel] (true, x, or y) clamp wheel (to avoid weird bounce with mouse wheel)
@param {string} [options.underflow=center] (top/bottom/center and left/right/center, or center) where to place world if too small for screen
@param {number} [options.factor=1] factor to multiply drag to increase the speed of movement
@param {string} [options.mouseButtons=all] changes which mouse buttons trigger drag, use: 'all', 'left', right' 'middle', or some combination, like, 'middle-right'


function each(object, fn) {
  keys(object).forEach(function (key) {
    return fn(object[key], key);
  });
}

function each ( object , fn ) { keys ( object ) . forEach ( function ( key ) { return fn ( object [ key ] , key ) ; } ) ; }

Array-like iteration for objects.

@param {Object} object
The object to iterate over

@param {obj:EachCallback} fn
The callback function which is called for each key in the object.


function reduce(object, fn) {
  var initial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;

  return keys(object).reduce(function (accum, key) {
    return fn(accum, object[key], key);
  }, initial);
}

function reduce ( object , fn ) { var initial = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : 0 ; return keys ( object ) . reduce ( function ( accum , key ) { return fn ( accum , object [ key ] , key ) ; } , initial ) ; }

Array-like reduce for objects.

@param {Object} object
The Object that you want to reduce.

@param {Function} fn
A callback function which is called for each key in the object. It
receives the accumulated value and the per-iteration value and key
as arguments.

@param {Mixed} [initial = 0]
Starting value

@return {Mixed}
The final accumulated value.


function isPlain(value) {
  return isObject(value) && toString.call(value) === '[object Object]' && value.constructor === Object;
}

function
isPlain
(
value
)
{
return
isObject
(
value
)
&&
toString
.
call
(
value
)
===
'[object Object]'
&&
value
.
constructor
===
Object
;
}

Returns whether an object appears to be a "plain" object - that is, a
direct instance of `Object`.

@param  {Object} value
@return {Boolean}

Returns whether an object appears to be a plain object - that is a direct instance of Object .


function logByType(type, args) {
  var stringify = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : !!IE_VERSION && IE_VERSION < 11;

  var lvl = log.levels[level];
  var lvlRegExp = new RegExp('^(' + lvl + ')$');

  if (type !== 'log') {

    // Add the type to the front of the message when it's not "log".
    args.unshift(type.toUpperCase() + ':');
  }

  // Add a clone of the args at this point to history.
  if (history) {
    history.push([].concat(args));
  }

  // Add console prefix after adding to history.
  args.unshift('VIDEOJS:');

  // If there's no console then don't try to output messages, but they will
  // still be stored in history.
  //
  // Was setting these once outside of this function, but containing them
  // in the function makes it easier to test cases where console doesn't exist
  // when the module is executed.
  var fn = window.console && window.console[type];

  // Bail out if there's no console or if this type is not allowed by the
  // current logging level.
  if (!fn || !lvl || !lvlRegExp.test(type)) {
    return;
  }

  // IEs previous to 11 log objects uselessly as "[object Object]"; so, JSONify
  // objects and arrays for those less-capable browsers.
  if (stringify) {
    args = args.map(function (a) {
      if (isObject(a) || Array.isArray(a)) {
        try {
          return JSON.stringify(a);
        } catch (x) {
          return String(a);
        }
      }

      // Cast to string before joining, so we get null and undefined explicitly
      // included in output (as we would in a modern console).
      return String(a);
    }).join(' ');
  }

  // Old IE versions do not allow .apply() for console methods (they are
  // reported as objects rather than functions).
  if (!fn.apply) {
    fn(args);
  } else {
    fn[Array.isArray(args) ? 'apply' : 'call'](window.console, args);
  }
}

function
logByType
(
type
,
args
)
{
var
stringify
=
arguments
.
length
>
2
&&
arguments
[
2
]
!==
undefined
arguments
[
2
]
:
!
!
IE_VERSION
&&
IE_VERSION
<
11
;
var
lvl
=
log
.
levels
[
level
]
;
var
lvlRegExp
=
new
RegExp
(
'^('
+
lvl
+
')$'
)
;
if
(
type
!==
'log'
)
{
args
.
unshift
(
type
.
toUpperCase
(
)
+
':'
)
;
}
if
(
history
)
{
history
.
push
(
[
]
.
concat
(
args
)
)
;
}
args
.
unshift
(
'VIDEOJS:'
)
;
var
fn
=
window
.
console
&&
window
.
console
[
type
]
;
if
(
!
fn
||
!
lvl
||
!
lvlRegExp
.
test
(
type
)
)
{
return
;
}
if
(
stringify
)
{
args
=
args
.
map
(
function
(
a
)
{
if
(
isObject
(
a
)
||
Array
.
isArray
(
a
)
)
{
try
{
return
JSON
.
stringify
(
a
)
;
}
catch
(
x
)
{
return
String
(
a
)
;
}
}
return
String
(
a
)
;
}
)
.
join
(
' '
)
;
}
if
(
!
fn
.
apply
)
{
fn
(
args
)
;
}
else
{
fn
[
Array
.
isArray
(
args
)
'apply'
:
'call'
]
(
window
.
console
,
args
)
;
}
}

Log messages to the console and history based on the type of message

@private
@param  {string} type
The name of the console method to use.

@param  {Array} args
The arguments to be passed to the matching console method.

@param  {boolean} [stringify]
By default, only old IEs should get console argument stringification,
but this is exposed as a parameter to facilitate testing.


function createEl() {
  var tagName = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'div';
  var properties = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  var content = arguments[3];

  var el = document.createElement(tagName);

  Object.getOwnPropertyNames(properties).forEach(function (propName) {
    var val = properties[propName];

    // See #2176
    // We originally were accepting both properties and attributes in the
    // same object, but that doesn't work so well.
    if (propName.indexOf('aria-') !== -1 || propName === 'role' || propName === 'type') {
      log$1.warn(tsml(_templateObject, propName, val));
      el.setAttribute(propName, val);

      // Handle textContent since it's not supported everywhere and we have a
      // method for it.
    } else if (propName === 'textContent') {
      textContent(el, val);
    } else {
      el[propName] = val;
    }
  });

  Object.getOwnPropertyNames(attributes).forEach(function (attrName) {
    el.setAttribute(attrName, attributes[attrName]);
  });

  if (content) {
    appendContent(el, content);
  }

  return el;
}

function createEl ( ) { var tagName = arguments . length > 0 && arguments [ 0 ] !== undefined ? arguments [ 0 ] : 'div' ; var properties = arguments . length > 1 && arguments [ 1 ] !== undefined ? arguments [ 1 ] : { } ; var attributes = arguments . length > 2 && arguments [ 2 ] !== undefined ? arguments [ 2 ] : { } ; var content = arguments [ 3 ] ; var el = document . createElement ( tagName ) ; Object . getOwnPropertyNames ( properties ) . forEach ( function ( propName ) { var val = properties [ propName ] ; if ( propName . indexOf ( 'aria-' ) !== - 1 || propName === 'role' || propName === 'type' ) { log$1 . warn ( tsml ( _templateObject , propName , val ) ) ; el . setAttribute ( propName , val ) ; } else if ( propName === 'textContent' ) { textContent ( el , val ) ; } else { el [ propName ] = val ; } } ) ; Object . getOwnPropertyNames ( attributes ) . forEach ( function ( attrName ) { el . setAttribute ( attrName , attributes [ attrName ] ) ; } ) ; if ( content ) { appendContent ( el , content ) ; } return el ; }

Creates an element and applies properties.

@param {string} [tagName='div']
Name of tag to be created.

@param {Object} [properties={}]
Element properties to be applied.

@param {Object} [attributes={}]
Element attributes to be applied.

@param {String|Element|TextNode|Array|Function} [content]
Contents for the element (see: {@link dom:normalizeContent})

@return {Element}
The element that was created.

Creates an element and applies properties .


function addClass(element, classToAdd) {
  if (element.classList) {
    element.classList.add(classToAdd);

    // Don't need to `throwIfWhitespace` here because `hasElClass` will do it
    // in the case of classList not being supported.
  } else if (!hasClass(element, classToAdd)) {
    element.className = (element.className + ' ' + classToAdd).trim();
  }

  return element;
}

function
addClass
(
element
,
classToAdd
)
{
if
(
element
.
classList
)
{
element
.
classList
.
add
(
classToAdd
)
;
}
else
if
(
!
hasClass
(
element
,
classToAdd
)
)
{
element
.
className
=
(
element
.
className
+
' '
+
classToAdd
)
.
trim
(
)
;
}
return
element
;
}

Add a CSS class name to an element

@param {Element} element
Element to add class name to.

@param {string} classToAdd
Class name to add.

@return {Element}
The dom element with the added class name.


function toggleClass(element, classToToggle, predicate) {

  // This CANNOT use `classList` internally because IE does not support the
  // second parameter to the `classList.toggle()` method! Which is fine because
  // `classList` will be used by the add/remove functions.
  var has = hasClass(element, classToToggle);

  if (typeof predicate === 'function') {
    predicate = predicate(element, classToToggle);
  }

  if (typeof predicate !== 'boolean') {
    predicate = !has;
  }

  // If the necessary class operation matches the current state of the
  // element, no action is required.
  if (predicate === has) {
    return;
  }

  if (predicate) {
    addClass(element, classToToggle);
  } else {
    removeClass(element, classToToggle);
  }

  return element;
}

function toggleClass ( element , classToToggle , predicate ) { var has = hasClass ( element , classToToggle ) ; if ( typeof predicate === 'function' ) { predicate = predicate ( element , classToToggle ) ; } if ( typeof predicate !== 'boolean' ) { predicate = ! has ; } if ( predicate === has ) { return ; } if ( predicate ) { addClass ( element , classToToggle ) ; } else { removeClass ( element , classToToggle ) ; } return element ; }

The callback definition for toggleElClass.

@callback Dom~PredicateCallback
@param {Element} element
The DOM element of the Component.

@param {string} classToToggle
The `className` that wants to be toggled

@return {boolean|undefined}
- If true the `classToToggle` will get added to `element`.
- If false the `classToToggle` will get removed from `element`.
- If undefined this callback will be ignored

Adds or removes a CSS class name on an element depending on an optional
condition or the presence/absence of the class name.

@param {Element} element
The element to toggle a class name on.

@param {string} classToToggle
The class that should be toggled

@param {boolean|PredicateCallback} [predicate]
See the return value for {@link Dom~PredicateCallback}

@return {Element}
The element with a class that has been toggled.

The callback definition for toggleElClass .


function getPointerPosition(el, event) {
  var position = {};
  var box = findPosition(el);
  var boxW = el.offsetWidth;
  var boxH = el.offsetHeight;

  var boxY = box.top;
  var boxX = box.left;
  var pageY = event.pageY;
  var pageX = event.pageX;

  if (event.changedTouches) {
    pageX = event.changedTouches[0].pageX;
    pageY = event.changedTouches[0].pageY;
  }

  position.y = Math.max(0, Math.min(1, (boxY - pageY + boxH) / boxH));
  position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));

  return position;
}

function getPointerPosition ( el , event ) { var position = { } ; var box = findPosition ( el ) ; var boxW = el . offsetWidth ; var boxH = el . offsetHeight ; var boxY = box . top ; var boxX = box . left ; var pageY = event . pageY ; var pageX = event . pageX ; if ( event . changedTouches ) { pageX = event . changedTouches [ 0 ] . pageX ; pageY = event . changedTouches [ 0 ] . pageY ; } position . y = Math . max ( 0 , Math . min ( 1 , ( boxY - pageY + boxH ) / boxH ) ) ; position . x = Math . max ( 0 , Math . min ( 1 , ( pageX - boxX ) / boxW ) ) ; return position ; }

x and y coordinates for a dom element or mouse pointer

@typedef {Object} Dom~Coordinates

@property {number} x
x coordinate in pixels

@property {number} y
y coordinate in pixels

Get pointer position in element
Returns an object with x and y coordinates.
The base on the coordinates are the bottom left of the element.

@param {Element} el
Element on which to get the pointer position on

@param {EventTarget~Event} event
Event object

@return {Dom~Coordinates}
A Coordinates object corresponding to the mouse position.


function appendContent(el, content) {
  normalizeContent(content).forEach(function (node) {
    return el.appendChild(node);
  });
  return el;
}

function appendContent ( el , content ) { normalizeContent ( content ) . forEach ( function ( node ) { return el . appendChild ( node ) ; } ) ; return el ; }

Normalizes and appends content to an element.

@param {Element} el
Element to append normalized content to.

@param {String|Element|TextNode|Array|Function} content
See the `content` argument of {@link dom:normalizeContent}

@return {Element}
The element with appended normalized content.

Normalizes and appends content to an element .


function getData(el) {
  var id = el[elIdAttr];

  if (!id) {
    id = el[elIdAttr] = newGUID();
  }

  if (!elData[id]) {
    elData[id] = {};
  }

  return elData[id];
}

function getData ( el ) { var id = el [ elIdAttr ] ; if ( ! id ) { id = el [ elIdAttr ] = newGUID ( ) ; } if ( ! elData [ id ] ) { elData [ id ] = { } ; } return elData [ id ] ; }

Returns the cache object where data for an element is stored

@param {Element} el
Element to store data for.

@return {Object}
The cache object for that el that was passed in.


function hasData(el) {
  var id = el[elIdAttr];

  if (!id) {
    return false;
  }

  return !!Object.getOwnPropertyNames(elData[id]).length;
}

function hasData ( el ) { var id = el [ elIdAttr ] ; if ( ! id ) { return false ; } return ! ! Object . getOwnPropertyNames ( elData [ id ] ) . length ; }

Returns whether or not an element has cached data

@param {Element} el
Check if this element has cached data.

@return {boolean}
- True if the DOM element has cached data.
- False otherwise.


function removeData(el) {
  var id = el[elIdAttr];

  if (!id) {
    return;
  }

  // Remove all stored data
  delete elData[id];

  // Remove the elIdAttr property from the DOM node
  try {
    delete el[elIdAttr];
  } catch (e) {
    if (el.removeAttribute) {
      el.removeAttribute(elIdAttr);
    } else {
      // IE doesn't appear to support removeAttribute on the document element
      el[elIdAttr] = null;
    }
  }
}

function removeData ( el ) { var id = el [ elIdAttr ] ; if ( ! id ) { return ; } delete elData [ id ] ; try { delete el [ elIdAttr ] ; } catch ( e ) { if ( el . removeAttribute ) { el . removeAttribute ( elIdAttr ) ; } else { el [ elIdAttr ] = null ; } } }

Delete data for the element from the cache and the guid attr from getElementById

@param {Element} el
Remove cached data for this element.


function _handleMultipleEvents(fn, elem, types, callback) {
  types.forEach(function (type) {
    // Call the event method for each one of the types
    fn(elem, type, callback);
  });
}

function _handleMultipleEvents ( fn , elem , types , callback ) { types . forEach ( function ( type ) { fn ( elem , type , callback ) ; } ) ; }

Loops through an array of event types and calls the requested method for each type.

@param {Function} fn
The event method we want to use.

@param {Element|Object} elem
Element or object to bind listeners to

@param {string} type
Type of event to bind to.

@param {EventTarget~EventListener} callback
Event listener.

Loops through an array of event types and calls the requested method for each type .


function off(elem, type, fn) {
  // Don't want to add a cache object through getElData if not needed
  if (!hasData(elem)) {
    return;
  }

  var data = getData(elem);

  // If no events exist, nothing to unbind
  if (!data.handlers) {
    return;
  }

  if (Array.isArray(type)) {
    return _handleMultipleEvents(off, elem, type, fn);
  }

  // Utility function
  var removeType = function removeType(t) {
    data.handlers[t] = [];
    _cleanUpEvents(elem, t);
  };

  // Are we removing all bound events?
  if (!type) {
    for (var t in data.handlers) {
      removeType(t);
    }
    return;
  }

  var handlers = data.handlers[type];

  // If no handlers exist, nothing to unbind
  if (!handlers) {
    return;
  }

  // If no listener was provided, remove all listeners for type
  if (!fn) {
    removeType(type);
    return;
  }

  // We're only removing a single handler
  if (fn.guid) {
    for (var n = 0; n < handlers.length; n++) {
      if (handlers[n].guid === fn.guid) {
        handlers.splice(n--, 1);
      }
    }
  }

  _cleanUpEvents(elem, type);
}

function off ( elem , type , fn ) { if ( ! hasData ( elem ) ) { return ; } var data = getData ( elem ) ; if ( ! data . handlers ) { return ; } if ( Array . isArray ( type ) ) { return _handleMultipleEvents ( off , elem , type , fn ) ; } var removeType = function removeType ( t ) { data . handlers [ t ] = [ ] ; _cleanUpEvents ( elem , t ) ; } ; if ( ! type ) { for ( var t in data . handlers ) { removeType ( t ) ; } return ; } var handlers = data . handlers [ type ] ; if ( ! handlers ) { return ; } if ( ! fn ) { removeType ( type ) ; return ; } if ( fn . guid ) { for ( var n = 0 ; n < handlers . length ; n ++ ) { if ( handlers [ n ] . guid === fn . guid ) { handlers . splice ( n -- , 1 ) ; } } } _cleanUpEvents ( elem , type ) ; }

Removes event listeners from an element

@param {Element|Object} elem
Object to remove listeners from.

@param {string|string[]} [type]
Type of listener to remove. Don't include to remove all events from element.

@param {EventTarget~EventListener} [fn]
Specific listener to remove. Don't include to remove listeners for an event
type.


function one(elem, type, fn) {
  if (Array.isArray(type)) {
    return _handleMultipleEvents(one, elem, type, fn);
  }
  var func = function func() {
    off(elem, type, func);
    fn.apply(this, arguments);
  };

  // copy the guid to the new function so it can removed using the original function's ID
  func.guid = fn.guid = fn.guid || newGUID();
  on(elem, type, func);
}

function one ( elem , type , fn ) { if ( Array . isArray ( type ) ) { return _handleMultipleEvents ( one , elem , type , fn ) ; } var func = function func ( ) { off ( elem , type , func ) ; fn . apply ( this , arguments ) ; } ; func . guid = fn . guid = fn . guid || newGUID ( ) ; on ( elem , type , func ) ; }

Trigger a listener only once for an event

@param {Element|Object} elem
Element or object to bind to.

@param {string|string[]} type
Name/type of event

@param {Event~EventListener} fn
Event Listener function


function autoSetup() {

  // Protect against breakage in non-browser environments.
  if (!isReal()) {
    return;
  }

  // One day, when we stop supporting IE8, go back to this, but in the meantime...*hack hack hack*
  // var vids = Array.prototype.slice.call(document.getElementsByTagName('video'));
  // var audios = Array.prototype.slice.call(document.getElementsByTagName('audio'));
  // var mediaEls = vids.concat(audios);

  // Because IE8 doesn't support calling slice on a node list, we need to loop
  // through each list of elements to build up a new, combined list of elements.
  var vids = document.getElementsByTagName('video');
  var audios = document.getElementsByTagName('audio');
  var mediaEls = [];

  if (vids && vids.length > 0) {
    for (var i = 0, e = vids.length; i < e; i++) {
      mediaEls.push(vids[i]);
    }
  }

  if (audios && audios.length > 0) {
    for (var _i = 0, _e = audios.length; _i < _e; _i++) {
      mediaEls.push(audios[_i]);
    }
  }

  // Check if any media elements exist
  if (mediaEls && mediaEls.length > 0) {

    for (var _i2 = 0, _e2 = mediaEls.length; _i2 < _e2; _i2++) {
      var mediaEl = mediaEls[_i2];

      // Check if element exists, has getAttribute func.
      // IE seems to consider typeof el.getAttribute == 'object' instead of
      // 'function' like expected, at least when loading the player immediately.
      if (mediaEl && mediaEl.getAttribute) {

        // Make sure this player hasn't already been set up.
        if (mediaEl.player === undefined) {
          var options = mediaEl.getAttribute('data-setup');

          // Check if data-setup attr exists.
          // We only auto-setup if they've added the data-setup attr.
          if (options !== null) {
            // Create new video.js instance.
            videojs$2(mediaEl);
          }
        }

        // If getAttribute isn't defined, we need to wait for the DOM.
      } else {
        autoSetupTimeout(1);
        break;
      }
    }

    // No videos were found, so keep looping unless page is finished loading.
  } else if (!_windowLoaded) {
    autoSetupTimeout(1);
  }
}

function autoSetup ( ) { if ( ! isReal ( ) ) { return ; } var vids = document . getElementsByTagName ( 'video' ) ; var audios = document . getElementsByTagName ( 'audio' ) ; var mediaEls = [ ] ; if ( vids && vids . length > 0 ) { for ( var i = 0 , e = vids . length ; i < e ; i ++ ) { mediaEls . push ( vids [ i ] ) ; } } if ( audios && audios . length > 0 ) { for ( var _i = 0 , _e = audios . length ; _i < _e ; _i ++ ) { mediaEls . push ( audios [ _i ] ) ; } } if ( mediaEls && mediaEls . length > 0 ) { for ( var _i2 = 0 , _e2 = mediaEls . length ; _i2 < _e2 ; _i2 ++ ) { var mediaEl = mediaEls [ _i2 ] ; if ( mediaEl && mediaEl . getAttribute ) { if ( mediaEl . player === undefined ) { var options = mediaEl . getAttribute ( 'data-setup' ) ; if ( options !== null ) { videojs$2 ( mediaEl ) ; } } } else { autoSetupTimeout ( 1 ) ; break ; } } } else if ( ! _windowLoaded ) { autoSetupTimeout ( 1 ) ; } }

Set up any tags that have a data-setup `attribute` when the player is started.

Set up any tags that have a data - setup attribute when the player is started .


function autoSetupTimeout(wait, vjs) {
  if (vjs) {
    videojs$2 = vjs;
  }

  window.setTimeout(autoSetup, wait);
}

function autoSetupTimeout ( wait , vjs ) { if ( vjs ) { videojs$2 = vjs ; } window . setTimeout ( autoSetup , wait ) ; }

Wait until the page is loaded before running autoSetup. This will be called in
autoSetup if `hasLoaded` returns false.

@param {number} wait
How long to wait in ms

@param {module:videojs} [vjs]
The videojs library function

Wait until the page is loaded before running autoSetup . This will be called in autoSetup if hasLoaded returns false .


function setTextContent(el, content) {
  if (el.styleSheet) {
    el.styleSheet.cssText = content;
  } else {
    el.textContent = content;
  }
}

function setTextContent ( el , content ) { if ( el . styleSheet ) { el . styleSheet . cssText = content ; } else { el . textContent = content ; } }

Add text to a DOM element.

@param {Element} el
The Element to add text content to.

@param {string} content
The text to add to the element.


function throttle(fn, wait) {
  var last = Date.now();

  var throttled = function throttled() {
    var now = Date.now();

    if (now - last >= wait) {
      fn.apply(undefined, arguments);
      last = now;
    }
  };

  return throttled;
}

function throttle ( fn , wait ) { var last = Date . now ( ) ; var throttled = function throttled ( ) { var now = Date . now ( ) ; if ( now - last >= wait ) { fn . apply ( undefined , arguments ) ; last = now ; } } ; return throttled ; }

Wraps the given function, `fn`, with a new function that only invokes `fn`
at most once per every `wait` milliseconds.

@param  {Function} fn
The function to be throttled.

@param  {Number}   wait
The number of milliseconds by which to throttle.

@return {Function}

Wraps the given function fn with a new function that only invokes fn at most once per every wait milliseconds .


function isValidEventType(type) {
  return (
    // The regex here verifies that the `type` contains at least one non-
    // whitespace character.
    typeof type === 'string' && /\S/.test(type) || Array.isArray(type) && !!type.length
  );
}

function isValidEventType ( type ) { return ( typeof type === 'string' && / \S / . test ( type ) || Array . isArray ( type ) && ! ! type . length ) ; }

Whether a value is a valid event type - non-empty string or array.

@private
@param  {string|Array} type
The type value to test.

@return {boolean}
Whether or not the type is a valid event type.

Whether a value is a valid event type - non - empty string or array .


function Component(player, options, ready) {
    classCallCheck(this, Component);

    // The component might be the player itself and we can't pass `this` to super
    if (!player && this.play) {
      this.player_ = player = this; // eslint-disable-line
    } else {
      this.player_ = player;
    }

    // Make a copy of prototype.options_ to protect against overriding defaults
    this.options_ = mergeOptions({}, this.options_);

    // Updated options with supplied options
    options = this.options_ = mergeOptions(this.options_, options);

    // Get ID from options or options element if one is supplied
    this.id_ = options.id || options.el && options.el.id;

    // If there was no ID from the options, generate one
    if (!this.id_) {
      // Don't require the player ID function in the case of mock players
      var id = player && player.id && player.id() || 'no_player';

      this.id_ = id + '_component_' + newGUID();
    }

    this.name_ = options.name || null;

    // Create element if one wasn't provided in options
    if (options.el) {
      this.el_ = options.el;
    } else if (options.createEl !== false) {
      this.el_ = this.createEl();
    }

    // Make this an evented object and use `el_`, if available, as its event bus
    evented(this, { eventBusKey: this.el_ ? 'el_' : null });
    stateful(this, this.constructor.defaultState);

    this.children_ = [];
    this.childIndex_ = {};
    this.childNameIndex_ = {};

    // Add any child components in options
    if (options.initChildren !== false) {
      this.initChildren();
    }

    this.ready(ready);
    // Don't want to trigger ready here or it will before init is actually
    // finished for all children that run this constructor

    if (options.reportTouchActivity !== false) {
      this.enableTouchActivity();
    }
  }

function Component ( player , options , ready ) { classCallCheck ( this , Component ) ; if ( ! player && this . play ) { this . player_ = player = this ; } else { this . player_ = player ; } this . options_ = mergeOptions ( { } , this . options_ ) ; options = this . options_ = mergeOptions ( this . options_ , options ) ; this . id_ = options . id || options . el && options . el . id ; if ( ! this . id_ ) { var id = player && player . id && player . id ( ) || 'no_player' ; this . id_ = id + '_component_' + newGUID ( ) ; } this . name_ = options . name || null ; if ( options . el ) { this . el_ = options . el ; } else if ( options . createEl !== false ) { this . el_ = this . createEl ( ) ; } evented ( this , { eventBusKey : this . el_ ? 'el_' : null } ) ; stateful ( this , this . constructor . defaultState ) ; this . children_ = [ ] ; this . childIndex_ = { } ; this . childNameIndex_ = { } ; if ( options . initChildren !== false ) { this . initChildren ( ) ; } this . ready ( ready ) ; if ( options . reportTouchActivity !== false ) { this . enableTouchActivity ( ) ; } }

A callback that is called when a component is ready. Does not have any
paramters and any callback value will be ignored.

@callback Component~ReadyCallback
@this Component

Creates an instance of this class.

@param {Player} player
The `Player` that this class should be attached to.

@param {Object} [options]
The key/value store of player options.

@param {Object[]} [options.children]
An array of children objects to intialize this component with. Children objects have
a name property that will be used if more than one component of the same type needs to be
added.

@param {Component~ReadyCallback} [ready]
Function that gets called when the `Component` is ready.

A callback that is called when a component is ready . Does not have any paramters and any callback value will be ignored .


function rangeCheck(fnName, index, maxIndex) {
  if (typeof index !== 'number' || index < 0 || index > maxIndex) {
    throw new Error('Failed to execute \'' + fnName + '\' on \'TimeRanges\': The index provided (' + index + ') is non-numeric or out of bounds (0-' + maxIndex + ').');
  }
}

An object that contains ranges of time for various reasons.

@typedef {Object} TimeRange

@property {number} length
The number of time ranges represented by this Object

@property {time-ranges:indexFunction} start
Returns the time offset at which a specified time range begins.

@property {time-ranges:indexFunction} end
Returns the time offset at which a specified time range begins.

@see https://developer.mozilla.org/en-US/docs/Web/API/TimeRanges

Check if any of the time ranges are over the maximum index.

@param {string} fnName
The function name to use for logging

@param {number} index
The index to check

@param {number} maxIndex
The maximum possible index

@throws {Error} if the timeRanges provided are over the maxIndex

An object that contains ranges of time for various reasons .


function getRange(fnName, valueIndex, ranges, rangeIndex) {
  rangeCheck(fnName, rangeIndex, ranges.length - 1);
  return ranges[rangeIndex][valueIndex];
}

function getRange ( fnName , valueIndex , ranges , rangeIndex ) { rangeCheck ( fnName , rangeIndex , ranges . length - 1 ) ; return ranges [ rangeIndex ] [ valueIndex ] ; }

Check if any of the time ranges are over the maximum index.

@param {string} fnName
The function name to use for logging

@param {string} valueIndex
The proprety that should be used to get the time. should be 'start' or 'end'

@param {Array} ranges
An array of time ranges

@param {Array} [rangeIndex=0]
The index to start the search at

@return {number}
The time that offset at the specified index.

@depricated rangeIndex must be set to a value, in the future this will throw an error.
@throws {Error} if rangeIndex is more than the length of ranges

Check if any of the time ranges are over the maximum index .


function createTimeRangesObj(ranges) {
  if (ranges === undefined || ranges.length === 0) {
    return {
      length: 0,
      start: function start() {
        throw new Error('This TimeRanges object is empty');
      },
      end: function end() {
        throw new Error('This TimeRanges object is empty');
      }
    };
  }
  return {
    length: ranges.length,
    start: getRange.bind(null, 'start', 0, ranges),
    end: getRange.bind(null, 'end', 1, ranges)
  };
}

function
createTimeRangesObj
(
ranges
)
{
if
(
ranges
===
undefined
||
ranges
.
length
===
0
)
{
return
{
length
:
0
,
start
:
function
start
(
)
{
throw
new
Error
(
'This TimeRanges object is empty'
)
;
}
,
end
:
function
end
(
)
{
throw
new
Error
(
'This TimeRanges object is empty'
)
;
}
}
;
}
return
{
length
:
ranges
.
length
,
start
:
getRange
.
bind
(
,
'start'
,
0
,
ranges
)
,
end
:
getRange
.
bind
(
,
'end'
,
1
,
ranges
)
}
;
}

Create a time range object givent ranges of time.

@param {Array} [ranges]
An array of time ranges.

Create a time range object givent ranges of time .


function createTimeRanges(start, end) {
  if (Array.isArray(start)) {
    return createTimeRangesObj(start);
  } else if (start === undefined || end === undefined) {
    return createTimeRangesObj();
  }
  return createTimeRangesObj([[start, end]]);
}

function createTimeRanges ( start , end ) { if ( Array . isArray ( start ) ) { return createTimeRangesObj ( start ) ; } else if ( start === undefined || end === undefined ) { return createTimeRangesObj ( ) ; } return createTimeRangesObj ( [ [ start , end ] ] ) ; }

Should create a fake `TimeRange` object which mimics an HTML5 time range instance.

@param {number|Array} start
The start of a single range or an array of ranges

@param {number} end
The end of a single range.

@private

Should create a fake TimeRange object which mimics an HTML5 time range instance .


function TextTrackCueList(cues) {
    classCallCheck(this, TextTrackCueList);

    var list = this; // eslint-disable-line

    if (IS_IE8) {
      list = document.createElement('custom');

      for (var prop in TextTrackCueList.prototype) {
        if (prop !== 'constructor') {
          list[prop] = TextTrackCueList.prototype[prop];
        }
      }
    }

    TextTrackCueList.prototype.setCues_.call(list, cues);

    /**
     * @memberof TextTrackCueList
     * @member {number} length
     *         The current number of `TextTrackCue`s in the TextTrackCueList.
     * @instance
     */
    Object.defineProperty(list, 'length', {
      get: function get$$1() {
        return this.length_;
      }
    });

    if (IS_IE8) {
      return list;
    }
  }

function TextTrackCueList ( cues ) { classCallCheck ( this , TextTrackCueList ) ; var list = this ; if ( IS_IE8 ) { list = document . createElement ( 'custom' ) ; for ( var prop in TextTrackCueList . prototype ) { if ( prop !== 'constructor' ) { list [ prop ] = TextTrackCueList . prototype [ prop ] ; } } } TextTrackCueList . prototype . setCues_ . call ( list , cues ) ; Object . defineProperty ( list , 'length' , { get : function get$$1 ( ) { return this . length_ ; } } ) ; if ( IS_IE8 ) { return list ; } }

Create an instance of this class..

@param {Array} cues
A list of cues to be initialized with


function getFileExtension(path) {
  if (typeof path === 'string') {
    var splitPathRe = /^(\/?)([\s\S]*?)((?:\.{1,2}|[^\/]+?)(\.([^\.\/\?]+)))(?:[\/]*|[\?].*)$/i;
    var pathParts = splitPathRe.exec(path);

    if (pathParts) {
      return pathParts.pop().toLowerCase();
    }
  }

  return '';
}

Returns the extension of the passed file name. It will return an empty string
if passed an invalid path.

@param {string} path
The fileName path like '/path/to/file.mp4'

@returns {string}
The extension in lower case or an empty string if no
extension could be found.

Returns the extension of the passed file name . It will return an empty string if passed an invalid path .


function loadTrack(src, track) {
  var opts = {
    uri: src
  };
  var crossOrigin = isCrossOrigin(src);

  if (crossOrigin) {
    opts.cors = crossOrigin;
  }

  xhr(opts, bind(this, function (err, response, responseBody) {
    if (err) {
      return log$1.error(err, response);
    }

    track.loaded_ = true;

    // Make sure that vttjs has loaded, otherwise, wait till it finished loading
    // NOTE: this is only used for the alt/video.novtt.js build
    if (typeof window.WebVTT !== 'function') {
      if (track.tech_) {
        var loadHandler = function loadHandler() {
          return parseCues(responseBody, track);
        };

        track.tech_.on('vttjsloaded', loadHandler);
        track.tech_.on('vttjserror', function () {
          log$1.error('vttjs failed to load, stopping trying to process ' + track.src);
          track.tech_.off('vttjsloaded', loadHandler);
        });
      }
    } else {
      parseCues(responseBody, track);
    }
  }));
}

Load a `TextTrack` from a specifed url.

@param {string} src
Url to load track from.

@param {TextTrack} track
Track to add cues to. Comes from the content at the end of `url`.

@private


function constructColor(color, opacity) {
  return 'rgba(' +
  // color looks like "#f0e"
  parseInt(color[1] + color[1], 16) + ',' + parseInt(color[2] + color[2], 16) + ',' + parseInt(color[3] + color[3], 16) + ',' + opacity + ')';
}

function constructColor ( color , opacity ) { return 'rgba(' + parseInt ( color [ 1 ] + color [ 1 ] , 16 ) + ',' + parseInt ( color [ 2 ] + color [ 2 ] , 16 ) + ',' + parseInt ( color [ 3 ] + color [ 3 ] , 16 ) + ',' + opacity + ')' ; }

Construct an rgba color from a given hex color code.

@param {number} color
Hex number for color, like #f0e.

@param {number} opacity
Value for opacity, 0.0 - 1.0.

@return {string}
The rgba color that was created, like 'rgba(255, 0, 0, 0.3)'.

@private

Construct an rgba color from a given hex color code .


function checkVolumeSupport(self, player) {
  // hide volume controls when they're not supported by the current tech
  if (player.tech_ && !player.tech_.featuresVolumeControl) {
    self.addClass('vjs-hidden');
  }

  self.on(player, 'loadstart', function () {
    if (!player.tech_.featuresVolumeControl) {
      self.addClass('vjs-hidden');
    } else {
      self.removeClass('vjs-hidden');
    }
  });
}

function checkVolumeSupport ( self , player ) { if ( player . tech_ && ! player . tech_ . featuresVolumeControl ) { self . addClass ( 'vjs-hidden' ) ; } self . on ( player , 'loadstart' , function ( ) { if ( ! player . tech_ . featuresVolumeControl ) { self . addClass ( 'vjs-hidden' ) ; } else { self . removeClass ( 'vjs-hidden' ) ; } } ) ; }

Check if volume control is supported and if it isn't hide the
`Component` that was passed  using the `vjs-hidden` class.

@param {Component} self
The component that should be hidden if volume is unsupported

@param {Player} player
A reference to the player

@private

Check if volume control is supported and if it isn t hide the Component that was passed using the vjs - hidden class .


function parseOptionValue(value, parser) {
  if (parser) {
    value = parser(value);
  }

  if (value && value !== 'none') {
    return value;
  }
}

function parseOptionValue ( value , parser ) { if ( parser ) { value = parser ( value ) ; } if ( value && value !== 'none' ) { return value ; } }

Get the actual value of an option.

@param  {string} value
The value to get

@param  {Function} [parser]
Optional function to adjust the value.

@return {Mixed}
- Will be `undefined` if no value exists
- Will be `undefined` if the given value is "none".
- Will be the actual value otherwise.

@private


function checkProgress() {
        if (_this3.el_.currentTime > 0) {
          // Trigger durationchange for genuinely live video
          if (_this3.el_.duration === Infinity) {
            _this3.trigger('durationchange');
          }
          _this3.off('timeupdate', checkProgress);
        }
      }

function checkProgress ( ) { if ( _this3 . el_ . currentTime > 0 ) { if ( _this3 . el_ . duration === Infinity ) { _this3 . trigger ( 'durationchange' ) ; } _this3 . off ( 'timeupdate' , checkProgress ) ; } }

Wait for the first `timeupdate` with currentTime > 0 - there may be several with 0

Wait for the first timeupdate with currentTime > 0 - there may be several with 0


function findFirstPassingTechSourcePair(outerArray, innerArray, tester) {
      var found = void 0;

      outerArray.some(function (outerChoice) {
        return innerArray.some(function (innerChoice) {
          found = tester(outerChoice, innerChoice);

          if (found) {
            return true;
          }
        });
      });

      return found;
    }

function findFirstPassingTechSourcePair ( outerArray , innerArray , tester ) { var found = void 0 ; outerArray . some ( function ( outerChoice ) { return innerArray . some ( function ( innerChoice ) { found = tester ( outerChoice , innerChoice ) ; if ( found ) { return true ; } } ) ; } ) ; return found ; }

Iterate over each `innerArray` element once per `outerArray` element and execute `tester` with both. If `tester` returns a non-falsy value, exit early and return that value.

Iterate over each innerArray element once per outerArray element and execute tester with both . If tester returns a non - falsy value exit early and return that value .


function markPluginAsActive(player, name) {
  player[PLUGIN_CACHE_KEY] = player[PLUGIN_CACHE_KEY] || {};
  player[PLUGIN_CACHE_KEY][name] = true;
}

function markPluginAsActive ( player , name ) { player [ PLUGIN_CACHE_KEY ] = player [ PLUGIN_CACHE_KEY ] || { } ; player [ PLUGIN_CACHE_KEY ] [ name ] = true ; }

Marks a plugin as "active" on a player.

Also, ensures that the player has an object for tracking active plugins.

@private
@param   {Player} player
A Video.js player instance.

@param   {string} name
The name of a plugin.