Working with Input + keyup + value and then giphy - javascript

I would like to get whatever user search via input after he will stop typing. Then i would like to pass it to giphy api but there i have a problem with passing variable/result. Here is my code :
const mainInput = document.querySelector(".main-input");
mainInput.addEventListener('keyup', getUserQuery);
function getUserQuery(e) {
let timeout = null;
let userQuery;
clearTimeout(timeout);
timeout = setTimeout(function() {
return userQuery = mainInput.value;
},300)
return userQuery;
}
//function makeUrlForSearch(getUserQuery) {
// let a = getUserQuery();
// console.log(a);
//}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
font-size: 10px;
}
.header {
padding: 1rem;
margin: 1rem auto;
}
.header-title {
font-size: 2rem;
}
.main-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
<!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>Wyszkuj Gipha!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header"><h1 class="header-title">Wyszukaj Gipha!</h1></header>
<main class="main">
<form class="main-form">
<input type="text" placeholder="Wyszukaj Gipha!" class="main-input" id="main-input">
</form>
</main>
<script src="main.js"></script>
</body>
</html>
the makerUrlForSearch is not working and i've beend siting on it for a while but its not working.
Can anyone help? So that i would get search made by user after 300ms after he stops typing and then use it in giphy api, but i cannot do it :(

There were a couple issues in the code you provided :
In getUserQuery function, you're returning userQuery before the asynchronous setTimeOut sets its value.
The makeUrlForSearch function is calling getUserQuery but is never called. I switched that and made it so getUserQuery calls the makeUrlForSearch function
In getUserQuery, the timeout declaration would always erase previous timeouts. I moved the let timeout = null instruction outside of your getUserQuery function to make it global so that a getUserQuery call can clear a previous timeout.
const mainInput = document.querySelector(".main-input");
mainInput.addEventListener('keyup', getUserQuery);
let timeout;
function getUserQuery(e) {
clearTimeout(timeout);
timeout = setTimeout(function() {
makeUrlForSearch(mainInput.value);
},300);
}
function makeUrlForSearch(getUserQuery) {
//let a = getUserQuery();
console.log(getUserQuery);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
font-size: 10px;
}
.header {
padding: 1rem;
margin: 1rem auto;
}
.header-title {
font-size: 2rem;
}
.main-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
<!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>Wyszkuj Gipha!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header"><h1 class="header-title">Wyszukaj Gipha!</h1></header>
<main class="main">
<form class="main-form">
<input type="text" placeholder="Wyszukaj Gipha!" class="main-input" id="main-input">
</form>
</main>
<script src="main.js"></script>
</body>
</html>

Below you can find a solution to your problem by using debounce function from lodash
I have made changes below. Added a raw debounce function.
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
$(document).ready(function(){
function makeUrlForSearch(query) {
let a = query;
console.log(a);
}
function getUserQuery(e) {
makeUrlForSearch(e.target.value);
}
document.querySelector(".main-input").addEventListener('keyup', debounce(getUserQuery, 300));
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
flex-flow: column wrap;
justify-content: center;
align-items: center;
font-size: 10px;
}
.header {
padding: 1rem;
margin: 1rem auto;
}
.header-title {
font-size: 2rem;
}
.main-input {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.core.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!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>Wyszkuj Gipha!</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header"><h1 class="header-title">Wyszukaj Gipha!</h1></header>
<main class="main">
<form class="main-form">
<input type="text" placeholder="Wyszukaj Gipha!" class="main-input" id="main-input">
</form>
</main>
<script src="main.js"></script>
</body>
</html>

Related

Input event listener not working at times

I have made a simple API based project wherein whenever the user enter some number in the input, the div below it with the output becomes visible and when the input field is empty the div gets hidden again as it was in the initial state. The problem is whenever I clear the input field gradually the setup works as expected but if I clear it quickly the div doesn't hide the div at all. Below given is the reference code for the same
let input = document.querySelector("#number-input");
let fact = document.querySelector(".fact-content");
input.addEventListener("input", getFact);
function getFact() {
let number = input.value;
if (number != "") {
let xhr = new XMLHttpRequest();
xhr.open("GET", "http://numbersapi.com/" + number);
xhr.onload = function () {
if (this.status == 200) {
fact.innerText = this.responseText;
fact.style.display = "block";
}
};
xhr.send();
}
else{
fact.innerText = "";
fact.style.display = "none";
}
}
#import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap');
*{
margin: 0;
padding: 0;
font-family: 'Varela Round', sans-serif;
box-sizing: border-box;
}
body{
background-color: #9AD0EC;
}
main{
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container{
width: 40%;
margin: auto;
line-height: 1.6;
background-color: #1572A1;
color: #eee;
padding: 2rem;
min-width: 500px;
border-radius: 5px;
}
.container h1{
font-size: 1.5em;
}
.container h4{
font-size: 1.2rem;
}
input{
padding: 0.5rem;
border-radius: 5px;
border: none;
margin: 10px 0;
width: 50%;
}
.fact-content{
display: none;
}
<!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" />
<link rel="stylesheet" href="style.css" />
<title>Number Fact</title>
</head>
<body>
<main>
<div class="container">
<h1>Get random fact based on numbers</h1>
<h4>Enter a number and get a random fact</h4>
<input
type="number"
id="number-input"
placeholder="Enter a number..."
/>
<p class="fact-content"></p>
</div>
</main>
</body>
</html>
Consider the case when you have two characters in your input. You delete one character, and initiate an AJAX request for the remaining character. Before that AJAX request completes, you delete the remaining character.
When you delete the final character, the event handler clears and hides the element. But then the previous AJAX request completes, and displays the outdated response in the element.
There are two things you can do here:
When the AJAX request completes, check that the input value is still the same as the number variable. If it's not, discard the response to the AJAX request.
Switch to using the fetch API, and use an AbortController instance to abort the in-flight request when the input value changes.
let input = document.querySelector("#number-input");
let fact = document.querySelector(".fact-content");
let abortToken = null;
input.addEventListener("input", getFact);
async function getFact() {
if (abortToken) {
abortToken.abort("Input changed");
abortToken = null;
}
let number = input.value;
if (!number) {
fact.innerText = "";
fact.style.display = "none";
return;
}
const url = `http://numbersapi.com/${number}`;
abortToken = new AbortController();
const { signal } = abortToken;
try {
const response = await fetch(url, { signal });
if (input.value !== number) {
// The input has been modified.
return;
}
if (!response.ok){
const errorMessage = await response.text();
console.error(response.status, response.statusText, errorMessage);
fact.innerText = "# ERROR #";
fact.style.display = "block";
return;
}
const text = await response.text();
fact.innerText = text;
fact.style.display = "block";
} catch {
}
}
#import url('https://fonts.googleapis.com/css2?family=Varela+Round&display=swap');
*{
margin: 0;
padding: 0;
font-family: 'Varela Round', sans-serif;
box-sizing: border-box;
}
body{
background-color: #9AD0EC;
}
main{
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container{
width: 40%;
margin: auto;
line-height: 1.6;
background-color: #1572A1;
color: #eee;
padding: 2rem;
min-width: 500px;
border-radius: 5px;
}
.container h1{
font-size: 1.5em;
}
.container h4{
font-size: 1.2rem;
}
input{
padding: 0.5rem;
border-radius: 5px;
border: none;
margin: 10px 0;
width: 50%;
}
.fact-content{
display: none;
}
<!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" />
<link rel="stylesheet" href="style.css" />
<title>Number Fact</title>
</head>
<body>
<main>
<div class="container">
<h1>Get random fact based on numbers</h1>
<h4>Enter a number and get a random fact</h4>
<input
type="number"
id="number-input"
placeholder="Enter a number..."
/>
<p class="fact-content"></p>
</div>
</main>
</body>
</html>

Why isn't this file opening?

Try stuffing this code into files index.html, style.css and app.js, it doesn't open. The browser says that "The webpage was reloaded because a problem occurred" and keeps on loading.I am using an MacBook Air with macOS Big Sur with an M1, if that's of any help. I removed the full HTML code and rewrote it again, and found out it is the javascript that is causing the issue. But I have no idea why, because 1) I think my code is correct and 2) I can't open the console to check for errors because the file doesn't open. Could anybody help me?
My HTML file is:
<!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">
<link rel="stylesheet" href="style.css">
<script src="./app.js" defer></script>
<title>Document</title>
</head>
<body>
<div class="type" contenteditable="true">In .type</div>
<div class="words">In .words</div>
</body>
</html>
My JavaScript file is:
const type = document.querySelector(".type");
const words = document.querySelector(".words");
console.log(type.innerHTML.split(""));
for (let i=0; i < type.innerHTML.split("").length; i++) {
type.innerHTML += `<span>${i}</span>`
}
And my css file is:
#import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background-color: #333;
}
.type, .words {
font-family: 'JetBrains Mono', monospace;
color: #fff;
border: 2px solid #007bff;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 80%;
height: 200px;
border-radius: 20px;
display: flex;
align-items: center;
padding: 50px;
font-size: 100px;
outline: none;
}
.type {
background-color: transparent;
z-index: 2;
}
.words {
background-color: #333;
z-index: 1;
}
You are running a loop on element type and updating it in loop.
You have created an endless loop my friend.
Try changing this-
for (let i=0; i < type.innerHTML.split("").length; i++) {
type.innerHTML += `<span>${i}</span>`
}
to this-
let typesplit = type.innerHTML.split("")
for (let i=0; i < typesplit.length ; i++) {
type.innerHTML += `<span>${i}</span>`
}
This way it won't update the value of .type every time.
Also try not to use type as variable name as it is a reserved word in Typescript which resembles JavaScript.

Why my JavaScript draggable slider is not working?

I'm trying to create a draggable slider with JavaScript. But it is not working on my one. I have tried the same JS code on a built-in HTML, from W3 School and that worked fluently. I can't understand what's the problem with my code!
I've tried almost everything on my concern. But still facing the same problem
let lists = document.querySelector("#lists");
let cursorRunningPosition;
let cursorStartingPosition;
let cursorMoved;
let scrollLeft;
let isdown = false;
lists.addEventListener("mousedown", (e) => {
isdown = true;
cursorStartingPosition = e.pageX;
lists.style.cursor = "grabbing";
if (isdown === true) {
scrollLeft = lists.scrollLeft;
}
})
lists.addEventListener("mouseup", (f) => {
isdown = false;
lists.style.cursor = "auto";
})
lists.addEventListener("mouseleave", (f) => {
isdown = false;
lists.style.cursor = "auto";
})
lists.addEventListener("mousemove", (g) => {
g.preventDefault();
if (isdown === true) {
cursorRunningPosition = g.pageX;
cursorMoved = cursorRunningPosition - cursorStartingPosition;
lists.scrollLeft = scrollLeft - cursorMoved;
}
})
li{
list-style-type: none;
background-color: lightcoral;
padding: 5px 10px 5px 10px;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: hidden;
}
#lists {
display: flex;
width: 157%;
justify-content: space-between;
}
.container {
width: 100%;
background-color: yellow;
height: 37vh;
overflow: hidden;
margin-left: 20%;
}
<!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">
<link rel="stylesheet" href="style.css">
<title>Test file</title>
</head>
<body>
<div class="container">
<div id="lists">
<li class="li-list">Home</li>
<li class="li-list">About</li>
<li class="li-list">Contact</li>
<li class="li-list">Portfolio</li>
<li class="li-list">Testimonials</li>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
const lists = document.querySelector(".container");
let cursorRunningPosition;
let cursorStartingPosition;
let cursorMoved;
let scrollLeft;
let isdown = false;
lists.addEventListener("mousedown", (e) => {
isdown = true;
cursorStartingPosition = e.pageX;
lists.style.cursor = "grabbing";
if (isdown === true) {
scrollLeft = lists.scrollLeft;
}
})
lists.addEventListener("mouseup", (f) => {
isdown = false;
lists.style.cursor = "auto";
})
lists.addEventListener("mouseleave", (f) => {
isdown = false;
lists.style.cursor = "auto";
})
lists.addEventListener("mousemove", (g) => {
g.preventDefault();
if (isdown == true) {
cursorRunningPosition = g.pageX;
cursorMoved = cursorRunningPosition - cursorStartingPosition;
lists.scrollLeft = scrollLeft - cursorMoved;
}
})
li{
list-style-type: none;
background-color: lightcoral;
padding: 5px 10px 5px 10px;
}
*{
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: hidden;
}
#lists {
display: flex;
width: 157%;
justify-content: space-between;
}
.container {
width: 80%;
background-color: yellow;
height: 37vh;
margin-left: 20%;
overflow: auto;
}
.container::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.container {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
<!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">
<link rel="stylesheet" href="style.css">
<title>Test file</title>
</head>
<body>
<div class="container">
<div id="lists">
<li class="li-list">Home</li>
<li class="li-list">About</li>
<li class="li-list">Contact</li>
<li class="li-list">Portfolio</li>
<li class="li-list">Testimonials</li>
</div>
</div>
<script src="app.js"></script>
</body>
</html>
I played around with this and const worked better then var or let and the css for the container:
.container {
width: 80%;
background-color: yellow;
height: 37vh;
margin-left: 20%;
overflow: auto;
}
width to 80% and margin-left to 20% and 'overflow: auto' that enables scrolling. then remove scroll bar:
.container::-webkit-scrollbar {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.container {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
PS: Click the 'Expand snippet' to see it better!

When I click the button to change all the another buttons to dark mode, it works just a single time

I made a button to change all the page to dark mode.
I have some dark buttons I want to change it to light when I click the button that change the page to dark mode.
The problem is when I want to change the page to dark mode it works, but with the dark buttons it works just a single time, and the second button doesn't work for the first time.
You will find the code that I write below.
Thanks.
let darkBackground = document.querySelector('body');
let darkModeBtn = document.getElementById('darkModeBtn');
let btnIcon = document.getElementById('btnIcon');
let codeButton = document.getElementsByClassName('btn-dark');
darkModeBtn.addEventListener('click', function() {
darkBackground.classList.toggle('darkbackground');
btnIcon.classList.toggle('fa-sun');
btnIcon.classList.toggle('fa-moon');
for (var i = 0, len = codeButton.length; len > i; i++) {
codeButton[i].classList.toggle('btn-light');
codeButton[i].classList.toggle('btn-dark');
};
});
.darkbackground {
background-color: rgb(46, 45, 49);
transition: .15s;
color: white;
}
.darkmodebtn {
font-size: 1.50rem;
padding: 0.5rem 0.85rem;
background-color: rgba(47, 128, 237, 1);
outline: none;
border: 0;
border-radius: 20px;
color: white;
position: fixed;
bottom: 18px;
right: 18px;
}
.darkmodebtn:focus {
outline: none;
}
<!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">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.1/css/all.css" integrity="sha384-vp86vTRFVJgpjF9jiIGPEEqYqlDwgyBgEF109VFjmqGmIY/Y4HV4d3Gp2irVfcrp" crossorigin="anonymous">
<title>Document</title>
</head>
<body>
Light and Black
Light and Black
Light and Black
<button class="darkmodebtn" id="darkModeBtn"><i id="btnIcon" class="fas fa-moon"></i></button>
</body>
</html>
let darkBackground = document.querySelector('body');
let darkModeBtn = document.getElementById('darkModeBtn');
let btnIcon = document.getElementById('btnIcon');
let codeButton = document.getElementsByClassName('code-btn');
darkModeBtn.addEventListener('click', function() {
darkBackground.classList.toggle('darkbackground');
btnIcon.classList.toggle('fa-sun');
btnIcon.classList.toggle('fa-moon');
for (var i = 0, len = codeButton.length; len > i; i++) {
codeButton[i].classList.toggle('btn-light');
codeButton[i].classList.toggle('btn-dark');
};
});
.darkbackground {
background-color: rgb(46, 45, 49);
transition: .15s;
color: white;
}
.darkmodebtn {
font-size: 1.50rem;
padding: 0.5rem 0.85rem;
background-color: rgba(47, 128, 237, 1);
outline: none;
border: 0;
border-radius: 20px;
color: white;
position: fixed;
bottom: 18px;
right: 18px;
}
.darkmodebtn:focus {
outline: none;
}
<!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">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#4.5.3/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.1/css/all.css" integrity="sha384-vp86vTRFVJgpjF9jiIGPEEqYqlDwgyBgEF109VFjmqGmIY/Y4HV4d3Gp2irVfcrp" crossorigin="anonymous">
<title>Document</title>
</head>
<body>
Light and Black
Light and Black
Light and Black
<button class="darkmodebtn" id="darkModeBtn"><i id="btnIcon" class="fas fa-moon"></i></button>
</body>
</html>

Can't load API using Proxy

window.addEventListener('load', () =>{
let lat;
let long;
if(navigator.geolocation){
navigator.geolocation.getCurrentPosition((position) =>{
lat=position.coords.latitude;
long=position.coords.longitude;
// console.log(position);
const proxy= 'http://cors-anywhere.herokuapp.com/';
const api= '${proxy}https://api.darksky.net/forecast/d5906bb943a9972ceca80788517a44bc/${lat},${long}';
fetch(api)
.then(response =>{
return response.json();
})
.then(data =>{
console.log(data);
});
});
}
else{
h1.textContent="hey please allow this app to access your location";
}
});
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body{
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: 'Montserrat', sans-serif;
background: linear-gradient(rgb(62, 101, 119),rgb(36, 35, 35));
}
.time,.temperature{
height: 30vh;
width: 50%;
justify-content: space-around;
align-items: center;
display: flex;
}
.temperature{
flex-direction: column;
}
.degree-section{
display: flex;
align-items: center;
cursor: pointer;
}
.degree-section h2{
font-size: 30px;
}
.degree-section span{
font-size: 20px;
margin: 0.3cm;
}
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Weather Forecast</title>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet">
</head>
<body>
<div class="time">
<h2>TimeZone</h2>
<p>Icon</p>
</div>
<div class="temperature">
<div class="degree-section">
<h2 class="value">34</h2>
<span class="fah">F</span>
</div>
<div class="temperature-description">its cold</div>
</div>
</body>
</html>
In the above code i am trying to create a weather app and for that i am using an API and a proxy to go around the course error but i am getting following error:
weather.html:71 GET http://127.0.0.1:5500/javascript_projects/$%7Bproxy%7Dhttps://api.darksky.net/forecast/d5906bb943a9972ceca80788517a44bc/$%7Blat%7D,$%7Blong%7D 404 (Not Found)
(anonymous) # weather.html:71
weather.html:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0
Promise.then (async)
(anonymous) # weather.html:75
I don't know to overcome it ...can someone please help me
You are building your request URL with a string:
const proxy= 'http://cors-anywhere.herokuapp.com/';
const api= '${proxy}https://api.darksky.net/forecast/d5906bb943a9972ceca80788517a44bc/${lat},${long}';
In order for the placeholders to work, you should be using template literals:
const proxy= 'http://cors-anywhere.herokuapp.com/';
const api= `${proxy}https://api.darksky.net/forecast/d5906bb943a9972ceca80788517a44bc/${lat},${long}`;
Note the change from ' to ``` in the definition of the api constant.

Categories