Advertisement
Guest User

Untitled

a guest
Aug 24th, 2016
66
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.39 KB | None | 0 0
  1. /* An attempt to get Froala's image uploader to upload to Firebase storage, and update a
  2. * custom record in the Firebase realtime database while we're at it.
  3. *
  4. * Froala expects to be doing an XHR (eg POST to some service) to upload the data, and whilst
  5. * we can hook before the XHR call, our options are pretty limited: basically we can cancel the
  6. * operation and that's it.
  7. *
  8. * Froala does support Amazon S3, but that's essentially another XHR POST to a slightly differently
  9. * constructed URL.
  10. *
  11. * Froala initialises a new XHR to a URL (opts.imageUploadURL + opts.imageUploadParams +
  12. * opts.imageUploadParam[content]) and a METHOD (opts.imageUploadMethod)
  13. *
  14. * This XHR is passed to a function which handles the FileRead (to generate the content).
  15. * The XHR's onload is used to trigger the UI update.
  16. *
  17. * Froala constructs its XHR using self.core.getXHR(url, method) where 'self' is the editor instance.
  18. * Therefore we should be able to monkey-patch a custom core.getXHR which watches for a special
  19. * 'url' (eg "firebase://"). If it sees it, it returns a custom object that behaves like an XHR,
  20. * and if it doesn't it just passes the call on to the original core.getXHR method.
  21. *
  22. * We need to emulate:
  23. * .onload()
  24. * .onerror()
  25. * .onabort()
  26. * .upload.onprogress()
  27. * .abort()
  28. * .send()
  29. * .readyState
  30. * .status (needs to return 2xx)
  31. * .responseText (needs to be JSON {link: some_url } )
  32. *
  33. * To make this work, include this plugin and invoke froala with a config like:
  34. * { imageUploadURL: 'firebase://storage/images/misc', imageUploadParam: 'file' }
  35. */
  36. (function($) {
  37. $.FroalaEditor.DEFAULTS = $.extend($.FroalaEditor.DEFAULTS, {
  38. firebasex: null // don't need this, firebase is massive! er global I mean
  39. });
  40.  
  41. function Interceptor(path) {
  42. this.path = path;
  43.  
  44. // 0:UNSENT, 1:OPENED, 2: HEADERS_RECEIVED, 3: LOADING, 4: DONE
  45. this.readyState = 0;
  46.  
  47. this.onload = null;
  48. this.onerror = null;
  49. this.onabort = null;
  50.  
  51. this.upload = {
  52. onprogress: null
  53. };
  54. }
  55.  
  56. Interceptor.prototype = {
  57. abort: function() {
  58. if(this.uploadTask) {
  59. this.uploadTask.cancel();
  60. this.uploadTask = null;
  61.  
  62. if(this.onabort) {
  63. this.onabort();
  64. }
  65. }
  66. },
  67. send: function(form_data) {
  68. var that = this;
  69. this.file = form_data.get('file');
  70. this.filename = this.file.name;
  71. this.filetype = this.file.type;
  72. this.uid = new Date().getTime();
  73.  
  74. var p1 = this.filename.split('.');
  75. var p2 = this.filetype.split('/');
  76.  
  77. if(p1.length > 1) {
  78. this.fileext = p1.pop();
  79. } else if(p2.length > 1) {
  80. this.fileext = p2.pop();
  81. } else {
  82. this.fileext = 'bin';
  83. }
  84. var firebase_path = [this.path, [this.uid, this.fileext].join('.')].join('/');
  85.  
  86. console.log("upload to firebase path: ", firebase_path);
  87.  
  88. var storage = firebase.storage();
  89. var ref = storage.ref();
  90. var file_ref = ref.child(firebase_path);
  91.  
  92. var metadata = this.filetype ? { contentType: this.filetype } : null;
  93.  
  94. this.uploadTask = file_ref.put(this.file, metadata);
  95.  
  96. this.uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED, function(snapshot) {
  97. // state change observer
  98. var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
  99. console.log("upload progress " + progress.toFixed(2) + "%");
  100.  
  101. if(that.upload.onprogress) {
  102. that.upload.onprogress({
  103. lengthComputable: true,
  104. loaded: snapshot.bytesTransferred,
  105. size: snapshot.totalBytes,
  106. total: snapshot.totalBytes
  107. });
  108. }
  109.  
  110. switch(snapshot.state) {
  111. case firebase.storage.TaskState.PAUSED:
  112. console.log("upload paused");
  113. break;
  114. case firebase.storage.TaskState.RUNNING:
  115. console.log("upload resumed");
  116. break;
  117. }
  118. }, function(error) {
  119. // error handler
  120. console.log("upload error: ", error.code);
  121. if(that.onerror) {
  122. console.log("invoke error cb");
  123. that.onerror({ responseText: error.code});
  124. }
  125. }, function() {
  126. // completion handler
  127. console.log("upload complete");
  128.  
  129. var downloadUrl = that.uploadTask.snapshot.downloadURL;
  130. // TODO: database callback
  131. that.readyState = 4; // DONE
  132. that.uploadTask = null;
  133.  
  134. that.status = 200;
  135. that.responseText = JSON.stringify({
  136. link: downloadUrl
  137. });
  138.  
  139. if(that.onload) {
  140. console.log("invoke completion cb");
  141. that.onload();
  142. }
  143. });
  144.  
  145. this.readyState = 3; // LOADING
  146. }
  147. };
  148.  
  149. $.FroalaEditor.PLUGINS.subverter = function(editor) {
  150. var oldXHR = editor.core.getXHR;
  151.  
  152. function _init() {
  153. console.log("subverter init");
  154.  
  155. if(firebase) {
  156. editor.core.getXHR = function(url, method) {
  157. console.log("subverter in the middle: ", url);
  158.  
  159. // if we see firebase://storage/some/path then we write
  160. // 'some/path/UNIQ.filetype' to firebase storage
  161. var re = new RegExp("firebase://([^/]+)/(.+)");
  162. var m = re.exec(url);
  163.  
  164. if(m) {
  165. console.log("MATCH %O", m);
  166.  
  167. if(m[1] == 'storage') {
  168. var path = m[2];
  169. var n = new Interceptor(path);
  170. return n;
  171. }
  172. }
  173. return oldXHR(url, method);
  174. };
  175. } else {
  176. console.log("missing firebase object");
  177. }
  178. }
  179.  
  180. return {
  181. _init: _init
  182. }
  183. };
  184.  
  185.  
  186. })(jQuery);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement