I am using the selection. I am selecting a value and getting the result in an input box, but the problem is, it is only working in the first row of my selection and not working when I am clicking second selection. Here is the code, Please share if you can solve this one or advice.
<script type="text/javascript">
function displayResult()
{
document.getElementById("mycall1").insertRow(-1).innerHTML = '<td><select id = "forcx" onchange="fillgap()"><option>Select</option> <option>Force</option><option>Angle</option><option>Area</option></select></td>';
document.getElementById("mycall2").insertRow(-1).innerHTML = '<td><input type="text" id="result1" size = "10" ></td>';
}
function fillgap(event){
var xnumb = 20;
var forcxlist = document.getElementById("forcx");
var forcxlistValue = forcxlist.options[forcxlist.selectedIndex].text;
if (forcxlistValue == "Force"){
document.getElementById("result1").value = xnumb;
}
}
</script>
Ok, so if i understand correctly
1) You want to add the: selection, results & + to the existing table
2) Add the options Force, Angle & Area to the select
3) If Force is selected, put the value '20' in the results td
4) When the + is clicked, a new row is added.
5 The newly added rows should behave exactly the same.
Given the above, I have done the following, I'm using jQuery as its simpler and I'm more familiar with it. Its easy.
The trick here is event delegation. at the time your page loads the new rows don't exist, that's why your JavaScript isn't working on them. you can read about it here: https://learn.jquery.com/events/event-delegation/
Here's the result:
$(document).ready(function() {
// add headers to table
$('table tr:first-child').append('<th>Result</th><th>Add</th>');
//add fields to table
$('table tr:not(:first-child)').append('<td><select class="selection"><option></option><option value="Force">Force</option><option value="Angle">Angle</option><option value="Area">Area</option></select></td><td class="result"></td><td><button type="button" class="displayResultBtn">+</button></td>');
// add new row when button is clicked
$('table').on('click','.displayResultBtn', function( event) {
var tRow = $(this).parent().parent().clone();
$(this).parents('table').append(tRow);
$('table tr:last-child td.result').empty();
});
// when the dropdown is changed, update the result to 20 if "Force" is selected.
$('table').on('change','.selection', function( event) {
var selection = $(this).val();
if (selection == "Force") {
$(this).parent().next().html('20');
// You can add more coditionals if you want to add didferent values for the other options.
} else {
$(this).parent().next().empty();
}
});
});
table,
td,
th {
border: 1px solid black;
white-space: nowrap;
}
table {
border-collapse: collapse;
width: 30%;
table-layout: auto;
}
td {
text-align: center;
vertical-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<table>
<tr>
<th>To</th>
<th>From</th>
<th>Detail</th>
<th>Selection</th>
</tr>
<tr>
<td>A</td>
<td>B</td>
<td>A+B</td>
</tr>
</table>
It's hard to answer with limited code provided, but I think your issue is that you are using id multiple times. Which is invalid. id should be unique and used once only.
I have put together some demo code here that will hopefully help you. It doesn't solve your exact problem(I dont have your html so i cant fully solve it). but hopefully this will give you an idea of how to handle accessing different rows, or specific unique ids.
I'm using jQuery here for simplicity, but the principle is the same:
Here's a fiddle if thats easier to play with: https://jsfiddle.net/BradChelly/4179e26q/
I hope this helps somewhat.
// highlight row by child selectors (:last-child)
$('#selectLastRowBtn').click(function(){
//clear any previous highlighting
$('#myTable tr:not(:first-child)').css('background-color','white');
// highlight the last row in the table.
$('#myTable tr:last-child').css('background-color','lightgrey');
});
// highlight row using a specific unique id
$('#selectRowByIdBtn').click(function(){
//get selected row id from dropdown
var rowId = $('#rowSelector option:selected').val();
//clear any previous highlighting
$('#myTable tr:not(:first-child)').css('background-color','white');
//highlight the row with the matching id from the selection dropdown
$('#myTable #row_'+rowId).css('background-color','lightgrey');
});
//
// ------Below is just stuff to make demo work, not relevant to the question
//
// Add row with unique id
$('#addNewRowBtn').click(function(){
var rowCount = $('#myTable tr').length;
$('#myTable').append('<tr id="row_'+rowCount+'"><td>23124</td><td>23124</td><td>23124</td><td>23124</td></tr>');
populateSelect(rowCount);
});
// populate select options
function populateSelect(rowCount){
$('#rowSelector').append('<option value="'+rowCount+'">'+rowCount+'</option>')
}
table {
width: 100%;
text-align: center;
}
table td {
border: 1px solid #333;
padding: 30px 0px;
}
table tr:first-child {
top: 0px;
background: #333;
}
table tr:first-child th {
color: #fff;
padding: 20px 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<table id="myTable">
<tr>
<th>Column One</th>
<th>Column Two</th>
<th>Column Three</th>
<th>Column Four</th>
</tr>
<tr id="row_1">
<td>23124</td>
<td>23124</td>
<td>23124</td>
<td>23124</td>
</tr>
</table>
<button id="addNewRowBtn">Add Row</button>
<h3>Using child selectors:</h3>
<button id="selectLastRowBtn">Highlight last row using child selector</button>
<h3>Highlight a row by id:</h3>
<select name="" id="rowSelector">
<option value="1">1</option>
</select>
<button id="selectRowByIdBtn">Highlight row by selected id</button>
Related
I have a two columned HTML table which I want to translate from English to Greek.
I desire to do that by double-clicking the Click to translate placeholder under the Greek column and then being prompted there, to insert a Greek text instead it.
In other words, I would interact with the HTML file to translate where the placeholder, right from web browser.
Any such (raw data) change should saved in the HTML file directly, without involving database programs such as a MySQL; thus, this program is aimed to be HTML-CSS-JS only.
table, th, td {
border: 1px solid black;
}
<!DOCTYPE html>
<html>
<body>
<section class="allEnglishSections">
<h2>Conditioning</h2>
<table>
<tr><th>English</th><th>Greek</th></tr>
<tr><td>if</td><td class="changeable">Click to translate</td></tr>
<tr><td>than</td><td class="changeable">Click to translate</td></tr>
<tr><td>else</td><td class="changeable">Click to translate</td></tr>
</table>
</section>
<script>
</script>
</body>
</html>
From searching data on how to achieve this, I understand I should use something similar to this pseudocode:
document.querySelectorAll(".changeable").addEventListener(ondblclick, function() {
myTranslation = prompt();
document.querySelector(".changeable").value = myTranslation;
}
But it is unclear to me how to actually selecting all text of a cell by double clicking it, and then changing it directly from web browser in such a way that the HTML file would change.
Is this even possible with latest ECMAScript and if so how will you achieve this?
An easy system would be to create a textarea inside the HTML on double click, and whenever you experience either the blur event or a specific key combination to remove the textarea and swapping it with a text node of it's own value.
Please note that I am added the events onto the tbody element. This is done because most events bubble up, and this way no matter how many <tr> elements get added in dynamically, I will have the same functionality without having to loop over the nodelist and add the event one-by-one.
I also use focusout instead of blur for a similar reason: blur does not bubble up, but focusout does.
Note The current version using the localStorage won't work on StackOverflow due to sandboxed permissions and so on. Copy/Paste the values into something like JSFiddle or Codepen to see a working example. I personally tested it on this JSFiddle in case you want to look at it.
I also did not use an example with AJAX/XHR as you seem relatively new to Javascript, and that needs for you to look up how REST APIs / XHR work. Feel free to make another question once you've done some fiddling with those, but for now that felt a bit out-of-scope for this question.
// get items from storage. if nothing is there originally we will get a null value
const fromStorage = localStorage.getItem('definitions');
// null values are falsey, so if it is null we need to use our default.
// otherwise we just JSON.parse the values we retrieved
const definitions = !fromStorage ? {
"if": null,
"when": null,
"tomato": null,
} : JSON.parse(fromStorage);
// I don't feel like running this command everytime I need to reference the tbody,
// thus, the reference to it here.
const tbody = document.querySelector('#definitions');
// adding an event listener on the tbody means that any of the same event that bubble up from it's children will reach here.
// This means you can add children in dynamically without needing to worry so long as they have
// a data-editorShown attribute
tbody.addEventListener('dblclick', e => {
const parent = e.target.parentElement;
// if somehow the event gets called from something that is NOT one of the TDs, we don't need to go any further from there.
// sidenote, all values in the Element.dataset are read as strings. you can set them to be whatever
// but when you read them, they will be strings.
if (parent.tagName !== 'TR' || parent.dataset.editorShown === 'true') return;
// The editor is now shown, so let's set that
parent.dataset.editorShown = true;
// get the last TD, which is where we will put our textarea
const dataTd = parent.querySelector('td:last-child');
// create a new textarea element
const textarea = document.createElement('textarea');
// the textarea gets some class
textarea.classList.add('full');
// and a placeholder
textarea.placeholder = "Double click to translate";
// the arguments for this function are backwards to me, but I think it's self explanatory what's happening
dataTd.replaceChild(textarea, dataTd.firstChild);
// get that focus on the textarea.
dataTd.firstChild.focus();
});
function blurOrKeypress(e) {
// split up largely for readability
if (e.target.tagName !== 'TEXTAREA') return false;
if (e.type === 'keypress' && e.code != 'Enter' && !e.ctrlKey) return false;
// a parent, a row, and a newly minted text node walk into a bar...
const parent = e.target.parentElement;
const row = parent.parentElement;
const text = document.createTextNode(e.target.value || 'Double click to translate');
/* .isConnected refers to it's state in the DOM. this was some work to try and stop an error that was
ocurring due to this being simultaneously the 'blur' 'keypress' event handler. Alas, it didn't.
If the error is really an issue, then wrapping the parent.replaceChild in a try/catch block should solve it for you.*/
if (e.target.isConnected) {
// use the dataset key + the textarea's value to update the definitions.
definitions[row.dataset.key] = e.target.value;
// write those to the local storage
localStorage.setItem('definitions', JSON.stringify(definitions));
// Or, if you are using a database, you would use some variety of AJAX/XHR call here.
// get rid of our text element
parent.replaceChild(text, e.target);
// reset the editorshown value in case we need to update this again
row.dataset.editorShown = false;
}
}
// the one thing I miss about jquery event listeners: adding multiple types of event by putting spaces
tbody.addEventListener('keypress', blurOrKeypress);
tbody.addEventListener('focusout', blurOrKeypress);
// gets the key/value pairs and maps them
tbody.append(...Object.entries(definitions).map(([word, translation]) => {
// table row, key TD and value TD cells.
const tr = document.createElement('tr');
const keyTd = document.createElement('td');
const valueTd = document.createElement('td');
// editor is not shown by default
tr.dataset.editorShown = false;
// we use this in an upper function.
tr.dataset.key = word;
// add the bold class just for visual interest. you do not need to do this.
keyTd.classList.add('bold');
// set the inner text to our word
keyTd.innerText = word;
// if it's already set, great! use that. otherwise, 'double click to translate'
valueTd.innerText = translation || 'Double click to translate';
// add these two values to our newly minted tr tag.
tr.append(keyTd, valueTd);
// return the TR tag so that the above tbody.append gets an element to actually append
return tr;
}));
/* Styling here to make myself feel better*/
textarea.full {
height: 1.5rem;
width: 100%;
padding: 3px;
line-height: 1.5rem;
}
.bold {
font-weight: bold;
}
td.bold {
font-style: unset;
}
table {
border-collapse: collapse;
width: 100%;
}
td {
color: #111;
width: 50%;
border: 1px solid lightgray;
box-sizing: border-box;
padding: 5px 10px;
border-width: 1px 0;
font-style: italic;
}
th {
border: 2px solid lightgray;
border-width: 0 0 2px;
padding-bottom: 6px;
text-decoration: underline;
font-style: unset;
font-size: 1.15rem;
}
tbody tr:nth-child(odd) {
background-color: lightgray;
}
<table>
<thead>
<tr>
<th>Word/Phrase</th>
<th>Translation</th>
</tr>
</thead>
<tbody id="definitions">
<!-- HTML generated later -->
</tbody>
</table>
I'll work on an example using contentEditable when I come back to comment this when I wake up. Hope it helps in the meantime.
Try using getElementById.
const if_in_greek = document.getElementById('translate-if');
const than_in_greek = document.getElementById('translate-than');
const else_in_greek = document.getElementById('translate-else');
if_in_greek.ondblclick = function() {
if_in_greek.innerHTML = "Translation of IF goes here"
}
than_in_greek.ondblclick = function() {
than_in_greek.innerHTML = "Translation of THAN goes here"
}
else_in_greek.ondblclick = function() {
else_in_greek.innerHTML = "Translation of ELSE goes here"
}
table,
th,
td {
border: 1px solid black;
}
<section class="allEnglishSections">
<h2>Conditioning</h2>
<table>
<tr>
<th>English</th>
<th>Greek</th>
</tr>
<tr>
<td>if</td>
<td id="translate-if">Click to translate</td>
</tr>
<tr>
<td>than</td>
<td id="translate-than">Click to translate</td>
</tr>
<tr>
<td>else</td>
<td id="translate-else">Click to translate</td>
</tr>
</table>
</section>
( UPDATED: See last section. )
One way of doing this, is to create an object which maps english words to greek words, and then add an eventlistener that catches the double click event on the table element, checks if the 'click to translate' element has been clicked and do the translation:
const dict = {
if: "αν",
than: "από",
else: "αλλιώς"
}
document.querySelector("table").addEventListener("dblclick", function(e){
// Check if the .changeable element has triggered the click event
if ( e.target.classList.contains("changeable")){
// Get the text content from the sibling element which contains the english word
const word = e.target.previousElementSibling.textContent;
// Check if we have the word in our dictionary
if ( dict[word] ){
// Change the text content of the 'click to translate' element with the greek word
e.target.textContent = dict[word];
}
}
});
table {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
<section class="allEnglishSections">
<h2>Conditioning</h2>
<table>
<tr><th>English</th><th>Greek</th></tr>
<tr><td>if</td><td class="changeable">Click to translate</td></tr>
<tr><td>than</td><td class="changeable">Click to translate</td></tr>
<tr><td>else</td><td class="changeable">Click to translate</td></tr>
</table>
</section>
Updated
Notes: As #Jhecht correcly pointed out, the querySelectorAll returns a NodeList that needs to be iterated. The easiest way to do that, is through the forEach method available to the NodeList object. The code would be written like this:
document.querySelectorAll(".changeable").forEach(function(element){
element.addEventListener( "dblclick", function(){ /* CODE HERE */ } );
});
If you see trying to attach multiple event listeners to a web page, you should reconsider your choice and instead attach a single event listener on a parent object which will be receiving all the events of its inner children. I applied this pattern in my solution.
Since the question has been updated, and the intentions are more clear, I am adding another code that enables the user to double click on the Click to translate area and allow them to enter a custom value:
document.querySelector("table").addEventListener("dblclick", function(e){
if ( e.target.classList.contains("changeable")){
e.target.setAttribute("contenteditable", true);
if ( e.target.textContent === "Click to translate" ){
e.target.textContent = "";
e.target.focus();
}
}
});
<section class="allEnglishSections">
<h2>Conditioning</h2>
<table>
<tr><th>English</th><th>Greek</th></tr>
<tr><td>if</td><td class="changeable">Click to translate</td></tr>
<tr><td>than</td><td class="changeable">Click to translate</td></tr>
<tr><td>else</td><td class="changeable">Click to translate</td></tr>
</table>
</section>
var $TABLE = $('#table');
var $BTN = $('#export-btn');
var $EXPORT = $('#export');
$('.table-add').click(function () {
var $clone = $TABLE.find('tr.hide').clone(true).removeClass('hide table-line');
$TABLE.find('table').append($clone);
});
$('.table-remove').click(function () {
$(this).parents('tr').detach();
});
$('.table-up').click(function () {
var $row = $(this).parents('tr');
if ($row.index() === 1) return; // Don't go above the header
$row.prev().before($row.get(0));
});
$('.table-down').click(function () {
var $row = $(this).parents('tr');
$row.next().after($row.get(0));
});
// A few jQuery helpers for exporting only
jQuery.fn.pop = [].pop;
jQuery.fn.shift = [].shift;
$BTN.click(function () {
var $rows = $TABLE.find('tr:not(:hidden)');
var headers = [];
var data = [];
// Get the headers (add special header logic here)
$($rows.shift()).find('th:not(:empty)').each(function () {
headers.push($(this).text().toLowerCase());
});
// Turn all existing rows into a loopable array
$rows.each(function () {
var $td = $(this).find('td');
var h = {};
// Use the headers from earlier to name our hash keys
headers.forEach(function (header, i) {
h[header] = $td.eq(i).text();
});
data.push(h);
});
// Output the result
$EXPORT.text(JSON.stringify(data));
});
.table-editable {
position: relative;
.glyphicon {
font-size: 20px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<div class="container">
<h1>HTML5 Editable Table</h1>
<p>Through the powers of <strong>contenteditable</strong> and some simple jQuery you can easily create a custom editable table. No need for a robust JavaScript library anymore these days.</p>
<ul>
<li>An editable table that exports a hash array. Dynamically compiles rows from headers</li>
<li>Simple / powerful features such as add row, remove row, move row up/down.</li>
</ul>
<div border="1" id="table" class="table-editable">
<span class="table-add glyphicon glyphicon-plus"></span>
<table style="border: 1px solid black;" class="table">
<tr>
<th>Name</th>
<th>Value</th>
<th></th>
<th></th>
</tr>
<tr>
<td contenteditable="true">Stir Fry</td>
<td contenteditable="true">stir-fry</td>
<td>
<span class="table-remove glyphicon glyphicon-remove"></span>
</td>
<td>
<span class="table-up glyphicon glyphicon-arrow-up"></span>
<span class="table-down glyphicon glyphicon-arrow-down"></span>
</td>
</tr>
<!-- This is our clonable table line -->
<tr class="hide">
<td contenteditable="true">Untitled</td>
<td contenteditable="true">undefined</td>
<td>
<span class="table-remove glyphicon glyphicon-remove"></span>
</td>
<td>
<span class="table-up glyphicon glyphicon-arrow-up"></span>
<span class="table-down glyphicon glyphicon-arrow-down"></span>
</td>
</tr>
</table>
</div>
<button id="export-btn" class="btn btn-primary">Export Data</button>
<p id="export"></p>
</div>
I am storing the html for a table in $scheduletext. I want to be able to edit any cell of the table when clicking it so I am using JQuery for the on click action. When I click on a cell it goes blank but will not allow me to type in it, what do I need to change to be able to type into this?
<html>
<body>
<div id="main">
<?php
print_r($scheduletext);
?>
</div>
<script type="text/javascript">
$('td').click(function(){
$(this).html("<contenteditable>");
});
</script>
</body>
</html>
For editing and testing purposes, since to run my code you also need the table, the CSS doesnt hurt either... I dumped it into JSfiddle to hopefully make it easier for anyone trying to give me a hand : https://jsfiddle.net/4yczepsj/
Thanks in advance!!
EDIT: For some reason JSfiddle doesnt do anything at all when clicked on, but on the live model on my site the cell goes blank when clicked, but nothing can be entered.
In calling .html("<contenteditable>") you're modifying the inner HTML of your td element to contain a <contenteditable> element (which isn't valid). What you actually want to do is set the contenteditable property:
$(this).prop('contenteditable', true);
contentEditable is an attribute.
Try this :
$(this).attr('contentEditable', true);
Content Editable is an attribute, not an element. You want to add the attribute contenteditable to the the elements you want to have editable content.
$('td').click(function(){
$(this).attr("contenteditable");
});
https://jsfiddle.net/4yczepsj/1/
$('table').on('mousedown', 'td', function (event) {
$(event.target).closest('td').prop("contentEditable", true);
});
NOTE this includes information that the other answers contain, credit to them, but I am adding a little bit more and putting it all on one place.
I made the following changes:
added tabindex so table cells are tabable.
give focus to the table cell on click.
add contenteditable attribute on focus.
select contents of table cell on focus.
remove contenteditable on blur(when the td loses focus).
function setSelection(element) {
// code for selection from http://stackoverflow.com/questions/3805852/select-all-text-in-contenteditable-div-when-it-focus-click#answer-3806004
setTimeout(function() {
var sel, range;
if (window.getSelection && document.createRange) {
range = document.createRange();
range.selectNodeContents(element);
sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
} else if (document.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
}
}, 0)
}
// add tabindex to all tds.
$('td').attr('tabindex', 0);
$('td').on('focus', function() {
$(this).attr('contenteditable', true);
setSelection(this);
}).on('blur', function() {
$(this).attr('contenteditable', false);
})
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
font-size: 90%;
}
th,
td {
padding: 8px;
}
td {
text-align: center;
}
table {
margin: 0 auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<div id="main">
<table>
<tr>
<th></th>
<th>22oz Dark</th>
<th>12ct 4oz Dark</th>
</tr>
<tr>
<th>2016-01-01</th>
<td>9785</td>
<td>2478</td>
</tr>
<tr>
<th>2016-01-02</th>
<td>8754</td>
<td>2136</td>
</tr>
<tr>
<th>2016-01-03</th>
<td>13587</td>
<td>2203</td>
</tr>
<tr>
<th>2016-01-04</th>
<td>14111</td>
<td>3297</td>
</tr>
<tr>
<th>2016-01-05</th>
<td>13212</td>
<td>3101</td>
</tr>
<tr>
<th>2016-01-06</th>
<td>16335</td>
<td>3299</td>
</tr>
<tr>
<th>2016-01-07</th>
<td>15421</td>
<td>3100</td>
</tr>
</table>
</div>
</body>
</html>
I am dynamically inserting a table row (or multiple rows) into a table upon an ajax call's return. I am looking to accomplish this by having an empty container type element inside of my html table that I can insert <tr> elements into. As I have seen from other posts, a div cannot hold a tr element, so my question is, is there a particular way that I can insert the html for row(s) into a table? It must be dynamic in nature, or in other words I need to be able to hold more than just one <tr>.
You can append to last row of table.
<table>
<tr><td>First Row</td></tr>
<tr><td>Middle Row</td></tr>
<tr><td>Last Row</td></tr>
</table>
<script>
$( "#tableid tr:last" ).append(
</script>
Assuming you aren't using jQuery, you can do something like this:
var myTable = document.getElementById('myTable').getElementsByTagName('tbody')[0];
var row = myTable.insertRow(myTable.rows.length);
You can then insert cells using insertCell on row.
Alternatively, if you have jQuery,
$("#myTable").append("<tr><td>Table Row with cell!</td></tr>");
I'm not sure why you wouldn't just use the <table> element directly, but you can use <tbody> elements as row containers within a table.
onload = function(){
document.getElementById("aButton").onclick = addRow.bind(null, "a");
document.getElementById("bButton").onclick = addRow.bind(null, "b");
}
function addRow(id) {
var r = document.getElementById(id).insertRow(-1);
var c = r.insertCell(-1);
c.innerHTML = "Row added at " + new Date().toLocaleTimeString();
}
body {
font-family: sans-serif;
font-size: 12px;
}
table {
border-collapse: collapse;
margin: 8px 0;
}
td {
border: 1px solid #ccc;
padding: 1px 2px;
}
<button id="aButton">Add row to 'A'</button>
<button id="bButton">Add row to 'B'</button>
<table>
<tbody><tr><td>Before A</td></tr></tbody>
<tbody id="a"></tbody>
<tbody>
<tr><td>After A</td></tr>
<tr><td>Before B</td></tr>
</tbody>
<tbody id="b"></tbody>
<tbody><tr><td>After B</td></tr></tbody>
</table>
I have a table where a row gets added every time I press a "Add" button. I have an "Edit" button which is placed in the first cell of the newly created row.
I want to highlight the row that is being edited. I know that I can get the current <tr> element like
var par = $(this).parent().parent();
But when I use,
par.css('border-color', 'red');
It does not change the color.
What mistake am I making and how should I highlight that particular row?
This is really about the styling of the <tr>. CSS doesn't like to style <tr>'s because they really only exist for semantics. In order to add a border to one, you need to make it display: block;.
Here is a jsFiddle and example code.
HTML
<table>
<tbody>
<tr><td>Some Content</td></tr>
<tr><td>Some Content</td></tr>
<tr>
<td>
Edit
</td>
</tr>
<tr><td>Some Content</td></tr>
<tr><td>Some Content</td></tr>
</tbody>
</table>
Javascript
$(".edit").click(function(e) {
$(this).closest('tr').toggleClass('editting');
e.preventDefault();
});
CSS
table tr {
display: block;
border: 1px solid rgba(0, 0, 0, 0);
}
.editting {
background: #FAA;
border: 1px solid red;
}
Please note how I used an rgba color to make the border opaque. There are other ways to do this, but if you leave the border off it causes the table to "jitter."
Assuming this refers to an element within the tr, then it will be better to use .closest() here
var par = $(this).closest('tr')
My table is being populated using ajax from a mysql database. I have a text field below it which adds the entered data to the database. All this works fine, but what i want to do is on adding that new row to the table, i want to dynamically show the user that their entry has been added (or simply refresh that div when new field has been added). Currently aim able to achieve that using a simple function:
function addItem(new_item, edit_table) {
var itemName = new_item;
var newRow = document.createElement('tr');
var rowCell = document.createElement('td');
rowCell.textContent = itemName;
// rowCell.addClass("grid");
newRow.appendChild(rowCell);
edit_table.appendChild(newRow);
}
However this does not let me add extra functionalities to that row e.g. i have a delete and edit icon upon hover. So by using this function i am able to show the new row added but its not exactly functioning. So i recon the better option would be to refresh that div when this happens.
I am using the following code to call the addItems method:
$('#b_go').click(function(){
//some other conditions, then using ajax to post the data
success: function (data) {
if(data == 'success') {
addItem(new_row, selected_table);
}
HTML for the table:
<table class="table table-striped table-bordered home" id="subjects">
<thead>
<th>Subject Title</th>
</thead>
<tbody>
<?php
$sql = mysql_query("select Title from Subject");
while($row = mysql_fetch_array($sql)) {
echo "<tr><td>";
echo $row['Title']?> <!--using html to output buttons for delete and edit for each row-->
<?;echo "</td></tr>";
}
?>
</tbody>
</table>
Css for the above table:
.table {
width: 100%;
margin-bottom: 18px;
}
.table th, .table td {
padding: 8px;
line-height: 18px;
text-align: left;
border-top: 1px solid #ddd;
}
.table th {
font-weight: bold;
vertical-align: bottom;
}
.table td {
vertical-align: top;
}
.table thead:first-child tr th, .table thead:first-child tr td {
border-top: 0;
}
.table-striped tbody tr:nth-child(odd) td, .table-striped tbody tr:nth-child(odd) th {
background-color: #f9f9f9;
}
.home {
width: 100%;
border-collapse: collapse;
text-align: left;
}
.home th {
font-size: 15px;
font-weight: 400;
color: #039;
padding: 10px 8px;
border-bottom: 2px solid #6678b1;
}
.home td {
line-height:15px;
border-bottom: 1px solid #E0E0E0;
border-left: 1px solid #E0E0E0;
font-size: 12px;
color: #404040;
padding: 9px 8px 3px 8px;
}
.home tbody tr:hover td {
background-color:#E6E6FF;
cursor: pointer;
}
Any help would be appreciated!
I have to leave work, but here's a quick and dirty answer.
When adding new elements dynamically that have pre-existing functions/events/actions that are already bound, the new elements will not automatically inherent the events/actions of their siblings. I recommend using jQuery for something like this.
For jQuery versions greater than 1.3 - use jQuery LIVE() function:
http://api.jquery.com/live/
Description: This will map the data passed to your new event handlers needed
For jQuery versions 1.7 or higher - use jquery ON() function:
http://api.jquery.com/on/
Description: method attaches event handlers to the currently selected set of elements in the jQuery object. This will attach the event handler to any new element you create.
Update: 11:57 AM Tuesday: Based on your comment. You need to use bind('click') or on('') function when you SUBMIT the form.
// First : Change your click code to this. You'll need the bind() function here. This will make it so your events will bind to each new row
$('#b_go').bind("click", function(){
//some other conditions, then using ajax to post the data
success: function (data) {
if(data == 'success') {
addItem(new_row, selected_table);
}
// Change your function to this:
function addItem(new_item, edit_table) {
var itemName = new_item;
var newRow = document.createElement('tr');
var rowCell = document.createElement('td');
rowCell.textContent = itemName;
$(rowCell).addClass("grid"); // Make sure GRID is the class being applied to your other TDs/TRs etc
newRow.appendChild(rowCell);
edit_table.appendChild(newRow);
$(edit_table +' tr:odd td').css('background','#f9f9f9'); // Set color for all odd rows.
}
HOW TO RELOAD TABLE:
STEP #1 - Create a new < div > layer with an ID #getDataGrid. THIS MUST WRAP AROUND YOUR TABLE.
STEP #2 - Create a new file like : data-grid.php and include the following HTML. Please also include any PHP business logic that would be needed to make the appropriate database calls to make this code successful:
<table class="table table-striped table-bordered home" id="subjects">
<thead>
<th>Subject Title</th>
</thead>
<tbody>
<?php
$sql = mysql_query("select Title from Subject");
while($row = mysql_fetch_array($sql)) {
echo "<tr><td>";
echo $row['Title']?> <!--using html to output buttons for delete and edit for each row-->
<?;echo "</td></tr>";
}
?>
</tbody>
</table>
STEP #3 : Update your click function:
$('#b_go').bind("click", function(){
//some other conditions, then using ajax to post the data
success: function (data) {
if(data == 'success') {
addItem(new_row, selected_table);
$.get('data-grid.php', function(getTable) {
$('#getDataGrid').html(getTable);
});
}
EXPLANATION. What this is doing on your click function is using jQuery to essentially perform a "GET" (just as PHP GET would perform). We are retrieveing our newly created data-grid.php file, and then PLACING the contents into the #getDataGrid div layer we created that wraps around the table. What this will do will actually wipe out the currently displayed table with the new displayed table.
Instead of only partially using a DOM approach, create the TD in javascript too.
function addItem(itemName) {
var newRow = document.createElement('tr');
var rowCell = documentcreateElement('td');
rowCell.textContent = itemName;
newRow.appendChild(rowCell);
document.getElementById('subjects').appendChild(newRow);
}
Do you have JQuery? You can make something similar in JS, but here's the concept.
Create a template of the new row in HTML
Add the row to the DB.
Add the row to the table:
var row = $("#myRowTemplate").clone();
row.attr("id", "");
//Bind the new data
row.find(".fname").text("Jack");
row.find(".lname").text("Dean");
//Bind a click event on the first name
row.find(".fname").click(function(){alert('Hi!');});
$("#myTable").find("tbody :first").append(row);
Hopes that's helps :)