dropsheet.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* dropsheet.js (C) 2014-present SheetJS -- http://sheetjs.com */
  2. /* vim: set ts=2: */
  3. var DropSheet = function DropSheet(opts) {
  4. if(!opts) opts = {};
  5. var nullfunc = function(){};
  6. if(!opts.errors) opts.errors = {};
  7. if(!opts.errors.badfile) opts.errors.badfile = nullfunc;
  8. if(!opts.errors.pending) opts.errors.pending = nullfunc;
  9. if(!opts.errors.failed) opts.errors.failed = nullfunc;
  10. if(!opts.errors.large) opts.errors.large = nullfunc;
  11. if(!opts.on) opts.on = {};
  12. if(!opts.on.workstart) opts.on.workstart = nullfunc;
  13. if(!opts.on.workend) opts.on.workend = nullfunc;
  14. if(!opts.on.sheet) opts.on.sheet = nullfunc;
  15. if(!opts.on.wb) opts.on.wb = nullfunc;
  16. var rABS = typeof FileReader !== 'undefined' && FileReader.prototype && FileReader.prototype.readAsBinaryString;
  17. var useworker = typeof Worker !== 'undefined';
  18. var pending = false;
  19. function fixdata(data) {
  20. var o = "", l = 0, w = 10240;
  21. for(; l<data.byteLength/w; ++l)
  22. o+=String.fromCharCode.apply(null,new Uint8Array(data.slice(l*w,l*w+w)));
  23. o+=String.fromCharCode.apply(null, new Uint8Array(data.slice(o.length)));
  24. return o;
  25. }
  26. function sheetjsw(data, cb, readtype) {
  27. pending = true;
  28. opts.on.workstart();
  29. var scripts = document.getElementsByTagName('script');
  30. var dropsheetPath;
  31. for (var i = 0; i < scripts.length; i++) {
  32. if (scripts[i].src.indexOf('dropsheet') != -1) {
  33. dropsheetPath = scripts[i].src.split('dropsheet.js')[0];
  34. }
  35. }
  36. var worker = new Worker(dropsheetPath + 'sheetjsw.js');
  37. worker.onmessage = function(e) {
  38. switch(e.data.t) {
  39. case 'ready': break;
  40. case 'e': pending = false; console.error(e.data.d); break;
  41. case 'xlsx':
  42. pending = false;
  43. opts.on.workend();
  44. cb(JSON.parse(e.data.d)); break;
  45. }
  46. };
  47. worker.postMessage({d:data,b:readtype,t:'xlsx'});
  48. }
  49. var last_wb;
  50. function to_json(workbook) {
  51. if(useworker && workbook.SSF) XLSX.SSF.load_table(workbook.SSF);
  52. var result = {};
  53. workbook.SheetNames.forEach(function(sheetName) {
  54. var roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName], {header:1});
  55. if(roa.length > 0) result[sheetName] = roa;
  56. });
  57. return result;
  58. }
  59. function choose_sheet(sheetidx) { process_wb(last_wb, sheetidx); }
  60. function process_wb(wb, sheetidx) {
  61. last_wb = wb;
  62. opts.on.wb(wb, sheetidx);
  63. var sheet = wb.SheetNames[sheetidx||0];
  64. var json = to_json(wb)[sheet];
  65. opts.on.sheet(json, wb.SheetNames, choose_sheet);
  66. }
  67. function handleDrop(e) {
  68. e.stopPropagation();
  69. e.preventDefault();
  70. if(pending) return opts.errors.pending();
  71. var files = e.dataTransfer.files;
  72. var i,f;
  73. for (i = 0, f = files[i]; i != files.length; ++i) {
  74. var reader = new FileReader();
  75. var name = f.name;
  76. reader.onload = function(e) {
  77. var data = e.target.result;
  78. var wb, arr;
  79. var readtype = {type: rABS ? 'binary' : 'base64' };
  80. if(!rABS) {
  81. arr = fixdata(data);
  82. data = btoa(arr);
  83. }
  84. function doit() {
  85. try {
  86. if(useworker) { sheetjsw(data, process_wb, readtype); return; }
  87. wb = XLSX.read(data, readtype);
  88. process_wb(wb);
  89. } catch(e) { console.log(e); opts.errors.failed(e); }
  90. }
  91. if(e.target.result.length > 1e6) opts.errors.large(e.target.result.length, function(e) { if(e) doit(); });
  92. else { doit(); }
  93. };
  94. if(rABS) reader.readAsBinaryString(f);
  95. else reader.readAsArrayBuffer(f);
  96. }
  97. }
  98. function handleDragover(e) {
  99. e.stopPropagation();
  100. e.preventDefault();
  101. e.dataTransfer.dropEffect = 'copy';
  102. }
  103. if(opts.drop.addEventListener) {
  104. opts.drop.addEventListener('dragenter', handleDragover, false);
  105. opts.drop.addEventListener('dragover', handleDragover, false);
  106. opts.drop.addEventListener('drop', handleDrop, false);
  107. }
  108. };