<commit_before>/*
 * tus-jquery-client
 * https://github.com/tus/tus-jquery-client
 *
 * Copyright (c) 2013 Transloadit Ltd and Contributors
 * http://tus.io/
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

(function ($) {
  'use strict';

  // The Public API
  var tus = window.tus = {
    upload: function(file, options) {
      var upload = new ResumableUpload(file, options);
      if (file) {
        upload._start();
      }
      return upload;
    },
    fingerprint: function(file) {
      return 'tus-' + file.name + '-' + file.type + '-' + file.size;
    }
  };

  function ResumableUpload(file, options) {
    // The file to upload
    this.file = file;
    // Options for resumable file uploads
    this.options = {
      // The tus upload endpoint url
      endpoint: options.endpoint,

      // The fingerprint for the file.
      // Uses our own fingerprinting if undefined.
      fingerprint: options.fingerprint,

      // @TODO: second option: resumable: true/false
      // false -> removes resume functionality
      resetBefore: options.resetBefore,
      resetAfter: options.resetAfter
    };

    // The url of the uploaded file, assigned by the tus upload endpoint
    this.fileUrl = null;

    // Bytes sent to the server so far
    this.bytesWritten = null;

    // @TODO Add this.bytesTotal again

    // the jqXHR object
    this._jqXHR = null;

    // Create a deferred and make our upload a promise object
    this._deferred = $.Deferred();
    this._deferred.promise(this);
  }

  // Creates a file resource at the configured tus endpoint and gets the url for it.
  ResumableUpload.prototype._start = function() {
    var self = this;

    // Optionally resetBefore
    if (self.options.resetBefore === true) {
      self._cachedUrl(false);
    }


    // @TODO this belongs in _uploadFile
    var transmit = function (url, bytesWritten) {
      // Save url
      self.bytesWritten = bytesWritten;

      if (self.bytesWritten === self.file.size) {
        // Cool, we already completely uploaded this.
        // Update progress to 100%.
        self._emitProgress();
        return self._emitDone();
      }

      self._cachedUrl(url);
      self._emitProgress();
      self._uploadFile(url, self.bytesWritten, self.file.size - 1);
    };

    if (!(self.fileUrl = self._cachedUrl())) {
      self._post(self.options.endpoint, self.file, transmit);
    } else {
      self._head(self.fileUrl, transmit);
    }
  };

  ResumableUpload.prototype._post = function(url, file, cb) {
    var self    = this;
    var options = {
      type: 'POST',
      url: url,
      headers: {
        'Content-Range': 'bytes */' + file.size,
        'Content-Disposition': 'attachment; filename="' + encodeURI(file.name) + '"'
      }
    };

    $.ajax(options)
      .fail(function(jqXHR, textStatus, errorThrown) {
        // @todo: Implement retry support
        self._emitFail('Could not post to file resource: ' + textStatus);
      })
      .done(function(data, textStatus, jqXHR) {
        if (!(url = jqXHR.getResponseHeader('Location'))) {
          return self._emitFail('Could not get url for file resource: ' + textStatus);
        }

        cb(url, 0);
      });
  };

  ResumableUpload.prototype._head = function(url, cb) {
    var self    = this;
    // @TODO probably needs cache: false option (and maybe more)
    var options = {
      type: 'HEAD',
      url: url
    };

    console.log('Resuming known url ' + url);

    $.ajax(options)
      .fail(function(jqXHR, textStatus, errorThrown) {
        // @TODO: Implement retry support
        self._emitFail('Could not head at file resource: ' + textStatus);
      })
      .done(function(data, textStatus, jqXHR) {
        var range = jqXHR.getResponseHeader('Range');
        var m     = range && range.match(/bytes=\d+-(\d+)/);
        var bytesWritten = 0;
        if (m) {
          // If the server has not received anything so far,
          // there will be no Range header present.
          bytesWritten = parseInt(m[1], 10) + 1;
        }

        cb(url, bytesWritten);
      });
  };

  // Uploads the file data to tus resource url created by _start()
  ResumableUpload.prototype._uploadFile = function(url, range_from, range_to) {
    var self  = this;

    var slice = self.file.slice || self.file.webkitSlice || self.file.mozSlice;
    var blob  = slice.call(self.file, range_from, range_to + 1, self.file.type);
    var xhr   = $.ajaxSettings.xhr();

    var options = {
      type: 'PUT',
      url: url,
      data: blob,
      processData: false,
      contentType: self.file.type,
      cache: false,
      xhr: function() {
        return xhr;
      },
      headers: {
        'Content-Range': 'bytes ' + range_from + '-' + range_to  + '/' + self.file.size
      }
    };

    $(xhr.upload).bind('progress', function(e) {
      self.bytesWritten = e.originalEvent.loaded;
      self._emitProgress(e);
    });

    this._jqXHR = $.ajax(options)
      .fail(function(jqXHR, textStatus, errorThrown) {
        // @TODO: Compile somewhat meaningful error
        // Needs to be cleaned up
        // Needs to have retry
        var msg = jqXHR.responseText || textStatus || errorThrown;
        self._emitFail(msg);
      })
      .done(function() {
        console.log('done', arguments, self, url);

        if (self.options.resetAfter === true) {
          self._cachedUrl(false);
        }

        self._emitDone();
      });
  };<commit_msg>refactor transmit function, move it into _uploadFile; also fixing progress report when resuming an upload<commit_after>/*
 * tus-jquery-client
 * https://github.com/tus/tus-jquery-client
 *
 * Copyright (c) 2013 Transloadit Ltd and Contributors
 * http://tus.io/
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

(function ($) {
  'use strict';

  // The Public API
  var tus = window.tus = {
    upload: function(file, options) {
      var upload = new ResumableUpload(file, options);
      if (file) {
        upload._start();
      }
      return upload;
    },
    fingerprint: function(file) {
      return 'tus-' + file.name + '-' + file.type + '-' + file.size;
    }
  };

  function ResumableUpload(file, options) {
    // The file to upload
    this.file = file;
    // Options for resumable file uploads
    this.options = {
      // The tus upload endpoint url
      endpoint: options.endpoint,

      // The fingerprint for the file.
      // Uses our own fingerprinting if undefined.
      fingerprint: options.fingerprint,

      // @TODO: second option: resumable: true/false
      // false -> removes resume functionality
      resetBefore: options.resetBefore,
      resetAfter: options.resetAfter
    };

    // The url of the uploaded file, assigned by the tus upload endpoint
    this.fileUrl = null;

    // Bytes sent to the server so far
    this.bytesWritten = null;

    // @TODO Add this.bytesTotal again

    // the jqXHR object
    this._jqXHR = null;

    // Create a deferred and make our upload a promise object
    this._deferred = $.Deferred();
    this._deferred.promise(this);
  }

  // Creates a file resource at the configured tus endpoint and gets the url for it.
  ResumableUpload.prototype._start = function() {
    var self = this;

    // Optionally resetBefore
    if (self.options.resetBefore === true) {
      self._cachedUrl(false);
    }

    if (!(self.fileUrl = self._cachedUrl())) {
      self._post(self.options.endpoint, self.file);
    } else {
      self._head(self.fileUrl);
    }
  };

  ResumableUpload.prototype._post = function(url, file, cb) {
    var self    = this;
    var options = {
      type: 'POST',
      url: url,
      headers: {
        'Content-Range': 'bytes */' + file.size,
        'Content-Disposition': 'attachment; filename="' + encodeURI(file.name) + '"'
      }
    };

    $.ajax(options)
      .fail(function(jqXHR, textStatus, errorThrown) {
        // @todo: Implement retry support
        self._emitFail('Could not post to file resource: ' + textStatus);
      })
      .done(function(data, textStatus, jqXHR) {
        if (!(url = jqXHR.getResponseHeader('Location'))) {
          return self._emitFail('Could not get url for file resource: ' + textStatus);
        }

        self._uploadFile(url, 0, file.size - 1);
      });
  };

  ResumableUpload.prototype._head = function(url, cb) {
    var self    = this;
    // @TODO probably needs cache: false option (and maybe more)
    var options = {
      type: 'HEAD',
      url: url
    };

    console.log('Resuming known url ' + url);

    $.ajax(options)
      .fail(function(jqXHR, textStatus, errorThrown) {
        // @TODO: Implement retry support
        self._emitFail('Could not head at file resource: ' + textStatus);
      })
      .done(function(data, textStatus, jqXHR) {
        var range = jqXHR.getResponseHeader('Range');
        var m     = range && range.match(/bytes=\d+-(\d+)/);
        var bytesWritten = 0;
        if (m) {
          // If the server has not received anything so far,
          // there will be no Range header present.
          bytesWritten = parseInt(m[1], 10) + 1;
        }

        self._uploadFile(url, bytesWritten, self.file.size - 1);
      });
  };

  // Uploads the file data to tus resource url created by _start()
  ResumableUpload.prototype._uploadFile = function(url, range_from, range_to) {
    var self  = this;
    this.bytesWritten = range_from;

    if (this.bytesWritten === this.file.size) {
      // Cool, we already completely uploaded this.
      // Update progress to 100%.
      this._emitProgress();
      return this._emitDone();
    }

    this._cachedUrl(url);
    this._emitProgress();

    var bytesWrittenAtStart = this.bytesWritten;

    var slice = self.file.slice || self.file.webkitSlice || self.file.mozSlice;
    var blob  = slice.call(self.file, range_from, range_to + 1, self.file.type);
    var xhr   = $.ajaxSettings.xhr();

    var options = {
      type: 'PUT',
      url: url,
      data: blob,
      processData: false,
      contentType: self.file.type,
      cache: false,
      xhr: function() {
        return xhr;
      },
      headers: {
        'Content-Range': 'bytes ' + range_from + '-' + range_to  + '/' + self.file.size
      }
    };

    $(xhr.upload).bind('progress', function(e) {
      self.bytesWritten = bytesWrittenAtStart + e.originalEvent.loaded;
      self._emitProgress(e);
    });

    this._jqXHR = $.ajax(options)
      .fail(function(jqXHR, textStatus, errorThrown) {
        // @TODO: Compile somewhat meaningful error
        // Needs to be cleaned up
        // Needs to have retry
        var msg = jqXHR.responseText || textStatus || errorThrown;
        self._emitFail(msg);
      })
      .done(function() {
        console.log('done', arguments, self, url);

        if (self.options.resetAfter === true) {
          self._cachedUrl(false);
        }

        self._emitDone();
      });
  };
{'fraction_non_alphanumeric': 0.12917614929449248, 'fraction_numerical': 0.002822030040964952, 'mean_word_length': 2.2474135382796336, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2046781', 'n_tokens_mistral': 3441, 'n_tokens_neox': 3308, 'n_words': 878}