@@ -31,6 +31,11 @@ function Dropify(element, options) {
3131 var defaults = {
3232 defaultFile : '' ,
3333 maxFileSize : 0 ,
34+ minWidth : 0 ,
35+ maxWidth : 0 ,
36+ minHeight : 0 ,
37+ maxHeight : 0 ,
38+ allowedFormats : [ 'portrait' , 'square' , 'landscape' ] ,
3439 messages : {
3540 'default' : 'Drag and drop a file here or click' ,
3641 'replace' : 'Drag and drop or click to replace' ,
@@ -47,23 +52,31 @@ function Dropify(element, options) {
4752 }
4853 } ;
4954
50- this . element = element ;
51- this . input = $ ( this . element ) ;
52- this . wrapper = null ;
53- this . preview = null ;
54- this . filenameWrapper = null ;
55- this . settings = $ . extend ( true , defaults , options , this . input . data ( ) ) ;
56- this . imgFileFormats = [ 'png' , 'jpg' , 'jpeg' , 'gif' , 'bmp' ] ;
57- this . file = null ;
58- this . filename = null ;
59- this . isDisabled = false ;
55+ this . element = element ;
56+ this . input = $ ( this . element ) ;
57+ this . wrapper = null ;
58+ this . preview = null ;
59+ this . filenameWrapper = null ;
60+ this . settings = $ . extend ( true , defaults , options , this . input . data ( ) ) ;
61+ this . imgFileExtensions = [ 'png' , 'jpg' , 'jpeg' , 'gif' , 'bmp' ] ;
62+ this . errorsEvent = $ . Event ( 'dropify.errors' ) ;
63+ this . isDisabled = false ;
64+ this . file = {
65+ object : null ,
66+ name : null ,
67+ size : null ,
68+ width : null ,
69+ height : null ,
70+ type : null
71+ } ;
6072
6173 this . onChange = this . onChange . bind ( this ) ;
6274 this . clearElement = this . clearElement . bind ( this ) ;
75+ this . onFileReady = this . onFileReady . bind ( this ) ;
6376
6477 this . translate ( ) ;
6578 this . createElements ( ) ;
66- this . setSize ( ) ;
79+ this . setContainerSize ( ) ;
6780
6881 this . input . on ( 'change' , this . onChange ) ;
6982}
@@ -74,8 +87,7 @@ function Dropify(element, options) {
7487Dropify . prototype . onChange = function ( )
7588{
7689 this . resetPreview ( ) ;
77- this . setFilename ( this . input . val ( ) ) ;
78- this . readUrl ( this . element ) ;
90+ this . readFile ( this . element ) ;
7991} ;
8092
8193/**
@@ -113,36 +125,99 @@ Dropify.prototype.createElements = function()
113125 var defaultFile = this . settings . defaultFile || '' ;
114126
115127 if ( defaultFile . trim ( ) != '' ) {
116- this . setFilename ( defaultFile ) ;
128+ this . file . name = this . cleanFilename ( defaultFile ) ;
117129 this . setPreview ( defaultFile ) ;
118130 }
119131} ;
120132
121133/**
122- * Read the file url using FileReader
134+ * Read the file using FileReader
123135 *
124136 * @param {Object } input
125137 */
126- Dropify . prototype . readUrl = function ( input )
138+ Dropify . prototype . readFile = function ( input )
127139{
128140 if ( input . files && input . files [ 0 ] ) {
129- var reader = new FileReader ( ) ;
130- this . file = input . files [ 0 ] ;
141+ var reader = new FileReader ( ) ;
142+ var image = new Image ( ) ;
143+ var file = input . files [ 0 ] ;
144+ var srcBase64 = null ;
145+ var _this = this ;
146+ var eventFileReady = $ . Event ( "dropify.fileReady" ) ;
147+
148+ this . setFileInformations ( file ) ;
149+ reader . readAsDataURL ( file ) ;
150+
151+ this . errorsEvent . errors = [ ] ;
152+
153+ this . checkFileSize ( ) ;
154+
155+ reader . onload = function ( _file ) {
156+ srcBase64 = _file . target . result ;
157+ if ( this . isImage ( ) ) {
158+ image . src = _file . target . result ;
159+ image . onload = function ( ) {
160+ _this . setFileDimensions ( this . width , this . height ) ;
161+ _this . validateImage ( ) ;
162+ _this . input . trigger ( eventFileReady , [ srcBase64 ] ) ;
163+ } ;
164+ } else {
165+ this . input . trigger ( eventFileReady , [ srcBase64 ] ) ;
166+ }
167+ } . bind ( this ) ;
168+
169+ this . input . on ( 'dropify.fileReady' , this . onFileReady ) ;
170+ }
171+ } ;
131172
132- if ( this . checkFileSize ( ) ) {
133- reader . onload = function ( e ) {
134- this . setPreview ( e . target . result , this . file . name ) ;
135- } . bind ( this ) ;
173+ /**
174+ * On file ready to show
175+ *
176+ * @param {Event } event
177+ * @param {String } src
178+ */
179+ Dropify . prototype . onFileReady = function ( event , src )
180+ {
181+ this . input . off ( 'dropify.fileReady' , this . onFileReady ) ;
136182
137- reader . readAsDataURL ( this . file ) ;
138- } else {
139- this . wrapper . addClass ( 'has-error' ) ;
140- this . resetPreview ( ) ;
141- this . clearElement ( ) ;
142- }
183+ if ( this . errorsEvent . errors . length === 0 ) {
184+ this . setPreview ( src , this . file . name ) ;
185+ } else {
186+ this . input . trigger ( this . errorsEvent , [ this ] ) ;
187+ for ( var i = this . errorsEvent . errors . length - 1 ; i >= 0 ; i -- ) {
188+ console . log ( this . errorsEvent . errors [ i ] . namespace ) ;
189+ } ;
190+ // this.wrapper.addClass('has-error');
191+ this . resetPreview ( ) ;
192+ this . clearElement ( ) ;
143193 }
144194} ;
145195
196+ /**
197+ * Set file informations
198+ * @param {File } file
199+ */
200+ Dropify . prototype . setFileInformations = function ( file )
201+ {
202+ this . file . object = file ;
203+ this . file . name = file . name ;
204+ this . file . size = file . size ;
205+ this . file . type = file . type ;
206+ this . file . width = null ;
207+ this . file . height = null ;
208+ } ;
209+
210+ /**
211+ * Set file dimensions
212+ * @param {Int } width
213+ * @param {Int } height
214+ */
215+ Dropify . prototype . setFileDimensions = function ( width , height )
216+ {
217+ this . file . width = width ;
218+ this . file . height = height ;
219+ } ;
220+
146221/**
147222 * Set the preview and animate it
148223 *
@@ -151,6 +226,7 @@ Dropify.prototype.readUrl = function(input)
151226Dropify . prototype . setPreview = function ( src )
152227{
153228 this . wrapper . removeClass ( 'has-error' ) . addClass ( 'has-preview' ) ;
229+ this . filenameWrapper . children ( '.dropify-filename-inner' ) . html ( this . file . name ) ;
154230 var render = this . preview . children ( '.dropify-render' ) ;
155231
156232 if ( this . isImage ( ) === true ) {
@@ -159,7 +235,6 @@ Dropify.prototype.setPreview = function(src)
159235 $ ( '<i />' ) . attr ( 'class' , 'dropify-font-file' ) . appendTo ( render ) ;
160236 $ ( '<span class="dropify-extension" />' ) . html ( this . getFileType ( ) ) . appendTo ( render ) ;
161237 }
162-
163238 this . preview . fadeIn ( ) ;
164239} ;
165240
@@ -177,13 +252,13 @@ Dropify.prototype.resetPreview = function()
177252} ;
178253
179254/**
180- * Get the filename
255+ * Clean the src and get the filename
181256 *
182- * @param {String } src with path
257+ * @param {String } src
183258 *
184- * @return {String } clean filename
259+ * @return {String } filename
185260 */
186- Dropify . prototype . getFilename = function ( src )
261+ Dropify . prototype . cleanFilename = function ( src )
187262{
188263 var filename = src . split ( '\\' ) . pop ( ) ;
189264 if ( filename == src ) {
@@ -193,40 +268,46 @@ Dropify.prototype.getFilename = function(src)
193268 return src != "" ? filename : '' ;
194269} ;
195270
196- /**
197- * Set the filename in the object and in the dom
198- *
199- * @param {String } filename
200- */
201- Dropify . prototype . setFilename = function ( filename )
202- {
203- var filename = this . getFilename ( filename ) ;
204- this . filename = filename ;
205- this . filenameWrapper . children ( '.dropify-filename-inner' ) . html ( filename ) ;
206- } ;
207-
208271/**
209272 * Clear the element, events are available
210273 */
211274Dropify . prototype . clearElement = function ( )
212275{
213- var eventBefore = $ . Event ( "dropify.beforeClear" ) ;
214- this . input . trigger ( eventBefore , [ this ] ) ;
276+ if ( this . errorsEvent . errors . length === 0 ) {
277+ var eventBefore = $ . Event ( "dropify.beforeClear" ) ;
278+ this . input . trigger ( eventBefore , [ this ] ) ;
279+
280+ if ( eventBefore . result !== false ) {
281+ this . resetFile ( ) ;
282+ this . input . val ( '' ) ;
283+ this . resetPreview ( ) ;
215284
216- if ( eventBefore . result !== false ) {
217- this . file = null ;
285+ this . input . trigger ( $ . Event ( "dropify.afterClear" ) , [ this ] ) ;
286+ }
287+ } else {
288+ this . resetFile ( ) ;
218289 this . input . val ( '' ) ;
219290 this . resetPreview ( ) ;
220-
221- var eventAfter = $ . Event ( "dropify.afterClear" ) ;
222- this . input . trigger ( eventAfter , [ this ] ) ;
223291 }
224292} ;
225293
226294/**
227- * Set the wrapper height
295+ * Reset file informations
228296 */
229- Dropify . prototype . setSize = function ( )
297+ Dropify . prototype . resetFile = function ( )
298+ {
299+ this . file . object = null ;
300+ this . file . name = null ;
301+ this . file . size = null ;
302+ this . file . type = null ;
303+ this . file . width = null ;
304+ this . file . height = null ;
305+ } ;
306+
307+ /**
308+ * Set the container height
309+ */
310+ Dropify . prototype . setContainerSize = function ( )
230311{
231312 if ( this . settings . height ) {
232313 this . wrapper . height ( this . settings . height ) ;
@@ -251,7 +332,7 @@ Dropify.prototype.isTouchDevice = function()
251332 */
252333Dropify . prototype . getFileType = function ( )
253334{
254- return this . filename . split ( '.' ) . pop ( ) . toLowerCase ( ) ;
335+ return this . file . name . split ( '.' ) . pop ( ) . toLowerCase ( ) ;
255336} ;
256337
257338/**
@@ -261,7 +342,7 @@ Dropify.prototype.getFileType = function()
261342 */
262343Dropify . prototype . isImage = function ( )
263344{
264- if ( this . imgFileFormats . indexOf ( this . getFileType ( ) ) != "-1" ) {
345+ if ( this . imgFileExtensions . indexOf ( this . getFileType ( ) ) != "-1" ) {
265346 return true ;
266347 }
267348
@@ -282,16 +363,12 @@ Dropify.prototype.translate = function()
282363
283364/**
284365 * Check the limit filesize.
285- *
286- * @return {Boolean }
287366 */
288367Dropify . prototype . checkFileSize = function ( )
289368{
290- if ( this . maxFileSizeToByte ( ) === 0 || this . file . size <= this . maxFileSizeToByte ( ) ) {
291- return true ;
369+ if ( this . maxFileSizeToByte ( ) !== 0 && this . file . size > this . maxFileSizeToByte ( ) ) {
370+ this . pushError ( "fileSize" ) ;
292371 }
293-
294- return false ;
295372} ;
296373
297374/**
@@ -321,6 +398,61 @@ Dropify.prototype.maxFileSizeToByte = function()
321398 return value ;
322399} ;
323400
401+ /**
402+ * Validate image dimensions and format
403+ */
404+ Dropify . prototype . validateImage = function ( )
405+ {
406+ if ( this . settings . minWidth !== 0 && this . settings . minWidth >= this . file . width ) {
407+ this . pushError ( "minWidth" ) ;
408+ }
409+
410+ if ( this . settings . maxWidth !== 0 && this . settings . maxWidth <= this . file . width ) {
411+ this . pushError ( "maxWidth" ) ;
412+ }
413+
414+ if ( this . settings . minHeight !== 0 && this . settings . minHeight >= this . file . height ) {
415+ this . pushError ( "minHeight" ) ;
416+ }
417+
418+ if ( this . settings . maxHeight !== 0 && this . settings . maxHeight <= this . file . height ) {
419+ this . pushError ( "maxHeight" ) ;
420+ }
421+
422+ if ( this . settings . allowedFormats . indexOf ( this . getImageFormat ( ) ) == "-1" ) {
423+ this . pushError ( "imageFormat" ) ;
424+ }
425+ } ;
426+
427+ /**
428+ * Get image format.
429+ * @return {String }
430+ */
431+ Dropify . prototype . getImageFormat = function ( )
432+ {
433+ if ( this . file . width == this . file . height ) {
434+ return "square" ;
435+ }
436+
437+ if ( this . file . width < this . file . height ) {
438+ return "portrait" ;
439+ }
440+
441+ if ( this . file . width > this . file . height ) {
442+ return "landscape" ;
443+ }
444+ } ;
445+
446+ /**
447+ * Push error
448+ * @param {String } errorKey
449+ */
450+ Dropify . prototype . pushError = function ( errorKey ) {
451+ var e = $ . Event ( "dropify.error." + errorKey ) ;
452+ this . errorsEvent . errors . push ( e ) ;
453+ this . input . trigger ( e , [ this ] ) ;
454+ } ;
455+
324456$ . fn [ pluginName ] = function ( options ) {
325457 this . each ( function ( ) {
326458 if ( ! $ . data ( this , "plugin_" + pluginName ) ) {
0 commit comments