Swapping 2 html table elements - javascript

So I made this sliding puzzle using html, css and JavaScript:
this is a table and my question is how do I swap 2 table elements?
Let's say the one with the face (id = tile-2) and the white empy one (id = empty)

Hmm... try this:
https://jsfiddle.net/h7sp1ey8/
<button onclick='swap();'>
Swap
</button>
<table>
<tr>
<td id='f1'>
Contents of td 1
</td>
</tr>
<tr>
<td id='f2'>
Contents of t2
</td>
</tr>
</table>
<script>
function swap()
{
var f1 =document.getElementById('f1');
var f2=document.getElementById('f2');
var initialinner = f1.innerHTML;
f1.innerHTML=f2.innerHTML;
f2.innerHTML=initialinner;
}
</script>
Post your code if you want an exact solution. Here is how you program should work:
get id of box to swap
get id of box to swap to
swap them using method I gave in jsfiddle

Related

Filling an html table through javascript

This is a project for uni for PHP/JavaScript. The concept is that we create an empty table, then get an input from the user and put this text in the odd lines of the table. Thing is, I've created the table and I can't get to pass the text to multiple paragraphs located inside the cells of the odd lines. I tried with getElementById to fill the cell's paragraph but I found out that each paragraph needs a unique id and so it fills only the first cell. Then I tried getElementsByClassName but this doesn't work cause there's no .innerHTML for it. Basically, all I want to do is take the same input and distribute it to multiple paragraphs or directly to the cells if there's a way. Code is at the bottom. The script doesn't work right now, I just left it in.
Thank you
<body>
<p class="p1">5th excercise Php</p><br><br><br>
<input type="button" id="btn" value="Give Input"><br><br>
<?php
echo "<table>";
for($i=1;$i<=10;$i++){
echo "<tr>";
for($j=1;$j<=10;$j++){
if($i % 2 == 0){
echo "<td style='background-color:green;color:green;'>"."<p>"."."."</p>"."</td>";
}
else{
echo "<td style='background-color:red; color:red;'>"."<p>"."."."</p>"."</td>";
}
}
echo "</tr>";
}
echo "</table>";
?>
<script>
document.getElementById("btn").onclick= function(){f()}
function f(){
var x= prompt("Give input");
document.getElementById("").style.color = "black";
document.getElementById("").innerHTML= x;
}
</script>
</body>
Since this is a homework assignment from school, I won't share any code samples.
Solution 1:
I would consider that the php loop already knows which rows are odd and even, so leveraging this with a class attribute would be easy enough.
Then use getElementsByClassName() to create a variable that can be iterated over in the javascript to fill in the values.
Solution 2:
Use getElementsByTagName() in your javascript to iterate over the TR's and calculate which rows are even or odd and make changes accordingly to the TD elements within .
This requires more work but will teach you more about how the getElement-style functions work.
You could add an id element to your paragraphs like this
"<p id='id_{$j}'>"
The 'id_{$j}' part will lead to to strings like id_0, id_1, etc.
Then you'd have to iterate through all columns in the JavaScript part and using those ids to set their innerHtml.
The difficulty you can meet, is that getElementByClassName renders an HTMLCollection, that is a pseudo collection but not something you can easily iterates over.
But you can steal (JS power!) the behavior of Array to that purpose. Like that:
const allCells = document.getElementsByClassName("first");
Array.prototype.forEach.call(allCells, function(elt) {
elt.innerHTML = choice;
});
So you just have to add a class name ("first" in my example) in the table cell you want (= the odd lines cells).
This can be achieved in different ways. Here i am giving you simple solution which simply add two classes even and odd in paragraph tag and using querySelector we can get all odd rows and add innerHtml easily.
document.getElementById("btn").onclick = function() {
f()
}
function f() {
var x = prompt("Give input");
document.querySelectorAll('.odd').forEach(p => {
p.innerHTML = x;
p.style.color='black';
});
}
<body>
<p class="p1">5th excercise Php</p><br><br><br>
<input type="button" id="btn" value="Give Input"><br><br>
<table>
<tr>
<td style='background-color:green;color:green;'>
<p class='even'></p>
</td>
</tr>
<tr>
<td style='background-color:red;color:red;'>
<p class='odd'></p>
</td>
</tr>
<tr>
<td style='background-color:green;color:green;'>
<p class='even'></p>
</td>
</tr>
<tr>
<td style='background-color:red;color:red;'>
<p class='odd'></p>
</td>
</tr>
<tr>
<td style='background-color:green;color:green;'>
<p class='even'></p>
</td>
</tr>
<tr>
<td style='background-color:red;color:red;'>
<p class='odd'></p>
</td>
</tr>
</table>
</body>
Here i have removed php code as i am not aware how to add it on stackoverflow but you can add your rows using php and it will work for you.

Get data of first cell of clicked table row [duplicate]

This question already has answers here:
JavaScript - Get data of first cell of selected table row
(3 answers)
Closed 8 years ago.
<table border="1" cellpadding="5" id="newtable">
<tr>
<th>Room No</th>
<th>AC</th>
<th>Deluxe</th>
<th>Tariff</th>
</tr>
<c:forEach var="room" items="${myrooms}">
<tr bgcolor="#4B476F" onMouseOver="this.bgColor='gold';" onMouseOut="this.bgColor='#4B476F';">
<td class="nr"><c:out value="${room.roomno}" /></td>
<td><c:out value="${room.ac}" /></td>
<td><c:out value="${room.deluxe}" /></td>
<td>₹<c:out value="${room.price}" /></td>
<td><button type="button" class="mybutton" onclick="rowFunction()">Pay</button> </td>
</tr>
</c:forEach>
</table>
On clicking the button corresponding to every row, I want my script to return the Room number i.e. the first cell data of the row. I have tried a lot of things after referring various articles on the Internet. Nothing seems to work. Please help. AND I REQUEST YOU TO POST NO JQUERY SOLUTIONS. ONLY JAVASCRIPT.
You can pass the clicked element to your function:
<td><button type="button" class="mybutton" onclick="rowFunction(this)">Pay</button> </td>
and traverse the DOM:
function rowFunction(el) {
var n = el.parentNode.parentNode.cells[0].textContent;
// ...
}
You can use the HTML5 function document.querySelectorAll to get a list of your buttons, then add an event listener to them that will allow you to access their parent row, and get its first cell.
var buttons = document.querySelectorAll('#newtable tbody .mybutton');
function buttonClicked(e) {
var button = this,
cell = button.parentElement,
row = cell.parentElement,
firstCell = row.querySelector('td');
alert(firstCell.innerHTML);
}
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', buttonClicked);
}
Here is the fiddle I used to verify my code. Also, consider using CSS instead of JavaScript to style your rows' color and hover color. It will be cleaner and more maintainable in the long term.
Use Like
$(".mybutton").click(function(){
alert($(this).parent().siblings().eq(0).text());
});
DEMO

Adding event handlers to each table row that will affect only that table row?

This isn't actually something I'm currently attempting to do; it just occurred to me while working with another table that I have no idea how I'd go about doing it, and the entire time on the train ride home I was puzzling over different solutions, none of which I could imagine working.
Imagine this situation: there is a table of 50 rows. On each row is a button. When clicked, this button should do something to the row it's on -- say, make all its text strikethrough, or make an AJAX call with the first cell's value, or something.
How would you go about binding those event handlers?
My initial thought was something like
buttons = document.getElementsByTagName("input");
rows = document.getElementsByTagName("tr");
for (i=0;i<buttons.length;i++) {
buttons[i].addEventListener('click',function() {
makeAjaxCall(rows[i]);
});
};
That is,
For each button in the document,
Add an event handler to that button,
Which will makeAjaxCall with the data of the row whose number corresponds to the button.
The problem, of course, being that makeAjaxCall will check the value of i when it's invoked, by which time, i is equal to buttons.length, and so the function will only ever work on the final row of the table.
So I suppose you'd need to find some way to actually hard-code the current value of i within the function handler... and that's something I don't even think is possible. Is it? How would you actually do something like this?
You can refer to the button object you are adding the event listener to using 'this'
Given the table in this format
<table>
<tr>
<td> <input type='button'> </td>
<td> 1st <td>
</tr>
<tr>
<td> <input type='button'> </td>
<td> 2nd <td>
</tr>
<tr>
<td> <input type='button'> </td>
<td> 3rd <td>
</tr>
</table>
The following code will allow you to access the data in the next cell, shown using console.log() rather than any ajax calls of course.
buttons = document.getElementsByTagName("input");
for (i=0;i<buttons.length;i++) {
buttons[i].addEventListener('click',function() {
makeAjaxCall(this);
});
};
function makeAjaxCall(btn) {
var sib=btn.parentNode.nextSibling;
while (sib.nodeName !='TD') {
sib=sib.nextSibling;
}
console.log(sib.innerHTML);
}
This can be extended to find any data in the row.
This section
while (sib.nodeName !='TD') {
sib=sib.nextSibling;
}
skips any extraneous characters (white space etc) between cells.
Fiddle Here
Interesting problem. I would go about doing it the way #kennebec suggests in the comment above.
Here is the fiddle: http://jsfiddle.net/u988D/
First, a slight change in markup to add data attributes
HTML
<table>
<tr>
<td data-to-json="id">1</td>
<td data-to-json="text">Lorem ipsum dolor.</td>
<td><button type="button">Click Me</button></td>
</tr>
<tr>
<td data-to-json="id">2</td>
<td data-to-json="text">Lorem ipsum dolor.</td>
<td><button type="button">Click Me</button></td>
</tr>
<tr>
<td data-to-json="id">3</td>
<td data-to-json="text">Lorem ipsum dolor.</td>
<td><button type="button">Click Me</button></td>
</tr>
</table>
Then the javascript. Probably can be optimized a bit more.
JS
var table = document.querySelector("table")
table.addEventListener("click", function(e) {
var element = e.target,
parent
//If the element is a button
if ( element && element.nodeName == "BUTTON" ) {
parent = element.parentNode
//Find the closest parent that is a TR
while ( parent.nodeName !== "TR" ) {
parent = parent.parentNode
}
//Convert Row to JSON
var json = {},
child
for ( var i = 0, _len = parent.children.length; i < _len; i++ ) {
child = parent.children[i]
if ( child.hasAttribute("data-to-json") ) json[child.getAttribute("data-to-json")] = child.innerText
}
// Do your AJAX stuff here
console.log(json)
}
})

Is it possible to replace a table cell without deleting it with javascript or jQuery?

Is it possible to replace a table cell without deleting it with javascript or jQuery? For example, if I have a table with several rows, each row having 5 cells, could I change the first cell of the first row through assignment instead of removing the cell and then inserting a new one?
EDIT (simplified):
<table>
<tr id="currentRowId1" name="currentRowId1">
<td style="text-align:center">
</td>
<td style="text-align:center">
</td>
<td style="text-align:center">
<input type="submit" onclick="changeOrder()" />
</td>
<td style="text-align:center">
</td>
<td>
</td>
</tr>
<tr id="currentRowId2" name="currentRowId2">
<td style="text-align:center">
</td>
<td style="text-align:center">
</td>
<td style="text-align:center">
<input type="submit" onclick="changeOrder()" />
</td>
<td style="text-align:center">
</td>
<td>
</td>
</tr>
</table>
js
function changeOrder(){
var row = document.getElementById("currentRowId1");
var otherRow = document.getElementById("currentRowId2");
row.cells[0] = otherRow.cells[0];
}
There is acutally no need to work with innerHTML here. You could replace the two elements like this:
var
a = document.getElementById('currentRowId1').cells[0],
e = document.getElementById('currentRowId2').cells[0],
e1 = e.nextSibling;
a.parentNode.replaceChild(e, a);
e1.parentNode.insertBefore(a, e1);
demo: http://jsfiddle.net/X4zzb/1/
There are multiple ways to do this. You can set the inner html of the cell as fabianhjr pointed out. You can also build a new element in javascript/jquery and use jquery's replaceWith() method.
You can use other jquery methods that will replace the cells, clone() and before() or after() I know this isn't what you asked for just pointing out other options.
Example #1:
var me = $("#cellId");
var newHtml = $("<div>blah blah blah</div>");
me.replaceWith(newHtml);
Example #2:
var me = $("#cellId");
var clone = me.clone();
// do some cool things with the clone change html whatever
me.replaceWith(clone);
If you just want to change whats inside it you can use..
document.getElementById('nameofyourcell').innerHTML = 'content';
You can't just assign the cell equal to something else like you tried in this line:
row.cells[0] = otherRow.cells[0]; // doesn't work
However, once you have a reference to the cell you can change what is inside it, e.g., to copy the contents from one cell to another:
row.cells[0].innerHTML = otherRow.cells[0].innerHTML;
You can also create, amend or remove the children of the cell via the reference to the cell.
If you are using jQuery there are a number of methods that achieve the same sort of thing, e.g., the following is equivalent to the above (but less efficient):
$(row.cells[0]).html( $(otherRow.cells[0].html() );

Combining Rows in Javascript

I'm looking for some help on the Javascript angle of this problem. I have a table that goes like...
<table>
<tbody>
<tr> (Row 1)
<td colspan="3">
<p>This Says Something</p>
</td>
</tr>
<tr> (Row 1a)
<td>
<select option>
</td>
</tr>
<tr> (Row 2)
<td colspan="3">
<p>This Says Something</p>
</td>
</tr>
<tr> (Row 2a)
<td>
<select option>
</td>
</tr>
<tr>
<td colspan="3">
<p>This Says Something</p>
</td>
</tr>
<tr>
<td>
<select option>
</td>
</tr>
<tbody>
</table>
There are actually more like 20 rows and row a's but I didn't think I'd want to copy them all.
I basically need to add a container row (a single row) around every two rows (# and #a). Something like:
<tr> (Container Row 1)
<td>
+<tr> (Row 1)
+<tr> (Row 1a)
</td>
</tr>
It needs to cycle through the whole table. Somehow it has to retain the HTML data inside since all of the "a"s have options.
I hope this makes sense...
Any help would be greatly appreciated, as I'm at a loss. I'm novice at best at javascript and am struggling my way through the DOM and TOM methods.
Thank you so much in advance for any help or headway.
[EDIT] For clarification, the table is already constructed from a third party database, I am editing it after it's constructed. I guess this clarifies why it would have to be javascript to be done through the DOM.
Embed another table:
<tr> (Container Row 1)
<td>
<table>
<tr><td>(Row 1a)</td></tr>
<tr><td>(Row 1b)</td></tr>
</table>
</td>
</tr>
Or if you are wanting to do that via Javascript, you can give the parent <td> an id and set it's innerHTML.
<tr> (Container Row 1)
<td id='rowX'>
</td>
</tr>
document.getElementById('rowX').innertHTML = "<table><tr><td>(Row 1a)</td></tr><tr><td>(Row 1b)</td></tr></table>";
As mentioned in another answer you can't add tr elements directly in td like you are trying.
You would first create an inner table.
If you were using jQuery you would do something like this:
//setup some click actions just to prove that they remain attached even after moving
$('#outterTable tr').click(function(){
alert('You clicked on row: '+$(this).text());
});
//update the table (group each even row with the one after it)
$('#outterTable tr:even').each(function() {
var $tr1 = $(this),
$tr2 = $tr1.next('tr'),
$t = $('<table></table>');
$('<tr></tr>').append($t).insertBefore($tr1);
//click actions will remain attached
//if that is not required, than use $tr1.remove()
$t.append($tr1).append($tr2);
});​
See this live jsFiddle example.
without jQuery it may look like that:
<script type="text/javascript">
<!--
function fx(table)
{
var tmp=document.createElement('table');
tmp.appendChild(document.createElement('tbody'))
while(table.rows.length)
{
if(table.rows.length%2==0)
{
var wrapper=tmp.lastChild.appendChild(document.createElement('tr'));
wrapper.appendChild(document.createElement('td'));
wrapper.getElementsByTagName('TD')[0].appendChild(document.createElement('table'));
wrapper.getElementsByTagName('TD')[0].lastChild.appendChild(document.createElement('tbody'));
}
wrapper.getElementsByTagName('TD')[0].lastChild.lastChild.appendChild(table.getElementsByTagName('TR')[0])
}
table.parentNode.replaceChild(tmp,table);
tmp.setAttribute('border',1);
}
window.onload=function(){fx(document.getElementsByTagName('table')[0]);}
//-->
</script>
Example#jsFiddle
But: why do you need this grouping?
If the only benefit is a visible grouping I would prefer to do this by setting the borders of the cells .
Give all cells a border and to the even a border-top:none / to the odd a border-bottom: none

Categories

Resources