/* * Tear Off Menus * * Copyright (c) 2004,2005, Mackley F. Pexton. All rights reserved. * * This file enhances Menu and it should be loaded after menu.js. */ /** Tear Off Menus are menu or submenu panels that have a title bar, a close box button, and (optionally) a resize button in the lower right hand corner. The menus can be grabbed by the user and "detached" from the menus so that they stay on the screen after the menus are hidden. These routines were made to work with AcmeMenu, but they can work independently if the menus are not used (as determined by whether the Menu object is defined). The resize routines need the DOM information routines: getElementLeft() getElementTop() getElementWidth() getElementHeight() getBorderWidth() getElementRef() Browser version flags are also used. They are defined in the following script files. One of them needs to be loaded. -or- A menu can be made detachable by calling the following function: The first argument is the document element's ID to make a tear off menu. The second argument is an object of options. Setting the title option displays the title in the added title bar. Setting the "resize" option to "true" puts a small graphic in the lower right corner of the panel which the user can use to click and drag to a new location. It can also be set to a string of additional comma separated document elements to resize in addition to the main element. The options that are recognized by make_tear_off_menu() are: title -- title to appear in title bar at the top. resize -- true/false to make panel resizable. It also can be a string that is a comma separated list of nodes to resize. close_image -- image to use to display the close box in the upper right corner of title bar. resize_image -- image to use to display the resize image in the lower right corner of the menu. class -- the class name to assign the title bar that is inserted into the top of the menu. object_name -- name of the object to use for the tear-off menu. This is the object that has the start() and stop() methods used as the menu's event handlers. Only one tear-off menu can be displayed at a time with this option. Default values for these options are defined below. **/ /////// Configuration Variables /////////////////////////// make_tear_off_menu.Default_Close_Image = ''; // set in CSS or in options //make_tear_off_menu.Default_Close_Image = '/images/close.gif'; make_tear_off_menu.Default_Title = ''; make_tear_off_menu.Default_Resize = false; make_tear_off_menu.Default_Class = 'menu-banner'; make_tear_off_menu.Default_Object_Name = ''; /////// End of Configuration Variables /////////////////// function make_tear_off_menu(id,opt) { var div = getElementRef(id); if (!div) return; // error if (typeof opt != 'object') opt = {}; var tom = opt['object_name']; if (!tom) tom = make_tear_off_menu.Default_Object_Name; if (!tom) { // Make name of next TearOffMenu control object and make it a global variable. var tom = 'tear_off_menu'+make_tear_off_menu.next_index++; eval (tom+'=new TearOffMenu'); } make_tear_off_menu.get_template(tom,opt); // Transfer tear_off_menu banner to document tree. var clone = make_tear_off_menu.template.childNodes[0].cloneNode(true); div.insertBefore(clone,div.childNodes[0]); if (! div.onmousedown) div.onmousedown = TearOffMenu.focus; if (opt['resize'] == null) opt['resize'] = make_tear_off_menu.Default_Resize; if (opt['resize']) make_resizable(div,opt); } make_tear_off_menu.get_template = function(object_name,opt) { if (opt['title'] == null) opt['title'] = make_tear_off_menu.Default_Title; var title_str = opt['title']; if (opt['class'] == null) opt['class'] = make_tear_off_menu.Default_Class; var class_str = opt['class'] ? (' class="'+opt['class']+'"') : ''; if (opt['close_image'] == null) opt['close_image'] = make_tear_off_menu.Default_Close_Image; var image_str = opt['close_image'] ? ('Close Panel.') : ' '; // Make template HTML. make_tear_off_menu.template.innerHTML='' + '
' + ''+image_str+'' + title_str + '
'; } make_tear_off_menu.next_index = 1; // index to make unique object names make_tear_off_menu.template = document.createElement("DIV"); /* ------------------------------------------------------------------------ */ /** Make Resizable Panel - An interface to Resize Me An easy way to automatically add a resize box to the lower right is to call make_resizable() with the ID of the document element that you want to resize. **/ /////// Configuration Variables /////////////////////////// make_resizable.Default_Resize_Image = '/images/resize.gif'; /////// End of Configuration Variables /////////////////// function make_resizable(id,opt) { var div = getElementRef(id); if (!div) return; // error if (!make_resizable.template || (opt['resize'] && typeof opt['resize'] != 'boolean')) make_resizable.get_template(opt); // Transfer resize image to document tree. var clone = make_resizable.template.childNodes[0].cloneNode(true); div.appendChild(clone); } make_resizable.get_template = function(opt) { if (typeof opt != 'object') opt = {}; var image = opt['resize_image']?opt['resize_image']:make_resizable.Default_Resize_Image; var img = new Image; img.src = image; // Element IDs of objects to resize. var resize_objects = 'this.parentNode.parentNode.parentNode'; // main object if (typeof opt['resize'] == 'string') resize_objects += ','+"'"+opt['resize']+"'"; // Build image and surround it with DIV tags to position it in lower right corner. // IE works better with a
whereas Mozilla likes using a better. // (IE wants to select and then drag and drop the tags.) make_resizable.template=document.createElement("DIV"); make_resizable.template.innerHTML='' + '
' + '
' + (bv.isIE ? '
' + (bv.isIE ? '
' : '') + '
' + '
'; } /* ------------------------------------------------------------------------ */ /* * Tear Off Menus * * Copyright (c) 2004, Mackley F. Pexton. All rights reserved. */ /** The TearOffMenu object tracks torn-off menus. It encompasses the move_me() methods below that are used to let the user to position a menu in the window. Hook up the methods to a document element like:
something
**/ function TearOffMenu() { // Object constructor tracking a tear-off menu. this.e = null; this.left = '0px'; this.top = '0px'; this.is_torn = false; } TearOffMenu.prototype.start = function(evt,e) { this.e = e; this.left = e.style.left; this.top = e.style.top; move_me.start(evt,e); if (self.Menu) { // Setup menu var m = Menu.menus[this.e.id]; if (!m) return; m.tear_off_menu = this; m.is_located = false; if (! m.onmouseover_tear_off) { m.onmouseover_tear_off = this.e.onmouseover; this.e.onmouseover = null; } if (! m.onclick_tear_off) { m.onclick_tear_off = this.e.onclick; this.e.onclick = null; } } } TearOffMenu.prototype.stop = function() { move_me.stop(); if (this.e.style.left != this.left || this.e.style.top != this.top) { this.is_torn = true; this.left = this.e.style.left; this.top = this.e.style.top; } } TearOffMenu.prototype.close = function() { this.is_torn = false; this.e.style.display = 'none'; if (self.Menu) { // Reset menu var m = Menu.menus[this.e.id]; if (!m) return; m.do_hide_menu(); m.tear_off_menu = null; if (m.onmouseover_tear_off) { this.e.onmouseover = m.onmouseover_tear_off; m.onmouseover_tear_off = null; } if (m.onclick_tear_off) { this.e.onclick = m.onclick_tear_off; m.onclick_tear_off = null; } } } // // Event handler to bring menu to the front when clicked on. // TearOffMenu.focus = function(evt) { evt = evt ? evt : window.event; e = evt.target ? evt.target : evt.srcElement; while (e && (e.nodeName != 'DIV' || ! e.id || ! Menu.menus[e.id])) e = e.parentNode; if (!e) return; move_me.focus(evt,e); } /* ------------------------------------------------------------------------ */ /* * Move Me * * Copyright (c) 2004-2005, Mackley F. Pexton. All rights reserved. */ /** The move_me() object methods allow a user to "grab" a document element with the mouse and move it to another position on the screen. Hook up the methods to a document element like:
something
**/ function move_me(evt) { // onmousemove handler if (!move_me.e) return; evt = evt ? evt : window.event ? window.event : null; if (document.selection && document.selection.empty) document.selection.empty(); //IE if (window.getSelection && window.getSelection().removeAllRanges) window.getSelection().removeAllRanges(); // Moz var l = (evt.pageX?evt.pageX:evt.clientX) - move_me.xdiff; var t = (evt.pageY?evt.pageY:evt.clientY) - move_me.ydiff; move_me.e.style.left = l+'px'; move_me.e.style.top = t+'px'; if (move_me.e.style.pixelTop != null) move_me.e.style.pixelTop = t; // Opera5 } move_me.start = function(evt,e) { // onmousedown handler var l = parseInt(e.style.left,10); if (isNaN(l)) l = 0; var t = parseInt(e.style.top,10); if (isNaN(t)) t = 0; move_me.xdiff = (evt.pageX?evt.pageX:evt.clientX)-l; move_me.ydiff = (evt.pageY?evt.pageY:evt.clientY)-t; move_me.e = e; move_me.focus(evt,e); move_me.attach_document_event_handlers(); move_me(evt,e); } move_me.stop = function() { // onmouseup handler move_me.e = null; move_me.unattach_document_event_handlers(); } move_me.focus = function(evt,e) { // Bring movable panel to forefront. // Refrain from setting zIndex unless needed because Mozilla resets // the user's position in