this is my javascript code the onclick functions do not trigger when i push the button I have tried with an event listener that listen only for the parent of the button aka the form but nothing in that case it fires once and it does not keep listening for further button clicks:
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
document.addEventListener('DOMContentLoaded', () =>{
const room__message = Handlebars.compile(document.querySelector('#room__message').innerHTML);
document.querySelector('#send__button').onclick = () =>{
console.log('hola el boton fue pulsado')
let message = document.querySelector('#message__input').value
let user = localStorage.getItem('user')
let channel = localStorage.getItem('channel')
console.log(message)
socket.emit('send message', {'message':message, 'user':user, 'room':channel})
document.querySelector('#message__input').value = '';
}
socket.on('connect', () =>{
socket.emit('join', { 'channel':localStorage.getItem('channel'), 'user':user })
load__list();
load_messages(localStorage.getItem('channel'))
});
document.querySelector('#add__room').onclick = () => {
let list = JSON.parse(localStorage.getItem('channel__list'));
let name_ = prompt("Please enter you'r new Channel's name", "");
while (name_ in list || name != null){
name_ = prompt("this name is already in the database", "");
}
if (name_ != null){
list.push(name_)
}
socket.emit('new room', {'name':name_})
};
socket.on('broadcast', data =>{
let message = data.message;
let user = data.user;
let timestamp = data.timestamp;
const msj = room__message({'message':message, 'user':user, 'timestamp':timestamp})
document.querySelector('.message__cont').innerHTML += msj;
});
});
the html looks like this:
<body>
<ul id="channel__list">
<li>
<button id="add__room">+</button>
</li>
</ul>
<div id="chanel__container">
<form id="channel__form" action="" >
<input type="text" id="message__input" autocomplete="off" placeholder="message">
<input type="submit" id="send__button" value="send">
</form>
</div>
</body>
it does run in a flask server I dont know if that may be an issue
First of all, there are quite a few syntax errors in your code.
Inside your HTML code
<from> tag is to be changed to <form>
Inside your JS code
ID room__message is not declared hence this will never return anything.
You have opened a function socket.io('connect') function but never closed.
Coming back to why the on click buttons are not getting triggered *
The possible reason this could be happening is that by the time your document readyState is already completed in this case the event DOMContentLoaded will not be fired at any point in time. This can be avoided by providing/checking document ready state.
Below are two sample codes (I am still not sure why you are using on click function inside a listener while you can use JS shorthand and directly use it)
Proper HTML code
<body>
<ul id="channel__list">
<li>
<button id="add__room">+</button>
</li>
</ul>
<div id="chanel__container">
<form id="channel__form">
<input
type="text"
id="message__input"
autocomplete="off"
placeholder="message"
/>
<input type="submit" id="send__button" value="send" />
</form>
</div>
</body>
Your actual JS code (a bit modification)
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", loadDomContent());
} else {
console.log("Current document load state: ", document.readyState);
loadDomContent();
}
function loadDomContent() {
const room__message = Handlebars.compile(
document.querySelector("#room__message").innerHTML
);
document.querySelector("#send__button").onclick = () => {
/* do something */
};
socket.on("connect", () => {
socket.emit("join", {
/* do other stuff }); */
});
});
document.querySelector("#add__room").click = () => {
console.log("I am working");
/* do something else */
};
socket.on("broadcast", data => {
/* send some stuff over */
});
}
Also, you can write something like this
<button onclick="addNewRoom()" id="add__room">+</button>
An declaring that as:
function addNewRoom(){
// do something
}
My Solution
the issue was in deed in the html, because it was changing the position of th ebutton by adding more elements to its container im guessing it changed the address to which the event was pointing at, thanks everybody for their input.
Related
i got two copies of the same code with slight variation but seems the second one isnt working.
I have tried using ChatGPT to identify issues however, nothing was found. But as far as i can see, it should work.
But, everything i refresh, its removed.
I want the buttons to stay there.
working code:
const todoList = document.querySelector(".todo-list");
const todoForm = document.querySelector(".add-todo");
const removeList = document.querySelector(".remove-List");
let items = JSON.parse(localStorage.getItem("todoList")) || [
{
title: "Write on, 'do not forget to', and press '+' to add",
done: false,
},
{
title: "press 'X' to remove",
done: false,
},
{
title: "search via 'search box'",
done: false,
},
{
title: "filter via 'all'",
done: false,
},
];
function addTodo(e) {
e.preventDefault();
const title = this.querySelector("[name=item]").value;
const todo = {
title,
done: false,
};
items.push(todo);
saveTodos();
this.reset();
}
function createList(list = [], listTarget) {
listTarget.innerHTML = list
.map((item, i) => {
return `<li>
<input type="checkbox" id="todo${i}" data-index="${i}"
${item.done ? "checked" : ""} />
<label for="todo${i}">${item.title}
<span class="font-size:30px" data-index="${i}">X</span>
</label>
</li>`;
})
.join("");
}
function toggleDone(e) {
if (!e.target.matches("input")) return;
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
saveTodos();
}
function removeSingle(e) {
if (!e.target.matches("span")) return;
const el = e.target;
const index = el.dataset.index;
items.splice(index, 1);
saveTodos();
if (items.length === 0) {
removeList.classList.add("hidden");
}
}
function saveTodos() {
localStorage.setItem("todoList", JSON.stringify(items));
createList(items, todoList);
showRemoveButton();
}
function removeData() {
items = [];
localStorage.removeItem("todoList");
createList(items, todoList);
removeList.classList.add("hidden");
}
function showRemoveButton() {
if (items.length > 1) return;
removeList.classList.remove("hidden");
}
todoList.addEventListener("click", toggleDone);
todoList.addEventListener("click", removeSingle);
todoForm.addEventListener("submit", addTodo);
removeList.addEventListener("click", removeData);
// Init list
createList(items, todoList);
<div class="ToDo-container">
<header class="app-header">
<div class="app-header1">
<div class="title">
<h1 class="app-title">ToDo List</h1>
</div>
<div class="select-button">
<select id="filter">
<option value="all">All</option>
<option value="completed">Completed</option>
<option value="incomplete">Incomplete</option>
</select>
</div>
</div>
<div class="search-header">
<input type="text" id="search" placeholder="Search Todos">
<button type="button" id="search-button" class="btn">Search</button>
</div>
</header>
<section class="app-body">
<div id="toDo">
<ul class="todo-list"></ul>
<form class="add-todo">
<input
type="text"
placeholder="Don't Forget to..."
name="item"
required
/>
<input type="submit" value="+" />
</form>
</div>
<button class="remove-List btn">Remove All</button>
</section>
</div>
// Add button function
function addButton() {
// Prompt for button link and name
var link = prompt("Enter the button link:");
var name = prompt("Enter the button name:");
// Create new button element
var newButton = document.createElement("button");
newButton.innerHTML = name;
newButton.setAttribute("onclick", "location.href='" + link + "'");
// Append new button to button container
document.getElementById("button-container").appendChild(newButton);
// Save buttons to local storage
saveButtons();
}
// Remove buttons function
function removeButtons() {
// Clear button container
document.getElementById("button-container").innerHTML = "";
// Save buttons to local storage
saveButtons();
}
// Save buttons to local storage
function saveButtons() {
// Get button container HTML
var buttonHTML = document.getElementById("button-container").innerHTML;
// Save button HTML to local storage
localStorage.setItem("buttons", buttonHTML);
}
// Load buttons from local storage on page load
window.onload = function () {
// Get button HTML from local storage
var buttonHTML = localStorage.getItem("buttons");
// Set button container HTML
document.getElementById("button-container").innerHTML = buttonHTML;
};
<div class="shortcuts-container">
<header class="shortcut-header">
<h1 class="shortcut-title">Quick Links</h1>
</header>
<section class="shortcut-body">
<form id="button-form">
<div id="button-container"></div>
<button type="button" onclick="addButton()">Add Button</button>
<button type="button" onclick="removeButtons()">Remove Buttons</button>
</form>
</section>
</div>
i want some help with identifying the bug in my code
As you have mentioned that your "second one" is not working, I have focused on the second piece of code. This peice of code adds a button for which we need to provide a link and name via alert box, which is technically supposed to be a hyperlink. I have added 2 buttons using that and refreshed page multiple times but the newly added buttons always stay. Local storage is working just fine.
Also, looking at your code, there is NO localStorage.removeItem() present. Hence the window.onload works fine. However, if you have any error logs in console of dev tools, please provide them for further debugging.
Also, if there is a way for you attach a video link of testing with dev tools console visible that would really help to understand why it doesn't work for you.
I have my HTML code:
<!DOCTYPE html>
<head>
<script src="../req.js"></script>
</head>
<link rel="stylesheet" href="style.css">
<html>
<body>
<h1> Recipes founder</h1>
<form class="example">
<input id ="query" type="text" placeholder="Insert a recipe.." name="search" value="">
<button id="searchRecipe" type="button" onkeydown="handler(e)" onclick="searchFile()"><i></i>Search</button>
</form>
<div id="content"></div>
</body>
</html>
and my js code associated with it:
function searchFile(e) {
// enter must do the same
const q = document.getElementById('query').value;
const total_q = `Title%3A${q}%20OR%20Description%3A${q}%20OR%20web%3A${q}`
fetch(
`http://localhost:8983/solr/recipe/select?indent=true&q.op=OR&q=${total_q}&rows=300`, { mode: 'cors' }
).then((res) => res.json())
// Take actual json
.then(({ response }) => appendData(response))
.catch(function (err) {
console.log(err)
});
}
function appendData(data) {
// clear previous research
document.getElementById("content").innerHTML = "";
let docs = data.docs;
// Take each element of the json file
for (elem of docs) {
var mainContainer = document.getElementById("content");
// title recipe
var a1 = document.createElement("a");
a1.setAttribute("href", elem.url);
var div = document.createElement("div");
div.innerHTML = elem.Title;
a1.appendChild(div);
// insert image of recipe and link for page in website
var a = document.createElement("a");
a.setAttribute("href", elem.Image);
var img = document.createElement("img");
// img.setAttribute("href", elem.url);
img.setAttribute("src", elem.Image);
a.appendChild(img);
// recipe description
var p = document.createElement("p");
p.innerHTML = elem.Description;
// Insert elements in dev
mainContainer.appendChild(a1);
mainContainer.appendChild(p);
mainContainer.appendChild(a);
}
}
function handler(event) {
if (event == "click") {
searchFile();
}
else if ((event.keyCode || event.which) == 13){
event.preventDefault();
event.cancelBubble = true;
event.returnValue = false;
event.stopPropagation();
event.preventDefault();
searchFile();
}
else {
console.log("Nothing")
}
}
What searchFile() and appendData() do is not important because they work. The target is when the user clicks on the search button or presses the enter key, searchFile() must be called. Clicking on the search button works, but the problem is when a user clicks enter, it navigates to http://localhost:8000/?search=SOMETHING (depends on what the user inserted) . I think it is the default behaviour of the enter key, I tried to prevent it using different codes but nothing works. I read that instead of using the event onkeypress we have to use onkeydown but I'm still in the same situation. I tried also to wait for the DOM to be loaded but nothing. Does someone have an idea about it?
Remove all the event handlers on the button
Make the button a submit button
Use the submit event on the form (this will trigger if the form submission is trigged by enter in the input or the button being clicked or enter being pressed over the button)
Prevent the default event behaviour (so the form data isn't submitted to a URL which the browser navigates to)
Don't bother doing any tests to try to figure out if it was a click or something else, all that matters if that the form was submitted.
const submitHandler = (event) => {
event.preventDefault();
alert("You can do your ajax search here");
};
document.querySelector('.example').addEventListener('submit', submitHandler);
<form class="example">
<input id="query" type="text" placeholder="Insert a recipe.." name="search" value="">
<button>Search</button>
</form>
I have a form and I am trying to listen to the event when the user submits the form. Here are my codes:
html:
const form = document.forms['testRegForm']
form.addEventListener('submit', e => {
e.preventDefault()
alert("Test");
var x = document.forms["required"]["mobile"].value;
if (x == "") {
alert("Mobile Number is required");
return false;
}else {
alert(x)
fetch(scriptURL, { method: 'POST', body: new FormData(form)})
.then(response =>
alert('Your request is submitted. We will get in touch with you soon')
)
.catch(error => alert(error.message))
}
})
<form name="testRegForm" style="font-family: Aladin;" >
<p>Register using mobile Number: </p>
<input type="number" placeholder="Number" pattern="\d{3}[\-]\d{3}[\-]\d{4}" name="mobile" maxlength="10" required><br><br>
<button type="submit">Submit</button>
<p></p>
</form>
But the event listener does not work when the submit button is clicked. This is verified by the fact that the alert - "Test" is not shown. Where am I wrong?
Your event is indeed firing, it just doesn't complete because of an error referencing the input. Also, make sure that the script is located just before the closing body tag so that the HTML will be fully parsed by the time the script is encountered.
Replace const form = document.forms['testRegForm'] with const form = document.querySelector("form") and modify your reference to the input as with a valid selector as shown below.
<!doctype html>
<html>
<head>
<title>test</title>
</head>
<body>
<form name="testRegForm" style="font-family: Aladin;" >
<p>Register using mobile Number: </p>
<input type="number" placeholder="Number" pattern="\d{3}[\-]\d{3}[\-]\d{4}" name="mobile" maxlength="10" required><br><br>
<button type="submit">Submit</button>
<p></p>
</form>
<script>
// A standard API for locating a DOM element is .querySelector()
// which takes any valid CSS selector:
const form = document.querySelector("form");
// Get your DOM references that you'll work with more than once
// only once, so this has been moved outside of the event callback.
// Also, "mobile" isn't an attribute, so your selector wasn't working
// for it. And, it's best to get references to DOM elements, rather
// than a particular property of an element so that if you decide you
// want a difference property value, you've already got the element
// reference and won't need to scan for it again.
var x = document.querySelector("[required][name='mobile']");
form.addEventListener('submit', e => {
e.preventDefault();
alert("Test");
if (x.value == "") {
alert("Mobile Number is required");
return false;
}else {
alert(x.value);
fetch(scriptURL, { method: 'POST', body: new FormData(form)})
.then(response =>
alert('Your request is submitted. We will get in touch with you soon')
).catch(error => alert(error.message))
}
});
</script>
<body>
</html>
I'm trying to use google invisible recaptcha on my web form (php and codeigniter 3). but somehow whenever I click on the Submit button, the google recaptcha keeps generating questions as if ignoring all the other codes before the execute command. so none of the console.log and alert ever appear. what is wrong with my code?
my code looks like this:
HTML
<form id="form_signup" method="post" action="/signup">
<input type="text" name="username"/>
<div class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="<?php echo $mysitekey; ?>"
data-callback="onSubmitFormSignupUser">
</div>
<button type="button" id="formSignup-btnSubmit">
Submit
</button>
</form>
JS
var widgetId = '';
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render('formSignup-btnSubmit', {
'sitekey' : $('#form_signup-recaptcha').attr('data-sitekey'),
'callback' : $('#form_signup-recaptcha').attr('data-callback'),
});
};
var onSubmitFormSignupUser = function(response) {
console.log('response', response);
if ($('[name="username"]').val()) {
alert('yes');
grecaptcha.execute(widgetId);
doSubmitFormToServer('#form_signup');
}
else {
alert('no');
grecaptcha.reset(widgetId);
}
}
var doSubmitFormToServer = function(selector) {
var myData = $(selector).serializeArray();
console.log('send form data', myData);
}
Well, you had a typo in the id, at least, here id="form_signup-recaptcha" and here: 'sitekey' : $('#formSignup-recaptcha').attr('data-sitekey'),, other than that, it is not clear, was it invoked at all, or not, as you've not provided the part of including the script, which should contain ?onload=onLoadRecaptcha parameter.
The code is below, but it won't work here, because of null origin. Check Codepen instead: https://codepen.io/extempl/pen/abOvBZv
sitekey used is one is for testing purposes only, as described here: https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha-v2-what-should-i-do
var widgetId = "";
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("formSignup-btnSubmit", {
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
var onSubmitFormSignupUser = function(response) {
console.log("response", response);
if ($('[name="username"]').val()) {
grecaptcha.execute(widgetId);
doSubmitFormToServer("#form_signup");
} else {
$(".status").text("failed");
grecaptcha.reset(widgetId);
}
};
var doSubmitFormToServer = function(selector) {
var myData = $(selector).serializeArray();
$(".status").text("submitted");
console.log("send form data", myData);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://www.google.com/recaptcha/api.js?onload=onLoadRecaptcha"></script>
<body>
<form id="form_signup" method="post" action="/signup">
<input type="text" name="username" />
<div
class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
data-callback="onSubmitFormSignupUser">
</div>
<button type="button" id="formSignup-btnSubmit">
Submit
</button>
<span class="status"></span>
</form>
</body>
it turns out that the solution is so simple.
this code
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("formSignup-btnSubmit", { // wrong element ID
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
should be like this
var onLoadRecaptcha = function() {
widgetId = grecaptcha.render("form_signup-recaptcha", { // corrent element ID
sitekey: $("#form_signup-recaptcha").attr("data-sitekey"),
callback: $("#form_signup-recaptcha").attr("data-callback")
});
};
because the recaptcha element is like this
<div
class="g-recaptcha"
id="form_signup-recaptcha"
data-size="invisible"
data-sitekey="6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"
data-callback="onSubmitFormSignupUser">
</div>
so basically the parameters for grecaptcha.render should follow the properties in the element that has g-recaptcha class. my mistake was that I used the button id, even though the element with g-recaptcha class was the div.
I don't remember reading about this particular thing in the documentation. I guess I'm too stupid to realize that before this.. I hope this makes things clear for others with the same problem.
On page 1, I have a div containing information.
<div id='information'></div>
And on page 2, I have a form with a textarea and a button.
<form>
<textarea id='new-info'></textarea>
<input type='submit' id='submit-info' value='pass'/>
</form>
Now what I want is when I click the submit button, the text inputted in the text area will be posted in div#information changing its previous content.
I have seen many other post on how to change div content, but those were unrelated to my problem.
One way is to do like what the other answers mentioned, to have each tab communicate to a central server that will get/send data to keep both tabs updated using AJAX for example.
But I'm here to tell you about another way though, it's to use what we already have designed for this kind of task exactly. What so called browser localStorage
Browser storage works like this pseudo code:
//set the value, it works as a hash map or assoc array.
localStorage .setItem("some_index_key", "some data") ;
// get the value by it's index key.
localStorage .getItem("some_index_key") ; // will get you "some data"
Where all the data will be shared among all open tabs for the same domain. And you can add event listener so whenever one value change, it will be reflected on all tabs.
addEvent(window, 'storage', function (event) {
if (event.key == 'some_index_key') {
output.innerHTML = event.newValue;
}
});
addEvent(myInputField, 'keyup', function () {
localStorage.setItem('some_index_key', this.value);
});
Check out this DEMO, you edit one field on page-A, and that value will be reflected on page-B offline without the need to burden the network.
To learn more, read this.
Real live example. The background color is controlled from another tab.
var screenone = document.getElementById('screenone');
screenone.addEventListener('keydown', screenOneFunction);
screenone.addEventListener('change', screenOneFunction);
function screenOneFunction()
{
document.body.style.backgroundColor = this.value;
localStorage.setItem("color1", this.value);
}
var screentwo = document.getElementById('screentwo');
screentwo.addEventListener('keydown', function (evt) {
localStorage.setItem("color2", this.value);
});
screentwo.addEventListener('change', function (evt) {
localStorage.setItem("color2", this.value);
});
var thebutton = document.getElementById('thebutton');
thebutton.addEventListener('click', function (evt) {
localStorage.clear();
screenone.value = "";
screentwo.value = "";
document.body.style.backgroundColor = "";
});
var storageHandler = function () {
document.body.style.backgroundColor = localStorage.color2;
var color1 = localStorage.color1;
var color2 = localStorage.color2;
screenone.value = color2;
screentwo.value = color1;
};
window.addEventListener("storage", storageHandler, false);
.screenone{ border: 1px solid black;}
input{ margin: 10px; width: 250px; height: 20px; border:round}
label{margin: 15px;}
<html>
<head>
</head>
<body>
<label> Type a color name e.g. red. Or enter a color hex code e.g. #001122 </label>
<br>
<input type="text" class="screenone" id="screenone" />
<label> This tab </label>
<br>
<input type="text" class="screentwo" id="screentwo" />
<label> Other opned tabs </label>
<br>
<input type="button" class=" " id="thebutton" value="clear" />
</body>
</html>
Hope this will give you an idea of how you can do it:
Page 2
HTML
<form>
<textarea id='new-info'></textarea>
<input type='submit' id='submit-info' value='pass'/>
</form>
JS
$("form").submit(function(e){
e.preventDefault();
$.post('save_data.php', { new_info:$("#new-info").val() }).done(function(data){
// Do something if you want to show that form has been sent
});
});
save_data.php
<?php
if (isset($_POST['new-info'])) {
// Update value in DB
}
?>
Page 1
HTML
<div id='information'>
</div>
JS
setInterval(search_after_info, 1000);
function search_after_info() {
$.get('get_data', function(data) {
$("#information").html(data);
});
}
You mean some thing like this ?
$("#submit-info").click(function() {
var content = $("#new-info").text();
$("#information").html(content);
});
If you thing about server side, tell more about technology, which you use.
This is exactly as the following:
Page 1:
<form action="test2.htm" method="get">
<textarea name ='new-info'></textarea>
<input type = 'submit' id='submit-info' value ='pass' onclick="postData();"/>
Page 2
<div id="information"></div>
<script>
if (location.search != "")
{
var x = location.search.substr(1).split(";")
for (var i=0; i<x.length; i++)
{
var y = x[i].split("=");
var DataValue = y[1];
document.getElementById("information").innerHTML = DataValue;
}
}
</script>