UserControl to block/hide/overlay all other controls on the page - asp.net

Say I've made a user control. I want it to have following behavior:
When its Visible property is true, users can only operate things inside it, but not anything outside of it, i.e. any other control in its containing user controls (if any) and the page is not accessible to users. (Even better if they'd also be invisible to users.)
The above effect lasts between postbacks, until its Visible is changed to false. When that happens, this user control is invisible to users, and stuff outside it are back to their normal state.
How can this be achieved?

One nice way would be to say have the UC in a div. You then pop the div with a dialog (jquery.UI dialog). When such a dialog is display, then the screen background goes gray, and only the control is visible. And if you click/use any button in that control that causes a page post-back, then it will collapse, disappear, and the page is back to normal with user being able to use.
The effect looks like this:
here is a GV to edit data. When I hit edit button, I display my UC (to edit the one row).
So, this grid:
so, this is a round about way to acheive your goal. By popping a div (with the UC inside), then we solue the "UI" for the user, focus for user in/on/looking at the pop dialog, and better yet, the whole screen background goes gray, and the user cannot select/use/click on any control on the page.
The above idea might not work for you, but if it can be adopted, then all of your messay code and handstands to disable the rest of the page is automatic done for you.
As noted, we all quite much have jQuery installed. You have to add jQuery.UI.
the code to pop the above dialog is thus then this:
<script>
function popedit() {
MyPWidth = "62em"
MyWidth = $(window).width()
if (MyWidth < 840) {
MyPWidth = (MyWidth - 25) + 'px'
}
var myDialog = $("#EditRecord");
myDialog.dialog({
title: "Edit Hotel",
width: MyPWidth,
modal: true,
appendTo: "form",
dialogClass : "dialogWithDropShadow",
close: myclose
});
}
So, above pops the "div" called EditRecord, and it does the rest for you.

It turned out to be actually pretty easy:
Lay a <div class="overlay"></div> as the topmost element inside the user control, enclosing any other elements and child controls. And define a .overlay class in the site CSS stylesheet as something like this:
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
overflow: auto;

Related

Ipad Safari - Can't scroll page if scrolling inside iframe

Is it possible to continue scrolling through a webpage even if you are touching inside an iframe? This problem only happens with iOS devices and I couldn't find any solutions for this!
My current page contains an iframe in the middle with width:95% and about 500px height, so when I reach the iframe I can't scroll any more (unless I touch very close to the sides).
Thanks
In my case, I had full access to the iframe and was dynamically inserting its content. Still, none of the solutions suggested by Brandon S worked. My solution:
Create a transparent div overlaying the iframe.
Capture any click events on the overlay and replicate them within the iframe (to allow the user to click on links/buttons)
This works because the overlaying div is part of the outer document, making it respond to touch/click events normally, and prevents the user from directly interacting with the iframe content.
Html Template:
<div style="position: relative;">
<div
style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; opacity: 0;"
ng-click="$ctrl.handleOverlayClick($event)"
></div>
</div>
Controller (AngularJS component)
...
constructor ($document, $element) {
this.iframe = $document[0].createElement('iframe');
this.iframe.width = '100%';
this.iframe.height = '100';
this.iframe.sandbox = 'allow-same-origin allow-scripts allow-popups allow-forms allow-top-navigation';
const element = $element[0].children.item(0);
element.appendChild(this.iframe);
this.contentDocument = this.iframe.contentDocument;
}
handleOverlayClick ($event) {
// Overlay element is an invisible layer on top of the iframe. We use this to
// capture scroll events which would be in the iframe (which don't work properly on iPad Safari)
// When a click is detected, we propigate that through to the iframe so the user can click on links
const rect = $event.target.getBoundingClientRect();
const x = $event.clientX - rect.left; // x position within the iframe
const y = $event.clientY - rect.top; // y position within the iframe
// triggering click on underlaying element
const clickedElement = this.contentDocument.elementFromPoint(x, y);
clickedElement && clickedElement.click();
}
It sounds like the iframe is receiving the user's scroll event, instead of the page. This can happen when part of the iframe's content doesn't fit within the size of the iframe element.
A solution to this problem is to stop the iframe from ever trying to scroll. There are few ways to accomplish this:
In iframe's HTML, add this CSS:
html, body {
overflow: hidden
}
If you don't have access to the iframe's HTML (because maybe the iframe is loading a 3rd party's content), you can put a wrapper div around the iframe and disable scrolling that way. Add this to the parent page HTML:
<div style="overflow: hidden"><iframe src="example.com"></iframe></div>
You can add this to the parent page HTML CSS to make browser use momentum so that ends up scrolling past the bottom of the iframe and then scrolls the page:
*{
-webkit-overflow-scrolling: touch
}
Add the legacy "scrolling" attribute to the iframe to stop the iframe from trying to scroll:
<iframe src="example.com" scrolling="no"></iframe>

Bootstrap modal at top of iframe regardless of scroll position. How do I position it on screen?

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.

Why don't click events trigger in Chrome when :active shifts the text?

I have some custom styles for buttons. To simulate the 3D look of it being pressed, I'm shifting the text down a few pixels using the :active pseudo-class, like this:
input[type=button] {
padding-top: 4px;
padding-bottom: 4px;
}
input[type=button]:active {
padding-top: 6px;
padding-bottom: 2px;
}
Trouble is, when I do this, in Chrome there are 2 pixels of dead space under the text. When those pixels are clicked, the "click" event is not triggered.
You can see it in action here: http://jsfiddle.net/yg775/ I exaggerated the shifting to make it more obvious. Click below the text on the button to see the effect.
Observations:
The size of the dead space is directly proportional to the number of pixels I am shifting the text.
The dead space is only under the text. Moving the mouse left or right on the X axis, you can see that the click event triggers when not directly under the text.
This only happens on Google Chrome
Someone else noticed this a while ago (Small dead space on a div button in chrome) but this problem is actually more pervasive than just the case he mentioned. Also the "answer" was to trigger on mousedown, but that won't work for me. "click" has different behavior than "mousedown", and I need "click".
Any thoughts how to get around this?
Unfortunately, it seems to be a bug with the .click() command: https://stackoverflow.com/a/5081144. In summary (quoted from above link):
If you mousedown on the padding move the mouse and mouseup on the padding, click event fires.
If you mousedown on the padding move the mouse but now mouseup on the text, there is no click event.
Since you need to use the .click() command, here may be a fix: http://jsfiddle.net/yg775/12/.
JQuery:
$('#button_box').mousedown(function() {
clicked = true;
});
$('#button_box').mouseup(function() {
if (clicked) {
paddingClicked = true;
$("#button_box").trigger( "click" );
}
});
$(document).mouseup(function() {
if (!paddingClicked) {
clicked = false;
}
});
$('#button_box').click(function() {
clicked = false;
if (paddingClicked) {
numClicks++;
$('#display').text(numClicks.toString()+' clicks');
paddingClicked = false;
}
});
I have a container div called button_box that gets used with .mousedown() and .mouseup(). These set two flags, which then calls .trigger( "click" ) that simulates a click.
The $(document).mouseup(...) is in place to catch if you click in the button and then drag the mouse outside before the .mouseup() buttons is called to reset the flag. Without it, you can then click outside of the button and then drag the mouse back in and it would register the .mouseup(). A bit hacky, but it works.

how to fill div with full height of page in css? (page is taller than 100%) for ajax loading gif background

ok there are several similar questions but not quite anything that I want.
I have few ajax requests on page and I want to show the image in the center of the screen, and its all working OK.
Just to make it look more prominent, I wanted to place that image on a div with translucent background, so its more obvious for the end users. Now comes the tricky part.
I made the div with css like this:
.divLoadingBackground
{
filter: Alpha(Opacity=40); -moz-opacity:0.4; opacity: 0.4;
width: 100%;
height: 100%;
background-color: #333;
position: fixed;
top: 0px;
left: 0px;
}
This fills the page up alright, or, I should say, this fills the viewport. If I scroll the page down, the page is again normal. I want this div to span the ENTIRE LENGTH of the page, no matter how long the page is.
Here is an example mockup of the problem I made to quickly demonstrate:
As you can see, I took the example of SO for the mockup ;) image 1 shows that its okay when it appears. image 2 shows that it goes up with the page on scroll.
I'm a c# developer and css is as alien to me as ancient latin.
How to make this divLoadingBackground div to fill out the entire length of the page?
Many thanks for any help.
If you need any additional info, please comment!
One thing I dont see in your css is z-index. Fixed, although, fixes this problem, sometimes, based on how other divs are positioned, your divLoadingBackground div could end up in one of the divs.
try adding
z-index: 9999;
or something similar and see if it works.
Would have put this in a comment, but it seems I have too low rep to comment.
Where is the .divLoadingBackground div located in the DOM tree? Since it has fixed position, it shouldn't scroll with the page. This makes me belive that the element is too deeply nested. Try putting it right in the body level of the page and see if that helps.
Also, are you sure that some other css directive isn't changing the position attribute to absolute or something?
Also, make sure to use the right DOCTYPE. That has some impact on fixed position elements.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Oh, and ofcourse, fixed position isn't supported in IE6 and below.
I believe you will need JavaScript/jQuery to dynamically set the height of the div in question to the height of the page once rendered.
And if you're entering the world of web, it's time to learn that new language "CSS" as well as perpahs-not-quite-as-daunting JavaScript.
When I needed such a functionality some years ago, I examined how Google Calendar did it.
Basically, they use a timer-driven JavaScript file that checks for the height of the window and adjust the height of a contained DIV tag accordingly (or of an IFRAME tag, just any container tag that you like).
Here is a code snippet from a page I worked on:
<script type="text/javascript">
document.getElementsByTagName("body")[0].style.height = "100%";
document.getElementsByTagName("html")[0].style.height = "100%";
document.getElementsByTagName("body")[0].style.minHeight = "100%";
document.getElementsByTagName("html")[0].style.minHeight = "100%";
function height()
{
try
{
height_iframe();
}
catch(err)
{
}
}
window.onload=height;
// --
var ie6WorkaroundIFrameResize = 1;
function height_iframe()
{
var any = false;
var offset = 300;
var c = document.getElementById("iframecontent");
if ( c!=null )
{
c.style.height = (GetClientHeight()-offset)+"px";
any = true;
var d = document.getElementById("iframeie6");
if ( d!=null )
{
d.style.height = (GetClientHeight()-(offset+ie6WorkaroundIFrameResize))+"px";
any = true;
ie6WorkaroundIFrameResize = 0;
}
}
if ( any )
{
setTimeout( 'height_iframe()', 300 );
}
}
function GetClientHeight()
{
return document.documentElement.clientHeight;
}
</script>
Basically, the script regularly checks for the height of the window via the GetClientHeight() function and adjusts the element in concern ("iframecontent") accordingly.
I subtract some offsets of fixed-height headers and footers.
AFAIK you would need to set the size of this divthrough javascript. I would recommend using jQuery, in this way :
//$(document).height() gives the size of the document
//(as opposed to $(window).height() that would give the size of the viewport
$("div#overlay").css('height',$(document).height());

is there a way to increase the length tooltip is displayed in asp.net chart?

I have a chart that displays a tooltip (string) when hovered over. Is there a way to control the delay/time the tooltip is displayed to the user?
<asp:Chart runat="server" ID="Chart2" Width="340px" Height="265px">
<!--Define Things in here-->
</asp:Chart>
Backend:
//define what rec is
string tooltip = rec;
Chart2.ToolTip = tooltip;
I just came up with a pretty simple solution to this classic problem with the help of some Javascript I borrowed from here: http://bonrouge.com/~js_tooltip
Asp.NET renders tooltips as a title attribute on the actual HTML page generated. You can take advantage of this fact to apply whatever style you like to the tooltip by overriding it with two very simple javascript functions.
function showTooltip(control) {
var ttext = control.title;
var tt = document.createElement('SPAN');
var tnode = document.createTextNode(ttext);
tt.appendChild(tnode);
control.parentNode.insertBefore(tt, control.nextSibling);
tt.className = "tooltipCss";
control.title = "";
}
function hideTooltip(control) {
var ttext = control.nextSibling.childNodes[0].nodeValue;
control.parentNode.removeChild(control.nextSibling);
control.title = ttext;
}
Next you need to design your css for your tooltip:
position:absolute;
border:1px solid gray;
width:300px;
margin:1em;
padding:3px;
background: Red;
Finally you need to wire up the JavaScript to your control
Chart2.Attributes.Add("onmouseover", "showTooltip(this)");
Chart2.Attributes.Add("onmouseout", "hideTooltip(this)");
Hope this helps.... I've been looking for a SIMPLE way of doing Tooltips for all my Asp.Net stuff for ages. I don't like to declare my Tooltip code in separate spans or whatever as this is really no good for my dynamically generated stuff. Anyway I just wanted to add this somewhere online. Hope it helps someone out.
Sorry, but probably not.
Most tooltips are a browser feature, and display either the alt tag of an img, or the title tag of most elements. So the control of how long that tooltip displays is going to vary from browser to browser.
It's possible that the tooltip is under your control, and is an html element displayed with javascript on mouseover, or the charts and the tooltip might be in Flash or Silverlight, but if that's the case we'd need to see your code.
I'm guessing probably not. If you need more flexibility I would recommend going with a jQuery tooltip solution.
To add to Ravendarksky's answer: I used his code but if I moved my mouse during the mouseout event over the tooltip content, IE would issue an unhandled exception (no issues in Chrome, I did not check Firefox):
0x800a138f - JavaScript runtime error: Unable to get property 'nodeValue' of undefined or null reference
So I simply wrapped the implementation of hideTooltip in a conditional checking for null and all was well in IE [and Chrome]:
function hideTooltip(control) {
if (control.nextSibling.childNodes[0] != null) {
var ttext = control.nextSibling.childNodes[0].nodeValue;
control.parentNode.removeChild(control.nextSibling);
control.title = ttext;
}
Or you can use HoverMenuExtender of asp.net. You can also modify the pop up content/design.
Code reference sample here: http://asp-net-example.blogspot.com/2009/11/ajax-hovermenuextender-how-to-use.html

Resources