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

- Defined in: packages/ember-droplet/ember-droplet-view.js:5 + Defined in: packages/ember-droplet/ember-droplet-view.js:65
@@ -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 @@

    change - packages/ember-droplet/ember-droplet-view.js:136 + packages/ember-droplet/ember-droplet-view.js:45

    @@ -462,7 +477,8 @@

    change

    - +

    Invoked when the content of the INPUT changes.

    +
    @@ -485,10 +501,8 @@

    Returns:

    -
    -

    didInsertElement -Invoked when the view is inserted into the DOM.

    +
    +

    didInsertElement

    () @@ -523,7 +537,7 @@

    didInsertElement - packages/ember-droplet/ember-droplet-view.js:54 + packages/ember-droplet/ember-droplet-view.js:114

    @@ -534,7 +548,8 @@

    didInsertElement

    - +

    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 + +

    + + + + + + +
    + +
    + + + + + + + + + +
    +

    MultipleInput

    + Object + + + + + + + + + +
    + + + +

    + + Defined in + + + + + packages/ember-droplet/ember-droplet-view.js:5 + +

    + + + + +
    + +
    + +
    + + + + + + +
    + + +
    +

    SingleInput

    + Object + + + + + + + + + +
    + + + +

    + + Defined in + + + + + packages/ember-droplet/ember-droplet-view.js:58 + +

    + + + + +
    + +
    + +
    + + + + + + +
    + + +
    +

    SingleInput

    + Ember.View + + + + + + + + + + -

    Default: "input"

    +

    Default: "img"

    @@ -1628,7 +1775,7 @@

    tagName

    - packages/ember-droplet/ember-droplet-view.js:26 + packages/ember-droplet/ember-droplet-view.js:11

    @@ -1642,7 +1789,7 @@

    tagName

    -

    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 */