JQuery replaced link not working under IE 8-10 - javascript

I made a popup and I have a problem with IE 8-10 (under IE11 no problem). My code replace an image to linked image. Link is working under Firefox, Chrome and IE11, but not working under other IE versions. This is a popop window by default. Here is my code:
<div id="fadeinboxrevol">
<div id="koppbase">
<p class="kalapacs"><img src="./images/original.png" alt="Click here" /></p>
</div>
</div>
<script type="text/javascript">
var tto = jQuery.noConflict();
function get_path() {
var piclist =['./images/1.png','./images/2.png','./images/3.png','./images/4.png'];
var linklist =['1.html','2.html','3.html','4.html'];
var random = Math.floor(Math.random()*piclist.length);
var picpath = piclist[random];
var linkpath = linklist[random];
var pack = [picpath, linkpath];
return pack;
}
tto(".kalapacs").click(function () {
var mypack = get_path();
var mypic = mypack[0];
var mypath = mypack[1];
var content1 = '<p class="torp"><img class="torve" src="'+mypic+'" alt="Don't wait" /><a class="tortext" href="'+mypath+'"></a></p>';
tto("#koppbase").html(content1);
});
</script>
And here is my CSS:
#fadeinboxrevol {
position: absolute;
width: auto;
left: 301px;
top: 262.5px;
visibility: visible;
border: none;
background-color: ;
padding: 0 px;
z-index: 999;
text-align: left;
}
.kalapacs:hover {
cursor: url(http://cur.cursors-4u.net/others/oth-5/oth438.cur), progress !important;
}
.torp {
position: relative;
}
.tortext {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
display: block;
z-index: 9999;
}
#revolclosebutton {
margin-top: -40px;
right: 20px;
position: absolute;
width: 16px;
z-index: 999;
}
Here is an example in jsfiddle, I use jQuery 1.11 version for better compatibility:
http://jsfiddle.net/mykee/uDCKL/
I tried this line too:
tto("#koppbase").replaceWith(content1);
but not helped. :-(
What's my problem?

The problem is this line of code: var content1 = '<p class="torp"><img class="torve" src="'+mypic+'" alt="Don't wait" /><a class="tortext" href="'+mypath+'"></a></p>';
Change it to: var content1 = '<p class="torp"><a class="tortext" href="'+mypath+'"><img class="torve" src="'+mypic+'" alt="Don't wait" /></a></p>';
When you look at older IE the a is empty after the img tag, so its hard to click it! (Hover down the 2nd image.)
Demo: http://jsfiddle.net/uDCKL/7/

I found a solution! Changed content1 line to this:
var content = '<p class="torp"><a class="tortext" href="'+mypath+'"><img class="torve" src="'+mypic+'" alt="Dont wait" /></a></p>';
And CSS replaced with this and working:
.kalapacs:hover {
cursor: url(http://cur.cursors-4u.net/others/oth-5/oth438.cur), progress !important;
}
.torp {
position: relative;
}
.tortext {
display: block;
}
#revolclosebutton {
margin-top: -40px;
right: 20px;
position: absolute;
width: 16px;
z-index: 99999;
}

Related

How to handle onclick null error for HTML added via JS?

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")){
}

How to achieve the same function of position:sticky using jQuery or JavaScript?

I'm having a hard time figuring out why the code below doesn't work as expected.
What I'm trying to achieve is same functionality with position:sticky whereas when the scrolled reaches the top of the #second-header then fixes its position below the #header which is also fixed, however, the height of the #header is unknown which is I believe can be calculated using the function outerHeight(true) on JQuery.
Then after reaching out to the bottom of the #second-header-container, remove the fixed position of #second-header turning it back to normal position.
Due to browser compatibility issues and other customization, I cannot simply use the position:sticky of css.
It looks like my logic is wrong, and I need help.
jQuery(document).ready(function(){
var $document = jQuery(document);
var header = jQuery('#header');
var second_header = jQuery('#second-header-container').find('#second-header');
var second_header_container = jQuery('#second-header-container');
var second_header_offset = second_header.offset().top;
var second_header_container_offset = second_header_container.offset().top;
jQuery(window).scroll(function(){
var top_margin = header.outerHeight(true);
var second_header_height = second_header.outerHeight(true);
var second_header_container_height = second_header_container.outerHeight(true);
if( jQuery(window).scrollTop() > (second_header_offset - second_header_height) && jQuery(window).scrollTop() < second_header_container_height) {
second_header.addClass('fixer');
second_header.css({position:'fixed', top:top_margin, 'z-index':'999999'});
} else {
second_header.removeClass('fixer');
second_header.css({position:'relative', top:'0px', 'z-index':'0'});
}
});
});
*{
color: #FFFFFF;
padding: 0;
margin: 0;
}
.fixer{
position: fixed;
width: 100%;
}
#header, .banner, #second-header, .contents{
padding: 5px;
}
#header{
position: fixed;
width: 100%;
height: 74px;
z-index: 99999;
background-color: #000000;
}
.banner{
padding-top: 84px;
height: 200px;
background-color: #583E5B;
}
#second-header-container{
min-height: 300px;
background-color: #775F5E;
}
#second-header{
padding-bottom: 10px;
padding-top: 10px;
background-color: #4C3D3C;
}
.contents{
min-height: 200px;
background-color: #97A36D;
}
.footer{
background-color: #80A379;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header id="header">HEADER</header>
<div class="banner">BANNER</div>
<div id="second-header-container">
<div id="second-header">SECOND-HEADER</div>
<!--Other contents and elements...-->
</div>
<div class="contents">OTHER...</div>
<footer class="contents footer">FOOTER</footer>
To achieve this you need first check if the scroll height is near the second div header and within the height of the second div. Then add a class that make it stick below the main header. I have created a sticky class and added it while scrolling conditions are met.
Please check below code
jQuery(document).ready(function() {
var headerHeight = $('#header').outerHeight(true);
var secondHeaderContainer = $('#second-header-container');
const secondHeaderTopPos = secondHeaderContainer.offset().top;
const secondHeaderContainerHeight = $(secondHeaderContainer).height();
$(window).scroll(function() {
const scrollTop = $(this).scrollTop();
const secondContainerHeightEnd = secondHeaderContainerHeight + secondHeaderTopPos - $('#second-header').height() - headerHeight;
if (((secondHeaderTopPos - headerHeight) <= scrollTop) && (secondContainerHeightEnd >= scrollTop)) {
$('#second-header').addClass('sticky').css('top', headerHeight);
} else {
$('#second-header').removeClass('sticky');
}
});
});
* {
color: #FFFFFF;
padding: 0;
margin: 0;
}
.sticky {
position: fixed;
width: 100%;
top: 0;
left: 0;
}
.fixer {
position: fixed;
width: 100%;
}
#header,
.banner,
#second-header,
.contents {
padding: 5px;
}
#header {
position: fixed;
width: 100%;
height: 74px;
z-index: 99999;
background-color: #000000;
}
.banner {
padding-top: 84px;
height: 200px;
background-color: #583E5B;
}
#second-header-container {
min-height: 300px;
background-color: #775F5E;
}
#second-header {
padding-bottom: 10px;
padding-top: 10px;
background-color: #4C3D3C;
}
.contents {
min-height: 200px;
background-color: #97A36D;
}
.footer {
background-color: #80A379;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<header id="header">HEADER</header>
<div class="banner">BANNER</div>
<div id="second-header-container">
<div id="second-header">SECOND-HEADER</div>
<!--Other contents and elements...-->
</div>
<div class="contents">OTHER...</div>
<footer class="contents footer">FOOTER</footer>

Changing position of absolute element without container overflow

Maybe an obvious question but how do I make an element with a absolute position not overflow its container when moving it's position right? I know I could change it to relative position or move it 99% but for my project that won't due. I tried using margins, padding, object-fit, all with no success. Thanks for any help
var green = document.getElementById('green');
function myFunct() {
green.style.right = '100%';
}
h1 {
position: relative;
width: 80%;
height: 100px;
margin: auto;
background-color: red;
}
#green {
position: absolute;
right: 0px;
height: 100px;
background-color: green;
width: 20px;
}
<h1>
<div id = 'green'></div>
</h1>
<button onclick="myFunct()">FindHighScore</button>
Use CSS calc()
var green = document.getElementById("green");
function myFunct() {
green.style.right = "calc(100% - 20px)";
}
Or, apply left: 0 and right: auto (reset)
var green = document.getElementById("green");
function myFunct() {
green.style.left = "0";
green.style.right = "auto";
}
A <div> should not be in a <h1> tag by the way.
You can set overflow to hidden at parent container.
<h1> permitted content is Phrasing content
var green = document.getElementById('green');
function myFunct() {
green.style.right = '100%';
}
div:not(#green) {
position: relative;
width: 80%;
height: 100px;
margin: auto;
background-color: red;
overflow: hidden;
}
#green {
position: absolute;
right: 0px;
height: 100px;
background-color: green;
width: 20px;
}
<div>
<div id='green'></div>
</div>
<button onclick="myFunct()">FindHighScore</button>

Can't click the h1 on mobile devices

I found a weird glitch/bug or something. My website has a simple code of two buttons and two images. If you click the button (simple h1 with event-listener), one of the images spins around. Simple. It works on my MacBook, even on "Inspect Element" and works great there if I try to simulate iPhone etc.
BUT! On my iPhone, if I click the h1, nothing happens. I tried everything, I got rid of all elements, tried z-index, nothing helped!
<div class="wrapper clearfix">
<img class="bg" src="images/bg.svg">
<img class="wheel" src="images/wheel.svg">
<div class="right">
<div class="g-recaptcha" data-sitekey="6LfhLTUUAAAAAMCrfKgrtViK22w1H98Uisw4dvlj"></div>
<h1 class="spin" data-spin="clicked">Roztočit</h1>
</div>
</div>
Css:
.wrapper{
width: 80vw;
position: relative;
height: 100vh;
}
.bg{
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 0;
pointer-events:none;
}
.wheel{
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
transition: all 2s;
z-index: 10;
pointer-events:none;
}
.clearfix:after {
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
.right{
width: 20vw;
min-width: 340px;
right: -20vw;
position: absolute;
padding-top: 20%;
top: 0;
z-index: 100;
}
.spin{
width: 304px;
background-color: #78da92;
line-height: 78px;
font-size: 25px;
color: #fff;
border-radius: 4px;
margin-top: 25px;
z-index: 100;
}
jQuery:
$(document).ready(function(){
document.addEventListener('click', function (e) {
var t = e.target;
if (!t.dataset.hasOwnProperty('spin')) return;
var fD = new FormData();
fD.append('boom', t.dataset.spin);
XXHR().request('get.php', function(response) {
var obj = JSON.parse(response);
console.log(obj);
$(".wheel").css("-ms-transform", "rotate("+obj.type1+"deg)");
$(".wheel").css("-webkit-transform", "rotate("+obj.type1+"deg)");
$(".wheel").css("transform", "rotate("+obj.type1+"deg)");
}, function(err, status) {
}, true, fD);
}, false);
document.addEventListener("keypress", function(event) {
if (event.keyCode == 32) {
var fD = new FormData();
fD.append('boom', 'clicked');
XXHR().request('get.php', function(response) {
var obj = JSON.parse(response);
console.log(obj);
$(".wheel").css("-ms-transform", "rotate("+obj.type1+"deg)");
$(".wheel").css("-webkit-transform", "rotate("+obj.type1+"deg)");
$(".wheel").css("transform", "rotate("+obj.type1+"deg)");
}, function(err, status) {
}, true, fD);
}
})
});
Note: There is no problem in jQuery/Javascript if you type:
$(".spin").click()
To you console, it works just fine, it spins on mobile.
The website to test your ideas:
http://uidave.com/wheel/
Good luck! Please help me!
iPhone's not recognising click events is a very old and reproducible behaviour. You can get around it by setting the cursor: pointer CSS property on the element you want clicked.

element.scrollTop/left is really slow in Safari, why?

When the given HTML code below is loaded in Safari 6.0.8, the scroll function executes in ~1500 ms. In Chrome that number is ~50 ms and in FireFox ~5 ms.
I've identified the scroll methods to be the culprits, but I can't figure out why Safari is so damn slow executing them. Is it an implementation detail of Safari, or am I doing something wrong?
<html>
<head>
<style>
.container {
width: 20%;
height: 100px;
background: #FF9800;
position: relative;
}
</style>
</head>
<body>
<div id="top">
<!-- 500 of these will be generated and added to the #top element -->
<div class="container">
<div style="position: absolute; left: -1px; top: -1px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;">
<div style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;">
<div style="position: absolute; left: 0px; top: 0px; width: 294.796875px; height: 110px;"></div>
</div>
<div style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;">
<div style="position: absolute; left: 0px; top: 0px; width: 200%; height: 200%;"></div>
</div>
</div>
</div>
</div>
<script>
//Generates the 500 container elements.
var numElements = 499;
var containerOriginal = document.querySelector(".container");
for(var i = 0; i < numElements; i++) {
var container = containerOriginal.cloneNode(true);
document.getElementById("top").appendChild(container);
}
//Why is this function so slow in Safari?
function scroll(el, et, sl, st) {
var containers = document.querySelectorAll(".container");
for(var i = 0; i < containers.length; i++) {
var container = containers[i];
var expand = container.children[0].children[0];
var shrink = container.children[0].children[1];
expand.scrollLeft = el;
expand.scrollTop = et;
shrink.scrollLeft = sl;
shrink.scrollTop = st;
}
}
//Execute the actual test on document ready.
document.addEventListener('DOMContentLoaded', function () {
console.time("test");
scroll(9, 9, 144, 101);
console.timeEnd("test");
}, false);
</script>
</body>
</html>
To my best guess of why this is so slow is because you are trying to load many elements. What I would suggest instead of
var expand = container.children[0].children[0];
var shrink = container.children[0].children[1];
putting a class on these children elements you are wanting to get and getting them that way.

Categories