I have made a popup whenever the image was not loaded but the problem scenario was, I am getting my popup even the image is loaded for the first time. So, I need to refresh it for disappearing it. How can I resolve it?
enter image description here
The problem is that I have included the condition to check the image is loaded or not after the code of popup .so for the first time the popup was appearing even it satisfies the condition.
Help me out of it.
You should edit your question so as to include your code, so your problem is reproducible.
You can store your image as a variable and pass a function that hides your pop-up once the image is loaded.
var img1 = document.createElement("img");
img1.onload = function() {
document.getElementById("**popup_ID").style.display='none';
};
img1.src = "**your_image_path**"; //Edit suggested by #vanowm
Change "your_image_path" and "popup_ID" to match your code.
Image has complete property that would tell if it finished loading or not. You can use that to show/hide popup on startup.
However to detect if image was successfully loaded or error occur, you'd need setup event listeners.
Here is a little example that does that:
let timer;
const elLoadGood = document.getElementById("loadGood"),
elLoadBad = document.getElementById("loadBad"),
elPopup = document.getElementById("popup"),
elImg = document.getElementById("myimage"),
imgSrc = "https://cdn.spacetelescope.org/archives/images/publicationjpg/heic1502a.jpg?";
//set event handlers
elImg.onload = imageOnLoad;
elImg.onerror = imageOnError;
//load image
imageLoad(imgSrc);
elLoadGood.addEventListener("click", e=>
{
//hide image
elImg.removeAttribute("src");
//load image
imageLoad(imgSrc + Date());
});
elLoadBad.addEventListener("click", e=>
{
//hide image
elImg.removeAttribute("src");
//load image
imageLoad(Date());
});
function imageLoad(src)
{
elPopup.classList.add("loading");
elImg.classList.remove("error");
elPopup.firstChild.textContent = "loading... please wait";
//show popup
imageFinished({});
//load image
elImg.src = src;
}
function imageFinished(img)
{
//check if image finished loading
if (img.complete)
{
elPopup.firstChild.textContent = "Finished loading. Close popup in 2 seconds";
elPopup.classList.remove("loading");
}
clearTimeout(timer);
//hide popup
timer = setTimeout(() => elPopup.classList.toggle("hidden", !!img.complete), ~~img.complete * 2000);
}
function imageOnLoad(e)
{
e.target.classList.remove("error");
imageFinished(e.target);
}
function imageOnError(e)
{
e.target.classList.add("error");
imageFinished(e.target);
}
div.img
{
position: absolute;
left: 0;
top: 0;
line-height: 100vh;
text-align: center;
width: 100%;
z-index: -2;
}
img
{
vertical-align: middle;
max-height: 100%;
max-width: 100%;
}
img.error
{
animation: error infinite 1s ease-in-out alternate;
padding: 1em;
border-radius: 100%;
}
#popup
{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
line-height: 100vh;
text-align: center;
z-index: -1;
background-color: transparent;
opacity: 1;
transition: background-color 1s, opacity .5s;
}
#popup>span
{
background-color: #ffffff7f;
color: black;
border: 1px solid;
padding: 1em;
}
#popup.loading
{
background-color: #0000007f;
}
#popup:not(.hidden) ~ *
{
filter: blur(5px);
}
#popup.loading ~ *
{
filter: blur(10px);
}
#popup.loading>span::before
{
content: "🗘";
width: 1em;
height: 1em;
line-height: 1em;
vertical-align: middle;
text-align: center;
animation: rotate infinite 1s linear;
display: inline-block;
}
#popup.hidden
{
opacity: 0;
}
#keyframes rotate {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
#keyframes error {
to {box-shadow: 0 0 30px 0 red}
from {box-shadow: 0 0 1px 0 red}
}
<button id="loadGood">load good image</button>
<button id="loadBad">load bad image</button>
<div id="popup" class="hidden"><span></span></div>
<div class="img"><img id="myimage"></div>
Related
I am currently building a website and I want a aesthetically pleasing landing page with a background fade in and out slideshow comprised of pictures that repeat y and x. I have the fading slideshow working perfectly and all I need is to repeat the image across the screen. Adding background: repeat to the CSS does not work. Below is may code:
HTML:
<div class="mybody" id="slider">
<div>
<h2>Dog Adoption</h2>
<p>Find the perfect match for your new four legged companion</p>
</div>
</div>
JavaScript:
var curIndex = 0,
imgDuration = 3000,
slider = document.getElementById("slider"),
slides = slider.childNodes; //get a hook on all child elements, this is live so anything we add will get listed
imgArray = [
'../../static/main/images/slideshow/dog2.jpg',
'../../static/main/images/slideshow/dog3.jpg',
'../../static/main/images/slideshow/dog4.jpg',
'../../static/main/images/slideshow/dog1.jpg',
];
//
// Dynamically add each image frame into the dom;
//
function buildSlideShow(arr) {
for (i = 0; i < arr.length; i++) {
var img = document.createElement('img');
img.src = arr[i];
slider.appendChild(img);
}
// note the slides reference will now contain the images so we can access them
}
//
// Our slideshow function, we can call this and it flips the image instantly, once it is
called it will roll
// our images at given interval [imgDuration];
//
function slideShow() {
function fadeIn(e) {
e.className = "fadeIn";
};
function fadeOut(e) {
e.className = "";
};
fadeOut(slides[curIndex]);
curIndex++;
if (curIndex === slides.length) {
curIndex = 0;
}
fadeIn(slides[curIndex]);
setTimeout(function () {
slideShow();
}, imgDuration);
};
buildSlideShow(imgArray);
slideShow();
CSS:
.mybody{
width: 100%;
min-height: 100vh;
max-height: fit-content;
top: 0px;
left: 0px;
padding: 0px;
/*background: url(../images/slideshow/dog1.jpg);*/
display: flex;
justify-content: center;
align-items: center;
text-align: center;
margin: 0px;
position: relative;
background-repeat: repeat;
}
.mybody img {
transition: opacity 1.5s;
position: absolute;
left: 0;
top: 0;
opacity:0;
background-repeat: repeat;
}
.mybody img.fadeIn {
opacity:1;
}
When I just set the background image as a fixed image (no JS) I get the desired result:
However when I comment out the backgorund image (as in above code) and just have the JS slideshow as the background, this is the result:
I essentially just need this image from the second picture to repeat as in the first picture and cannot figure out how to make this happen although I am sure there is a simple fix/solution. If anyone could be of help it would be much appreciated. Thanks in advance!
You can't repeat an image without duplicating it. But you can repeat background so, you can make the slide using divs with background. Note the usage of css classes instead of jquery fade.
slide = 1;
setInterval(function() {
$(".slide").removeClass("active");
$(".div" + slide).addClass("active");
slide++
if (slide == 4) {
slide = 1;
}
}, 1000)
body {
height: 100vh;
width: 100%;
position: relative;
padding: 0;
margin: 0;
text-align: center;
padding: 30px;
}
.slide {
background-repeat: repeat;
background-size: 100px;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
opacity: 0;
transition: 1000ms all;
}
.slide.active {
opacity: 1;
}
.div1 {
background: url('https://picsum.photos/id/101/200');
}
.div2 {
background: url('https://picsum.photos/id/102/200');
}
.div3 {
background: url('https://picsum.photos/id/103/200');
}
.text {
position: relative;
z-index: 2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<body>
<div class="slide div1">
</div>
<div class="slide div2">
</div>
<div class="slide div3">
</div>
<div class="text">
<h1>dog trainer</h1>
<p>best in the world</p>
</div>
</body>
I have a custom cursor on my site that is working perfectly apart from one thing. When clicking through to a new page, when the page loads the cursor resets itself to the top left of the page regardless of where you leave the mouse on the page, then once you moved the mouse the cursor moves back to where the mouse is. I have tried removing "top" & "left" from the CSS but the problem remains. I cant see what is causing this to happen, and I just need the cursor to stay where the mouse is positioned on the page and not reset every time you navigate to a new page.
jQuery(document).ready(function($) {
let cursor = document.querySelector('#custom-cursor');
if(/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)) {
$('#custom-cursor').remove();
}
else { cursor.style.display = 'block';}
document.addEventListener('mousemove', evt => {
let { clientX: x, clientY: y } = evt;
let scale = 1;
if (evt.target.matches('a,span,[onclick],img,video,i')) {
cursor.classList.add('active');
scale = 0.5;
} else {
cursor.classList.remove('active');
}
cursor.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;
});
});
* {
cursor: none;
}
#custom-cursor {
display: none;
position: fixed;
width: 20px; height: 20px;
top: -10px;
left: -10px;
border: 2px solid black;
border-radius: 50%;
opacity: 1;
background-color: #fb4d98;
pointer-events: none;
z-index: 99999999;
transition:
transform ease-out 0.15s,
border 0.5s,
opacity 0.5s,
background-color 0.5s;
}
#custom-cursor.active {
opacity: 0.5;
background-color: #000;
border: 2px solid #fb4d98;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="custom-cursor"></div>
Use ordinary CSS cursor as shown in the other answer and replace it with you fancy cursor in the first mouse event:
jQuery(document).ready(function($) {
let cursor = document.querySelector('#custom-cursor');
document.addEventListener('mousemove', evt => {
document.body.classList.add('custom-cursor-moved')
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)) {
$('#custom-cursor').remove();
} else {
cursor.style.display = 'block';
}
let {
clientX: x,
clientY: y
} = evt;
let scale = 1;
if (evt.target.matches('a,span,[onclick],img,video,i')) {
cursor.classList.add('active');
scale = 0.5;
} else {
cursor.classList.remove('active');
}
cursor.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;
});
});
body {
height: 100vh;
}
html,
body {
margin: 0;
padding: 0;
}
* {
cursor: url(https://i.stack.imgur.com/7pmmV.png) 0 0, auto;
}
.custom-cursor-moved,
.custom-cursor-moved * {
cursor: none !important;
}
#custom-cursor {
display: none;
position: fixed;
width: 20px;
height: 20px;
top: -10px;
left: -10px;
border: 2px solid black;
border-radius: 50%;
opacity: 1;
background-color: #fb4d98;
pointer-events: none;
z-index: 99999999;
transition: transform ease-out 0.15s, border 0.5s, opacity 0.5s, background-color 0.5s;
}
#custom-cursor.active {
opacity: 0.5;
background-color: #000;
border: 2px solid #fb4d98;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="custom-cursor"></div>
Try me.<br> Try me.
It needs a bit of modifications (better cursor image, fix it hotspot etc.) but it works.
Be very, very careful when doing such thing. Try to not break any accessibility tools and please do not assume that Android/some specific user-agent HAS touchscreen, etc.. Use proper APIs.
Use CSS cursor property instead:
html {
cursor: url(https://cdn.sstatic.net/Sites/stackoverflow/Img/favicon.ico?v=ec617d715196) 0 0, auto;
height: 100%;
}
Try me.
I have 2 different div, i want the div1 to fade in after 20s and fade-out after 10s and after 30s i want div2 to fade in and after 10s div2 should also fade out. this should keep happening on load of page
bubbleMessage1 = document.getElementById("bubbleMessage1");
bubbleMessage2 = document.getElementById("bubbleMessage2");
bubbleMessage1.style.display = "none";
bubbleMessage2.style.display = "none";
$(function () {
// Different timeouts for each divs
setTimeout(function(){
var times = [20000, 50000];
var counter = 0;
divs = $('#bubbleMessage1, #bubbleMessage2');
function showDiv() {
// hide all divs, filter current index, and fadeIn
divs.hide().eq(counter).fadeIn(500, "linear");
// set time out duration from array of times
setTimeout(showDiv, times[counter]);
// cycle the counter
counter = (counter + 1) % divs.length;
};
showDiv();
}, 20000)
// show first div
});
.chat-bubble-1{
width: 230px;
height: 65px;
background-color: #486622;
text-align: center;
padding: 0.5rem;
line-height: 66px;
color: #fff;
border-radius: 22px;
position: relative;
}
.chat-bubble-1::after{
content: '';
position: absolute;
height: 32px;
width: 32px;
border-bottom: 2px solid #486622;
border-right: 2px solid #486622;
border-left: 0px solid #486622;
border-top: 0px solid #486622;
top : 100%;
left: 74%;
transform: rotate(45deg);
margin-top: -22px;
background: #486622;
}
#keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in{
animation: fadeIn ease-in 1;
}
.fade-out{
animation: fadeOut ease-in 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-container">
<div class="chat-bubble-1" id="bubbleMessage1">
Hi i'm bot How can i help you?
</div>
<div class="chat-bubble-1" id="bubbleMessage2">
I'm still here How can i help you?
</div>
</div>
I tried to use setTimeout loop to achieve this but i was getting error.then i found this jquery method.the problem is the div will not fade-out after 10s. div1 fades and div2 comes immediately. Can anyone please give a solution really appreciate it.thanks
The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and
successor to Window.setTimeout()) sets a timer which executes a
function or specified piece of code once the timer expires.
setTimeout gets extra args you can use in your code.
Change for instance from:
setTimeout(showDiv);
to:
setTimeout(showDiv, times[counter], times, (i+1)%2);
instead of using local vars.
Working demo:
bubbleMessage1 = document.getElementById("bubbleMessage1");
bubbleMessage2 = document.getElementById("bubbleMessage2");
bubbleMessage1.style.display = "none";
bubbleMessage2.style.display = "none";
// Different timeouts for each divs
setTimeout(function(t, i){
var times = t;
var counter = i;
divs = $('#bubbleMessage1, #bubbleMessage2');
function showDiv(t, i) {
var times = t;
var counter = i;
// hide all divs, filter current index, and fadeIn
divs.hide().eq(counter).fadeIn(500, "linear");
// set time out duration from array of times
setTimeout(showDiv, times[counter], times, (i+1)%2);
// ^^^^^^^^^^^^^^^^^^
// params added...
// cycle the counter
counter = (counter + 1) % divs.length;
};
showDiv(times, counter);
}, 2000, [2000, 5000], 0);
// ^^^^^^^^^^^^^^^^^^
// params added...
.chat-bubble-1{
width: 230px;
height: 65px;
background-color: #486622;
text-align: center;
padding: 0.5rem;
line-height: 66px;
color: #fff;
border-radius: 22px;
position: relative;
}
.chat-bubble-1::after{
content: '';
position: absolute;
height: 32px;
width: 32px;
border-bottom: 2px solid #486622;
border-right: 2px solid #486622;
border-left: 0px solid #486622;
border-top: 0px solid #486622;
top : 100%;
left: 74%;
transform: rotate(45deg);
margin-top: -22px;
background: #486622;
}
#keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in{
animation: fadeIn ease-in 1;
}
.fade-out{
animation: fadeOut ease-in 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-container">
<div class="chat-bubble-1" id="bubbleMessage1">
Hi i'm bot How can i help you?
</div>
<div class="chat-bubble-1" id="bubbleMessage2">
I'm still here How can i help you?
</div>
</div>
I've tried to look for a solution for this but have failed miserably. It's my first ever time using JS (I'm trying to learn) so the possibility of my just not understanding the answers in the search results properly is quite high - sorry about that.
I am wanting a JS carousel, generated from an array, with Prev/Next buttons (ideally responsive etc but that'll come at a later stage), preferably with captions underneath. I can get the carousel to work but I end up getting a text link when I click on either Prev or Next. And I've no idea how to add the caption array underneath (I've taken out the JS for the captions for now because it was messing everything else up even further).
Relevant HTML:
<body onload="changePilt()">
<span id="prev" class="arrow">❮</span>
<div class="karussell" id="karussell">
<img class="karu" name="esislaid">
</div>
<span id="next" class="arrow">❯</span>
<div class="caption">
<h3 name="esikiri"></h3>
</div>
</body>
CSS, just in case:
.karussell {
position: relative;
width: 100%;
max-height: 600px;
overflow: hidden;
}
.arrow {
cursor: pointer;
position: absolute;
top: 40%;
width: auto;
color: #00A7E0;
margin-top: -22px;
padding: 16px;
font-weight: bold;
font-size: 18px;
transition: 0.6s ease;
border-radius: 0 3px 3px 0;
}
#next {
right: 0;
border-radius: 3px 0 0 3px;
}
#prev {
left: 0;
}
.arrow:hover {
background-color: rgba(0,0,0,0.8);
}
.caption {
text-align: center;
color: #00A7E0;
padding: 2px 16px;
}
.karu {
max-width: 75%;
}
#media (max-width:767px){.karu{max-width: 95%;}}
And finally, the dreaded JS:
var i = 0;
var s = 0;
var esileht = [];
var aeg = 5000;
//Image List
esileht[0] = 'img/tooted/raamat/graafvanalinn2016.jpg';
esileht[1] = 'img/tooted/kaart/kaart_taskus_esipool.jpg';
esileht[2] = 'img/tooted/kaart/graafkaart_esikylg.jpg';
//Change Image
function changePilt (){
document.esislaid.src = esileht[i];
if(i < esileht.length -1){
i++;
} else {
i = 0;
}
setTimeout("changePilt()", aeg);
}
document.onload = function() {
}
// Left and Right arrows
//J2rgmine
function jargmine(){
s = s + 1;
s = s % esileht.length;
return esileht [s];
}
//Eelmine
function eelmine(){
if (s === 0) {
s = esileht.length;
}
s = s -1;
return esileht[s];
}
document.getElementById('prev').addEventListener('click', function (e){
document.getElementById('karussell').innerHTML = eelmine();
}
);
document.getElementById('next').addEventListener('click', function (e) {
document.getElementById('karussell').innerHTML = jargmine();
}
);
I'm sure the solution is dreadfully obvious, I just cannot seem to be able to figure it out...
instead of innerHTML change src attribute of image
document.querySelector('#karussell img').src = eelmine();
And
document.querySelector('#karussell img').src = jargmine();
I'm trying to emulate a ripple effect when clicking in a button, but I got weird behaviour when happy clicking. I'm coding in vanilla JS for learning purposes. Please could anybody tell me where I've got it wrong?
Here's the full code:
Html
<button class="button button--ok ripple">Button</button>
<button class="button button--cancel ripple">Button</button>
Css
body {
width: 800px;
margin: 0 auto;
padding: 30px 0 0 0;
font: "Helvetica neue", Helvetica, sans-serif;
}
.button {
position: relative;
padding: 10px 20px;
color: #fff;
border: none;
outline: none;
cursor: pointer;
box-shadow: 0 0 4px rgba(0,0,0,.4);
overflow: hidden;
font-size: 16px;
letter-spacing: 1px;
}
.button--ok {
background-color: #65DE65;
}
.button--cancel {
background-color: tomato;
}
.circle {
width: 10px;
height: 10px;
position: absolute;
transform: translate(-50%, -50%);
border-radius: 5px;
background-color: #fff;
}
.ripple.animate .circle {
animation: ripple 2s;
}
#keyframes ripple {
from {
transform: scale(1);
opacity: .4;
}
to {
transform: scale(100);
opacity: 0;
}
}
Js
var ripple = document.getElementsByClassName("ripple");
for (var i = 0; i < ripple.length; i++) {
ripple[i].addEventListener("click", function(e) {
// Store this for later
var self = this;
// Get x and y coordinates
var x = e.offsetY+"px";
var y = e.offsetX+"px";
// Create the layer effect and apply a circle class,
// then set coordinates
var circle = document.createElement("div");
circle.setAttribute("class", "circle");
circle.style.top = x;
circle.style.left = y;
// Append layer effect to parent and add animate class
// to start the animation
self.appendChild(circle);
self.className += " animate";
// Remove layer effect once is done animating (2 seconds)
setTimeout(function() {
var elements = self.getElementsByClassName("circle");
for (var i = 0; i < elements.length; i++) {
self.removeChild(elements[i]);
}
}, 2000);
}, false);
}
Mine: Codepen
Disired: Codepen
Hi I see what you are trying to do and I too tried to explain the bizzare effect. Anyway I tried to do something and it worked, made the .circle .animate to simply .animate and changed the scale(1) to scale(1,1), scale(width,height) setting.
Inside style the changes are:
.animate {
animation: ripple 2s forwards;
-webkit-animation-name:ripple;
-webkit-animation-duration: 2s;
}
#keyframes ripple {
from {
transform: scale(1,1);
opacity: 0.4;
}
to {
transform: scale(100,100);
opacity: 0;
}
}
Here is the jsfiddle. For chrome and safari support added the -webkit- property.