HTML5 drag and drop file field

2019-09-14 23:20发布

问题:

I want to enhance a critical form with drag and drop functionality. I know that modern browser are capable of this via HTML5 file API.

However I do NOT want an instant upload or to upload multiple files, I am simply looking for duplicate functionality to ye olde fashioned file field.

After doing a-little research I've found the HTML5 file API requires an independent upload from the rest of the form (lame). Which is not the desired behavior.

So I then considered making a standard file field and setting it to position : absolute; visibility : hidden; and having to follow around the mouse inside the the dropZone via .mousemove. But this is not possible as the browser window is out of focus while the user grab's their file!

I also attempted to make the file field huge and invisible, but styling the field in this way is not possible.

Any ideas?

回答1:

Here is what ended up working, I set the vanilla upload field to opacity : 0 and positioned it under the mouse when the mouse is over the visible dropZone div, via the 'dragover' event.

'dragover' overcomes the problem with the browser window being out of focus, and provides .pageX and .pageY which I then bound to the invisible file field's .top and .left.

However the resulting position of the file field is different on osx vs windows OSs, so a catch had to be put in to position the file field appropriately based on OS. I am pasting my working code below, and I have written a lib that detects browsers, OS and devices. So you will need to find your own way to detect osx vs windows.

dropText  = $ '#dropText'
jdropZone = $ '#resume'
fileField = $ '#draggy'

unless $.browser.msie

    `var addEvent=(function(){if(document.addEventListener){return function(el,type,fn){if(el&&el.nodeName||el===window){el.addEventListener(type,fn,false)}else if(el&&el.length){for(var i=0;i<el.length;i++){addEvent(el[i],type,fn)}}}}else{return function(el,type,fn){if(el&&el.nodeName||el===window){el.attachEvent('on'+type,function(){return fn.call(el,window.event)})}else if(el&&el.length){for(var i=0;i<el.length;i++){addEvent(el[i],type,fn)}}}}})();(function(){var pre=document.createElement('pre');pre.id="view-source";addEvent(window,'click',function(event){if(event.target.hash=='#view-source'){if(!document.getElementById('view-source')){var xhr=new XMLHttpRequest();xhr.onreadystatechange=function(){if(this.readyState==4&&this.status==200){pre.innerHTML=this.responseText.replace(/[<>]/g,function(m){return{'<':'&lt;','>':'&gt;'}[m]});prettyPrint()}};document.body.appendChild(pre);xhr.open("GET",window.location,true);xhr.send()}document.body.className='view-source';var sourceTimer=setInterval(function(){if(window.location.hash!='#view-source'){clearInterval(sourceTimer);document.body.className=''}},200)}})})();`

    x = 0
    y = -50

    x = -200 unless device.mac
    x = -130 if device.mac      

    #alert x

    dragover = (e) ->
        #e.preventDefault()
        fileField.css top : e.pageY+y, left : e.pageX+x

    dropZone = document.getElementById 'resume'

    addEvent dropZone, 'dragover', dragover

    fileField.on 'change', ->
        fieldVal = fileField.attr 'value'
        fieldVal = fieldVal.split 'fakepath'
        fieldVal = fieldVal[fieldVal.length-1]
        fieldVal = fieldVal.substr 1, fieldVal.length if $.browser.webkit
        dropText.text 'Your Resume: '+fieldVal

else

    fileField.css
        position : 'static'
        opacity  : 1
    dropText.text 'Upload Your Resume Here: '