It supposed to show two different images by moving the slider to the left or right.
enter image description here
However, i got this error.
enter image description here
Seems like the setProperty isnt working properly as I wished and I tried to use plain CSS they complained about
enter image description here
So probably the javascript isnt working properly?
Does anyone know what's the problem is? thanks
HTML
<main>
<div class="container">
<div class="image-container">
<img class="image-before slider-image"
src="/img/before.png" alt="before image">
<img class="image-after slider-image"
src="/img/after.png" alt="before image">
</div>
<input type="range" min="0" step="10" max="100" value="50" class="slider" aria-label="Percentage of before photo shown" />
<div class="slider-line">
<div class="slider-button" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" fill="currentColor" viewBox="0 0 256 256"><rect width="256" height="256" fill="none"></rect><line x1="128" y1="40" x2="128" y2="216" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line><line x1="96" y1="128" x2="16" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line><polyline points="48 160 16 128 48 96" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></polyline><line x1="160" y1="128" x2="240" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></line><polyline points="208 96 240 128 208 160" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"></polyline></svg>
</div>
</div>
</div>
</main>
SCSS
*,
*::after,
*::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
$white : #dddddd;
$position: 50%;
$box-shadow: 1px 1px 1px hsl(0, 50%, 2%, .5);
img {
display: block;
max-width: 100%;
}
main {
display: grid;
place-items: center;
min-height: 100vh;
}
.container {
display: grid;
place-content: center;
position: relative;
overflow: hidden;
border-radius: 1rem;
position: $position;
}
.image-container {
max-width: 800px;
max-height: 90vh;
aspect-ratio: 1/1;
}
.slider-image{
width: 100%;
height: 100%;
object-fit: cover;
object-position: left;
}
.image-before {
position: absolute;
inset: 0;
width: $position;
}
.slider {
position: absolute;
inset: 0;
cursor: pointer;
opacity: 0;
// for firefox
width: 100%;
height: 100%;
&:focus-visible ~ .slider-button{
outline: 5px solid black;
outline-offset: 3px;
}
}
// .slider:focus-visible ~ .slider-button {
// outline: 5px solid black;
// outline-offset: 3px;
// }
.slider-line {
position: absolute;
inset: 0;
width: 0.2rem;
height: 100%;
background-color: $white;
z-index: 10;
left: $position;
transform: translateX(-50%);
pointer-events: none;
}
.slider-button {
position: absolute;
background-color: $white;
padding: .5rem;
border-radius: 100vw;
display: grid;
place-items: center;
top: 50%;
left: $position;
transform: translateX(-50%);
pointer-events: none;
z-index: 100;
box-shadow: $box-shadow;
}
JS
const container = document.querySelector(".container");
document.querySelector(".slider").addEventListener("input", (e) => {
container.style.setProperty(`$position`), `${e.target.value}%`;
});
I think you're closing the parenthesis pair of setProperty early. ${e.target.value}% is the second argument of this function call.
Also, the property set, is position (just as it is in CSS), not $position
document.querySelector(".slider").addEventListener("input", (e) => {
container.style.setProperty(`position`, `${e.target.value}%`);
});
The answer was already solved :
It seems like due to the (What runs) chrome extension, this issue is occurring.
Error handling response: TypeError: self.processResponse is not a function
If it didn't help you, just tell me.
I figured out two problems in here. First is the parenthesis closed wrongly. Second is SASS is a CSS preprocessor, which means that all SASS specific information disapears when you compile it to CSS. How to control Sass Variable with javascript
hence, here is my solution
scss
$position: 50%;
.container {
display: grid;
place-content: center;
position: relative;
overflow: hidden;
border-radius: 1rem;
--position: var(--position, $position);}
.image-before {
position: absolute;
inset: 0;
width: var(--position, $position);
}
.slider-line {
position: absolute;
inset: 0;
width: 0.2rem;
height: 100%;
background-color: $white;
z-index: 10;
left: var(--position, $position);
transform: translateX(-50%);
pointer-events: none;
}
.slider-button {
position: absolute;
background-color: $white;
padding: .5rem;
border-radius: 100vw;
display: grid;
place-items: center;
top: 50%;
left: var(--position, $position);
transform: translateX(-50%);
pointer-events: none;
z-index: 100;
box-shadow: $box-shadow;
}
app.js
const container = document.querySelector(".container");
document.querySelector(".slider").addEventListener("input", (e) => {
container.style.setProperty(`--position`, `${e.target.value}%`);
});```
Is it possible to create the broken line using HTML/CSS/JS, not picture.
It has to look like in a photo.
P.S. sorry for my ENG)
.broken-line {
position: relative;
height: 10px;
border-top: 1px solid #000;
}
.broken-line:before {
position: absolute; left: -1px; top: -1px;
content: '';
border-top: 10px solid #000;
border-right: 10px solid transparent;
}
.broken-line:after {
position: absolute; left: -2px; top: -2px;
content: '';
border-top: 10px solid white;
border-right: 10px solid transparent;
}
<div class="broken-line"></div>
You can use an SVG to make something like this pretty easily.
<svg viewBox="0 0 500 80" width="500" height="80" stroke="blue">
<text x="75" y="22" fontsize="20" stroke="black">I'm text and I'm on a line lalalalala</text>
<line x1="0" x2="50" y1="80" y2="30" />
<line x1="50" x2="500" y1="30" y2="30" />
</svg>
.broken-line {
width: 180px; /* The width/length of the normal line */
height: 10px; /* The "height" of the broken part */
border-top: 2px solid #19c4b0; /* The normal line */
border-left: 2px solid #19c4b0; /* The broken line */
transform: skew(-45deg);
-moz-transform: skew(-45deg);
-webkit-transform: skew(-45deg);
}
<div class="broken-line"></div>
You could also add a border-radius easily if you want...
Example:
...
border-radius: 10px;
...
Try the following
.broken-line {
border-top: 5px solid red;
border-radius: 25px;
}
You can change the border-radius to whatever you want to make it more sharp.
Yes there's multiple ways to accomplish it with html/css/svg/js. Here's an example of one technique to get you started.
body {
padding: 5rem 2rem;
}
.container {
position: relative;
}
.line-tooltip {
display: inline-block;
position: absolute;
left: 1.75rem;
border-bottom: dodgerblue 2px solid;
transform: translateY(-2rem);
opacity: 0;
transition: opacity .25s ease;
}
.line-tooltip:before {
content: "";
display: block;
position: absolute;
bottom: -1.1rem;
left: -.5rem;
height: 1.25rem;
width: 2px;
background-color: dodgerblue;
transform: rotate(45deg);
}
#line-test {
color: dodgerblue;
}
#line-test:hover + .line-tooltip {
opacity: 1;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" rel="stylesheet"/>
<div class="container">
<i id="line-test" class="fas fa-info-circle"></i> <- Hover the icon...
<aside class="line-tooltip">Hey I'm some text that makes a nifty tooltip. Yay!</aside>
</div>
I've got this little UI I'm working on and I'm just now applying some animation to it so it can be activated via keypress in-game. I've sort of got both animations I want, I just can't get them working together, at the same time.
I'm not really familiar with CSS animations, If I could just do this all with after effects, I'd be dandy, but nevertheless.
I have created this image to sort of provide a brief explanation of what I'm looking for and I've got a JSFiddle with the slideout code, plus I'll include a snippet for the fade-in code.
Brief Explanation of What I'm Looking For:
Here is the JSFiddle for the slideout animation
Here is the JSFiddle with additions made since posting
Below is the Snippet for the FadeIn Animation
.positive {
color: rgb(114, 204, 114);
}
.negative {
color: rgb(224, 50, 50);
}
.tempbg {
background-color: #3f3f3f;
}
.portrait {
background-image: url("https://gdurl.com/VKq8");
position: fixed;
top: 34px;
left: 560px;
width: 120px;
height: 120px;
border-radius: 110px;
z-index: 2;
display: block;
opacity: 1;
}
.container {
background-color: rgba(0, 0, 0, 0.288);
position: absolute;
top: 50px;
left: 660px;
width: 260px;
height: 85px;
border-radius: 50px;
border-bottom-left-radius: 0%;
border-top-left-radius: 0%;
z-index: 1;
}
/*#heal, #armor, #hunger, #thirst, #stamina, #voice {
}*/
#boxHeal, #boxArmor, #boxStamina, #boxHunger, #boxThirst, #boxVoice {
width: 100%;
height: 100%;
transition: 0.2s ease-in-out;
}
#heal {
position: absolute;
left: 26px;
bottom: 70px;
width: 140px;
height: 10px;
padding: 0;
float:left;
}
#armor {
position: absolute;
left: 27px;
bottom: 54px;
width: 140px;
height: 10px;
}
#hunger {
position: absolute;
left: 62px;
bottom: 28px;
width: 113px;
height: 10px;
}
.iconhunger {
position: relative;
left: -40px;
bottom: 10px;
z-index: 3;
align-content: left;
}
#thirst {
position: absolute;
left: 22px;
bottom: 54px;
width: 113px;
height: 10px;
padding: 0;
float:left;
}
.iconthirst {
position: relative;
left: 0.5px;
bottom: -29.5px;
z-index: 3;
align-content: left;
}
#stamina {
position: absolute;
left: 62.5px;
bottom: 1px;
width: 113px;
height: 10px;
padding: 0;
float:left;
}
.iconstamina {
position: absolute;
z-index: 3;
align-content: left;
left: -36px;
bottom: -3px;
}
#voice {
position: absolute;
left: 200px;
bottom: -00px;
width: 107.5px;
height: 10px;
padding: 0;
float:left;
}
.fa-microphone {
position: absolute;
z-index: 3;
left: 69px;
bottom: 25px;
color: #525151;
font-size: 38px;
}
.fa-microphonebg {
position: absolute;
top: 0px;
left: 140px;
width: 121px;
height: 85px;
background-image:
radial-gradient(circle at 0% 50%, rgba(0,0,0,0) 50px, #fff 51px);
border-top-right-radius: 40px;
border-bottom-right-radius: 40px;
z-index: 2;
}
#boxHeal {
background: rgb(97, 191, 92);
border: solid 0.3px rgb(97, 191, 92);
border-radius: 30px;
}
#boxArmor {
background: rgb(96, 136, 220);
border: solid 0.3px rgb(96, 136, 220);
border-radius: 180px;
border: -5px;
}
#boxHunger {
background: rgb(255, 255, 255);
position: absolute;
left: -10px;
bottom: 7px;
border: solid 0.3px #ffffff;
border-radius: 30px;
}
#boxThirst {
background:rgb(255, 255, 255);
position: absolute;
left: 30px;
bottom: -34px;
border: solid 0.3px #ffffff;
border-radius: 30px;
}
#boxStamina {
background: rgb(255, 255, 255);
position: absolute;
left: -10px;
bottom: 4px;
border: solid 0.3px #ffffff;
border-radius: 30px;
}
#boxVoice {
background: rgb(180, 180, 180);
position: absolute;
z-index: 4;
height: 27px;
width: 14.1px;
left: 215px;
bottom: 36.5px;
border-radius: 30px;
}
#boxVoice.active {
background: rgb(46, 196, 66);
}
.position {
font-family: "gta-ui", Verdana, Tahoma;
font-size: 30px;
position: absolute;
bottom: 0.35%;
left: 16%;
text-shadow: -1px 1px 2px #000, 1px 1px 2px #000, 1px -1px 0 #000, -1px -1px 0 #000;
color: #ffffff;
}
.seperator {
color: rgb(224, 50, 50);
}
.seperator2 {
color: rgb(240, 200, 80);
}
#slideout {
position: fixed;
top: 100px;
left: -25px;
animation-delay: : 2s;
-webkit-transition-duration: 0.3s;
-moz-transition-duration: 0.3s;
-o-transition-duration: 0.3s;
transition-duration: 0.3s;
}
#slideout_tab {
position: relative;
top: 0;
left: 0;
}
#slideout_inner {
position: absolute;
top: -100px;
left: 26px;
}
#showblock:not(:checked)+#slideout {
left: -195px;
opacity: 0;
display: none;
}
#showblock:checked+#slideout {
opacity: 1;
display: block;
-webkit-animation: fadeInFromNone 0.5s ease-out;
-moz-animation: fadeInFromNone 0.5s ease-out;
-o-animation: fadeInFromNone 0.5s ease-out;
animation: fadeInFromNone 0.5s ease-out;
}
#-webkit-keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
#-moz-keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
#-o-keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
#keyframes fadeInFromNone {
0% {
display: none;
opacity: 0;
}
1% {
display: block;
opacity: 0;
}
100% {
display: block;
opacity: 1;
}
}
#showblock {
opacity: 1;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>SoL RP UI</title>
<link href="css/style.css" rel="stylesheet" type="text/css"/>
<link rel="stylesheet" href="https://icono-49d6.kxcdn.com/icono.min.css">
<script src="https://kit.fontawesome.com/3f31cfc768.js"></script>
</head>
<body class="tempbg">
<div class="portrait">
</div>
<input type="checkbox" id="showblock">
<div id="slideout">
<label id="slideout_tab" for="showblock" title="Admin Slider">
</label>
<div id="slideout_inner">
<div class="container">
<div id="heal">
<div id="boxHeal"></div>
</div>
<div id="armor">
<div id="boxArmor"></div>
</div>
<div id="hunger">
<svg class="iconhunger" width="36" height="12" viewBox="0 0 14 12" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M9.44096 7.09788L12.0944 4.62314C13.9855 2.86906 14.0734 1.25095 13.9708 0.462298C13.9561 0.407908 13.9268 0.353518 13.8828 0.312725C13.7656 0.203945 13.5897 0.203945 13.4724 0.312725L12.6954 1.03339L2.94672 10.0893C2.62421 10.3885 2.62421 10.8916 2.94672 11.1907C3.26923 11.4899 3.81164 11.4899 4.13415 11.1907L4.33939 10.946C4.70588 10.4973 6.58232 7.98172 6.86086 7.58739C6.97813 7.42422 7.09541 7.32904 7.18337 7.28825C7.32997 7.23386 7.44724 7.30185 7.44724 7.30185C8.09227 7.65538 8.91321 7.58739 9.44096 7.09788Z" fill="white"/>
<path d="M4.95508 6.20047C5.49749 5.9965 5.86398 6.17327 6.09854 6.36364L6.86084 5.65657C6.65561 5.43901 6.46503 5.08547 6.68493 4.59596C6.99278 3.90249 7.242 3.45377 6.17184 2.37957C5.131 1.29176 3.4598 0.285548 2.68283 0.0679876C2.50692 0.027195 2.331 0 2.19906 0C2.1844 0 2.1844 0 2.16974 0C2.12577 0 2.09645 0.0135975 2.06713 0.0407925C1.99383 0.10878 1.99383 0.21756 2.06713 0.27195L4.70587 2.7195C4.83781 2.84188 4.83781 3.04584 4.70587 3.18182C4.57393 3.3042 4.35404 3.3042 4.20744 3.18182L3.89959 2.89627L3.21058 2.25719C2.69749 1.78127 2.36032 1.46853 2.03781 1.22378C1.26084 0.625486 0.95299 0.611888 0.95299 0.611888C0.95299 0.611888 0.835713 0.598291 0.733095 0.679876C0.645137 0.775058 0.659797 0.883838 0.659797 0.883838C0.659797 0.883838 0.674456 1.16939 1.33414 1.90365C1.59802 2.2028 1.93519 2.51554 2.44828 2.99145L3.13728 3.63054L3.44514 3.91608C3.57707 4.03846 3.57707 4.24242 3.44514 4.3784C3.3132 4.50078 3.0933 4.50078 2.94671 4.3784L0.307964 1.93085C0.234666 1.86286 0.117388 1.86286 0.0587496 1.93085C0.0294302 1.95804 0.0147705 1.98524 0.0147705 2.02603C0.0147705 2.02603 0.0147705 2.03963 0.0147705 2.05322C0.0147705 2.1756 0.0440899 2.33877 0.0880689 2.50194C0.307964 3.22261 1.40744 4.75913 2.58022 5.75175C3.73833 6.71717 4.20744 6.48601 4.95508 6.20047Z" fill="white"/>
<path d="M9.51434 7.737C9.1625 7.95456 8.73737 8.07694 8.29758 8.07694C8.03371 8.07694 7.78449 8.03614 7.53528 7.95456L10.6138 11.3539C11.0683 11.7619 11.7866 11.7619 12.2264 11.3539C12.6662 10.946 12.6662 10.2661 12.2264 9.85821L9.51434 7.737Z" fill="white"/>
</g>
</svg>
<div id="boxHunger">
</div>
</div>
<div id="thirst">
<svg class="iconthirst" width="36" height="14" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.74196 0.100677C3.72525 0.0356591 3.65843 -0.013104 3.57491 0.00315034C3.52479 0.0194047 3.49138 0.0519134 3.47467 0.100677C2.9067 4.55437 0 5.46462 0 8.5692C0.0501155 10.5035 1.68722 12.0476 3.67514 11.9989C5.61294 11.9664 7.16652 10.4385 7.19993 8.5692C7.21663 5.48087 4.30993 4.55437 3.74196 0.100677ZM3.19069 5.02575C3.15728 5.15579 3.10716 5.30207 3.07375 5.44836C2.82317 6.34235 2.52248 7.35013 2.52248 8.52044C2.52248 9.15436 2.13826 9.38192 1.77075 9.38192C1.35312 9.38192 1.01902 9.05683 1.01902 8.65048C1.01902 7.26885 1.70393 6.35861 2.30531 5.56215C2.48907 5.31833 2.67283 5.07451 2.82317 4.84695C2.88999 4.74943 3.00693 4.73317 3.10716 4.79819C3.12387 4.81444 3.14057 4.8307 3.15728 4.84695C3.19069 4.89572 3.20739 4.96073 3.19069 5.02575Z" fill="white"/>
</svg>
<div id="boxThirst"></div>
</div>
<div id="stamina">
<svg class="iconstamina" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Capa_1" x="0px" y="0px" width="22px" height="22px" viewBox="0 0 487.811 487.81" style="enable-background:new 0 0 487.811 487.81;" xml:space="preserve">
<g>
<g>
<g id="_x33_6_24_">
<g>
<path d="M150.463,109.521h150.512c3.955,0,7.16-3.206,7.16-7.161c0-3.955-3.205-7.161-7.16-7.161H150.463 c-3.955,0-7.161,3.206-7.161,7.161C143.302,106.315,146.508,109.521,150.463,109.521z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/>
<path d="M15.853,179.537h150.511c3.955,0,7.161-3.206,7.161-7.161s-3.206-7.16-7.161-7.16H15.853 c-3.955,0-7.161,3.205-7.161,7.16S11.898,179.537,15.853,179.537z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/>
<path d="M56.258,253.214c0,3.955,3.206,7.162,7.161,7.162H213.93c3.955,0,7.161-3.207,7.161-7.162s-3.206-7.16-7.161-7.16H63.419 C59.464,246.054,56.258,249.259,56.258,253.214z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/>
<path d="M142.396,336.44H7.161C3.206,336.44,0,339.645,0,343.6s3.206,7.161,7.161,7.161h135.235c3.955,0,7.161-3.206,7.161-7.161 S146.351,336.44,142.396,336.44z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/>
<path d="M385.729,154.418c21.6,0,39.111-17.513,39.111-39.114s-17.512-39.113-39.111-39.113 c-21.605,0-39.119,17.513-39.119,39.113C346.609,136.905,364.123,154.418,385.729,154.418z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/>
<path d="M450.066,143.155c-22.459,31.459-52.533,35.102-84.895,15.89c-2.203-1.306-11.977-6.691-14.141-7.977 c-52.061-30.906-104.061-18.786-138.934,30.05c-14.819,20.771,19.455,40.459,34.108,19.93 c18.018-25.232,40.929-32.533,65.986-24.541c-12.83,22.27-24.047,44.405-39.875,75.853 c-15.832,31.448-50.787,56.562-84.374,36.92c-24.235-14.165-46.09,20.651-21.928,34.772 c45.854,26.799,99.619,10.343,127.066-24.493c0.952,0.509,1.958,0.968,3.062,1.354c22.422,7.812,51.814,28.61,60.77,35.981 c8.953,7.371,24.336,44.921,33.471,63.788c11.082,22.893,46.871,6.219,35.748-16.771c-10.355-21.406-27.736-64.129-41.293-74.938 c-10.875-8.669-31.988-24.803-49.895-33.956c12.115-23.466,24.729-46.679,38.008-69.491 c42.328,12.969,82.561-2.308,111.215-42.446C498.996,142.312,464.73,122.624,450.066,143.155z" data-original="#000000" class="active-path" data-old_color="#000000" fill="#FFFFFF"/>
</g>
</g>
</g>
</g>
</svg>
<div id="boxStamina"></div>
</div>
<div id="voice">
<div class="fa-microphonebg">
<i class="fas fa-microphone"></i>
</div>
<div id="boxVoice"></div>
</div>
</div> /*container*/
</div> /*slideout_inner*/
</div> /*slideout*/
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js">
</script>
<script src="js/app.js">
</script>
</body>
</html>
Your question is very broad, however I think one can sum it up to two methods:
Use classes to describe the state of the elements (e.g. the circle in the middle or on the left)
Use transform: translateX() together with the transition property.
For example, in the following snippet the right class is toggled upon clicking the red box:
const box = document.getElementById('box');
box.addEventListener('click', () => {
box.classList.toggle('right');
});
#container {
width: 80px;
height: 40px;
background-color: gray;
}
#box {
display: inline-block;
width: 40px;
height: 40px;
background-color: red;
margin: auto;
transition: all 0.4s;
}
.right {
transform: translateX(100%); /* When an element has the 'right' class,
it would move to the right by 100% */
transition: all 0.4s;
}
<div id="container">
<div id="box"></div>
</div>
You can modify this minimal example and play with the properties that vary among the "states" of your objects: their width, opacity and - of course - translate, as mentioned above.
I have a JavaScript application where users can search for places on a map. The input text provides autocomplete suggestions: as the user types, some suggestions appear at the bottom of the text input itself.
I'm using a third party JavaScript autocomplete library which charge per user request.
Unfortunately each keystroke counts as a single request since the library doesn't implement any debouncing when receiving the onInput callback from the input element. So the suggestions look snappy but at a cost of many user requests.
What I'd like to do is to redefine the on input callback inside the input element to implement debouncing (let's say 500ms).
Since the third party library accepts the JavaScript element itself, I cannot use an external debouncing mechanism: (probably the library detects the onInput message sent by the input element itself)
var placesAutocomplete = places({
appId: 'xxxxxxxxxxx',
apiKey: 'kkkkkkkkkk',
container: document.querySelector('#inputelement'), // <- the library accepts the element itself, not an "on input" listener (which could be easily debounced by an external function)
language: G_lang
});
placesAutocomplete.on('change', function(res){
// user leaves the input text, set lat lon on my map (code not shown here on SO)
var lat = res.suggestion.latlng.lat;
var lon = res.suggestion.latlng.lng;
finish(lat, lon);
});
the debounce must be provided by the JavaScript element itself. So basically, the element should fire an onInput callback filtered by the debouncing mechanism.
Is it possible to do so by using vanilla JavaScript only?
EDIT
Looks like someone tried to make a pull request for a debounce feature on the GitHub project page but got rejected:
https://github.com/algolia/places/issues/281
and someone else forked the library and merged the pull request on its own fork -> https://github.com/AcuityScheduling/places/tree/feature/debounce
Using the official codepen, I made this hackish debounced version:
var client = algoliasearch("latency", "6be0576ff61c053d5f9a3225e2a90f76")
var index = client.initIndex('movies');
var myAutocomplete = autocomplete('#search-input', {
hint: false
}, [{
source: autocomplete.sources.hits(index, {
hitsPerPage: 5
}),
displayKey: 'title',
templates: {
suggestion: function(suggestion) {
var sugTemplate = "<img src='" + suggestion.image + "'/><span>" + suggestion._highlightResult.title.value + "</span>"
return sugTemplate;
}
}
}]).on('autocomplete:selected', function(event, suggestion, dataset) {
console.log(suggestion, dataset);
});
document.querySelector(".searchbox [type='reset']").addEventListener("click", function() {
document.querySelector(".aa-input").focus();
this.classList.add("hide");
myAutocomplete.autocomplete.setVal("");
});
document.querySelector("#debouncer").addEventListener("input", function() {
var s = document.querySelector("#search-input");
s.value = this.value;
clearTimeout(this.tick);
this.tick = setTimeout(() => s.dispatchEvent(new KeyboardEvent('input')), 500);
});
document.querySelector("#search-input").addEventListener("input", function() {
var searchbox = document.querySelector(".aa-input");
var reset = document.querySelector(".searchbox [type='reset']");
if (searchbox.value.length === 0) {
reset.classList.add("hide");
} else {
reset.classList.remove('hide');
}
});
body {
padding: 60px;
}
.searchbox {
display: inline-block;
position: relative;
width: 200px;
height: 37px;
white-space: nowrap;
box-sizing: border-box;
font-size: 13px;
font-family: arial, sans-serif;
}
#debouncer {
position: absolute;
z-index: 1;
box-sizing:border-box;
padding: 0 30px 0 37px;
width: 100%;
height: 100%;
vertical-align: middle;
white-space: normal;
font-size: inherit;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: none;
border:0;
}
.algolia-autocomplete {
display: block;
height: 100%;
}
.searchbox__wrapper {
width: 100%;
height: 100%;
}
.searchbox__input {
display: inline-block;
-webkit-transition: box-shadow .4s ease, background .4s ease;
transition: box-shadow .4s ease, background .4s ease;
border: 0;
border-radius: 19px;
box-shadow: inset 0 0 0 1px #D9D9D9;
color:transparent;
background: #FFFFFF;
padding: 0;
padding-right: 30px;
padding-left: 37px;
width: 100%;
height: 100%;
vertical-align: middle;
white-space: normal;
font-size: inherit;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
.searchbox__input::-webkit-search-decoration,
.searchbox__input::-webkit-search-cancel-button,
.searchbox__input::-webkit-search-results-button,
.searchbox__input::-webkit-search-results-decoration {
display: none;
}
#debouncer:hover ~ * .searchbox__input {
box-shadow: inset 0 0 0 1px silver;
}
#debouncer:focus ~ * .searchbox__input,
#debouncer:active ~ * .searchbox__input {
outline: 0;
box-shadow: inset 0 0 0 1px #4098CE;
background: #FFFFFF;
}
#debouncer::-webkit-input-placeholder {
color: #AAAAAA;
}
#debouncer::-moz-placeholder {
color: #AAAAAA;
}
#debouncer:-ms-input-placeholder {
color: #AAAAAA;
}
#debouncer::placeholder {
color: #AAAAAA;
}
.searchbox__submit {
position: absolute; z-index:2;
top: 0;
right: inherit;
left: 0;
margin: 0;
border: 0;
border-radius: 18px 0 0 18px;
background-color: rgba(255, 255, 255, 0);
padding: 0;
width: 37px;
height: 100%;
vertical-align: middle;
text-align: center;
font-size: inherit;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.searchbox__submit::before {
display: inline-block;
margin-right: -4px;
height: 100%;
vertical-align: middle;
content: '';
}
.searchbox__submit:hover,
.searchbox__submit:active {
cursor: pointer;
}
.searchbox__submit:focus {
outline: 0;
}
.searchbox__submit svg {
width: 17px;
height: 17px;
vertical-align: middle;
fill: #666666;
}
.searchbox__reset {
position: absolute; z-index:2;
top: 8px;
right: 8px;
margin: 0;
border: 0;
background: none;
cursor: pointer;
padding: 0;
font-size: inherit;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
fill: rgba(0, 0, 0, 0.5);
}
.searchbox__reset.hide {
display: none;
}
.searchbox__reset:focus {
outline: 0;
}
.searchbox__reset svg {
display: block;
margin: 4px;
width: 13px;
height: 13px;
}
.searchbox__input:valid~.searchbox__reset {
display: block;
-webkit-animation-name: sbx-reset-in;
animation-name: sbx-reset-in;
-webkit-animation-duration: .15s;
animation-duration: .15s;
}
#-webkit-keyframes sbx-reset-in {
0% {
-webkit-transform: translate3d(-20%, 0, 0);
transform: translate3d(-20%, 0, 0);
opacity: 0;
}
100% {
-webkit-transform: none;
transform: none;
opacity: 1;
}
}
#keyframes sbx-reset-in {
0% {
-webkit-transform: translate3d(-20%, 0, 0);
transform: translate3d(-20%, 0, 0);
opacity: 0;
}
100% {
-webkit-transform: none;
transform: none;
opacity: 1;
}
}
.aa-dropdown-menu {
position: relative;
top: -6px;
border-radius: 3px;
margin: 6px 0 0;
padding: 0;
text-align: left;
height: auto;
position: relative;
background: transparent;
border: none;
width: 100%;
left: 0 !important;
box-shadow: 0 1px 0 0 rgba(0, 0, 0, 0.2), 0 2px 3px 0 rgba(0, 0, 0, 0.1);
}
.aa-dropdown-menu:before {
position: absolute;
content: '';
width: 14px;
height: 14px;
background: #fff;
z-index: 0;
top: -7px;
border-top: 1px solid #D9D9D9;
border-right: 1px solid #D9D9D9;
transform: rotate(-45deg);
border-radius: 2px;
z-index: 999;
display: block;
left: 24px;
}
.aa-dropdown-menu .aa-suggestions {
position: relative;
z-index: 1000;
}
.aa-dropdown-menu [class^="aa-dataset-"] {
position: relative;
border: solid 1px #D9D9D9;
border-radius: 3px;
overflow: auto;
padding: 8px 8px 8px;
}
.aa-dropdown-menu * {
box-sizing: border-box;
}
.aa-suggestion {
font-size: 1.1em;
padding: 4px 4px 0;
display: block;
width: 100%;
height: 38px;
clear: both;
}
.aa-suggestion span {
white-space: nowrap!important;
text-overflow: ellipsis;
overflow: hidden;
display: block;
float: left;
line-height: 2em;
width: calc(100% - 30px);
}
.aa-suggestion.aa-cursor {
background: #eee;
}
.aa-suggestion em {
color: #4098CE;
}
.aa-suggestion img {
float: left;
vertical-align: middle;
height: 30px;
width: 20px;
margin-right: 6px;
}
<script src="//cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js"></script>
<script src="//cdn.jsdelivr.net/autocomplete.js/0/autocomplete.min.js"></script>
<form novalidate="novalidate" onsubmit="return false;" class="searchbox">
<div role="search" class="searchbox__wrapper">
<input id="debouncer" type="text" name="search" autocomplete="off" placeholder="Search for a movie">
<input id="search-input" type="search" name="autocomplete" autocomplete="off" required="required" class="searchbox__input">
<button type="submit" title="Submit your search query." class="searchbox__submit">
<svg role="img" aria-label="Search">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sbx-icon-search-13"></use>
</svg>
</button>
<button type="reset" title="Clear the search query." class="searchbox__reset hide">
<svg role="img" aria-label="Reset">
<use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#sbx-icon-clear-3"></use>
</svg>
</button>
</div>
</form>
<div class="svg-icons" style="height: 0; width: 0; position: absolute; visibility: hidden">
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="sbx-icon-clear-3" viewBox="0 0 40 40"><path d="M16.228 20L1.886 5.657 0 3.772 3.772 0l1.885 1.886L20 16.228 34.343 1.886 36.228 0 40 3.772l-1.886 1.885L23.772 20l14.342 14.343L40 36.228 36.228 40l-1.885-1.886L20 23.772 5.657 38.114 3.772 40 0 36.228l1.886-1.885L16.228 20z" fill-rule="evenodd"/></symbol>
<symbol id="sbx-icon-search-13" viewBox="0 0 40 40"><path d="M26.806 29.012a16.312 16.312 0 0 1-10.427 3.746C7.332 32.758 0 25.425 0 16.378 0 7.334 7.333 0 16.38 0c9.045 0 16.378 7.333 16.378 16.38 0 3.96-1.406 7.593-3.746 10.426L39.547 37.34c.607.608.61 1.59-.004 2.203a1.56 1.56 0 0 1-2.202.004L26.807 29.012zm-10.427.627c7.322 0 13.26-5.938 13.26-13.26 0-7.324-5.938-13.26-13.26-13.26-7.324 0-13.26 5.936-13.26 13.26 0 7.322 5.936 13.26 13.26 13.26z" fill-rule="evenodd"/></symbol>
</svg>
</div>
This approach is hardly better than this autocomplete implementation itself..
Hope it may help.
I think I managed to find a very good solution. I forked the library and enabled the debounce feature (which was already there, only disabled for the autocomplete form).
End result: 80% usage drop given a small autocomplete lag of 200ms, perfectly acceptable
I am creating a sort-of popup menu that is specific to each .smallCatalogBlock div. The circle you see under the title is the trigger. The issue I am having is that if you click on the blue circle, both popup menus fadeIn, when it should only be that specific one.
The same applies to the popup title. It uses only the first .smallCatalogBlock information, opposed to the one clicked on.
Does anyone know how I can leave this in the dynamic setup I am going for, while populating the specific information for the one clicked on?
var catalogName = $('.smallCatalogBlock').data('fill-specs');
//Filling Circle
$('.catalogSmallCircle').html(
'<div class="catalogSmallCircleIn" data-catalog-name=' + catalogName + '><div class="total-center"><div class="circlePlus"></div></div></div><div class="catalogCircleExpand"><div class="catalogExpandClose">x</div><div class="total-center expandText"><span class="catalogName pdfSubHeader"></span><p class="dGw circleExpandText"></p><button class="catalogDownload downloadButton" name="Profile_Catalog" data-catalog-now="Profile Small Catalog Button" data-catalog-view-name="Profile Catalog">View</button><button class="catalogDownload requestButton" data-catalog-name="Profile Catalog">Request</button></div></div>'
)
//Circle Expand
$('.catalogSmallCircleIn').on('click', function() {
// old $('.catalogSmallCircle').addClass('rectangle').find('.catalogSmallCircleIn').hide();
$(this).closest('.catalogSmallCircle').addClass('rectangle').find('.catalogSmallCircleIn').hide();
// old $('.catalogCircleExpand').fadeIn(100).addClass('rectangle');
//$(this).closest('.catalogCircleExpand').fadeIn(100).addClass('rectangle');
$('.catalogCircleExpand').fadeIn(100).addClass('rectangle');
//Getting Catalog Name
let catalogChoice = $(this).data('catalog-name');
$('.catalogName').html(catalogChoice);
event.stopPropagation();
});
//Close Circle
$('.catalogExpandClose').on('click', function(event) {
$('.catalogSmallCircle').removeClass('rectangle').find('.catalogSmallCircleIn').fadeIn();
$('.catalogCircleExpand').hide().removeClass('rectangle');
});
.smallCatalogWrap {
width: 100%;
height: auto;
margin: 60px 0;
}
.smallCatalogBlock {
width: 25%;
height: auto;
display: inline-block;
vertical-align: top;
margin: 20px auto;
text-decoration: none;
}
.smallCatalogTitle {
font-family: 'Nunito', sans-serif;
color: #4d4d4d;
font-size: 1.3rem;
text-align: center;
display: block;
font-weight: 400;
}
.smallCatalogButtonWrap {
margin-top: 15px;
width: 100%;
position: relative;
}
.catalogSmallCircle {
background: #225DB8;
width: 70px;
height: 70px;
position: absolute;
margin: 10px auto;
left: 90%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
border-radius: 100%;
box-shadow: 0 0 20px rgba(0, 0, 0, .9);
border: 2px solid #FFF;
webkit-transition: all 1s;
transition: all 1s;
cursor: pointer;
}
.catalogSmallCircle.rectangle {
border-radius: 0;
border: 2px solid #094765;
background: linear-gradient(to bottom right, #225DB8, #4174C2);
width: 400px;
min-height: 200px;
webkit-transition: all 1s;
transition: all 1s;
transform: translate(-45%, -45%);
-webkit-transform: translate(-45%, -45%);
z-index: 1;
cursor: auto;
}
.catalogSmallCircleIn {
width: 100%;
height: 100%;
position: relative;
}
.circlePlus {
background-size: 30px 30px;
width: 30px;
height: 30px;
display: block;
margin: 0 auto;
z-index: 1;
}
.catalogCircleExpand {
height: 0;
display: none;
opacity: 0;
webkit-transition: all .5s;
transition: all .5s;
}
.catalogCircleExpand.rectangle {
opacity: 1;
height: auto;
webkit-transition: all .5s;
transition: all .5s;
transition-delay: .4s;
-webkit-transition-delay: .4s;
padding: 10px 0;
}
.expandText .catalogDownload {
font-size: 1.1rem;
padding: .7em 1.1em;
}
.expandText .pdfSubHeader {
font-size: 1.1rem;
}
.catalogExpandClose {
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="smallCatalogWrap">
<div class="smallCatalogBlock" data-fill-specs="Catalog">
<span class="smallCatalogTitle">Catalog</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div>
<div class="smallCatalogBlock" data-fill-specs="Technology">
<span class="smallCatalogTitle">Technology</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div>
</div>
You have to loop over the smallCatalogBlocks and build them individually, otherwise they will all have the same catalog name. And then in your event handlers, you have to make all your selectors be contextual lookups.
I ran the modified code, and it appears to be building the circles correctly, however for some reason the text is not showing up on them, even though the text is there if you inspect the element. Didn't figure that part out, but this should show you at least how to do the contextual logic and the looping to build the elements.
$('.smallCatalogBlock').each(function(index, catalogBlock){
var catalogName = $(catalogBlock).data('fill-specs');
console.log(catalogName);
//Filling Circle
$('.catalogSmallCircle', catalogBlock).html(
'<div class="catalogSmallCircleIn" data-catalog-name='+ catalogName +'><div class="total-center"><div class="circlePlus"></div></div></div><div class="catalogCircleExpand"><div class="catalogExpandClose">x</div><div class="total-center expandText"><span class="catalogName pdfSubHeader"></span><p class="dGw circleExpandText"></p><button class="catalogDownload downloadButton" name="Profile_Catalog" data-catalog-now="Profile Small Catalog Button" data-catalog-view-name="Profile Catalog">View</button><button class="catalogDownload requestButton" data-catalog-name="Profile Catalog">Request</button></div></div>'
)
});
//Circle Expand
$('.catalogSmallCircleIn').on('click', function(event) {
var $smallCircle = $(this).closest('.catalogSmallCircle');
$smallCircle
.addClass('rectangle')
.find('.catalogSmallCircleIn')
.hide();
$smallCircle
.find('.catalogCircleExpand')
.fadeIn(100)
.addClass('rectangle');
//Getting Catalog Name
let catalogChoice = $(this).data('catalog-name');
console.log(catalogChoice);
$smallCircle.find('.catalogName').html(catalogChoice);
event.stopPropagation();
});
//Close Circle
$('.catalogExpandClose').on('click', function(event) {
var $smallCircle = $(this).closest('.catalogSmallCircle');
$smallCircle
.removeClass('rectangle')
.find('.catalogSmallCircleIn')
.fadeIn();
$smallCircle
.find('.catalogCircleExpand')
.hide()
.removeClass('rectangle');
});
.smallCatalogWrap {
width: 100%;
height: auto;
margin: 60px 0;
}
.smallCatalogBlock {
width: 25%;
height: auto;
display: inline-block;
vertical-align: top;
margin: 20px auto;
text-decoration: none;
}
.smallCatalogTitle {
font-family: 'Nunito', sans-serif;
color: #4d4d4d;
font-size: 1.3rem;
text-align: center;
display: block;
font-weight: 400;
}
.smallCatalogButtonWrap {
margin-top: 15px;
width: 100%;
position: relative;
}
.catalogSmallCircle {
background: #225DB8;
width: 70px;
height: 70px;
position: absolute;
margin: 10px auto;
left: 90%;
-webkit-transform: translateX(-50%);transform: translateX(-50%);
border-radius: 100%;
box-shadow: 0 0 20px rgba(0,0,0,.9);
border: 2px solid #FFF;
webkit-transition: all 1s;transition: all 1s;
cursor: pointer;
}
.catalogSmallCircle.rectangle {
border-radius: 0;
border: 2px solid #094765;
background: linear-gradient(to bottom right,#225DB8,#4174C2);
width: 400px;
min-height: 200px;
webkit-transition: all 1s; transition: all 1s;transform: translate(-45%, -45%);-webkit-transform: translate(-45%, -45%);
z-index: 1;
cursor: auto;
}
.catalogSmallCircleIn {
width: 100%;
height: 100%;
position: relative;
}
.circlePlus {
background-size: 30px 30px;
width: 30px;
height: 30px;
display: block;
margin: 0 auto;
z-index: 1;
}
.catalogCircleExpand {
height: 0;
display: none;
opacity: 0;
webkit-transition: all .5s;
transition: all .5s;
}
.catalogCircleExpand.rectangle {
opacity: 1;
height: auto;
webkit-transition: all .5s;
transition: all .5s;
transition-delay: .4s;
-webkit-transition-delay: .4s;
padding: 10px 0;
}
.expandText .catalogDownload {
font-size: 1.1rem;
padding: .7em 1.1em;
}
.expandText .pdfSubHeader {
font-size: 1.1rem;
}
.catalogExpandClose {
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="smallCatalogWrap">
<div class="smallCatalogBlock" data-fill-specs="Catalog">
<span class="smallCatalogTitle">Catalog</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div><div class="smallCatalogBlock" data-fill-specs="Technology">
<span class="smallCatalogTitle">Technology</span>
<div class="smallCatalogButtonWrap">
<div class="catalogSmallCircle"></div>
</div>
</div>
</div>