I have a piece of code below which works fine when it comes to adding text from a modal window into a textarea:
<script type="text/javascript">
var plusbutton_clicked;
function insertQuestion(form) {
var $tbody = $('#qandatbl > tbody');
var $tr = $("<tr class='optionAndAnswer' align='center'></tr>");
var $plusrow = $("<td class='plusrow'></td>");
var $question = $("<td class='question'></td>");
$('.questionTextArea').each( function() {
var $this = $(this);
var $questionText = $("<textarea class='textAreaQuestion'></textarea>").attr('name',$this.attr('name')+"[]")
.attr('value',$this.val());
$question.append($questionText);
});
$('.plusimage').each( function() {
var $this = $(this);
var $plusimagerow = $("<a onclick='return plusbutton(this);'><img src='Images/plussign.jpg' width='30' height='30' alt='Look Up Previous Question' class='imageplus'/></a>").attr('name',$this.attr('name')+"[]")
.attr('value',$this.val());
$plusrow.append($plusimagerow);
});
$tr.append($plusrow);
$tr.append($question);
$tbody.append($tr);
form.questionText.value = "";
$('.questionTextArea').val('');
}
function closewindow() {
$.modal.close();
return false;
}
$('.plusimage').live('click', function() {
plusbutton($(this));
});
function plusbutton(plus_id) {
// Set global info
plusbutton_clicked = plus_id;
// Display an external page using an iframe
var src = "previousquestions.php";
$.modal('<iframe src="' + src + '" style="border:0;width:100%;height:100%;">');
return false;
}
function addwindow(questionText) {
if(window.console) console.log();
if($(plusbutton_clicked).attr('id')=='mainPlusbutton') {
$('#mainTextarea').val(questionText);
} else {
$(plusbutton_clicked).parent('td').next('td.question').find('textarea.textAreaQuestion').val(questionText);
}
$.modal.close();
return false;
}
</script>
But the problem is that if I include this code below which I need into the function insertQuestion(form) {, then it stops the text adding into the textarea, why is it doing this?
var $qid = $("<td class='qid'>" + qnum + "</td>" );
...
$tr.append($qid);
$qid is the question number for each row, so everytime a row is added, it adds a question number by plus 1 each time.
Blow is the html code of where it appends the textarea from the top into a table row:
<table id="question">
<tr>
<th colspan="2">
Question Number <span class="questionNum">1</span>
<input type="hidden" class="num_questions" name="numQuestion" value="1">
</th>
</tr>
<tr>
<td rowspan="3">Question:</td>
<td rowspan="3">
<textarea class="questionTextArea" id="mainTextarea" rows="5" cols="40" name="questionText"></textarea>
</td>
</tr>
</table>
UPDATE:
I have included links to both applications. One that works but does not include $qid, and one that includes $qid and doesn't work but which I do need working. Please follow steps in both applications so you can test it yourself and see what is happening:
Application 1: No $qid but working.
Aplication 2: Contains $qid but not working:
Follow steps below for both applications:
Click on "Add Question" button, then will add a textarea within a new row.
Click on the "Green Plus" button within the table row you just added, a modal window will appear.
In modal window it displays a search bar, in search bar type in "AAA" and click on "Search" button
Results will appear of your search, click on "Add" button to add a row. You will find out modal window is closed but the content from the "Question" field is not added in the textarea within the row you clicked on the green plus button
Try explicity setting the td value with
var $qid = $("<td class='qid'></td>" ).text(qnum);
$tr.append($qid);
And then replace the text setting code from
$(plusbutton_clicked).parent('td').next('td.question').find('textarea.textAreaQuestion').val(questionText);
to
$(plusbutton_clicked).closest('tr').find('textarea.textAreaQuestion').val(questionText);
You can try it easily if you try with text:
var $qid = $("<td class='qid'>"+ qnum + "</td>" );
$tr.append($qid);
or
$("<td class='qid'></td>" ).text('hello').appendTo($tr);
Related
I've a form in which containing one <div> tag and the HTML within it. This is what I've when page loads. Then through AJAX I'm appending the same block(i.e. ) to the existing one. In every <div> tag there is one <table> and in that <table> I've a button with class products. After clicking on it I'm calculating the no. of rows present in that table only and assigning the id to the newly added row. But the issue I'm facing is when I add multiple such tables using AJAX and click on add button of any table it's calculating the total no. of rows present in all tables and adding that much no. of rows to the table in which I clicked add button. This shouldn't have to happen. It has to add only one row. I've created a jsfiddle for your reference. In fiddle I've put in static HTMl so it's working fine over there but on my local machine when I add multiple tables using AJAX I'm getting wrong no. of rows added.For example if I added three tables and click on add button of first table then it's adding four rows to that table. Why it's counting the total no. of rows present in all the tables present on a page?Is there any need to improve my script? My script is as follows:
$(document).ready(function() {
$('.products').click(function () {
var table_id = $(this).closest('table').attr('id');
var no = table_id.match(/\d+/)[0];
//var first_row = $(this).closest('table').find('tbody tr:first').attr('id');
var first_row = $('#'+table_id).find('tbody tr:first').attr('id');
var new_row = $('#'+first_row).clone();
var tbody = $('tbody', '#'+table_id);
var n = $('tr', tbody).length + 1;
new_row.attr('id', 'reb' + no +'_'+ n);
$(':input', new_row).not('.prod_list').remove();
$('select', new_row).attr('name','product_id_'+no+'['+n+']');
$('select', new_row).attr('id','product_id_'+no+'_'+n);
$('<button style="color:#C00; opacity: 2;" type="button" class="close delete" data-dismiss="alert" aria-hidden="true">×</button>').appendTo( $(new_row.find('td:first')) );
tbody.append(new_row);
$('.delete').on('click', deleteRow);
});
});
Following is jsFiddle link: http://jsfiddle.net/vrNAL/2/
I think what you mean to query is this:
var tbody = $('#' + table_id + ' tbody');
Instead of:
var tbody = $('tbody', '#' + table_id);
From the jQuery documentation, I don't think selectors work this way.
You are doing some strange things with the IDs here. why are you getting the IDs and selecting the sleemts with that, instead of using the selected elements directly?
Example:
var table_id = $(this).closest('table').attr('id');
var table = $("#" + table_id);
Is the same as just
var table = $(this).closest('table');
and
var first_row = $('#'+table_id).find('tbody tr:first').attr('id');
var new_row = $('#'+first_row).clone();
is the same as:
var new_row = table.find('tbody tr:first').clone();
I have a form where user can submit a few values and they get stored inside a list in a span separated by a comma, like this:
<li>
<span>
Harvard,Marketing,2009,2014
</span>
<br><a>[Remove]</a>
<br><a>[Edit]</a>
</li>
//output
Harvard,Marketing,2009,2014
[Remove]
[Edit]
When clicking on [Edit] I'd like to show up the form replacing the list space with the values in the span filling the inputs showing in the new form so the user can modify them and save again. How can I accomplish this?
Complete code on jsFiddle: http://jsfiddle.net/YueX2/
Please run it so you can see how it works, just click on "Add another" and then on the "Save" button.
is a bit messy but should give you an idea how to do this.
the given template for the "li" is slightly modified
<li>
<span>
Harvard,Marketing,2009,2014
</span>
<br>[Remove]
<br>[Edit]
</li>
the code could be like this:
$('.edit').click(function(){
var parent = $(this).parent();
//get the String from the span element
var values = $.trim( parent.find('span').text() );
//and plit them
values = values.split(',');
//prepend an container to hold the inputs
parent.prepend('<div class="editCont"></div>');
var container = parent.find('.editCont');
//create inputs for each of the seperated values
for(var v in values){
container.append('<input type="text" value="'+values[v]+'" /><br>');
}
//create save link and bind click event to it
container.append('<a href="#" class="editContButton" >save</a><br>');
parent.find('.editContButton').click(function(){
//collect all values from the inputs
var text = [];
var inputs = container.find('input');
for(var i = 0; i < inputs.length; i++){
text.push( $(inputs[i]).val() );
}
parent.find('span').show();
//replace the text in the span element and remove container with inputs again
parent.find('span').text( text.join(",") );
container.remove();
})
parent.find('span').hide();
});
If clicked on Edit the text in the span is split and an input for every entry is created and at the end i add a save link.
If the link is klicked the inputs get joined to an sting and replace the old text in the spawn.
the hide and unhiding of the spawn is optional ;)
When edit is clicked, you can split the content of that span, since it's already comma separated. Then you can take new input and apply it to the span on save. I edited your edit function, and added a new save function.
//existing edit method
$(document).on('click', '.edit', function () {
//hides edit and remove buttons
$(".removeParent, .edit").hide();
//splits span into separate terms
var terms = $(this).siblings("span").html().split(",");
//makes new form
$(this).parents("li").append("<input id='edit1' type='text' value=" + terms[0] + ">" + "<input id='edit2' type='text' value=" + terms[1] + ">" + "<input id='edit3' type='text' value=" + terms[2] + ">" + "<input id='edit4' type='text' value=" + terms[3] + "><input type='button' class='saveEdit' value='Save'>");
});
//additional save method
$(document).on('click', '.saveEdit', function () {
//unhides edit and remove buttons
$(".removeParent, .edit").show();
//makes the new string for the span
var newString = $("#edit1").val()+","+$("#edit2").val()+"," +$("#edit3").val()+","+$("#edit4").val();
//replaces the html of the span with the new string
$(this).siblings("span").html(newString);
//hides new form and save button
$(this).hide();
$("#edit1, #edit2, #edit3, #edit4").hide();
});
I am trying to following the example here and create a popover table row. When I just copy the code it works like a charm. But in the table where I want the popup to work it fails.
I have the following JavaScript code (same as Fiddle):
// Popover
var options = { placement: 'bottom', trigger: 'manual', html: true, title: 'This row' };
function createPopover(element, args) {
var href = $(element).data('popover-url'), txt = $(element).data('popover-content');
var html = '<p>Challenge: Can you click the link in a popover?</p><p><a href="' + href
+ '">' + txt + '</a></p>';
$(element).data('content', html).popover(args);
}
function popoverPlacementBottom() {
createPopover($(this), options);
}
$('.row').each(popoverPlacementBottom);
var insidePopover = false;
function attachEvents(tr) {
$('.popover').on('mouseenter', function () {
insidePopover = true;
});
$('.popover').on('mouseleave', function () {
insidePopover = false;
$(tr).popover('hide');
});
}
$('table').on('mouseenter', 'tr', function () {
var tr = $(this);
setTimeout(function () {
if (!insidePopover) {
$(tr).popover('show');
attachEvents(tr);
}
}, 200);
});
$('table').on('mouseleave', 'tr', function () {
var tr = $(this);
setTimeout(function () {
if (!insidePopover) $(tr).popover('hide');
}, 200);
});
and try to have popovers on this table:
<table class="table table-condensed scrollable popup">
<thead>
<tbody id="logEvents">
<tr class="row" data-popover-url="#url_for_row_1" data-popover-content="line 1" data-
original-title="" title="">
<td class="col-md-1">18:27</td>
<td class="col-md-5">InfoService</td>
<td>Blabla...</td>
</tr>
</tbody>
</table>
This however, does not work. While it does work at the table underneath which looks like this:
<table class="popup">
<tbody>
<tr class="row" data-popover-url="#url_for_row_1" data-popover-content="line 1" data-original- title="" title="">
<td>the first line</td>
</tr>
</tbody>
</table>
Why does it not work at the table where it should work? I hope someone can help me out.
/EDIT Okay I made my own Fiddle HERE.
Strangely enough the code works in the Fiddle. But on my webpage it does not. The only difference with the Fiddle is that the tr rows are dynamically generated everytime an event happens by the function:
return "<tr " + trClass + " data-popover-content='line 1' data-popover-url='#url_for_row_1'>"
+ "<td class='col-md-1'>" + time + "</td>"
+ "<td class='col-md-5'>" + item.Source + "</td>"
+ "<td>" + item.DescriptionShort + "</td>"
// + "<td class='col-md-6'>" + "<a id='pop' data-content='test' data-
toggle='popover'>" + item.DescriptionShort + "</a></td>"
+ "</tr>";
Could this have anything to do with it? (e.g., that the id's and classes come after the document-ready? And that I need to reassign the classes every time a new event happens? And if so, how?
Okay the problem was in the generated code! The <tr>'s were generated everytime an event happened and so I should not assign the popover event only at document ready, but also everytime a new row was created.
I put the popover() function in his own pop namespace, and added the pop.popOver() after the new event made a new row. Looked as follows:
this.addData = function (item) {
var container = $(this.cId);
container.append(this.getEventHtml(item));
pop.popOver();
}
Now the popups show! YEAH! Thanks to Suman Bogati for his help.
I have a table to which I am currently dynamically adding rows: http://jsfiddle.net/fmuW6/5/
Now I'd like to add a new column to the table as well with a click of a button. The user will enter the column header in a textbox.
How can I achieve this? If the user adds 4 rows, the Add a new Column button should take care of all the existing rows (adding checkbox in each one).
update
I'm looking to add column name and checkbox at row level.
so I've added the text box in which the user will input the column name: http://jsfiddle.net/fmuW6/10/
<input type=text placeholder='columnname'/>
<button type="button" id="btnAddCol">Add new column</button></br></br>
so then when user clicks the button the columnname should be the value in the textbox and at the row level should be checkboxes. So basically the new column should be appended to all tr in the table except the first row since that is the column names
I updated your fiddle with a small example how you could do that.
jsFiddle - Link
var myform = $('#myform'),
iter = 0;
$('#btnAddCol').click(function () {
myform.find('tr').each(function(){
var trow = $(this);
if(trow.index() === 0){
trow.append('<td>Col+'iter+'</td>');
}else{
trow.append('<td><input type="checkbox" name="cb'+iter+'"/></td>');
}
});
iter += 1;
});
This would add a new column to every row, including an count-variable that gets applied to the first row as name and to the name-attribute of the checkboxes on the following rows.
Consider using th - elements for the table header, that way you wouldn't need the index-check i'm making and it would be more semantically correct.
I left out the part where the user would put in a name for the column, but as you see, you could just replace the iter - value with that in the end.
Modern pure JavaScript solution:
const addColumn = () => {
[...document.querySelectorAll('#table tr')].forEach((row, i) => {
const input = document.createElement("input")
input.setAttribute('type', 'text')
const cell = document.createElement(i ? "td" : "th")
cell.appendChild(input)
row.appendChild(cell)
});
}
document.querySelector('button').onclick = addColumn
<table id="table">
<tr><th><input type="text" value="test 1" /><th/></tr>
<tr><td><input type="text" value="test 2" /><td/></tr>
</table>
<button type="button">add column</button>
First row will contain a th instead of td. Each new cell contains a input. Feel free to change this to suit your need.
The answer works, but still here is an alternative way where we use thead and tbody !
JS
$('#irow').click(function(){
if($('#row').val()){
$('#mtable tbody').append($("#mtable tbody tr:last").clone());
$('#mtable tbody tr:last :checkbox').attr('checked',false);
$('#mtable tbody tr:last td:first').html($('#row').val());
}
});
$('#icol').click(function(){
if($('#col').val()){
$('#mtable tr').append($("<td>"));
$('#mtable thead tr>td:last').html($('#col').val());
$('#mtable tbody tr').each(function(){$(this).children('td:last').append($('<input type="checkbox">'))});
}
});
Use this code for adding new column:
$('#btnAddCol').click(function () {
$("tr").append("<td>New Column</td>");
});
But you need to change the value for the first row with a text and others to include a <input type="checkbox" />. And it is better to
Check it out jsFiddle .............................
http://jsfiddle.net/fmuW6/8/
$(document).ready(function () {
$('#btnAdd').click(function () {
var count = 3, first_row = $('#Row2');
while(count-- > 0) first_row.clone().appendTo('#blacklistgrid');
});
$('#btnAddCol').click(function () {
$("#blacklistgrid tr").each(function(){
$(this).append("<td>test</td>");
})
});
});
Using a table of 4 columns:
I can add values dinamically like this:
var TableId = "table_" + id;
var table = $("#" + TableId );
table.find("tbody tr").remove();
table.append("<tr><td>" + "1" + "</td><td>" + "lorem" + "</td><td>" + "ipsum" + "</td><td>" + "dolor" + "</td></tr>");
and the final result will be:
I have a application which you can access here. If you open the application please click on the "Add" button a couple of times. This will add a new row into a table below. In each table row there is an AJAX file uploader.
Now the problem is that if I click on the "Upload" button in any row except the first row, then the uploading only happens in the first row so it is only uploading the first file input only.
Why is it doing this and how can I get it so that when then the user clicks the "Upload" button, the file input within that row of the "Upload" button is uploaded and not the first row being uploaded?
Below is the full code where it appends the file AJAX file uploaded in each table row:
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='upload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='startUpload();' >" +
"<p id='f1_upload_process' align='center'>Loading...<br/><img src='Images/loader.gif' /><br/></p><p id='f1_upload_form' align='center'><br/><label>" +
"File: <input name='fileImage' type='file' class='fileImage' /></label><br/><label><input type='submit' name='submitBtn' class='sbtn' value='Upload' /></label>" +
"</p> <iframe id='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);
}
function startUpload(){
document.getElementById('f1_upload_process').style.visibility = 'visible';
document.getElementById('f1_upload_form').style.visibility = 'hidden';
return true;
}
function stopUpload(success){
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!<\/span><br/><br/>';
}
else {
result = '<span class="emsg">There was an error during file upload!<\/span><br/><br/>';
}
document.getElementById('f1_upload_process').style.visibility = 'hidden';
document.getElementById('f1_upload_form').innerHTML = result + '<label>File: <input name="fileImage" type="file"/><\/label><label><input type="submit" name="submitBtn" class="sbtn" value="Upload" /><\/label>';
document.getElementById('f1_upload_form').style.visibility = 'visible';
return true;
}
UPDATE:
Current Code:
var $fileImage = $("<form action='upload.php' method='post' enctype='multipart/form-data' target='upload_target' onsubmit='startUpload(this);' >" +
"<p class='f1_upload_process' align='center'>Loading...<br/><img src='Images/loader.gif' /><br/></p><p class='f1_upload_form' align='center'><br/><label>" +
"File: <input name='fileImage' type='file' class='fileImage' /></label><br/><label><input type='submit' name='submitBtn' class='sbtn' value='Upload' /></label>" +
"</p> <iframe class='upload_target' name='upload_target' src='#' style='wclassth:0;height:0;border:0px solclass #fff;'></iframe></form>");
function stopUpload(success, source_form){
var result = '';
if (success == 1){
result = '<span class="msg">The file was uploaded successfully!<\/span><br/><br/>';
}
else {
result = '<span class="emsg">There was an error during file upload!<\/span><br/><br/>';
}
$(source_form).find('.f1_upload_process').style.visibility = 'hidden';
$(source_form).find('.f1_upload_form').innerHTML = result + '<label>File: <input name="fileImage" type="file"/><\/label><label><input type="submit" name="submitBtn" class="sbtn" value="Upload" /><\/label>';
$(source_form).find('.f1_upload_form').style.visibility = 'visible';
return true;
}
Why am I getting an error on this line below:
$(source_form).find('.f1_upload_form').style.visibility = 'visible';
Without seeing the full cose, your problem seems to be that you are working with ID's, which must be unique within one document. If several elements are using the same ID, in the best case a browser will use the first one (which it does here), in the worst case nothing will work.
When adding a new upload form, you have to give the elements in it unique ID's. You could do that simply by attaching a counting variable to window, e.g.
$(document).ready( function(){ window.formCount=0; } );
You could then add that number to the ID of the newly added form.
Apart from this, by using the this variable, you can carry a reference to the correct form through, e.g. like onsubmit='startUpload(this);' as well as function startUpload(f){...
You should then be able to access things within the form using $(f).find(...).
There are many ways to make this work and solve the issue of multiple ID's. What I would do: var $fileImage = $("<form action... In this form where it says id I would instead use class. Then as above, change the onsubmit (in the same line) by adding "this" to its brackets. Then change the function startUpload as here:
function startUpload(source_form){
$(source_form).find('.f1_upload_process').css('visibility','visible');
$(source_form).find('.f1_upload_form').css('visibility','hidden');
return true;
}
You have to do the same thing for other functions where you want to access something inside the form that is sending a file. Pass a reference to the form to the function using this in the function call's brackets, then access things inside the form as I showed above.