Cascading Popup Menus v5.2

Overview

This file explains how to go about creating and editing menus using the Cascading Popup Menus JavaScript. If you're not familiar with JavaScript syntax, you may find the Syntax Helper script useful, which can create the relevant commands listed here from selections in forms.

Colour coding used in this document: Variable or Object Name, 'String value', Number value, Boolean value (true or false), File Name.

Conditions of Use

By using this script, you agree that:

  1. EITHER:
    1. Donating Users: This script is "donation-ware". Users who decide to make a donation to support this script may use it without placing a visible link on the resulting website. Please consider making a donation, as I have put in a lot of time developing, debugging and documenting scripts, and any support is welcome.
    2. Free Users: If you download and use this script for free, you must place a visible link on websites using this script to the front page of my site, e.g. 'DHTML / JavaScript by TwinHelix Designs'.
  2. You must leave the "Script Name/Copyright/URL" comment in the source of the script file.
  3. This script is provided on an "AS-IS" basis, without any warranties, and you use it entirely at your own risk.
  4. You must not redistribute this script to third parties, either intact or modified.

If these conditions do not suit your project, please contact me to arrange alternatives.

Files You Need

This script is split over several files:

The pop_core.js and pop_data.js must be included in order, either above the events file (for single frame usage) or in the frameset (for cross-frame usage of the script, see the Frameset Readme for more info).

Menu Data: File Structure

var ItemStyleName = new ItemStyle(...parameters...);

var ObjectName = new PopupMenu('ObjectName');
with (ObjectName)
{
 startMenu(...parameters...);
 addItem(...parameters...);
}

...menu effects and optional code...

First, you create ItemStyles, which are collections of sizes, colours, borders and CSS classnames to be applied to menus and items later. This allows you to give different menus a consistent look and feel.

Then, you create one or more menu objects, giving each a unique name. The example script includes one named pMenu. Each menu object must be passed its own name in quotes.

To these menu objects, you add individual menus using the startMenu and addItem commands.

Finally, the Menu Effects section at the bottom of the file is optional. It contains extra code for borders, dropshadows, animation, custom mouse events in menus (examples like status messages are included), and custom item arrangement. Comments are included there, alongside the functions called. Read through if you're interested. Otherwise, the entire menu effects section can be deleted if you don't want to use them.

ItemStyle()

var ItemStyleName = new ItemStyle( Length, Spacing, 'Popout Indicator', Indicator Position, Padding, 'Out Background', 'Over Background', 'Out Text Class', 'Over Text Class', 'Out Border Class', 'Over Border Class', Out Opacity, Over Opacity, 'Link Cursor', 'Default Cursor');

startMenu()

startMenu( 'Menuname', Orientation, Left Offset, Top Offset, Menu Breadth, Default ItemStyle, 'Parent Frame', Show onclick);

addItem()

addItem( 'Item HTML', 'URL / Menuname / Command', 'Item Type', Custom ItemStyle, Length, Spacing.....);

The addItem() and startMenu() commands return references to the objects they create. One practical use for this is to add an onclick action to an 'sm:' type menu item (that normally cannot navigate to a file), set as evaluable strings. You can also apply onmouseover and onmouseout handlers to items the same way. Suggested syntax:

with(addItem('Text', 'menuName', 'sm:')) onclick='window.location.href="file.html"';

Advanced Positioning (Centering menus etc.)

As mentioned above, the Left and Top positions for each menu can be JavaScript expressions. I've provided several functions in this script with the page object, to detect window dimensions or the position of a named anchor, and use that to align menus. They are:

The values from these expressions are then set as the distance (in pixels) from the upper-left corner of the entire document, to the upper-left corner of the menu in question (this overrides the normal relative positioning from parent menus). You can write your own expressions if you want (and call your own functions perhaps), otherwise here are some cut-and-paste replacements for the standard root menu in the single-frame example:

// Centre the menu, set its left position as half the window width, less half the menu width:
startMenu('root', false, 'page.winW()/2 - pMenu.menu.root[0].menuW/2', 0, 17, hBar);

// Scroll the menu with the page, set its top position to the window scroll position.
startMenu('root', false, 10, 'page.scrollY()', 17, hBar);

// Hover the menu over an anchor <a id="home" name="home"> in the page, positioned 20px below it.
// If you're doing this, you should have the anchor before or near this script in the document,
// a good idea is to move the whole script just before the closing BODY tag.
startMenu('root', false, 'page.elmPos("home").x', 'page.elmPos("home").y + 20', 17, hBar);

If you're using cross-frame menus, include the name of the relevant frame in the expression like so: 'content.page.scrollY()'.

Frameset Readme

This script supports displaying menus in different frames with a few tweaks -- see the demo frameset. To do this, you must include the pop_core.js and any pop_data.js files in the frameset, and include the .CSS and pop_events.js files in ALL documents loaded in the frames. Then, all you have to do is make sure you include a 'parent frame' value with each of your startMenu() commands, so menus will display in the correct frame. There are several restrictions however:

I also recommend you specify item filenames absolutely, e.g. '/folder/file.html', as relative navigation around framesets can get tricky. Item targets are measured relative to the frameset file, so addItem('a', 'b', '') will load 'b' in the whole frameset. Of course, you can set the frame target normally to load files in subframes, like addItem('a', 'b', 'content');

The example setup allows the menus in sub-frames scroll with their windows. All you have to do is use the 'page' object in that frame in a formula to get the current scrolling position of that frame, and then add or subtract pixels to position the menus from the scroll position, e.g. for a menu in a frame named 'xyz', we would set it to appear in that frame and appear near the top and 100px from the left:

startMenu('menuName', false, 'xyz.page.scrollX()+100', 'xyz.page.scrollY()+10', 17, hBar, 'xyz');

Relative positioning works too (that is, numbers as positions), but only really makes sense if the menus are in the same frame or the frames are aligned with each other in the frameset.