A few months ago, a member posted a question in the CSS category looking for a way to adjust the horizontal spacing of his menu. I just wrote a beginner’s jQuery script that seems to do the trick, but it needs the help of an event listener (I think) that will detect when the width of the <ul> changes (user changes font size maybe).
Is it possible to write an event listener (I guess that’s what it would be called) that would detect a change in the width of the <ul> and trigger a script? If so, I’ll post some example code in need of the listener/handler thingy and go from there.
(function() {
window.addEventListener("resize", resizeThrottler, false);
var resizeTimeout;
function resizeThrottler() {
// ignore resize events as long as an actualResizeHandler execution is in the queue
if ( !resizeTimeout ) {
resizeTimeout = setTimeout(function() {
resizeTimeout = null;
actualResizeHandler();
// The actualResizeHandler will execute at a rate of 15fps
}, 66);
}
}
function actualResizeHandler() {
// handle the resize event
...
}
}());
I read the Mozilla list while searching for a solution and didn’t recognize anything that might work. Your example seems to effect the resizing of something but I can’t tell what triggers it. My need is to detect a change in the width of a container and trigger the script that I already wrote (which should work after the page is loaded). Detecting the change in width is what I don’t know how to do. With that, I’m well into my level of incompetence.
You could probably determine the width of the element, store it in a variable, and then set a timer to regularly check the width to see if it’s changed, and if so, do something. Seems a bit cumbersome, though.
I binged on Z Nation on Netflix this weekend. About half the quality of TWD but still pretty good. (6.5-7/10 imo) It’s more fun an lighthearted than TWD.
But it’s a SyFy Original and I’ve never seen one of those go more than 2 seasons before getting insane and extremely low quality.
I think this is perfect. I am so annoyed by hesitations in browsers that seeing “No polling of the DOM” is nothing short of over-the-top amazing!!! I’ll need to experiment with it for awhile to understand what I can do with it, but so far it rocks!
How do I code a line under the console.log that displays the width of “myList”?
How far back is this code compatible or is it? It looks cutting edge. What about cross-browser/device compatibility?
I’m not sure when I’ll be back but hopefully it will be with the sample menu and my few lines of jQuery code which I hope you will be in the mood to rewrite as real JS.
Looking at the conversation in this thread, I feel like I am off topic
I hooked that script to my little jQuery script and IT WORKS! :amazed:
Resizing the window width shows that the width of the <ul> (via the menu items) changes to keep the width of the <ul> within a 12px range overall (6px at each end) of the parent <div>. This resizing is expected to be short of smooth (slightly jumpy) because we only perform one quick math calculation to derive the menu width and then run one loop. More accuracy would be a little more complicated.
Resizing the font (which affects the width of the <ul>) is a lot jumpier. I would be very grateful if some kind person would translate my jQuery script into real JavaScript so we can find out if it makes a difference. Or maybe there are other techniques available to hide this jumpiness. However, even if the jumpiness cannot be hidden or abated, it shouldn’t be considered a real problem. Really. Who goes around dragging window widths and changing font sizes other than webbies?
Oh, swap the commented out lines in the jQuery with their most likely mate (the padd lines) and the width of the buttons becomes adaptable rather than the space between them (which becomes fixed).
The big downside? The menu items cannot wrap, so usefulness is limited to wider designs.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOM Elements! Y U No Resize Event?</title>
<style>
body {
font-size:100%;
padding:0;
}
div {
width:70%;
background-color:red;
border-radius:16px;
padding:0 25px;
margin:0 auto;
}
ul {
list-style:none;
display:table;
border-spacing:0 0;
word-spacing:-.3125em;
white-space:nowrap;
padding:0;
margin:0 auto;
}
li {
display:inline-block;
height:52px;
word-spacing:0;
text-align:center;
background-color:rgba(255,255,0 .4);
outline:1px solid lime;
}
li:before {
content:"";
display:inline-block;
height:100%;
vertical-align:middle;
}
a {
display:inline-block;
vertical-align:middle;
outline:1px solid blue;
background-color:pink;
padding:.125em 8px;
margin:0 .75em;
}
</style>
</head>
<body>
<div id="menuBox">
<ul id="myList">
<li class="buttonBox"><a href="#">Yo!</a></li>
<li class="buttonBox"><a href="#">Hi There!</a></li>
<li class="buttonBox"><a href="#">How About Today?</a></li>
<li class="buttonBox"><a href="#">OK!</a></li>
<li class="buttonBox"><a href="#">Another Day?</a></li>
<li class="buttonBox"><a href="#">No.</a></li>
</ul>
</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-latest.min.js"></script>
<script>
(function(){
var attachEvent = document.attachEvent;
var isIE = navigator.userAgent.match(/Trident/);
var requestFrame = (function(){
var raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame ||
function(fn){ return window.setTimeout(fn, 20); };
return function(fn){ return raf(fn); };
})();
var cancelFrame = (function(){
var cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame ||
window.clearTimeout;
return function(id){ return cancel(id); };
})();
function resizeListener(e){
var win = e.target || e.srcElement;
if (win.__resizeRAF__) cancelFrame(win.__resizeRAF__);
win.__resizeRAF__ = requestFrame(function(){
var trigger = win.__resizeTrigger__;
trigger.__resizeListeners__.forEach(function(fn){
fn.call(trigger, e);
});
});
}
function objectLoad(e){
this.contentDocument.defaultView.__resizeTrigger__ = this.__resizeElement__;
this.contentDocument.defaultView.addEventListener('resize', resizeListener);
}
window.addResizeListener = function(element, fn){
if (!element.__resizeListeners__) {
element.__resizeListeners__ = [];
if (attachEvent) {
element.__resizeTrigger__ = element;
element.attachEvent('onresize', resizeListener);
} else {
if (getComputedStyle(element).position == 'static') element.style.position = 'relative';
var obj = element.__resizeTrigger__ = document.createElement('object');
obj.setAttribute('style', 'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; pointer-events: none; z-index: -1;');
obj.__resizeElement__ = element;
obj.onload = objectLoad;
obj.type = 'text/html';
if (isIE) element.appendChild(obj);
obj.data = 'about:blank';
if (!isIE) element.appendChild(obj);
}
}
element.__resizeListeners__.push(fn);
};
window.removeResizeListener = function(element, fn){
element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);
if (!element.__resizeListeners__.length) {
if (attachEvent) element.detachEvent('onresize', resizeListener);
else {
element.__resizeTrigger__.contentDocument.defaultView.removeEventListener('resize', resizeListener);
element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__);
}
}
}
})();
function fitMenu() {
var buttons = $('.buttonBox a'); // # of button objects
var margins = parseInt($(buttons[1]).css('margin-right'));
// var padd = parseInt($(buttons[1]).css('padding-right'));
var menuBox = $('div').width();
var navWidth = $('#myList').width();
var drift = 2*$(buttons).length;
var diff = (menuBox - navWidth);
if (diff < 0 || diff >= drift) {
correction = Math.floor(diff/drift);
margins = margins + correction;
// padd = padd + correction;
for (i = 0; i < buttons.length; i++) {
$(buttons[i]).css('margin-left',margins);
$(buttons[i]).css('margin-right',margins);
// $(buttons[i]).css('padding-left',padd);
// $(buttons[i]).css('padding-right',padd);
};
};
};
var myElement = document.getElementById('myList'),
myResizeFn = function(){
fitMenu();
};
addResizeListener(myElement, myResizeFn);
window.onresize = fitMenu;
window.onload = fitMenu;
</script>
</body>
</html>