I have some simple transition animation, I want to make text ( A href ) invisible, so I used "display: none" and I want to make it visible with "display: block" after image coming through it using "onclick" thing from javascript on that image. Here is my jsfiddle : http://jsfiddle.net/ofy4t5a8/
#facebook_text a {
position: absolute;
font-size: 15px;
color: #000;
text-decoration: none;
margin-left: 50px;
margin-top: -10px;
z-index: 1;
display: none;
}
#facebook_image.fly {
position: absolute;
margin-left: 125px;
margin-top: 0px;
transition: all 5s ease-out;
}
#facebook_image img {
position: absolute;
z-index: 10;
height: 35px;
width: 35px;
margin-top: -15px;
}
<div id="facebook_text">
Facebook
</div>
<div id="facebook_image">
<img class="image_animation" src="facebook.jpg"></img>
</div>
<script>
document.querySelector('.image_animation').onmouseover=function() {
var d = document.getElementById("facebook_image");
d.className = d.className + " fly";
}
</script>
facebook_imageYou should catch event when it ends, you can do it like this:
transitionEnd = (function transitionEndEventName() {
var i,
el = document.createElement('div'),
transitions = {
'transition':'transitionend',
'MozTransition':'transitionend',
'WebkitTransition':'webkitTransitionEnd'
};
for (i in transitions) {
if (transitions.hasOwnProperty(i) && el.style[i] != undefined) {
return transitions[i];
}
}
})();
var a = document.querySelector('a');
var b = document.querySelector('.facebook_image');
b.addEventListener(transitionEnd, function(){
a.style.display = "block";
}
Related
I have markup that is added via JS that has an onclick action (it's a close button).
Essentially:
User clicks play button
A modal appears with the video and a close modal button (both which are added via JS)
As my close button (.modal--close) isn't on the page on load, I'm getting a Cannot set properties of null (setting 'onclick') (I think).
My thoughts are that the because the DOMContentLoaded event was already fired at this point, it is causing the error? But unsure how to resolve it.
Demo
if (document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
function ready() {
if(document.querySelector(".open-video")){
document.querySelector(".open-video").onclick = function (e) {
e.preventDefault();
var modal = document.querySelector(".videoModal");
// get data
var triggerURL = this.getAttribute("href");
var triggerID = this.getAttribute("data-modal");
// update modal attributes with trigger data
modal.setAttribute("data-video", triggerURL);
modal.setAttribute("id", triggerID);
var modalID = '#'+ triggerID;
modal.classList.add("modal--open");
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
modal.innerHTML = html;
return false;
}
}
// close modal
document.querySelector(".modal--close").onclick = function (e) {
e.preventDefault();
console.log("test");
}
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
overflow: hidden;
display: none;
padding: 70px 80px;
}
.modal--close {
position: fixed;
right: 50%;
top: 32px;
width: 16px;
height: 16px;
z-index: 999999;
pointer-events: auto !important;
}
.modal--close:hover:before, .modal--close:hover:after {
background-color: #F15A40;
}
.modal--close:before, .modal--close:after {
content: "";
position: absolute;
left: 15px;
height: 16px;
width: 2px;
background-color: #FFFFFF;
}
.modal--close:before {
transform: rotate(45deg);
}
.modal--close:after {
transform: rotate(-45deg);
}
.modal--open {
display: block;
}
.modal .modal__wrapper {
position: relative;
top: 50%;
transform: translateY(-50%);
max-height: 100%;
overflow: hidden;
z-index: 150;
}
.modal .modal__wrapper:before {
content: "";
display: block;
padding-top: 56.25%;
}
.modal .modal__wrapper iframe, .modal .modal__wrapper video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
outline: none;
}
.modal .modal__overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000000;
}
<a class="button--play open-video" data-modal="video--1" href="https://www.youtube.com/embed/NpEaa2P7qZI">Click me</a>
<div class="videoModal modal modal__post--modal">
<a id="modal_close" class="modal__close"></a>
<div class="modal__wrapper"></div>
<div class="modal__overlay"></div>
</div>
Edit
Have also tried moving the event listener after the markup has been added:
if (document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
function ready() {
let video_btn = document.querySelector(".open-video");
let close_btn = document.querySelector(".modal--close");
let modal = document.querySelector(".videoModal");
if(video_btn){
video_btn.addEventListener("click", function (e) {
e.preventDefault();
// get data
var triggerURL = this.getAttribute("href");
var triggerID = this.getAttribute("data-modal");
// update modal attributes with trigger data
modal.setAttribute("data-video", triggerURL);
modal.setAttribute("id", triggerID);
var modalID = '#'+ triggerID;
modal.classList.add("modal--open");
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
modal.innerHTML = html;
return false;
close_btn.addEventListener("click", function (e) {
e.preventDefault();
console.log("test");
});
});
}
}
With the above, the modal launches fine, but when I click .modal--close, nothing happens (no console.log and no console errors).
Edit 2
Have also tried moving the second event listener above the code snippet that adds the markup:
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
close_btn.addEventListener("click", function (e) {
e.preventDefault();
console.log("test");
});
modal.innerHTML = html;
return false;
With the above however, when I click the .open-video button, I get the error Cannot read properties of null (reading 'addEventListener')
if (document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
function ready() {
var modal = document.querySelector(".videoModal");
var triggerURL;
if(document.querySelector(".open-video")){
document.querySelector(".open-video").onclick = function (e) {
e.preventDefault();
// get data
triggerURL = this.getAttribute("href");
var triggerID = this.getAttribute("data-modal");
// update modal attributes with trigger data
modal.setAttribute("data-video", triggerURL);
modal.setAttribute("id", triggerID);
var modalID = '#'+ triggerID;
modal.classList.add("modal--open");
return false;
}
}
// close modal
var html = '<div class="modal__wrapper"><iframe width="640" height="360" src="'+ triggerURL + '?rel=0&autoplay=1" frameborder="0" allowfullscreen></iframe></div><div class="modal__overlay"></div>';
modal.innerHTML = html;
if(document.querySelector(".modal--close")){
document.querySelector(".modal--close").onclick = function (e) {
e.preventDefault();
console.log("test");
}
}
}
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999;
overflow: hidden;
display: none;
padding: 70px 80px;
}
.modal--close {
position: fixed;
right: 50%;
top: 32px;
width: 16px;
height: 16px;
z-index: 999999;
pointer-events: auto !important;
}
.modal--close:hover:before, .modal--close:hover:after {
background-color: #F15A40;
}
.modal--close:before, .modal--close:after {
content: "";
position: absolute;
left: 15px;
height: 16px;
width: 2px;
background-color: #FFFFFF;
}
.modal--close:before {
transform: rotate(45deg);
}
.modal--close:after {
transform: rotate(-45deg);
}
.modal--open {
display: block;
}
.modal .modal__wrapper {
position: relative;
top: 50%;
transform: translateY(-50%);
max-height: 100%;
overflow: hidden;
z-index: 150;
}
.modal .modal__wrapper:before {
content: "";
display: block;
padding-top: 56.25%;
}
.modal .modal__wrapper iframe, .modal .modal__wrapper video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
outline: none;
}
.modal .modal__overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #000000;
}
<a class="button--play open-video" data-modal="video--1" href="https://www.youtube.com/embed/NpEaa2P7qZI">Click me</a>
<div class="videoModal modal modal__post--modal">
<a id="modal_close" class="modal__close"></a>
<div class="modal__wrapper"></div>
<div class="modal__overlay"></div>
</div>
Just wrap the code snippet that fires the issues with below function.
if(document.querySelector(".modal--close")){
}
This is the code i'm working on, and i don't know why everytime that i refresh the page i need to click 2 times to open the menu. Once i click the second time all works correctly.
This is the html of the button:
var x = document.getElementById("overlay-menu");
x.style.height = "0%";
function showMenu() {
var x = document.getElementById("overlay-menu");
if (x.style.height === "0%") {
x.style.height = "100%";
} else {
x.style.height = "0%";
}
}
.overlay-menu {
width: 100%;
height: 0%;
padding: 0;
margin: 0;
background-color: #ffffff;
z-index: 10000;
position: fixed;
color: #0A0A0A;
overflow: hidden;
display: block;
transition: .5s cubic-bezier(.55, .03, .26, 1.01);
}
.nav-menu-text {
width: fit-content;
height: fit-content;
margin: 0;
padding: 0;
color: #EB761D;
font-size: 15px;
position: relative;
top: 2.8em;
cursor: pointer;
}
<p class="nav-menu-text" onclick="showMenu()">MENU</p>
<div class="overlay-menu" id="overlay-menu">
<!-- code of the menu -->
</div>
x.style.height is probably not "0%" when your code runs, try changing the condition from:
if (x.style.height === "0%") {
to
if (x.style.height !== "100%") {
I have made a Fiddle that should explain the problem quite well (I hope):
JSFiddle
In short: I have a JS tooltip that is not supposed to take its parents width but rather just use auto width (until it reaches max-width and then wrap text). This works fine, unless the parent element has position:relative set, and then the tooltipchild inherits the width. I don't know how to prevent this from happening.
A solution that would work is to set a min-width but that is
not elegant
still doesn't explain why this acts the way it does
looks stupid when the tooltip is 1 or 2 words only
I have to include code for the fiddle link but it's a very extensive fiddle and since I can't pinpoint the issue, I'll just have to put something here (sorry!) - so this snippet will be of little use I'm afraid
<button id="tooltip">Click me</button>
button {
margin-left: 40%;
width: 50px;
position: relative; /* THE OFFENDING PROBLEM*/
}
var tooltip = document.getElementById("tooltip");
tooltip.addEventListener('mouseover', function() {
tlite.show(tooltip, {
text: template,
orientation: "bottom"
})
})
Maybe I found I trick that it works for you. My solution is to create a tooltip with an internal span in it. Now, we can format our new span putting parent span (our old .tlite span) to width:400px that it works like a max-width!
Ok, maybe the description is intricated, but with code become very simple. Follow me! ;)
Let's create our tooltip template with an internal span:
var template = document.createElement('span');
template.innerHTML = "<span class='internal'>ncididunt This tooltip is the.</span>";
Now we can put almost all our tooltip CSS in this new span:
.tlite {
/* here you can leave all the CSS concerning the animations and the positioning */
position: absolute;
z-index: 1000;
display: block;
visibility: hidden;
-webkit-transition: transition .25s ease-out;
transition: opacity .25s ease-out;
opacity: 0;
width: 400px; /* It's a width but it works like a max-width for internal span */
}
.tlite .internal{
display: inline-block; /* This does the trick! Super important! */
padding: .4rem .6rem;
text-align: left;
white-space: normal;
text-decoration: none;
pointer-events: none;
color: white;
border-radius: 5px;
background: green;
}
.tlite .internal::before {
position: absolute;
display: block;
width: 10px;
height: 10px;
content: ' ';
transform: rotate(45deg);
background: inherit;
}
.tlite-n .internal::before {
top: -3px;
left: 50%;
margin-left: -5px;
}
.tlite-nw .internal::before {
top: -3px;
left: 10px;
}
.tlite-ne .internal::before {
top: -3px;
right: 10px;
}
.tlite-s .internal::before {
bottom: -3px;
left: 50%;
margin-left: -5px;
}
.tlite-se .internal::before {
right: 10px;
bottom: -3px;
}
.tlite-sw .internal::before {
bottom: -3px;
left: 10px;
}
.tlite-w .internal::before {
top: 50%;
left: -3px;
margin-top: -5px;
}
.tlite-e .internal::before {
top: 50%;
right: -3px;
margin-top: -5px;
}
Now we can write how much we want and our new <span class="internal"> can grow up to 400px!
Try it:
/* he making of a tooltip is now very convulted because I had to alter a bit to fit the Fiddle; just ignore that*/
var template = document.createElement('span');
template.innerHTML = "<span class='internal'>Only few words.</span>";
var template2 = document.createElement('span');
template2.innerHTML = "<span class='internal'>This tooltip is positioned correctly and now it can grow up to 400px.</span>";
var template3 = document.createElement('span');
template3.innerHTML = "<span class='internal'>This tooltip has the width it should have but is placed wrong.</span>";
var tooltip = document.getElementById("tooltip");
tooltip.addEventListener('mouseover', function() {
tlite.show(tooltip, {
text: template,
orientation: "bottom"
})
})
tooltip.addEventListener('mouseleave', function() {
tlite.hide(tooltip);
})
var tabletooltip = document.getElementById("tabletooltip");
tabletooltip.addEventListener('mouseover', function() {
tlite.show(tabletooltip, {
text: template2,
orientation: "bottom"
})
})
tabletooltip.addEventListener('mouseleave', function() {
tlite.hide(tabletooltip);
})
var tabletooltip2 = document.getElementById("tabletooltip2");
tabletooltip2.addEventListener('mouseover', function() {
tlite.show(tabletooltip2, {
text: template3,
orientation: "bottom"
})
})
tabletooltip2.addEventListener('mouseleave', function() {
tlite.hide(tabletooltip2);
})
/*LIBRARY */
function tlite(getTooltipOpts) {
document.addEventListener('mouseover', function(e) {
var el = e.target;
var opts = getTooltipOpts(el);
if (!opts) {
el = el.parentElement;
opts = el && getTooltipOpts(el);
}
opts && tlite.show(el, opts, true);
});
}
tlite.show = function(el, opts, isAuto) {
opts = opts || {};
(el.tooltip || Tooltip(el, opts)).show();
function Tooltip(el, opts) {
var tooltipEl;
var showTimer;
var text;
el.addEventListener('mousedown', autoHide);
el.addEventListener('mouseleave', autoHide);
function show() {
if (opts['text']) {
text = opts['text'].innerHTML
} else {
text = ' ';
}
text && !showTimer && (showTimer = setTimeout(fadeIn, isAuto ? 150 : 1))
}
function autoHide() {
tlite.hide(el, true);
}
function hide(isAutoHiding) {
if (isAuto === isAutoHiding) {
showTimer = clearTimeout(showTimer);
tooltipEl && el.removeChild(tooltipEl);
tooltipEl = undefined;
delete el.tooltip; //experimental addition for the angular library version of the tooltip
}
}
function fadeIn() {
if (!tooltipEl) {
tooltipEl = createTooltip(el, text, opts);
}
}
return el.tooltip = {
show: show,
hide: hide
};
}
function createTooltip(el, text, opts) {
/*console.log('create')*/
var tooltipEl = document.createElement('span');
var grav = opts.grav || 'n';
tooltipEl.className = 'tlite ' + (grav ? 'tlite-' + grav : '');
tooltipEl.innerHTML = text;
el.appendChild(tooltipEl);
var arrowSize = 10;
var top = el.offsetTop;
var left = el.offsetLeft;
if (tooltipEl.offsetParent === el) {
top = left = 0;
}
var width = el.offsetWidth;
var height = el.offsetHeight;
var tooltipHeight = tooltipEl.offsetHeight;
var tooltipWidth = tooltipEl.offsetWidth;
var centerEl = left + (width / 2);
var vertGrav = grav[0];
var horzGrav = grav[1];
tooltipEl.style.top = (
vertGrav === 's' ? (top - tooltipHeight - arrowSize) :
vertGrav === 'n' ? (top + height + arrowSize) :
(top + (height / 2) - (tooltipHeight / 2))
) + 'px';
tooltipEl.style.left = (
horzGrav === 'w' ? left :
horzGrav === 'e' ? left + width - tooltipWidth :
vertGrav === 'w' ? (left + width + arrowSize) :
vertGrav === 'e' ? (left - tooltipWidth - arrowSize) :
(centerEl - tooltipWidth / 2)
) + 'px';
tooltipEl.className += ' tlite-visible';
return tooltipEl;
}
};
tlite.hide = function(el, isAuto) {
el.tooltip && el.tooltip.hide(isAuto);
};
if (typeof module !== 'undefined' && module.exports) {
module.exports = tlite;
}
button {
margin-left: 40%;
width: 50px;
position: relative; /* NOW, NO PROBLEM! ;) */
}
table {
margin-left: 30%;
}
#tabletooltip {
position: relative;
}
/* library css */
.tlite {
position: absolute;
z-index: 1000;
display: block;
visibility: hidden;
-webkit-transition: transition .25s ease-out;
transition: opacity .25s ease-out;
opacity: 0;
width: 400px;
}
.tlite .internal{
display: inline-block;
padding: .4rem .6rem;
text-align: left;
white-space: normal;
text-decoration: none;
pointer-events: none;
color: white;
border-radius: 5px;
background: green;
}
/*
tables need an extra class for the positioning of the tooltip
*/
.tlite-table tr td,
.tlite-table tr th {
position: relative;
}
.tlite-visible {
visibility: visible;
opacity: 1;
}
.tlite .internal::before {
position: absolute;
display: block;
width: 10px;
height: 10px;
content: ' ';
transform: rotate(45deg);
background: inherit;
}
.tlite-n .internal::before {
top: -3px;
left: 50%;
margin-left: -5px;
}
.tlite-nw .internal::before {
top: -3px;
left: 10px;
}
.tlite-ne .internal::before {
top: -3px;
right: 10px;
}
.tlite-s .internal::before {
bottom: -3px;
left: 50%;
margin-left: -5px;
}
.tlite-se .internal::before {
right: 10px;
bottom: -3px;
}
.tlite-sw .internal::before {
bottom: -3px;
left: 10px;
}
.tlite-w .internal::before {
top: 50%;
left: -3px;
margin-top: -5px;
}
.tlite-e .internal::before {
top: 50%;
right: -3px;
margin-top: -5px;
}
<h3>
Any object that has position:relative has troubles with the width of the tooltip. EX:
</h3>
<button id="tooltip">Click me</button>
<p>
Remove the position and it works as intended.
</p>
<h3>
BUT for some situations, I need position:relative, otherwise the tooltip is displayed at the wrong place. EX:
</h3>
<table style="width:25%">
<tr>
<th>titel1</th>
<th>title2</th>
</tr>
<tr>
<td id="tabletooltip">tooltip with position:relative</td>
<td id="tabletooltip2">tooltip without position:relative</td>
</tr>
</table>
Having a slider with images implementation from array, cant figure out why images dont want to be shown up from array, tryed to make a path but it didnt work.I want this code to reflect this image every time a push the button: fpoimg.com/100x100.
Im trying to fix it only with clean javascript.
Here is a sandbox
var slider = {
slides: ['100x100', '100x100', '100x100', '100x100'],
frame:0,
set:function(image){
path = path || 'http://fpoimg.com/';
document.getElementById('scr').style.backgroundImage ="url ("+path+ image+")";
},
init:function() {
this.set(this.slides[this.frame]);
},
left:function() {
this.frame--;
if(frame < 0) this.frame = this.slides.length - 1;
this.set(this.slides[this.frame]);
},
right:function() {
if(this.frame == this.slides.length) this.frame = 0;
this.set(this.slides[this.frame]);
}
};
window.onload = function() {
slider.init();
setInterval(function() {
slider.right();
},5000);
};
.scr {
margin:20px auto;
width: 600px;
height: 320px;
margin-top:20px;
background-color: white;
background-size:cover;
}
button {
position: absolute;
top: 150px;
width: 25px;
height: 150px;
font-size: 30px;
text-align: center;
background:none;
border:none;
}
.left {
left:25px;
}
.right {
right:25px;
}
<body>
<button class="left" onclick="slider.left();"><</button>
<div class="scr"></div>
<button class="right" onclick="slider.right();">></button>
</body>
On Line 6 of your Javascript, you have used getElementById('scr'). You have no element with an Id or scr, you needed to use getElementsByClassName('scr')
Your new code:
var slider = {
slides: ['100x100', '100x100', '100x100', '100x100'],
frame: 0,
set: function(image) {
path = path || 'http://fpoimg.com/';
document.getElementsByClassName('scr').style.backgroundImage = "url (" + path + image + ")";
},
init: function() {
this.set(this.slides[this.frame]);
},
left: function() {
this.frame--;
if (frame < 0) this.frame = this.slides.length - 1;
this.set(this.slides[this.frame]);
},
right: function() {
if (this.frame == this.slides.length) this.frame = 0;
this.set(this.slides[this.frame]);
}
};
window.onload = function() {
slider.init();
setInterval(function() {
slider.right();
}, 5000);
};
.scr {
margin: 20px auto;
width: 600px;
height: 320px;
margin-top: 20px;
background-color: white;
background-size: cover;
}
button {
position: absolute;
top: 150px;
width: 25px;
height: 150px;
font-size: 30px;
text-align: center;
background: none;
border: none;
}
.left {
left: 25px;
}
.right {
right: 25px;
}
<body>
<button class="left" onclick="slider.left();">
</button>
<div class="scr"></div>
<button class="right" onclick="slider.right();"></button>
</body>
It seems you've got getElementById() when you meant getElementsByClassName()
i have little animation with picture, i want to change cursor to default ( on picture ), after animation start, if you try my animation, you will see that after onclick function you still have cursor: pointer on pic. but i want there to be default after animation.
my fiddle: http://jsfiddle.net/1u6kbz7q/
HTML
<div id="facebook_text">
Odkaz
</div>
<div id="facebook_image">
<img class="facebook_animation" src="facebook.jpg"></img>
</div>
<script src="facebook_animation.js" type="text/javascript"></script>
CSS
#facebook_text {
display: none;
}
#facebook_text a {
position: absolute;
font-size: 15px;
text-decoration: none;
margin-left: 50px;
margin-top: 35px;
z-index: 1;
}
#facebook_text a:hover {
color: #e5e500;
}
#facebook_image.fly {
position: absolute;
margin-left: 125px;
margin-top: 0px;
transition: ease-in-out 1s;
}
#facebook_image img {
position: absolute;
z-index: 10;
height: 35px;
width: 35px;
margin-top: 25px;
transition: ease-in-out 1s;
cursor: pointer;
}
javascript
document.querySelector('.facebook_animation').onclick=function() {
var d = document.getElementById("facebook_image");
d.className = d.className + " fly";
d.style.cursor = 'default';
var t = document.getElementById("facebook_text");
var delayed = setTimeout(function() {
t.style.display = 'block';
}, 500);
}
No need to involve JS on that cursor matter: http://jsfiddle.net/1u6kbz7q/3/
you're already adding the .fly, so simply target the .fly's image in CSS
#facebook_image.fly img{
cursor: default;
}
also <img> is a self-closing tag. no need to use the closing </img>