Let me start of by saying I am not much a coder and pretty much fumble my way through using javascript libraries and jquery etc. I discovered and have been using classie.js to add classes to divs and elements on in my html when they are appear at a certain scroll distance on the page. so in my header i have a LOT of scripts to add and remove classes... for example:
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 100,
feature = document.querySelector("#welcomediv");
if (distanceY > shrinkOn) {
classie.remove(feature,"welcomewish");
} else {
classie.add(feature,"welcomewish");
}
});
}
window.onload = init();
</script>
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 300,
feature = document.querySelector("#slidetext");
if (distanceY > shrinkOn) {
classie.remove(feature,"welcomewish");
} else {
classie.add(feature,"welcomewish");
}
});
}
window.onload = init();
</script>
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 50, <?php /*?>130<?php */?>
feature = document.querySelector("#roundfeatures-panel");
if (distanceY > shrinkOn) {
classie.add(feature,"appearnow");
} else {
if (classie.has(feature,"appearnow")) {
classie.remove(feature,"appearnow");
}
}
});
}
window.onload = init();
</script>
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 140,
feature = document.querySelector("#roundfeatures-panel");
if (distanceY > shrinkOn) {
classie.add(feature,"expandnow");
} else {
if (classie.has(feature,"expandnow")) {
classie.remove(feature,"expandnow");
}
}
});
}
window.onload = init();
</script>
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 1000,
feature = document.querySelector("#futureevents-panel");
if (distanceY > shrinkOn) {
classie.add(feature,"appearnow");
} else {
if (classie.has(feature,"appearnow")) {
classie.remove(feature,"appearnow");
}
}
});
}
window.onload = init();
</script>
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 1400,
feature = document.querySelector("#viewallworkshops");
if (distanceY > shrinkOn) {
classie.add(feature,"slideinnow");
} else {
if (classie.has(feature,"slideinnow")) {
classie.remove(feature,"slideinnow");
}
}
});
}
window.onload = init();
</script>
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 2250,
feature = document.querySelector("#subscribe-panel");
if (distanceY > shrinkOn) {
classie.add(feature,"appearnow");
} else {
if (classie.has(feature,"appearnow")) {
classie.remove(feature,"appearnow");
}
}
});
}
window.onload = init();
</script>
(...and there are even more! and if i had my way, i'd probably add more still, because i like what i can do with the elements by adding and removing classes in this way. but if feels clunky and messy and is very hard to maintain.)
and then obviously my html elements on the page.
The problems with this are:
1) ugly scripts in my header.. is there a way i can condense the scripts in some way and retain their purpose?
2) Whenever i add new elements or take them out of the page, i have to manually change the number (shrinkOn) associated with each instance. This becomes a nightmare to be honest. It would be better if i could in some way say "when this element appears on the page" or "100px after this element appears on the page" rather than stating a strict number of pixels the page has scrolled. IS this possible with classie, or do i need to look at another option?
thanks in advance and i hope this question is appropriate.
Yes, that code can readily be parameterized, as all the blocks are doing the same thing.
Have an array of updates to do:
var scrollUpdates = [];
A function to add each update (this is purely for convenience, you could directly add them above):
addScrollUpdate(featureSelector, shrinkOn, className) {
scrollUpdates.push({
featureSelector: featureSelector,
shrinkOn: shrinkOn,
className: className
});
}
One handler handles them:
window.addEventListener('scroll', function(e){
scrollUpdates.forEach(function(update) {
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
feature = document.querySelector(update.featureSelector);
if (distanceY > update.shrinkOn) {
classie.add(feature, update.className);
} else {
if (classie.has(feature, update.className)) {
classie.remove(feature, update.className);
}
}
});
});
And you add each one like this:
addScrollUpdate("#welcomediv", 100, "welcomewish");
Putting it all together in one window load handler:
window.onload = function() {
var scrollUpdates = [];
addScrollUpdate(featureSelector, shrinkOn, className) {
scrollUpdates.push({
featureSelector: featureSelector,
shrinkOn: shrinkOn,
className: className
});
}
window.addEventListener('scroll', function(e){
scrollUpdates.forEach(function(update) {
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
feature = document.querySelector(update.featureSelector);
if (distanceY > update.shrinkOn) {
classie.add(feature, update.className);
} else {
if (classie.has(feature, update.className)) {
classie.remove(feature, update.className);
}
}
});
});
addScrollUpdate("#welcomediv", 100, "welcomewish");
addScrollUpdate("#slidetext", 300, "welcomewish");
// ...and so on...
};
However, I wouldn't use the window load event for this, that happens very late in the page load process. Instead, I'd put the script tag at the end of the HTML, just before the closing </body> tag, and run it immediately in an inline-invoked function expression:
(function() {
// the code here
})();
Side note: I don't know Classie, but you probably don't need the has test before calling remove.
Related
I am trying to add a css class to my sticky navbar when I scroll down on an interior page. I cannot get the event listener to console.log anything when scrolling down. What am I missing/doing incorrectly?
jQuery(document).ready(function($) {
// call resizeHeader() onload if not home page
if (top.location.pathname !== '/') {
window.onload = resizeHeader()
}
//resize header func
function resizeHeader() {
window.addEventListener('scroll', function(){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 1
nav = document.querySelector(".navbar")
if (distanceY > shrinkOn) {
console.log('scrolled')
nav.classList.add("smallerNav")
} else {
if (nav.classList.contains("smallerNav")) {
console.log('back to top')
nav.classList.remove("smallerNav")
}
}
})
}
})
I want to make a sticky banner, which becomes fixed at top when it is scrolled and unsticks at the end of the page. The document height is dependent upon images, that's why I use window load event. I have the following code:
function saleBanner() {
$(window).bind("load", function() {
// Make sale banner fixed-at-top
var s = $('.sale-container');
var pos = s.offset();
var maxTop = $(document).outerHeight() - 828 - s.outerHeight(); // 828 is the total height of site footer and sign up form
function fixedBanner() {
var currentTop = $(window).scrollTop();
if (currentTop >= pos.top && currentTop < maxTop) {
s.attr("style", ""); //kill absolute positioning
s.addClass('fixed-at-top'); //stick it
} else if (currentTop >= maxTop) {
s.removeClass('fixed-at-top'); //un-stick
s.css({bottom: 0}); //set sticker right above the footer
} else {
s.removeClass('fixed-at-top'); //top of page
}
}
$(window).scroll(fixedBanner);
});
}
saleBanner();
I want to make this function work on window resize as well. So I added the following code:
function resizeBanner() {
var viewportWidth = $(window).width();
if (viewportWidth > 767) {
saleBanner();
}
}
I have one more function resizeWindow for mobile menu, which I also need to work on window resize. So when I put this two functions together, they don't work (although they work on window resize separately):
$(window).resize(function(e) {
resizeWindow(e);
resizeBanner(e);
});
Where is my mistake? How can I make both functions work on window resize?
Update: Here is the whole code for resizeWindow function. It's rather long, but may be it would be helpful for the answer.
// Mobile menu
var MQM = 768;
var viewportWidth = $(window).width();
function navSlide() {
var headerHeight = $('.cd-header').height();
$(window).on('scroll', {previousTop: 0}, function () {
var currentTop = $(window).scrollTop();
//check if user is scrolling up
if (currentTop < this.previousTop ) {
//if scrolling up...
if (currentTop > 0 && $('.cd-header').hasClass('is-fixed')) {
$('.cd-header').addClass('is-visible');
} else {
$('.cd-header').removeClass('is-visible is-fixed');
}
} else {
//if scrolling down...
if(!$('.cd-header').hasClass('menu-is-open')) {
$('.cd-header').removeClass('is-visible');
}
if( currentTop > headerHeight && !$('.cd-header').hasClass('is-fixed')) $('.cd-header').addClass('is-fixed');
}
this.previousTop = currentTop;
});
}
// Primary navigation slide-in effect on load
if(viewportWidth < MQM) {
navSlide();
}
function addOverflow() {
$('html').addClass('overflow-hidden');
$('body').addClass('overflow-hidden');
}
function removeOverflow() {
$('html').removeClass('overflow-hidden');
$('body').removeClass('overflow-hidden');
}
function hideHeader() {
$('.cd-header').removeClass('is-fixed is-visible');
}
function hideMenu() {
$('.cd-header').removeClass('menu-is-open is-fixed is-visible');
$('.cd-menu-icon').removeClass('is-clicked');
}
function resizeWindow() {
var viewportWidth = $(window).width();
$(window).off('scroll'); // unbind scroll event
if (viewportWidth > 767) {
if ($('.cd-primary-nav').hasClass('is-visible')) {
if ($('.algolia__search-content').hasClass('algolia__search-content--active')) {
hideMenu();
$('.search-trigger').addClass('is-clicked');
$('.search-header').addClass('is-fixed');
} else {
hideMenu();
if (!$('.js-algolia__input').is(':focus')) {
$('.cd-primary-nav').removeClass('is-visible').one('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',function(){
removeOverflow();
});
$('.search-trigger').removeClass('is-clicked');
$('.search-header').removeClass('is-fixed');
} else {
$('.search-trigger').addClass('is-clicked');
$('.search-header').addClass('is-fixed');
}
}
} else {
hideHeader();
}
} else {
navSlide();
if ($('.cd-primary-nav').hasClass('is-visible')) {
$('.cd-header').addClass('menu-is-open');
$('.cd-menu-icon').addClass('is-clicked');
$('.search-trigger').removeClass('is-clicked');
$('.search-header').removeClass('is-fixed');
}
}
}
I'm trying to disable this script to run at a certain screen size.
<script>
function init() {
window.addEventListener('scroll', function(e){
var distanceY = window.pageYOffset || document.documentElement.scrollTop,
shrinkOn = 250,
header = document.querySelector("header");
if (distanceY > shrinkOn) {
classie.add(header,"smaller");
} else {
if (classie.has(header,"smaller")) {
classie.remove(header,"smaller");
}
}
});
}
window.onload = init();
</script>
I've tried wrapping the code with the following
if($(window).width() > 1200) {
// script here
}
And
window.addEventListener('resize', function(){
if(window.innerWidth > 568){
// script here
}
});
But none of them seems to work. Any recommendations?
i would like to know how i can manipulate the inview.js script that the moment when its fired is not at first pixels in viewport, and the last when the element is going out but rather for example 50pixels later or earlier.
the script of inview.js is
(function ($) {
function getViewportHeight() {
var height = window.innerHeight; // Safari, Opera
var mode = document.compatMode;
if ( (mode || !$.support.boxModel) ) { // IE, Gecko
height = (mode == 'CSS1Compat') ?
document.documentElement.clientHeight : // Standards
document.body.clientHeight; // Quirks
}
return height;
}
$(window).scroll(function () {
var vpH = getViewportHeight(),
scrolltop = (document.documentElement.scrollTop ?
document.documentElement.scrollTop :
document.body.scrollTop),
elems = [];
// naughty, but this is how it knows which elements to check for
$.each($.cache, function () {
if (this.events && this.events.inview) {
elems.push(this.handle.elem);
}
});
if (elems.length) {
$(elems).each(function () {
var $el = $(this),
top = $el.offset().top,
height = $el.height(),
inview = $el.data('inview') || false;
if (scrolltop > (top + height) || scrolltop + vpH < top) {
if (inview) {
$el.data('inview', false);
$el.trigger('inview', [ false ]);
}
} else if (scrolltop < (top + height)) {
if (!inview) {
$el.data('inview', true);
$el.trigger('inview', [ true ]);
}
}
});
}
});
// kick the event to pick up any elements already in view.
// note however, this only works if the plugin is included after the elements are bound to 'inview'
$(function () {
$(window).scroll();
});
})(jQuery);
all credits go to here
my attemp was to add a value to offset top top = $el.offset().top + 50, which works! but how can i change the value for the bottom up?
thanks ted
I'd recommend using http://imakewebthings.com/jquery-waypoints/
Which you can call like so to achieve your desired effect at 10% from the bottom:
$('.flyIn').waypoint(function() {
$(this).removeClass('hidden');
$(this).addClass('animated fadeInUp');
}, { offset: '90%' });
I'm trying to get the dimensions of my containerNode which is a member of my dojox dialog widget, when the widget's showing animation ends.
this.dialog = new dojox.widget.Dialog( { sizeToViewport: true });
var dialogContainer = this.dialog.containerNode;
Which function or property should I use?
Since dojo V1.7 you could use dojo.position.
With the given example:
var position = dojo.position(dialogContainer);
var dimensions = {
width: position.w,
height: position.h
}
This call requires dojo/dom-geometry.
Let me know if it worked pls..
Ok, 2nd attempt now. As experimenting a little bit, didn't lead to a solution. How about a nasty little workaround?
Researching on the sizeToViewPort-option of the dojox.widget.dialog i found out, that by default there is a padding of 35px to the ViewPort. So if you know the size of the viewport, you could get the dimensions of the dialog by substracting the padding from it..
So maybe this helps:
function getNewDialog(the_padding) {
if (!the_padding || isNaN(the_padding)) {
the_padding = 35;
}
var dialog = new dojox.widget.Dialog({
sizeToViewport: true,
padding: the_padding + 'px' //nasty string conversion
});
return dialog;
}
function getViewPortSize() {
var viewPortWidth;
var viewPortHeight;
// mozilla/netscape/opera/IE7
if (typeof window.innerWidth != 'undefined') {
viewPortWidth = window.innerWidth;
viewPortHeight = window.innerHeight;
}
// IE6 in standards compliant mode
else if (typeof document.documentElement !== 'undefined' && typeof document.documentElement.clientWidth !== 'undefined' && document.documentElement.clientWidth !== 0) {
viewPortWidth = document.documentElement.clientWidth;
viewPortHeight = document.documentElement.clientHeight;
}
// older versions of IE fallback
else {
viewPortWidth = document.getElementsByTagName('body')[0].clientWidth;
viewPortHeight = document.getElementsByTagName('body')[0].clientHeight;
}
return {
width: viewPortWidth,
heigth: viewPortHeight
};
}
function getDialogSize(the_padding) {
if (!the_padding) {
the_padding = 35;
}
var vp_size = getViewPortSize();
return {
width: vp_size.width - the_padding,
heigth: vp_size.heigth - the_padding
};
}
var costumPadding = 35; // this is also the default value of dojox.widget.dialog ...
var dialog = getNewDialog(costumPadding);
var dialogSize = getDialogSize(costumPadding);
Hope I didn't miss anything.
This is one of possible sollutions
dojo.connect(mydialog, "show", function(){
setTimeout(function(){
var position = dojo.position(dialogContainer);
var dimensions = {
width: position.w,
height: position.h
}
alert(position.h);
},mydialog.duration + 1500);
});