178 lines
5.4 KiB
JavaScript
Executable File
178 lines
5.4 KiB
JavaScript
Executable File
(function( parent ) {
|
|
'use strict';
|
|
|
|
/** parent object, set in the end of the selfcalling function **/
|
|
var parent = parent || window,
|
|
/** instance of File Reader **/
|
|
reader,
|
|
readFile,
|
|
/**
|
|
* Removes class from element
|
|
* @param htmlObject target element
|
|
* @param string "class to be removed"
|
|
**/
|
|
removeClass = function( el, value ) {
|
|
if ( !el.className ) return false;
|
|
var classes = el.className.split(' '),
|
|
ret = [];
|
|
for( var i = 0, l = classes.length; i < l; ++i )
|
|
if( classes[i] != value )
|
|
ret.push( classes[ i ] );
|
|
el.className = ret.join(' ');
|
|
};
|
|
|
|
if( !window.FileReader || !document.addEventListener ) {
|
|
throw( "File API not supported" );
|
|
readFile = function(){ throw( "File API not supported" ); };
|
|
}
|
|
else {
|
|
reader = new FileReader();
|
|
readFile = function ( file, callback, method ) {
|
|
/** Error handler (throws error at the console) **/
|
|
reader.onerror = function( e ) {
|
|
var message,
|
|
lut = [ "File not found.", "File coulnot be opened",
|
|
"File couldnot be uploaded", "Couldnot read File", "File too large" ];
|
|
// http://www.w3.org/TR/FileAPI/#ErrorDescriptions
|
|
throw( lut[ ( e.target.error.code - 1 ) ] );
|
|
},
|
|
/** Success, calling the callback **/
|
|
reader.onloadend = function( e ) {
|
|
callback && callback( e.target.result, file.name );
|
|
reader.onloadend = null;
|
|
};
|
|
|
|
// the method is specified in the beginning of the file
|
|
reader[ method ]( file );
|
|
return false;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Drag n Drop Files module
|
|
* @param HTMLElement, could be the Body
|
|
* @param DOMElement/String, if a string is specified then a div will be built and appended to the body
|
|
* with that String as its id. If a dom element is passed, that will be used instead. This object
|
|
* acts as an overlay and the file should be droped to this object. If this object is null, then the first argument
|
|
* will be used as the overlay.
|
|
* @param Function, will be called with the file data, and the filename as its arguments
|
|
* @param String, possible values "text, binarytext, arrabuffer" decides how the file will be read
|
|
* if let null, defaults to text
|
|
* @param String, class name to be added to the overlay (default is '__fadingIn')
|
|
**/
|
|
parent.dragNDrop = function( body, overlay_id, callback, method, _clss ) {
|
|
var win = window;
|
|
// check to see if we are using a mobile device - no need for dragNdrop in devices
|
|
// that do not support it somehow yet
|
|
if( ( 'ontouchstart' in window ) )
|
|
return "mobile";
|
|
|
|
/** JS Object, used to define the file-reading method **/
|
|
var method_lut = {
|
|
'text' : 'readAsText',
|
|
'binary' : 'readAsBinaryText',
|
|
'arrayBuffer': 'readAsArrayBuffer'
|
|
},
|
|
/** class added/removed from overlay object **/
|
|
clss = _clss ? _clss : "__fadingIn",
|
|
method = method ? method_lut[ method ] : 'readAsText',
|
|
/** how many events cast (dragenter/dragleave) **/
|
|
entered = 0,
|
|
/**
|
|
* DOMElement sink for the drag events
|
|
* if left unspecified then the body inherits the role
|
|
**/
|
|
overlay = !!overlay_id ? overlay_id : body,
|
|
/**
|
|
* (void) if the overlay_id specified is a string, then a div with that id is built
|
|
* and appended to the body. Else the default is used
|
|
**/
|
|
_overlayBuilder = function() {
|
|
if( typeof overlay_id === "string" )
|
|
{
|
|
var tmp = document.createElement( 'div' );
|
|
overlay = document.createElement( 'div' );
|
|
overlay.id = overlay_id;
|
|
|
|
tmp.innerHTML = "Drag n drop Files!";
|
|
overlay.appendChild( tmp );
|
|
|
|
body.appendChild( overlay );
|
|
tmp = null;
|
|
}
|
|
},
|
|
/**
|
|
* JS Object
|
|
* The events Object contains various functions that control
|
|
* the behavior of the events fired
|
|
**/
|
|
events = {
|
|
/**
|
|
* (void) Prevents default action and bubbling up
|
|
**/
|
|
silencer : function( e ) {
|
|
e.preventDefault();
|
|
e.stopPropagation()
|
|
},
|
|
|
|
/**
|
|
* Shows message to drop file
|
|
**/
|
|
onDragEnter : function( e ) {
|
|
// overlay.className += " " + clss;
|
|
++entered;
|
|
|
|
setTimeout(function() {
|
|
if( entered > 1 )
|
|
entered = 1;
|
|
}, 10 )
|
|
},
|
|
/**
|
|
* Hides the overlay... twist included!
|
|
**/
|
|
onDragLeave : function( e ) {
|
|
--entered;
|
|
|
|
if( entered <= 0 )
|
|
{
|
|
removeClass( overlay, clss );
|
|
entered = 0;
|
|
}
|
|
},
|
|
/**
|
|
* Files dropped
|
|
**/
|
|
onDrop : function( e ) {
|
|
// prevent the event from bubbling/firing default
|
|
events.silencer( e );
|
|
|
|
// Hide the overlay
|
|
removeClass( overlay, clss );
|
|
entered = 0;
|
|
|
|
/** dropped files. **/
|
|
var files = e.dataTransfer.files,
|
|
len;
|
|
|
|
// If anything is wrong with the dropped files, exit.
|
|
if( !files || !files.length )
|
|
return false;
|
|
|
|
len = files.length;
|
|
while( len-- )
|
|
// iterate files array and load them
|
|
readFile( files[ len ], callback, method );
|
|
}
|
|
};
|
|
|
|
(function init() {
|
|
//_overlayBuilder();
|
|
// events initialization
|
|
body.parentNode.addEventListener( "dragenter", events.onDragEnter, false );
|
|
body.addEventListener( "dragleave", events.onDragLeave, false );
|
|
body.addEventListener( "dragover", events.silencer, false);
|
|
body.addEventListener( "drop", events.onDrop, false);
|
|
return false;
|
|
})( body );
|
|
};
|
|
})( window ); |