Recently, while customizing (forgive me Russian scholars), I would even call it web modding (sorry again, dear Russian scholars) of standard form elements, and in particular the file element, I came across a big nuisance: it turned out to be unprofitable for customization. The point is this: from the file element we especially need its "Upload files" dialog box, which cannot be extracted using software in Mozilla and Opera browsers, i.e. command document.getElementById ('SaveForm'). click (); will return nothing. The developers claim that it is unsafe, which is debatable. But IE pleased me, it sends a mouse click to the file element without hindrance, most likely due to an oversight of developers who left the “most dangerous hole” in your security.
As I just did not dodge nothing. Googling for three hours, stumbled upon the first testimony of the ideal
solution : put the file in a div, make the div transparent (opacity: 0%), draw your attention to the fact that it should be made transparent, but not invisible (visibility: hidden), relatively speaking opacity : 0% hides the element from the eyes, and visibility: hidden also from the mouse. But if you play with the font sizes, the method begins to lose its appeal, you have the opportunity to miss the invisible button.
An hour later, I came across another example of
yamzbrowser (allows you to upload files to the server from a swf object inserted into an html page). He repeats the first method, but! with one difference: it inserts a div under the mouse cursor when moving. By the way, I managed to find it out thanks to Opera (I usually use Fox, and this is a great coincidence that I opened the example with Opera), since the author forgot to set transparency for her too.
Having studied both methods, I combined them into one and developed a solution for wider use on the Web. And so, sit down comfortably we begin.
Assumptions
- The size of the file substitute element may differ significantly from the size of the file itself.
- The file element is part of the form.
- Only paranoid disables JavaScript in the browser.
- The visitor refers to those modest 99% of users using Firefox, Opera or IE
- The solution should work using the same algorithm in all browsers, i.e. the option of using different tools for IE is document.getElementById ('SaveForm'). click (); and substitution for FF and Opera is unacceptable
- The solution can be duplicated on the page.
Algorithm
When you hover the mouse over the substitute button, the layer with the element is inserted under the cursor so that the cursor is in the middle of the layer, so we will know for sure that the user will not miss the button and the visibility changes to visible: the layer with the element remains invisible but accessible to the mouse. When the cursor is moved, we move the layer within the substituting button, upon reaching the edge of the button, visibility is set to hidden.
Recipe
HTML
<form>
<div id="divFile1" class="file" onmousemove="divFileMove(this.id, 'buttonFile1',event);">
<input type="file" name="UploadFile" id="file1" size="1" onchange="result(this.id, 'divResult');" tabindex="1" />
</div>
<div id="divResult"> </div>
<image src="./images/fileUploadButton.jpg" id="buttonFile1" onmouseover="divFileShow('divFile1', event);"/>
</form>
CSS
div.file{
position : absolute ;
top : -1000px ;
left : -1000px ;
-moz-opacity : 0 ;
filter : alpha(opacity=0) ;
opacity : 0% ;
visibility : hidden ;
}
div.file - it is the .file class that is used and not id, in view of assumption number 6.
top, left: -1000px - hides the layer before javascript gets to it, just in case.
-moz-opacity, filter: alpha, opacity - sets the transparency for FF, IE and Opera, respectively.
visibility: hidden - hides from the mouse.
Javascript
Function divFileShow (divId, e), where divId is the id of the layer with the element file, e is the event. The mouseX and mouseY functions calculate the mouse position relative to the upper left corner for all browsers. It makes the layer visible to the mouse and inserts it under the cursor so that the cursor is in the middle of the layer, so we don’t miss.
function divFileShow ( divId,e ){
var div = document .getElementById ( divId ) ;
div.style.left = ( mouseX ( e ) - Math . round ( div.offsetWidth / 2 )) + "px" ;
div.style.top = ( mouseY ( e ) - Math . round ( div.offsetHeight / 2 )) + "px" ;
div.style.visibility = "visible" ;
}
The divFileMove function (divId, butId, e), where divId is the layer id, butId is the replacement button id (necessary for getting the button dimensions), e-event. It makes the layer move after the mouse when the butId object reaches the boundary.
function divFileMove ( divId, butId, e ){
var div = document .getElementById ( divId ) ;
var button = document .getElementById ( butId ) ;
var move = true ;
var divX = parseInt ( div.style.left ) + Math . round ( div.offsetWidth / 2 ) ;
var divY = parseInt ( div.style.top ) + Math . round ( div.offsetHeight / 2 ) ;
if ( divX < button.offsetLeft || divX > ( button.offsetLeft + button.offsetWidth )) {
move = false ;
}
if ( divY < button.offsetTop || divY > ( button.offsetTop + button.offsetHeight )){
move = false ;
}
if ( move ){
div.style.left = ( mouseX ( e ) - div.offsetWidth / 2 ) + "px" ;
div.style.top = ( mouseY ( e ) - div.offsetHeight / 2 ) + "px" ;
} else {
div.style.visibility = "hidden" ;
}
}
Function result (fileId, divResultId), where fileId is the id of the file element, divResultId is the layer id where the name of the selected file will be displayed. The function passes only the file name to the innerHTML layer (for example, “all my passwords.txt”), and in the title attribute it places the full path, in my opinion, this is more convenient.
')
function result ( fileId, divResultId ){
var divResult = document .getElementById ( divResultId ) ;
var formFile = document .getElementById ( fileId ) ;
divResult.innerHTML = formFile.value. replace ( /^([^\\\/]*(\\|\/))*/ ,"" ) ;
divResult.setAttribute ( "title",formFile.value ) ;
}
And lastly, two functions (mouseX (e), mouseY (e), where e is event) that determine the location of the cursor on the page for IE and other browsers, they differ only in two letters, so I’ll give one of them.
function mouseX ( e ){
if ( e.pageX ) return e.pageX;
if ( e.clientX ) return e.clientX + document . body .scrollLeft;
}
Note
Since the layer with the file element overlaps the button, the event is not passed to it: hover, so if you need to simulate mouse pointing, you will have to add the corresponding functionality yourself either by changing the button class or changing the image.
Working example , if someone wants to help the right case, place an example for your online presentation, I guarantee the link and thanks to this article.
Tested in browsers Firefox 2, Opera 9, IE 6.
Thanks for attention.
PS Report bugs in advance without departing from the checkout;)