diff --git a/bower.json b/bower.json
index 01e8706..e1dcb86 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "ember-droplet",
- "version": "0.5.9",
+ "version": "0.6.0",
"homepage": "https://github.com/Wildhoney/EmberDroplet",
"authors": [
"Adam Timberlake "
diff --git a/dist/ember-droplet.js b/dist/ember-droplet.js
index 91cc86b..9e74311 100644
--- a/dist/ember-droplet.js
+++ b/dist/ember-droplet.js
@@ -417,6 +417,66 @@
"use strict";
+ /**
+ * @property MultipleInput
+ * @type {Object}
+ */
+ var MultipleInput = {
+
+ /**
+ * @property tagName
+ * @type {String}
+ * @default "input"
+ */
+ tagName: 'input',
+
+ /**
+ * @property classNames
+ * @type {String}
+ * @default "files"
+ */
+ classNames: 'files',
+
+ /**
+ * @property attributeBindings
+ * @type {Array}
+ */
+ attributeBindings: ['name', 'type', 'multiple'],
+
+ /**
+ * @property file
+ * @type {String}
+ * @default "file"
+ */
+ type: 'file',
+
+ /**
+ * @property multiple
+ * @type {String}
+ * @default "multiple"
+ */
+ multiple: 'multiple',
+
+ /**
+ * Invoked when the content of the INPUT changes.
+ *
+ * @method change
+ * @return {Boolean}
+ */
+ change: function() {
+ var files = this.get('element').files;
+ return this.get('parentView').traverseFiles(files);
+ }
+
+ };
+
+ /**
+ * @property SingleInput
+ * @type {Object}
+ */
+ var SingleInput = $ember.copy(MultipleInput);
+ SingleInput.multiple = false;
+
/**
* @module App
* @class DropletView
@@ -467,8 +527,9 @@
image: null,
/**
- * @method didInsertElement
* Invoked when the view is inserted into the DOM.
+ *
+ * @method didInsertElement
* @return {void}
*/
didInsertElement: function() {
@@ -512,59 +573,20 @@
* @property MultipleInput
* @type {Ember.View}
*/
- MultipleInput: $ember.View.extend({
+ MultipleInput: $ember.View.extend(MultipleInput),
- /**
- * @property tagName
- * @type {String}
- * @default "input"
- */
- tagName: 'input',
-
- /**
- * @property classNames
- * @type {String}
- * @default "files"
- */
- classNames: 'files',
-
- /**
- * @property attributeBindings
- * @type {Array}
- */
- attributeBindings: ['name', 'type', 'multiple'],
-
- /**
- * @property file
- * @type {String}
- * @default "file"
- */
- type: 'file',
-
- /**
- * @property multiple
- * @type {String}
- * @default "multiple"
- */
- multiple: 'multiple',
-
- /**
- * @method change
- * Invoked when the content of the INPUT changes.
- * @return {Boolean}
- */
- change: function() {
- var files = this.get('element').files;
- return this.get('parentView').traverseFiles(files);
- }
-
- }),
+ /**
+ * @property SingleInput
+ * @type {Ember.View}
+ */
+ SingleInput: $ember.View.extend(SingleInput),
/**
+ * Invoked when the user drops a file onto the droppable area.
+ *
* @method drop
* @param event {jQuery.Event}
* @param [files = []] {Array}
- * Invoked when the user drops a file onto the droppable area.
* @return {Boolean}
*/
drop: function(event, files) {
@@ -573,10 +595,11 @@
},
/**
- * @method traverseFiles
- * @param files {FileList}
* Accepts a FileList object, and traverses them to determine if they're valid, adding them
* as either valid or invalid.
+ *
+ * @method traverseFiles
+ * @param files {FileList}
* @return {boolean}
*/
traverseFiles: function(files) {
@@ -584,26 +607,33 @@
// Find the controller, and the `mimeTypes` and `extensions` property.
var controller = $ember.get(this, 'controller'),
mimeTypes = $ember.get(controller, 'mimeTypes'),
- extensions = $ember.get(controller, 'extensions');
+ extensions = $ember.get(controller, 'extensions'),
+ options = $ember.get(controller, 'dropletOptions') || { limit: Infinity };
- // Assert that we have the `mineTypes` property, and that it's an array.
+ // Assert that we have the `mimeTypes` property, and that it's an array.
$ember.assert('`mimeTypes` is undefined. Does your controller implement the `$emberDropletController` mixin?', !!mimeTypes);
$ember.assert('`mimeTypes` is not an array. It should be an array of valid MIME types.', !!$ember.isArray(mimeTypes));
for (var index = 0, numFiles = files.length; index < numFiles; index++) {
- if (!files.hasOwnProperty(index)&&(!(index in files))) {
+ if (!files.hasOwnProperty(index) && (!(index in files))) {
continue;
}
- var file = files[index],
+ var file = files[index],
fileExt = file.name.split('.').pop();
- // Determine if the file is valid based on its MIME type or extension.
- if (($.inArray(file.type, mimeTypes) === -1)&&($.inArray(fileExt, extensions) === -1)) {
+ // Determine if the file is valid based on its MIME type or extension, and we haven't exceeded
+ // the user defined limit for the amount of files to upload in one go.
+ var invalidMime = ($.inArray(file.type, mimeTypes) === -1) && ($.inArray(fileExt, extensions) === -1),
+ currentLength = $ember.get(controller, 'validFiles').length;
+
+ if (invalidMime || currentLength === options.limit) {
+
// If it isn't valid, then we'll add it as an invalid file.
controller.send('addInvalidFile', file);
continue;
+
}
// Otherwise the file has a valid MIME type or extension, and therefore be added as a good file.
@@ -616,9 +646,10 @@
},
/**
+ * Prevents default behaviour and propagation on nodes where it's undesirable.
+ *
* @method _preventDefaultBehaviour
* @param event {jQuery.Event}
- * Prevents default behaviour and propagation on nodes where it's undesirable.
* @return {void}
* @private
*/
diff --git a/dist/ember-droplet.min.js b/dist/ember-droplet.min.js
index 94fb998..f5dc0d2 100644
--- a/dist/ember-droplet.min.js
+++ b/dist/ember-droplet.min.js
@@ -1,2 +1,2 @@
/*! ember-droplet by Adam Timberlake created on 2014-09-17 */
-!function(a,b,c){"use strict";a.DropletController=b.Mixin.create({mimeTypes:["image/jpeg","image/jpg","image/gif","image/png","text/plain"],extensions:["jpeg","jpg","gif","png"],requestHeaders:{},postData:{},files:[],uploadStatus:{uploading:!1,percentComplete:0,error:!1},init:function(){b.set(this,"files",[]),this._super()},actions:{addValidFile:function(a){return this._addFile(a,!0)},addInvalidFile:function(a){return this._addFile(a,!1)},deleteFile:function(a){return b.set(a,"deleted",!0),a},clearAllFiles:function(){b.set(this,"files",[])},uploadAllFiles:function(){var d={fileSizeHeader:!0,useArray:!0};if(0===b.get(this,"validFiles").length)return!1;var e=b.get(this,"dropletUrl"),f=b.get(this,"dropletOptions")||d,g=new c.Deferred,h=this.get("postData"),i=this.get("requestHeaders");b.set(this,"uploadStatus.uploading",!0),b.set(this,"uploadStatus.error",!1),b.assert("You must specify the `dropletUrl` parameter in order to upload files.",!!e);var j=new a.XMLHttpRequest;j.open("post",e,!0);var k=new a.FormData,l=f.useArray?"file[]":"file";b.EnumerableUtils.forEach(b.get(this,"validFiles"),function(a){k.append(l,a.file)},this);for(var m in h)h.hasOwnProperty(m)&&k.append(m,h[m]);this._addProgressListener(j.upload),this._addSuccessListener(j.upload,g),this._addErrorListener(j.upload,g),j.onreadystatechange=function(){4===j.readyState&&Ember.run(function(){var c=a.JSON.parse(j.responseText);g.resolve(c),b.tryInvoke(this,"didUploadFiles",[c])}.bind(this))}.bind(this),f.fileSizeHeader&&j.setRequestHeader("X-File-Size",this._getSize());for(m in i)(i.hasOwnProperty(m)||m in i)&&j.setRequestHeader(m,i[m]);return j.send(k),g.promise()}},validFiles:b.computed(function(){return this._filesByProperties({valid:!0,deleted:!1,uploaded:!1})}).property("files.length","files.@each.deleted","files.@each.uploaded"),invalidFiles:b.computed(function(){return this._filesByProperties({valid:!1})}).property("files.length","files.@each.deleted"),uploadedFiles:b.computed(function(){return this._filesByProperties({uploaded:!0})}).property("files.length","files.@each.uploaded"),deletedFiles:b.computed(function(){return this._filesByProperties({deleted:!0})}).property("files.length","files.@each.deleted"),_filesByProperties:function(a){return b.get(this,"files").filter(function(b){for(var c in a)if((a.hasOwnProperty(c)||c in a)&&b[c]!==a[c])return!1;return!0})},_getSize:function(){var a=0;return b.EnumerableUtils.forEach(b.get(this,"validFiles"),function(b){a+=b.file.size}),a},_addSuccessListener:function(a){a.addEventListener("load",function(){Ember.run(function(){b.EnumerableUtils.forEach(b.get(this,"validFiles"),function(a){b.set(a,"uploaded",!0)}),b.set(this,"uploadStatus.uploading",!1)}.bind(this))}.bind(this),!1)},_addErrorListener:function(a,c){a.addEventListener("error",function(){Ember.run(function(){b.set(this,"uploadStatus.uploading",!1),b.set(this,"uploadStatus.error",!0),c&&c.reject()}.bind(this))}.bind(this))},_addProgressListener:function(a){a.addEventListener("progress",function(a){Ember.run(function(){if(a.lengthComputable){var c=a.loaded/this._getSize()*100;b.set(this,"uploadStatus.percentComplete",Math.round(c))}}.bind(this))}.bind(this),!1)},_addFile:function(a,c){var d="extension-%@".fmt(a.name.match(/\.(.+)$/i)[1]).toLowerCase(),e={file:a,valid:c,uploaded:!1,deleted:!1,className:d};return b.get(this,"files").pushObject(e),e}})}(window,window.Ember,window.jQuery),function(a,b){"use strict";a.DropletView=b.View.extend({classNames:["droppable"],ImagePreview:b.View.extend({tagName:"img",attributeBindings:["src"],src:null,image:null,didInsertElement:function(){var c=new a.FileReader,d=b.get(this,"image.file");return d.type.match(/^image\//i)?(c.onload=function(a){this.get("isDestroyed")!==!0&&b.set(this,"src",a.target.result)}.bind(this),void c.readAsDataURL(d)):void this.destroy()}}),MultipleInput:b.View.extend({tagName:"input",classNames:"files",attributeBindings:["name","type","multiple"],type:"file",multiple:"multiple",change:function(){var a=this.get("element").files;return this.get("parentView").traverseFiles(a)}}),drop:function(a,b){return this._preventDefaultBehaviour(a),this.traverseFiles(a.dataTransfer.files||b)},traverseFiles:function(a){var c=b.get(this,"controller"),d=b.get(c,"mimeTypes"),e=b.get(c,"extensions");b.assert("`mimeTypes` is undefined. Does your controller implement the `$emberDropletController` mixin?",!!d),b.assert("`mimeTypes` is not an array. It should be an array of valid MIME types.",!!b.isArray(d));for(var f=0,g=a.length;g>f;f++)if(a.hasOwnProperty(f)||f in a){var h=a[f],i=h.name.split(".").pop();-1!==$.inArray(h.type,d)||-1!==$.inArray(i,e)?c.send("addValidFile",h):c.send("addInvalidFile",h)}return!0},_preventDefaultBehaviour:function(a){a.preventDefault(),a.stopPropagation()},dragOver:function(a){this._preventDefaultBehaviour(a)},dragEnter:function(a){this._preventDefaultBehaviour(a)},dragLeave:function(a){this._preventDefaultBehaviour(a)}})}(window,window.Ember);
\ No newline at end of file
+!function(a,b,c){"use strict";a.DropletController=b.Mixin.create({mimeTypes:["image/jpeg","image/jpg","image/gif","image/png","text/plain"],extensions:["jpeg","jpg","gif","png"],requestHeaders:{},postData:{},files:[],uploadStatus:{uploading:!1,percentComplete:0,error:!1},init:function(){b.set(this,"files",[]),this._super()},actions:{addValidFile:function(a){return this._addFile(a,!0)},addInvalidFile:function(a){return this._addFile(a,!1)},deleteFile:function(a){return b.set(a,"deleted",!0),a},clearAllFiles:function(){b.set(this,"files",[])},uploadAllFiles:function(){var d={fileSizeHeader:!0,useArray:!0};if(0===b.get(this,"validFiles").length)return!1;var e=b.get(this,"dropletUrl"),f=b.get(this,"dropletOptions")||d,g=new c.Deferred,h=this.get("postData"),i=this.get("requestHeaders");b.set(this,"uploadStatus.uploading",!0),b.set(this,"uploadStatus.error",!1),b.assert("You must specify the `dropletUrl` parameter in order to upload files.",!!e);var j=new a.XMLHttpRequest;j.open("post",e,!0);var k=new a.FormData,l=f.useArray?"file[]":"file";b.EnumerableUtils.forEach(b.get(this,"validFiles"),function(a){k.append(l,a.file)},this);for(var m in h)h.hasOwnProperty(m)&&k.append(m,h[m]);this._addProgressListener(j.upload),this._addSuccessListener(j.upload,g),this._addErrorListener(j.upload,g),j.onreadystatechange=function(){4===j.readyState&&Ember.run(function(){var c=a.JSON.parse(j.responseText);g.resolve(c),b.tryInvoke(this,"didUploadFiles",[c])}.bind(this))}.bind(this),f.fileSizeHeader&&j.setRequestHeader("X-File-Size",this._getSize());for(m in i)(i.hasOwnProperty(m)||m in i)&&j.setRequestHeader(m,i[m]);return j.send(k),g.promise()}},validFiles:b.computed(function(){return this._filesByProperties({valid:!0,deleted:!1,uploaded:!1})}).property("files.length","files.@each.deleted","files.@each.uploaded"),invalidFiles:b.computed(function(){return this._filesByProperties({valid:!1})}).property("files.length","files.@each.deleted"),uploadedFiles:b.computed(function(){return this._filesByProperties({uploaded:!0})}).property("files.length","files.@each.uploaded"),deletedFiles:b.computed(function(){return this._filesByProperties({deleted:!0})}).property("files.length","files.@each.deleted"),_filesByProperties:function(a){return b.get(this,"files").filter(function(b){for(var c in a)if((a.hasOwnProperty(c)||c in a)&&b[c]!==a[c])return!1;return!0})},_getSize:function(){var a=0;return b.EnumerableUtils.forEach(b.get(this,"validFiles"),function(b){a+=b.file.size}),a},_addSuccessListener:function(a){a.addEventListener("load",function(){Ember.run(function(){b.EnumerableUtils.forEach(b.get(this,"validFiles"),function(a){b.set(a,"uploaded",!0)}),b.set(this,"uploadStatus.uploading",!1)}.bind(this))}.bind(this),!1)},_addErrorListener:function(a,c){a.addEventListener("error",function(){Ember.run(function(){b.set(this,"uploadStatus.uploading",!1),b.set(this,"uploadStatus.error",!0),c&&c.reject()}.bind(this))}.bind(this))},_addProgressListener:function(a){a.addEventListener("progress",function(a){Ember.run(function(){if(a.lengthComputable){var c=a.loaded/this._getSize()*100;b.set(this,"uploadStatus.percentComplete",Math.round(c))}}.bind(this))}.bind(this),!1)},_addFile:function(a,c){var d="extension-%@".fmt(a.name.match(/\.(.+)$/i)[1]).toLowerCase(),e={file:a,valid:c,uploaded:!1,deleted:!1,className:d};return b.get(this,"files").pushObject(e),e}})}(window,window.Ember,window.jQuery),function(a,b){"use strict";var c={tagName:"input",classNames:"files",attributeBindings:["name","type","multiple"],type:"file",multiple:"multiple",change:function(){var a=this.get("element").files;return this.get("parentView").traverseFiles(a)}},d=b.copy(c);d.multiple=!1,a.DropletView=b.View.extend({classNames:["droppable"],ImagePreview:b.View.extend({tagName:"img",attributeBindings:["src"],src:null,image:null,didInsertElement:function(){var c=new a.FileReader,d=b.get(this,"image.file");return d.type.match(/^image\//i)?(c.onload=function(a){this.get("isDestroyed")!==!0&&b.set(this,"src",a.target.result)}.bind(this),void c.readAsDataURL(d)):void this.destroy()}}),MultipleInput:b.View.extend(c),SingleInput:b.View.extend(d),drop:function(a,b){return this._preventDefaultBehaviour(a),this.traverseFiles(a.dataTransfer.files||b)},traverseFiles:function(a){var c=b.get(this,"controller"),d=b.get(c,"mimeTypes"),e=b.get(c,"extensions"),f=b.get(c,"dropletOptions")||{limit:1/0};b.assert("`mimeTypes` is undefined. Does your controller implement the `$emberDropletController` mixin?",!!d),b.assert("`mimeTypes` is not an array. It should be an array of valid MIME types.",!!b.isArray(d));for(var g=0,h=a.length;h>g;g++)if(a.hasOwnProperty(g)||g in a){var i=a[g],j=i.name.split(".").pop(),k=-1===$.inArray(i.type,d)&&-1===$.inArray(j,e),l=b.get(c,"validFiles").length;k||l===f.limit?c.send("addInvalidFile",i):c.send("addValidFile",i)}return!0},_preventDefaultBehaviour:function(a){a.preventDefault(),a.stopPropagation()},dragOver:function(a){this._preventDefaultBehaviour(a)},dragEnter:function(a){this._preventDefaultBehaviour(a)},dragLeave:function(a){this._preventDefaultBehaviour(a)}})}(window,window.Ember);
\ No newline at end of file
diff --git a/docs/classes/DropletView.html b/docs/classes/DropletView.html
index c9fc215..047de1f 100644
--- a/docs/classes/DropletView.html
+++ b/docs/classes/DropletView.html
@@ -94,7 +94,7 @@ DropletView Class
@@ -147,18 +147,14 @@ Methods
- change
-Invoked when the content of the INPUT changes.
+ change
- didInsertElement
-Invoked when the view is inserted into the DOM.
+ didInsertElement
@@ -270,6 +266,27 @@ Properties
+
+
+
+ MultipleInput
+
+
+
+
+
+
+ SingleInput
+
+
+
+
+
+
+ SingleInput
+
+
+
@@ -355,7 +372,7 @@ _preventDefaultBehaviour
- packages/ember-droplet/ember-droplet-view.js:203
+ packages/ember-droplet/ember-droplet-view.js:233
@@ -366,7 +383,8 @@ _preventDefaultBehaviour
-
+
Prevents default behaviour and propagation on nodes where it's undesirable.
+
@@ -384,8 +402,7 @@ Parameters:
-
Prevents default behaviour and propagation on nodes where it's undesirable.
-
+
@@ -413,10 +430,8 @@ Returns:
-
-
change
-Invoked when the content of the INPUT changes.
+
+
change
()
@@ -451,7 +466,7 @@
-
+
Invoked when the content of the INPUT changes.
+
@@ -485,10 +501,8 @@
Returns:
-
-
didInsertElement
-Invoked when the view is inserted into the DOM.
+
-
+
Invoked when the view is inserted into the DOM.
+
@@ -603,7 +618,7 @@
dragEnter
-
packages/ember-droplet/ember-droplet-view.js:224
+
packages/ember-droplet/ember-droplet-view.js:255
@@ -706,7 +721,7 @@
dragLeave
-
packages/ember-droplet/ember-droplet-view.js:233
+
packages/ember-droplet/ember-droplet-view.js:264
@@ -809,7 +824,7 @@
dragOver
-
packages/ember-droplet/ember-droplet-view.js:215
+
packages/ember-droplet/ember-droplet-view.js:246
@@ -918,7 +933,7 @@
drop
-
packages/ember-droplet/ember-droplet-view.js:148
+
packages/ember-droplet/ember-droplet-view.js:169
@@ -929,7 +944,8 @@
drop
-
+
Invoked when the user drops a file onto the droppable area.
+
@@ -962,8 +978,7 @@ Parameters:
-
= []]
-Invoked when the user drops a file onto the droppable area.
+
= []]
@@ -1038,7 +1053,7 @@ traverseFiles
- packages/ember-droplet/ember-droplet-view.js:160
+ packages/ember-droplet/ember-droplet-view.js:182
@@ -1049,7 +1064,9 @@ traverseFiles
-
+
Accepts a FileList object, and traverses them to determine if they're valid, adding them
+as either valid or invalid.
+
@@ -1067,9 +1084,7 @@ Parameters:
-
Accepts a FileList object, and traverses them to determine if they're valid, adding them
-as either valid or invalid.
-
+
@@ -1128,7 +1143,7 @@ attributeBindings
- packages/ember-droplet/ember-droplet-view.js:33
+ packages/ember-droplet/ember-droplet-view.js:25
@@ -1142,8 +1157,6 @@ attributeBindings
- Default: ['src']
-
@@ -1174,7 +1187,7 @@ attributeBindings
- packages/ember-droplet/ember-droplet-view.js:116
+ packages/ember-droplet/ember-droplet-view.js:93
@@ -1188,6 +1201,8 @@ attributeBindings
+ Default: ['src']
+
@@ -1218,7 +1233,7 @@ classNames
- packages/ember-droplet/ember-droplet-view.js:13
+ packages/ember-droplet/ember-droplet-view.js:73
@@ -1264,7 +1279,7 @@ classNames
- packages/ember-droplet/ember-droplet-view.js:109
+ packages/ember-droplet/ember-droplet-view.js:18
@@ -1310,7 +1325,7 @@ file
- packages/ember-droplet/ember-droplet-view.js:122
+ packages/ember-droplet/ember-droplet-view.js:31
@@ -1356,7 +1371,7 @@ image
- packages/ember-droplet/ember-droplet-view.js:47
+ packages/ember-droplet/ember-droplet-view.js:107
@@ -1402,7 +1417,7 @@ ImagePreview
- packages/ember-droplet/ember-droplet-view.js:20
+ packages/ember-droplet/ember-droplet-view.js:80
@@ -1446,7 +1461,7 @@ multiple
- packages/ember-droplet/ember-droplet-view.js:129
+ packages/ember-droplet/ember-droplet-view.js:38
@@ -1492,7 +1507,139 @@ MultipleInput
- packages/ember-droplet/ember-droplet-view.js:96
+ packages/ember-droplet/ember-droplet-view.js:157
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- Default: "img"
+ Default: "input"
diff --git a/docs/data.json b/docs/data.json
index 6324e15..2b005d2 100644
--- a/docs/data.json
+++ b/docs/data.json
@@ -36,7 +36,7 @@
"namespaces": {},
"tag": "module",
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 5,
+ "line": 65,
"type": "Ember.Mixin",
"extends": "Ember.Mixin"
}
@@ -66,7 +66,7 @@
"module": "App",
"namespace": "",
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 5
+ "line": 65
}
},
"classitems": [
@@ -423,148 +423,178 @@
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 13,
+ "line": 5,
"itemtype": "property",
- "name": "classNames",
- "type": "{Array}",
- "default": "['droppable']",
+ "name": "MultipleInput",
+ "type": "{Object}",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 20,
+ "line": 11,
"itemtype": "property",
- "name": "ImagePreview",
- "type": "{Ember.View}",
+ "name": "tagName",
+ "type": "{String}",
+ "default": "\"input\"",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 26,
+ "line": 18,
"itemtype": "property",
- "name": "tagName",
+ "name": "classNames",
"type": "{String}",
- "default": "\"img\"",
+ "default": "\"files\"",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 33,
+ "line": 25,
"itemtype": "property",
"name": "attributeBindings",
"type": "{Array}",
- "default": "['src']",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 40,
+ "line": 31,
"itemtype": "property",
- "name": "src",
+ "name": "file",
"type": "{String}",
- "default": "null",
+ "default": "\"file\"",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 47,
+ "line": 38,
"itemtype": "property",
- "name": "image",
+ "name": "multiple",
"type": "{String}",
- "default": "null",
+ "default": "\"multiple\"",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 54,
+ "line": 45,
+ "description": "Invoked when the content of the INPUT changes.",
"itemtype": "method",
- "name": "didInsertElement\nInvoked when the view is inserted into the DOM.",
+ "name": "change",
"return": {
"description": "",
- "type": "Void"
+ "type": "Boolean"
},
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 96,
+ "line": 58,
"itemtype": "property",
- "name": "MultipleInput",
- "type": "{Ember.View}",
+ "name": "SingleInput",
+ "type": "{Object}",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 102,
+ "line": 73,
"itemtype": "property",
- "name": "tagName",
- "type": "{String}",
- "default": "\"input\"",
+ "name": "classNames",
+ "type": "{Array}",
+ "default": "['droppable']",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 109,
+ "line": 80,
"itemtype": "property",
- "name": "classNames",
+ "name": "ImagePreview",
+ "type": "{Ember.View}",
+ "class": "DropletView",
+ "module": "App"
+ },
+ {
+ "file": "packages/ember-droplet/ember-droplet-view.js",
+ "line": 86,
+ "itemtype": "property",
+ "name": "tagName",
"type": "{String}",
- "default": "\"files\"",
+ "default": "\"img\"",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 116,
+ "line": 93,
"itemtype": "property",
"name": "attributeBindings",
"type": "{Array}",
+ "default": "['src']",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 122,
+ "line": 100,
"itemtype": "property",
- "name": "file",
+ "name": "src",
"type": "{String}",
- "default": "\"file\"",
+ "default": "null",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 129,
+ "line": 107,
"itemtype": "property",
- "name": "multiple",
+ "name": "image",
"type": "{String}",
- "default": "\"multiple\"",
+ "default": "null",
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 136,
+ "line": 114,
+ "description": "Invoked when the view is inserted into the DOM.",
"itemtype": "method",
- "name": "change\nInvoked when the content of the INPUT changes.",
+ "name": "didInsertElement",
"return": {
"description": "",
- "type": "Boolean"
+ "type": "Void"
},
"class": "DropletView",
"module": "App"
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 148,
+ "line": 157,
+ "itemtype": "property",
+ "name": "MultipleInput",
+ "type": "{Ember.View}",
+ "class": "DropletView",
+ "module": "App"
+ },
+ {
+ "file": "packages/ember-droplet/ember-droplet-view.js",
+ "line": 163,
+ "itemtype": "property",
+ "name": "SingleInput",
+ "type": "{Ember.View}",
+ "class": "DropletView",
+ "module": "App"
+ },
+ {
+ "file": "packages/ember-droplet/ember-droplet-view.js",
+ "line": 169,
+ "description": "Invoked when the user drops a file onto the droppable area.",
"itemtype": "method",
"name": "drop",
"params": [
@@ -575,7 +605,7 @@
},
{
"name": "[files",
- "description": "= []] \nInvoked when the user drops a file onto the droppable area.",
+ "description": "= []]",
"type": "Array"
}
],
@@ -588,13 +618,14 @@
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 160,
+ "line": 182,
+ "description": "Accepts a FileList object, and traverses them to determine if they're valid, adding them\nas either valid or invalid.",
"itemtype": "method",
"name": "traverseFiles",
"params": [
{
"name": "files",
- "description": "\nAccepts a FileList object, and traverses them to determine if they're valid, adding them\nas either valid or invalid.",
+ "description": "",
"type": "FileList"
}
],
@@ -607,13 +638,14 @@
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 203,
+ "line": 233,
+ "description": "Prevents default behaviour and propagation on nodes where it's undesirable.",
"itemtype": "method",
"name": "_preventDefaultBehaviour",
"params": [
{
"name": "event",
- "description": "\nPrevents default behaviour and propagation on nodes where it's undesirable.",
+ "description": "",
"type": "jQuery.Event"
}
],
@@ -628,7 +660,7 @@
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 215,
+ "line": 246,
"itemtype": "method",
"name": "dragOver",
"params": [
@@ -647,7 +679,7 @@
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 224,
+ "line": 255,
"itemtype": "method",
"name": "dragEnter",
"params": [
@@ -666,7 +698,7 @@
},
{
"file": "packages/ember-droplet/ember-droplet-view.js",
- "line": 233,
+ "line": 264,
"itemtype": "method",
"name": "dragLeave",
"params": [
diff --git a/docs/files/packages_ember-droplet_ember-droplet-view.js.html b/docs/files/packages_ember-droplet_ember-droplet-view.js.html
index 157167c..18ebba2 100644
--- a/docs/files/packages_ember-droplet_ember-droplet-view.js.html
+++ b/docs/files/packages_ember-droplet_ember-droplet-view.js.html
@@ -94,6 +94,66 @@ File: packages/ember-droplet/ember-droplet-view.js
"use strict";
+ /**
+ * @property MultipleInput
+ * @type {Object}
+ */
+ var MultipleInput = {
+
+ /**
+ * @property tagName
+ * @type {String}
+ * @default "input"
+ */
+ tagName: 'input',
+
+ /**
+ * @property classNames
+ * @type {String}
+ * @default "files"
+ */
+ classNames: 'files',
+
+ /**
+ * @property attributeBindings
+ * @type {Array}
+ */
+ attributeBindings: ['name', 'type', 'multiple'],
+
+ /**
+ * @property file
+ * @type {String}
+ * @default "file"
+ */
+ type: 'file',
+
+ /**
+ * @property multiple
+ * @type {String}
+ * @default "multiple"
+ */
+ multiple: 'multiple',
+
+ /**
+ * Invoked when the content of the INPUT changes.
+ *
+ * @method change
+ * @return {Boolean}
+ */
+ change: function() {
+ var files = this.get('element').files;
+ return this.get('parentView').traverseFiles(files);
+ }
+
+ };
+
+ /**
+ * @property SingleInput
+ * @type {Object}
+ */
+ var SingleInput = $ember.copy(MultipleInput);
+ SingleInput.multiple = false;
+
/**
* @module App
* @class DropletView
@@ -144,8 +204,9 @@ File: packages/ember-droplet/ember-droplet-view.js
image: null,
/**
- * @method didInsertElement
* Invoked when the view is inserted into the DOM.
+ *
+ * @method didInsertElement
* @return {void}
*/
didInsertElement: function() {
@@ -189,59 +250,20 @@ File: packages/ember-droplet/ember-droplet-view.js
* @property MultipleInput
* @type {Ember.View}
*/
- MultipleInput: $ember.View.extend({
-
- /**
- * @property tagName
- * @type {String}
- * @default "input"
- */
- tagName: 'input',
+ MultipleInput: $ember.View.extend(MultipleInput),
- /**
- * @property classNames
- * @type {String}
- * @default "files"
- */
- classNames: 'files',
-
- /**
- * @property attributeBindings
- * @type {Array}
- */
- attributeBindings: ['name', 'type', 'multiple'],
-
- /**
- * @property file
- * @type {String}
- * @default "file"
- */
- type: 'file',
-
- /**
- * @property multiple
- * @type {String}
- * @default "multiple"
- */
- multiple: 'multiple',
-
- /**
- * @method change
- * Invoked when the content of the INPUT changes.
- * @return {Boolean}
- */
- change: function() {
- var files = this.get('element').files;
- return this.get('parentView').traverseFiles(files);
- }
-
- }),
+ /**
+ * @property SingleInput
+ * @type {Ember.View}
+ */
+ SingleInput: $ember.View.extend(SingleInput),
/**
+ * Invoked when the user drops a file onto the droppable area.
+ *
* @method drop
* @param event {jQuery.Event}
* @param [files = []] {Array}
- * Invoked when the user drops a file onto the droppable area.
* @return {Boolean}
*/
drop: function(event, files) {
@@ -250,10 +272,11 @@ File: packages/ember-droplet/ember-droplet-view.js
},
/**
- * @method traverseFiles
- * @param files {FileList}
* Accepts a FileList object, and traverses them to determine if they're valid, adding them
* as either valid or invalid.
+ *
+ * @method traverseFiles
+ * @param files {FileList}
* @return {boolean}
*/
traverseFiles: function(files) {
@@ -261,26 +284,33 @@ File: packages/ember-droplet/ember-droplet-view.js
// Find the controller, and the `mimeTypes` and `extensions` property.
var controller = $ember.get(this, 'controller'),
mimeTypes = $ember.get(controller, 'mimeTypes'),
- extensions = $ember.get(controller, 'extensions');
+ extensions = $ember.get(controller, 'extensions'),
+ options = $ember.get(controller, 'dropletOptions') || { limit: Infinity };
- // Assert that we have the `mineTypes` property, and that it's an array.
+ // Assert that we have the `mimeTypes` property, and that it's an array.
$ember.assert('`mimeTypes` is undefined. Does your controller implement the `$emberDropletController` mixin?', !!mimeTypes);
$ember.assert('`mimeTypes` is not an array. It should be an array of valid MIME types.', !!$ember.isArray(mimeTypes));
for (var index = 0, numFiles = files.length; index < numFiles; index++) {
- if (!files.hasOwnProperty(index)&&(!(index in files))) {
+ if (!files.hasOwnProperty(index) && (!(index in files))) {
continue;
}
- var file = files[index],
+ var file = files[index],
fileExt = file.name.split('.').pop();
- // Determine if the file is valid based on its MIME type or extension.
- if (($.inArray(file.type, mimeTypes) === -1)&&($.inArray(fileExt, extensions) === -1)) {
+ // Determine if the file is valid based on its MIME type or extension, and we haven't exceeded
+ // the user defined limit for the amount of files to upload in one go.
+ var invalidMime = ($.inArray(file.type, mimeTypes) === -1) && ($.inArray(fileExt, extensions) === -1),
+ currentLength = $ember.get(controller, 'validFiles').length;
+
+ if (invalidMime || currentLength === options.limit) {
+
// If it isn't valid, then we'll add it as an invalid file.
controller.send('addInvalidFile', file);
continue;
+
}
// Otherwise the file has a valid MIME type or extension, and therefore be added as a good file.
@@ -293,9 +323,10 @@ File: packages/ember-droplet/ember-droplet-view.js
},
/**
+ * Prevents default behaviour and propagation on nodes where it's undesirable.
+ *
* @method _preventDefaultBehaviour
* @param event {jQuery.Event}
- * Prevents default behaviour and propagation on nodes where it's undesirable.
* @return {void}
* @private
*/
diff --git a/docs/modules/App.html b/docs/modules/App.html
index 17009ae..1fc7d1e 100644
--- a/docs/modules/App.html
+++ b/docs/modules/App.html
@@ -94,7 +94,7 @@ App Module
diff --git a/example/index.html b/example/index.html
index de0bc8c..fe6c5c9 100644
--- a/example/index.html
+++ b/example/index.html
@@ -59,7 +59,7 @@ Uploaded Percentage: {{uploadStatus.percentComp
{{/each}}
- {{view view.MultipleInput}}
+ {{view view.SingleInput}}
{{/view}}
diff --git a/example/scripts/package/ember-droplet-view.js b/example/scripts/package/ember-droplet-view.js
index 27c1ec1..634b071 100644
--- a/example/scripts/package/ember-droplet-view.js
+++ b/example/scripts/package/ember-droplet-view.js
@@ -2,6 +2,66 @@
"use strict";
+ /**
+ * @property MultipleInput
+ * @type {Object}
+ */
+ var MultipleInput = {
+
+ /**
+ * @property tagName
+ * @type {String}
+ * @default "input"
+ */
+ tagName: 'input',
+
+ /**
+ * @property classNames
+ * @type {String}
+ * @default "files"
+ */
+ classNames: 'files',
+
+ /**
+ * @property attributeBindings
+ * @type {Array}
+ */
+ attributeBindings: ['name', 'type', 'multiple'],
+
+ /**
+ * @property file
+ * @type {String}
+ * @default "file"
+ */
+ type: 'file',
+
+ /**
+ * @property multiple
+ * @type {String}
+ * @default "multiple"
+ */
+ multiple: 'multiple',
+
+ /**
+ * Invoked when the content of the INPUT changes.
+ *
+ * @method change
+ * @return {Boolean}
+ */
+ change: function() {
+ var files = this.get('element').files;
+ return this.get('parentView').traverseFiles(files);
+ }
+
+ };
+
+ /**
+ * @property SingleInput
+ * @type {Object}
+ */
+ var SingleInput = $ember.copy(MultipleInput);
+ SingleInput.multiple = false;
+
/**
* @module App
* @class DropletView
@@ -52,8 +112,9 @@
image: null,
/**
- * @method didInsertElement
* Invoked when the view is inserted into the DOM.
+ *
+ * @method didInsertElement
* @return {void}
*/
didInsertElement: function() {
@@ -97,59 +158,20 @@
* @property MultipleInput
* @type {Ember.View}
*/
- MultipleInput: $ember.View.extend({
-
- /**
- * @property tagName
- * @type {String}
- * @default "input"
- */
- tagName: 'input',
+ MultipleInput: $ember.View.extend(MultipleInput),
- /**
- * @property classNames
- * @type {String}
- * @default "files"
- */
- classNames: 'files',
-
- /**
- * @property attributeBindings
- * @type {Array}
- */
- attributeBindings: ['name', 'type', 'multiple'],
-
- /**
- * @property file
- * @type {String}
- * @default "file"
- */
- type: 'file',
-
- /**
- * @property multiple
- * @type {String}
- * @default "multiple"
- */
- multiple: 'multiple',
-
- /**
- * @method change
- * Invoked when the content of the INPUT changes.
- * @return {Boolean}
- */
- change: function() {
- var files = this.get('element').files;
- return this.get('parentView').traverseFiles(files);
- }
-
- }),
+ /**
+ * @property SingleInput
+ * @type {Ember.View}
+ */
+ SingleInput: $ember.View.extend(SingleInput),
/**
+ * Invoked when the user drops a file onto the droppable area.
+ *
* @method drop
* @param event {jQuery.Event}
* @param [files = []] {Array}
- * Invoked when the user drops a file onto the droppable area.
* @return {Boolean}
*/
drop: function(event, files) {
@@ -158,10 +180,11 @@
},
/**
- * @method traverseFiles
- * @param files {FileList}
* Accepts a FileList object, and traverses them to determine if they're valid, adding them
* as either valid or invalid.
+ *
+ * @method traverseFiles
+ * @param files {FileList}
* @return {boolean}
*/
traverseFiles: function(files) {
@@ -169,26 +192,33 @@
// Find the controller, and the `mimeTypes` and `extensions` property.
var controller = $ember.get(this, 'controller'),
mimeTypes = $ember.get(controller, 'mimeTypes'),
- extensions = $ember.get(controller, 'extensions');
+ extensions = $ember.get(controller, 'extensions'),
+ options = $ember.get(controller, 'dropletOptions') || { limit: Infinity };
- // Assert that we have the `mineTypes` property, and that it's an array.
+ // Assert that we have the `mimeTypes` property, and that it's an array.
$ember.assert('`mimeTypes` is undefined. Does your controller implement the `$emberDropletController` mixin?', !!mimeTypes);
$ember.assert('`mimeTypes` is not an array. It should be an array of valid MIME types.', !!$ember.isArray(mimeTypes));
for (var index = 0, numFiles = files.length; index < numFiles; index++) {
- if (!files.hasOwnProperty(index)&&(!(index in files))) {
+ if (!files.hasOwnProperty(index) && (!(index in files))) {
continue;
}
- var file = files[index],
+ var file = files[index],
fileExt = file.name.split('.').pop();
- // Determine if the file is valid based on its MIME type or extension.
- if (($.inArray(file.type, mimeTypes) === -1)&&($.inArray(fileExt, extensions) === -1)) {
+ // Determine if the file is valid based on its MIME type or extension, and we haven't exceeded
+ // the user defined limit for the amount of files to upload in one go.
+ var invalidMime = ($.inArray(file.type, mimeTypes) === -1) && ($.inArray(fileExt, extensions) === -1),
+ currentLength = $ember.get(controller, 'validFiles').length;
+
+ if (invalidMime || currentLength === options.limit) {
+
// If it isn't valid, then we'll add it as an invalid file.
controller.send('addInvalidFile', file);
continue;
+
}
// Otherwise the file has a valid MIME type or extension, and therefore be added as a good file.
@@ -201,9 +231,10 @@
},
/**
+ * Prevents default behaviour and propagation on nodes where it's undesirable.
+ *
* @method _preventDefaultBehaviour
* @param event {jQuery.Event}
- * Prevents default behaviour and propagation on nodes where it's undesirable.
* @return {void}
* @private
*/
diff --git a/package.json b/package.json
index bd881a9..30c2d44 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ember-droplet",
- "version": "0.5.9",
+ "version": "0.6.0",
"author": "Adam Timberlake",
"dependencies": {
"bower": "^1.3.10",
diff --git a/packages/ember-droplet/ember-droplet-view.js b/packages/ember-droplet/ember-droplet-view.js
index 27c1ec1..634b071 100644
--- a/packages/ember-droplet/ember-droplet-view.js
+++ b/packages/ember-droplet/ember-droplet-view.js
@@ -2,6 +2,66 @@
"use strict";
+ /**
+ * @property MultipleInput
+ * @type {Object}
+ */
+ var MultipleInput = {
+
+ /**
+ * @property tagName
+ * @type {String}
+ * @default "input"
+ */
+ tagName: 'input',
+
+ /**
+ * @property classNames
+ * @type {String}
+ * @default "files"
+ */
+ classNames: 'files',
+
+ /**
+ * @property attributeBindings
+ * @type {Array}
+ */
+ attributeBindings: ['name', 'type', 'multiple'],
+
+ /**
+ * @property file
+ * @type {String}
+ * @default "file"
+ */
+ type: 'file',
+
+ /**
+ * @property multiple
+ * @type {String}
+ * @default "multiple"
+ */
+ multiple: 'multiple',
+
+ /**
+ * Invoked when the content of the INPUT changes.
+ *
+ * @method change
+ * @return {Boolean}
+ */
+ change: function() {
+ var files = this.get('element').files;
+ return this.get('parentView').traverseFiles(files);
+ }
+
+ };
+
+ /**
+ * @property SingleInput
+ * @type {Object}
+ */
+ var SingleInput = $ember.copy(MultipleInput);
+ SingleInput.multiple = false;
+
/**
* @module App
* @class DropletView
@@ -52,8 +112,9 @@
image: null,
/**
- * @method didInsertElement
* Invoked when the view is inserted into the DOM.
+ *
+ * @method didInsertElement
* @return {void}
*/
didInsertElement: function() {
@@ -97,59 +158,20 @@
* @property MultipleInput
* @type {Ember.View}
*/
- MultipleInput: $ember.View.extend({
-
- /**
- * @property tagName
- * @type {String}
- * @default "input"
- */
- tagName: 'input',
+ MultipleInput: $ember.View.extend(MultipleInput),
- /**
- * @property classNames
- * @type {String}
- * @default "files"
- */
- classNames: 'files',
-
- /**
- * @property attributeBindings
- * @type {Array}
- */
- attributeBindings: ['name', 'type', 'multiple'],
-
- /**
- * @property file
- * @type {String}
- * @default "file"
- */
- type: 'file',
-
- /**
- * @property multiple
- * @type {String}
- * @default "multiple"
- */
- multiple: 'multiple',
-
- /**
- * @method change
- * Invoked when the content of the INPUT changes.
- * @return {Boolean}
- */
- change: function() {
- var files = this.get('element').files;
- return this.get('parentView').traverseFiles(files);
- }
-
- }),
+ /**
+ * @property SingleInput
+ * @type {Ember.View}
+ */
+ SingleInput: $ember.View.extend(SingleInput),
/**
+ * Invoked when the user drops a file onto the droppable area.
+ *
* @method drop
* @param event {jQuery.Event}
* @param [files = []] {Array}
- * Invoked when the user drops a file onto the droppable area.
* @return {Boolean}
*/
drop: function(event, files) {
@@ -158,10 +180,11 @@
},
/**
- * @method traverseFiles
- * @param files {FileList}
* Accepts a FileList object, and traverses them to determine if they're valid, adding them
* as either valid or invalid.
+ *
+ * @method traverseFiles
+ * @param files {FileList}
* @return {boolean}
*/
traverseFiles: function(files) {
@@ -169,26 +192,33 @@
// Find the controller, and the `mimeTypes` and `extensions` property.
var controller = $ember.get(this, 'controller'),
mimeTypes = $ember.get(controller, 'mimeTypes'),
- extensions = $ember.get(controller, 'extensions');
+ extensions = $ember.get(controller, 'extensions'),
+ options = $ember.get(controller, 'dropletOptions') || { limit: Infinity };
- // Assert that we have the `mineTypes` property, and that it's an array.
+ // Assert that we have the `mimeTypes` property, and that it's an array.
$ember.assert('`mimeTypes` is undefined. Does your controller implement the `$emberDropletController` mixin?', !!mimeTypes);
$ember.assert('`mimeTypes` is not an array. It should be an array of valid MIME types.', !!$ember.isArray(mimeTypes));
for (var index = 0, numFiles = files.length; index < numFiles; index++) {
- if (!files.hasOwnProperty(index)&&(!(index in files))) {
+ if (!files.hasOwnProperty(index) && (!(index in files))) {
continue;
}
- var file = files[index],
+ var file = files[index],
fileExt = file.name.split('.').pop();
- // Determine if the file is valid based on its MIME type or extension.
- if (($.inArray(file.type, mimeTypes) === -1)&&($.inArray(fileExt, extensions) === -1)) {
+ // Determine if the file is valid based on its MIME type or extension, and we haven't exceeded
+ // the user defined limit for the amount of files to upload in one go.
+ var invalidMime = ($.inArray(file.type, mimeTypes) === -1) && ($.inArray(fileExt, extensions) === -1),
+ currentLength = $ember.get(controller, 'validFiles').length;
+
+ if (invalidMime || currentLength === options.limit) {
+
// If it isn't valid, then we'll add it as an invalid file.
controller.send('addInvalidFile', file);
continue;
+
}
// Otherwise the file has a valid MIME type or extension, and therefore be added as a good file.
@@ -201,9 +231,10 @@
},
/**
+ * Prevents default behaviour and propagation on nodes where it's undesirable.
+ *
* @method _preventDefaultBehaviour
* @param event {jQuery.Event}
- * Prevents default behaviour and propagation on nodes where it's undesirable.
* @return {void}
* @private
*/