How to get out of onmousemove event? - javascript

I am dynamically creating a table, with a set number of rows and columns. Once you fire the onmousedown event, it will run a loop to find out which <td></td> you pressed and are moving over, and set it's background color to red.
JSFiddle
I just don't understand how to stop the background color changing once you have fired the onmouseup event.
This is the code part that I am stuck on:
function mousedown() {
var elements = document.querySelector('table').getElementsByTagName('td');
for (var i = 0; i < elements.length; i++) {
elements[i].onmousemove = function() {
this.style.background = "red";
}
elements[i].onmouseup = function() {
this.style.background = "none";
};
}
}

Simply use a flag:
var flag = false;
function mousedown() {
flag = true;
var elements = document.querySelector('table').getElementsByTagName('td');
for (var i = 0; i < elements.length; i++) {
elements[i].onmousemove = function() {
if (flag) this.style.background = "red";
}
elements[i].onmouseup = function() {
flag = false;
};
}
}

JSFiddle here.
I added:
function mouseup() {
var elements = document.querySelector('table').getElementsByTagName('td');
for (var i = 0; i < elements.length; i++) {
elements[i].onmousemove = null;
}
}
and
table.onmouseup = mouseup;

Slightly different approach: http://jsfiddle.net/QYg28/
(function() {
var body = document.querySelector('body');
var table = document.createElement('table');
function createTable(rows, columns) {
var tr;
var td;
for (var i = 0; i < rows; i++) {
tr = document.createElement('tr');
table.appendChild(tr);
for (var j = 0; j < columns; j++) {
td = document.createElement('td');
td.onmouseover = function(){
if(mouseDown)
this.style.background = "red";
}
tr.appendChild(td);
}
}
body.appendChild(table);
}
mouseDown = false;
function mousedown() {
mouseDown = true;
}
function mouseup(){
mouseDown = false;
}
window.onload = createTable(25, 25);
table.onmousedown = mousedown;
table.onmouseup = mouseup;
})();

Related

HTML Table Range Selection/Deselection in JavaScript

I need the functionality of selecting and deselecting a table cell range. The attached code works perfectly but it uses JQuery while the rest of my project uses plain JavaScript. onmousedown, onmouseover, and onmouseup are the three mouse events used in this code.
I tried to convert this JQuery code to plain JavaScript but could not succeed. I would very much appreciate if you can help me in this regard.
Thank you!
var table = $("#table");
var isMouseDown = false;
var startRowIndex = null;
var startCellIndex = null;
function selectTo(cell) {
var row = cell.parent();
var cellIndex = cell.index();
var rowIndex = row.index();
var rowStart, rowEnd, cellStart, cellEnd;
if (rowIndex < startRowIndex) {
rowStart = rowIndex;
rowEnd = startRowIndex;
} else {
rowStart = startRowIndex;
rowEnd = rowIndex;
}
if (cellIndex < startCellIndex) {
cellStart = cellIndex;
cellEnd = startCellIndex;
} else {
cellStart = startCellIndex;
cellEnd = cellIndex;
}
for (var i = rowStart; i <= rowEnd; i++) {
var rowCells = table.find("tr").eq(i).find("td");
for (var j = cellStart; j <= cellEnd; j++) {
rowCells.eq(j).addClass("selected");
}
}
}
table.find("td").mousedown(function (e) {
isMouseDown = true;
var cell = $(this);
table.find(".selected").removeClass("selected"); // deselect everything
if (e.shiftKey) {
selectTo(cell);
} else {
cell.addClass("selected");
startCellIndex = cell.index();
startRowIndex = cell.parent().index();
}
return false; // prevent text selection
})
.mouseover(function () {
if (!isMouseDown) return;
table.find(".selected").removeClass("selected");
selectTo($(this));
})
.bind("selectstart", function () {
return false;
});
$(document).mouseup(function () {
isMouseDown = false;
});
table td {
border: 1px solid #999;
width: 40px;
height: 15px;
margin: 10px;
}
td.selected {
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
Click and drag mouse or use shift key to select cells.
<table id="table">
<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>
</body>
Use querySelectorAll and play with the index or use foreach depending on the use.
window.onload = function() {
var table = document.getElementById('table');
var isMouseDown = false;
var startRowIndex = null;
var startColumnIndex = null;
table.querySelectorAll('tr').forEach(function(tr, rowIndex) {
tr.querySelectorAll('td').forEach(
function(td, columnIndex) {
td.addEventListener('mousedown', function() {
isMouseDown = true;
startRowIndex = rowIndex;
startColumnIndex = columnIndex;
table.querySelectorAll('td').forEach(function(td) {
td.removeAttribute('class')
})
setSelectedInRange(startRowIndex, startColumnIndex, rowIndex, columnIndex)
})
td.addEventListener('mouseover', function() {
if(!isMouseDown) return;
setSelectedInRange(startRowIndex, startColumnIndex, rowIndex, columnIndex)
})
}
)
})
document.addEventListener('mouseup', function() {
isMouseDown = false;
})
}
function setSelectedInRange(rowStart, columnStart, rowEnd, columnEnd) {
var table = document.getElementById('table');
table.querySelectorAll('td').forEach(function(td) {
td.removeAttribute('class')
})
if(rowStart > rowEnd) {
var temp = rowStart;
rowStart = rowEnd;
rowEnd = temp;
}
if(columnStart > columnEnd) {
var temp = columnStart;
columnStart = columnEnd;
columnEnd = temp;
}
var rows = table.querySelectorAll('tr');
for(var i = rowStart; i <= rowEnd; i++) {
var currentRow = rows[i];
var columns = currentRow.querySelectorAll('td');
for(var j = columnStart; j <= columnEnd; j++) {
columns[j].setAttribute('class', 'selected')
}
}
}

Unable to edit input field added via javascript

I have a simple table with cells. When the user clicks on a cell, a textbox is added inside the cell where they can edit the content. However, when i double click a cell to edit it's content, the attributes of the input field show up. It does not allow me to edit and add another value. Here is the script I'm using.
window.onload = function() {
var cells = document.getElementsByTagName("td");
var theads = document.getElementsByTagName("th");
for (let i = 0; i < cells.length; i++) {
cells[i].addEventListener("click", function() {
highlightCell(i);
});
}
function highlightCell(x) {
var txtBox = document.createElement("input");
txtBox.id = "myTxt";
txtBox.type = "text";
for (var i = 0; i<9; i++) {
if (i == x) {
txtBox.value = cells[i].innerHTML;
cells[i].innerHTML = "";
cells[i].appendChild(txtBox);
cells[i].style.backgroundColor = "lightBlue";
}
}
}
}
Found the solution, just needed to use select(). This highlights the selected field, adds a input box which the user can update, then save the value in the cell when enter is pressed.
function highlightCell(x) {
//add input field inside cell
var txtBox = document.createElement("input");
txtBox.id = x;
txtBox.type = "text";
for (var i = 0; i<9; i++) {
if (i == x) {
txtBox.value = cells[i].innerHTML;
cells[i].innerHTML = "";
cells[i].appendChild(txtBox);
txtBox.select();
cells[i].style.backgroundColor = "lightBlue";
cells[x].onkeypress = function(){
var event = window.event;
var btnPress = event.keyCode;
if(btnPress == 13)
{
var elem = document.getElementById(x);
cells[x].innerHTML = elem.value;
elem.parentNode.removeChild(elem);
}
}
} else {
cells[i].style.backgroundColor = "white";
}
}
}

Hide / show buttons with javascript

I have this function which hides some buttons and create another button, when I click on the button created it should make again visible those who were hidden before , but it doesn't really work.
function hideButtons(){
var buttons=document.getElementsByTagName("input");
for(var i=0;i<buttons.length;i++) {
if(buttons[i].type=="button"){
buttons[i].style.display="none";}
}
var back=document.createElement("input");
back.setAttribute("type", "button");
back.setAttribute("value","BACK");
back.setAttribute("id","btnBack");
back.onclick=showButtons();
document.body.appendChild(back);
}
function showButtons(){
var buttons=document.getElementsByTagName("input");
for(var i=0;i<buttons.length;i++) {
buttons[i].style.display="initial";
}
}
You must not call the listener function when you attach the event listener:
function hideButtons () {
var buttons = document.querySelectorAll("input[type=button]");
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.display = "none";
if (buttons[i].getAttribute("id") === "btnBack") {
// remove the id from the current "back" button
buttons[i].removeAttribute("id");
}
}
var back = document.createElement("input");
back.setAttribute("type", "button");
back.setAttribute("value","BACK");
back.setAttribute("id","btnBack");
back.onclick = showButtons; // important!
document.body.appendChild(back);
}
function showButtons () {
var buttons = document.querySelectorAll("input[type=button]");
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.display = "initial";
}
}
Like PeterMader said the problem is that you're calling the showButtons() function in the event listener. You want to call a reference to the function like Peter suggested, or another way is to wrap showButtons() in a function.
function hideButtons() {
var buttons = document.getElementsByTagName("input");
for (var i = 0; i < buttons.length; i++) {
if (buttons[i].type == "button") {
buttons[i].style.display = "none";
}
}
var back = document.createElement("input");
back.setAttribute("type", "button");
back.setAttribute("value", "BACK");
back.setAttribute("id", "btnBack");
back.onclick = function() {
showButtons();
}
document.body.appendChild(back);
}
function showButtons() {
var buttons = document.getElementsByTagName("input");
for (var i = 0; i < buttons.length; i++) {
buttons[i].style.display = "initial";
}
}
hideButtons();
<input type="button">
<input type="button">
<input type="button">
<input>

Changing status of <td> on click with javascript

I am making a conways game of life in javascript and having trouble getting my onclick implementation to work. It is supposed to change the life status of the cell when the td is clicked, but instead I am getting an error at my console that says : TypeError: World.tds is undefined.
TLDR: Can't figure out why onclick won't work. World.tds[] is undefined for some reason.
Onclick implementation:
if (table !== null) {
for (var i = 0; i < 20; i++) {
for (var j = 0; j < 20; j++)
World.tds[i][j].onclick = function() {
if (World.tds[i][j].cells.alive) {
World.tds[i][j].cells.alive = false;
} else {
World.tds[i][j].cells.alive = true;
}
};
}
}
Constructor and tds[] filling
var World = function() {
this.h = maxH;
this.w = maxW;
this.tds = [];
};
//generate the world in which the cells move
World.prototype.init = function() {
var row, cell;
for (var r = 0; r < this.h; r++) {
this.tds[r] = [];
row = document.createElement('tr');
for (var c = 0; c < this.w; c++) {
cell = document.createElement('td');
this.tds[r][c] = cell;
row.appendChild(cell);
}
table.appendChild(row);
}
};
Problem Statement - When you trigger the click handler, by that time values of i and j have updated to 20 each and World.tds[20][20] is undefined.
Update your code inside for loop to
(function(i,j) {
World.tds[i][j].onclick = function() {
if (World.tds[i][j].cells.alive) {
World.tds[i][j].cells.alive = false;
} else {
World.tds[i][j].cells.alive = true;
}
};
})(i,j);

How to save localStorage setted dynamically from onclick this.nameClass

So, i have this javascript code:
function check(x) {
elements = document.getElementsByClassName(x);
for (var i = 0; i < elements.length; i++) {
elements[i].style.backgroundColor = "yellow";
}
}
With this code, i can change the backgroundColor of anything with any class in my html page.
I have many "a" tags with differents class, for example:
<a class="1" onclick="check(this.className)">text 1</a>
<a class="2" onclick="check(this.className)">text 2</a>
<a class="3" onclick="check(this.className)">text 3</a>
<a class="4" onclick="check(this.className)">text 4</a>
And when I click on then I can change background color.
My problem is when I try to save this change in localStorage. I´m wanting to save the background color change to, on load page, check if users have clicked to change background color or not, for example:
function check(x) {
elements = document.getElementsByClassName(x);
for (var i = 0; i < elements.length; i++) {
elements[i].style.backgroundColor = "yellow";
}
if (localStorage[x] != "yellow") {
elements[i].style.color = "yellow";
localStorage[x] = "yellow";
} else {
elements[i].style.color = "";
localStorage[x] = "";
}
}
window.onload = function() {
if (localStorage[x]) {
elements[i].style.backgroundColor = localStorage[x];
}
}
This is the way i found to highlight text user think is interting and he wants to mark, but this is not working.
Can someone helps me with this?
You can do something like
function check(x) {
var elements = document.getElementsByClassName(x);
for (var i = 0; i < elements.length; i++) {
elements[i].style.backgroundColor = "yellow";
}
var colors = localStorage.getItem('colors');
colors = colors ? colors.split(',') : [];
if (colors.indexOf(x) == -1) {
colors.push(x);
localStorage.setItem('colors', colors.join(','));
}
console.log(colors, localStorage.getItem('colors'))
}
window.onload = function () {
var colors = localStorage.getItem('colors');
if (colors) {
colors = colors.split(',');
for (var i = 0; i < colors.length; i++) {
check(colors[i])
}
}
}
Demo: Fiddle
Put everything in a for loop:
function check(x) {
elements = document.getElementsByClassName(x);
for (var i = 0; i < elements.length; i++) {
elements[i].style.backgroundColor = "yellow";
if (localStorage[x] != "yellow") {
elements[i].style.color = "yellow";
localStorage[x] = "yellow";
} else {
elements[i].style.color = "";
localStorage[x] = "";
}
}
}
window.onload = function() {
var elements = document.getElementsByClassName("a");
for (var i = 0; i < elements.length; i++) {
if (localStorage[x]) {
elements[i].style.backgroundColor = localStorage[x];
}
}
}
Note that i have document.getElementsByClassName("a") in the second loop, replace "a" with whatever class that all your tags share.

Categories

Resources