scrollTop does not work well inside iframe - javascript

I have a html file created with cloudconvert.com that I wrapped with java script to highlight text inside it and scroll to first highlight using JQuery scrollTop() function. See example:
function doSearch2(text,color) {
if (window.find && window.getSelection) {
document.designMode = "on";
var sel = window.getSelection();
sel.collapse(document.body, 0);
while (window.find(text)) {
document.execCommand("HiliteColor", false, color);
sel.collapseToEnd();
}
document.designMode = "off";
} else if (document.body.createTextRange) {
var textRange = document.body.createTextRange();
while (textRange.findText(text)) {
textRange.execCommand("BackColor", false, color);
textRange.collapse(false);
}
}
var sel2 = document.getSelection();
var seltop = $(sel2.anchorNode.parentElement).offset().top;
var doccurrenttop = $('#page-container').scrollTop();
var scrollto = doccurrenttop + seltop - 70; // spce of 70px
if (scrollto < 0) { scrollto = 0; }
$('#page-container').scrollTop(scrollto);
}
doSearch2("Cross","yellow");
http://jsfiddle.net/3c3vx862/
I try to insert doSearch2() function into the head of the html file and load it on iframe inside new html document. Then I call doSearch2() from button on the outer document.
The scrollTop works fine, except on some cases (like scrolling to the bottom of the document and other random locations). When I debug it I find that sel2 (= document.getSelection()) is zero.
Any Ideas ?
Thanks !

Well it doesnt work probably for all that generated script and html you have there but you can take a look at this jsfiddle I made for you here.
Add this to your html page:
Top
Script
jQuery(document).ready(function($){
// browser window scroll (in pixels) after which the "back to top" link is shown
var offset = 300,
//browser window scroll (in pixels) after which the "back to top" link opacity is reduced
offset_opacity = 1200,
//duration of the top scrolling animation (in ms)
scroll_top_duration = 700,
//grab the "back to top" link
$back_to_top = $('.cd-top');
//hide or show the "back to top" link
$(window).scroll(function(){
( $(this).scrollTop() > offset ) ? $back_to_top.addClass('cd-is-visible') : $back_to_top.removeClass('cd-is-visible cd-fade-out');
if( $(this).scrollTop() > offset_opacity ) {
$back_to_top.addClass('cd-fade-out');
}
});
//smooth scroll to top
$back_to_top.on('click', function(event){
event.preventDefault();
$('body,html').animate({
scrollTop: 0 ,
}, scroll_top_duration
);
});
});
CSS
.cd-top {
display: inline-block;
height: 40px;
width: 40px;
position: fixed;
bottom: 100px;
right: 10px;
z-index: 10;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.05);
/* image replacement properties */
overflow: hidden;
text-indent: 100%;
white-space: nowrap;
background: rgba(232, 98, 86, 0.8) url(../img/cd-top-arrow.svg) no-repeat center 50%;
visibility: hidden;
opacity: 0;
-webkit-transition: opacity .3s 0s, visibility 0s .3s;
-moz-transition: opacity .3s 0s, visibility 0s .3s;
transition: opacity .3s 0s, visibility 0s .3s;
}
.cd-top.cd-is-visible, .cd-top.cd-fade-out, .no-touch .cd-top:hover {
-webkit-transition: opacity .3s 0s, visibility 0s 0s;
-moz-transition: opacity .3s 0s, visibility 0s 0s;
transition: opacity .3s 0s, visibility 0s 0s;
}
.cd-top.cd-is-visible {
/* the button becomes visible */
visibility: visible;
opacity: 1;
}
.cd-top.cd-fade-out {
/* if the user keeps scrolling down, the button is out of focus and becomes less visible */
opacity: .5;
}
.no-touch .cd-top:hover {
background-color: #e86256;
opacity: 1;
}
#media only screen and (min-width: 768px) {
.cd-top {
right: 20px;
bottom: 20px;
}
}
#media only screen and (min-width: 1024px) {
.cd-top {
height: 60px;
width: 60px;
right: 30px;
bottom: 30px;
}
}
jsFiddle here

Related

Change background color of header on scroll

I want to change the background color of my header (from transparent to black) when it scrolls. How can I do this?
I use a CMS to create the header. That is my code at the moment:
<script>
jQuery(function($) {
$(window).scroll(function() {
if ($(document).scrollTop() > 50) {
$('#section-padding').addClass('reduce-section-padding');
$('#row-width').addClass('increase-row-width');
$('#my-site-logo').addClass('reduce-logo');
} else {
$('#section-padding').removeClass('reduce-section-padding');
$('#section-padding').addClass('slow-transition');
$('#row-width').removeClass('increase-row-width');
$('#row-width').addClass('slow-transition');
$('#my-site-logo').removeClass('reduce-logo');
$('#my-site-logo').addClass('slow-transition');
}
});
});
</script>
<style>
.reduce-section-padding {
transition: all 0.9s ease-out 0s;
padding-top: 0px !important;
padding-bottom: 0px !important;
}
.reduce-logo {
transition: all 0.9s ease-out 0s;
transform: scale(0.8) !important;
/* Standard syntax */
/*content: url(/wp-content/uploads/2020/05/favicon.png) !important;*/
}
.increase-row-width {
transition: all 0.9s ease-out 0s;
width: 70% !important;
}
.slow-transition {
transition: all 0.9s ease-out 0s;
}
#main-content {
margin-top: 5vw;
}
</style>
You can use plain JavaScript like this:
(JSFiddle: https://jsfiddle.net/omartheman949/5jLngzkh/12/)
Place the following script tag and it's contents under your existing script tag (or place the contents of the following script tag inside your existing script tag):
<script>
var prevScrollpos = window.pageYOffset;
window.onscroll = function() {
var currentScrollPos = window.pageYOffset;
if (window.pageYOffset === 0) {
document.getElementById("header").style.backgroundColor = "transparent";
document.getElementById("header").style.color = "black";
} else {
document.getElementById("header").style.backgroundColor = "black";
document.getElementById("header").style.color = "white";
}
prevScrollpos = currentScrollPos;
}
</script>

IntersectionObserver: Trigger event when scrolling back to the top

I am starting to use the IntersectionObserver API and could create some basic animations, which includes hiding and appearing of elements. However, once a person wants to scroll back to the top, the elements which disappeared by one of the triggers are not getting visible again.
My Solution so far
So I thought I might create another test variable within the intersection observer callback function (the stepI and stepII variable in my code), which checks if the callback function was previously triggered. If so, instead of disappearing the elements, let them appear again.
My current problem
So let's say a background image (id="hiddenImg") should appear when the first text block (id="I") passes the 50% border of the viewport and it disappears when the second text block (id="II") enters this area. Even though the image is getting visible again when scrolling back up, if the user does not scroll back completely (so that the second text block goes out of the viewport) and then scrolls back to the bottom, the disappearing trigger of that second text block is not called. This would mean that the background image would stay visible, which it shouldn't.
Here is the js part:
var stepI = false;
var stepII = false;
// list of options
let options = {
rootMargin: '0px 0px -50%' //WHEN reaching half of the viewport
};
// instantiate a new Intersection Observer
"use strict";
var intersectionObserver = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (change) {
if (change.isIntersecting) {
if (change.target.id == "I") {
$("#hiddenImg").removeClass("hidden_img");
$("#hiddenImg").addClass("visible_img");
stepI = true;
observer.unobserve(change.target);
}
if (change.target.id == "II") {
if (stepII == false) {
$("#hiddenImg").removeClass("visible_map");
$("#hiddenImg").addClass("hidden_map");
stepII = true
} else {
$("#hiddenImg").removeClass("hidden_map");
$("#hiddenImg").addClass("visible_map");
stepII = false;
}
}
}
});
},options);
// list of paragraphs
let elements = document.querySelectorAll(".stepper");
for (let elm of elements) {
intersectionObserver.observe(elm);
}
Here is my complete code:
<html>
<head>
<!-- Load the polyfill. -->
<script src="/js/intersection-observer.js"></script>
<script src='https://unpkg.com/intersection-observer#0.5.0/intersection-observer.js'></script>
</head>
<body>
<style>
.intro-imgs {
display: block;
margin: 0 auto; /* Will not center vertically and won't work in IE6/7. */
left: 0;
right: 0;
position: fixed;
position: expression(fixed);
}
.hidden_img {
visibility: hidden;
opacity: 0;
-ms-transform: scaleX(0); /* IE 9 */
-webkit-transform: scaleX(0); /* Safari 3-8 */
-o-transform: scaleX(0);
-moz-transform: scaleX(0);
transform: scaleX(0);
-webkit-transition: visibility 0s 0.5s, opacity 0.5s linear, -webkit-transform 0.5s;
-moz-transition: visibility 0s 0.5s, opacity 0.5s linear, -moz-transform 0.5s;
-o-transition: visibility 0s 0.5s, opacity 0.5s linear, -o-transform 0.5s;
transition: visibility 0s 0.5s, opacity 0.5s linear, transform 0.5s;
}
.visible_img {
visibility: visible;
opacity: 1;
-ms-transform: scaleX(1); /* IE 9 */
-webkit-transform: scaleX(1); /* Safari 3-8 */
-o-transform: scaleX(1);
-moz-transform: scaleX(1);
transform: scaleX(1);
-webkit-transition: opacity 0.5s linear, -webkit-transform 0.5s;
-moz-transition: opacity 0.5s linear, -moz-transform 0.5s;
-o-transition: opacity 0.5s linear, -o-transform 0.5s;
transition: opacity 0.5s linear, transform 0.5s;
}
.stepper{
max-width: 70rem;
margin: 550px auto 600px auto;
width: 90%;
background-color: rgba(248, 248, 248, 0.95);
font-family: "Helvetica";
font-size: 17px;
line-height: 26px;
padding: 15px;
}
</style>
<!--HTML-->
<div class="headline">
<img id="hiddenImg" class="hidden_img intro-imgs" src="https://image.shutterstock.com/image-photo/funny-portrait-hero-260nw-410898763.jpg" >
</div>
<div id="I" class="stepper">
<p>Lorem Ipsum</p>
</div>
<div id="II" class="stepper">
<h1>THE HEADLINE</h1>
</div>
<!-- SCRIPT-->
<script>
var stepI = false;
var stepII = false;
// list of options
let options = {
rootMargin: '0px 0px -50%' //WHEN reaching half of the viewport
};
// instantiate a new Intersection Observer
"use strict";
var intersectionObserver = new IntersectionObserver(function (entries, observer) {
entries.forEach(function (change) {
if (change.isIntersecting) {
if (change.target.id == "I") {
$("#hiddenImg").removeClass("hidden_img");
$("#hiddenImg").addClass("visible_img");
stepI = true;
observer.unobserve(change.target);
}
if (change.target.id == "II") {
if (stepII == false) {
$("#hiddenImg").removeClass("visible_map");
$("#hiddenImg").addClass("hidden_map");
stepII = true
} else {
$("#hiddenImg").removeClass("hidden_map");
$("#hiddenImg").addClass("visible_map");
stepII = false;
}
}
}
});
},options);
// list of paragraphs
let elements = document.querySelectorAll(".stepper");
for (let elm of elements) {
intersectionObserver.observe(elm);
}
</script>
</body>

Sticky header snapping to top to early

I've been playing around with this code forever. I have a sticky nav implemented on my site and it's supposed to activate once the header becomes out of sight when the user scrolls. The header div is above the nav div. The sticky part works fine but it activates too soon. It snaps to the top immediately once I start scrolling and then doesn't snap back to it's original position once the header comes into view again.
Here's the jquery that makes it work:
(function($) {
var $body,
$target,
targetoffsetTop,
resizetimer,
stickyclass = 'sticky'
function updateCoords() {
targetoffsetTop = $target.offset().top
}
function makesticky() { //Sets the sticky class to activate once
var scrollTop = $(document).scrollTop() //the scroll offset is greater than
if (scrollTop >= targetoffsetTop) { //how far the div is from the top.
if (!$body.hasClass(stickyclass)) {
$body.addClass(stickyclass)
}
} else {
if ($body.hasClass(stickyclass)) {
$body.removeClass(stickyclass)
}
}
}
$(window).on('load', function() {
$body = $(document.body)
$target = $('#header_lg') //This is the target div that get's sticky
updateCoords()
$(window).on('scroll', function() {
requestAnimationFrame(makesticky)
})
$(window).on('resize', function() {
clearTimeout(resizetimer)
resizetimer = setTimeout(function() {
$body.removeClass(stickyclass)
updateCoords()
makesticky()
}, 50)
})
})
})(jQuery)
CSS:
#header_lg { //Before sticky
width: 100%;
height: 75px;
padding: .7%;
background-color: blue;
-webkit-transition: height 1s, width 1s;
-moz-transition: height 1s, width 1s;
transition: height 1s, width 1s;
}
body.sticky #header_lg { //After sticky
position: fixed;
top: 0;
left: 0;
height: 100px;
width: 100%;
}
I'm fairly new with javascript so any suggestions from you experts as to why the code isn't working right would be greatly appreciated. If it's important, the page is in a bootstrap format so it's within the visible-lg class with a container class inside that set to style="width:100%; margin:0; padding:0;". The HTML code is just an empty div with some filler text.
you did not write correctly your CSS comments (different from js):
try this:(thanks #Toni for her usefull pen here i forked to demonstrate )
#header_lg { /*Before sticky*/
width: 100%;
height: 75px;
padding: .7%;
background-color: blue;
-webkit-transition: height 1s, width 1s;
-moz-transition: height 1s, width 1s;
transition: height 1s, width 1s;
}
body.sticky #header_lg { /*After sticky*/
position: fixed;
top: 0;
left: 0;
height: 100px;
width: 100%;
}

Responsive Image Background Quality Issues

I have a header that changes size when a user scrolls past a certain point via JavaScript.
When a user scrolls beyond 50px, the class .smaller is added to the header, which affects the child elements, including the logo.
However, when the logo DIV element is resized, the quality of the image seems to change; the edges seem much more jagged and sharper.
This is how it looks normally:
And scrolled:
Here is the CSS:
div#header div.logo {
width: 400px;
height: 90px;
margin: 5px;
background: url(../img/logo.png) no-repeat center center;
background-size:contain;
float:left;
padding:0 !important;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-ms-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
}
div#header.smaller div.logo {
width:262px;
height:40px;
-webkit-transition: all 0.3s;
-moz-transition: all 0.3s;
-ms-transition: all 0.3s;
-o-transition: all 0.3s;
transition: all 0.3s;
}
Relevant JavaScript:
window.onload = init();
function init() {
//header resize on scroll
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 50,
header = document.querySelector("#header");
if (distanceY > shrinkOn) {
classie.add(header,"smaller");
} else {
if (classie.has(header,"smaller")) {
classie.remove(header,"smaller");
}
}
});
}
Why is there such a noticeable change in image quality, and how can this be avoided?
The image got blurry when navigator resize your image on the fly. SVG image will not blur your logo.
e.g. virtuehost.net/clients/go2markets check this site and try to resize this logo.

How to add css transitions to js scroll in header?

I have a header that appears when the page scrolls down. I am trying to add css transitions to make it fade in and out because I've read that using javascript for fading is not as efficient.
.header-wrapper {
top:0;
left:0;
right:0;
position: fixed;
display:none;
height: 60px;
border-top: 1px solid #000;
background: red;
z-index: 1;
}
.header-wrapper.active {
display:block;
}
.header {
background-color:#000;
height:80px;
}
Here is the js fiddle
$(window).scroll(function () {
var y = $(window).scrollTop();
// if above 300 and doesn't have active class yet
if (y > 300 && !$('.header-wrapper').hasClass('active')) {
$('.header-wrapper').addClass('active');
// if below 300 has still has active class
} else if(y <= 300 && $('.header-wrapper').hasClass('active')) {
$('.header-wrapper').removeClass('active');
}
});
Transitions are added with the css3 property transition.
One common reason for confusion: you can only transition properties that accept numeric values. Thus, you can't transition between display: block and display: none.
However you can transition between opacity: 0 and opacity: 1 with:
transition: 0.5s opacity
That would look something like this:
.bottomMenu {
...
opacity: 0;
transition: 0.5s opacity;
...
}
.bottomMenu.active {
opacity: 1;
}
For your particular case, I might recommend transitioning the height between 0 and 60px.
For that you can use:
transition: 0.5s height
So:
.bottomMenu {
...
height: 0;
transition: 0.5s height;
...
}
.bottomMenu.active {
height: 80px;
}
To animate the opacity the element must be visible. So remove the display:none and make it fully transparent (opacity:0). You can then use CSS transitions to animate the opacity when the classname changes:
.bottomMenu {
...
display:block;
opacity: 0;
transition: opacity .25s ease-in-out;
-moz-transition: opacity .25s ease-in-out;
-webkit-transition: opacity .25s ease-in-out;
}
.bottomMenu.active {
opacity:1
}
http://jsfiddle.net/oL9ro4gL/6/
Furthermore, you're not restricted to just animating the opacity:
.bottomMenu {
...
transition: all .25s ease-in-out;
}
.bottomMenu.active {
opacity:1;
height: 60px;
background-color: blue;
transform:rotate(180deg);
color:white;
font-size:40px;
etc...
}
http://jsfiddle.net/oL9ro4gL/8/
Unfortunately, you can't animate the display property. See this question and its suggestions for workarounds.

Categories