Bootstrap modal popup ignores scroll position if in iframe - javascript

I have a bootstrap modal popup that works great if the webpage is not in an iframe, like so:
https://jgroups-dev.herokuapp.com/ (click Find a Group, then click a Email button)
However, when it is within an iframe the modal popup anchors to the top of the iframe, completely ignoring the user's scroll position:
http://www.yourjourney.tv/connect/j-group-catalogue/
To try to hack around this issue, I'm attempting to manually set the modal popup's top property based on the scroll position within the iframe, however $(window).scrollTop() and other variants are all returning either 0 or 40 from within the iframe.
$('.send-email-modal').modal();
setTimeout(function () {
if(inIframe()) {
var emailModal = $('.send-email-modal .modal-dialog');
var win = $(window);
var offset1 = win.scrollTop();
var offset2 = document.documentElement.scrollTop || document.body.scrollTop;
console.log('offset1: ' + offset1);
console.log('offset2: ' + offset2);
var positionWindow = (offset1 + (win.height() / 2)) - (emailModal.height() / 2);
console.log('win.height(): ' + win.height());
console.log('emailModal.height(): ' + emailModal.height());
console.log('positionWindow: ' + positionWindow);
emailModal.css({ 'top': positionWindow });
}
}, 500);
Here is the console output:
offset1: 40
main.js:54 offset2: 40
main.js:56 win.height(): 27037
main.js:58 emailModal.height(): 426
main.js:59 positionWindow: 13345.5
If I can't retrieve how far down the user has scrolled in the iframe from code within the iframe, then I have no chance of being able to position the bootstrap modal popup correctly. Help very much appreciated, I've run into a brick wall on this one...

Possible issue: It is not ignoring the scroll value. The user scroll is taking place in the parent window. Your iframe's height is probably equal to it's document height. Modal is always place on the top center (with some margin) of the containing window(in this case your iframe). and hence it works fine when you see it in stand alone window. And it's near the starting of the document inside the iframe.
Possible Solution [in case of same origin]
From inside your iframe, check if the page has a parent window (to ensure it is inside a iframe) and if it has read the value of the scrollTop and then manually adjust the modal css top property.
parent == self // for any top level window
Following will give you the scroll top of the parent window
parent.document.body.scrollTop
In case of cross origin
In case of different origins of iframe and the parent, you will not be able to access the parent's properties.
Try using the postMessage. send the value of scrollTop from parent to the iframe wherever user scrolls. Save this value and use it whenever you show the modal.
Read more about postMessage here https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

Related

Vue.js 2 can get body scroll position but not set body scroll position

I have a Vue.js app where I am opening a modal and need to set the body under it to a fixed position to prevent it scrolling on mobile. This of course scrolls it to the top. Before opening the modal, I get the scroll position and set it like so:
this.bposition = document.body.scrollTop
console.log(document.body.scrollTop)
And this works fine, I can output the correct position in my console. But then, when I close my modal, I try to do this:
console.log(this.bposition) // proves my close function is running and gets the correct value
var el = document.querySelector('body')
el.scrollLeft = 0 // have tried with and without this line
el.scrollTop = this.bposition
But to no avail, the page will not scroll. I have tried on various elements within the page as well, none of them scroll.
UGH. I found the solution. Apparently, even though the class that was making my body fixed was being removed when the modal was closed, it was not being removed fast enough. I solved this by introducing a timeout:
setTimeout(() => {
el.scrollTop = this.bposition
}, 500)
UPDATE:
Somewhat faster, I found the function (in external code) that removes the class and duplicated it before my call, which works even better:
var el = document.querySelector('body')
el.classList.remove('with-modal')
el.scrollTop = this.bposition

Adjust Iframe height dynamically and set scroll if content height change on client side event (Text Expand/Collapse using +/- buttons)

I have been searching around for a solution to set scroll of iframe sourcing same domain page using javascript. I just want to have scroll on the iframe only if the content's height is greater that the window height. Came across solutions using setInterval. In IE i dont get a proper scrollheight for a page that has some content hidden. The works fine in chrome and mozila although. Also it looks like i have to set anyways max-hright of the iframe to get this code working on chrome and IE when the use click on +/- in the iframe page. I dont have controll over the source page for iframe. Also there are events where in the content height of the iframe changes at client side like expand/collapse thing. Any suggestions as to why it is happening or any other options to implement.
Iframe container (div)
border: groove;border-width: thin;display:none;position:fixed;z-index:998;width:800px;background-color: white;right: 83px;top:22px;
Iframe style
top: 20px;margin:0;padding:0
Javascript function that gets called based on interval to set iframe height to that content height
function AdjustIframeHeightOnLoad() {
var screenHeight = $(window).height();
var iframeContentHeight;
var iframeContentwidth;
iframeContentHeight = document.getElementById("iframe_ObjectLink").contentWindow.document.body.scrollHeight;
iframeContentwidth = document.getElementById("iframe_ObjectLink").contentWindow.document.body.scrollWidth;
if (iframeContentHeight > (screenHeight - 47)) {
document.getElementById("objectionMenuContentContainer_div").style.height = (screenHeight - 27) + "px";
document.getElementById("iframe_ObjectLink").height = (screenHeight - 47);
document.getElementById("iframe_ObjectLink").contentWindow.document.documentElement.style.overflowY = "scroll";
}
else {
document.getElementById("objectionMenuContentContainer_div").style.height = iframeContentHeight + "px";
document.getElementById("iframe_ObjectLink").height = (iframeContentHeight - 25);
document.getElementById("iframe_ObjectLink").contentWindow.document.documentElement.style.overflowY = "hidden";
}
if (iframeContentwidth > 883)
document.getElementById("iframe_ObjectLink").contentWindow.document.documentElement.style.overflowX = "scroll";
else
document.getElementById("iframe_ObjectLink").contentWindow.document.documentElement.style.overflowX = "hidden";
}

Get Default Height Of Element On Webpage after css height has been applied)

How do I go about getting what the height of an element on a page would be if it ignored the 'height' css property applied to it?
The site I'm working on is http://www.wncba.co.uk/results and the actual script I've got so far is:
jQuery(document).ready(function($) {
document.origContentHeight = $("#auto-resize").outerHeight(true);
refreshContentSize(); //run initially
$(window).resize(function() { //run whenever window size changes
refreshContentSize();
});
});
function refreshContentSize()
{
var startPos = $("#auto-resize").position();
var topHeight = startPos.top;
var footerHeight = $("#footer").outerHeight(true);
var viewportHeight = $(window).height();
var spaceForContent = viewportHeight - footerHeight - topHeight;
if (spaceForContent <= document.origContentHeight)
{
var newHeight = document.origContentHeight;
}
else
{
var newHeight = spaceForContent;
}
$("#auto-resize").css('height', newHeight);
return;
}
[ http://www.wncba.co.uk/results/javascript/fill-page.js ]
What I'm trying to do is get the main page content to stretch to fill the window so that the green lines always flow all the way down the page and the 'Valid HTML5' and 'Designed By' messages are never above the bottom of the window. I don't want the footer to stick to the bottom. I just want it to stay there instead of moving up the page if there's not enough content to fill above to fill it. It also must adapt itself accordingly if the browser window size changes.
The script I've got so far works but there's a small issue that I want to fix with it. At the moment if the content on the page changes dynamically (resulting in the page becoming longer or shorter) the script won't detect this. The variable document.origContentHeight will remain set as the old height.
Is there a way of detecting the height of an element (e.g. #auto-resize in the example) and whether or not it has changed ignoring the height that has been set for it in css? I would then use this to update the variable document.origContentHeight and re-run the script.
Thanks.
I don't think there is a way to detect when an element size changed except using a plugin,
$(element).resize(function() //only works when element = window
but why don't you call refreshContentSize function on page changes dynamically?
Look at this jsFiddle DEMO, you will understand what I mean.
Or you can use Jquery-resize-plugin.
I've got it working. I had to rethink it a bit. The solution is on the live site.
The one think I'd like to change if possible is the
setInterval('refreshContentSize()', 500); // in case content size changes
Is there a way of detecting that the table row has changed size without chacking every 500ms. I tried (#content).resize(function() but couldn't to get it to work.

How to know when an element will be off screen?

I am writing a simple script that displays a dialog box when a user hovers over a profile picture. It dynamically determines the profile pics location on the page and then places itself to the left of it and about 100px above it. This part is working fine.
My issue arises when a profile pic is at the top of the screen and a user mouses over it. The dialog will appear but the top portion of it will be above the fold (i.e. not in the current browser window). Naturally this is not good usability and I would like it to appear on the screen.
My question is how do I know when a dialog will be off screen so I can recalculate its position on the page?
I saw this question which seems like the same as mine but unfortunately no actual solution was provided other then to link to a jQuery plugin. I am using Prototype.
Prototype already provides positions with Element.viewportOffset().
Edit, as Mathew points out document.viewport gives the rest of the information. For example,
var dialogtop = dialog.viewportOffset().top;
if (dialogtop < 0) {
// above top of screen
}
elseif (dialogtop + dialog.getHeight > document.viewport.getHeight()) {
// below bottom of screen
}
You'll want to find the profile pic's position relative to the document (here's a good article on how, though I suspect Prototype's Element.Offset already handles this), then compare it to the body's scrollTop property to see if it's close enough to the top that it needs to have its dialog repositioned.
I am familiar with this problem, however, last time I was able to use a library (Seadragon) to get the screen dimensions and mouse position. I was also working with a fixed size overlay so no code to share with you other than general approach.
For my pop up box I decided to use the event mouse position rather than location of the div on the page. I then compared the mouse position to the known screen size, which I determined on start or resize.
From How do I get the size of the browser window using Prototype.js?
var viewport = document.viewport.getDimensions(); // Gets the viewport as an object literal
var width = viewport.width; // Usable window width
var height = viewport.height; // Usable window height
In Prototype you can also get the mouse coordinates:
function getcords(e){
mouseX = Event.pointerX(e);
mouseY = Event.pointerY(e);
//for testing put the mouse cords in a div for testing purposes
$('debug').innerHTML = 'mouseX:' + mouseX + '-- mouseY:' + mouseY;
}
Source : http://remorse.nl/2008/06/mouse_coordinates_with_prototype/

A bit of problem with implementing a modal dialog

I am developing a modal dialog as a part of a web application. There is one thing that's been of a puzzle to me. Please watch a movie clip that I just uploded at http://inter.freetzi.com/example/. I feel strongly that I have to accompany my question with a video because this is the case when it's better to see once, than to hear 100 times.
(It could be vertical scrolling, or both vertical and horizontal at the same time. But I am using horizontal scrolling in my example, so watch for it.)
Here's about my question:
Width of the transparent mask affects the width of the page itself. But in Opera, for exemple, every time the window gets resized, the page gets width that is at most close to 'true'. While in IE, once the transparent mask has affected the width, afterwards the page remembers it and stays with it. What is the problem and how to settle it? How to make IE behave the way Opera does?
In my project, I do the following:
//curViewpointW and curViewpointH are current width and height of the viewpoint (current is meant to be the moment of the resize event)
oMask.style.width = curViewpointW + 'px';
oMask.style.height = curViewpointH + 'px';
var pageWH = getPageWH(); //getPageWH() is a function that gets current width and height of the page (with scrolling if there is any)
var curPageW = pageWH[0];
var curPageH = pageWH[1];
if (curPageW > curViewpointW) {
oMask.style.width = curPageW + 'px';
}
if (curPageH > curViewpointH) {
oMask.style.height = curPageH + 'px';
}
But IE ignores that somehow...
P.S. It's jQuery in my example, so many of you may have used its dialog before.
Have you looked into setting an onresize event handler that will adjust your mask dimensions when the window is resized? If you are using Prototype, you can set up such a handler unobtrusively like this:
Event.observe(document.onresize ? document : window, "resize", function() {//dostuff});
courtesy of the Roberto Cosenza blog

Categories

Resources