jQuery addClass not working on DOM fired from JS - javascript

Basically I have a menu HTML code that is injected into the DOM via a jQuery function, i.e.
$.get("/clients/nav_menu.html", function(data) {
$("nav").html(data);
$('#side-menu').metisMenu(); //menu plugin for Bootstrap
});
However, after changing the loading of menu to the above script, the Bootstrap distribution package (sb-admin-2) that came with the below lines of code failed during load only (resize continues to work fine) for the code marked (*******) below:
$(function() {
$(window).bind("load resize", function() {
topOffset = 50;
width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width;
if (width < 768) {
$('div.navbar-collapse').addClass('collapse'); // *******
topOffset = 100;
} else {
$('div.navbar-collapse').removeClass('collapse');
}
height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1;
height = height - topOffset;
if (height < 1) height = 1;
if (height > topOffset) {
$("#page-wrapper").css("min-height", (height) + "px");
}
});
var url = window.location;
var element = $('ul.nav a').filter(function() {
return this.href == url;
}).addClass('active').parent().parent().addClass('in').parent();
if (element.is('li')) {
element.addClass('active');
}
});
The piece of code marked (*******) above fires during load and resize, and div.navbar-collapse resides in the menu HTML code that was injected as mentioned above. I just don't understand why it fails to modify the DOM element during load, but once I resize the screen width, the class 'collapse' gets added to the div.
What I've tried:
made sure that each time I reload the page, the screen size is less than 768px - didn't work;
bringing the code marked (*******) to the end of all my js scripts - didn't work;
bringing the code marked (*******) into the $.get callback right after the menu was loaded - didn't work;

Related

can't change z index with javascript

I'm trying to change the Z index of an image according to the scroll position,currently in chrome (but it should be working on all broswers).
anyway, it's not working on chrome, unless I get into inspection mode and I don't understand why it's only working in inspection mode?
this is the script:
$( window ).scroll(function() {
var scrollTop = $(window).scrollTop();
if ($(this).scrollTop()>700) {
document.getElementById("back-ground-image").style.zIndex = "-9";
console.log("-9");
} else {
document.getElementById("back-ground-image").style.zIndex = "-19";
console.log("-19");
}
});
Problem
What you need is $(document) not $(window).
By default, you scroll the $(document), not the $(window).
However, when you open your Chrome DevTools, the $(window) is not being scrolled which is why your code works.
To fix the issue, change $(window).scroll() to $(document).scroll() and $(window).scrollTop() to $(document).scrollTop()
Improvements
1. Use jQuery functions
Also, if you're already using jQuery, why not use jQuery selectors and .css():
$("#back-ground-image").css('zIndex', '-9')
instead of
document.getElementById("back-ground-image").style.zIndex = "-9";
2. Use DRY code
(Don't Repeat Yourself)
If you follow recommendation #1, why not set $("#back-ground-image") to a variable instead of repeating it twice.
$(document).scroll(function() {
var scrollTop = $(document).scrollTop(),
$bkImg = $("#back-ground-image");
if ($(this).scrollTop() > 700) {
$bkImg.css('zIndex', '-9');
console.log("-9");
} else {
$bkImg.css('zIndex', '-19');
console.log("-19");
}
});
Otherwise, you could use:
$(document).scroll(function() {
var scrollTop = $(document).scrollTop(),
background = document.getElementById("back-ground-image");
if ($(this).scrollTop()>700) {
background.style.zIndex = "-9";
console.log("-9");
} else {
background.style.zIndex = "-19";
console.log("-19");
}
});

scroll to with easing does not work with infinite js. scroll to with easing conflicting with infinite js

PLEASE VIEW SOURCE CODE ON BOTH PAGES.
On this page: _p1.html It is "page 1" Use the scroll bar on the right side of the browser to scroll all the way down to bottom of page. "page 2" will appear. I am using infinite scroll js.
I am also using scroll to anchor point with easing. Go back to top of the page again: _p1.html Click on "scroll down to item A" It scrolls down to middle of page with easing. Now, scroll down even more. Page 2 loads. Great. Now, click on "scroll down to item B" Item B just jumps to the middle page when it supposed to scroll with easing.
What is wrong? How do I fix this?
If you go directly to page 2 here: _p2.html Click on item B. You will see that easing works. BUT when on page 1 AND infinite js, the easing scroll does not work.
What is wrong? How do I fix this?
The scroll to js is fired off at page load and is not running again when new content is loaded into the page. Therefore the scroll effect will not work on any additional content loaded into the page (page2, page3, and so on). we need to find a way to re-trigger the javascript when new content is introduced and loaded into the page.
You can attach the event handler to a parent, in this case I've used $(document) but to avoid excess overhead use the closest parent, then tell jQuery to only bubble-up the event to '.page-scroll'. This way if any new elements are added to the document which have the class page-scroll this event will be attached to them as well.
$(function() {
$(document).on('click', '.page-scroll', function(e) {
e.preventDefault();
var $anchor = $(e.target);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 2500, 'easeInOutExpo');
});
});
EDIT
To make this work in your situation where the script may be included more than once, you have to make sure to only load jQuery, bootstrap and jasny once, then wrap the rest of the script in a window.onload event handler. as the window only loads once, if the script is included after the window is loaded it will not be executed.
I've also reduced the included jquery easings to only include easeInOutExpo which is the easing you are using in your function.
Replace all of the scripts on each page with the following script.
<script>
if (typeof jQuery == 'undefined') {
var newJQuery = document.createElement('script');
newJQuery.type = 'text/javascript';
newJQuery.src = 'https://code.jquery.com/jquery-2.1.1.min.js';
document.body.appendChild(newJQuery);
window.jQueryInterval = window.setInterval(function(){
if(typeof jQuery != 'undefined') {
window.clearInterval(window.jQueryInterval);
var newBootstrap = document.createElement('script');
newBootstrap.type = 'text/javascript';
newBootstrap.src = 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js';
document.body.appendChild(newBootstrap);
var newJasny = document.createElement('script');
newJasny.type = 'text/javascript';
newJasny.src = 'https://cdnjs.cloudflare.com/ajax/libs/jasny-bootstrap/3.1.3/js/jasny-bootstrap.min.js';
document.body.appendChild(newJasny);
/******************************************
Infinite jQuery Scroll
#author Fabio Mangolini
http://www.responsivewebmobile.com
******************************************/
//location.href = 'index.html#start';
var pages = []; //key value array that maps the pages. Ex. 1=>page2.html, 2=>page3.html
var current = 0; //the index of the starting page. 0 for index.html in this case
var loaded = []; //key value array to prevent loading a page more than once
//get all the pages link inside the #pages div and fill an array
$('#pages a').each(function(index) {
pages[index] = $(this).attr('href');
loaded[$(this).attr('href')] = 0; //initialize all the pages to be loaded to 0. It means that they are not yet been loaded.
});
//on scroll gets when bottom of the page is reached and calls the function do load more content
$(window).scroll(function() {
//Not always the pos == h statement is verified, expecially on mobile devices, that's why a 300px of margin are assumed.
if ($(window).scrollTop() + $(window).height() >= $(document).height() - 300) {
console.log("bottom of the page reached!");
//in some broswer (es. chrome) if the scroll is fast, the bottom
//reach events fires several times, this may cause the page loaging
//more than once. To prevent such situation every time the bottom is
//reached the number of time is added to that page in suach a way to call
//the loadMoreContent page only when the page value in "loaded" array is
//minor or equal to one
loaded[pages[current + 1]] = loaded[pages[current + 1]] + 1;
if (loaded[pages[current + 1]] <= 1)
loadMoreContent(current + 1);
}
});
//loads the next page and append it to the content with a fadeIn effect.
//Before loading the content it shows and hides the loaden Overlay DIV
function loadMoreContent(position) {
//try to load more content only if the counter is minor than the number of total pages
if (position < pages.length) {
$('#loader').fadeIn('slow', function() {
$.get(pages[position], function(data) {
$('#loader').fadeOut('slow', function() {
$('#scroll-container').append(data).fadeIn(999);
current = position;
});
});
});
}
}
jQuery.extend(jQuery.easing, {
easeInOutExpo: function(e, f, a, h, g) {
if (f === 0) {
return a;
}
if (f === g) {
return a + h;
}
if ((f /= g / 2) < 1) {
return h / 2 * Math.pow(2, 10 * (f - 1)) + a;
}
return h / 2 * (-Math.pow(2, -10 * --f) + 2) + a;
}
});
/*jQuery to collapse the navbar on scroll
$(window).scroll(function() {
if ($(".navbar").offset().top > 50) {
$(".navbar-fixed-top").addClass("top-nav-collapse");
} else {
$(".navbar-fixed-top").removeClass("top-nav-collapse");
}
});
*/
//jQuery for page scrolling feature - requires jQuery Easing plugin
$(document).on('click', '.page-scroll', function(e) {
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 2500, 'easeInOutExpo');
e.preventDefault();
});
}
},1);
};
</script>

When Using Critical CSS, Jquery function does is not running on load

I'm trying to optimise my website (http://www.mazion.co.uk).
As such, I tried to create critical CSS for the site using penthouse. (See Critical CSS used here - this was generated by the main developer of penthouse for me).
However, when using critical CSS, one of the subpages on my website does not load properly. BUT, when I fully inline the CSS (or don't do anything to optimise CSS), this sub-page loads correctly.
On this sub-page - http://www.mazion.co.uk/courses, there are a number of boxes that are resized using a JS function (see below) that is run on.ready and on.resize (i.e. when resizing the screen) which ensures that all boxes are of the same size.
When using critical CSS, the resizing function works on.resize but not on.ready. On the other hand, with inline CSS, the resizing function works as expected on.resize and on on.ready...
Thus, I was wondering if someone could help me in identifying the problem. I have tried to inline the styles for the boxes directly into the HTML, but I was unsuccessful...
You can see this problem by going to http://www.mazion.co.uk/courses/ and having a look at the boxes. If you then resize your browser, all the boxes will resize themselves so that they are all the same height... This resizing that make all the boxes the same height should actually happen automatically when the page loads....
Js Function (Not Extremely important to question, but helps in setting the scene)
jQuery(document).ready(function($){
$(window).resize(function() {
resizeCourseBoxes()
resizeTopBespokeCoursesBoxes()
resizeMidBespokeCoursesBoxes()
}).resize(); // Trigger resize handlers.
});
// Ensure that all the courses boxes are the same height (this ensures that the rows are of the same size...)
function resizeCourseBoxes() {
jQuery(function($) {
courseHeader = $('.course_header')
maxTextHeight = Math.max.apply(
Math, courseHeader.map(function() {
return $(this).height()
}).get())
for (var i = 0; i < courseHeader.length; i++) {
currentHeight = courseHeader[i].offsetHeight
new_padding = Number(maxTextHeight) - currentHeight + 10
courseHeader[i].style.marginBottom = new_padding + 'px'
};
})
}
// Ensure that all mid section (prices section) of the bespoke section is the same
function resizeTopBespokeCoursesBoxes() {
jQuery(function($) {
CoursePriceSection = $('.green_bx_top')
maxTextHeight = Math.max.apply(
Math, CoursePriceSection.map(function() {
return $(this).height()
}).get())
for (var i = 0; i < CoursePriceSection.length; i++) {
currentHeight = CoursePriceSection[i].offsetHeight
new_padding = Number(maxTextHeight) - currentHeight + 10
CoursePriceSection[i].style.marginBottom = new_padding + 'px'
};
})
}
// Ensure that all mid section (prices section) of the bespoke section is the same
function resizeMidBespokeCoursesBoxes() {
jQuery(function($) {
CoursePriceSection = $('.green_bx_mid')
maxTextHeight = Math.max.apply(
Math, CoursePriceSection.map(function() {
return $(this).height()
}).get())
for (var i = 0; i < CoursePriceSection.length; i++) {
currentHeight = CoursePriceSection[i].offsetHeight
new_padding = Number(maxTextHeight) - currentHeight
CoursePriceSection[i].style.marginBottom = new_padding + 'px'
};
})
}
The answer to my problem was simple:
Critical CSS is specific for each HTML page. Thus critical CSS for each individual page should be calculated separately...
(I was using the same critical CSS for all my subpages...).

Run a function inside ajax success call back

i have a snippet i created which checks all of the images inside a div and adds a class dependant on their size.
I have this currently on document ready and i works perfectly fine when the page is loaded.
However, im making a CMS where you can edit text on the page itself and then it updates via ajax.
The call response normally looks like:
success: function (response) {
if (response.databaseSuccess) {
$("#container #" +response.postid).load("#container #" +response.postContentID);
$targetForm.find(".saveupdatebutton").qtip("hide");
}
}
After this, the images inside the div that is loaded via the .load() function are not resized.
I have tried putting the code i use in that success response but no luck.
How should i be calling the code after the response?
Heres the code:
$(document).ready(function () {
// check each image in the .blogtest divs for their width. If its less than X make it full size, if not its poor and keep it normal
var box = $(".blogtest");
box.find("img.buildimage").on('load', function () {
var img = $(this),
width = img.width();
if (width >= 650) {
img.addClass("buildimage-large");
} else if (width < 500 && width > 101) {
img.addClass("buildimage-small");
}
// if image is less than X, its most likely a smiley
else if (width < 100) {
img.addClass("buildimage-smiley");
}
}).filter(function () {
//if the image is already loaded manually trigger the event
return this.complete;
}).trigger('load');
});
Depending on which version of jQuery you are using, you might be able to just change .on to .live like this:
box.find("img.buildimage").live('load', function () {
If that does NOT work, then you can try below. Then you'd have to do it the "right" way below:
First externalize your function for the image resizing:
$(document).ready(function () {
// check each image in the .blogtest divs for their width. If its less than X make it full size, if not its poor and keep it normal
var box = $(".blogtest");
box.find("img.buildimage").on('load', imageOnload)
.filter(function () {
//if the image is already loaded manually trigger the event
return this.complete;
})
.trigger('load');
});
function imageOnload(evt){
var img = $(evt.currentTarget),
width = img.width();
if (width >= 650) {
img.addClass("buildimage-large");
} else if (width < 500 && width > 101) {
img.addClass("buildimage-small");
}
// if image is less than X, its most likely a smiley
else if (width < 100) {
img.addClass("buildimage-smiley");
}
}
Then, you can just add this statment in your success callback:
$("#container #" +response.postid).on("load", imageOnload);

Load script if screen wide enough AND if parent div is in view

I have a twitter feed I currently display on my website when the viewport is 1250px or wider. So when the screen is wide enough, it calls in some content (which calls the javaScript file for the twitter feed.
My current code is this...
function checkSize(){
if ($(window).width() > 1250) {
$(".tweet").load("/ajax/");
}
}
checkSize();
$(window).resize(function() {
checkSize();
});
Now this works fine, however as the twitter script is near the bottom of the page, how can I only load the script when the div appears in user view?
I have tried something like this however it does not work
function checkSize(){
if ($(window).width() > 1250 && $(".tweet").is(':visible')) {
$(".tweet").load("/ajax/");
}
}
So to confirm, I want to only call in this content when the screen width is 1250px or wider AND when the user is at the bottom of the page so the parent div is visible (.tweet).
Any help would be appreciated.
I have added a codepen to test with here http://codepen.io/anon/pen/ezksD
This will determine if the user has scrolled down far enough for it to be visible.
function checkSize(){
if ($(window).width() > 1250 && $(".tweet").offset().top < $(window).scrollTop()) {
$(".tweet").load("/ajax/");
}
}
I think you'll have to find out how far the user has scrolled to be able to identity if the div is visible.
So what you could do is (wrote this from mobile and didn't check your code for syntax errors):
var loaded = false;
var proximity = 0;
if (loaded == false){
$(window).scroll(function () {
var scrollBottom = $(".tweet").offset().top - $(window).scrollTop();
var windowWidth = $(window).width();
if (scrollBottom <= proximity && windowWidth > 1250 && loaded == false)
{
$(".tweet").load("/ajax/");
loaded = true;
}
});
}
Hope that helps you.

Categories