What I'm trying to accomplish here is to get an alert to show up every time the phone is shaken. But I keep getting an error saying:
Uncaught TypeError: Cannot call method 'addEventListener' of undefined
Is it because it doesn't know what 'shake' is? The reason for more than one shake is because I'll be adding different animations depending on what shake its on.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="initial-scale=1.0, width=device-width, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<title>Shake animation</title>
<style type="text/css">
body {
background: #E9E9E9;
color: #333;
font: 1em/1.3em "Helvetica Neue", Helvetica, Arial, Verdana, sans-serif; /* 16px / 21px */
text-shadow: rgba(255,255,255,0.8) 0 1px 0;
text-align: center;
}
</style>
<script type="text/javascript" src="shake.js"></script>
</head>
<body>
<div class="answerListener" id="answer1"></div>
<div class="answerListener" id="answer2"></div>
<div class="answerListener" id="answer3"></div>
<div class="answerListener" id="answer4"></div>
<script type="text/javascript">
window.onload = function() {
var answer = document.getElementsByClassName('answerListener');
var current = 1;
for (i = 0; answer.length; i++) {
answer[i].addEventListener('shake', function() {
if (current == 1) {
alert('shake1');
}
if (current == 2) {
alert('shake2');
}
if (current == 3) {
alert('shake3');
}
if (current == 4) {
alert('shake4');
}
current = current + 1;
}, false);
}
};
</script>
</body>
Your code looks good except for one small problem: your for loop does not terminate:
for (i = 0; answer.length; i++) {
should be
for (i = 0; i < answer.length; i++) {
You are getting the error because once i exceeds answer.length, answer[i] is undefined and therefore answer[i].addEventListener is attempting to call the method of a non-existing element.
Good luck.
Related
I'm running my code in node.js I've seen that running code in node could play a part. But this was never a problem. It keeps saying my variable that points to my element 'document is not defined'. I don't know what I'm doing wrong, I'm linking it correctly but still confused I also tried putting my scripts on the bottom and top with defer.
let seconds = 00;
let tens = 00;
let appendTens = document.querySelector('#tens');
let appendSeconds = document.querySelector('#seconds');
let stop = document.querySelector('#button-stop');
let start = document.querySelector('#button-start');
let reset = document.querySelector('#button-reset');
let interval; //store timer values
// this function will run when start is clicked
const startTimer = () =>{
tens++
if(tens < 9){
appendTens.textContent = `0${tens}`
}
if(tens > 9){
appendTens.textContent = tens;
}
if(tens > 99){
seconds++
appendSeconds.textContent = `0${seconds}`;
tens = 0;
appendTens.textContent = "0" + 0;
}
if(seconds > 9){
appendSeconds.textContent = seconds;
}
};
start.onclick = function(){
interval = setinterval(startTimer)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Stopwatch</title>
<link rel="stylesheet" href="stopwatch.css">
</head>
<body>
<div class="wrapper">
<h1>Stopwatch</h1>
<h2>Vanilla JavaScript Stopwatch</h2>
<p><span id="seconds">00</span>:<span id="tens">00</span></p>
<button id="button-start">Start</button>
<button id="button-stop">Stop</button>
<button id="button-reset">Reset</button>
</div>
<script type="module" src="stopwatcj.js"></script>
</body>
</html>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-self: center;
background-color: rgb(248, 180, 55);
}
.wrapper {
margin-top: 10%;
text-align: center;
color: #fff;
}
.wrapper button {
background-color: rgb(248, 180, 55);
border: 1px solid white;
padding: 10px 20px;
color: #fff;
}
.wrapper button:hover {
cursor: pointer;
opacity: 30%;
}
document which is a part of Html DOM is not a part of nodejs. Since you might be using nodejs to compile your js code that's why you are getting this error. Please try to run this simply in browser.
im creating to-do list without any tutorial and i stucked when i tried to code clear button. I have a problem because this code removing only half of 'li' items in my list. I checked length of document.querySelectorAll('li) and it return correct value of list length , and i think in each loop execution i delete first element because document.querySelector('li) return only first element. Could you help me? And another question : Is somewhere in web program that can i see step by step exection of my code with DOM? I found few sites but there i can only debug code without html and css.
There is my code:
let clear = document.querySelector('.clear');
let input = document.querySelector('.input');
let submit = document.querySelector('.submit');
let list = document.querySelector('.list');
submit.addEventListener('click', function() {
const el = document.createElement('li');
list.appendChild(el);
let items = document.querySelectorAll('li');
for (i = 0; i < items.length; i++) {
items[items.length - 1].textContent = input.value;
}
});
clear.addEventListener('click', function() {
console.log(document.querySelectorAll('li').length);
for (i = 0; i < document.querySelectorAll('li').length; i++)
list.removeChild(document.querySelector('li'));
console.log(list);
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
max-height: 100vh;
max-width: 90vw;
}
h1 {
text-align: center;
}
.wrap {
padding: 50px;
border: 2px solid black;
border-radius: 20%;
background-color: red;
}
.list {
width: 100%;
margin-left: 100px;
font-size: 2rem;
font-weight: bold;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="wrap">
<h1>To do list</h1>
<input type="text" placeholder="Add an item!" class="input" />
<button class="submit">Submit</button>
<button class="clear">Clear List</button>
</div>
<ol class="list"></ol>
<script src="script.js"></script>
</body>
</html>
In your case, your loop was calculating its length each time of the loop while i was still incrementing
I you had two elements, it would have deleted the first item, then at the second loop, the list would have a length of 1 and i would be equals to 1 so the loop would break
You can use a for of loop instead of a for i loop and remove the child by reference
clear.addEventListener('click', function() {
const childs = document.querySelectorAll('li')
for (const child of childs){
list.removeChild(child)
}
});
Note : this can also be done using a for i loop if you instantiate the list
clear.addEventListener('click', function() {
const childs = document.querySelectorAll('li')
for (let i = 0; i < childs.length; i++){
list.removeChild(childs[i])
}
});
I invent a new way to solve it
clear.addEventListener('click', function () {
for (i = 0; i < document.querySelectorAll('li').length + i; i++)
list.removeChild(document.querySelector('li'));
console.log(list);
});
In each iteration I add 'i' . So i update length
how to make progressBar work during long-time loops of computing?
by using setInterval()? by using async or await? how? please show me in code.
I know using VUE's bind can help,but I want simple js-code without any outside import to do this.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style type="text/css">
#myProgress {
width: 100%;
background-color: #ddd;
}
#myBar {
width: 10%;
height: 30px;
background-color: #4caf50;
text-align: center;
line-height: 30px;
color: white;
}
</style>
</head>
<body>
<div style="text-align: center">
<h2>RSA!</h2>
<div id="myProgress">
<div id="myBar">10%</div>
</div>
<br />
<label>输入素数的范围,最大:21474836:</label>
<input
type="number"
id="myCount"
placeholder=""
value="2147483"
min="100"
max="21474836"
/>
<button class="dom1" onclick="initPrim()">1.素数生成器</button><br />
<div
id="result0"
style="width: 100%; word-break: break-all; word-wrap: break-word"
></div>
<br />
</div>
</body>
<!--21474836 2147483647 sqrt(Integer.MAX)=46341-->
<script>
var PrimeArray = [2];
//initPrim 生成素数表
async function initPrim(limit) {
document.getElementById("result0").innerHTML = " ";
var count = document.getElementById("myCount").value;
for (i = 2; i < count; i++) {
let j;
let tag = 0;
for (
j = 0;
j < PrimeArray.length && PrimeArray[j] < Math.sqrt(i) + 1;
j++
) {
if (i % PrimeArray[j] == 0) {
tag = 1;
break;
}
}
if (tag == 0) {
PrimeArray.push(i);
}
}
document.getElementById("result0").append("p=\t" + PrimeArray);
}
</script>
</html>
HTML Web Workers is the solution that I need.
Question closed!
https://www.w3schools.com/HTML/html5_webworkers.asp
I have been developing a chat room User Interface and I have a question.
In my UI I am using a div as my textbox and have a max message length of 500. There is a counter to show how many characters you have left, like '245/500'. On Google, this works fine but on safari, if you type one letter then delete it the counter goes from 1 to 4 and not 1 to 0. This also breaks my placeholder for the div.
Your help is much appreciated.
Here is some example code, clone it, then run it in Safari then try Google.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<title>HTML Stuff</title>
<style>
#text-div {
width: 200px;
padding: 10px;
max-height: 50px;
background-color: rgb(197, 226, 252);
overflow-y: scroll;
overflow-x: hidden;
}
#text-div:empty:before {
content: attr(data-placeholder);
color: rgb(102, 101, 101);
}
#counter {
font-weight: bolder;
font-size: 50px;
}
</style>
</head>
<body>
<div id="text-div" contenteditable="true" data-placeholder="This is a Placeholder"></div>
<div id="counter">0</div>
</body>
<script>
var text = document.getElementById('text-div')
var counter = document.getElementById('counter')
$('#text-div').on('input', () => {
counter.innerHTML = text.innerHTML.length
})
</script>
</html>
Using element.innerHTML will return the contents + the characters "&", "<", ">" as HTML entities "&", "<" and ">" - MDN
Use element.innerText.length to get consistent results about the length of ONLY the contents!
var text = document.getElementById('text-div')
var counter = document.getElementById('counter')
$('#text-div').on('input', () => {
counter.innerText = text.innerText.length - 1
})
Check the documentation!
I'm building a programmable calculator that uses a contenteditable div as a place to enter the expression you need evaluated. The div listens for the user to strike the return key, then passes its text content to the calculator engine, clears itself, and then displays the result of the expression.
Everything works as expected on desktop browsers, but under mobile browsers, there is some strange behaviour when the return key is pressed when the caret is not at the end of the text. Sometimes hitting the return key will insert a space or newline, sometimes it will submit and clear everything before the caret, and under Chrome it seems to create a new div element. Any ideas what I'm doing wrong?
I have successfully tested the code in Firefox 59.0.2 and Chromium 65.0.3325.181 running on Ubuntu 17.10, and Firefox 59.0.2 running on Windows 7. I have unsuccessfully tested the code in Firefox 59.0.2 and Chrome 65.0.3325.109 running on Android 8.1.0.
window.addEventListener("load", function () {
"use strict";
var i = document.getElementById("i");
var o = document.getElementById("o");
i.addEventListener("keypress", function (e) {
if (e.key === "Enter") {
e.preventDefault();
o.textContent = i.textContent;
i.textContent = "";
return false;
}
return true;
});
});
div {
font-size: 24px;
padding: 1em;
border: 1px solid black;
min-height: 1em;
box-sizing: content-box;
margin: 1em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=0">
<title>Test</title>
</head>
<body>
<div id="i" contenteditable="true"></div>
<div id="o"></div>
</body>
</html>
EDIT:
After some work, I've made an alternate method of detecting input, copying the text, and clearing the box. It no longer listens for keystrokes but watches for changes in the box itself. It works on desktop but fails in similar ways on mobile. It also has the added problem that it will crash Firefox mobile if you type too quickly. I've tested the code on the same browsers as before.
window.addEventListener("load", function () {
"use strict";
var i = document.getElementById("i");
var o = document.getElementById("o");
var getText;
var input;
getText = function (e) {
var s = [];
e.childNodes.forEach(function (n) { // get every child
switch (n.nodeType) {
case 1: // element, so recurse
s.push(getText(n));
break;
case 3: // text
s.push(n.nodeValue);
break;
}
});
return s.join("");
};
input = function (e) {
if (i.childNodes.length > 1 || (i.firstChild && i.firstChild.nodeType != 3)) { // checking for added <br />
e.preventDefault();
o.textContent = getText(i);
while (i.firstChild) { // clear element
i.removeChild(i.firstChild);
}
// add and remove listener to prevent event from firing on clear
i.removeEventListener("input", input);
setTimeout(function () {
i.addEventListener("input", input, true);
}, 100);
return false;
}
return true;
};
i.addEventListener("input", input, true);
});
div {
font-size: 24px;
padding: 1em;
border: 1px solid black;
min-height: 1em;
box-sizing: content-box;
margin: 1em;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=0">
<title>Test</title>
</head>
<body>
<div id="i" contenteditable="true"></div>
<div id="o"></div>
</body>
</html>
EDIT 2 (with workaround):
After some thinking, I realized I don't need to use a contenteditable div, so I've re-worked it to use a styled text input field which works properly.
window.addEventListener("load", function () {
"use strict";
var f = document.getElementById("f");
var i = document.getElementById("i");
var o = document.getElementById("o");
f.addEventListener("submit", function (e) {
e.preventDefault();
o.textContent = i.value;
i.value = "";
return false;
});
});
input[type="text"] {
display: block;
width: 100%;
overflow: auto;
outline: none;
border: none;
border-radius: 0;
box-shadow: none;
box-sizing: content-box;
}
#i, div {
width: calc(100% - 4em - 2px);
min-height: 1em;
font-size: 24px;
padding: 1em;
border: 1px solid black;
min-height: 1em;
margin: 1em;
color: black;
font-family: serif;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=0">
<title>Test</title>
</head>
<body>
<form id="f" name="f">
<input id="i" name="i" type="text" >
</form>
<div id="o"></div>
</body>
</html>