How to append file name in the row it belongs to? - javascript

I have an application you can access [here][1]. When you open up the application, you will see an "Add" button on top, click this twice and you will see 2 table rows appear with each row containing it's own file input.
The problem is: suppose you try to upload a file (a small file for quick upload) in the second row's file input. After you have uploaded a file, the name of the file which has been uploaded is appended into both the top row and the second row. This is incorrect, it should only append the file name in the second row only because you used the second row's file input to upload that file.
How can I append the file name within the same row as the file input used to upload the file?
Below is the code for the form which contains the file input:
function insertQuestion(form) {
var $tbody = $('#qandatbl > tbody');
var $tr = $("<tr class='optionAndAnswer' align='center'></tr>");
var $image = $("<td class='image'></td>");
var $fileImage = $("<form action='imageupload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='return imageClickHandler(this);' class='imageuploadform' >" +
"Image File: <input name='fileImage' type='file' class='fileImage' /></label><br/><label class='imagelbl'>" +
"<input type='submit' name='submitImageBtn' class='sbtnimage' value='Upload' /></label>" +
"<label><input type='button' name='imageClear' class='imageClear' value='Clear File'/></label>" +
"</p><ul class='listImage' align='left'></ul>" +
"<iframe class='upload_target' name='upload_target' src='#' style='width:0;height:0;border:0px;solid;#fff;'></iframe></form>");
$image.append($fileImage);
$tr.append($image);
$tbody.append($tr);
};
Below is the handler the form directs to when clicked:
function imageClickHandler(imageuploadform){
if(imageValidation(imageuploadform)){
return startImageUpload(imageuploadform);
}
return false;
}
Below is where the file uploading starts and stops:
function startImageUpload(imageuploadform){
$(imageuploadform).find('.imagef1_upload_process').css('visibility','visible');
return true;
}
function htmlEncode(value) { return $('<div/>').text(value).html(); }
function stopImageUpload(success, imagefilename){
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!</span><br/><br/>';
$('.listImage').append('<div>' + htmlEncode(imagefilename) + '<button type="button" class="deletefileimage">Delete</button><br/><hr/></div>');
}
else {
result = '<span class="emsg">There was an error during file upload!</span><br/><br/>';
}
$(".deletefileimage").on("click", function(event) {
$(this).parent().remove();
});
return true;
}
CORRECT SOLUTION:
function imageClickHandler(imageuploadform){
if(imageValidation(imageuploadform)){
window.lastUploadImageIndex = $('.imageuploadform').index(imageuploadform);
return startImageUpload(imageuploadform);
}
return false;
}
$('.listImage').eq(window.lastUploadImageIndex).append('<div>' + htmlEncode(imagefilename) + '<button type="button" class="deletefileimage">Delete</button><br/><hr/></div>');

Your basic problem is:
$('.listImage')
That is a selector for "any element with the class 'listImage'". Since you've clicked add twice, there are two elements with this class, and your selector matches (and appends) to both of them.
Use a more specific selector for your append and you should be all set.
Unfortunately, I can't recommend a specific way of doing that, because I don't know how your stopImageUpload function is being called. If it's being triggered by a jQuery event handler, then you can refer to "this" inside your function to get the element that triggered the event, and you should be able to use that to figure out which .listImage to append to.
If it's not triggered by an event handler, then I would imagine that whatever function is calling it knows which file input triggered things.
Once you know which element you actually want to append to, you can target it using jQuery's eq method/selector. Here are a couple examples:
$('.listImage:eq(0)') // selects the first listImage only
$('.listImage').eq(2) // selects the third listImage only

Related

add more button dont work in wordpress dashboard

im working on custom post in wordpress, in this custom post i wanna add many photos using wp_attachment the problem im having here is that when i click addmore nothing happen, its like if wordpress is ignoring my jquery file
my code
<div class="col-sm-9">
<input type="file" name="aduploadfiles[]" id="uploadfiles2" size="35" class="form-control" />
<input type="button" id="add_more2" class="upload" value="add more photo"/>
</div>
and this is the javascript im using
var abc = 0; //Declaring and defining global increement variable
$(document).ready(function() {
//To add new input file field dynamically, on click of "Add More Files" button below function will be executed
$('#add_more2').click(function() {
$(this).before($("<div/>", {id: 'uploadfiles2'}).fadeIn('slow').append(
$("<input/>", {name: 'aduploadfiles[]', type: 'file', id: 'aduploadfiles',size:'35', class:'form-control'})
));
});
//following function will executes on change event of file input to select different file
$('body').on('change', '#file', function(){
if (this.files && this.files[0]) {
abc += 1; //increementing global variable by 1
var z = abc - 1;
var x = $(this).parent().find('#previewimg' + z).remove();
$(this).before("<div id='abcd"+ abc +"' class='abcd'><img id='previewimg" + abc + "' src=''/></div>");
var reader = new FileReader();
reader.onload = imageIsLoaded;
reader.readAsDataURL(this.files[0]);
$(this).hide();
$("#abcd"+ abc).append($("<img/>", {id: 'img', src: 'x.png', alt: 'delete'}).click(function() {
$(this).parent().parent().remove();
}));
}
});
//To preview image
function imageIsLoaded(e) {
$('#previewimg' + abc).attr('src', e.target.result);
};
$('#upload').click(function(e) {
var name = $(":file").val();
if (!name)
{
alert("First Image Must Be Selected");
e.preventDefault();
}
});
});
this works fine when i try it in a wordpress pages but in dashboard itdoesn't want to work even my javascript is loaded
There are several issues:
1. $ is not available. Use jQuery
In WordPress, jQuery runs in compatibility mode, i.e. the $ shortcut is not available. You can solve this by capturing jQuery as function argument in the ready method, like this:
jQuery(document).ready(function($) {
The rest of the code in the ready callback can then continue to use $.
2. Wrong selector for file upload input element
You mentioned the wrong id in the jQuery selector: your file upload element has id uploadfiles2, not file. So change:
$('body').on('change', '#file', function(){
To:
$('body').on('change', '[name="aduploadfiles[]"]', function(){
3. Duplicate id values
Each time when you add a new button, you create a div with an id of uploadfiles2: but that id already exists. In HTML id values must be unique, otherwise unexpected things happen.
All the elements you create dynamically should get a dynamically created (distinct) id value (or no id at all).

Unable to get element id dynamically in javascript

I have a list of students that I am looping through and adding to my page. Each student has a unique ID, and when getStudentInfo is invoked, it does something with the id. The problem is that whichever student I click, I get back the same id, belonging to student1.
Where am I going wrong?
foreach ($students as $student) {
echo '<tr>';
echo '<td>
'.$student[student_permalink].'
<input type="submit"
value="info"
onclick="getStudentInfo()"
class="student-name-btn"
id="'.$student[student_permalink].'"
/>
</td>';
}
js:
function getStudentInfo() {
var studentLink = $('.student-name-btn').attr('id');
console.log(studentLink);
}
Your code is selecting all the buttons on the page with that class and than reads the id of the first one in the list. You are not limiting it to the one that was clicked.
What most people would do is add events with jQuery and not inline.
//needs to be loaded after the element or document ready
$(".student-name-btn").on("click", function() {
console.log(this.id);
});
For yours to work, you would need to pass a reference to the button that was clicked.
onclick="getStudentInfo(this)"
and than change it to use the node passed in
function getStudentInfo(btn) {
var studentLink = $(btn).attr('id');
console.log(studentLink);
}
You can pass the reference to the element being clicked on the onclick event
foreach ($students as $student) {
echo '<tr>';
echo '<td>
'.$student[student_permalink].'
<input type="submit"
value="info"
onclick="getStudentInfo(this)" // << added this which refers to the input
class="student-name-btn"
id="'.$student[student_permalink].'"
/>
</td>';
}
And then use that to fetch the id in the js
function getStudentInfo(el) {
var studentLink = $(el).attr('id');
console.log(studentLink);
}
Don't use inline events - there's no need to clutter up the HTML with that. You have a common class on your element, so just make a jQuery handler and use an instance of this
$('.student-name-btn').click(function() {
var id = this.id;
});
Like #epascarello alluded to, you are not selecting the button that was actually clicked. What you should do is have your event handling in your JS, not in the HTML so you can see better how it works and use the this keyword within the closure to reference the clicked button.
$(document).on('click', '.student-name-btn', function(evt) {
// Prevent default if trying to do your own logic
evt.preventDefault();
// Need to use the "this" keyword to reference the clicked element
var studentId = $(this).attr('id');
console.log(studentId);
});
You can do this without inline JavaScript and since you're using jQuery drop the onClick() and the form element:
echo '<tr>';
echo '<td id="'.$student['student_permalink'].'" >
'.$student['student_permalink'].'
</td>';
You also need to quote the identifier in the array variable, 'student_permalink'.
The jQuery will be this:
$('td').click(function() {
var studentLink = this.id;
console.log(studentLink);
});

List selected files from file input

I want to list selected file from file input.
<div class="fileUpload myButton">
<span>Upload</span>
<input type="file" name="imageURL[]" id="imageURL" multiple="" class="file" />
</div>
<div id="file-list">
</div>
I have this code
(function () {
var filesUpload = document.getElementById("imageURL"),z
fileList = document.getElementById("file-list");
function uploadFile (file) {
var li = document.createElement("li"),
div = document.createElement("div"),
reader,
xhr,
fileInfo;
li.appendChild(div);
// Present file info and append it to the list of files
fileInfo = "<div class=\"neutral\">File: <strong>" + file.name + "</strong> with the size <strong>" + parseInt(file.size / 1024, 10) + "</strong> kb is in queue.</div>";
div.innerHTML = fileInfo;
fileList.appendChild(div);
}
function traverseFiles (files) {
if (typeof files !== "undefined") {
for (var i=0, l=files.length; i<l; i++) {
uploadFile(files[i]);
}
}
else {
fileList.innerHTML = "<div class=\"neutral\">Your browser does not support Multiple File Upload, but you can still upload your file. We recommend you to upload to a more modern browser, like Google Chrome for example.<div>";
}
}
filesUpload.addEventListener("change", function () {
traverseFiles(this.files);
}, false);
})();
But the problem is when the user selects another files it is added to the list but the old files is not uploaded when the form is submitted.
Simplified: when the user selects file1.pdf and file2.pdf
The list shows file1.pdf and file2.pdf
When he selects again another files file3.pdf and file4.pdf
the list shows file1.pdf , file2.pdf, file3.pdf and file4.pdf
But when he submit the form only file3.pdf and file4.pdf is uploaded
My question is how to remove the files which will not be uploaded from the list.
OR a way to upload all the files in the list.
Thanks in advance.
What is happening is that the input is emptied when selecting more files, hence not uploading the previously displayed files.
SOLUTION 1: To combat this you could create a new input in the change event handler, although this could get quite messy.
You would have to get all files from all the inputs on upload. You have not shown your actual upload code, so I cannot give an example in context:
filesUpload.on("change", function () {
traverseFiles(this.files); //Add initial files to list
create_new_input();
}
function create_new_input() {
var new_input = $('<input type="file" />'); //create file selector
new_input.on("change", function() {traverseFiles($(this).get(0).files);}); //
$('body').append(new_input); //Add this input to your page
}, false);
You will have to add all files that you receive in the traverseFilesto the xhr. This example uses jQuery, and I would recommend that you use it all the time!
SOLUTION 2:
Other wise you can empty the file list box on input changed:
filesUpload.addEventListener("change", function () {
document.getElementById('file-list').innerHTML = "";
traverseFiles(this.files);
}, false);
Good luck!
Your Problem is that you manipulate the value of input multiple times. The second time someone selects a file using the html file input, the originally selected files are "overwritten" from the inputs value attribute.
You could hook into your forms submit and add the files you already stored in your html.
Another way to do it would be to work with several file input elements.
So every time someone selects files and you add them to your html, hide the old file input and add a new one like this ...
adjust your html code like this:
<div class="fileUpload myButton">
<span>Upload</span>
<input type="file" class="imageUrlInput" name="imageURL[0]" id="imageURL" multiple="" class="file" />
</div>
<div id="file-list">
</div>
Adjust your Javascript like this:
function uploadFile (file) {
var li = document.createElement("li"),
div = document.createElement("div"),
reader,
xhr,
fileInfo;
li.appendChild(div);
// now here we receive the HTML input element for the files.
var currentInput = $('#imageURL');
var imageUrlInputsCount = $('.imageUrlInput').length;
// now we change the 'id' attribute of said element because id's should be unique right?
currentInput.attr('id','imageUrl_'+imageUrlInputsCount);
// now, we append a new input element with an incremented array key defined by the length of already existing input elements
currentInput.append('<input type="file" name="imageURL['+imageUrlInputsCount+']" id="imageURL" multiple="" class="file" />');
// and finally we hide the old element
currentInput.hide();
// Present file info and append it to the list of files
fileInfo = "<div class=\"neutral\">File: <strong>" + file.name + "</strong> with the size <strong>" + parseInt(file.size / 1024, 10) + "</strong> kb is in queue.</div>";
div.innerHTML = fileInfo;
fileList.appendChild(div);
}
Now make sure that in your retrieving server code (php/jsp/asp,node.js or whatever you are using) you change checking for imageURL, you iterate over imageURL since now you have several sets of imageURLs. i.e. your imageURL parameter could look like this:
imageURL = array (
0 => array(
'foo1.pdf',
'foo2.pdf',
'foo3.pdf',
),
1 => array(
'foo4.pdf',
'foo5.pdf',
'foo6.pdf',
)
3 => array(
'foo7.pdf',
'foo8.pdf',
'foo9.pdf',
)
)

How can I retrieve input values from elements added after page load?

I'm working with Zend Framework 1.12 and I've need to be able to dynamically add and delete fields from a sub-form, in this case we're associating hyperlinks to a parent "promotion".
I haven't found a way to accomplish dynamically adding and removing elements via Zend, and the rare tutorial I've found that claimed to do this are half a decade old and aren't working when I attempt them.
So what I am doing is storing the links I need to work with in a Zend Hidden input field and then dealing with the JSON data after I submit. Not very efficient, but it's the only thing I've gotten to work so far.
Below is the section of the code I'm working with:
Assume a form like:
<form action="/promos/edit/promo_id/15" method="POST" id="form_edit">
<!-- input is Zend_Form_Element_Hidden -->
<input type="hidden" id="link_array" value="{ contains the JSON string }"/>
<button id="add_link">Add Link</button>
</form>
The purpose is that every time the Add Link button is pressed, the form adds fields to allow the user to input new hyperlinks that will be associated with the specific items.
Here's the function:
// add links
$('#add_link').click(
function(e) {
e.preventDefault();
link = '<div class="p_link new_link">' +
'<div class="element_wrap">' +
'<label for="link_name" class="form_label optional">Text: </label>' +
'<input type="text" id="new_link_name" name="link_name"/>' +
'</div>' +
'<div class="element_wrap">' +
'<label for="link_http" class="form_label optional">http://</label>' +
'<input type="text" id="new_link_http" name="link_http"/>' +
'</div>' +
'<div class="element_wrap">' +
'<button class="submit delete_link">Delete</button>' +
'</div>' +
'</div>';
$('#add_link').prev().after(link);
}
);
Now, what I need to do is on submit, for every new_link class element, to take the links name and http reference and place it in a json object. Here's the code as I have it so far (I know I don't have both input fields represented at this point):
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = document.getElementsByClassName('new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).children('#new_link_name').text();
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
My problem is that: var new_links = document.getElementsByClassName('new_link'); will collect all the newly added new_link elements, but it does not pull in any value that has been input into the text fields.
I need to know how I can apparently bind any input I make to the input field's value attribute, because right now anything I type into these new elements are tossed out and the field appears empty when it's anything but.
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = $('.new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).find('input').val(); // you need input values! This line //is changed...
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
JSFIDDLE: http://jsfiddle.net/DZuLJ/
EDit: You can't have multiple IDS (make class for each input, and target class, if you want link names and http's)

chrome and IE not containing values after creating clone of file type

i am using the following code in order to create ajax upload script .my current task is to create a form on the fly using jquery so i do this by following code
<script src="http://code.jquery.com/jquery-latest.js"></script>
<input id="files" name="file" type="file" value=""/>
<script>
$(document).ready(function () {
$('#files').live('change', function () {
var formId = 'jUploadForm';
var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>');
var oldElement = $('#files');
var newElement = $(oldElement).clone();
$(oldElement).attr('id', 'files');
$(oldElement).before(newElement);
alert('fffffff');
//alert(projectid);
//return false;
$(oldElement).appendTo(form);
});
});
</script>
The error in aboce code is that after appending newElement using before the file value which i have select will be gonemeans whatever i select from browse button that will be present in the cloned file type but will be removed from the original file type i have.
above problem is only occuring in chrome and IE it is working fine in mozila
Please help
You can't put oldElement before newElement because you haven't added newElement to the DOM yet.
Similarly, you can't append oldElement to the form because form hasn't been added to the DOM, either.
Both newElement and form have to be added to the document after you create them before you can do any manipulation relative to them.
Finally, you're not doing anything when you run $(oldElement).attr('id', 'files'); because the ID of oldElement already is files.

Categories

Resources