Cross-browser, clean solution for drop-down menus across frames? - javascript

Let me start off by saying I really like Superfish (& jQuery). Unfortunately, this - apparently? - does not offer cross-frame support out of the box.
Situation: extranet website, consisting of 2 frames, divided horizontally. The top frame (the smallest one) contains a menu. When hovering over this menu, the "drop down" content gets displayed in the bottom frame (over the other elements there, of course). Here's an example (and actually, the solution we're using today): http://javascript.cooldev.com/scripts/coolmenu/demos/frames/
So does anyone know a way to build a clean (using standard HTML/CSS and as little as JS as possible) solution? Any help would be appreciated! :)

I guess the armies will take on the »ditch your frames« thing, so I won't. I'm assuming you have informed yourself of frameless alternatives and have come to the conclusion that you need frames (for whatever [absurd] reason).
The short story is: you cannot break out of a frame, same as you can't break out of a window. All content is contained within the frame / window - there is no way to have content bleed through.
That said, you have two options left.
Your parent document happens to be a regular document containing two iframes, and all documents are served from the same host (SOP). In this case your menu-frame can create elements in the parent-frame that actually overlap the iframes themselves. So you could position an element within the parent-frame to appear below the corresponding element of the menu-frame, while having it z-indexed over the content-frame
Your parent-frame is a frameset-document and thus doesn't take any content other than frames. You're shit out of luck. The only thing you can do is have your menu-frame do the same trick described in (1), but append the menu-elements to the content-frame.
Either option sucks. If you have the option, ditch your frames. Any dumb server-side language (php, ruby, python, …) allows you to extract often re-used components (like a navigation) into seperate files and link them in every other document you've got. SSI might be an option, too.

If the only reason you're using a frame is to keep the menus attached to the top of the window, then you can simply use position: fixed in the CSS.

Building a drop-down menu system that crosses frames is like building a normal drop-down menu system (mouse over the menu "head", show the menu "body"; mouse out of the head, hide the body; etc.), except:
Since elements cannot actually cross frame boundaries, the best you can do is to have the head in one frame and the body in the other (like COOLjsMenu).
To coordinate the two halves, you can either (depending on the situation) have one frame directly manipulate the other frame's elements, or pass messages between frames and have each frame manage its own elements.
So the extra complication is how to manage the two halves:
If both frames come from the same origin, then JavaScript from one frame can directly manipulate the other frame's elements. (Since you are using COOLjsMenu, I would assume this is the case for your extranet.)
If frames come from different origins, then they cannot manipulate each other's elements, though you may still be able to pass messages between frames:
If you only need to support "modern" browsers (Firefox 3+, Chrome, Safari 4+, IE 8+, Opera 9.5+), then you can use window.postMessage().
If you need to support older browsers (namely IE 6-7), you can use easyXDM (which also uses window.postMessage() if available in the user's browser).
In this case, you will need JavaScript in each frame to manipulate its own elements and communicate with the other frame.
Actually building a cross-frame drop-down menu system is left as an exercise for the reader :-)

You could just use a pure-CSS menu (like http://csswizardry.com/2011/02/creating-a-pure-css-dropdown-menu/). I'm not sure exactly why the navigation is in a different frame, but this will give you the functionality and flexibility to move the drop down lists up or down (by adjusting the padding/margin/top properties in CSS) to fit to the bottom of the frame.

The ideal solution would be to NOT use frames. Instead, you should ideally have your menu setup with a fixed position. The correct CSS for your menu element would be:
position:fixed
You may have to make some other tweaks, such as setting the z-index of your menu to be greater than the rest of your document. If you used fixed positioning, you might be able to get away with using NO javascript. Here are a few examples of menus that use fixed positioning:
Collection of 21 fixed position menus -- For example, the Face Works menu does pretty much the same thing as your menu without using frames.
CSS Floating Menu
CSS: fixed menus
You should note that a frame cannot access content outside of itself. There is no CSS/JavaScript that will let your top frame gain access to the contents of your bottom frame. It would be a security flaw to allow for this to happen. If you really need to use frames then stick with something similar to your current solution.

I hate to play devil's advocate, but you can break out of frames, because at my work we have a JavaScript menu that does just that. It's a very old library but it does do it. You can see the grey frameborders quite clearly and the menu is breaking out of the top frame and appearing over three other frames.

We've used drop down menus with cross frame support before without a too much of a problem. One way to do it is with allwebmenus, a powerful javascript menu builder with lots of really great features, and includes cross frame support out of the box: http://www.likno.com/examples.html?example=crossframe
This page explains how likno does it: http://www.likno.com/drop-down-css-menu/compilepropertiescrossframe.htm.
Deluxe menu also does a similar thing:
http://deluxe-menu.com/data-samples/cross-frame-horizontal-1-sample.htm
and is cheaper if you only want to do it on a single website, but more expensive for multiple sites.

Related

Detect what percentage of viewport is obstructed by another window?

What I'd like to do, if it's technically possible, is leverage JavaScript (frameworks such as jQuery are totally fine, too), to determine what percentage of an inactive browser window might still be in view.
For example, in the image below, imagine I'm working on a project for CNN.com. In this scenario, I know I can use window.onfocus and window.onblur to determine whether the window marked as Background window is in focus or not.
[![enter image description here][1]][1]
However, I'm interested in measuring what percentage of the viewport/page for the Background window is visible to the end user, and/or what percentage of the page for the Background window is not visible. Or, an alternative approach could also be to simply determine whether an element (by ID) is in view on the Background window or it's obstructed by any foreground windows.
After extensive Googling and Stack Overflow searching, I'm not finding a solution for what I'm trying to achieve. This could obviously be due to technical impossibility, but I wanted to ensure I've left no stone unturned in troubleshooting.
The use case here is that I'd like to be able to pause videos and animations, etc. when a given element is not visible on the page -- not just when the window is not active at the moment, since users can often have windows arranged side-by-side, and might want to watch a video while multi-tasking. even though the window might be active at a given moment. Conversely, if a window is covered up, the desire here (for business purposes) is to pause the video, so we are not serving videos (or video ads) when a player is out of view.

Detect whether "overflow: auto" works properly (mobile browsers)

I'd like to detect in some "nice" way (Modernizr most likely, but whatever) whether a layout should have embedded scrollable regions of the page, or else (for some mobile use) should just flow all content as one scrollable mass.
The specific case is a "EULA"-like page, where there's a form with an "I ACCEPT" button or whatever, and then a mass of hideous all-caps legal stuff. On a big screen I'd like the whole form visible, so I'd like to put the legal stuff in its own scrolling box. However, on a mobile device that would be kind-of ugly (though I'm no mobile ux expert), so I was thinking of just dropping it all in-line so that the user could read the text (LOL) with simple swipes to scroll, and then at the bottom the buttons would scroll into view.
I suppose I could just check for touch with Modernizr, but that doesn't seem quite right.
edit — though I'm pretty sure that what I described would probably be a usability win anyway, the thing is I'm finding that my Android devices won't pay any attention to "overflow: auto" on a <div> in the middle of a page.
The approach I've taken is to rely on Modernizr.touch and Modernizr.overflowscrolling tests. If Modernizr inserts the touch and no-overflowscrolling classes in the html element in the DOM (or just check Modernizr.touch and Modernizr.overflowscrolling directly), then I avoid overflow:auto. This means that Android devices that mishandle overflow:auto do not get it.
This might be an imperfect solution; there might be devices that can handle overflow:auto that don't get it in this case. But that's not exactly the end of the world, at least in my case. And it seems to work correctly for all the most common devices/browsers.
And it has the virtue of being simple. I already had Modernizr loaded for other uses.
As others have said, the Modernizr.overflowscrolling checks for the overflow-scrolling css property, not for whether the device can scroll content within a div using overflow: auto.
In fact, in my recent testing, the Nexus 5 actually returns Modernizr.overflowscrolling as false, so it cannot be relied on.
This very small script (with no dependencies) seems to enable touch scrolling for devices (Android 2.3) lacking support...
http://chris-barr.com/2010/05/scrolling_a_overflowauto_element_on_a_touch_screen_device/
Link to repo:
https://github.com/chrismbarr/TouchScroll

Dynamically Resizing Flash Object to Fill Window

I have a Flash/Flex object (Flashlight-VNC), which I would like to dynamically resize to fit the entire window after pressing a button in the Flex app. This would preferably happen without restarting the Flex app (and therefore the VNC session). I would just use the built-in Flash fullscreen mode, however Adobe's somewhat silly security restrictions prevent keyboard input while in fullscreen mode.
How exactly can I do this? I'm already using SWFObject to embed the SWF, if that helps. I am open to any solution utilizing ActionScript, JavaScript, or both, however I am not all too familiar with ActionScript or Flex, and the AS-based solutions I have found involve extending a "Sprite" object to add resize functionality, which Flashlight-VNC does not seem to use.
I see that there is a very similar question already posted on this site, however the accepted answer points to one dead link and another link that does not answer my question (my goal is to resize the object on command, not from when the page loads).
Thanks!
This really isn't related to flash. It's more about HTML DOM manipulation. You want to make sure your Flash SWF is set to use 100%/100% and then when you want to trigger "full screen" mode change the html container to be placed in the top-left-most corner and have a width/height of 100% of screen.
You'll still have the browser's toolbars and tabs and address bar, but if you want keyboard input there aren't many options.

What optimizations does a browser perform when a DOM element is being rendered off screen?

I control an iframe being rendered on another domain. Is there a clear way of telling whether this iframe is being rendered above or below the fold on the parent page? Obviously, I can't access the parent DOM because of the same origin policy restriction.
For example, I tried measuring the speed of rendering on a canvas or VML tag, hoping it would be faster when the tag isn't on screen. This didn't work - there was no discernable speed difference. Ditto for DOM manipulation - there doesn't seem to be a way to differentiate between reflow/repaint operations below or above the fold.
What about flash? I don't have much experience, but could one check how quickly a browser renders flash operations? Or does flash have any 'onvisible' events outside of the DOM standard?
I don't think so.
The same origin policy restriction prevents that, although you can use url parameters, which can be set by the javascript embedding the ad, to the offset on the page.
According to the author of SoundManager2 Scott Schiller, there's a slight difference in the latency of the JS->Flash communication bridge depending on whether the flash movie is on screen or not. That is, it's slower when it is not on screen.
This really varies by-browser, as different browsers interact with the Flash plugin differently. The most precise explanation I could find is on an old connectedpixel post.
At the point of writing, Firefox didn't init a flash object until it was scrolled on page. IE, on the other hand, resized the Stage element when it scrolled into view. No versions of browser, Flash, or OS are given, so this may have changed since that test.
In short, I need to make a flash object and play with it, watching for various events.

Minimum iframe size to avoid scrollbar?

I'm trying to display an iframe, which can be pointed to various urls, and would like to dynamically resize it to display its contents without a scrollbar.
How can I find those dimensions?
I don't think this is possible. Many sites resize their content to fit their container, so resizing the container to fit the content will be messy at best. Additionally, due to the single-origin policy, JavaScript won't be able to inspect the page loaded in the iframe if it comes from another site, so I don't think you'll even be able to tell if it needs to scroll or not.
You could approximate it by calculating the dimensions ahead of time, but even then it would only be a guess, since the exact size of objects in the browser is controlled only by the browser. If the user has picked a large font size, for example, there may be no size you can expand the iframe to that will be big enough for the user to see the entire page without scrolling.
You can only do it by communicating between the iframe and your website. This is the technique OpenSocial gadgets use for example. This is only possible if both the iframe and the parent are under control, in which case you can use HTML5 cross-window messaging and fall back to other cross-domain hacks if the browser can't deal with that.
You could also try to avoid the iframe by pulling the site directly and serving its content. That would only be possible for a very limited number of sites, mostly just static sites, and even then, not ideal by any means.

Categories