Site URL: https://petnotify.sporksquad.com/
I'm building a website for a client, and I built two stacked containers within it. I want only the bottom half with the navbar to be sticky and have the disappear / reappear feature. It works perfectly until I scroll up too quickly and the bottom part overtakes the top container with the logo and social icons. I would love to prevent this from happening and
properly stopping below the top container when you reach the top of the page.
I followed this tutorial and this is my Elementor set-up. The code I used is
<script>
document.addEventListener('DOMContentLoaded', function() {
jQuery(function($) {
var mywindow = $(window);
var mypos = mywindow.scrollTop();
let scrolling = false; /* For throlling scroll event */
window.addEventListener('scroll', function() {
scrolling = true;
});
setInterval(() => {
if (scrolling) {
scrolling = false;
if (mypos > 20) {
if (mywindow.scrollTop() > mypos) {
$('#stickyheaders').addClass('headerup');
} else {
$('#stickyheaders').removeClass('headerup');
}
}
mypos = mywindow.scrollTop();
}
}, 300);
});
});
</script>
<style>
#stickyheaders{
transition : transform 0.4s ease;
}
.headerup{
transform: translateY(-20vh); /*adjust this value to the height of your header*/
}
</style>
I've tried messing around with the vh for the height of header (each container is 10vh so the header is 20vh). Not sure what else to do as I'm not super familiar with jQuery but I'm sure it's an easy fix.
As the title suggests I want to detect the start and end of a scrollable element built using overflow.
The following code works:
var scrollAmount = 150;
var scrollBox = $('.js-compare_scroll');
var arrowLeft = $('.js-compare_scroll_left');
var arrowRight = $('.js-compare_scroll_right');
var inactive = 'm-inactive';
$(arrowLeft).on('click', function () {
$(this).parent().find(scrollBox).stop().animate({
scrollLeft: '-='+scrollAmount
}, function() {
arrowRight.removeClass(inactive);
if(scrollBox.scrollLeft() === 0) {
arrowLeft.addClass(inactive);
}
});
});
$(arrowRight).on('click', function () {
$(this).parent().find(scrollBox).stop().animate({
scrollLeft: '+='+scrollAmount
}, function() {
arrowLeft.removeClass(inactive);
if(scrollBox.scrollLeft() + scrollBox.innerWidth() >= scrollBox[0].scrollWidth) {
arrowRight.addClass(inactive);
}
});
});
However the class to style the inactive colour of the arrows only appears once the animation completes. I need to add the class before the animation completes because it has a delay. I believe by default it is 400.
Is there anyway to detect this and apply the arrow classes where needed?
Thanks.
Came back from a break and realised I should take the checking if its at the end off the click event and onto a scroll event. This works a lot better now.
Is Google Chrome on Windows having problems to render iframe scrollbars?
I wrote a very simple code to show what is happening (at least with me on chrome 52.0.2743.82 m):
<button>Toggle visibility</button>
<br />
<iframe scrolling="yes" seamless src="https://en.wikipedia.org/wiki/Lorem_ipsum" frameborder="0" style="width: 700px; height: 300px"></iframe>
<script type="text/javascript">
$("button").on("click", function() {
$("iframe").toggle();
});
</script>
Plunker link to code
When the page is loaded, the iframe as it scrollbar are visible.
Hide and show the iframe clicking the button. The scrollbar disappears.
This issue apparently occurs only in chrome.
Anyone is experiencing this too? Any fixes/workarounds?
It seems that bug appeared with the update Chrome 52.0.2743.82 (http://googlechromereleases.blogspot.fr/2016/07/stable-channel-update.html)
One possible workaround is to use the attribute visibility with position: absolute instead of display to show or hide the iframe.
A chrome bug ticket exists for this item: https://bugs.chromium.org/p/chromium/issues/detail?id=641881
I've had this problem, and using visibility instead of display: none wasn't an option.
My workaround was to set overflow: scroll on the <body> of the document being displayed in the iframe, whenever I set the iframe to be visible again. This seems to force the scrollbar to appear on the iframe again. You can then reset the overflow to its old value, and the scrollbar will remain on the iframe. You need to wait for a repaint before you can reset the overflow, though, so I put this in a timeout with delay 0.
function showIframe(iframe) {
var iframeBody = iframe.contentDocument.body;
$(iframe).show();
var oldOverflow = iframeBody.css("overflow");
iframeBody.css("overflow", "scroll");
window.setTimeout(function () {
iframeBody.css("overflow", oldOverflow);
}, 0);
}
There is a "flash" of scrollbar with this workaround if the iframe in question doesn't need to scroll, though, so it might be worth using the visibility workaround for that brief moment where the repaint is required, to avoid the flash.
Here's a workaround I've developed for an application I'm building. It has multiple <iframe> elements in a Foundation tab-control.
I used MutationObserver to observe when the <iframe>'s parent element (a Foundation div.tabs-content div.content element) becomes active, then I toggle the iframe's document's overflow property. The runtime effect is imperceivable.
I originally wanted to observe the <iframe> directly, however no DOM mutation events were raised when the iframe itself's changed display property, I guess because technically speaking element.style values are not part of the DOM-structure proper.
Here's my code (Vanilla.js, no jQuery). If you're using in your application you will want to replace my visibility-detection code with something that is applicable to your document:
window.addEventListener('DOMContentLoaded', function(e) {
var observer = new MutationObserver( onContentMutated );
var options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['class'] };
var iframeContainers = document.querySelectorAll('.tabs-content .content');
for(var i = 0; i < iframeContainers.length; i++) {
observer.observe( iframeContainers[i], options );
}
});
function onContentMutated(mutations) {
for(var i = 0; i < mutations.length; i++) {
var m = mutations[i];
var thisIsNowAnActiveTab = m.target.classList.contains('active');
if( thisIsNowAnActiveTab ) {
// get the corresponding iframe and fiddle with its DOM
var iframes = m.target.getElementsByTagName("iframe");
if( iframes.length == 0 ) continue;
var iframe = iframes[0];
iframe.contentWindow.document.documentElement.style.overflow = 'hidden';
// the timeout is to trigger Chrome to recompute the necessity of the scrollbars, which makes them visible again. Because the timeout period is 0 there should be no visible change to users.
setTimeout( function(s) {
s.overflow = 'auto';
}, 0, iframe.contentWindow.document.documentElement.style );
}
console.log( m.type );
}
}
For the given example you can do:
$("iframe").toggle(1)
In my case, it worked by setting back the height:
$("iframe").css("height", "100%")
I had a similar issue on Chrome with an iframe embedded into a jQuery UI tab. When the tab containing the iframe is first displayed, the scrollbar appears. But when I switch to another tab and back to the tab with the iframe then the scrollbar disappears. All the solutions proposed here didn't work for me.
Here is what I did to fix the issue :
First, I create the tabs :
$("#mytabs").tabs();
Then I bind a function to the event "tabsactivate" and I check if the target tab is the one containing the iframe. If it is the case I call a function fixChromeScrollBar() described later on :
$("#mytabs").on("tabsactivate", function(event, ui) {
if ($(event.originalEvent.target).attr("href") == "#mytab-with-iframe") {
fixChromeScrollBar();
}
});
And finally here is the function fixChromeScrollBar() which sets the overflow style attribute of the iframe body (as already said) to either "scroll" or "auto". I noticed that when I only define the "auto" or "scroll" value then if I switch to another tab and back to the iframe I lose the scrollbars. The only way to maintain them is to alternate between the two values each time the iframe appears. It is weird but it works :
function fixChromeScrollBar() {
var iFrameBody = $("#myiframe").contents().find("body");
var originalOverflow = $(iFrameBody).css("overflow");
if (originalOverflow == "visible" || originalOverflow == "auto") {
$(iFrameBody).css("overflow", "scroll");
} else {
$(iFrameBody).css("overflow", "auto");
}
}
You can notice that this method is called only if you switch to the tab containing the iframe so if you click multiple times on this tab without switching to another one this code will only be executed the first time.
Apparently setting src refreshes iframe in chrome, for given example code will be:
<script type="text/javascript">
$("button").on("click", function() {
$('iframe').toggle().attr('src', function(i, val) { return val; });
});
</script>
I adapted Dai's example to my own React IFrame component. I have an iframe within a tab panel, which is itself in a collapsible panel. When either of those get toggled, I force the iframe to repaint. It works wonderfully.
private iframe: HTMLIFrameElement;
private displayObserver: MutationObserver;
componentDidMount() {
// Detect style attribute changes for the containing collapsible components
// If the display goes from 'none' to something else, then we need to redraw the iframe
// so we get the scrollbar back as it should be.
if (isChrome()) {
this.displayObserver = new MutationObserver(this.onContentMutated);
const options = { attributes: true, childList: false, characterData: false, subtree: false, attributeFilter: ['style'] };
const tabPanelAncestor = this.findAncestor(this.iframe, '.tab-panel-content');
if (tabPanelAncestor) {
this.displayObserver.observe(tabPanelAncestor, options);
}
const collapsibleAncestor = this.findAncestor(this.iframe, '.collapsible');
if (collapsibleAncestor) {
this.displayObserver.observe(collapsibleAncestor, options);
}
}
}
private readonly onContentMutated = (mutations: Array<MutationRecord>) => {
R.forEach( (mutation) => {
const targetElement = mutation.target as Element;
const style = targetElement.getAttribute('style');
if (style && !style.match(/display: none/)) {
this.iframe.contentWindow.location.reload(true);
}
}, mutations);
}
private readonly findAncestor = (element: HTMLElement, sel: string): Node | null => {
if (typeof element.closest === 'function') {
return element.closest(sel) || null;
}
let ancestor: HTMLElement | null = element;
while (ancestor) {
if (ancestor.matches(sel)) {
return ancestor;
}
ancestor = ancestor.parentElement;
}
return null;
}
i had this script used on my site but there's no easing effect on it can anyone tell me how to add easing effect on this script?
<script>
var scaffold = document.getElementById('scaffold');
var menu = document.getElementById('menu');
menu.addEventListener('core-select', function(e) {
if (e.detail.isSelected) {
scrollToSection(e.detail.item.getAttribute('name'));
}
});
function scrollToSection(id) {
var section = document.getElementById(id);
if (section) {
scaffold.$.headerPanel.scroller.scrollTop = section.offsetTop, 500;
}
}
If it is possible to use jQuery you can use its animate method.
I'm building a site where I want the certain sections to be hidden until the mouse is moved. They then remain visible whilst the mouse is moving, however, if it remains still for a couple of seconds they hide again.
I'm using jQuery on the site, in my ready state I have:
var hide = setTimeout(function() {
hideNav();
}, 2000);
$('body').mousemove(function() {
clearTimeout(hide);
var hide = setTimeout(function() {
hideNav();
}, 2000);
showNav();
});
And the functions that show/hide content
function hideNav() {
$('#primary').fadeOut(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeOut(1000);
}
}
function showNav() {
$('#primary').fadeIn(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeIn(1000);
}
}
This sort of works, except the timeout for hiding the elements ends up fighting with the function to show it when the mouse moves resulting in a lot of flickering.
EDIT: The mouse movement needs to be for anywhere on the page, not just when hovering over the element that is to be shown/hidden.
Any help would be appreciated.
Thanks
Try using $.stop http://api.jquery.com/stop/
If its in the 1 second of fading out when you move your mouse, it should stop the animation of fading out and fade back in.
function hideNav() {
$('#primary').stop().fadeOut(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeOut(1000);
}
}
function showNav() {
$('#primary').stop().fadeIn(1000);
var lightbox = $('#lightbox');
if (lightbox.length) {
lightbox.fadeIn(1000);
}
}
Also, I would remove var from the var hide = ... in your mousemove function. If hide is a global variable, just reuse it inside mousemove (doesn't need to be redeclared).