Trying to click div and fire off function in a class everytime it is clicked...says TypeError in console - javascript

I have been looking at how to use classes to create objects in Javascript and wanted to create a class with a function inside that I could use once a div is clicked...However, every time I click the div I get TypeError
I have google search answers and see results with a button in html solution, but I want to do this using javascript only.
I have tried using
document.getElementById("myDiv").onclick = function(event) {Bucket.selectAndFill(event)};
but it says that selectAndFill is not a function in the console.
let buckets = [];
class Bucket {
constructor(Content, SelectStatus) {
this.content = Content;
this.selectStatus = SelectStatus;
}
selectAndFill() {
for (let bucket of buckets) {
this.content = "i changed it";
}
}
}
for (let i = 0; i < 4; i++) {
buckets[i] = new Bucket("empty", false);
console.log(buckets[i]);
}
//this line was my attempt but it says that selectAndFill is not a function in the console
document.getElementById("myDiv").onclick = function() {
Bucket.selectAndFill()
};
#myDiv {
position: relative;
width: 100px;
height: 100px;
background: red;
}
<div id="myDiv">
</div>

You can call the function from Class modifying the call this way:
const bucketFill = new Bucket;
document.getElementById("myDiv").onclick = bucketFill.selectAndFill;

Just add static keyword next to the method.
let buckets = [];
class Bucket {
constructor(Content, SelectStatus) {
this.content = Content;
this.selectStatus = SelectStatus;
}
static selectAndFill() {
for (let bucket of buckets) {
this.content = "i changed it";
}
console.log(buckets);
}
}
for (let i = 0; i < 4; i++) {
buckets[i] = new Bucket("empty", false);
console.log(buckets[i]);
}
document.getElementById("myDiv").onclick = function() {
Bucket.selectAndFill();
};
#myDiv {
position: relative;
width: 100px;
height: 100px;
background: red;
}
<div id="myDiv">
</div>

Related

how to remove the quotes or get element from this (javascript)

As topic, how can I remove the quote in the picuture below or get the img element from this?
(https://i.stack.imgur.com/kdPAP.png)
I m new to javascript and start making an image slider that can pop up a window while clicked to the image.
I cloned the li object which is clicked, and try to open it in the new window, it do work but how can I get the img only without the li?
Right now i m trying to call the cloned this object with innerHTML, but it shows the img element with quote, is there any way to remove the quote?
the quote that i want to remove
first time ask a question in here, if i violate any rules in the post, i delete the post, sorry for causing any inconvenience.
Here is the code
<!DOCTYPE html>
<html>
<head>
<style>
.risuto1 {
max-width: 480px;
max-height: 270px;
margin: auto;
position: relative;
}
ul {
list-style-type: none;
margin: auto;
padding: 0;
}
.aitemu>img {
max-width: 100%;
}
.aitemu {
display: none;
position: relative;
}
.aitemu.akutibu {
display: block;
}
.risuto1>.mae,
.tsugi {
width: auto;
height: auto;
padding: 20px;
top: 102.6px;
position: absolute;
cursor: pointer;
background-color: red;
}
.risuto1>.tsugi {
left: 431.8px;
}
</style>
</head>
<body>
<script>
var risuto1 = document.createElement("div");
risuto1.classList.add("risuto1");
document.body.appendChild(risuto1);
var suraidaaitemu = document.createElement("ul");
suraidaaitemu.classList.add("suraidaaitemu");
risuto1.appendChild(suraidaaitemu);
var imejisosurisuto = ["https://pbs.twimg.com/media/CGGc3wKVEAAjmWj?format=jpg&name=medium", "https://pbs.twimg.com/media/EYCXvuzU8AEepqD?format=jpg&name=large", "https://s3-ap-northeast-1.amazonaws.com/cdn.bibi-star.jp/production/imgs/images/000/668/074/original.jpg?1626914998", "https://livedoor.blogimg.jp/rin20064/imgs/7/3/73251146.jpg", "https://www.tbs.co.jp/anime/oregairu/character/img/chara_img_02.jpg"]
//var imejirisuto=[]
for (var n = 0; n < imejisosurisuto.length; n++) {
var imeji = document.createElement("img");
imeji.src = imejisosurisuto[n];
var aitemu = document.createElement("li");
aitemu.classList.add("aitemu");
suraidaaitemu.appendChild(aitemu);
aitemu.appendChild(imeji);
aitemu.onclick=atarashivindou;
}
var akutibunasaishonoko = document.querySelector(".suraidaaitemu").firstChild;
akutibunasaishonoko.classList.add("akutibu");
var mae = document.createElement("div");
mae.classList.add("mae");
mae.innerHTML = "&#10094";
risuto1.appendChild(mae);
var tsugi = document.createElement("div");
tsugi.classList.add("tsugi");
tsugi.innerHTML = "&#10095";
risuto1.appendChild(tsugi);
var tensuu = 0;
var suraido = document.querySelector(".suraidaaitemu").children;
var gokeisuraido = suraido.length;
tsugi.onclick = function () {
Tsugi("Tsugi");
}
mae.onclick = function () {
Tsugi("Mae");
}
function Tsugi(houkou) {
if (houkou == "Tsugi") {
tensuu++;
if (tensuu == gokeisuraido) {
tensuu = 0;
}
}
else {
if (tensuu == 0) {
tensuu = gokeisuraido - 1;
}
else {
tensuu--;
}
}
for (var i = 0; i < suraido.length; i++) {
suraido[i].classList.remove("akutibu");
}
suraido[tensuu].classList.add("akutibu");
}
function atarashivindou(){
var Atarashivindou = window.open("", "_blank", "width: 1000px, max-height: 562.5px");
var kakudaigazou=document.createElement("div");
kakudaigazou.classList.add("kakudaigazou");
Atarashivindou.document.body.appendChild(kakudaigazou);
var koronaitemu=this.cloneNode(true);
var koronimeji=koronaitemu.innerHTML;
kakudaigazou.append(koronimeji);
}
</script>
</body>
.innerHTML is a string. You don't want to append a string, but the element. So change this:
var koronaitemu=this.cloneNode(true);
var koronimeji=koronaitemu.innerHTML;
kakudaigazou.append(koronimeji);
...to this:
var koronimeji=this.querySelector("img").cloneNode();
kakudaigazou.append(koronimeji);

How do I programatically change a picture inside a div?

Here there is full code as you guys can see.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Collage</title>
</head>
<style>
div
{
background: url("Image/191203174105-edward-whitaker-1-large-169.jpg")
;
height: 300px;
width: 300px;
}
</style>
<body>
<div id="div"></div>
<button id="button">Next</button>
<script>
As here I took variable im where I feed 3 images.
var im=[
{'img':'Image/191203174105-edward-whitaker-1-large-169.jpg',}
,{'img':'Image/5718897981_10faa45ac3_b-640x624.jpg',},
{'img':'Image/gettyimages-836272842-612x612.jpg',},
];
var a=document.getElementById('button');
var b=document.getElementById('div')
a.addEventListener('click',next);
so here according to my knowledge it should provide the link of the each pic as loop starts but in program. I dont get the desired result. Can you please help me understand why this is happening?
function next()
{
for(var i=1;i<im.length;i++)
{
b.style.background=`url(${im[i].img})`;
}
}
</script>
</body>
</html>
var i = 0;
var im = [{
'img': 'https://picsum.photos/536/354'
},
{
'img': 'https://picsum.photos/id/237/536/354'
},
{
'img': 'https://picsum.photos/seed/picsum/536/354'
}
];
var a = document.getElementById('button');
var b = document.getElementById('div')
a.addEventListener('click', next);
function next() {
console.log(i);
b.style.background = `url(${im[i].img})`;
i++;
if (i == im.length) {
i = 0;
}
}
div {
background: url("https://picsum.photos/id/1084/536/354?grayscale");
height: 300px;
width: 300px;
}
<div id="div"></div>
<button id="button">Next</button>
If you're looking to cycle through pictures on a button click, then you can't really use a loop. In the code that you posted, on the click of the button, it rapidly looped through all of the pictures. You need to create a counter, and increment it on each button click.
The snippet below I've added in a previous button as well and you can cycle through the pictures both forward and backward.
const im = {
'img1': 'https://placehold.it/300x150/ff0000/ffffff?text=image_1',
'img2': 'https://placehold.it/300x150/00ff00/ffffff?text=image_2',
'img3': 'https://placehold.it/300x150/0000ff/ffffff?text=image_3',
};
const imgDiv = document.getElementById('imgDiv')
const btnNext = document.getElementById('btnNext');
const btnPrev = document.getElementById('btnPrev');
const totImages = Object.keys(im).length;
let imgNumber = 1;
btnNext.addEventListener('click', next);
btnPrev.addEventListener('click', prev);
function next() {
imgNumber++
let img = imgNumber <= totImages ? `img${imgNumber}` : null;
if (img) imgDiv.style.background = `url(${im[img]})`;
if (imgNumber === totImages) btnNext.disabled = true;
if (imgNumber > 1) btnPrev.disabled = false;
}
function prev() {
imgNumber--
let img = imgNumber >= 0 ? `img${imgNumber}` : null;
if (img) imgDiv.style.background = `url(${im[img]})`;
if (imgNumber < totImages) btnNext.disabled = false;
if (imgNumber === 1) btnPrev.disabled = true;
}
#imgDiv {
background: url("https://placehold.it/300x150/ff0000/ffffff?text=image_1");
height: 150px;
width: 300px;
}
#btnDiv {
width: 300px;
height: auto;
position: relative;
}
#btnPrev {
position: absolute;
left: 0;
top: 0;
}
#btnNext {
position: absolute;
right: 0;
top: 0;
}
<div id="imgDiv"></div>
<div id='btnDiv'>
<button id="btnPrev" disabled>&loarr; Prev</button>
<button id="btnNext">Next &roarr;</button>
</div>

How do I dynamically add image on hover to a button?

I am trying to add a on hover show image on a button that I am creating dynamically. I would love any suggestions.
arrayHere = [{
"date": "2/22/19",
"note1": "Hello"
}, {
"date": "1/11/18",
"note1": "hi"
}]
populateData(arrayHere);
populateData(array) {
var notesDates = document.getElementById("notes-dates");
for (var i = 0; i < arrayHere.length; i++) {
let dateLink = document.createElement("button");
let displayNote1 = arrayHere[i].note1;
dateLink.innerHTML = arrayHere[i].date;
notesDates.appendChild(dateLink);
dateLink.onclick = function() {
DisplayChange(displayNotes1);
}
}
function DisplayChange(displayNotes1) {
document.getElementById("changeHere").innerHTML = displayNotes1;
}
}
I've tried using JQuery, instead of getting errors, nothing shows up on the page.
CSS
.buttonWithImage {
background-image: url("https://image.shutterstock.com/z/stock-vector-vector-illustration-of-goggle-with-two-eye-on-yellow-color-background-317985974.jpg");
background-size: cover;
height: 40px;
}
HTML
<button id="button">Click me</button>
JS
var btn = document.getElementById("button");
btn.addEventListener("mouseover", handler);
function handler(scope){
scope.target.className = "buttonWithImage";
console.log(scope.target);
}

Is there a way to add class to all elements

I browsed thru various similar questions, but I found nowhere real help on my problem. There are some Jquery examples, but none of them weren't applicable, since I want to do it by vanilla JavaScript only.
The Problem
I have rating widget which I want to build like every time I click on "p" element, eventListener adds class "good" on all p elements before and on the clicked one, and remove class good on all that are coming after the clicked one.
My Thoughts
I tried to select all the "p" elements and iterate over them by using a for loop to add class before and on clicked element, and to leave it unchanged or remove after, but somewhere I am doing it wrong, and it adds class only on clicked element not on all previous ones.
My Code
function rating () {
var paragraph = document.getElementsByTagName('p');
for (var i = 0; i < paragraph.length; i++) {
paragraph[i].addEventListener('click', function(e) {
e.target.className='good';
})
}
}
rating();
Result
Expected result is that every p element before the clicked one, including clicked one should be having class good after click and all the ones that are after the clicked one, should have no classes.
Actual Result: Only clicked element is having class good.
Using Array#forEach , Element#nextElementSibling and Element#previousElementSibling
General logic behind this is to loop through all the previous and next sibling elements. For each element, add or remove the class .good until there are no more siblings to handle.
const ps = document.querySelectorAll('p');
ps.forEach(p => {
p.addEventListener("click", function() {
let next = this.nextElementSibling;
let prev = this;
while(prev !== null){
prev.classList.add("good");
prev = prev.previousElementSibling;
}
while(next !== null){
next.classList.remove("good");
next = next.nextElementSibling;
}
})
})
p.good {
background-color: red;
}
p.good::after {
content: ".good"
}
p {
background-color: lightgrey;
}
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>
Alternative:
Using Array#slice to get the previous and next group of p's.
const ps = document.querySelectorAll('p');
ps.forEach((p,i,list) => {
p.addEventListener("click", function() {
const arr = [...list];
const previous = arr.slice(0,i+1);
const next = arr.slice(i+1);
previous.forEach(pre=>{
pre.classList.add("good");
})
next.forEach(nex=>{
nex.classList.remove("good");
});
})
})
p.good {
background-color: red;
}
p.good::after {
content: ".good"
}
p {
background-color: lightgrey;
}
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>
function setup() {
var paragraph = document.querySelectorAll("p");
for (p of paragraph) {
p.onclick = (event) => {
let index = Array.from(paragraph).indexOf(event.target);
[].forEach.call(paragraph, function(el) {
el.classList.remove("good");
});
for (let i = 0; i <= index; i++) {
paragraph[i].classList.add("good");
}
}
}
}
//Example case
document.body.innerHTML = `
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>`;
setup();
The key ingredient is to use Node.compareDocumentPosition() to find out if an element precedes or follows another element:
var paragraphs;
function handleParagraphClick(e) {
this.classList.add('good');
paragraphs.forEach((paragraph) => {
if (paragraph === this) {
return;
}
const bitmask = this.compareDocumentPosition(paragraph);
if (bitmask & Node.DOCUMENT_POSITION_FOLLOWING) {
paragraph.classList.remove('good');
}
if (bitmask & Node.DOCUMENT_POSITION_PRECEDING) {
paragraph.classList.add('good');
}
});
}
function setup() {
paragraphs = [...document.getElementsByTagName('p')];
paragraphs.forEach((paragraph) => {
paragraph.addEventListener('click', handleParagraphClick);
});
}
setup();
#rating { display: flex; }
p { font-size: 32px; cursor: default; }
p:hover { background-color: #f0f0f0; }
.good { color: orange; }
<div id='rating'>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
<p>*</p>
</div>`

How to handle multi key press for game purposes in jquery/javascript?

I'm trying to do a multi-key press combination validation for a "little game" test im doing.
Basically is a character from Mortal Kombat which I move with ASDW keys... but what happens if I want to duck and block at the same time (would be S + K) for example. And I couldn't make it work :S
Now... not only that, if I'm pressing only S, which will duck. Then I press K (while keeping S pushed) it should block while ducking. If I release the K, it should keep ducking. Is this one possible as well?
How to handle for example combinations for doing skills in javascript?
Like if I press S->D->Punch would do a skill (not pressed at the same time but a sequence)
Is there any possible way of doing all this?
This is my entire code inside a simple HTML so you can see it entirely:
P.S: Look at the comment in the preload image part, i mean, the animations are choppy while trying to move the character from one way to another... why is that? what am i doing wrong?
<! DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<style>
#reptile_wrapper {
top: 120px;
left: 140px;
position:relative;
}
#container {
margin-top: 240px;
margin-left: 470px;
width: 890px;
height: 301px; /* entire one 547px */
background: url("img/bgs/pit_background.png") no-repeat;
background-size: 100%;
}
#pit {
top: 0px;
position: relative;
width: 890px;
height: 300px;
background: url("img/bgs/pit.png") no-repeat;
background-size: 100%;
}
#pit_chain {
position: absolute;
width: 150px;
height: 340px;
background: url("img/bgs/pit_chains.png") no-repeat;
margin-left: 695;
}
</style>
</head>
<body>
<audio src="sounds/mk3thepit.mp3" preload="auto" loop="true" autoplay="true" autobuffer></audio>
<div id="pit_chain">
</div>
<div id="container">
<div id="pit">
<div id="reptile_wrapper">
<img src="img/reptile_idle.gif"/>
</div>
</div>
</div>
<script>
/* Preload all the images and gifs */
function preloadImages(srcs, imgs, callback) {
var img;
var remaining = srcs.length;
for (var i = 0; i < srcs.length; i++) {
img = new Image();
img.onload = function() {
--remaining;
if (remaining <= 0) {
callback();
}
};
img.src = srcs[i];
imgs.push(img);
}
}
// then to call it, you would use this
var imageSrcs = ["img", "img/bgs"];
var images = [];
preloadImages(imageSrcs, images, startGame());
/* End of preloading images and gifs */
var duckImages = ["d01", "d02"];
var defaultY = '120px';
reptileIdleAnimation();
function startGame() {
var keys = [];
window.addEventListener("keydown",
function(e){
keys[e.keyCode] = e.keyCode;
var keysArray = getNumberArray(keys);
if(keysArray.toString() == "68"){
$("#reptile_wrapper img").attr('src', 'img/reptile_walk_forward.gif')
.parent().css({left: '+=5px'});
}else if(keysArray.toString() == "17,65"){
// document.body.innerHTML += " Select all!"
}
},
false);
window.addEventListener('keyup',
function(e){
keys[e.keyCode] = false;
reptileIdleAnimation();
},
false);
function getNumberArray(arr){
var newArr = new Array();
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] == "number"){
newArr[newArr.length] = arr[i];
}
}
return newArr;
}
}
</script>
</body>
</html>
Thanks.
You don't necessarily need to rely on jQuery for capturing the keys.
Here is a plain javascript solution
var keys = [];
document.body.innerHTML = "Keys currently pressed: "
window.addEventListener("keydown",
function(e){
keys[e.keyCode] = e.keyCode;
var keysArray = getNumberArray(keys);
document.body.innerHTML = "Keys currently pressed:" + keysArray;
if(keysArray.toString() == "17,65"){
document.body.innerHTML += " Select all!"
}
},
false);
window.addEventListener('keyup',
function(e){
keys[e.keyCode] = false;
document.body.innerHTML = "Keys currently pressed: " + getNumberArray(keys);
},
false);
function getNumberArray(arr){
var newArr = new Array();
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] == "number"){
newArr[newArr.length] = arr[i];
}
}
return newArr;
}
As you can see, detecting multiple keypresses and releases at the same time is not a problem, technically speaking.
I think the only browser culprit here (for plain JS) is e.keyCode. If you want to use jQuery you can rewrite the listener definitions so that they use jQuery.
In this question i asked for a proper but plain image preloader.
See the answer supplied; you can use this code to handle the preloading properly.
Hope that helps!

Categories