Move html td element using JavaScript - javascript

I am currently creating a basic javascript car racer whereby the car is a an HTML tr element placed in a td. I want to have it that when I push the key "e" player one will move and if the "d" key is pressed player 2 will move. I want to do this by using an eventListener to have it that when the key is pressed the car will move from its original td element to the next td element and remove the car from the previous. This will make it look like the car has moved. I do not know how to have this element moved using the key press but my code is below. Thanks for the help!
document.addEventListener('DOMContentLoaded', function() {
//run the code
function move = function(player){
/*
psuedo code:
if Keypressed = "E"
then move first car forward
else d move second car forward
if player1 has moved to the end
then end the game
else for player 2
set a var to add up the total moves, user can then easily adapted the length of the road and have it match
the var total.
*/
}
function keyPress = function(e){
if (e.charCode == "e"){
//move player one
}
else if (e.charCode == "d"){
//move player 2
}
else{
alert("Invalid key stroke");
}
}
})
.racer_table td {
background-color: white;
height: 50px;
width: 50px;
border: 5px;
border-color: black;
}
.racer_table td.active {
background-color: black;
}
<link rel="stylesheet" type = "text/css" href="style.css">
<script type="text/javascript" src="racer.js"> </script>
<body>
<table class="racer_table">
<tr id="player1_strip">
<td class="active"></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr id="player2_strip">
<td class="active"></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</body>
</html>

I would set a var with the object then use jquery's 'next' function for sibling object.
if you add this button <button id="x1"/> this will work as an example:
$("#x1").click(function() {
var active = $("#player1_strip").children(".active");
active.next().addClass("active");
active.removeClass("active");
});

No jQuery solution. There is probably some other solution without need for an id, but I think this one is cleaner. You add an id to each <td> like 'tile1e', 'tile2e' etc. Then, your keypress function would look like this:
function keyPress = function(e){
if (e.charCode == "e"){
var tile = document.querySelector("#player1_strip > .active"); // get player tile
var nextTile = 'tile' + (tile.id[4] + 1) + 'e'; // get id of the next tile
tile.className = "";
document.getElementById(nextTile).className = "active";
}
else if (e.charCode == "d"){
var tile = document.querySelector("#player2_strip > .active"); // get player tile
var nextTile = 'tile' + (tile.id[4] + 1) + 'd'; // get id of the next tile
tile.className = "";
document.getElementById(nextTile).className = "active";
}
else{
alert("Invalid key stroke");
}
}
and the table something like this
<table class="racer_table">
<tr id="player1_strip">
<td id='tile0e' class="active"></td>
<td id='tile1e'></td>
<td id='tile2e'></td> <!-- move active to the next empty td element -->
<td id='tile3e'></td>
<td id='tile4e'></td>
<td id='tile5e'></td>
<td id='tile6e'></td>
<td id='tile7e'></td>
<td id='tile8e'></td>
<td id='tile9e'></td>
</tr>
<tr id="player2_strip">
<td id='tile0d' class="active"></td>
<td id='tile1d'></td>
<td id='tile2d'></td>
<td id='tile3d'></td>
<td id='tile4d'></td>
<td id='tile5d'></td>
<td id='tile6d'></td>
<td id='tile7d'></td>
<td id='tile8d'></td>
<td id='tile9d'></td>
</tr>
</table>
I hope you get the idea behind this.
But feel free to use the jQuery solution if you are comfortable with that, it is so much simpler.

Related

Border around specific set of cells

I have done the component with table like this.
The problem is, when user chooses a range of cell like this, how can i put the border around that groups( the border likes the first one in group of cells) ?
I tried to use different class for each cell's border style, but it seems imposible, because i dont know which cell user will pick, how big the group of cell's size will be
Thank a lot and sorry about my English
Had the same task this week and sadly the question did not hold any answer, except for external libraries. So here is my approach.
In the following example I am using the class Marked to mark the cells as being selected and the dataset to flag which cells define which outer bound(s).
;window.onload = (event) => {
//REM: Assign mousedown event
document.querySelector('table').addEventListener('mousedown',_onMouseDownTable, false)
};
/***
* MouseDown event for the table, handles cells
*/
function _onMouseDownTable(event){
//REM: Checking for 'td'...
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
const tObject = {Down: event.target};
//REM: ...add event for marking cells
this.onmousemove = ((object, event) => {
if(
event.target &&
event.target.tagName.toLowerCase() === 'td'
){
object.Move = event.target
}
else{
delete object.Move
};
_markCells(object.Down, object.Move)
}).bind(null, tObject);
//REM: ...add event for finish marking cells
this.onmouseleave = this.onmouseup = ((object, event) => {
this.onmouseleave = this.onmousemove = this.onmouseup = null;
}).bind(null, tObject)
}
};
/***
* Marks cells between cell a and cell b
*/
function _markCells(a, b){
if(a && b){
//REM: Table of a (thus usually b)
const tTable = a.closest('table');
//REM: Remove existing marks and border data
tTable.querySelectorAll('td.Marked, td[data-bounds-left], td[data-bounds-right], td[data-bounds-top], td[data-bounds-bottom]').forEach((td) => {
td.classList.remove('Marked');
delete td.dataset.boundsLeft;
delete td.dataset.boundsRight;
delete td.dataset.boundsTop;
delete td.dataset.boundsBottom
});
//REM: The lowest (top to bottom / left to right) and the largest coordinate
const
tMaxColumn = Math.max(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMaxRow = Math.max(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex)),
tMinColumn = Math.min(Number(a.dataset.columnIndex), Number(b.dataset.columnIndex)),
tMinRow = Math.min(Number(a.dataset.rowIndex), Number(b.dataset.rowIndex));
//REM: Mark all cells between Min and Max
for(let row = tMinRow; row <= tMaxRow; row++){
for(let column = tMinColumn; column <= tMaxColumn; column++){
const tCell = tTable.querySelector(`td[data-row-index='${row}'][data-column-index='${column}']`);
if(tCell){
//REM: If outer left bound...
if(column === tMinColumn){
tCell.dataset.boundsLeft = true
};
//REM: If outer right bound...
if(column === tMaxColumn){
tCell.dataset.boundsRight = true
};
//REM: If outer top bound...
if(row === tMinRow){
tCell.dataset.boundsTop = true
};
//REM: If outer bottom bound...
if(row === tMaxRow){
tCell.dataset.boundsBottom = true
};
//REM: Set cell as marked
tCell.classList.add('Marked')
}
}
}
}
};
td{
border: 2px solid #000;
background-color: grey;
height: 25px;
width: 200px;
}
td.Marked{
background-color: #1e90ff
}
td.Marked[data-bounds-left]{
border-left-color: red
}
td.Marked[data-bounds-right]{
border-right-color: red
}
td.Marked[data-bounds-top]{
border-top-color: red
}
td.Marked[data-bounds-bottom]{
border-bottom-color: red
}
<table>
<tbody>
<tr>
<td data-column-index="0" data-row-index="0"></td>
<td data-column-index="1" data-row-index="0"></td>
<td data-column-index="2" data-row-index="0"></td>
<td data-column-index="3" data-row-index="0"></td>
<td data-column-index="4" data-row-index="0"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="1"></td>
<td data-column-index="1" data-row-index="1"></td>
<td data-column-index="2" data-row-index="1"></td>
<td data-column-index="3" data-row-index="1"></td>
<td data-column-index="4" data-row-index="1"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="2"></td>
<td data-column-index="1" data-row-index="2"></td>
<td data-column-index="2" data-row-index="2"></td>
<td data-column-index="3" data-row-index="2"></td>
<td data-column-index="4" data-row-index="2"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="3"></td>
<td data-column-index="1" data-row-index="3"></td>
<td data-column-index="2" data-row-index="3"></td>
<td data-column-index="3" data-row-index="3"></td>
<td data-column-index="4" data-row-index="3"></td>
</tr>
<tr>
<td data-column-index="0" data-row-index="4"></td>
<td data-column-index="1" data-row-index="4"></td>
<td data-column-index="2" data-row-index="4"></td>
<td data-column-index="3" data-row-index="4"></td>
<td data-column-index="4" data-row-index="4"></td>
</tr>
</tbody>
</table>
Note that this is just a draft and not a finished solution, since it depends heavily on the already existing implementation and use-case.

How to loop through a table and get the td elements to follow a condition

I just want make so it the tr hides when the td does not follow the requirements, tried with jQuery and JavaScript, don't know what's wrong.
$(document).ready(function(){
$("td").each(function() {
var id = $(this).attr("price_search");
if (id > value4 && id < value5) {
$(this).hide;
}
else {
$(this).hide;
}
});
});
You can do this.
Hope this will help you.
$(document).ready(function() {
var value4 = 2;
var value5 = 4;
$("td").each(function() {
var id = $(this).attr("price_search");
if (id > value4 && id < value5) {
$(this).hide();
} else {
$(this).show();
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td price_search="3">10</td>
<td price_search="2">20</td>
<td price_search="3">30</td>
</tr>
</table>
I am going to go out on a limb here and make broad assumptions on content not in the question.
Your .hide; is invalid syntax
You are missing value for two variables value4 and value4 which frankly are not well named variables at all. I will make an assumption that those are better named and that they come from somewhere during the page rendering.
I make an assumption that you have something you want to filter/hide by those upper/lower price points.
I make the assumption the attribute might contain values that need to be parsed (not a number as they are)
var lowerPricePoint = .45;
var upperPricePoint = 5.25;
$(function() {
$("td").filter('[price_search]').each(function() {
// parse out a price from perhaps formatted values
let price = Number.parseFloat($(this).attr("price_search").replace(/\$|,/g, ''));
// toggle visibility of the row
$(this).closest('tr').toggle(price > lowerPricePoint && price < upperPricePoint);
});
});
td {
border: solid black 1px;
padding: 0.4em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<table>
<tr>
<td>Wear it</td>
<td price_search="123.13">Shoes</td>
</tr>
<tr>
<td>Drive it</td>
<td price_search="$23,123.13">Car</td>
</tr>
<tr>
<td>Drink it</td>
<td price_search="3.13">Beet Juice</td>
</tr>
<tr>
<td>Eat it</td>
<td price_search="12.13">Can of expensive corn</td>
</tr>
<tr>
<td>Cheap</td>
<td price_search="35">Radish</td>
</tr>
<tr>
<td>Use it</td>
<td price_search="1.45">Paper towel</td>
</tr>
<tr>
<td>Plain</td>
<td price_search="$1.87">Butter</td>
</tr>
<tr>
<td>Herb</td>
<td price_search="$2.45">Butter</td>
</tr>
<tr>
<td>Cheap</td>
<td price_search="15">Gum</td>
</tr>
</table>

javascript colspan dynamically while delete cell?

could anyone help me on my code?
I try to make a sample code on the following action:
1. when the user click on the button, the "hello" will take cell 1 and cell 2 while the other cell 3 to 10 will remain.
2. When the user click on the button again, nothing happen.
I try to set a flag to false after the user click on it to let nothing happen if user click again; however, it doesn't work at all. The user can click until the first row's cells deleted just left "hello".
Any solution in javascript or JQuery? I try to search for static variable in javascript but seem impossible.
Thank you in advance.
var flag = false;
function clickhere(){
if(flag = true){
var cell = document.getElementById('a');
document.getElementById("row").deleteCell(1);
cell.setAttribute("colspan", 2);
cell.innerHTML = "hello";
flag=false;
}
}
<table border="1">
<tr id="row">
<td id="a">1</td>
<td id="b">2</td>
<td id="c">3</td>
<td id="d">4</td>
<td id="e">5</td>
</tr>
<tr>
<td id="f">6</td>
<td id="g">7</td>
<td id="h">8</td>
<td id="i">9</td>
<td id="j">10</td>
</tr>
</table>
<input type="button" value="Click" onclick="clickhere();"/>
You have a couple of opportunities to address. Firstly, your if is doing an assignment rather than a a comparison. Since your flag is a boolean we can use it directly. Secondly, your initial assignment and the one at the end of the function should probably be opposite.
Here is one way you might correct things.
var flag = false;
function clickhere(){
if(flag){ return; }
flag = true;
var cell = document.getElementById('a');
document.getElementById("row").deleteCell(1);
cell.setAttribute("colspan", 2);
cell.innerHTML = "hello";
}
<table border="1">
<tr id="row">
<td id="a">1</td>
<td id="b">2</td>
<td id="c">3</td>
<td id="d">4</td>
<td id="e">5</td>
</tr>
<tr>
<td id="f">6</td>
<td id="g">7</td>
<td id="h">8</td>
<td id="i">9</td>
<td id="j">10</td>
</tr>
</table>
<input type="button" value="Click" onclick="clickhere();" />

jQuery selecting direct "parents", not similar

I got a fixed structure of a table like this one:
<table>
<tr><td class="lvl-0">1</td><tr>
<tr><td class="lvl-1">2</td><tr>
<tr><td class="lvl-2">3</td><tr>
<tr><td class="lvl-2">4</td><tr>
<tr><td class="lvl-2">5</td><tr>
<tr><td class="lvl-1">6</td><tr>
<tr><td class="lvl-2">7</td><tr>
<tr><td class="lvl-2 selected">8</td><tr>
<tr><td class="lvl-2">9</td><tr>
</table>
I want to select every lvl parent.
That means I want to select every lvl previously from the selected. Except similar. That means in this example it would be 6 and 1
I tried it with this:
var ss = [];
for(var l = lvl; l <= 5; l++){
ss.push('td.lvl-'+l);
}
var ul = jQuery('table').find(ss.join(',')).closest('tr');
var pa = jQuery('.selected').closest('tr').prevAll('tr').not(ul);
But it also select number 2
// EDIT
I have a jsfiddle
http://jsfiddle.net/g7yhwojg/3/ selected should be:
14
13
10
1
I got it on my own.
var lvls = [];
pa = pa.filter(function(){
var pc = jQuery(this).find('td').attr('class');
if(lvls.indexOf(pc) == -1){
console.log(pc);
lvls.push(pc);
return true;
}
return false;
});
http://jsfiddle.net/g7yhwojg/11/
I looped through all the upper elemnts and took everytime only the first.
While you've already posted your own answer, I thought I'd offer an alternative, in case you're interested:
// caching the selected element (selecting by its id):
var selected = $('#selected'),
// caching the regular expression, in case it might be
// be needed again later; this matches a serious of
// one or more (+) numbers (\d) at the end of the
// string ($):
levelRegex = /\d+$/,
// finding the numbers at the end of the selected
// element's class attribute, and using parseInt()
// to convert that to a number in base-10:
selectedLevel = parseInt(selected.attr('class').match(levelRegex), 10),
// caching the selected element's closest ancestor
// <tr> element:
selectedParent = selected.closest('tr'),
// caching the <tr> elements before the selectedParent:
rowsBefore = selectedParent.prevAll(),
// using map() to iterate over those elements and
// if their child <td> element has a class equal to
// 'lvl-' + (selectedLevel - 1)
// we first decrement selectedLevel, and then
// return the text of the current <tr> element;
// decrementing here means we can only ever
// retrieve the first instance of an element
// with a 'lower' level:
pseudoParents = rowsBefore.map(function (i) {
if ($(this).find('td').hasClass('lvl-' + (selectedLevel - 1))) {
--selectedLevel;
return this.textContent;
}
// converting the 'map' into a native Array:
}).get();
console.log(pseudoParents);
// ["14", "13", "10", "1"]
var selected = $('#selected'),
levelRegex = /\d+$/,
selectedLevel = parseInt(selected.attr('class').match(levelRegex), 10),
selectedParent = selected.closest('tr'),
rowsBefore = selectedParent.prevAll(),
pseudoParents = rowsBefore.map(function(i) {
if ($(this).find('td').hasClass('lvl-' + (selectedLevel - 1))) {
--selectedLevel;
return this.textContent.trim();
}
}).get();
// snippet logs to the bottom of the result panel:
snippet.log(pseudoParents);
// logs to the console (obviously):
console.log(pseudoParents);
// ["14", "13", "10", "1"]
.lvl-0 {
padding-left: 10px;
}
.lvl-1 {
padding-left: 30px;
}
.lvl-2 {
padding-left: 50px;
}
.lvl-3 {
padding-left: 70px;
}
.lvl-4 {
padding-left: 90px;
}
.lvl-5 {
padding-left: 110px;
}
body {
color: #ffffff;
background: #000000;
}
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td class="lvl-0">1</td>
</tr>
<tr>
<td class="lvl-1">2</td>
</tr>
<tr>
<td class="lvl-2">3</td>
</tr>
<tr>
<td class="lvl-2">4</td>
</tr>
<tr>
<td class="lvl-2">5</td>
</tr>
<tr>
<td class="lvl-1">6</td>
</tr>
<tr>
<td class="lvl-2">7</td>
</tr>
<tr>
<td class="lvl-2">8</td>
</tr>
<tr>
<td class="lvl-2">9</td>
</tr>
<tr>
<td class="lvl-1">10</td>
</tr>
<tr>
<td class="lvl-2">11</td>
</tr>
<tr>
<td class="lvl-2">12</td>
</tr>
<tr>
<td class="lvl-2">13</td>
</tr>
<tr>
<td class="lvl-3">14</td>
</tr>
<tr>
<td class="lvl-4">15</td>
</tr>
<tr>
<td class="lvl-4" id="selected">16</td>
</tr>
<tr>
<td class="lvl-3">17</td>
</tr>
<tr>
<td class="lvl-1">18</td>
</tr>
<tr>
<td class="lvl-2">19</td>
</tr>
<tr>
<td class="lvl-2">20</td>
</tr>
<tr>
<td class="lvl-2">21</td>
</tr>
</table>
External JS Fiddle demo, for experimentation and development.
Note that in both the Stack Snippet, and the JS Fiddle, I've corrected the HTML to close the <tr> elements, otherwise the erroneous <tr> tags at the end of each line of the <table> was creating a new, empty, <tr> for no reason.
References:
JavaScript:
JavaScript Regular Expressions Guide (MDN).
Node.textContent.
parseInt().
String.prototype.match().
String.prototype.trim().
jQuery:
attr().
closest().
get().
map().
prevAll().

Changing adjacent cells in table when an event is triggered in JQuery

I'm trying to make a game of lights out. I can get the lights to toggle on and off when i click them, but i am having trouble thinking up logic to make the adjacent one come one as well. For example if i click an edge of the table, I should see the three lights adjacent to the light i clicked, become lit. I'm thinking maybe it has something to do with the "this" bound in my click method, Maybe the "this" is only referencing the one i clicked on and not the adjacent ones. I need to know, perhaps how to get it to reference the adjacent ones?
<html>
<head>
<title>Lights Out!</title>
<script type="text/javascript" src="jquery-1.4.js"></script>
<script type= "text/javascript">
var gameBoard = new Array(getTdCount())
function lightStatus(position)
{
//if light is on
if(gameBoard[position] ==true)
{
//set the original status back to false
gameBoard[position] = false;
return false
}
//turn on light
gameBoard[position]=true;
return gameBoard[position]
}
function getTdCount()
{
return $("td").length;
}
function getTrCount()
{
return $("tr").length;
}
function switchLights( obj, num )
{
if(lightStatus(num))
{
$("img", obj).attr('src', 'on.png')
}
else
{
$("img", obj).attr('src', 'off.png')
}
}
$(document).ready(function()
{
$("#board tr td").hover(function()
{
$(this).css('border-color', '00FFCC');
},
function()
{
$(this).css('border-color', 'black')
})
var $offProtoType = $('#offprototype').css('display', 'block').removeAttr('id')
$('td').append($offProtoType)
$tds = $('#board tr td');
$tds.click(function()
{
var num = $tds.index(this) + 1;
switchLights(this, num)
})
});
</script>
<style type="text/css">
td
{
border-style:solid;
border-color:black;
background-color:black;
float:left;
}
body
{
background-color: grey;
color: green;
}
</style>
</head>
<body>
<img style = "display:none" id="offprototype" src ="off.png">
<img style = "display:none" id="onprototype" src ="on.png">
<h1 align="center">Lights Out<h1>
<table id="board" border="3" bgcolor="black" align="center">
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
<input type="button" value="Shuffle" onclick="change()"/>
</body>
</html>
Use $(this).next() and $(this).prev() to get a reference to the next & previous.
You can use $(this).index() to obtain the position of the 'this' among its siblings; so use something like the following for abobe and below.
var pos = $(this).index();
var prevRow = $(this).parent().prev('tr');
var above = prevRow && prevRow.children().slice(pos);
var nextRow = $(this).parent().next('tr');
var below = prevRow && prevRow.children().slice(pos);
Probably the easiest thing to do is take a look at http://jqueryminute.com/finding-immediately-adjacent-siblings/ if you want just the siblings. If you want the whole row then you can use parent to select the parent element of the cell which should be the row.

Categories

Resources