How to pass on dynamic delay to d3.interval - javascript

d3.interval takes two parameters, callback and delay,e.g.
d3.interval(callback, delay).
I was wondering if it is possible to pass on a dynamic delay for each interval.
For example, in the following, I am asking the interval to run at 1000ms delay. But is there a way I can ask d3.interval to run at 0ms, 1000ms, 2000ms, 3000ms respectively for interval# 1,2,3,4.
I tried like desiredDelay[counterF] but it did not work.
const masterSelection = d3.selectAll('[class^="text"]');
const node = masterSelection.nodes();
const len = node.length - 1;
let counterF = 0;
const del = 1000;
const desiredDelay = [0, 1000, 2000, 3000]
let ticker = d3.interval(
e => {
const element = masterSelection['_groups'][0][counterF];
const selection = d3.select(element).node();
console.log(selection);
counterF++;
(counterF > len) ? ticker.stop(): null
}, del
)
<!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>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<body>
<div class='text1'>one</div>
<div class='text2'>two</div>
<div class='text3'>three</div>
<div class='text4'>four</div>
</body>
<script type="text/javascript" src="prod.js"></script>
</html>

Short answer: you can't.
If you look at the source code you'll see that if the delay is not null...
if (delay == null) return t.restart(callback, delay, time), t;
...it will be coerced to a number using the unary plus operator:
t.restart = function(callback, delay, time) {
delay = +delay,
etc...
What you can do is creating your own interval function, which is out of the scope of this answer.

Adapted from this, the following works as desired and is to be used with d3.timeout.
const masterSelection = d3.selectAll('[class^="text"]');
const node = masterSelection.nodes();
const len = node.length - 1;
let counter = 0;
//const del = 1000;
const delay = [0, 1000, 2000, 3000];
function show() {
const element = masterSelection["_groups"][0][counter];
const selection = d3.select(element).node();
console.log(selection);
counter++;
if (counter > len) return
d3.timeout(show, delay[counter]);
}
show();
<!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>
</head>
<script type="text/javascript" src="https://d3js.org/d3.v7.min.js"></script>
<body>
<div class='text1'>one</div>
<div class='text2'>two</div>
<div class='text3'>three</div>
<div class='text4'>four</div>
</body>
<script type="text/javascript"></script>
</html>

Related

Why isnt my button displaying value onto the div

I want the button with the id of number1 to display the value of 1 on to the input box which has the id of quest which is short for question.I also want to know if my code can be made more readable.
<!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>Calucator</title>
<style>
body{
text-align: center;
}
</style>
<script>
const quest = document.getElementById("quest");
const data = quest.value;
const yourElement = document.createElement("div");
function nums(){
const num1 = document.getElementById('number1').innerText = 1;
data.textContent = num1;
}
function run() {
nums()
yourElement.textContent = data
quest.appendChild(yourElement);
}
</script>
</head>
<body>
<h1>Calucator</h1>
<input type="number" placeholder="Enter now" name="" id="quest">
<button onclick="run()">=</button>
<br>
<button onclick="" id="number1">1</button>
</body>
</html>
<script>
const quest = document.getElementById("quest");
const data = quest.value;
const yourElement = document.createElement("div");
//PROBLEM 1: You are not attaching yourElement to the DOM. See Element.insertBefore / Element.appendChild
function nums(){
const num1 = document.getElementById('number1').innerText = 1;
data.textContent = num1;
}
function run() {
nums()
yourElement.textContent = data
quest.appendChild(yourElement);
}
</script>
And
<button onclick="run()">=</button>
Problem 2: Don't use inline element event handling. It isn't safe and Content-Security-Policy won't allow it. Instead, use JavaScript Element.addEventListener(...)

Selecting Dropdown option, change h1 with javascript

I am very new to coding and couldn't find solution with if condition for this.
I know how I can do it with html code and options, but this time I need to make it with arrays and if function.
Basically I just need a dropdown with languages (which I made) and then when I click on specific language (for example, English) - I need to change html h1 to "Hello!", when I click Latvian "Labdien" etc.
Basically I need to write a proper if function, hope you could tell me what's wrong there.
const select = document.getElementById("select"),
arr = ["Latvian", "English", "Russian"];
for (var i = 0; i < arr.length; i++) {
var option = document.createElement("OPTION"),
txt = document.createTextNode(arr[i]);
option.appendChild(txt);
option.setAttribute("value", arr[i]);
select.insertBefore(option, select.lastChild);
}
if (arr[0] = "Latvian") {
document.getElementById("heading").innerHTML = "Labdien!";
} else if (arr[1] == "English") {
document.getElementById("heading").innerHTML = "Hello!";
} else if (arr[2] == "Russian") {
document.getElementById("heading").innerHTML = "Добрый день!";
}
<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>JavaScript Dropdown</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1 class="heading" id="heading"></h1>
<select class="drop" id="select"></select>
<script src="./main.js"></script>
</body>
Still figuring out whats wrong with if statement, there is some problem in :
if(arr[0] == "Latvian")
else if(arr[1] == "English")
else if(arr[2] == "Russian").
Or maybe I need to call a function and then place it onchoice in HTML? Help.. been googling and youtubing all day
You can add a change event listener to the select element. Also, you can use the index of each language as the value of the select options, and use the same array when set the h1 inner HTML:
var select = document.getElementById("select");
var arr = [
{ id: 1, language: 'Latvian', title: 'Labdien!' },
{ id: 2, language: 'English', title: 'Hello!' },
{ id: 3, language: 'Russian', title: 'Добрый день!' }
];
for (var i = 0; i < arr.length; i++) {
var option = document.createElement("OPTION");
var txt = document.createTextNode(arr[i].language);
option.appendChild(txt);
option.setAttribute('value', arr[i].id);
select.insertBefore(option, select.lastChild);
}
// add a change event listener to handle the language title
select.addEventListener('change', changeHeading);
// trigger a change event in order to display the selected language's title
select.dispatchEvent(new Event('change'));
function changeHeading(event) {
var language = arr.find(
(language) => language.id === parseInt(event.target.value)
);
document.getElementById('heading').innerHTML = language.title;
}
<!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>JavaScript Dropdown</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1 class="heading" id="heading"></h1>
<select class="drop" id="select"></select>
<script src="./main.js"></script>
</body>
</html>

Javascript - setTimeout

I am learning Javascript right now. I have a small issue that I can't figure out how to solve it. I would like to clear content of my html page after my function displayed "Hi hi" in web page.
<html>
<body onload="alertFunc()">
<script>
function alertFunc() {
var statement = "Hi hi"
for (let i = 0; i < statement.length; i++) {
let c = statement.charAt(i);
setTimeout(function(){
document.write(c);
},i * 1000);
}
}
</script>
</body>
</html>
try this to clear content of your site after 1 second
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Learning </title>
</head>
<body>
<script>
document.write('hi hi');
function alertFunc() {
setTimeout(function(){
document.write(' ');
}, 1000);
}
alertFunc();
</script>
</body>
</html>
if you want to change content with time again and again then you have to use setInterval

JavaScript works fine in the console but not in the linked .js file

I know this is a really annoying question that you have all seen a thousand times, but I can manipulate something in the DOM with my javascript fine, but when it comes to being executed in a separate .js file it does nothing. I have tried everything, if someone could help it would be much appreciated.
Here is my JS/HTML. As you can see I even linked it with the fullpath:
function randomRGB() {
const r = Math.floor(Math.random() * 256);
const g = Math.floor(Math.random() * 256);
const b = Math.floor(Math.random() * 256);
return `rgb(${r}, ${g}, ${b})`
}
const h1 = document.querySelector('h1');
h1.style.color = randomRGB();
setInterval(function(){
h1.style.color = randomRGB();
}, 500 )
<!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>
</head>
<body>
<h1>Hello</h1>
<script type="text/javascript" src="/Users/goldenpanda/Documents/VSCODE/RandomColors/app.js"></script>
</body>
</html>

Mask original e-mail on registration page using Javascript

I need to setup a page that allows users to register using their e-mail but as a requirement the e-mail shouldn't be "visible" for human eyes, I guess there's got to be a better way to do it, but so far I came up with this option using JQuery:
I created a fake control that handles the masking and captures the text so that it can be assigned to a hidden field (so that the previously working code will keep working without changes).
var emailControl = $("#eMail");
var firstHalf = "";
var secondHalf = "";
var fullMail = "";
emailControl.keyup(function(e){
var control = e.currentTarget;
var currentText = $(control).val();
if (currentText.length == 0){
fullMail = '';
firstHalf = '';
secondHalf = '';
$(control).attr('type', 'password');
}
else{
var components = currentText.split("#");
var hiddenPart = "•".repeat(components[0].length);
detectChanges(currentText);
if (components.length == 2) {
secondHalf = '#' + components[1];
}
$(control).attr('type', 'text');
$(control).val(hiddenPart + secondHalf);
fullMail = firstHalf + secondHalf;
}
});
function detectChanges(originalText) {
var position = originalText.indexOf('#');
if (position == -1) {
position = originalText.length;
}
for (var i = 0; i < position; i++){
if (originalText[i] != "•"){
firstHalf = firstHalf.substring(0, i) + originalText[i] + firstHalf.substring(i+1);
}
}
}
I did manage to get it working here: https://codepen.io/icampana/pen/KbegKE
You could give the input tag type of password: type="password".
It may cause some janky things to happen with autofill.
<!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>
</head>
<body>
<form>
email: <input type="password" name="email">
</form>
</body>
</html>
You could also do something similar with CSS
<!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>
input {
-webkit-text-security: circle;
}
</style>
</head>
<body>
<form>
email: <input name="email">
</form>
</body>
</html>

Categories