In IE9, FormData is not supported, which makes uploading files using XMLHttpRequest a lot less trivial.
Can this be done? I've seen iFrames mentioned, and while I'm not opposed to writing some hairy code, I'm at a loss as to how to achieve this (there are many resources talking about uploading to an iFrame but not about how to get the file from the iFrame to the server).
Using vanilla JavaScript (no third party libraries), how would one upload a file asynchronously without the use of FormData?
This code should do the trick. Sorry was a long time ago and I thought that IE9 also could upload using XHR (It should, but this is the Iframe option).
It does the following:
Add a file input to your page (can also be done in HTML)
Put that file selector in a form
add credentials to the form
Submit the form to the iframe and use its page as return value.
fileSelection = document.createElement("div");
//create the file input
fileSelection.browseSelect = document.createElement("input");
fileSelection.browseSelect.type = "file";
fileSelection.browseSelect.name = "file[]";
fileSelection.browseSelect.style.display = "block";
fileSelection.browseSelect.style.position = "absolute";
fileSelection.browseSelect.style.left = "50%";
fileSelection.browseSelect.style.top = "auto";
fileSelection.browseSelect.style.height = "36px";
fileSelection.browseSelect.style.width = "36px";
fileSelection.browseSelect.style.bottom = "0px";
fileSelection.browseSelect.style.margin = "0px 0px -1px 90px";
fileSelection.browseSelect.style.filter = "alpha(opacity=0)";
fileSelection.browseSelect.style.zIndex = 14;
//Put a form in it.
fileSelection.form = document.createElement("form");
fileSelection.form.method = "POST";
fileSelection.form.action = [url to server]; //put your own file upload handler here.
fileSelection.form.enctype = "multipart/form-data";
fileSelection.form.encoding = "multipart/form-data";
fileSelection.appendChild(fileSelection.form);
//Append the file input to the form.
fileSelection.form.appendChild(fileSelection.browseSelect);
document.body.appendChild(fileSelection);
function doUploadObjectUpload()
{
var tempFrame = document.createElement("iframe");
tempFrame.src = "";
tempFrame.allowTransparancy = "true";
tempFrame.style.display = "none";
tempFrame.frameBorder = 0;
tempFrame.style.backgroundColor = "transparent";
tempFrame.onload = followUpOnHTML4Upload.bind(this,tempFrame);
tempFrame.name = "tmpFrameUpload"
this.appendChild(tempFrame);
this.form.target = tempFrame.name;
this.form.name = "uploadForm";
this.form.acceptCharset = "UTF-8"
//This is an example of a hidden input, used to pass extra vars to the server. Add more if you need them.
var tempNodePath = document.createElement("input");
tempNodePath.type = "hidden";
tempNodePath.value = [dir]; //if you want specify a target path.
tempNodePath.name = "filePath";
this.form.insertBefore(tempNodePath, this.form.childNodes[0]);
this.form.submit();
}
function followUpOnHTML4Upload(frameId)
{
//Here you can check the response that came back from the page.
}
PHP for example will store the files in $_FILES
Related
im new to angular and i have to add a button to an app so when i click, it should start downloading a file already recorded.
i have this code
var _RecordStopCallback = function(blob){
if (!blob && blob.length==0){
$scope.isRecorded = false;
return;
}
$scope.recordObj.recordedData = blob;
const url = URL.createObjectURL(blob);
var el = $("#downloads").html("");
var hf = $("<a></a>");
hf.attr({
src:url,
href:url,
download:$scope.recordFilename
}).html($scope.recordFilename);
hf.appendTo(el);
$scope.isStoping = false;
$scope.recordStatus = false;
$scope.isRecorded = true;
$scope.recordStatusText = "Start";
$scope.streamError = "";
_changeStatusText();
$scope.$apply();
$scope.saveProcess();
and in the HTML file this:
<div ng-show="isRecorded" class="color-info"> Recorded File : <span id='downloads'></span>
<button ng-click="{{recordFilename}}" class="btn-circle btn-circle-default">
<i class="zmdi zmdi-download"></i></button>
this line:
<span id='downloads'></span>
displays the recoded filename and makes it as a link so when you click on it you can directly donwload it, but i dont know how to make the button do the same thing?
any help would be appreciated!
You may register a callback for the button getting clicked and there you can create the same link you showed in your question, style it as hidden, insert it into the DOM and call .click() on it.
Inserting into DOM is required as some browsers will not start the download otherwise.
There is an image element , how do I use this same img element without sending another request to the server. Its important to note, I don't want image1.jpg downloaded twice from the webserver. Any ideas?
function loadCarousels(carouselLoc, carouselId) {
$("li").find(carouselLoc).each(function (index) {
var img = this;
var outer = 0;
$(carouselId).find("ul").each(function (innerIndex) {
var liX = document.createElement("li");
$(this).append(liX);
var imgInner = document.createElement("img");
imgInner.src = img.src;
$(imgInner).appendTo(liX);
console.log($(this));
});
});
}
Is how I currently try but it doesn't work. it creates a separate image.
Browsers should be already pretty aggressive on caching images: Chrome often shows multiple requests, but if you check from the second on usually they're all satisfied using the cache.
In case you want to cache internally in your JS code, try to cache images by URL like the following:
// use this as JS cache
var images = {};
function loadCarousels(carouselLoc, carouselId) {
$("li").find(carouselLoc).each(function (index) {
var img = this;
var outer = 0;
// cache it
if(!images[img.src]){
images[img.src] = document.createElement("img");
// if the user disable the cache, this should prevent another request
images[img.src].src = img.src;
}
$(carouselId).find("ul").each(function (innerIndex) {
var liX = document.createElement("li");
$(this).append(liX);
// retrieve from the cache
var imgInner = images[img.src];
$(imgInner).appendTo(liX);
console.log($(this));
});
});
}
I need to load cross-domain JavaScript
files dynamically for bookmarklets in my site http://jsbookmarklets.com/
The solution should satisfy:
Fetch the path of current file
The domain of current web-page and JS file in execution are different
The solution should be cross-browser
Multiple scripts might be loaded at once asynchronously (that's why the related questions mentioned below are not a fit)
I want to get the file path of currently executing JavaScript code for dynamically loading few more resources (more CSS files and JS files like custom code and jQuery, jQuery UI and Ext JS libraries) which are stored in the same/relative folder as the JavaScript Bookmarklet.
The following approach does not fit my problem:
var scripts = document.getElementsByTagName("script");
var src = scripts[scripts.length-1].src;
alert("THIS IS: "+src);
Related questions which do not fit my problem:
Get the url of currently executing js file when dynamically loaded
Get script path
The current solution that I'm using, which works, but is very lengthy:
var fnFullFilePathToFileParentPath = function(JSFullFilePath){
var JSFileParentPath = '';
if(JSFullFilePath) {
JSFileParentPath = JSFullFilePath.substring(0,JSFullFilePath.lastIndexOf('/')+1);
} else {
JSFileParentPath = null;
}
return JSFileParentPath;
};
var fnExceptionToFullFilePath = function(e){
var JSFullFilePath = '';
if(e.fileName) { // firefox
JSFullFilePath = e.fileName;
} else if (e.stacktrace) { // opera
var tempStackTrace = e.stacktrace;
tempStackTrace = tempStackTrace.substr(tempStackTrace.indexOf('http'));
tempStackTrace = tempStackTrace.substr(0,tempStackTrace.indexOf('Dummy Exception'));
tempStackTrace = tempStackTrace.substr(0,tempStackTrace.lastIndexOf(':'));
JSFullFilePath = tempStackTrace;
} else if (e.stack) { // firefox, opera, chrome
(function(){
var str = e.stack;
var tempStr = str;
var strProtocolSeparator = '://';
var idxProtocolSeparator = tempStr.indexOf(strProtocolSeparator)+strProtocolSeparator.length;
var tempStr = tempStr.substr(idxProtocolSeparator);
if(tempStr.charAt(0)=='/') {
tempStr = tempStr.substr(1);
idxProtocolSeparator++;
}
var idxHostSeparator = tempStr.indexOf('/');
tempStr = tempStr.substr(tempStr.indexOf('/'));
var idxFileNameEndSeparator = tempStr.indexOf(':');
var finalStr = (str.substr(0,idxProtocolSeparator + idxHostSeparator + idxFileNameEndSeparator));
finalStr = finalStr.substr(finalStr.indexOf('http'));
JSFullFilePath = finalStr;
}());
} else { // internet explorer
JSFullFilePath = null;
}
return JSFullFilePath;
};
var fnExceptionToFileParentPath = function(e){
return fnFullFilePathToFileParentPath(fnExceptionToFullFilePath(e));
};
var fnGetJSFileParentPath = function() {
try {
throw new Error('Dummy Exception');
} catch (e) {
return fnExceptionToFileParentPath(e);
}
};
var JSFileParentPath = fnGetJSFileParentPath();
alert('File parent path: ' + JSFileParentPath);
var s = document.createElement('script');
s.setAttribute('src', 'code.js');
document.body.appendChild(s);
Can you not simply do this?
var myScriptDir = 'http://somesite.tld/path-to-stuff/';
var s = document.createElement('script');
s.setAttribute('src', myScriptDir + 'code.js');
document.body.appendChild(s);
// code inside http://somesite.tld/path-to-stuff/code.js will use myScriptDir to load futher resources from the same directory.
If you don't want to have code inside the script to be responsible for loading further resources you can use the onload attribute of the script tag, like s.onload=function(){...}. For cross browser compatibility you might first load jQuery and then use the getScript function. Relevant links are http://www.learningjquery.com/2009/04/better-stronger-safer-jquerify-bookmarklet and http://api.jquery.com/jQuery.getScript/
Some of the comments have already mentioned this, but I'll try to elaborate a bit more.
The simplest, most cross-browser, cross-domain way of figuring out the path of the current script is to hard-code the script's path into the script itself.
In general, you may be loading third-party script files, so this would not be possible. But in your case, all the script files are under your control. You're already adding code to load resources (CSS, JS, etc.), you might as well include the script path as well.
Im using the below code of ajax
// JavaScript Document
function createTeam() {
var name=document.getElementById("name").value;
if(name==null || name==""){
var div3 = document.getElementById("errorMessage");
var text = "Enter Team";
div3.style.display = "block";
div3.style.color = "red";
div3.style.fontSize = "65%";
div3.innerHTML = text;
}else{
xmlhttp=new XMLHttpRequest();
xmlhttp.open("POST","/TeamServlet?name="+name+"&task=create",true);
xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlhttp.send();
xmlhttp.onreadystatechange= readResponse;
}
function readResponse(){
if (xmlhttp.readyState == 4)
{
response = xmlhttp.responseText;
$('#button').hide("slow");
if(response == "false"){
var div2 = document.getElementById("errorMessage");
var text = "Unable to create team.";
div2.style.display = "block";
div2.style.color = "red";
div2.style.fontSize = "65%";
div2.innerHTML = text;
}
if(response == "true"){
var div = document.getElementById("errorMessage");
var text1 = "Team created.";
div.style.display = "block";
div.style.color = "red";
div.style.fontSize = "65%";
div.innerHTML = text1;
}
}
}
}
But what happens is when I use this ajax the URL doesnt appear on the address bar of the browser.how can I achieve that? The only url that comes is that after I submit my login form, and that is this http://localhost:8080/LoginServlet?task=login
but after this,even if I navigate to other jsps/servlets none of those url come.How can I fix this ajax code?
This is the basic purpose of AJAX: do Asynchronous request, on the "background". All request done with AJAX doesn't trigger the loading icon of the browser nor change the current URL.
If you want to do something like that, you should have a look to the HTML5 History API. Because it's a huge subject, I can't show you "one" answer but I give you some resource to get in:
explanation & demo http://html5doctor.com/history-api/
explanation & demo http://dev.opera.com/articles/view/introducing-the-html5-history-api/
explanation & demo http://diveintohtml5.info/history.html
explanation & demo http://robertnyman.com/2011/08/03/html5-history-api-and-improving-end-user-experience/
demo http://html5demos.com/history
The problem you'll find is that this API is not supported in all browsers, so you'll need to use a polyfill to make your code cross-browser compatible. Here is a list of cross-browser polyfill you can use:
History.js https://github.com/browserstate/history.js
PJAX (pushState + ajax = pjax) http://pjax.heroku.com/
hashchange jQuery event http://benalman.com/projects/jquery-hashchange-plugin/
HistoryManager Mootools Plugin http://mootools.net/forge/p/historymanager/
SWFAddress http://www.asual.com/swfaddress/ & jQuery Address http://www.asual.com/jquery/address/
jQuery History Plugin https://balupton.com/projects/jquery-history
jQuery Ajaxy http://balupton.com/projects/jquery-ajaxy
Hasher https://github.com/millermedeiros/hasher/
sHistory https://github.com/tatsh/sHistory
This list is maintained by the Modernizr team, the lasted version is available at https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
Why would you want to display url of an ajax request in address bar? Ajax requests are to be performed if you want to make calls to the server without navigating away from current page. If you want to change url in address bar then you will have to redirect the user to the said url, you don't need Ajax for that.
First,I created a hidden frame like this:
var oHiddenFrame = null;
if(oHiddenFrame == null){
oHiddenFrame = document.createElement("iframe");
oHiddenFrame.name = "hiddenFrame";
oHiddenFrame.id = "hiddenFrame";
oHiddenFrame.style.height = "0px";
oHiddenFrame.style.width = "0px";
oHiddenFrame.style.position = "absolute";
oHiddenFrame.style.visbility = "hidden";
document.body.appendChild(oHiddenFrame);
}
Then,I add a event to the button like this:
var fnLocation = function(){
frames["hiddenFrame"].location.href = "http://meckmeck.cn";
}
var oButton = document.getElementById("mb_submit");
oButton.addEventListener("click", fnLocation, false);
When I click the button,I got a error:
frames.hiddenFrame is undefined
There's no such thing as document.frames. The name-indexed frame array is window.frames (aka just frames).
0-iframes are so old-school, and these days mostly associated with malware-installing exploits (especially on Chinese pages). How about using an XMLHttpRequest instead?