We want to reduce the number of steps it takes for a user to upload a file on our website; so we're using jQuery to open and postback files using the below markup (simplified):
<a onclick="$('#uplRegistrationImage').click();">
Change profile picture
</a>
<!-- Hidden to keep the UI clean -->
<asp:FileUpload ID="uplRegistrationImage"
runat="server"
ClientIDMode="static"
Style="display:none"
onchange="$('#btnSubmitImage').click();" />
<asp:Button runat="server"
ID="btnSubmitImage"
ClientIDMode="static"
Style="display:none"
OnClick="btnSubmitImage_OnClick"
UseSubmitBehavior="False" />
This works absolutely fine in Firefox and Chrome; opening the file dialog when the link is clicked and firing the postback when a file is selected.
However in IE9 after the file upload has loaded and a user has selected a file; insteaed of the OnChange working I get a "SCRIPT5 Access is denied" error. I've tried setting an arbitrary timeout, setting intervals to check if a file is given to no avail.
There are a number of other questions relating to this; however none appear to have a decent answer (One said set the file dialog to be transparent and hover behind a button!)
Has anyone else resolved this? Or is it absolutely necessary that I provide a button for IE users?
For security reasons, what you are trying to do is not possible. It seems to be the IE9 will not let you submit a form in this way unless it was an actual mouse click on the File Upload control that triggers it.
For arguments sake, I was able to use your code to do the submit in the change handler, but it worked only when I clicked the Browse button myself. I even set up polling in the $(document).ready method for a variable set by the change handler that indicates a submission should be triggered - this didn't work either.
The solutions to this problem appear to be:
Styling the control in such a way that it sits behind a button. You mentioned this in your question, but the answer provided by Romas here In JavaScript can I make a "click" event fire programmatically for a file input element? does in fact work (I tried in IE9, Chrome v23 and FF v15).
Using a Flash-based approach (GMail does this). I tried out the Uploadify demo and it seems to work quite nicely.
Styling a File Upload:
http://www.quirksmode.org/dom/inputfile.html
http://www.shauninman.com/archive/2007/09/10/styling_file_inputs_with_css_and_the_dom
References:
jQuery : simulating a click on a <input type="file" /> doesn't work in Firefox?
IE9 file input triggering using Javascript
getting access is denied error on IE8
Hey this solution works.
for download we should be using MSBLOB
$scope.getSingleInvoicePDF = function(invoiceNumberEntity) {
var fileName = invoiceNumberEntity + ".pdf";
var pdfDownload = document.createElement("a");
document.body.appendChild(pdfDownload);
AngularWebService.getFileWithSuffix("ezbillpdfget",invoiceNumberEntity,"pdf" ).then(function(returnedJSON) {
var fileBlob = new Blob([returnedJSON.data], {type: 'application/pdf'});
if (navigator.appVersion.toString().indexOf('.NET') > 0) { // for IE browser
window.navigator.msSaveBlob(fileBlob, fileName);
} else { // for other browsers
var fileURL = window.URL.createObjectURL(fileBlob);
pdfDownload.href = fileURL;
pdfDownload.download = fileName;
pdfDownload.click();
}
});
};
This solution looks like it might work. You'll have to wrap it in a <form> and get it to post in the jquery change handler, and probably handle it in form_load using the __eventtarget or and iframe or whatever it is that web forms uses, but it allows you to select a file, and by submitting the form, it should send it. I can't test it however, since I don't have an environment set up at home.
http://jsfiddle.net/axpLc/1/
<a onclick="$('#inputFile').click();">
Change profile picture
</a>
<div id='divHide'>
<input id='inputFile' type='file' />
</div>
$('#inputFile').change(function() { alert('ran'); });
#divHide { display:none; }
Well, like SLC stated you should utilize the <Form> tag.
First you should indicate the amount of files; which should be determined by your input fields. The second step will be to stack them into an array.
<input type="file" class="upload" name="fileX[]"/>
Then create a loop; by looping it will automatically be determined based on the input field it's currently on.
$("input[#type=file]:nth(" + n +")")
Then you'll notice that each file chosen; will replace the input name to the file-name. That should be a very, very basic way to submit multiple files through jQuery.
If you'd like a single item:
$("input[#type=file]").change(function(){
doIt(this, fileMax);
});
That should create a Div where the maximum file found; and attaches to the onEvent. The correlating code above would need these also:
var fileMax = 3;
<input type="file" class="upload" name="fileX[]" />
This should navigate the DOM parent tree; then create the fields respectively. That is one way; the other way is the one you see above with SLC. There are quite a few ways to do it; it's just how much of jQuery do you want manipulating it?
Hopefully that helps; sorry if I misunderstood your question.
Related
I try to upload an image on my instagram, so I need to select path for upload files
but I can't use form.file_field.send_keys(path) because Instagram manage upload via JS, so the form not exist, it's only when I click on button "+" then the "File Upload" window appear.
I try :
#browser.send_keys #path
#browser.send_keys :enter
but not works too...
I don't found a method to interact with this sub-windows "File Upload" to give the path of image.
Any idea?
EDIT :
<nav class="NXc7H f11OC "><div class="_8MQSO ZoygQ "><div class=""><div class="rBWT5"></div><div class="KGiwt"><div class="A8wCM"><div class="BvyAW"><div class="q02Nz"><a class="_0TPg" href="/"><span class="glyphsSpriteHome__outline__24__grey_9 u-__7" aria-label="Home"></span></a></div><div class="q02Nz"><a class="_0TPg" href="/explore/"><span class="glyphsSpriteSearch__outline__24__grey_9 u-__7" aria-label="Search & Explore"></span></a></div><div class="q02Nz _0TPg" role="menuitem" tabindex="0"><span class="glyphsSpriteNew_post__outline__24__grey_9 u-__7" aria-label="New Post" style=""></span></div><div class="q02Nz"><a class="_0TPg " href="/accounts/activity/"><span class="glyphsSpriteHeart__outline__24__grey_9 u-__7" aria-label="Activity"></span></a></div><div class="q02Nz"><a class="_0TPg" href="/tristan_grey_30/"><span class="glyphsSpriteUser__filled__24__grey_9 u-__7" aria-label="Profile"></span></a></div></div></div></div><form class="Q9en_" enctype="multipart/form-data" method="POST" role="presentation"><input accept="image/jpeg" class="tb_sK" type="file"></form></div></div></nav>
if I try using the <form> contain in <nav>, nothing happen, there is onClick event on "+" :
{
!0 !== this.$_MobileNav2 && (this.$_MobileNav2 = !0, r(d[1]).logAction_DEPRECATED('cameraIconClick'), this.$_MobileNav3 ? (this.$_MobileNav3.selectFile(), this.props.onStartCreation()) : (i(d[2])('No image form'), this.props.onImageFormError()), this.$_MobileNav2 = !1)
}
It's manage by JS I think...
You aren't going to like the answer, but Watir will not interact with that window opened up by the OS in any way. Going a step further, Ruby itself does not interact with these OS level dialogues.
There are a couple of things that you may want to reference to confirm this, and that's perfectly acceptable:
Watir's Philosophy on Downloads (and conversely Uploading)
An answer by Thomas Walpole explaining what I just did
A possible solution using Capybara::Node::Actions#attach_file
In any case, you are attempting to interact with an object that does not have a way of being interacted with through Ruby, let alone Watir, and thus your desired solution is impossible.
Your best case is the Capybara attach_file method. If that doesn't work, nothing is going to outside of a literal OS scripting language such as AutoIt or Sikuli
You can find the SikuliX project page here. DrapsTV did a roughly hour-long playlist about the setup and quickstart of SikuliX. The link to the first episode in the series is linked here.
Good luck.
I'm going to go with a bit of a JavaScript hack to expose the hidden <input type="file">. The first thing to do is identify the input type file on the page, then use some JavaScript to make it visible. Then once it is visible use send_keys to pass in the path to the local file and selenium should do the rest for you.
file_upload_element = #browser.file_field
#browser.execute_script("return arguments[0].setAttribute( 'style', 'display: inline !important')", file_upload_element)
file_upload_element.set(<path_to_local_file>)
Some caveats. I don't use Watir, I've tried to write the above code based on the Watir documentation and the code you have provided, it is a guess though. I can write it in a language I'm familiar with if that helps. I am hoping it's close enough to point you in the right direction though.
As mentioned the comments earlier, can you try appending the file input element to the html and then use that to upload the file.
# get the frame element or any button that opens the file upload window
ele = driver.find_element_by_id("frame/button id goes here")
# add a hidden file input ( might have to change the onchange event based on the events associated to the button in above line as you don't have a form)
driver.execute_script("var x= document.createElement('INPUT');x.setAttribute('type', 'file'); x.setAttribute('onchange','this.form.submit()');x.setAttribute('hidden', 'true'); arguments[0].appendChild(x);",ele)
# send the picture path here ( this should upload the file)
driver.find_element_by_xpath("//input[#type='file']").send_keys("picture path should go here")
Can you please try this and let me know your outcome.
#browser.file_field.set file_upload works for me
I had to update my Chrome Driver which was little bit tricky on Windows. Belows is my complete script for upload to a Dropbox File Request:
require 'watir'
#setting the path to my updated ChromeDriver:
Selenium::WebDriver::Chrome::Service.driver_path = 'C:\#Ruby\#no_pub\install\chromedriver.exe'
class Dropbox_Request
def initialize(url, file_upload)
#browser = Watir::Browser.new
#browser.goto url
#browser.file_field.set file_upload
#browser.text_field(:name => 'fname').set "first"
#browser.text_field(:name => 'lname').set "last"
#browser.text_field(:name => 'email').set "email#gmail.com"
#browser.button(:class => ["button-primary", "submission-form__submit"]).click()
end
end
I am new to HTML5 and javascript and I have a question.
I have the following HTML code
<img id='image_preview'/>";
<input type='file' name='fileUpl' id='fileUpl' onchange='doUpl();' accept='image/*'/>
So in short, there is a button, every time I click it, doUpl() is executed. It loads a picture and shows a preview of the picture into <img ... >
the js function is
function doUpl() {
var file = document.getElementById('fileUpl').files[0];
...
dataUrl = canvas.toDataURL("image/jpeg");
document.getElementById('image_preview').src = dataUrl;
...
I would like to have the input field pre-loaded with a default picture path (ex. c:\test.jpg) and the preview of test.jpg already shown when the page is loaded the first time. If the button is pressed the picture is updated.
At the moment, when I first load the html page there is no preview and the input path is empty.
Can anyone help me with this?
Thanks :)
edit: sorry for the confusion. the test img is of course on the server not on the client PC.
I would like to have the input field pre-loaded with a default picture path (ex. c:\test.jpg)
You can do that using the value attribute. Something like this:
<input type='file' name='fileUpl' id='fileUpl' onchange='doUpl();' accept='image/*' value='c:\test.jpg'/>
the preview of test.jpg already shown when the page is loaded the first time.
There are a couple ways you can do this. The basic one is to do like above, using the src attribute:
<img id='image_preview' src='c:\test.jpg'/>"
But, I think is better to do using javascript, because, if one day you need to change this standard image, you only change it on the input element.
</body>
<script>
// self executing function here
(function() {
doUpl(); //this will execute when page is loaded.
})();
</script>
P.S. This is only possible if you have c:\test.jpg on your server
You can check if there is something on the input and fake the img and fake the path but you cannot get a real image from the user hard drive because it's security
If you are talking about preloading images from the client's filesystem, I'm afraid this is not possible due to obvious security reasons:
The specification of the File API states that:
(..) This specification also assumes that the primary user interaction is
with the element of HTML forms [HTML], and that
all files that are being read by FileReader objects have first been
selected by the user (..)
I implemented a HTML page which runs locally on a Linux machine (using the most current firefox versions). It is used to embed a plugin which I have programmed.
At the moment, I statically pass a file path, the plugin has to load, that is hard-coded in the HTML file:
<embed id="embed1" type="application/x-bbx" src="/tmp/testfile.bbx"></embed>
The HTML page is generated for all .bbx files. I'm currently trying to figure out how I can avoid the hard-coded path by adding an <input type="file"> element. The aim is to dynamically change the loaded file (specified by src) to avoid the need of generating the HTML page for all .bbx files.
As browsers do not allow access to the file path: how I can change the embed's source according to the loaded file?
For several technical reasons, I would like to avoid using JQuery. Also note, that the page is run solely locally by specific users.
EDIT 1: The plugin is scriptable, i.e. I can invoke functions on and pass parameters to the plugin using JavaScript. Thus, it would suffice to get the whole file path and pass it to the plugin which in turn does the rest internally.
EDIT 2: For clarification: I want to avoid the burden of having the user enter the file path manually, which is why I intended to use <input type="file">
var Target = "/tmp/testfile2.bbx";
var Source = document.getElementById('embed1');
var Clone = Source.cloneNode(true);
Clone.setAttribute('src',Target);
Source.parentNode.replaceChild(Clone,Source);
But history of browser gets no event here... so .back() will work incorrectly.
Thats how I got here today. Hope this helps. And sorry if a was not fluxed to the right moment. ;-)
If I understood right, this should do it!
<script>
var embed1 = document.getElementById('embed1');
embed1.src = 'your path';
</script>
Here is a complete example:
JSFiddle
<input type="text" id="path" name="path" />
<input type="submit" id="submit" value="Change it" onclick="changePath()">
<embed id="embed1" type="application/x-bbx" src="/tmp/testfile.bbx"></embed>
<script>
function changePath() {
var e = document.getElementById('path');
var val = e.value;
var embed1 = document.getElementById('embed1');
embed1.src = val;
}
</script>
Firefox (and probably other browsers) want to keep whatever text the user entered in the text input, even after a reload. Just including the default text (that I want the input to revert to) in the html doesn't work:
<input tyep='text' value='default text' />
And neither does trying to use JS
window.onload = function() {document.getElementById("mytextinput").value = 'default text'}
You can use plain old HTML :)
Set autocomplete='off' in the attribute
<input type='text' value='default text' autocomplete='off' />
This works on most modern browsers.
Technically, you don't have to run a function onload to clear it--you could just put the javascript right in the page. For instance:
document.getElementById("mytextinput").value = ''
or with jQuery
$("mytextinput").val('');
Note that it's always a good idea to work with a dom listener to ensure that your javascript fires after the dom has been properly built. So, in the example of jQuery, this would be as easy as
$(document).ready(function() {
$("mytextinput").val('');
});
Try this:
<input type='text' id='mytextinput' value='default text' />
<script>
document.getElementById("mytextinput").value = 'default text';
</script>
This code should run as soon as the textbox has loaded. The onload event can seem inconsistent, I'm not entirely sure how it behaves in multiple browsers on different actions like refreshing.
You can call the script differently, put it in a function, put it somewhere else etc, but it's good to start with a working version.
If this doesn't work on other browsers there isn't much you can do because some browsers will try and be 'helpful' and always autofill for you.
I think you should do a server side coding on page reload. Page reload is generally a postback type idea . The page gets reloaded from server. If you are doing asp.net , in page_load method add your default text. :)
There is a HTML textarea. I'm able to catch that event when a local file is dragged and dropped onto the textarea. But how to obtain the name of the dropped file? (To be modified and inserted into the textarea finally.)
The following expressions returns None in that case:
event.dataTransfer.files
event.dataTransfer.getData('text/plain')
I made a short example for Firefox 3 that is my target platform currently.
<script>
function init() {
document.getElementById('x').addEventListener('drop', onDrop, true)
}
function onDrop(event) {
var data = event.dataTransfer.getData('text/plain')
event.preventDefault()
alert('files: ' + event.dataTransfer.files + ' && data: ' + data + '.')
}
</script>
<body onload='init()'>
<textarea cols=70 rows=20 id='x'></textarea>
This is a bit late - but I think what you are looking for is this:
event.dataTransfer.files[0].name
You can also get the following properties:
event.dataTransfer.files[0].size
event.dataTransfer.files[0].type
And you can loop thru these files with the following:
var listOfNames='';
for(var i=0,tot=event.dataTransfer.files.length; i<tot; i++){
listOfNames+=event.dataTransfer.files[i].name + '\r\n';
}
Btw - if you are using jQuery then the dataTransfer object can be found here:
event.originalEvent.dataTransfer.files[0].name
Don't know if it's still relevant, but I faced the same problem. Here's how I solved it:
Create a normal upload form with a single input field (type="file")
Add this HTML attribute to the input field:
dropzone="copy file:image/png file:image/jpg file:image/jpeg"
Set JQuery listener or whatever to catch the "drop"-event on the input field
When you drag & drop a local image on the input field, the "value" attribute is filled automatically and you can process it like any other HTML form.
I also wrapped the form into another HTML element (div), set the size of the div and set overflow:hidden via CSS - this way, you can get rid of the "browse" button. It's not nice, but it works. I also used the AjaxForm plugin to upload the image in the background - works very nice.
as far as I know, you need to obtain an instance of nsIFile in order to get the file path (the File class does not offer this feature).
This MDC page explains how to do this: https://developer.mozilla.org/En/DragDrop/Recommended_Drag_Types#file.
Note that although not listed in the previous link, obtaining an nsIFile instance requires privileges escalation (cf. my answer to Can I drag files from the desktop to a drop area in Firefox 3.5 and initiate an upload? show how to do this).
im doing it by detecting mouseover and mousedown over the "Drop" zone
Alemjerus is correct, you don't have access to what you're looking for.
The behavior you mentioned in reply to his comment is the default behavior of certain browsers. For instance, with the stackoverflow textarea for this entry, if I use Safari and drag a file into it, it places the file's path into the textarea. With firefox 3.5, on the other hand, it attempts to open the file with the browser.
Basically, the "drag and drop" functionality you're attempting to implement is something thats handled by the browser and OS on the client machine -- you can't use Javascript for this purpose.
You can not do it with Javascript because of security reasons. Javascript VM has no direct access to OS file system. You can only drag and drop text.