Strange Height Matching Behavior in jQuery - javascript

I have a design which uses side-by-side divs that need to be height matched. This works perfectly well on page load, but on window resize, things tend to get all out of whack. The elements that are getting their heights changed are becoming larger or smaller than the heights of their target elements - sometimes by very large margins.
var specials = $('#specials');
var specialsPicture = $('#specials_contain .picture');
This is a function that gets called on page load and on the window resize event:
function matchAll() {
match(specialsPicture, specials, {min: 768, max: null});
}
Here's the actual matching function:
function match(elem, target, range) {
// if no max
if (range.max == null) {
// if in range
if (window.innerWidth >= range.min) {
// resize element to target height
elem.outerHeight( target.outerHeight() );
}
// if there is a max
} else {
// if in range
if (window.innerWidth >= range.min && window.innerWidth <= range.max) {
// resize
elem.outerHeight( target.outerHeight() );
}
}
}
Here is a screenshot of what happens:
It seems like such a simple piece of code, but I can't seem to figure out what might be happening. Thanks for the help.

Related

How do I check if an element is higher than itself?

I'm trying to make a collapsible submenu that, when there isn't enough space to fit all items, will throw overflowing items into a Bootstrap-style dropdown menu.
I'm doing this by checking if the submenu is greater than a certain height. If it's higher than this set height, it's considered overflowing and thus need to run it's function. However, the project I'm working on can't really have set heights on elements. These might change over time, and it will be a maintenance nightmare to go through all the code if something changes.
So how do I check if an element's height is higher than its own (I guess 'initial') height?
Setting if(menuHeight >= menuHeight) will cause a Maximum call stack size exceeded-error and crash the tab in Chrome.
Example:
var CollapseMenu = {
init: function(parent) {
var menu = parent;
var menuHeight = menu.height(); // Using jQuery here; vanilla JS could also work
if(menuHeight >= 64) // This is the set height I want to avoid
// ...
} else {
// ...
}
}
}
$(function() {
var submenu = $('.submenu');
if(submenu.length) {
CollapseMenu.init($('.submenu ul'));
}
$(window).resize(function() {
if(submenu.length) {
CollapseMenu.init($('.submenu ul'));
}
});
});

$(window).resize not firing function properly on height/width condition

I have a fixed-positioned full-screen image gallery. The container div height is set via jQuery, and the next div (#page) has a margin-top equal to window.height.
Here is this code:
var windowH = $(window).height();
var windowW = $(window).width();
function marginTop() {
var currentH = $(window).height();
$("#page").css("margin-top", currentH +'px');
$("#image-gallery").css("height", currentH +'px');
console.log('mTop fired!');
};
$(window).resize(function() {
var newH = $(window).height(); // Records new windows height after resize
var newW = $(window).width();
var maxH = windowH + 90; // Sets a positive delta of some px
var maxW = windowW + 60;
var minH = windowH - 90; // Sets a negative delta of some px
var minW = windowW - 60;
if(newH > maxH) { // If the height difference is more than 50px, then set new marginTop for #page
marginTop();
console.log('fire for bigger height');
} else if(newH < minH) {
marginTop();
console.log('fire for smaller height');
} else if(newW > maxW) {
marginTop();
console.log('fire for bigger width');
} else if(newW < minW ) {
marginTop();
console.log('fire for smaller width');
}
});
I've split the conditions in several else if statement because it didn't work fine, and I had to check out when it was working, when not.
The various if...elseif...elseif... solve a problem on mobile browsers: without that delta, the #image-gallery div would change dimension when the address bar appears or disappears, resulting in stuttering adjustments of the div's height. Moreover, i did not want to redraw the whole thing for small changes in viewport on desktop too.
However it has some problem, as it doesn't work correctly. In particular:
marginTop() is fired only for window.resize with smaller height (checked from console.log)
on desktop, if the window is resized through the top-right-corner button, it doesn't fire at all.
removing all the if-else-if conditions, it works fine on desktop in any situation (but the address-bar is still a problem on mobile)
Can't figure it out, the code seems fine to me, but not to browsers. Where's the catch?
Tested on Firefox and Chrome latest
There's a host of small problems here. Your if statement, as is, will never reach the width compares. First of all, with the width being in a if else with the height, then height is always evaluated first and width is never hit if height is adjusted.
Next, your "current height|width" as seen at var windowH = $(window).height(); is never reset. This means, if the user show up with a viewport (say browser is minimized) of 200:150, then height:width will always be measured based on 200:150. This would make for a very different experience from someone using a much larger viewport.
Another issue, often found with window re-sizing, is the multiple amount of times your code will fire. This can cause major issue with overlapping commands, thus causing double feedback.
Below is how I would handle this and a suggested rebuild.
/* simple method to get the current window size as an object where h=height && w=width */
function getWindowSize() {
return { h: $(window).height(), w: $(window).width() };
}
function doWork(typ, msg) {
// report msg of change to console
console.log(typ == 'h' ? 'HEIGHT:\t' : 'WIDTH:\t', msg);
// we really only need fire your method if height has changed
if (typ == 'h') marginTop();
// a change was made, now to reset
window.sizeCheck = getWindowSize();
}
// your original method
// brokered off so it can be used independently
function marginTop() {
var currentH = $(window).height();
console.log('currentH', currentH)
$("#page").css("margin-top", currentH +'px');
$("#image-gallery, #page").height(currentH);
console.log('mTop fired!');
}
/* action area for window resize event */
function windowResize() {
// made my variables short and sweet,
// sch=sizeCheck, scu=sizeCurrent
var sch = window.sizeCheck, // get previously set size
scu = getWindowSize(),
maxH = sch.h + 90,
minH = sch.h - 90,
maxW = sch.w + 60,
minW = sch.w - 60;
if (scu.h > maxH) doWork('h', 'View Got <b>Taller</b>');
else if (scu.h < minH) doWork('h', 'View Got <i>shorteR</i>');
// for what you want, the following isn't even really nec
// but i'll leave it in so you can see the work
if (scu.w > maxW) doWork('w', 'View Got <b>Wider</b>');
else if (scu.w < minW) doWork('w', 'View Got <i>thinneR</i>');
}
$(function() {
// ezier to maintain one global variable than to scope
// shot 2 which could easily be overriden in a latter method,
// by simple confusion
window.sizeCheck = getWindowSize();
// call of event to establish correct margin for the page div
marginTop()
$(window).resize(function(e) {
// this will clear our timer everytime resize is called
if (this.tmrResize) clearTimeout(this.tmrResize);
// resize is called multiple times per second,
// this helps to seperate the call,
// and ensure a little time gap (1/4 second here)
this.tmrResize = setTimeout(windowResize, 250);
});
})
html, body { margin: 0; padding: 0; }
#image-gallery {
background: blue;
color: white;
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#page { background: white; color: red; height: 400px; position: relative; z-index: 1; }
p { padding: 3em; text-align: center; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="image-gallery">
<p>
image Gallery
</p>
</div>
<div id="page">
<p>
next page
</p>
</div>
Someone passed by and then voted -1 to my question. I'd just like to know who's the braveheart that judges others without even posting a simple comment. This behaviour should be forbidden, we're not on 9gag neither 4chan.

JS CSS line clamp reset (TextOverflowClamp.js)

I'm using TextOverflowClamp.js to try and line clamp some text. It works while decreasing window width, but does not reset after increasing window width. Can someone help with resetting the line clamp after the clamp is triggered and window width becomes greater than set conditional size?
Codepen
All the code is in the Codepen, but my resize and load functions are here:
var winWidth;
$(window).resize(function () {
winWidth = $(window).width();
if (winWidth <= 991) {
loadClamp();
}
else {
// reset line clamp code here
}
}).resize();
function loadClamp() {
$(window).on('resize', function() {
// TextOverflowClamp.js
clamp(document.getElementById('js-toclamp1'), 1);
});
}
I couldn't seem to find a proper site for TextOverflowClamp.js. However, reading through the code itself, it seems passing 0 as the second parameter should remove the truncation (It is unclear if this is intentional but it seems to work). However, if there were any inner elements initially, those are lost and were not retained. In the case of your example, it is just text, so it should be fine:
var winWidth;
$(window).resize(function () {
winWidth = $(window).width();
if (winWidth <= 991) {
loadClamp(1);
}
else {
// back to normal
loadClamp(0);
}
}).resize();
function loadClamp(lines) {
clamp(document.getElementById('js-toclamp1'), lines);
}
Some additional notes on your code. You were adding an additional resize handler every time you called loadClamp and there was really no reason for this. I removed that.
Additionally, it is important that you place the TextOverflowClamp code before your own code.
http://jsfiddle.net/w9nkad0u/

check image width from its source and not from its size on the page - javascript

i have user submitted content on my website that contains image tags.
I have used this:
<script type="text/javascript">
$(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
function resize() {
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');
}
resize();
});
</script>
Which assigns a different class to each image depending on its size. This works fine, however if the user is on a ipad / small screen size and the .blogtest div is less than the defined size, it always get put as a small image.
What i wanted to do was the check the image width from its source so that no matter what the screen size, i can always assign the best class.
Thanks. Craig.

jQuery function on window events (load and resize)

I'm not sure how to use the order of the window events load and resize on jQuery to make it work when resizing. The first function is used to get the total width except the scrollbar width, because the CSS is using the device width, but the JS is using the document width.
The second function adds a style when the total screen width is between 768px and 1024px, and it should work when I load the page at any screen, after resizing, etc. I'm doing a lot of tests and I think the problem is about the window events order.
For being more specific about the problems, it doesn't remove the style when I load the page at 900px and I expand it to > 1024px! Or by the contrary, it doesn't add the style when I load the page at 1300px and I shorten the width to 900px.
I think it's 'cause of the load and resize events order, but I'm not totally sure. Or maybe I'm not doing the correct declaration of the variable into the resize.
The code:
function viewport() {
var e = window, a = 'inner';
if (!('innerWidth' in window )) {
a = 'client';
e = document.documentElement || document.body;
}
return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
$(document).ready(function(){
var vpwidth=$(window).width();
$(window).on('resize', function(){
var changeWidth = (($('.main-content .wrap').width() * 96.3)/100) - 312;
if(vpwidth >= 768 && vpwidth <= 1024) {
$('.contentleft, .contentright').css('width', changeWidth + 'px');
} else {
$('.contentleft, .contentright').removeAttr('style');
}
}).resize();
});
I believe the issue is that you're not re-calculating the vpwidth on resize, So the value you got when the page was loaded will be used every time window is resized.
try
$(document).ready(function(){
$(window).on('resize', function(){
var vpwidth=$(window).width(); // get the new value after resize
var changeWidth = (($('.main-content .wrap').width() * 96.3)/100) - 312;
if(vpwidth >= 768 && vpwidth <= 1024) {
$('.contentleft, .contentright').css('width', changeWidth + 'px');
} else {
$('.contentleft, .contentright').removeAttr('style');
}
}).resize();
});
The issue is because you are not recalculating the width (vpwidth) on resize function.
It is initialized and set on page load itself and hence doesn't change when the window is resized causing the style to not be added or removed.
You need to re-assign the value to the variable from within the resize function.
$(window).on('resize', function(){
var vpwidth=$(window).width();
}
Demo Fiddle

Categories

Resources