fileapi 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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