cells not being made/displayed - javascript

im relatively new to coding and i am having an issue with my code, and it isnt a syntax error.
using visual studio code, the goLive extension, and a js file connected to an html file.
the link to the picture is
here
, and although it looks cut off, there is nothing below it
sorry if the code is a bit messy, im not good by any means. it doesnt make the grid though, and i dont know why?
i realized i had an issue with the className function, so i changed it from:
tile.className(cell-white/black);
to
tile.className = "cell-white/black";
that took away the error i got, but it still didnt work.

Here is a quick working solution:
<html>
<head>
<style>
#board {
display: table;
}
.row {
display: table-row;
height: 50px;
}
.cell-black {
display: table-cell;
background-color: black;
height: 50px;
width: 50px;
}
.cell-white {
display: table-cell;
background-color: antiquewhite;
height: 50px;
width: 50px;
}
</style>
<script>
window.onload = function() {
const columns = 8;
const rows = 8;
generateBoard(columns, rows);
}
function generateBoard(cols, rows) {
const board = document.getElementById('board');
for(let r = 0; r < rows; r++) {
const row = document.createElement('div');
row.className = 'row';
for(let c = 0; c < cols; c++) {
const cell = document.createElement('div');
if (r % 2 === 0){
cell.className = c % 2 === 0 ? 'cell-black' : 'cell-white';
}
else {
cell.className = c % 2 === 0 ? 'cell-white' : 'cell-black';
}
row.append(cell)
}
board.append(row);
}
}
</script>
</head>
<body>
<div id="board"></div>
</body>
</html>
To test locally just save this code as index.html somewhere on your computer and open with Chrome or Firefox, or maybe you can run it using VS Code and goLive extension.
Also I would suggest that you rename the question to be something like drawing chessboard-like grid using javascript, css and html.

Related

How can I make a loop that checks if the chess pieces can hit eachother?

My goal is to make sort of a chess game where you can place multiple towers or rooks, and the game is supposed to check if the chess pieces can hit each other or not, so far I have made the code you can see under, but I am stuck on the loop that checks if one rook can hit another rook. I am quite confused on how to check this. If anyone could help me or give me any hints on how to make the loop it would mean a lot! (Sorry for the norwegian variable names, if you need a translation or anything I will gladly help with it!!!)
Thanks in advance!!!
<!doctype html>
<html lang="no">
<head>
<title> Standardoppsett </title>
<meta charset="utf-8">
</head>
<style>
body{
font-size: 25px;
}
.board {
width: 360px;
height: 360px;
border: 32px solid;
border-color: darkslategray;
border-radius: 5px;
}
.firkant {
height:calc(100% / 8);
width: calc(100% / 8);
text-align: center;
border: 1px black solid;
}
.hvit{
background:white;
}
.svart{
background:grey;
}
td:hover {
background: lightgreen;
cursor: pointer
}
</style>
<body>
<table class="board"></table>
<script>
let tableEl = document.querySelector("table")
let liste = []
for(let i = 1; i < 9; i++) {
let trEl = document.createElement('tr');
for(let j = 1; j < 9; j++) {
let tdEl = document.createElement('td');
tdEl.setAttribute("id","rute"+i+j)
tdEl.addEventListener("click",plasserTårn)
trEl.appendChild(tdEl);
// Bare på grunn av css
tdEl.className = (i%2 === j%2) ? "hvit firkant" : "svart firkant";
}
tableEl.appendChild(trEl);
}
function plasserTårn(e){
let trykketFirkant = e.target
let plassertBrikke = {rad:trykketFirkant.id.substring(5,4), kolonne:trykketFirkant.id.substring(6,5)}
liste.push(plassertBrikke)
console.log(liste)
console.log(plassertBrikke)
for(let i = 0;i<liste.length;i++){
let rekkefolgehusker = i
for (let k = rekkefolgehusker;k<liste.length;k++) {
if(liste[i].rad == liste.rad[k]) {
console.log("tårn blir slott");
}
}
}
}
</script>
</body>
</html>
I'm not 100% sure what you want, but before pushing plassertBrikke to liste, you can do something like this to see if plassertBrikke can take any of the rooks already on the board.
const piecesUpForGrabs = liste.filter(rook => {
return plassertBrikke.rad === rook.rad || plassertBrikke.kolonne === rook.kolonne;
})
console.log('plassertBrikke can take these pieces:', piecesUpForGrabs);

How to add hundreds of shapes on page without slowing page load

I am trying to add hundreds of little "squares"/shapes on a page using JS. However, whether using SVG or divs, the page load is very slow. Is there a more efficient way to create multiple shapes on a page without slowing down the page load?
Here is an example in JSFiddle, which has both svg and div examples
Here is the JS:
var num = 700
for (i=0; i < num; i++){
let el = '<div class="els"></div>';
let elSVG = '<svg class="els"></svg>';
let container = document.getElementById("test");
container.innerHTML = container.innerHTML + elSVG
}
Instead of concatenating HTML text to the innerHTML each time, append an <svg> element. Also, you should only query for #test (aka container) once; outside of your loop.
const
container = document.getElementById('test'),
num = 700;
const createSvg = () => {
const svg = document.createElement('SVG');
svg.classList.add('els');
return svg;
};
for (let i = 0; i < num; i++) {
container.append(createSvg());
}
body {
background-color: #111
}
.els {
display: inline-block;
width: 10px;
height: 10px;
margin-right: 16px;
background-color: #EEE;
}
<div id="test"></div>
Update: As Danny mentioned, you could append all the SVG elements to a DocumentFragment and then append said fragment to the container afterwards.
const fragment = new DocumentFragment();
for (let i = 0; i < num; i++) {
fragment.append(createSvg());
}
container.append(fragment);
You will always slow page load, it can not be done without slowing down.
But you can be smart in creating content.
innerHTML and append will trigger Browser reflow/repaint for every insertion
Use a DocumentFragment to built all HTML in memory, then inject the DocumentFragment once.
https://developer.mozilla.org/en-US/docs/Web/API/DocumentFragment
You might also want to look into <template>,
a cloned template parses the HTML only once
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template
<style>
body {
background-color: black
}
.els {
height: 2px;
width: 1px;
background-color: white;
margin-right: 1px;
display: inline-block;
}
</style>
<div id="$Container">
</div>
<script>
console.time();
let fragment = new DocumentFragment();
let num = 4 * 700;
for (i = 0; i < num; i++) {
let el = document.createElement("div");
el.classList.add("els");
el.appendChild(document.createElement("svg"))
.classList.add("els");
fragment.append(el);
}
$Container.append(fragment);
console.timeEnd();
</script>

How to add hover effect upon mouseover to all divs on a page?

I have a 16x16 grid of small squares. I have added a permanent "hover" effect to make the very first box turn red when I put my mouse over it. However, I want to add the same effect to all of the boxes on the page. I can't figure out how to do it - I have tried to add an event listener to the whole page and used target.nodeName and target.NodeValue, but to no avail. I have included the working version where the fix box turns red on mouseover.
var n=16; //take grid column value as you want
const bigContainer = document.querySelector('.bigContainer')
for(var i = 1; i < n; i++) {
bigContainer.innerHTML+='<div class="row">';
for(j = 0; j < n; j++) {
bigContainer.innerHTML+='<div class="smallBox">';
}
}
const smallBox = document.querySelector('.smallBox');
smallBox.addEventListener('mouseover', () => {
smallBox.classList.add('permahover');
});
.smallBox {
border: 1px solid black;
width: 20px;
height: 20px;
display: inline-block;
}
.permahover {
background: red;
}
h1 {
text-align: center;
}
.bigContainer {
text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">
</div>
The immediate problem you are having is that this is only querying, and subsequently adding an event listener to, one element.
const smallBox = document.querySelector('.smallBox');
smallBox.addEventListener('mouseover', () => {
smallBox.classList.add('permahover');
});
In the above portion of your code, querySelector only returns the first matching element. You may be looking for querySelectorAll here which returns a NodeList of matching elements.
You have two options (perhaps others if you want to restructure your code further). The naive approach is to, in fact, query for all of the cells and add event listeners to each of them.
var n=16; //take grid column value as you want
const bigContainer = document.querySelector('.bigContainer')
for(var i = 1; i < n; i++) {
bigContainer.innerHTML+='<div class="row">';
for(j = 0; j < n; j++) {
bigContainer.innerHTML+='<div class="smallBox">';
}
}
const smallBoxes = document.querySelectorAll('.smallBox');
[...smallBoxes].forEach(smallBox => {
smallBox.addEventListener('mouseover', () => {
smallBox.classList.add('permahover');
});
})
.smallBox {
border: 1px solid black;
width: 20px;
height: 20px;
display: inline-block;
}
.permahover {
background: red;
}
h1 {
text-align: center;
}
.bigContainer {
text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">
</div>
Another option is to use event delegation as you identified. Here is how you can leverage that. Note: this approach is a bit tricker for an aggressive event like "mouseover" as you may get false positive targets (like the outer container for example).
var n=16; //take grid column value as you want
const bigContainer = document.querySelector('.bigContainer')
for(var i = 1; i < n; i++) {
bigContainer.innerHTML+='<div class="row">';
for(j = 0; j < n; j++) {
bigContainer.innerHTML+='<div class="smallBox">';
}
}
bigContainer.addEventListener('mouseover', e => {
var target = e.target
if (target !== bigContainer) {
target.classList.add('permahover')
}
})
.smallBox {
border: 1px solid black;
width: 20px;
height: 20px;
display: inline-block;
}
.permahover {
background: red;
}
h1 {
text-align: center;
}
.bigContainer {
text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">
</div>
You need to use a delegation event, because all the small boxes don't exist on the page when the page is loaded (You can figure out in the inspector element that only your first box has the event listener).
So you listen the whole container (because it is always on the page on load)
bigContainer.addEventListener('mouseover', () => {
// Code for checking if we hovered a small div & if yes applying the style
});
...and then do a comparaison with the event.target (which will be the small div hovered)
if (event.target.matches('.smallBox')) {
event.target.classList.add('permahover');
}
var n=16; //take grid column value as you want
const bigContainer = document.querySelector('.bigContainer')
for(var i = 1; i < n; i++) {
bigContainer.innerHTML+='<div class="row">';
for(j = 0; j < n; j++) {
bigContainer.innerHTML+='<div class="smallBox">';
}
}
const smallBox = document.querySelector('.smallBox');
bigContainer.addEventListener('mouseover', () => {
if (event.target.matches('.smallBox')) {
event.target.classList.add('permahover');
}
});
.smallBox {
border: 1px solid black;
width: 20px;
height: 20px;
display: inline-block;
}
.permahover {
background: red;
}
h1 {
text-align: center;
}
.bigContainer {
text-align: center;
}
<h1>Etch-a-Sketch Assignment - The Odin Project</h1>
<div class="bigContainer">
</div>
You can use forEach method to loop through all boxes and add eventListener on each one.
If all of them have .smallBox class you can do it like this:
const smallBoxes = document.querySelectorAll('.smallBox');
smallBoxes.forEach(box => box.addEventListener('mouseover', () => {
smallBox.classList.add('permahover');
}))
I hope it helped you!
let smallBoxes = document.querySelectorAll('.smallBox');
[...smallBoxes].forEach(el => {
el.addEventListener('mouseover', e => e.target.classList.add('permahover'));
});
you should set the eventlistener to your DOM and ask if the trigger element are one of your elements which are that specific class. So you can handle every element with that class.
var n = 16; //take grid column value as you want
const bigContainer = document.querySelector('.bigContainer')
for (var i = 1; i < n; i++) {
bigContainer.innerHTML += '<div class="row">';
for (j = 0; j < n; j++) {
bigContainer.innerHTML += '<div class="smallBox">';
}
}
document.addEventListener('mouseover', function(e) {
if (e.target && e.target.className == 'smallBox') {
var target = e.target;
target.classList.add('permahover');
}
});
Working js fiddle: https://jsfiddle.net/nwukf205/
hope i could help you :)
if you got questions just ask
Have you tried the :hover selector? Not sure if you want specify any dynamic actions here, but it's easy to do basic stuff.
https://www.w3schools.com/cssref/sel_hover.asp
a:hover {
background-color: yellow;
}
I haven't tried your example myself but something similar to this has been answered here:
Hover on element and highlight all elements with the same class

Get only the ellipsis text using jquery

Nice code, just wondered if it is possible to query and get the ellipsis text (i.e. with the dots in and not the original text)?
If I add the text
This is a long sentence
and (using the relevant css for ellipsis) it gets shortened to
This is a long sen ...
Is there a way to get the text
"This is a long sen ..."
from the $("p") DOM object rather than the original text?
Try that:
function getEllipsis(command, characters) {
for (var i = command.length; i >= 0; i--) {
if (command.substring(0, i).length < characters) {
if (i < command.length) {
command = command.substring(0, i) + "...";
}
return command;
}
}
}
console.log(getEllipsis("I am a long sentence",16))
console.log(getEllipsis("But I am even longer",20))
I have a rough draft that needs some browser-specific tweaking.
JavaScript:
jQuery.fn.getShowingText = function () {
// Add temporary element for measuring character widths
$('body').append('<div id="Test" style="padding:0;border:0;height:auto;width:auto;position:absolute;display:none;"></div>');
var longString = $(this).text();
var eleWidth = $(this).innerWidth();
var totalWidth = 0;
var totalString = '';
var finished = false;
var ellipWidth = $('#Test').html('…').innerWidth();
var offset = 7; // seems to differ based on browser (6 for Chrome and 7 for Firefox?)
for (var i = 0;
(i < longString.length) && ((totalWidth) < (eleWidth-offset)); i++) {
$('#Test').text(longString.charAt(i));
totalWidth += $('#Test').innerWidth();
totalString += longString.charAt(i);
if(i+1 === longString.length)
{
finished = true;
}
}
$('body').remove('#Test'); // Clean up temporary element
if(finished === false)
{
return totalString.substring(0,totalString.length-3)+"…";
}
else
{
return longString;
}
}
console.log($('#ellDiv').getShowingText());
CSS:
#Test {
padding:0;
border:0;
height: auto;
width: auto;
position:absolute;
white-space: pre;
}
div {
width: 100px;
white-space: nowrap;
border: 1px solid #000;
overflow:hidden;
text-overflow:ellipsis;
padding:0;
}
With the caveat that the offset needs to change depending on the browser, unless someone can figure out what is causing it.
I suspect letter-spacing or similar?

Javascript for-loop to control button click states

I'm new to JavaScript but moving over from ActionScript, so I'm using a lot of AS3 logic and not sure what's possible and not.
I have a series of 5 dots for an image slider nav. The dots are just CSS styled dots, so I'm trying to make it so I can control the colors using element.style.backgroundColor.
Here's my script:
function btnFeatured(thisBtn) {
btnFeatured_reset();
for (i = 1; i <= 5; i++) {
if (thisBtn === document.getElementById("dotFeat" + i)) {
document.getElementById("dotFeat" + i).style.backgroundColor = "#ffae00";
}
}
}
function btnFeatured_reset() {
for (i = 1; i <= 5; i++) {
document.getElementById("dotFeat" + i).style.backgroundColor = "#969696";
}
}
Seems to work just fine, but when I click the dot, it turns orange (ffae00) and then immediately turns back to gray (969696).
And just in case, here's the style I'm using for the dots:
#featured-nav a {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 8px;
background-color: #969696;
border-bottom: none;
margin: 0 14px;
}
#featured-nav a:hover {
background-color: #ffae00;
border-bottom: none;
}
And my html:
Change the HTML to
test
test
test
test
test
and the JS:
function btnFeatured(thisBtn) {
for (i = 1; i <= 5; i++) {
var state = parseInt(thisBtn.id.slice(-1),10) == i,
elem = document.getElementById("dotFeat" + i);
elem.style.backgroundColor = (state ? "#ffae00" : "#969696");
}
return false;
}
FIDDLE
Even better would be to not use inline JS, but proper event handlers.

Categories

Resources