I'm really new to javascript and jquery and I'm trying to get a button to autoclick from an existing code base. I am having trouble getting the button to do that even though this is what I've been following How to auto click an input button.
The code is below. I've tried using both .submit() and .click() but the start-game-btn doesn't seem to get pressed either way. I've put a console.log within the button whenever it's pressed and the message doesn't seem to get logged.
console.log("loading...")
$(() => {
$("#start-game-btn").click(event => {
console.log("start-game")
$("#errors").text("")
event.preventDefault()
const height = parseInt($("#height").val())
const width = parseInt($("#width").val())
const food = parseInt($("#food").val())
let MaxTurnsToNextFoodSpawn = 0
if ($("#food-spawn-chance").val()) {
MaxTurnsToNextFoodSpawn = parseInt($("#food-spawn-chance").val())
}
const snakes = []
$(".snake-group").each(function() {
const url = "http://0.0.0.0:8080/"//$(".snake-url", $(this)).val()
console.log(url)
if (!url) {
return
}
snakes.push({
name: "M1",//$(".snake-name", $(this)).val(),
url
})
})
if (snakes.length === 0) {
$("#errors").text("No snakes available")
}
console.log(12)
fetch("http://localhost:3005/games", {
method: "POST",
body: JSON.stringify({
width,
height,
food,
MaxTurnsToNextFoodSpawn,
"snakes": snakes,
})
}).then(resp => resp.json())
.then(json => {
const id = json.ID
fetch(`http://localhost:3005/games/${id}/start`, {
method: "POST"
}).then(_ => {
$("#board").attr("src", `http://localhost:3009?engine=http://localhost:3005&game=${id}`)
}).catch(err => $("#errors").text(err))
})
.catch(err => $("#errors").text(err))
})
console.log("ready!")
})
window.onload = function(){
var button = document.getElementById('start-game-btn');
button.form.submit();
console.log("Done!!")
}
Everytime I refresh the page the log shows:
loading...
ready!
Done!!
What I think it should be logging is (or at least that's what I'm trying to achieve):
loading...
start-game
ready!
Done!!
submit() does not work because it is for submitting forms.
button.form.submit(); does not work because it assumes your button is part of a form.
As it looks like you are using jQuery, try just calling the jQuery click function without any parameters using a jQuery selector.
eg.
$("#start-game-btn").click();
Related
I'm still new to javascript, I have this javascript problem from CS50 that is supposed to open a mailbox and clicking on an email is supposed to open the email. I think my on click part of the problem is right, but when I open my page and click on an email it doesnt call the open_mail() function.
I've solved that the problem is that the load_mailbox function for being asynchronous is beign called after the DOM finishes to load, so technically theres no div with the class email-box when the DOM finishes to load, but i don't know how to solve this problem, can someone help please.
document.addEventListener('DOMContentLoaded', function() {
// Use buttons to toggle between views
document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox'));
document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent'));
document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive'));
document.querySelector('#compose').addEventListener('click', compose_email);
document.querySelector('#compose-form').addEventListener('submit', send_mail);
document.querySelectorAll('.email-box').forEach(function(box) {
box.addEventListener('click', function (){
open_mail();
})
});
// By default, load the inbox
load_mailbox('inbox');
});
function load_mailbox(mailbox) {
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
document.querySelector('#email-content').innerHTML = "";
emails.forEach(inbox_mail);
})
};
function inbox_mail(email) {
const element = document.createElement('div');
if (document.querySelector(`#email-${email.id}`) === null) {
element.id = (`email-${email.id}`);
element.className = ("email-box");
element.innerHTML = `<p>From ${email.sender}</p><p>${email.subject}</p><p>At ${email.timestamp}
</p>`;
document.querySelector('#email-content').append(element);
}
}
I´d say the easiest solution would be to put the addEventListener to a point after the elements with class .email-box are created, e.g in your .then function after inbox_mail ran for each email
.then(emails => {
document.querySelector('#email-content').innerHTML = "";
emails.forEach(inbox_mail);
document.querySelectorAll('.email-box').forEach(function(box) {
box.addEventListener('click', function (){
open_mail();
});
});
});
DOMContentLoaded will trigger when the DOM from the initial request/response was loaded. What you are doing in your fetch callback is called "DOM-Manipulation" as you create elements and append them to the DOM that has already been loaded.
I have strange problem with buttons that are requesting for displaying templates on client page.
This is client side code. The main task of entire class is to just enable user to click button, send request and get response with HTML that has been rendered from handlebars template and just paste it in partiuclar place on client side. It works, but only once. After first click and displaying elements, I totally lose any interaction with those buttons. There is no request, and there is no even EventListener for clicking. I get no error. Completely there is no single reaction after clicking.
class Weapons {
constructor() {
this.buttons = document.querySelectorAll('.type')
}
async displayWeapon(path) {
const container = document.querySelector('.shop-container')
await fetch(`weapons/${path}`).then(response => response.json()).then(data => container.innerHTML += data);
}
chooseWeapon() {
this.buttons.forEach(btn => {
btn.addEventListener('click', (e) => {
console.log('click');
let weaponType = e.target.dataset.type
switch (weaponType) {
case 'pistols':
console.log('click');
return this.displayWeapon(weaponType)
case 'rifles':
console.log('click');
return this.displayWeapon(weaponType)
case 'grenades':
console.log('click');
return this.displayWeapon(weaponType)
case 'closerange':
console.log('click');
return this.displayWeapon(weaponType)
case 'rocketlauchner':
console.log('click');
return this.displayWeapon(weaponType)
}
})
})
}
}
document.addEventListener('DOMContentLoaded', function () {
const weapons = new Weapons();
weapons.chooseWeapon();
> When I invoke displayWeapon(path) here it also works, but immidiately
> after displaying html elements clicking on buttons again does not
> initiate any action.
})
Here is app.get function but I doubt it's source of problem.
app.get('/weapons/:id', (req, res) => {
console.log('req');
console.log(req.url);
let type = req.params.id;
res.render(type, function (err, html) {
res.json(html);
})
})
Ok. The answer is actually simple. In fetch function container.innerHTML += data. This line deletes my html with buttons, and the same time it deletes eventListeners. So I need just to modify my html.
I want to know how to make a Tab highlight everytime an event happens, in this case, it would be a call. So, if the user isn't in my website in the moment, he will know that a event happenned. My useEffect looks like the following:
useEffect(() => {
if (newCall < calls.length){
setHighlight(true)
setNewCall(calls.length)
}
}, [calls.length])
useEffect(() => {
if (newCall < calls.length){
setHighlight(!'your state name')
setInterval(()=>setHighlight(!'your state name'),2000)
setNewCall(calls.length)
}
}, [calls.length])
The above fragment of code sets highlight and so does the user knows that an event has happened and after 2 seconds the highlight will be returned to the initial state.
It seems as though the solution is a combination of:
Browser tab change notification like when you get a new gmail e-mail or a new tweet in Twitter
and
Detect If Browser Tab Has Focus
useEffect(() => {
window.onfocus = function(){
document.title = "Original Title"
}
return () => {
window.onfocus = null;
}
}, []);
useEffect(() => {
if (newCall < calls.length){
document.title = `Original Title (${calls.length} calls)`
}
}, [calls.length])
i have this code that checks if the user has logged in or not, if the user has not logged in, it redirects the user to the login page to log in and if he/she has logged in, they would be allowed to upload content on the page. this is the code:
let vocals = document.getElementsByClassName("up");// class name of certain divs in the program
for (let i = 0; i < vocals.length; i++) {
vocals[i].addEventListener("click", () => {
let check = "php/checkCookie.php";
fetch(check, { method: "GET" })
.then((res) => res.text())
.then((data) => {
if (data == 0) {
shout("Login Before You Can Create", 0);
setInterval(() => {
location.href = "logincheck.html";
}, 3000);
} else {
document.getElementById(`e${i}`).click();
}
});
...
});
}
the code:
document.getElementById(`e${i}`).click();
is supposed to open the file explorer so that the user can pick a file and upload, but it doesn't work, and it does not show an error.
those anyone know why and has a solution, thanks in advance
Maybe your element doesn't support click() on it? If I remember correctly, click() works on on several elements, but not all. It should work on <input>, and <a>.
You could also try this instead:
document.getElementById(`e${i}`).dispatchEvent(new MouseEvent('mousedown'))
document.getElementById(`e${i}`).dispatchEvent(new MouseEvent('mouseup'))
So another day, another problem. I'm rewriting my website from jQuery to vanilla ES6 and i have a problem with my form. Previously I was triggering a different action on jQuery .done() and on .error() and it worked just fine, but now my specified action triggers on xhr.addEventListener("error", e => { code }, but not on xhr.addEventListener("load ", e => { code }.
Here is the code that I have:
form.addEventListener("submit", e => {
e.preventDefault();
for (let i = inputFail.length; i--; ) {
inputFail[i].remove();
}
if (validateForm()) {
const formData = new FormData(form);
const xhr = new XMLHttpRequest();
xhr.addEventListener("error", e => {
console.log("error");
const failPL = "Nie udało się, spróbuj jeszcze raz.";
const failENG = "Something went wrong, please try again.";
const postFail = document.createElement("div");
const failText = document.createElement("p");
postFail.classList.add("form__fail");
postFail.classList.add("fade-in-out");
if (langPL.classList.contains("button--lang--active")) {
failText.innerText = failPL;
postFail.appendChild(failText);
form.appendChild(postFail);
} else {
failText.innerText = failENG;
postFail.appendChild(failText);
form.appendChild(postFail);
}
setTimeout(() => {
postFail.remove();
}, 5000)
});
xhr.addEventListener("load ", e => {
console.log("success");
const successPl = 'Dziękuję za wiadomość!';
const successENG = 'Thank you for your message!';
const postSuccess = document.createElement("div");
const successText = document.createElement("p");
postSuccess.classList.add("form__success");
postSuccess.classList.add("fade-in-out");
form.reset();
if (langPL.classList.contains("button--lang--active")) {
successText.innerText = successPl;
postSuccess.appendChild(successText);
form.appendChild(postSuccess);
} else {
successText.innerText = successENG;
postSuccess.appendChild(successText);
form.appendChild(postSuccess);
}
setTimeout(() => {
postSuccess.remove();
}, 5000)
});
xhr.open("POST", form.action);
xhr.send(formData);
}
})
So basically when I turn off the internet connection and sumbit the form, an error event is fired and a nice, red div with error text is appended to the form letting a user know that the POST has failed and he/she should try again. I want to have a similar thing with form.reset() after succesfully submiting it, but it just doesn't work. I do get an e-mail from the form so it is working, but it seems that the "load" event doesn't fire. I've also tried with xhr.status === 200 and xhr.readyState === 4 but again, no luck. So - what is the exact equivalent of jquery .done() form method?
I will appreciate all the help, but please do not suggest sticking to jQuery.
but not on xhr.addEventListener("load ", e => { code }.
You have an extra space there. Change to
xhr.addEventListener("load"
Note that you could iterate automatically over your inputFails via
inputFail.forEach(element => element.remove());
Your current for loop's syntax has issues, too. (the second part is the while condition, not the incrementer/decrementer)
Also, don't use IE's not-so-reliable .innerText, use the standard method .textContent instead.
You can simplify this
setTimeout(() => {
postSuccess.remove();
}, 5000)
to
setTimeout(postSuccess.remove, 5000);
since it's a standalone function, and so can be passed as a parameter itself.