fileapi 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,4 +1,4 @@
1
- /*! FileAPI 2.0.9 - BSD | git://github.com/mailru/FileAPI.git
1
+ /*! FileAPI 2.0.11 - BSD | git://github.com/mailru/FileAPI.git
2
2
  * FileAPI — a set of javascript tools for working with files. Multiupload, drag'n'drop and chunked file upload. Images: crop, resize and auto orientation by EXIF.
3
3
  */
4
4
 
@@ -105,6 +105,7 @@
105
105
  document = window.document,
106
106
  doctype = document.doctype || {},
107
107
  userAgent = window.navigator.userAgent,
108
+ safari = /safari\//i.test(userAgent) && !/chrome\//i.test(userAgent),
108
109
 
109
110
  // https://github.com/blueimp/JavaScript-Load-Image/blob/master/load-image.js#L48
110
111
  apiURL = (window.createObjectURL && window) || (window.URL && URL.revokeObjectURL && URL) || (window.webkitURL && webkitURL),
@@ -119,12 +120,14 @@
119
120
  jQuery = window.jQuery,
120
121
 
121
122
  html5 = !!(File && (FileReader && (window.Uint8Array || FormData || XMLHttpRequest.prototype.sendAsBinary)))
122
- && !(/safari\//i.test(userAgent) && !/chrome\//i.test(userAgent) && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25
123
+ && !(safari && /windows/i.test(userAgent)), // BugFix: https://github.com/mailru/FileAPI/issues/25
123
124
 
124
125
  cors = html5 && ('withCredentials' in (new XMLHttpRequest)),
125
126
 
126
127
  chunked = html5 && !!Blob && !!(Blob.prototype.webkitSlice || Blob.prototype.mozSlice || Blob.prototype.slice),
127
128
 
129
+ normalize = ('' + ''.normalize).indexOf('[native code]') > 0,
130
+
128
131
  // https://github.com/blueimp/JavaScript-Canvas-to-Blob
129
132
  dataURLtoBlob = window.dataURLtoBlob,
130
133
 
@@ -280,7 +283,7 @@
280
283
  * FileAPI (core object)
281
284
  */
282
285
  api = {
283
- version: '2.0.9',
286
+ version: '2.0.11',
284
287
 
285
288
  cors: false,
286
289
  html5: true,
@@ -795,28 +798,84 @@
795
798
  getDropFiles: function (evt, callback){
796
799
  var
797
800
  files = []
801
+ , all = []
802
+ , items
798
803
  , dataTransfer = _getDataTransfer(evt)
799
- , entrySupport = _isArray(dataTransfer.items) && dataTransfer.items[0] && _getAsEntry(dataTransfer.items[0])
800
- , queue = api.queue(function (){ callback(files); })
804
+ , transFiles = dataTransfer.files
805
+ , transItems = dataTransfer.items
806
+ , entrySupport = _isArray(transItems) && transItems[0] && _getAsEntry(transItems[0])
807
+ , queue = api.queue(function (){ callback(files, all); })
801
808
  ;
802
809
 
803
- _each((entrySupport ? dataTransfer.items : dataTransfer.files) || [], function (item){
810
+ if( entrySupport ){
811
+ if( normalize && transFiles ){
812
+ var
813
+ i = transFiles.length
814
+ , file
815
+ , entry
816
+ ;
817
+
818
+ items = new Array(i);
819
+ while( i-- ){
820
+ file = transFiles[i];
821
+
822
+ try {
823
+ entry = _getAsEntry(transItems[i]);
824
+ }
825
+ catch( err ){
826
+ api.log('[err] getDropFiles: ', err);
827
+ entry = null;
828
+ }
829
+
830
+ if( _isEntry(entry) ){
831
+ // OSX filesystems use Unicode Normalization Form D (NFD),
832
+ // and entry.file(…) can't read the files with the same names
833
+ if( entry.isDirectory || (entry.isFile && file.name == file.name.normalize('NFC')) ){
834
+ items[i] = entry;
835
+ }
836
+ else {
837
+ items[i] = file;
838
+ }
839
+ }
840
+ else {
841
+ items[i] = file;
842
+ }
843
+ }
844
+ }
845
+ else {
846
+ items = transItems;
847
+ }
848
+ }
849
+ else {
850
+ items = transFiles;
851
+ }
852
+
853
+ _each(items || [], function (item){
804
854
  queue.inc();
805
855
 
806
856
  try {
807
- if( entrySupport ){
808
- _readEntryAsFiles(item, function (err, entryFiles){
857
+ if( entrySupport && _isEntry(item) ){
858
+ _readEntryAsFiles(item, function (err, entryFiles, allEntries){
809
859
  if( err ){
810
860
  api.log('[err] getDropFiles:', err);
811
861
  } else {
812
862
  files.push.apply(files, entryFiles);
813
863
  }
864
+ all.push.apply(all, allEntries);
865
+
814
866
  queue.next();
815
867
  });
816
868
  }
817
869
  else {
818
- _isRegularFile(item, function (yes){
819
- yes && files.push(item);
870
+ _isRegularFile(item, function (yes, err){
871
+ if( yes ){
872
+ files.push(item);
873
+ }
874
+ else {
875
+ item.error = err;
876
+ }
877
+ all.push(item);
878
+
820
879
  queue.next();
821
880
  });
822
881
  }
@@ -1491,13 +1550,13 @@
1491
1550
  }
1492
1551
 
1493
1552
 
1494
- function _hasSupportReadAs(as){
1495
- return FileReader && !!FileReader.prototype['readAs'+as];
1553
+ function _hasSupportReadAs(method){
1554
+ return FileReader && !!FileReader.prototype['readAs' + method];
1496
1555
  }
1497
1556
 
1498
1557
 
1499
- function _readAs(file, fn, as, encoding){
1500
- if( api.isBlob(file) && _hasSupportReadAs(as) ){
1558
+ function _readAs(file, fn, method, encoding){
1559
+ if( api.isBlob(file) && _hasSupportReadAs(method) ){
1501
1560
  var Reader = new FileReader;
1502
1561
 
1503
1562
  // Add event listener
@@ -1519,10 +1578,10 @@
1519
1578
  try {
1520
1579
  // ReadAs ...
1521
1580
  if( encoding ){
1522
- Reader['readAs'+as](file, encoding);
1581
+ Reader['readAs' + method](file, encoding);
1523
1582
  }
1524
1583
  else {
1525
- Reader['readAs'+as](file);
1584
+ Reader['readAs' + method](file);
1526
1585
  }
1527
1586
  }
1528
1587
  catch (err){
@@ -1530,33 +1589,36 @@
1530
1589
  }
1531
1590
  }
1532
1591
  else {
1533
- _emit(file, fn, 'error', undef, { error: 'filreader_not_support_'+as });
1592
+ _emit(file, fn, 'error', undef, { error: 'filreader_not_support_' + method });
1534
1593
  }
1535
1594
  }
1536
1595
 
1537
1596
 
1538
1597
  function _isRegularFile(file, callback){
1539
1598
  // http://stackoverflow.com/questions/8856628/detecting-folders-directories-in-javascript-filelist-objects
1540
- if( !file.type && (file.size % 4096) === 0 && (file.size <= 102400) ){
1599
+ if( !file.type && (safari || ((file.size % 4096) === 0 && (file.size <= 102400))) ){
1541
1600
  if( FileReader ){
1542
1601
  try {
1543
- var Reader = new FileReader();
1602
+ var reader = new FileReader();
1544
1603
 
1545
- _one(Reader, _readerEvents, function (evt){
1604
+ _one(reader, _readerEvents, function (evt){
1546
1605
  var isFile = evt.type != 'error';
1547
- callback(isFile);
1548
1606
  if( isFile ){
1549
- Reader.abort();
1607
+ reader.abort();
1608
+ callback(isFile);
1609
+ }
1610
+ else {
1611
+ callback(false, reader.error);
1550
1612
  }
1551
1613
  });
1552
1614
 
1553
- Reader.readAsDataURL(file);
1615
+ reader.readAsDataURL(file);
1554
1616
  } catch( err ){
1555
- callback(false);
1617
+ callback(false, err);
1556
1618
  }
1557
1619
  }
1558
1620
  else {
1559
- callback(null);
1621
+ callback(null, new Error('FileReader is not supported'));
1560
1622
  }
1561
1623
  }
1562
1624
  else {
@@ -1565,6 +1627,11 @@
1565
1627
  }
1566
1628
 
1567
1629
 
1630
+ function _isEntry(item){
1631
+ return item && (item.isFile || item.isDirectory);
1632
+ }
1633
+
1634
+
1568
1635
  function _getAsEntry(item){
1569
1636
  var entry;
1570
1637
  if( item.getAsEntry ){ entry = item.getAsEntry(); }
@@ -1576,45 +1643,68 @@
1576
1643
  function _readEntryAsFiles(entry, callback){
1577
1644
  if( !entry ){
1578
1645
  // error
1579
- callback('invalid entry');
1646
+ var err = new Error('invalid entry');
1647
+ entry = new Object(entry);
1648
+ entry.error = err;
1649
+ callback(err.message, [], [entry]);
1580
1650
  }
1581
1651
  else if( entry.isFile ){
1582
1652
  // Read as file
1583
- entry.file(function(file){
1653
+ entry.file(function (file){
1584
1654
  // success
1585
1655
  file.fullPath = entry.fullPath;
1586
- callback(false, [file]);
1656
+ callback(false, [file], [file]);
1587
1657
  }, function (err){
1588
1658
  // error
1589
- callback('FileError.code: '+err.code);
1659
+ entry.error = err;
1660
+ callback('FileError.code: ' + err.code, [], [entry]);
1590
1661
  });
1591
1662
  }
1592
1663
  else if( entry.isDirectory ){
1593
- var reader = entry.createReader(), result = [];
1664
+ var
1665
+ reader = entry.createReader()
1666
+ , firstAttempt = true
1667
+ , files = []
1668
+ , all = [entry]
1669
+ ;
1670
+
1671
+ var onerror = function (err){
1672
+ // error
1673
+ entry.error = err;
1674
+ callback('DirectoryError.code: ' + err.code, files, all);
1675
+ };
1676
+ var ondone = function ondone(entries){
1677
+ if( firstAttempt ){
1678
+ firstAttempt = false;
1679
+ if( !entries.length ){
1680
+ entry.error = new Error('directory is empty');
1681
+ }
1682
+ }
1594
1683
 
1595
- reader.readEntries(function(entries){
1596
1684
  // success
1597
- api.afor(entries, function (next, entry){
1598
- _readEntryAsFiles(entry, function (err, files){
1599
- if( err ){
1600
- api.log(err);
1601
- }
1602
- else {
1603
- result = result.concat(files);
1604
- }
1685
+ if( entries.length ){
1686
+ api.afor(entries, function (next, entry){
1687
+ _readEntryAsFiles(entry, function (err, entryFiles, allEntries){
1688
+ if( !err ){
1689
+ files = files.concat(entryFiles);
1690
+ }
1691
+ all = all.concat(allEntries);
1605
1692
 
1606
- if( next ){
1607
- next();
1608
- }
1609
- else {
1610
- callback(false, result);
1611
- }
1693
+ if( next ){
1694
+ next();
1695
+ }
1696
+ else {
1697
+ reader.readEntries(ondone, onerror);
1698
+ }
1699
+ });
1612
1700
  });
1613
- });
1614
- }, function (err){
1615
- // error
1616
- callback('directory_reader: ' + err);
1617
- });
1701
+ }
1702
+ else {
1703
+ callback(false, files, all);
1704
+ }
1705
+ };
1706
+
1707
+ reader.readEntries(ondone, onerror);
1618
1708
  }
1619
1709
  else {
1620
1710
  _readEntryAsFiles(_getAsEntry(entry), callback);
@@ -1735,8 +1825,8 @@
1735
1825
  _type = 0;
1736
1826
  onHover.call(evt[currentTarget], false, evt);
1737
1827
 
1738
- api.getDropFiles(evt, function (files){
1739
- onDrop.call(evt[currentTarget], files, evt);
1828
+ api.getDropFiles(evt, function (files, all){
1829
+ onDrop.call(evt[currentTarget], files, all, evt);
1740
1830
  });
1741
1831
  });
1742
1832
  }
@@ -2528,7 +2618,13 @@
2528
2618
  });
2529
2619
 
2530
2620
  this.each(function (file){
2531
- next(file, data, queue, arg);
2621
+ try{
2622
+ next(file, data, queue, arg);
2623
+ }
2624
+ catch( err ){
2625
+ api.log('FileAPI.Form._to: ' + err.message);
2626
+ complete(err);
2627
+ }
2532
2628
  });
2533
2629
 
2534
2630
  queue.check();
@@ -2756,14 +2852,19 @@
2756
2852
  var _this = this, options = this.options;
2757
2853
 
2758
2854
  FormData.toData(function (data){
2759
- // Start uploading
2760
- options.upload(options, _this);
2761
- _this._send.call(_this, options, data);
2855
+ if( data instanceof Error ){
2856
+ _this.end(0, data.message);
2857
+ }
2858
+ else{
2859
+ // Start uploading
2860
+ options.upload(options, _this);
2861
+ _this._send.call(_this, options, data);
2862
+ }
2762
2863
  }, options);
2763
2864
  },
2764
2865
 
2765
2866
  _send: function (options, data){
2766
- var _this = this, xhr, uid = _this.uid, onloadFuncName = _this.uid + "Load", url = options.url;
2867
+ var _this = this, xhr, uid = _this.uid, onLoadFnName = _this.uid + "Load", url = options.url;
2767
2868
 
2768
2869
  api.log('XHR._send:', data);
2769
2870
 
@@ -2802,7 +2903,7 @@
2802
2903
  _this.end(status, statusText);
2803
2904
 
2804
2905
  api.event.off(window, 'message', onPostMessage);
2805
- window[uid] = xhr = transport = window[onloadFuncName] = null;
2906
+ window[uid] = xhr = transport = window[onLoadFnName] = null;
2806
2907
  }
2807
2908
  ;
2808
2909
 
@@ -2818,7 +2919,7 @@
2818
2919
 
2819
2920
  api.event.on(window, 'message', onPostMessage);
2820
2921
 
2821
- window[onloadFuncName] = function (){
2922
+ window[onLoadFnName] = function (){
2822
2923
  try {
2823
2924
  var
2824
2925
  win = transport.contentWindow
@@ -2833,7 +2934,7 @@
2833
2934
 
2834
2935
  xhr = document.createElement('div');
2835
2936
  xhr.innerHTML = '<form target="'+ uid +'" action="'+ url +'" method="POST" enctype="multipart/form-data" style="position: absolute; top: -1000px; overflow: hidden; width: 1px; height: 1px;">'
2836
- + '<iframe name="'+ uid +'" src="javascript:false;" onload="' + onloadFuncName + '()"></iframe>'
2937
+ + '<iframe name="'+ uid +'" src="javascript:false;" onload="window.' + onLoadFnName + ' && ' + onLoadFnName + '();"></iframe>'
2837
2938
  + (jsonp && (options.url.indexOf('=?') < 0) ? '<input value="'+ uid +'" name="'+jsonp+'" type="hidden"/>' : '')
2838
2939
  + '</form>'
2839
2940
  ;
@@ -2856,7 +2957,11 @@
2856
2957
 
2857
2958
  // send
2858
2959
  _this.readyState = 2; // loaded
2859
- form.submit();
2960
+ try {
2961
+ form.submit();
2962
+ } catch (err) {
2963
+ api.log('iframe.error: ' + err);
2964
+ }
2860
2965
  form = null;
2861
2966
  }
2862
2967
  else {
@@ -3487,7 +3592,7 @@
3487
3592
 
3488
3593
  if( api.multiFlash ){
3489
3594
  // check state:
3490
- // i — published
3595
+ // p — published
3491
3596
  // i — initialization
3492
3597
  // r — ready
3493
3598
  if( state == 'i' || state == 'r' ){
@@ -3649,8 +3754,8 @@
3649
3754
  try {
3650
3755
  api.log('(js -> flash).'+name+':', data);
3651
3756
  return flash.get(id.flashId || id).cmd(name, data);
3652
- } catch (e){
3653
- api.log('(js -> flash).onError:', e);
3757
+ } catch (err){
3758
+ api.log('(js -> flash).onError:', err.toString());
3654
3759
  if( !last ){
3655
3760
  // try again
3656
3761
  setTimeout(function (){ flash.cmd(id, name, data, true); }, 50);
@@ -4125,10 +4230,8 @@
4125
4230
  var _each = api.each,
4126
4231
  _cameraQueue = [];
4127
4232
 
4128
-
4129
- if (api.support.flash && (api.media && !api.support.media)) {
4233
+ if (api.support.flash && (api.media && (!api.support.media || !api.html5))) {
4130
4234
  (function () {
4131
-
4132
4235
  function _wrap(fn) {
4133
4236
  var id = fn.wid = api.uid();
4134
4237
  api.Flash._fn[id] = fn;
@@ -1,3 +1,3 @@
1
1
  window.FileAPI =
2
- debug: true
3
- staticPath: '/js/jquery.fileapi/FileAPI/'
2
+ debug: false
3
+ staticPath: '/js/jquery.fileapi/FileAPI/'
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Fileapi
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.2"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fileapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-15 00:00:00.000000000 Z
12
+ date: 2015-08-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -95,18 +95,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
95
95
  - - ! '>='
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
- segments:
99
- - 0
100
- hash: -202280194601742829
101
98
  required_rubygems_version: !ruby/object:Gem::Requirement
102
99
  none: false
103
100
  requirements:
104
101
  - - ! '>='
105
102
  - !ruby/object:Gem::Version
106
103
  version: '0'
107
- segments:
108
- - 0
109
- hash: -202280194601742829
110
104
  requirements: []
111
105
  rubyforge_project:
112
106
  rubygems_version: 1.8.24