I've asked a lot of jQuery questions recently as I'm trying to use it rather good old Javascript, as I mentioned in previous questions, "I'm currently having to extend an very old ASP.NET site which has a database generated front end and is a behemoth of an application, it needs completely rewriting - however I've been told to add to it than redevelop it "
Now what I'm doing is once the backend is rendering a table to the interface I wish to loop through the tr elements of the table, within one of the td elements of the tr there are two radio buttons. I need to determine the name of the radio button group as I don't define them, the systems does using a GUID or something?
This is the table for example...
<table id="tableID">
<tr>
<td class="qCol">
<!-- Label here -->
</td>
<td class="qCo2">
<!-- img here -->
<!-- and a text box -->
</td>
<td class="qCo3">
<!-- select menu here -->
</td>
<td class="qCo4">
<!-- radio buttons here -->
</td>
<td class="qCo5">
<!-- select menu here -->
</td>
<td class="qCo6">
<!-- hidden validation image here -->
</td>
<tr>
</table>
Okay, I'm looping through the table and at the same time switching the innerHTML of one cell to another and hiding some of the rows, I'll be adding functionality to show these later, here's the jQuery:
$('#tableID tr').each(function (i) {
/*switch select and validation and clear */
$(this).children('td.qCol').html($(this).children('td.aCol5').html());
$(this).children('td.aCol5').html($(this).children('td.vCol'.html(""));
/* hide all but the first row*/
if (i >= 1) {
$(this).hide();
}
now I'm trying to determine the name attribute of the radio buttons that will be in the cell with class .qCo4, however I'm having no luck as the following returns an error and is "undefined"...
/* get the radio button name and check if either are selected*/
// check something exists...
if ($('input:radio', this).attr('name')) {
var thisRadioName = $(this).closest("input:radio").attr('name').val();
alert(thisRadioName);
}
$this is the tr element, so should I be using child rather than closest? If this makes no sense I can expand and explain better.
you should use find() or children(). closest() goes up the tree, while find looks for elements down the tree
var thisRadioName = $(this).find("input:radio").attr('name');
you can use also ':checked' to check if any radio is checked
var checkedRadio = $(this).find("input:radio:checked")
You should use children if you are absolutely sure that the elements you are looking for are direct child of the element, otherwise use find(). (using finds protect you from refactoring code if you modify the html, like adding a wrapping div for other reasons like styiling)
look at this fiddle: http://jsfiddle.net/nicolapeluchetti/Evq6y/
var thisRadioName = $(this).find("input:radio").attr('name');
should do what you want
Related
I have a button, when I click I want it to get all data from the row. My .php file (i also have php code not included here) looks like so (I trimmed out the table for stackoverflow)
<tr class='rowdata'>
<td>Bob</thd>
</tr>
<input type='submit' class='getRow' value='ClickMe'>
<script>
$(".getRow").click(function() {
var rowOfData = $(this).closest(".rowdata");
alert(rowOfData.text());
});
</script>
Right now I click and nothing happens. Any ideas? The . prefix means it is searching for class.
Well first, have you checked your developer's console (F12) to see if you have any errors. Are you sure you've referenced the JQuery library.
Next, even with JQuery referenced, .closest() is going to search the ancestor elements of the element you call it on. If your button is not a descendant of the element you wish to find, you won't find it.
Now, assuming that .closest() does find your row, you are then asking for the .text() in the entire row. This may be what you want, but it's seems more likely that you'd want data cell by cell.
Also, your button is a submit button which is used for submitting form data, but it doesn't appear that that's what you're doing here. If that's the case, use a regular button.
And, your HTML isn't valid as you have a bad closing tag for your cell.
So, correcting all that:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr class='rowdata'>
<td>Bob</td>
<td>Smith</td>
<td><input type='button' class='getRow' value='ClickMe'></td>
</tr>
</table>
<script>
$(".getRow").click(function() {
var rowOfData = $(this).closest(".rowdata");
alert(rowOfData.text()); // Gets all the text in the row
alert($("td:first-child", rowOfData).text()); // Gets just first cell
});
</script>
I'm currently using Nightwatch to do some automated tests, but CSS selectors were extremely complex and did not do the job for me. I've instead started to look at XPath to do the job however the table in question is fairly complex.
I want to be able to .click() a button within a td value, where that specific row in the table contains a specific value. The table looks like this:
Username Email Display Name Buttons to Click (1st one wanted)
test test#example test (1st button)(2nd button)
test2 test2#example test (1st button)(2nd button)
Each of these values are within a tr > td so being able to find it is proving difficult. This is my currently XPath:
.click('/table[#id="admin-user-list"]/tbody/tr[td = "test2"]/td/button')
The HTML tree looks like this:
<div id>
<div class>
<table class>
<tbody>
<tr>
<td data-bind>(username)
<td data-bind>(email)
<td data-bind>(display name)
<td button>
(1st button)
(2nd button)
</tr>
</tbody>
Each row has its own tr with those exact tds inside.
Some help would be appreciated :)
.click('//table[#id="admin-user-list"]/tbody/tr[./td[text()='test2']/td/button')
logic: //table[#id="admin-user-list"]/tbody/tr[./td[text()='test2']
- tr with td that has text
/td/button -button in that row
but actually this is not really good idea to do that, as you are searching for that value in each column. Better to use combination of columnName+value
Let's check on that table sample: https://www.w3schools.com/css/css_table.asp
We'll search for table data in column by name, for example table column = Country, data = UK
//*[#id='customers']//tr/td[count(//*[#id='customers']//th[text()='Country']/preceding-sibling::*)+1][text()='UK']
again, logic is simple:
general locator is:
//*[#id='customers']//tr/td - we are searching for table data
with parameters: [text()='UK'] and position = same, as in column name [count(column_position)]
How to get column position:
just get column with needed text:
//*[#id='customers']//th[text()='Country'] and count it's preceding siblings:
//*[#id='customers']//th[text()='Country']/preceding-sibling::* , also we should add +1 , as we need current element's position. and count that staff, so here is the result: [count(//*[#id='customers']//th[text()='Country']/preceding-sibling::*)+1]
so having column position we can get general locator:
tableId = customers; columnName= Country; dataText = UK;
//*[#id='tableId']//tr/td[count(//*[#id='tableId']//th[text()='columnName']/preceding-sibling::*)+1][text()='dataText']
And here is locator to get hole row by data+columnName
//*[#id='customers']//tr[./td[count(//*[#id='customers']//th[text()='Country']/preceding-sibling::*)+1][text()='UK']]
and basically you can search anything inside of it, for example just add in the end
/td/button - to get button from it
I have an html table that looks like the following:
<table id="tree">
<tr id="foo-1">
<td>fooId1</td>
<td>fooName1</td>
<td>fooCsv1</td>
<td><button id="button-1" type="button" disabled>Save</button></td>
</tr>
<tr id="foo-2">
<td>fooId2</td>
<td>fooName2</td>
<td>fooCsv2</td>
<td><button id="button-2" type="button" disabled>Save</button></td>
</tr>
</table>
There are two modifications I want to do to this table:
-First, I want to make the fooName and fooCsv td elements editable (there are actually a couple more editable columns, but I'm just using two to make this example simpler). I know that I can simply put an input inside the td element and set the value, but was wondering if there's a simpler way.
-Second, I want the Save button in each row to become enabled when a user changes the text in that row via typing/copy-paste/etc. I've googled and found that I might be able to do this by adding a handler for an input event, but I'm not sure of the simplest way to incorporate this, and I'm not sure if it has ramifications for the first task I have.
I think this should be easy if I knew much about html and javascript, but I don't, so does anyone know a simple way to achieve what I'm trying to do?
<td contenteditable="true">fooName1</td>
And use what ever you want to post the table HTML
edit:
http://jsfiddle.net/9yyKN/11/
//Listen to blur event in contenteditable td elements
$('td[contenteditable=true]').blur(function () {
$(this).parent('tr').find('button').removeAttr('disabled');
});
//When a button is clicked find the nearest contenteditable td //element(s) and push their
text content to an array, this array is later being posted.
$('button').click(function () {
var contents = $(this).parents().find('td[contenteditable=true]');
var contentArray = [];
for (i = 0; i < contents.length; i++) {
contentArray[i] = contents[i].innerHTML;
}
$.post("test.php", contentArray);
});
I am developing a webapp using Spring, jsp, javascript, jquery.
I display a table using datatables.
When I click on a table row I want it to change all fields to an inline edit inputs, selects etc. In addition I want to show some extra input fields in the next row and a save button.
Now I see several ways of doing this. I am not sure which one to take.
I can get a handle to selected row and then iterate over the td and transform them to input/select fields. I can then insert an extra row for the new fields and the save button.
I don't see this as a clean solution. I will have to issue a Post manually instead of using the Spring ModelAttribute binding for the form. (Can I still use ModelAttribute here?)
I can create an edit form in a jsp file which looks like:
<form:form action="" commandName="">
<td> <input ... > </td>
<td> <select ... > </td>
</tr>
<tr>
<td> <label> <input new field> </td>
<td> <button> </td>
</tr>
Note I do not have a beginning in a jsp file as I plan to reuse the tr from the existing row in the table.
This way I would be able to have a clean form and also use the update method I have already written which binds the form to a Java class. Also I do not have to bother about the alignment of input fields with the column names.
The generated html looks like
...
The problem with this approach is the placement of form element in the html causes the entire form to be cramped into one cell of the table which does not look good and messes up the whole layout. Is there a way out? Should I just replace the contents of the table with a having a colspan and then put divs inside this element and fine tune the css to ensure that the input fields align with the column names in the table?
Is there a better solution you can suggest?
In case the question is not very clear I can fill in more details.
This is what I would do (coming from a server-side development background, as I know developers love easy solutions)
Wrap the table with a single form
on Edit row (clicking row) open an ajax request that returns pure html that looks like the exact tr, only with whatever extra you want to include:
<tr><td><input type="text" name="text1" ... /></td><td>second row... </td></tr>
<tr><td colspan="2">And hey, here is more, and the save button ... </td></tr>
in jQuery replace tr with content retrieved (myTr.replace($(ajaxResponse))) or something similar
now Save button is a regular submit for the form
if you want to submit via ajax, once done, return the old html in your ajax response and replace the two trs with the old tr (you just need to hook it by giving new trs an attribute that you can find easily in jquery)
don't forget to switch off a global key to prevent double editing, users can edit one row at a time
Update: adding a second solution to dump load on client instead of server
To avoid overloading the server (though I wouldn't be worried about it until it becomes a regular habit), you can make your form fields as a template inside your HTML and use string replacement (or jQuery Templates), so instead of ajaxing to get response in step 2, you call the template, and replace the strings with attributes you save in every row... like this:
<div id="myTemplate"> // or you can use jQuery script templates
<tr><td><input type="text" name="${Name}" ... /> id is ${Id}</td><td>${SecondRow}... </td></tr>
<tr><td colspan="2">Save button here.... and may be more text ${MoreText}</td></tr>
</div>
in every row in your code add sufficient attributes or ids to know what you want to replace with, like this:
<tr data-itemid="34"><td ><input type="text" name="text1" id="findme" ... /></td><td data-moretext="here is more text">second column </td></tr>...etc
so now in your replacement script:
$("#myTemplate").html().replace("${Name}", $(thisrow).find("#findme").attr("name"))
.replace("${Id}",$(thisrow).attr("data-itemid"));
etc...
Of course after submission it has to be a to server, but in case user "cancels" you can have another readonly template
By the way, that is the way I usually go with, I use jQuery templates, and create edit and view templates, but I also repeat edit forms and I use jQuery ajax submit manually... but that... my friend, is not a simple clean and maintainable solution I'm afraid
I've been into an issue like this a year before. This is a messy problem. Either way if you traverse each td of row and convert it into text field or You can create a separate jsp file for this.
But the best in this case is to change the content of td to input field and post the data manually. because in this case you cannot wrap form tag around tr. You have to manually post the values of each input field.
P.S The very best solution is to create an edit dialog.
There is another solution, but I'm under the impression you won't like it very much... you can use a single form for the whole datatable (wrapping the whole table in a form is permitted) generate input fields for the current row and if it's updated submit the form asyncronously with javascript and restore td contents to the original html, if you name your fields such as name="field[]" you can also submit multiple rows at a time (I don't know if you'd want that though).
You can write html code such as
<form action="">
<table>
<tr><td><input type="hidden" name="row[]" value="1"/><input name="field[]"/></td></tr>
<tr><td>field value for row2</td></tr>
<tr><td><input type="hidden" name="row[]" value="3"/><input name="field[]"/></td></tr>
</table>
</form>
you can just grab the form with jquery and submit it via xmlhttprequest as I suspect you would if each row was a separate form (which is illegal), if you don't want multiple rows, just remove the [] and submit each row
and upon submitting the values you get them numbered correctly, don't know exactly how it would behave in java but in php I'd get the following:
$_GET[row][0] = 1;
$_GET[field][0] = 'value typed in row1';
$_GET[row][1] = 3;
$_GET[field][1] = 'value typed in row3';
Alternative table definition to avoid having the same name again
<form action="">
<table>
<tr><td><input name="field[1]"/></td></tr>
<tr><td>field value for row2</td></tr>
<tr><td><input name="field[3]"/></td></tr>
</table>
</form>
It's the same table as above only you set explicit indexes for each entry thus avoiding duplicate names in the response, preferrably use a unique identifier which can describe the row from the table that you're modifying in there (when possible I use the primary key) instead of the row number, just in case that wasn't clear enough.
Have you tried:
Wrap whole table in the form
have the data entries as disabled inputs with their borders hidden via CSS
when user clicks edit, enable the inputs and show the borders
You'll probably need hidden elements for each field
When user submits the form, post via ajax and set the inputs back to disabled with hidden borders
What about contenteditable?
Demo: http://jsfiddle.net/SO_AMK/XQekC/
jQuery:
var ctrlDown = false;
$(document).keydown(function(e) {
if (e.which = "ctrlKey") {
ctrlDown = true;
}
}).keyup(function(e) {
if (e.which = "ctrlKey") {
ctrlDown = false;
}
});
$('#example').dataTable();
$("#example tr").click(function() {
if ($(this).hasClass("row_selected") && ctrlDown) {
submitRow($(this));
return false; // Break out so the next if doesn't run
}
else if ($(this).hasClass("row_selected") && ctrlDown == false) {
return false; // Break out so the next if doesn't run
}
if ($(this).siblings(".row_selected").length && ctrlDown == false) {
$(this).siblings(".row_selected").each(function() {
submitRow($(this));
});
}
$(this).addClass("row_selected");
$(this).children("td").each(function() {
$(this).attr("contenteditable", true);
});
});
function submitRow(elm) {
var data = [];
$(elm).removeClass("row_selected").children("td").each(function() {
data.push($(this).text());
});
alert(data); // This will stop the keyup from firing, but you won't (I hope) really be using alerts
}
This has everything but a submit-to-server function, it's also completely inline and has support for selecting multiple rows.
The only bug is, when it shows the data alert the focus goes off of the main window so the keyup event never fires, since you probably won't be using alerts this shouldn't be an issue. To fix it in the fiddle, press and release ctrl after the alert closes before clicking a row.
I see couple of problems
Your no. Of columns in the table & the edit columns you show are different
You might not be having complete data to edit the row so you might need to do an Ajax call and get it
If you have complete data on then you don't need point 2, let's assume you have a function f called with the clicked tr as the parameter
function f(row)
{
var newRow = yourTable.insertRow(parseInt(row.rowIndex,10)+1);
//you can place the above or below the clicked row , or you can even make the row visible false And then show the new row
Var newCell = newRow.insertCell(0);
newCell.colspan = 6;//the count if columns in your table row
NewCell.innerHTML = " put your HTML content here";
}
I have a html table displayed in a showmodal dialog window, the html-body has several divs, each div having several tables, tr and td within them.
The user will update entries within the input tag so i need to capture the change.
One such div looks like below. How to I retrieve all these values on a button click. I have heard of serialize() method. Will it work for all tag types, "insert","select", "option" etc etc.
<div>
<table>
<tr><td></td><td></td><td></td>
</tr>
</table>
<table>
<tr><td></td><td></td>
</tr>
<tr><td></td><td></td><td></td><td></td>
</tr>
</table>
<table>
<tr><td></td>
</tr>
</table>
</div>
Apologies, writing my solution in a pseudocode fashion:
//I created a div container and then loop through all the divs
//then retrieve values using one of the below
$("classname > div[id]").each(function(){
var a= document.getElementsByName("name of the tag"); //by name
var b= document.getElementById("id of the tag"); //by id
var c= $("input[class='"+trd_id+"']:checked").val(); // for radio button
});
// loop by div counts and alert the values. Solved my problems