Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* An attempt to get Froala's image uploader to upload to Firebase storage, and update a
- * custom record in the Firebase realtime database while we're at it.
- *
- * Froala expects to be doing an XHR (eg POST to some service) to upload the data, and whilst
- * we can hook before the XHR call, our options are pretty limited: basically we can cancel the
- * operation and that's it.
- *
- * Froala does support Amazon S3, but that's essentially another XHR POST to a slightly differently
- * constructed URL.
- *
- * Froala initialises a new XHR to a URL (opts.imageUploadURL + opts.imageUploadParams +
- * opts.imageUploadParam[content]) and a METHOD (opts.imageUploadMethod)
- *
- * This XHR is passed to a function which handles the FileRead (to generate the content).
- * The XHR's onload is used to trigger the UI update.
- *
- * Froala constructs its XHR using self.core.getXHR(url, method) where 'self' is the editor instance.
- * Therefore we should be able to monkey-patch a custom core.getXHR which watches for a special
- * 'url' (eg "firebase://"). If it sees it, it returns a custom object that behaves like an XHR,
- * and if it doesn't it just passes the call on to the original core.getXHR method.
- *
- * We need to emulate:
- * .onload()
- * .onerror()
- * .onabort()
- * .upload.onprogress()
- * .abort()
- * .send()
- * .readyState
- * .status (needs to return 2xx)
- * .responseText (needs to be JSON {link: some_url } )
- *
- * To make this work, include this plugin and invoke froala with a config like:
- * { imageUploadURL: 'firebase://storage/images/misc', imageUploadParam: 'file' }
- */
- (function($) {
- $.FroalaEditor.DEFAULTS = $.extend($.FroalaEditor.DEFAULTS, {
- firebasex: null // don't need this, firebase is massive! er global I mean
- });
- function Interceptor(path) {
- this.path = path;
- // 0:UNSENT, 1:OPENED, 2: HEADERS_RECEIVED, 3: LOADING, 4: DONE
- this.readyState = 0;
- this.onload = null;
- this.onerror = null;
- this.onabort = null;
- this.upload = {
- onprogress: null
- };
- }
- Interceptor.prototype = {
- abort: function() {
- if(this.uploadTask) {
- this.uploadTask.cancel();
- this.uploadTask = null;
- if(this.onabort) {
- this.onabort();
- }
- }
- },
- send: function(form_data) {
- var that = this;
- this.file = form_data.get('file');
- this.filename = this.file.name;
- this.filetype = this.file.type;
- this.uid = new Date().getTime();
- var p1 = this.filename.split('.');
- var p2 = this.filetype.split('/');
- if(p1.length > 1) {
- this.fileext = p1.pop();
- } else if(p2.length > 1) {
- this.fileext = p2.pop();
- } else {
- this.fileext = 'bin';
- }
- var firebase_path = [this.path, [this.uid, this.fileext].join('.')].join('/');
- console.log("upload to firebase path: ", firebase_path);
- var storage = firebase.storage();
- var ref = storage.ref();
- var file_ref = ref.child(firebase_path);
- var metadata = this.filetype ? { contentType: this.filetype } : null;
- this.uploadTask = file_ref.put(this.file, metadata);
- this.uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, function(snapshot) {
- // state change observer
- var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
- console.log("upload progress " + progress.toFixed(2) + "%");
- if(that.upload.onprogress) {
- that.upload.onprogress({
- lengthComputable: true,
- loaded: snapshot.bytesTransferred,
- size: snapshot.totalBytes,
- total: snapshot.totalBytes
- });
- }
- switch(snapshot.state) {
- case firebase.storage.TaskState.PAUSED:
- console.log("upload paused");
- break;
- case firebase.storage.TaskState.RUNNING:
- console.log("upload resumed");
- break;
- }
- }, function(error) {
- // error handler
- console.log("upload error: ", error.code);
- if(that.onerror) {
- console.log("invoke error cb");
- that.onerror({ responseText: error.code});
- }
- }, function() {
- // completion handler
- console.log("upload complete");
- var downloadUrl = that.uploadTask.snapshot.downloadURL;
- // TODO: database callback
- that.readyState = 4; // DONE
- that.uploadTask = null;
- that.status = 200;
- that.responseText = JSON.stringify({
- link: downloadUrl
- });
- if(that.onload) {
- console.log("invoke completion cb");
- that.onload();
- }
- });
- this.readyState = 3; // LOADING
- }
- };
- $.FroalaEditor.PLUGINS.subverter = function(editor) {
- var oldXHR = editor.core.getXHR;
- function _init() {
- console.log("subverter init");
- if(firebase) {
- editor.core.getXHR = function(url, method) {
- console.log("subverter in the middle: ", url);
- // if we see firebase://storage/some/path then we write
- // 'some/path/UNIQ.filetype' to firebase storage
- var re = new RegExp("firebase://([^/]+)/(.+)");
- var m = re.exec(url);
- if(m) {
- console.log("MATCH %O", m);
- if(m[1] == 'storage') {
- var path = m[2];
- var n = new Interceptor(path);
- return n;
- }
- }
- return oldXHR(url, method);
- };
- } else {
- console.log("missing firebase object");
- }
- }
- return {
- _init: _init
- }
- };
- })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement