mirror of
https://github.com/rstudio/shiny.git
synced 2026-02-05 04:05:06 -05:00
Split up shiny.js
This commit is contained in:
207
srcjs/input_binding_fileinput.js
Normal file
207
srcjs/input_binding_fileinput.js
Normal file
@@ -0,0 +1,207 @@
|
||||
var IE8FileUploader = function(shinyapp, id, fileEl) {
|
||||
this.shinyapp = shinyapp;
|
||||
this.id = id;
|
||||
this.fileEl = fileEl;
|
||||
this.beginUpload();
|
||||
};
|
||||
(function() {
|
||||
this.beginUpload = function() {
|
||||
var self = this;
|
||||
// Create invisible frame
|
||||
var iframeId = 'shinyupload_iframe_' + this.id;
|
||||
this.iframe = document.createElement('iframe');
|
||||
this.iframe.id = iframeId;
|
||||
this.iframe.name = iframeId;
|
||||
this.iframe.setAttribute('style', 'position: fixed; top: 0; left: 0; width: 0; height: 0; border: none');
|
||||
$('body').append(this.iframe);
|
||||
var iframeDestroy = function() {
|
||||
// Forces Shiny to flushReact, flush outputs, etc. Without this we get
|
||||
// invalidated reactives, but observers don't actually execute.
|
||||
self.shinyapp.makeRequest('uploadieFinish', [], function(){}, function(){});
|
||||
$(self.iframe).remove();
|
||||
};
|
||||
if (this.iframe.attachEvent) {
|
||||
this.iframe.attachEvent('onload', iframeDestroy);
|
||||
} else {
|
||||
this.iframe.onload = iframeDestroy;
|
||||
}
|
||||
|
||||
this.form = document.createElement('form');
|
||||
this.form.method = 'POST';
|
||||
this.form.setAttribute('enctype', 'multipart/form-data');
|
||||
this.form.action = "session/" + encodeURI(this.shinyapp.config.sessionId) +
|
||||
"/uploadie/" + encodeURI(this.id);
|
||||
this.form.id = 'shinyupload_form_' + this.id;
|
||||
this.form.target = iframeId;
|
||||
$(this.form).insertAfter(this.fileEl).append(this.fileEl);
|
||||
this.form.submit();
|
||||
};
|
||||
}).call(IE8FileUploader.prototype);
|
||||
|
||||
var FileUploader = function(shinyapp, id, files) {
|
||||
this.shinyapp = shinyapp;
|
||||
this.id = id;
|
||||
FileProcessor.call(this, files);
|
||||
};
|
||||
$.extend(FileUploader.prototype, FileProcessor.prototype);
|
||||
(function() {
|
||||
this.makeRequest = function(method, args, onSuccess, onFailure, blobs) {
|
||||
this.shinyapp.makeRequest(method, args, onSuccess, onFailure, blobs);
|
||||
};
|
||||
this.onBegin = function(files, cont) {
|
||||
var self = this;
|
||||
|
||||
// Reset progress bar
|
||||
this.$setError(null);
|
||||
this.$setActive(true);
|
||||
this.$setVisible(true);
|
||||
this.onProgress(null, 0);
|
||||
|
||||
this.totalBytes = 0;
|
||||
this.progressBytes = 0;
|
||||
$.each(files, function(i, file) {
|
||||
self.totalBytes += file.size;
|
||||
});
|
||||
|
||||
var fileInfo = $.map(files, function(file, i) {
|
||||
return {
|
||||
name: file.name,
|
||||
size: file.size,
|
||||
type: file.type
|
||||
};
|
||||
});
|
||||
|
||||
this.makeRequest(
|
||||
'uploadInit', [fileInfo],
|
||||
function(response) {
|
||||
self.jobId = response.jobId;
|
||||
self.uploadUrl = response.uploadUrl;
|
||||
cont();
|
||||
},
|
||||
function(error) {
|
||||
self.onError(error);
|
||||
});
|
||||
};
|
||||
this.onFile = function(file, cont) {
|
||||
var self = this;
|
||||
this.onProgress(file, 0);
|
||||
|
||||
$.ajax(this.uploadUrl, {
|
||||
type: 'POST',
|
||||
cache: false,
|
||||
xhr: function() {
|
||||
var xhrVal = $.ajaxSettings.xhr();
|
||||
if (xhrVal.upload) {
|
||||
xhrVal.upload.onprogress = function(e) {
|
||||
if (e.lengthComputable) {
|
||||
self.onProgress(
|
||||
file,
|
||||
(self.progressBytes + e.loaded) / self.totalBytes);
|
||||
}
|
||||
};
|
||||
}
|
||||
return xhrVal;
|
||||
},
|
||||
data: file,
|
||||
processData: false,
|
||||
success: function() {
|
||||
self.progressBytes += file.size;
|
||||
cont();
|
||||
},
|
||||
error: function(jqXHR, textStatus, errorThrown) {
|
||||
self.onError(jqXHR.responseText || textStatus);
|
||||
}
|
||||
});
|
||||
};
|
||||
this.onComplete = function() {
|
||||
var self = this;
|
||||
this.makeRequest(
|
||||
'uploadEnd', [this.jobId, this.id],
|
||||
function(response) {
|
||||
self.$setActive(false);
|
||||
self.onProgress(null, 1);
|
||||
self.$bar().text('Upload complete');
|
||||
},
|
||||
function(error) {
|
||||
self.onError(error);
|
||||
});
|
||||
this.$bar().text('Finishing upload');
|
||||
};
|
||||
this.onError = function(message) {
|
||||
this.$setError(message || '');
|
||||
this.$setActive(false);
|
||||
};
|
||||
this.onAbort = function() {
|
||||
this.$setVisible(false);
|
||||
};
|
||||
this.onProgress = function(file, completed) {
|
||||
this.$bar().width(Math.round(completed*100) + '%');
|
||||
this.$bar().text(file ? file.name : '');
|
||||
};
|
||||
this.$container = function() {
|
||||
return $('#' + $escape(this.id) + '_progress.shiny-file-input-progress');
|
||||
};
|
||||
this.$bar = function() {
|
||||
return $('#' + $escape(this.id) + '_progress.shiny-file-input-progress .progress-bar');
|
||||
};
|
||||
this.$setVisible = function(visible) {
|
||||
this.$container().css('visibility', visible ? 'visible' : 'hidden');
|
||||
};
|
||||
this.$setError = function(error) {
|
||||
this.$bar().toggleClass('bar-danger', (error !== null));
|
||||
if (error !== null) {
|
||||
this.onProgress(null, 1);
|
||||
this.$bar().text(error);
|
||||
}
|
||||
};
|
||||
this.$setActive = function(active) {
|
||||
this.$container().toggleClass('active', !!active);
|
||||
};
|
||||
}).call(FileUploader.prototype);
|
||||
|
||||
|
||||
function uploadFiles(evt) {
|
||||
// If previously selected files are uploading, abort that.
|
||||
var el = $(evt.target);
|
||||
var uploader = el.data('currentUploader');
|
||||
if (uploader)
|
||||
uploader.abort();
|
||||
|
||||
var files = evt.target.files;
|
||||
var IE8 = (browser.isIE && browser.IEVersion === 8);
|
||||
var id = fileInputBinding.getId(evt.target);
|
||||
|
||||
if (!IE8 && files.length === 0)
|
||||
return;
|
||||
|
||||
// Start the new upload and put the uploader in 'currentUploader'.
|
||||
if (IE8) {
|
||||
/*jshint nonew:false */
|
||||
new IE8FileUploader(exports.shinyapp, id, evt.target);
|
||||
} else {
|
||||
el.data('currentUploader', new FileUploader(exports.shinyapp, id, files));
|
||||
}
|
||||
}
|
||||
|
||||
var fileInputBinding = new InputBinding();
|
||||
$.extend(fileInputBinding, {
|
||||
find: function(scope) {
|
||||
return $(scope).find('input[type="file"]');
|
||||
},
|
||||
getId: function(el) {
|
||||
return InputBinding.prototype.getId.call(this, el) || el.name;
|
||||
},
|
||||
getValue: function(el) {
|
||||
return null;
|
||||
},
|
||||
setValue: function(el, value) {
|
||||
// Not implemented
|
||||
},
|
||||
subscribe: function(el, callback) {
|
||||
$(el).on('change.fileInputBinding', uploadFiles);
|
||||
},
|
||||
unsubscribe: function(el) {
|
||||
$(el).off('.fileInputBinding');
|
||||
}
|
||||
});
|
||||
inputBindings.register(fileInputBinding, 'shiny.fileInputBinding');
|
||||
Reference in New Issue
Block a user