Javascript function run self on resize - javascript

I have a function, that I run on trigger through an element like $('.element').tileHeightInit();.
The function needs to run on window.load and window.resize. I guess I could define another function inside and run it there, but I figured there was a way to use this to run itself or something.
My function:
// master function for resizing tile elements
$.fn.tileHeightInit = function (
args = {
'breakPoint' : breakPoint,
'container' : container,
'squared' : squared,
'blockMargin' : blockMargin,
})
{
var breakPoint = args['breakPoint'],
container = args['container'],
squared = args['squared'],
blockMargin = args['blockMargin'];
var gridElements = $(this);
if (typeof(breakPoint)==='undefined') breakPoint = 767;
if (typeof(container)==='undefined') container = 'body';
if (typeof(squared)==='undefined') squared = true;
if (typeof(blockMargin)==='undefined') blockMargin = 30;
// return false if no elements found;
if($(container).find(gridElements).length < 1){
return false;
}
// run if window is larger than breakpoint
if($(window).width() >= breakPoint){
$(container).each(function(){
// height reset. Allows tiles to become smaller on risizing.
$(this).find(gridElements).each(function(){
$(this).height('auto');
})
// Get an array of all element heights
var elementHeights = $(this).find(gridElements).map(function() {
// block height datafield
var dataHeight = $(this).data('block-height');
// block widht datafield
var dataWidth = $(this).data('block-width');
// if squared is enabled
if(squared === true){
// if block is wider than tall, return width as height parameter for quadratic tiles
if($(this).height() < $(this).outerWidth() && dataWidth == 1){
// return height divided by data-height
return $(this).outerWidth();
} else{
// return width, since tile is wider than it's tall
return $(this).height() / dataHeight;
}
} else{
// return base height divided by block size;
return $(this).height() / dataHeight;
}
}).get();
// Math.max takes a variable number of arguments
// `apply` is equivalent to passing each height as an argument
var maxHeight = Math.max.apply(null, elementHeights);
// Set each height to the max height
$(this).find(gridElements).each(function(){
// variable for data-height attribute
var dataHeight = $(this).data('block-height');
// the missing margin the block would have had if split into more
var marginDiff = (dataHeight - 1) * blockMargin;
// set height to highest tile * data-height attribute + the margin difference between current block and surrounding blocks
$(this).height((maxHeight * dataHeight) + marginDiff);
});
})
} else{
// if smaller than breakpoint (colons collapsed)
$(container).find(gridElements).each(function(){
// reset height
$(this).height('auto');
})
}
} // END tileHeightInit();
$(window).resize(function(){
$('li').tileHeightInit({
'breakPoint': 500,
});
})
Basically I will be running this function on multiple elements, making writing them all into resize, load and possible more events seem inefficient.

Related

How can I make it so this script executes only above a certain screen size?

I'm using this script which I purchased from some website in German, so I can't understand the instructions. Basically, I want to make it so this is only triggered on screens above 768 pixels. I've tried a few different things and can't seem to get it to work. I'm not very well versed in Javascript. If someone could show me how to do this, I would be very grateful.
$(document).ready(function() {
//Build Bubble Machines with the Bubble Engine ------------------------
var SoapBubbleMachineNumber1 = $('fn').BubbleEngine({
particleSizeMin: 0,
particleSizeMax: 60,
particleSourceX: 0,
particleSourceY: 500,
particleAnimationDuration: 5000,
particleDirection: 'right',
particleAnimationDuration: 6000,
particleAnimationVariance: 2000,
particleScatteringX: 500,
particleScatteringY: 300,
gravity: -100
});
//Start Bubble Machine 1 ---------------------------------------------
SoapBubbleMachineNumber1.addBubbles(50);
});
var w = window,
d = document,
e = d.documentElement,
g = d.getElementsByTagName('body')[0],
x = w.innerWidth || e.clientWidth || g.clientWidth;
if(x > 768){
//your code here.
}
The first part is a pretty robust function to find the window width.
What you would then do is wrap your code shown in a function and call the function within the //your code here part
first google translator is your friend ;) If nothing works ask a german like me ;)
Anyhow :
function executeme(minWidth,minHeight){
var width = window.innerWidth|| document.documentElement.clientWidth||
Document.body.clientWidth;
var height = window.innerHeight || document.documentElement.clientHeight ||
document.body.clientHeight;
if (width < minWidth){return false;}
if (height < minHeight){return false;}
return true;
}
this will work on the browser window
If you want to know how much space is left in a div for example
function getGeometry(id){
try{
var element=document.getElementById()
} catch (ex){
return false;
}
var rect = element.getBoundingClientRect();
// uncomment to see the whole show :)
// console.log(rect);
return rect;
}
function runOnElementGeometry(id,minWidth,minHeight){
try{
var element=document.getElementById()
} catch (ex){
return false;
}
var rect = element.getBoundingClientRect();
if (rect.width < minWidth){return false;}
if (rect.height < minHeight){return false;}
return true;
}
if you need also the position of the element on the page you need to add the scroll positions (not needed for the width and height)
var x = window.scrollX
var y = window.scrollY
Now you can check whats going on and either start your bubbeles or even not :)

close popify modal and maintain scroll position in page

My close button function (via below main plugin file) refreshes to the top of page; I need to maintain position in long vertical scroll page, when clicking close button to exit popup.
HTML for button:
X
Main popify plugin JS:
// JavaScript Document
/** A modal pop-up.
Basic usage.
--------------------------------------------------------------------
HTML elemets that the plugin will create on document ready.
<!--
An overlay that will act as a background for the pop-ups.
Only one will be added to the DOM.
-->
<div id="flyPopifyOverlay" class="flyPopifyHide"><!-- Empty. --></div>
<!--
A wrapper element for each pop-up's content.
-->
<div class="flyPopifyOverlayContent" class="flyPopifyHide">
</div>
--------------------------------------------------------------------
The following options can be pased to the plugin:
Option name: default value
opacity: 1
The popup's background opacity.
minY: 0
The highest the pop-up can follow the scroll vertically
relative to the document.
maxY: $(document).height() - popup.height()
The lowest the pop-up can follow the scroll vertically
relative to the document.
--------------------------------------------------------------------
The pop-up's wrapper element ('.flyPopifyOverlayContent') will respond
to the following events:
fly-popify-show:
Displays the pop-up.
fly-popify-hide:
Hides the pop-up.
There are 2 (two) helper plugin functions: popifyOpen and popifyClose.
They, respectivley open and close the pop-ups they're invoked on.
Note that these helper functions can be called on the .flyPopifyOverlayContent
elements themselves or any descendant elements.
<code>
// Popify some content.
$('#content').popify();
// Will open the pop-up in which the a elements reside.
$('#content .comeClass a').popifyOpen();
// Same as the above.
$('#content').popifyClose();
// Will open all pop-ups.
$('.flyPopifyOverlayContent').popifyOpen();
// No effect.
$('body').popifyOpen();
</code>
*/
var jqPopify = false;
if ('undefined' != typeof jqFly) {
jqPopify = jqFly;
} else if ('undefined' != typeof jQuery) {
jqPopify = jQuery;
}
(function($){
// Default options.
var defaultSettings = {
// The popup's background opacity.
opacity: 0,
// The highest the pop-up can follow the scroll vertically.
minY: 0,
// The lowest the pop-up can follow the scroll vertically.
maxY: null // Note that this is just a temp. Will get calculcated for each individual pop-up.
};
var inlineStyles = {
overlay: {
display: 'none',
position: 'absolute',
top: '0',
left: '0',
opacity: '0.50',
background: '#000',
zIndex: '-100'
},
overlayContent: {
display: 'block',
opacity:0,
position: 'absolute',
top: '0',
left: '0',
zIndex: '-100'
}
};
function showLightbox(e) {
if (!$('#flyPopifyOverlay').hasClass('flyPopifyHide')) {
return;
}
$('#flyPopifyOverlay')
.removeClass('flyPopifyHide')
.stop(true)
.clearQueue()
.show()
//.animate({ opacity: 0.53 });
$(this)
.removeClass('flyPopifyHide')
.stop(true)
.clearQueue()
.show();
$(window).scroll();
onWindowResize();
};
function hideLightbox(e) {
var overlayContent = $(this);
$(this)
.addClass('flyPopifyHide')
.stop(true)
.clearQueue()
.animate({ /*opacity: 0 */}, function() {
$(overlayContent).hide();
});
$('#flyPopifyOverlay')
.addClass('flyPopifyHide')
.stop(true)
.clearQueue()
.animate({ /*opacity: 0*/ }, function() {
$('#flyPopifyOverlay').hide();
});
};
function onWindowResize(e) {
$('#flyPopifyOverlay')
// Pretty simple. What happens when overlay needs to be offseted?
// Let's say it starts from 100th pixel to allow for navigation menu
// interaction?
.width($(document).width())
.height($(document).height());
};
/**
* onWindowScrollResize()
*
* Called when the viewport changes, for both positon (relative to [0,0])
* and dimensions (width and height).
*/
function onWindowScrollResize(e) {
// There shouldn't be more then 1 (one) pop-up opened at a time in general,
// so don't take into account the posibility of more the 1 opened.
popup = $('.flyPopifyOverlayContent').not('.flyPopifyHide').first();
if (!popup.size()) {
return;
}
var toX = 0;
var toY = 0;
// Make sure the object is copied, otherwise we're modifing
// the element's settings variable.
var settings = popup.data('settings');//$.extend({}, popup.data('settings'));
// Make sure used settings are correct.
if (!settings.maxY) {
settings.maxY = $(document).height() - $(popup).height();
}
if (!settings.maxX) {
settings.maxX = $(document).width() - $(popup).width();
}
// Code repeats. It's simply lines.
// TODO: Come up with a generic center(k1, k2, v1, v2, maxK1, maxK2).
// k1 represents the line's left most point and k2 right most point.
// v1 and v2 are the viewport's points (which is a line as well).
// maxK1 and maxK2 are the bounds.
// Vertical and horizontal alignemnt of the pop up is identical
// due to both axis being the same - can be represented as
// lines on a flat plane.
// ************ Process horizontal. ************
// Get the center X relative to the window's width.
if (popup.width() < $(document).width()) {
var x = parseInt($(window).width()/2);
x -= parseInt(popup.width()/2);
toX = $(window).scrollLeft() + x;
if (popup.width() > $(window).width()) {
var vpLeftX = $(window).scrollLeft();
var vpRightX = vpLeftX + $(window).width();
var pLeftX = parseInt(popup.css('left'));
var pRightX = pLeftX + popup.width();
if (vpLeftX < pLeftX) {
toX = $(window).scrollLeft();
} else if (vpRightX > pRightX) {
toX = vpRightX - popup.width();
} else {
toX = pLeftX;
}
}
// Upper bound.
if (settings.minX > toX) {
toX = settings.minX;
}
// Lower bound.
if (settings.maxX <= toX) {
//toX = $(document).height() - popup.height() - 1;
toX = settings.maxX - 1;
}
}
// ************ END process horizontal. ************
// ************ Process vertical. ************
// If the height of the popup is less then the document,
// only then it will be centered.
if (popup.height() < $(document).height()) {
// Get the center Y relative to the viewport's height.
var y = parseInt($(window).height()/2);
y -= parseInt(popup.height()/2);
toY = $(window).scrollTop() + y;
if (popup.height() > $(window).height()) {
var vpTopY = $(window).scrollTop();
var vpBottomY = vpTopY + $(window).height();
var pTopY = parseInt(popup.css('top'));
var pBottomY = pTopY + popup.height();
if (vpTopY < pTopY) {
toY = $(window).scrollTop();
} else if (vpBottomY > pBottomY) {
toY = vpBottomY - popup.height();
} else {
toY = pTopY;
}
}
// Upper bound.
if (settings.minY > toY) {
toY = settings.minY;
}
// Lower bound.
if (settings.maxY <= toY) {
//toY = $(document).height() - popup.height() - 1;
toY = settings.maxY - 1;
}
}
// ************ END process vertical. ************
popup
.stop(true)
.clearQueue()
.animate({ top: toY, left: toX, opacity: 1 }, 500);
};
$.fn.popifyOpen = function(options) {
var settings = $.extend(true,
// No settings for popifyOpen.
{},
// User supplied.
options
);
$(this).trigger('fly-popify-show');
$('#flyPopifyOverlay , .flyPopifyOverlayContent').css({'z-index':9998,opacity:1});
$('#flyPopifyOverlay ').css({opacity: 0.5});
return this;
};
$.fn.popifyClose = function(options) {
var settings = $.extend(true,
// No settings for popifyClse.
{},
// User supplied.
options
);
$(this).trigger('fly-popify-hide');
$('#flyPopifyOverlay , .flyPopifyOverlayContent, .closePopup').css({'z-index':-100,display:'none', opacity:0});
window.location.reload();
return this;
};
$.fn.popifyRefresh = function() {
onWindowScrollResize();
return this;
};
$.fn.popifyIsOpen = function() {
if (1 == $(this).parents('.flyPopifyOverlayContent:first').size()) {
return !$(this).parents('.flyPopifyOverlayContent:first').hasClass('flyPopifyHide');
};
return false;
}
;
$.fn.popify = function(options) {
// Merge (deep) user settings to defaults and produce
// the global settings for this invokation.
var settings = $.extend(true,
defaultSettings,
// User supplied.
options
);
this.each(function(i, content) {
var overlayContent = null;
// Copy global settings.
var tempSettings = $.extend({}, settings);
// Determine maximum Y.
if (tempSettings.maxY) {
tempSettings.maxY = tempSettings.maxY - $(content).height();
if (0 >= tempSettings.maxY ) {
tempSettings.maxY = 1;
}
}
// Wrap in jQuery object.
content = $(content);
// Save the settings.
content
.detach();
$('<div class="flyPopifyOverlayContent flyPopifyHide"></div>')
.appendTo('body')
.append(content);
// Figure out the parent overlay element, since it has not id just use parent().
overlayContent = $(content.parent());
// Set initial opacity to 0.
overlayContent
.data('settings', tempSettings)
.css(inlineStyles.overlayContent)
// Setup default hide/show events.
.bind('fly-popify-show', showLightbox)
.bind('fly-popify-hide', hideLightbox);
});
$(window).trigger('resize');
return this;
};
// These are the global actions and event handlers that have
// to be carried out / defined before the plugin is invoked.
$(document).ready(function(e){
// If not already added, add the global overlay element.
$('body').append('<div id="flyPopifyOverlay" class="flyPopifyHide"><!-- Empty. --></div>');
$('#flyPopifyOverlay')
.css(inlineStyles.overlay);
$('#flyPopifyOverlay').bind('click', function(e) {
$('.flyPopifyOverlayContent').not('.flyPopifyHide')
.trigger('fly-popify-hide');
window.location.reload(true);
});
$(window)
.bind('resize', onWindowResize)
.bind('resize scroll', onWindowScrollResize);
});
})(jqPopify);
Remove the window.location.reload line here:
$.fn.popifyClose = function(options) {
var settings = $.extend(true,
// No settings for popifyClse.
{},
// User supplied.
options
);
$(this).trigger('fly-popify-hide');
$('#flyPopifyOverlay , .flyPopifyOverlayContent, .closePopup').css({'z-index':-100,display:'none', opacity:0});
// REMOVE THIS LINE
// window.location.reload();
return this;
};
If you HAVE to reload the page when closing the popup, here are a couple subjects related to keeping the scroll position on reload:
Refresh Page and Keep Scroll Position
keep scroll position after location.reload()

making a function works on specific widths

I am trying to make this function works only when the screen size is above 1024px.
//Parallax background image
var velocity = 0.5;
function update(){
var pos = $(window).scrollTop();
$('.parallax').each(function() {
var $element = $(this);
var height = $element.height();
$(this).css('background-position', '40%' + Math.round((height - pos) * velocity) + 'px');
});
};$(window).bind('scroll', update); update();
Here is what I have tried to do:
//Parallax background image
var velocity = 0.5;
$(window).on("ready resize", function() {
if ($(window).width() < 770) {
function update(){
var pos = $(window).scrollTop();
$('.parallax').each(function() {
var $element = $(this);
var height = $element.height();
$(this).css('background-position', '40%' + Math.round((height - pos) * velocity) + 'px');
});
};});$(window).bind('scroll', update); update();
I really don't know what I am doing wrong...
You haven't stated what the problem you're coming across is. If it's "my code doesn't work", then perhaps you should check your syntax first. Your braces are messed up.
//Initialize velocity and empty update function
var velocity = 0.5;
var update = function () {};
//When window is ready (content loaded) OR resized, execute the following function
$(window).on("ready resize", function () {
if ($(window).width() >= 1024) { //Check if window width is 1024px wide or larger
update = function () { //Set update to run this function when executed.
var pos = $(window).scrollTop(); //Get scrollbar position https://api.jquery.com/scrollTop/
//For each element with 'parallax' class, execute the following function
$('.parallax').each(function () {
var $element = $(this); //Get the current parallax-classed element
var height = $element.height(); //Save the current height of this element
//Set the CSS of this parallax-classed element set the background position
$(this).css('background-position', '40% + ' + Math.round((height - pos) * velocity) + 'px');
});
};
} else { //Execute if screen width is < 1024px
update = function () {}; //Set update to do nothing
}
});
//When window is scrolled through, run the update function
$(window).bind('scroll', update);
//update();
Last line is unnecessary, as resize will handle function value, and scroll will handle the execution.
You were missing a + or - within the background-position setting.
So for example, if the result of your Math.round() was "30", then Javascript would interpret that line as $(this).css('background-position', '40%30px'); which obviously would cause issues. I'm sure you wanted it to say something like $(this).css('background-position', '40% + 30px');.

Rewrite function from getElementById to getElementsByClassName or getElementsByTagName

I'm using this code by RobG from this answer to fit text inside an dynamic width container by id. But ideally I would like to use it on several elements at the same time. How could I rewrite this to work with getElementsByClassName or getElementsByTagName?
<script>
function resize(el, factor) {
// Get element width
var width = el.offsetWidth;
// set default for factor
if (typeof factor == 'undefined') {
factor = 5;
}
// Set fontsize to new size
el.style.fontSize = (width / factor | 0) + 'px';
}
window.onload = function() {
function doResize() {resize(document.getElementById('fit'), 6);}
window.onresize = doResize;
doResize();
}
</script>
<div id="fit">Some text</div>
Get the elements and call the function in an iteration
function resize(el, factor) {
// Get element width
var width = el.offsetWidth;
// set default for factor
if (typeof factor == 'undefined') {
factor = 5;
}
// Set fontsize to new size
el.style.fontSize = (width / factor | 0) + 'px';
}
window.onload = function() {
function doResize() {
/* get a nodelist */
var elems = document.getElementsByClassName('myClass');
/* iterate over nodelist */
for (var i=elems.length; i--;) {
resize(elems[i], 6); // call function for each element
}
}
window.onresize = doResize;
doResize();
}
You're better off using querySelectorAll('.myClass') than getElementsByClassName. It's supported in IE8, where getElementsByClassName isn't.

How to detect if element has 'auto' height

Both window.getComputedStyle(element).height and element.clientHeight are returning the current height of the element in pixels, regardless of the value set in the CSS.
Is there any way to find out if the height was set to auto, or other units than pixels ?
One solution that #pvnarula suggests through the page he linked is to temporarily change the contents of the element, then compare heights.
A little bit hacky...
Please try:
document.getElementById("ele_id").style.height
Also check the following plugin:
http://gregpettit.ca/2012/jquery-check-if-element-has-auto-widthheight/
Update:
Based on other answers and lot of online research I came up with a mix of everything in a single function. Check out the jsfiddle here:
https://jsfiddle.net/oriadam/d01ap7r6/3/
// input a jQuery element
// return true for elements with auto height (90-100% is considered auto as well)
// return false for elements with fixed height
function is_height_auto($e) {
var e = $e[0],
// check fixed style:
chk = function(value) {
return /\d/.test(value) && !/^(100|9\d)\%/.test(value);
};
// start from the first, easiest, inline styles
if (chk(e.style.height)) {
// console.log('fixed for having style', e.style.height)
return false;
}
// start from the first, easiest, inline styles
var overflow = getComputedStyle(e)['overflow'];
if (overflow == 'scroll' || overflow == 'auto' || (e.tagName == 'BODY' && overflow == 'visible')) {
// console.log('auto for having overflow or is body', getComputedStyle(e)['overflow'], e.tagName);
return true;
}
// deprecated chrome way - check each rule that applies to the element
if (typeof getMatchedCSSRules == 'function') {
var i, MatchedCSSRules = getMatchedCSSRules(e) || [];
for (i = MatchedCSSRules.length; i; i--) {
if (MatchedCSSRules[i - 1].style.height) {
// console.log('found height at MatchedCSSRules[' + (i - 1) + ']: ', MatchedCSSRules[i - 1], ' All matches: ', MatchedCSSRules)
return !chk(MatchedCSSRules[i - 1].style.height);
}
}
}
// append something, see if height was changed, remove the something
var originalHeight = $e.height(),
$ghost = jQuery('<b style="display:block;height:1px;width:1px;padding:0;margin:0;">').appendTo($e),
newHeight = $e.height();
$ghost.remove(); // cleanup
// console.log('Using a ghost got ',newHeight > originalHeight,' originalHeight=' + originalHeight + ' newHeight=' + newHeight)
return newHeight > originalHeight;
} //is_height_auto()
** Ghost element method explained (Previous answer):**
Greg Pettit had a pretty good answer in his blog, here is the main idea:
What’s unique about having auto height? Well, the fact that it allows height to change dynamically, of course!
Clone the element
Put it in visibility:hidden and position:absolute
Remove it's content
See if height changed (it should be around 0
now).
Cleanup
var isAutoHeight = function(element) {
// make a staging area for all our work.
$('body').append('');
// assume false by default
var autoHeight = false;
// clone the div and move it; get its height
var clone = element.clone();
clone.appendTo('#stage');
var initialHeight = clone.height();
// destroy all the content and compare height
clone.html('');
var currentHeight = clone.height();
if (currentHeight < initialHeight) {
autoHeight = true;
}
// get that clone and its smelly duplicate ID out of the DOM!
clone.remove();
// do the same for the stage
$('#stage').remove();
return autoHeight;
};
Ran into a bug using the method of clone->heightCheck->remove innerHTML->heightCompare. Where it does not register a change in height, even if the element has 100%/auto height.
Instead, this method appears to work:
let autoHeight = false;
// Set up stage area with 100% height/width
const stage = document.createElement('div');
stage.setAttribute('style', "position: relative; height: 100%; width: 100%;");
// Add stage to body
document.body.appendChild(stage);
// Clone the element and append to stage
const clone = element.cloneNode(false);
stage.appendChild(clone);
// Get Initial Height
const initialHeight = clone.offsetHeight;
// Squish content
stage.setAttribute('style', "position: relative; height: 1px; width: 1px;");
// Get new height
const currentHeight = clone.offsetHeight;
// Get max height (if it exists)
const hasMaxHeight = getComputedStyle(clone)["maxHeight"];
// Compare
if (currentHeight < initialHeight && hasMaxHeight == 'none') {
// Has 100% or auto height, and no maxHeight
} else if (hasMaxHeight !== 'none') {
// Flexible, but has a maxHeight
} else {
// Constrained by height size
}
// Remove elements
stage.remove();
Starting by Oriadam answer I created following jQuery function:
/**
* Checks if the element has explicitly set height by CSS styles.
* E.g.:
*
* var $myElement = jQuery('.my-element');
* if ($myElement.hasExplicitHeight()) {
* //...
* }
*
* This function is needed as .height() or .css('height') return a value, even
* if no height property was explicitly set using CSS.
*
* #returns {Boolean}
*/
jQuery.fn.hasExplicitHeight = function() {
var $element = jQuery(this);
var $clone = $element.clone();
$clone.html('');
$clone.css('visibility', 'hidden');
$clone.css('position', 'absolute');
$clone.insertAfter($element);
var hasExplicitHeight = $element.css('height') === $clone.css('height');
$clone.remove();
return hasExplicitHeight;
};
It works fine under condition that it is called only after the document is ready:
jQuery(function() {
// this code is launched only after the document is ready
jQuery('.my-element').hasExplicitHeight();
});

Categories