I'm going to develop a firefox extension which adds a button beside the file input fields (the <input type="file"> tag) when a file is selected.
The file overlay.js, which contains the extension's logic, manages the "file choose" event through this method:
var xpitest = {
...
onFileChosen: function(e) {
var fileInput = e.explicitOriginalTarget;
if(fileInput.type=="file"){
var parentDiv = fileInput.parentNode;
var newButton = top.window.content.document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("id", "Firefox.Now_button_id");
newButton.setAttribute("value", "my button");
newButton.setAttribute("name", "Firefox.Now_button_name");
parentDiv.insertBefore(newButton, fileInput);
}
}
...
}
window.addEventListener("change", function(e) {xpitest.onFileChosen(e)},false);
My problem is that, everytime I choose a file, a new button is being added, see this picture:
http://img11.imageshack.us/img11/5844/sshotn.png
If I select the same file more than once, no new button appears (this is correct).
As we can see, on the first file input, only one file has been selected.
On the second one I've chosen two different files, in effect two buttons have been created...
On the third, I've chosen three different files.
The correct behavior should be this:
when a file is chosen, create my_button beside the input field
if my_button exists, delete it and create another one (I need this, beacuse I should connect it to a custom event which will do something with the file name)
My question is: how can I correctly delete the button? Note that the my_button html code does not appear on page source!
Thanks
Pardon me if I'm thinking too simply, but couldn't you just do this?
var button = document.getElementById('Firefox.Now_button_id')
button.parentNode.removeChild(button)
Is this what you were looking for? Feel free to correct me if I misunderstood you.
Solved. I set an ID for each with the following method:
onPageLoad: function(e){
var inputNodes = top.window.content.document.getElementsByTagName("input");
for(var i=0; i<inputNodes.length; i++){
if(inputNodes[i].type=="file")
inputNodes[i].setAttribute("id",i.toString());
}
}
I call this method only on page load:
var appcontent = document.getElementById("appcontent"); // browser
if(appcontent)
appcontent.addEventListener("DOMContentLoaded", xpitest.onPageLoad, true);
Then I've modified the onFileChosen method in this way:
onFileChosen: function(e) {
var fileInput = e.explicitOriginalTarget;
if(fileInput.type=="file"){
var parentDiv = fileInput.parentNode;
var buttonId = fileInput.id + "Firefox.Now_button_id";
var oldButton = top.window.content.document.getElementById(buttonId);
if(oldButton!=null){
parentDiv.removeChild(oldButton);
this.count--;
}
var newButton = top.window.content.document.createElement("input");
newButton.setAttribute("type", "button");
newButton.setAttribute("id", buttonId);
newButton.setAttribute("value", "my button");
newButton.setAttribute("name", "Firefox.Now_button_name");
parentDiv.insertBefore(newButton, fileInput);
this.count++;
}
}
Related
I am currently creating a program which utilizes localStorage to create a site with a wishlist like functionality. However when I go to generate the html page that should create the wishlist with the photo of the item, the name and a button to remove said item from the list. But when I go to assign the onClick functionality to the button, the function fires on page load rather then on click. I have four main java script functions, one to add to the localstorage, one to remove from local storage, a helper function for removing and the one that will generate the wishlist page (where the problem is).
function genWishListPage(){
for (var i = 0; i < localStorage.length; i++) {
var item = getWishlist(i);
var name = document.createElement("p");
var removeButton = document.createElement("button");
var image = document.createElement("img")
image.src = item.image;
removeButton.innerText = "Remove from wishlist";
removeButton.onClick = RemoveFromWishList(item.name);
removeButton.setAttribute("ID","remove");
name.innerText = item.name;
document.body.appendChild(image);
document.body.appendChild(name);
document.body.appendChild(removeButton);
document.body.appendChild(document.createElement("BR"));
//removeButton.setAttribute("onclick", RemoveFromWishList(item.name));
//removeButton.addEventListener('click', RemoveFromWishList(item.name));
//document.getElementById("remove").addEventListener("click",RemoveFromWishList(item.name));
}
}
The commented parts are ways I have already tried and gotten the same bug.
Any help or advice is appreciated.
When you write
removeButton.onClick = RemoveFromWishList(item.name); you are assigning the return value of the function call to the onClick event. Instead you can write
removeButton.onClick = function() { RemoveFromWishList(item.name);}
You should assign a function to the onClick event listener.
I have tried so many examples but none of them works
t
(function() {
var textFile = null,
makeTextFile = function(text) {
var data = new Blob([text], {
type: 'text/plain'
});
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
return textFile;
};
var create = document.getElementById('create'),
textbox = document.getElementById('textbox');
create.addEventListener('click', function() {
var link = document.getElementById('downloadlink');
link.href = makeTextFile(textbox.value);
link.style.display = 'block';
}, false);
})();
<textarea id="textbox">Type something here</textarea>
<button id="create">Create file</button>
<a download="info.txt" id="downloadlink" style="display: none">Download</a>
here is a code which is working good but i need to download automatically without using link
is it possible?
You could use the following script to create and save automatically a file from the browser to your operating system. This code works only on latest version of Chrome.
What the script does?
It creates a temporary URL containing the specified File object or Blob object - Programmatically click the link just created so the file will be download by the browser.
Immediately after remove the link from the page.
var saveDataToFile = function (data, fileName, properties) {
window.URL = window.URL || window.webkitURL;
var file = new File(data, fileName, properties),
link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = fileName;
document.body.appendChild(link);
link.click();
var timer = setTimeout(function () {
window.URL.revokeObjectURL(link.href);
document.body.removeChild(link);
clearTimeout(timer);
}, 100);
};
If you deconstruct this problem, there's a few key points:
Initially, when the user hasn't typed text into the textarea, the button should not be visible. (I may be wrong here though)
When the user starts typing, the button has to appear.
Whatever is inside the textarea after that, has to be downloadable per click on the button.
So, it's a matter of two event listeners.
The first one is "focus": when the textarea received focus, its value is an empty string, and the button appears. The user hasn't yet started typing, but there's actually no need to force them to.
The second one is "change": per every change in the field, we need to update the value of href attribute of the link, so that when the user clicks that element, file download happens, and the content is precisely what's inside the textarea. Good thing, a function passed to "change" event listener is executed with the first argument instance of Event, which means you can do event.target.value to get the new value per every change. It means, the whole text from within textarea.
Summing up, it's
<textarea id="textbox" placeholder="Type something here"></textarea>
<a download="info.txt" id="create" href="#" style="display: none;">Create file</a>
and
(function() {
var textFile = null,
makeTextFile = function(text) {
var data = new Blob([text], {
type: 'text/plain'
});
// If we are replacing a previously generated file we need to
// manually revoke the object URL to avoid memory leaks.
if (textFile !== null) {
window.URL.revokeObjectURL(textFile);
}
textFile = window.URL.createObjectURL(data);
return textFile;
};
var create = document.getElementById('create');
var textbox = document.getElementById('textbox');
textbox.addEventListener('focus', function (event) {
create.style.display = 'block';
create.href = makeTextFile(''); // initially, the text is empty.
});
textbox.addEventListener('change', function (event) {
create.href = makeTextFile(event.target.value); // per every change, update value of href attribute of #create
});
})();
Take note that only a element can have href assigned with Blob value. Using a button element would be a little bit more complicated, so it might be easier to just make the a element look like a button.
See the Codepen to make sure it works as you expect, or feel free to edit it otherwise.
first, the prototype:
function Notification (title, message, id) {
var $title = this.title = title;
var $message = this.message = message;
var $id = this.id = title;
/* ---------------creating HTML prototype */
var $mainDiv = $("<div></div>").appendTo($("#wrapper"));
$mainDiv.attr('id', $id);
$mainDiv.addClass('main-div');
var $dismissButton = $("<button>X</button>").appendTo($mainDiv);
$dismissButton.attr('id', 'dismissButton');
var $pTitle = $("<h2></h2>").appendTo($mainDiv);
$pTitle.attr('id', 'title');
$pTitle.text($title);
var $para = $("<p></p>").appendTo($mainDiv);
$para.attr('id', 'message');
$para.text($message);
var $ul = $("<ul></ul>").appendTo($mainDiv);
var $li1 = $("<li></li>").appendTo($ul);
$li1.attr('id', 'okButton');
var $button = $("<button>Ok</button>").appendTo($li1);
$button.addClass('buttons');
/* ---------------Dismissing notifications */
$("#dismissButton").click(function() {
document.getElementById($id).remove();
});
};
So, the prototype is made using new Notification(*arguments here*) and there we get a box with a notification widget. so far so good.
when i press the X button (id dismissbutton) it should remove the box, and it does.
However. if i use the new notification several times i get several boxes (with different ids for the $mainDiv) with their dismiss buttons not working. the upmost widget box's dismiss button is the only one that works, and it deleted all the other boxes as well.
I need to seperate them and have the dismiss button working for each box seperately.
thanks in advance :)
The problem here is that you are creating multiple elements with the same ID (which is invalid HTML by the way).
Every time your run
var $dismissButton = $("<button>X</button>").appendTo($mainDiv);
$dismissButton.attr('id', 'dismissButton')
A new "dismiss button" is being created, which has the same ID (dismissButton) with the previous "dismiss buttons" (if any).
The other thing is that every time you run
$("#dismissButton").click(function() {
document.getElementById($id).remove();
});
You instruct only the first "dismiss button" to remove the element identified by the ID $id when clicked.
In my opinion the best way to fix this is by using references to the elements themselves and not IDs.
So I would make the creation of the dismiss button like this;
var $dismissButton = $("<button>X</button>").appendTo($mainDiv);
And determine its click callback like this
$dismissButton.on('click', function () {
$mainDiv.remove();
});
This should work fine for you.
Last, but not least I would avoid giving the same ID to any elements, since it produces invalid HTML code. You are doing so in the following lines
$dismissButton.attr('id', 'dismissButton');
$pTitle.attr('id', 'title');
$para.attr('id', 'message');
$li1.attr('id', 'okButton');
thanks for the upcoming assistance, I am working on a uploader and trying to add a javascript delete link to each extra input field. I have one that adds a child.
here is a codepen: http://codepen.io/anon/pen/NPPmYP
What I am wanting to do is during creation of the extra input fields, Here is my code if anyone is able to help.
I also tried these methods and they didnt work
<script language="javascript">
<!--
function _add_more() {
files.appendChild(document.createElement("br"));
var del = document.createTextNode("Delete ");
document.getElementById("files").appendChild(del);
var extra = document.createElement('input');
extra.type="file";
extra.id="images[]";
extra.name="images[]";
extra.size="50";
extra.accept="image/jpeg";
document.getElementById("files").appendChild(extra);
}
</script>
I tried changing what I have for that line into
var del = document.createTextNode('delete ');
But it just showed it as text instead of making it a clickable link, I am really unsure on how to create the function to remove a child without effecting any others. Thank you for the upcoming support
You'll need to attach an event handler to the click of the delete link.
Something like this. (Updated as per comment)
<script language="javascript">
function _add_more() {
var del = document.createElement("a");
del.appendChild(document.createTextNode("Delete"));
del.href="#"; // Apply link styling
var extra = document.createElement('input');
extra.type="file";
extra.id="images[]";
extra.name="images[]";
extra.size="50";
extra.accept="image/jpeg";
var additionalFile = document.createElement('span');
additionalFile.appendChild(document.createElement("br"));
additionalFile.appendChild(del);
additionalFile.appendChild(extra);
document.getElementById("files").appendChild(additionalFile);
del.addEventListener('click', function(event){
additionalFile.parentElement.removeChild(additionalFile);
event.preventDefault();
});
}
</script>
I'm using CKFinder in combination with CKEditor, but also as standalone file input image popup window. So when someone clicks the "upload"-button, a new popup window appears in which someone could select an image / file / Flash-file to upload.
For the field "avatar" I need to only select image files. It shouldn't be possible to select another filetype. How can I get this working? In the documentation I can't find very helpful information.
In CKEditor it's possible to only select an image or a file from within the CKFinder-popup, but it looks like the same option has been forgotten in the standalone version of CKFinder.
I need to achieve "ckfinder.html?type=Image", but I don't want to modify ckfinder.js because that will affect also other file popup dialogs in which someone should be able to select even images as files.
I'm including CKFinder like in the popup sample:
var finder = new CKFinder();
finder.basePath = '../'; // The path for the installation of CKFinder (default = "/ckfinder/").
finder.selectActionFunction = SetFileField;
finder.popup();
Thanks in advance for your help!
you should try it,
*
LoadImage
is id of button select file,
picUrl
is id of text link
$('#LoadImage').click(function () {
var finder = new CKFinder();
finder.selectActionFunction = function (fileUrl) {
fileUrl = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
$('#picUrl').val = (fileUrl);
}
selectFileWithCKFinder('picUrl');
})
function selectFileWithCKFinder(elementId) {
CKFinder.popup({
chooseFiles: true,
width: 800,
height: 600,
onInit: function (finder) {
finder.on('files:choose', function (evt) {
var file = evt.data.files.first();
var output = document.getElementById(elementId);
output.value = file.getUrl();
});
finder.on('file:choose:resizedImage', function (evt) {
var output = document.getElementById(elementId);
output.value = evt.data.resizedUrl;
});
}
});
}