attache_rails 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 07bb6c168bed2d516774523756dd125d86ca0729
4
- data.tar.gz: b788a5d74a9b1d51c7c6981a6f57d98da62ba060
3
+ metadata.gz: 4da5e22bb598e1b06cbb35fc8492b02f3e004978
4
+ data.tar.gz: 7b1d38f4fb5193ca9490ab1d4463d74938c5300d
5
5
  SHA512:
6
- metadata.gz: 3c8e22d8e34a7a2464af773442eee64f857ccb274e3ea53f9f58732f422b583c2d3b0cca7b32778d5f1d1f407cd166729f68381eff3401358e296bd169d9b65d
7
- data.tar.gz: 1bb4fc71ecfbfa8301ed12eba825dd541ae508b184ebdf62e2c4948033463a025711af00feccde92478e5ae69aca32cee370915dd9535c27bb85a06233546a73
6
+ metadata.gz: b254f432f52a43161cf4c19aed219623e795315984d2fbafa66c09169b39075300776b2a20f8c21bac0465ad130939ec6e7ab2c211e5aa9b772bc1468072b8c3
7
+ data.tar.gz: ed680e0629577892f63c29e103743ba1383e61e6d33427420352f07605e4b8a0425b871c85f36a9210e5cb763dac8925ab1f7e5ff544724fbc318fd39443b12f
@@ -11,8 +11,11 @@ if (typeof AttacheFilePreview === 'undefined') {
11
11
  },
12
12
 
13
13
  render: function() {
14
+ var previewClassName = "attache-file-preview";
15
+
14
16
  // progressbar
15
17
  if (this.state.srcWas != this.props.src) {
18
+ previewClassName = previewClassName + " attache-loading";
16
19
  var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
17
20
  var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
18
21
  var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
@@ -33,7 +36,7 @@ if (typeof AttacheFilePreview === 'undefined') {
33
36
 
34
37
  // combined
35
38
  return (
36
- React.createElement("div", {className: "attache-file-preview"},
39
+ React.createElement("div", {className: previewClassName},
37
40
  progress,
38
41
  img,
39
42
  React.createElement("div", {className: "clearfix"},
@@ -11,8 +11,11 @@ if (typeof AttacheFilePreview === 'undefined') {
11
11
  },
12
12
 
13
13
  render: function() {
14
+ var previewClassName = "attache-file-preview";
15
+
14
16
  // progressbar
15
17
  if (this.state.srcWas != this.props.src) {
18
+ previewClassName = previewClassName + " attache-loading";
16
19
  var className = this.props.className || "progress-bar progress-bar-striped active" + (this.props.src ? " progress-bar-success" : "");
17
20
  var pctString = this.props.pctString || (this.props.src ? 100 : this.props.percentLoaded) + "%";
18
21
  var pctDesc = this.props.pctDesc || (this.props.src ? 'Loading...' : pctString);
@@ -33,7 +36,7 @@ if (typeof AttacheFilePreview === 'undefined') {
33
36
 
34
37
  // combined
35
38
  return (
36
- <div className="attache-file-preview">
39
+ <div className={previewClassName}>
37
40
  {progress}
38
41
  {img}
39
42
  <div className="clearfix">
@@ -4,17 +4,18 @@ var AttacheCORSUpload = (function() {
4
4
  AttacheCORSUpload.prototype.onComplete = function(uid, json) { };
5
5
  AttacheCORSUpload.prototype.onProgress = function(uid, json) { };
6
6
  AttacheCORSUpload.prototype.onError = function(uid, status) { alert(status); };
7
+ AttacheCORSUpload.prototype.createLocalThumbnail = function() { }; // for overwriting
7
8
 
8
9
  function AttacheCORSUpload(options) {
9
10
  if (options == null) options = {};
10
11
  for (option in options) {
11
12
  this[option] = options[option];
12
13
  }
13
- this.handleFileSelect(options.file_element);
14
+ this.handleFileSelect(options.file_element, options.files);
14
15
  }
15
16
 
16
- AttacheCORSUpload.prototype.handleFileSelect = function(file_element) {
17
- var f, files, output, _i, _len, _results, url, $ele, prefix;
17
+ AttacheCORSUpload.prototype.handleFileSelect = function(file_element, files) {
18
+ var f, output, _i, _len, _results, url, $ele, prefix;
18
19
  $ele = $(file_element);
19
20
  url = $ele.data('uploadurl');
20
21
  if ($ele.data('hmac')) {
@@ -26,13 +27,13 @@ var AttacheCORSUpload = (function() {
26
27
  }
27
28
 
28
29
  prefix = Date.now() + "_";
29
- files = file_element.files;
30
30
  output = [];
31
31
  _results = [];
32
32
  for (_i = 0, _len = files.length; _i < _len; _i++) {
33
33
  f = files[_i];
34
+ this.createLocalThumbnail(f); // if any
34
35
  f.uid = prefix + (counter++);
35
- this.onProgress(f.uid, { filename: f.name, percentLoaded: 0, bytesLoaded: 0, bytesTotal: f.size });
36
+ this.onProgress(f.uid, { src: f.src, filename: f.name, percentLoaded: 0, bytesLoaded: 0, bytesTotal: f.size });
36
37
  _results.push(this.performUpload(f, url));
37
38
  }
38
39
  return _results;
@@ -74,7 +75,7 @@ var AttacheCORSUpload = (function() {
74
75
  var percentLoaded;
75
76
  if (e.lengthComputable) {
76
77
  percentLoaded = Math.round((e.loaded / e.total) * 100);
77
- return this_s3upload.onProgress(file.uid, { filename: file.name, percentLoaded: percentLoaded, bytesLoaded: e.loaded, bytesTotal: e.total });
78
+ return this_s3upload.onProgress(file.uid, { src: file.src, filename: file.name, percentLoaded: percentLoaded, bytesLoaded: e.loaded, bytesTotal: e.total });
78
79
  }
79
80
  };
80
81
  }
@@ -21,17 +21,20 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
21
21
  this.setState(this.state);
22
22
  },
23
23
 
24
- onChange: function() {
25
- var file_element = this.getDOMNode().firstChild;
24
+ performUpload: function(file_element, files) {
26
25
  // user cancelled file chooser dialog. ignore
27
- if (! file_element || file_element.files.length == 0) return;
28
- if (! this.props.multiple) this.state.files = {};
26
+ if (! files || files.length == 0) return;
27
+ if (! this.props.multiple) {
28
+ this.state.files = {};
29
+ files = Array.prototype.splice.apply(files, [0, 1]); // array of 1 element
30
+ }
29
31
 
30
32
  this.setState(this.state);
31
33
  // upload the file via CORS
32
34
  var that = this;
33
35
  new AttacheCORSUpload({
34
36
  file_element: file_element,
37
+ files: files,
35
38
  onComplete: this.setFileValue,
36
39
  onProgress: this.setFileValue,
37
40
  onError: function(uid, status) {
@@ -44,6 +47,31 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
44
47
  file_element.value = '';
45
48
  },
46
49
 
50
+ onChange: function() {
51
+ var file_element = this.getDOMNode().firstChild;
52
+ this.performUpload(file_element, file_element && file_element.files);
53
+ },
54
+
55
+ onDragOver: function(e) {
56
+ e.stopPropagation();
57
+ e.preventDefault();
58
+ $(this.getDOMNode()).addClass('attache-dragover');
59
+ },
60
+
61
+ onDragLeave: function(e) {
62
+ e.stopPropagation();
63
+ e.preventDefault();
64
+ $(this.getDOMNode()).removeClass('attache-dragover');
65
+ },
66
+
67
+ onDrop: function(e) {
68
+ e.stopPropagation();
69
+ e.preventDefault();
70
+ var file_element = this.getDOMNode().firstChild;
71
+ this.performUpload(file_element, e.target.files || e.dataTransfer.files);
72
+ $(this.getDOMNode()).removeClass('attache-dragover');
73
+ },
74
+
47
75
  setFileValue: function(key, value) {
48
76
  this.state.files[key] = value;
49
77
  this.setState(this.state);
@@ -58,14 +86,19 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
58
86
 
59
87
  var previews = [];
60
88
  $.each(that.state.files, function(key, result) {
89
+ // json is input[value], drop non essential values
90
+ var copy = JSON.parse(JSON.stringify(result));
91
+ delete copy.src;
92
+ delete copy.filename;
93
+ var json = JSON.stringify(copy);
94
+ //
95
+ result.multiple = that.props.multiple;
61
96
  if (result.path) {
62
97
  var parts = result.path.split('/');
63
98
  parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
64
99
  result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
65
100
  result.filename = result.src.split('/').pop().split(/[#?]/).shift();
66
- result.multiple = that.props.multiple;
67
101
  }
68
- var json = JSON.stringify(result);
69
102
  previews.push(
70
103
  React.createElement("div", {className: "attache-file-input"},
71
104
  React.createElement("input", {type: "hidden", name: that.props.name, value: json, readOnly: "true"}),
@@ -90,7 +123,7 @@ var AttacheFileInput = React.createClass({displayName: "AttacheFileInput",
90
123
 
91
124
  var className = ["attache-file-selector", "attache-placeholders-count-" + placeholders.length, "attache-previews-count-" + previews.length, this.props['data-classname']].join(' ').trim();
92
125
  return (
93
- React.createElement("label", {htmlFor: that.props.id, className: className},
126
+ React.createElement("label", {htmlFor: that.props.id, className: className, onDragOver: this.onDragOver, onDragLeave: this.onDragLeave, onDrop: this.onDrop},
94
127
  React.createElement("input", React.__spread({type: "file"}, that.props, {onChange: this.onChange})),
95
128
  React.createElement("input", {type: "hidden", name: that.props.name, value: ""}),
96
129
  React.createElement(Header, React.__spread({}, that.props)),
@@ -21,17 +21,20 @@ var AttacheFileInput = React.createClass({
21
21
  this.setState(this.state);
22
22
  },
23
23
 
24
- onChange: function() {
25
- var file_element = this.getDOMNode().firstChild;
24
+ performUpload: function(file_element, files) {
26
25
  // user cancelled file chooser dialog. ignore
27
- if (! file_element || file_element.files.length == 0) return;
28
- if (! this.props.multiple) this.state.files = {};
26
+ if (! files || files.length == 0) return;
27
+ if (! this.props.multiple) {
28
+ this.state.files = {};
29
+ files = Array.prototype.splice.apply(files, [0, 1]); // array of 1 element
30
+ }
29
31
 
30
32
  this.setState(this.state);
31
33
  // upload the file via CORS
32
34
  var that = this;
33
35
  new AttacheCORSUpload({
34
36
  file_element: file_element,
37
+ files: files,
35
38
  onComplete: this.setFileValue,
36
39
  onProgress: this.setFileValue,
37
40
  onError: function(uid, status) {
@@ -44,6 +47,31 @@ var AttacheFileInput = React.createClass({
44
47
  file_element.value = '';
45
48
  },
46
49
 
50
+ onChange: function() {
51
+ var file_element = this.getDOMNode().firstChild;
52
+ this.performUpload(file_element, file_element && file_element.files);
53
+ },
54
+
55
+ onDragOver: function(e) {
56
+ e.stopPropagation();
57
+ e.preventDefault();
58
+ $(this.getDOMNode()).addClass('attache-dragover');
59
+ },
60
+
61
+ onDragLeave: function(e) {
62
+ e.stopPropagation();
63
+ e.preventDefault();
64
+ $(this.getDOMNode()).removeClass('attache-dragover');
65
+ },
66
+
67
+ onDrop: function(e) {
68
+ e.stopPropagation();
69
+ e.preventDefault();
70
+ var file_element = this.getDOMNode().firstChild;
71
+ this.performUpload(file_element, e.target.files || e.dataTransfer.files);
72
+ $(this.getDOMNode()).removeClass('attache-dragover');
73
+ },
74
+
47
75
  setFileValue: function(key, value) {
48
76
  this.state.files[key] = value;
49
77
  this.setState(this.state);
@@ -58,14 +86,19 @@ var AttacheFileInput = React.createClass({
58
86
 
59
87
  var previews = [];
60
88
  $.each(that.state.files, function(key, result) {
89
+ // json is input[value], drop non essential values
90
+ var copy = JSON.parse(JSON.stringify(result));
91
+ delete copy.src;
92
+ delete copy.filename;
93
+ var json = JSON.stringify(copy);
94
+ //
95
+ result.multiple = that.props.multiple;
61
96
  if (result.path) {
62
97
  var parts = result.path.split('/');
63
98
  parts.splice(parts.length-1, 0, encodeURIComponent(that.props['data-geometry'] || '128x128#'));
64
99
  result.src = that.props['data-downloadurl'] + '/' + parts.join('/');
65
100
  result.filename = result.src.split('/').pop().split(/[#?]/).shift();
66
- result.multiple = that.props.multiple;
67
101
  }
68
- var json = JSON.stringify(result);
69
102
  previews.push(
70
103
  <div className="attache-file-input">
71
104
  <input type="hidden" name={that.props.name} value={json} readOnly="true" />
@@ -90,7 +123,7 @@ var AttacheFileInput = React.createClass({
90
123
 
91
124
  var className = ["attache-file-selector", "attache-placeholders-count-" + placeholders.length, "attache-previews-count-" + previews.length, this.props['data-classname']].join(' ').trim();
92
125
  return (
93
- <label htmlFor={that.props.id} className={className}>
126
+ <label htmlFor={that.props.id} className={className} onDragOver={this.onDragOver} onDragLeave={this.onDragLeave} onDrop={this.onDrop}>
94
127
  <input type="file" {...that.props} onChange={this.onChange}/>
95
128
  <input type="hidden" name={that.props.name} value="" />
96
129
  <Header {...that.props} />
@@ -92,7 +92,8 @@ module AttacheRails
92
92
  define_method "#{name}_attributes", -> (geometry) { str = self.send(name); Utils.attache_url_for(str, geometry) if str; }
93
93
  define_method "#{name}=", -> (value) {
94
94
  new_value = (value.respond_to?(:read) ? Utils.attache_upload_and_get_json(value) : value)
95
- super(Utils.array(new_value).first)
95
+ okay = JSON.parse(new_value)['path'] rescue nil
96
+ super(Utils.array(okay ? new_value : nil).first)
96
97
  }
97
98
  define_method "#{name}_discard_was",-> do
98
99
  new_value = self.send("#{name}")
@@ -121,7 +122,11 @@ module AttacheRails
121
122
  end
122
123
  }
123
124
  define_method "#{name}=", -> (array) {
124
- new_value = Utils.array(array).collect {|value| value.respond_to?(:read) ? Utils.attache_upload_and_get_json(value) : value }
125
+ new_value = Utils.array(array).inject([]) {|sum,value|
126
+ hash = value.respond_to?(:read) ? Utils.attache_upload_and_get_json(value) : value
127
+ okay = JSON.parse(hash)['path'] rescue nil
128
+ okay ? sum + [hash] : sum
129
+ }
125
130
  super(Utils.array new_value)
126
131
  }
127
132
  define_method "#{name}_discard_was",-> do
@@ -1,3 +1,3 @@
1
1
  module AttacheRails
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attache_rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - choonkeat
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-04 00:00:00.000000000 Z
11
+ date: 2015-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails