Shrink to fit a div vertically inside a window - javascript

I want a window that shrinks to fit the current window. This Fiddle is very close to what I want to achieve. To use it simply resize the output window vertically until the blue line gets cutoff. Then reverse the process. However, I want it to continue to work even if there is padding and/or other elements on the page.
<div id="output"></div>
<div id="sample" class="sampleClass">
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
</div>
window.addEventListener("resize", updateDimensions);
var originalHeight = document.getElementById('sample').offsetHeight;
var safeBuffer = 15;
function updateDimensions(){
var node = document.getElementById('sample');
var windowDimensions = {width: window.innerWidth, height: window.innerHeight};
var dimensions = node.getBoundingClientRect();
var nodeBottom = dimensions.bottom;
var nodeHeight = node.offsetHeight;
var nodeTop = dimensions.top;
var windowHeight = windowDimensions.height;
var windowIsCutOff = windowHeight <= nodeBottom;
var windowIsShowing = windowHeight >= nodeTop;
console.log('windowHeight: ' + windowHeight + ' safeBuffer: ' + safeBuffer);
console.log('nodeHeight: ' + nodeHeight + ' originalHeight: ' + originalHeight);
var nodeCanGrowBigger = (windowHeight - safeBuffer - 10) > nodeHeight && nodeHeight < originalHeight;
console.log('nodeCanGrowBigger: ' + nodeCanGrowBigger);
if(windowIsShowing && windowIsCutOff) {
console.log('do work');
shrinkWindow(nodeBottom, windowHeight, nodeHeight);
}
if(nodeCanGrowBigger){
growWindow(nodeBottom, windowHeight, nodeHeight);
}
}
function growWindow(nodeBottom, windowHeight, nodeHeight){
var node = document.getElementById('sample');
var originalHeight = nodeHeight;
var offset = nodeHeight - windowHeight;
var newHeight;
if(offset >= -safeBuffer && offset <= safeBuffer){
newHeight = originalHeight;
}
else if(offset >= 0){
newHeight = originalHeight + offset;
console.log('positive calculation originalHeight: ' + originalHeight + ' offset: ' + offset + ' for newHeight: ' + newHeight);
}else{
newHeight = originalHeight - offset;
console.log('negative', newHeight);
}
node.style.height = newHeight + 'px';
console.log('height attmpted changed to', newHeight);
console.log('height offset', node.offsetHeight);
console.log('height style', node.style.height);
}
function shrinkWindow(nodeBottom, windowHeight, nodeHeight) {
var node = document.getElementById('sample');
var originalHeight = nodeHeight;
//console.log('originalHeight', originalHeight);
//console.log('nodeBottom:' + nodeBottom + ' windowHeight: ' + windowHeight);
var offset = nodeHeight - windowHeight;
//console.log('offset', offset);
var newHeight;
if(offset >= -safeBuffer && offset <= safeBuffer){
newHeight = originalHeight - (safeBuffer + 1);
}
else if(offset >= 0){
newHeight = originalHeight - offset;
//console.log('positive calculation originalHeight: ' + originalHeight + ' offset: ' + offset + ' for newHeight: ' + newHeight);
}else{
newHeight = originalHeight + offset;
//console.log('negative', newHeight);
}
node.style.height = newHeight + 'px';
/*
console.log('height attmpted changed to', newHeight);
console.log('height offset', node.offsetHeight);
console.log('height style', node.style.height);
*/
}
.sampleClass {
padding: 0px;
height: 300px;
overflow-y: auto;
border: solid blue;
//margin: 10px 300px 10px 25px;
margin: 0px
position: 'relative'
}
This JavaScript solution I came up with feels overly complex. It doesn't solve for things like padding, or more content on the page either. Can I solve this problem with plain old CSS or a JS extension?
I know Kendo ui has this effect in their Modal windows (at least in the 5 year old version we use). I'm not open to using Kendo.

Difficult to say if this will work for your situation ... Look at the following touch-up. It could use more work, but I think it will point you in the direction I was heading:
function updateDimensions(){
var node = document.getElementById('sample');
var windowDimensions = {width: window.innerWidth, height: window.innerHeight};
var dimensions = node.getBoundingClientRect();
var nodeBottom = dimensions.bottom;
var nodeHeight = node.offsetHeight;
var nodeTop = dimensions.top;
var windowHeight = windowDimensions.height;
var windowIsCutOff = windowHeight <= nodeBottom;
var windowIsShowing = windowHeight >= nodeTop;
console.log('windowHeight: ' + windowHeight + ' safeBuffer: ' + safeBuffer);
console.log('nodeHeight: ' + nodeHeight + ' originalHeight: ' + originalHeight);
var nodeCanGrowBigger = (windowHeight - safeBuffer - 10) > nodeHeight && nodeHeight < originalHeight;
console.log('nodeCanGrowBigger: ' + nodeCanGrowBigger);
if ( (windowIsShowing && windowIsCutOff) || nodeCanGrowBigger ) {
growWindow(nodeTop, windowHeight, nodeHeight);
}
}
function growWindow(nodeTop, windowHeight, nodeHeight){
var node = document.getElementById('sample');
var offset = windowHeight - ( nodeTop + nodeHeight + safeBuffer );
var newHeight = nodeHeight + offset;
node.style.height = newHeight + 'px';
}
As you can see, I use nodeTop instead of nodeBottom for the calculation and I used the combination of nodeTop, nodeHeight and safeBuffer to indicate the bottom of the node, then used the difference of that with the window for the offset. This should work regardless of whether you're shrinking or expanding the window.

This is the version most like Kendo UI:
window.addEventListener("resize", updateDimensions);
var node = document.getElementById('sample');
var style = node.currentStyle || window.getComputedStyle(node);
var marginTop = style.marginTop.replace("px", "");
marginTop = parseInt(marginTop, 10);
var innerNode = document.getElementById('inner');
var innerNodeStyle = innerNode.currentStyle || window.getComputedStyle(innerNode);
var innerMarginTop = innerNodeStyle.marginTop.replace("px", "");
innerMarginTop = parseInt(innerMarginTop, 10);
var innerMarginBottom = innerNodeStyle.marginBottom.replace("px", "");
innerMarginBottom = parseInt(innerMarginBottom, 10);
var totalInnerMarginSize = innerMarginTop + innerMarginBottom;
var safeBuffer = 0;
//if(marginTop < 20){
safeBuffer = 20;
//}
var originalHeight = node.offsetHeight + marginTop + safeBuffer;
function updateDimensions(){
var windowDimensions = {width: window.innerWidth, height: window.innerHeight};
var dimensions = node.getBoundingClientRect();
//console.log('totalInnerMarginSize: ' + totalInnerMarginSize);
var cutoffPoint = marginTop + node.offsetHeight + safeBuffer + totalInnerMarginSize ;
var nodeTop = dimensions.top;
var innerNodeDimensions = innerNode.getBoundingClientRect();
var innerNodeTop = innerNodeDimensions.top;
var innerNodeHeight = innerNodeDimensions.height;
//console.log('innerNodeHeight: ' + innerNodeHeight);
var windowHeight = windowDimensions.height;
console.log('windowHeight: ' + windowHeight + ' cutoffPoint: ' + cutoffPoint);
var windowIsCutOff = windowHeight <= cutoffPoint;
//console.log('windowHeight: ' + windowHeight + ' nodeTop: ' + nodeTop);
var windowIsShowing = windowHeight > nodeTop;
var nodeCanGrowBigger = windowHeight > cutoffPoint && cutoffPoint < originalHeight;
//console.log('nodeCanGrowBigger: ' + nodeCanGrowBigger);
//console.log('windowHeight: ' + windowHeight + ' cutoffPoint: ' + cutoffPoint
//+ ' originalHeight: ' + originalHeight);
//console.log('windowIsShowing: ' + windowIsShowing + ' windowIsCutOff: ' + windowIsCutOff + ' nodeCanGrowBigger: ' + nodeCanGrowBigger);
if ( (windowIsShowing && windowIsCutOff) || nodeCanGrowBigger ) {
resizeWindow(innerNodeHeight, windowHeight, cutoffPoint);
}
}
function resizeWindow(innerHeight, windowHeight, cutoffPoint){
//console.log('innerHeight: ' + innerHeight + ' windowHeight: ' + windowHeight
//+ ' cutoffPoint: ' + cutoffPoint);
var newHeight = innerHeight - (cutoffPoint - windowHeight);
innerNode.style.height = newHeight + 'px';
}
<div id="output"></div>
<div id="sample" class="sampleClass">
<h1>
Header
</h1>
<div id="inner">
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
<div>hello</div>
</div>
<h1>
footer
</h1>
</div>
.sampleClass {
padding: 10px;
//height: 300px;
overflow-y: auto;
border: solid blue;
//margin: 10px 300px 10px 25px;
margin: 70px;
position: 'relative'
}
#inner{
position: 'relative';
overflow-y: auto;
border: solid red 1px;
}

Related

offset not changing after jQuery animation

http://plnkr.co/edit/c6OaitTTvLhltk7b3muf?p=preview
I'm working on a jQuery animation and need to have the animated divs retain their new offset after the animation ends.
The goal of the animation is to be able to click on one of the smaller circles at the bottom and it will swap places/size with the larger circle at the top.
function leadershipToShow(id) {
console.log('leadershipToShow (' + id + ')');
var x = $('.activeLeadership').offset().left;
var y = $('.activeLeadership').offset().top;
var h = $('.activeLeadership').height();
var w = $('.activeLeadership').width();
if($(id).hasClass('activeLeadership')){ console.log('already selected');return false; }
console.log('x ' + x + ', y ' + y);
console.log($(id).offset());
var xi = $(id).offset().left;
var yi = $(id).offset().top;
console.log('xi ' + xi + ', yi ' + yi);
var hi = $(id).height();
var wi = $(id).width();
var xOffset = Math.abs(x - xi);
var yOffset = Math.abs(y - yi);
console.log('xOffset ' + xOffset + ', yOffset ' + yOffset);
$(id).animate({
left: -xOffset + 15,
top: -yOffset,
height: h,
width: w
}, 500, 'linear', function() {console.log('Id Animation Complete');});
var selected = $('.activeLeadership');
console.log(selected.offset());
selected.animate({
left: xOffset + 15,
top: yOffset,
height: hi,
width: wi
}, 500, 'linear',function() {
console.log('selected Animation Complete');
console.log('new active ' + $('.activeLeadership').attr('id'));
console.log('new active position x ' + $('.activeLeadership').offset().left + ', y ' + $('.activeLeadership').offset().top);
console.log('previous active ' + selected.attr('id'));
console.log('previous active position x ' + selected.offset().left + ', y ' + selected.offset().top);}
);
$(id).addClass('activeLeadership');
selected.removeClass('activeLeadership');
}
I got some help with this and figured it out. The solution is that you have to take the offsets of the divs based on their first offset locations. After they've been animated, moving them again is always relative to their starting offset. So to make this work you have to store their starting offset locations in a global variable outside of the function. With an if statement you then associate the id of the div with the variable of the initial offset. Then it is just a matter of taking the difference between the div you want to animate's initial offset and the location you want to move it to.
updated plunker http://plnkr.co/edit/c6OaitTTvLhltk7b3muf?p=preview
var circle0 = { 'left': $('#circle0').offset().left, 'top': $('#circle0').offset().top };
var bigCircle = { 'height': $('.activeLeadership').height(), 'width': $('.activeLeadership').width() };
var circle1 = { 'left': $('#circle1').offset().left, 'top': $('#circle1').offset().top };
var circle2 = { 'left': $('#circle2').offset().left, 'top': $('#circle2').offset().top };
var circle3 = { 'left': $('#circle3').offset().left, 'top': $('#circle3').offset().top };
var circle4 = { 'left': $('#circle4').offset().left, 'top': $('#circle4').offset().top };
var otherCircles = { 'height': $('#circle1').height(), 'width': $('#circle1').width() };
var time = 400;
function leadershipToShow(id) {
var circleToMoveUp = $(id);
if(circleToMoveUp.hasClass('activeLeadership')){ return false; }
var originOfCircleToMoveUp;
if(id === '#circle0'){ originOfCircleToMoveUp = circle0; }
else if(id === '#circle1'){ originOfCircleToMoveUp = circle1; }
else if(id === '#circle2'){ originOfCircleToMoveUp = circle2; }
else if(id === '#circle3'){ originOfCircleToMoveUp = circle3; }
else if(id === '#circle4'){ originOfCircleToMoveUp = circle4; }
var xOffsetUp = circle0.left - originOfCircleToMoveUp.left;
var yOffsetUp = circle0.top - originOfCircleToMoveUp.top;
var circleToMoveDown = $('.activeLeadership');
var originOfCircleToMoveDown;
if(circleToMoveDown.attr('id') === 'circle0'){ originOfCircleToMoveDown = circle0; }
else if(circleToMoveDown.attr('id') === 'circle1'){ originOfCircleToMoveDown = circle1; }
else if(circleToMoveDown.attr('id') === 'circle2'){ originOfCircleToMoveDown = circle2; }
else if(circleToMoveDown.attr('id') === 'circle3'){ originOfCircleToMoveDown = circle3; }
else if(circleToMoveDown.attr('id') === 'circle4'){ originOfCircleToMoveDown = circle4; }
var xOffsetDown = circleToMoveUp.offset().left - originOfCircleToMoveDown.left;
var yOffsetDown = circleToMoveUp.offset().top - originOfCircleToMoveDown.top;
/* SMALL CIRCLE to BIG CIRCLE animation */
circleToMoveUp.animate({
left: xOffsetUp + 15,
top: yOffsetUp,
height: bigCircle.height,
width: bigCircle.width
}, time, 'linear');
/* BIG CIRCLE to SMALL CIRCLE animation */
circleToMoveDown.animate({
left: xOffsetDown + 15,
top: yOffsetDown,
height: otherCircles.height,
width: otherCircles.width
}, time, 'linear');
circleToMoveUp.addClass('activeLeadership');
circleToMoveDown.removeClass('activeLeadership');
}

Why do the colored balls keep on going down past the edge of the page

I have the following JavaScript; the intent is that circles will bounce on the screen, off all edges.
I went to a variable storing the window's height and width, because I thought failure to bounce off the bottom of the screen might because the node was progressively expanding, so my original check against jQuery(window).height() was pointless.
However, after having addressed this way of making a window bouncy on the edges, or tried to (it's at http://cats.stornge.com), I have not seen a ball bounce off one edge of the window, and if you watch your scrollbar, you can see that they are going well beyond the original bottom of the window as they fall.
var viewport_height = jQuery(window).height()
var viewport_width = jQuery(window).width();
var available_images = ['red.png', 'orange.png', 'yellow.png',
'green.png', 'blue.png', 'purple.png', 'brown.png', 'black.png',
'grey.png']; //, 'white.png'];
var bodies = [];
for(var i = 0; i < 3; ++i)
{
body = {id: i, velocity_y : Math.random(),
velocity_x: Math.random() * 10 - 5,
position_x: Math.random() * viewport_width - 100,
position_y: Math.random() * viewport_height - 100};
document.write('<img id="' + i + '" src="' + available_images[Math.floor(Math.random() * available_images.length)] + '" style="z-index: ' + i + '" />');
bodies[bodies.length] = body;
}
function iterate()
{
for(var index = 0; index < bodies.length; ++index)
{
bodies[index].velocity_y += .1;
bodies[index].position_x += bodies[index].velocity_x;
bodies[index].position_y += bodies[index].velocity_y;
var position = jQuery('#' + index).position();
if (position.top + 100 > viewport_height)
{
bodies[index].velocity_y = - bodies[index].velocity_y;
bodies[index].position_y = viewport_height - 100;
}
if (position.top < 0)
{
bodies[index].velocity_y = - bodies[index].velocity_y;
bodies[index].position_y = 0;
}
if (position.left > viewport_width - 100)
{
bodies[index].velocity_x = -bodies[index].velocity_x;
bodies[index].position_x = viewport_width - 100;
}
jQuery('#' + index).css('margin-top',
bodies[index].position_y + 'px');
jQuery('#' + index).css('margin-left',
bodies[index].position_x + 'px');
}
}
setInterval(iterate, 30);
I'd love to see how to make this code set bouncy walls at the boundaries of the original viewport.
When changing the margin-top and margin-left, the width and height of the window started to change as well.
I got this to work by changing the css() calls setting margin-top and margin-left to offset(). I also added another if statement to make sure the balls bounced off the left-hand side as well:
var viewport_height = jQuery(window).height()
var viewport_width = jQuery(window).width();
var available_images = ['red.png', 'orange.png', 'yellow.png',
'green.png', 'blue.png', 'purple.png', 'brown.png', 'black.png',
'grey.png']; //, 'white.png'];
var bodies = [];
for(var i = 0; i < 3; ++i)
{
body = {id: i, velocity_y : Math.random(),
velocity_x: Math.random() * 10 - 5,
position_x: Math.random() * viewport_width - 100,
position_y: Math.random() * viewport_height - 100};
document.write('<img id="' + i + '" src="http://cats.stornge.com/' + available_images[Math.floor(Math.random() * available_images.length)] + '" style="z-index: ' + i + '" />');
bodies[bodies.length] = body;
}
function iterate()
{
for(var index = 0; index < bodies.length; ++index)
{
bodies[index].velocity_y += .1;
bodies[index].position_x += bodies[index].velocity_x;
bodies[index].position_y += bodies[index].velocity_y;
var position = jQuery('#' + index).position();
if (position.top + 100 > viewport_height)
{
bodies[index].velocity_y = - bodies[index].velocity_y;
bodies[index].position_y = viewport_height - 100;
}
if (position.top < 0)
{
bodies[index].velocity_y = - bodies[index].velocity_y;
bodies[index].position_y = 0;
}
if (position.left > viewport_width - 100)
{
bodies[index].velocity_x = -bodies[index].velocity_x;
bodies[index].position_x = viewport_width - 100;
}
if (position.left < 0)
{
bodies[index].velocity_x = -bodies[index].velocity_x;
bodies[index].position_x = 0;
}
jQuery('#' + index).offset({top: bodies[index].position_y, left: bodies[index].position_x });
}
}
setInterval(iterate, 30);

Add close button to popup

How do add a close button to the following popup by putting a cross on the target page?
Currently it closes if I click anywhere outside the box, but would prefer a Cross "X" on the box or the corner.
<script language="javascript">
$(document).ready(function() {
//Change these values to style your modal popup
var align = 'center'; //Valid values; left, right, center
var top = 100; //Use an integer (in pixels)
var width =700; //Use an integer (in pixels)
var padding = 10; //Use an integer (in pixels)
var backgroundColor = '#FFFFFF'; //Use any hex code
var source = '../page.php'; //Refer to any page on your server, external pages are not valid e.g. http://www.google.co.uk
var borderColor = '#333333'; //Use any hex code
var borderWeight = 4; //Use an integer (in pixels)
var borderRadius = 5; //Use an integer (in pixels)
var fadeOutTime = 300; //Use any integer, 0 = no fade
var disableColor = '#666666'; //Use any hex code
var disableOpacity = 40; //Valid range 0-100
var loadingImage = '../images/loading.gif'; //Use relative path from this page
//This method initialises the modal popup
$(".modal").click(function() {
modalPopup(align, top, width, padding, disableColor, disableOpacity, backgroundColor, borderColor, borderWeight, borderRadius, fadeOutTime, source, loadingImage);
});
//This method hides the popup when the escape key is pressed
$(document).keyup(function(e) {
if (e.keyCode == 27) {
closePopup(fadeOutTime);
}
});
});
</script>
<script>
function closePopup(fadeOutTime) {
fade('outerModalPopupDiv', fadeOutTime);
document.getElementById('blockModalPopupDiv').style.display='none';
}
function modalPopup(align, top, width, padding, disableColor, disableOpacity, backgroundColor, borderColor, borderWeight, borderRadius, fadeOutTime, url, loadingImage){
var containerid = "innerModalPopupDiv";
var popupDiv = document.createElement('div');
var popupMessage = document.createElement('div');
var blockDiv = document.createElement('div');
popupDiv.setAttribute('id', 'outerModalPopupDiv');
popupDiv.setAttribute('class', 'outerModalPopupDiv');
popupMessage.setAttribute('id', 'innerModalPopupDiv');
popupMessage.setAttribute('class', 'innerModalPopupDiv');
blockDiv.setAttribute('id', 'blockModalPopupDiv');
blockDiv.setAttribute('class', 'blockModalPopupDiv');
blockDiv.setAttribute('onClick', 'closePopup(' + fadeOutTime + ')');
document.body.appendChild(popupDiv);
popupDiv.appendChild(popupMessage);
document.body.appendChild(blockDiv);
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ //test for MSIE x.x;
var ieversion=new Number(RegExp.$1) // capture x.x portion and store as a number
if(ieversion>6) {
getScrollHeight(top);
}
} else {
getScrollHeight(top);
}
document.getElementById('outerModalPopupDiv').style.display='block';
document.getElementById('outerModalPopupDiv').style.width = width + 'px';
document.getElementById('outerModalPopupDiv').style.padding = borderWeight + 'px';
document.getElementById('outerModalPopupDiv').style.background = borderColor;
document.getElementById('outerModalPopupDiv').style.borderRadius = borderRadius + 'px';
document.getElementById('outerModalPopupDiv').style.MozBorderRadius = borderRadius + 'px';
document.getElementById('outerModalPopupDiv').style.WebkitBorderRadius = borderRadius + 'px';
document.getElementById('outerModalPopupDiv').style.borderWidth = 0 + 'px';
document.getElementById('outerModalPopupDiv').style.position = 'absolute';
document.getElementById('outerModalPopupDiv').style.zIndex = 100;
document.getElementById('innerModalPopupDiv').style.padding = padding + 'px';
document.getElementById('innerModalPopupDiv').style.background = backgroundColor;
document.getElementById('innerModalPopupDiv').style.borderRadius = (borderRadius - 3) + 'px';
document.getElementById('innerModalPopupDiv').style.MozBorderRadius = (borderRadius - 3) + 'px';
document.getElementById('innerModalPopupDiv').style.WebkitBorderRadius = (borderRadius - 3) + 'px';
document.getElementById('blockModalPopupDiv').style.width = 100 + '%';
document.getElementById('blockModalPopupDiv').style.border = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.padding = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.margin = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.background = disableColor;
document.getElementById('blockModalPopupDiv').style.opacity = (disableOpacity / 100);
document.getElementById('blockModalPopupDiv').style.filter = 'alpha(Opacity=' + disableOpacity + ')';
document.getElementById('blockModalPopupDiv').style.zIndex = 99;
document.getElementById('blockModalPopupDiv').style.position = 'fixed';
document.getElementById('blockModalPopupDiv').style.top = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.left = 0 + 'px';
if(align=="center") {
document.getElementById('outerModalPopupDiv').style.marginLeft = (-1 * (width / 2)) + 'px';
document.getElementById('outerModalPopupDiv').style.left = 50 + '%';
} else if(align=="left") {
document.getElementById('outerModalPopupDiv').style.marginLeft = 0 + 'px';
document.getElementById('outerModalPopupDiv').style.left = 10 + 'px';
} else if(align=="right") {
document.getElementById('outerModalPopupDiv').style.marginRight = 0 + 'px';
document.getElementById('outerModalPopupDiv').style.right = 10 + 'px';
} else {
document.getElementById('outerModalPopupDiv').style.marginLeft = (-1 * (width / 2)) + 'px';
document.getElementById('outerModalPopupDiv').style.left = 50 + '%';
}
blockPage();
var page_request = false;
if (window.XMLHttpRequest) {
page_request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
page_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
page_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { }
}
} else {
return false;
}
page_request.onreadystatechange=function(){
if((url.search(/.jpg/i)==-1) && (url.search(/.jpeg/i)==-1) && (url.search(/.gif/i)==-1) && (url.search(/.png/i)==-1) && (url.search(/.bmp/i)==-1)) {
pageloader(page_request, containerid, loadingImage);
} else {
imageloader(url, containerid, loadingImage);
}
}
page_request.open('GET', url, true);
page_request.send(null);
}
</script>
Page opens with this link
<a class="modal" href="javascript:void(0);">here</a>
Put an element in your source page (here page.php as you wrote) and give it a unique id or anything else (for example id="CloseModal"). And in your script, write this event handler:
$('body').on('click', '#CloseModal', function () {
closePopup(fadeOutTime);
});
If you don't want to change your source page, and make close button globally for all popups, change your modalPopup function and add these lines to it:
var closeDiv = document.createElement('div');
closeDiv.setAttribute('id', 'CloseModal');
closeDiv.innerHTML = '[CLOSE]';
popupDiv.appendChild(closeDiv);
These code will add the close tag to the popup itself. And jquery code that I wrote before, will handle the click of it.
Here is your final scripts and functions:
<script language="javascript">
$(document).ready(function() {
//Change these values to style your modal popup
var align = 'center'; //Valid values; left, right, center
var top = 100; //Use an integer (in pixels)
var width =700; //Use an integer (in pixels)
var padding = 10; //Use an integer (in pixels)
var backgroundColor = '#FFFFFF'; //Use any hex code
var source = '../page.php'; //Refer to any page on your server, external pages are not valid e.g. http://www.google.co.uk
var borderColor = '#333333'; //Use any hex code
var borderWeight = 4; //Use an integer (in pixels)
var borderRadius = 5; //Use an integer (in pixels)
var fadeOutTime = 300; //Use any integer, 0 = no fade
var disableColor = '#666666'; //Use any hex code
var disableOpacity = 40; //Valid range 0-100
var loadingImage = '../images/loading.gif'; //Use relative path from this page
//This method initialises the modal popup
$(".modal").click(function() {
modalPopup(align, top, width, padding, disableColor, disableOpacity, backgroundColor, borderColor, borderWeight, borderRadius, fadeOutTime, source, loadingImage);
});
//This method hides the popup when the escape key is pressed
$(document).keyup(function(e) {
if (e.keyCode == 27) {
closePopup(fadeOutTime);
}
});
// jquery event handler for CloseModal button
$('body').on('click', '#CloseModal', function () {
closePopup(fadeOutTime);
});
});
</script>
<script>
function closePopup(fadeOutTime) {
fade('outerModalPopupDiv', fadeOutTime);
document.getElementById('blockModalPopupDiv').style.display='none';
}
function modalPopup(align, top, width, padding, disableColor, disableOpacity, backgroundColor, borderColor, borderWeight, borderRadius, fadeOutTime, url, loadingImage){
var containerid = "innerModalPopupDiv";
var popupDiv = document.createElement('div');
var popupMessage = document.createElement('div');
var blockDiv = document.createElement('div');
popupDiv.setAttribute('id', 'outerModalPopupDiv');
popupDiv.setAttribute('class', 'outerModalPopupDiv');
popupMessage.setAttribute('id', 'innerModalPopupDiv');
popupMessage.setAttribute('class', 'innerModalPopupDiv');
blockDiv.setAttribute('id', 'blockModalPopupDiv');
blockDiv.setAttribute('class', 'blockModalPopupDiv');
blockDiv.setAttribute('onClick', 'closePopup(' + fadeOutTime + ')');
document.body.appendChild(popupDiv);
// creating the close button and append it to popup
var closeDiv = document.createElement('div');
closeDiv.setAttribute('id', 'CloseModal');
closeDiv.innerHTML = '[CLOSE]';
popupDiv.appendChild(closeDiv);
popupDiv.appendChild(popupMessage);
document.body.appendChild(blockDiv);
if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)){ //test for MSIE x.x;
var ieversion=new Number(RegExp.$1) // capture x.x portion and store as a number
if(ieversion>6) {
getScrollHeight(top);
}
} else {
getScrollHeight(top);
}
document.getElementById('outerModalPopupDiv').style.display='block';
document.getElementById('outerModalPopupDiv').style.width = width + 'px';
document.getElementById('outerModalPopupDiv').style.padding = borderWeight + 'px';
document.getElementById('outerModalPopupDiv').style.background = borderColor;
document.getElementById('outerModalPopupDiv').style.borderRadius = borderRadius + 'px';
document.getElementById('outerModalPopupDiv').style.MozBorderRadius = borderRadius + 'px';
document.getElementById('outerModalPopupDiv').style.WebkitBorderRadius = borderRadius + 'px';
document.getElementById('outerModalPopupDiv').style.borderWidth = 0 + 'px';
document.getElementById('outerModalPopupDiv').style.position = 'absolute';
document.getElementById('outerModalPopupDiv').style.zIndex = 100;
document.getElementById('innerModalPopupDiv').style.padding = padding + 'px';
document.getElementById('innerModalPopupDiv').style.background = backgroundColor;
document.getElementById('innerModalPopupDiv').style.borderRadius = (borderRadius - 3) + 'px';
document.getElementById('innerModalPopupDiv').style.MozBorderRadius = (borderRadius - 3) + 'px';
document.getElementById('innerModalPopupDiv').style.WebkitBorderRadius = (borderRadius - 3) + 'px';
document.getElementById('blockModalPopupDiv').style.width = 100 + '%';
document.getElementById('blockModalPopupDiv').style.border = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.padding = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.margin = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.background = disableColor;
document.getElementById('blockModalPopupDiv').style.opacity = (disableOpacity / 100);
document.getElementById('blockModalPopupDiv').style.filter = 'alpha(Opacity=' + disableOpacity + ')';
document.getElementById('blockModalPopupDiv').style.zIndex = 99;
document.getElementById('blockModalPopupDiv').style.position = 'fixed';
document.getElementById('blockModalPopupDiv').style.top = 0 + 'px';
document.getElementById('blockModalPopupDiv').style.left = 0 + 'px';
if(align=="center") {
document.getElementById('outerModalPopupDiv').style.marginLeft = (-1 * (width / 2)) + 'px';
document.getElementById('outerModalPopupDiv').style.left = 50 + '%';
} else if(align=="left") {
document.getElementById('outerModalPopupDiv').style.marginLeft = 0 + 'px';
document.getElementById('outerModalPopupDiv').style.left = 10 + 'px';
} else if(align=="right") {
document.getElementById('outerModalPopupDiv').style.marginRight = 0 + 'px';
document.getElementById('outerModalPopupDiv').style.right = 10 + 'px';
} else {
document.getElementById('outerModalPopupDiv').style.marginLeft = (-1 * (width / 2)) + 'px';
document.getElementById('outerModalPopupDiv').style.left = 50 + '%';
}
blockPage();
var page_request = false;
if (window.XMLHttpRequest) {
page_request = new XMLHttpRequest();
} else if (window.ActiveXObject) {
try {
page_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
page_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) { }
}
} else {
return false;
}
page_request.onreadystatechange=function(){
if((url.search(/.jpg/i)==-1) && (url.search(/.jpeg/i)==-1) && (url.search(/.gif/i)==-1) && (url.search(/.png/i)==-1) && (url.search(/.bmp/i)==-1)) {
pageloader(page_request, containerid, loadingImage);
} else {
imageloader(url, containerid, loadingImage);
}
}
page_request.open('GET', url, true);
page_request.send(null);
}
</script>
If you are using boostrap then use this code onclick of close button or image
$("#your-popup-id").modal('hide');
and if you are not using boostrap then this will work
$("#your-popup-id").hide();

How to break a number into randomly generated parts

I want to make a div that is full width on the page. It's a container. Then I want to fill it in with divs, and width of each div is 50*n, where n is a randomly generated number. Assume I have a container div with width of 1240px. Now I run a JS function that fills it with e.g. 10 divs with different widths. Now if I sum up all inner divs widths, I get 1240px.
This way I always know that when I run filling function, I get a collection of divs that altogether always are 1240px. Number of divs shouldn't be a fixed number, so there can be 4 or 7 divs. The number of divs amount is generated randomly. Then, if there is some space left, for 1240 px this number is 40px I suppose, it is filled with some dummy div that doesn't have to be of 50*n width.
I have created a function but it doesn't always work as supposed to.
function generateItems() {
originalwidth = $(document).width() - 40;
var fullwidth = 0;
var counter = 0;
do{
var randomnumber = 1 + Math.floor(Math.random() * 4);
tempwidth = 50 * randomnumber;
fullwidth += tempwidth;
if (fullwidth > originalwidth) {
$('#questions').append('<div class="question-area" style="width:' + (originalwidth - fullwidth) + 'px;"><strong>' + (originalwidth - fullwidth) + '</strong></div>');
break;
}
width_padding = tempwidth;
$('#questions').append('<div class="question-area" style="width:' + width_padding + 'px;">' + width_padding + '</div>');
counter++;
}
while (true);
}
I am not even sure it's a good way I have chosen to solve such a task. Please share your thoughts on how to better do this.
I've refactored the code from your answer a bit.
See: http://jsfiddle.net/thirtydot/Bk2yw/
function generateItems() {
var slotWidth = 50,
maxSlots = 3,
thisSlotNum, thisWidth;
var remainingSlots = Math.floor($('#questions').width() / slotWidth),
remainingWidth = $('#questions').width() % slotWidth;
while (remainingSlots > 0) {
thisSlotNum = Math.min(remainingSlots, 1 + Math.floor(Math.random() * maxSlots));
remainingSlots -= thisSlotNum;
thisWidth = thisSlotNum * slotWidth;
$('#questions').append('<div class="question-area" style="width:' + thisWidth + 'px;"><strong>' + thisWidth + '</strong></div>');
}
if (remainingWidth) {
$('#questions').append('<div class="question-area" style="width:' + remainingWidth + 'px;"><strong>' + remainingWidth + '</strong></div>');
}
}
I played a little more with the code and it seems I made it work properly, though I am sure there is something to improve.
Here is the code:
function generateItems() {
originalwidth = $(document).width() - 40;
$('#questions').css('width', originalwidth);
var fullwidth = 0;
var counter = 0;
do{
var randomnumber = 1 + Math.floor(Math.random() * 4);
tempwidth = 50 * randomnumber;
fullwidth += tempwidth;
if (fullwidth > originalwidth) {
$('#questions').append('<div class="question-area" style="width:' + (originalwidth + tempwidth - fullwidth) + 'px;"><strong>' + (originalwidth + tempwidth - fullwidth) + '</strong></div>');
break;
}
width_padding = tempwidth;
$('#questions').append('<div class="question-area" style="width:' + width_padding + 'px;">' + width_padding + '</div>');
counter++;
}
while (true);
}
Here is an screenshot of how it works. The bottom row is the result for another width of the page.
A couple of problems:
fullwidth += tempwidth;
if (fullwidth > originalwidth) {
$('#questions').append('<div class="question-area" style="width:' + (originalwidth - fullwidth) + 'px;"><strong>' + (originalwidth - fullwidth) + '</strong></div>');
break;
}
Here you have already "gone over" the original width with the fullwidth variable, so when you do originalwidth - fullwidth it's always negative (by definition because fullwidth > originalwidth).
Another problem is that if the random width is for example 150 pixels and you have 140 pixels of space left, your code considers that as space running out and puts in the dummy div of 140 px. It's not clear from your question but you probably want a 100 px block and the rest filled with a 40 px block.
Here's a working version:
function generateItems() {
var originalwidth = $(document).width() - 40;
var fullwidth = 0;
var counter = 0;
do{
var randomnumber = 1 + Math.floor(Math.random() * 3);
var tempwidth = 50 * randomnumber;
if (fullwidth + tempwidth > originalwidth) {
var diff = originalwidth - fullwidth;
if( originalwidth - fullwidth > 50 ) {
tempwidth = diff - ( diff % 50 );
}
else {
$('#questions').append('<div class="question-area" style="width:' + diff + 'px;"><strong>' + diff + '</strong></div>');
break;
}
}
fullwidth += tempwidth;
$('#questions').append('<div class="question-area" style="width:' + tempwidth + 'px;">' + tempwidth + '</div>');
counter++;
}
while (true);
}

Use jQuery set .css RIGHT if #foo + offset left is greater than page width

Ok, so I am trying to use jQuery to get the innerWidth() of an element #preview. I want to create a conditional that says IF x offset LEFT + #preview width is greater than page width, give it style right: z where z = #preview width + xOffset.
I apologize my code below is a mess and the syntax for .css ("right", (rightFloat + xOffset) + "px") (line 125) is off, but that's part of my problem.
<script>
$(document).ready(function(){
//append "gallery" class to all items with "popup" class
imagePreview();
$(".popup").addClass("gallery");
});
//The overlay or pop-up effect
this.imagePreview = function() { /* CONFIG */
xOffset = 40;
yOffset = 40;
// these 2 variable determine popup's distance from the cursor
// you might want to adjust to get the right result
/* END CONFIG */
$("a.preview").click(function(e) {
return false;
});
$("a.preview").hover(function(e) {
this.t = this.title;
this.title = "";
var c = (this.t != "") ? "<br/>" + this.t : "";
var rightFloat = e.pageX + ("#preview").innerWidth;
$("body").append("<p id='preview'><img src='" + this.href + "' alt='Image preview' />" + c + "</p>");
$("#preview").hide().css("top", (e.pageY - yOffset) + "px").css("left", (e.pageX + xOffset) + "px").fadeIn("2000");
while ((left + 400) > window.innerWidth) {.css("right", (rightFloat + xOffset) + "px")
}
}, function() {
this.title = this.t;
$("#preview").remove();
});
$("a.preview").mousemove(function(e) {
var top = e.pageY - yOffset;
var left = e.pageX + xOffset;
var rightFloat = e.pageX + ("#preview").innerWidth;
//flips the image if it gets too close to the right side
while ((left + 400) > window.innerWidth) {.css("right", +(rightFlaot + xOffset) + "px")
}
$("#preview").css("top", top + "px").css("left", left + "px");
});
};
</script>
Try using http://api.jquery.com/offset/
if($('#preview').offset().right<0){
var right = parseInt($(window).width()) - e.pageX + xOffset;
$("#preview").css("top", top + "px").css("right", right + "px");
}else{
var left = e.pageX + xOffset;
$("#preview").css("top", top + "px").css("left", left + "px");
}
I made these fixes because I couldn't get your code to work in jsfiddle:
var xOffset = 40;
var yOffset = 40;
$("a.preview").bind('mouseover',function(e){
var rightFloat = parseFloat(e.pageX)+$("#preview").innerWidth();
var ptop = parseFloat(e.pageY) - yOffset;
var pleft = parseFloat(e.pageX) + xOffset;
$("#preview").css({"top":ptop + "px","left":pleft + "px"});
});
There's the fixes for the top half but I have no idea what you're trying to do with the bottom part (with the while loop). Can you explain what functionality you want?

Categories