2
\$\begingroup\$

They've always annoyed me, and as a matter of principle, would like to leave my HTML/CSS intact and have the various file upload plugins work with consistent behavior with any styled element.

The following script places a transparent file input over a selected input. Note that solutions such as triggering an upload script based on another element being clicked are not supported by all browsers, so please do not recommend doing so. One deficiency of my current solution is that cursor pointer doesn't work with Chrome. Another is that I have not addressed border radius on the new element, and will consider doing to in the future. I am also sure there are other changes that should be made. Please advise of recommended changes.

See https://jsfiddle.net/4noentrp/2/ for a working example.

PS. I would think all file upload plugins should default to similar functionality. Agree?

jQuery.fn.extend({
    makeInput: function (o) {
        var arr = [];
        this.each(function () {
            var $this = $(this);
            if ( $this.is( "input:file" ) ) {var elem=$this;}
            else {
                var position = $this.position();
                var elem = $('<input/>', $.extend({},o,{
                    type: 'file',
                    style: 'height: ' + $this.outerHeight() + 'px;width: ' + $this.outerWidth() + 'px;top: ' + position.top + 'px;left:' + position.left + 'px;margin-top:' + $this.css('marginTop') + ';position:absolute;cursor:pointer;z-index:9999;opacity:0;filter: alpha(opacity=0)'
                    }
                )).insertAfter(this);
            }
            arr.push(elem[0]);
        });
        return $(arr);
    }
});

$('.makeInput').makeInput({name:'bla'}).fileupload({
    add: function (e, data) {
        alert(data.originalFiles[0].name+' submitted');
    }
});

Related HTML and CSS is shown below, however, the primary script is the JavaScript located above.

<div class="box">
    <div>bla bla bla<a href="javascript:void(0)" class="makeInput">inline</a>bla bla bla</div>
    <p class="makeInput">block</p>
    <p class="makeInput" id="float">float</p>
    <p class="makeInput" id="position-static">position-static</p>
    <p class="makeInput" id="position-absolute">position-absolute</p>
    <p class="makeInput" id="position-relative">position-relative</p>
</div>

a {
    border: 1px solid black;
}
p {
    width: 120px;
    border: 1px solid black;
}
#float {
    float:right;
}
#position-absolute {
    position: relative;
    left: 30px;
    top: 80px;
}
#position-relative {
    position: relative;
    left: 30px;
    top: 80px;
}
#position-static {
    position: static;
}
\$\endgroup\$
  • \$\begingroup\$ I like the idea of this extending the jquery.fileupload plugin - however what is wrong with using <label for="input_id">select</label> and hiding the input offscreen.. works for me, and styles easily too :) \$\endgroup\$ – CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Oct 20 '15 at 13:25
  • \$\begingroup\$ @CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Does it work for all browsers? Some upload plugin documentation states for security, some browsers require that the actual input is clicked. \$\endgroup\$ – user1032531 Oct 20 '15 at 13:31
  • \$\begingroup\$ well the label is attached to the input with the for attribute so it triggers the input - jsfiddle example \$\endgroup\$ – CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Oct 20 '15 at 13:36
  • \$\begingroup\$ Also,it would be great if you could data- the attributes like name, accept, multiple, required.. \$\endgroup\$ – CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Oct 20 '15 at 13:47
  • 1
    \$\begingroup\$ @CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Good point. Instead of passing the input name, I will pass an object which will include name, accept, etc. Also, I will check to see if the original element is a file input, and if so, not update it. \$\endgroup\$ – user1032531 Oct 20 '15 at 14:17
1
\$\begingroup\$

I know my answer comes a bit late, but I thought I'll share. I don't really get the problem you're facing. What's wrong with doing the regular styling of label, as in my example?

Answering your questions:

@CᴴᵁᴮᴮʸNᴵᴺᴶᴬ Does it work for all browsers?

<label> was introduced in HTML4, even IE6+ can support it.

My reason for creating this script is to allow the buttons on a jQueryUI dialog to work as file upload triggers (...)

Don't use JavaScript (and especially it's libraries) for elements and functionalities that you can create with pure (X)HTML and CSS. But if you have to do the file upload with a jQuery UI buttons or any other element and you don't want to create and style a <label>, you can simply do:

var fileInput = document.querySelector('input[type="file"]');

document.querySelector('input[type="button"]').onclick = function() {
  fileInput.click();
}
fileInput.onchange = function() {
  this.form.submit();
};

Where input[type="file"] bear display: none and input[type="button"] can be any element that we'd like to trigger file upload action. Take a peak into my working example.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.