PrimeFaces 4.0 Dialog headers fit well to dialog window in IE and Firefox but not in Chrome unless i move mouse cursor over the dialog header. When I move the cursor to dialog header it scales and fits the dialog window by itself. I get this problem for all dialogs I use not just the one I posted below. I only have this problem in Chrome. Do you know why this is happening in Chrome and how can I fix this?
The dialog codes and screenshots are below :
This is the status of dialog header when it's opened first
This is the status of dialog header when I move mouse cursor over it.
You see it got normal size.
Dialog codes :
<p:dialog header="#{graphAnalysis.charts.chartTitle} Distribution"
closeOnEscape="true" width="800" dynamic="true"
height="550" widgetVar="lineChartDialog" closable="true"
onShow="loadLineChart()" minimizable="true" position="center"
id="distChartDialogId" >
<h:form style="margin-top: 20px;" id="chartForm">
<p:lineChart id="lineChartId" value="#{graphAnalysis.charts.currentChart}"
style="height: 450px;width: 750px" animate="true" legendPosition="e"
widgetVar="lineChartWg" yaxisLabel="Fraction of Proteins"
xaxisLabel="#{graphAnalysis.charts.chartTitle}"
title="#{graphAnalysis.charts.chartTitle} Distribution" zoom="true" />
<p:remoteCommand name="loadLineChart" update="lineChartId" async="true" process="#this" />
<p:commandButton type="button" value="Export" icon="ui-icon-extlink" onclick="exportLineChart()"/>
</h:form>
</p:dialog>
Another dialog code :
<p:dialog width="800" height="500" widgetVar="graphVis" dynamic="true"
closable="true" draggable="true" minimizable="true" position="center"
closeOnEscape="true" header="Graph Visualization" onShow="updateGraph()">
<h:form>
<p:panel style="border: none;height:450px" id="graphPanel">
<p:mindmap value="#{browse.graph.root}" style="width: 800px;height: 600px">
<p:ajax event="select" listener="#{browse.graph.onNodeSelect}" />
<p:ajax event="dblselect" listener="#{browse.graph.onNodeDblselect}"
oncomplete="details.show()"/>
</p:mindmap>
</p:panel>
<p:remoteCommand name="updateGraph" update="graphPanel" async="true" process="#this" />
</h:form>
</p:dialog>
My page structure is like that :
<html>
<f:view>
<h:head>
...
</h:head>
<h:body>
<p:layout>
<p:layoutUnit>
HEAD
</p:layoutUnit>
<p:layoutUnit>
BODY
</p:layoutUnit>
<p:layoutUnit>
FOOTER
</p:layoutUnit>
</p:layout>
DIALOG CODES HERE
</h:body>
</f:view>
</html>
My solution is very nasty and there are some scenarios, in which it won't work, but in most cases header is displayed correctly now.
Add code to your JavaScript file:
function waitForDialogToLoad(dialog, initialWidth, counter){
//if there was less then 50 tries, try again
if(counter<50){
//if dialog hasn't changed its width, it means it hasn't appeared
if(dialog.width()==initialWidth){
//increase counter
counter ++;
//and try again
setTimeout(waitForDialogToLoad,10,dialog,initialWidth, counter);
}
else{
//set final width of header
var header = dialog.find(".ui-dialog-titlebar");
header.width(dialog.width());
}
}
}
function showDlg(dialog) {
$.browser.chrome = /chrom(e|ium)/.test(navigator.userAgent.toLowerCase());
//if the browser is chrome
if($.browser.chrome){
//find dialog object
var dialogDOM = $("#"+dialog.id.replace(/\:/g,"\\:"));
//set initial width of header
var header = dialogDOM.find(".ui-dialog-titlebar");
header.width(dialogDOM.width());
//remember width of header
var currentWidth = dialogDOM.width();
//show dialog
dialog.show();
//set entry counter
var counter = 0;
//after 10 miliseconds check if dialog has appeared
setTimeout(waitForDialogToLoad,10,dialogDOM,currentWidth, counter);
}
else{
dialog.show();
}
}
Then in view, instead of
dialog.show();
call
showDlg(dialog);
Related
Here is my code for tabbed bar:
<Alloy>
<Window class="container">
<Label id="label" onClick="doClick">Hello, World</Label>
<TabbedBar id="bb1" platform="ios" backgroundColor="#369" top="50" height="25" width="200">
<!-- The Labels tag sets the TabbedBar.labels property. -->
<Labels>
<!-- Specify text with node text or the title attribute. -->
<!-- Can also specify the enabled, image and width attributes. -->
<Label>One</Label>
<Label>Two</Label>
<Label>Three</Label>
</Labels>
<!-- Place additional views for the TabbedBar here. -->
<Views>
<View backgroundColor='red'>1</View>
<View>2</View>
<View><Label>Does this work!</Label></View>
</Views>
</TabbedBar>
</Window>
</Alloy>
When I click on a tab, how can I make sure that the view corresponds to the button pressed - I know how to do this in titanium but not alloy.
Cheers.
I had the same problem yesterday. I'm sure there must be a better way but I couldn't see anything in the documentation, this was my solution:
var animation = require('alloy/animation');
var previousIndex = $.tabbedBar.getIndex();
$.tabbedBar.addEventListener('click', function(){
var currentIndex = $.tabbedBar.getIndex();
var viewArr = [];
viewArr[0] = $.view1;
viewArr[1] = $.view2;
viewArr[2] = $.view3;
animation.crossFade(viewArr[previousIndex], viewArr[currentIndex], 700)
previousIndex = currentIndex;
});
EDIT:
(In case you don't know, on Android there's a module to give you similar functionality: https://github.com/ricardoalcocer/viewpager but check issue #5 on the original repo as you'll have to incorporate that into any build. On the Android version, you don't need to handle the clicks yourself.)
When embedding a Bootstrap app in an iframe, modal dialogs always open at the top of the iframe, not the top of the screen. As an example, go to http://getbootstrap.com/javascript/ and open an example modal on the page. Then using the sample code below which places the same bootstrap page in an iframe, find a modal and open it:
<html>
<head>
</head>
<body>
<table width="100%">
<tr><td colspan="2" style="height:80px;background-color:red;vertical-align:top">Here's some header content I don't control</td></tr>
<tr><td style="width:230px;height:10080px;background-color:red;vertical-align:top">Here's some sidebar content I don't control either</td>
<td valign="top">
<iframe width="100%" height="10000px"
scrolling="no" src="http://getbootstrap.com/javascript/">
</iframe>
</td>
</tr>
</table>
</body>
</html>
Demo in fiddle
How do I go about positioning the modal on the screen in this scenario?
UPDATE: Unfortunately, my iFrame cannot fill the screen, nor can I make it fixed since it needs to blend into the rest of the page and the page itself has enough content to scroll. This is not my design and I ultimately intend to rework the whole thing, but this is what I have to work around for now. As a temporary option, I'm using javascript to tell the iframe parent to scroll to the top where the modal dialog pops up. While this is acceptable, this isn't the desired behavior.
I'm using angularjs and the ui-bootstrap library in my code but as you can see above, it's a bootstrap issue.
If your iframe has the same document.domain as the parent window or it is a sub domain, you can use the code below inside the iframe:
$('#myModal').on('show.bs.modal', function (e) {
if (window.top.document.querySelector('iframe')) {
$('#myModal').css('top', window.top.scrollY); //set modal position
}
});
show.bs.modal will fire after you call $('#myModal').show()
window.top.scrollY will get the scrollY position from the parent window
In case your document.domain differs from the parent, you can hack it getting the onmousedown position inside the iframe. For example:
$('#htmlElement').on('mousedown', function (event) {
event.preventDefault();
$('#myModal').data('y', event.pageY); // store the mouseY position
$('#myModal').modal('show');
});
$('#myModal').on('show.bs.modal', function (e) {
var y = $('#myModal').data('y'); // gets the mouseY position
$('#myModal').css('top', y);
});
Quite old question but I don't see the solution/workaround I've found. It might be helpful for someone in the future.
I had the same issue - my iFrame doesn't fill the entire screen, it displays bootstrap's modal and it is loading content from different domain than the parent page.
TL;DR
Use window.postMessage() API - Documentation here. for communication between parent and iframe (cross-domain)
pass message with currentScrollPosition and Y position of your iframe
Reveive message and update modal's padding from the top
In my case the workaround was to use window.postMessage() API - Documentation here.
It requires to add some extra code to the parent and handle message in an iFrame.
You can add EventListener and listen to 'scroll' event. Each time the event handling function is invoked you can get currentScrollPosition like document.scrollingElement.scrollTop.
Keep in mind that your iframe can have some margin from the top in the parent page so you should also get its 'offset'.
After that you can post these two values to your iframe e.g. ncp_iframe.contentWindow.postMessage(message, '*');
Note that the message has to be a String value
After that in your iFrame you need to add EventListener and listen to 'message' event.
The event handling function will pass your 'message' in event.data property. Having that you can update modal padding. (Looks much better if you don't use animations e.g. fade, in classes);
Quick Example:
Parent:
window.addEventListener('scroll', function(event){
var myIframe = document.querySelector('#myIframe');
var topOffset = myIframe.getBoundingClientRect().top + window.scrollY;
var currentScroll = document.scrollingElement.scrollTop;
myIframe.contentWindow.postMessage(topOffset + ':' + currentScroll, '*');
});
iFrame:
window.addEventListener('message', function(event) {
var messageContent = event.data.split(':');
var topOffset = messageContent[0];
var currentScroll = messageContent[1];
//calculate padding value and update the modal top-padding
}, false);
This is a bug in most browsers (IE appears fine) where the elements are fixed to the iframe, not the window. Typically, if you need something to be relative to the main document, it has to be in the main document.
A workaround is to wrap your iframe in a fixed position div that takes up the whole width of the screen and then maximize the iframe within that. This appears to resolve the issue
HTML:
<div class="fixframe">
<iframe src="http://getbootstrap.com/javascript/"></iframe>
</div>
CSS:
.fixframe {
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
}
.fixframe iframe {
height: 100%;
width: 100%;
}
Working Demo in fiddle
See Also:
position:fixed inside of an iframe
iframe with a css fixed position : possible?
position fixed div in iframe not working
It is because the class .modal has position: fixed attribute. Try position: relative instead.
I am pretty new to Javascript and struggeling to get the click event on the mediaelment player. My aim is to block the click that it doesn't get through to the modal box behind the player.
Here the relevant part of the html:
<div class="player_bg" id="mybg" style="display: none" onclick="close_over(this.id)">
<!-- onclick="close_over(this.id)" -->
<div class="video-modal" onclick="close_over(this.parentNode.id)"></div>
<div class="videoplayer">
<video id="myVideo" width="640" height="360" poster="" controls="controls" preload="auto" onclick="close_over(this.id)">
<!-- MP4 for Safari, IE9, iPhone, iPad, Android, and Windows Phone 7 -->
<source type="video/mp4" src="">
<!-- WebM/VP8 for Firefox4, Opera, and Chrome -->
<source type="video/webm" src="">
<!-- Ogg/Vorbis for older Firefox and Opera versions -->
<source type="video/ogg" src="">
<object width="640" height="360" type="application/x-shockwave-flash" data="../_styles/js/flashmediaelement.swf">
<param name="movie" value="flashmediaelement.swf" />
<param name="flashvars" value="controls=true&file=">
<img src="" width="320" height="220" title="No video playback capabilities, please download the video" alt="" >
</object>
</video>
</div>
</div>
and here is my javascript:
function close_over(who) {
if (who == "myVideo") {
} elseĀ {
el = document.getElementById("mybg");
el.style.display ="none";
//(el.style.display == "block") ? "none" : "block";
$('video, audio').each(function() {
$(this)[0].player.pause();
});
}
}
(video-modal is just a button defined as background-image, the 'active layer' is 'mybg')
This gives me the click event two times. First I get it and it is blocked by the if clause (as I wanted it to be) and then it gets through to the modal box (mybg)and is handled by the else clause (which I don't want).
As starting point I only had this javascript code:
function close_over(who) {
el = document.getElementById("mybg");
el.style.display ="none";
//(el.style.display == "block") ? "none" : "block";
$('video, audio').each(function() {
$(this)[0].player.pause();
});
}
(yes, the 'who' is obsolete in this example)
Both scripts react fine when I click on the play/pause button in the controls but not if I click in the video to pause it or in the timeline in the controls.
Any ideas?
You can listen the mediaelement player click event while initiating the mediaelement player. and once you get the mediaelement player click event you can stop propagation of the event so it does not propagate to outer elements. Here is the code snippet to do above.
$("#myVideo").mediaelementplayer({
// if the <video width> is not specified, this is the default
defaultVideoWidth: 480,
// if the <video height> is not specified, this is the default
defaultVideoHeight: 270,
// if set, overrides <video width>
videoWidth: -1,
// if set, overrides <video height>
videoHeight: -1,
// width of audio player
audioWidth: 30,
// height of audio player
audioHeight: 400,
// initial volume when the player starts
startVolume: 0.8,
// useful for <audio> player loops
loop: false,
// enables Flash and Silverlight to resize to content size
enableAutosize: false,
// the order of controls you want on the control bar (and other plugins below)
features: ["playpause", "progress", "current", "duration", "tracks", "volume", "fullscreen"],
// Hide controls when playing and mouse is not over the video
alwaysShowControls: false,
// force iPad's native controls
iPadUseNativeControls: false,
// force iPhone's native controls
iPhoneUseNativeControls: false,
// force Android's native controls
AndroidUseNativeControls: false,
// forces the hour marker (##:00:00)
alwaysShowHours: false,
// show framecount in timecode (##:00:00:00)
showTimecodeFrameCount: false,
// used when showTimecodeFrameCount is set to true
framesPerSecond: 25,
// turns keyboard support on and off for this instance
enableKeyboard: true,
// when this player starts, it will pause other players
pauseOtherPlayers: true,
// array of keyboard commands
keyActions: [],
//autoPlay the video on load;
autoPlay: false,
//path to get flash player;
pluginPath: 'specify your plugin path here',
//name of the flash;
flashName: "flashmediaelement.swf",
// show mode on browser.
success: function (player, node) {
//Add the custom event here.
player.addEventListener("click", function (e) {
console.log("clicked ", e);
//IE9 & Other Browsers
if (e.stopPropagation) {
e.stopPropagation();
}
//IE8 and Lower
else {
e.cancelBubble = true;
}
});
},
error: function (e) {
//TODO: fires when a problem is detected
}
});
I'm trying to display an iframe in my mobile web application, but I'm having trouble restricting the size of the iframe to the dimensions of the iPhone screen. The height and width attributes on the iframe element seem to have no effect, strangely. Surrounding it with a div manages to constrain it, but then I'm unable to scroll within the iframe.
Has anyone tackled iframes in mobile safari before? Any ideas where to start?
Yeah, you can't constrain the iframe itself with height and width. You should put a div around it. If you control the content in the iframe, you can put some JS within the iframe content that will tell the parent to scroll the div when the touch event is received.
like this:
The JS:
setTimeout(function () {
var startY = 0;
var startX = 0;
var b = document.body;
b.addEventListener('touchstart', function (event) {
parent.window.scrollTo(0, 1);
startY = event.targetTouches[0].pageY;
startX = event.targetTouches[0].pageX;
});
b.addEventListener('touchmove', function (event) {
event.preventDefault();
var posy = event.targetTouches[0].pageY;
var h = parent.document.getElementById("scroller");
var sty = h.scrollTop;
var posx = event.targetTouches[0].pageX;
var stx = h.scrollLeft;
h.scrollTop = sty - (posy - startY);
h.scrollLeft = stx - (posx - startX);
startY = posy;
startX = posx;
});
}, 1000);
The HTML:
<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" id="iframe" src="url" />
</div>
If you don't control the iframe content, you can use an overlay over the iframe in a similar manner, but then you can't interact with the iframe contents other than to scroll it - so you can't, for example, click links in the iframe.
It used to be that you could use two fingers to scroll within an iframe, but that doesn't work anymore.
Update: iOS 6 broke this solution for us. I've been attempting to get a new fix for it, but nothing has worked yet. In addition, it is no longer possible to debug javascript on the device since they introduced Remote Web Inspector, which requires a Mac to use.
If the iFrame content is not yours then the solution below will not work.
With Android all you need to do is to surround the iframe with a DIV and set the height on the div to document.documentElement.clientHeight. IOS, however, is a different animal. Although I have not yet tried Sharon's solution it does seem like a good solution. I did find a simpler solution but it only works with IOS 5.+.
Surround your iframe element with a DIV (lets call it scroller), set the height of the DIV and make sure that the new DIV has the following styling:
$('#scroller').css({'overflow' : 'auto', '-webkit-overflow-scrolling' : 'touch'});
This alone will work but you will notice that in most implementations the content in the iframe goes blank when scrolling and is basically rendered useless. My understanding is that this behavior has been reported as a bug to Apple as early as iOS 5.0. To get around that problem, find the body element in the iframe and add -webkit-transform', 'translate3d(0, 0, 0) like so:
$('#contentIframe').contents().find('body').css('-webkit-transform', 'translate3d(0, 0, 0)');
If your app or iframe is heavy on memory usage you might get a hitchy scroll for which you might need to use Sharon's solution.
This only works if you control both the outside page and the iframe page.
On the outside page, make the iframe unscrollable.
<iframe src="" height=200 scrolling=no></iframe>
On the iframe page, add this.
<!doctype html>
...
<style>
html, body {height:100%; overflow:hidden}
body {overflow:auto; -webkit-overflow-scrolling:touch}
</style>
This works because modern browsers uses html to determine the height, so we just give that a fixed height and turn the body into a scrollable node.
I have put #Sharon's code together into the following, which works for me on the iPad with two-finger scrolling. The only thing you should have to change to get it working is the src attribute on the iframe (I used a PDF document).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Pdf Scrolling in mobile Safari</title>
</head>
<body>
<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" id="iframe" src="data/testdocument.pdf" />
</div>
<script type="text/javascript">
setTimeout(function () {
var startY = 0;
var startX = 0;
var b = document.body;
b.addEventListener('touchstart', function (event) {
parent.window.scrollTo(0, 1);
startY = event.targetTouches[0].pageY;
startX = event.targetTouches[0].pageX;
});
b.addEventListener('touchmove', function (event) {
event.preventDefault();
var posy = event.targetTouches[0].pageY;
var h = parent.document.getElementById("scroller");
var sty = h.scrollTop;
var posx = event.targetTouches[0].pageX;
var stx = h.scrollLeft;
h.scrollTop = sty - (posy - startY);
h.scrollLeft = stx - (posx - startX);
startY = posy;
startX = posx;
});
}, 1000);
</script>
</body>
</html>
<div id="scroller" style="height: 400px; width: 100%; overflow: auto;">
<iframe height="100%" id="iframe" scrolling="no" width="100%" src="url" />
</div>
I'm building my first site and this helped me get this working for all sites that I use iframe embededding for.
Thanks!
Sharon's method worked for me, however when a link in the iframe is followed and then the browser back button is pressed, the cached version of the page is loaded and the iframe is no longer scrollable. To overcome this I used some code to refresh the page as follows:
if ('ontouchstart' in document.documentElement)
{
document.getElementById('Scrolling').src = document.getElementById('SCrolling').src;
}
I implemented the following and it works well. Basically, I set the body dimensions according to the size of the iFrame content. It does mean that our non-iFrame menu can be scrolled off the screen, but otherwise, this makes our sites functional with iPad and iPhone. "workbox" is the ID of our iFrame.
// Configure for scrolling peculiarities of iPad and iPhone
if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1)
{
document.body.style.width = "100%";
document.body.style.height = "100%";
$("#workbox").load(function (){ // Wait until iFrame content is loaded before checking dimensions of the content
iframeWidth = $("#workbox").contents().width();
if (iframeWidth > 400)
document.body.style.width = (iframeWidth + 182) + 'px';
iframeHeight = $("#workbox").contents().height();
if (iframeHeight>200)
document.body.style.height = iframeHeight + 'px';
});
}
Purely using MSchimpf and Ahmad's code, I made adjustments so I could have the iframe within a div, therefore keeping a header and footer for back button and branding on my page. Updated code:
<script type="text/javascript">
$("#webview").bind('pagebeforeshow', function(event){
$("#iframe").attr('src',cwebview);
});
if (navigator.userAgent.indexOf('iPhone') != -1 || navigator.userAgent.indexOf('iPad') != -1)
{
$("#webview-content").css("width","100%");
$("#webview-content").css("height","100%");
$("#iframe").load(function (){ // Wait until iFrame content is loaded before checking dimensions of the content
iframeWidth = $("#iframe").contents().width();
if (iframeWidth > 400)
$("#webview-content").css("width",(iframeWidth + 182) + 'px');
iframeHeight = $("#iframe").contents().height();
if (iframeHeight>200)
$("#webview-content").css("height",iframeHeight + 'px');
});
}
</script>
and the html
<div class="header" data-role="header" data-position="fixed">
</div>
<div id="webview-content" data-role="content" style="height:380px;">
<iframe id="iframe"></iframe>
</div><!-- /content -->
<div class="footer" data-role="footer" data-position="fixed">
</div><!-- /footer -->
Don't scroll the IFrame page or its content, scroll the parent page. If you control the IFrame content, you can use the iframe-resizer library to turn the iframe element itself into a proper block level element, with a natural/correct/native height. Also, don't attempt to position (fixed, absolute) your iframe in the parent page, or present an iframe in a modal window, especially if it has form elements.
I also suspect that iOS Safari has a non-standards behavior that expands your iframe's height to its natural height, much like the iframe-resizer library will do for desktop browsers, which seem to render responsive iframe content at height 0px or 150px or some other not useful default. If you need to contrain width, try a max-width style inside the iframe.
The solution is to use Scrolling="no" on the iframe.
That's it.
I have a drop-down/multi-level CSS menu on a page. The menu however doesn't appear over a flash chart I have. The apparent fix seems to be to put wmode:transparent (or opaque), but that doesn't work for me. I have also tried setting the z-level in the CSS to very high values (2000) but that doesn't work either.
In addition, I'm using open-flash-chart-v2 to generate the chart. (though I don't think it matters, but it limits my ability to pass variables as I'm not using the embed or object tag directly).
<script type="text/javascript">
swfobject.embedSWF("/ofc-library/open-flash-chart.swf", "chart", "100%", "100%", "9.0.0", "expressInstall.swf", {"wmode" : "transparent"});
</script>
Page showing problem (This doesn't currently show the z-index attempt to fix.)
The wmode tag has not been set correctly.
Here is the correct code:
<object width="100%" height="100%" style="visibility: visible;" id="chart" data="/ofc-library/open-flash-chart.swf" type="application/x-shockwave-flash"><param value="transparent" name="wmode"/></object>
Here is your code:
<object width="100%" height="100%" type="application/x-shockwave-flash" data="/ofc-library/open-flash-chart.swf" id="chart" style="visibility: visible;"><param name="flashvars" value="wmode=transparent"/></object>
Specifically:
<param name="flashvars" value="wmode=transparent"/>
should be:
<param value="transparent" name="wmode"/>
Here is how to do it correctly (note the empty hash before the params. wmode is a param not a flashvar):
swfobject.embedSWF("/ofc-library/open-flash-chart.swf", "chart", "100%", "100%", "9.0.0", "expressInstall.swf", {}, {"wmode" : "transparent"})
Because you are using swfObject, try this:
var so = new SWFObject("/ofc-library/open-flash-chart.swf", "chart", "100%", "100%", "9.0.0", "expressInstall.swf");
so.addParam("wmode", "transparent");
so.write("flashcontent");