[fusion-commits] r1482 - in sandbox/jx2: jx jx/images
jx/images/delicious jx/lib lib templates/mapguide/standard
templates/mapserver/standard widgets
svn_fusion at osgeo.org
svn_fusion at osgeo.org
Thu Aug 28 08:29:20 EDT 2008
Author: pagameba
Date: 2008-08-28 08:29:20 -0400 (Thu, 28 Aug 2008)
New Revision: 1482
Added:
sandbox/jx2/jx/images/delicious/
sandbox/jx2/jx/images/delicious/button_bg.png
sandbox/jx2/jx/images/delicious/dialog_chrome.png
sandbox/jx2/jx/images/delicious/dialog_resize.png
sandbox/jx2/jx/images/delicious/emblems.png
sandbox/jx2/jx/images/delicious/flyout_chrome.png
sandbox/jx2/jx/images/delicious/tree.png
sandbox/jx2/jx/images/panel_controls.png
sandbox/jx2/jx/lib/jxlib.js
sandbox/jx2/jx/lib/jxlib.uncompressed.js
sandbox/jx2/jx/lib/jxskin_border.css
sandbox/jx2/jx/lib/jxskin_delicious.css
Removed:
sandbox/jx2/jx/css/
sandbox/jx2/jx/lib/jx_combined.css
sandbox/jx2/jx/lib/jx_combined.js
sandbox/jx2/jx/lib/jx_compressed.js
Modified:
sandbox/jx2/jx/images/close.png
sandbox/jx2/jx/images/disclose.png
sandbox/jx2/jx/images/help.png
sandbox/jx2/jx/images/maximize.png
sandbox/jx2/jx/images/minimize.png
sandbox/jx2/jx/images/tree_folder.png
sandbox/jx2/jx/images/tree_folder_open.png
sandbox/jx2/jx/images/tree_last_node.png
sandbox/jx2/jx/images/tree_minus.png
sandbox/jx2/jx/images/tree_node.png
sandbox/jx2/jx/images/tree_none.png
sandbox/jx2/jx/images/tree_page.png
sandbox/jx2/jx/images/tree_plus.png
sandbox/jx2/lib/ApplicationDefinition.js
sandbox/jx2/lib/ButtonTool.js
sandbox/jx2/lib/Map.js
sandbox/jx2/lib/MenuBase.js
sandbox/jx2/lib/fusion.js
sandbox/jx2/templates/mapguide/standard/index.html
sandbox/jx2/templates/mapserver/standard/ApplicationDefinition.xml
sandbox/jx2/templates/mapserver/standard/index.html
sandbox/jx2/widgets/ColorPicker.js
sandbox/jx2/widgets/EditableScale.js
sandbox/jx2/widgets/LayerManager.js
sandbox/jx2/widgets/Legend.js
sandbox/jx2/widgets/MapMenu.js
sandbox/jx2/widgets/Measure.js
sandbox/jx2/widgets/Navigator.js
sandbox/jx2/widgets/Print.js
sandbox/jx2/widgets/SaveMap.js
sandbox/jx2/widgets/SelectionPanel.js
sandbox/jx2/widgets/TaskPane.js
sandbox/jx2/widgets/ViewOptions.js
Log:
first cut, things more or less working
Modified: sandbox/jx2/jx/images/close.png
===================================================================
(Binary files differ)
Added: sandbox/jx2/jx/images/delicious/button_bg.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/delicious/button_bg.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: sandbox/jx2/jx/images/delicious/dialog_chrome.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/delicious/dialog_chrome.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: sandbox/jx2/jx/images/delicious/dialog_resize.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/delicious/dialog_resize.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: sandbox/jx2/jx/images/delicious/emblems.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/delicious/emblems.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: sandbox/jx2/jx/images/delicious/flyout_chrome.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/delicious/flyout_chrome.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: sandbox/jx2/jx/images/delicious/tree.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/delicious/tree.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: sandbox/jx2/jx/images/disclose.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/help.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/maximize.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/minimize.png
===================================================================
(Binary files differ)
Added: sandbox/jx2/jx/images/panel_controls.png
===================================================================
(Binary files differ)
Property changes on: sandbox/jx2/jx/images/panel_controls.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: sandbox/jx2/jx/images/tree_folder.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_folder_open.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_last_node.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_minus.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_node.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_none.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_page.png
===================================================================
(Binary files differ)
Modified: sandbox/jx2/jx/images/tree_plus.png
===================================================================
(Binary files differ)
Deleted: sandbox/jx2/jx/lib/jx_combined.css
===================================================================
--- sandbox/jx2/jx/lib/jx_combined.css 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/jx/lib/jx_combined.css 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,1105 +0,0 @@
-/*
-Copyright (c) 2006, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.net/yui/license.txt
-version: 0.11.0
-*/
-body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}
-table{border-collapse:collapse;border-spacing:0;}
-fieldset,img{border:0;}
-address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}
-ol,ul {list-style:none;}
-caption,th {text-align:left;}
-h1,h2,h3,h4,h5,h6{font-size:100%;}
-q:before,q:after{content:'';}
-/*
-DMSG additions for Jx
-*/
-a{outline:none;}
-.png24{filter:expression(Jx.applyPNGFilter(this))}
-.jxClearer{display:block;position:relative;float:none;clear:both;font-size:0;line-height:0;width:0;height:0;margin:0;padding:0;}
-.jxDisabled{opacity:0.4;-moz-opacity:0.4;filter:Alpha(opacity=40);}
-/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* ============= */
-/* BUTTON STYLES */
-/* ============= */
-
-div.jxButtonContainer {
- display: block;
- position: relative;
- float: left;
-}
-
-/* jxButtons consist of an A, containing a SPAN, which contains an image.
- Buttons can use the sliding door technique with background images to horizontally
- accomodate icons with labels. */
-
-a.jxButton {
- display: block;
- position: relative;
- float: left;
-}
-
-span.jxButtonSpan {
- /* If using background images, the SPAN contains the right side of the background */
- /* use padding to make space between the icon and button edge */
- /* padding-left: 0px;*/ /* butts up to the left of the button bg image */
- display: block;
- position: relative;
- float: left;
- font-size: 0px;
- line-height: 0px;
-}
-
-img.jxButtonIcon {
- position: relative;
- float: left;
-}
-
-span.jxButtonLabel {
- display: block;
- position: relative;
- float: left;
- cursor: pointer;
-}
-
-span.jxButtonLabel.jxButtonEmptyLabel {
- /* collapse empty labels */
- padding: 0px;
- width: 0px;
- overflow: hidden;
-}
-
-.jxButtonMenu a span.jxButtonLabel.jxButtonEmptyLabel,
-a.jxButtonFlyout span.jxButtonLabel.jxButtonEmptyLabel {
- /* expand empty labels that have a menu */
- overflow: visible;
-}
-
-span.jxButtonEmptyLabel {
- /* collapse empty labels for FF */
-}
-
-.jxFlyout {
- position: absolute;
- display: block;
- clear: both;
- float: none;
- top: 100%;
- left: 0px;
- z-index: 100;
-}
-
-.jxButtonContentTop .jxFlyout {
- top: auto;
- bottom: 100%;
-}
-
-.jxButtonContentLeft .jxFlyout {
- left: auto;
- right: 0px;
-}
-/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* =================== */
-/* COLOR PICKER STYLES */
-/* =================== */
-
-/*.jxColorPicker {
- position: absolute;
- display: none;
- top: 100%;
- width: 212px;
- left: 0px;
- border: 1px solid #000;
- padding: 2px;
- background-color: #eee;
-}*/
-
-.jxColorBar {
- position: relative;
-}
-
-table.jxColorGrid {
- position: relative;
- border-collapse: collapse;
- empty-cells: show;
- clear:both;
-}
-
-.jxColorGrid td {
- border: 1px solid #000;
-}
-
-.jxColorGrid td.emptyCell {
- border: 0px solid #000;
-}
-
-.jxColorGrid td.emptyCell span {
- display: block;
- width: 7px;
- height: 7px;
- line-height: 0px;
- font-size: 0px;
- border: 0px solid #000;
- padding: 1px;
- margin: 0px;
-}
-
-.jxColorGrid a.colorSwatch {
- display: block;
- width: 7px;
- height: 7px;
- line-height: 0px;
- font-size: 0px;
- border: 0px solid #000;
- margin: 0px;
- padding: 1px;
-}
-
-.jxColorGrid a.borderWhite:hover {
- border: 1px solid #fff;
- padding: 0px;
-}
-
-.jxColorGrid a.borderBlack:hover {
- border: 1px solid #000;
- padding: 0px;
-}
-
-input.jxHexInput {
- width: 55px;
- vertical-align: middle;
-}
-
-input.jxAlphaInput {
- width: 30px;
- vertical-align: middle;
-}
-
-div.jxColorPreview {
- float: left;
- position: relative;
- width: 20px;
- height: 20px;
- border: 1px solid #000;
- margin: 2px;
- vertical-align: middle;
- background-image: url('../images/grid.png');
-}
-
-div.jxColorButtonPreview {
- float: left;
- width: 14px;
- height: 14px;
- border: 1px solid #000;
- background-image: url('../images/grid.png');
-}
-
-div.jxColorButtonPreview div {
- width: 14px;
- height: 14px;
- position: absolute;
-}
-
-div.jxColorPreview img {
- position: absolute;
- z-index: 0;
-}
-
-div.jxColorPreview div {
- width: 20px;
- height: 20px;
- position: absolute;
- z-index: 1;
-}
-
-
-label.jxColorLabel,
-label.jxAlphaLabel {
- width: auto;
- font-family: Arial, sans-serif;
- font-size: 12px;
- line-height: 24px;
- padding: 2px;
- vertical-align: middle;
-}
-
-a.jxColorClose {
- position: absolute;
- top: 0px;
- right: 0px;
- width: 20px;
- height: 20px;
-}
-
-a.jxColorClose img {
- width: 20px;
- height: 20px;
-}/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* ============= */
-/* DIALOG STYLES */
-/* ============= */
-
-.jxDialogContainer {
- position:absolute;
- display: block;
- font-size: 0px;
- line-height: 0px;
-}
-
-.jxDialog {
- display: block;
- z-index: 1;
-}
-
-.jxDialogModal {
- position: absolute;
- display: block;
- top: 0px;
- left: 0px;
- width: 100%;
- height: 100%;
-}
-
-.jxDialogBgTL,
-.jxDialogBgT,
-.jxDialogBgTR,
-.jxDialogBgR,
-.jxDialogBgBR,
-.jxDialogBgB,
-.jxDialogBgBL,
-.jxDialogBgL {
- position: absolute;
-}
-
-.jxDialogBgTL img,
-.jxDialogBgT img,
-.jxDialogBgTR img,
-.jxDialogBgR img,
-.jxDialogBgBR img,
-.jxDialogBgB img,
-.jxDialogBgBL img,
-.jxDialogBgL img {
- position: relative;
-}
-
-.jxDialogTitle {
- position: relative;
- display: block;
-}
-
-
-/* the Dialog Help Area is likely to be depricated */
-
-.jxDialogHelp {
- position: absolute;
- left: 100%;
- top: 21px;
- width: 200px;
- height: 100px;
- border: 1px solid #999;
- background-color: #fff;
- overflow: auto;
- padding: 0px;
-}
-
-.jxDialogHelpCloseButton {
- position: absolute;
- top: 2px;
- right: 2px;
-}
-
-.jxDialogContent {
- position:relative;
- overflow: auto;
- display: block;
-}
-
-.jxDialogAction {
- position: relative;
- overflow: hidden;
- display: block;
-}
-
-.jxDialogCloseButton,
-.jxDialogHelpButton {
- position: absolute;
- display: block;
-}
-
-.jxDialogResize {
- position: absolute;
-}
-
-iframe.jxDialogShim {
- position:absolute;
- top: 0px;
- left: 0px;
- width: 100%;
- height: 100%;
- filter: Alpha(opacity:0);
- opacity: 0;
- -moz-opacity: 0;
- z-index: -1;
-}.jxGridContainer {
- position: absolute;
- top: 0;
- left: 0;
- border-left: 0px solid #96a7b4;
- border-top: 0px solid #96a7b4;
- border-right: 1px solid #96a7b4;
- border-bottom: 1px solid #96a7b4;
- overflow: hidden;
- font-family: Arial, Verdana, sans-serif;
- font-size: 12px;
- font-weight: normal;
-}
-
-.jxGridTable {
- position: relative;
- table-layout: fixed;
- border-collapse: collapse;
- border-style: none;
- width: 0px;
-}
-
-.jxGridColHeadHide {
- height: 0px;
- line-height: 0px;
- font-size: 0px;
- background-color: #fff;
- white-space: normal;
-}
-
-.jxGridColHeadHide p, .jxGridRowHeadHide p {
- font-size: 0px;
- line-height: 0px;
- height: 0px;
- margin: 0px;
- padding: 0px;
-}
-
-.jxGridRowHeadHide {
- width: 0px;
- white-space: normal;
-}
-
-.jxGridCell {
- border-right: 1px solid #cecece;
- border-bottom: 1px solid #cecece;
- overflow: hidden;
- padding-left: 3px;
- padding-right: 3px;
- overflow: hidden;
- /* can change this to normal */
- white-space: nowrap;
- /* only applies in IE and Safari right now */
- text-overflow: ellipsis;
-}
-
-.jxGridColHead {
- border-top: 0px solid #96a7b4;
- border-right: 1px solid #96a7b4;
- border-bottom: 1px solid #96a7b4;
- border-left: 0px solid #96a7b4;
- background-color: #ebebeb;
- text-align: center;
- font-weight: bold;
- color: #45525f;
-}
-
-.jxGridRowHead {
- border-top: 0px solid #96a7b4;
- border-right: 1px solid #96a7b4;
- border-bottom: 1px solid #96a7b4;
- border-left: 0px solid #96a7b4;
- background-color: #ebebeb;
- text-align: center;
- font-weight: bold;
- color: #45525f;
-}
-
-.jxGridRowAll {
- background-color: #fff;
-}
-
-.jxGridRowOdd {
- /*background-color: pink;*/
-}
-
-.jxGridRowEven {
- /*background-color: lime;*/
-}
-
-.jxGridRowOdd td {
- border-right: 1px solid #999;
- border-bottom: 1px solid #999;
-}
-
-.jxGridRowEven td {
- border-right: 1px solid #999;
- border-bottom: 1px solid #999;
-}
-
-.jxGridRowSelected {
- background-color: #dae6f2;
-}
-
-.jxGridColumnSelected {
- background-color: #dae6f2;
-}
-
-.jxGridCellSelected {
- background-color: #dae6f2;
-}
-
-.jxGridRowPrelight {
- background-color: #f2f2f2;
-}
-
-.jxGridCellPrelight {
- /*background-color: green;*/
-}
-
-.jxGridRowHeaderPrelight {
- background-color: #dfdfdf;
-}
-
-.jxGridColumnHeaderPrelight {
- background-color: #dfdfdf;
-}
-
-.jxGridRowHeaderSelected {
- background-color: #6d7f8e;
- color: #fff;
-}
-
-.jxGridColumnHeaderSelected {
- background-color: #6d7f8e;
- color: #fff;
-}/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* ============== */
-/* JX MENU STYLES */
-/* ============== */
-
-/* Jx Menus and Sub-menus are all built out of nested ULs
- For this to work visually, the margins and padding need to be flattened
- out, and the list marker needs to be hidden
-*/
-
-ul.jxMenu, ul.jxSubMenu {
- /* this allows menus and submenus to be re-positioned */
- position: absolute;
- display: block;
- clear: both;
- float: none;
- /* this allows menus and sub menus to appear above everything */
- z-index: 100;
- list-style-type: none;
-}
-
-ul.jxMenu {
- top: 100%;
- left: 0px;
-}
-
-.jxButtonContentTop ul.jxMenu {
- top: auto;
- bottom: 100%;
-}
-
-.jxButtonContentLeft ul.jxMenu {
- left: auto;
- right: 0px;
-}
-
-li.jxMenuItem, li.jxSubMenuItem {
- /* This is needed for IE to make sure submenus don't open space in the parent menu */
- display: inline;
- clear: both;
- float: none;
-}
-
-li.jxMenuItem div.jxButtonContainer {
- float: none;
-}
-
-ul.jxMenu a, ul.jxSubMenu a {
- display: block;
- text-decoration: none;
- white-space: nowrap;
- clear: both;
- float: none;
-}
-
-ul.jxMenu img, ul.jxSubMenu img {
- padding-right: 5px;
-}
-
-ul.jxMenu span, ul.jxSubMenu span {
- display: block;
-/* clear: both; */ /*this caused a problem where menu's with images wrapped*/
- float: none;
-}
-
-ul.jxMenu span.jxMenuSeparator {
- display: block;
-}
-
-iframe.jxMenuShim {
- position:absolute;
- top: 0px;
- left: 0px;
- width: 100%;
- height: 100%;
- filter: Alpha(opacity:0);
- opacity: 0;
- -moz-opacity: 0;
- z-index: -1;
-}/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* =============== */
-/* JX PANEL STYLES */
-/* =============== */
-
-.jxPanel {
- position:relative;
-}
-
-/* the content panel inside a panel */
-.jxPanelContent {
- /* position relative is required for panels to work correctly in safari */
- position: relative;
- display: block;
- /* set the width to 100% to make the content resize properly when the container resizes */
- width: 100%;
- /* height gets set by javascript */
- height: auto;
- /* content gains scroll bars as needed */
- overflow: auto;
- border-top: 1px solid #fff;
- border-bottom: 1px solid #999;
- margin: 0px;
- padding: 0px;
- border-top: none;
- background-color: #fff;
- /*white-space: nowrap;*/ /* need wrapping off for trees */
-}
-
-/* ======================= */
-/* JX PANEL MANAGER STYLES */
-/* ======================= */
-
-.jxPanelTitle {
- /* position relative is required for panel dragging to work correctly in safari */
- position:relative;
- width: 100%;
- background-image: url(../images/snap_bg.png);
- background-repeat: repeat-x;
- background-position: left top;
- border-top: 1px solid #fff;
- border-bottom: 1px solid #666;
- /* note this is hard coded into jx.js JxPanel initialize function - change there as well as here */
- height: 22px;
- margin: 0;
- padding: 0;
- /* this prevents lines from wrapping when content is resized */
- white-space: nowrap;
-/* -moz-box-sizing: border-box;*/
-}
-
-.jxPanelLabel {
- /* make room for the loading spinner */
- padding-left: 25px;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 12px;
- font-weight: bold;
- /* line-height vertically aligns the label in the containing div. In the border
- box model, this should be the containers height less padding and borders. In
- the content box model, it should be the height of the container. */
- line-height:21px;
- /* make the text align properly with an neighbouring inline image */
- /*vertical-align: top;*/
- color: #000;
-}
-
-a.jxPanelMaximize,
-a.jxPanelHelp {
- position: absolute;
- top: 1px;
- padding: 0px;
- margin: 0px;
- border: 0px;
- width: 20px;
- height: 20px;
-}
-
-.jxPanelTitle a.jxPanelHelp {
- right: 20px;
-}
-
-.jxPanelTitle a.jxPanelMaximize {
- right: 2px;
-}
-
-/* removed - this is a WebStudio specific style and needs to be moved there when
- we update WebStudio */
-
-/*
-.jxPanelTitle a.jxPanelClose {
- right: 2px;
- z-index: 10;
-
-}
-*/
-
-a.jxPanelMaximize img,
-a.jxPanelHelp img,
-a.jxPanelLoading img {
- border: 0px;
- /* the margin needs to make up the difference between it's width/height
- and the width/height of the parent a */
- margin: 0px;
- /* width/height has to be the actual image width/height */
- width: 20px;
- height: 20px;
-}
-
-a.jxPanelLoading img {
- visibility:hidden;
- position: absolute;
- top: 1px;
- left: 2px;
-}
-/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* ============= */
-/* PICKER STYLES */
-/* ============= */
-
-/* the jx Picker is intended to replace lists and combo boxes that require
- a richer set of features such as text input, images and styles in the
- selection list and better control over the list size. */
-
-div.jxPicker {
- position: relative;
- display: block;
- padding: 0px;
- padding-right: 22px;
- margin: 0px;
- border: 0px;
- font-family: Arial, Helvetica, sans-serif;
- font-size:11px;
- z-index: 1;
- line-height: 24px;
- float: left;
-}
-
-.jxPickerDiscloser {
- position: absolute;
- right: 3px;
- top: 3px;
-}
-
-.jxPickerDiscloser img {
- width: 16px;
- height: 16px;
- border: 0px;
-}
-
-.jxPickerInput {
- position: relative;
- display: block;
- float: left;
- /*padding-right: 16px;*/
- line-height: 24px;
- height: 24px;
- padding: 0px 10px;
-}
-
-div.jxPickerOptions {
- position: absolute;
- top: 100%;
- left: 0px;
- width: 100%;
- height: auto;
- background-color: #fff;
- overflow: auto;
- border: 1px solid #333;
- color: #000;
- z-index: 1;
- display: none;
- text-align: right;
-}
-
-div.jxPickerOptions ul {
- position: relative;
- display: block;
- margin: 0px;
- padding: 0px;
- border: none;
- list-style-type: none;
-}
-
-div.jxPickerOptions li {
- position: relative;
- display: block;
- margin: 0px;
- padding: 0px;
- border: none;
- height:20px;
-}
-
-div.jxPickerOptions a {
- position: relative;
- display: block;
- text-decoration: none;
- white-space: nowrap;
- /* this value needs to be the height of it's parent
- minus it's own margin, padding and border values */
- line-height:20px;
- /* height needs to be set for IE. Same value as line height. */
- height: 20px;
- color: #000;
- background-position: right top;
- background-repeat: no-repeat;
- padding: 0px 4px;
-}
-
-div.jxPickerOptions a:hover {
- background-color: #E1EDFA;
- /*background-color: #ffffcc; */
-}
-
-div.jxPickerOptions a.selected {
- font-weight: bold;
- background-color: #ffffb3;
-}
-/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* ========== */
-/* TAB STYLES */
-/* ========== */
-
-/* Note: There are some specific styles for IE in tabs_ie.css
-
- The tabBox consists of a box containing a tabbar and the tab content areas.
- It can be used within the body or nested within another object.
-*/
-
-.jxTabSetContainer {
- /* This is an example of a container that can be used to hold a tabBox
- the position need to be explicitly set, as well as the width and height. */
- position: relative;
- display: block;
-
-}
-
-.jxTabSetContainer .jxToolbarContainer {
- z-index: auto;
-}
-
-.tabContent {
- /* the width and height need to be set to 100% to:
- 1. fill the tab box area
- 2. allow a scrolling content area in IE */
- display: none;
- position: relative;
- width:100%;
- height: 100%;
- overflow: auto;
-}
-
-.tabContentActive {
- display: block;
-}
-
-/* TAB BOX MODE */
-.jxTabBoxTop,
-.jxTabBoxBottom,
-.jxTabBoxLeft,
-.jxTabBoxRight {
- overflow: visible;
-}
-
-/* TAB BOX MODE */
-.jxTabBoxTop .jxBarTop,
-.jxTabBoxBottom .jxBarBottom,
-.jxTabBoxLeft .jxBarLeft,
-.jxTabBoxRight .jxBarRight {
- position: absolute;
-}
-
-
-/* The tabbar is built out of a UL
- The tab background uses the sliding door technique so tabs can expand to
- accomodate content up to 200 px wide (top/bottom tabs) or 200px high
- (left/right tabs). All parts and states of the tab BG graphics are in the
- same image so they can be treated like sprites.
-
- Horizontal tabs can contain text or an image label. Vertical tabs need an
- image label.
-*/
-
-/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* ============== */
-/* TOOLBAR STYLES */
-/* ============== */
-
-/* Multiple toolbars can be housed in the toolbar container the container will expand
- vertically to accomodate wrapped toolbars */
-.jxToolbarContainer {
- display: block;
- position: relative;
- z-index: 1;
-}
-
-/* Horizontally oriented toolbars */
-.jxBarTop,
-.jxBarBottom {
- width: 100%; /* fills the width, may be needed for JS style sniffing */
- height: auto; /* since the last element clears the float, a height may not be needed */
-}
-
-/* Vertically oriented toolbars */
-.jxBarLeft,
-.jxBarRight {
- width: auto;
- height: 100%;
-}
-
-/* a label can optionally be used preceeding a toolbar.
- the line height is used to center the label relative to the toolbar. */
-.toolbarLabel {
- display: block;
- position: relative;
- float: left;
-}
-
-/* The jx toolbar is built out of a UL
- For this to work visually, the margins and padding need to be flattened
- out, and the list markers need to be hidden
- UL's are floated left so multiple toolbars can be in the samae row.
- In IE, the UL needs to have a specified width to prevent button wrapping. */
-
-ul.jxToolbar {
- display: block;
- position: relative;
- float: left;
- list-style-type: none;
-}
-
-/* LI's are floated to the left, to make a horizontal row of buttons*/
-li.jxToolItem {
- display: block;
- position: relative;
- float: left;
- font-size: 0px;
- line-height: 0px;
-}
-
-/* Seperator height should match that of button images
- and the margins+padding+border should add up to the same total too. */
-li.jxToolItem .separator {
- display: block;
- position: relative;
- float: left;
- font-size: 0px;
- line-height: 0px;
-}
-
-/* Vertically oriented toolbars need floats cleared */
-.jxBarLeft label.toolbarLabel,
-.jxBarLeft ul.jxToolbar,
-.jxBarLeft li.jxToolItem,
-.jxBarRight label.toolbarLabel,
-.jxBarRight ul.jxToolbar,
-.jxBarRight li.jxToolItem
-{
- clear: both;
-}
-
-
-/* DEPRICATED STYLES */
-
-/* Vertically oriented toolbars do not need to fill their containers horizontally */
-.verticalToolbar {
- width: auto;
-}
-
-/* Vertically oriented toolbars need floats cleared */
-.verticalToolbar label.toolbarLabel,
-.verticalToolbar ul.jxToolbar,
-.verticalToolbar li.jxToolItem
-{
- clear: both;
-}
-
-/**
- * @project Jx
- * @revision $Id: jx_combined.css 776 2008-08-22 18:46:25Z madair $
- * @author Fred Warnock (fwarnock at dmsolutions.ca)
- * @copyright © 2006 DM Solutions Group Inc.
- */
-
-/* =========== */
-/* TREE STYLES */
-/* =========== */
-
-/* The jx tree built out of nested ULs
- For this to work visually, the margins and padding need to be flattened
- out, and the list marker needs to be hidden
-*/
-
-
-.jxTree, .jxTreeRoot {
- /* relative positioning is required for IE to fix the peek-a-boo bug */
- position:relative;
- list-style: none;
- margin: 0px;
- padding: 0px;
-}
-
-.jxTreeNest {
- list-style: none;
- margin: 0px;
- padding: 0px;
- background-repeat: repeat-y;
- background-position: left top;
-}
-
-/* Node Classes */
-
-.jxTree li, .jxTreeRoot li {
- /* relative positioning is required for IE to fix the peek-a-boo bug */
- position:relative;
- margin: 0px;
- padding: 0px;
- background-repeat: no-repeat;
- /* background branches may need to shift up/down according to height of the node */
- background-position: left top;
- white-space: nowrap;
- width: 100%;
-}
-
-.jxTree li {
- margin-left: 16px;
-}
-
-.jxTree li.jxDisabled, .jxTreeRoot li.jxDisabled {
- opacity: 0.4; /* css 3 */
- -moz-opacity: 0.4; /* moz-specific */
- filter: Alpha(opacity=40); /* IE only */
-}
-
-.jxTree a, .jxTreeRoot a {
- margin: 0px;
- padding: 0px;
- padding-left: 2px;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 11px;
- color: #000;
- text-decoration: none;
- /* Line Height needs to be an even number so branches line up properly */
- line-height: 20px;
-}
-
-.jxTree a:hover, .jxTreeRoot a:hover {
- background-color: #E1EDFA;
- /*background-color: #ffffcc; */
-}
-
-.jxTree img, .jxTreeRoot img {
- border: 0px;
- width: 16px;
- height: 16px;
-}
-
-.jxTreeNest {background-image: url(../images/tree_vert_line.png);}
-.jxTreeNode {background-image: url(../images/tree_node.png);}
-.jxTreeNodeLast {background-image: url(../images/tree_last_node.png);}
-
-.jxTreeDropzone {
- text-decoration:underline;
- font-weight:bold;
-}
-
-.jxTreeSelectedNode {
- background-color: #AFD4FA;
- /*background-color: #ddffaa; */
- font-weight:bold;
-}
-
-.jxTreeCutNode {
- opacity: 0.4; /* css 3 */
- -moz-opacity: 0.4; /* moz-specific */
- filter: Alpha(opacity=40); /* IE only */
-}
-
-.jxTreeCutNode a:hover {
- background-color: #fff;
-}
-
-.jxTreeNode, .jxTreeNodeLast {
-/* width: 100%;*/
-}
-
-.jxTreeNode a, .jxTreeNode img, .jxTreeNode input {
- vertical-align: middle;
-}
-
-.jxTreeNodeLast a, .jxTreeNodeLast img, .jxTreeNodeLast input {
- vertical-align: middle;
-}
-
-.jxTreeNodeImage {
-}
-
-.jxTreeNodeIcon {
- margin: 0px;
-}
\ No newline at end of file
Deleted: sandbox/jx2/jx/lib/jx_combined.js
===================================================================
--- sandbox/jx2/jx/lib/jx_combined.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/jx/lib/jx_combined.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,14064 +0,0 @@
-/******************************************************************************
- * Prototype JavaScript framework, version 1.5.0
- * (c) 2005-2007 Sam Stephenson
- * Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
- ******************************************************************************
- * Jx UI Library, version 1.0
- * Copyright © 2008, DM Solutions Group Inc.
- * Jx is freely distributable under the terms of an MIT-style license.
- *****************************************************************************/
-/* Prototype JavaScript framework, version 1.5.0
- * (c) 2005-2007 Sam Stephenson
- *
- * Prototype is freely distributable under the terms of an MIT-style license.
- * For details, see the Prototype web site: http://prototype.conio.net/
- *
-/*--------------------------------------------------------------------------*/
-
-var Prototype = {
- Version: '1.5.0',
- BrowserFeatures: {
- XPath: !!document.evaluate
- },
-
- ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
- emptyFunction: function() {},
- K: function(x) { return x }
-}
-
-var Class = {
- create: function() {
- return function() {
- this.initialize.apply(this, arguments);
- }
- }
-}
-
-var Abstract = new Object();
-
-Object.extend = function(destination, source) {
- for (var property in source) {
- destination[property] = source[property];
- }
- return destination;
-}
-
-Object.extend(Object, {
- inspect: function(object) {
- try {
- if (object === undefined) return 'undefined';
- if (object === null) return 'null';
- return object.inspect ? object.inspect() : object.toString();
- } catch (e) {
- if (e instanceof RangeError) return '...';
- throw e;
- }
- },
-
- keys: function(object) {
- var keys = [];
- for (var property in object)
- keys.push(property);
- return keys;
- },
-
- values: function(object) {
- var values = [];
- for (var property in object)
- values.push(object[property]);
- return values;
- },
-
- clone: function(object) {
- return Object.extend({}, object);
- }
-});
-
-Function.prototype.bind = function() {
- var __method = this, args = $A(arguments), object = args.shift();
- return function() {
- return __method.apply(object, args.concat($A(arguments)));
- }
-}
-
-Function.prototype.bindAsEventListener = function(object) {
- var __method = this, args = $A(arguments), object = args.shift();
- return function(event) {
- return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments)));
- }
-}
-
-Object.extend(Number.prototype, {
- toColorPart: function() {
- var digits = this.toString(16);
- if (this < 16) return '0' + digits;
- return digits;
- },
-
- succ: function() {
- return this + 1;
- },
-
- times: function(iterator) {
- $R(0, this, true).each(iterator);
- return this;
- }
-});
-
-var Try = {
- these: function() {
- var returnValue;
-
- for (var i = 0, length = arguments.length; i < length; i++) {
- var lambda = arguments[i];
- try {
- returnValue = lambda();
- break;
- } catch (e) {}
- }
-
- return returnValue;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var PeriodicalExecuter = Class.create();
-PeriodicalExecuter.prototype = {
- initialize: function(callback, frequency) {
- this.callback = callback;
- this.frequency = frequency;
- this.currentlyExecuting = false;
-
- this.registerCallback();
- },
-
- registerCallback: function() {
- this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- stop: function() {
- if (!this.timer) return;
- clearInterval(this.timer);
- this.timer = null;
- },
-
- onTimerEvent: function() {
- if (!this.currentlyExecuting) {
- try {
- this.currentlyExecuting = true;
- this.callback(this);
- } finally {
- this.currentlyExecuting = false;
- }
- }
- }
-}
-String.interpret = function(value){
- return value == null ? '' : String(value);
-}
-
-Object.extend(String.prototype, {
- gsub: function(pattern, replacement) {
- var result = '', source = this, match;
- replacement = arguments.callee.prepareReplacement(replacement);
-
- while (source.length > 0) {
- if (match = source.match(pattern)) {
- result += source.slice(0, match.index);
- result += String.interpret(replacement(match));
- source = source.slice(match.index + match[0].length);
- } else {
- result += source, source = '';
- }
- }
- return result;
- },
-
- sub: function(pattern, replacement, count) {
- replacement = this.gsub.prepareReplacement(replacement);
- count = count === undefined ? 1 : count;
-
- return this.gsub(pattern, function(match) {
- if (--count < 0) return match[0];
- return replacement(match);
- });
- },
-
- scan: function(pattern, iterator) {
- this.gsub(pattern, iterator);
- return this;
- },
-
- truncate: function(length, truncation) {
- length = length || 30;
- truncation = truncation === undefined ? '...' : truncation;
- return this.length > length ?
- this.slice(0, length - truncation.length) + truncation : this;
- },
-
- strip: function() {
- return this.replace(/^\s+/, '').replace(/\s+$/, '');
- },
-
- stripTags: function() {
- return this.replace(/<\/?[^>]+>/gi, '');
- },
-
- stripScripts: function() {
- return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
- },
-
- extractScripts: function() {
- var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
- var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
- return (this.match(matchAll) || []).map(function(scriptTag) {
- return (scriptTag.match(matchOne) || ['', ''])[1];
- });
- },
-
- evalScripts: function() {
- return this.extractScripts().map(function(script) { return eval(script) });
- },
-
- escapeHTML: function() {
- var div = document.createElement('div');
- var text = document.createTextNode(this);
- div.appendChild(text);
- return div.innerHTML;
- },
-
- unescapeHTML: function() {
- var div = document.createElement('div');
- div.innerHTML = this.stripTags();
- return div.childNodes[0] ? (div.childNodes.length > 1 ?
- $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) :
- div.childNodes[0].nodeValue) : '';
- },
-
- toQueryParams: function(separator) {
- var match = this.strip().match(/([^?#]*)(#.*)?$/);
- if (!match) return {};
-
- return match[1].split(separator || '&').inject({}, function(hash, pair) {
- if ((pair = pair.split('='))[0]) {
- var name = decodeURIComponent(pair[0]);
- var value = pair[1] ? decodeURIComponent(pair[1]) : undefined;
-
- if (hash[name] !== undefined) {
- if (hash[name].constructor != Array)
- hash[name] = [hash[name]];
- if (value) hash[name].push(value);
- }
- else hash[name] = value;
- }
- return hash;
- });
- },
-
- toArray: function() {
- return this.split('');
- },
-
- succ: function() {
- return this.slice(0, this.length - 1) +
- String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
- },
-
- camelize: function() {
- var parts = this.split('-'), len = parts.length;
- if (len == 1) return parts[0];
-
- var camelized = this.charAt(0) == '-'
- ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
- : parts[0];
-
- for (var i = 1; i < len; i++)
- camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
-
- return camelized;
- },
-
- capitalize: function(){
- return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
- },
-
- underscore: function() {
- return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
- },
-
- dasherize: function() {
- return this.gsub(/_/,'-');
- },
-
- inspect: function(useDoubleQuotes) {
- var escapedString = this.replace(/\\/g, '\\\\');
- if (useDoubleQuotes)
- return '"' + escapedString.replace(/"/g, '\\"') + '"';
- else
- return "'" + escapedString.replace(/'/g, '\\\'') + "'";
- }
-});
-
-String.prototype.gsub.prepareReplacement = function(replacement) {
- if (typeof replacement == 'function') return replacement;
- var template = new Template(replacement);
- return function(match) { return template.evaluate(match) };
-}
-
-String.prototype.parseQuery = String.prototype.toQueryParams;
-
-var Template = Class.create();
-Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
-Template.prototype = {
- initialize: function(template, pattern) {
- this.template = template.toString();
- this.pattern = pattern || Template.Pattern;
- },
-
- evaluate: function(object) {
- return this.template.gsub(this.pattern, function(match) {
- var before = match[1];
- if (before == '\\') return match[2];
- return before + String.interpret(object[match[3]]);
- });
- }
-}
-
-var $break = new Object();
-var $continue = new Object();
-
-var Enumerable = {
- each: function(iterator) {
- var index = 0;
- try {
- this._each(function(value) {
- try {
- iterator(value, index++);
- } catch (e) {
- if (e != $continue) throw e;
- }
- });
- } catch (e) {
- if (e != $break) throw e;
- }
- return this;
- },
-
- eachSlice: function(number, iterator) {
- var index = -number, slices = [], array = this.toArray();
- while ((index += number) < array.length)
- slices.push(array.slice(index, index+number));
- return slices.map(iterator);
- },
-
- all: function(iterator) {
- var result = true;
- this.each(function(value, index) {
- result = result && !!(iterator || Prototype.K)(value, index);
- if (!result) throw $break;
- });
- return result;
- },
-
- any: function(iterator) {
- var result = false;
- this.each(function(value, index) {
- if (result = !!(iterator || Prototype.K)(value, index))
- throw $break;
- });
- return result;
- },
-
- collect: function(iterator) {
- var results = [];
- this.each(function(value, index) {
- results.push((iterator || Prototype.K)(value, index));
- });
- return results;
- },
-
- detect: function(iterator) {
- var result;
- this.each(function(value, index) {
- if (iterator(value, index)) {
- result = value;
- throw $break;
- }
- });
- return result;
- },
-
- findAll: function(iterator) {
- var results = [];
- this.each(function(value, index) {
- if (iterator(value, index))
- results.push(value);
- });
- return results;
- },
-
- grep: function(pattern, iterator) {
- var results = [];
- this.each(function(value, index) {
- var stringValue = value.toString();
- if (stringValue.match(pattern))
- results.push((iterator || Prototype.K)(value, index));
- })
- return results;
- },
-
- include: function(object) {
- var found = false;
- this.each(function(value) {
- if (value == object) {
- found = true;
- throw $break;
- }
- });
- return found;
- },
-
- inGroupsOf: function(number, fillWith) {
- fillWith = fillWith === undefined ? null : fillWith;
- return this.eachSlice(number, function(slice) {
- while(slice.length < number) slice.push(fillWith);
- return slice;
- });
- },
-
- inject: function(memo, iterator) {
- this.each(function(value, index) {
- memo = iterator(memo, value, index);
- });
- return memo;
- },
-
- invoke: function(method) {
- var args = $A(arguments).slice(1);
- return this.map(function(value) {
- return value[method].apply(value, args);
- });
- },
-
- max: function(iterator) {
- var result;
- this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value >= result)
- result = value;
- });
- return result;
- },
-
- min: function(iterator) {
- var result;
- this.each(function(value, index) {
- value = (iterator || Prototype.K)(value, index);
- if (result == undefined || value < result)
- result = value;
- });
- return result;
- },
-
- partition: function(iterator) {
- var trues = [], falses = [];
- this.each(function(value, index) {
- ((iterator || Prototype.K)(value, index) ?
- trues : falses).push(value);
- });
- return [trues, falses];
- },
-
- pluck: function(property) {
- var results = [];
- this.each(function(value, index) {
- results.push(value[property]);
- });
- return results;
- },
-
- reject: function(iterator) {
- var results = [];
- this.each(function(value, index) {
- if (!iterator(value, index))
- results.push(value);
- });
- return results;
- },
-
- sortBy: function(iterator) {
- return this.map(function(value, index) {
- return {value: value, criteria: iterator(value, index)};
- }).sort(function(left, right) {
- var a = left.criteria, b = right.criteria;
- return a < b ? -1 : a > b ? 1 : 0;
- }).pluck('value');
- },
-
- toArray: function() {
- return this.map();
- },
-
- zip: function() {
- var iterator = Prototype.K, args = $A(arguments);
- if (typeof args.last() == 'function')
- iterator = args.pop();
-
- var collections = [this].concat(args).map($A);
- return this.map(function(value, index) {
- return iterator(collections.pluck(index));
- });
- },
-
- size: function() {
- return this.toArray().length;
- },
-
- inspect: function() {
- return '#<Enumerable:' + this.toArray().inspect() + '>';
- }
-}
-
-Object.extend(Enumerable, {
- map: Enumerable.collect,
- find: Enumerable.detect,
- select: Enumerable.findAll,
- member: Enumerable.include,
- entries: Enumerable.toArray
-});
-var $A = Array.from = function(iterable) {
- if (!iterable) return [];
- if (iterable.toArray) {
- return iterable.toArray();
- } else {
- var results = [];
- for (var i = 0, length = iterable.length; i < length; i++)
- results.push(iterable[i]);
- return results;
- }
-}
-
-Object.extend(Array.prototype, Enumerable);
-
-if (!Array.prototype._reverse)
- Array.prototype._reverse = Array.prototype.reverse;
-
-Object.extend(Array.prototype, {
- _each: function(iterator) {
- for (var i = 0, length = this.length; i < length; i++)
- iterator(this[i]);
- },
-
- clear: function() {
- this.length = 0;
- return this;
- },
-
- first: function() {
- return this[0];
- },
-
- last: function() {
- return this[this.length - 1];
- },
-
- compact: function() {
- return this.select(function(value) {
- return value != null;
- });
- },
-
- flatten: function() {
- return this.inject([], function(array, value) {
- return array.concat(value && value.constructor == Array ?
- value.flatten() : [value]);
- });
- },
-
- without: function() {
- var values = $A(arguments);
- return this.select(function(value) {
- return !values.include(value);
- });
- },
-
- indexOf: function(object) {
- for (var i = 0, length = this.length; i < length; i++)
- if (this[i] == object) return i;
- return -1;
- },
-
- reverse: function(inline) {
- return (inline !== false ? this : this.toArray())._reverse();
- },
-
- reduce: function() {
- return this.length > 1 ? this : this[0];
- },
-
- uniq: function() {
- return this.inject([], function(array, value) {
- return array.include(value) ? array : array.concat([value]);
- });
- },
-
- clone: function() {
- return [].concat(this);
- },
-
- size: function() {
- return this.length;
- },
-
- inspect: function() {
- return '[' + this.map(Object.inspect).join(', ') + ']';
- }
-});
-
-Array.prototype.toArray = Array.prototype.clone;
-
-function $w(string){
- string = string.strip();
- return string ? string.split(/\s+/) : [];
-}
-
-if(window.opera){
- Array.prototype.concat = function(){
- var array = [];
- for(var i = 0, length = this.length; i < length; i++) array.push(this[i]);
- for(var i = 0, length = arguments.length; i < length; i++) {
- if(arguments[i].constructor == Array) {
- for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
- array.push(arguments[i][j]);
- } else {
- array.push(arguments[i]);
- }
- }
- return array;
- }
-}
-var Hash = function(obj) {
- Object.extend(this, obj || {});
-};
-
-Object.extend(Hash, {
- toQueryString: function(obj) {
- var parts = [];
-
- this.prototype._each.call(obj, function(pair) {
- if (!pair.key) return;
-
- if (pair.value && pair.value.constructor == Array) {
- var values = pair.value.compact();
- if (values.length < 2) pair.value = values.reduce();
- else {
- key = encodeURIComponent(pair.key);
- values.each(function(value) {
- value = value != undefined ? encodeURIComponent(value) : '';
- parts.push(key + '=' + encodeURIComponent(value));
- });
- return;
- }
- }
- if (pair.value == undefined) pair[1] = '';
- parts.push(pair.map(encodeURIComponent).join('='));
- });
-
- return parts.join('&');
- }
-});
-
-Object.extend(Hash.prototype, Enumerable);
-Object.extend(Hash.prototype, {
- _each: function(iterator) {
- for (var key in this) {
- var value = this[key];
- if (value && value == Hash.prototype[key]) continue;
-
- var pair = [key, value];
- pair.key = key;
- pair.value = value;
- iterator(pair);
- }
- },
-
- keys: function() {
- return this.pluck('key');
- },
-
- values: function() {
- return this.pluck('value');
- },
-
- merge: function(hash) {
- return $H(hash).inject(this, function(mergedHash, pair) {
- mergedHash[pair.key] = pair.value;
- return mergedHash;
- });
- },
-
- remove: function() {
- var result;
- for(var i = 0, length = arguments.length; i < length; i++) {
- var value = this[arguments[i]];
- if (value !== undefined){
- if (result === undefined) result = value;
- else {
- if (result.constructor != Array) result = [result];
- result.push(value)
- }
- }
- delete this[arguments[i]];
- }
- return result;
- },
-
- toQueryString: function() {
- return Hash.toQueryString(this);
- },
-
- inspect: function() {
- return '#<Hash:{' + this.map(function(pair) {
- return pair.map(Object.inspect).join(': ');
- }).join(', ') + '}>';
- }
-});
-
-function $H(object) {
- if (object && object.constructor == Hash) return object;
- return new Hash(object);
-};
-ObjectRange = Class.create();
-Object.extend(ObjectRange.prototype, Enumerable);
-Object.extend(ObjectRange.prototype, {
- initialize: function(start, end, exclusive) {
- this.start = start;
- this.end = end;
- this.exclusive = exclusive;
- },
-
- _each: function(iterator) {
- var value = this.start;
- while (this.include(value)) {
- iterator(value);
- value = value.succ();
- }
- },
-
- include: function(value) {
- if (value < this.start)
- return false;
- if (this.exclusive)
- return value < this.end;
- return value <= this.end;
- }
-});
-
-var $R = function(start, end, exclusive) {
- return new ObjectRange(start, end, exclusive);
-}
-
-var Ajax = {
- getTransport: function() {
- return Try.these(
- function() {return new XMLHttpRequest()},
- function() {return new ActiveXObject('Msxml2.XMLHTTP')},
- function() {return new ActiveXObject('Microsoft.XMLHTTP')}
- ) || false;
- },
-
- activeRequestCount: 0
-}
-
-Ajax.Responders = {
- responders: [],
-
- _each: function(iterator) {
- this.responders._each(iterator);
- },
-
- register: function(responder) {
- if (!this.include(responder))
- this.responders.push(responder);
- },
-
- unregister: function(responder) {
- this.responders = this.responders.without(responder);
- },
-
- dispatch: function(callback, request, transport, json) {
- this.each(function(responder) {
- if (typeof responder[callback] == 'function') {
- try {
- responder[callback].apply(responder, [request, transport, json]);
- } catch (e) {}
- }
- });
- }
-};
-
-Object.extend(Ajax.Responders, Enumerable);
-
-Ajax.Responders.register({
- onCreate: function() {
- Ajax.activeRequestCount++;
- },
- onComplete: function() {
- Ajax.activeRequestCount--;
- }
-});
-
-Ajax.Base = function() {};
-Ajax.Base.prototype = {
- setOptions: function(options) {
- this.options = {
- method: 'post',
- asynchronous: true,
- contentType: 'application/x-www-form-urlencoded',
- encoding: 'UTF-8',
- parameters: ''
- }
- Object.extend(this.options, options || {});
-
- this.options.method = this.options.method.toLowerCase();
- if (typeof this.options.parameters == 'string')
- this.options.parameters = this.options.parameters.toQueryParams();
- }
-}
-
-Ajax.Request = Class.create();
-Ajax.Request.Events =
- ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
-
-Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
- _complete: false,
-
- initialize: function(url, options) {
- this.transport = Ajax.getTransport();
- this.setOptions(options);
- this.request(url);
- },
-
- request: function(url) {
- this.url = url;
- this.method = this.options.method;
- var params = this.options.parameters;
-
- if (!['get', 'post'].include(this.method)) {
- // simulate other verbs over post
- params['_method'] = this.method;
- this.method = 'post';
- }
-
- params = Hash.toQueryString(params);
- if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_='
-
- // when GET, append parameters to URL
- if (this.method == 'get' && params)
- this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params;
-
- try {
- Ajax.Responders.dispatch('onCreate', this, this.transport);
-
- this.transport.open(this.method.toUpperCase(), this.url,
- this.options.asynchronous);
-
- if (this.options.asynchronous)
- setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10);
-
- this.transport.onreadystatechange = this.onStateChange.bind(this);
- this.setRequestHeaders();
-
- var body = this.method == 'post' ? (this.options.postBody || params) : null;
-
- this.transport.send(body);
-
- /* Force Firefox to handle ready state 4 for synchronous requests */
- if (!this.options.asynchronous && this.transport.overrideMimeType)
- this.onStateChange();
-
- }
- catch (e) {
- this.dispatchException(e);
- }
- },
-
- onStateChange: function() {
- var readyState = this.transport.readyState;
- if (readyState > 1 && !((readyState == 4) && this._complete))
- this.respondToReadyState(this.transport.readyState);
- },
-
- setRequestHeaders: function() {
- var headers = {
- 'X-Requested-With': 'XMLHttpRequest',
- 'X-Prototype-Version': Prototype.Version,
- 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
- };
-
- if (this.method == 'post') {
- headers['Content-type'] = this.options.contentType +
- (this.options.encoding ? '; charset=' + this.options.encoding : '');
-
- /* Force "Connection: close" for older Mozilla browsers to work
- * around a bug where XMLHttpRequest sends an incorrect
- * Content-length header. See Mozilla Bugzilla #246651.
- */
- if (this.transport.overrideMimeType &&
- (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
- headers['Connection'] = 'close';
- }
-
- // user-defined headers
- if (typeof this.options.requestHeaders == 'object') {
- var extras = this.options.requestHeaders;
-
- if (typeof extras.push == 'function')
- for (var i = 0, length = extras.length; i < length; i += 2)
- headers[extras[i]] = extras[i+1];
- else
- $H(extras).each(function(pair) { headers[pair.key] = pair.value });
- }
-
- for (var name in headers)
- this.transport.setRequestHeader(name, headers[name]);
- },
-
- success: function() {
- return !this.transport.status
- || (this.transport.status >= 200 && this.transport.status < 300);
- },
-
- respondToReadyState: function(readyState) {
- var state = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.evalJSON();
-
- if (state == 'Complete') {
- try {
- this._complete = true;
- (this.options['on' + this.transport.status]
- || this.options['on' + (this.success() ? 'Success' : 'Failure')]
- || Prototype.emptyFunction)(transport, json);
- } catch (e) {
- this.dispatchException(e);
- }
-
- if ((this.getHeader('Content-type') || 'text/javascript').strip().
- match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
- this.evalResponse();
- }
-
- try {
- (this.options['on' + state] || Prototype.emptyFunction)(transport, json);
- Ajax.Responders.dispatch('on' + state, this, transport, json);
- } catch (e) {
- this.dispatchException(e);
- }
-
- if (state == 'Complete') {
- // avoid memory leak in MSIE: clean up
- this.transport.onreadystatechange = Prototype.emptyFunction;
- }
- },
-
- getHeader: function(name) {
- try {
- return this.transport.getResponseHeader(name);
- } catch (e) { return null }
- },
-
- evalJSON: function() {
- try {
- var json = this.getHeader('X-JSON');
- return json ? eval('(' + json + ')') : null;
- } catch (e) { return null }
- },
-
- evalResponse: function() {
- try {
- return eval(this.transport.responseText);
- } catch (e) {
- this.dispatchException(e);
- }
- },
-
- dispatchException: function(exception) {
- (this.options.onException || Prototype.emptyFunction)(this, exception);
- Ajax.Responders.dispatch('onException', this, exception);
- }
-});
-
-Ajax.Updater = Class.create();
-
-Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), {
- initialize: function(container, url, options) {
- this.container = {
- success: (container.success || container),
- failure: (container.failure || (container.success ? null : container))
- }
-
- this.transport = Ajax.getTransport();
- this.setOptions(options);
-
- var onComplete = this.options.onComplete || Prototype.emptyFunction;
- this.options.onComplete = (function(transport, param) {
- this.updateContent();
- onComplete(transport, param);
- }).bind(this);
-
- this.request(url);
- },
-
- updateContent: function() {
- var receiver = this.container[this.success() ? 'success' : 'failure'];
- var response = this.transport.responseText;
-
- if (!this.options.evalScripts) response = response.stripScripts();
-
- if (receiver = $(receiver)) {
- if (this.options.insertion)
- new this.options.insertion(receiver, response);
- else
- receiver.update(response);
- }
-
- if (this.success()) {
- if (this.onComplete)
- setTimeout(this.onComplete.bind(this), 10);
- }
- }
-});
-
-Ajax.PeriodicalUpdater = Class.create();
-Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
- initialize: function(container, url, options) {
- this.setOptions(options);
- this.onComplete = this.options.onComplete;
-
- this.frequency = (this.options.frequency || 2);
- this.decay = (this.options.decay || 1);
-
- this.updater = {};
- this.container = container;
- this.url = url;
-
- this.start();
- },
-
- start: function() {
- this.options.onComplete = this.updateComplete.bind(this);
- this.onTimerEvent();
- },
-
- stop: function() {
- this.updater.options.onComplete = undefined;
- clearTimeout(this.timer);
- (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
- },
-
- updateComplete: function(request) {
- if (this.options.decay) {
- this.decay = (request.responseText == this.lastText ?
- this.decay * this.options.decay : 1);
-
- this.lastText = request.responseText;
- }
- this.timer = setTimeout(this.onTimerEvent.bind(this),
- this.decay * this.frequency * 1000);
- },
-
- onTimerEvent: function() {
- this.updater = new Ajax.Updater(this.container, this.url, this.options);
- }
-});
-function $(element) {
- if (arguments.length > 1) {
- for (var i = 0, elements = [], length = arguments.length; i < length; i++)
- elements.push($(arguments[i]));
- return elements;
- }
- if (typeof element == 'string')
- element = document.getElementById(element);
- return Element.extend(element);
-}
-
-if (Prototype.BrowserFeatures.XPath) {
- document._getElementsByXPath = function(expression, parentElement) {
- var results = [];
- var query = document.evaluate(expression, $(parentElement) || document,
- null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
- for (var i = 0, length = query.snapshotLength; i < length; i++)
- results.push(query.snapshotItem(i));
- return results;
- };
-}
-
-document.getElementsByClassName = function(className, parentElement) {
- if (Prototype.BrowserFeatures.XPath) {
- var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
- return document._getElementsByXPath(q, parentElement);
- } else {
- var children = ($(parentElement) || document.body).getElementsByTagName('*');
- var elements = [], child;
- for (var i = 0, length = children.length; i < length; i++) {
- child = children[i];
- if (Element.hasClassName(child, className))
- elements.push(Element.extend(child));
- }
- return elements;
- }
-};
-
-/*--------------------------------------------------------------------------*/
-
-if (!window.Element)
- var Element = new Object();
-
-Element.extend = function(element) {
- if (!element || _nativeExtensions || element.nodeType == 3) return element;
-
- if (!element._extended && element.tagName && element != window) {
- var methods = Object.clone(Element.Methods), cache = Element.extend.cache;
-
- if (element.tagName == 'FORM')
- Object.extend(methods, Form.Methods);
- if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName))
- Object.extend(methods, Form.Element.Methods);
-
- Object.extend(methods, Element.Methods.Simulated);
-
- for (var property in methods) {
- var value = methods[property];
- if (typeof value == 'function' && !(property in element))
- element[property] = cache.findOrStore(value);
- }
- }
-
- element._extended = true;
- return element;
-};
-
-Element.extend.cache = {
- findOrStore: function(value) {
- return this[value] = this[value] || function() {
- return value.apply(null, [this].concat($A(arguments)));
- }
- }
-};
-
-Element.Methods = {
- visible: function(element) {
- return $(element).style.display != 'none';
- },
-
- toggle: function(element) {
- element = $(element);
- Element[Element.visible(element) ? 'hide' : 'show'](element);
- return element;
- },
-
- hide: function(element) {
- $(element).style.display = 'none';
- return element;
- },
-
- show: function(element) {
- $(element).style.display = '';
- return element;
- },
-
- remove: function(element) {
- element = $(element);
- element.parentNode.removeChild(element);
- return element;
- },
-
- update: function(element, html) {
- html = typeof html == 'undefined' ? '' : html.toString();
- $(element).innerHTML = html.stripScripts();
- setTimeout(function() {html.evalScripts()}, 10);
- return element;
- },
-
- replace: function(element, html) {
- element = $(element);
- html = typeof html == 'undefined' ? '' : html.toString();
- if (element.outerHTML) {
- element.outerHTML = html.stripScripts();
- } else {
- var range = element.ownerDocument.createRange();
- range.selectNodeContents(element);
- element.parentNode.replaceChild(
- range.createContextualFragment(html.stripScripts()), element);
- }
- setTimeout(function() {html.evalScripts()}, 10);
- return element;
- },
-
- inspect: function(element) {
- element = $(element);
- var result = '<' + element.tagName.toLowerCase();
- $H({'id': 'id', 'className': 'class'}).each(function(pair) {
- var property = pair.first(), attribute = pair.last();
- var value = (element[property] || '').toString();
- if (value) result += ' ' + attribute + '=' + value.inspect(true);
- });
- return result + '>';
- },
-
- recursivelyCollect: function(element, property) {
- element = $(element);
- var elements = [];
- while (element = element[property])
- if (element.nodeType == 1)
- elements.push(Element.extend(element));
- return elements;
- },
-
- ancestors: function(element) {
- return $(element).recursivelyCollect('parentNode');
- },
-
- descendants: function(element) {
- return $A($(element).getElementsByTagName('*'));
- },
-
- immediateDescendants: function(element) {
- if (!(element = $(element).firstChild)) return [];
- while (element && element.nodeType != 1) element = element.nextSibling;
- if (element) return [element].concat($(element).nextSiblings());
- return [];
- },
-
- previousSiblings: function(element) {
- return $(element).recursivelyCollect('previousSibling');
- },
-
- nextSiblings: function(element) {
- return $(element).recursivelyCollect('nextSibling');
- },
-
- siblings: function(element) {
- element = $(element);
- return element.previousSiblings().reverse().concat(element.nextSiblings());
- },
-
- match: function(element, selector) {
- if (typeof selector == 'string')
- selector = new Selector(selector);
- return selector.match($(element));
- },
-
- up: function(element, expression, index) {
- return Selector.findElement($(element).ancestors(), expression, index);
- },
-
- down: function(element, expression, index) {
- return Selector.findElement($(element).descendants(), expression, index);
- },
-
- previous: function(element, expression, index) {
- return Selector.findElement($(element).previousSiblings(), expression, index);
- },
-
- next: function(element, expression, index) {
- return Selector.findElement($(element).nextSiblings(), expression, index);
- },
-
- getElementsBySelector: function() {
- var args = $A(arguments), element = $(args.shift());
- return Selector.findChildElements(element, args);
- },
-
- getElementsByClassName: function(element, className) {
- return document.getElementsByClassName(className, element);
- },
-
- readAttribute: function(element, name) {
- element = $(element);
- if (document.all && !window.opera) {
- var t = Element._attributeTranslations;
- if (t.values[name]) return t.values[name](element, name);
- if (t.names[name]) name = t.names[name];
- var attribute = element.attributes[name];
- if(attribute) return attribute.nodeValue;
- }
- return element.getAttribute(name);
- },
-
- getHeight: function(element) {
- return $(element).getDimensions().height;
- },
-
- getWidth: function(element) {
- return $(element).getDimensions().width;
- },
-
- classNames: function(element) {
- return new Element.ClassNames(element);
- },
-
- hasClassName: function(element, className) {
- if (!(element = $(element))) return;
- var elementClassName = element.className;
- if (elementClassName.length == 0) return false;
- if (elementClassName == className ||
- elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
- return true;
- return false;
- },
-
- addClassName: function(element, className) {
- if (!(element = $(element))) return;
- Element.classNames(element).add(className);
- return element;
- },
-
- removeClassName: function(element, className) {
- if (!(element = $(element))) return;
- Element.classNames(element).remove(className);
- return element;
- },
-
- toggleClassName: function(element, className) {
- if (!(element = $(element))) return;
- Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
- return element;
- },
-
- observe: function() {
- Event.observe.apply(Event, arguments);
- return $A(arguments).first();
- },
-
- stopObserving: function() {
- Event.stopObserving.apply(Event, arguments);
- return $A(arguments).first();
- },
-
- // removes whitespace-only text node children
- cleanWhitespace: function(element) {
- element = $(element);
- var node = element.firstChild;
- while (node) {
- var nextNode = node.nextSibling;
- if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
- element.removeChild(node);
- node = nextNode;
- }
- return element;
- },
-
- empty: function(element) {
- return $(element).innerHTML.match(/^\s*$/);
- },
-
- descendantOf: function(element, ancestor) {
- element = $(element), ancestor = $(ancestor);
- while (element = element.parentNode)
- if (element == ancestor) return true;
- return false;
- },
-
- scrollTo: function(element) {
- element = $(element);
- var pos = Position.cumulativeOffset(element);
- window.scrollTo(pos[0], pos[1]);
- return element;
- },
-
- getStyle: function(element, style) {
- element = $(element);
- if (['float','cssFloat'].include(style))
- style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat');
- style = style.camelize();
- var value = element.style[style];
- if (!value) {
- if (document.defaultView && document.defaultView.getComputedStyle) {
- var css = document.defaultView.getComputedStyle(element, null);
- value = css ? css[style] : null;
- } else if (element.currentStyle) {
- value = element.currentStyle[style];
- }
- }
-
- if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none'))
- value = element['offset'+style.capitalize()] + 'px';
-
- if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
- if (Element.getStyle(element, 'position') == 'static') value = 'auto';
- if(style == 'opacity') {
- if(value) return parseFloat(value);
- if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
- if(value[1]) return parseFloat(value[1]) / 100;
- return 1.0;
- }
- return value == 'auto' ? null : value;
- },
-
- setStyle: function(element, style) {
- element = $(element);
- for (var name in style) {
- var value = style[name];
- if(name == 'opacity') {
- if (value == 1) {
- value = (/Gecko/.test(navigator.userAgent) &&
- !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0;
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
- } else if(value === '') {
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');
- } else {
- if(value < 0.00001) value = 0;
- if(/MSIE/.test(navigator.userAgent) && !window.opera)
- element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') +
- 'alpha(opacity='+value*100+')';
- }
- } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat';
- element.style[name.camelize()] = value;
- }
- return element;
- },
-
- getDimensions: function(element) {
- element = $(element);
- var display = $(element).getStyle('display');
- if (display != 'none' && display != null) // Safari bug
- return {width: element.offsetWidth, height: element.offsetHeight};
-
- // All *Width and *Height properties give 0 on elements with display none,
- // so enable the element temporarily
- var els = element.style;
- var originalVisibility = els.visibility;
- var originalPosition = els.position;
- var originalDisplay = els.display;
- els.visibility = 'hidden';
- els.position = 'absolute';
- els.display = 'block';
- var originalWidth = element.clientWidth;
- var originalHeight = element.clientHeight;
- els.display = originalDisplay;
- els.position = originalPosition;
- els.visibility = originalVisibility;
- return {width: originalWidth, height: originalHeight};
- },
-
- makePositioned: function(element) {
- element = $(element);
- var pos = Element.getStyle(element, 'position');
- if (pos == 'static' || !pos) {
- element._madePositioned = true;
- element.style.position = 'relative';
- // Opera returns the offset relative to the positioning context, when an
- // element is position relative but top and left have not been defined
- if (window.opera) {
- element.style.top = 0;
- element.style.left = 0;
- }
- }
- return element;
- },
-
- undoPositioned: function(element) {
- element = $(element);
- if (element._madePositioned) {
- element._madePositioned = undefined;
- element.style.position =
- element.style.top =
- element.style.left =
- element.style.bottom =
- element.style.right = '';
- }
- return element;
- },
-
- makeClipping: function(element) {
- element = $(element);
- if (element._overflow) return element;
- element._overflow = element.style.overflow || 'auto';
- if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
- element.style.overflow = 'hidden';
- return element;
- },
-
- undoClipping: function(element) {
- element = $(element);
- if (!element._overflow) return element;
- element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
- element._overflow = null;
- return element;
- }
-};
-
-Object.extend(Element.Methods, {childOf: Element.Methods.descendantOf});
-
-Element._attributeTranslations = {};
-
-Element._attributeTranslations.names = {
- colspan: "colSpan",
- rowspan: "rowSpan",
- valign: "vAlign",
- datetime: "dateTime",
- accesskey: "accessKey",
- tabindex: "tabIndex",
- enctype: "encType",
- maxlength: "maxLength",
- readonly: "readOnly",
- longdesc: "longDesc"
-};
-
-Element._attributeTranslations.values = {
- _getAttr: function(element, attribute) {
- return element.getAttribute(attribute, 2);
- },
-
- _flag: function(element, attribute) {
- return $(element).hasAttribute(attribute) ? attribute : null;
- },
-
- style: function(element) {
- return element.style.cssText.toLowerCase();
- },
-
- title: function(element) {
- var node = element.getAttributeNode('title');
- return node.specified ? node.nodeValue : null;
- }
-};
-
-Object.extend(Element._attributeTranslations.values, {
- href: Element._attributeTranslations.values._getAttr,
- src: Element._attributeTranslations.values._getAttr,
- disabled: Element._attributeTranslations.values._flag,
- checked: Element._attributeTranslations.values._flag,
- readonly: Element._attributeTranslations.values._flag,
- multiple: Element._attributeTranslations.values._flag
-});
-
-Element.Methods.Simulated = {
- hasAttribute: function(element, attribute) {
- var t = Element._attributeTranslations;
- attribute = t.names[attribute] || attribute;
- return $(element).getAttributeNode(attribute).specified;
- }
-};
-
-// IE is missing .innerHTML support for TABLE-related elements
-if (document.all && !window.opera){
- Element.Methods.update = function(element, html) {
- element = $(element);
- html = typeof html == 'undefined' ? '' : html.toString();
- var tagName = element.tagName.toUpperCase();
- if (['THEAD','TBODY','TR','TD'].include(tagName)) {
- var div = document.createElement('div');
- switch (tagName) {
- case 'THEAD':
- case 'TBODY':
- div.innerHTML = '<table><tbody>' + html.stripScripts() + '</tbody></table>';
- depth = 2;
- break;
- case 'TR':
- div.innerHTML = '<table><tbody><tr>' + html.stripScripts() + '</tr></tbody></table>';
- depth = 3;
- break;
- case 'TD':
- div.innerHTML = '<table><tbody><tr><td>' + html.stripScripts() + '</td></tr></tbody></table>';
- depth = 4;
- }
- $A(element.childNodes).each(function(node){
- element.removeChild(node)
- });
- depth.times(function(){ div = div.firstChild });
-
- $A(div.childNodes).each(
- function(node){ element.appendChild(node) });
- } else {
- element.innerHTML = html.stripScripts();
- }
- setTimeout(function() {html.evalScripts()}, 10);
- return element;
- }
-};
-
-Object.extend(Element, Element.Methods);
-
-var _nativeExtensions = false;
-
-if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
- ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) {
- var className = 'HTML' + tag + 'Element';
- if(window[className]) return;
- var klass = window[className] = {};
- klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__;
- });
-
-Element.addMethods = function(methods) {
- Object.extend(Element.Methods, methods || {});
-
- function copy(methods, destination, onlyIfAbsent) {
- onlyIfAbsent = onlyIfAbsent || false;
- var cache = Element.extend.cache;
- for (var property in methods) {
- var value = methods[property];
- if (!onlyIfAbsent || !(property in destination))
- destination[property] = cache.findOrStore(value);
- }
- }
-
- if (typeof HTMLElement != 'undefined') {
- copy(Element.Methods, HTMLElement.prototype);
- copy(Element.Methods.Simulated, HTMLElement.prototype, true);
- copy(Form.Methods, HTMLFormElement.prototype);
- [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) {
- copy(Form.Element.Methods, klass.prototype);
- });
- _nativeExtensions = true;
- }
-}
-
-var Toggle = new Object();
-Toggle.display = Element.toggle;
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.Insertion = function(adjacency) {
- this.adjacency = adjacency;
-}
-
-Abstract.Insertion.prototype = {
- initialize: function(element, content) {
- this.element = $(element);
- this.content = content.stripScripts();
-
- if (this.adjacency && this.element.insertAdjacentHTML) {
- try {
- this.element.insertAdjacentHTML(this.adjacency, this.content);
- } catch (e) {
- var tagName = this.element.tagName.toUpperCase();
- if (['TBODY', 'TR'].include(tagName)) {
- this.insertContent(this.contentFromAnonymousTable());
- } else {
- throw e;
- }
- }
- } else {
- this.range = this.element.ownerDocument.createRange();
- if (this.initializeRange) this.initializeRange();
- this.insertContent([this.range.createContextualFragment(this.content)]);
- }
-
- setTimeout(function() {content.evalScripts()}, 10);
- },
-
- contentFromAnonymousTable: function() {
- var div = document.createElement('div');
- div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
- return $A(div.childNodes[0].childNodes[0].childNodes);
- }
-}
-
-var Insertion = new Object();
-
-Insertion.Before = Class.create();
-Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
- initializeRange: function() {
- this.range.setStartBefore(this.element);
- },
-
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment, this.element);
- }).bind(this));
- }
-});
-
-Insertion.Top = Class.create();
-Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(true);
- },
-
- insertContent: function(fragments) {
- fragments.reverse(false).each((function(fragment) {
- this.element.insertBefore(fragment, this.element.firstChild);
- }).bind(this));
- }
-});
-
-Insertion.Bottom = Class.create();
-Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
- initializeRange: function() {
- this.range.selectNodeContents(this.element);
- this.range.collapse(this.element);
- },
-
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.appendChild(fragment);
- }).bind(this));
- }
-});
-
-Insertion.After = Class.create();
-Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
- initializeRange: function() {
- this.range.setStartAfter(this.element);
- },
-
- insertContent: function(fragments) {
- fragments.each((function(fragment) {
- this.element.parentNode.insertBefore(fragment,
- this.element.nextSibling);
- }).bind(this));
- }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Element.ClassNames = Class.create();
-Element.ClassNames.prototype = {
- initialize: function(element) {
- this.element = $(element);
- },
-
- _each: function(iterator) {
- this.element.className.split(/\s+/).select(function(name) {
- return name.length > 0;
- })._each(iterator);
- },
-
- set: function(className) {
- this.element.className = className;
- },
-
- add: function(classNameToAdd) {
- if (this.include(classNameToAdd)) return;
- this.set($A(this).concat(classNameToAdd).join(' '));
- },
-
- remove: function(classNameToRemove) {
- if (!this.include(classNameToRemove)) return;
- this.set($A(this).without(classNameToRemove).join(' '));
- },
-
- toString: function() {
- return $A(this).join(' ');
- }
-};
-
-Object.extend(Element.ClassNames.prototype, Enumerable);
-var Selector = Class.create();
-Selector.prototype = {
- initialize: function(expression) {
- this.params = {classNames: []};
- this.expression = expression.toString().strip();
- this.parseExpression();
- this.compileMatcher();
- },
-
- parseExpression: function() {
- function abort(message) { throw 'Parse error in selector: ' + message; }
-
- if (this.expression == '') abort('empty expression');
-
- var params = this.params, expr = this.expression, match, modifier, clause, rest;
- while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
- params.attributes = params.attributes || [];
- params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
- expr = match[1];
- }
-
- if (expr == '*') return this.params.wildcard = true;
-
- while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) {
- modifier = match[1], clause = match[2], rest = match[3];
- switch (modifier) {
- case '#': params.id = clause; break;
- case '.': params.classNames.push(clause); break;
- case '':
- case undefined: params.tagName = clause.toUpperCase(); break;
- default: abort(expr.inspect());
- }
- expr = rest;
- }
-
- if (expr.length > 0) abort(expr.inspect());
- },
-
- buildMatchExpression: function() {
- var params = this.params, conditions = [], clause;
-
- if (params.wildcard)
- conditions.push('true');
- if (clause = params.id)
- conditions.push('element.readAttribute("id") == ' + clause.inspect());
- if (clause = params.tagName)
- conditions.push('element.tagName.toUpperCase() == ' + clause.inspect());
- if ((clause = params.classNames).length > 0)
- for (var i = 0, length = clause.length; i < length; i++)
- conditions.push('element.hasClassName(' + clause[i].inspect() + ')');
- if (clause = params.attributes) {
- clause.each(function(attribute) {
- var value = 'element.readAttribute(' + attribute.name.inspect() + ')';
- var splitValueBy = function(delimiter) {
- return value + ' && ' + value + '.split(' + delimiter.inspect() + ')';
- }
-
- switch (attribute.operator) {
- case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break;
- case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break;
- case '|=': conditions.push(
- splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect()
- ); break;
- case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break;
- case '':
- case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break;
- default: throw 'Unknown operator ' + attribute.operator + ' in selector';
- }
- });
- }
-
- return conditions.join(' && ');
- },
-
- compileMatcher: function() {
- this.match = new Function('element', 'if (!element.tagName) return false; element = $(element); return ' + this.buildMatchExpression());
- },
-
- findElements: function(scope) {
- var element;
-
- if (element = $(this.params.id))
- if (this.match(element))
- if (!scope || Element.childOf(element, scope))
- return [element];
-
- scope = (scope || document).getElementsByTagName(this.params.tagName || '*');
-
- var results = [];
- for (var i = 0, length = scope.length; i < length; i++)
- if (this.match(element = scope[i]))
- results.push(Element.extend(element));
-
- return results;
- },
-
- toString: function() {
- return this.expression;
- }
-}
-
-Object.extend(Selector, {
- matchElements: function(elements, expression) {
- var selector = new Selector(expression);
- return elements.select(selector.match.bind(selector)).map(Element.extend);
- },
-
- findElement: function(elements, expression, index) {
- if (typeof expression == 'number') index = expression, expression = false;
- return Selector.matchElements(elements, expression || '*')[index || 0];
- },
-
- findChildElements: function(element, expressions) {
- return expressions.map(function(expression) {
- return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) {
- var selector = new Selector(expr);
- return results.inject([], function(elements, result) {
- return elements.concat(selector.findElements(result || element));
- });
- });
- }).flatten();
- }
-});
-
-function $$() {
- return Selector.findChildElements(document, $A(arguments));
-}
-var Form = {
- reset: function(form) {
- $(form).reset();
- return form;
- },
-
- serializeElements: function(elements, getHash) {
- var data = elements.inject({}, function(result, element) {
- if (!element.disabled && element.name) {
- var key = element.name, value = $(element).getValue();
- if (value != undefined) {
- if (result[key]) {
- if (result[key].constructor != Array) result[key] = [result[key]];
- result[key].push(value);
- }
- else result[key] = value;
- }
- }
- return result;
- });
-
- return getHash ? data : Hash.toQueryString(data);
- }
-};
-
-Form.Methods = {
- serialize: function(form, getHash) {
- return Form.serializeElements(Form.getElements(form), getHash);
- },
-
- getElements: function(form) {
- return $A($(form).getElementsByTagName('*')).inject([],
- function(elements, child) {
- if (Form.Element.Serializers[child.tagName.toLowerCase()])
- elements.push(Element.extend(child));
- return elements;
- }
- );
- },
-
- getInputs: function(form, typeName, name) {
- form = $(form);
- var inputs = form.getElementsByTagName('input');
-
- if (!typeName && !name) return $A(inputs).map(Element.extend);
-
- for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
- var input = inputs[i];
- if ((typeName && input.type != typeName) || (name && input.name != name))
- continue;
- matchingInputs.push(Element.extend(input));
- }
-
- return matchingInputs;
- },
-
- disable: function(form) {
- form = $(form);
- form.getElements().each(function(element) {
- element.blur();
- element.disabled = 'true';
- });
- return form;
- },
-
- enable: function(form) {
- form = $(form);
- form.getElements().each(function(element) {
- element.disabled = '';
- });
- return form;
- },
-
- findFirstElement: function(form) {
- return $(form).getElements().find(function(element) {
- return element.type != 'hidden' && !element.disabled &&
- ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
- });
- },
-
- focusFirstElement: function(form) {
- form = $(form);
- form.findFirstElement().activate();
- return form;
- }
-}
-
-Object.extend(Form, Form.Methods);
-
-/*--------------------------------------------------------------------------*/
-
-Form.Element = {
- focus: function(element) {
- $(element).focus();
- return element;
- },
-
- select: function(element) {
- $(element).select();
- return element;
- }
-}
-
-Form.Element.Methods = {
- serialize: function(element) {
- element = $(element);
- if (!element.disabled && element.name) {
- var value = element.getValue();
- if (value != undefined) {
- var pair = {};
- pair[element.name] = value;
- return Hash.toQueryString(pair);
- }
- }
- return '';
- },
-
- getValue: function(element) {
- element = $(element);
- var method = element.tagName.toLowerCase();
- return Form.Element.Serializers[method](element);
- },
-
- clear: function(element) {
- $(element).value = '';
- return element;
- },
-
- present: function(element) {
- return $(element).value != '';
- },
-
- activate: function(element) {
- element = $(element);
- element.focus();
- if (element.select && ( element.tagName.toLowerCase() != 'input' ||
- !['button', 'reset', 'submit'].include(element.type) ) )
- element.select();
- return element;
- },
-
- disable: function(element) {
- element = $(element);
- element.disabled = true;
- return element;
- },
-
- enable: function(element) {
- element = $(element);
- element.blur();
- element.disabled = false;
- return element;
- }
-}
-
-Object.extend(Form.Element, Form.Element.Methods);
-var Field = Form.Element;
-var $F = Form.Element.getValue;
-
-/*--------------------------------------------------------------------------*/
-
-Form.Element.Serializers = {
- input: function(element) {
- switch (element.type.toLowerCase()) {
- case 'checkbox':
- case 'radio':
- return Form.Element.Serializers.inputSelector(element);
- default:
- return Form.Element.Serializers.textarea(element);
- }
- },
-
- inputSelector: function(element) {
- return element.checked ? element.value : null;
- },
-
- textarea: function(element) {
- return element.value;
- },
-
- select: function(element) {
- return this[element.type == 'select-one' ?
- 'selectOne' : 'selectMany'](element);
- },
-
- selectOne: function(element) {
- var index = element.selectedIndex;
- return index >= 0 ? this.optionValue(element.options[index]) : null;
- },
-
- selectMany: function(element) {
- var values, length = element.length;
- if (!length) return null;
-
- for (var i = 0, values = []; i < length; i++) {
- var opt = element.options[i];
- if (opt.selected) values.push(this.optionValue(opt));
- }
- return values;
- },
-
- optionValue: function(opt) {
- // extend element because hasAttribute may not be native
- return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.TimedObserver = function() {}
-Abstract.TimedObserver.prototype = {
- initialize: function(element, frequency, callback) {
- this.frequency = frequency;
- this.element = $(element);
- this.callback = callback;
-
- this.lastValue = this.getValue();
- this.registerCallback();
- },
-
- registerCallback: function() {
- setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
- },
-
- onTimerEvent: function() {
- var value = this.getValue();
- var changed = ('string' == typeof this.lastValue && 'string' == typeof value
- ? this.lastValue != value : String(this.lastValue) != String(value));
- if (changed) {
- this.callback(this.element, value);
- this.lastValue = value;
- }
- }
-}
-
-Form.Element.Observer = Class.create();
-Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
- getValue: function() {
- return Form.Element.getValue(this.element);
- }
-});
-
-Form.Observer = Class.create();
-Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), {
- getValue: function() {
- return Form.serialize(this.element);
- }
-});
-
-/*--------------------------------------------------------------------------*/
-
-Abstract.EventObserver = function() {}
-Abstract.EventObserver.prototype = {
- initialize: function(element, callback) {
- this.element = $(element);
- this.callback = callback;
-
- this.lastValue = this.getValue();
- if (this.element.tagName.toLowerCase() == 'form')
- this.registerFormCallbacks();
- else
- this.registerCallback(this.element);
- },
-
- onElementEvent: function() {
- var value = this.getValue();
- if (this.lastValue != value) {
- this.callback(this.element, value);
- this.lastValue = value;
- }
- },
-
- registerFormCallbacks: function() {
- Form.getElements(this.element).each(this.registerCallback.bind(this));
- },
-
- registerCallback: function(element) {
- if (element.type) {
- switch (element.type.toLowerCase()) {
- case 'checkbox':
- case 'radio':
- Event.observe(element, 'click', this.onElementEvent.bind(this));
- break;
- default:
- Event.observe(element, 'change', this.onElementEvent.bind(this));
- break;
- }
- }
- }
-}
-
-Form.Element.EventObserver = Class.create();
-Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
- getValue: function() {
- return Form.Element.getValue(this.element);
- }
-});
-
-Form.EventObserver = Class.create();
-Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), {
- getValue: function() {
- return Form.serialize(this.element);
- }
-});
-if (!window.Event) {
- var Event = new Object();
-}
-
-Object.extend(Event, {
- KEY_BACKSPACE: 8,
- KEY_TAB: 9,
- KEY_RETURN: 13,
- KEY_ESC: 27,
- KEY_LEFT: 37,
- KEY_UP: 38,
- KEY_RIGHT: 39,
- KEY_DOWN: 40,
- KEY_DELETE: 46,
- KEY_HOME: 36,
- KEY_END: 35,
- KEY_PAGEUP: 33,
- KEY_PAGEDOWN: 34,
-
- element: function(event) {
- return event.target || event.srcElement;
- },
-
- isLeftClick: function(event) {
- return (((event.which) && (event.which == 1)) ||
- ((event.button) && (event.button == 1)));
- },
-
- pointerX: function(event) {
- return event.pageX || (event.clientX +
- (document.documentElement.scrollLeft || document.body.scrollLeft));
- },
-
- pointerY: function(event) {
- return event.pageY || (event.clientY +
- (document.documentElement.scrollTop || document.body.scrollTop));
- },
-
- stop: function(event) {
- if (event.preventDefault) {
- event.preventDefault();
- event.stopPropagation();
- } else {
- event.returnValue = false;
- event.cancelBubble = true;
- }
- },
-
- // find the first node with the given tagName, starting from the
- // node the event was triggered on; traverses the DOM upwards
- findElement: function(event, tagName) {
- var element = Event.element(event);
- while (element.parentNode && (!element.tagName ||
- (element.tagName.toUpperCase() != tagName.toUpperCase())))
- element = element.parentNode;
- return element;
- },
-
- observers: false,
-
- _observeAndCache: function(element, name, observer, useCapture) {
- if (!this.observers) this.observers = [];
- if (element.addEventListener) {
- this.observers.push([element, name, observer, useCapture]);
- element.addEventListener(name, observer, useCapture);
- } else if (element.attachEvent) {
- this.observers.push([element, name, observer, useCapture]);
- element.attachEvent('on' + name, observer);
- }
- },
-
- unloadCache: function() {
- if (!Event.observers) return;
- for (var i = 0, length = Event.observers.length; i < length; i++) {
- Event.stopObserving.apply(this, Event.observers[i]);
- Event.observers[i][0] = null;
- }
- Event.observers = false;
- },
-
- observe: function(element, name, observer, useCapture) {
- element = $(element);
- useCapture = useCapture || false;
-
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.attachEvent))
- name = 'keydown';
-
- Event._observeAndCache(element, name, observer, useCapture);
- },
-
- stopObserving: function(element, name, observer, useCapture) {
- element = $(element);
- useCapture = useCapture || false;
-
- if (name == 'keypress' &&
- (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
- || element.detachEvent))
- name = 'keydown';
-
- if (element.removeEventListener) {
- element.removeEventListener(name, observer, useCapture);
- } else if (element.detachEvent) {
- try {
- element.detachEvent('on' + name, observer);
- } catch (e) {}
- }
- }
-});
-
-/* prevent memory leaks in IE */
-if (navigator.appVersion.match(/\bMSIE\b/))
- Event.observe(window, 'unload', Event.unloadCache, false);
-var Position = {
- // set to true if needed, warning: firefox performance problems
- // NOT neeeded for page scrolling, only if draggable contained in
- // scrollable elements
- includeScrollOffsets: false,
-
- // must be called before calling withinIncludingScrolloffset, every time the
- // page is scrolled
- prepare: function() {
- this.deltaX = window.pageXOffset
- || document.documentElement.scrollLeft
- || document.body.scrollLeft
- || 0;
- this.deltaY = window.pageYOffset
- || document.documentElement.scrollTop
- || document.body.scrollTop
- || 0;
- },
-
- realOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.scrollTop || 0;
- valueL += element.scrollLeft || 0;
- element = element.parentNode;
- } while (element);
- return [valueL, valueT];
- },
-
- cumulativeOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- } while (element);
- return [valueL, valueT];
- },
-
- positionedOffset: function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- element = element.offsetParent;
- if (element) {
- if(element.tagName=='BODY') break;
- var p = Element.getStyle(element, 'position');
- if (p == 'relative' || p == 'absolute') break;
- }
- } while (element);
- return [valueL, valueT];
- },
-
- offsetParent: function(element) {
- if (element.offsetParent) return element.offsetParent;
- if (element == document.body) return element;
-
- while ((element = element.parentNode) && element != document.body)
- if (Element.getStyle(element, 'position') != 'static')
- return element;
-
- return document.body;
- },
-
- // caches x/y coordinate pair to use with overlap
- within: function(element, x, y) {
- if (this.includeScrollOffsets)
- return this.withinIncludingScrolloffsets(element, x, y);
- this.xcomp = x;
- this.ycomp = y;
- this.offset = this.cumulativeOffset(element);
-
- return (y >= this.offset[1] &&
- y < this.offset[1] + element.offsetHeight &&
- x >= this.offset[0] &&
- x < this.offset[0] + element.offsetWidth);
- },
-
- withinIncludingScrolloffsets: function(element, x, y) {
- var offsetcache = this.realOffset(element);
-
- this.xcomp = x + offsetcache[0] - this.deltaX;
- this.ycomp = y + offsetcache[1] - this.deltaY;
- this.offset = this.cumulativeOffset(element);
-
- return (this.ycomp >= this.offset[1] &&
- this.ycomp < this.offset[1] + element.offsetHeight &&
- this.xcomp >= this.offset[0] &&
- this.xcomp < this.offset[0] + element.offsetWidth);
- },
-
- // within must be called directly before
- overlap: function(mode, element) {
- if (!mode) return 0;
- if (mode == 'vertical')
- return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
- element.offsetHeight;
- if (mode == 'horizontal')
- return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
- element.offsetWidth;
- },
-
- page: function(forElement) {
- var valueT = 0, valueL = 0;
-
- var element = forElement;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
-
- // Safari fix
- if (element.offsetParent==document.body)
- if (Element.getStyle(element,'position')=='absolute') break;
-
- } while (element = element.offsetParent);
-
- element = forElement;
- do {
- if (!window.opera || element.tagName=='BODY') {
- valueT -= element.scrollTop || 0;
- valueL -= element.scrollLeft || 0;
- }
- } while (element = element.parentNode);
-
- return [valueL, valueT];
- },
-
- clone: function(source, target) {
- var options = Object.extend({
- setLeft: true,
- setTop: true,
- setWidth: true,
- setHeight: true,
- offsetTop: 0,
- offsetLeft: 0
- }, arguments[2] || {})
-
- // find page position of source
- source = $(source);
- var p = Position.page(source);
-
- // find coordinate system to use
- target = $(target);
- var delta = [0, 0];
- var parent = null;
- // delta [0,0] will do fine with position: fixed elements,
- // position:absolute needs offsetParent deltas
- if (Element.getStyle(target,'position') == 'absolute') {
- parent = Position.offsetParent(target);
- delta = Position.page(parent);
- }
-
- // correct by body offsets (fixes Safari)
- if (parent == document.body) {
- delta[0] -= document.body.offsetLeft;
- delta[1] -= document.body.offsetTop;
- }
-
- // set position
- if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
- if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
- if(options.setWidth) target.style.width = source.offsetWidth + 'px';
- if(options.setHeight) target.style.height = source.offsetHeight + 'px';
- },
-
- absolutize: function(element) {
- element = $(element);
- if (element.style.position == 'absolute') return;
- Position.prepare();
-
- var offsets = Position.positionedOffset(element);
- var top = offsets[1];
- var left = offsets[0];
- var width = element.clientWidth;
- var height = element.clientHeight;
-
- element._originalLeft = left - parseFloat(element.style.left || 0);
- element._originalTop = top - parseFloat(element.style.top || 0);
- element._originalWidth = element.style.width;
- element._originalHeight = element.style.height;
-
- element.style.position = 'absolute';
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.width = width + 'px';
- element.style.height = height + 'px';
- },
-
- relativize: function(element) {
- element = $(element);
- if (element.style.position == 'relative') return;
- Position.prepare();
-
- element.style.position = 'relative';
- var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
- var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
-
- element.style.top = top + 'px';
- element.style.left = left + 'px';
- element.style.height = element._originalHeight;
- element.style.width = element._originalWidth;
- }
-}
-
-// Safari returns margins on body which is incorrect if the child is absolutely
-// positioned. For performance reasons, redefine Position.cumulativeOffset for
-// KHTML/WebKit only.
-if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
- Position.cumulativeOffset = function(element) {
- var valueT = 0, valueL = 0;
- do {
- valueT += element.offsetTop || 0;
- valueL += element.offsetLeft || 0;
- if (element.offsetParent == document.body)
- if (Element.getStyle(element, 'position') == 'absolute') break;
-
- element = element.offsetParent;
- } while (element);
-
- return [valueL, valueT];
- }
-}
-
-Element.addMethods();// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
-
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-//
-// script.aculo.us is freely distributable under the terms of an MIT-style license.
-// For details, see the script.aculo.us web site: http://script.aculo.us/
-
-var Builder = {
- NODEMAP: {
- AREA: 'map',
- CAPTION: 'table',
- COL: 'table',
- COLGROUP: 'table',
- LEGEND: 'fieldset',
- OPTGROUP: 'select',
- OPTION: 'select',
- PARAM: 'object',
- TBODY: 'table',
- TD: 'table',
- TFOOT: 'table',
- TH: 'table',
- THEAD: 'table',
- TR: 'table'
- },
- // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
- // due to a Firefox bug
- node: function(elementName) {
- elementName = elementName.toUpperCase();
-
- // try innerHTML approach
- var parentTag = this.NODEMAP[elementName] || 'div';
- var parentElement = document.createElement(parentTag);
- try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
- parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
- } catch(e) {}
- var element = parentElement.firstChild || null;
-
- // see if browser added wrapping tags
- if(element && (element.tagName.toUpperCase() != elementName))
- element = element.getElementsByTagName(elementName)[0];
-
- // fallback to createElement approach
- if(!element) element = document.createElement(elementName);
-
- // abort if nothing could be created
- if(!element) return;
-
- // attributes (or text)
- if(arguments[1])
- if(this._isStringOrNumber(arguments[1]) ||
- (arguments[1] instanceof Array)) {
- this._children(element, arguments[1]);
- } else {
- var attrs = this._attributes(arguments[1]);
- if(attrs.length) {
- try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
- parentElement.innerHTML = "<" +elementName + " " +
- attrs + "></" + elementName + ">";
- } catch(e) {}
- element = parentElement.firstChild || null;
- // workaround firefox 1.0.X bug
- if(!element) {
- element = document.createElement(elementName);
- for(attr in arguments[1])
- element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
- }
- if(element.tagName.toUpperCase() != elementName)
- element = parentElement.getElementsByTagName(elementName)[0];
- }
- }
-
- // text, or array of children
- if(arguments[2])
- this._children(element, arguments[2]);
-
- return element;
- },
- _text: function(text) {
- return document.createTextNode(text);
- },
-
- ATTR_MAP: {
- 'className': 'class',
- 'htmlFor': 'for'
- },
-
- _attributes: function(attributes) {
- var attrs = [];
- for(attribute in attributes)
- attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
- '="' + attributes[attribute].toString().escapeHTML() + '"');
- return attrs.join(" ");
- },
- _children: function(element, children) {
- if(typeof children=='object') { // array can hold nodes and text
- children.flatten().each( function(e) {
- if(typeof e=='object')
- element.appendChild(e)
- else
- if(Builder._isStringOrNumber(e))
- element.appendChild(Builder._text(e));
- });
- } else
- if(Builder._isStringOrNumber(children))
- element.appendChild(Builder._text(children));
- },
- _isStringOrNumber: function(param) {
- return(typeof param=='string' || typeof param=='number');
- },
- build: function(html) {
- var element = this.node('div');
- $(element).update(html.strip());
- return element.down();
- },
- dump: function(scope) {
- if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
-
- var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
- "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
- "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
- "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
- "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
- "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
-
- tags.each( function(tag){
- scope[tag] = function() {
- return Builder.node.apply(Builder, [tag].concat($A(arguments)));
- }
- });
- }
-}
-// script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
-
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// Contributors:
-// Justin Palmer (http://encytemedia.com/)
-// Mark Pilgrim (http://diveintomark.org/)
-// Martin Bialasinki
-//
-// script.aculo.us is freely distributable under the terms of an MIT-style license.
-// For details, see the script.aculo.us web site: http://script.aculo.us/
-
-// converts rgb() and #xxx to #xxxxxx format,
-// returns self (or first argument) if not convertable
-String.prototype.parseColor = function() {
- var color = '#';
- if(this.slice(0,4) == 'rgb(') {
- var cols = this.slice(4,this.length-1).split(',');
- var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
- } else {
- if(this.slice(0,1) == '#') {
- if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
- if(this.length==7) color = this.toLowerCase();
- }
- }
- return(color.length==7 ? color : (arguments[0] || this));
-}
-
-/*--------------------------------------------------------------------------*/
-
-Element.collectTextNodes = function(element) {
- return $A($(element).childNodes).collect( function(node) {
- return (node.nodeType==3 ? node.nodeValue :
- (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
- }).flatten().join('');
-}
-
-Element.collectTextNodesIgnoreClass = function(element, className) {
- return $A($(element).childNodes).collect( function(node) {
- return (node.nodeType==3 ? node.nodeValue :
- ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
- Element.collectTextNodesIgnoreClass(node, className) : ''));
- }).flatten().join('');
-}
-
-Element.setContentZoom = function(element, percent) {
- element = $(element);
- element.setStyle({fontSize: (percent/100) + 'em'});
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
- return element;
-}
-
-Element.getOpacity = function(element){
- return $(element).getStyle('opacity');
-}
-
-Element.setOpacity = function(element, value){
- return $(element).setStyle({opacity:value});
-}
-
-Element.getInlineOpacity = function(element){
- return $(element).style.opacity || '';
-}
-
-Element.forceRerendering = function(element) {
- try {
- element = $(element);
- var n = document.createTextNode(' ');
- element.appendChild(n);
- element.removeChild(n);
- } catch(e) { }
-};
-
-/*--------------------------------------------------------------------------*/
-
-Array.prototype.call = function() {
- var args = arguments;
- this.each(function(f){ f.apply(this, args) });
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Effect = {
- _elementDoesNotExistError: {
- name: 'ElementDoesNotExistError',
- message: 'The specified DOM element does not exist, but is required for this effect to operate'
- },
- tagifyText: function(element) {
- if(typeof Builder == 'undefined')
- throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
-
- var tagifyStyle = 'position:relative';
- if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1';
-
- element = $(element);
- $A(element.childNodes).each( function(child) {
- if(child.nodeType==3) {
- child.nodeValue.toArray().each( function(character) {
- element.insertBefore(
- Builder.node('span',{style: tagifyStyle},
- character == ' ' ? String.fromCharCode(160) : character),
- child);
- });
- Element.remove(child);
- }
- });
- },
- multiple: function(element, effect) {
- var elements;
- if(((typeof element == 'object') ||
- (typeof element == 'function')) &&
- (element.length))
- elements = element;
- else
- elements = $(element).childNodes;
-
- var options = Object.extend({
- speed: 0.1,
- delay: 0.0
- }, arguments[2] || {});
- var masterDelay = options.delay;
-
- $A(elements).each( function(element, index) {
- new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
- });
- },
- PAIRS: {
- 'slide': ['SlideDown','SlideUp'],
- 'blind': ['BlindDown','BlindUp'],
- 'appear': ['Appear','Fade']
- },
- toggle: function(element, effect) {
- element = $(element);
- effect = (effect || 'appear').toLowerCase();
- var options = Object.extend({
- queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
- }, arguments[2] || {});
- Effect[element.visible() ?
- Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
- }
-};
-
-var Effect2 = Effect; // deprecated
-
-/* ------------- transitions ------------- */
-
-Effect.Transitions = {
- linear: Prototype.K,
- sinoidal: function(pos) {
- return (-Math.cos(pos*Math.PI)/2) + 0.5;
- },
- reverse: function(pos) {
- return 1-pos;
- },
- flicker: function(pos) {
- return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
- },
- wobble: function(pos) {
- return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
- },
- pulse: function(pos, pulses) {
- pulses = pulses || 5;
- return (
- Math.round((pos % (1/pulses)) * pulses) == 0 ?
- ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
- 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
- );
- },
- none: function(pos) {
- return 0;
- },
- full: function(pos) {
- return 1;
- }
-};
-
-/* ------------- core effects ------------- */
-
-Effect.ScopedQueue = Class.create();
-Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
- initialize: function() {
- this.effects = [];
- this.interval = null;
- },
- _each: function(iterator) {
- this.effects._each(iterator);
- },
- add: function(effect) {
- var timestamp = new Date().getTime();
-
- var position = (typeof effect.options.queue == 'string') ?
- effect.options.queue : effect.options.queue.position;
-
- switch(position) {
- case 'front':
- // move unstarted effects after this effect
- this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
- e.startOn += effect.finishOn;
- e.finishOn += effect.finishOn;
- });
- break;
- case 'with-last':
- timestamp = this.effects.pluck('startOn').max() || timestamp;
- break;
- case 'end':
- // start effect after last queued effect has finished
- timestamp = this.effects.pluck('finishOn').max() || timestamp;
- break;
- }
-
- effect.startOn += timestamp;
- effect.finishOn += timestamp;
-
- if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
- this.effects.push(effect);
-
- if(!this.interval)
- this.interval = setInterval(this.loop.bind(this), 15);
- },
- remove: function(effect) {
- this.effects = this.effects.reject(function(e) { return e==effect });
- if(this.effects.length == 0) {
- clearInterval(this.interval);
- this.interval = null;
- }
- },
- loop: function() {
- var timePos = new Date().getTime();
- for(var i=0, len=this.effects.length;i<len;i++)
- if(this.effects[i]) this.effects[i].loop(timePos);
- }
-});
-
-Effect.Queues = {
- instances: $H(),
- get: function(queueName) {
- if(typeof queueName != 'string') return queueName;
-
- if(!this.instances[queueName])
- this.instances[queueName] = new Effect.ScopedQueue();
-
- return this.instances[queueName];
- }
-}
-Effect.Queue = Effect.Queues.get('global');
-
-Effect.DefaultOptions = {
- transition: Effect.Transitions.sinoidal,
- duration: 1.0, // seconds
- fps: 60.0, // max. 60fps due to Effect.Queue implementation
- sync: false, // true for combining
- from: 0.0,
- to: 1.0,
- delay: 0.0,
- queue: 'parallel'
-}
-
-Effect.Base = function() {};
-Effect.Base.prototype = {
- position: null,
- start: function(options) {
- this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
- this.currentFrame = 0;
- this.state = 'idle';
- this.startOn = this.options.delay*1000;
- this.finishOn = this.startOn + (this.options.duration*1000);
- this.event('beforeStart');
- if(!this.options.sync)
- Effect.Queues.get(typeof this.options.queue == 'string' ?
- 'global' : this.options.queue.scope).add(this);
- },
- loop: function(timePos) {
- if(timePos >= this.startOn) {
- if(timePos >= this.finishOn) {
- this.render(1.0);
- this.cancel();
- this.event('beforeFinish');
- if(this.finish) this.finish();
- this.event('afterFinish');
- return;
- }
- var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
- var frame = Math.round(pos * this.options.fps * this.options.duration);
- if(frame > this.currentFrame) {
- this.render(pos);
- this.currentFrame = frame;
- }
- }
- },
- render: function(pos) {
- if(this.state == 'idle') {
- this.state = 'running';
- this.event('beforeSetup');
- if(this.setup) this.setup();
- this.event('afterSetup');
- }
- if(this.state == 'running') {
- if(this.options.transition) pos = this.options.transition(pos);
- pos *= (this.options.to-this.options.from);
- pos += this.options.from;
- this.position = pos;
- this.event('beforeUpdate');
- if(this.update) this.update(pos);
- this.event('afterUpdate');
- }
- },
- cancel: function() {
- if(!this.options.sync)
- Effect.Queues.get(typeof this.options.queue == 'string' ?
- 'global' : this.options.queue.scope).remove(this);
- this.state = 'finished';
- },
- event: function(eventName) {
- if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
- if(this.options[eventName]) this.options[eventName](this);
- },
- inspect: function() {
- var data = $H();
- for(property in this)
- if(typeof this[property] != 'function') data[property] = this[property];
- return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
- }
-}
-
-Effect.Parallel = Class.create();
-Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
- initialize: function(effects) {
- this.effects = effects || [];
- this.start(arguments[1]);
- },
- update: function(position) {
- this.effects.invoke('render', position);
- },
- finish: function(position) {
- this.effects.each( function(effect) {
- effect.render(1.0);
- effect.cancel();
- effect.event('beforeFinish');
- if(effect.finish) effect.finish(position);
- effect.event('afterFinish');
- });
- }
-});
-
-Effect.Event = Class.create();
-Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
- initialize: function() {
- var options = Object.extend({
- duration: 0
- }, arguments[0] || {});
- this.start(options);
- },
- update: Prototype.emptyFunction
-});
-
-Effect.Opacity = Class.create();
-Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- // make this work on IE on elements without 'layout'
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
- this.element.setStyle({zoom: 1});
- var options = Object.extend({
- from: this.element.getOpacity() || 0.0,
- to: 1.0
- }, arguments[1] || {});
- this.start(options);
- },
- update: function(position) {
- this.element.setOpacity(position);
- }
-});
-
-Effect.Move = Class.create();
-Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- var options = Object.extend({
- x: 0,
- y: 0,
- mode: 'relative'
- }, arguments[1] || {});
- this.start(options);
- },
- setup: function() {
- // Bug in Opera: Opera returns the "real" position of a static element or
- // relative element that does not have top/left explicitly set.
- // ==> Always set top and left for position relative elements in your stylesheets
- // (to 0 if you do not need them)
- this.element.makePositioned();
- this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
- this.originalTop = parseFloat(this.element.getStyle('top') || '0');
- if(this.options.mode == 'absolute') {
- // absolute movement, so we need to calc deltaX and deltaY
- this.options.x = this.options.x - this.originalLeft;
- this.options.y = this.options.y - this.originalTop;
- }
- },
- update: function(position) {
- this.element.setStyle({
- left: Math.round(this.options.x * position + this.originalLeft) + 'px',
- top: Math.round(this.options.y * position + this.originalTop) + 'px'
- });
- }
-});
-
-// for backwards compatibility
-Effect.MoveBy = function(element, toTop, toLeft) {
- return new Effect.Move(element,
- Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
-};
-
-Effect.Scale = Class.create();
-Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
- initialize: function(element, percent) {
- this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- var options = Object.extend({
- scaleX: true,
- scaleY: true,
- scaleContent: true,
- scaleFromCenter: false,
- scaleMode: 'box', // 'box' or 'contents' or {} with provided values
- scaleFrom: 100.0,
- scaleTo: percent
- }, arguments[2] || {});
- this.start(options);
- },
- setup: function() {
- this.restoreAfterFinish = this.options.restoreAfterFinish || false;
- this.elementPositioning = this.element.getStyle('position');
-
- this.originalStyle = {};
- ['top','left','width','height','fontSize'].each( function(k) {
- this.originalStyle[k] = this.element.style[k];
- }.bind(this));
-
- this.originalTop = this.element.offsetTop;
- this.originalLeft = this.element.offsetLeft;
-
- var fontSize = this.element.getStyle('font-size') || '100%';
- ['em','px','%','pt'].each( function(fontSizeType) {
- if(fontSize.indexOf(fontSizeType)>0) {
- this.fontSize = parseFloat(fontSize);
- this.fontSizeType = fontSizeType;
- }
- }.bind(this));
-
- this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
-
- this.dims = null;
- if(this.options.scaleMode=='box')
- this.dims = [this.element.offsetHeight, this.element.offsetWidth];
- if(/^content/.test(this.options.scaleMode))
- this.dims = [this.element.scrollHeight, this.element.scrollWidth];
- if(!this.dims)
- this.dims = [this.options.scaleMode.originalHeight,
- this.options.scaleMode.originalWidth];
- },
- update: function(position) {
- var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
- if(this.options.scaleContent && this.fontSize)
- this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
- this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
- },
- finish: function(position) {
- if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
- },
- setDimensions: function(height, width) {
- var d = {};
- if(this.options.scaleX) d.width = Math.round(width) + 'px';
- if(this.options.scaleY) d.height = Math.round(height) + 'px';
- if(this.options.scaleFromCenter) {
- var topd = (height - this.dims[0])/2;
- var leftd = (width - this.dims[1])/2;
- if(this.elementPositioning == 'absolute') {
- if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
- if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
- } else {
- if(this.options.scaleY) d.top = -topd + 'px';
- if(this.options.scaleX) d.left = -leftd + 'px';
- }
- }
- this.element.setStyle(d);
- }
-});
-
-Effect.Highlight = Class.create();
-Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
- this.start(options);
- },
- setup: function() {
- // Prevent executing on elements not in the layout flow
- if(this.element.getStyle('display')=='none') { this.cancel(); return; }
- // Disable background image during the effect
- this.oldStyle = {};
- if (!this.options.keepBackgroundImage) {
- this.oldStyle.backgroundImage = this.element.getStyle('background-image');
- this.element.setStyle({backgroundImage: 'none'});
- }
- if(!this.options.endcolor)
- this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
- if(!this.options.restorecolor)
- this.options.restorecolor = this.element.getStyle('background-color');
- // init color calculations
- this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
- this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
- },
- update: function(position) {
- this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
- return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
- },
- finish: function() {
- this.element.setStyle(Object.extend(this.oldStyle, {
- backgroundColor: this.options.restorecolor
- }));
- }
-});
-
-Effect.ScrollTo = Class.create();
-Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- this.start(arguments[1] || {});
- },
- setup: function() {
- Position.prepare();
- var offsets = Position.cumulativeOffset(this.element);
- if(this.options.offset) offsets[1] += this.options.offset;
- var max = window.innerHeight ?
- window.height - window.innerHeight :
- document.body.scrollHeight -
- (document.documentElement.clientHeight ?
- document.documentElement.clientHeight : document.body.clientHeight);
- this.scrollStart = Position.deltaY;
- this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
- },
- update: function(position) {
- Position.prepare();
- window.scrollTo(Position.deltaX,
- this.scrollStart + (position*this.delta));
- }
-});
-
-/* ------------- combination effects ------------- */
-
-Effect.Fade = function(element) {
- element = $(element);
- var oldOpacity = element.getInlineOpacity();
- var options = Object.extend({
- from: element.getOpacity() || 1.0,
- to: 0.0,
- afterFinishInternal: function(effect) {
- if(effect.options.to!=0) return;
- effect.element.hide().setStyle({opacity: oldOpacity});
- }}, arguments[1] || {});
- return new Effect.Opacity(element,options);
-}
-
-Effect.Appear = function(element) {
- element = $(element);
- var options = Object.extend({
- from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
- to: 1.0,
- // force Safari to render floated elements properly
- afterFinishInternal: function(effect) {
- effect.element.forceRerendering();
- },
- beforeSetup: function(effect) {
- effect.element.setOpacity(effect.options.from).show();
- }}, arguments[1] || {});
- return new Effect.Opacity(element,options);
-}
-
-Effect.Puff = function(element) {
- element = $(element);
- var oldStyle = {
- opacity: element.getInlineOpacity(),
- position: element.getStyle('position'),
- top: element.style.top,
- left: element.style.left,
- width: element.style.width,
- height: element.style.height
- };
- return new Effect.Parallel(
- [ new Effect.Scale(element, 200,
- { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
- new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
- Object.extend({ duration: 1.0,
- beforeSetupInternal: function(effect) {
- Position.absolutize(effect.effects[0].element)
- },
- afterFinishInternal: function(effect) {
- effect.effects[0].element.hide().setStyle(oldStyle); }
- }, arguments[1] || {})
- );
-}
-
-Effect.BlindUp = function(element) {
- element = $(element);
- element.makeClipping();
- return new Effect.Scale(element, 0,
- Object.extend({ scaleContent: false,
- scaleX: false,
- restoreAfterFinish: true,
- afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping();
- }
- }, arguments[1] || {})
- );
-}
-
-Effect.BlindDown = function(element) {
- element = $(element);
- var elementDimensions = element.getDimensions();
- return new Effect.Scale(element, 100, Object.extend({
- scaleContent: false,
- scaleX: false,
- scaleFrom: 0,
- scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
- restoreAfterFinish: true,
- afterSetup: function(effect) {
- effect.element.makeClipping().setStyle({height: '0px'}).show();
- },
- afterFinishInternal: function(effect) {
- effect.element.undoClipping();
- }
- }, arguments[1] || {}));
-}
-
-Effect.SwitchOff = function(element) {
- element = $(element);
- var oldOpacity = element.getInlineOpacity();
- return new Effect.Appear(element, Object.extend({
- duration: 0.4,
- from: 0,
- transition: Effect.Transitions.flicker,
- afterFinishInternal: function(effect) {
- new Effect.Scale(effect.element, 1, {
- duration: 0.3, scaleFromCenter: true,
- scaleX: false, scaleContent: false, restoreAfterFinish: true,
- beforeSetup: function(effect) {
- effect.element.makePositioned().makeClipping();
- },
- afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
- }
- })
- }
- }, arguments[1] || {}));
-}
-
-Effect.DropOut = function(element) {
- element = $(element);
- var oldStyle = {
- top: element.getStyle('top'),
- left: element.getStyle('left'),
- opacity: element.getInlineOpacity() };
- return new Effect.Parallel(
- [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
- new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
- Object.extend(
- { duration: 0.5,
- beforeSetup: function(effect) {
- effect.effects[0].element.makePositioned();
- },
- afterFinishInternal: function(effect) {
- effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
- }
- }, arguments[1] || {}));
-}
-
-Effect.Shake = function(element) {
- element = $(element);
- var oldStyle = {
- top: element.getStyle('top'),
- left: element.getStyle('left') };
- return new Effect.Move(element,
- { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
- new Effect.Move(effect.element,
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
- new Effect.Move(effect.element,
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
- new Effect.Move(effect.element,
- { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
- new Effect.Move(effect.element,
- { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
- new Effect.Move(effect.element,
- { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
- effect.element.undoPositioned().setStyle(oldStyle);
- }}) }}) }}) }}) }}) }});
-}
-
-Effect.SlideDown = function(element) {
- element = $(element).cleanWhitespace();
- // SlideDown need to have the content of the element wrapped in a container element with fixed height!
- var oldInnerBottom = element.down().getStyle('bottom');
- var elementDimensions = element.getDimensions();
- return new Effect.Scale(element, 100, Object.extend({
- scaleContent: false,
- scaleX: false,
- scaleFrom: window.opera ? 0 : 1,
- scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
- restoreAfterFinish: true,
- afterSetup: function(effect) {
- effect.element.makePositioned();
- effect.element.down().makePositioned();
- if(window.opera) effect.element.setStyle({top: ''});
- effect.element.makeClipping().setStyle({height: '0px'}).show();
- },
- afterUpdateInternal: function(effect) {
- effect.element.down().setStyle({bottom:
- (effect.dims[0] - effect.element.clientHeight) + 'px' });
- },
- afterFinishInternal: function(effect) {
- effect.element.undoClipping().undoPositioned();
- effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
- }, arguments[1] || {})
- );
-}
-
-Effect.SlideUp = function(element) {
- element = $(element).cleanWhitespace();
- var oldInnerBottom = element.down().getStyle('bottom');
- return new Effect.Scale(element, window.opera ? 0 : 1,
- Object.extend({ scaleContent: false,
- scaleX: false,
- scaleMode: 'box',
- scaleFrom: 100,
- restoreAfterFinish: true,
- beforeStartInternal: function(effect) {
- effect.element.makePositioned();
- effect.element.down().makePositioned();
- if(window.opera) effect.element.setStyle({top: ''});
- effect.element.makeClipping().show();
- },
- afterUpdateInternal: function(effect) {
- effect.element.down().setStyle({bottom:
- (effect.dims[0] - effect.element.clientHeight) + 'px' });
- },
- afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
- effect.element.down().undoPositioned();
- }
- }, arguments[1] || {})
- );
-}
-
-// Bug in opera makes the TD containing this element expand for a instance after finish
-Effect.Squish = function(element) {
- return new Effect.Scale(element, window.opera ? 1 : 0, {
- restoreAfterFinish: true,
- beforeSetup: function(effect) {
- effect.element.makeClipping();
- },
- afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping();
- }
- });
-}
-
-Effect.Grow = function(element) {
- element = $(element);
- var options = Object.extend({
- direction: 'center',
- moveTransition: Effect.Transitions.sinoidal,
- scaleTransition: Effect.Transitions.sinoidal,
- opacityTransition: Effect.Transitions.full
- }, arguments[1] || {});
- var oldStyle = {
- top: element.style.top,
- left: element.style.left,
- height: element.style.height,
- width: element.style.width,
- opacity: element.getInlineOpacity() };
-
- var dims = element.getDimensions();
- var initialMoveX, initialMoveY;
- var moveX, moveY;
-
- switch (options.direction) {
- case 'top-left':
- initialMoveX = initialMoveY = moveX = moveY = 0;
- break;
- case 'top-right':
- initialMoveX = dims.width;
- initialMoveY = moveY = 0;
- moveX = -dims.width;
- break;
- case 'bottom-left':
- initialMoveX = moveX = 0;
- initialMoveY = dims.height;
- moveY = -dims.height;
- break;
- case 'bottom-right':
- initialMoveX = dims.width;
- initialMoveY = dims.height;
- moveX = -dims.width;
- moveY = -dims.height;
- break;
- case 'center':
- initialMoveX = dims.width / 2;
- initialMoveY = dims.height / 2;
- moveX = -dims.width / 2;
- moveY = -dims.height / 2;
- break;
- }
-
- return new Effect.Move(element, {
- x: initialMoveX,
- y: initialMoveY,
- duration: 0.01,
- beforeSetup: function(effect) {
- effect.element.hide().makeClipping().makePositioned();
- },
- afterFinishInternal: function(effect) {
- new Effect.Parallel(
- [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
- new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
- new Effect.Scale(effect.element, 100, {
- scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
- sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
- ], Object.extend({
- beforeSetup: function(effect) {
- effect.effects[0].element.setStyle({height: '0px'}).show();
- },
- afterFinishInternal: function(effect) {
- effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
- }
- }, options)
- )
- }
- });
-}
-
-Effect.Shrink = function(element) {
- element = $(element);
- var options = Object.extend({
- direction: 'center',
- moveTransition: Effect.Transitions.sinoidal,
- scaleTransition: Effect.Transitions.sinoidal,
- opacityTransition: Effect.Transitions.none
- }, arguments[1] || {});
- var oldStyle = {
- top: element.style.top,
- left: element.style.left,
- height: element.style.height,
- width: element.style.width,
- opacity: element.getInlineOpacity() };
-
- var dims = element.getDimensions();
- var moveX, moveY;
-
- switch (options.direction) {
- case 'top-left':
- moveX = moveY = 0;
- break;
- case 'top-right':
- moveX = dims.width;
- moveY = 0;
- break;
- case 'bottom-left':
- moveX = 0;
- moveY = dims.height;
- break;
- case 'bottom-right':
- moveX = dims.width;
- moveY = dims.height;
- break;
- case 'center':
- moveX = dims.width / 2;
- moveY = dims.height / 2;
- break;
- }
-
- return new Effect.Parallel(
- [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
- new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
- new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
- ], Object.extend({
- beforeStartInternal: function(effect) {
- effect.effects[0].element.makePositioned().makeClipping();
- },
- afterFinishInternal: function(effect) {
- effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
- }, options)
- );
-}
-
-Effect.Pulsate = function(element) {
- element = $(element);
- var options = arguments[1] || {};
- var oldOpacity = element.getInlineOpacity();
- var transition = options.transition || Effect.Transitions.sinoidal;
- var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
- reverser.bind(transition);
- return new Effect.Opacity(element,
- Object.extend(Object.extend({ duration: 2.0, from: 0,
- afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
- }, options), {transition: reverser}));
-}
-
-Effect.Fold = function(element) {
- element = $(element);
- var oldStyle = {
- top: element.style.top,
- left: element.style.left,
- width: element.style.width,
- height: element.style.height };
- element.makeClipping();
- return new Effect.Scale(element, 5, Object.extend({
- scaleContent: false,
- scaleX: false,
- afterFinishInternal: function(effect) {
- new Effect.Scale(element, 1, {
- scaleContent: false,
- scaleY: false,
- afterFinishInternal: function(effect) {
- effect.element.hide().undoClipping().setStyle(oldStyle);
- } });
- }}, arguments[1] || {}));
-};
-
-Effect.Morph = Class.create();
-Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
- initialize: function(element) {
- this.element = $(element);
- if(!this.element) throw(Effect._elementDoesNotExistError);
- var options = Object.extend({
- style: {}
- }, arguments[1] || {});
- if (typeof options.style == 'string') {
- if(options.style.indexOf(':') == -1) {
- var cssText = '', selector = '.' + options.style;
- $A(document.styleSheets).reverse().each(function(styleSheet) {
- if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
- else if (styleSheet.rules) cssRules = styleSheet.rules;
- $A(cssRules).reverse().each(function(rule) {
- if (selector == rule.selectorText) {
- cssText = rule.style.cssText;
- throw $break;
- }
- });
- if (cssText) throw $break;
- });
- this.style = cssText.parseStyle();
- options.afterFinishInternal = function(effect){
- effect.element.addClassName(effect.options.style);
- effect.transforms.each(function(transform) {
- if(transform.style != 'opacity')
- effect.element.style[transform.style.camelize()] = '';
- });
- }
- } else this.style = options.style.parseStyle();
- } else this.style = $H(options.style)
- this.start(options);
- },
- setup: function(){
- function parseColor(color){
- if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
- color = color.parseColor();
- return $R(0,2).map(function(i){
- return parseInt( color.slice(i*2+1,i*2+3), 16 )
- });
- }
- this.transforms = this.style.map(function(pair){
- var property = pair[0].underscore().dasherize(), value = pair[1], unit = null;
-
- if(value.parseColor('#zzzzzz') != '#zzzzzz') {
- value = value.parseColor();
- unit = 'color';
- } else if(property == 'opacity') {
- value = parseFloat(value);
- if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout))
- this.element.setStyle({zoom: 1});
- } else if(Element.CSS_LENGTH.test(value))
- var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/),
- value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null;
-
- var originalValue = this.element.getStyle(property);
- return $H({
- style: property,
- originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
- targetValue: unit=='color' ? parseColor(value) : value,
- unit: unit
- });
- }.bind(this)).reject(function(transform){
- return (
- (transform.originalValue == transform.targetValue) ||
- (
- transform.unit != 'color' &&
- (isNaN(transform.originalValue) || isNaN(transform.targetValue))
- )
- )
- });
- },
- update: function(position) {
- var style = $H(), value = null;
- this.transforms.each(function(transform){
- value = transform.unit=='color' ?
- $R(0,2).inject('#',function(m,v,i){
- return m+(Math.round(transform.originalValue[i]+
- (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) :
- transform.originalValue + Math.round(
- ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
- style[transform.style] = value;
- });
- this.element.setStyle(style);
- }
-});
-
-Effect.Transform = Class.create();
-Object.extend(Effect.Transform.prototype, {
- initialize: function(tracks){
- this.tracks = [];
- this.options = arguments[1] || {};
- this.addTracks(tracks);
- },
- addTracks: function(tracks){
- tracks.each(function(track){
- var data = $H(track).values().first();
- this.tracks.push($H({
- ids: $H(track).keys().first(),
- effect: Effect.Morph,
- options: { style: data }
- }));
- }.bind(this));
- return this;
- },
- play: function(){
- return new Effect.Parallel(
- this.tracks.map(function(track){
- var elements = [$(track.ids) || $$(track.ids)].flatten();
- return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
- }).flatten(),
- this.options
- );
- }
-});
-
-Element.CSS_PROPERTIES = $w(
- 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
- 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
- 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
- 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
- 'fontSize fontWeight height left letterSpacing lineHeight ' +
- 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
- 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
- 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
- 'right textIndent top width wordSpacing zIndex');
-
-Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
-
-String.prototype.parseStyle = function(){
- var element = Element.extend(document.createElement('div'));
- element.innerHTML = '<div style="' + this + '"></div>';
- var style = element.down().style, styleRules = $H();
-
- Element.CSS_PROPERTIES.each(function(property){
- if(style[property]) styleRules[property] = style[property];
- });
- if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) {
- styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
- }
- return styleRules;
-};
-
-Element.morph = function(element, style) {
- new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
- return element;
-};
-
-['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom',
- 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
- function(f) { Element.Methods[f] = Element[f]; }
-);
-
-Element.Methods.visualEffect = function(element, effect, options) {
- s = effect.gsub(/_/, '-').camelize();
- effect_class = s.charAt(0).toUpperCase() + s.substring(1);
- new Effect[effect_class](element, options);
- return $(element);
-};
-
-Element.addMethods();// script.aculo.us dragdrop.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
-
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Sammi Williams (http://www.oriontransfer.co.nz, sammi at oriontransfer.co.nz)
-//
-// script.aculo.us is freely distributable under the terms of an MIT-style license.
-// For details, see the script.aculo.us web site: http://script.aculo.us/
-
-if(typeof Effect == 'undefined')
- throw("dragdrop.js requires including script.aculo.us' effects.js library");
-
-var Droppables = {
- drops: [],
-
- remove: function(element) {
- this.drops = this.drops.reject(function(d) { return d.element==$(element) });
- },
-
- add: function(element) {
- element = $(element);
- var options = Object.extend({
- greedy: true,
- hoverclass: null,
- tree: false
- }, arguments[1] || {});
-
- // cache containers
- if(options.containment) {
- options._containers = [];
- var containment = options.containment;
- if((typeof containment == 'object') &&
- (containment.constructor == Array)) {
- containment.each( function(c) { options._containers.push($(c)) });
- } else {
- options._containers.push($(containment));
- }
- }
-
- if(options.accept) options.accept = [options.accept].flatten();
-
- Element.makePositioned(element); // fix IE
- options.element = element;
-
- this.drops.push(options);
- },
-
- findDeepestChild: function(drops) {
- deepest = drops[0];
-
- for (i = 1; i < drops.length; ++i)
- if (Element.isParent(drops[i].element, deepest.element))
- deepest = drops[i];
-
- return deepest;
- },
-
- isContained: function(element, drop) {
- var containmentNode;
- if(drop.tree) {
- containmentNode = element.treeNode;
- } else {
- containmentNode = element.parentNode;
- }
- return drop._containers.detect(function(c) { return containmentNode == c });
- },
-
- isAffected: function(point, element, drop) {
- return (
- (drop.element!=element) &&
- ((!drop._containers) ||
- this.isContained(element, drop)) &&
- ((!drop.accept) ||
- (Element.classNames(element).detect(
- function(v) { return drop.accept.include(v) } ) )) &&
- Position.within(drop.element, point[0], point[1]) );
- },
-
- deactivate: function(drop) {
- if(drop.hoverclass)
- Element.removeClassName(drop.element, drop.hoverclass);
- this.last_active = null;
- },
-
- activate: function(drop) {
- if(drop.hoverclass)
- Element.addClassName(drop.element, drop.hoverclass);
- this.last_active = drop;
- },
-
- show: function(point, element) {
- if(!this.drops.length) return;
- var affected = [];
-
- if(this.last_active) this.deactivate(this.last_active);
- this.drops.each( function(drop) {
- if(Droppables.isAffected(point, element, drop))
- affected.push(drop);
- });
-
- if(affected.length>0) {
- drop = Droppables.findDeepestChild(affected);
- Position.within(drop.element, point[0], point[1]);
- if(drop.onHover)
- drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
-
- Droppables.activate(drop);
- }
- },
-
- fire: function(event, element) {
- if(!this.last_active) return;
- Position.prepare();
-
- if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
- if (this.last_active.onDrop)
- this.last_active.onDrop(element, this.last_active.element, event);
- },
-
- reset: function() {
- if(this.last_active)
- this.deactivate(this.last_active);
- }
-}
-
-var Draggables = {
- drags: [],
- observers: [],
-
- register: function(draggable) {
- if(this.drags.length == 0) {
- this.eventMouseUp = this.endDrag.bindAsEventListener(this);
- this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
- this.eventKeypress = this.keyPress.bindAsEventListener(this);
-
- Event.observe(document, "mouseup", this.eventMouseUp);
- Event.observe(document, "mousemove", this.eventMouseMove);
- Event.observe(document, "keypress", this.eventKeypress);
- }
- this.drags.push(draggable);
- },
-
- unregister: function(draggable) {
- this.drags = this.drags.reject(function(d) { return d==draggable });
- if(this.drags.length == 0) {
- Event.stopObserving(document, "mouseup", this.eventMouseUp);
- Event.stopObserving(document, "mousemove", this.eventMouseMove);
- Event.stopObserving(document, "keypress", this.eventKeypress);
- }
- },
-
- activate: function(draggable) {
- if(draggable.options.delay) {
- this._timeout = setTimeout(function() {
- Draggables._timeout = null;
- window.focus();
- Draggables.activeDraggable = draggable;
- }.bind(this), draggable.options.delay);
- } else {
- window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
- this.activeDraggable = draggable;
- }
- },
-
- deactivate: function() {
- this.activeDraggable = null;
- },
-
- updateDrag: function(event) {
- if(!this.activeDraggable) return;
- var pointer = [Event.pointerX(event), Event.pointerY(event)];
- // Mozilla-based browsers fire successive mousemove events with
- // the same coordinates, prevent needless redrawing (moz bug?)
- if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
- this._lastPointer = pointer;
-
- this.activeDraggable.updateDrag(event, pointer);
- },
-
- endDrag: function(event) {
- if(this._timeout) {
- clearTimeout(this._timeout);
- this._timeout = null;
- }
- if(!this.activeDraggable) return;
- this._lastPointer = null;
- this.activeDraggable.endDrag(event);
- this.activeDraggable = null;
- },
-
- keyPress: function(event) {
- if(this.activeDraggable)
- this.activeDraggable.keyPress(event);
- },
-
- addObserver: function(observer) {
- this.observers.push(observer);
- this._cacheObserverCallbacks();
- },
-
- removeObserver: function(element) { // element instead of observer fixes mem leaks
- this.observers = this.observers.reject( function(o) { return o.element==element });
- this._cacheObserverCallbacks();
- },
-
- notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
- if(this[eventName+'Count'] > 0)
- this.observers.each( function(o) {
- if(o[eventName]) o[eventName](eventName, draggable, event);
- });
- if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
- },
-
- _cacheObserverCallbacks: function() {
- ['onStart','onEnd','onDrag'].each( function(eventName) {
- Draggables[eventName+'Count'] = Draggables.observers.select(
- function(o) { return o[eventName]; }
- ).length;
- });
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var Draggable = Class.create();
-Draggable._dragging = {};
-
-Draggable.prototype = {
- initialize: function(element) {
- var defaults = {
- handle: false,
- reverteffect: function(element, top_offset, left_offset) {
- var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
- new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
- queue: {scope:'_draggable', position:'end'}
- });
- },
- endeffect: function(element) {
- var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0;
- new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
- queue: {scope:'_draggable', position:'end'},
- afterFinish: function(){
- Draggable._dragging[element] = false
- }
- });
- },
- zindex: 1000,
- revert: false,
- scroll: false,
- scrollSensitivity: 20,
- scrollSpeed: 15,
- snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
- delay: 0
- };
-
- if(!arguments[1] || typeof arguments[1].endeffect == 'undefined')
- Object.extend(defaults, {
- starteffect: function(element) {
- element._opacity = Element.getOpacity(element);
- Draggable._dragging[element] = true;
- new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
- }
- });
-
- var options = Object.extend(defaults, arguments[1] || {});
-
- this.element = $(element);
-
- if(options.handle && (typeof options.handle == 'string'))
- this.handle = this.element.down('.'+options.handle, 0);
-
- if(!this.handle) this.handle = $(options.handle);
- if(!this.handle) this.handle = this.element;
-
- if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
- options.scroll = $(options.scroll);
- this._isScrollChild = Element.childOf(this.element, options.scroll);
- }
-
- Element.makePositioned(this.element); // fix IE
-
- this.delta = this.currentDelta();
- this.options = options;
- this.dragging = false;
-
- this.eventMouseDown = this.initDrag.bindAsEventListener(this);
- Event.observe(this.handle, "mousedown", this.eventMouseDown);
-
- Draggables.register(this);
- },
-
- destroy: function() {
- Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
- Draggables.unregister(this);
- },
-
- currentDelta: function() {
- return([
- parseInt(Element.getStyle(this.element,'left') || '0'),
- parseInt(Element.getStyle(this.element,'top') || '0')]);
- },
-
- initDrag: function(event) {
- if(typeof Draggable._dragging[this.element] != 'undefined' &&
- Draggable._dragging[this.element]) return;
- if(Event.isLeftClick(event)) {
- // abort on form elements, fixes a Firefox issue
- var src = Event.element(event);
- if((tag_name = src.tagName.toUpperCase()) && (
- tag_name=='INPUT' ||
- tag_name=='SELECT' ||
- tag_name=='OPTION' ||
- tag_name=='BUTTON' ||
- tag_name=='TEXTAREA')) return;
-
- var pointer = [Event.pointerX(event), Event.pointerY(event)];
- var pos = Position.cumulativeOffset(this.element);
- this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
-
- Draggables.activate(this);
- Event.stop(event);
- }
- },
-
- startDrag: function(event) {
- this.dragging = true;
-
- if(this.options.zindex) {
- this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
- this.element.style.zIndex = this.options.zindex;
- }
-
- if(this.options.ghosting) {
- this._clone = this.element.cloneNode(true);
- Position.absolutize(this.element);
- this.element.parentNode.insertBefore(this._clone, this.element);
- }
-
- if(this.options.scroll) {
- if (this.options.scroll == window) {
- var where = this._getWindowScroll(this.options.scroll);
- this.originalScrollLeft = where.left;
- this.originalScrollTop = where.top;
- } else {
- this.originalScrollLeft = this.options.scroll.scrollLeft;
- this.originalScrollTop = this.options.scroll.scrollTop;
- }
- }
-
- Draggables.notify('onStart', this, event);
-
- if(this.options.starteffect) this.options.starteffect(this.element);
- },
-
- updateDrag: function(event, pointer) {
- if(!this.dragging) this.startDrag(event);
- Position.prepare();
- Droppables.show(pointer, this.element);
- Draggables.notify('onDrag', this, event);
-
- this.draw(pointer);
- if(this.options.change) this.options.change(this);
-
- if(this.options.scroll) {
- this.stopScrolling();
-
- var p;
- if (this.options.scroll == window) {
- with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
- } else {
- p = Position.page(this.options.scroll);
- p[0] += this.options.scroll.scrollLeft + Position.deltaX;
- p[1] += this.options.scroll.scrollTop + Position.deltaY;
- p.push(p[0]+this.options.scroll.offsetWidth);
- p.push(p[1]+this.options.scroll.offsetHeight);
- }
- var speed = [0,0];
- if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
- if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
- if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
- if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
- this.startScrolling(speed);
- }
-
- // fix AppleWebKit rendering
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
-
- Event.stop(event);
- },
-
- finishDrag: function(event, success) {
- this.dragging = false;
-
- if(this.options.ghosting) {
- Position.relativize(this.element);
- Element.remove(this._clone);
- this._clone = null;
- }
-
- if(success) Droppables.fire(event, this.element);
- Draggables.notify('onEnd', this, event);
-
- var revert = this.options.revert;
- if(revert && typeof revert == 'function') revert = revert(this.element);
-
- var d = this.currentDelta();
- if(revert && this.options.reverteffect) {
- this.options.reverteffect(this.element,
- d[1]-this.delta[1], d[0]-this.delta[0]);
- } else {
- this.delta = d;
- }
-
- if(this.options.zindex)
- this.element.style.zIndex = this.originalZ;
-
- if(this.options.endeffect)
- this.options.endeffect(this.element);
-
- Draggables.deactivate(this);
- Droppables.reset();
- },
-
- keyPress: function(event) {
- if(event.keyCode!=Event.KEY_ESC) return;
- this.finishDrag(event, false);
- Event.stop(event);
- },
-
- endDrag: function(event) {
- if(!this.dragging) return;
- this.stopScrolling();
- this.finishDrag(event, true);
- Event.stop(event);
- },
-
- draw: function(point) {
- var pos = Position.cumulativeOffset(this.element);
- if(this.options.ghosting) {
- var r = Position.realOffset(this.element);
- pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
- }
-
- var d = this.currentDelta();
- pos[0] -= d[0]; pos[1] -= d[1];
-
- if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
- pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
- pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
- }
-
- var p = [0,1].map(function(i){
- return (point[i]-pos[i]-this.offset[i])
- }.bind(this));
-
- if(this.options.snap) {
- if(typeof this.options.snap == 'function') {
- p = this.options.snap(p[0],p[1],this);
- } else {
- if(this.options.snap instanceof Array) {
- p = p.map( function(v, i) {
- return Math.round(v/this.options.snap[i])*this.options.snap[i] }.bind(this))
- } else {
- p = p.map( function(v) {
- return Math.round(v/this.options.snap)*this.options.snap }.bind(this))
- }
- }}
-
- var style = this.element.style;
- if((!this.options.constraint) || (this.options.constraint=='horizontal'))
- style.left = p[0] + "px";
- if((!this.options.constraint) || (this.options.constraint=='vertical'))
- style.top = p[1] + "px";
-
- if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
- },
-
- stopScrolling: function() {
- if(this.scrollInterval) {
- clearInterval(this.scrollInterval);
- this.scrollInterval = null;
- Draggables._lastScrollPointer = null;
- }
- },
-
- startScrolling: function(speed) {
- if(!(speed[0] || speed[1])) return;
- this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
- this.lastScrolled = new Date();
- this.scrollInterval = setInterval(this.scroll.bind(this), 10);
- },
-
- scroll: function() {
- var current = new Date();
- var delta = current - this.lastScrolled;
- this.lastScrolled = current;
- if(this.options.scroll == window) {
- with (this._getWindowScroll(this.options.scroll)) {
- if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
- var d = delta / 1000;
- this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
- }
- }
- } else {
- this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
- this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
- }
-
- Position.prepare();
- Droppables.show(Draggables._lastPointer, this.element);
- Draggables.notify('onDrag', this);
- if (this._isScrollChild) {
- Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
- Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
- Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
- if (Draggables._lastScrollPointer[0] < 0)
- Draggables._lastScrollPointer[0] = 0;
- if (Draggables._lastScrollPointer[1] < 0)
- Draggables._lastScrollPointer[1] = 0;
- this.draw(Draggables._lastScrollPointer);
- }
-
- if(this.options.change) this.options.change(this);
- },
-
- _getWindowScroll: function(w) {
- var T, L, W, H;
- with (w.document) {
- if (w.document.documentElement && documentElement.scrollTop) {
- T = documentElement.scrollTop;
- L = documentElement.scrollLeft;
- } else if (w.document.body) {
- T = body.scrollTop;
- L = body.scrollLeft;
- }
- if (w.innerWidth) {
- W = w.innerWidth;
- H = w.innerHeight;
- } else if (w.document.documentElement && documentElement.clientWidth) {
- W = documentElement.clientWidth;
- H = documentElement.clientHeight;
- } else {
- W = body.offsetWidth;
- H = body.offsetHeight
- }
- }
- return { top: T, left: L, width: W, height: H };
- }
-}
-
-/*--------------------------------------------------------------------------*/
-
-var SortableObserver = Class.create();
-SortableObserver.prototype = {
- initialize: function(element, observer) {
- this.element = $(element);
- this.observer = observer;
- this.lastValue = Sortable.serialize(this.element);
- },
-
- onStart: function() {
- this.lastValue = Sortable.serialize(this.element);
- },
-
- onEnd: function() {
- Sortable.unmark();
- if(this.lastValue != Sortable.serialize(this.element))
- this.observer(this.element)
- }
-}
-
-var Sortable = {
- SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
-
- sortables: {},
-
- _findRootElement: function(element) {
- while (element.tagName.toUpperCase() != "BODY") {
- if(element.id && Sortable.sortables[element.id]) return element;
- element = element.parentNode;
- }
- },
-
- options: function(element) {
- element = Sortable._findRootElement($(element));
- if(!element) return;
- return Sortable.sortables[element.id];
- },
-
- destroy: function(element){
- var s = Sortable.options(element);
-
- if(s) {
- Draggables.removeObserver(s.element);
- s.droppables.each(function(d){ Droppables.remove(d) });
- s.draggables.invoke('destroy');
-
- delete Sortable.sortables[s.element.id];
- }
- },
-
- create: function(element) {
- element = $(element);
- var options = Object.extend({
- element: element,
- tag: 'li', // assumes li children, override with tag: 'tagname'
- dropOnEmpty: false,
- tree: false,
- treeTag: 'ul',
- overlap: 'vertical', // one of 'vertical', 'horizontal'
- constraint: 'vertical', // one of 'vertical', 'horizontal', false
- containment: element, // also takes array of elements (or id's); or false
- handle: false, // or a CSS class
- only: false,
- delay: 0,
- hoverclass: null,
- ghosting: false,
- scroll: false,
- scrollSensitivity: 20,
- scrollSpeed: 15,
- format: this.SERIALIZE_RULE,
- onChange: Prototype.emptyFunction,
- onUpdate: Prototype.emptyFunction
- }, arguments[1] || {});
-
- // clear any old sortable with same element
- this.destroy(element);
-
- // build options for the draggables
- var options_for_draggable = {
- revert: true,
- scroll: options.scroll,
- scrollSpeed: options.scrollSpeed,
- scrollSensitivity: options.scrollSensitivity,
- delay: options.delay,
- ghosting: options.ghosting,
- constraint: options.constraint,
- handle: options.handle };
-
- if(options.starteffect)
- options_for_draggable.starteffect = options.starteffect;
-
- if(options.reverteffect)
- options_for_draggable.reverteffect = options.reverteffect;
- else
- if(options.ghosting) options_for_draggable.reverteffect = function(element) {
- element.style.top = 0;
- element.style.left = 0;
- };
-
- if(options.endeffect)
- options_for_draggable.endeffect = options.endeffect;
-
- if(options.zindex)
- options_for_draggable.zindex = options.zindex;
-
- // build options for the droppables
- var options_for_droppable = {
- overlap: options.overlap,
- containment: options.containment,
- tree: options.tree,
- hoverclass: options.hoverclass,
- onHover: Sortable.onHover
- }
-
- var options_for_tree = {
- onHover: Sortable.onEmptyHover,
- overlap: options.overlap,
- containment: options.containment,
- hoverclass: options.hoverclass
- }
-
- // fix for gecko engine
- Element.cleanWhitespace(element);
-
- options.draggables = [];
- options.droppables = [];
-
- // drop on empty handling
- if(options.dropOnEmpty || options.tree) {
- Droppables.add(element, options_for_tree);
- options.droppables.push(element);
- }
-
- (this.findElements(element, options) || []).each( function(e) {
- // handles are per-draggable
- var handle = options.handle ?
- $(e).down('.'+options.handle,0) : e;
- options.draggables.push(
- new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
- Droppables.add(e, options_for_droppable);
- if(options.tree) e.treeNode = element;
- options.droppables.push(e);
- });
-
- if(options.tree) {
- (Sortable.findTreeElements(element, options) || []).each( function(e) {
- Droppables.add(e, options_for_tree);
- e.treeNode = element;
- options.droppables.push(e);
- });
- }
-
- // keep reference
- this.sortables[element.id] = options;
-
- // for onupdate
- Draggables.addObserver(new SortableObserver(element, options.onUpdate));
-
- },
-
- // return all suitable-for-sortable elements in a guaranteed order
- findElements: function(element, options) {
- return Element.findChildren(
- element, options.only, options.tree ? true : false, options.tag);
- },
-
- findTreeElements: function(element, options) {
- return Element.findChildren(
- element, options.only, options.tree ? true : false, options.treeTag);
- },
-
- onHover: function(element, dropon, overlap) {
- if(Element.isParent(dropon, element)) return;
-
- if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
- return;
- } else if(overlap>0.5) {
- Sortable.mark(dropon, 'before');
- if(dropon.previousSibling != element) {
- var oldParentNode = element.parentNode;
- element.style.visibility = "hidden"; // fix gecko rendering
- dropon.parentNode.insertBefore(element, dropon);
- if(dropon.parentNode!=oldParentNode)
- Sortable.options(oldParentNode).onChange(element);
- Sortable.options(dropon.parentNode).onChange(element);
- }
- } else {
- Sortable.mark(dropon, 'after');
- var nextElement = dropon.nextSibling || null;
- if(nextElement != element) {
- var oldParentNode = element.parentNode;
- element.style.visibility = "hidden"; // fix gecko rendering
- dropon.parentNode.insertBefore(element, nextElement);
- if(dropon.parentNode!=oldParentNode)
- Sortable.options(oldParentNode).onChange(element);
- Sortable.options(dropon.parentNode).onChange(element);
- }
- }
- },
-
- onEmptyHover: function(element, dropon, overlap) {
- var oldParentNode = element.parentNode;
- var droponOptions = Sortable.options(dropon);
-
- if(!Element.isParent(dropon, element)) {
- var index;
-
- var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
- var child = null;
-
- if(children) {
- var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
-
- for (index = 0; index < children.length; index += 1) {
- if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
- offset -= Element.offsetSize (children[index], droponOptions.overlap);
- } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
- child = index + 1 < children.length ? children[index + 1] : null;
- break;
- } else {
- child = children[index];
- break;
- }
- }
- }
-
- dropon.insertBefore(element, child);
-
- Sortable.options(oldParentNode).onChange(element);
- droponOptions.onChange(element);
- }
- },
-
- unmark: function() {
- if(Sortable._marker) Sortable._marker.hide();
- },
-
- mark: function(dropon, position) {
- // mark on ghosting only
- var sortable = Sortable.options(dropon.parentNode);
- if(sortable && !sortable.ghosting) return;
-
- if(!Sortable._marker) {
- Sortable._marker =
- ($('dropmarker') || Element.extend(document.createElement('DIV'))).
- hide().addClassName('dropmarker').setStyle({position:'absolute'});
- document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
- }
- var offsets = Position.cumulativeOffset(dropon);
- Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
-
- if(position=='after')
- if(sortable.overlap == 'horizontal')
- Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
- else
- Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
-
- Sortable._marker.show();
- },
-
- _tree: function(element, options, parent) {
- var children = Sortable.findElements(element, options) || [];
-
- for (var i = 0; i < children.length; ++i) {
- var match = children[i].id.match(options.format);
-
- if (!match) continue;
-
- var child = {
- id: encodeURIComponent(match ? match[1] : null),
- element: element,
- parent: parent,
- children: [],
- position: parent.children.length,
- container: $(children[i]).down(options.treeTag)
- }
-
- /* Get the element containing the children and recurse over it */
- if (child.container)
- this._tree(child.container, options, child)
-
- parent.children.push (child);
- }
-
- return parent;
- },
-
- tree: function(element) {
- element = $(element);
- var sortableOptions = this.options(element);
- var options = Object.extend({
- tag: sortableOptions.tag,
- treeTag: sortableOptions.treeTag,
- only: sortableOptions.only,
- name: element.id,
- format: sortableOptions.format
- }, arguments[1] || {});
-
- var root = {
- id: null,
- parent: null,
- children: [],
- container: element,
- position: 0
- }
-
- return Sortable._tree(element, options, root);
- },
-
- /* Construct a [i] index for a particular node */
- _constructIndex: function(node) {
- var index = '';
- do {
- if (node.id) index = '[' + node.position + ']' + index;
- } while ((node = node.parent) != null);
- return index;
- },
-
- sequence: function(element) {
- element = $(element);
- var options = Object.extend(this.options(element), arguments[1] || {});
-
- return $(this.findElements(element, options) || []).map( function(item) {
- return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
- });
- },
-
- setSequence: function(element, new_sequence) {
- element = $(element);
- var options = Object.extend(this.options(element), arguments[2] || {});
-
- var nodeMap = {};
- this.findElements(element, options).each( function(n) {
- if (n.id.match(options.format))
- nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
- n.parentNode.removeChild(n);
- });
-
- new_sequence.each(function(ident) {
- var n = nodeMap[ident];
- if (n) {
- n[1].appendChild(n[0]);
- delete nodeMap[ident];
- }
- });
- },
-
- serialize: function(element) {
- element = $(element);
- var options = Object.extend(Sortable.options(element), arguments[1] || {});
- var name = encodeURIComponent(
- (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
-
- if (options.tree) {
- return Sortable.tree(element, arguments[1]).children.map( function (item) {
- return [name + Sortable._constructIndex(item) + "[id]=" +
- encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
- }).flatten().join('&');
- } else {
- return Sortable.sequence(element, arguments[1]).map( function(item) {
- return name + "[]=" + encodeURIComponent(item);
- }).join('&');
- }
- }
-}
-
-// Returns true if child is contained within element
-Element.isParent = function(child, element) {
- if (!child.parentNode || child == element) return false;
- if (child.parentNode == element) return true;
- return Element.isParent(child.parentNode, element);
-}
-
-Element.findChildren = function(element, only, recursive, tagName) {
- if(!element.hasChildNodes()) return null;
- tagName = tagName.toUpperCase();
- if(only) only = [only].flatten();
- var elements = [];
- $A(element.childNodes).each( function(e) {
- if(e.tagName && e.tagName.toUpperCase()==tagName &&
- (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
- elements.push(e);
- if(recursive) {
- var grandchildren = Element.findChildren(e, only, recursive, tagName);
- if(grandchildren) elements.push(grandchildren);
- }
- });
-
- return (elements.length>0 ? elements.flatten() : []);
-}
-
-Element.offsetSize = function (element, type) {
- return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
-}
-// script.aculo.us controls.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
-
-// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
-// (c) 2005, 2006 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
-// (c) 2005, 2006 Jon Tirsen (http://www.tirsen.com)
-// Contributors:
-// Richard Livsey
-// Rahul Bhargava
-// Rob Wills
-//
-// script.aculo.us is freely distributable under the terms of an MIT-style license.
-// For details, see the script.aculo.us web site: http://script.aculo.us/
-
-// Autocompleter.Base handles all the autocompletion functionality
-// that's independent of the data source for autocompletion. This
-// includes drawing the autocompletion menu, observing keyboard
-// and mouse events, and similar.
-//
-// Specific autocompleters need to provide, at the very least,
-// a getUpdatedChoices function that will be invoked every time
-// the text inside the monitored textbox changes. This method
-// should get the text for which to provide autocompletion by
-// invoking this.getToken(), NOT by directly accessing
-// this.element.value. This is to allow incremental tokenized
-// autocompletion. Specific auto-completion logic (AJAX, etc)
-// belongs in getUpdatedChoices.
-//
-// Tokenized incremental autocompletion is enabled automatically
-// when an autocompleter is instantiated with the 'tokens' option
-// in the options parameter, e.g.:
-// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
-// will incrementally autocomplete with a comma as the token.
-// Additionally, ',' in the above example can be replaced with
-// a token array, e.g. { tokens: [',', '\n'] } which
-// enables autocompletion on multiple tokens. This is most
-// useful when one of the tokens is \n (a newline), as it
-// allows smart autocompletion after linebreaks.
-
-if(typeof Effect == 'undefined')
- throw("controls.js requires including script.aculo.us' effects.js library");
-
-var Autocompleter = {}
-Autocompleter.Base = function() {};
-Autocompleter.Base.prototype = {
- baseInitialize: function(element, update, options) {
- this.element = $(element);
- this.update = $(update);
- this.hasFocus = false;
- this.changed = false;
- this.active = false;
- this.index = 0;
- this.entryCount = 0;
-
- if(this.setOptions)
- this.setOptions(options);
- else
- this.options = options || {};
-
- this.options.paramName = this.options.paramName || this.element.name;
- this.options.tokens = this.options.tokens || [];
- this.options.frequency = this.options.frequency || 0.4;
- this.options.minChars = this.options.minChars || 1;
- this.options.onShow = this.options.onShow ||
- function(element, update){
- if(!update.style.position || update.style.position=='absolute') {
- update.style.position = 'absolute';
- Position.clone(element, update, {
- setHeight: false,
- offsetTop: element.offsetHeight
- });
- }
- Effect.Appear(update,{duration:0.15});
- };
- this.options.onHide = this.options.onHide ||
- function(element, update){ new Effect.Fade(update,{duration:0.15}) };
-
- if(typeof(this.options.tokens) == 'string')
- this.options.tokens = new Array(this.options.tokens);
-
- this.observer = null;
-
- this.element.setAttribute('autocomplete','off');
-
- Element.hide(this.update);
-
- Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this));
- Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));
- },
-
- show: function() {
- if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
- if(!this.iefix &&
- (navigator.appVersion.indexOf('MSIE')>0) &&
- (navigator.userAgent.indexOf('Opera')<0) &&
- (Element.getStyle(this.update, 'position')=='absolute')) {
- new Insertion.After(this.update,
- '<iframe id="' + this.update.id + '_iefix" '+
- 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
- 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
- this.iefix = $(this.update.id+'_iefix');
- }
- if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
- },
-
- fixIEOverlapping: function() {
- Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
- this.iefix.style.zIndex = 1;
- this.update.style.zIndex = 2;
- Element.show(this.iefix);
- },
-
- hide: function() {
- this.stopIndicator();
- if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
- if(this.iefix) Element.hide(this.iefix);
- },
-
- startIndicator: function() {
- if(this.options.indicator) Element.show(this.options.indicator);
- },
-
- stopIndicator: function() {
- if(this.options.indicator) Element.hide(this.options.indicator);
- },
-
- onKeyPress: function(event) {
- if(this.active)
- switch(event.keyCode) {
- case Event.KEY_TAB:
- case Event.KEY_RETURN:
- this.selectEntry();
- Event.stop(event);
- case Event.KEY_ESC:
- this.hide();
- this.active = false;
- Event.stop(event);
- return;
- case Event.KEY_LEFT:
- case Event.KEY_RIGHT:
- return;
- case Event.KEY_UP:
- this.markPrevious();
- this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
- return;
- case Event.KEY_DOWN:
- this.markNext();
- this.render();
- if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
- return;
- }
- else
- if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
- (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;
-
- this.changed = true;
- this.hasFocus = true;
-
- if(this.observer) clearTimeout(this.observer);
- this.observer =
- setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
- },
-
- activate: function() {
- this.changed = false;
- this.hasFocus = true;
- this.getUpdatedChoices();
- },
-
- onHover: function(event) {
- var element = Event.findElement(event, 'LI');
- if(this.index != element.autocompleteIndex)
- {
- this.index = element.autocompleteIndex;
- this.render();
- }
- Event.stop(event);
- },
-
- onClick: function(event) {
- var element = Event.findElement(event, 'LI');
- this.index = element.autocompleteIndex;
- this.selectEntry();
- this.hide();
- },
-
- onBlur: function(event) {
- // needed to make click events working
- setTimeout(this.hide.bind(this), 250);
- this.hasFocus = false;
- this.active = false;
- },
-
- render: function() {
- if(this.entryCount > 0) {
- for (var i = 0; i < this.entryCount; i++)
- this.index==i ?
- Element.addClassName(this.getEntry(i),"selected") :
- Element.removeClassName(this.getEntry(i),"selected");
-
- if(this.hasFocus) {
- this.show();
- this.active = true;
- }
- } else {
- this.active = false;
- this.hide();
- }
- },
-
- markPrevious: function() {
- if(this.index > 0) this.index--
- else this.index = this.entryCount-1;
- this.getEntry(this.index).scrollIntoView(true);
- },
-
- markNext: function() {
- if(this.index < this.entryCount-1) this.index++
- else this.index = 0;
- this.getEntry(this.index).scrollIntoView(false);
- },
-
- getEntry: function(index) {
- return this.update.firstChild.childNodes[index];
- },
-
- getCurrentEntry: function() {
- return this.getEntry(this.index);
- },
-
- selectEntry: function() {
- this.active = false;
- this.updateElement(this.getCurrentEntry());
- },
-
- updateElement: function(selectedElement) {
- if (this.options.updateElement) {
- this.options.updateElement(selectedElement);
- return;
- }
- var value = '';
- if (this.options.select) {
- var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
- if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
- } else
- value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
-
- var lastTokenPos = this.findLastToken();
- if (lastTokenPos != -1) {
- var newValue = this.element.value.substr(0, lastTokenPos + 1);
- var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
- if (whitespace)
- newValue += whitespace[0];
- this.element.value = newValue + value;
- } else {
- this.element.value = value;
- }
- this.element.focus();
-
- if (this.options.afterUpdateElement)
- this.options.afterUpdateElement(this.element, selectedElement);
- },
-
- updateChoices: function(choices) {
- if(!this.changed && this.hasFocus) {
- this.update.innerHTML = choices;
- Element.cleanWhitespace(this.update);
- Element.cleanWhitespace(this.update.down());
-
- if(this.update.firstChild && this.update.down().childNodes) {
- this.entryCount =
- this.update.down().childNodes.length;
- for (var i = 0; i < this.entryCount; i++) {
- var entry = this.getEntry(i);
- entry.autocompleteIndex = i;
- this.addObservers(entry);
- }
- } else {
- this.entryCount = 0;
- }
-
- this.stopIndicator();
- this.index = 0;
-
- if(this.entryCount==1 && this.options.autoSelect) {
- this.selectEntry();
- this.hide();
- } else {
- this.render();
- }
- }
- },
-
- addObservers: function(element) {
- Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
- Event.observe(element, "click", this.onClick.bindAsEventListener(this));
- },
-
- onObserverEvent: function() {
- this.changed = false;
- if(this.getToken().length>=this.options.minChars) {
- this.startIndicator();
- this.getUpdatedChoices();
- } else {
- this.active = false;
- this.hide();
- }
- },
-
- getToken: function() {
- var tokenPos = this.findLastToken();
- if (tokenPos != -1)
- var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
- else
- var ret = this.element.value;
-
- return /\n/.test(ret) ? '' : ret;
- },
-
- findLastToken: function() {
- var lastTokenPos = -1;
-
- for (var i=0; i<this.options.tokens.length; i++) {
- var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
- if (thisTokenPos > lastTokenPos)
- lastTokenPos = thisTokenPos;
- }
- return lastTokenPos;
- }
-}
-
-Ajax.Autocompleter = Class.create();
-Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), {
- initialize: function(element, update, url, options) {
- this.baseInitialize(element, update, options);
- this.options.asynchronous = true;
- this.options.onComplete = this.onComplete.bind(this);
- this.options.defaultParams = this.options.parameters || null;
- this.url = url;
- },
-
- getUpdatedChoices: function() {
- entry = encodeURIComponent(this.options.paramName) + '=' +
- encodeURIComponent(this.getToken());
-
- this.options.parameters = this.options.callback ?
- this.options.callback(this.element, entry) : entry;
-
- if(this.options.defaultParams)
- this.options.parameters += '&' + this.options.defaultParams;
-
- new Ajax.Request(this.url, this.options);
- },
-
- onComplete: function(request) {
- this.updateChoices(request.responseText);
- }
-
-});
-
-// The local array autocompleter. Used when you'd prefer to
-// inject an array of autocompletion options into the page, rather
-// than sending out Ajax queries, which can be quite slow sometimes.
-//
-// The constructor takes four parameters. The first two are, as usual,
-// the id of the monitored textbox, and id of the autocompletion menu.
-// The third is the array you want to autocomplete from, and the fourth
-// is the options block.
-//
-// Extra local autocompletion options:
-// - choices - How many autocompletion choices to offer
-//
-// - partialSearch - If false, the autocompleter will match entered
-// text only at the beginning of strings in the
-// autocomplete array. Defaults to true, which will
-// match text at the beginning of any *word* in the
-// strings in the autocomplete array. If you want to
-// search anywhere in the string, additionally set
-// the option fullSearch to true (default: off).
-//
-// - fullSsearch - Search anywhere in autocomplete array strings.
-//
-// - partialChars - How many characters to enter before triggering
-// a partial match (unlike minChars, which defines
-// how many characters are required to do any match
-// at all). Defaults to 2.
-//
-// - ignoreCase - Whether to ignore case when autocompleting.
-// Defaults to true.
-//
-// It's possible to pass in a custom function as the 'selector'
-// option, if you prefer to write your own autocompletion logic.
-// In that case, the other options above will not apply unless
-// you support them.
-
-Autocompleter.Local = Class.create();
-Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
- initialize: function(element, update, array, options) {
- this.baseInitialize(element, update, options);
- this.options.array = array;
- },
-
- getUpdatedChoices: function() {
- this.updateChoices(this.options.selector(this));
- },
-
- setOptions: function(options) {
- this.options = Object.extend({
- choices: 10,
- partialSearch: true,
- partialChars: 2,
- ignoreCase: true,
- fullSearch: false,
- selector: function(instance) {
- var ret = []; // Beginning matches
- var partial = []; // Inside matches
- var entry = instance.getToken();
- var count = 0;
-
- for (var i = 0; i < instance.options.array.length &&
- ret.length < instance.options.choices ; i++) {
-
- var elem = instance.options.array[i];
- var foundPos = instance.options.ignoreCase ?
- elem.toLowerCase().indexOf(entry.toLowerCase()) :
- elem.indexOf(entry);
-
- while (foundPos != -1) {
- if (foundPos == 0 && elem.length != entry.length) {
- ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
- elem.substr(entry.length) + "</li>");
- break;
- } else if (entry.length >= instance.options.partialChars &&
- instance.options.partialSearch && foundPos != -1) {
- if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
- partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
- elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
- foundPos + entry.length) + "</li>");
- break;
- }
- }
-
- foundPos = instance.options.ignoreCase ?
- elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
- elem.indexOf(entry, foundPos + 1);
-
- }
- }
- if (partial.length)
- ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
- return "<ul>" + ret.join('') + "</ul>";
- }
- }, options || {});
- }
-});
-
-// AJAX in-place editor
-//
-// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
-
-// Use this if you notice weird scrolling problems on some browsers,
-// the DOM might be a bit confused when this gets called so do this
-// waits 1 ms (with setTimeout) until it does the activation
-Field.scrollFreeActivate = function(field) {
- setTimeout(function() {
- Field.activate(field);
- }, 1);
-}
-
-Ajax.InPlaceEditor = Class.create();
-Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
-Ajax.InPlaceEditor.prototype = {
- initialize: function(element, url, options) {
- this.url = url;
- this.element = $(element);
-
- this.options = Object.extend({
- paramName: "value",
- okButton: true,
- okText: "ok",
- cancelLink: true,
- cancelText: "cancel",
- savingText: "Saving...",
- clickToEditText: "Click to edit",
- okText: "ok",
- rows: 1,
- onComplete: function(transport, element) {
- new Effect.Highlight(element, {startcolor: this.options.highlightcolor});
- },
- onFailure: function(transport) {
- alert("Error communicating with the server: " + transport.responseText.stripTags());
- },
- callback: function(form) {
- return Form.serialize(form);
- },
- handleLineBreaks: true,
- loadingText: 'Loading...',
- savingClassName: 'inplaceeditor-saving',
- loadingClassName: 'inplaceeditor-loading',
- formClassName: 'inplaceeditor-form',
- highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
- highlightendcolor: "#FFFFFF",
- externalControl: null,
- submitOnBlur: false,
- ajaxOptions: {},
- evalScripts: false
- }, options || {});
-
- if(!this.options.formId && this.element.id) {
- this.options.formId = this.element.id + "-inplaceeditor";
- if ($(this.options.formId)) {
- // there's already a form with that name, don't specify an id
- this.options.formId = null;
- }
- }
-
- if (this.options.externalControl) {
- this.options.externalControl = $(this.options.externalControl);
- }
-
- this.originalBackground = Element.getStyle(this.element, 'background-color');
- if (!this.originalBackground) {
- this.originalBackground = "transparent";
- }
-
- this.element.title = this.options.clickToEditText;
-
- this.onclickListener = this.enterEditMode.bindAsEventListener(this);
- this.mouseoverListener = this.enterHover.bindAsEventListener(this);
- this.mouseoutListener = this.leaveHover.bindAsEventListener(this);
- Event.observe(this.element, 'click', this.onclickListener);
- Event.observe(this.element, 'mouseover', this.mouseoverListener);
- Event.observe(this.element, 'mouseout', this.mouseoutListener);
- if (this.options.externalControl) {
- Event.observe(this.options.externalControl, 'click', this.onclickListener);
- Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener);
- Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
- }
- },
- enterEditMode: function(evt) {
- if (this.saving) return;
- if (this.editing) return;
- this.editing = true;
- this.onEnterEditMode();
- if (this.options.externalControl) {
- Element.hide(this.options.externalControl);
- }
- Element.hide(this.element);
- this.createForm();
- this.element.parentNode.insertBefore(this.form, this.element);
- if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);
- // stop the event to avoid a page refresh in Safari
- if (evt) {
- Event.stop(evt);
- }
- return false;
- },
- createForm: function() {
- this.form = document.createElement("form");
- this.form.id = this.options.formId;
- Element.addClassName(this.form, this.options.formClassName)
- this.form.onsubmit = this.onSubmit.bind(this);
-
- this.createEditField();
-
- if (this.options.textarea) {
- var br = document.createElement("br");
- this.form.appendChild(br);
- }
-
- if (this.options.okButton) {
- okButton = document.createElement("input");
- okButton.type = "submit";
- okButton.value = this.options.okText;
- okButton.className = 'editor_ok_button';
- this.form.appendChild(okButton);
- }
-
- if (this.options.cancelLink) {
- cancelLink = document.createElement("a");
- cancelLink.href = "javascript:void(0)";
- cancelLink.appendChild(document.createTextNode(this.options.cancelText));
- cancelLink.onclick = this.onclickCancel.bind(this);
- cancelLink.className = 'editor_cancel';
- this.form.appendChild(cancelLink);
- }
- },
- hasHTMLLineBreaks: function(string) {
- if (!this.options.handleLineBreaks) return false;
- return string.match(/<br/i) || string.match(/<p>/i);
- },
- convertHTMLLineBreaks: function(string) {
- return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
- },
- createEditField: function() {
- var text;
- if(this.options.loadTextURL) {
- text = this.options.loadingText;
- } else {
- text = this.getText();
- }
-
- var obj = this;
-
- if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
- this.options.textarea = false;
- var textField = document.createElement("input");
- textField.obj = this;
- textField.type = "text";
- textField.name = this.options.paramName;
- textField.value = text;
- textField.style.backgroundColor = this.options.highlightcolor;
- textField.className = 'editor_field';
- var size = this.options.size || this.options.cols || 0;
- if (size != 0) textField.size = size;
- if (this.options.submitOnBlur)
- textField.onblur = this.onSubmit.bind(this);
- this.editField = textField;
- } else {
- this.options.textarea = true;
- var textArea = document.createElement("textarea");
- textArea.obj = this;
- textArea.name = this.options.paramName;
- textArea.value = this.convertHTMLLineBreaks(text);
- textArea.rows = this.options.rows;
- textArea.cols = this.options.cols || 40;
- textArea.className = 'editor_field';
- if (this.options.submitOnBlur)
- textArea.onblur = this.onSubmit.bind(this);
- this.editField = textArea;
- }
-
- if(this.options.loadTextURL) {
- this.loadExternalText();
- }
- this.form.appendChild(this.editField);
- },
- getText: function() {
- return this.element.innerHTML;
- },
- loadExternalText: function() {
- Element.addClassName(this.form, this.options.loadingClassName);
- this.editField.disabled = true;
- new Ajax.Request(
- this.options.loadTextURL,
- Object.extend({
- asynchronous: true,
- onComplete: this.onLoadedExternalText.bind(this)
- }, this.options.ajaxOptions)
- );
- },
- onLoadedExternalText: function(transport) {
- Element.removeClassName(this.form, this.options.loadingClassName);
- this.editField.disabled = false;
- this.editField.value = transport.responseText.stripTags();
- Field.scrollFreeActivate(this.editField);
- },
- onclickCancel: function() {
- this.onComplete();
- this.leaveEditMode();
- return false;
- },
- onFailure: function(transport) {
- this.options.onFailure(transport);
- if (this.oldInnerHTML) {
- this.element.innerHTML = this.oldInnerHTML;
- this.oldInnerHTML = null;
- }
- return false;
- },
- onSubmit: function() {
- // onLoading resets these so we need to save them away for the Ajax call
- var form = this.form;
- var value = this.editField.value;
-
- // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
- // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
- // to be displayed indefinitely
- this.onLoading();
-
- if (this.options.evalScripts) {
- new Ajax.Request(
- this.url, Object.extend({
- parameters: this.options.callback(form, value),
- onComplete: this.onComplete.bind(this),
- onFailure: this.onFailure.bind(this),
- asynchronous:true,
- evalScripts:true
- }, this.options.ajaxOptions));
- } else {
- new Ajax.Updater(
- { success: this.element,
- // don't update on failure (this could be an option)
- failure: null },
- this.url, Object.extend({
- parameters: this.options.callback(form, value),
- onComplete: this.onComplete.bind(this),
- onFailure: this.onFailure.bind(this)
- }, this.options.ajaxOptions));
- }
- // stop the event to avoid a page refresh in Safari
- if (arguments.length > 1) {
- Event.stop(arguments[0]);
- }
- return false;
- },
- onLoading: function() {
- this.saving = true;
- this.removeForm();
- this.leaveHover();
- this.showSaving();
- },
- showSaving: function() {
- this.oldInnerHTML = this.element.innerHTML;
- this.element.innerHTML = this.options.savingText;
- Element.addClassName(this.element, this.options.savingClassName);
- this.element.style.backgroundColor = this.originalBackground;
- Element.show(this.element);
- },
- removeForm: function() {
- if(this.form) {
- if (this.form.parentNode) Element.remove(this.form);
- this.form = null;
- }
- },
- enterHover: function() {
- if (this.saving) return;
- this.element.style.backgroundColor = this.options.highlightcolor;
- if (this.effect) {
- this.effect.cancel();
- }
- Element.addClassName(this.element, this.options.hoverClassName)
- },
- leaveHover: function() {
- if (this.options.backgroundColor) {
- this.element.style.backgroundColor = this.oldBackground;
- }
- Element.removeClassName(this.element, this.options.hoverClassName)
- if (this.saving) return;
- this.effect = new Effect.Highlight(this.element, {
- startcolor: this.options.highlightcolor,
- endcolor: this.options.highlightendcolor,
- restorecolor: this.originalBackground
- });
- },
- leaveEditMode: function() {
- Element.removeClassName(this.element, this.options.savingClassName);
- this.removeForm();
- this.leaveHover();
- this.element.style.backgroundColor = this.originalBackground;
- Element.show(this.element);
- if (this.options.externalControl) {
- Element.show(this.options.externalControl);
- }
- this.editing = false;
- this.saving = false;
- this.oldInnerHTML = null;
- this.onLeaveEditMode();
- },
- onComplete: function(transport) {
- this.leaveEditMode();
- this.options.onComplete.bind(this)(transport, this.element);
- },
- onEnterEditMode: function() {},
- onLeaveEditMode: function() {},
- dispose: function() {
- if (this.oldInnerHTML) {
- this.element.innerHTML = this.oldInnerHTML;
- }
- this.leaveEditMode();
- Event.stopObserving(this.element, 'click', this.onclickListener);
- Event.stopObserving(this.element, 'mouseover', this.mouseoverListener);
- Event.stopObserving(this.element, 'mouseout', this.mouseoutListener);
- if (this.options.externalControl) {
- Event.stopObserving(this.options.externalControl, 'click', this.onclickListener);
- Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener);
- Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener);
- }
- }
-};
-
-Ajax.InPlaceCollectionEditor = Class.create();
-Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype);
-Object.extend(Ajax.InPlaceCollectionEditor.prototype, {
- createEditField: function() {
- if (!this.cached_selectTag) {
- var selectTag = document.createElement("select");
- var collection = this.options.collection || [];
- var optionTag;
- collection.each(function(e,i) {
- optionTag = document.createElement("option");
- optionTag.value = (e instanceof Array) ? e[0] : e;
- if((typeof this.options.value == 'undefined') &&
- ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true;
- if(this.options.value==optionTag.value) optionTag.selected = true;
- optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e));
- selectTag.appendChild(optionTag);
- }.bind(this));
- this.cached_selectTag = selectTag;
- }
-
- this.editField = this.cached_selectTag;
- if(this.options.loadTextURL) this.loadExternalText();
- this.form.appendChild(this.editField);
- this.options.callback = function(form, value) {
- return "value=" + encodeURIComponent(value);
- }
- }
-});
-
-// Delayed observer, like Form.Element.Observer,
-// but waits for delay after last key input
-// Ideal for live-search fields
-
-Form.Element.DelayedObserver = Class.create();
-Form.Element.DelayedObserver.prototype = {
- initialize: function(element, delay, callback) {
- this.delay = delay || 0.5;
- this.element = $(element);
- this.callback = callback;
- this.timer = null;
- this.lastValue = $F(this.element);
- Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
- },
- delayedListener: function(event) {
- if(this.lastValue == $F(this.element)) return;
- if(this.timer) clearTimeout(this.timer);
- this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
- this.lastValue = $F(this.element);
- },
- onTimerEvent: function() {
- this.timer = null;
- this.callback(this.element, $F(this.element));
- }
-};
-// script.aculo.us slider.js v1.7.0, Fri Jan 19 19:16:36 CET 2007
-
-// Copyright (c) 2005, 2006 Marty Haught, Thomas Fuchs
-//
-// script.aculo.us is freely distributable under the terms of an MIT-style license.
-// For details, see the script.aculo.us web site: http://script.aculo.us/
-
-if(!Control) var Control = {};
-Control.Slider = Class.create();
-
-// options:
-// axis: 'vertical', or 'horizontal' (default)
-//
-// callbacks:
-// onChange(value)
-// onSlide(value)
-Control.Slider.prototype = {
- initialize: function(handle, track, options) {
- var slider = this;
-
- if(handle instanceof Array) {
- this.handles = handle.collect( function(e) { return $(e) });
- } else {
- this.handles = [$(handle)];
- }
-
- this.track = $(track);
- this.options = options || {};
-
- this.axis = this.options.axis || 'horizontal';
- this.increment = this.options.increment || 1;
- this.step = parseInt(this.options.step || '1');
- this.range = this.options.range || $R(0,1);
-
- this.value = 0; // assure backwards compat
- this.values = this.handles.map( function() { return 0 });
- this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
- this.options.startSpan = $(this.options.startSpan || null);
- this.options.endSpan = $(this.options.endSpan || null);
-
- this.restricted = this.options.restricted || false;
-
- this.maximum = this.options.maximum || this.range.end;
- this.minimum = this.options.minimum || this.range.start;
-
- // Will be used to align the handle onto the track, if necessary
- this.alignX = parseInt(this.options.alignX || '0');
- this.alignY = parseInt(this.options.alignY || '0');
-
- this.trackLength = this.maximumOffset() - this.minimumOffset();
-
- this.handleLength = this.isVertical() ?
- (this.handles[0].offsetHeight != 0 ?
- this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
- (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
- this.handles[0].style.width.replace(/px$/,""));
-
- this.active = false;
- this.dragging = false;
- this.disabled = false;
-
- if(this.options.disabled) this.setDisabled();
-
- // Allowed values array
- this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
- if(this.allowedValues) {
- this.minimum = this.allowedValues.min();
- this.maximum = this.allowedValues.max();
- }
-
- this.eventMouseDown = this.startDrag.bindAsEventListener(this);
- this.eventMouseUp = this.endDrag.bindAsEventListener(this);
- this.eventMouseMove = this.update.bindAsEventListener(this);
-
- // Initialize handles in reverse (make sure first handle is active)
- this.handles.each( function(h,i) {
- i = slider.handles.length-1-i;
- slider.setValue(parseFloat(
- (slider.options.sliderValue instanceof Array ?
- slider.options.sliderValue[i] : slider.options.sliderValue) ||
- slider.range.start), i);
- Element.makePositioned(h); // fix IE
- Event.observe(h, "mousedown", slider.eventMouseDown);
- });
-
- Event.observe(this.track, "mousedown", this.eventMouseDown);
- Event.observe(document, "mouseup", this.eventMouseUp);
- Event.observe(document, "mousemove", this.eventMouseMove);
-
- this.initialized = true;
- },
- dispose: function() {
- var slider = this;
- Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
- Event.stopObserving(document, "mouseup", this.eventMouseUp);
- Event.stopObserving(document, "mousemove", this.eventMouseMove);
- this.handles.each( function(h) {
- Event.stopObserving(h, "mousedown", slider.eventMouseDown);
- });
- },
- setDisabled: function(){
- this.disabled = true;
- },
- setEnabled: function(){
- this.disabled = false;
- },
- getNearestValue: function(value){
- if(this.allowedValues){
- if(value >= this.allowedValues.max()) return(this.allowedValues.max());
- if(value <= this.allowedValues.min()) return(this.allowedValues.min());
-
- var offset = Math.abs(this.allowedValues[0] - value);
- var newValue = this.allowedValues[0];
- this.allowedValues.each( function(v) {
- var currentOffset = Math.abs(v - value);
- if(currentOffset <= offset){
- newValue = v;
- offset = currentOffset;
- }
- });
- return newValue;
- }
- if(value > this.range.end) return this.range.end;
- if(value < this.range.start) return this.range.start;
- return value;
- },
- setValue: function(sliderValue, handleIdx){
- if(!this.active) {
- this.activeHandleIdx = handleIdx || 0;
- this.activeHandle = this.handles[this.activeHandleIdx];
- this.updateStyles();
- }
- handleIdx = handleIdx || this.activeHandleIdx || 0;
- if(this.initialized && this.restricted) {
- if((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
- sliderValue = this.values[handleIdx-1];
- if((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
- sliderValue = this.values[handleIdx+1];
- }
- sliderValue = this.getNearestValue(sliderValue);
- this.values[handleIdx] = sliderValue;
- this.value = this.values[0]; // assure backwards compat
-
- this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
- this.translateToPx(sliderValue);
-
- this.drawSpans();
- if(!this.dragging || !this.event) this.updateFinished();
- },
- setValueBy: function(delta, handleIdx) {
- this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
- handleIdx || this.activeHandleIdx || 0);
- },
- translateToPx: function(value) {
- return Math.round(
- ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
- (value - this.range.start)) + "px";
- },
- translateToValue: function(offset) {
- return ((offset/(this.trackLength-this.handleLength) *
- (this.range.end-this.range.start)) + this.range.start);
- },
- getRange: function(range) {
- var v = this.values.sortBy(Prototype.K);
- range = range || 0;
- return $R(v[range],v[range+1]);
- },
- minimumOffset: function(){
- return(this.isVertical() ? this.alignY : this.alignX);
- },
- maximumOffset: function(){
- return(this.isVertical() ?
- (this.track.offsetHeight != 0 ? this.track.offsetHeight :
- this.track.style.height.replace(/px$/,"")) - this.alignY :
- (this.track.offsetWidth != 0 ? this.track.offsetWidth :
- this.track.style.width.replace(/px$/,"")) - this.alignY);
- },
- isVertical: function(){
- return (this.axis == 'vertical');
- },
- drawSpans: function() {
- var slider = this;
- if(this.spans)
- $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
- if(this.options.startSpan)
- this.setSpan(this.options.startSpan,
- $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
- if(this.options.endSpan)
- this.setSpan(this.options.endSpan,
- $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
- },
- setSpan: function(span, range) {
- if(this.isVertical()) {
- span.style.top = this.translateToPx(range.start);
- span.style.height = this.translateToPx(range.end - range.start + this.range.start);
- } else {
- span.style.left = this.translateToPx(range.start);
- span.style.width = this.translateToPx(range.end - range.start + this.range.start);
- }
- },
- updateStyles: function() {
- this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
- Element.addClassName(this.activeHandle, 'selected');
- },
- startDrag: function(event) {
- if(Event.isLeftClick(event)) {
- if(!this.disabled){
- this.active = true;
-
- var handle = Event.element(event);
- var pointer = [Event.pointerX(event), Event.pointerY(event)];
- var track = handle;
- if(track==this.track) {
- var offsets = Position.cumulativeOffset(this.track);
- this.event = event;
- this.setValue(this.translateToValue(
- (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
- ));
- var offsets = Position.cumulativeOffset(this.activeHandle);
- this.offsetX = (pointer[0] - offsets[0]);
- this.offsetY = (pointer[1] - offsets[1]);
- } else {
- // find the handle (prevents issues with Safari)
- while((this.handles.indexOf(handle) == -1) && handle.parentNode)
- handle = handle.parentNode;
-
- if(this.handles.indexOf(handle)!=-1) {
- this.activeHandle = handle;
- this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
- this.updateStyles();
-
- var offsets = Position.cumulativeOffset(this.activeHandle);
- this.offsetX = (pointer[0] - offsets[0]);
- this.offsetY = (pointer[1] - offsets[1]);
- }
- }
- }
- Event.stop(event);
- }
- },
- update: function(event) {
- if(this.active) {
- if(!this.dragging) this.dragging = true;
- this.draw(event);
- // fix AppleWebKit rendering
- if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
- Event.stop(event);
- }
- },
- draw: function(event) {
- var pointer = [Event.pointerX(event), Event.pointerY(event)];
- var offsets = Position.cumulativeOffset(this.track);
- pointer[0] -= this.offsetX + offsets[0];
- pointer[1] -= this.offsetY + offsets[1];
- this.event = event;
- this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
- if(this.initialized && this.options.onSlide)
- this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
- },
- endDrag: function(event) {
- if(this.active && this.dragging) {
- this.finishDrag(event, true);
- Event.stop(event);
- }
- this.active = false;
- this.dragging = false;
- },
- finishDrag: function(event, success) {
- this.active = false;
- this.dragging = false;
- this.updateFinished();
- },
- updateFinished: function() {
- if(this.initialized && this.options.onChange)
- this.options.onChange(this.values.length>1 ? this.values : this.value, this);
- this.event = null;
- }
-}/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx Core
- *
- * Purpose:
- * Implementation of core and base classes for Jx components.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-/**
- * Class: Jx
- * Jx is a global singleton object that contains the entire Jx library
- * within it. All Jx functions, attributes and classes are accessed
- * through the global Jx object. Jx should not create any other
- * global variables, if you discover that it does then please report
- * it as a bug
- */
-
-/* LEAVE THIS SEMI-COLON, IT PREVENTS PROBLEMS WITH COMPRESSION */
-;
-
-/* firebug console supressor for IE/Safari/Opera */
-Event.observe(window, 'load', function() {
- if (!("console" in window) || !("firebug" in window.console)) {
- var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
- "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
-
- window.console = {};
- for (var i = 0; i < names.length; ++i) {
- window.console[names[i]] = function() {};
- }
- }
-});
-/* inspired by extjs, removes css image flicker and related problems in IE 6 */
-var ua = navigator.userAgent.toLowerCase();
-var isIE = ua.indexOf("msie") > -1,
- isIE7 = ua.indexOf("msie 7") > -1;
-if(isIE && !isIE7) {
- try {
- document.execCommand("BackgroundImageCache", false, true);
- } catch(e) {}
-}
-
-/* Setup global namespace
- * If jxcore is loaded by jx.js, then the namespace and baseURL are
- * already established
- */
-if (typeof Jx == 'undefined') {
- var Jx = {};
- /**
- * Property: {Boolean} COMBINED_CSS
- * controls whether Jx uses a single, combined CSS file or
- * individual ones. The combined version is used automatically
- * if the combined or compressed version of Jx is used,
- * otherwise separate ones are used.
- */
- Jx.COMBINED_CSS = true;
- var aScripts = document.getElementsByTagName('SCRIPT');
- for (var i=0; i<aScripts.length; i++) {
- var s = aScripts[i].src;
- //only check for lib/jx because we were loaded by
- var n = s.indexOf('lib/jx');
- if (n != -1) {
- /**
- * Property: {String} baseURL
- * This is the URL that Jx was loaded from, it is
- * automatically calculated from the script tag
- * src property that included Jx.
- */
- Jx.baseURL = s.substring(0,n);
- break;
- }
- }
-}
-
-/**
- * Property: {Object} importRules
- *
- * an object containing a list of CSS files to be included
- * to make the loaded Jx components function correctly
- */
-Jx.importRules = {};
-/**
- * Property: {Object} importRules
- *
- * an object containing a list of CSS files to be included
- * to make the loaded Jx components function correctly
- */
-Jx.importRulesIE = {};
-
-/**
- * Method: addStyleSheet
- *
- * Individual components of Jx call this function to get their
- * style sheets imported at run time.
- *
- * Parameters:
- *
- * styleSheet {String} the relative path to the CSS file (relative
- * to <Jx.baseURL>).
- *
- * ieOnly {Boolean} if true, then the style sheet is only loaded
- * if the browser is Internet Explorer.
- */
-Jx.addStyleSheet = function(styleSheet, ieOnly) {
- if (ieOnly) {
- this.importRulesIE[styleSheet] = styleSheet;
- } else {
- this.importRules[styleSheet] = styleSheet;
- }
-};
-
-/* everything needs reset.css */
-Jx.addStyleSheet('reset.css');
-
-/**
- * Method: applyPNGFilter
- *
- * Static method that applies the PNG Filter Hack for IE browsers
- * when showing 24bit PNG's. Used automatically for img tags with
- * a class of png24.
- *
- * The filter is applied using a nifty feature of IE that allows javascript to
- * be executed as part of a CSS style rule - this ensures that the hack only
- * gets applied on IE browsers.
- *
- * Parameters:
- *
- * object {Object} the object (img) to which the filter needs to be applied.
- */
-Jx.applyPNGFilter = function(o) {
- var t=Jx.baseURL + "images/a_pixel.png";
- if( o.src != t ) {
- var s=o.src;
- o.src = t;
- o.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+s+"',sizingMethod='scale')";
- }
-};
-
-Jx.imgQueue = []; //The queue of images to be loaded
-Jx.imgLoaded = {}; //a hash table of images that have been loaded and cached
-Jx.imagesLoading = 0; //counter for number of concurrent image loads
-
-/**
- * Method: addToImgQueue
- *
- * request that an image be set to a DOM IMG element src attribute. This puts
- * the image into a queue and there are private methods to manage that queue
- * and limit image loading to 2 at a time.
- */
-Jx.addToImgQueue = function(obj) {
- if (Jx.imgLoaded[obj.src]) {
- //if this image was already requested (i.e. it's in cache) just set it directly
- obj.domElement.src = obj.src;
- } else {
- //otherwise stick it in te queue
- Jx.imgQueue.push(obj);
- Jx.imgLoaded[obj.src] = true;
- }
- //start the queue management process
- Jx.checkImgQueue();
-};
-
-/**
- * Method: checkImgQueue
- *
- * An internal method that ensures no more than 2 images are loading at a time.
- */
-Jx.checkImgQueue = function() {
- //console.log(this.imgQueue.length+":"+this.imagesLoading);
- while (Jx.imagesLoading < 2 && Jx.imgQueue.length > 0) {
- Jx.loadNextImg();
- }
-};
-
-/**
- * Method: loadNextImg
- *
- * An internal method actually populate the DOM element with the image source.
- */
-Jx.loadNextImg = function() {
- var obj = Jx.imgQueue.shift();
- if (obj) {
- ++Jx.imagesLoading;
- obj.domElement.onload = function(){--Jx.imagesLoading; Jx.checkImgQueue();};
- obj.domElement.onerror = function(){--Jx.imagesLoading; Jx.checkImgQueue();};
- obj.domElement.src = obj.src;
- }
-};
-
-
-/**
- * Class: Jx.Listener
- *
- * Jx.Listener is a mix-in class that performs common listener functions
- * for objects that support listeners. It is intended to be added to
- * existing classes using the following syntax:
- *
- * (code)
- * Object.extends( MyClass.prototype, Jx.Listener.prototype)
- * (end)
- *
- * The Jx.Listener class functions provide support for managing a list of
- * listeners (add, remove) and dispatching events to listeners (processEvent).
- */
-Jx.Listener = Class.create();
-Jx.Listener.prototype = {
- /**
- * Method: addListener
- *
- * add a listener to the provided list.
- *
- * Parameters:
- *
- * list {Array} the array of listeners to add the listener to.
- *
- * object {Object} the object to add as a listener.
- */
- addListener: function (list,obj) {list.push(obj);},
- /**
- * Method: removeListener
- *
- * remove a listener from the provided list.
- *
- * Parameters:
- *
- * list {Array} the array of listeners to remove the listener from.
- *
- * obj {Object} the object to remove as a listener.
- */
- removeListener: function(list,obj) {
- for(var i=0;i<list.length;i++) {if (list[i] == obj) {list.splice(i,1); break;}}},
- /**
- * Method: processEvent
- *
- * call each listener with a given method and event.
- *
- * Parameters:
- *
- * list {Array} the array of listeners to call.
- *
- * fnName {String} the name of a function to call on each listener.
- *
- * obj {Object} an object to pass to each listener.
- */
- processEvent: function(list,fnName,obj){list.each(function(o){if (o[fnName]) {o[fnName](obj);}});}
-};
-
-/**
- * Class: Jx.UniqueId
- *
- * Jx.UniqueId is used to assign unique ids to selected elements
- * This is used to solve a problem where multiple external html
- * fragments are loaded into the DOM via ajax at runtime. It is
- * not always possible to ensure that every element has a unique
- * id. This is not a problem if you are using id for CSS styling
- * but if you are using it to access elements using $() then
- * you may get unexpected results.
- *
- * Jx.UniqueId is a mix-in class. Extend an existing class to
- * enable it to handle unique ids. Register the ids that you
- * want to be unique and then get a reference to those objects
- * through the interface exposed by this class.
- *
- * The class retrieves the elements by id by walking a dom object
- * and retains references to each of the actual DOM objects
- * you have registered.
- */
-Jx.UniqueId = Class.create();
-Jx.UniqueId.prototype = {
- /**
- * Property: {Array} uniqueIdRefs
- *
- * an array of references obtained from by registering ids
- */
- uniqueIdRefs: null,
- /**
- * Method: initUniqueId
- *
- * initialize the UniqueId object. This must be called prior to
- * calling the <registerIds> function. Typically, it is called
- * in the constructor of an object that includes Jx.UniqueId.
- */
- initUniqueId: function() {
- this.uniqueIdRefs = [];
- },
- /**
- * Method: deregisterIds
- *
- * removes all registered ids
- */
- deregisterIds: function() {
- this.uniqueIdRefs.length = 0;
- },
- /**
- * Method: registerIds
- *
- * searches the domObj for each of the ids passed in and
- * obtains a unique reference to them so that subsequent
- * calls to <getObj> will return the right object.
- *
- * Parameters:
- *
- * aIds {Array} an array of strings containing ids of DOM elements
- * to register.
- *
- * domObj {Object} an HTML element reference to search for unique
- * ids within
- */
- registerIds: function (aIds, domObj) {
- if (aIds.indexOf(domObj.id) != -1) {
- this.uniqueIdRefs[domObj.id] = domObj;
- }
- for (var i=0; i<domObj.childNodes.length; i++) {
- this.registerIds(aIds, domObj.childNodes[i]);
- }
- },
- /**
- * Method: getObj
- *
- * return an object by id if it was previously registered
- *
- * Parameters:
- *
- * id {String} the original registered id to get the DOM object for
- *
- * Returns:
- *
- * {Object} returns an object or null if the requested id did not
- * exist in the original DOM object or if the id was not registered.
- */
- getObj: function(id) {
- return this.uniqueIdRefs[id] || null;
- }
-};
-
-/**
- * Class: Jx.Action
- *
- * Jx.Action is a utility class that provides a mechanism to separate
- * the user interface code from the implementation code for a particular
- * piece of functionality. A Jx.Action is used primarily as the basis for
- * clickable UI elements such as Jx.Button and Jx.MenuItem that need to
- * execute a particular function when the user clicks them. The Jx.Action
- * includes a mechanism for controlling the state of the action, allowing
- * an application to enable or disable an action at any time. A single
- * Jx.Action may be used with multiple buttons and menu items, allowing
- * the application to easily keep various user interface elements
- * synchronized without having to explicitly maintain all of them.
- *
- * A new instance of Jx.Action is created by passing a function object
- * to the constructor. The function object may be a function name or
- * the result of using the Prototype bind() function.
- *
- * For example:
- *
- * (code)
- * //Example 1:
- * //use a function reference directly
- * function myFunction() { alert('my function'); }
- * var action = new Jx.Action(myFunction);
- *
- * //Example 2:
- * //use a function bound to an object through bind()
- * var myClass = Class.create();
- * myClass.prototype = {
- * initialize: function() {this.x = 1;},
- * getX: function() {alert(this.x); }
- * };
- *
- * var myInstance = new myClass();
- * var action = new Jx.Action(myInstance.getX.bind(myInstance));
- *
- * (end)
- *
- * To enable or disable a Jx.Action (and consequently update any associated
- * buttons or menu items), use the setEnabled([true|false]) method.
- *
- * For example:
- *
- * (code)
- * //disable an action
- * action.setEnabled(false);
- * (end)
- */
-Jx.Action = Class.create();
-Jx.Action.prototype = {
- /**
- * Property: {Array} pcl
- * an array of property change listeners attached to this action
- */
- pcl: null,
- /**
- * Property: {Boolean} enabled
- *
- * whether the action (and its associated interface object) is
- * currently enabled or not. This is controlled through the
- * setEnabled function
- */
- enabled : null,
- /**
- * Constructor: Jx.Action
- *
- * construct a new instance of Jx.Action that invokes a function
- * when activated
- *
- * Parameters:
- *
- * f - {Function} the function that this action triggers
- */
- initialize: function(f) {
- this.pcl = [];
- this.enabled = true;
- this.actionPerformed = f;
- },
- /**
- * Method: addPropertyChangeListener
- *
- * add a property change listener to this action. When the enabled
- * state of the action changes, all property change listeners are
- * notified through their propertyChanged method.
- *
- * Parameters:
- *
- * obj - {Object} the object to notify of property changes
- */
- addPropertyChangeListener: function(obj){this.addListener(this.pcl, obj);},
- /**
- * Method: removePropertyChangeListener
- *
- * remove a property change listener from this action.
- *
- * Parameters:
- *
- * obj - {Object} the property change listener to remove.
- */
- removePropertyChangeListener: function(obj) {
- this.removeListener(this.pcl, obj);
- },
- /**
- * Method: isEnabled
- *
- * return whether the action is currently enabled or not.
- *
- * Return: {Boolean}
- */
- isEnabled: function() {return this.enabled;},
- /**
- * Method: setEnabled
- *
- * set the state of this action.
- *
- * Parameters:
- *
- * b - {Boolean} a boolean value to set enabled state of this action to.
- */
- setEnabled: function(b){
- /* prevent unnecessary propogation of propertyChanged */
- if (this.enabled == b) {
- return;
- }
- this.enabled = b;
- this.processEvent(this.pcl,'propertyChanged',this);
- },
- /**
- * Method: bindTo
- *
- * convenience function to bind an item to this action. This
- * adds the item as a property change listener to the action
- * and adds the action as an ActionListener to the item.
- *
- * Parameters:
- *
- * item - {Object} the object to bind the action to.
- */
- bindTo : function( item ) {
- this.addPropertyChangeListener(item);
- item.addActionListener(this);
- },
- /**
- * Method: unbindFrom
- *
- * convenience function to undo a binding between an object and
- * this action.
- *
- * Parameters:
- *
- * item - {Object} the object to unbind from this action.
- */
- unbindFrom: function(item) {
- this.removePropertyChangeListener(item);
- item.removeActionListener(this);
- },
- /**
- * Method: actionPerformed
- *
- * placeholder function to conform to the ActionListener interface.
- *
- * Parameters:
- *
- * obj - {Object} the object that performed the action.
- */
- actionPerformed : function(obj) { alert('actionPerformed'); }
-};
-Object.extend(Jx.Action.prototype, Jx.Listener.prototype);
-
-/**
- * Class: Element
- *
- * Element is a global object provided by the prototype.js library. The
- * functions documented here are extensions to the Element object provided
- * by Jx to make cross-browser compatibility easier to achieve.
- */
-Object.extend( Element, {
- /**
- * Method: getBoxSizing
- *
- * return the box sizing of an element, one of 'content-box' or
- *'border-box'.
- *
- * Parameters:
- *
- * elem - {Object} the element to get the box sizing of.
- *
- * Return: {String} the box sizing of the element.
- */
- getBoxSizing : function(elem) {
- var result = 'content-box';
- elem = $(elem);
- if (elem.currentStyle || window.opera) {
- var cm = document["compatMode"];
- if (cm == "BackCompat" || cm == "QuirksMode") {
- result = 'border-box';
- } else {
- result = 'content-box';
- }
- } else {
- if (arguments.length == 0) {
- node = document.documentElement;
- }
- var sizing = Element.getStyle(elem, "-moz-box-sizing");
- if (!sizing) {
- sizing = Element.getStyle(elem, "box-sizing");
- }
- result = (sizing ? sizing : 'content-box');
- }
- return result;
- },
- /**
- * Method: getContentBoxSize
- *
- * return the size of the content area of an element. This is the size of
- * the element less margins, padding, and borders.
- *
- * Parameters:
- *
- * elem - {Object} the element to get the content size of.
- *
- * Return: {Object} an object with two properties, width and height, that
- * are the size of the content area of the measured element.
- */
- getContentBoxSize : function(elem) {
- elem = $(elem);
- Element.toggleMeasurable(elem);
- var w = elem.offsetWidth;
- var h = elem.offsetHeight;
- var padding = Element.getPaddingSize(elem);
- var border = Element.getBorderSize(elem);
- Element.toggleMeasurable(elem);
- w = w - padding.left - padding.right - border.left - border.right;
- h = h - padding.bottom - padding.top - border.bottom - border.top;
- return {width: w, height: h};
- },
- /**
- * Method: getBorderBoxSize
- *
- * return the size of the border area of an element. This is the size of
- * the element less margins.
- *
- * Parameters:
- *
- * elem - {Object} the element to get the border sizing of.
- *
- * Return: {Object} an object with two properties, width and height, that
- * are the size of the border area of the measured element.
- */
- getBorderBoxSize: function(elem) {
- elem = $(elem);
- Element.toggleMeasurable(elem);
- var w = elem.offsetWidth;
- var h = elem.offsetHeight;
- Element.toggleMeasurable(elem);
- return {width: w, height: h};
- },
- /**
- * Method: setContentBoxSize
- *
- * set either or both of the width and height of an element to
- * the provided size. This function ensures that the content
- * area of the element is the requested size and the resulting
- * size of the element may be larger depending on padding and
- * borders.
- *
- * Parameters:
- *
- * elem - {Object} the element to set the content area of.
- *
- * size - {Object} an object with a width and/or height property that is the size to set
- * the content area of the element to.
- */
- setContentBoxSize : function(elem, size) {
- elem = $(elem);
- if (Element.getBoxSizing(elem) == 'border-box') {
- var padding = Element.getPaddingSize(elem);
- var border = Element.getBorderSize(elem);
- if (typeof size.width != 'undefined') {
- var width = (size.width + padding.left + padding.right + border.left + border.right);
- if (width < 0) {
- width = 0;
- }
- elem.style.width = width + 'px';
- }
- if (typeof size.height != 'undefined') {
- var height = (size.height + padding.top + padding.bottom + border.top + border.bottom);
- if (height < 0) {
- height = 0;
- }
- elem.style.height = height + 'px';
- }
- } else {
- if (typeof size.width != 'undefined') {
- elem.style.width = size.width + 'px';
- }
- if (typeof size.height != 'undefined') {
- elem.style.height = size.height + 'px';
- }
- }
- },
- /**
- * Method: setBorderBoxSize
- *
- * set either or both of the width and height of an element to
- * the provided size. This function ensures that the border
- * size of the element is the requested size and the resulting
- * content areaof the element may be larger depending on padding and
- * borders.
- *
- * Parameters:
- *
- * elem - {Object} the element to set the border size of.
- *
- * size - {Object} an object with a width and/or height property that is the size to set
- * the content area of the element to.
- */
- setBorderBoxSize : function(elem, size) {
- elem = $(elem);
- if (Element.getBoxSizing(elem) == 'content-box') {
- var padding = Element.getPaddingSize(elem);
- var border = Element.getBorderSize(elem);
- var margin = Element.getMarginSize(elem);
- if (typeof size.width != 'undefined') {
- var width = (size.width - padding.left - padding.right - border.left - border.right - margin.left - margin.right);
- if (width < 0) {
- width = 0;
- }
- elem.style.width = width + 'px';
- }
- if (typeof size.height != 'undefined') {
- var height = (size.height - padding.top - padding.bottom - border.top - border.bottom - margin.top - margin.bottom);
- if (height < 0) {
- height = 0;
- }
- elem.style.height = height + 'px';
- }
- } else {
- if (typeof size.width != 'undefined' && size.width >= 0) {
- elem.style.width = size.width + 'px';
- }
- if (typeof size.height != 'undefined' && size.height >= 0) {
- elem.style.height = size.height + 'px';
- }
- }
- },
- /**
- * Method: getPaddingSize
- *
- * returns the padding for each edge of an element
- *
- * Parameters:
- *
- * elem - {Object} The element to get the padding for.
- *
- * Return: {Object} an object with properties left, top, right and bottom
- * that contain the associated padding values.
- */
- getPaddingSize : function (elem) {
- elem = $(elem);
- Element.toggleMeasurable(elem);
- var l = Element.getNumber(Element.getStyle(elem, 'padding-left'));
- var t = Element.getNumber(Element.getStyle(elem, 'padding-top'));
- var r = Element.getNumber(Element.getStyle(elem, 'padding-right'));
- var b = Element.getNumber(Element.getStyle(elem, 'padding-bottom'));
- Element.toggleMeasurable(elem);
- return {left:l, top:t, right: r, bottom: b};
- },
- /**
- * Method: getBorderSize
- *
- * returns the border size for each edge of an element
- *
- * Parameters:
- *
- * elem - {Object} The element to get the borders for.
- *
- * Return: {Object} an object with properties left, top, right and bottom
- * that contain the associated border values.
- */
- getBorderSize : function(elem) {
- elem = $(elem);
- Element.toggleMeasurable(elem);
- var l = Element.getNumber(Element.getStyle(elem, 'border-left-width'));
- var t = Element.getNumber(Element.getStyle(elem, 'border-top-width'));
- var r = Element.getNumber(Element.getStyle(elem, 'border-right-width'));
- var b = Element.getNumber(Element.getStyle(elem, 'border-bottom-width'));
- Element.toggleMeasurable(elem);
- return {left:l, top:t, right: r, bottom: b};
- },
- /**
- * Method: getMarginSize
- *
- * returns the margin size for each edge of an element
- *
- * Parameters:
- *
- * elem - {Object} The element to get the margins for.
- *
- * Return: {Object} an object with properties left, top, right and bottom
- * that contain the associated margin values.
- */
- getMarginSize : function(elem) {
- elem = $(elem);
- Element.toggleMeasurable(elem);
- var l = Element.getNumber(Element.getStyle(elem, 'margin-left'));
- var t = Element.getNumber(Element.getStyle(elem, 'margin-top'));
- var r = Element.getNumber(Element.getStyle(elem, 'margin-right'));
- var b = Element.getNumber(Element.getStyle(elem, 'margin-bottom'));
- Element.toggleMeasurable(elem);
- return {left:l, top:t, right: r, bottom: b};
- },
- /**
- * Method: getNumber
- *
- * safely parse a number and return its integer value. A NaN value
- * returns 0. CSS size values are also parsed correctly.
- *
- * Parameters:
- *
- * n - {Mixed} the string or object to parse.
- *
- * Return: {Integer} the integer value that the parameter represents
- */
- getNumber: function(n) {
- var result = n==null||isNaN(parseInt(n))?0:parseInt(n);
- return result;
- },
- /**
- * Method: getPageDimensions
- *
- * return the dimensions of the browser client area.
- *
- * Return: {Object} an object containing a width and height property
- * that represent the width and height of the browser client area.
- */
- getPageDimensions: function() {
- return {width: Element.getInsideWindowWidth(), height: Element.getInsideWindowHeight()};
- },
- /**
- * Method: getInsideWindowWidth
- *
- * returns the width of the browser client area
- *
- * Return: {Integer} the width of the browser client area
- */
- getInsideWindowWidth: function() {
- if (window.innerWidth) {
- return window.innerWidth;
- } else if (document.compatMode && document.compatMode.indexOf("CSS1") >= 0) {
- // measure the html element's clientWidth
- return document.body.parentElement.clientWidth;
- } else if (document.body && document.body.clientWidth) {
- return document.body.clientWidth;
- }
- return 0;
- },
- /**
- * Method: getInsideWindowHeight
- *
- * returns the height of the browser client area
- *
- * Return: {Integer} the height of the browser client area
- */
- getInsideWindowHeight: function() {
- if (window.innerHeight) {
- return window.innerHeight;
- } else if (document.compatMode && document.compatMode.indexOf("CSS1") >= 0) {
- // measure the html element's clientHeight
- return document.body.parentElement.clientHeight;
- } else if (document.body && document.body.clientHeight) {
- return document.body.clientHeight;
- }
- return 0;
- },
- /**
- * Method: toggleMeasurable
- *
- * toggles an element's display style property so it can be
- * measured. If the element has display: none, it is
- * changed to display: block and made temporarily visible
- * so that it can be measured. Calling this function
- * a second time with the same element will revert the
- * changes. This allows an element to be measured in
- * various ways.
- *
- * Parameters:
- *
- * elem - {Object} the element to measure.
- */
- toggleMeasurable: function(elem) {
- if (Element.getStyle(elem, 'display') == 'none') {
- elem.old = {};
- elem.old.display = elem.style.display;
- elem.old.visibility = elem.style.visibility;
- elem.old.position = elem.style.position;
- elem.style.position = 'absolute';
- elem.style.visibility = 'hidden';
- elem.style.display = 'block';
- } else {
- if (elem.old) {
- elem.style.display = elem.old.display;
- elem.style.visibility = elem.old.visibility;
- elem.style.position = elem.old.position;
- elem.old = null;
- }
- }
- }
-} );
-
-/**
- * Class: Jx.ContentLoader
- *
- * ContentLoader is a mix-in class that provides a consistent
- * mechanism for other Jx controls to load content in one of
- * four different ways:
- *
- * o using an existing element, by id
- *
- * o using an existing element, by object reference
- *
- * o using an HTML string
- *
- * o using a URL to get the content remotely
- */
-Jx.ContentLoader = Class.create();
-Jx.ContentLoader.prototype = {
- /**
- * Property: bContentLoaded
- *
- * tracks the load state of the content, specifically useful
- * in the case of remote content.
- */
- bContentLoaded: false,
- /**
- * Method: contentLoaded
- *
- * callback function that handles remote content
- *
- * Parameters:
- *
- * element - {Object} the element to put the content into
- *
- * options - {Object} the options that were passed to loadContent originally, only
- * used to get the optional onContentLoaded callback function.
- *
- * r - {XmlHttpRequest} the XmlHttpRequest object that has the content.
- */
- contentLoaded: function(element, options, r) {
- element.innerHTML = r.responseText;
- this.bContentLoaded = true;
- if (options.onContentLoaded) {
- options.onContentLoaded();
- }
- },
- /**
- * Method: contentLoadFailed
- *
- * callback function that handles failure to load remote content
- *
- * Parameters:
- *
- * options - {Object} the options that were passed to loadContent originally, only
- * used to get the optional onContentLoadedFailed callback function.
- *
- * r - {XmlHttpRequest} the XmlHttpRequest object that has the failure code
- */
- contentLoadFailed: function(options, r) {
- this.bContentLoaded = false;
- if (options.onContentLoadFailed) {
- options.onContentLoadFailed();
- }
- },
- /**
- * Method: loadContent
- *
- * triggers loading of content based on parameters passed in the
- * options parameter. The options parameter can have the following
- * attributes:
- *
- * Parameters:
- * element - {Object} the element to insert the content into
- * options - {Object} an object containing the attributes indicating what
- * content to load.
- *
- * Options:
- * content - {HTMLElement} an HTML element that becomes the content
- * contentID - {String} the id of an element to use as the content
- * contentURL - {String} URL to get the content remotely
- * contentHTML - {String} some HTML to use as the innerHTML of the content
- * area.
- * onContentLoaded - {Function} a function to call when the content is
- * loaded.
- * onContentLoadFailed - a function object that is called if the content
- * fails to load, primarily useful when using the contentURL method of
- * loading content.
- */
- loadContent: function(element, options) {
- options = options || {};
- element = $(element);
- if (options.content) {
- element.appendChild(options.content);
- this.bContentLoaded = true;
- } else if (options.contentID) {
- var c = $(options.contentID);
- if (c) {
- element.appendChild(c);
- this.bContentLoaded = true;
- }
- } else if (options.contentURL) {
- this.bContentLoaded = false;
- var ts = '';//'ts=' + (new Date()).getTime();
- var a = new Ajax.Request( options.contentURL,
- Object.extend({method:'get',
- onSuccess:this.contentLoaded.bind(this, element, options),
- onFailure: this.contentLoadFailed.bind(this, options),
- //requestHeaders: ['If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT'],
- parameters: ts}));
- } else if (options.contentHTML) {
- element.innerHTML = options.contentHTML;
- this.bContentLoaded = true;
- } else {
- this.bContentLoaded = true;
- }
- if (this.bContentLoaded && options.onContentLoaded) {
- options.onContentLoaded();
- }
- }
-};/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Button
- *
- * Purpose:
- * Implementation of a generic button widget and several
- * useful subclasses.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-/**
- * Class: Jx.Button
- *
- * Jx.Button creates a clickable element in the application that is hooked
- * to an instance of Jx.Action. When the button is clicked, it activates
- * its associated Jx.Action instance. When the Jx.Action associated with
- * the button is enabled or disabled, the Jx.Button updates its visual
- * appearance to reflect the current state of the Jx.Action.
- *
- * Visually, a Jx.Button consists of an <A> tag that may contain either
- * an image, a label, or both (the label appears to the right of the button
- * if both are present). The default styles for Jx.Button expect the
- * image to be 16 x 16 pixels, with a padding of 4px and a border of 1px
- * which results in an element that is 26 pixels high. The width of the
- * button automatically accomodates the image and label as required.
- *
- * When you construct a new instance of Jx.Button, the button does not
- * automatically get inserted into the application. Typically a button
- * is used as part of building another capability such as a Jx.Toolbar.
- * However, if you want to manually insert the button into your
- * application, you may use the domObj property of the Jx.Button instance.
- * In this case, you will use one of the DOM manipulation functions such
- * as appendChild, and pass button.domObj. For example:
- *
- * (code)
- * var button = new Jx.Button(myAction, options);
- * var li = $('myListItem'); //obtain a reference to a DOM element
- * li.appendChild(button.domObj);
- * (end)
- *
- * To use a Jx.Button in an application, you must first create an instance
- * of Jx.Action and then pass it as the first parameter to the Jx.Button
- * constructor. The second argument to a Jx.Button constructor is an options
- * object allows configuring the button.
- *
- * (code)
- * Example:
- * function myFunc() { alert('you clicked me'); }
- * var action = new Jx.Action(myFunc);
- * var options = {
- * imgPath: 'images/mybutton.png',
- * tooltip: 'click me!',
- * label: 'click me'
- * }
- * var button = new Jx.Button(action, options);
- * (end)
- */
-
-Jx.addStyleSheet('button/button.css');
-
-Jx.Button = Class.create();
-Object.extend(Jx.Button.prototype, Jx.Listener.prototype);
-Object.extend(Jx.Button.prototype, {
- /**
- * Property: {Array} al
- * an array of action listeners that are attached to the button.
- */
- al: null,
- /**
- * Property: {Object} domObj
- * the HTML element that is inserted into the DOM for this button
- */
- domObj: null,
- /**
- * Property: {Boolean} enabled
- * whether the button is enabled or not. This is controlled by
- * the Action object that the button is associated with.
- */
- enabled:null,
- /**
- * Constructor: Jx.Button
- * create a new button.
- *
- * Parameters:
- * action - {Object} the action to trigger for this button.
- * options - {Object} an object containing optional properties for this
- * button as below.
- *
- * Options:
- * image - optional. A string value that is the url to load the image to
- * display in this button. The default styles size this image to 16 x 16.
- * If not provided, then the button will have no icon.
- * tooltip - optional. A string value to use as the alt/title attribute of
- * the <A> tag that wraps the button, resulting in a tooltip that appears
- * when the user hovers the mouse over a button in most browsers. If
- * not provided, the button will have no tooltip.
- * label - optional. A string value that is used as a label on the button.
- * disabledClass - optional. A string value that is the name of a CSS class
- * to put on the <A> tag if the button is in a disabled state. If not
- * provided, the default class jxDisabled is used. You may provide
- * your own class or override jxDisabled.
- * imgClass - optional. A string value that is the name of a CSS class to
- * put on the <IMG> element. The default value is jxButtonIcon.
- */
- initialize : function( action, options ) {
- options = options || {};
- this.al = [];
- this.action = action; //TODO move action into options
-
- var imgPath = (options.imgPath || options.image) || '';
- var tooltip = options.tooltip || '';
- var label = options.label || '';
- this.disabledClass = options.disabledClass || 'jxDisabled';
-
- this.domA = document.createElement('a');
- this.domA.className = 'jxButton';
- this.domA.href='javascript:void(0)'; //make hover effects work in IE
- this.domA.onclick = this.onclick.bindAsEventListener(this);
- this.domA.title = tooltip;
- this.domA.alt = tooltip;
-
- var span = document.createElement('span');
- span.className = 'jxButtonSpan';
- this.domA.appendChild(span);
-
-
- // if (imgPath != '') {
- // this.domImg = document.createElement('span');
- // this.domImg.className = 'jxButtonIcon';
- // if (options.imageClass && options.imageClass != '') {
- // Element.addClassName(this.domImg, options.imageClass);
- // }
- // this.domImg.style.backgroundImage = "url("+imgPath+")";
- // this.domImg.innerHTML = ' ';
- // span.appendChild(this.domImg);
- // }
-
- this.domLabel = document.createElement('span');
- this.domLabel.className = 'jxButtonContent';
- //this.domLabel.className = label != '' ? 'jxButtonLabel' : ''; //jxButtonLabel jxButtonEmptyLabel';
- this.domLabel.innerHTML = label != '' ? label : ' ';
- span.appendChild(this.domLabel);
-
- if (label != '') {
- Element.addClassName(this.domLabel, 'jxButtonLabel');
- }
-
- if (imgPath != '') {
- Element.addClassName(this.domLabel, 'jxButtonIcon');
- this.domLabel.style.backgroundImage = "url("+imgPath+")";
- }
-
- /* if this is an action button, then hook to the action */
- if (this.action) {
- this.action.bindTo(this);
- this.propertyChanged(this.action);
- }
-
- this.domObj = document.createElement('div');
- this.domObj.className = 'jxButtonContainer';
- this.domObj.appendChild(this.domA);
-
- if (options.halign && options.halign == 'left') {
- Element.addClassName(this.domObj, 'jxButtonContentLeft');
- }
- if (options.valign && options.valign == 'top') {
- Element.addClassName(this.domObj, 'jxButtonContentTop');
- }
- },
- /**
- * Method: onclick
- * triggered when the user clicks the button, processes the
- * actionPerformed event
- */
- onclick : function() {
- if (this.enabled) {
- this.processEvent(this.al, 'actionPerformed', this);
- }
- return false;
- },
- /**
- * Method: addActionListener
- * add an action listener to the button
- *
- * Parameters:
- * obj - {Object} the object to add as an action listener
- */
- addActionListener: function(obj) {
- this.addListener(this.al,obj);
- },
- /**
- * Method: removeActionListener
- * remove an action listener from the button
- *
- * Parameters:
- * obj - {Object} the object to remove.
- */
- removeActionListener : function(obj) {
- this.removeListener(this.al, obj);
- },
- /**
- * Method: propertyChanged
- * implements the PropertyChangeListener interface
- * for handling the enabled state changing on the action
- * associated with this button
- *
- * Parameters:
- * obj - {Object} the action that is changing state
- */
- propertyChanged: function(obj) {
- this.enabled = obj.isEnabled();
- if (this.enabled) {
- Element.removeClassName( this.domObj, this.disabledClass );
- } else {
- Element.addClassName( this.domObj, this.disabledClass );
- }
- },
- /**
- * Method: setImage
- * set the image of this button to a new image URL
- *
- * Parameters:
- * path - {String} the new url to use as the image for this button
- */
- setImage: function(path) {
- if (this.domImg) {
- this.domImg.src = path;
- }
- },
- /**
- * Method: setLabel
- *
- * sets the text of the button. Only works if a label was supplied
- * when the button was constructed
- *
- * Parametera:
- *
- * label - {String} the new label for the button
- */
- setLabel: function(label) {
- if (this.domLabel) {
- this.domLabel.innerHTML = label;
- }
- },
- /**
- * Method: setTooltip
- * sets the tooltip displayed by the button
- *
- * Parameters:
- * tooltip - {String} the new tooltip
- */
- setTooltip: function(tooltip) {
- if (this.domImg) {
- this.domImg.title = tooltip;
- this.domImg.alt = tooltip;
- }
- }
-} );
-
-/**
- * Class: Jx.Button.Flyout
- *
- * Flyout buttons expose a panel when the user clicks the button. The
- * panel can have arbitrary content.
- *
- * The button itself does not trigger an external action. You must provide
- * any necessary code to hook up elements in the panel to your application.
- */
-Jx.Button.Flyout = Class.create();
-Object.extend(Jx.Button.Flyout.prototype, Jx.Button.prototype);
-Object.extend(Jx.Button.Flyout.prototype, Jx.ContentLoader.prototype);
-Object.extend(Jx.Button.Flyout.prototype, {
- /**
- * Property: content
- * {HTMLElement} a reference to the DOM node that contains the flyout
- * content
- */
- content: null,
- /**
- * Constructor: Jx.Button.Flyout
- * construct a new instance of a flyout button. The single options
- * argument takes the same parameters as <Jx.Button.initialize> plus
- * content loading options as per <Jx.ContentLoader>.
- *
- * Parameters:
- * options - {Object} an options object used to initialize the button.
- * See <Jx.Button::Jx.Button>
- */
- initialize: function(options) {
- options = options || {};
- var a = new Jx.Action(this.show.bind(this));
- Jx.Button.prototype.initialize.apply(this, [a, options]);
- Element.addClassName(this.domA, 'jxButtonFlyout');
-
- /* iframe shim to prevent scrollbars and
- inputs from showing through the menu */
- this.iframe = document.createElement('iframe');
- this.iframe.className = 'jxMenuShim';
- this.iframe.scrolling = 'no';
- this.iframe.frameborder = 0;
-
- this.content = document.createElement('div');
- Element.addClassName(this.content, 'jxFlyout');
- this.loadContent(this.content, options);
- this.domObj.appendChild(this.content);
- this.content.style.display = 'none';
-
- this.keypressWatcher = this.keypressHandler.bindAsEventListener(this);
- this.hideWatcher = this.clickHandler.bindAsEventListener(this);
- },
-
- /**
- * Method: show
- * Show the flyout content
- */
- show: function() {
- if (!window.opera && !this.iframe.parentNode) {
- this.content.appendChild(this.iframe);
- }
- this.content.style.display = 'block';
- Event.observe(window, 'keypress', this.keypressWatcher);
- Event.observe(document, 'click', this.hideWatcher);
- },
-
- /**
- * Method: hide
- * Hide the flyout content
- */
- hide: function() {
- this.content.style.display = 'none';
- Event.stopObserving(window, 'keypress', this.keypressWatcher);
- Event.stopObserving(document, 'click', this.hideWatcher);
- },
- /**
- * Method: clickHandler
- * hide flyout if the user clicks outside of the flyout
- */
- clickHandler: function(e) {
- var elm = Event.element(e);
- if (!Element.descendantOf(elm, this.domObj.parentNode)) {
- this.hide();
- }
- },
- /**
- * Method: keypressHandler
- * hide flyout if the user presses the ESC key
- */
- keypressHandler: function(e) {
- var charCode=(e.charCode)?e.charCode:e.keyCode;
- if (charCode == Event.KEY_ESC) {
- this.hide();
- }
- }
-});
-
-/**
- * Class: Jx.Button.Multi
- *
- * Multi buttons are used to contain multiple buttons in a drop down list
- * where only one button is actually visible and clickable in the interface.
- *
- * When the user clicks the active button, it performs its normal action.
- * The user may also click a drop-down arrow to the right of the button and
- * access the full list of buttons. Clicking a button in the list causes
- * that button to replace the active button in the toolbar and performs
- * the button's regular action.
- *
- * Other buttons can be added to the Multi button using the <add> function.
- */
-Jx.Button.Multi = Class.create();
-Jx.Button.Multi.prototype = {
- /**
- * Property: {<Jx.Button>} activeButton
- * the currently selected button
- */
- activeButton: null,
- /**
- * Property: {Array} buttons
- * an array of all available buttons
- */
- buttons: null,
- /**
- * Constructor: Jx.Button.Multi
- * construct a new instance of Jx.Button.Multi.
- */
- initialize: function() {
- this.buttons = [];
- this.content = document.createElement('div');
- this.tb = new Jx.Toolbar(this.content, 'right');
- this.flyout = new Jx.Button.Flyout({content: this.content, label: ' '});
- Element.addClassName(this.flyout.domObj.firstChild, 'jxButtonMulti');
-
- this.domObj = document.createElement('div');
- //this.domObj.className = 'jxButtonMulti';
- this.buttonContainer = document.createElement('div');
- this.buttonContainer.className = 'jxButtonMultiContainer';
- this.domObj.appendChild(this.buttonContainer);
- this.domObj.appendChild(this.flyout.domObj);
- },
- /**
- * Method: add
- * adds one or more buttons to the Multi button. The first button
- * added becomes the active button initialize. This function
- * takes a variable number of arguments, each of which is expected
- * to be an instance of <Jx.Button>.
- *
- * Parameters:
- * button - {<Jx.Button>} a <Jx.Button> instance, may be repeated in the parameter list
- */
- add: function() {
- for (var i=0; i<arguments.length; i++) {
- var theButton = arguments[i];
- var action = new Jx.Action(this.setButton.bind(this, theButton));
- var button = new Jx.Button(action, {});
- var click = button.domA.onclick;
- button.domObj = theButton.domObj.cloneNode(true);
- button.domObj.onclick = click;
- this.tb.add(button);
- if (!this.activeButton) {
- this.buttonContainer.appendChild(theButton.domObj);
- this.activeButton = theButton;
- }
- }
- },
- /**
- * Method: setActiveButton
- * update the menu item to be the requested button.
- *
- * Parameters:
- * button - {<Jx.Button>} a <Jx.Button> instance that was added to this multi button.
- */
- setActiveButton: function(button) {
- while(this.buttonContainer.childNodes.length > 0) {
- this.buttonContainer.removeChild(this.buttonContainer.firstChild);
- }
- this.buttonContainer.appendChild(button.domObj);
- },
- /**
- * Method: setButton
- * update the active button in the menu item, trigger the button's action
- * and hide the flyout that contains the buttons.
- *
- * Parameters:
- * button - {<Jx.Button>} The button to set as the active button
- */
- setButton: function(button) {
- this.setActiveButton(button);
- button.onclick();
- this.flyout.hide();
- }
-};
-
-/**
- * Class: Jx.Button.Picker
- *
- * A Picker button allows the user to choose an item from a list of items.
- * The items can be any HTML element. The chosen item is placed into the
- * menu item.
- */
-Jx.Button.Picker = Class.create();
-Object.extend(Jx.Button.Picker.prototype, Jx.Button.Flyout.prototype);
-Object.extend(Jx.Button.Picker.prototype, {
- /**
- * Property: {HTMLElement} ul
- * the UL element that contains the items to pick from
- */
- ul: null,
- /**
- * Property {HTMLElement} selectedItem
- * the currently selected item
- */
- selectedItem: null,
- /**
- * Constructor: Jx.Button.Picker
- * construct a new instance of <Jx.Button.Picker>
- */
- initialize: function() {
- Jx.Button.Flyout.prototype.initialize.apply(this, arguments);
- this.ul = document.createElement('ul');
- this.content.appendChild(this.ul);
- Element.removeClassName(this.domLabel, 'jxButtonEmptyLabel');
- },
- /**
- * Method: add
- * adds one or more items to the picker, passed as separate arguments.
- *
- * Parameters:
- * item - {Object} can be present one or more times in the argument list. The item
- * to be added can be a Jx object with a domObj property, a string,
- * or an HTML element reference.
- */
- add: function() {
- for (var i=0; i<arguments.length; i++) {
- var thing = arguments[i];
- if (thing.domObj) {
- thing = thing.domObj;
- }
- var li = document.createElement('li');
- var a = document.createElement('a');
-
- li.appendChild(a);
- if (typeof(thing) == 'string') {
- a.innerHTML = thing;
- } else {
- a.appendChild(thing);
- }
- this.ul.appendChild(li);
-
- if (!this.selectedItem) {
- this.updateButton(a);
- }
- }
- },
- /**
- * Method: clickHandler
- * handle the user selecting an item in the list
- *
- * Parameters:
- * e - {Event} the event object associated with the click event
- */
- clickHandler: function(e) {
- var elm = Event.element(e);
- if (!Element.descendantOf(elm, this.domObj.parentNode)) {
- this.hide();
- return;
- }
- var a = Event.findElement(e, 'A');
- if (a && Element.descendantOf(a, this.ul)) {
- this.updateButton(a);
- this.hide();
- }
- },
- /**
- * Method: updateButton
- * updates the button to contain the picked item
- *
- * Parameters:
- * a - {HTMLElement} the A tag that the user clicked on
- */
- updateButton: function(a) {
- while(this.domLabel.childNodes.length > 0) {
- this.domLabel.removeChild(this.domLabel.firstChild);
- }
- this.domLabel.appendChild(a.firstChild.cloneNode(true));
- this.selectedItem = a.firstChild;
- }
-
-});/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Color
- *
- * Purpose:
- * Implementation of a color selection panel.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-Jx.addStyleSheet('color/color.css');
-
-/**
- * Class: Jx.ColorPanel
- *
- * A Jx.ColorPanel presents a user interface for selecting colors. Currently,
- * the user can either enter a HEX colour value or select from a palette of
- * web-safe colours. The user can also enter an opacity value.
- *
- * A Jx.ColorPanel can be embedded anywhere in a web page by appending its
- * <Jx.ColorPanel.domObj> property to an HTML element. However, a
- * a Jx.Button subclass is provided ( <Jx.Button.Color> ) that embeds a
- * colour panel inside a button for easy use in toolbars.
- *
- * Colour changes are propogated via a colorChanged listener pattern. To
- * be notified of changes in a Jx.ColorPanel, register a color change
- * listener that implements a colorChanged method. For instance:
- *
- * (code)
- * var colorChangeListener = {
- * colorChanged: function(colorPanel) {
- * alert('the color changed to: ' + colorPanel.color);
- * }
- * }
- *
- * var colorPanel = new Jx.ColorPanel();
- * colorPanel.addColorChangeListener(colorChangeListener);
- *
- * document.getElementsByTagName('BODY')[0].appendChild(colorPanel.domObj);
- * (end)
- */
-Jx.ColorPanel = Class.create();
-
-Jx.ColorPanel.prototype = {
- /**
- * Property: {HTMLElement} domObj
- * the HTML element representing the color panel
- */
- domObj: null,
- /**
- * Property {String} color
- * the currently selected colour, in hex format
- */
- color: null,
- /**
- * Property: {Float} alpha
- * the current alpha value, between 0 (transparent) and 1 (opaque)
- */
- alpha: null,
- /**
- * Property: {Array} ccl
- * color change property listeners
- */
- ccl: null,
- /**
- * Property: {Array} hexColors
- * an array of valid hex values that are used to build a web-safe
- * palette
- */
- hexColors: ['00', '33', '66', '99', 'CC', 'FF'],
- /**
- * Constructor: Jx.ColorPanel
- * initialize a new instance of Jx.ColorPanel
- *
- * Parameters:
- * options - {Object} an object containing a variable list of optional initialization
- * parameters.
- *
- * Options:
- * color - a colour to initialize the panel with, defaults to #000000
- * (black) if not specified.
- * alpha - an alpha value to initialize the panel with, defaults to 1
- * (opaque) if not specified.
- */
- initialize: function(options) {
-
- options = options || {};
- this.keypressWatcher = this.keypressHandler.bind(this);
-
- this.ccl = [];
-
- this.color = options.color || '#000000';
- this.alpha = options.alpha || 1;
-
- this.domObj = document.createElement('div');
- this.domObj.className = 'jxColorPanel';
-
- var top = document.createElement('div');
- top.className = 'jxColorBar';
-
- var d = document.createElement('div');
- d.className = 'jxColorPreview';
-
- // var img = document.createElement('img');
- // img.src = Jx.baseURL + '/color/grid.png';
- // d.appendChild(img);
-
- this.selectedSwatch = document.createElement('div');
- d.appendChild(this.selectedSwatch);
-
- top.appendChild(d);
-
- this.colorInputLabel = document.createElement('label');
- this.colorInputLabel.className = 'jxColorLabel';
- this.colorInputLabel.innerHTML = '#';
- top.appendChild(this.colorInputLabel);
-
- this.colorInput = document.createElement('input');
- this.colorInput.className = 'jxHexInput';
- this.colorInput.type = 'text';
- this.colorInput.maxLength = 6;
- Event.observe(this.colorInput, 'keyup', this.colorChanged.bind(this));
- Event.observe(this.colorInput, 'blur', this.colorChanged.bind(this));
- Event.observe(this.colorInput, 'change', this.colorChanged.bind(this));
- top.appendChild(this.colorInput);
-
- this.alphaLabel = document.createElement('label');
- this.alphaLabel.className = 'jxAlphaLabel';
- this.alphaLabel.innerHTML = 'alpha (%)';
- top.appendChild(this.alphaLabel);
-
- this.alphaInput = document.createElement('input');
- this.alphaInput.className = 'jxAlphaInput';
- this.alphaInput.type = 'text';
- this.alphaInput.maxLength = 3;
- Event.observe(this.alphaInput, 'keyup', this.alphaChanged.bind(this));
- top.appendChild(this.alphaInput);
-
- this.domObj.appendChild(top);
-
- var a = document.createElement('a');
- a.href="javascript:void(0)";
- a.className = 'jxColorClose';
- a.alt = 'Close';
- a.title = 'Close';
- Event.observe(a, 'click', this.hide.bind(this));
-
- img = document.createElement('img');
- img.className = 'png24';
- img.src = Jx.baseURL + 'images/close.png';
- a.appendChild(img);
-
- this.domObj.appendChild(a);
-
- d = document.createElement('div');
- d.className = 'jxClearer';
- this.domObj.appendChild(d);
-
- var swatchClick = this.swatchClick.bindAsEventListener(this);
- var swatchOver = this.swatchOver.bindAsEventListener(this);
-
- var table = document.createElement('table');
- table.className = 'jxColorGrid';
- var tbody = document.createElement('tbody');
- table.appendChild(tbody);
- for (var i=0; i<12; i++) {
- var tr = document.createElement('tr');
- for (var j=-3; j<18; j++) {
- var bSkip = false;
- var r, g, b;
- /* hacky approach to building first three columns
- * because I couldn't find a good way to do it
- * programmatically
- */
-
- if (j < 0) {
- if (j == -3 || j == -1) {
- r = g = b = 0;
- bSkip = true;
- } else {
- if (i<6) {
- r = g = b = i;
- } else {
- if (i == 6) {
- r = 5; g = 0; b = 0;
- } else if (i == 7) {
- r = 0; g = 5; b = 0;
- } else if (i == 8) {
- r = 0; g = 0; b = 5;
- } else if (i == 9) {
- r = 5; g = 5; b = 0;
- } else if (i == 10) {
- r = 0; g = 5; b = 5;
- } else if (i == 11) {
- r = 5; g = 0; b = 5;
- }
- }
- }
- } else {
- /* remainder of the columns are built
- * based on the current row/column
- */
- r = parseInt(i/6)*3 + parseInt(j/6);
- g = j%6;
- b = i%6;
- }
- var bgColor = '#'+this.hexColors[r]+this.hexColors[g]+this.hexColors[b];
-
- var td = document.createElement('td');
- if (!bSkip) {
- td.style.backgroundColor = bgColor;
-
- var a = document.createElement('a');
- if ((r > 2 && g > 2) || (r > 2 && b > 2) || (g > 2 && b > 2)) {
- a.className = 'colorSwatch borderBlack';
- } else {
- a.className = 'colorSwatch borderWhite';
- }
- a.href = '#';
- a.title = bgColor;
- a.alt = bgColor;
- a.swatchColor = bgColor;
-
- a.onmouseover = swatchOver;
- a.onclick = swatchClick;
-
- td.appendChild(a);
- } else {
- var span = document.createElement('span');
- td.className = 'emptyCell';
- td.appendChild(span);
- }
- tr.appendChild(td);
- }
- tbody.appendChild(tr);
- }
-
- this.domObj.appendChild(table);
-
- var d = document.createElement('div');
- d.className = 'jxColorPreview';
- this.previewSwatch = document.createElement('div');
- d.appendChild(this.previewSwatch);
- this.previewSwatch.style.backgroundColor = this.color;
- this.domObj.appendChild(d);
-
- this.previewLabel = document.createElement('label');
- this.previewLabel.className = 'jxColorLabel';
- this.previewLabel.innerHTML = this.color;
- this.domObj.appendChild(this.previewLabel);
-
- d = document.createElement('div');
- d.className = 'jxClearer';
- this.domObj.appendChild(d);
-
- this.updateSelected();
- },
-
- /**
- * Method: swatchOver
- * handle the mouse moving over a colour swatch by updating the preview
- *
- * Parameters:
- * e - {Event} the mousemove event object
- */
- swatchOver: function(e) {
- var a = Event.element(e);
-
- this.previewSwatch.style.backgroundColor = a.swatchColor;
- this.previewLabel.innerHTML = a.swatchColor;
- },
-
- /**
- * Method: swatchClick
- * handle mouse click on a swatch by updating the color and hiding the
- * panel.
- *
- * Parameters:
- * e - {Event} the mouseclick event object
- */
- swatchClick: function(e) {
- var a = Event.element(e);
-
- this.color = a.swatchColor;
- this.updateSelected();
- this.hide();
- },
-
- /**
- * Method: colorChanged
- * handle the user entering a new colour value manually by updating the
- * selected colour if the entered value is valid HEX.
- */
- colorChanged: function() {
- var color = this.colorInput.value;
- if (color.substring(0,1) == '#') {
- color = color.substring(1);
- }
- if (color.toLowerCase().match(/^[0-9a-f]{6}$/)) {
- this.color = '#' +color.toUpperCase();
- this.updateSelected();
- }
- },
-
- /**
- * Method: alphaChanged
- * handle the user entering a new alpha value manually by updating the
- * selected alpha if the entered value is valid alpha (0-100).
- */
- alphaChanged: function() {
- var alpha = this.alphaInput.value;
- if (alpha.match(/^[0-9]{1,3}$/)) {
- this.alpha = parseFloat(alpha/100);
- this.updateSelected();
- }
- },
-
- /**
- * Method: setColor
- * set the colour represented by this colour panel
- *
- * Parameters:
- * color - {String} the new hex color value
- */
- setColor: function( color ) {
- this.colorInput.value = color;
- this.colorChanged();
- },
-
- /**
- * Method: setAlpha
- * set the alpha represented by this colour panel
- *
- * Parameters:
- * alpha - {Integer} the new alpha value (between 0 and 100)
- */
- setAlpha: function( alpha ) {
- this.alphaInput.value = alpha;
- this.alphaChanged();
- },
-
- /**
- * Method: updateSelected
- * update the colour panel user interface based on the current
- * colour and alpha values
- */
- updateSelected: function() {
- this.selectedSwatch.style.backgroundColor = this.color;
- this.colorInput.value = this.color.substring(1);
-
- this.alphaInput.value = parseInt(this.alpha*100);
- if (this.alpha < 1) {
- this.selectedSwatch.style.opacity = this.alpha;
- this.selectedSwatch.style.filter = 'Alpha(opacity='+(this.alpha*100)+')';
- } else {
- this.selectedSwatch.style.opacity = '';
- this.selectedSwatch.style.filter = '';
- }
- this.processEvent(this.ccl,'colorChanged',this);
- },
-
- /**
- * Method: show
- * show the panel
- */
- show: function() {
- this.domObj.style.display = 'block';
- Event.observe(window, 'keypress', this.keypressWatcher);
- },
-
- /**
- * Method: hide
- * hide the panel
- */
- hide: function() {
- this.domObj.style.display = 'none';
- Event.stopObserving(window, 'keypress', this.keypressWatcher);
-
- },
-
- /**
- * Method: keypressHandler
- * handle the user pressing a key. If the key is the ESC key, then
- * hide the color panel
- *
- * Parameters:
- * e - {Event} The keypress event
- */
- keypressHandler: function(e) {
- var charCode=(e.charCode)?e.charCode:e.keyCode;
- if (charCode == Event.KEY_ESC) {
- this.hide();
- }
- },
- /**
- * Method: addColorChangeListener
- * add a colour change listener, an object that has a colorChanged
- * function.
- *
- * Parameters:
- * obj - {Object} The colour change listener to call when the colour changes.
- */
- addColorChangeListener: function(obj){this.addListener(this.ccl, obj);},
- /**
- * Method: removeColorChangeListener
- * remove a previously added colour change listener
- *
- * Parameters:
- * obj - {Object} The colour change listener to remove
- */
- removeColorChangeListener: function(obj) {
- this.removeListener(this.ccl, obj);
- }
-};
-Object.extend(Jx.ColorPanel.prototype, Jx.Listener.prototype);
-
-/**
- * Class: Jx.Button.Color
- *
- * A <Jx.ColorPanel> wrapped up in a Jx.Button. The button includes a
- * preview of the currently selected color. Clicking the button opens
- * the color panel.
- *
- * Inherits From:
- * <Jx.Button.Flyout>
- */
-Jx.Button.Color = Class.create();
-Object.extend(Jx.Button.Color.prototype, Jx.Button.Flyout.prototype);
-Object.extend(Jx.Button.Color.prototype, {
- /**
- * Property: { Array } colorPanel
- * By declaring this property as an array in the prototype, the
- * array is used for all instances making it a Class property.
- * A <Jx.ColorPanel> instance used by all color buttons is made the
- * first element so that only one color panel is ever created.
- */
- colorPanel: [],
- /**
- * Property: {HTMLElement} swatch
- * a div used to represent the current colour in the button.
- */
- swatch: null,
- /**
- * Property: {String} color
- * the current colour of this button in hex. We have to maintain
- * it here because we share a colour panel with all other colour
- * buttons
- */
- color: null,
- /**
- * Property: {Integer} alpha
- * the current alpha of this button. We have to maintain
- * it here because we share a colour panel with all other colour
- * buttons
- */
- alpha: null,
- /**
- * Property: {Array} ccl
- * color change property listeners
- */
- ccl: null,
- /**
- * Constructor: Jx.Button.Color
- * initialize a new colour button.
- *
- * Parameters:
- * options - {Object} an object containing a variable list of optional initialization
- * parameters.
- *
- * Options:
- * color - a colour to initialize the panel with, defaults to #000000
- * (black) if not specified.
- * alpha - an alpha value to initialize the panel with, defaults to 1
- * (opaque) if not specified.
- */
-
- initialize: function(options) {
- options = options || {};
- options.label = options.label || ' ';
- this.color = options.color || '#000000';
- this.alpha = options.alpha || 100;
- this.ccl = [];
-
- if (this.colorPanel.length == 0) {
- this.colorPanel[0] = new Jx.ColorPanel();
- }
- var d = document.createElement('div');
- d.className = 'jxColorButtonPreview';
-
- this.selectedSwatch = document.createElement('div');
- d.appendChild(this.selectedSwatch);
-
- /* create a button with a label so it doesn't get an empty label class
- and then replace the label text with the swatch */
- Jx.Button.Flyout.prototype.initialize.apply(this, [options]);
- Element.addClassName(this.domObj.firstChild, 'jxButtonColor');
- this.domObj.firstChild.firstChild.insertBefore(d, this.domObj.firstChild.firstChild.firstChild);
- this.updateSwatch();
- },
-
- /**
- * Method: show
- * show the color panel when the user clicks the button
- */
- show: function() {
- if (this.colorPanel[0].currentButton) {
- this.colorPanel[0].currentButton.hide();
- }
- this.colorPanel[0].currentButton = this;
- this.colorPanel[0].addColorChangeListener(this);
- this.content.appendChild(this.colorPanel[0].domObj);
- this.colorPanel[0].domObj.style.display = 'block';
- Jx.Button.Flyout.prototype.show.apply(this, arguments);
- /* setting these before causes an update problem when clicking on
- * a second color button when another one is open - the color
- * wasn't updating properly
- */
- this.colorPanel[0].setColor(this.color);
- this.colorPanel[0].setAlpha(this.alpha);
- },
-
- /**
- * Method: hide
- * hide the colour panel
- */
- hide: function() {
- this.colorPanel[0].removeColorChangeListener(this);
- Jx.Button.Flyout.prototype.hide.apply(this, arguments);
- this.colorPanel[0].currentButton = null;
- },
-
- /**
- * Method: setColor
- * set the colour represented by this colour panel
- *
- * Parameters:
- * color - {String} the new hex color value
- */
- setColor: function(color) {
- this.color = color;
- this.updateSwatch();
- },
-
- /**
- * Method: setAlpha
- * set the alpha represented by this colour panel
- *
- * Parameters:
- * alpha - {Integer} the new alpha value (between 0 and 100)
- */
- setAlpha: function(alpha) {
- this.alpha = alpha;
- this.updateSwatch();
- },
-
- /**
- * Method: colorChanged
- * colorChangeListener callback function when the user changes
- * the colour in the panel (just update the preview).
- */
- colorChanged: function(panel) {
- this.color = panel.color;
- this.alpha = panel.alpha * 100;
- this.updateSwatch();
- this.processEvent(this.ccl,'colorChanged',this);
- },
-
- /**
- * Method: updateSwatch
- * Update the swatch color for the current color
- */
- updateSwatch: function() {
- this.selectedSwatch.style.backgroundColor = this.color;
- if (this.alpha < 100) {
- this.selectedSwatch.style.opacity = this.alpha/100;
- this.selectedSwatch.style.filter = 'Alpha(opacity='+(this.alpha)+')';
- } else {
- this.selectedSwatch.style.opacity = '';
- this.selectedSwatch.style.filter = '';
- }
- },
- /**
- * Method: addColorChangeListener
- * add a colour change listener, an object that has a colorChanged
- * function.
- *
- * Parameters:
- * obj - {Object} The colour change listener to call when the colour changes.
- */
- addColorChangeListener: function(obj){this.addListener(this.ccl, obj);},
- /**
- * Method: removeColorChangeListener
- * remove a previously added colour change listener
- *
- * Parameters:
- * obj - {Object} The colour change listener to remove
- */
- removeColorChangeListener: function(obj) {
- this.removeListener(this.ccl, obj);
- }
-});
-/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Dialog
- *
- * Purpose:
- * Implementation of a javascript Dialog for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-Jx.addStyleSheet('dialog/dialog.css');
-
-/**
- * Class: Jx.Dialog
- *
- * A Jx.Dialog implements a floating dialog. Dialogs represent a useful way
- * to present users with certain information or application controls.
- * Jx.Dialog is designed to provide the same types of features as traditional
- * operating system dialog boxes, including:
- *
- * - dialogs may be modal (user must dismiss the dialog to continue) or
- * non-modal
- *
- * - dialogs are moveable (user can drag the title bar to move the dialog
- * around)
- *
- * - dialogs may be a fixed size or allow user resizing.
- *
- * - dialogs may have associated help content that is available as a slide-out
- * help panel on the right-hand side of the dialog.
- *
- * Jx.Dialog uses <Jx.ContentLoader> to load content into the content area
- * of the dialog. Refer to the <Jx.ContentLoader> documentation for details
- * on content options. Jx.Dialog also uses <Jx.ContentLoader> to load
- * help content, using non-standard options prefixed by 'help' instead of
- * 'content' (see options in initialize below).
- *
- * (code)
- * var dialog = new Jx.Dialog({});
- * (end)
- *
- * Inherits From:
- * <Jx.ContentLoader>, <Jx.UniqueId>
- */
-Jx.Dialog = Class.create();
-Jx.Dialog.prototype = {
- /**
- * Property: {Function} onClose
- * if specified by the caller, this is a function to invoke
- * when the dialog closes.
- */
- onClose : null,
- /**
- * Property: {Function} onOpen
- * if specified by the caller, this is a function to invoke
- * when the dialog opens.
- */
- onOpen : null,
- /**
- * Property: {Function} onChange
- * if specified by the caller, this is a function to invoke
- * when any input element in the dialog is changed.
- */
- onChange : null,
- /**
- * Property: {String} title
- * the text to display in the title bar of the dialog.
- */
- title : null,
- /**
- * Property: {HTMLElement} content
- * the content area element of the dialog, used to load user-
- * specified content into.
- */
- content : null,
- /**
- * Property: {HTMLElement} action
- * the action area element of the dialog, used for buttons.
- */
- action : null,
- /**
- * Property: {Object} values
- * when dialog content is loaded, the content is inspected for input
- * elements and a record of them is keep in this object for later
- * reference.
- */
- values : null,
- /**
- * Property: {Object} actions
- * when dialog content is loaded, the content is inspected for
- * input elements of type 'button' and a record of them is
- * kept in this object for later reference.
- */
- actions : null,
- /**
- * Property: {Function} handler
- * if specified by the caller, this is a function to invoke
- * when an input of type button is clicked by the user.
- */
- handler : null,
- /**
- * TODO: Jx.Dialog.bContentLoaded
- * remove this property, it is provided by Jx.ContentLoader.
- */
- bContentLoaded : null,
- /**
- * Property: {Array} zIndex
- * class variable containing the last assigned z-index so that
- * dialogs stack correctly.
- */
- zIndex: [101],
- /**
- * Property: {Array} stack
- * class variable containing the list of visible dialogs used to
- * manage the z-index of non-modal dialogs. This allows the user
- * to click a dialog and have it appear in front of other dialogs.
- */
- stack: [],
- /**
- * Property: {HTMLElement} blanket
- * modal dialogs prevent interaction with the rest of the application
- * while they are open, this element is displayed just under the
- * dialog to prevent the user from clicking anything.
- */
- blanket: null,
-
- /**
- * Property: firstShow
- * {Boolean} true if the dialog has not been made visible yet. This
- * facilitates resizing of <Jx.Layout> managed elements in the dialog
- */
- firstShow: true,
-
- /**
- * Property: {Boolean} modal
- * whether or not the dialog is modal.
- */
- modal: true,
- /**
- * Constructor: Jx.Dialog
- * Construct a new instance of Jx.Dialog
- *
- * Parameters:
- * options - {Object} an object containing options for the dialog.
- *
- * Options:
- * onChange - (optional) {Function} a function to call if the user changes
- * the value of any input in the dialog
- * onClose - (optional) {Function} a function to call when the user closes
- * the dialog
- * onOpen - (optional) {Function} a function to call when the user opens
- * the dialog
- * onContentLoaded - (optional) {Function} a function to call when the
- * content of the dialog has been loaded, used primarily with
- * asynchronous content
- * handler - (optional) {Function} a function to call when the user clicks
- * on any input of type 'button' in the dialog
- * modal - (optional) {Boolean} controls whether the dialog will be modal
- * or not. The default is to create modal dialogs.
- * top - (optional) {Integer} the distance in pixels to initially place
- * the dialog from the top edge of its container. Default is 0 unless
- * bottom is specified, in which case the top value is not used.
- * bottom - (optional) {Integer} the distance in pixels to initially place
- * the dialog from the bottom edge of its container. Default is null, which
- * means that the dialog is not positioned relative to the bottom of its
- * container. If top and bottom are specified, top is used.
- * left - (optional) {Integer} the distance in pixels to initially place
- * the dialog from the left edge of its container.
- * right - (optional) {Integer} the distance in pixels to initially place
- * the dialog from the right edge of its container. Default is null, which
- * means that the dialog is not positioned relative to the right of its
- * container. If left and right are specified, left is used.
- * width - (optional) {Integer} the initial width in pixels of the dialog.
- * The default value is 250 if not specified.
- * height - (optional) {Integer} the initial height in pixels of the
- * dialog. The default value is 250 if not specified.
- * title - (optional) {String} the title of the dialog box. "New Dialog"
- * is the default value.
- * titleHeight - (optional) {Integer} the height, in pixels, of the
- * dialog's title bar. The default value is 22, and works with the default
- * dialog styles. Only change this value is you are overriding the
- * default style of the dialog's title bar
- * closeImg - (optional) {String} URL to an image to use for the close
- * button in the dialog title bar area. The default value is to use
- * the close image provided by Jx. Only override this value if you are
- * changing the default style of the dialog's title bar.
- * helpID - (optional) {String} passed to <Jx.ContentLoader> for loading
- * help content.
- * helpURL - (optional) {String} passed to <Jx.ContentLoader> for loading
- * help content.
- * helpHTML - (optional) {String} passed to <Jx.ContentLoader> for loading
- * help content.
- * help - (optional) {Object} passed to <Jx.ContentLoader> for loading
- * help content.
- * contentID - (optional) {String} passed to <Jx.ContentLoader> for loading
- * dialog content.
- * contentURL - (optional) {String} passed to <Jx.ContentLoader> for loading
- * dialog content.
- * contentHTML - (optional) {String} passed to <Jx.ContentLoader> for loading
- * dialog content.
- * content - (optional) {Object} passed to <Jx.ContentLoader> for loading
- * dialog content.
- * buttons - (optional) {Array} an array of strings that contain the labels
- * for buttons to create in the Action area of the dialog.
- * id - (optional) {String} an HTML ID to assign to the dialog, primarily
- * used for applying CSS styles to specific dialogs
- * parentObj - (optional) {HTMLElement} a reference to an HTML element that
- * the dialog is to be contained by. The default value is for the dialog
- * to be contained by the body element.
- * resizeable - (optional) {Boolean} determines whether the dialog is
- * resizeable by the user or not. Default is false.
- * imageBaseUrl - (optional) {String} the path to the various dialog edge
- * images. If not specified, then Jx.baseURL is used.
- */
- initialize: function(options) {
- this.initUniqueId();
- this.values = {};
- this.actions = {};
- this.handler = options.handler?options.handler:null;
- if (options.onChange) {this.onChange = options.onChange;}
- if (options.onClose) {this.onClose = options.onClose;}
- if (options.onOpen) {this.onOpen = options.onOpen;}
- if (options.onContentLoaded) {this.onContentLoaded = options.onContentLoaded;}
-
- this.imageBaseUrl = options.imageBaseUrl || Jx.baseURL + "/images/";
- if (this.imageBaseUrl.slice(-1) != '/') {
- this.imageBaseUrl += '/';
- }
- this.modal = typeof options.modal == 'undefined' ? true : options.modal;
-
- var w = options.width || 250;
- var h = options.height || 250;
- var b = (typeof options.bottom != 'undefined') ? options.bottom : null;
- var r = (typeof options.right != 'undefined') ? options.right : null;
- var t = (typeof options.top != 'undefined') ? options.top : (b != null ? null : 0);
- var l = (typeof options.left != 'undefined') ? options.left : (r != null ? null : 0);
-
- this.blanket = document.createElement('div');
- this.blanket.className = 'jxDialogModal';
- this.blanket.style.display = 'none';
-
- if (!window.opera && this.modal) {
- var iframe = document.createElement('iframe');
- iframe.className = 'jxDialogShim';
- iframe.scrolling = 'no';
- iframe.frameborder = 0;
- this.blanket.appendChild(iframe);
- if (options.parentObj) {
- $(options.parentObj).appendChild(this.blanket);
- } else {
- document.body.appendChild(this.blanket);
- var temp = new Jx.Layout(this.blanket);
- temp.resize();
- }
- }
-
- /* dragHandle is the title bar */
- this.dragHandle = document.createElement('div');
- this.dragHandle.innerHTML = options.title || ' ';
- this.dragHandle.style.width = '100%';
-
- var domObj = document.createElement('div');
- domObj.className = 'jxDialogContainer';
- this.domObj = domObj;
- /* set the id if passed in through options */
- if (options.id) {
- domObj.id = options.id;
- }
-
- var dialogObj = document.createElement('div');
- dialogObj.className = 'jxDialog';
- this.innerDialogObj = dialogObj;
-
- var titleObj = document.createElement('div');
- titleObj.className = 'jxDialogTitle';
- this.title = titleObj;
- titleObj.appendChild(this.dragHandle);
-
- /* element must be in the page to be measured */
- titleObj.style.visibility = 'hidden';
- document.getElementsByTagName('BODY')[0].appendChild(titleObj);
- this.titleHeight = Element.getBorderBoxSize(titleObj).height;
- document.getElementsByTagName('BODY')[0].removeChild(titleObj);
- titleObj.style.visibility = '';
-
- var contentObj = document.createElement('div');
- contentObj.className = 'jxDialogContent';
- this.content = contentObj;
-
- domObj.appendChild(dialogObj);
- dialogObj.appendChild(titleObj);
- dialogObj.appendChild(contentObj);
-
- new Jx.Layout(dialogObj, {width: w, height: h});
- new Jx.Layout(titleObj, {top: 0, left: 0, right: 0, bottom: null, height: this.titleHeight, width: null});
-
- /* optional 'action' area for buttons if necessary */
- this.actionHeight = 0;
- if (options.buttons) {
- var actionObj = document.createElement('div');
- actionObj.className = 'jxDialogAction';
- actionObj.style.visibility = 'hidden';
- document.getElementsByTagName('BODY')[0].appendChild(actionObj);
- this.actionHeight = parseInt(Element.getStyle(actionObj, 'height'));
- document.getElementsByTagName('BODY')[0].removeChild(actionObj);
- actionObj.style.visibility = '';
- dialogObj.appendChild(actionObj);
- new Jx.Layout(actionObj, {top: null, left: 0, right: 0, bottom: 0, height: this.actionHeight, width: null});
- this.action = actionObj;
- this.setButtons(options.buttons);
- }
-
- new Jx.Layout(contentObj, {top: this.titleHeight, left: 0, right: 0, bottom: this.actionHeight});
-
-
- /* build the decorations for the title bar */
- var atag = document.createElement('a');
- atag.href = 'javascript:void(0)';
- atag.className = 'jxDialogCloseButton';
- atag.onclick = this.close.bindAsEventListener(this);
-
- var close = document.createElement('img');
- if(options.closeImg) {
- close.src = options.closeImg;
- }
- else {
- close.src = this.imageBaseUrl + 'icon_close.png';
- }
- close.alt = 'Close Dialog';
- close.title = 'Close Dialog';
- atag.appendChild(close);
- titleObj.appendChild(atag);
-
- if (options.helpID || options.helpHTML || options.helpURL || options.help) {
- /* put a button in the title bar to open help */
- var atag2 = document.createElement('a');
- atag2.href = 'javascript:void(0)';
- atag2.className = 'jxDialogHelpButton';
- atag2.onclick = this.toggleHelp.bindAsEventListener(this);
- var help = document.createElement('img');
- help.src = this.imageBaseUrl + 'icon_quickhelp.png';
- help.alt = 'Help';
- help.title = 'Help';
- atag2.appendChild(help);
- titleObj.appendChild(atag2);
-
- /* make the help area */
- this.help = document.createElement('div');
- this.help.className = 'jxDialogHelp';
- this.help.style.display = 'none';
- this.help.isVisible = false;
- var helpOpts = {};
- helpOpts.contentID = options.helpID;
- helpOpts.content = options.help;
- helpOpts.contentURL = options.helpURL;
- helpOpts.contentHTML = options.helpHTML;
- helpOpts.onContentLoaded = this.onHelpContentLoaded.bind(this);
- this.loadContent(this.help, helpOpts);
- dialogObj.appendChild(this.help);
- }
-
- var contentOpts = {};
- contentOpts.contentID = options.contentID;
- contentOpts.content = options.content;
- contentOpts.contentURL = options.contentURL;
- contentOpts.contentHTML = options.contentHTML;
- contentOpts.onContentLoaded = this.onDialogContentLoaded.bind(this);
- this.loadContent(contentObj, contentOpts);
-
- /* element must be in the page to be measured */
- dialogObj.style.visibility = 'hidden';
- document.body.appendChild(dialogObj);
- //force an initial size calculation
- dialogObj.resize();
-
- /* the outer box needs to be sized to the border box size plus margins
- * of the inner box.
- */
-
- this.dialogBoxSize = Element.getBorderBoxSize(dialogObj);
- this.dialogBoxMargins = Element.getMarginSize(dialogObj);
-
- var containerSize = {width: this.dialogBoxSize.width, height: this.dialogBoxSize.height};
- containerSize.width += this.dialogBoxMargins.left + this.dialogBoxMargins.right;
- containerSize.height += this.dialogBoxMargins.top + this.dialogBoxMargins.bottom;
-
- document.body.removeChild(dialogObj);
- dialogObj.style.visibility = '';
- domObj.appendChild(dialogObj);
-
- /* now create overall container with the correct size */
- domObj.style.display = "none";
-
- Element.setBorderBoxSize(domObj, {width:(containerSize.width), height:(containerSize.height)});
-
- domObj.style.position = 'absolute';
- if (t != null) {
- domObj.style.top = (t) + 'px';
- } else {
- domObj.style.bottom = (b) + 'px';
- }
- if (l != null) {
- domObj.style.left = (l) + 'px';
- } else {
- domObj.style.right = (r) + 'px';
- }
-
- if (options.parentObj) {
- $(options.parentObj).appendChild(domObj);
- } else {
- document.body.appendChild(domObj);
- }
-
- /* Background */
- this.DTOffset = 0;
- this.DBOffset = 0;
- this.DROffset = 0;
- this.DLOffset = 0;
- this.decorationOffsets = {top:0, right: 0, bottom: 0, left: 0};
-
- /* top left */
-
- var imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgTL';
- var img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_tl.png';
- img.className = 'png24'; /* apply png hack for IE */
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.decorationOffsets.top += parseInt(Element.getStyle(img,'width'));
- this.decorationOffsets.left += parseInt(Element.getStyle(img,'height'));
-
- /* top right */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgTR';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_tr.png';
- img.className = 'png24'; /* apply png hack for IE */
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.decorationOffsets.top += parseInt(Element.getStyle(img,'width'));
- this.decorationOffsets.right += parseInt(Element.getStyle(img,'height'));
-
- /* bottom right */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgBR';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_br.png';
- img.className = 'png24'; /* apply png hack for IE */
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.decorationOffsets.bottom += parseInt(Element.getStyle(img,'width'));
- this.decorationOffsets.right += parseInt(Element.getStyle(img,'height'));
-
- /* bottom left */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgBL';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_bl.png';
- img.className = 'png24'; /* apply png hack for IE */
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.decorationOffsets.bottom += parseInt(Element.getStyle(img,'width'));
- this.decorationOffsets.left += parseInt(Element.getStyle(img,'height'));
-
- /* top */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgT';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_t.png';
- img.className = 'png24'; /* apply png hack for IE */
- img.style.width = containerSize.width-this.decorationOffsets.top + 'px';
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.topImg = img;
-
- /* bottom */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgB';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_b.png';
- img.className = 'png24'; /* apply png hack for IE */
- img.style.width = containerSize.width-this.decorationOffsets.bottom + 'px';
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.bottomImg = img;
-
- /* left */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgL';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_l.png';
- img.className = 'png24'; /* apply png hack for IE */
- img.style.height = containerSize.height-this.decorationOffsets.left + 'px';
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.leftImg = img;
-
- /* right */
- imgContainer = document.createElement('div');
- imgContainer.className = 'jxDialogBgR';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + 'dialog_glow_r.png';
- img.className = 'png24'; /* apply png hack for IE */
- img.style.height = containerSize.height-this.decorationOffsets.right + 'px';
- imgContainer.appendChild(img);
- domObj.appendChild(imgContainer);
- this.rightImg = img;
-
-
- Event.observe(domObj, 'mousedown', this.mouseDown.bind(this));
- Event.observe(this.title, 'mousedown', this.mouseDown.bind(this));
-
- if (options.resizeable) {
- this.resizeHandle = document.createElement('div');
- this.resizeHandle.className = 'jxDialogResize';
- this.resizeHandle.style.position = 'absolute'; //required for Draggable
- this.domObj.appendChild(this.resizeHandle);
-
- this.resizeHandleSize = {width:parseInt(Element.getStyle(this.resizeHandle,'width')),
- height:parseInt(Element.getStyle(this.resizeHandle,'height'))};
-
- this.resizeHandle.style.top = (containerSize.height-this.resizeHandleSize.height) + 'px';
- this.resizeHandle.style.left = (containerSize.width-this.resizeHandleSize.width) + 'px';
- new Draggable(this.resizeHandle, {starteffect: false, endeffect: false,change:this.ondrag.bind(this), zindex: 0});
- }
-
- this.bOpen = false;
- },
- /**
- * Method: mouseDown
- * handle the user clicking the title area, promote the dialog to the
- * top of the stack so it is fully visible to the user.
- */
- mouseDown: function() {
- for (var i=0; i<this.stack.length; i++) {
- if (this.stack[i] == this) {
- this.stack.splice(i, 1);
- this.stack.push(this);
- }
- }
- for (var i=0; i<this.stack.length; i++) {
- this.stack[i].domObj.style.zIndex = (101 + i);
- }
- },
- /**
- * Method: ondrag
- * callback function for user-resizing of the dialog
- *
- * Parameters:
- * obj - {Object} a drag object that indicates what happened.
- */
- ondrag: function(obj) {
- this.mouseDown();
-
- var delta = obj.currentDelta();
- //delta is top/left of resize image. Bottom/right of the dialog needs to be
- //adjusted for size of image (20x20).
- var deltaX = delta[0] + this.resizeHandleSize.width;
- var deltaY = delta[1] + this.resizeHandleSize.height;
- this.resize({width: deltaX, height: deltaY});
- },
- /**
- * Method: resize
- * programmatically resize the dialog in either or both dimensions
- *
- * Parameters:
- * newSize - {Object} an object containing either or both 'width' and 'height' properties
- * that hold the new width or height in pixels
- */
- resize: function(newSize) {
-
- /* let jxLayout manage the internal stuff */
- this.innerDialogObj.resize(newSize);
-
- /* sizing logic for container
- *
- * we need to set the size of this.innerDialogObj to the requested size
- * then size the title, content and action area within it and expand
- * this.domObj to contain it properly. Then we need to position the
- * images appropriately too.
- */
- if (newSize.width) {
- var outerWidth = newSize.width;
- Element.setBorderBoxSize(this.domObj, {width: outerWidth});
- Element.setBorderBoxSize(this.topImg, {width:outerWidth-this.decorationOffsets.top});
- Element.setBorderBoxSize(this.bottomImg, {width:outerWidth-this.decorationOffsets.bottom});
- }
- if (newSize.height) {
- var outerHeight = newSize.height;
- Element.setBorderBoxSize(this.domObj, {height: outerHeight});
- Element.setBorderBoxSize(this.leftImg, {height:outerHeight-this.decorationOffsets.left});
- Element.setBorderBoxSize(this.rightImg, {height:outerHeight-this.decorationOffsets.right});
- if (this.help) {
- Element.setBorderBoxSize(this.help, {height:newSize.height - this.titleHeight});
- }
- }
- },
- /**
- * Method: setTitle
- * set the text of the dialog title.
- *
- * Parameters:
- * title - {String} the new title
- */
- setTitle: function( title ) {
- this.title.childNodes[0].innerHTML = title;
- },
- /**
- * Method: setButtons
- * create buttons in the action area of the dialog
- *
- * Parameters:
- * buttons - {Array} an array of strings containing the labels to place on the
- * buttons. One button is created for each label.
- */
- setButtons: function(buttons) {
- this.action.innerHTML = '';
- for (var i=0; i<buttons.length;i++) {
- var button = document.createElement('input');
- button.id = buttons[i];
- button.type = 'button';
- button.className = 'normalButton';
- button.name = buttons[i];
- button.value = buttons[i];
- button.onclick = this.buttonHandler.bind(this, button);
- this.action.appendChild(button);
- this.uniqueIdRefs[button.id] = button;
- }
- },
- /**
- * Method: processInputs
- * look through the DOM obj for nodes of type INPUT and register
- * for events on them.
- *
- * Parameters:
- * obj - {HTMLElement} the DOM obj to process
- */
- processInputs : function(obj) {
- for (var i=0;i<obj.childNodes.length; i++) {
- var node = obj.childNodes[i];
- if (node.tagName == 'INPUT' || node.tagName == 'SELECT' || node.tagName == 'TEXTAREA') {
- if (node.type == 'button') {
- this.actions[node.id] = node;
- node.onclick = this.buttonHandler.bind(this, node);
- } else {
- this.values[node.id] = node;
- if (this.onChange) {
- node.onchange = this.onChangeHandler.bind(this, node);
- }
- }
- } else {
- if (node.childNodes) {
- this.processInputs(node);
- }
- }
- }
- },
- /**
- * Method: buttonHandler
- * handle button events, dispatching to user handler if required.
- *
- * Parameters:
- * input - {HTMLElement} the input element that triggered a click event
- * event - {Event} the event object
- */
- buttonHandler : function(input, event) {
- if (this.handler) {
- this.handler(input.value, this);
- }
- },
- /**
- * Method: onChangeHandler
- * handle onchange events, dispatching to user handler if required.
- *
- * Parameters:
- * input - {HTMLElement} the input element that triggered an onchange event
- * event - {Event} the event object
- */
- onChangeHandler: function(input, event) {
- if (this.onChange) {
- this.onChange(input, this);
- }
- },
- /**
- * Method: getValue
- * retrieve the value of an input element in the dialog. This is done
- * safely so depending on the type of the input.
- *
- * Parameters:
- * name - {String} the id of the element to get the value of
- *
- * Returns: {String} the value or an empty string.
- */
- getValue : function( name ) {
- var result = '';
- var input = this.values[name];
- if (input) {
- switch (input.tagName) {
- case 'INPUT':
- result = input.value;
- break;
- case 'SELECT':
- result = input.options[input.selectedIndex].value;
- }
- }
- return result;
- },
- /**
- * Method: setValue
- * set the value of an input element in the dialog. This is done
- * safely depending on the type of the input.
- *
- * Parameters:
- * name - {String} the id of the element to set the value of
- * value - {String} the value to set
- */
- setValue : function( name, value ) {
- if (typeof this.values[name] != 'undefined') {
- if (this.values[name].type == 'text' || this.values[name].type == 'hidden') {
- this.values[name].value = value;
- }
- }
- },
- /**
- * Method: show
- * show the dialog
- */
- show : function( ) {
- this.stack.push(this);
- if (this.modal) {
- this.blanket.style.zIndex = this.zIndex[0]++;
- this.blanket.style.visibility = 'visible';
- this.blanket.style.display = 'block';
- }
- this.domObj.style.zIndex = this.zIndex[0]++;
- Effect.Appear(this.domObj, {duration: 0.1});
- this.domObj.style.display = 'block';
- new Draggable(this.domObj, {handle:this.dragHandle, starteffect: false, endeffect: false});
- this.content.resize({forceResize: this.firstShow});
- this.firstShow = false;
- },
- /**
- * Method: hide
- * hide the dialog
- */
- hide : function() {
- for (var i=0; i<this.stack.length; i++) {
- if (this.stack[i] == this) {
- this.stack.splice(i,1);
- }
- }
- this.zIndex[0]--;
- Effect.Fade(this.domObj, {duration: 0.3});
- //this.domObj.style.display = 'none';
- if (this.modal) {
- this.blanket.style.visibility = 'hidden';
- this.zIndex[0]--;
- }
-
- },
- /**
- * Method: open
- * open the dialog. This may be delayed depending on the
- * asynchronous loading of dialog content. The onOpen
- * callback function is called when the dialog actually
- * opens
- */
- open: function() {
- if (!this.bOpen) {
- this.bOpen = true;
- }
- if (this.bContentLoaded) {
- this.show();
- if (this.onOpen) this.onOpen();
- }
- },
- /**
- * Method: close
- * close the dialog and trigger the onClose callback function
- * if necessary
- */
- close: function() {
- this.bOpen = false;
- this.hide();
- if (this.onClose) this.onClose();
- },
- /**
- * Method: onDialogContentLoaded
- * handle the dialog content being loaded. This triggers
- * processing of inputs and the onContentLoaded callback
- * function (if necessary). Also, if the dialog was previously
- * requested to be opened, this will actually open it.
- */
- onDialogContentLoaded : function() {
- this.processInputs(this.content);
- if (this.onContentLoaded) {
- this.onContentLoaded(this);
- }
- if (this.bOpen) {
- //may need to do this?
- //window.setTimeout(this.open.bind(this),1);
- this.open();
- this.bOpen = false;
- }
- },
- /**
- * Method: onHelpContentLoaded
- * handle the help content being loaded.
- */
- onHelpContentLoaded : function() {
- var img = document.createElement('img');
- img.className = 'jxDialogHelpCloseButton png24';
- img.src = this.imageBaseUrl + 'help_close.png';
- img.onclick = this.toggleHelp.bind(this);
- img.alt = 'Close Help';
- img.title = 'Close Help';
- this.help.appendChild(img);
- },
- /**
- * Method: toggleHelp
- * show or hide the help panel.
- */
- toggleHelp: function() {
- if (this.help.isVisible) {
- Effect.Fade(this.help, {duration: 0.3});
- } else {
- var actionSize = this.action ? Element.getBorderBoxSize(this.action) : {width: 0, height: 0};
- var contentSize = Element.getBorderBoxSize(this.content);
- Element.setBorderBoxSize(this.help, {height:contentSize.height+actionSize.height});
- Effect.Appear(this.help, {duration: 0.3});
- }
- this.help.isVisible = !this.help.isVisible;
- }
-};
-Object.extend(Jx.Dialog.prototype, Jx.UniqueId.prototype);
-Object.extend(Jx.Dialog.prototype, Jx.ContentLoader.prototype);/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Grid
- *
- * Purpose:
- * Implementation of a javascript Grid control for Jx.
- *
- * Jx.Grid is a tabular control with convenient controls for resizing columns,
- * sorting, and inline editing. It is created inside another element, typically a
- * div. If the div is resizable (for instance it fills the page or there is a
- * user control allowing it to be resized), you must call the resize() method
- * of the grid to let it know that its container has been resized.
- *
- * When creating a new Jx.Grid, you can specify a number of options for the grid
- * that control its appearance and functionality.
- *
- * Jx.Grid renders data that comes from an external source. This external
- * source, called the model, must implement the following interface.
- *
- * *Mandatory Functions*
- *
- * addGridListener(l) - mandatory
- * mandatory. This function accepts one argument, l, which is the listener
- * to add. The model can then call the gridChanged() method on the grid
- * listener object when something in the model changes.
- *
- * removeGridListener(l) - mandatory
- * mandatory. This function accepts one argument, l, which is the listener
- * to remove. The listener should have been previously added using
- * addGridListener.
- *
- * getColumnCount() - mandatory
- * mandatory. This function returns the number of columns of data in the
- * model as an integer value.
- *
- * getColumnHeaderHTML(column) - mandatory
- * mandatory. This function returns an HTML string to be placed in the
- * column header for the given column index.
- *
- * getColumnHeaderHeight() - mandatory
- * mandatory. This function returns an integer which is the height of the
- * column header row in pixels.
- *
- * getColumnWidth(column) - mandatory
- * mandatory. This function returns an integer which is the width of the
- * given column in pixels.
- *
- * getRowHeaderHTML(row) - mandatory
- * mandatory. This function returns an HTML string to be placed in the row
- * header for the given row index
- *
- * getRowHeaderWidth() - mandatory
- * mandatory. This function returns an integer which is the width of the row
- * header column in pixels.
- *
- * getRowHeight(row) - mandatory
- * mandatory. This function returns an integer which is the height of the
- * given row in pixels.
- *
- * getRowCount() - mandatory
- * mandatory. This function returns the number of rows of data in the model
- * as an integer value.
- *
- * getValueAt(row, column) - mandatory
- * mandatory. This function returns an HTML string which is the text to place
- * in the cell at the given row and column.
- *
- * isCellEditable(row, column) - mandatory
- * mandatory. This function returns a boolean value to indicate if a given
- * cell is editable by the user.
- *
- * *Optional Functions*
- *
- * setColumnWidth(column, width) - optional
- * optional. This function is called with a column index and width in pixels
- * when a column is resized. This function is only required if the grid
- * allows resizeable columns.
- *
- * setValueAt(row, column, value) - optional
- * optional. This function is called with the row and column of a cell and a
- * new value for the cell. It is mandatory to provide this function if any of
- * the cells in the model are editable.
- *
- * rowSelected(row) - optional
- * optional. This function is called by the grid to indicate that the user
- * has selected a row by clicking on the row header.
- *
- * columnSelected(column) - optional
- * optional. This function is called by the grid to indicate that the user
- * has selected a column by clicking on the column header.
- *
- * cellSelected(row, column) - optional
- * optional. This function is called by the grid to indicate that the user
- * has selected a cell by clicking on the cell in the grid.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-/* our default css styles */
-Jx.addStyleSheet('grid/grid.css');
-
-/**
- * Class: Jx.Grid
- * A tabular control that has fixed scrolling headers on the rows and columns
- * like a spreadsheet.
- */
-Jx.Grid = Class.create();
-Jx.Grid.prototype = {
- domObj : null,
- model : null,
- /**
- * Constructor: Jx.Grid
- * construct a new instance of Jx.Grid within the domObj
- *
- * Parameters:
- * domObj - {HTMLElement} the HTML element to create the grid inside.
- * The grid will resize to fill the domObj.
- * options - you can specify some options as attributes of a
- * generic object.
- *
- * Options:
- * alternateRowColors - defaults to false. If set to true, then
- * alternating CSS classes are used for rows
- * rowHeaders - defaults to false. If set to true, then a column
- * of row header cells are displayed.
- * columnHeaders - defaults to false. If set to true, then a column
- * of row header cells are displayed.
- * rowSelection - defaults to false. If set to true, allow the
- * user to select rows.
- * cellSelection - defaults to false. If set to true, allow the
- * user to select cells.
- */
- initialize : function( domObj, options ) {
- this.domObj = $(domObj);
-
- /* if this grid is the content of a Jx Panel, this will
- allow the grid to resize when the panel resizes
- */
- if (!this.domObj.jxLayout) {
- new Jx.Layout(this.domObj);
- }
- this.domObj.jxLayout.addSizeChangeListener(this);
-
- options = options || {};
-
- this.rowColObj = document.createElement('div');
- this.rowColObj.className = 'jxGridContainer';
-
- this.colObj = document.createElement('div');
- this.colObj.className = 'jxGridContainer';
- this.colTable = document.createElement('table');
- this.colTable.className = 'jxGridTable';
- this.colTableHead = document.createElement('thead');
- this.colTable.appendChild(this.colTableHead);
- this.colTableBody = document.createElement('tbody');
- this.colTable.appendChild(this.colTableBody);
- this.colObj.appendChild(this.colTable);
-
- this.rowObj = document.createElement('div');
- this.rowObj.className = 'jxGridContainer';
- this.rowTable = document.createElement('table');
- this.rowTable.className = 'jxGridTable';
- this.rowTableHead = document.createElement('thead');
- this.rowTable.appendChild(this.rowTableHead);
- this.rowObj.appendChild(this.rowTable);
-
- this.gridObj = document.createElement('div');
- this.gridObj.className = 'jxGridContainer';
- this.gridObj.style.overflow = 'scroll';
- this.gridTable = document.createElement('table');
- this.gridTable.className = 'jxGridTable';
- this.gridTableBody = document.createElement('tbody');
- this.gridTable.appendChild(this.gridTableBody);
- this.gridObj.appendChild(this.gridTable);
-
- this.domObj.appendChild(this.rowColObj);
- this.domObj.appendChild(this.rowObj);
- this.domObj.appendChild(this.colObj);
- this.domObj.appendChild(this.gridObj);
-
- this.bAlternateRowColors = options.alternateRowColors || false;
- this.showRowHeader = options.rowHeaders || false;
- this.showColumnHeader = options.columnHeaders || false;
- this.rowSelection = options.rowSelection || false;
- this.cellSelection = options.cellSelection || false;
-
- Event.observe(this.gridObj, 'scroll', this.onScroll.bind(this));
- Event.observe(this.gridObj, 'click', this.onClickGrid.bindAsEventListener(this));
- Event.observe(this.rowObj, 'click', this.onClickRowHeader.bindAsEventListener(this));
- Event.observe(this.colObj, 'click', this.onClickColumnHeader.bindAsEventListener(this));
- Event.observe(this.gridObj, 'mousemove', this.onMouseMoveGrid.bindAsEventListener(this));
- Event.observe(this.rowObj, 'mousemove', this.onMouseMoveRowHeader.bindAsEventListener(this));
- Event.observe(this.colObj, 'mousemove', this.onMouseMoveColumnHeader.bindAsEventListener(this));
- },
-
- /**
- * Method: onScroll
- * handle the grid scrolling by updating the position of the headers
- */
- onScroll: function() {
- this.colObj.scrollLeft = this.gridObj.scrollLeft;
- this.rowObj.scrollTop = this.gridObj.scrollTop;
- },
-
- /**
- * Method: sizeChanged
- * Handle the container of the grid resizing
- */
- sizeChanged: function() {
- this.resize();
- },
-
- /**
- * Method: resize
- * resize the grid to fit inside its container. This involves knowing something
- * about the model it is displaying (the height of the column header and the
- * width of the row header) so nothing happens if no model is set
- */
- resize: function() {
- if (!this.model) {
- return;
- }
-
- /* TODO: Jx.Grid.resize
- * if not showing column or row, should we handle the resize differently
- */
- var colHeight = this.showColumnHeader ? this.model.getColumnHeaderHeight() : 1;
- var rowWidth = this.showRowHeader ? this.model.getRowHeaderWidth() : 1;
-
- var size = Element.getContentBoxSize(this.domObj);
-
- /* -1 because of the right/bottom borders */
- this.rowColObj.style.width = (rowWidth - 1) + 'px';
- this.rowColObj.style.height = (colHeight - 1) + 'px';
-
- this.rowObj.style.top = (colHeight) + 'px';
- this.rowObj.style.left = '0px';
- this.rowObj.style.width = (rowWidth - 1) + 'px';
- this.rowObj.style.height = (size.height - colHeight - 1) + 'px';
-
- this.colObj.style.top = '0px';
- this.colObj.style.left = (rowWidth) + 'px';
- this.colObj.style.width = (size.width - rowWidth - 1) + 'px';
- this.colObj.style.height = (colHeight - 1) + 'px';
-
- this.gridObj.style.top = (colHeight) + 'px';
- this.gridObj.style.left = (rowWidth) + 'px';
- this.gridObj.style.width = (size.width - rowWidth - 1) + 'px';
- this.gridObj.style.height = (size.height - colHeight - 1) + 'px';
- },
-
- /**
- * Method: setModel
- * set the model for the grid to display. If a model is attached to the grid
- * it is removed and the new model is displayed.
- *
- * Parameters:
- * model - {Object} the model to use for this grid
- */
- setModel: function(model) {
- if (this.model) {
- this.model.removeGridListener(this);
- }
- this.model = model;
- if (this.model) {
- this.domObj.jxLayout.resize();
- this.model.addGridListener(this);
- this.createGrid();
- this.resize();
- } else {
- this.destroyGrid();
- }
- },
-
- /**
- * Method: destroyGrid
- * destroy the contents of the grid safely
- */
- destroyGrid: function() {
- var n = this.colTableHead.cloneNode(false);
- this.colTable.replaceChild(n, this.colTableHead);
- this.colTableHead = n;
-
- n = this.colTableBody.cloneNode(false);
- this.colTable.replaceChild(n, this.colTableBody);
- this.colTableBody = n;
-
- n = this.rowTableHead.cloneNode(false);
- this.rowTable.replaceChild(n, this.rowTableHead);
- this.rowTableHead = n;
-
- n = this.gridTableBody.cloneNode(false);
- this.gridTable.replaceChild(n, this.gridTableBody);
- this.gridTableBody = n;
-
- },
-
- /**
- * Method: createGrid
- * create the grid for the current model
- */
- createGrid: function() {
- this.destroyGrid();
- if (this.model) {
- var model = this.model;
- var nColumns = model.getColumnCount();
- var nRows = model.getRowCount();
-
- /* create header if necessary */
- if (this.showColumnHeader) {
- var colHeight = model.getColumnHeaderHeight();
- var trHead = document.createElement('tr');
- this.colTableHead.appendChild(trHead);
- var trBody = document.createElement('tr');
- this.colTableBody.appendChild(trBody);
-
- var th = document.createElement('th');
- th.style.width = '0px';
- th.style.height = '0px';
- trHead.appendChild(th);
- th = th.cloneNode(true);
- th.style.height = (colHeight) + 'px';
- trBody.appendChild(th);
- for (var i=0; i<nColumns; i++) {
- var colWidth = model.getColumnWidth(i);
- th = document.createElement('th');
- th.className = 'jxGridColHeadHide';
- th.style.width = (colWidth) + 'px';
- var p = document.createElement('p');
- p.style.height = '0px';
- p.style.width = (colWidth) + 'px';
- th.appendChild(p);
- trHead.appendChild(th);
-
- th = document.createElement('th');
- th.className = 'jxGridColHead';
- th.innerHTML = model.getColumnHeaderHTML(i);
- trBody.appendChild(th);
- }
- /* one extra column at the end for filler */
- var th = document.createElement('th');
- th.style.width = '1000px';
- th.style.height = '0px';
- trHead.appendChild(th);
- th = th.cloneNode(true);
- th.style.height = (colHeight - 1) + 'px';
- th.className = 'jxGridColHead';
- trBody.appendChild(th);
-
- }
-
- if (this.showRowHeader) {
- var rowWidth = model.getRowHeaderWidth();
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- td.style.width = '0px';
- td.style.height = '0px';
- tr.appendChild(td);
- var th = document.createElement('th');
- th.style.width = (rowWidth) + 'px';
- th.style.height = '0px';
- tr.appendChild(th);
- this.rowTableHead.appendChild(tr);
- for (var i=0; i<nRows; i++) {
- var rowHeight = model.getRowHeight(i);
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- td.className = 'jxGridRowHeadHide';
- td.style.width = '0px';
- td.style.height = (rowHeight)+'px';
- var p = document.createElement('p');
- p.style.width = '0px';
- p.style.height = (rowHeight)+'px';
- td.appendChild(p);
- tr.appendChild(td);
- var th = document.createElement('th');
- th.className = 'jxGridRowHead';
- th.innerHTML = model.getRowHeaderHTML(i);
- tr.appendChild(th);
- this.rowTableHead.appendChild(tr);
- }
- /* one extra row at the end for filler */
- var tr = document.createElement('tr');
- var td = document.createElement('td');
- td.style.width = '0px';
- td.style.height = '1000px';
- tr.appendChild(td);
- var th = document.createElement('th');
- th.style.width = (rowWidth) + 'px';
- th.style.height = '1000px';
- th.className = 'jxGridRowHead';
- tr.appendChild(th);
- this.rowTableHead.appendChild(tr);
- }
-
- var colHeight = model.getColumnHeaderHeight();
- var trBody = document.createElement('tr');
- this.gridTableBody.appendChild(trBody);
-
- var td = document.createElement('td');
- td.style.width = '0px';
- td.style.height = '0px';
- trBody.appendChild(td);
- for (var i=0; i<nColumns; i++) {
- var colWidth = model.getColumnWidth(i);
- td = document.createElement('td');
- td.className = 'jxGridColHeadHide';
- td.style.width = (colWidth) + 'px';
- var p = document.createElement('p');
- p.style.height = '0px';
- p.style.width = (colWidth) + 'px';
- td.appendChild(p);
- trBody.appendChild(td);
- }
-
- for (var j=0; j<nRows; j++) {
- var rowHeight = model.getRowHeight(j);
- var actualRowHeight = rowHeight;
- var tr = document.createElement('tr');
- this.gridTableBody.appendChild(tr);
-
- var td = document.createElement('td');
- td.className = 'jxGridRowHeadHide';
- td.style.width = '0px';
- td.style.height = (rowHeight) + 'px';
- var p = document.createElement('p');
- p.style.height = (rowHeight) + 'px';
- td.appendChild(p);
- tr.appendChild(td);
- for (var i=0; i<nColumns; i++) {
- var colWidth = model.getColumnWidth(i);
- td = document.createElement('td');
- td.className = 'jxGridCell';
- td.innerHTML = model.getValueAt(j,i);
- tr.appendChild(td);
- var tdSize = Element.getDimensions(td);
- if (tdSize.height > actualRowHeight) {
- actualRowHeight = tdSize.height;
- }
- }
- /* some notes about row sizing
- * In Safari, the height of a TR is always returned as 0
- * In Safari, the height of any given TD is the height it would
- * render at, not the actual height of the row
- * In IE, the height is returned 1px bigger than any other browser
- * Firefox just works
- *
- * So, for Safari, we have to measure every TD and take the highest one
- * and if its IE, we subtract 1 from the overall height, making all
- * browsers identical
- *
- * Using document.all is not a good hack for this
- */
- if (document.all) {
- actualRowHeight -= 1;
- }
- if (this.showRowHeader) {
- this.setRowHeaderHeight(j, actualRowHeight);
- }
- /* if we apply the class before adding content, it
- * causes a rendering error in IE (off by 1) that is 'fixed'
- * when another class is applied to the row, causing dynamic
- * shifting of the row heights
- */
- if (this.bAlternateRowColors) {
- tr.className = (j%2) ? 'jxGridRowOdd' : 'jxGridRowEven';
- } else {
- tr.className = 'jxGridRowAll';
- }
- }
-
- }
- },
-
- /**
- * Method: setRowHeaderHeight
- * set the height of a row. This is used internally to adjust the height of
- * the row header when cell contents wrap. A limitation of the table structure
- * is that overflow: hidden on a td will work horizontally but not vertically
- *
- * Parameters:
- * row - {Integer} the row to set the height for
- * height - {Integer} the height to set the row (in pixels)
- */
- setRowHeaderHeight: function(row, height) {
- //this.rowTableHead.childNodes[row+1].childNodes[0].style.height = (height) + 'px';
- this.rowTableHead.childNodes[row+1].childNodes[0].childNodes[0].style.height = (height) + 'px';
- },
-
- /**
- * Method: gridChanged
- * called through the grid listener interface when data has changed in the
- * underlying model
- *
- * Parameters:
- * model - {Object} the model that changed
- * row - {Integer} the row that changed
- * col - {Integer} the column that changed
- * value - {Mixed} the new value
- */
- gridChanged: function(model, row, col, value) {
- if (this.model == model) {
- this.gridObj.childNodes[row].childNodes[col].innerHTML = value;
- }
- },
-
- /**
- * Method: prelightRowHeader
- * apply the jxGridRowHeaderPrelight style to the header cell of a row.
- * This removes the style from the previously pre-lit row header.
- *
- * Parameters:
- * row - {Integer} the row to pre-light the header cell of
- */
- prelightRowHeader: function(row) {
- var cell = (row >= 0 && row < this.rowTableHead.rows.length-1) ? this.rowTableHead.rows[row+1].cells[1] : null;
- if (this.prelitRowHeader != cell) {
- if (this.prelitRowHeader) {
- Element.removeClassName(this.prelitRowHeader, 'jxGridRowHeaderPrelight');
- }
- this.prelitRowHeader = cell;
- if (this.prelitRowHeader) {
- Element.addClassName(this.prelitRowHeader, 'jxGridRowHeaderPrelight');
- }
- }
- },
-
- /**
- * Method: prelightColumnHeader
- * apply the jxGridColumnHeaderPrelight style to the header cell of a column.
- * This removes the style from the previously pre-lit column header.
- *
- * Parameters:
- * col - {Integer} the column to pre-light the header cell of
- */
- prelightColumnHeader: function(col) {
- if (this.colTableBody.rows.length == 0) {
- return;
- }
- var cell = (col >= 0 && col < this.colTableBody.rows[0].cells.length-1) ? this.colTableBody.rows[0].cells[col+1] : null;
- if (this.prelitColumnHeader != cell) {
- if (this.prelitColumnHeader) {
- Element.removeClassName(this.prelitColumnHeader, 'jxGridColumnHeaderPrelight');
- }
- this.prelitColumnHeader = cell;
- if (this.prelitColumnHeader) {
- Element.addClassName(this.prelitColumnHeader, 'jxGridColumnHeaderPrelight');
- }
- }
- },
-
- /**
- * Method: prelightRow
- * apply the jxGridRowPrelight style to row.
- * This removes the style from the previously pre-lit row.
- *
- * Parameters:
- * row - {Integer} the row to pre-light
- */
- prelightRow: function(row) {
- var tr = (row >= 0 && row < this.gridTableBody.rows.length-1) ? this.gridTableBody.rows[row+1] : null;
-
- if (this.prelitRow != row) {
- if (this.prelitRow) {
- Element.removeClassName(this.prelitRow, 'jxGridRowPrelight');
- }
- this.prelitRow = tr;
- if (this.prelitRow && !Element.hasClassName(this.prelitRow, 'jxGridRowSelected')) {
- this.prelightRowHeader(row);
- Element.addClassName(this.prelitRow, 'jxGridRowPrelight');
- }
- }
- },
-
- /**
- * Method: prelightColumn
- * apply the jxGridColumnPrelight style to a column.
- * This removes the style from the previously pre-lit column.
- *
- * Parameters:
- * col - {Integer} the column to pre-light
- *
- * TODO: Jx.Grid.prelightColumn
- * Not Yet Implemented.
- */
- prelightColumn: function(col) {
- /* TODO: Jx.Grid.prelightColumn
- * implement column prelighting (possibly)
- */
- this.prelightColumnHeader(col);
- },
-
- /**
- * Method: prelightCell
- * apply the jxGridCellPrelight style to a cell.
- * This removes the style from the previously pre-lit cell.
- *
- * Parameters:
- * row - {Integer} the row of the cell to pre-light
- * col - {Integer} the column of the cell to pre-light
- */
- prelightCell: function(row, col) {
- var td = (row >=0 && col >=0 && row < this.gridTableBody.rows.length - 1 && col < this.gridTableBody.rows[row+1].cells.length - 1) ? this.gridTableBody.rows[row+1].cells[col+1] : null;
- if (this.prelitCell != td) {
- if (this.prelitCell) {
- Element.removeClassName(this.prelitCell, 'jxGridCellPrelight');
- }
- this.prelitCell = td;
- if (this.prelitCell) {
- Element.addClassName(this.prelitCell, 'jxGridCellPrelight');
- this.prelightRow(row);
- this.prelightColumn(col);
- }
- }
- },
-
- /**
- * Method: selectCell
- * Select a cell and apply the jxGridCellSelected style to it.
- * This deselects a previously selected cell.
- *
- * If the model supports cell selection, it should implement
- * a cellSelected function to receive notification of the selection.
- *
- * Parameters:
- * row - {Integer} the row of the cell to select
- * col - {Integer} the column of the cell to select
- */
- selectCell: function(row, col) {
- var td = (row >=0 && col >=0 && row < this.gridTableBody.rows.length - 1 && col < this.gridTableBody.rows[row+1].cells.length - 1) ? this.gridTableBody.rows[row+1].cells[col+1] : null;
- if (!td) {
- return;
- }
-
- if (this.selectedCell) {
- Element.addClassName(this.selectedCell, 'jxGridCellSelected');
- } else {
- Element.removeClassName(this.selectedCell, 'jxGridCellSelected');
- }
- },
-
- /**
- * Method: selectRowHeader
- * Apply the jxGridRowHeaderSelected style to the row header cell of a
- * selected row.
- *
- * Parameters:
- * row - {Integer} the row header to select
- * selected - {Boolean} the new state of the row header
- */
- selectRowHeader: function(row, selected) {
- var cell = (row >= 0 && row < this.rowTableHead.rows.length-1) ? this.rowTableHead.rows[row+1].cells[1] : null;
- if (!cell) {
- return;
- }
- if (selected) {
- Element.addClassName(cell, 'jxGridRowHeaderSelected');
- } else {
- Element.removeClassName(cell, 'jxGridRowHeaderSelected');
- }
- },
-
- /**
- * Method: selectRow
- * Select a row and apply the jxGridRowSelected style to it.
- *
- * If the model supports row selection, it should implement
- * a rowSelected function to receive notification of the selection.
- *
- * Parameters:
- * row - {Integer} the row to select
- * selected - {Boolean} the new state of the row
- */
- selectRow: function(row, selected) {
- var tr = (row >= 0 && row < this.gridTableBody.rows.length - 1) ? this.gridTableBody.rows[row+1] : null;
- if (tr) {
- if (selected) {
- Element.addClassName(tr, 'jxGridRowSelected');
- } else {
- Element.removeClassName(tr, 'jxGridRowSelected');
- }
- }
- this.selectRowHeader(row, selected);
- },
-
- /**
- * method: selectColumnHeader
- * Apply the jxGridColumnHeaderSelected style to the column header cell of a
- * selected column.
- *
- * Parameters:
- * col - {Integer} the column header to select
- * selected - {Boolean} the new state of the column header
- */
- selectColumnHeader: function(col, selected) {
- if (this.colTableBody.rows.length == 0) {
- return;
- }
- var cell = (col >= 0 && col < this.colTableBody.rows[0].cells.length-1) ? this.colTableBody.rows[0].cells[col+1] : null;
- if (cell == null) {
- return;
- }
-
- if (selected) {
- Element.addClassName(cell, 'jxGridColumnHeaderSelected');
- } else {
- Element.removeClassName(cell, 'jxGridColumnHeaderSelected');
- }
- },
-
- /**
- * Method: selectColumn
- * Select a column.
- * This deselects a previously selected column.
- *
- * Parameters:
- * col - {Integer} the column to select
- * selected - {Boolean} the new state of the column
- */
- selectColumn: function(col, selected) {
- /* todo: implement column selection */
- if (col >= 0 && col < this.gridTable.rows[0].cells.length) {
- if (selected) {
- for (var i=0; i<this.gridTable.rows.length; i++) {
- Element.removeClassName(this.gridTable.rows[i].cells[this.selectedColumn + 1], 'jxGridColumnSelected');
- }
- } else {
- for (var i=0; i<this.gridTable.rows.length; i++) {
- Element.addClassName(this.gridTable.rows[i].cells[col+1], 'jxGridColumnSelected');
- }
-
- }
- }
- this.selectColumnHeader(col, selected);
- },
-
- /**
- * Method: onMouseMoveGrid
- * handle the mouse moving over the main grid. This pre-lights the cell,
- * and subsquently the row and column (and headers).
- *
- * Parameters:
- * e - {Event} the browser event object
- */
- onMouseMoveGrid: function(e) {
- var rc = this.getRowColumnFromEvent(e);
- this.prelightCell(rc.row, rc.column);
- },
-
- /**
- * Method: onMouseMoveRowHeader
- * handle the mouse moving over the row header cells. This pre-lights
- * the row and subsequently the row header.
- *
- * Parameters:
- * e - {Event} the browser event object
- */
- onMouseMoveRowHeader: function(e) {
- var rc = this.getRowColumnFromEvent(e);
- this.prelightRow(rc.row);
- },
-
- /**
- * Method: onMouseMoveColumnHeader
- * handle the mouse moving over the column header cells. This pre-lights
- * the column and subsequently the column header.
- *
- * Parameters:
- * e - {Event} the browser event object
- */
- onMouseMoveColumnHeader: function(e) {
- var rc = this.getRowColumnFromEvent(e);
- this.prelightColumn(rc.column);
- },
-
- /**
- * Method: onClickGrid
- * handle the user clicking on the grid. This triggers an
- * event to the model (if a cellSelected function is provided).
- *
- * The following is an example of a function in the model that selects
- * a row when the cellSelected function is called and deselects any rows
- * that are currently selected.
- *
- * (code)
- * cellSelected: function(grid, row,col) {
- * if (this.selectedRow != null) {
- * grid.selectRow(this.selectedRow, false);
- * }
- * this.selectedRow = row;
- * grid.selectRow(row, true);
- * }
- *
- * Parameters:
- * e - {Event} the browser event object
- */
- onClickGrid: function(e) {
- var rc = this.getRowColumnFromEvent(e);
- //this.selectCell(rc.row, rc.column);
-
- if (this.model.cellSelected) {
- this.model.cellSelected(this, rc.row, rc.column);
- }
- },
-
- /**
- * Method: onClickRowHeader
- * handle the user clicking on the row header. This triggers an
- * event to the model (if a rowSelected function is provided) which
- * can then select the row if desired.
- *
- * The following is an example of a function in the model that selects
- * a row when the rowSelected function is called and deselects any rows
- * that are currently selected. More complex code could be written to
- * allow the user to select multiple rows.
- *
- * (code)
- * rowSelected: function(grid, row) {
- * if (this.selectedRow != null) {
- * grid.selectRow(this.selectedRow, false);
- * }
- * this.selectedRow = row;
- * grid.selectRow(row, true);
- * }
- * (end)
- *
- * Parameters:
- * e - {Event} the browser event object
- */
- onClickRowHeader: function(e) {
- var rc = this.getRowColumnFromEvent(e);
-
- if (this.model.rowSelected) {
- this.model.rowSelected(this, rc.row);
- }
- },
-
- /**
- * Method: onClickColumnHeader
- * handle the user clicking on the column header. This triggers column
- * selection and column (and header) styling changes and an
- * event to the model (if a columnSelected function is provided)
- *
- * The following is an example of a function in the model that selects
- * a column when the columnSelected function is called and deselects any
- * columns that are currently selected. More complex code could be written
- * to allow the user to select multiple columns.
- *
- * (code)
- * colSelected: function(grid, col) {
- * if (this.selectedColumn != null) {
- * grid.selectColumn(this.selectedColumn, false);
- * }
- * this.selectedColumn = col;
- * grid.selectColumn(col, true);
- * }
- * (end)
- *
- * Parameters:
- * e - {Event} the browser event object
- */
- onClickColumnHeader: function(e) {
- var rc = this.getRowColumnFromEvent(e);
-
- if (this.model.columnSelected) {
- this.model.columnSelected(this, rc.column);
- }
- },
-
- /**
- * method: getRowColumnFromEvent
- * retrieve the row and column indexes from an event click.
- * This function is used by the grid, row header and column
- * header to safely get these numbers.
- *
- * If the event isn't valid (i.e. it wasn't on a TD or TH) then
- * the returned values will be -1, -1
- *
- * Parameters:
- * e - {Event} the browser event object
- *
- * @return Object an object with two properties, row and column,
- * that contain the row and column that was clicked
- */
- getRowColumnFromEvent: function(e) {
- var td = Event.element(e);
- if (td.tagName != 'TD' && td.tagName != 'TH') {
- return {row:-1,column:-1};
- }
- var tr = td.parentNode;
- var col = td.cellIndex - 1; /* because of hidden spacer column */
- var row = tr.rowIndex - 1; /* because of hidden spacer row */
-
- if (col == -1) {
- /* bug in safari returns 0 for cellIndex - only choice seems
- * to be to loop through the row
- */
- for (var i=0; i<tr.childNodes.length; i++) {
- if (tr.childNodes[i] == td) {
- col = i - 1;
- break;
- }
- }
- }
- return {row:row,column:col};
- }
-};/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Layout
- *
- * Purpose:
- * Implementation of a javascript layout engine for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-/**
- * Class: Jx.Layout
- *
- * Jx.Layout is used to provide more flexible layout options for applications
- *
- * Jx.Layout wraps an existing DOM element (typically a div) and provides
- * extra functionality for sizing that element within its parent and sizing
- * elements contained within it that have a 'resize' function attached to them.
- *
- * To create a Jx.Layout, pass the element or id plus an options object to
- * the constructor:
- *
- * (code)
- * var myContainer = new Jx.Layout('myDiv', options);
- * (end)
- *
- * Inherits From:
- * <Jx.Listener>
- */
-
-Jx.Layout = Class.create();
-Jx.Layout.prototype = {
- scl: null,
- /**
- * Constructor: Jx.Layout
- * Create a new instance of Jx.Layout.
- *
- * Parameters:
- * domObj - {HTMLElement} element or id to apply the layout to
- * options - {Object} options can be passed to the Jx.Layout as an object
- * with some, all, or none of the options below.
- *
- * Options:
- * position - how to position the element, either 'absolute' or 'relative'.
- * The default (if not passed) is 'absolute'. When using
- * 'absolute' positioning, both the width and height are
- * controlled by Jx.Layout. If 'relative' positioning is used
- * then only the width is controlled, allowing the height to
- * be controlled by its content.
- * left - the distance (in pixels) to maintain the left edge of the element
- * from its parent element. The default value is 0. If this is set
- * to 'null', then the left edge can be any distance from its parent
- * based on other parameters.
- * right - the distance (in pixels) to maintain the right edge of the element
- * from its parent element. The default value is 0. If this is set
- * to 'null', then the right edge can be any distance from its parent
- * based on other parameters.
- * top - the distance (in pixels) to maintain the top edge of the element
- * from its parent element. The default value is 0. If this is set
- * to 'null', then the top edge can be any distance from its parent
- * based on other parameters.
- * bottom - the distance (in pixels) to maintain the bottom edge of the element
- * from its parent element. The default value is 0. If this is set
- * to 'null', then the bottom edge can be any distance from its parent
- * based on other parameters.
- * width - the width (in pixels) of the element. The default value is null.
- * If this is set to 'null', then the width can be any value based on
- * other parameters.
- * height - the height (in pixels) of the element. The default value is null.
- * If this is set to 'null', then the height can be any value based on
- * other parameters.
- * minWidth - the minimum width that the element can be sized to. The default
- * value is 0.
- * minHeight - the minimum height that the element can be sized to. The
- * default value is 0.
- * maxWidth - the maximum width that the element can be sized to. The default
- * value is -1, which means no maximum.
- * maxHeight - the maximum height that the element can be sized to. The
- * default value is -1, which means no maximum.
- */
- initialize: function(domObj, options) {
- options = options || {};
- this.options = new Jx.Constraint(options);
- this.domObj = $(domObj);
- this.domObj.resize = this.resize.bind(this);
- this.domObj.style.position = this.options.position;
- this.domObj.jxLayout = this;
-
- if (this.domObj.parentNode && this.domObj.parentNode.tagName == 'BODY') {
- Event.observe(window, 'resize', this.windowResize.bind(this));
- }
-
- this.scl = [];
- },
-
- /**
- * Method: windowResize
- * when the window is resized, any Jx.Layout controlled elements that are
- * direct children of the BODY element are resized
- */
- windowResize: function() {
- if (this.resizeTimer) {
- window.clearTimeout(this.resizeTimer);
- this.resizeTimer = null;
- }
- this.resizeTimer = window.setTimeout(this.resize.bind(this), 250);
- },
-
- /**
- * Method: resize
- * resize the element controled by this Jx.Layout object.
- *
- * Parameters:
- * options - new options to apply, see <Jx.Layout::Jx.Layout>
- */
- resize: function(options) {
- this.resizeTimer = null;
- var needsResize = false;
- if (options) {
- for (var i in options) {
- if (this.options[i] != options[i]) {
- needsResize = true;
- this.options[i] = options[i];
- }
- }
- if (options.forceResize) {
- needsResize = true;
- }
- }
-
-
- var parentSize;
- if (this.domObj.parentNode.tagName == 'BODY') {
- parentSize = Element.getPageDimensions();
- } else {
- parentSize = Element.getContentBoxSize(this.domObj.parentNode);
- }
-
- if (this.lastParentSize && !needsResize) {
- needsResize = (this.lastParentSize.width != parentSize.width ||
- this.lastParentSize.height != parentSize.height);
- } else {
- needsResize = true;
- }
- this.lastParentSize = parentSize;
-
- if (!needsResize) {
- return;
- }
-
- var l, t, w, h;
-
- /* calculate left and width */
- if (this.options.left != null) {
- /* fixed left */
- l = this.options.left;
- if (this.options.right == null) {
- /* variable right */
- if (this.options.width == null) {
- //console.log( 'fixed left, variable right, variable width' );
- /* variable right and width
- * set right to min, stretch width */
- w = parentSize.width - l;
- if (w < this.options.minWidth ) {
- w = this.options.minWidth;
- }
- if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
- w = this.options.maxWidth;
- }
- } else {
- //console.log( 'fixed left, variable right, fixed width' );
- /* variable right, fixed width
- * use width
- */
- w = this.options.width;
- }
- } else {
- /* fixed right */
- if (this.options.width == null) {
- //console.log( 'fixed left, fixed right, variable width' );
-
- /* fixed right, variable width
- * stretch width
- */
- w = parentSize.width - l - this.options.right;
- if (w < this.options.minWidth) {
- w = this.options.minWidth;
- }
- if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
- w = this.options.maxWidth;
- }
- } else {
- //console.log( 'fixed left, fixed right, fixed width' );
-
- /* fixed right, fixed width
- * respect left and width, allow right to stretch
- */
- w = this.options.width;
- }
- }
-
- } else {
- if (this.options.right == null) {
- if (this.options.width == null) {
- //console.log( 'variable left, variable right, variable width' );
-
- /* variable left, width and right
- * set left, right to min, stretch width
- */
- l = 0;
- w = parentSize.width;
- if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
- l = l + parseInt(w - this.options.maxWidth)/2;
- w = this.options.maxWidth;
- }
- } else {
- //console.log( 'variable left, variable right, fixed width' );
-
- /* variable left, fixed width, variable right
- * distribute space between left and right
- */
- w = this.options.width;
- l = parseInt((parentSize.width - w)/2);
- if (l < 0) {
- l = 0;
- }
- }
- } else {
- if (this.options.width != null) {
- //console.log( 'variable left, fixed right, fixed width' );
-
- /* variable left, fixed width, fixed right
- * left is calculated directly
- */
- w = this.options.width;
- l = parentSize.width - w - this.options.right;
- if (l < 0) {
- l = 0;
- }
- } else {
- //console.log( 'variable left, fixed right, variable width' );
-
- /* variable left and width, fixed right
- * set left to min value and stretch width
- */
- l = 0;
- w = parentSize.width - this.options.right;
- if (w < this.options.minWidth) {
- w = this.options.minWidth;
- }
- if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
- l = w - this.options.maxWidth - this.options.right;
- w = this.options.maxWidth;
- }
- }
- }
- }
-
- /* calculate the top and height */
- if (this.options.top != null) {
- /* fixed top */
- t = this.options.top;
- if (this.options.bottom == null) {
- /* variable bottom */
- if (this.options.height == null) {
- //console.log( 'fixed top, variable bottom, variable height' );
-
- /* variable bottom and height
- * set bottom to min, stretch height */
- h = parentSize.height - t;
- if (h < this.options.minHeight) {
- h = this.options.minHeight;
- }
- if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
- h = this.options.maxHeight;
- }
- } else {
- //console.log( 'fixed top, variable bottom, fixed height' );
-
- /* variable bottom, fixed height
- * stretch height
- */
- h = this.options.height;
- if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
- t = h - this.options.maxHeight;
- h = this.options.maxHeight;
- }
- }
- } else {
- /* fixed bottom */
- if (this.options.height == null) {
- //console.log( 'fixed top, fixed bottom, variable height' );
-
- /* fixed bottom, variable height
- * stretch height
- */
- h = parentSize.height - t - this.options.bottom;
- if (h < this.options.minHeight) {
- h = this.options.minHeight;
- }
- if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
- h = this.options.maxHeight;
- }
- } else {
- //console.log( 'fixed top, fixed bottom, fixed height' );
-
- /* fixed bottom, fixed height
- * respect top and height, allow bottom to stretch
- */
- h = this.options.height;
- }
- }
-
- } else {
- if (this.options.bottom == null) {
- if (this.options.height == null) {
- //console.log( 'variable top, variable bottom, variable height' );
-
- /* variable top, height and bottom
- * set top, bottom to min, stretch height
- */
- t = 0;
- h = parentSize.height;
- if (h < this.options.minHeight) {
- h = this.options.minHeight;
- }
- if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
- t = parseInt((parentSize.height - this.options.maxHeight)/2);
- h = this.options.maxHeight;
- }
- } else {
- //console.log( 'variable top, variable bottom, fixed height' );
-
- /* variable top, fixed height, variable bottom
- * distribute space between top and bottom
- */
- h = this.options.height;
- t = parseInt((parentSize.height - h)/2);
- if (t < 0) {
- t = 0;
- }
- }
- } else {
- if (this.options.height != null) {
- //console.log( 'variable top, fixed bottom, fixed height' );
-
- /* variable top, fixed height, fixed bottom
- * top is calculated directly
- */
- h = this.options.height;
- t = parentSize.height - h - this.options.bottom;
- if (t < 0) {
- t = 0;
- }
- } else {
- //console.log( 'variable top, fixed bottom, variable height' );
-
- /* variable top and height, fixed bottom
- * set top to min value and stretch height
- */
- t = 0;
- h = parentSize.height - this.options.bottom;
- if (h < this.options.minHeight) {
- h = this.options.minHeight;
- }
- if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
- t = parentSize.height - this.options.maxHeight - this.options.bottom;
- h = this.options.maxHeight;
- }
- }
- }
- }
-
- this.domObj.style.position = this.options.position;
- if (this.options.position == 'absolute') {
- var padding = Element.getPaddingSize(this.domObj.parentNode);
-
- this.domObj.style.left = (l+padding.left) + 'px';
- this.domObj.style.top = (t+padding.top) + 'px';
- Element.setBorderBoxSize(this.domObj, {width: w, height: h} );
- } else {
- var sizeOpts = {width: w};
- if (this.options.height) {
- sizeOpts.height = this.options.height;
- }
- Element.setBorderBoxSize(this.domObj, sizeOpts);
- }
-
- var o = {forceResize: options ? options.forceResize : false};
- for (var i=0; i<this.domObj.childNodes.length; i++) {
- var c = this.domObj.childNodes[i];
- if (c.resize) {
- c.resize(o);
- }
- }
- this.processEvent(this.scl,'sizeChanged',this);
- },
- /**
- * Method: addSizeChangeListener
- * add a size change listener to be notified when the size of the
- * element changes.
- *
- * Parameters:
- * obj - {Object} a size change listener
- */
- addSizeChangeListener: function(obj){this.addListener(this.scl, obj);},
- /**
- * Method: removeSizeChangeListener
- * remove a size change listener
- *
- * Parameters:
- * obj - {Object} a size change listener
- */
- removeSizeChangeListener: function(o) {
- this.removeListener(this.scl, o);
- }
-};
-Object.extend(Jx.Layout.prototype, Jx.Listener.prototype);
-
-/**
- * Class: Jx.Constraint
- * A utility class used with <Jx.Layout> to represent the current
- * set of constraints on an element. This object is not intended
- * to be instantiated directly by a user
- */
-Jx.Constraint = Class.create();
-Jx.Constraint.prototype = {
- position: 'absolute',
- left: 0,
- right: 0,
- top: 0,
- bottom: 0,
- width: null,
- height: null,
- minWidth: 0,
- minHeight: 0,
- maxWidth: -1,
- maxHeight: -1,
- initialize: function(o) {
- for( var i in o ) {
- this[i] = o[i];
- }
- }
-};/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Menu
- *
- * Purpose:
- * Implementation of a javascript menuing system for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-
- Jx.addStyleSheet('menu/menu.css');
- Jx.addStyleSheet('button/button.css');
-
-/**
- * Class: Jx.MenuItem
- * A menu item is a single entry in a menu. It is typically composed of
- * a label and an optional icon. Selecting the menu item triggers an
- * action.
- */
-Jx.MenuItem = Class.create();
-Object.extend(Jx.MenuItem.prototype, Jx.Listener.prototype);
-Object.extend(Jx.MenuItem.prototype, {
- /**
- * Property: al
- * {Array} action listeners
- */
- al: null,
- /**
- * Property: domObj
- * {HTMLElement} the HTML element for this menu item.
- */
- domObj: null,
- /**
- * Property: parent
- * {<Jx.SubMenu> or <Jx.Menu>} the menu that contains the menu item.
- */
- parent: null,
- /**
- * Property: enabled
- * {Boolean} whether the menu item is enabled or not
- */
- enabled: false,
- /**
- * Property: button
- * {<Jx.Button>} the clickable part of the menu item is managed as a
- * <Jx.Button>
- */
- button: null,
- /**
- * Constructor: Jx.MenuItem
- * Create a new instance of Jx.MenuItem
- *
- * Parameters:
- * action - {<Jx.Action>} the action to invoke when the menu item is
- * invoked
- * options - {Object} an object containing options as below.
- *
- * Options:
- * image - {String} URL to an image to use as an icon on this menu item
- * label - {String} the label for the menu item.
- */
- initialize: function(action, options) {
- this.initializeItem(options);
- action.bindTo(this);
- this.propertyChanged(action);
- },
- /**
- * Method: initializeItem
- * Internal method to initalize the button for this menu item.
- *
- * Parameters:
- * options - {Object} an object containing options as below.
- *
- * Options:
- * image - {String} URL to an image to use as an icon on this menu item
- * label - {String} the label for the menu item. */
- initializeItem: function(options) {
- if (!options.image) {
- options.image = Jx.baseURL + 'images/a_pixel.png';
- }
- if (!options.label) {
- options.label = ' ';
- }
- this.label = options.label || ' ';
- this.image = options.image || null;
-
- this.al = [];
- this.domObj = document.createElement('li');
- this.domObj.className = 'jxMenuItem';
-
- /* menu items are buttons without the jxButton class */
- var action = new Jx.Action(this.processActionEvent.bindAsEventListener(this))
- this.button = new Jx.Button(action, options);
- //Element.removeClassName(this.button.domA, 'jxButton');
-
- Event.observe(this.button.domObj, 'mouseover', this.onmouseover.bindAsEventListener(this), true);
-
- this.domObj.appendChild(this.button.domObj);
- },
- /**
- * Method: setParent
- * Set the parent of this menu item
- *
- * Parameters:
- * obj - {Object} the new parent
- */
- setParent: function(obj) {
- this.parent = obj;
- },
- /**
- * Method: hide
- * Hide the menu item.
- */
- hide: function() {},
- /**
- * Method: show
- * Show the menu item
- */
- show: function() {},
- /**
- * Method: addActionListener
- * Add an action listener to this menu item
- *
- * Parameters:
- * obj - {Object} the action listener
- */
- addActionListener: function(obj) { this.addListener(this.al,obj); },
- /**
- * Method: removeActionListener
- * Remove an action listener from this menu item
- *
- * Parameters:
- * obj - {Object} the action listener
- */
- removeActionListener : function(obj) { this.removeListener(this.al, obj); },
- /**
- * Method: processActionEvent
- * Process an action event by informing any action listeners that the action
- * associated with this menu item and hiding the menu.
- *
- * Parameters:
- * e - {Event} the event associated with the user clicking on the menu item
- */
- processActionEvent: function(e) {
- if (this.enabled) {
- this.processEvent(this.al, 'actionPerformed', this);
- if (this.parent && this.parent.deactivate) {
- this.parent.deactivate(e);
- }
- }
- },
- /**
- * Method: propertyChanged
- * Track when a property of the action changes and update the state of the
- * menu item accordingly.
- *
- * Parameters:
- * obj - {<Jx.Action>} the action object
- */
- propertyChanged: function(obj) {
- this.enabled = obj.isEnabled();
- if (this.enabled) {
- Element.removeClassName( this.domObj.childNodes[0].childNodes[0], 'jxDisabled' );
- } else {
- Element.addClassName( this.domObj.childNodes[0].childNodes[0], 'jxDisabled' );
- }
- },
- /**
- * Method: onmouseover
- * handle the mouse moving over the menu item
- *
- * Parameters:
- * e - {Event} the mousemove event
- */
- onmouseover: function(e) {
- var target = Event.element(e);
- if (this.parent && this.parent.setVisibleItem) {
- this.parent.setVisibleItem(this);
- }
- this.show();
- }
-});
-
-/**
- * Class: Jx.MenuSeparator
- * A convenience class to create a visual separator in a menu.
- */
-Jx.MenuSeparator = Class.create();
-Object.extend(Jx.MenuSeparator.prototype, {
- /**
- * Property: domObj
- * {HTMLElement} the HTML element that the separator is contained
- * within
- */
- domObj: null,
- /**
- * Property: parent
- * {<Jx.Menu>, <Jx.SubMenu>} the menu that the separator is in.
- */
- parent: null,
- /**
- * Constructor: Jx.MenuSeparator
- * Create a new instance of a menu separator
- */
- initialize: function() {
- this.domObj = document.createElement('li');
- this.domObj.className = 'jxMenuItem';
- var span = document.createElement('span');
- span.className = 'jxMenuSeparator';
- span.innerHTML = ' ';
- this.domObj.appendChild(span);
- },
- /**
- * Method: setParent
- * Set the parent of this menu item
- *
- * Parameters:
- * obj - {Object} the new parent
- */
- setParent: function(obj) {
- this.parent = obj;
- },
- /**
- * Method: hide
- * Hide the menu item.
- */
- hide: function() {},
- /**
- * Method: show
- * Show the menu item
- */
- show: function() {}
-});
-
-/**
- * Class: Jx.SubMenu
- * A sub menu contains menu items within a main menu or another
- * sub menu.
- *
- * Inherits From:
- * <Jx.MenuItem>
- */
-Jx.SubMenu = Class.create();
-Object.extend(Jx.SubMenu.prototype, Jx.MenuItem.prototype);
-Object.extend(Jx.SubMenu.prototype, {
- /**
- * Property: subDomObj
- * {HTMLElement} the HTML container for the sub menu.
- */
- subDomObj: null,
- /**
- * Property: parent
- * {<Jx.Menu> or <Jx.SubMenu>} the menu or sub menu that this sub menu
- * belongs
- */
- parent: null,
- /**
- * Property: visibleItem
- * {<Jx.MenuItem>} the visible item within the menu
- */
- visibleItem: null,
- /**
- * Property: items
- * {Array} the menu items that are in this sub menu.
- */
- items: null,
- /**
- * Constructor: Jx.SubMenu
- * Create a new instance of Jx.SubMenu
- *
- * Parameters:
- * options - see <Jx.MenuItem::Jx.MenuItem>
- */
- initialize: function(options) {
- this.open = false;
- this.items = [];
- this.initializeItem(options);
- Element.addClassName(this.domObj.childNodes[0].childNodes[0], 'jxButtonSubMenu');
-
- this.iframe = document.createElement('iframe');
- this.iframe.className = 'jxMenuShim';
- this.iframe.scrolling = 'no';
- this.iframe.frameborder = 0;
-
- this.subDomObj = document.createElement('ul');
- this.subDomObj.className = 'jxSubMenu';
- this.subDomObj.style.display = 'none';
-
- // this.button.domObj.appendChild(this.subDomObj);
- this.domObj.appendChild(this.subDomObj);
- },
- /**
- * Method: setParent
- * Set the parent of this sub menu
- *
- * Parameters:
- * obj - {Object} the parent
- */
- setParent: function(obj) {
- this.parent = obj;
- },
- /**
- * Method: show
- * Show the sub menu
- */
- show: function() {
- if (this.open || this.items.length == 0) {
- return;
- }
-
- this.open = true;
- this.subDomObj.style.display = 'block';
- if (!window.opera) {
- this.subDomObj.childNodes[0].appendChild(this.iframe);
- var size = Element.getBorderBoxSize(this.subDomObj);
- this.iframe.style.width = size.width + "px";
- this.iframe.style.height = size.height + "px";
-
- }
- this.setActive(true);
- },
- /**
- * Method: hide
- * Hide the sub menu
- */
- hide: function() {
- if (!this.open) {
- return;
- }
- this.open = false;
- for (var i=0; i<this.items.length; i++) {
- this.items[i].hide();
- }
- this.subDomObj.style.display = 'none';
- if (!window.opera && this.iframe.parentNode) {
- this.subDomObj.childNodes[0].removeChild(this.iframe);
- }
- this.visibleItem = null;
- },
- /**
- * Method: add
- * Add menu items to the sub menu.
- *
- * Parameters:
- * item - {<Jx.MenuItem>} the menu item to add. Multiple menu items
- * can be added by passing multiple arguments to this function.
- */
- add : function() { /* menu */
- for (var i=0; i<arguments.length; i++) {
- var item = arguments[i];
- this.items.push(item);
- item.setParent(this);
- this.subDomObj.appendChild(item.domObj);
- }
- },
- /**
- * Method: insertBefore
- * Insert a menu item before another menu item.
- *
- * Parameters:
- * newItem - {<Jx.MenuItem>} the menu item to insert
- * targetItem - {<Jx.MenuItem>} the menu item to insert before
- */
- insertBefore: function(newItem, targetItem) {
- var bInserted = false;
- for (var i=0; i<this.items.length; i++) {
- if (this.items[i] == targetItem) {
- this.items.splice(i, 0, newItem);
- this.subDomObj.insertBefore(newItem.domObj, targetItem.domObj);
- bInserted = true;
- break;
- }
- }
- if (!bInserted) {
- this.add(newItem);
- }
- },
- /**
- * Method: remove
- * Remove a single menu item from the menu.
- *
- * Parameters:
- * item - {<Jx.MenuItem} the menu item to remove.
- */
- remove: function(item) {
- for (var i=0; i<this.items.length; i++) {
- if (this.items[i] == item) {
- this.items.splice(i,1);
- this.subDomObj.removeChild(item.domObj);
- break;
- }
- }
- },
- /**
- * Method: processActionEvent
- * Process an action event coming from the menu item that
- * represents the sub menu in its parent by showing or hiding
- * the sub menu.
- */
- processActionEvent: function(e) {
- if (this.open) {
- this.hide();
- } else {
- this.show();
- }
- return Event.stop(e);
- },
- /**
- * Method: deactivate
- * Deactivate the sub menu
- *
- * Parameters:
- * e - {Event} the event that triggered the menu being
- * deactivated.
- */
- deactivate: function(e) {
- if (this.parent) {
- this.parent.deactivate(e);
- }
- },
- /**
- * Method: isActive
- * Indicate if this sub menu is active
- *
- * Returns:
- * {Boolean} true if the <Jx.Menu> that ultimately contains
- * this sub menu is active, false otherwise.
- */
- isActive: function() {
- if (this.parent) {
- return this.parent.isActive();
- } else {
- return false;
- }
- },
- /**
- * Method: setActive
- * Set the active state of the <Jx.Menu> that contains this sub menu
- *
- * Parameters:
- * isActive - {Boolean} the new active state
- */
- setActive: function(isActive) {
- if (this.parent && this.parent.setActive) {
- this.parent.setActive(isActive);
- }
- },
- /**
- * Method: setVisibleItem
- * Set a sub menu of this menu to be visible and hide the previously
- * visible one.
- *
- * Parameters:
- * obj - {<Jx.SubMenu>} the sub menu that should be visible
- */
- setVisibleItem: function(obj) {
- if (this.visibleItem != obj) {
- if (this.visibleItem && this.visibleItem.hide) {
- this.visibleItem.hide();
- }
- this.visibleItem = obj;
- this.visibleItem.show();
- }
- }
-});
-
-/**
- * Class: Jx.Menu
- * A main menu as opposed to a sub menu that lives inside the menu.
- *
- * TODO: Jx.Menu
- * revisit this to see if Jx.Menu and Jx.SubMenu can be merged into
- * a single implementation.
- */
-Jx.Menu = Class.create();
-Jx.Menu.prototype = {
- /**
- * Property: domObj
- * {HTMLElement} The HTML element containing the menu.
- */
- domObj : null,
- /**
- * Property: buttonObj
- * {<Jx.Button>} The button that represents this menu in a toolbar and
- * opens the menu.
- */
- buttonObj : null,
- /**
- * Property: subDomObj
- * {HTMLElement} the HTML element that contains the menu items
- * within the menu.
- */
- subDomObj : null,
- /**
- * Property: items
- * {Array} the items in this menu
- */
- items : null,
- /**
- * Property: menus
- * {Array} Class variable that contains a reference to all
- * menus shared by all menu instances.
- */
- menus : [],
- /**
- * Constructor: Jx.Menu
- * Create a new instance of Jx.Menu.
- *
- * Parameters:
- * options - {Object} an options object passed directly to the
- * <Jx.Button> when creating the button that triggers this menu.
- * If options is not passed, then no button is created.
- */
- initialize : function(options) {
- /* stores menu items and sub menus */
- this.items = [];
-
- /* iframe shim to prevent scrollbars and
- inputs from showing through the menu */
- this.iframe = document.createElement('iframe');
- this.iframe.className = 'jxMenuShim';
- this.iframe.scrolling = 'no';
- this.iframe.frameborder = 0;
-
- /* the DOM element that holds the actual menu */
- this.subDomObj = document.createElement('ul');
- this.subDomObj.className = 'jxMenu';
- this.subDomObj.style.display = 'none';
-
- /* if options are passed, make a button inside an LI so the
- menu can be embedded inside a toolbar */
- if (options) {
- this.domObj = document.createElement('li');
-
- var action = new Jx.Action(this.show.bind(this));
- this.button = new Jx.Button(action, options);
- Element.addClassName(this.button.domObj.firstChild, 'jxButtonMenu');
- this.domObj.appendChild(this.button.domObj);
-
- Event.observe(this.domObj, 'mouseover', this.onMouseOver.bindAsEventListener(this));
- //this.button.domObj.appendChild(this.subDomObj);
- this.domObj.appendChild(this.subDomObj);
- }
-
- /* pre-bind the hide function for efficiency */
- this.hideWatcher = this.hide.bindAsEventListener(this);
- },
- /**
- * Method: add
- * Add menu items to the sub menu.
- *
- * Parameters:
- * item - {<Jx.MenuItem>} the menu item to add. Multiple menu items
- * can be added by passing multiple arguments to this function.
- */
- add : function() {
- for (var i=0; i<arguments.length; i++) {
- var item = arguments[i];
- this.items.push(item);
- item.setParent(this);
- this.subDomObj.appendChild(item.domObj);
- }
- },
- /**
- * Method: deactivate
- * Deactivate the menu by hiding it.
- */
- deactivate: function() { this.hide(); },
- /**
- * Method: actionPerformed
- * Any action performed in the menu ultimately calls this
- * method to hide the menu.
- */
- actionPerformed : function() {this.hide();},
- /**
- * Method: onMouseOver
- * Handle the user moving the mouse over the button for this menu
- * by showing this menu and hiding the other menu.
- *
- * Parameters:
- * e - {Event} the mouse event
- */
- onMouseOver: function(e) {
- if (this.menus[0] && this.menus[0] != this) {
- this.show(e);
- }
- },
- /**
- * Method: hide
- * Hide the menu.
- *
- * Parameters:
- * e - {Event} the mouse event
- */
- hide: function(e) {
- if (e) {
- var root = Event.findElement(e, 'LI');
- if (root == this.domObj) {
- return;
- }
- }
- if (this.menus[0] && this.menus[0] == this) {
- this.menus[0] = null;
- }
- for (var i=0; i<this.items.length; i++) {
- this.items[i].hide(e);
- }
- Event.stopObserving(document, 'click', this.hideWatcher, true);
- this.subDomObj.style.display = 'none';
- },
- /**
- * Method: show
- * Show the menu
- *
- * Parameters:
- * e - {Event} the mouse event
- */
- show : function(e) {
- if (this.menus[0] && this.menus[0] != this) {
- this.menus[0].hide(e);
- }
- if (this.items.length ==0) {
- return;
- }
- this.menus[0] = this;
- this.subDomObj.style.display = 'block';
- this.subDomObj.style.visibility = 'visible';
-
- if (!window.opera) {
- this.subDomObj.childNodes[0].appendChild(this.iframe);
- var size = Element.getContentBoxSize(this.subDomObj);
- this.iframe.style.width = size.width + "px";
- this.iframe.style.height = size.height + "px";
- }
- Event.stop(e);
- /* fix bug in IE that closes the menu as it opens because of bubbling */
- Event.observe(document, 'click', this.hideWatcher, true);
- },
- /**
- * Method: setVisibleItem
- * Set the sub menu that is currently open
- *
- * Parameters:
- * obj- {<Jx.SubMenu>} the sub menu that just became visible
- */
- setVisibleItem: function(obj) {
- if (this.visibleItem != obj) {
- if (this.visibleItem && this.visibleItem.hide) {
- this.visibleItem.hide();
- }
- this.visibleItem = obj;
- this.visibleItem.show();
- }
- }
-};
-
-/**
- * Class: Jx.ContextMenu
- * A <Jx.Menu> that has no button but can be opened at a specific
- * browser location to implement context menus (for instance).
- *
- * Inherits From:
- * <Jx.Menu>
- */
-Jx.ContextMenu = Class.create();
-Object.extend(Jx.ContextMenu.prototype, Jx.Menu.prototype);
-Object.extend(Jx.ContextMenu.prototype, {
- /**
- * Constructor: Jx.ContextMenu
- * create a new context menu
- *
- * Parameters:
- * id - {HTMLElement} element or id to make this the context menu
- * for. The menu hooks the oncontextmenu event of the element
- * and shows itself at the mouse position where the right-click
- * happened.
- */
- initialize : function(id) {
- Jx.Menu.prototype.initialize.apply(this, []);
- document.getElementsByTagName('BODY')[0].appendChild(this.subDomObj);
- if ($(id)) {
- $(id).oncontextmenu = this.show.bindAsEventListener(this);;
- }
- },
- /**
- * Method: show
- * Show the context menu at the location of the mouse click
- *
- * Parameters:
- * e - {Event} the mouse event
- */
- show : function(e) {
- this.subDomObj.style.left = Event.pointerX(e) + "px";
- this.subDomObj.style.top = Event.pointerY(e) + "px";
- Jx.Menu.prototype.show.apply(this, [e]);
- }
-});/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Panel
- *
- * Purpose:
- * Implementation of a javascript panels for Jx. Panels are vertically
- * oriented areas that can be resized by the user dragging the panel title
- * bar.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-Jx.addStyleSheet('panel/panel.css');
-
-/**
- * Class: Jx.PanelManager
- * A panel manager manages a set of panels within a DOM element.
- */
-Jx.PanelManager = Class.create();
-Jx.PanelManager.prototype = {
- /**
- * Property: panels
- * {Array} the panels being managed by the manager
- */
- panels: null,
- /**
- * Property: height
- * {Integer} the height of the container, cached for speed
- */
- height: null,
- /**
- * Property: firstLayout
- * {Boolean} true until the panel manager has first been resized
- */
- firstLayout: true,
- /**
- * Constructor: Jx.PanelManager
- * Create a new instance of Jx.PanelManager.
- *
- * Parameters:
- * domObj - {HTMLElement} the HTML element that will contain the panels
- * panels - {Array} the panels to go into the PanelManager
- *
- * TODO: Jx.PanelManager.initialize
- * Remove the panels parameter in favour of an add method.
- */
- initialize: function(domObj, panels) {
- this.domObj = $(domObj);
- this.panels = panels;
- var d = document.createElement('div');
- d.style.position = 'absolute';
- new Jx.Layout(d, {minHeight:0,maxHeight:0,height:0});
- var elements = [d];
- for (var i=0; i<this.panels.length; i++) {
- elements.push(this.panels[i].domObj);
- }
- this.splitter = new Jx.Splitter(this.domObj, {splitInto: panels.length+1,
- layout: 'vertical',
- elements: elements });
- /* redirect splitter sizeChanged so we can capture the first time the
- * splitter is layed out in the client in a way that we can measure
- * the title bar heights
- */
- this.splitter.sizeChanged = this.sizeChanged.bind(this);
- /* create the bars for the panel manager */
- for (var i=0; i<this.panels.length; i++) {
- var panel = this.panels[i];
- this.splitter.bars[i].appendChild(panel.title);
- this.splitter.bars[i].style.height = Element.getBorderBoxSize(panel.title).height + 'px';
- Element.removeClassName(this.splitter.bars[i], 'jxSplitterBar');
- Element.addClassName(this.splitter.bars[i], 'jxPanelBar');
- panel.manager = this;
- }
- },
- /**
- * Method: sizeChanged
- * called when the size of the container of the splitter changes. This tracks the
- * first time the panel titles have a non-zero height (i.e. they are put in the
- * DOM and are visible) and recalculates the panel title height then.
- */
- sizeChanged: function() {
- if (this.firstLayout) {
- if (Element.getBorderBoxSize(this.panels[0].title).height != 0) {
- for (var i=0; i<this.splitter.bars.length; i++) {
- var panel = this.panels[i];
- this.splitter.bars[i].style.height = Element.getBorderBoxSize(panel.title).height + 'px';
- this.splitter.bars[i].size = null;
- }
- this.firstLayout = false;
- Jx.Splitter.prototype.sizeChanged.apply(this.splitter, []);
- }
- } else {
- Jx.Splitter.prototype.sizeChanged.apply(this.splitter, []);
- }
- },
-
- /**
- * Method: maximizePanel
- * Maximize the panel, taking up all available space (taking into
- * consideration any minimum or maximum values)
- */
- maximizePanel: function(panel) {
- var h = Element.getContentBoxSize(this.domObj).height;
-
- var t = 0;
- for (var i=1; i<this.splitter.elements.length; i++) {
- var p = this.splitter.elements[i];
- t += Element.getBorderBoxSize(p.leftBar).height;
- if (p !== panel.domObj) {
- p.jxLayout.resize({top: t, height: p.jxLayout.options.minHeight, bottom: null});
- t += p.jxLayout.options.minHeight;
- p.rightBar.style.top = t + 'px';
- } else {
- break;
- }
- }
-
- b = h;
- for (var i=this.splitter.elements.length - 1; i > 0; i--) {
- p = this.splitter.elements[i];
- if (p !== panel.domObj) {
- b -= p.jxLayout.options.minHeight;
- p.jxLayout.resize({top: b, height: p.jxLayout.options.minHeight, bottom: null});
- b -= Element.getBorderBoxSize(p.leftBar).height;
- p.leftBar.style.top = b + 'px';
-
- } else {
- break;
- }
- }
- panel.domObj.jxLayout.resize({top: t, height:b - t, bottom: null});
- }
-};
-
-/**
- * Class: Jx.Panel
- * A panel that can be displayed inside a panel manager.
- */
-Jx.Panel = Class.create();
-Jx.Panel.prototype = {
- /**
- * Property: labelObj
- * the DOM object that holds the label in the title bar.
- */
- labelObj : null,
- /**
- * Property: state
- * the state of this panel
- */
- state : 'open',
- /**
- * Property: busyCount
- * track the busy state of this panel - used to control a 'loading' image
- */
- busyCount : null,
- /**
- * Property: bContentReady
- * {Boolean} is the content ready to be displayed?
- */
- bContentReady : null,
- /**
- * Property: onContentReady
- * {Function} a function to call when the content is ready
- */
- onContentReady : null,
-
- /**
- * Constructor: Jx.Panel
- * Initialize a new Jx.Panel instance
- *
- * Options:
- *
- * label - String, the title of the Jx Panel
- * toolbar - element to use as the toolbar
- * menubar - element to use as the menu
- * content - element to use as the content. A content area is created
- * if none is provided. Otherwise, the content element is moved
- * in the DOM
- * statusbar - element to use as the statusbar
- * helpCallback - function to call when the user clicks the contextual help button
- * state - initial state of the panel (open or closed)
- *
- * Inherits From:
- * <Jx.UniqueId>, <Jx.ContentLoader>
- */
- initialize : function(options){
- //console.log("Jx.Panel::initialize('"+options.label+"')");
- this.initUniqueId();
-
- /* set up the title object */
- this.title = document.createElement('div');
- this.title.className = "jxPanelTitle";
- //TODO: Jx.Panel.initialize
- //Opera is broken because it doesn't report the height of the
- //title bars at all unless set through javascript
- //this is a hack until we can figure out from css what the height is
- this.title.style.height = '22px';
-
- this.labelObj = document.createElement('span');
- this.labelObj.className = 'jxPanelLabel';
- this.labelObj.innerHTML = options.label?options.label:'empty';
-
- this.imageBaseUrl = options.imageBaseUrl || Jx.baseURL + 'images/';
-
- var a, img;
- if (options.helpCallback) {
- a = document.createElement('a');
- a.className = 'jxPanelHelp';
- a.href = 'javascript:void(0)';
- Event.observe(a, 'click', options.helpCallback);
- img = document.createElement('img');
- img.src = this.imageBaseUrl + "help.png";
- img.alt = 'Help on this panel';
- img.title = 'Help on this panel';
- a.appendChild(img);
- this.title.appendChild(a);
- }
-
- a = document.createElement('a');
- a.className = 'jxPanelMaximize';
- a.href = 'javascript:void(0)';
- Event.observe(a, 'click', this.maximize.bindAsEventListener(this));
- img = document.createElement('img');
- img.src = this.imageBaseUrl + "maximize.png";
- img.alt = 'Maximize Panel';
- img.title = 'Maximize Panel';
- a.appendChild(img);
- this.title.appendChild(a);
-
- a = document.createElement('a');
- a.className = 'jxPanelLoading';
- a.href = 'javascript:void(0)';
- img = document.createElement('img');
- img.src = this.imageBaseUrl + "loading.gif";
- img.alt = 'Loading Panel';
- img.title = 'Loading Panel';
- a.appendChild(img);
- this.loadingObj = {};
- this.loadingObj.link = a;
- this.loadingObj.img = img;
- this.title.appendChild(this.loadingObj.link);
- this.title.appendChild(this.labelObj);
-
- Event.observe(this.title, 'dblclick', this.maximize.bindAsEventListener(this));
-
- this.domObj = document.createElement('div');
- this.domObj.className = 'jxPanel';
-
- this.jxLayout = new Jx.Layout(this.domObj, options.constraint || {});
- this.jxLayout.addSizeChangeListener(this);
-
- var top = 0;
- var bottom = 0;
- if (options.menubar) {
- this.menubar = options.menubar;
- this.domObj.appendChild(options.menubar);
- var h = Element.getBorderBoxSize(options.menubar).height;
- new Jx.Layout(this.menubar, {top: top, height:h});
- top += h;
- }
- if (options.toolbar) {
- this.toolbar = options.toolbar;
- this.domObj.appendChild(options.toolbar);
- var h = Element.getBorderBoxSize(options.toolbar).height;
- new Jx.Layout(this.toolbar, {top:top, height: h});
- }
-
- if (options.statusbar) {
- this.statusbar = options.statusbar;
- this.domObj.appendChild(options.statusbar);
- var h = Element.getBorderBoxSize(options.statusbar).height;
- new Jx.Layout(this.statusbar, {bottom: bottom, height: h, top: null});
- bottom += h;
- }
- this.content = document.createElement('div');
- Element.addClassName(this.content, 'jxPanelContent');
- new Jx.Layout(this.content, {top: top, bottom: bottom});
- this.domObj.appendChild(this.content);
- this.loadContent(this.content, options);
-
- this.busyCount = 0;
- this.bContentReady = false;
- },
- /**
- * Method: setLabel
- * Set the label in the title bar of this panel
- *
- * Parameters:
- * s - {String} the new label
- */
- setLabel: function(s) {
- this.labelObj.innerHTML = s;
- },
- /**
- * Method: getLabel
- * Get the label of the title bar of this panel
- *
- * Returns:
- * {String} the label
- */
- getLabel: function() {
- return this.labelObj.innerHTML;
- },
- /**
- * Method: finalize
- * Clean up the panel
- */
- finalize: function() {
- this.domObj = null;
- this.deregisterIds();
- },
- /**
- * Method: maximize
- * Maximize this panel
- */
- maximize: function() {
- if (this.manager) {
- this.manager.maximizePanel(this);
- }
- },
- /**
- * Method: setContent
- * set the content of this panel to some HTML
- *
- * Parameters:
- * html - {String} the new HTML to go in the panel
- */
- setContent : function (html) {
- //console.log('Jx.Panel::setContent()');
- this.content.innerHTML = html;
- this.bContentReady = true;
- },
- /**
- * Method: setContentURL
- * Set the content of this panel to come from some URL.
- *
- * Parameters:
- * url - {String} URL to some HTML content for this panel
- */
- setContentURL : function (url) {
- this.bContentReady = false;
- this.setBusy(true);
- if (arguments[1]) {
- this.onContentReady = arguments[1];
- }
- if (url.indexOf('?') == -1) {
- url = url + '?';
- }
- //var ts = (new Date()).getTime();
- //url = url + 'ts='+ts;
- var opts = { method: 'get',
- onComplete:this.panelContentLoaded.bind(this),
- requestHeaders: ['If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT']};
- var a = new Ajax.Request( url, opts);
- },
- /**
- * Method: panelContentLoaded
- * When the content of the panel is loaded from a remote URL, this
- * method is called when the ajax request returns.
- *
- * Parameters:
- * r - {XmlHttpRequest} the XmlHttpRequest object
- */
- panelContentLoaded: function(r) {
- this.content.innerHTML = r.responseText;
- this.bContentReady = true;
- this.setBusy(false);
- if (this.onContentReady) {
- window.setTimeout(this.onContentReady.bind(this),1);
- }
- },
- /**
- * Method: setBusy
- * Set the panel as busy or not busy, which displays a loading image
- * in the title bar.
- *
- * Parameters:
- * isBusy - {Boolean} the busy state
- */
- setBusy : function(isBusy) {
- this.busyCount += isBusy?1:-1;
- this.loadingObj.img.style.visibility = (this.busyCount>0)?'visible':'hidden';
- },
- /**
- * Method: sizeChanged
- * handle the size of the container changing by resizing the various
- * elements of the panel.
- */
- sizeChanged: function() {
- var top = 0;
- var bottom = 0;
- if (this.menubar) {
- this.menubar.style.height = '';
- var size = Element.getBorderBoxSize(this.menubar);
- this.menubar.resize({height:size.height});
- top += size.height;
- }
- if (this.toolbar) {
- this.toolbar.style.height = '';
- var size = Element.getBorderBoxSize(this.toolbar);
- this.toolbar.resize({height:size.height});
- top += size.height;
- }
- if (this.statusbar) {
- this.statusbar.style.height = '';
- var size = Element.getBorderBoxSize(this.statusbar);
- this.statusbar.resize({height:size.height});
- bottom += size.height;
- }
- if (top || bottom) {
- this.content.resize({bottom: bottom, top: top});
- }
- }
-};
-Object.extend(Jx.Panel.prototype, Jx.UniqueId.prototype);
-Object.extend(Jx.Panel.prototype, Jx.ContentLoader.prototype);/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Picker
- *
- * Purpose:
- * Implementation of a javascript Pick List for Jx. This is analagous to an
- * HTML select except that it allows other things to be put in the list. The
- * selected item from the list can also be editable.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-Jx.addStyleSheet('picker/picker.css');
-
-/**
- * Class: Jx.Picker
- * A drop down list of selectable items that can be any HTML.
- *
- * Inherits From:
- * <Jx.Listener>
- */
-Jx.Picker = Class.create();
-Jx.Picker.prototype = {
- /**
- * Property: sl
- * {Array} selection listeners
- */
- sl : null,
-
- /**
- * Property: domObj
- * {HTMLElement} the div that contains the control,
- * used to show/hide the control
- */
- domObj : null,
- /**
- * Property: ul
- * {HTMLElement} the ul that contains the selectable items
- */
- ul : null,
- /**
- * Property: currentSelection
- * {Object} current selection in the list
- */
- currentSelection : null,
-
- /**
- * Property: isEditable
- * {Boolean} is the selected item editable?
- **/
- isEditable: false,
- /**
- * Constructor: Jx.Picker
- * create a new instance of Jx.Picker
- *
- * Options:
- * editable - {Boolean} defaults to false. If true, then the selected item
- * is editable.
- */
- initialize: function(options) {
- options = options || {};
-
- this.domObj = document.createElement('div');
- this.domObj.className = 'jxPicker';
- this.isEditable = options.editable || false;
-
- if (this.isEditable) {
- this.domInput = document.createElement('input');
- this.domInput.type = 'text';
- Event.observe(this.domInput, 'change', this.valueChanged.bind(this));
- Event.observe(this.domInput, 'keydown', this.onKeyPress.bind(this));
- } else {
- this.domInput = document.createElement('span');
- }
- this.domInput.className = 'jxPickerInput';
-
- this.domObj.appendChild(this.domInput);
-
- this.domA = document.createElement('a');
- this.domA.href = 'javascript:void(0)';
- this.domA.className = 'jxPickerDiscloser';
- Event.observe(this.domA, 'click', this.toggle.bind(this));
-
- this.domButton = document.createElement('img');
- this.domButton.src = Jx.baseURL + 'images/disclose2.png';
- Element.addClassName(this.domButton, 'png24');
- this.domA.appendChild(this.domButton);
- this.domObj.appendChild(this.domA);
-
- if (!window.opera) {
- //insert iframeShim for IE to cover other controls in the page.
- var iframe = document.createElement('iframe');
- iframe.className = 'jxDialogShim';
- iframe.scrolling = 'no';
- iframe.frameborder = 0;
- this.domObj.appendChild(iframe);
- }
-
- this.domListDiv = document.createElement('div');
- this.domListDiv.className = 'jxPickerOptions';
- this.domListDiv.style.display = 'none';
- this.domObj.appendChild(this.domListDiv);
- this.domList = document.createElement('ul');
- this.domListDiv.appendChild(this.domList);
- this.sl = [];
- },
-
- /**
- * Method: onKeyPress
- * Handle the user pressing a key by looking for an ENTER key to set the
- * value.
- *
- * Parameters:
- * e - {Event} the keypress event
- */
- onKeyPress: function(e) {
- var charCode = (e.charCode) ? e.charCode : ((e.keyCode) ? e.keyCode : e.which);
- if (charCode == Event.KEY_RETURN) {
- this.valueChanged();
- }
- },
-
- /**
- * Method: valueChanged
- * When the value is changed, propogate the change to the selection
- * listeners
- */
- valueChanged: function() {
- this.processEvent(this.sl, 'selectionChanged', this);
- },
-
- /**
- * Method: add
- * add a new item to the pick list
- *
- * Parameters:
- * domObj - {HTMLElement} the element to add
- * idx - {Integer} the index to add the element add
- */
- add: function(domObj, idx) {
- var li = document.createElement('li');
- var a = document.createElement('a');
- a.href="javascript:void(0)";
-
- if (typeof(domObj) == 'string') {
- a.innerHTML = domObj;
- } else {
- a.appendChild(domObj);
- }
- Event.observe(a, 'click', this.pick.bindAsEventListener(this));
- li.appendChild(a);
-
- if (arguments.length > 1 && this.domList.childNodes.length > idx) {
- this.domList.insertBefore(li, this.domList.childNodes[idx]);
- } else {
- this.domList.appendChild(li);
- }
- if (this.getValue() == '') {
- this.setValue(a.childNodes[0]);
- }
- },
-
- /**
- * Method: remove
- * Remove the item at the given index
- *
- * Parameters:
- * idx - {Integer} the item to remove.
- */
- remove: function(idx) {
- if (idx > 0 && idx < this.domList.childNodes.length) {
- this.domList.removeChild(this.domList.childNodes[idx]);
- }
- },
-
- /**
- * Method: pick
- * user has clicked something in the list, select it
- *
- * Parameters:
- * e - {Event} the mouse event from the user's click
- */
- pick: function(e) {
- var target = Event.element(e);
- if (target.tagName == 'A') {
- this.currentSelection = target;
- this.setValue(this.currentSelection.childNodes[0]);
- this.valueChanged();
- }
- this.close();
- },
- /**
- * Method: setValue
- * set the value of the picker
- *
- * Parameters:
- * value - {Object} the new value. May be a string, a text node, or
- * another DOM element.
- */
- setValue: function(value) {
- if (this.isEditable) {
- if (typeof(value) == 'string') {
- this.domInput.value = value;
- } else if (value.nodeType && value.nodeType == 3) {
- this.domInput.value = value.nodeValue;
- } else {
- this.domInput.value = value.innerHTML;
- }
- } else if (!this.isEditable) {
- if (typeof(value) == 'string') {
- this.domInput.innerHTML = value;
- } else if (value.nodeType && value.nodeType == 3) {
- this.domInput.innerHTML = value.nodeValue;
- } else {
- this.domInput.appendChild(value);
- }
- }
- },
-
- /**
- * Method: getValue
- * Return the current value
- *
- * Returns:
- * {Object} returns the currently selected item
- */
- getValue: function() {
- value = '';
- if (this.isEditable) {
- value = this.domInput.value;
- } else if (this.domInput.childNodes.length > 0) {
- if (this.domInput.childNodes[0].nodeType == 3) {
- value = this.domInput.innerHTML;
- } else {
- value = this.domInput.childNodes[0];
- }
- }
- return value;
- },
-
- /**
- * Method: toggle
- * Toggle the display of the list associated with the picker
- */
- toggle: function() {
- if (this.domListDiv.style.display == 'block') {
- this.close();
- } else {
- this.open();
- }
- },
-
- /**
- * Method: open
- * Open the pick list
- */
- open: function() {
- if (!this.keypressListener) {
- this.keypressListener = this.keypress.bindAsEventListener(this);
- }
- this.domListDiv.style.display = 'block';
- Event.observe(document, 'keypress', this.keypressListener);
- //Effect.SlideDown(this.domObj, 0.2);
- },
- /**
- * Method: keypress
- * Handle a key press event when the list is open so we can close it if the
- * user hits the ESC key.
- *
- * Parameters:
- * e - {Event} the keypress event
- */
- keypress: function(e) {
- var charCode=(e.charCode)?e.charCode:e.keyCode;
- if (charCode == Event.KEY_ESC) {
- this.close();
- }
- },
- /**
- * Method: close
- * Close the picker.
- */
- close: function() {
- this.domListDiv.style.display = 'none';
- Event.stopObserving(document, 'keypress', this.keypressListener);
- //Effect.SlideUp(this.domObj, 0.2);
- },
- /**
- * Method: addSelectionListener
- * Add a selection listener to the picker
- *
- * Parameters:
- * obj - {Object} the selection listener
- */
- addSelectionListener: function(obj) { this.addListener(this.sl, obj); },
- /**
- * Method: removeSelectionListener
- * Remove a selection listener to the picker
- *
- * Parameters:
- * obj - {Object} the selection listener
- */
- removeSelectionListener: function(obj) { this.removeListener(this.sl, obj); },
- /**
- * Method: getSelection
- * return the current selection
- *
- * Returns:
- * {Object} the current selection or an empty string.
- */
- getSelection: function() {
- return this.currentSelection ? this.currentSelection.name : '';
- }
-};
-Object.extend(Jx.Picker.prototype, Jx.Listener.prototype);/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Splitter
- *
- * Purpose:
- * Implementation of a javascript Splitter for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-/**
- * Class: Jx.Splitter
- * a Jx.Splitter creates two or more containers within a parent container
- * and provides user control over the size of the containers. The split
- * can be made horizontally or vertically.
- *
- * A horizontal split creates containers that divide the space horizontally
- * with vertical bars between the containers. A vertical split divides
- * the space vertically and creates horizontal bars between the containers.
- */
-
-Jx.Splitter = Class.create();
-Jx.Splitter.prototype = {
- /**
- * Property: domObj
- * {HTMLElement} the element being split
- */
- domObj: null,
- /**
- * Property: elements
- * {Array} an array of elements that are displayed in each of the split
- * areas
- */
- elements: null,
- /**
- * Property: bars
- * {Array} an array of the bars between each of the elements used to
- * resize the split areas.
- */
- bars: null,
- /**
- * Property: firstUpdate
- * {Boolean} track the first resize event so that unexposed Jx things
- * can be forced to calculate their size the first time they are exposed.
- */
- firstUpdate: true,
- /**
- * Constructor: Jx.Splitter
- * Create a new instance of Jx.Splitter
- *
- * Parameters:
- * domObj - {HTMLElement} the element or id of the element to split
- * options - {Object} optional arguments specified as properties of
- * this object are as below.
- *
- * Options:
- * elements - {Array} an array of elements to put into the split areas.
- * If splitInto is not set, then it is calculated from the length of
- * this array.
- * splitInto - {Integer} the number of elements to split the domObj into.
- * If not set, then the length of the elements option is used, or 2 if
- * elements is not specified. If splitInto is specified and elements
- * is specified, then splitInto is used. If there are more elements than
- * splitInto specifies, then the extras are ignored. If there are less
- * elements than splitInto specifies, then extras are created.
- * containerOptions - {Array} an array of objects that provide options
- * for the <Jx.Layout> constraints on each element.
- * layout - {String} either 'horizontal' or 'vertical', indicating the
- * direction in which the domObj is to be split.
- * snappers - {Array} an array of objects which can be used to snap
- * elements open or closed.
- */
- initialize: function(domObj, options) {
- options = options || {};
-
- this.domObj = $(domObj);
- this.domObj.style.overflow = 'hidden';
- if (this.domObj.jxLayout) {
- this.domObj.jxLayout.addSizeChangeListener(this);
- }
-
- this.elements = [];
- this.bars = [];
-
- var nSplits = options.splitInto || (options.elements ? options.elements.length : 2);
-
- var aContainerOpts = options.containerOptions || [];
-
- for (var i=0; i<nSplits; i++) {
- this.elements[i] = options.elements ? options.elements[i] : this.prepareElement();
- this.domObj.appendChild(this.elements[i]);
- if (!this.elements[i].jxLayout) {
- new Jx.Layout(this.elements[i], aContainerOpts[i]);
- }
- }
-
- for (var i=1; i<nSplits; i++) {
- this.bars[i-1] = this.prepareBar();
- this.bars[i-1].leftSide = this.elements[i-1];
- this.bars[i-1].rightSide = this.elements[i];
- this.elements[i-1].rightBar = this.bars[i-1];
- this.elements[i].leftBar = this.bars[i-1];
- this.domObj.appendChild(this.bars[i-1]);
- }
-
- this.layout = options.layout || 'horizontal';
- this.establishConstraints();
-
- if (options.snappers) {
- for (var i=0; i<options.snappers.length; i++) {
- if (options.snappers[i]) {
- new Jx.Splitter.Snapper(options.snappers[i], this.elements[i], this);
- }
- }
- }
- },
- /**
- * Method: prepareElement
- * Prepare a new, empty element to go into a split area.
- *
- * Returns:
- * {HTMLElement} an HTMLElement that goes into a split area.
- */
- prepareElement: function(){
- var o = document.createElement('div');
- o.style.position = 'absolute';
- o.leftBar = null;
- o.rightBar = null;
- return o;
- },
-
- /**
- * Method: prepareBar
- * Prepare a new, empty bar to go into between split areas.
- *
- * Returns:
- * {HTMLElement} an HTMLElement that becomes a bar.
- */
- prepareBar: function() {
- var o = document.createElement('div');
- o.className = 'jxSplitterBar';
- o.style.position = 'absolute';
- o.title = 'drag this bar to resize';
- o.style.lineHeight = '1px'; // for IE, horizontal bars
- o.splitterObj = this;
- return o;
- },
-
- /**
- * Method: establishConstraints
- * Setup the initial set of constraints that set the behaviour of the
- * bars between the elements in the split area.
- */
- establishConstraints: function() {
- if (this.layout == 'horizontal') {
- for (var i=0; i< this.bars.length; i++) {
- this.bars[i].style.top = '0px';
- this.bars[i].style.height = '100%';
- new Draggable(this.bars[i], { constraint: 'horizontal' ,
- starteffect : function(element) {
- element.style.backgroundColor = '#eee';
- },
- endeffect : function(element) {
- element.style.backgroundColor = '';
- }
- });
- }
- } else {
- for (var i=0; i< this.bars.length; i++) {
- this.bars[i].style.left = '0px';
- this.bars[i].style.width = '100%';
- new Draggable(this.bars[i], { constraint: 'vertical' ,
- starteffect : function(element) {
- element.style.backgroundColor = '#eee';
- },
- endeffect : function(element) {
- element.style.backgroundColor = '';
- }
- });
- }
- }
- Draggables.addObserver(this);
- },
-
- /**
- * Method: onEnd
- * Handle the end of a drag event on a bar.
- *
- * Parameters:
- * eventName - {String} the name associated with the drag event
- * obj - {HTMLElement} the bar that was dragged
- * event - {Event} the event object associated with the drag
- */
- onEnd: function(eventName, obj, event) {
- if (obj.element.splitterObj != this) {
- return;
- }
- if (this.layout == 'horizontal') {
- this.dragHorizontal(eventName, obj, event);
- } else {
- this.dragVertical(eventName, obj, event);
- }
- },
-
- /**
- * Method: dragHorizontal
- * In a horizontally split container, handle a bar being dragged left or
- * right by resizing the elements on either side of the bar.
- *
- * Parameters:
- * eventName - {String} the name associated with the drag event
- * obj - {HTMLElement} the bar that was dragged
- * event - {Event} the event object associated with the drag
- */
- dragHorizontal: function(eventName, obj, event) {
- var leftEdge = parseInt(obj.element.style.left);
- var leftSide = obj.element.leftSide;
- var rightSide = obj.element.rightSide;
-
- /* process right side first */
- var rsLeft, rsWidth, rsRight;
-
- if (!obj.element.size) {
- obj.element.size = Element.getBorderBoxSize(obj.element);
- }
- var barSize = obj.element.size;
- rsLeft = leftEdge + barSize.width;
-
- var parentSize = Element.getContentBoxSize(this.domObj);
-
- if (rightSide.jxLayout.options.width != null) {
- rsWidth = rightSide.jxLayout.options.width + rightSide.jxLayout.options.left - rsLeft;
- rsRight = parentSize.width - rsLeft - rsWidth;
- } else {
- rsWidth = parentSize.width - rightSide.jxLayout.options.right - rsLeft;
- rsRight = rightSide.jxLayout.options.right;
- }
-
- /* enforce constraints on right side */
- if (rsWidth < 0) {
- rsWidth = 0;
- }
-
- if (rsWidth < rightSide.jxLayout.options.minWidth) {
- rsWidth = rightSide.jxLayout.options.minWidth;
- }
- if (rightSide.jxLayout.options.maxWidth >= 0 && rsWidth > rightSide.jxLayout.options.maxWidth) {
- rsWidth = rightSide.jxLayout.options.maxWidth;
- }
-
- rsLeft = parentSize.width - rsRight - rsWidth;
- leftEdge = rsLeft - barSize.width;
-
- /* process left side */
- var lsLeft, lsWidth;
- lsLeft = leftSide.jxLayout.options.left;
- lsWidth = leftEdge - lsLeft;
-
- /* enforce constraints on left */
- if (lsWidth < 0) {
- lsWidth = 0;
- }
- if (lsWidth < leftSide.jxLayout.options.minWidth) {
- lsWidth = leftSide.jxLayout.options.minWidth;
- }
- if (leftSide.jxLayout.options.maxWidth >= 0 &&
- lsWidth > leftSide.jxLayout.options.maxWidth) {
- lsWidth = leftSide.jxLayout.options.maxWidth;
- }
-
- /* update the leftEdge to accomodate constraints */
- if (lsLeft + lsWidth != leftEdge) {
- /* need to update right side, ignoring constraints because left side
- constraints take precedence (arbitrary decision)
- */
- leftEdge = lsLeft + lsWidth;
- var delta = leftEdge + barSize.width - rsLeft;
- rsLeft += delta;
- rsWidth -= delta;
- }
-
- /* put bar in its final location based on constraints */
- obj.element.style.left = leftEdge + 'px';
-
- /* update leftSide positions */
- if (leftSide.jxLayout.options.width == null) {
- var parentSize = Element.getContentBoxSize(this.domObj);
- leftSide.jxLayout.resize({right: parentSize.width - lsLeft-lsWidth});
- } else {
- leftSide.jxLayout.resize({width: lsWidth});
- }
-
- /* update rightSide position */
- if (rightSide.jxLayout.options.width == null) {
- rightSide.jxLayout.resize({left:rsLeft});
- } else {
- rightSide.jxLayout.resize({left: rsLeft, width: rsWidth});
- }
- },
-
- /**
- * Method: dragVertical
- * In a vertically split container, handle a bar being dragged up or
- * down by resizing the elements on either side of the bar.
- *
- * Parameters:
- * eventName - {String} the name associated with the drag event
- * obj - {HTMLElement} the bar that was dragged
- * event - {Event} the event object associated with the drag
- */
- dragVertical: function(eventName, obj, event) {
- /* top edge of the bar */
- var topEdge = parseInt(obj.element.style.top);
-
- /* the containers on either side of the bar */
- var topSide = obj.element.leftSide;
- var bottomSide = obj.element.rightSide;
-
- /* measure the bar and parent container for later use */
- if (!obj.element.size) {
- obj.element.size = Element.getBorderBoxSize(obj.element);
- }
- var barSize = obj.element.size;
- var parentSize = Element.getContentBoxSize(this.domObj);
-
- /* process top side first */
- var bsTop, bsHeight, bsBottom;
-
- /* top edge of bottom side is the top edge of bar plus the height of the bar */
- bsTop = topEdge + barSize.height;
-
- if (bottomSide.jxLayout.options.height != null) {
- /* bottom side height is fixed */
- bsHeight = bottomSide.jxLayout.options.height + bottomSide.jxLayout.options.top - bsTop;
- bsBottom = parentSize.height - bsTop - bsHeight;
- } else {
- /* bottom side height is not fixed. */
- bsHeight = parentSize.height - bottomSide.jxLayout.options.bottom - bsTop;
- bsBottom = bottomSide.jxLayout.options.bottom;
- }
-
- /* enforce constraints on bottom side */
- if (bsHeight < 0) {
- bsHeight = 0;
- }
-
- if (bsHeight < bottomSide.jxLayout.options.minHeight) {
- bsHeight = bottomSide.jxLayout.options.minHeight;
- }
-
- if (bottomSide.jxLayout.options.maxHeight >= 0 && bsHeight > bottomSide.jxLayout.options.maxHeight) {
- bsHeight = bottomSide.jxLayout.options.maxHeight;
- }
-
- /* recalculate the top of the bottom side in case it changed
- due to a constraint. The bar may have moved also.
- */
- bsTop = parentSize.height - bsBottom - bsHeight;
- topEdge = bsTop - barSize.height;
-
- /* process left side */
- var tsTop, tsHeight;
- tsTop = topSide.jxLayout.options.top;
- tsHeight = topEdge - tsTop;
-
- /* enforce constraints on left */
- if (tsHeight < 0) {
- tsHeight = 0;
- }
- if (tsHeight < topSide.jxLayout.options.minHeight) {
- tsHeight = topSide.jxLayout.options.minHeight;
- }
- if (topSide.jxLayout.options.maxHeight >= 0 &&
- tsHeight > topSide.jxLayout.options.maxHeight) {
- tsHeight = topSide.jxLayout.options.maxHeight;
- }
-
- /* update the topEdge to accomodate constraints */
- if (tsTop + tsHeight != topEdge) {
- /* need to update right side, ignoring constraints because left side
- constraints take precedence (arbitrary decision)
- */
- topEdge = tsTop + tsHeight;
- var delta = topEdge + barSize.height - bsTop;
- bsTop += delta;
- bsHeight -= delta;
- }
-
- /* put bar in its final location based on constraints */
- obj.element.style.top = topEdge + 'px';
-
- /* update topSide positions */
- if (topSide.jxLayout.options.height == null) {
- topSide.jxLayout.resize({bottom: parentSize.height - tsTop-tsHeight});
- } else {
- topSide.jxLayout.resize({height: tsHeight});
- }
-
- /* update bottomSide position */
- if (bottomSide.jxLayout.options.height == null) {
- bottomSide.jxLayout.resize({top:bsTop});
- } else {
- bottomSide.jxLayout.resize({top: bsTop, height: bsHeight});
- }
- },
-
- /**
- * Method: sizeChanged
- * handle the size of the container being changed.
- */
- sizeChanged: function() {
- if (this.layout == 'horizontal') {
- this.horizontalResize();
- } else {
- this.verticalResize();
- }
- },
-
- /**
- * Method: horizontalResize
- * Resize a horizontally layed-out container
- */
- horizontalResize: function() {
- var availableSpace = Element.getContentBoxSize(this.domObj).width;
- var overallWidth = availableSpace;
-
- for (var i=0; i<this.bars.length; i++) {
- var bar = this.bars[i];
- if (!bar.size) {
- bar.size = Element.getBorderBoxSize(bar);
- }
- availableSpace -= bar.size.width;
- }
-
- var nVariable = 0;
- var jxo;
- for (var i=0; i<this.elements.length; i++) {
- var e = this.elements[i];
- jxo = e.jxLayout.options;
- if (jxo.width != null) {
- availableSpace -= parseInt(jxo.width);
- } else {
- var w = 0;
- if (jxo.right != 0 ||
- jxo.left != 0) {
- w = Element.getBorderBoxSize(e).width;
- }
-
- availableSpace -= w;
- nVariable++;
- }
- }
-
- if (nVariable == 0) { /* all fixed */
- /* stick all available space in the last one */
- availableSpace += jxo.width;
- jxo.width = null;
- nVariable = 1;
- }
-
- var amount = parseInt(availableSpace / nVariable);
- /* account for rounding errors */
- var remainder = availableSpace % nVariable;
-
- var currentPosition = 0;
-
- for (var i=0; i<this.elements.length; i++) {
- var e = this.elements[i];
- var jxl = e.jxLayout;
- var jxo = jxl.options;
- if (jxo.width != null) {
- jxl.resize({left: currentPosition});
- currentPosition += jxo.width;
- } else {
- var a = amount;
- if (nVariable == 1) {
- a += remainder;
- }
- nVariable--;
-
- var w = 0;
- if (jxo.right != 0 || jxo.left != 0) {
- w = Element.getBorderBoxSize(e).width + a;
- } else {
- w = a;
- }
-
- if (w < 0) {
- if (nVariable > 0) {
- amount = amount + w/nVariable;
- }
- w = 0;
- }
- if (w < jxo.minWidth) {
- if (nVariable > 0) {
- amount = amount + (w - jxo.minWidth)/nVariable;
- }
- w = jxo.minWidth;
- }
- if (jxo.maxWidth >= 0 && w > jxo.maxWidth) {
- if (nVariable > 0) {
- amount = amount + (w - jxo.maxWidth)/nVariable;
- }
- w = e.options.maxWidth;
- }
-
- var r = overallWidth - currentPosition - w;
- jxl.resize({left: currentPosition, right: r});
- currentPosition += w;
- }
- if (e.rightBar) {
- e.rightBar.style.left = currentPosition + 'px';
- currentPosition += e.rightBar.size.width;
- }
- }
- },
-
- /**
- * Method: verticalResize
- * Resize a vertically layed out container.
- */
- verticalResize: function() {
- var availableSpace = Element.getContentBoxSize(this.domObj).height;
- var overallHeight = availableSpace;
-
- for (var i=0; i<this.bars.length; i++) {
- var bar = this.bars[i];
- if (!bar.size) {
- bar.size = Element.getBorderBoxSize(bar);
- }
- availableSpace -= bar.size.height;
- }
-
- var nVariable = 0;
-
- var jxo;
- for (var i=0; i<this.elements.length; i++) {
- var e = this.elements[i];
- jxo = e.jxLayout.options;
- if (jxo.height != null) {
- availableSpace -= parseInt(jxo.height);
- } else {
- var h = 0;
- if (jxo.bottom != 0 || jxo.top != 0) {
- h = Element.getBorderBoxSize(e).height;
- }
-
- availableSpace -= h;
- nVariable++;
- }
- }
-
- if (nVariable == 0) { /* all fixed */
- /* stick all available space in the last one */
- availableSpace += jxo.height;
- jxo.height = null;
- nVariable = 1;
- }
-
- var amount = parseInt(availableSpace / nVariable);
- /* account for rounding errors */
- var remainder = availableSpace % nVariable;
-
- var currentPosition = 0;
-
- for (var i=0; i<this.elements.length; i++) {
- var e = this.elements[i];
- var jxl = e.jxLayout;
- var jxo = jxl.options;
- if (jxo.height != null) {
- jxl.resize({top: currentPosition});
- currentPosition += jxo.height;
- } else {
- var a = amount;
- if (nVariable == 1) {
- a += remainder;
- }
- nVariable--;
-
- var h = 0;
- if (jxo.bottom != 0 ||
- jxo.top != 0) {
- h = Element.getBorderBoxSize(e).height + a;
- } else {
- h = a;
- }
-
- if (h < 0) {
- if (nVariable > 0) {
- amount = amount + h/nVariable;
- }
- h = 0;
- }
- if (h < jxo.minHeight) {
- if (nVariable > 0) {
- amount = amount + (h - jxo.minHeight)/nVariable;
- }
- h = jxo.minHeight;
- }
- if (jxo.maxHeight >= 0 && h > jxo.maxHeight) {
- if (nVariable > 0) {
- amount = amount + (h - jxo.maxHeight)/nVariable;
- }
- h = jxo.maxHeight;
- }
-
- var r = overallHeight - currentPosition - h;
- jxl.resize({top: currentPosition, bottom: r});
- currentPosition += h;
- }
- if (e.rightBar) {
- e.rightBar.style.top = currentPosition + 'px';
- currentPosition += e.rightBar.size.height;
- }
- }
- }
-};
-
-/**
- * Class: Jx.Splitter.Snapper
- * A helper class to create an element that can snap a split panel open or
- * closed.
- */
-Jx.Splitter.Snapper = Class.create();
-Jx.Splitter.Snapper.prototype = {
- /**
- * Property: snapper
- * {HTMLElement} the DOM element of the snapper (the thing that gets
- * clicked).
- */
- snapper: null,
- /**
- * Property: element
- * {HTMLElement} An element of the <Jx.Splitter> that gets controlled
- * by this snapper
- */
- element: null,
- /**
- * Property: splitter
- * {<Jx.Splitter>} the splitter that this snapper is associated with.
- */
- splitter: null,
- /**
- * Property: layout
- * {String} track the layout of the splitter for convenience.
- */
- layout: 'vertical',
- /**
- * Constructor: Jx.Splitter.Snapper
- * Create a new Jx.Splitter.Snapper
- *
- * Parameters:
- * snapper - {HTMLElement} the clickable thing that snaps the element
- * open and closed
- * element - {HTMLElement} the element that gets controlled by the snapper
- * splitter - {<Jx.Splitter>} the splitter that this all happens inside of.
- */
- initialize: function(snapper, element, splitter) {
- this.snapper = snapper;
- this.element = element;
- element.jxLayout.addSizeChangeListener(this);
- this.splitter = splitter;
- this.layout = splitter.layout;
- var jxo = this.element.jxLayout.options;
- var size = Element.getBorderBoxSize(this.element);
- if (this.layout == 'vertical') {
- this.originalSize = size.height;
- this.minimumSize = jxo.minHeight ? jxo.minHeight : 0;
- } else {
- this.originalSize = size.width;
- this.minimumSize = jxo.minWidth ? jxo.minWidth : 0;
- }
-
- Event.observe(snapper, 'click', this.toggleElement.bind(this));
- },
-
- /**
- * Method: toggleElement
- * Snap the element open or closed.
- */
- toggleElement: function() {
- var size = Element.getBorderBoxSize(this.element);
- var newSize = {};
- if (this.layout == 'vertical') {
- if (size.height == this.minimumSize) {
- newSize.height = this.originalSize;
- } else {
- this.originalSize = size.height;
- newSize.height = this.minimumSize;
- }
- } else {
- if (size.width == this.minimumSize) {
- newSize.width = this.originalSize;
- } else {
- this.originalSize = size.width;
- newSize.width = this.minimumSize;
- }
- }
- this.element.jxLayout.resize(newSize);
- this.splitter.sizeChanged();
- },
-
- /**
- * Method: sizeChanged
- * Handle the size of the element changing to see if the
- * toggle state has changed.
- */
- sizeChanged: function() {
- var size = Element.getBorderBoxSize(this.element);
- if (this.layout == 'vertical') {
- if (size.height == this.minimumSize) {
- Element.addClassName(this.snapper, 'jxSnapClosed');
- Element.removeClassName(this.snapper, 'jxSnapOpened');
- } else {
- Element.addClassName(this.snapper, 'jxSnapOpened');
- Element.removeClassName(this.snapper, 'jxSnapClosed');
- }
- } else {
- if (size.width == this.minimumSize) {
- Element.addClassName(this.snapper, 'jxSnapClosed');
- Element.removeClassName(this.snapper, 'jxSnapOpened');
- } else {
- Element.addClassName(this.snapper, 'jxSnapOpened');
- Element.removeClassName(this.snapper, 'jxSnapClosed');
- }
- }
- }
-};/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Tab
- *
- * Purpose:
- * Implementation of a javascript tabbed panel capability for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-Jx.addStyleSheet('tab/tabs.css');
-Jx.addStyleSheet('tabs/tabs_ie.css', true);
-
-/**
- * Class: Jx.TabSet
- * A TabSet manages a set of <Jx.Tab> content areas by ensuring that only one
- * of the content areas is visible (i.e. the active tab). TabSet does not
- * manage the actual tabs. The instances of <Jx.Tab> that are to be managed
- * as a set have to be added to both a TabSet and a <Jx.Toolbar>. The content
- * areas of the <Jx.Tab>s are sized to fit the content area that the TabSet
- * is managing.
- *
- * (code)
- * var tabBar = new Jx.Toolbar('tabBar');
- * var tabSet = new Jx.TabSet('tabArea');
- *
- * var tab1 = new Jx.Tab('tab 1', {contentID: 'content1'});
- * var tab2 = new Jx.Tab('tab 2', {contentID: 'content2'});
- * var tab3 = new Jx.Tab('tab 3', {contentID: 'content3'});
- * var tab4 = new Jx.Tab('tab 4', {contentURL: 'test_content.html'});
- *
- * tabSet.add(t1, t2, t3, t4);
- * tabBar.add(t1, t2, t3, t4);
- * (end)
- *
- * Inherits From:
- * <Jx.Listener>
- */
-Jx.TabSet = Class.create();
-Jx.TabSet.prototype = {
- /**
- * Property: domObj
- * {HTMLElement} The HTML element that represents this tab set in the DOM.
- * The content areas of each tab are sized to fill the domObj.
- */
- domObj : null,
- /**
- * Property: sl
- * {Array} array of selection listeners.
- */
- sl: null,
- /**
- * Constructor: Jx.TabSet
- * Create a new instance of <Jx.TabSet> within a specific element of
- * the DOM.
- *
- * Parameters:
- * domObj - {HTMLElement} an element or id of an element to put the
- * content of the tabs into.
- */
- initialize : function(domObj) {
- this.domObj = $(domObj);
- if (!Element.hasClassName(this.domObj, 'jxTabSetContainer')) {
- Element.addClassName(this.domObj, 'jxTabSetContainer');
- }
- this.sl = [];
- },
- /**
- * Method: sizeChanged
- * Respond to the size of the container changing.
- *
- * TODO: is this needed?
- */
- sizeChanged: function() {
- this.resizeTabBox();
- },
- /**
- * Method: resizeTabBox
- * Resize the tab set content area and propogate the changes to
- * each of the tabs managed by the tab set.
- */
- resizeTabBox: function() {
-
- var parentSize = Element.getContentBoxSize(this.domObj.parentNode);
- Element.setBorderBoxSize(this.domObj, {width: parentSize.width, height: parentSize.height});
- // this is a bullshit hack for IE. We need to set the tab content height
- // for IE when the tabs are in a snap panel, otherwise the tab content
- // doesn't collapse with the panel and no scrollbars appear. This only
- // affects the height. In fact, setting the width breaks tab placement
-
- for (var i=0; i<this.domObj.childNodes.length; i++) {
- // don't try to set the height on a text node
- if (this.domObj.childNodes[i].nodeType == 3) {
- continue;
- }
- Element.setBorderBoxSize(this.domObj.childNodes[i], {height: parentSize.height});
- if (this.domObj.childNodes[i].resize) {
- this.domObj.childNodes[i].resize({forceResize: true});
- }
- }
- },
-
- /**
- * Method: add
- * Add one or more <Jx.Tab>s to the TabSet.
- *
- * Parameters:
- * tab - {<Jx.Tab>} an instance of <Jx.Tab> to add to the tab set. More
- * than one tab can be added by passing extra parameters to this method.
- */
- add : function() {
- for (var i=0; i<arguments.length; i++) {
- var tab = arguments[i];
- tab.addSelectionListener(this);
- this.domObj.appendChild(tab.content);
- if (!this.activeTab) {
- this.setActiveTab(tab);
- }
- }
- },
- /**
- * Method: remove
- * Remove a tab from the TabSet.
- *
- * Parameters:
- * tab - {<Jx.Tab>} the tab to remove.
- *
- * TODO: Implement remove for Jx.TabSet
- */
- remove : function(tab) {},
- /**
- * Method: setActiveTab
- * Set the active tab to the one passed to this method
- *
- * Parameters:
- * tab - {<Jx.Tab>} the tab to make active.
- */
- setActiveTab: function(tab) {
- if (this.activeTab) {
- Element.removeClassName(this.activeTab.domObj, 'tabActive');
- Element.removeClassName(this.activeTab.content, 'tabContentActive');
- }
- this.activeTab = tab;
- Element.addClassName(this.activeTab.domObj, 'tabActive');
- Element.addClassName(this.activeTab.content, 'tabContentActive');
- if (this.activeTab.content.resize) {
- this.activeTab.content.resize({forceResize: true});
- }
- },
- /**
- * Method: selectionChanged
- * Handle selection changing on the tabs themselves and activate the
- * appropriate tab in response.
- *
- * Parameters:
- * tab - {<Jx.Tab>} the tab to make active.
- */
- selectionChanged: function(tab) {
- this.setActiveTab(tab);
- this.processEvent(this.sl, 'selectionChanged', tab);
- },
- /**
- * Method: addSelectionListener
- * Add a selection listener
- *
- * Parameters:
- * obj - {Object} the selection listener to add
- */
- addSelectionListener: function(obj) { this.addListener(this.sl, obj); },
- /**
- * Method: removeSelectionListener
- * Remove a selection listener
- *
- * Parameters:
- * obj - {Object} the selection listener to remove
- */
- removeSelectionListener: function(obj) { this.removeListener(this.sl, obj); }
-};
-Object.extend(Jx.TabSet.prototype, Jx.Listener.prototype);
-
-/**
- * Class: Jx.Tab
- * A single tab in a tab set. A tab has a label (displayed in the tab) and a
- * content area that is displayed when the tab is active. A tab has to be
- * added to both a <Jx.TabSet> (for the content) and <Jx.Toolbar> (for the
- * actual tab itself) in order to be useful. Alternately, you can use
- * a <Jx.TabBox> which combines both into a single control at the cost of
- * some flexibility in layout options.
- *
- * A tab is a <Jx.ContentLoader> and you can specify the initial content of
- * the tab using any of the methods supported by
- * <Jx.ContentLoader::loadContent>. You can acccess the actual DOM element
- * that contains the content (if you want to dynamically insert content
- * for instance) via the <Jx.Tab::content> property.
- *
- * (code)
- * var tab1 = new Jx.Tab('tab 1', {contentID: 'content1'});
- * (end)
- *
- * Inherits From:
- * <Jx.Listener>, <Jx.ContentLoader>
- */
-Jx.Tab = Class.create();
-Jx.Tab.prototype = {
- /**
- * Property: domObj
- * {HTMLElement} The button that is used to activate the tab.
- */
- domObj: null,
- /**
- * Property: content
- * {HTMLElement} The content area that is displayed when the tab is active.
- */
- content: null,
- /**
- * Property: name
- * {String} the name of the tab is also the label.
- */
- name: null,
- /**
- * Property: sl
- * {Array} an array of selection listeners.
- */
- sl: null,
- /**
- * Constructor: Jx.Tab
- * Create a new instance of Jx.Tab.
- *
- * Parameters:
- * name - {String} the name (and label) of the tab.
- * options - {Object} an object containing options that are used
- * to control the appearance of the tab. See
- * <Jx.ContentLoader::loadContent> and <Jx.Layout::Jx.Layout> for
- * valid options.
- */
- initialize : function(name, options) {
- this.sl = [];
- options = options || {};
- if (!options.label) {
- options.label = name;
- }
- this.name = name;
- this.content = document.createElement('div');
- this.content.className = 'tabContent';
- this.loadContent(this.content, options);
- var a = new Jx.Action(this.clicked.bind(this));
- var b = new Jx.Button(a, options);
- this.domObj = b.domA;
- // rename the element from jxButton to jxTab
- // Element.removeClassName(this.domObj, 'jxButton');
- Element.addClassName(this.domObj, 'jxTab');
- new Jx.Layout(this.content, options);
- //this.content.resize = this.resize.bind(this);
- },
- /**
- * Method: clicked
- * Handle the tab being clicked by generating a selectionChanged
- * event.
- */
- clicked: function() {
- this.processEvent(this.sl, 'selectionChanged', this);
- this.domObj.childNodes[0].blur();
- },
- /**
- * Method: addSelectionListener
- * Add a selection listener
- *
- * Parameters:
- * obj - {Object} the selection listener to add
- */
- addSelectionListener: function(obj) { this.addListener(this.sl, obj); },
- /**
- * Method: removeSelectionListener
- * Remove a selection listener
- *
- * Parameters:
- * obj - {Object} the selection listener to remove
- */
- removeSelectionListener: function(obj) { this.removeListener(this.sl, obj); }
-};
-Object.extend(Jx.Tab.prototype, Jx.Listener.prototype);
-Object.extend(Jx.Tab.prototype, Jx.ContentLoader.prototype);
-
-/**
- * Class: Jx.TabBox
- * A convenience class to handle the common case of a single toolbar
- * directly attached to the content area of the tabs. It manages both a
- * <Jx.Toolbar> and a <Jx.TabSet> so that you don't have to. If you are using
- * a TabBox, then tabs only have to be added to the TabBox rather than to
- * both a <Jx.TabSet> and a <Jx.Toolbar>.
- *
- * (code)
- * var tabBox = new Jx.TabBox('subTabArea', 'top');
- *
- * var tab1 = new Jx.Tab('Tab 1', {contentID: 'content4'});
- * var tab2 = new Jx.Tab('Tab 2', {contentID: 'content5'});
- *
- * tabBox.add(tab1, tab2);
- * (end)
- *
- * Inherits From:
- * <Jx.Listener>
- */
-Jx.TabBox = Class.create();
-Jx.TabBox.prototype = {
- /**
- * Property: tabBar
- * {<Jx.Toolbar>} the toolbar for this tab box.
- */
- tabBar: null,
- /**
- * Property: tabSet
- * {<Jx.TabSet>} the tab set for this tab box.
- */
- tabSet: null,
- /**
- * Constructor: Jx.TabBox
- */
- initialize : function(domObj, position) {
- var parent = $(domObj);
- position = position || 'top';
- var tabBarDiv = document.createElement('div');
- parent.appendChild(tabBarDiv);
- this.tabBar = new Jx.Toolbar(tabBarDiv, position);
- this.tabSet = new Jx.TabSet(parent);
- switch (position) {
- case 'top':
- Element.addClassName(parent, 'jxTabBoxTop');
- break;
- case 'bottom':
- Element.addClassName(parent, 'jxTabBoxBottom');
- break;
- case 'left':
- Element.addClassName(parent, 'jxTabBoxLeft');
- Element.addClassName(tabBarDiv, 'verticalToolbar');
- break;
- case 'right':
- Element.addClassName(parent, 'jxTabBoxRight');
- Element.addClassName(tabBarDiv, 'verticalToolbar');
- break;
- }
- this.sl = [];
- },
- /**
- * Method: sizeChanged
- * Handle the size of the content area of the tab box changing.
- *
- * TODO: is this needed?
- */
- sizeChanged: function() { this.tabSet.sizeChanged(); },
-
- /**
- * Method: add
- * Add one or more <Jx.Tab>s to the TabBox.
- *
- * Parameters:
- * tab - {<Jx.Tab>} an instance of <Jx.Tab> to add to the tab box. More
- * than one tab can be added by passing extra parameters to this method.
- * Unlike <Jx.TabSet>, tabs do not have to be added to a separate
- * <Jx.Toolbar>.
- */
- add : function() {
- this.tabBar.add.apply(this.tabBar, arguments);
- this.tabSet.add.apply(this.tabSet, arguments);
- },
- /**
- * Method: remove
- * Remove a tab from the TabSet.
- *
- * Parameters:
- * tab - {<Jx.Tab>} the tab to remove.
- *
- * TODO: implement remove for Jx.TabBox.
- */
- remove : function(tab) { /* TODO */ }
-};
-Object.extend(Jx.TabBox.prototype, Jx.Listener.prototype);
-/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Toolbar
- *
- * Purpose:
- * Implementation of a javascript Toolbar for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-/**
- * import stylesheets
- */
-Jx.addStyleSheet('toolbar/toolbar.css');
-Jx.addStyleSheet('button/button.css');
-
-/**
- * Class: Jx.Toolbar
- *
- * A toolbar is a container object that contains other objects such as
- * buttons. The toolbar organizes the objects it contains automatically,
- * wrapping them as necessary. Multiple toolbars may be placed within
- * the same containing object.
- *
- * Jx.Toolbar includes CSS classes for styling the appearance of a
- * toolbar to be similar to traditional desktop application toolbars.
- *
- * There is one special object, Jx.ToolbarSeparator, that provides
- * a visual separation between objects in a toolbar.
- *
- * The following example shows how to create a Jx.Toolbar instance and place two objects in it.
- * (code)
- * //myToolbarContainer is the id of a <div> in the HTML page.
- * function myFunction() {}
- * var myToolbar = new Jx.Toolbar('myToolbarContainer');
- *
- * var myAction = new Jx.Action(myFunction):
- * var myButton = new Jx.Button(myAction);
- *
- * var myElement = document.createElement('select');
- *
- * myToolbar.add(myButton, new Jx.ToolbarSeparator(), myElement);
- * (end)
- *
- * While a toolbar is generally a *dumb* container, it serves a special purpose
- * for menus by providing some infrastructure so that menus can behave
- * properly.
- *
- * In general, almost anything can be placed in a Toolbar, and mixed with
- * anything else.
- */
-Jx.Toolbar = Class.create();
-Jx.Toolbar.prototype = {
- /**
- * Property: items
- * {Array} an array of the things in the toolbar.
- */
- items : null,
- /**
- * Property: domObj
- * {HTMLElement} the HTML element that the toolbar lives in
- */
- domObj : null,
- /**
- * Property: isActive
- * When a toolbar contains <Jx.Menu> instances, they want to know
- * if any menu in the toolbar is active and this is how they
- * find out.
- */
- isActive : false,
- /**
- * Constructor: Jx.Toolbar
- * Create a new instance of Jx.Toolbar.
- *
- * Parameters:
- * domObj - {HTMLElement} object reference or id to place the toolbar in.
- * position - one of 'top', 'right', 'bottom', or 'left', indicates how
- * the toolbar is being placed in the page and may influence the behaviour
- * of items in the toolbar that open sub panels, they will tend to open
- * them towards the center of the page. Default is top.
- */
- initialize : function(domObj, position) {
- var parent = $(domObj);
- this.domObj = document.createElement('ul');
- Element.addClassName(this.domObj,'jxToolbar');
-
- if (!Element.hasClassName(parent, 'jxToolbarContainer')) {
- Element.addClassName(parent, 'jxToolbarContainer');
- parent.appendChild(this.domObj);
- var clearer = document.createElement('div');
- clearer.className = 'jxClearer';
- parent.appendChild(clearer);
- } else {
- parent.insertBefore(this.domObj, parent.lastChild);
- }
- switch (position) {
- case 'top':
- Element.addClassName(parent, 'jxBarTop');
- break;
- case 'right':
- Element.addClassName(parent, 'jxBarRight');
- break;
- case 'bottom':
- Element.addClassName(parent, 'jxBarBottom');
- break;
- case 'left':
- Element.addClassName(parent, 'jxBarLeft');
- break;
- default:
- Element.addClassName(parent, 'jxBarTop');
- }
- this.deactivateWatcher = this.deactivate.bindAsEventListener(this);
-
- },
- /**
- * Method: add
- * Add an item to the toolbar. If the item being added is a Jx component
- * with a domObj property, the domObj is added. If the item being added
- * is an LI element, then it is given a CSS class of *jxToolItem*.
- * Otherwise, the thing is wrapped in a <Jx.ToolbarItem>.
- *
- * Parameters:
- * thing - {Object} the thing to add. More than one thing can be added
- * by passing multiple arguments.
- */
- add : function( ) {
- for (var i=0; i<arguments.length; i++) {
- var thing = arguments[i];
- thing.toolbar = this;
- if (thing.domObj) {
- thing = thing.domObj;
- }
- if (thing.tagName == 'LI') {
- if (!Element.hasClassName(thing, 'jxToolItem')) {
- Element.addClassName(thing, 'jxToolItem');
- }
- this.domObj.appendChild(thing);
- } else {
- var item = new Jx.ToolbarItem(thing);
- this.domObj.appendChild(item.domObj);
- }
- }
- },
- /**
- * Method: deactivate
- * Deactivate the Toolbar (when it is acting as a menu bar).
- */
- deactivate: function() {
- for (var i=0; i<this.items.length; i++) {
- this.items[i].hide();
- }
- this.setActive(false);
- },
- /**
- * Method: isActive
- * Indicate if the toolbar is currently active (as a menu bar)
- *
- * Returns:
- * {Boolean}
- */
- isActive: function() {
- return this.isActive;
- },
- /**
- * Method: setActive
- * Set the active state of the toolbar (for menus)
- *
- * Parameters:
- * b - {Boolean} the new state
- */
- setActive: function(b) {
- this.isActive = b;
- if (this.isActive) {
- Event.observe(document, 'click', this.deactivateWatcher);
- } else {
- Event.stopObserving(document, 'click', this.deactivateWatcher);
- }
- },
- /**
- * Method: setVisibleItem
- * For menus, they want to know which menu is currently open.
- *
- * Parameters:
- * obj - {<Jx.Menu>} the menu that just opened.
- */
- setVisibleItem: function(obj) {
- if (this.visibleItem && this.visibleItem.hide && this.visibleItem != obj) {
- this.visibleItem.hide();
- }
- this.visibleItem = obj;
- if (this.isActive()) {
- this.visibleItem.show();
- }
- }
-};
-
-/**
- * Class: Jx.ToolbarItem
- * A helper class to provide a container for something to go into
- * a <Jx.Toolbar>.
- */
-Jx.ToolbarItem = Class.create();
-Jx.ToolbarItem.prototype = {
- /**
- * Property: domObj
- * {HTMLElement} an element to contain the thing to be placed in the
- * toolbar.
- */
- domObj: null,
- /**
- * Constructor: Jx.ToolbarItem
- * Create a new instance of Jx.ToolbarItem.
- *
- * Parameters:
- * jxThing - {Object} the thing to be contained.
- */
- initialize : function( jxThing ) {
- this.al = [];
- this.domObj = document.createElement('li');
- this.domObj.className = 'jxToolItem';
- if (jxThing) {
- if (jxThing.domObj) {
- this.domObj.appendChild(jxThing.domObj);
- if (jxThing instanceof Jx.Tab) {
- // this.domObj.className = 'jxTabItem';
- Element.addClassName(this.domObj, 'jxTabItem');
- }
- } else {
- this.domObj.appendChild(jxThing);
- if (Element.hasClassName(jxThing, 'jxTab')) {
- // this.domObj.className = 'jxTabItem';
- Element.addClassName(this.domObj, 'jxTabItem');
- }
- }
- }
- }
-};
-
-/**
- * Class: Jx.ToolbarSeparator
- * A helper class that represents a visual separator in a <Jx.Toolbar>
- */
-Jx.ToolbarSeparator = Class.create();
-Jx.ToolbarSeparator.prototype = {
- /**
- * Property: domObj
- * {HTMLElement} The DOM element that goes in the <Jx.Toolbar>
- */
- domObj: null,
- /**
- * Constructor: Jx.ToolbarSeparator
- * Create a new Jx.ToolbarSeparator
- */
- initialize: function() {
- this.domObj = document.createElement('li');
- this.domObj.className = 'jxToolItem';
- this.domSpan = document.createElement('span');
- this.domSpan.className = 'separator';
- this.domObj.appendChild(this.domSpan);
- }
-};
-
-/**
- * $Id: jx_combined.js 776 2008-08-22 18:46:25Z madair $
- *
- * Title: Jx.Tree
- *
- * Purpose:
- * Implementation of a javascript Tree for Jx.
- *
- * Author:
- * Paul Spencer (pspencer at dmsolutions.ca)
- *
- * Copyright:
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-Jx.addStyleSheet('tree/tree.css');
-Jx.addStyleSheet('tree/tree_ie.css', true);
-
-/**
- * Class: Jx.TreeItem
- * An item in a tree. An item is a leaf node that has no children.
- *
- * Jx.TreeItem supports selection listeners. When an item in the tree
- * is selected by the user, listeners are called by invoking the
- * selectionChanged method on the listener and passing the tree item
- * object that was selected. The application is responsible for
- * changing the style of the selected item in the tree and for
- * tracking selection if that is important.
- *
- * When the selection changes, the mouse event that triggered the
- * selection change is passed to the listener as a lastEvent
- * member of the tree item object. You can use this to determine
- * if the item was clicked, double-clicked, right clicked etc.
- *
- * Inherits From:
- * <Jx.Listener>
- */
-Jx.TreeItem = Class.create();
-Jx.TreeItem.prototype = {
- /**
- * Property: data
- * {Object} arbitrary data associated with the TreeItem
- */
- data : null,
- /**
- * Property: domObj
- * {HTMLElement} a reference to the HTML element that is the TreeItem
- * in the DOM
- */
- domObj : null,
- /**
- * Property: parent
- * {Object} the folder or tree that this item belongs to
- */
- parent : null,
- /**
- * Property: currentClassName
- * {String} the current CSS class name for this TreeItem.
- *
- * TODO: Property currentClassName
- * This property does not appear to be used?
- */
- currentClassName : null,
- /**
- * Property: onClick
- * {Function} callback function to invoke with the TreeItem is clicked
- */
- onClick : null,
- /**
- * Property: sl
- * {Array} an array of selection listeners
- */
- sl : null,
- /**
- * Property: enabled
- * {Boolean} is the TreeItem enabled or not?
- */
- enabled : null,
- /**
- * Property: contextMenu
- *
- * {<Jx.ContextMenu>} an optional context menu for the TreeItem
- */
- contextMenu : null,
- /**
- * Constructor: Jx.TreeItem
- * Create a new instance of Jx.TreeItem with the associated options
- *
- * Parameters:
- * options - {Object} an object containing the below optional
- * attributes that control how the TreeItem functions.
- *
- * Options:
- * label - {String} the label to display for the TreeItem
- * data - {Object} any arbitrary data to be associated with the TreeItem
- * contextMenu - {<Jx.ContextMenu>} the context menu to trigger if there
- * is a right click on the node
- * imgNode - {String} URL to an image to use for the node of this
- * TreeItem. Not sure if this should ever be set.
- * imgIcon - {String} URL to an image to use as the icon next to the
- * label of this TreeItem
- * enabled - {Boolean} the initial state of the TreeItem. If the
- * TreeItem is not enabled, it cannot be clicked.
- */
- initialize : function( options ) {
- this.initializeItem(options);
- },
- /**
- * Method: initializeItem
- * internal method to initialize the TreeItem.
- *
- * Parameters:
- * options - See <Jx.TreeItem::Jx.TreeItem>
- */
- initializeItem: function(options) {
- options = options || {};
- this.sl = [];
- var label = options.label || 'new node';
- this.data = options.data || null;
- this.contextMenu = options.contextMenu || null;
-
- this.imgNode = options.imgNode || Jx.baseURL + 'images/tree_none.png';
- this.imgIcon = options.imgIcon || Jx.baseURL + 'images/tree_page.png';
-
- this.domObj = document.createElement('li');
- this.domObj.className = 'jxTreeNode';
- this.currentClassName = 'jxTreeNode';
-
- var elm = document.createElement('img');
- elm.className = 'jxTreeNodeImage';
- //elm.src = this.imgNode;
- Jx.addToImgQueue({domElement: elm, src: this.imgNode});
- this.domObj.appendChild(elm);
-
- elm = document.createElement('img');
- elm.className = 'jxTreeNodeIcon';
- //elm.src = this.imgIcon;
- Jx.addToImgQueue({domElement: elm, src: this.imgIcon});
- this.domObj.appendChild(elm);
-
- elm = document.createElement('a');
- elm.href = 'javascript:void(0)';
- elm.onclick = this.selected.bindAsEventListener(this);
- elm.ondblclick = this.selected.bindAsEventListener(this);
- elm.oncontextmenu = this.showMenu.bindAsEventListener(this);
- elm.innerHTML = label;
- this.domObj.appendChild(elm);
-
- //this.update(false);
- //TODO: this could cause a memory leak in remove
- this.domObj.jxTreeItem = this;
- this.domObj.childNodes[2].jxTreeItem = this;
-
- this.onClick = options.onClick || null;
- this.enabled = typeof options.enabled != 'undefined' ? options.enabled : true;
- if (this.enabled) {
- Element.removeClassName(this.domObj, 'jxDisabled');
- } else {
- Element.addClassName(this.domObj, 'jxDisabled');
- }
- var clearer = document.createElement('span');
- clearer.className = 'jxClearer';
- this.domObj.appendChild(clearer);
- },
- /**
- * Method: finalize
- * Clean up the TreeItem and remove all DOM references
- */
- finalize: function() { this.finalizeItem(); },
- /**
- * Method: finalizeItem
- * Clean up the TreeItem and remove all DOM references
- */
- finalizeItem: function() {
- if (!this.domObj) {
- return;
- }
- this.domObj.childNodes[2].onclick = null;
- this.domObj.childNodes[2].ondblclick = null;
- this.domObj.childNodes[2].oncontextmenu = null;
- this.contextMenu = null;
- this.onClick = null;
- for (var i=this.sl.length; i>=0; i--) {
- this.removeSelectionListener(this.sl[i]);
- }
- this.parent = null;
- this.domObj.jxTreeItem = null;
- this.domObj = null;
- },
- /**
- * Method: clone
- * Create a clone of the TreeItem
- *
- * Returns:
- * {<Jx.TreeItem>} a copy of the TreeItem
- */
- clone : function() {
- var options = { label : this.domObj.childNodes[2].innerHTML,
- data : this.data,
- onClick : this.onClick,
- imgNode : this.imgNode,
- imgIcon : this.imgIcon
- };
- var item = new Jx.TreeItem(options);
- return item;
- },
- /**
- * Method: update
- * Update the CSS of the TreeItem's DOM element in case it has changed
- * position
- *
- * Parameters:
- * shouldDescend - {Boolean} propagate changes to child nodes?
- */
- update : function(shouldDescend) {
- var isLast = (arguments.length > 1) ? arguments[1] :
- (this.parent && this.parent.isLastNode(this));
- if (isLast) {
- Element.removeClassName(this.domObj, 'jxTreeNode');
- Element.addClassName(this.domObj, 'jxTreeNodeLast');
- } else {
- Element.removeClassName(this.domObj, 'jxTreeNodeLast');
- Element.addClassName(this.domObj, 'jxTreeNode');
- }
- },
- /**
- * Method: selected
- * Called when the DOM element for the TreeItem is clicked, the
- * node is selected.
- *
- * Parameters:
- * e - {Event} the DOM event
- */
- selected : function(e) {
- this.lastEvent = e?e:event;
- this.processEvent(this.sl,'selectionChanged',this);
- },
- /**
- * Method: showMenu
- * Called when the DOM element for the TreeItem is right-clicked. The
- * node is selected and the context menu displayed (if there is one).
- *
- * Parameters:
- * e - {Event} the DOM event
- */
- showMenu: function(e) {
- this.lastEvent = e?e:event;
- this.processEvent(this.sl,'selectionChanged',this);
- if (this.contextMenu) {
- this.contextMenu.show(this.lastEvent);
- }
- Event.stop(e);
- },
- /**
- * Method: addSelectionListener
- * Add a selection listener.
- *
- * Parameters:
- * obj - {Object} the object to add as a selection listener
- */
- addSelectionListener: function(obj){this.addListener(this.sl, obj);},
- /**
- * Method: removeSelectionListener
- * Remove a selection listener.
- *
- * Parameters:
- * obj - {Object} the object to remove as a selection listener
- */
- removeSelectionListener: function(obj) {this.removeListener(this.sl, obj);},
- /**
- * Method: getName
- * Get the label associated with a TreeItem
- *
- * Returns:
- * {String} the name
- */
- getName : function() { return this.domObj.childNodes[2].innerHTML; },
- /**
- * Method: setName
- * Set the label of a TreeItem
- *
- * Parameters:
- * name - {String} the new label
- */
- setName : function(name) { this.domObj.childNodes[2].innerHTML = name; },
- /**
- * Method: propertyChanged
- * A property of an object has changed, synchronize the state of the
- * TreeItem with the state of the object
- *
- * Parameters:
- * obj - {Object} the object whose state has changed
- */
- propertyChanged : function(obj) {
- this.enabled = obj.isEnabled();
- if (this.enabled) {
- Element.removeClassName(this.domObj, 'jxDisabled');
- } else {
- Element.addClassName(this.domObj, 'jxDisabled');
- }
- }
-};
-Object.extend(Jx.TreeItem.prototype, Jx.Listener.prototype);
-
-/**
- * Class: Jx.TreeFolder
- *
- * A Jx.TreeFolder is an item in a tree that can contain other items. It is
- * expandable and collapsible.
- *
- * Inherits From:
- * <Jx.TreeItem>
- */
-Jx.TreeFolder = Class.create();
-Object.extend(Jx.TreeFolder.prototype, Jx.TreeItem.prototype);
-Object.extend(Jx.TreeFolder.prototype, {
- /**
- * Property: subDomObj
- * {HTMLElement} an HTML container for the things inside the folder
- */
- subDomObj : null,
- /**
- * Property: nodes
- * {Array} an array of references to the javascript objects that are
- * children of this folder
- */
- nodes : null,
- /**
- * Property: isOpen
- * {Boolean} is the folder open or not?
- */
- isOpen : false,
- /**
- * Property: dl
- * {Array} disclosure listeners
- */
- dl : null,
- /**
- * Constructor: Jx.TreeFolder
- * Create a new instance of Jx.TreeFolder
- *
- * Parameters:
- * options - {Object} an object containing any of the options of a
- * <Jx.TreeItem> (see <Jx.TreeItem::Jx.TreeItem>) plus the following
- * optional attributes that control how the TreeFolder functions.
- *
- * Options:
- * imgTreePlus - {String} a URL to an image for opening the folder
- * imgTreeMinus - {String} a URL to an image for closing the folder
- * imgTreeFolder - {String} a URL to an image to represent the folder
- * when it is closed
- * imgTreeFolderOpen - {String} a URL to an image to represent the folder
- * when it is open
- */
- initialize : function( options ) {
- this.initializeFolder(options);
- },
- /**
- * Method: initializeFolder
- * Internal method for initializing a folder.
- *
- * Parameters:
- * options - {Object} see <Jx.TreeFolder::Jx.TreeFolder> for options.
- */
- initializeFolder : function(options) {
- options = options || {};
- this.initializeItem(options);
-
- this.imgTreePlus = options.imgTreePlus || Jx.baseURL + 'images/tree_plus.png';
- this.imgTreeMinus = options.imgTreeMinus || Jx.baseURL + 'images/tree_minus.png';
-
- this.imgTreeFolder = options.imgTreeFolder || Jx.baseURL + 'images/tree_folder.png';
- this.imgTreeFolderOpen = options.imgTreeFolderOpen || Jx.baseURL + 'images/tree_folder_open.png';
-
- //console.log('imgTreePlus is ' + this.imgTreePlus);
- //this.domObj.childNodes[0].src = this.imgTreePlus;
- //this.domObj.childNodes[1].src = this.imgTreeFolder;
- Jx.addToImgQueue({domElement: this.domObj.childNodes[0], src: this.imgTreePlus});
- Jx.addToImgQueue({domElement: this.domObj.childNodes[1], src: this.imgTreeFolder});
-
- this.domObj.childNodes[0].onclick = this.clicked.bindAsEventListener(this);
-
- this.nodes = [];
- this.subDomObj = document.createElement('ul');
- this.domObj.appendChild(this.subDomObj);
- this.subDomObj.className = 'jxTree';
- this.isOpen = options.isOpen || false;
- this.dl = [];
- if (this.isOpen) {
- this.expand();
- } else {
- this.collapse();
- }
- //this.makeDroppable();
- },
- /**
- * Method: finalize
- * Clean up a TreeFolder.
- */
- finalize: function() {
- this.finalizeFolder();
- this.finalizeItem();
- this.subDomObj = null;
- },
- /**
- * Method: finalizeFolder
- * Internal method to clean up folder-related stuff.
- */
- finalizeFolder: function() {
- this.domObj.childNodes[0].onclick = null;
- for (var i=this.nodes.length-1; i>=0; i--) {
- this.nodes[i].finalize();
- if (this.nodes[i].domObj) this.subDomObj.removeChild(this.nodes[i].domObj);
- this.nodes.pop();
- }
- for (var i=this.dl.length-1; i>=0; i--) {
- this.removeDisclosureListener(this.dl[i]);
- }
- },
- /*
- makeDroppable : function() {
- if (!document.Jx.TreeCurrentTimeout) document.Jx.TreeCurrentTimeout = null;
- Droppables.add(this.domObj.childNodes[2], {
- greedy : true,
- onHover : function(draggable, droppable, overlap) {
- var dropped = droppable.parentNode.jxTreeItem;
- if (document.Jx.TreeCurrentTimeout &&
- document.currentDroppable != droppable) {
- window.clearTimeout(document.Jx.TreeCurrentTimeout);
- document.Jx.TreeCurrentTimeout = null;
- }
- if (!document.Jx.TreeCurrentTimeout &&
- dropped.nodes &&
- !dropped.isOpen)
- {
- document.Jx.TreeCurrentTimeout = window.setTimeout(dropped.expand.bind(dropped), 700);
- }
-
- if (!document.currentHighlight != droppable) {
- if (droppable == draggable)
- {
- Droppables.remove(droppable);
- }
- if (document.currentDroppable &&
- document.currentDroppable != droppable) {
- Element.removeClassName(document.currentDroppable,
- 'jxTreeDropzone');
- }
-
- Element.addClassName(droppable, 'jxTreeDropzone');
- document.currentDroppable = droppable;
- }
- },
- onDrop : function(draggable, droppable) {
- var dragged = draggable.jxTreeItem;
- var dropped = droppable.parentNode.jxTreeItem;
-
- Element.removeClassName(droppable,
- 'jxTreeDropzone');
- if (dropped.nodes) {
- dragged.parent.remove(dragged);
- dropped.append(dragged);
- dropped.expand();
- } else if (dropped.parent != null) {
- dragged.parent.remove(dragged);
- dropped.parent.insert(dragged,dropped);
- }
- }
- });
- },
- */
- /**
- * Method: clone
- * Create a clone of the TreeFolder
- *
- * Returns:
- * {<Jx.TreeFolder>} a copy of the TreeFolder
- */
- clone : function() {
- var options = { label : this.domObj.childNodes[2].innerHTML,
- data : this.data,
- onClick : this.onClick,
- imgTreePlus : this.imgTreePlus,
- imgTreeMinus : this.imgTreeMinus,
- imgTreeFolder : this.imgTreeFolder,
- imgTreeFolderOpen : this.imgTreeFolderOpen
- };
- var node = new Jx.TreeFolder(options);
- for (var i=0;i<this.nodes.length;i++) {
- node.append(this.nodes[i].clone());
- }
- return node;
- },
- /**
- * Method: isLastNode
- * Indicates if a node is the last thing in the folder.
- *
- * Parameters:
- * node - {Jx.TreeItem} the node to check
- *
- * Returns:
- *
- * {Boolean}
- */
- isLastNode : function(node) {
- if (this.nodes.length == 0) {
- return false;
- } else {
- return this.nodes[this.nodes.length-1] == node;
- }
- },
- /**
- * Method: update
- * Update the CSS of the TreeFolder's DOM element in case it has changed
- * position.
- *
- * Parameters:
- * shouldDescend - {Boolean} propagate changes to child nodes?
- */
- update : function(bDescend) {
- /* avoid update if not attached to tree yet */
- if (!this.parent) return;
- var bLast = false;
- if (arguments.length > 1) {
- bLast = arguments[1];
- } else {
- bLast = (this.parent && this.parent.isLastNode(this));
- }
-
- if (bLast) {
- this.domObj.className = 'jxTreeNodeLast';
- this.subDomObj.className = 'jxTree';
- } else {
- this.domObj.className = 'jxTreeNode';
- this.subDomObj.className = 'jxTree jxTreeNest';
- }
-
- if (this.isOpen) {
- //this.domObj.childNodes[0].src = this.imgTreeMinus;
- //this.domObj.childNodes[1].src = this.imgTreeFolderOpen;
- Jx.addToImgQueue({domElement: this.domObj.childNodes[0], src: this.imgTreeMinus});
- Jx.addToImgQueue({domElement: this.domObj.childNodes[1], src: this.imgTreeFolderOpen});
- } else {
- //this.domObj.childNodes[0].src = this.imgTreePlus;
- //this.domObj.childNodes[1].src = this.imgTreeFolder;
- Jx.addToImgQueue({domElement: this.domObj.childNodes[0], src: this.imgTreePlus});
- Jx.addToImgQueue({domElement: this.domObj.childNodes[1], src: this.imgTreeFolder});
- }
-
- if (this.nodes && bDescend) {
- //this.nodes.each(function(n){n.update(true);});
- for(var i=0; i<this.nodes.length; i++) {
- this.nodes[i].update(false, i==this.nodes.length-1);
- }
- }
- },
- /**
- * Method: append
- * append a node at the end of the sub-tree
- *
- * Parameters:
- * node - {Object} the node to append.
- */
- append : function( node ) {
- node.parent = this;
- this.nodes.push(node);
- this.subDomObj.appendChild( node.domObj );
- this.update(true);
- },
- /**
- * Method: insert
- * insert a node after refNode. If refNode is null, insert at beginning
- *
- * Parameters:
- * node - {Object} the node to insert
- * refNode - {Object} the node to insert before
- */
- insert : function( node, refNode ) {
- node.parent = this;
- //if refNode is not supplied, insert at the beginning.
- if (!refNode) {
- this.nodes.unshift(node);
- //sanity check to make sure there is actually something there
- if (this.subDomObj.childNodes.length ==0) {
- this.subDomObj.appendChild(node.domObj);
- } else {
- this.subDomObj.insertBefore(node.domObj, this.subDomObj.childNodes[0]);
- }
- } else {
- //walk all nodes looking for the ref node. Track if it actually
- //happens so we can append if it fails.
- var b = false;
- for(var i=0;i<this.nodes.length;i++) {
- if (this.nodes[i] == refNode) {
- //increment to append after ref node. If this pushes us
- //past the end, it'll get appended below anyway
- i = i + 1;
- if (i < this.nodes.length) {
- this.nodes.splice(i, 0, node);
- this.subDomObj.insertBefore(node.domObj, this.subDomObj.childNodes[i]);
- b = true;
- break;
- }
- }
- }
- //if the node wasn't inserted, it is because refNode didn't exist
- //and so the fallback is to just append the node.
- if (!b) {
- this.nodes.push(node);
- this.subDomObj.appendChild(node.domObj);
- }
- }
- this.update(true);
- //if (this.parent)
- // this.parent.update(true);
- },
- /**
- * Method: remove
- * remove the specified node from the tree
- *
- * Parameters:
- * node - {Object} the node to remove
- */
- remove : function(node) {
- node.parent = null;
- for(var i=0;i<this.nodes.length;i++) {
- if (this.nodes[i] == node) {
- this.nodes.splice(i, 1);
- this.subDomObj.removeChild(this.subDomObj.childNodes[i]);
- break;
- }
- }
- this.update(true);
- //if (this.parent)
- // this.parent.update(true);
- },
- /**
- * Method: replace
- * Replace a node with another node
- *
- * Parameters:
- * newNode - {Object} the node to put into the tree
- * refNode - {Object} the node to replace
- *
- * Returns:
- * {Boolean} true if the replacement was successful.
- */
- replace: function( newNode, refNode ) {
- //walk all nodes looking for the ref node.
- var b = false;
- for(var i=0;i<this.nodes.length;i++) {
- if (this.nodes[i] == refNode) {
- if (i < this.nodes.length) {
- newNode.parent = this;
- this.nodes.splice(i, 1, newNode);
- this.subDomObj.replaceChild(newNode.domObj, refNode.domObj);
- return true;
- }
- }
- }
- return false;
- },
-
- /**
- * Method: clicked
- * handle the user clicking on this folder by expanding or
- * collapsing it.
- *
- * Parameters:
- * e - {Event} the event object
- */
- clicked : function(e) {
- e = e?e:event;
- if (this.isOpen) {
- this.collapse();
- } else {
- this.expand();
- }
- },
- /**
- * Method: expand
- * Expands the folder
- */
- expand : function() {
- this.isOpen = true;
- this.subDomObj.style.display = 'block';
- this.update(true);
- this.processEvent(this.dl, 'disclosed', this);
- },
- /**
- * Method: collapse
- * Collapses the folder
- */
- collapse : function() {
- this.isOpen = false;
- this.subDomObj.style.display = 'none';
- this.update(true);
- this.processEvent(this.dl, 'disclosed', this);
- },
- /**
- * Method: addDisclosureListener
- * Add a disclosure (when the folder is opened) listener
- *
- * Parameters:
- * obj - {Object} a discloser listener to add
- */
- addDisclosureListener: function(obj){this.addListener(this.dl, obj);},
- /**
- * Method: removeDisclosureListener
- * Remove a disclosure listener
- *
- * Parameters:
- * obj - {Object} a discloser listener to remove
- */
- removeDisclosureListener: function(obj) {this.removeListener(this.dl, obj);},
- /**
- * Method: findChild
- * Get a reference to a child node by recursively searching the tree
- *
- * Parameters:
- * path - {Array} an array of labels of nodes to search for
- *
- * Returns:
- * {Object} the node or null if the path was not found
- */
- findChild : function(path) {
- //path is empty - we are asking for this node
- if (path.length == 0)
- return this;
-
- //path has only one thing in it - looking for something in this folder
- if (path.length == 1)
- {
- for (var i=0; i<this.nodes.length; i++)
- {
- if (this.nodes[i].getName() == path[0])
- return this.nodes[i];
- }
- return null;
- }
- //path has more than one thing in it, find a folder and descend into it
- var childName = path.shift();
- for (var i=0; i<this.nodes.length; i++)
- {
- if (this.nodes[i].getName() == childName && this.nodes[i].findChild)
- return this.nodes[i].findChild(path);
- }
- return null;
- }
-});
-
-/**
- * Class: Jx.Tree
- * Jx.Tree displays hierarchical data in a tree structure of folders and nodes.
- *
- * Inherits From:
- * <Jx.TreeFolder>
- */
-Jx.Tree = Class.create();
-Object.extend( Jx.Tree.prototype, Jx.TreeFolder.prototype );
-Object.extend( Jx.Tree.prototype, {
- /**
- * Constructor: Jx.Tree
- * Create a new instance of Jx.Tree
- *
- * Parameters:
- * id - {String} the id of the DOM element to create the tree inside.
- */
- initialize : function( id ) {
- this.subDomObj = document.createElement('ul');
- this.subDomObj.className = 'jxTreeRoot';
- $(id).appendChild(this.subDomObj);
- this.nodes = [];
- this.dl = [];
- this.isOpen = true;
- },
- /**
- * Method: finalize
- * Clean up a Jx.Tree instance
- */
- finalize: function() {
- this.clear();
- this.subDomObj.parentNode.removeChild(this.subDomObj);
- },
- /**
- * Method: clear
- * Clear the tree of all child nodes
- */
- clear: function() {
- for (var i=this.nodes.length-1; i>=0; i--) {
- this.subDomObj.removeChild(this.nodes[i].domObj);
- this.nodes[i].finalize();
- this.nodes.pop();
- }
- },
- /**
- * Method: update
- * Update the CSS of the Tree's DOM element in case it has changed
- * position
- *
- * Parameters:
- * shouldDescend - {Boolean} propagate changes to child nodes?
- */
- update: function(shouldDescend) {
- var bLast = true;
- if (this.subDomObj)
- {
- if (bLast) {
- Element.removeClassName(this.subDomObj, 'jxTreeNest');
- } else {
- Element.addClassName(this.subDomObj, 'jxTreeNest');
- }
- }
- if (this.nodes && shouldDescend) {
- this.nodes.each(function(n){n.update(false);});
- }
- },
- /**
- * Method: append
- * Append a node at the end of the sub-tree
- *
- * Parameters:
- * node - {Object} the node to append.
- */
- append: function( node ) {
- node.parent = this;
- this.nodes.push(node);
- this.subDomObj.appendChild( node.domObj );
- this.update(true);
- }
-});/**
- * this file is to be loaded/included after all other Jx files
- *
- * Copyright © 2008, DM Solutions Group Inc.
- */
-/******************************************************************************
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *****************************************************************************/
-
-if (Jx.COMBINED_CSS) {
- //console.log('Jx.COMBINED_CSS');
- document.write('<link type="text/css" rel="stylesheet" href="'+Jx.baseURL+'lib/jx_combined.css" />\n');
-} else {
- //console.log('no Jx.COMBINED_CSS');
- for (var styleSheet in Jx.importRules) {
- var url = Jx.baseURL+styleSheet;
- document.write('<link type="text/css" rel="stylesheet" href="'+url+'" />\n');
- }
- document.write('<!--[if IE]>');
- for (var styleSheet in Jx.importRulesIE) {
- var url = Jx.baseURL+styleSheet;
- document.write('<link type="text/css" rel="stylesheet" href="'+url+'" />\n');
- }
- document.write('<![endif]-->\n');
-}
\ No newline at end of file
Deleted: sandbox/jx2/jx/lib/jx_compressed.js
===================================================================
--- sandbox/jx2/jx/lib/jx_compressed.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/jx/lib/jx_compressed.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,639 +0,0 @@
-
-var Prototype={Version:'1.5.0',BrowserFeatures:{XPath:!!document.evaluate},ScriptFragment:'(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',emptyFunction:function(){},K:function(x){return x}}
-var Class={create:function(){return function(){this.initialize.apply(this,arguments);}}}
-var Abstract=new Object();Object.extend=function(destination,source){for(var property in source){destination[property]=source[property];}
-return destination;}
-Object.extend(Object,{inspect:function(object){try{if(object===undefined)return'undefined';if(object===null)return'null';return object.inspect?object.inspect():object.toString();}catch(e){if(e instanceof RangeError)return'...';throw e;}},keys:function(object){var keys=[];for(var property in object)
-keys.push(property);return keys;},values:function(object){var values=[];for(var property in object)
-values.push(object[property]);return values;},clone:function(object){return Object.extend({},object);}});Function.prototype.bind=function(){var __method=this,args=$A(arguments),object=args.shift();return function(){return __method.apply(object,args.concat($A(arguments)));}}
-Function.prototype.bindAsEventListener=function(object){var __method=this,args=$A(arguments),object=args.shift();return function(event){return __method.apply(object,[(event||window.event)].concat(args).concat($A(arguments)));}}
-Object.extend(Number.prototype,{toColorPart:function(){var digits=this.toString(16);if(this<16)return'0'+digits;return digits;},succ:function(){return this+1;},times:function(iterator){$R(0,this,true).each(iterator);return this;}});var Try={these:function(){var returnValue;for(var i=0,length=arguments.length;i<length;i++){var lambda=arguments[i];try{returnValue=lambda();break;}catch(e){}}
-return returnValue;}}
-var PeriodicalExecuter=Class.create();PeriodicalExecuter.prototype={initialize:function(callback,frequency){this.callback=callback;this.frequency=frequency;this.currentlyExecuting=false;this.registerCallback();},registerCallback:function(){this.timer=setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},stop:function(){if(!this.timer)return;clearInterval(this.timer);this.timer=null;},onTimerEvent:function(){if(!this.currentlyExecuting){try{this.currentlyExecuting=true;this.callback(this);}finally{this.currentlyExecuting=false;}}}}
-String.interpret=function(value){return value==null?'':String(value);}
-Object.extend(String.prototype,{gsub:function(pattern,replacement){var result='',source=this,match;replacement=arguments.callee.prepareReplacement(replacement);while(source.length>0){if(match=source.match(pattern)){result+=source.slice(0,match.index);result+=String.interpret(replacement(match));source=source.slice(match.index+match[0].length);}else{result+=source,source='';}}
-return result;},sub:function(pattern,replacement,count){replacement=this.gsub.prepareReplacement(replacement);count=count===undefined?1:count;return this.gsub(pattern,function(match){if(--count<0)return match[0];return replacement(match);});},scan:function(pattern,iterator){this.gsub(pattern,iterator);return this;},truncate:function(length,truncation){length=length||30;truncation=truncation===undefined?'...':truncation;return this.length>length?this.slice(0,length-truncation.length)+truncation:this;},strip:function(){return this.replace(/^\s+/,'').replace(/\s+$/,'');},stripTags:function(){return this.replace(/<\/?[^>]+>/gi,'');},stripScripts:function(){return this.replace(new RegExp(Prototype.ScriptFragment,'img'),'');},extractScripts:function(){var matchAll=new RegExp(Prototype.ScriptFragment,'img');var matchOne=new RegExp(Prototype.ScriptFragment,'im');return(this.match(matchAll)||[]).map(function(scriptTag){return(scriptTag.match(matchOne)||['',''])[1];});},evalScripts:function(){return this.extractScripts().map(function(script){return eval(script)});},escapeHTML:function(){var div=document.createElement('div');var text=document.createTextNode(this);div.appendChild(text);return div.innerHTML;},unescapeHTML:function(){var div=document.createElement('div');div.innerHTML=this.stripTags();return div.childNodes[0]?(div.childNodes.length>1?$A(div.childNodes).inject('',function(memo,node){return memo+node.nodeValue}):div.childNodes[0].nodeValue):'';},toQueryParams:function(separator){var match=this.strip().match(/([^?#]*)(#.*)?$/);if(!match)return{};return match[1].split(separator||'&').inject({},function(hash,pair){if((pair=pair.split('='))[0]){var name=decodeURIComponent(pair[0]);var value=pair[1]?decodeURIComponent(pair[1]):undefined;if(hash[name]!==undefined){if(hash[name].constructor!=Array)
-hash[name]=[hash[name]];if(value)hash[name].push(value);}
-else hash[name]=value;}
-return hash;});},toArray:function(){return this.split('');},succ:function(){return this.slice(0,this.length-1)+
-String.fromCharCode(this.charCodeAt(this.length-1)+1);},camelize:function(){var parts=this.split('-'),len=parts.length;if(len==1)return parts[0];var camelized=this.charAt(0)=='-'?parts[0].charAt(0).toUpperCase()+parts[0].substring(1):parts[0];for(var i=1;i<len;i++)
-camelized+=parts[i].charAt(0).toUpperCase()+parts[i].substring(1);return camelized;},capitalize:function(){return this.charAt(0).toUpperCase()+this.substring(1).toLowerCase();},underscore:function(){return this.gsub(/::/,'/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();},dasherize:function(){return this.gsub(/_/,'-');},inspect:function(useDoubleQuotes){var escapedString=this.replace(/\\/g,'\\\\');if(useDoubleQuotes)
-return'"'+escapedString.replace(/"/g,'\\"')+'"';else
-return"'"+escapedString.replace(/'/g,'\\\'')+"'";}});String.prototype.gsub.prepareReplacement=function(replacement){if(typeof replacement=='function')return replacement;var template=new Template(replacement);return function(match){return template.evaluate(match)};}
-String.prototype.parseQuery=String.prototype.toQueryParams;var Template=Class.create();Template.Pattern=/(^|.|\r|\n)(#\{(.*?)\})/;Template.prototype={initialize:function(template,pattern){this.template=template.toString();this.pattern=pattern||Template.Pattern;},evaluate:function(object){return this.template.gsub(this.pattern,function(match){var before=match[1];if(before=='\\')return match[2];return before+String.interpret(object[match[3]]);});}}
-var $break=new Object();var $continue=new Object();var Enumerable={each:function(iterator){var index=0;try{this._each(function(value){try{iterator(value,index++);}catch(e){if(e!=$continue)throw e;}});}catch(e){if(e!=$break)throw e;}
-return this;},eachSlice:function(number,iterator){var index=-number,slices=[],array=this.toArray();while((index+=number)<array.length)
-slices.push(array.slice(index,index+number));return slices.map(iterator);},all:function(iterator){var result=true;this.each(function(value,index){result=result&&!!(iterator||Prototype.K)(value,index);if(!result)throw $break;});return result;},any:function(iterator){var result=false;this.each(function(value,index){if(result=!!(iterator||Prototype.K)(value,index))
-throw $break;});return result;},collect:function(iterator){var results=[];this.each(function(value,index){results.push((iterator||Prototype.K)(value,index));});return results;},detect:function(iterator){var result;this.each(function(value,index){if(iterator(value,index)){result=value;throw $break;}});return result;},findAll:function(iterator){var results=[];this.each(function(value,index){if(iterator(value,index))
-results.push(value);});return results;},grep:function(pattern,iterator){var results=[];this.each(function(value,index){var stringValue=value.toString();if(stringValue.match(pattern))
-results.push((iterator||Prototype.K)(value,index));})
-return results;},include:function(object){var found=false;this.each(function(value){if(value==object){found=true;throw $break;}});return found;},inGroupsOf:function(number,fillWith){fillWith=fillWith===undefined?null:fillWith;return this.eachSlice(number,function(slice){while(slice.length<number)slice.push(fillWith);return slice;});},inject:function(memo,iterator){this.each(function(value,index){memo=iterator(memo,value,index);});return memo;},invoke:function(method){var args=$A(arguments).slice(1);return this.map(function(value){return value[method].apply(value,args);});},max:function(iterator){var result;this.each(function(value,index){value=(iterator||Prototype.K)(value,index);if(result==undefined||value>=result)
-result=value;});return result;},min:function(iterator){var result;this.each(function(value,index){value=(iterator||Prototype.K)(value,index);if(result==undefined||value<result)
-result=value;});return result;},partition:function(iterator){var trues=[],falses=[];this.each(function(value,index){((iterator||Prototype.K)(value,index)?trues:falses).push(value);});return[trues,falses];},pluck:function(property){var results=[];this.each(function(value,index){results.push(value[property]);});return results;},reject:function(iterator){var results=[];this.each(function(value,index){if(!iterator(value,index))
-results.push(value);});return results;},sortBy:function(iterator){return this.map(function(value,index){return{value:value,criteria:iterator(value,index)};}).sort(function(left,right){var a=left.criteria,b=right.criteria;return a<b?-1:a>b?1:0;}).pluck('value');},toArray:function(){return this.map();},zip:function(){var iterator=Prototype.K,args=$A(arguments);if(typeof args.last()=='function')
-iterator=args.pop();var collections=[this].concat(args).map($A);return this.map(function(value,index){return iterator(collections.pluck(index));});},size:function(){return this.toArray().length;},inspect:function(){return'#<Enumerable:'+this.toArray().inspect()+'>';}}
-Object.extend(Enumerable,{map:Enumerable.collect,find:Enumerable.detect,select:Enumerable.findAll,member:Enumerable.include,entries:Enumerable.toArray});var $A=Array.from=function(iterable){if(!iterable)return[];if(iterable.toArray){return iterable.toArray();}else{var results=[];for(var i=0,length=iterable.length;i<length;i++)
-results.push(iterable[i]);return results;}}
-Object.extend(Array.prototype,Enumerable);if(!Array.prototype._reverse)
-Array.prototype._reverse=Array.prototype.reverse;Object.extend(Array.prototype,{_each:function(iterator){for(var i=0,length=this.length;i<length;i++)
-iterator(this[i]);},clear:function(){this.length=0;return this;},first:function(){return this[0];},last:function(){return this[this.length-1];},compact:function(){return this.select(function(value){return value!=null;});},flatten:function(){return this.inject([],function(array,value){return array.concat(value&&value.constructor==Array?value.flatten():[value]);});},without:function(){var values=$A(arguments);return this.select(function(value){return!values.include(value);});},indexOf:function(object){for(var i=0,length=this.length;i<length;i++)
-if(this[i]==object)return i;return-1;},reverse:function(inline){return(inline!==false?this:this.toArray())._reverse();},reduce:function(){return this.length>1?this:this[0];},uniq:function(){return this.inject([],function(array,value){return array.include(value)?array:array.concat([value]);});},clone:function(){return[].concat(this);},size:function(){return this.length;},inspect:function(){return'['+this.map(Object.inspect).join(', ')+']';}});Array.prototype.toArray=Array.prototype.clone;function $w(string){string=string.strip();return string?string.split(/\s+/):[];}
-if(window.opera){Array.prototype.concat=function(){var array=[];for(var i=0,length=this.length;i<length;i++)array.push(this[i]);for(var i=0,length=arguments.length;i<length;i++){if(arguments[i].constructor==Array){for(var j=0,arrayLength=arguments[i].length;j<arrayLength;j++)
-array.push(arguments[i][j]);}else{array.push(arguments[i]);}}
-return array;}}
-var Hash=function(obj){Object.extend(this,obj||{});};Object.extend(Hash,{toQueryString:function(obj){var parts=[];this.prototype._each.call(obj,function(pair){if(!pair.key)return;if(pair.value&&pair.value.constructor==Array){var values=pair.value.compact();if(values.length<2)pair.value=values.reduce();else{key=encodeURIComponent(pair.key);values.each(function(value){value=value!=undefined?encodeURIComponent(value):'';parts.push(key+'='+encodeURIComponent(value));});return;}}
-if(pair.value==undefined)pair[1]='';parts.push(pair.map(encodeURIComponent).join('='));});return parts.join('&');}});Object.extend(Hash.prototype,Enumerable);Object.extend(Hash.prototype,{_each:function(iterator){for(var key in this){var value=this[key];if(value&&value==Hash.prototype[key])continue;var pair=[key,value];pair.key=key;pair.value=value;iterator(pair);}},keys:function(){return this.pluck('key');},values:function(){return this.pluck('value');},merge:function(hash){return $H(hash).inject(this,function(mergedHash,pair){mergedHash[pair.key]=pair.value;return mergedHash;});},remove:function(){var result;for(var i=0,length=arguments.length;i<length;i++){var value=this[arguments[i]];if(value!==undefined){if(result===undefined)result=value;else{if(result.constructor!=Array)result=[result];result.push(value)}}
-delete this[arguments[i]];}
-return result;},toQueryString:function(){return Hash.toQueryString(this);},inspect:function(){return'#<Hash:{'+this.map(function(pair){return pair.map(Object.inspect).join(': ');}).join(', ')+'}>';}});function $H(object){if(object&&object.constructor==Hash)return object;return new Hash(object);};ObjectRange=Class.create();Object.extend(ObjectRange.prototype,Enumerable);Object.extend(ObjectRange.prototype,{initialize:function(start,end,exclusive){this.start=start;this.end=end;this.exclusive=exclusive;},_each:function(iterator){var value=this.start;while(this.include(value)){iterator(value);value=value.succ();}},include:function(value){if(value<this.start)
-return false;if(this.exclusive)
-return value<this.end;return value<=this.end;}});var $R=function(start,end,exclusive){return new ObjectRange(start,end,exclusive);}
-var Ajax={getTransport:function(){return Try.these(function(){return new XMLHttpRequest()},function(){return new ActiveXObject('Msxml2.XMLHTTP')},function(){return new ActiveXObject('Microsoft.XMLHTTP')})||false;},activeRequestCount:0}
-Ajax.Responders={responders:[],_each:function(iterator){this.responders._each(iterator);},register:function(responder){if(!this.include(responder))
-this.responders.push(responder);},unregister:function(responder){this.responders=this.responders.without(responder);},dispatch:function(callback,request,transport,json){this.each(function(responder){if(typeof responder[callback]=='function'){try{responder[callback].apply(responder,[request,transport,json]);}catch(e){}}});}};Object.extend(Ajax.Responders,Enumerable);Ajax.Responders.register({onCreate:function(){Ajax.activeRequestCount++;},onComplete:function(){Ajax.activeRequestCount--;}});Ajax.Base=function(){};Ajax.Base.prototype={setOptions:function(options){this.options={method:'post',asynchronous:true,contentType:'application/x-www-form-urlencoded',encoding:'UTF-8',parameters:''}
-Object.extend(this.options,options||{});this.options.method=this.options.method.toLowerCase();if(typeof this.options.parameters=='string')
-this.options.parameters=this.options.parameters.toQueryParams();}}
-Ajax.Request=Class.create();Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];Ajax.Request.prototype=Object.extend(new Ajax.Base(),{_complete:false,initialize:function(url,options){this.transport=Ajax.getTransport();this.setOptions(options);this.request(url);},request:function(url){this.url=url;this.method=this.options.method;var params=this.options.parameters;if(!['get','post'].include(this.method)){params['_method']=this.method;this.method='post';}
-params=Hash.toQueryString(params);if(params&&/Konqueror|Safari|KHTML/.test(navigator.userAgent))params+='&_='
-if(this.method=='get'&¶ms)
-this.url+=(this.url.indexOf('?')>-1?'&':'?')+params;try{Ajax.Responders.dispatch('onCreate',this,this.transport);this.transport.open(this.method.toUpperCase(),this.url,this.options.asynchronous);if(this.options.asynchronous)
-setTimeout(function(){this.respondToReadyState(1)}.bind(this),10);this.transport.onreadystatechange=this.onStateChange.bind(this);this.setRequestHeaders();var body=this.method=='post'?(this.options.postBody||params):null;this.transport.send(body);if(!this.options.asynchronous&&this.transport.overrideMimeType)
-this.onStateChange();}
-catch(e){this.dispatchException(e);}},onStateChange:function(){var readyState=this.transport.readyState;if(readyState>1&&!((readyState==4)&&this._complete))
-this.respondToReadyState(this.transport.readyState);},setRequestHeaders:function(){var headers={'X-Requested-With':'XMLHttpRequest','X-Prototype-Version':Prototype.Version,'Accept':'text/javascript, text/html, application/xml, text/xml, */*'};if(this.method=='post'){headers['Content-type']=this.options.contentType+
-(this.options.encoding?'; charset='+this.options.encoding:'');if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005)
-headers['Connection']='close';}
-if(typeof this.options.requestHeaders=='object'){var extras=this.options.requestHeaders;if(typeof extras.push=='function')
-for(var i=0,length=extras.length;i<length;i+=2)
-headers[extras[i]]=extras[i+1];else
-$H(extras).each(function(pair){headers[pair.key]=pair.value});}
-for(var name in headers)
-this.transport.setRequestHeader(name,headers[name]);},success:function(){return!this.transport.status||(this.transport.status>=200&&this.transport.status<300);},respondToReadyState:function(readyState){var state=Ajax.Request.Events[readyState];var transport=this.transport,json=this.evalJSON();if(state=='Complete'){try{this._complete=true;(this.options['on'+this.transport.status]||this.options['on'+(this.success()?'Success':'Failure')]||Prototype.emptyFunction)(transport,json);}catch(e){this.dispatchException(e);}
-if((this.getHeader('Content-type')||'text/javascript').strip().match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i))
-this.evalResponse();}
-try{(this.options['on'+state]||Prototype.emptyFunction)(transport,json);Ajax.Responders.dispatch('on'+state,this,transport,json);}catch(e){this.dispatchException(e);}
-if(state=='Complete'){this.transport.onreadystatechange=Prototype.emptyFunction;}},getHeader:function(name){try{return this.transport.getResponseHeader(name);}catch(e){return null}},evalJSON:function(){try{var json=this.getHeader('X-JSON');return json?eval('('+json+')'):null;}catch(e){return null}},evalResponse:function(){try{return eval(this.transport.responseText);}catch(e){this.dispatchException(e);}},dispatchException:function(exception){(this.options.onException||Prototype.emptyFunction)(this,exception);Ajax.Responders.dispatch('onException',this,exception);}});Ajax.Updater=Class.create();Object.extend(Object.extend(Ajax.Updater.prototype,Ajax.Request.prototype),{initialize:function(container,url,options){this.container={success:(container.success||container),failure:(container.failure||(container.success?null:container))}
-this.transport=Ajax.getTransport();this.setOptions(options);var onComplete=this.options.onComplete||Prototype.emptyFunction;this.options.onComplete=(function(transport,param){this.updateContent();onComplete(transport,param);}).bind(this);this.request(url);},updateContent:function(){var receiver=this.container[this.success()?'success':'failure'];var response=this.transport.responseText;if(!this.options.evalScripts)response=response.stripScripts();if(receiver=$(receiver)){if(this.options.insertion)
-new this.options.insertion(receiver,response);else
-receiver.update(response);}
-if(this.success()){if(this.onComplete)
-setTimeout(this.onComplete.bind(this),10);}}});Ajax.PeriodicalUpdater=Class.create();Ajax.PeriodicalUpdater.prototype=Object.extend(new Ajax.Base(),{initialize:function(container,url,options){this.setOptions(options);this.onComplete=this.options.onComplete;this.frequency=(this.options.frequency||2);this.decay=(this.options.decay||1);this.updater={};this.container=container;this.url=url;this.start();},start:function(){this.options.onComplete=this.updateComplete.bind(this);this.onTimerEvent();},stop:function(){this.updater.options.onComplete=undefined;clearTimeout(this.timer);(this.onComplete||Prototype.emptyFunction).apply(this,arguments);},updateComplete:function(request){if(this.options.decay){this.decay=(request.responseText==this.lastText?this.decay*this.options.decay:1);this.lastText=request.responseText;}
-this.timer=setTimeout(this.onTimerEvent.bind(this),this.decay*this.frequency*1000);},onTimerEvent:function(){this.updater=new Ajax.Updater(this.container,this.url,this.options);}});function $(element){if(arguments.length>1){for(var i=0,elements=[],length=arguments.length;i<length;i++)
-elements.push($(arguments[i]));return elements;}
-if(typeof element=='string')
-element=document.getElementById(element);return Element.extend(element);}
-if(Prototype.BrowserFeatures.XPath){document._getElementsByXPath=function(expression,parentElement){var results=[];var query=document.evaluate(expression,$(parentElement)||document,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null);for(var i=0,length=query.snapshotLength;i<length;i++)
-results.push(query.snapshotItem(i));return results;};}
-document.getElementsByClassName=function(className,parentElement){if(Prototype.BrowserFeatures.XPath){var q=".//*[contains(concat(' ', @class, ' '), ' "+className+" ')]";return document._getElementsByXPath(q,parentElement);}else{var children=($(parentElement)||document.body).getElementsByTagName('*');var elements=[],child;for(var i=0,length=children.length;i<length;i++){child=children[i];if(Element.hasClassName(child,className))
-elements.push(Element.extend(child));}
-return elements;}};if(!window.Element)
-var Element=new Object();Element.extend=function(element){if(!element||_nativeExtensions||element.nodeType==3)return element;if(!element._extended&&element.tagName&&element!=window){var methods=Object.clone(Element.Methods),cache=Element.extend.cache;if(element.tagName=='FORM')
-Object.extend(methods,Form.Methods);if(['INPUT','TEXTAREA','SELECT'].include(element.tagName))
-Object.extend(methods,Form.Element.Methods);Object.extend(methods,Element.Methods.Simulated);for(var property in methods){var value=methods[property];if(typeof value=='function'&&!(property in element))
-element[property]=cache.findOrStore(value);}}
-element._extended=true;return element;};Element.extend.cache={findOrStore:function(value){return this[value]=this[value]||function(){return value.apply(null,[this].concat($A(arguments)));}}};Element.Methods={visible:function(element){return $(element).style.display!='none';},toggle:function(element){element=$(element);Element[Element.visible(element)?'hide':'show'](element);return element;},hide:function(element){$(element).style.display='none';return element;},show:function(element){$(element).style.display='';return element;},remove:function(element){element=$(element);element.parentNode.removeChild(element);return element;},update:function(element,html){html=typeof html=='undefined'?'':html.toString();$(element).innerHTML=html.stripScripts();setTimeout(function(){html.evalScripts()},10);return element;},replace:function(element,html){element=$(element);html=typeof html=='undefined'?'':html.toString();if(element.outerHTML){element.outerHTML=html.stripScripts();}else{var range=element.ownerDocument.createRange();range.selectNodeContents(element);element.parentNode.replaceChild(range.createContextualFragment(html.stripScripts()),element);}
-setTimeout(function(){html.evalScripts()},10);return element;},inspect:function(element){element=$(element);var result='<'+element.tagName.toLowerCase();$H({'id':'id','className':'class'}).each(function(pair){var property=pair.first(),attribute=pair.last();var value=(element[property]||'').toString();if(value)result+=' '+attribute+'='+value.inspect(true);});return result+'>';},recursivelyCollect:function(element,property){element=$(element);var elements=[];while(element=element[property])
-if(element.nodeType==1)
-elements.push(Element.extend(element));return elements;},ancestors:function(element){return $(element).recursivelyCollect('parentNode');},descendants:function(element){return $A($(element).getElementsByTagName('*'));},immediateDescendants:function(element){if(!(element=$(element).firstChild))return[];while(element&&element.nodeType!=1)element=element.nextSibling;if(element)return[element].concat($(element).nextSiblings());return[];},previousSiblings:function(element){return $(element).recursivelyCollect('previousSibling');},nextSiblings:function(element){return $(element).recursivelyCollect('nextSibling');},siblings:function(element){element=$(element);return element.previousSiblings().reverse().concat(element.nextSiblings());},match:function(element,selector){if(typeof selector=='string')
-selector=new Selector(selector);return selector.match($(element));},up:function(element,expression,index){return Selector.findElement($(element).ancestors(),expression,index);},down:function(element,expression,index){return Selector.findElement($(element).descendants(),expression,index);},previous:function(element,expression,index){return Selector.findElement($(element).previousSiblings(),expression,index);},next:function(element,expression,index){return Selector.findElement($(element).nextSiblings(),expression,index);},getElementsBySelector:function(){var args=$A(arguments),element=$(args.shift());return Selector.findChildElements(element,args);},getElementsByClassName:function(element,className){return document.getElementsByClassName(className,element);},readAttribute:function(element,name){element=$(element);if(document.all&&!window.opera){var t=Element._attributeTranslations;if(t.values[name])return t.values[name](element,name);if(t.names[name])name=t.names[name];var attribute=element.attributes[name];if(attribute)return attribute.nodeValue;}
-return element.getAttribute(name);},getHeight:function(element){return $(element).getDimensions().height;},getWidth:function(element){return $(element).getDimensions().width;},classNames:function(element){return new Element.ClassNames(element);},hasClassName:function(element,className){if(!(element=$(element)))return;var elementClassName=element.className;if(elementClassName.length==0)return false;if(elementClassName==className||elementClassName.match(new RegExp("(^|\\s)"+className+"(\\s|$)")))
-return true;return false;},addClassName:function(element,className){if(!(element=$(element)))return;Element.classNames(element).add(className);return element;},removeClassName:function(element,className){if(!(element=$(element)))return;Element.classNames(element).remove(className);return element;},toggleClassName:function(element,className){if(!(element=$(element)))return;Element.classNames(element)[element.hasClassName(className)?'remove':'add'](className);return element;},observe:function(){Event.observe.apply(Event,arguments);return $A(arguments).first();},stopObserving:function(){Event.stopObserving.apply(Event,arguments);return $A(arguments).first();},cleanWhitespace:function(element){element=$(element);var node=element.firstChild;while(node){var nextNode=node.nextSibling;if(node.nodeType==3&&!/\S/.test(node.nodeValue))
-element.removeChild(node);node=nextNode;}
-return element;},empty:function(element){return $(element).innerHTML.match(/^\s*$/);},descendantOf:function(element,ancestor){element=$(element),ancestor=$(ancestor);while(element=element.parentNode)
-if(element==ancestor)return true;return false;},scrollTo:function(element){element=$(element);var pos=Position.cumulativeOffset(element);window.scrollTo(pos[0],pos[1]);return element;},getStyle:function(element,style){element=$(element);if(['float','cssFloat'].include(style))
-style=(typeof element.style.styleFloat!='undefined'?'styleFloat':'cssFloat');style=style.camelize();var value=element.style[style];if(!value){if(document.defaultView&&document.defaultView.getComputedStyle){var css=document.defaultView.getComputedStyle(element,null);value=css?css[style]:null;}else if(element.currentStyle){value=element.currentStyle[style];}}
-if((value=='auto')&&['width','height'].include(style)&&(element.getStyle('display')!='none'))
-value=element['offset'+style.capitalize()]+'px';if(window.opera&&['left','top','right','bottom'].include(style))
-if(Element.getStyle(element,'position')=='static')value='auto';if(style=='opacity'){if(value)return parseFloat(value);if(value=(element.getStyle('filter')||'').match(/alpha\(opacity=(.*)\)/))
-if(value[1])return parseFloat(value[1])/100;return 1.0;}
-return value=='auto'?null:value;},setStyle:function(element,style){element=$(element);for(var name in style){var value=style[name];if(name=='opacity'){if(value==1){value=(/Gecko/.test(navigator.userAgent)&&!/Konqueror|Safari|KHTML/.test(navigator.userAgent))?0.999999:1.0;if(/MSIE/.test(navigator.userAgent)&&!window.opera)
-element.style.filter=element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');}else if(value===''){if(/MSIE/.test(navigator.userAgent)&&!window.opera)
-element.style.filter=element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'');}else{if(value<0.00001)value=0;if(/MSIE/.test(navigator.userAgent)&&!window.opera)
-element.style.filter=element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'')+'alpha(opacity='+value*100+')';}}else if(['float','cssFloat'].include(name))name=(typeof element.style.styleFloat!='undefined')?'styleFloat':'cssFloat';element.style[name.camelize()]=value;}
-return element;},getDimensions:function(element){element=$(element);var display=$(element).getStyle('display');if(display!='none'&&display!=null)
-return{width:element.offsetWidth,height:element.offsetHeight};var els=element.style;var originalVisibility=els.visibility;var originalPosition=els.position;var originalDisplay=els.display;els.visibility='hidden';els.position='absolute';els.display='block';var originalWidth=element.clientWidth;var originalHeight=element.clientHeight;els.display=originalDisplay;els.position=originalPosition;els.visibility=originalVisibility;return{width:originalWidth,height:originalHeight};},makePositioned:function(element){element=$(element);var pos=Element.getStyle(element,'position');if(pos=='static'||!pos){element._madePositioned=true;element.style.position='relative';if(window.opera){element.style.top=0;element.style.left=0;}}
-return element;},undoPositioned:function(element){element=$(element);if(element._madePositioned){element._madePositioned=undefined;element.style.position=element.style.top=element.style.left=element.style.bottom=element.style.right='';}
-return element;},makeClipping:function(element){element=$(element);if(element._overflow)return element;element._overflow=element.style.overflow||'auto';if((Element.getStyle(element,'overflow')||'visible')!='hidden')
-element.style.overflow='hidden';return element;},undoClipping:function(element){element=$(element);if(!element._overflow)return element;element.style.overflow=element._overflow=='auto'?'':element._overflow;element._overflow=null;return element;}};Object.extend(Element.Methods,{childOf:Element.Methods.descendantOf});Element._attributeTranslations={};Element._attributeTranslations.names={colspan:"colSpan",rowspan:"rowSpan",valign:"vAlign",datetime:"dateTime",accesskey:"accessKey",tabindex:"tabIndex",enctype:"encType",maxlength:"maxLength",readonly:"readOnly",longdesc:"longDesc"};Element._attributeTranslations.values={_getAttr:function(element,attribute){return element.getAttribute(attribute,2);},_flag:function(element,attribute){return $(element).hasAttribute(attribute)?attribute:null;},style:function(element){return element.style.cssText.toLowerCase();},title:function(element){var node=element.getAttributeNode('title');return node.specified?node.nodeValue:null;}};Object.extend(Element._attributeTranslations.values,{href:Element._attributeTranslations.values._getAttr,src:Element._attributeTranslations.values._getAttr,disabled:Element._attributeTranslations.values._flag,checked:Element._attributeTranslations.values._flag,readonly:Element._attributeTranslations.values._flag,multiple:Element._attributeTranslations.values._flag});Element.Methods.Simulated={hasAttribute:function(element,attribute){var t=Element._attributeTranslations;attribute=t.names[attribute]||attribute;return $(element).getAttributeNode(attribute).specified;}};if(document.all&&!window.opera){Element.Methods.update=function(element,html){element=$(element);html=typeof html=='undefined'?'':html.toString();var tagName=element.tagName.toUpperCase();if(['THEAD','TBODY','TR','TD'].include(tagName)){var div=document.createElement('div');switch(tagName){case'THEAD':case'TBODY':div.innerHTML='<table><tbody>'+html.stripScripts()+'</tbody></table>';depth=2;break;case'TR':div.innerHTML='<table><tbody><tr>'+html.stripScripts()+'</tr></tbody></table>';depth=3;break;case'TD':div.innerHTML='<table><tbody><tr><td>'+html.stripScripts()+'</td></tr></tbody></table>';depth=4;}
-$A(element.childNodes).each(function(node){element.removeChild(node)});depth.times(function(){div=div.firstChild});$A(div.childNodes).each(function(node){element.appendChild(node)});}else{element.innerHTML=html.stripScripts();}
-setTimeout(function(){html.evalScripts()},10);return element;}};Object.extend(Element,Element.Methods);var _nativeExtensions=false;if(/Konqueror|Safari|KHTML/.test(navigator.userAgent))
-['','Form','Input','TextArea','Select'].each(function(tag){var className='HTML'+tag+'Element';if(window[className])return;var klass=window[className]={};klass.prototype=document.createElement(tag?tag.toLowerCase():'div').__proto__;});Element.addMethods=function(methods){Object.extend(Element.Methods,methods||{});function copy(methods,destination,onlyIfAbsent){onlyIfAbsent=onlyIfAbsent||false;var cache=Element.extend.cache;for(var property in methods){var value=methods[property];if(!onlyIfAbsent||!(property in destination))
-destination[property]=cache.findOrStore(value);}}
-if(typeof HTMLElement!='undefined'){copy(Element.Methods,HTMLElement.prototype);copy(Element.Methods.Simulated,HTMLElement.prototype,true);copy(Form.Methods,HTMLFormElement.prototype);[HTMLInputElement,HTMLTextAreaElement,HTMLSelectElement].each(function(klass){copy(Form.Element.Methods,klass.prototype);});_nativeExtensions=true;}}
-var Toggle=new Object();Toggle.display=Element.toggle;Abstract.Insertion=function(adjacency){this.adjacency=adjacency;}
-Abstract.Insertion.prototype={initialize:function(element,content){this.element=$(element);this.content=content.stripScripts();if(this.adjacency&&this.element.insertAdjacentHTML){try{this.element.insertAdjacentHTML(this.adjacency,this.content);}catch(e){var tagName=this.element.tagName.toUpperCase();if(['TBODY','TR'].include(tagName)){this.insertContent(this.contentFromAnonymousTable());}else{throw e;}}}else{this.range=this.element.ownerDocument.createRange();if(this.initializeRange)this.initializeRange();this.insertContent([this.range.createContextualFragment(this.content)]);}
-setTimeout(function(){content.evalScripts()},10);},contentFromAnonymousTable:function(){var div=document.createElement('div');div.innerHTML='<table><tbody>'+this.content+'</tbody></table>';return $A(div.childNodes[0].childNodes[0].childNodes);}}
-var Insertion=new Object();Insertion.Before=Class.create();Insertion.Before.prototype=Object.extend(new Abstract.Insertion('beforeBegin'),{initializeRange:function(){this.range.setStartBefore(this.element);},insertContent:function(fragments){fragments.each((function(fragment){this.element.parentNode.insertBefore(fragment,this.element);}).bind(this));}});Insertion.Top=Class.create();Insertion.Top.prototype=Object.extend(new Abstract.Insertion('afterBegin'),{initializeRange:function(){this.range.selectNodeContents(this.element);this.range.collapse(true);},insertContent:function(fragments){fragments.reverse(false).each((function(fragment){this.element.insertBefore(fragment,this.element.firstChild);}).bind(this));}});Insertion.Bottom=Class.create();Insertion.Bottom.prototype=Object.extend(new Abstract.Insertion('beforeEnd'),{initializeRange:function(){this.range.selectNodeContents(this.element);this.range.collapse(this.element);},insertContent:function(fragments){fragments.each((function(fragment){this.element.appendChild(fragment);}).bind(this));}});Insertion.After=Class.create();Insertion.After.prototype=Object.extend(new Abstract.Insertion('afterEnd'),{initializeRange:function(){this.range.setStartAfter(this.element);},insertContent:function(fragments){fragments.each((function(fragment){this.element.parentNode.insertBefore(fragment,this.element.nextSibling);}).bind(this));}});Element.ClassNames=Class.create();Element.ClassNames.prototype={initialize:function(element){this.element=$(element);},_each:function(iterator){this.element.className.split(/\s+/).select(function(name){return name.length>0;})._each(iterator);},set:function(className){this.element.className=className;},add:function(classNameToAdd){if(this.include(classNameToAdd))return;this.set($A(this).concat(classNameToAdd).join(' '));},remove:function(classNameToRemove){if(!this.include(classNameToRemove))return;this.set($A(this).without(classNameToRemove).join(' '));},toString:function(){return $A(this).join(' ');}};Object.extend(Element.ClassNames.prototype,Enumerable);var Selector=Class.create();Selector.prototype={initialize:function(expression){this.params={classNames:[]};this.expression=expression.toString().strip();this.parseExpression();this.compileMatcher();},parseExpression:function(){function abort(message){throw'Parse error in selector: '+message;}
-if(this.expression=='')abort('empty expression');var params=this.params,expr=this.expression,match,modifier,clause,rest;while(match=expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)){params.attributes=params.attributes||[];params.attributes.push({name:match[2],operator:match[3],value:match[4]||match[5]||''});expr=match[1];}
-if(expr=='*')return this.params.wildcard=true;while(match=expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)){modifier=match[1],clause=match[2],rest=match[3];switch(modifier){case'#':params.id=clause;break;case'.':params.classNames.push(clause);break;case'':case undefined:params.tagName=clause.toUpperCase();break;default:abort(expr.inspect());}
-expr=rest;}
-if(expr.length>0)abort(expr.inspect());},buildMatchExpression:function(){var params=this.params,conditions=[],clause;if(params.wildcard)
-conditions.push('true');if(clause=params.id)
-conditions.push('element.readAttribute("id") == '+clause.inspect());if(clause=params.tagName)
-conditions.push('element.tagName.toUpperCase() == '+clause.inspect());if((clause=params.classNames).length>0)
-for(var i=0,length=clause.length;i<length;i++)
-conditions.push('element.hasClassName('+clause[i].inspect()+')');if(clause=params.attributes){clause.each(function(attribute){var value='element.readAttribute('+attribute.name.inspect()+')';var splitValueBy=function(delimiter){return value+' && '+value+'.split('+delimiter.inspect()+')';}
-switch(attribute.operator){case'=':conditions.push(value+' == '+attribute.value.inspect());break;case'~=':conditions.push(splitValueBy(' ')+'.include('+attribute.value.inspect()+')');break;case'|=':conditions.push(splitValueBy('-')+'.first().toUpperCase() == '+attribute.value.toUpperCase().inspect());break;case'!=':conditions.push(value+' != '+attribute.value.inspect());break;case'':case undefined:conditions.push('element.hasAttribute('+attribute.name.inspect()+')');break;default:throw'Unknown operator '+attribute.operator+' in selector';}});}
-return conditions.join(' && ');},compileMatcher:function(){this.match=new Function('element','if (!element.tagName) return false; element = $(element); return '+this.buildMatchExpression());},findElements:function(scope){var element;if(element=$(this.params.id))
-if(this.match(element))
-if(!scope||Element.childOf(element,scope))
-return[element];scope=(scope||document).getElementsByTagName(this.params.tagName||'*');var results=[];for(var i=0,length=scope.length;i<length;i++)
-if(this.match(element=scope[i]))
-results.push(Element.extend(element));return results;},toString:function(){return this.expression;}}
-Object.extend(Selector,{matchElements:function(elements,expression){var selector=new Selector(expression);return elements.select(selector.match.bind(selector)).map(Element.extend);},findElement:function(elements,expression,index){if(typeof expression=='number')index=expression,expression=false;return Selector.matchElements(elements,expression||'*')[index||0];},findChildElements:function(element,expressions){return expressions.map(function(expression){return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null],function(results,expr){var selector=new Selector(expr);return results.inject([],function(elements,result){return elements.concat(selector.findElements(result||element));});});}).flatten();}});function $$(){return Selector.findChildElements(document,$A(arguments));}
-var Form={reset:function(form){$(form).reset();return form;},serializeElements:function(elements,getHash){var data=elements.inject({},function(result,element){if(!element.disabled&&element.name){var key=element.name,value=$(element).getValue();if(value!=undefined){if(result[key]){if(result[key].constructor!=Array)result[key]=[result[key]];result[key].push(value);}
-else result[key]=value;}}
-return result;});return getHash?data:Hash.toQueryString(data);}};Form.Methods={serialize:function(form,getHash){return Form.serializeElements(Form.getElements(form),getHash);},getElements:function(form){return $A($(form).getElementsByTagName('*')).inject([],function(elements,child){if(Form.Element.Serializers[child.tagName.toLowerCase()])
-elements.push(Element.extend(child));return elements;});},getInputs:function(form,typeName,name){form=$(form);var inputs=form.getElementsByTagName('input');if(!typeName&&!name)return $A(inputs).map(Element.extend);for(var i=0,matchingInputs=[],length=inputs.length;i<length;i++){var input=inputs[i];if((typeName&&input.type!=typeName)||(name&&input.name!=name))
-continue;matchingInputs.push(Element.extend(input));}
-return matchingInputs;},disable:function(form){form=$(form);form.getElements().each(function(element){element.blur();element.disabled='true';});return form;},enable:function(form){form=$(form);form.getElements().each(function(element){element.disabled='';});return form;},findFirstElement:function(form){return $(form).getElements().find(function(element){return element.type!='hidden'&&!element.disabled&&['input','select','textarea'].include(element.tagName.toLowerCase());});},focusFirstElement:function(form){form=$(form);form.findFirstElement().activate();return form;}}
-Object.extend(Form,Form.Methods);Form.Element={focus:function(element){$(element).focus();return element;},select:function(element){$(element).select();return element;}}
-Form.Element.Methods={serialize:function(element){element=$(element);if(!element.disabled&&element.name){var value=element.getValue();if(value!=undefined){var pair={};pair[element.name]=value;return Hash.toQueryString(pair);}}
-return'';},getValue:function(element){element=$(element);var method=element.tagName.toLowerCase();return Form.Element.Serializers[method](element);},clear:function(element){$(element).value='';return element;},present:function(element){return $(element).value!='';},activate:function(element){element=$(element);element.focus();if(element.select&&(element.tagName.toLowerCase()!='input'||!['button','reset','submit'].include(element.type)))
-element.select();return element;},disable:function(element){element=$(element);element.disabled=true;return element;},enable:function(element){element=$(element);element.blur();element.disabled=false;return element;}}
-Object.extend(Form.Element,Form.Element.Methods);var Field=Form.Element;var $F=Form.Element.getValue;Form.Element.Serializers={input:function(element){switch(element.type.toLowerCase()){case'checkbox':case'radio':return Form.Element.Serializers.inputSelector(element);default:return Form.Element.Serializers.textarea(element);}},inputSelector:function(element){return element.checked?element.value:null;},textarea:function(element){return element.value;},select:function(element){return this[element.type=='select-one'?'selectOne':'selectMany'](element);},selectOne:function(element){var index=element.selectedIndex;return index>=0?this.optionValue(element.options[index]):null;},selectMany:function(element){var values,length=element.length;if(!length)return null;for(var i=0,values=[];i<length;i++){var opt=element.options[i];if(opt.selected)values.push(this.optionValue(opt));}
-return values;},optionValue:function(opt){return Element.extend(opt).hasAttribute('value')?opt.value:opt.text;}}
-Abstract.TimedObserver=function(){}
-Abstract.TimedObserver.prototype={initialize:function(element,frequency,callback){this.frequency=frequency;this.element=$(element);this.callback=callback;this.lastValue=this.getValue();this.registerCallback();},registerCallback:function(){setInterval(this.onTimerEvent.bind(this),this.frequency*1000);},onTimerEvent:function(){var value=this.getValue();var changed=('string'==typeof this.lastValue&&'string'==typeof value?this.lastValue!=value:String(this.lastValue)!=String(value));if(changed){this.callback(this.element,value);this.lastValue=value;}}}
-Form.Element.Observer=Class.create();Form.Element.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{getValue:function(){return Form.Element.getValue(this.element);}});Form.Observer=Class.create();Form.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{getValue:function(){return Form.serialize(this.element);}});Abstract.EventObserver=function(){}
-Abstract.EventObserver.prototype={initialize:function(element,callback){this.element=$(element);this.callback=callback;this.lastValue=this.getValue();if(this.element.tagName.toLowerCase()=='form')
-this.registerFormCallbacks();else
-this.registerCallback(this.element);},onElementEvent:function(){var value=this.getValue();if(this.lastValue!=value){this.callback(this.element,value);this.lastValue=value;}},registerFormCallbacks:function(){Form.getElements(this.element).each(this.registerCallback.bind(this));},registerCallback:function(element){if(element.type){switch(element.type.toLowerCase()){case'checkbox':case'radio':Event.observe(element,'click',this.onElementEvent.bind(this));break;default:Event.observe(element,'change',this.onElementEvent.bind(this));break;}}}}
-Form.Element.EventObserver=Class.create();Form.Element.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{getValue:function(){return Form.Element.getValue(this.element);}});Form.EventObserver=Class.create();Form.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{getValue:function(){return Form.serialize(this.element);}});if(!window.Event){var Event=new Object();}
-Object.extend(Event,{KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,KEY_HOME:36,KEY_END:35,KEY_PAGEUP:33,KEY_PAGEDOWN:34,element:function(event){return event.target||event.srcElement;},isLeftClick:function(event){return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},pointerX:function(event){return event.pageX||(event.clientX+
-(document.documentElement.scrollLeft||document.body.scrollLeft));},pointerY:function(event){return event.pageY||(event.clientY+
-(document.documentElement.scrollTop||document.body.scrollTop));},stop:function(event){if(event.preventDefault){event.preventDefault();event.stopPropagation();}else{event.returnValue=false;event.cancelBubble=true;}},findElement:function(event,tagName){var element=Event.element(event);while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase())))
-element=element.parentNode;return element;},observers:false,_observeAndCache:function(element,name,observer,useCapture){if(!this.observers)this.observers=[];if(element.addEventListener){this.observers.push([element,name,observer,useCapture]);element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){this.observers.push([element,name,observer,useCapture]);element.attachEvent('on'+name,observer);}},unloadCache:function(){if(!Event.observers)return;for(var i=0,length=Event.observers.length;i<length;i++){Event.stopObserving.apply(this,Event.observers[i]);Event.observers[i][0]=null;}
-Event.observers=false;},observe:function(element,name,observer,useCapture){element=$(element);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent))
-name='keydown';Event._observeAndCache(element,name,observer,useCapture);},stopObserving:function(element,name,observer,useCapture){element=$(element);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent))
-name='keydown';if(element.removeEventListener){element.removeEventListener(name,observer,useCapture);}else if(element.detachEvent){try{element.detachEvent('on'+name,observer);}catch(e){}}}});if(navigator.appVersion.match(/\bMSIE\b/))
-Event.observe(window,'unload',Event.unloadCache,false);var Position={includeScrollOffsets:false,prepare:function(){this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;},realOffset:function(element){var valueT=0,valueL=0;do{valueT+=element.scrollTop||0;valueL+=element.scrollLeft||0;element=element.parentNode;}while(element);return[valueL,valueT];},cumulativeOffset:function(element){var valueT=0,valueL=0;do{valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;element=element.offsetParent;}while(element);return[valueL,valueT];},positionedOffset:function(element){var valueT=0,valueL=0;do{valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;element=element.offsetParent;if(element){if(element.tagName=='BODY')break;var p=Element.getStyle(element,'position');if(p=='relative'||p=='absolute')break;}}while(element);return[valueL,valueT];},offsetParent:function(element){if(element.offsetParent)return element.offsetParent;if(element==document.body)return element;while((element=element.parentNode)&&element!=document.body)
-if(Element.getStyle(element,'position')!='static')
-return element;return document.body;},within:function(element,x,y){if(this.includeScrollOffsets)
-return this.withinIncludingScrolloffsets(element,x,y);this.xcomp=x;this.ycomp=y;this.offset=this.cumulativeOffset(element);return(y>=this.offset[1]&&y<this.offset[1]+element.offsetHeight&&x>=this.offset[0]&&x<this.offset[0]+element.offsetWidth);},withinIncludingScrolloffsets:function(element,x,y){var offsetcache=this.realOffset(element);this.xcomp=x+offsetcache[0]-this.deltaX;this.ycomp=y+offsetcache[1]-this.deltaY;this.offset=this.cumulativeOffset(element);return(this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+element.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+element.offsetWidth);},overlap:function(mode,element){if(!mode)return 0;if(mode=='vertical')
-return((this.offset[1]+element.offsetHeight)-this.ycomp)/element.offsetHeight;if(mode=='horizontal')
-return((this.offset[0]+element.offsetWidth)-this.xcomp)/element.offsetWidth;},page:function(forElement){var valueT=0,valueL=0;var element=forElement;do{valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;if(element.offsetParent==document.body)
-if(Element.getStyle(element,'position')=='absolute')break;}while(element=element.offsetParent);element=forElement;do{if(!window.opera||element.tagName=='BODY'){valueT-=element.scrollTop||0;valueL-=element.scrollLeft||0;}}while(element=element.parentNode);return[valueL,valueT];},clone:function(source,target){var options=Object.extend({setLeft:true,setTop:true,setWidth:true,setHeight:true,offsetTop:0,offsetLeft:0},arguments[2]||{})
-source=$(source);var p=Position.page(source);target=$(target);var delta=[0,0];var parent=null;if(Element.getStyle(target,'position')=='absolute'){parent=Position.offsetParent(target);delta=Position.page(parent);}
-if(parent==document.body){delta[0]-=document.body.offsetLeft;delta[1]-=document.body.offsetTop;}
-if(options.setLeft)target.style.left=(p[0]-delta[0]+options.offsetLeft)+'px';if(options.setTop)target.style.top=(p[1]-delta[1]+options.offsetTop)+'px';if(options.setWidth)target.style.width=source.offsetWidth+'px';if(options.setHeight)target.style.height=source.offsetHeight+'px';},absolutize:function(element){element=$(element);if(element.style.position=='absolute')return;Position.prepare();var offsets=Position.positionedOffset(element);var top=offsets[1];var left=offsets[0];var width=element.clientWidth;var height=element.clientHeight;element._originalLeft=left-parseFloat(element.style.left||0);element._originalTop=top-parseFloat(element.style.top||0);element._originalWidth=element.style.width;element._originalHeight=element.style.height;element.style.position='absolute';element.style.top=top+'px';element.style.left=left+'px';element.style.width=width+'px';element.style.height=height+'px';},relativize:function(element){element=$(element);if(element.style.position=='relative')return;Position.prepare();element.style.position='relative';var top=parseFloat(element.style.top||0)-(element._originalTop||0);var left=parseFloat(element.style.left||0)-(element._originalLeft||0);element.style.top=top+'px';element.style.left=left+'px';element.style.height=element._originalHeight;element.style.width=element._originalWidth;}}
-if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){Position.cumulativeOffset=function(element){var valueT=0,valueL=0;do{valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;if(element.offsetParent==document.body)
-if(Element.getStyle(element,'position')=='absolute')break;element=element.offsetParent;}while(element);return[valueL,valueT];}}
-Element.addMethods();var Builder={NODEMAP:{AREA:'map',CAPTION:'table',COL:'table',COLGROUP:'table',LEGEND:'fieldset',OPTGROUP:'select',OPTION:'select',PARAM:'object',TBODY:'table',TD:'table',TFOOT:'table',TH:'table',THEAD:'table',TR:'table'},node:function(elementName){elementName=elementName.toUpperCase();var parentTag=this.NODEMAP[elementName]||'div';var parentElement=document.createElement(parentTag);try{parentElement.innerHTML="<"+elementName+"></"+elementName+">";}catch(e){}
-var element=parentElement.firstChild||null;if(element&&(element.tagName.toUpperCase()!=elementName))
-element=element.getElementsByTagName(elementName)[0];if(!element)element=document.createElement(elementName);if(!element)return;if(arguments[1])
-if(this._isStringOrNumber(arguments[1])||(arguments[1]instanceof Array)){this._children(element,arguments[1]);}else{var attrs=this._attributes(arguments[1]);if(attrs.length){try{parentElement.innerHTML="<"+elementName+" "+
-attrs+"></"+elementName+">";}catch(e){}
-element=parentElement.firstChild||null;if(!element){element=document.createElement(elementName);for(attr in arguments[1])
-element[attr=='class'?'className':attr]=arguments[1][attr];}
-if(element.tagName.toUpperCase()!=elementName)
-element=parentElement.getElementsByTagName(elementName)[0];}}
-if(arguments[2])
-this._children(element,arguments[2]);return element;},_text:function(text){return document.createTextNode(text);},ATTR_MAP:{'className':'class','htmlFor':'for'},_attributes:function(attributes){var attrs=[];for(attribute in attributes)
-attrs.push((attribute in this.ATTR_MAP?this.ATTR_MAP[attribute]:attribute)+'="'+attributes[attribute].toString().escapeHTML()+'"');return attrs.join(" ");},_children:function(element,children){if(typeof children=='object'){children.flatten().each(function(e){if(typeof e=='object')
-element.appendChild(e)
-else
-if(Builder._isStringOrNumber(e))
-element.appendChild(Builder._text(e));});}else
-if(Builder._isStringOrNumber(children))
-element.appendChild(Builder._text(children));},_isStringOrNumber:function(param){return(typeof param=='string'||typeof param=='number');},build:function(html){var element=this.node('div');$(element).update(html.strip());return element.down();},dump:function(scope){if(typeof scope!='object'&&typeof scope!='function')scope=window;var tags=("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY "+"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET "+"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);tags.each(function(tag){scope[tag]=function(){return Builder.node.apply(Builder,[tag].concat($A(arguments)));}});}}
-String.prototype.parseColor=function(){var color='#';if(this.slice(0,4)=='rgb('){var cols=this.slice(4,this.length-1).split(',');var i=0;do{color+=parseInt(cols[i]).toColorPart()}while(++i<3);}else{if(this.slice(0,1)=='#'){if(this.length==4)for(var i=1;i<4;i++)color+=(this.charAt(i)+this.charAt(i)).toLowerCase();if(this.length==7)color=this.toLowerCase();}}
-return(color.length==7?color:(arguments[0]||this));}
-Element.collectTextNodes=function(element){return $A($(element).childNodes).collect(function(node){return(node.nodeType==3?node.nodeValue:(node.hasChildNodes()?Element.collectTextNodes(node):''));}).flatten().join('');}
-Element.collectTextNodesIgnoreClass=function(element,className){return $A($(element).childNodes).collect(function(node){return(node.nodeType==3?node.nodeValue:((node.hasChildNodes()&&!Element.hasClassName(node,className))?Element.collectTextNodesIgnoreClass(node,className):''));}).flatten().join('');}
-Element.setContentZoom=function(element,percent){element=$(element);element.setStyle({fontSize:(percent/100)+'em'});if(navigator.appVersion.indexOf('AppleWebKit')>0)window.scrollBy(0,0);return element;}
-Element.getOpacity=function(element){return $(element).getStyle('opacity');}
-Element.setOpacity=function(element,value){return $(element).setStyle({opacity:value});}
-Element.getInlineOpacity=function(element){return $(element).style.opacity||'';}
-Element.forceRerendering=function(element){try{element=$(element);var n=document.createTextNode(' ');element.appendChild(n);element.removeChild(n);}catch(e){}};Array.prototype.call=function(){var args=arguments;this.each(function(f){f.apply(this,args)});}
-var Effect={_elementDoesNotExistError:{name:'ElementDoesNotExistError',message:'The specified DOM element does not exist, but is required for this effect to operate'},tagifyText:function(element){if(typeof Builder=='undefined')
-throw("Effect.tagifyText requires including script.aculo.us' builder.js library");var tagifyStyle='position:relative';if(/MSIE/.test(navigator.userAgent)&&!window.opera)tagifyStyle+=';zoom:1';element=$(element);$A(element.childNodes).each(function(child){if(child.nodeType==3){child.nodeValue.toArray().each(function(character){element.insertBefore(Builder.node('span',{style:tagifyStyle},character==' '?String.fromCharCode(160):character),child);});Element.remove(child);}});},multiple:function(element,effect){var elements;if(((typeof element=='object')||(typeof element=='function'))&&(element.length))
-elements=element;else
-elements=$(element).childNodes;var options=Object.extend({speed:0.1,delay:0.0},arguments[2]||{});var masterDelay=options.delay;$A(elements).each(function(element,index){new effect(element,Object.extend(options,{delay:index*options.speed+masterDelay}));});},PAIRS:{'slide':['SlideDown','SlideUp'],'blind':['BlindDown','BlindUp'],'appear':['Appear','Fade']},toggle:function(element,effect){element=$(element);effect=(effect||'appear').toLowerCase();var options=Object.extend({queue:{position:'end',scope:(element.id||'global'),limit:1}},arguments[2]||{});Effect[element.visible()?Effect.PAIRS[effect][1]:Effect.PAIRS[effect][0]](element,options);}};var Effect2=Effect;Effect.Transitions={linear:Prototype.K,sinoidal:function(pos){return(-Math.cos(pos*Math.PI)/2)+0.5;},reverse:function(pos){return 1-pos;},flicker:function(pos){return((-Math.cos(pos*Math.PI)/4)+0.75)+Math.random()/4;},wobble:function(pos){return(-Math.cos(pos*Math.PI*(9*pos))/2)+0.5;},pulse:function(pos,pulses){pulses=pulses||5;return(Math.round((pos%(1/pulses))*pulses)==0?((pos*pulses*2)-Math.floor(pos*pulses*2)):1-((pos*pulses*2)-Math.floor(pos*pulses*2)));},none:function(pos){return 0;},full:function(pos){return 1;}};Effect.ScopedQueue=Class.create();Object.extend(Object.extend(Effect.ScopedQueue.prototype,Enumerable),{initialize:function(){this.effects=[];this.interval=null;},_each:function(iterator){this.effects._each(iterator);},add:function(effect){var timestamp=new Date().getTime();var position=(typeof effect.options.queue=='string')?effect.options.queue:effect.options.queue.position;switch(position){case'front':this.effects.findAll(function(e){return e.state=='idle'}).each(function(e){e.startOn+=effect.finishOn;e.finishOn+=effect.finishOn;});break;case'with-last':timestamp=this.effects.pluck('startOn').max()||timestamp;break;case'end':timestamp=this.effects.pluck('finishOn').max()||timestamp;break;}
-effect.startOn+=timestamp;effect.finishOn+=timestamp;if(!effect.options.queue.limit||(this.effects.length<effect.options.queue.limit))
-this.effects.push(effect);if(!this.interval)
-this.interval=setInterval(this.loop.bind(this),15);},remove:function(effect){this.effects=this.effects.reject(function(e){return e==effect});if(this.effects.length==0){clearInterval(this.interval);this.interval=null;}},loop:function(){var timePos=new Date().getTime();for(var i=0,len=this.effects.length;i<len;i++)
-if(this.effects[i])this.effects[i].loop(timePos);}});Effect.Queues={instances:$H(),get:function(queueName){if(typeof queueName!='string')return queueName;if(!this.instances[queueName])
-this.instances[queueName]=new Effect.ScopedQueue();return this.instances[queueName];}}
-Effect.Queue=Effect.Queues.get('global');Effect.DefaultOptions={transition:Effect.Transitions.sinoidal,duration:1.0,fps:60.0,sync:false,from:0.0,to:1.0,delay:0.0,queue:'parallel'}
-Effect.Base=function(){};Effect.Base.prototype={position:null,start:function(options){this.options=Object.extend(Object.extend({},Effect.DefaultOptions),options||{});this.currentFrame=0;this.state='idle';this.startOn=this.options.delay*1000;this.finishOn=this.startOn+(this.options.duration*1000);this.event('beforeStart');if(!this.options.sync)
-Effect.Queues.get(typeof this.options.queue=='string'?'global':this.options.queue.scope).add(this);},loop:function(timePos){if(timePos>=this.startOn){if(timePos>=this.finishOn){this.render(1.0);this.cancel();this.event('beforeFinish');if(this.finish)this.finish();this.event('afterFinish');return;}
-var pos=(timePos-this.startOn)/(this.finishOn-this.startOn);var frame=Math.round(pos*this.options.fps*this.options.duration);if(frame>this.currentFrame){this.render(pos);this.currentFrame=frame;}}},render:function(pos){if(this.state=='idle'){this.state='running';this.event('beforeSetup');if(this.setup)this.setup();this.event('afterSetup');}
-if(this.state=='running'){if(this.options.transition)pos=this.options.transition(pos);pos*=(this.options.to-this.options.from);pos+=this.options.from;this.position=pos;this.event('beforeUpdate');if(this.update)this.update(pos);this.event('afterUpdate');}},cancel:function(){if(!this.options.sync)
-Effect.Queues.get(typeof this.options.queue=='string'?'global':this.options.queue.scope).remove(this);this.state='finished';},event:function(eventName){if(this.options[eventName+'Internal'])this.options[eventName+'Internal'](this);if(this.options[eventName])this.options[eventName](this);},inspect:function(){var data=$H();for(property in this)
-if(typeof this[property]!='function')data[property]=this[property];return'#<Effect:'+data.inspect()+',options:'+$H(this.options).inspect()+'>';}}
-Effect.Parallel=Class.create();Object.extend(Object.extend(Effect.Parallel.prototype,Effect.Base.prototype),{initialize:function(effects){this.effects=effects||[];this.start(arguments[1]);},update:function(position){this.effects.invoke('render',position);},finish:function(position){this.effects.each(function(effect){effect.render(1.0);effect.cancel();effect.event('beforeFinish');if(effect.finish)effect.finish(position);effect.event('afterFinish');});}});Effect.Event=Class.create();Object.extend(Object.extend(Effect.Event.prototype,Effect.Base.prototype),{initialize:function(){var options=Object.extend({duration:0},arguments[0]||{});this.start(options);},update:Prototype.emptyFunction});Effect.Opacity=Class.create();Object.extend(Object.extend(Effect.Opacity.prototype,Effect.Base.prototype),{initialize:function(element){this.element=$(element);if(!this.element)throw(Effect._elementDoesNotExistError);if(/MSIE/.test(navigator.userAgent)&&!window.opera&&(!this.element.currentStyle.hasLayout))
-this.element.setStyle({zoom:1});var options=Object.extend({from:this.element.getOpacity()||0.0,to:1.0},arguments[1]||{});this.start(options);},update:function(position){this.element.setOpacity(position);}});Effect.Move=Class.create();Object.extend(Object.extend(Effect.Move.prototype,Effect.Base.prototype),{initialize:function(element){this.element=$(element);if(!this.element)throw(Effect._elementDoesNotExistError);var options=Object.extend({x:0,y:0,mode:'relative'},arguments[1]||{});this.start(options);},setup:function(){this.element.makePositioned();this.originalLeft=parseFloat(this.element.getStyle('left')||'0');this.originalTop=parseFloat(this.element.getStyle('top')||'0');if(this.options.mode=='absolute'){this.options.x=this.options.x-this.originalLeft;this.options.y=this.options.y-this.originalTop;}},update:function(position){this.element.setStyle({left:Math.round(this.options.x*position+this.originalLeft)+'px',top:Math.round(this.options.y*position+this.originalTop)+'px'});}});Effect.MoveBy=function(element,toTop,toLeft){return new Effect.Move(element,Object.extend({x:toLeft,y:toTop},arguments[3]||{}));};Effect.Scale=Class.create();Object.extend(Object.extend(Effect.Scale.prototype,Effect.Base.prototype),{initialize:function(element,percent){this.element=$(element);if(!this.element)throw(Effect._elementDoesNotExistError);var options=Object.extend({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:'box',scaleFrom:100.0,scaleTo:percent},arguments[2]||{});this.start(options);},setup:function(){this.restoreAfterFinish=this.options.restoreAfterFinish||false;this.elementPositioning=this.element.getStyle('position');this.originalStyle={};['top','left','width','height','fontSize'].each(function(k){this.originalStyle[k]=this.element.style[k];}.bind(this));this.originalTop=this.element.offsetTop;this.originalLeft=this.element.offsetLeft;var fontSize=this.element.getStyle('font-size')||'100%';['em','px','%','pt'].each(function(fontSizeType){if(fontSize.indexOf(fontSizeType)>0){this.fontSize=parseFloat(fontSize);this.fontSizeType=fontSizeType;}}.bind(this));this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;this.dims=null;if(this.options.scaleMode=='box')
-this.dims=[this.element.offsetHeight,this.element.offsetWidth];if(/^content/.test(this.options.scaleMode))
-this.dims=[this.element.scrollHeight,this.element.scrollWidth];if(!this.dims)
-this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth];},update:function(position){var currentScale=(this.options.scaleFrom/100.0)+(this.factor*position);if(this.options.scaleContent&&this.fontSize)
-this.element.setStyle({fontSize:this.fontSize*currentScale+this.fontSizeType});this.setDimensions(this.dims[0]*currentScale,this.dims[1]*currentScale);},finish:function(position){if(this.restoreAfterFinish)this.element.setStyle(this.originalStyle);},setDimensions:function(height,width){var d={};if(this.options.scaleX)d.width=Math.round(width)+'px';if(this.options.scaleY)d.height=Math.round(height)+'px';if(this.options.scaleFromCenter){var topd=(height-this.dims[0])/2;var leftd=(width-this.dims[1])/2;if(this.elementPositioning=='absolute'){if(this.options.scaleY)d.top=this.originalTop-topd+'px';if(this.options.scaleX)d.left=this.originalLeft-leftd+'px';}else{if(this.options.scaleY)d.top=-topd+'px';if(this.options.scaleX)d.left=-leftd+'px';}}
-this.element.setStyle(d);}});Effect.Highlight=Class.create();Object.extend(Object.extend(Effect.Highlight.prototype,Effect.Base.prototype),{initialize:function(element){this.element=$(element);if(!this.element)throw(Effect._elementDoesNotExistError);var options=Object.extend({startcolor:'#ffff99'},arguments[1]||{});this.start(options);},setup:function(){if(this.element.getStyle('display')=='none'){this.cancel();return;}
-this.oldStyle={};if(!this.options.keepBackgroundImage){this.oldStyle.backgroundImage=this.element.getStyle('background-image');this.element.setStyle({backgroundImage:'none'});}
-if(!this.options.endcolor)
-this.options.endcolor=this.element.getStyle('background-color').parseColor('#ffffff');if(!this.options.restorecolor)
-this.options.restorecolor=this.element.getStyle('background-color');this._base=$R(0,2).map(function(i){return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16)}.bind(this));this._delta=$R(0,2).map(function(i){return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]}.bind(this));},update:function(position){this.element.setStyle({backgroundColor:$R(0,2).inject('#',function(m,v,i){return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart());}.bind(this))});},finish:function(){this.element.setStyle(Object.extend(this.oldStyle,{backgroundColor:this.options.restorecolor}));}});Effect.ScrollTo=Class.create();Object.extend(Object.extend(Effect.ScrollTo.prototype,Effect.Base.prototype),{initialize:function(element){this.element=$(element);this.start(arguments[1]||{});},setup:function(){Position.prepare();var offsets=Position.cumulativeOffset(this.element);if(this.options.offset)offsets[1]+=this.options.offset;var max=window.innerHeight?window.height-window.innerHeight:document.body.scrollHeight-
-(document.documentElement.clientHeight?document.documentElement.clientHeight:document.body.clientHeight);this.scrollStart=Position.deltaY;this.delta=(offsets[1]>max?max:offsets[1])-this.scrollStart;},update:function(position){Position.prepare();window.scrollTo(Position.deltaX,this.scrollStart+(position*this.delta));}});Effect.Fade=function(element){element=$(element);var oldOpacity=element.getInlineOpacity();var options=Object.extend({from:element.getOpacity()||1.0,to:0.0,afterFinishInternal:function(effect){if(effect.options.to!=0)return;effect.element.hide().setStyle({opacity:oldOpacity});}},arguments[1]||{});return new Effect.Opacity(element,options);}
-Effect.Appear=function(element){element=$(element);var options=Object.extend({from:(element.getStyle('display')=='none'?0.0:element.getOpacity()||0.0),to:1.0,afterFinishInternal:function(effect){effect.element.forceRerendering();},beforeSetup:function(effect){effect.element.setOpacity(effect.options.from).show();}},arguments[1]||{});return new Effect.Opacity(element,options);}
-Effect.Puff=function(element){element=$(element);var oldStyle={opacity:element.getInlineOpacity(),position:element.getStyle('position'),top:element.style.top,left:element.style.left,width:element.style.width,height:element.style.height};return new Effect.Parallel([new Effect.Scale(element,200,{sync:true,scaleFromCenter:true,scaleContent:true,restoreAfterFinish:true}),new Effect.Opacity(element,{sync:true,to:0.0})],Object.extend({duration:1.0,beforeSetupInternal:function(effect){Position.absolutize(effect.effects[0].element)},afterFinishInternal:function(effect){effect.effects[0].element.hide().setStyle(oldStyle);}},arguments[1]||{}));}
-Effect.BlindUp=function(element){element=$(element);element.makeClipping();return new Effect.Scale(element,0,Object.extend({scaleContent:false,scaleX:false,restoreAfterFinish:true,afterFinishInternal:function(effect){effect.element.hide().undoClipping();}},arguments[1]||{}));}
-Effect.BlindDown=function(element){element=$(element);var elementDimensions=element.getDimensions();return new Effect.Scale(element,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:elementDimensions.height,originalWidth:elementDimensions.width},restoreAfterFinish:true,afterSetup:function(effect){effect.element.makeClipping().setStyle({height:'0px'}).show();},afterFinishInternal:function(effect){effect.element.undoClipping();}},arguments[1]||{}));}
-Effect.SwitchOff=function(element){element=$(element);var oldOpacity=element.getInlineOpacity();return new Effect.Appear(element,Object.extend({duration:0.4,from:0,transition:Effect.Transitions.flicker,afterFinishInternal:function(effect){new Effect.Scale(effect.element,1,{duration:0.3,scaleFromCenter:true,scaleX:false,scaleContent:false,restoreAfterFinish:true,beforeSetup:function(effect){effect.element.makePositioned().makeClipping();},afterFinishInternal:function(effect){effect.element.hide().undoClipping().undoPositioned().setStyle({opacity:oldOpacity});}})}},arguments[1]||{}));}
-Effect.DropOut=function(element){element=$(element);var oldStyle={top:element.getStyle('top'),left:element.getStyle('left'),opacity:element.getInlineOpacity()};return new Effect.Parallel([new Effect.Move(element,{x:0,y:100,sync:true}),new Effect.Opacity(element,{sync:true,to:0.0})],Object.extend({duration:0.5,beforeSetup:function(effect){effect.effects[0].element.makePositioned();},afterFinishInternal:function(effect){effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);}},arguments[1]||{}));}
-Effect.Shake=function(element){element=$(element);var oldStyle={top:element.getStyle('top'),left:element.getStyle('left')};return new Effect.Move(element,{x:20,y:0,duration:0.05,afterFinishInternal:function(effect){new Effect.Move(effect.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(effect){new Effect.Move(effect.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(effect){new Effect.Move(effect.element,{x:-40,y:0,duration:0.1,afterFinishInternal:function(effect){new Effect.Move(effect.element,{x:40,y:0,duration:0.1,afterFinishInternal:function(effect){new Effect.Move(effect.element,{x:-20,y:0,duration:0.05,afterFinishInternal:function(effect){effect.element.undoPositioned().setStyle(oldStyle);}})}})}})}})}})}});}
-Effect.SlideDown=function(element){element=$(element).cleanWhitespace();var oldInnerBottom=element.down().getStyle('bottom');var elementDimensions=element.getDimensions();return new Effect.Scale(element,100,Object.extend({scaleContent:false,scaleX:false,scaleFrom:window.opera?0:1,scaleMode:{originalHeight:elementDimensions.height,originalWidth:elementDimensions.width},restoreAfterFinish:true,afterSetup:function(effect){effect.element.makePositioned();effect.element.down().makePositioned();if(window.opera)effect.element.setStyle({top:''});effect.element.makeClipping().setStyle({height:'0px'}).show();},afterUpdateInternal:function(effect){effect.element.down().setStyle({bottom:(effect.dims[0]-effect.element.clientHeight)+'px'});},afterFinishInternal:function(effect){effect.element.undoClipping().undoPositioned();effect.element.down().undoPositioned().setStyle({bottom:oldInnerBottom});}},arguments[1]||{}));}
-Effect.SlideUp=function(element){element=$(element).cleanWhitespace();var oldInnerBottom=element.down().getStyle('bottom');return new Effect.Scale(element,window.opera?0:1,Object.extend({scaleContent:false,scaleX:false,scaleMode:'box',scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(effect){effect.element.makePositioned();effect.element.down().makePositioned();if(window.opera)effect.element.setStyle({top:''});effect.element.makeClipping().show();},afterUpdateInternal:function(effect){effect.element.down().setStyle({bottom:(effect.dims[0]-effect.element.clientHeight)+'px'});},afterFinishInternal:function(effect){effect.element.hide().undoClipping().undoPositioned().setStyle({bottom:oldInnerBottom});effect.element.down().undoPositioned();}},arguments[1]||{}));}
-Effect.Squish=function(element){return new Effect.Scale(element,window.opera?1:0,{restoreAfterFinish:true,beforeSetup:function(effect){effect.element.makeClipping();},afterFinishInternal:function(effect){effect.element.hide().undoClipping();}});}
-Effect.Grow=function(element){element=$(element);var options=Object.extend({direction:'center',moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.full},arguments[1]||{});var oldStyle={top:element.style.top,left:element.style.left,height:element.style.height,width:element.style.width,opacity:element.getInlineOpacity()};var dims=element.getDimensions();var initialMoveX,initialMoveY;var moveX,moveY;switch(options.direction){case'top-left':initialMoveX=initialMoveY=moveX=moveY=0;break;case'top-right':initialMoveX=dims.width;initialMoveY=moveY=0;moveX=-dims.width;break;case'bottom-left':initialMoveX=moveX=0;initialMoveY=dims.height;moveY=-dims.height;break;case'bottom-right':initialMoveX=dims.width;initialMoveY=dims.height;moveX=-dims.width;moveY=-dims.height;break;case'center':initialMoveX=dims.width/2;initialMoveY=dims.height/2;moveX=-dims.width/2;moveY=-dims.height/2;break;}
-return new Effect.Move(element,{x:initialMoveX,y:initialMoveY,duration:0.01,beforeSetup:function(effect){effect.element.hide().makeClipping().makePositioned();},afterFinishInternal:function(effect){new Effect.Parallel([new Effect.Opacity(effect.element,{sync:true,to:1.0,from:0.0,transition:options.opacityTransition}),new Effect.Move(effect.element,{x:moveX,y:moveY,sync:true,transition:options.moveTransition}),new Effect.Scale(effect.element,100,{scaleMode:{originalHeight:dims.height,originalWidth:dims.width},sync:true,scaleFrom:window.opera?1:0,transition:options.scaleTransition,restoreAfterFinish:true})],Object.extend({beforeSetup:function(effect){effect.effects[0].element.setStyle({height:'0px'}).show();},afterFinishInternal:function(effect){effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);}},options))}});}
-Effect.Shrink=function(element){element=$(element);var options=Object.extend({direction:'center',moveTransition:Effect.Transitions.sinoidal,scaleTransition:Effect.Transitions.sinoidal,opacityTransition:Effect.Transitions.none},arguments[1]||{});var oldStyle={top:element.style.top,left:element.style.left,height:element.style.height,width:element.style.width,opacity:element.getInlineOpacity()};var dims=element.getDimensions();var moveX,moveY;switch(options.direction){case'top-left':moveX=moveY=0;break;case'top-right':moveX=dims.width;moveY=0;break;case'bottom-left':moveX=0;moveY=dims.height;break;case'bottom-right':moveX=dims.width;moveY=dims.height;break;case'center':moveX=dims.width/2;moveY=dims.height/2;break;}
-return new Effect.Parallel([new Effect.Opacity(element,{sync:true,to:0.0,from:1.0,transition:options.opacityTransition}),new Effect.Scale(element,window.opera?1:0,{sync:true,transition:options.scaleTransition,restoreAfterFinish:true}),new Effect.Move(element,{x:moveX,y:moveY,sync:true,transition:options.moveTransition})],Object.extend({beforeStartInternal:function(effect){effect.effects[0].element.makePositioned().makeClipping();},afterFinishInternal:function(effect){effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle);}},options));}
-Effect.Pulsate=function(element){element=$(element);var options=arguments[1]||{};var oldOpacity=element.getInlineOpacity();var transition=options.transition||Effect.Transitions.sinoidal;var reverser=function(pos){return transition(1-Effect.Transitions.pulse(pos,options.pulses))};reverser.bind(transition);return new Effect.Opacity(element,Object.extend(Object.extend({duration:2.0,from:0,afterFinishInternal:function(effect){effect.element.setStyle({opacity:oldOpacity});}},options),{transition:reverser}));}
-Effect.Fold=function(element){element=$(element);var oldStyle={top:element.style.top,left:element.style.left,width:element.style.width,height:element.style.height};element.makeClipping();return new Effect.Scale(element,5,Object.extend({scaleContent:false,scaleX:false,afterFinishInternal:function(effect){new Effect.Scale(element,1,{scaleContent:false,scaleY:false,afterFinishInternal:function(effect){effect.element.hide().undoClipping().setStyle(oldStyle);}});}},arguments[1]||{}));};Effect.Morph=Class.create();Object.extend(Object.extend(Effect.Morph.prototype,Effect.Base.prototype),{initialize:function(element){this.element=$(element);if(!this.element)throw(Effect._elementDoesNotExistError);var options=Object.extend({style:{}},arguments[1]||{});if(typeof options.style=='string'){if(options.style.indexOf(':')==-1){var cssText='',selector='.'+options.style;$A(document.styleSheets).reverse().each(function(styleSheet){if(styleSheet.cssRules)cssRules=styleSheet.cssRules;else if(styleSheet.rules)cssRules=styleSheet.rules;$A(cssRules).reverse().each(function(rule){if(selector==rule.selectorText){cssText=rule.style.cssText;throw $break;}});if(cssText)throw $break;});this.style=cssText.parseStyle();options.afterFinishInternal=function(effect){effect.element.addClassName(effect.options.style);effect.transforms.each(function(transform){if(transform.style!='opacity')
-effect.element.style[transform.style.camelize()]='';});}}else this.style=options.style.parseStyle();}else this.style=$H(options.style)
-this.start(options);},setup:function(){function parseColor(color){if(!color||['rgba(0, 0, 0, 0)','transparent'].include(color))color='#ffffff';color=color.parseColor();return $R(0,2).map(function(i){return parseInt(color.slice(i*2+1,i*2+3),16)});}
-this.transforms=this.style.map(function(pair){var property=pair[0].underscore().dasherize(),value=pair[1],unit=null;if(value.parseColor('#zzzzzz')!='#zzzzzz'){value=value.parseColor();unit='color';}else if(property=='opacity'){value=parseFloat(value);if(/MSIE/.test(navigator.userAgent)&&!window.opera&&(!this.element.currentStyle.hasLayout))
-this.element.setStyle({zoom:1});}else if(Element.CSS_LENGTH.test(value))
-var components=value.match(/^([\+\-]?[0-9\.]+)(.*)$/),value=parseFloat(components[1]),unit=(components.length==3)?components[2]:null;var originalValue=this.element.getStyle(property);return $H({style:property,originalValue:unit=='color'?parseColor(originalValue):parseFloat(originalValue||0),targetValue:unit=='color'?parseColor(value):value,unit:unit});}.bind(this)).reject(function(transform){return((transform.originalValue==transform.targetValue)||(transform.unit!='color'&&(isNaN(transform.originalValue)||isNaN(transform.targetValue))))});},update:function(position){var style=$H(),value=null;this.transforms.each(function(transform){value=transform.unit=='color'?$R(0,2).inject('#',function(m,v,i){return m+(Math.round(transform.originalValue[i]+
-(transform.targetValue[i]-transform.originalValue[i])*position)).toColorPart()}):transform.originalValue+Math.round(((transform.targetValue-transform.originalValue)*position)*1000)/1000+transform.unit;style[transform.style]=value;});this.element.setStyle(style);}});Effect.Transform=Class.create();Object.extend(Effect.Transform.prototype,{initialize:function(tracks){this.tracks=[];this.options=arguments[1]||{};this.addTracks(tracks);},addTracks:function(tracks){tracks.each(function(track){var data=$H(track).values().first();this.tracks.push($H({ids:$H(track).keys().first(),effect:Effect.Morph,options:{style:data}}));}.bind(this));return this;},play:function(){return new Effect.Parallel(this.tracks.map(function(track){var elements=[$(track.ids)||$$(track.ids)].flatten();return elements.map(function(e){return new track.effect(e,Object.extend({sync:true},track.options))});}).flatten(),this.options);}});Element.CSS_PROPERTIES=$w('backgroundColor backgroundPosition borderBottomColor borderBottomStyle '+'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth '+'borderRightColor borderRightStyle borderRightWidth borderSpacing '+'borderTopColor borderTopStyle borderTopWidth bottom clip color '+'fontSize fontWeight height left letterSpacing lineHeight '+'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+'maxWidth minHeight minWidth opacity outlineColor outlineOffset '+'outlineWidth paddingBottom paddingLeft paddingRight paddingTop '+'right textIndent top width wordSpacing zIndex');Element.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;String.prototype.parseStyle=function(){var element=Element.extend(document.createElement('div'));element.innerHTML='<div style="'+this+'"></div>';var style=element.down().style,styleRules=$H();Element.CSS_PROPERTIES.each(function(property){if(style[property])styleRules[property]=style[property];});if(/MSIE/.test(navigator.userAgent)&&!window.opera&&this.indexOf('opacity')>-1){styleRules.opacity=this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];}
-return styleRules;};Element.morph=function(element,style){new Effect.Morph(element,Object.extend({style:style},arguments[2]||{}));return element;};['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom','collectTextNodes','collectTextNodesIgnoreClass','morph'].each(function(f){Element.Methods[f]=Element[f];});Element.Methods.visualEffect=function(element,effect,options){s=effect.gsub(/_/,'-').camelize();effect_class=s.charAt(0).toUpperCase()+s.substring(1);new Effect[effect_class](element,options);return $(element);};Element.addMethods();if(typeof Effect=='undefined')
-throw("dragdrop.js requires including script.aculo.us' effects.js library");var Droppables={drops:[],remove:function(element){this.drops=this.drops.reject(function(d){return d.element==$(element)});},add:function(element){element=$(element);var options=Object.extend({greedy:true,hoverclass:null,tree:false},arguments[1]||{});if(options.containment){options._containers=[];var containment=options.containment;if((typeof containment=='object')&&(containment.constructor==Array)){containment.each(function(c){options._containers.push($(c))});}else{options._containers.push($(containment));}}
-if(options.accept)options.accept=[options.accept].flatten();Element.makePositioned(element);options.element=element;this.drops.push(options);},findDeepestChild:function(drops){deepest=drops[0];for(i=1;i<drops.length;++i)
-if(Element.isParent(drops[i].element,deepest.element))
-deepest=drops[i];return deepest;},isContained:function(element,drop){var containmentNode;if(drop.tree){containmentNode=element.treeNode;}else{containmentNode=element.parentNode;}
-return drop._containers.detect(function(c){return containmentNode==c});},isAffected:function(point,element,drop){return((drop.element!=element)&&((!drop._containers)||this.isContained(element,drop))&&((!drop.accept)||(Element.classNames(element).detect(function(v){return drop.accept.include(v)})))&&Position.within(drop.element,point[0],point[1]));},deactivate:function(drop){if(drop.hoverclass)
-Element.removeClassName(drop.element,drop.hoverclass);this.last_active=null;},activate:function(drop){if(drop.hoverclass)
-Element.addClassName(drop.element,drop.hoverclass);this.last_active=drop;},show:function(point,element){if(!this.drops.length)return;var affected=[];if(this.last_active)this.deactivate(this.last_active);this.drops.each(function(drop){if(Droppables.isAffected(point,element,drop))
-affected.push(drop);});if(affected.length>0){drop=Droppables.findDeepestChild(affected);Position.within(drop.element,point[0],point[1]);if(drop.onHover)
-drop.onHover(element,drop.element,Position.overlap(drop.overlap,drop.element));Droppables.activate(drop);}},fire:function(event,element){if(!this.last_active)return;Position.prepare();if(this.isAffected([Event.pointerX(event),Event.pointerY(event)],element,this.last_active))
-if(this.last_active.onDrop)
-this.last_active.onDrop(element,this.last_active.element,event);},reset:function(){if(this.last_active)
-this.deactivate(this.last_active);}}
-var Draggables={drags:[],observers:[],register:function(draggable){if(this.drags.length==0){this.eventMouseUp=this.endDrag.bindAsEventListener(this);this.eventMouseMove=this.updateDrag.bindAsEventListener(this);this.eventKeypress=this.keyPress.bindAsEventListener(this);Event.observe(document,"mouseup",this.eventMouseUp);Event.observe(document,"mousemove",this.eventMouseMove);Event.observe(document,"keypress",this.eventKeypress);}
-this.drags.push(draggable);},unregister:function(draggable){this.drags=this.drags.reject(function(d){return d==draggable});if(this.drags.length==0){Event.stopObserving(document,"mouseup",this.eventMouseUp);Event.stopObserving(document,"mousemove",this.eventMouseMove);Event.stopObserving(document,"keypress",this.eventKeypress);}},activate:function(draggable){if(draggable.options.delay){this._timeout=setTimeout(function(){Draggables._timeout=null;window.focus();Draggables.activeDraggable=draggable;}.bind(this),draggable.options.delay);}else{window.focus();this.activeDraggable=draggable;}},deactivate:function(){this.activeDraggable=null;},updateDrag:function(event){if(!this.activeDraggable)return;var pointer=[Event.pointerX(event),Event.pointerY(event)];if(this._lastPointer&&(this._lastPointer.inspect()==pointer.inspect()))return;this._lastPointer=pointer;this.activeDraggable.updateDrag(event,pointer);},endDrag:function(event){if(this._timeout){clearTimeout(this._timeout);this._timeout=null;}
-if(!this.activeDraggable)return;this._lastPointer=null;this.activeDraggable.endDrag(event);this.activeDraggable=null;},keyPress:function(event){if(this.activeDraggable)
-this.activeDraggable.keyPress(event);},addObserver:function(observer){this.observers.push(observer);this._cacheObserverCallbacks();},removeObserver:function(element){this.observers=this.observers.reject(function(o){return o.element==element});this._cacheObserverCallbacks();},notify:function(eventName,draggable,event){if(this[eventName+'Count']>0)
-this.observers.each(function(o){if(o[eventName])o[eventName](eventName,draggable,event);});if(draggable.options[eventName])draggable.options[eventName](draggable,event);},_cacheObserverCallbacks:function(){['onStart','onEnd','onDrag'].each(function(eventName){Draggables[eventName+'Count']=Draggables.observers.select(function(o){return o[eventName];}).length;});}}
-var Draggable=Class.create();Draggable._dragging={};Draggable.prototype={initialize:function(element){var defaults={handle:false,reverteffect:function(element,top_offset,left_offset){var dur=Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;new Effect.Move(element,{x:-left_offset,y:-top_offset,duration:dur,queue:{scope:'_draggable',position:'end'}});},endeffect:function(element){var toOpacity=typeof element._opacity=='number'?element._opacity:1.0;new Effect.Opacity(element,{duration:0.2,from:0.7,to:toOpacity,queue:{scope:'_draggable',position:'end'},afterFinish:function(){Draggable._dragging[element]=false}});},zindex:1000,revert:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,snap:false,delay:0};if(!arguments[1]||typeof arguments[1].endeffect=='undefined')
-Object.extend(defaults,{starteffect:function(element){element._opacity=Element.getOpacity(element);Draggable._dragging[element]=true;new Effect.Opacity(element,{duration:0.2,from:element._opacity,to:0.7});}});var options=Object.extend(defaults,arguments[1]||{});this.element=$(element);if(options.handle&&(typeof options.handle=='string'))
-this.handle=this.element.down('.'+options.handle,0);if(!this.handle)this.handle=$(options.handle);if(!this.handle)this.handle=this.element;if(options.scroll&&!options.scroll.scrollTo&&!options.scroll.outerHTML){options.scroll=$(options.scroll);this._isScrollChild=Element.childOf(this.element,options.scroll);}
-Element.makePositioned(this.element);this.delta=this.currentDelta();this.options=options;this.dragging=false;this.eventMouseDown=this.initDrag.bindAsEventListener(this);Event.observe(this.handle,"mousedown",this.eventMouseDown);Draggables.register(this);},destroy:function(){Event.stopObserving(this.handle,"mousedown",this.eventMouseDown);Draggables.unregister(this);},currentDelta:function(){return([parseInt(Element.getStyle(this.element,'left')||'0'),parseInt(Element.getStyle(this.element,'top')||'0')]);},initDrag:function(event){if(typeof Draggable._dragging[this.element]!='undefined'&&Draggable._dragging[this.element])return;if(Event.isLeftClick(event)){var src=Event.element(event);if((tag_name=src.tagName.toUpperCase())&&(tag_name=='INPUT'||tag_name=='SELECT'||tag_name=='OPTION'||tag_name=='BUTTON'||tag_name=='TEXTAREA'))return;var pointer=[Event.pointerX(event),Event.pointerY(event)];var pos=Position.cumulativeOffset(this.element);this.offset=[0,1].map(function(i){return(pointer[i]-pos[i])});Draggables.activate(this);Event.stop(event);}},startDrag:function(event){this.dragging=true;if(this.options.zindex){this.originalZ=parseInt(Element.getStyle(this.element,'z-index')||0);this.element.style.zIndex=this.options.zindex;}
-if(this.options.ghosting){this._clone=this.element.cloneNode(true);Position.absolutize(this.element);this.element.parentNode.insertBefore(this._clone,this.element);}
-if(this.options.scroll){if(this.options.scroll==window){var where=this._getWindowScroll(this.options.scroll);this.originalScrollLeft=where.left;this.originalScrollTop=where.top;}else{this.originalScrollLeft=this.options.scroll.scrollLeft;this.originalScrollTop=this.options.scroll.scrollTop;}}
-Draggables.notify('onStart',this,event);if(this.options.starteffect)this.options.starteffect(this.element);},updateDrag:function(event,pointer){if(!this.dragging)this.startDrag(event);Position.prepare();Droppables.show(pointer,this.element);Draggables.notify('onDrag',this,event);this.draw(pointer);if(this.options.change)this.options.change(this);if(this.options.scroll){this.stopScrolling();var p;if(this.options.scroll==window){with(this._getWindowScroll(this.options.scroll)){p=[left,top,left+width,top+height];}}else{p=Position.page(this.options.scroll);p[0]+=this.options.scroll.scrollLeft+Position.deltaX;p[1]+=this.options.scroll.scrollTop+Position.deltaY;p.push(p[0]+this.options.scroll.offsetWidth);p.push(p[1]+this.options.scroll.offsetHeight);}
-var speed=[0,0];if(pointer[0]<(p[0]+this.options.scrollSensitivity))speed[0]=pointer[0]-(p[0]+this.options.scrollSensitivity);if(pointer[1]<(p[1]+this.options.scrollSensitivity))speed[1]=pointer[1]-(p[1]+this.options.scrollSensitivity);if(pointer[0]>(p[2]-this.options.scrollSensitivity))speed[0]=pointer[0]-(p[2]-this.options.scrollSensitivity);if(pointer[1]>(p[3]-this.options.scrollSensitivity))speed[1]=pointer[1]-(p[3]-this.options.scrollSensitivity);this.startScrolling(speed);}
-if(navigator.appVersion.indexOf('AppleWebKit')>0)window.scrollBy(0,0);Event.stop(event);},finishDrag:function(event,success){this.dragging=false;if(this.options.ghosting){Position.relativize(this.element);Element.remove(this._clone);this._clone=null;}
-if(success)Droppables.fire(event,this.element);Draggables.notify('onEnd',this,event);var revert=this.options.revert;if(revert&&typeof revert=='function')revert=revert(this.element);var d=this.currentDelta();if(revert&&this.options.reverteffect){this.options.reverteffect(this.element,d[1]-this.delta[1],d[0]-this.delta[0]);}else{this.delta=d;}
-if(this.options.zindex)
-this.element.style.zIndex=this.originalZ;if(this.options.endeffect)
-this.options.endeffect(this.element);Draggables.deactivate(this);Droppables.reset();},keyPress:function(event){if(event.keyCode!=Event.KEY_ESC)return;this.finishDrag(event,false);Event.stop(event);},endDrag:function(event){if(!this.dragging)return;this.stopScrolling();this.finishDrag(event,true);Event.stop(event);},draw:function(point){var pos=Position.cumulativeOffset(this.element);if(this.options.ghosting){var r=Position.realOffset(this.element);pos[0]+=r[0]-Position.deltaX;pos[1]+=r[1]-Position.deltaY;}
-var d=this.currentDelta();pos[0]-=d[0];pos[1]-=d[1];if(this.options.scroll&&(this.options.scroll!=window&&this._isScrollChild)){pos[0]-=this.options.scroll.scrollLeft-this.originalScrollLeft;pos[1]-=this.options.scroll.scrollTop-this.originalScrollTop;}
-var p=[0,1].map(function(i){return(point[i]-pos[i]-this.offset[i])}.bind(this));if(this.options.snap){if(typeof this.options.snap=='function'){p=this.options.snap(p[0],p[1],this);}else{if(this.options.snap instanceof Array){p=p.map(function(v,i){return Math.round(v/this.options.snap[i])*this.options.snap[i]}.bind(this))}else{p=p.map(function(v){return Math.round(v/this.options.snap)*this.options.snap}.bind(this))}}}
-var style=this.element.style;if((!this.options.constraint)||(this.options.constraint=='horizontal'))
-style.left=p[0]+"px";if((!this.options.constraint)||(this.options.constraint=='vertical'))
-style.top=p[1]+"px";if(style.visibility=="hidden")style.visibility="";},stopScrolling:function(){if(this.scrollInterval){clearInterval(this.scrollInterval);this.scrollInterval=null;Draggables._lastScrollPointer=null;}},startScrolling:function(speed){if(!(speed[0]||speed[1]))return;this.scrollSpeed=[speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];this.lastScrolled=new Date();this.scrollInterval=setInterval(this.scroll.bind(this),10);},scroll:function(){var current=new Date();var delta=current-this.lastScrolled;this.lastScrolled=current;if(this.options.scroll==window){with(this._getWindowScroll(this.options.scroll)){if(this.scrollSpeed[0]||this.scrollSpeed[1]){var d=delta/1000;this.options.scroll.scrollTo(left+d*this.scrollSpeed[0],top+d*this.scrollSpeed[1]);}}}else{this.options.scroll.scrollLeft+=this.scrollSpeed[0]*delta/1000;this.options.scroll.scrollTop+=this.scrollSpeed[1]*delta/1000;}
-Position.prepare();Droppables.show(Draggables._lastPointer,this.element);Draggables.notify('onDrag',this);if(this._isScrollChild){Draggables._lastScrollPointer=Draggables._lastScrollPointer||$A(Draggables._lastPointer);Draggables._lastScrollPointer[0]+=this.scrollSpeed[0]*delta/1000;Draggables._lastScrollPointer[1]+=this.scrollSpeed[1]*delta/1000;if(Draggables._lastScrollPointer[0]<0)
-Draggables._lastScrollPointer[0]=0;if(Draggables._lastScrollPointer[1]<0)
-Draggables._lastScrollPointer[1]=0;this.draw(Draggables._lastScrollPointer);}
-if(this.options.change)this.options.change(this);},_getWindowScroll:function(w){var T,L,W,H;with(w.document){if(w.document.documentElement&&documentElement.scrollTop){T=documentElement.scrollTop;L=documentElement.scrollLeft;}else if(w.document.body){T=body.scrollTop;L=body.scrollLeft;}
-if(w.innerWidth){W=w.innerWidth;H=w.innerHeight;}else if(w.document.documentElement&&documentElement.clientWidth){W=documentElement.clientWidth;H=documentElement.clientHeight;}else{W=body.offsetWidth;H=body.offsetHeight}}
-return{top:T,left:L,width:W,height:H};}}
-var SortableObserver=Class.create();SortableObserver.prototype={initialize:function(element,observer){this.element=$(element);this.observer=observer;this.lastValue=Sortable.serialize(this.element);},onStart:function(){this.lastValue=Sortable.serialize(this.element);},onEnd:function(){Sortable.unmark();if(this.lastValue!=Sortable.serialize(this.element))
-this.observer(this.element)}}
-var Sortable={SERIALIZE_RULE:/^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,sortables:{},_findRootElement:function(element){while(element.tagName.toUpperCase()!="BODY"){if(element.id&&Sortable.sortables[element.id])return element;element=element.parentNode;}},options:function(element){element=Sortable._findRootElement($(element));if(!element)return;return Sortable.sortables[element.id];},destroy:function(element){var s=Sortable.options(element);if(s){Draggables.removeObserver(s.element);s.droppables.each(function(d){Droppables.remove(d)});s.draggables.invoke('destroy');delete Sortable.sortables[s.element.id];}},create:function(element){element=$(element);var options=Object.extend({element:element,tag:'li',dropOnEmpty:false,tree:false,treeTag:'ul',overlap:'vertical',constraint:'vertical',containment:element,handle:false,only:false,delay:0,hoverclass:null,ghosting:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,format:this.SERIALIZE_RULE,onChange:Prototype.emptyFunction,onUpdate:Prototype.emptyFunction},arguments[1]||{});this.destroy(element);var options_for_draggable={revert:true,scroll:options.scroll,scrollSpeed:options.scrollSpeed,scrollSensitivity:options.scrollSensitivity,delay:options.delay,ghosting:options.ghosting,constraint:options.constraint,handle:options.handle};if(options.starteffect)
-options_for_draggable.starteffect=options.starteffect;if(options.reverteffect)
-options_for_draggable.reverteffect=options.reverteffect;else
-if(options.ghosting)options_for_draggable.reverteffect=function(element){element.style.top=0;element.style.left=0;};if(options.endeffect)
-options_for_draggable.endeffect=options.endeffect;if(options.zindex)
-options_for_draggable.zindex=options.zindex;var options_for_droppable={overlap:options.overlap,containment:options.containment,tree:options.tree,hoverclass:options.hoverclass,onHover:Sortable.onHover}
-var options_for_tree={onHover:Sortable.onEmptyHover,overlap:options.overlap,containment:options.containment,hoverclass:options.hoverclass}
-Element.cleanWhitespace(element);options.draggables=[];options.droppables=[];if(options.dropOnEmpty||options.tree){Droppables.add(element,options_for_tree);options.droppables.push(element);}
-(this.findElements(element,options)||[]).each(function(e){var handle=options.handle?$(e).down('.'+options.handle,0):e;options.draggables.push(new Draggable(e,Object.extend(options_for_draggable,{handle:handle})));Droppables.add(e,options_for_droppable);if(options.tree)e.treeNode=element;options.droppables.push(e);});if(options.tree){(Sortable.findTreeElements(element,options)||[]).each(function(e){Droppables.add(e,options_for_tree);e.treeNode=element;options.droppables.push(e);});}
-this.sortables[element.id]=options;Draggables.addObserver(new SortableObserver(element,options.onUpdate));},findElements:function(element,options){return Element.findChildren(element,options.only,options.tree?true:false,options.tag);},findTreeElements:function(element,options){return Element.findChildren(element,options.only,options.tree?true:false,options.treeTag);},onHover:function(element,dropon,overlap){if(Element.isParent(dropon,element))return;if(overlap>.33&&overlap<.66&&Sortable.options(dropon).tree){return;}else if(overlap>0.5){Sortable.mark(dropon,'before');if(dropon.previousSibling!=element){var oldParentNode=element.parentNode;element.style.visibility="hidden";dropon.parentNode.insertBefore(element,dropon);if(dropon.parentNode!=oldParentNode)
-Sortable.options(oldParentNode).onChange(element);Sortable.options(dropon.parentNode).onChange(element);}}else{Sortable.mark(dropon,'after');var nextElement=dropon.nextSibling||null;if(nextElement!=element){var oldParentNode=element.parentNode;element.style.visibility="hidden";dropon.parentNode.insertBefore(element,nextElement);if(dropon.parentNode!=oldParentNode)
-Sortable.options(oldParentNode).onChange(element);Sortable.options(dropon.parentNode).onChange(element);}}},onEmptyHover:function(element,dropon,overlap){var oldParentNode=element.parentNode;var droponOptions=Sortable.options(dropon);if(!Element.isParent(dropon,element)){var index;var children=Sortable.findElements(dropon,{tag:droponOptions.tag,only:droponOptions.only});var child=null;if(children){var offset=Element.offsetSize(dropon,droponOptions.overlap)*(1.0-overlap);for(index=0;index<children.length;index+=1){if(offset-Element.offsetSize(children[index],droponOptions.overlap)>=0){offset-=Element.offsetSize(children[index],droponOptions.overlap);}else if(offset-(Element.offsetSize(children[index],droponOptions.overlap)/2)>=0){child=index+1<children.length?children[index+1]:null;break;}else{child=children[index];break;}}}
-dropon.insertBefore(element,child);Sortable.options(oldParentNode).onChange(element);droponOptions.onChange(element);}},unmark:function(){if(Sortable._marker)Sortable._marker.hide();},mark:function(dropon,position){var sortable=Sortable.options(dropon.parentNode);if(sortable&&!sortable.ghosting)return;if(!Sortable._marker){Sortable._marker=($('dropmarker')||Element.extend(document.createElement('DIV'))).hide().addClassName('dropmarker').setStyle({position:'absolute'});document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);}
-var offsets=Position.cumulativeOffset(dropon);Sortable._marker.setStyle({left:offsets[0]+'px',top:offsets[1]+'px'});if(position=='after')
-if(sortable.overlap=='horizontal')
-Sortable._marker.setStyle({left:(offsets[0]+dropon.clientWidth)+'px'});else
-Sortable._marker.setStyle({top:(offsets[1]+dropon.clientHeight)+'px'});Sortable._marker.show();},_tree:function(element,options,parent){var children=Sortable.findElements(element,options)||[];for(var i=0;i<children.length;++i){var match=children[i].id.match(options.format);if(!match)continue;var child={id:encodeURIComponent(match?match[1]:null),element:element,parent:parent,children:[],position:parent.children.length,container:$(children[i]).down(options.treeTag)}
-if(child.container)
-this._tree(child.container,options,child)
-parent.children.push(child);}
-return parent;},tree:function(element){element=$(element);var sortableOptions=this.options(element);var options=Object.extend({tag:sortableOptions.tag,treeTag:sortableOptions.treeTag,only:sortableOptions.only,name:element.id,format:sortableOptions.format},arguments[1]||{});var root={id:null,parent:null,children:[],container:element,position:0}
-return Sortable._tree(element,options,root);},_constructIndex:function(node){var index='';do{if(node.id)index='['+node.position+']'+index;}while((node=node.parent)!=null);return index;},sequence:function(element){element=$(element);var options=Object.extend(this.options(element),arguments[1]||{});return $(this.findElements(element,options)||[]).map(function(item){return item.id.match(options.format)?item.id.match(options.format)[1]:'';});},setSequence:function(element,new_sequence){element=$(element);var options=Object.extend(this.options(element),arguments[2]||{});var nodeMap={};this.findElements(element,options).each(function(n){if(n.id.match(options.format))
-nodeMap[n.id.match(options.format)[1]]=[n,n.parentNode];n.parentNode.removeChild(n);});new_sequence.each(function(ident){var n=nodeMap[ident];if(n){n[1].appendChild(n[0]);delete nodeMap[ident];}});},serialize:function(element){element=$(element);var options=Object.extend(Sortable.options(element),arguments[1]||{});var name=encodeURIComponent((arguments[1]&&arguments[1].name)?arguments[1].name:element.id);if(options.tree){return Sortable.tree(element,arguments[1]).children.map(function(item){return[name+Sortable._constructIndex(item)+"[id]="+
-encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));}).flatten().join('&');}else{return Sortable.sequence(element,arguments[1]).map(function(item){return name+"[]="+encodeURIComponent(item);}).join('&');}}}
-Element.isParent=function(child,element){if(!child.parentNode||child==element)return false;if(child.parentNode==element)return true;return Element.isParent(child.parentNode,element);}
-Element.findChildren=function(element,only,recursive,tagName){if(!element.hasChildNodes())return null;tagName=tagName.toUpperCase();if(only)only=[only].flatten();var elements=[];$A(element.childNodes).each(function(e){if(e.tagName&&e.tagName.toUpperCase()==tagName&&(!only||(Element.classNames(e).detect(function(v){return only.include(v)}))))
-elements.push(e);if(recursive){var grandchildren=Element.findChildren(e,only,recursive,tagName);if(grandchildren)elements.push(grandchildren);}});return(elements.length>0?elements.flatten():[]);}
-Element.offsetSize=function(element,type){return element['offset'+((type=='vertical'||type=='height')?'Height':'Width')];}
-if(typeof Effect=='undefined')
-throw("controls.js requires including script.aculo.us' effects.js library");var Autocompleter={}
-Autocompleter.Base=function(){};Autocompleter.Base.prototype={baseInitialize:function(element,update,options){this.element=$(element);this.update=$(update);this.hasFocus=false;this.changed=false;this.active=false;this.index=0;this.entryCount=0;if(this.setOptions)
-this.setOptions(options);else
-this.options=options||{};this.options.paramName=this.options.paramName||this.element.name;this.options.tokens=this.options.tokens||[];this.options.frequency=this.options.frequency||0.4;this.options.minChars=this.options.minChars||1;this.options.onShow=this.options.onShow||function(element,update){if(!update.style.position||update.style.position=='absolute'){update.style.position='absolute';Position.clone(element,update,{setHeight:false,offsetTop:element.offsetHeight});}
-Effect.Appear(update,{duration:0.15});};this.options.onHide=this.options.onHide||function(element,update){new Effect.Fade(update,{duration:0.15})};if(typeof(this.options.tokens)=='string')
-this.options.tokens=new Array(this.options.tokens);this.observer=null;this.element.setAttribute('autocomplete','off');Element.hide(this.update);Event.observe(this.element,"blur",this.onBlur.bindAsEventListener(this));Event.observe(this.element,"keypress",this.onKeyPress.bindAsEventListener(this));},show:function(){if(Element.getStyle(this.update,'display')=='none')this.options.onShow(this.element,this.update);if(!this.iefix&&(navigator.appVersion.indexOf('MSIE')>0)&&(navigator.userAgent.indexOf('Opera')<0)&&(Element.getStyle(this.update,'position')=='absolute')){new Insertion.After(this.update,'<iframe id="'+this.update.id+'_iefix" '+'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" '+'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');this.iefix=$(this.update.id+'_iefix');}
-if(this.iefix)setTimeout(this.fixIEOverlapping.bind(this),50);},fixIEOverlapping:function(){Position.clone(this.update,this.iefix,{setTop:(!this.update.style.height)});this.iefix.style.zIndex=1;this.update.style.zIndex=2;Element.show(this.iefix);},hide:function(){this.stopIndicator();if(Element.getStyle(this.update,'display')!='none')this.options.onHide(this.element,this.update);if(this.iefix)Element.hide(this.iefix);},startIndicator:function(){if(this.options.indicator)Element.show(this.options.indicator);},stopIndicator:function(){if(this.options.indicator)Element.hide(this.options.indicator);},onKeyPress:function(event){if(this.active)
-switch(event.keyCode){case Event.KEY_TAB:case Event.KEY_RETURN:this.selectEntry();Event.stop(event);case Event.KEY_ESC:this.hide();this.active=false;Event.stop(event);return;case Event.KEY_LEFT:case Event.KEY_RIGHT:return;case Event.KEY_UP:this.markPrevious();this.render();if(navigator.appVersion.indexOf('AppleWebKit')>0)Event.stop(event);return;case Event.KEY_DOWN:this.markNext();this.render();if(navigator.appVersion.indexOf('AppleWebKit')>0)Event.stop(event);return;}
-else
-if(event.keyCode==Event.KEY_TAB||event.keyCode==Event.KEY_RETURN||(navigator.appVersion.indexOf('AppleWebKit')>0&&event.keyCode==0))return;this.changed=true;this.hasFocus=true;if(this.observer)clearTimeout(this.observer);this.observer=setTimeout(this.onObserverEvent.bind(this),this.options.frequency*1000);},activate:function(){this.changed=false;this.hasFocus=true;this.getUpdatedChoices();},onHover:function(event){var element=Event.findElement(event,'LI');if(this.index!=element.autocompleteIndex)
-{this.index=element.autocompleteIndex;this.render();}
-Event.stop(event);},onClick:function(event){var element=Event.findElement(event,'LI');this.index=element.autocompleteIndex;this.selectEntry();this.hide();},onBlur:function(event){setTimeout(this.hide.bind(this),250);this.hasFocus=false;this.active=false;},render:function(){if(this.entryCount>0){for(var i=0;i<this.entryCount;i++)
-this.index==i?Element.addClassName(this.getEntry(i),"selected"):Element.removeClassName(this.getEntry(i),"selected");if(this.hasFocus){this.show();this.active=true;}}else{this.active=false;this.hide();}},markPrevious:function(){if(this.index>0)this.index--
-else this.index=this.entryCount-1;this.getEntry(this.index).scrollIntoView(true);},markNext:function(){if(this.index<this.entryCount-1)this.index++
-else this.index=0;this.getEntry(this.index).scrollIntoView(false);},getEntry:function(index){return this.update.firstChild.childNodes[index];},getCurrentEntry:function(){return this.getEntry(this.index);},selectEntry:function(){this.active=false;this.updateElement(this.getCurrentEntry());},updateElement:function(selectedElement){if(this.options.updateElement){this.options.updateElement(selectedElement);return;}
-var value='';if(this.options.select){var nodes=document.getElementsByClassName(this.options.select,selectedElement)||[];if(nodes.length>0)value=Element.collectTextNodes(nodes[0],this.options.select);}else
-value=Element.collectTextNodesIgnoreClass(selectedElement,'informal');var lastTokenPos=this.findLastToken();if(lastTokenPos!=-1){var newValue=this.element.value.substr(0,lastTokenPos+1);var whitespace=this.element.value.substr(lastTokenPos+1).match(/^\s+/);if(whitespace)
-newValue+=whitespace[0];this.element.value=newValue+value;}else{this.element.value=value;}
-this.element.focus();if(this.options.afterUpdateElement)
-this.options.afterUpdateElement(this.element,selectedElement);},updateChoices:function(choices){if(!this.changed&&this.hasFocus){this.update.innerHTML=choices;Element.cleanWhitespace(this.update);Element.cleanWhitespace(this.update.down());if(this.update.firstChild&&this.update.down().childNodes){this.entryCount=this.update.down().childNodes.length;for(var i=0;i<this.entryCount;i++){var entry=this.getEntry(i);entry.autocompleteIndex=i;this.addObservers(entry);}}else{this.entryCount=0;}
-this.stopIndicator();this.index=0;if(this.entryCount==1&&this.options.autoSelect){this.selectEntry();this.hide();}else{this.render();}}},addObservers:function(element){Event.observe(element,"mouseover",this.onHover.bindAsEventListener(this));Event.observe(element,"click",this.onClick.bindAsEventListener(this));},onObserverEvent:function(){this.changed=false;if(this.getToken().length>=this.options.minChars){this.startIndicator();this.getUpdatedChoices();}else{this.active=false;this.hide();}},getToken:function(){var tokenPos=this.findLastToken();if(tokenPos!=-1)
-var ret=this.element.value.substr(tokenPos+1).replace(/^\s+/,'').replace(/\s+$/,'');else
-var ret=this.element.value;return/\n/.test(ret)?'':ret;},findLastToken:function(){var lastTokenPos=-1;for(var i=0;i<this.options.tokens.length;i++){var thisTokenPos=this.element.value.lastIndexOf(this.options.tokens[i]);if(thisTokenPos>lastTokenPos)
-lastTokenPos=thisTokenPos;}
-return lastTokenPos;}}
-Ajax.Autocompleter=Class.create();Object.extend(Object.extend(Ajax.Autocompleter.prototype,Autocompleter.Base.prototype),{initialize:function(element,update,url,options){this.baseInitialize(element,update,options);this.options.asynchronous=true;this.options.onComplete=this.onComplete.bind(this);this.options.defaultParams=this.options.parameters||null;this.url=url;},getUpdatedChoices:function(){entry=encodeURIComponent(this.options.paramName)+'='+
-encodeURIComponent(this.getToken());this.options.parameters=this.options.callback?this.options.callback(this.element,entry):entry;if(this.options.defaultParams)
-this.options.parameters+='&'+this.options.defaultParams;new Ajax.Request(this.url,this.options);},onComplete:function(request){this.updateChoices(request.responseText);}});Autocompleter.Local=Class.create();Autocompleter.Local.prototype=Object.extend(new Autocompleter.Base(),{initialize:function(element,update,array,options){this.baseInitialize(element,update,options);this.options.array=array;},getUpdatedChoices:function(){this.updateChoices(this.options.selector(this));},setOptions:function(options){this.options=Object.extend({choices:10,partialSearch:true,partialChars:2,ignoreCase:true,fullSearch:false,selector:function(instance){var ret=[];var partial=[];var entry=instance.getToken();var count=0;for(var i=0;i<instance.options.array.length&&ret.length<instance.options.choices;i++){var elem=instance.options.array[i];var foundPos=instance.options.ignoreCase?elem.toLowerCase().indexOf(entry.toLowerCase()):elem.indexOf(entry);while(foundPos!=-1){if(foundPos==0&&elem.length!=entry.length){ret.push("<li><strong>"+elem.substr(0,entry.length)+"</strong>"+
-elem.substr(entry.length)+"</li>");break;}else if(entry.length>=instance.options.partialChars&&instance.options.partialSearch&&foundPos!=-1){if(instance.options.fullSearch||/\s/.test(elem.substr(foundPos-1,1))){partial.push("<li>"+elem.substr(0,foundPos)+"<strong>"+
-elem.substr(foundPos,entry.length)+"</strong>"+elem.substr(foundPos+entry.length)+"</li>");break;}}
-foundPos=instance.options.ignoreCase?elem.toLowerCase().indexOf(entry.toLowerCase(),foundPos+1):elem.indexOf(entry,foundPos+1);}}
-if(partial.length)
-ret=ret.concat(partial.slice(0,instance.options.choices-ret.length))
-return"<ul>"+ret.join('')+"</ul>";}},options||{});}});Field.scrollFreeActivate=function(field){setTimeout(function(){Field.activate(field);},1);}
-Ajax.InPlaceEditor=Class.create();Ajax.InPlaceEditor.defaultHighlightColor="#FFFF99";Ajax.InPlaceEditor.prototype={initialize:function(element,url,options){this.url=url;this.element=$(element);this.options=Object.extend({paramName:"value",okButton:true,okText:"ok",cancelLink:true,cancelText:"cancel",savingText:"Saving...",clickToEditText:"Click to edit",okText:"ok",rows:1,onComplete:function(transport,element){new Effect.Highlight(element,{startcolor:this.options.highlightcolor});},onFailure:function(transport){alert("Error communicating with the server: "+transport.responseText.stripTags());},callback:function(form){return Form.serialize(form);},handleLineBreaks:true,loadingText:'Loading...',savingClassName:'inplaceeditor-saving',loadingClassName:'inplaceeditor-loading',formClassName:'inplaceeditor-form',highlightcolor:Ajax.InPlaceEditor.defaultHighlightColor,highlightendcolor:"#FFFFFF",externalControl:null,submitOnBlur:false,ajaxOptions:{},evalScripts:false},options||{});if(!this.options.formId&&this.element.id){this.options.formId=this.element.id+"-inplaceeditor";if($(this.options.formId)){this.options.formId=null;}}
-if(this.options.externalControl){this.options.externalControl=$(this.options.externalControl);}
-this.originalBackground=Element.getStyle(this.element,'background-color');if(!this.originalBackground){this.originalBackground="transparent";}
-this.element.title=this.options.clickToEditText;this.onclickListener=this.enterEditMode.bindAsEventListener(this);this.mouseoverListener=this.enterHover.bindAsEventListener(this);this.mouseoutListener=this.leaveHover.bindAsEventListener(this);Event.observe(this.element,'click',this.onclickListener);Event.observe(this.element,'mouseover',this.mouseoverListener);Event.observe(this.element,'mouseout',this.mouseoutListener);if(this.options.externalControl){Event.observe(this.options.externalControl,'click',this.onclickListener);Event.observe(this.options.externalControl,'mouseover',this.mouseoverListener);Event.observe(this.options.externalControl,'mouseout',this.mouseoutListener);}},enterEditMode:function(evt){if(this.saving)return;if(this.editing)return;this.editing=true;this.onEnterEditMode();if(this.options.externalControl){Element.hide(this.options.externalControl);}
-Element.hide(this.element);this.createForm();this.element.parentNode.insertBefore(this.form,this.element);if(!this.options.loadTextURL)Field.scrollFreeActivate(this.editField);if(evt){Event.stop(evt);}
-return false;},createForm:function(){this.form=document.createElement("form");this.form.id=this.options.formId;Element.addClassName(this.form,this.options.formClassName)
-this.form.onsubmit=this.onSubmit.bind(this);this.createEditField();if(this.options.textarea){var br=document.createElement("br");this.form.appendChild(br);}
-if(this.options.okButton){okButton=document.createElement("input");okButton.type="submit";okButton.value=this.options.okText;okButton.className='editor_ok_button';this.form.appendChild(okButton);}
-if(this.options.cancelLink){cancelLink=document.createElement("a");cancelLink.href="javascript:void(0)";cancelLink.appendChild(document.createTextNode(this.options.cancelText));cancelLink.onclick=this.onclickCancel.bind(this);cancelLink.className='editor_cancel';this.form.appendChild(cancelLink);}},hasHTMLLineBreaks:function(string){if(!this.options.handleLineBreaks)return false;return string.match(/<br/i)||string.match(/<p>/i);},convertHTMLLineBreaks:function(string){return string.replace(/<br>/gi,"\n").replace(/<br\/>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<p>/gi,"");},createEditField:function(){var text;if(this.options.loadTextURL){text=this.options.loadingText;}else{text=this.getText();}
-var obj=this;if(this.options.rows==1&&!this.hasHTMLLineBreaks(text)){this.options.textarea=false;var textField=document.createElement("input");textField.obj=this;textField.type="text";textField.name=this.options.paramName;textField.value=text;textField.style.backgroundColor=this.options.highlightcolor;textField.className='editor_field';var size=this.options.size||this.options.cols||0;if(size!=0)textField.size=size;if(this.options.submitOnBlur)
-textField.onblur=this.onSubmit.bind(this);this.editField=textField;}else{this.options.textarea=true;var textArea=document.createElement("textarea");textArea.obj=this;textArea.name=this.options.paramName;textArea.value=this.convertHTMLLineBreaks(text);textArea.rows=this.options.rows;textArea.cols=this.options.cols||40;textArea.className='editor_field';if(this.options.submitOnBlur)
-textArea.onblur=this.onSubmit.bind(this);this.editField=textArea;}
-if(this.options.loadTextURL){this.loadExternalText();}
-this.form.appendChild(this.editField);},getText:function(){return this.element.innerHTML;},loadExternalText:function(){Element.addClassName(this.form,this.options.loadingClassName);this.editField.disabled=true;new Ajax.Request(this.options.loadTextURL,Object.extend({asynchronous:true,onComplete:this.onLoadedExternalText.bind(this)},this.options.ajaxOptions));},onLoadedExternalText:function(transport){Element.removeClassName(this.form,this.options.loadingClassName);this.editField.disabled=false;this.editField.value=transport.responseText.stripTags();Field.scrollFreeActivate(this.editField);},onclickCancel:function(){this.onComplete();this.leaveEditMode();return false;},onFailure:function(transport){this.options.onFailure(transport);if(this.oldInnerHTML){this.element.innerHTML=this.oldInnerHTML;this.oldInnerHTML=null;}
-return false;},onSubmit:function(){var form=this.form;var value=this.editField.value;this.onLoading();if(this.options.evalScripts){new Ajax.Request(this.url,Object.extend({parameters:this.options.callback(form,value),onComplete:this.onComplete.bind(this),onFailure:this.onFailure.bind(this),asynchronous:true,evalScripts:true},this.options.ajaxOptions));}else{new Ajax.Updater({success:this.element,failure:null},this.url,Object.extend({parameters:this.options.callback(form,value),onComplete:this.onComplete.bind(this),onFailure:this.onFailure.bind(this)},this.options.ajaxOptions));}
-if(arguments.length>1){Event.stop(arguments[0]);}
-return false;},onLoading:function(){this.saving=true;this.removeForm();this.leaveHover();this.showSaving();},showSaving:function(){this.oldInnerHTML=this.element.innerHTML;this.element.innerHTML=this.options.savingText;Element.addClassName(this.element,this.options.savingClassName);this.element.style.backgroundColor=this.originalBackground;Element.show(this.element);},removeForm:function(){if(this.form){if(this.form.parentNode)Element.remove(this.form);this.form=null;}},enterHover:function(){if(this.saving)return;this.element.style.backgroundColor=this.options.highlightcolor;if(this.effect){this.effect.cancel();}
-Element.addClassName(this.element,this.options.hoverClassName)},leaveHover:function(){if(this.options.backgroundColor){this.element.style.backgroundColor=this.oldBackground;}
-Element.removeClassName(this.element,this.options.hoverClassName)
-if(this.saving)return;this.effect=new Effect.Highlight(this.element,{startcolor:this.options.highlightcolor,endcolor:this.options.highlightendcolor,restorecolor:this.originalBackground});},leaveEditMode:function(){Element.removeClassName(this.element,this.options.savingClassName);this.removeForm();this.leaveHover();this.element.style.backgroundColor=this.originalBackground;Element.show(this.element);if(this.options.externalControl){Element.show(this.options.externalControl);}
-this.editing=false;this.saving=false;this.oldInnerHTML=null;this.onLeaveEditMode();},onComplete:function(transport){this.leaveEditMode();this.options.onComplete.bind(this)(transport,this.element);},onEnterEditMode:function(){},onLeaveEditMode:function(){},dispose:function(){if(this.oldInnerHTML){this.element.innerHTML=this.oldInnerHTML;}
-this.leaveEditMode();Event.stopObserving(this.element,'click',this.onclickListener);Event.stopObserving(this.element,'mouseover',this.mouseoverListener);Event.stopObserving(this.element,'mouseout',this.mouseoutListener);if(this.options.externalControl){Event.stopObserving(this.options.externalControl,'click',this.onclickListener);Event.stopObserving(this.options.externalControl,'mouseover',this.mouseoverListener);Event.stopObserving(this.options.externalControl,'mouseout',this.mouseoutListener);}}};Ajax.InPlaceCollectionEditor=Class.create();Object.extend(Ajax.InPlaceCollectionEditor.prototype,Ajax.InPlaceEditor.prototype);Object.extend(Ajax.InPlaceCollectionEditor.prototype,{createEditField:function(){if(!this.cached_selectTag){var selectTag=document.createElement("select");var collection=this.options.collection||[];var optionTag;collection.each(function(e,i){optionTag=document.createElement("option");optionTag.value=(e instanceof Array)?e[0]:e;if((typeof this.options.value=='undefined')&&((e instanceof Array)?this.element.innerHTML==e[1]:e==optionTag.value))optionTag.selected=true;if(this.options.value==optionTag.value)optionTag.selected=true;optionTag.appendChild(document.createTextNode((e instanceof Array)?e[1]:e));selectTag.appendChild(optionTag);}.bind(this));this.cached_selectTag=selectTag;}
-this.editField=this.cached_selectTag;if(this.options.loadTextURL)this.loadExternalText();this.form.appendChild(this.editField);this.options.callback=function(form,value){return"value="+encodeURIComponent(value);}}});Form.Element.DelayedObserver=Class.create();Form.Element.DelayedObserver.prototype={initialize:function(element,delay,callback){this.delay=delay||0.5;this.element=$(element);this.callback=callback;this.timer=null;this.lastValue=$F(this.element);Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));},delayedListener:function(event){if(this.lastValue==$F(this.element))return;if(this.timer)clearTimeout(this.timer);this.timer=setTimeout(this.onTimerEvent.bind(this),this.delay*1000);this.lastValue=$F(this.element);},onTimerEvent:function(){this.timer=null;this.callback(this.element,$F(this.element));}};if(!Control)var Control={};Control.Slider=Class.create();Control.Slider.prototype={initialize:function(handle,track,options){var slider=this;if(handle instanceof Array){this.handles=handle.collect(function(e){return $(e)});}else{this.handles=[$(handle)];}
-this.track=$(track);this.options=options||{};this.axis=this.options.axis||'horizontal';this.increment=this.options.increment||1;this.step=parseInt(this.options.step||'1');this.range=this.options.range||$R(0,1);this.value=0;this.values=this.handles.map(function(){return 0});this.spans=this.options.spans?this.options.spans.map(function(s){return $(s)}):false;this.options.startSpan=$(this.options.startSpan||null);this.options.endSpan=$(this.options.endSpan||null);this.restricted=this.options.restricted||false;this.maximum=this.options.maximum||this.range.end;this.minimum=this.options.minimum||this.range.start;this.alignX=parseInt(this.options.alignX||'0');this.alignY=parseInt(this.options.alignY||'0');this.trackLength=this.maximumOffset()-this.minimumOffset();this.handleLength=this.isVertical()?(this.handles[0].offsetHeight!=0?this.handles[0].offsetHeight:this.handles[0].style.height.replace(/px$/,"")):(this.handles[0].offsetWidth!=0?this.handles[0].offsetWidth:this.handles[0].style.width.replace(/px$/,""));this.active=false;this.dragging=false;this.disabled=false;if(this.options.disabled)this.setDisabled();this.allowedValues=this.options.values?this.options.values.sortBy(Prototype.K):false;if(this.allowedValues){this.minimum=this.allowedValues.min();this.maximum=this.allowedValues.max();}
-this.eventMouseDown=this.startDrag.bindAsEventListener(this);this.eventMouseUp=this.endDrag.bindAsEventListener(this);this.eventMouseMove=this.update.bindAsEventListener(this);this.handles.each(function(h,i){i=slider.handles.length-1-i;slider.setValue(parseFloat((slider.options.sliderValue instanceof Array?slider.options.sliderValue[i]:slider.options.sliderValue)||slider.range.start),i);Element.makePositioned(h);Event.observe(h,"mousedown",slider.eventMouseDown);});Event.observe(this.track,"mousedown",this.eventMouseDown);Event.observe(document,"mouseup",this.eventMouseUp);Event.observe(document,"mousemove",this.eventMouseMove);this.initialized=true;},dispose:function(){var slider=this;Event.stopObserving(this.track,"mousedown",this.eventMouseDown);Event.stopObserving(document,"mouseup",this.eventMouseUp);Event.stopObserving(document,"mousemove",this.eventMouseMove);this.handles.each(function(h){Event.stopObserving(h,"mousedown",slider.eventMouseDown);});},setDisabled:function(){this.disabled=true;},setEnabled:function(){this.disabled=false;},getNearestValue:function(value){if(this.allowedValues){if(value>=this.allowedValues.max())return(this.allowedValues.max());if(value<=this.allowedValues.min())return(this.allowedValues.min());var offset=Math.abs(this.allowedValues[0]-value);var newValue=this.allowedValues[0];this.allowedValues.each(function(v){var currentOffset=Math.abs(v-value);if(currentOffset<=offset){newValue=v;offset=currentOffset;}});return newValue;}
-if(value>this.range.end)return this.range.end;if(value<this.range.start)return this.range.start;return value;},setValue:function(sliderValue,handleIdx){if(!this.active){this.activeHandleIdx=handleIdx||0;this.activeHandle=this.handles[this.activeHandleIdx];this.updateStyles();}
-handleIdx=handleIdx||this.activeHandleIdx||0;if(this.initialized&&this.restricted){if((handleIdx>0)&&(sliderValue<this.values[handleIdx-1]))
-sliderValue=this.values[handleIdx-1];if((handleIdx<(this.handles.length-1))&&(sliderValue>this.values[handleIdx+1]))
-sliderValue=this.values[handleIdx+1];}
-sliderValue=this.getNearestValue(sliderValue);this.values[handleIdx]=sliderValue;this.value=this.values[0];this.handles[handleIdx].style[this.isVertical()?'top':'left']=this.translateToPx(sliderValue);this.drawSpans();if(!this.dragging||!this.event)this.updateFinished();},setValueBy:function(delta,handleIdx){this.setValue(this.values[handleIdx||this.activeHandleIdx||0]+delta,handleIdx||this.activeHandleIdx||0);},translateToPx:function(value){return Math.round(((this.trackLength-this.handleLength)/(this.range.end-this.range.start))*(value-this.range.start))+"px";},translateToValue:function(offset){return((offset/(this.trackLength-this.handleLength)*(this.range.end-this.range.start))+this.range.start);},getRange:function(range){var v=this.values.sortBy(Prototype.K);range=range||0;return $R(v[range],v[range+1]);},minimumOffset:function(){return(this.isVertical()?this.alignY:this.alignX);},maximumOffset:function(){return(this.isVertical()?(this.track.offsetHeight!=0?this.track.offsetHeight:this.track.style.height.replace(/px$/,""))-this.alignY:(this.track.offsetWidth!=0?this.track.offsetWidth:this.track.style.width.replace(/px$/,""))-this.alignY);},isVertical:function(){return(this.axis=='vertical');},drawSpans:function(){var slider=this;if(this.spans)
-$R(0,this.spans.length-1).each(function(r){slider.setSpan(slider.spans[r],slider.getRange(r))});if(this.options.startSpan)
-this.setSpan(this.options.startSpan,$R(0,this.values.length>1?this.getRange(0).min():this.value));if(this.options.endSpan)
-this.setSpan(this.options.endSpan,$R(this.values.length>1?this.getRange(this.spans.length-1).max():this.value,this.maximum));},setSpan:function(span,range){if(this.isVertical()){span.style.top=this.translateToPx(range.start);span.style.height=this.translateToPx(range.end-range.start+this.range.start);}else{span.style.left=this.translateToPx(range.start);span.style.width=this.translateToPx(range.end-range.start+this.range.start);}},updateStyles:function(){this.handles.each(function(h){Element.removeClassName(h,'selected')});Element.addClassName(this.activeHandle,'selected');},startDrag:function(event){if(Event.isLeftClick(event)){if(!this.disabled){this.active=true;var handle=Event.element(event);var pointer=[Event.pointerX(event),Event.pointerY(event)];var track=handle;if(track==this.track){var offsets=Position.cumulativeOffset(this.track);this.event=event;this.setValue(this.translateToValue((this.isVertical()?pointer[1]-offsets[1]:pointer[0]-offsets[0])-(this.handleLength/2)));var offsets=Position.cumulativeOffset(this.activeHandle);this.offsetX=(pointer[0]-offsets[0]);this.offsetY=(pointer[1]-offsets[1]);}else{while((this.handles.indexOf(handle)==-1)&&handle.parentNode)
-handle=handle.parentNode;if(this.handles.indexOf(handle)!=-1){this.activeHandle=handle;this.activeHandleIdx=this.handles.indexOf(this.activeHandle);this.updateStyles();var offsets=Position.cumulativeOffset(this.activeHandle);this.offsetX=(pointer[0]-offsets[0]);this.offsetY=(pointer[1]-offsets[1]);}}}
-Event.stop(event);}},update:function(event){if(this.active){if(!this.dragging)this.dragging=true;this.draw(event);if(navigator.appVersion.indexOf('AppleWebKit')>0)window.scrollBy(0,0);Event.stop(event);}},draw:function(event){var pointer=[Event.pointerX(event),Event.pointerY(event)];var offsets=Position.cumulativeOffset(this.track);pointer[0]-=this.offsetX+offsets[0];pointer[1]-=this.offsetY+offsets[1];this.event=event;this.setValue(this.translateToValue(this.isVertical()?pointer[1]:pointer[0]));if(this.initialized&&this.options.onSlide)
-this.options.onSlide(this.values.length>1?this.values:this.value,this);},endDrag:function(event){if(this.active&&this.dragging){this.finishDrag(event,true);Event.stop(event);}
-this.active=false;this.dragging=false;},finishDrag:function(event,success){this.active=false;this.dragging=false;this.updateFinished();},updateFinished:function(){if(this.initialized&&this.options.onChange)
-this.options.onChange(this.values.length>1?this.values:this.value,this);this.event=null;}};Event.observe(window,'load',function(){if(!("console"in window)||!("firebug"in window.console)){var names=["log","debug","info","warn","error","assert","dir","dirxml","group","groupEnd","time","timeEnd","count","trace","profile","profileEnd"];window.console={};for(var i=0;i<names.length;++i){window.console[names[i]]=function(){};}}});var ua=navigator.userAgent.toLowerCase();var isIE=ua.indexOf("msie")>-1,isIE7=ua.indexOf("msie 7")>-1;if(isIE&&!isIE7){try{document.execCommand("BackgroundImageCache",false,true);}catch(e){}}
-if(typeof Jx=='undefined'){var Jx={};Jx.COMBINED_CSS=true;var aScripts=document.getElementsByTagName('SCRIPT');for(var i=0;i<aScripts.length;i++){var s=aScripts[i].src;var n=s.indexOf('lib/jx');if(n!=-1){Jx.baseURL=s.substring(0,n);break;}}}
-Jx.importRules={};Jx.importRulesIE={};Jx.addStyleSheet=function(styleSheet,ieOnly){if(ieOnly){this.importRulesIE[styleSheet]=styleSheet;}else{this.importRules[styleSheet]=styleSheet;}};Jx.addStyleSheet('reset.css');Jx.applyPNGFilter=function(o){var t=Jx.baseURL+"images/a_pixel.png";if(o.src!=t){var s=o.src;o.src=t;o.runtimeStyle.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+s+"',sizingMethod='scale')";}};Jx.imgQueue=[];Jx.imgLoaded={};Jx.imagesLoading=0;Jx.addToImgQueue=function(obj){if(Jx.imgLoaded[obj.src]){obj.domElement.src=obj.src;}else{Jx.imgQueue.push(obj);Jx.imgLoaded[obj.src]=true;}
-Jx.checkImgQueue();};Jx.checkImgQueue=function(){while(Jx.imagesLoading<2&&Jx.imgQueue.length>0){Jx.loadNextImg();}};Jx.loadNextImg=function(){var obj=Jx.imgQueue.shift();if(obj){++Jx.imagesLoading;obj.domElement.onload=function(){--Jx.imagesLoading;Jx.checkImgQueue();};obj.domElement.onerror=function(){--Jx.imagesLoading;Jx.checkImgQueue();};obj.domElement.src=obj.src;}};Jx.Listener=Class.create();Jx.Listener.prototype={addListener:function(list,obj){list.push(obj);},removeListener:function(list,obj){for(var i=0;i<list.length;i++){if(list[i]==obj){list.splice(i,1);break;}}},processEvent:function(list,fnName,obj){list.each(function(o){if(o[fnName]){o[fnName](obj);}});}};Jx.UniqueId=Class.create();Jx.UniqueId.prototype={uniqueIdRefs:null,initUniqueId:function(){this.uniqueIdRefs=[];},deregisterIds:function(){this.uniqueIdRefs.length=0;},registerIds:function(aIds,domObj){if(aIds.indexOf(domObj.id)!=-1){this.uniqueIdRefs[domObj.id]=domObj;}
-for(var i=0;i<domObj.childNodes.length;i++){this.registerIds(aIds,domObj.childNodes[i]);}},getObj:function(id){return this.uniqueIdRefs[id]||null;}};Jx.Action=Class.create();Jx.Action.prototype={pcl:null,enabled:null,initialize:function(f){this.pcl=[];this.enabled=true;this.actionPerformed=f;},addPropertyChangeListener:function(obj){this.addListener(this.pcl,obj);},removePropertyChangeListener:function(obj){this.removeListener(this.pcl,obj);},isEnabled:function(){return this.enabled;},setEnabled:function(b){if(this.enabled==b){return;}
-this.enabled=b;this.processEvent(this.pcl,'propertyChanged',this);},bindTo:function(item){this.addPropertyChangeListener(item);item.addActionListener(this);},unbindFrom:function(item){this.removePropertyChangeListener(item);item.removeActionListener(this);},actionPerformed:function(obj){alert('actionPerformed');}};Object.extend(Jx.Action.prototype,Jx.Listener.prototype);Object.extend(Element,{getBoxSizing:function(elem){var result='content-box';elem=$(elem);if(elem.currentStyle||window.opera){var cm=document["compatMode"];if(cm=="BackCompat"||cm=="QuirksMode"){result='border-box';}else{result='content-box';}}else{if(arguments.length==0){node=document.documentElement;}
-var sizing=Element.getStyle(elem,"-moz-box-sizing");if(!sizing){sizing=Element.getStyle(elem,"box-sizing");}
-result=(sizing?sizing:'content-box');}
-return result;},getContentBoxSize:function(elem){elem=$(elem);Element.toggleMeasurable(elem);var w=elem.offsetWidth;var h=elem.offsetHeight;var padding=Element.getPaddingSize(elem);var border=Element.getBorderSize(elem);Element.toggleMeasurable(elem);w=w-padding.left-padding.right-border.left-border.right;h=h-padding.bottom-padding.top-border.bottom-border.top;return{width:w,height:h};},getBorderBoxSize:function(elem){elem=$(elem);Element.toggleMeasurable(elem);var w=elem.offsetWidth;var h=elem.offsetHeight;Element.toggleMeasurable(elem);return{width:w,height:h};},setContentBoxSize:function(elem,size){elem=$(elem);if(Element.getBoxSizing(elem)=='border-box'){var padding=Element.getPaddingSize(elem);var border=Element.getBorderSize(elem);if(typeof size.width!='undefined'){var width=(size.width+padding.left+padding.right+border.left+border.right);if(width<0){width=0;}
-elem.style.width=width+'px';}
-if(typeof size.height!='undefined'){var height=(size.height+padding.top+padding.bottom+border.top+border.bottom);if(height<0){height=0;}
-elem.style.height=height+'px';}}else{if(typeof size.width!='undefined'){elem.style.width=size.width+'px';}
-if(typeof size.height!='undefined'){elem.style.height=size.height+'px';}}},setBorderBoxSize:function(elem,size){elem=$(elem);if(Element.getBoxSizing(elem)=='content-box'){var padding=Element.getPaddingSize(elem);var border=Element.getBorderSize(elem);var margin=Element.getMarginSize(elem);if(typeof size.width!='undefined'){var width=(size.width-padding.left-padding.right-border.left-border.right-margin.left-margin.right);if(width<0){width=0;}
-elem.style.width=width+'px';}
-if(typeof size.height!='undefined'){var height=(size.height-padding.top-padding.bottom-border.top-border.bottom-margin.top-margin.bottom);if(height<0){height=0;}
-elem.style.height=height+'px';}}else{if(typeof size.width!='undefined'&&size.width>=0){elem.style.width=size.width+'px';}
-if(typeof size.height!='undefined'&&size.height>=0){elem.style.height=size.height+'px';}}},getPaddingSize:function(elem){elem=$(elem);Element.toggleMeasurable(elem);var l=Element.getNumber(Element.getStyle(elem,'padding-left'));var t=Element.getNumber(Element.getStyle(elem,'padding-top'));var r=Element.getNumber(Element.getStyle(elem,'padding-right'));var b=Element.getNumber(Element.getStyle(elem,'padding-bottom'));Element.toggleMeasurable(elem);return{left:l,top:t,right:r,bottom:b};},getBorderSize:function(elem){elem=$(elem);Element.toggleMeasurable(elem);var l=Element.getNumber(Element.getStyle(elem,'border-left-width'));var t=Element.getNumber(Element.getStyle(elem,'border-top-width'));var r=Element.getNumber(Element.getStyle(elem,'border-right-width'));var b=Element.getNumber(Element.getStyle(elem,'border-bottom-width'));Element.toggleMeasurable(elem);return{left:l,top:t,right:r,bottom:b};},getMarginSize:function(elem){elem=$(elem);Element.toggleMeasurable(elem);var l=Element.getNumber(Element.getStyle(elem,'margin-left'));var t=Element.getNumber(Element.getStyle(elem,'margin-top'));var r=Element.getNumber(Element.getStyle(elem,'margin-right'));var b=Element.getNumber(Element.getStyle(elem,'margin-bottom'));Element.toggleMeasurable(elem);return{left:l,top:t,right:r,bottom:b};},getNumber:function(n){var result=n==null||isNaN(parseInt(n))?0:parseInt(n);return result;},getPageDimensions:function(){return{width:Element.getInsideWindowWidth(),height:Element.getInsideWindowHeight()};},getInsideWindowWidth:function(){if(window.innerWidth){return window.innerWidth;}else if(document.compatMode&&document.compatMode.indexOf("CSS1")>=0){return document.body.parentElement.clientWidth;}else if(document.body&&document.body.clientWidth){return document.body.clientWidth;}
-return 0;},getInsideWindowHeight:function(){if(window.innerHeight){return window.innerHeight;}else if(document.compatMode&&document.compatMode.indexOf("CSS1")>=0){return document.body.parentElement.clientHeight;}else if(document.body&&document.body.clientHeight){return document.body.clientHeight;}
-return 0;},toggleMeasurable:function(elem){if(Element.getStyle(elem,'display')=='none'){elem.old={};elem.old.display=elem.style.display;elem.old.visibility=elem.style.visibility;elem.old.position=elem.style.position;elem.style.position='absolute';elem.style.visibility='hidden';elem.style.display='block';}else{if(elem.old){elem.style.display=elem.old.display;elem.style.visibility=elem.old.visibility;elem.style.position=elem.old.position;elem.old=null;}}}});Jx.ContentLoader=Class.create();Jx.ContentLoader.prototype={bContentLoaded:false,contentLoaded:function(element,options,r){element.innerHTML=r.responseText;this.bContentLoaded=true;if(options.onContentLoaded){options.onContentLoaded();}},contentLoadFailed:function(options,r){this.bContentLoaded=false;if(options.onContentLoadFailed){options.onContentLoadFailed();}},loadContent:function(element,options){options=options||{};element=$(element);if(options.content){element.appendChild(options.content);this.bContentLoaded=true;}else if(options.contentID){var c=$(options.contentID);if(c){element.appendChild(c);this.bContentLoaded=true;}}else if(options.contentURL){this.bContentLoaded=false;var ts='';var a=new Ajax.Request(options.contentURL,Object.extend({method:'get',onSuccess:this.contentLoaded.bind(this,element,options),onFailure:this.contentLoadFailed.bind(this,options),parameters:ts}));}else if(options.contentHTML){element.innerHTML=options.contentHTML;this.bContentLoaded=true;}else{this.bContentLoaded=true;}
-if(this.bContentLoaded&&options.onContentLoaded){options.onContentLoaded();}}};Jx.addStyleSheet('button/button.css');Jx.Button=Class.create();Object.extend(Jx.Button.prototype,Jx.Listener.prototype);Object.extend(Jx.Button.prototype,{al:null,domObj:null,enabled:null,initialize:function(action,options){options=options||{};this.al=[];this.action=action;var imgPath=(options.imgPath||options.image)||'';var tooltip=options.tooltip||'';var label=options.label||'';this.disabledClass=options.disabledClass||'jxDisabled';this.domA=document.createElement('a');this.domA.className='jxButton';this.domA.href='javascript:void(0)';this.domA.onclick=this.onclick.bindAsEventListener(this);this.domA.title=tooltip;this.domA.alt=tooltip;var span=document.createElement('span');span.className='jxButtonSpan';this.domA.appendChild(span);this.domLabel=document.createElement('span');this.domLabel.className='jxButtonContent';this.domLabel.innerHTML=label!=''?label:' ';span.appendChild(this.domLabel);if(label!=''){Element.addClassName(this.domLabel,'jxButtonLabel');}
-if(imgPath!=''){Element.addClassName(this.domLabel,'jxButtonIcon');this.domLabel.style.backgroundImage="url("+imgPath+")";}
-if(this.action){this.action.bindTo(this);this.propertyChanged(this.action);}
-this.domObj=document.createElement('div');this.domObj.className='jxButtonContainer';this.domObj.appendChild(this.domA);if(options.halign&&options.halign=='left'){Element.addClassName(this.domObj,'jxButtonContentLeft');}
-if(options.valign&&options.valign=='top'){Element.addClassName(this.domObj,'jxButtonContentTop');}},onclick:function(){if(this.enabled){this.processEvent(this.al,'actionPerformed',this);}
-return false;},addActionListener:function(obj){this.addListener(this.al,obj);},removeActionListener:function(obj){this.removeListener(this.al,obj);},propertyChanged:function(obj){this.enabled=obj.isEnabled();if(this.enabled){Element.removeClassName(this.domObj,this.disabledClass);}else{Element.addClassName(this.domObj,this.disabledClass);}},setImage:function(path){if(this.domImg){this.domImg.src=path;}},setLabel:function(label){if(this.domLabel){this.domLabel.innerHTML=label;}},setTooltip:function(tooltip){if(this.domImg){this.domImg.title=tooltip;this.domImg.alt=tooltip;}}});Jx.Button.Flyout=Class.create();Object.extend(Jx.Button.Flyout.prototype,Jx.Button.prototype);Object.extend(Jx.Button.Flyout.prototype,Jx.ContentLoader.prototype);Object.extend(Jx.Button.Flyout.prototype,{content:null,initialize:function(options){options=options||{};var a=new Jx.Action(this.show.bind(this));Jx.Button.prototype.initialize.apply(this,[a,options]);Element.addClassName(this.domA,'jxButtonFlyout');this.iframe=document.createElement('iframe');this.iframe.className='jxMenuShim';this.iframe.scrolling='no';this.iframe.frameborder=0;this.content=document.createElement('div');Element.addClassName(this.content,'jxFlyout');this.loadContent(this.content,options);this.domObj.appendChild(this.content);this.content.style.display='none';this.keypressWatcher=this.keypressHandler.bindAsEventListener(this);this.hideWatcher=this.clickHandler.bindAsEventListener(this);},show:function(){if(!window.opera&&!this.iframe.parentNode){this.content.appendChild(this.iframe);}
-this.content.style.display='block';Event.observe(window,'keypress',this.keypressWatcher);Event.observe(document,'click',this.hideWatcher);},hide:function(){this.content.style.display='none';Event.stopObserving(window,'keypress',this.keypressWatcher);Event.stopObserving(document,'click',this.hideWatcher);},clickHandler:function(e){var elm=Event.element(e);if(!Element.descendantOf(elm,this.domObj.parentNode)){this.hide();}},keypressHandler:function(e){var charCode=(e.charCode)?e.charCode:e.keyCode;if(charCode==Event.KEY_ESC){this.hide();}}});Jx.Button.Multi=Class.create();Jx.Button.Multi.prototype={activeButton:null,buttons:null,initialize:function(){this.buttons=[];this.content=document.createElement('div');this.tb=new Jx.Toolbar(this.content,'right');this.flyout=new Jx.Button.Flyout({content:this.content,label:' '});Element.addClassName(this.flyout.domObj.firstChild,'jxButtonMulti');this.domObj=document.createElement('div');this.buttonContainer=document.createElement('div');this.buttonContainer.className='jxButtonMultiContainer';this.domObj.appendChild(this.buttonContainer);this.domObj.appendChild(this.flyout.domObj);},add:function(){for(var i=0;i<arguments.length;i++){var theButton=arguments[i];var action=new Jx.Action(this.setButton.bind(this,theButton));var button=new Jx.Button(action,{});var click=button.domA.onclick;button.domObj=theButton.domObj.cloneNode(true);button.domObj.onclick=click;this.tb.add(button);if(!this.activeButton){this.buttonContainer.appendChild(theButton.domObj);this.activeButton=theButton;}}},setActiveButton:function(button){while(this.buttonContainer.childNodes.length>0){this.buttonContainer.removeChild(this.buttonContainer.firstChild);}
-this.buttonContainer.appendChild(button.domObj);},setButton:function(button){this.setActiveButton(button);button.onclick();this.flyout.hide();}};Jx.Button.Picker=Class.create();Object.extend(Jx.Button.Picker.prototype,Jx.Button.Flyout.prototype);Object.extend(Jx.Button.Picker.prototype,{ul:null,selectedItem:null,initialize:function(){Jx.Button.Flyout.prototype.initialize.apply(this,arguments);this.ul=document.createElement('ul');this.content.appendChild(this.ul);Element.removeClassName(this.domLabel,'jxButtonEmptyLabel');},add:function(){for(var i=0;i<arguments.length;i++){var thing=arguments[i];if(thing.domObj){thing=thing.domObj;}
-var li=document.createElement('li');var a=document.createElement('a');li.appendChild(a);if(typeof(thing)=='string'){a.innerHTML=thing;}else{a.appendChild(thing);}
-this.ul.appendChild(li);if(!this.selectedItem){this.updateButton(a);}}},clickHandler:function(e){var elm=Event.element(e);if(!Element.descendantOf(elm,this.domObj.parentNode)){this.hide();return;}
-var a=Event.findElement(e,'A');if(a&&Element.descendantOf(a,this.ul)){this.updateButton(a);this.hide();}},updateButton:function(a){while(this.domLabel.childNodes.length>0){this.domLabel.removeChild(this.domLabel.firstChild);}
-this.domLabel.appendChild(a.firstChild.cloneNode(true));this.selectedItem=a.firstChild;}});Jx.addStyleSheet('color/color.css');Jx.ColorPanel=Class.create();Jx.ColorPanel.prototype={domObj:null,color:null,alpha:null,ccl:null,hexColors:['00','33','66','99','CC','FF'],initialize:function(options){options=options||{};this.keypressWatcher=this.keypressHandler.bind(this);this.ccl=[];this.color=options.color||'#000000';this.alpha=options.alpha||1;this.domObj=document.createElement('div');this.domObj.className='jxColorPanel';var top=document.createElement('div');top.className='jxColorBar';var d=document.createElement('div');d.className='jxColorPreview';this.selectedSwatch=document.createElement('div');d.appendChild(this.selectedSwatch);top.appendChild(d);this.colorInputLabel=document.createElement('label');this.colorInputLabel.className='jxColorLabel';this.colorInputLabel.innerHTML='#';top.appendChild(this.colorInputLabel);this.colorInput=document.createElement('input');this.colorInput.className='jxHexInput';this.colorInput.type='text';this.colorInput.maxLength=6;Event.observe(this.colorInput,'keyup',this.colorChanged.bind(this));Event.observe(this.colorInput,'blur',this.colorChanged.bind(this));Event.observe(this.colorInput,'change',this.colorChanged.bind(this));top.appendChild(this.colorInput);this.alphaLabel=document.createElement('label');this.alphaLabel.className='jxAlphaLabel';this.alphaLabel.innerHTML='alpha (%)';top.appendChild(this.alphaLabel);this.alphaInput=document.createElement('input');this.alphaInput.className='jxAlphaInput';this.alphaInput.type='text';this.alphaInput.maxLength=3;Event.observe(this.alphaInput,'keyup',this.alphaChanged.bind(this));top.appendChild(this.alphaInput);this.domObj.appendChild(top);var a=document.createElement('a');a.href="javascript:void(0)";a.className='jxColorClose';a.alt='Close';a.title='Close';Event.observe(a,'click',this.hide.bind(this));img=document.createElement('img');img.className='png24';img.src=Jx.baseURL+'images/close.png';a.appendChild(img);this.domObj.appendChild(a);d=document.createElement('div');d.className='jxClearer';this.domObj.appendChild(d);var swatchClick=this.swatchClick.bindAsEventListener(this);var swatchOver=this.swatchOver.bindAsEventListener(this);var table=document.createElement('table');table.className='jxColorGrid';var tbody=document.createElement('tbody');table.appendChild(tbody);for(var i=0;i<12;i++){var tr=document.createElement('tr');for(var j=-3;j<18;j++){var bSkip=false;var r,g,b;if(j<0){if(j==-3||j==-1){r=g=b=0;bSkip=true;}else{if(i<6){r=g=b=i;}else{if(i==6){r=5;g=0;b=0;}else if(i==7){r=0;g=5;b=0;}else if(i==8){r=0;g=0;b=5;}else if(i==9){r=5;g=5;b=0;}else if(i==10){r=0;g=5;b=5;}else if(i==11){r=5;g=0;b=5;}}}}else{r=parseInt(i/6)*3+parseInt(j/6);g=j%6;b=i%6;}
-var bgColor='#'+this.hexColors[r]+this.hexColors[g]+this.hexColors[b];var td=document.createElement('td');if(!bSkip){td.style.backgroundColor=bgColor;var a=document.createElement('a');if((r>2&&g>2)||(r>2&&b>2)||(g>2&&b>2)){a.className='colorSwatch borderBlack';}else{a.className='colorSwatch borderWhite';}
-a.href='#';a.title=bgColor;a.alt=bgColor;a.swatchColor=bgColor;a.onmouseover=swatchOver;a.onclick=swatchClick;td.appendChild(a);}else{var span=document.createElement('span');td.className='emptyCell';td.appendChild(span);}
-tr.appendChild(td);}
-tbody.appendChild(tr);}
-this.domObj.appendChild(table);var d=document.createElement('div');d.className='jxColorPreview';this.previewSwatch=document.createElement('div');d.appendChild(this.previewSwatch);this.previewSwatch.style.backgroundColor=this.color;this.domObj.appendChild(d);this.previewLabel=document.createElement('label');this.previewLabel.className='jxColorLabel';this.previewLabel.innerHTML=this.color;this.domObj.appendChild(this.previewLabel);d=document.createElement('div');d.className='jxClearer';this.domObj.appendChild(d);this.updateSelected();},swatchOver:function(e){var a=Event.element(e);this.previewSwatch.style.backgroundColor=a.swatchColor;this.previewLabel.innerHTML=a.swatchColor;},swatchClick:function(e){var a=Event.element(e);this.color=a.swatchColor;this.updateSelected();this.hide();},colorChanged:function(){var color=this.colorInput.value;if(color.substring(0,1)=='#'){color=color.substring(1);}
-if(color.toLowerCase().match(/^[0-9a-f]{6}$/)){this.color='#'+color.toUpperCase();this.updateSelected();}},alphaChanged:function(){var alpha=this.alphaInput.value;if(alpha.match(/^[0-9]{1,3}$/)){this.alpha=parseFloat(alpha/100);this.updateSelected();}},setColor:function(color){this.colorInput.value=color;this.colorChanged();},setAlpha:function(alpha){this.alphaInput.value=alpha;this.alphaChanged();},updateSelected:function(){this.selectedSwatch.style.backgroundColor=this.color;this.colorInput.value=this.color.substring(1);this.alphaInput.value=parseInt(this.alpha*100);if(this.alpha<1){this.selectedSwatch.style.opacity=this.alpha;this.selectedSwatch.style.filter='Alpha(opacity='+(this.alpha*100)+')';}else{this.selectedSwatch.style.opacity='';this.selectedSwatch.style.filter='';}
-this.processEvent(this.ccl,'colorChanged',this);},show:function(){this.domObj.style.display='block';Event.observe(window,'keypress',this.keypressWatcher);},hide:function(){this.domObj.style.display='none';Event.stopObserving(window,'keypress',this.keypressWatcher);},keypressHandler:function(e){var charCode=(e.charCode)?e.charCode:e.keyCode;if(charCode==Event.KEY_ESC){this.hide();}},addColorChangeListener:function(obj){this.addListener(this.ccl,obj);},removeColorChangeListener:function(obj){this.removeListener(this.ccl,obj);}};Object.extend(Jx.ColorPanel.prototype,Jx.Listener.prototype);Jx.Button.Color=Class.create();Object.extend(Jx.Button.Color.prototype,Jx.Button.Flyout.prototype);Object.extend(Jx.Button.Color.prototype,{colorPanel:[],swatch:null,color:null,alpha:null,ccl:null,initialize:function(options){options=options||{};options.label=options.label||' ';this.color=options.color||'#000000';this.alpha=options.alpha||100;this.ccl=[];if(this.colorPanel.length==0){this.colorPanel[0]=new Jx.ColorPanel();}
-var d=document.createElement('div');d.className='jxColorButtonPreview';this.selectedSwatch=document.createElement('div');d.appendChild(this.selectedSwatch);Jx.Button.Flyout.prototype.initialize.apply(this,[options]);Element.addClassName(this.domObj.firstChild,'jxButtonColor');this.domObj.firstChild.firstChild.insertBefore(d,this.domObj.firstChild.firstChild.firstChild);this.updateSwatch();},show:function(){if(this.colorPanel[0].currentButton){this.colorPanel[0].currentButton.hide();}
-this.colorPanel[0].currentButton=this;this.colorPanel[0].addColorChangeListener(this);this.content.appendChild(this.colorPanel[0].domObj);this.colorPanel[0].domObj.style.display='block';Jx.Button.Flyout.prototype.show.apply(this,arguments);this.colorPanel[0].setColor(this.color);this.colorPanel[0].setAlpha(this.alpha);},hide:function(){this.colorPanel[0].removeColorChangeListener(this);Jx.Button.Flyout.prototype.hide.apply(this,arguments);this.colorPanel[0].currentButton=null;},setColor:function(color){this.color=color;this.updateSwatch();},setAlpha:function(alpha){this.alpha=alpha;this.updateSwatch();},colorChanged:function(panel){this.color=panel.color;this.alpha=panel.alpha*100;this.updateSwatch();this.processEvent(this.ccl,'colorChanged',this);},updateSwatch:function(){this.selectedSwatch.style.backgroundColor=this.color;if(this.alpha<100){this.selectedSwatch.style.opacity=this.alpha/100;this.selectedSwatch.style.filter='Alpha(opacity='+(this.alpha)+')';}else{this.selectedSwatch.style.opacity='';this.selectedSwatch.style.filter='';}},addColorChangeListener:function(obj){this.addListener(this.ccl,obj);},removeColorChangeListener:function(obj){this.removeListener(this.ccl,obj);}});Jx.addStyleSheet('dialog/dialog.css');Jx.Dialog=Class.create();Jx.Dialog.prototype={onClose:null,onOpen:null,onChange:null,title:null,content:null,action:null,values:null,actions:null,handler:null,bContentLoaded:null,zIndex:[101],stack:[],blanket:null,firstShow:true,modal:true,initialize:function(options){this.initUniqueId();this.values={};this.actions={};this.handler=options.handler?options.handler:null;if(options.onChange){this.onChange=options.onChange;}
-if(options.onClose){this.onClose=options.onClose;}
-if(options.onOpen){this.onOpen=options.onOpen;}
-if(options.onContentLoaded){this.onContentLoaded=options.onContentLoaded;}
-this.imageBaseUrl=options.imageBaseUrl||Jx.baseURL+"/images/";if(this.imageBaseUrl.slice(-1)!='/'){this.imageBaseUrl+='/';}
-this.modal=typeof options.modal=='undefined'?true:options.modal;var w=options.width||250;var h=options.height||250;var b=(typeof options.bottom!='undefined')?options.bottom:null;var r=(typeof options.right!='undefined')?options.right:null;var t=(typeof options.top!='undefined')?options.top:(b!=null?null:0);var l=(typeof options.left!='undefined')?options.left:(r!=null?null:0);this.blanket=document.createElement('div');this.blanket.className='jxDialogModal';this.blanket.style.display='none';if(!window.opera&&this.modal){var iframe=document.createElement('iframe');iframe.className='jxDialogShim';iframe.scrolling='no';iframe.frameborder=0;this.blanket.appendChild(iframe);if(options.parentObj){$(options.parentObj).appendChild(this.blanket);}else{document.body.appendChild(this.blanket);var temp=new Jx.Layout(this.blanket);temp.resize();}}
-this.dragHandle=document.createElement('div');this.dragHandle.innerHTML=options.title||' ';this.dragHandle.style.width='100%';var domObj=document.createElement('div');domObj.className='jxDialogContainer';this.domObj=domObj;if(options.id){domObj.id=options.id;}
-var dialogObj=document.createElement('div');dialogObj.className='jxDialog';this.innerDialogObj=dialogObj;var titleObj=document.createElement('div');titleObj.className='jxDialogTitle';this.title=titleObj;titleObj.appendChild(this.dragHandle);titleObj.style.visibility='hidden';document.getElementsByTagName('BODY')[0].appendChild(titleObj);this.titleHeight=Element.getBorderBoxSize(titleObj).height;document.getElementsByTagName('BODY')[0].removeChild(titleObj);titleObj.style.visibility='';var contentObj=document.createElement('div');contentObj.className='jxDialogContent';this.content=contentObj;domObj.appendChild(dialogObj);dialogObj.appendChild(titleObj);dialogObj.appendChild(contentObj);new Jx.Layout(dialogObj,{width:w,height:h});new Jx.Layout(titleObj,{top:0,left:0,right:0,bottom:null,height:this.titleHeight,width:null});this.actionHeight=0;if(options.buttons){var actionObj=document.createElement('div');actionObj.className='jxDialogAction';actionObj.style.visibility='hidden';document.getElementsByTagName('BODY')[0].appendChild(actionObj);this.actionHeight=parseInt(Element.getStyle(actionObj,'height'));document.getElementsByTagName('BODY')[0].removeChild(actionObj);actionObj.style.visibility='';dialogObj.appendChild(actionObj);new Jx.Layout(actionObj,{top:null,left:0,right:0,bottom:0,height:this.actionHeight,width:null});this.action=actionObj;this.setButtons(options.buttons);}
-new Jx.Layout(contentObj,{top:this.titleHeight,left:0,right:0,bottom:this.actionHeight});var atag=document.createElement('a');atag.href='javascript:void(0)';atag.className='jxDialogCloseButton';atag.onclick=this.close.bindAsEventListener(this);var close=document.createElement('img');if(options.closeImg){close.src=options.closeImg;}
-else{close.src=this.imageBaseUrl+'icon_close.png';}
-close.alt='Close Dialog';close.title='Close Dialog';atag.appendChild(close);titleObj.appendChild(atag);if(options.helpID||options.helpHTML||options.helpURL||options.help){var atag2=document.createElement('a');atag2.href='javascript:void(0)';atag2.className='jxDialogHelpButton';atag2.onclick=this.toggleHelp.bindAsEventListener(this);var help=document.createElement('img');help.src=this.imageBaseUrl+'icon_quickhelp.png';help.alt='Help';help.title='Help';atag2.appendChild(help);titleObj.appendChild(atag2);this.help=document.createElement('div');this.help.className='jxDialogHelp';this.help.style.display='none';this.help.isVisible=false;var helpOpts={};helpOpts.contentID=options.helpID;helpOpts.content=options.help;helpOpts.contentURL=options.helpURL;helpOpts.contentHTML=options.helpHTML;helpOpts.onContentLoaded=this.onHelpContentLoaded.bind(this);this.loadContent(this.help,helpOpts);dialogObj.appendChild(this.help);}
-var contentOpts={};contentOpts.contentID=options.contentID;contentOpts.content=options.content;contentOpts.contentURL=options.contentURL;contentOpts.contentHTML=options.contentHTML;contentOpts.onContentLoaded=this.onDialogContentLoaded.bind(this);this.loadContent(contentObj,contentOpts);dialogObj.style.visibility='hidden';document.body.appendChild(dialogObj);dialogObj.resize();this.dialogBoxSize=Element.getBorderBoxSize(dialogObj);this.dialogBoxMargins=Element.getMarginSize(dialogObj);var containerSize={width:this.dialogBoxSize.width,height:this.dialogBoxSize.height};containerSize.width+=this.dialogBoxMargins.left+this.dialogBoxMargins.right;containerSize.height+=this.dialogBoxMargins.top+this.dialogBoxMargins.bottom;document.body.removeChild(dialogObj);dialogObj.style.visibility='';domObj.appendChild(dialogObj);domObj.style.display="none";Element.setBorderBoxSize(domObj,{width:(containerSize.width),height:(containerSize.height)});domObj.style.position='absolute';if(t!=null){domObj.style.top=(t)+'px';}else{domObj.style.bottom=(b)+'px';}
-if(l!=null){domObj.style.left=(l)+'px';}else{domObj.style.right=(r)+'px';}
-if(options.parentObj){$(options.parentObj).appendChild(domObj);}else{document.body.appendChild(domObj);}
-this.DTOffset=0;this.DBOffset=0;this.DROffset=0;this.DLOffset=0;this.decorationOffsets={top:0,right:0,bottom:0,left:0};var imgContainer=document.createElement('div');imgContainer.className='jxDialogBgTL';var img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_tl.png';img.className='png24';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.decorationOffsets.top+=parseInt(Element.getStyle(img,'width'));this.decorationOffsets.left+=parseInt(Element.getStyle(img,'height'));imgContainer=document.createElement('div');imgContainer.className='jxDialogBgTR';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_tr.png';img.className='png24';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.decorationOffsets.top+=parseInt(Element.getStyle(img,'width'));this.decorationOffsets.right+=parseInt(Element.getStyle(img,'height'));imgContainer=document.createElement('div');imgContainer.className='jxDialogBgBR';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_br.png';img.className='png24';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.decorationOffsets.bottom+=parseInt(Element.getStyle(img,'width'));this.decorationOffsets.right+=parseInt(Element.getStyle(img,'height'));imgContainer=document.createElement('div');imgContainer.className='jxDialogBgBL';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_bl.png';img.className='png24';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.decorationOffsets.bottom+=parseInt(Element.getStyle(img,'width'));this.decorationOffsets.left+=parseInt(Element.getStyle(img,'height'));imgContainer=document.createElement('div');imgContainer.className='jxDialogBgT';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_t.png';img.className='png24';img.style.width=containerSize.width-this.decorationOffsets.top+'px';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.topImg=img;imgContainer=document.createElement('div');imgContainer.className='jxDialogBgB';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_b.png';img.className='png24';img.style.width=containerSize.width-this.decorationOffsets.bottom+'px';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.bottomImg=img;imgContainer=document.createElement('div');imgContainer.className='jxDialogBgL';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_l.png';img.className='png24';img.style.height=containerSize.height-this.decorationOffsets.left+'px';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.leftImg=img;imgContainer=document.createElement('div');imgContainer.className='jxDialogBgR';img=document.createElement('img');img.src=this.imageBaseUrl+'dialog_glow_r.png';img.className='png24';img.style.height=containerSize.height-this.decorationOffsets.right+'px';imgContainer.appendChild(img);domObj.appendChild(imgContainer);this.rightImg=img;Event.observe(domObj,'mousedown',this.mouseDown.bind(this));Event.observe(this.title,'mousedown',this.mouseDown.bind(this));if(options.resizeable){this.resizeHandle=document.createElement('div');this.resizeHandle.className='jxDialogResize';this.resizeHandle.style.position='absolute';this.domObj.appendChild(this.resizeHandle);this.resizeHandleSize={width:parseInt(Element.getStyle(this.resizeHandle,'width')),height:parseInt(Element.getStyle(this.resizeHandle,'height'))};this.resizeHandle.style.top=(containerSize.height-this.resizeHandleSize.height)+'px';this.resizeHandle.style.left=(containerSize.width-this.resizeHandleSize.width)+'px';new Draggable(this.resizeHandle,{starteffect:false,endeffect:false,change:this.ondrag.bind(this),zindex:0});}
-this.bOpen=false;},mouseDown:function(){for(var i=0;i<this.stack.length;i++){if(this.stack[i]==this){this.stack.splice(i,1);this.stack.push(this);}}
-for(var i=0;i<this.stack.length;i++){this.stack[i].domObj.style.zIndex=(101+i);}},ondrag:function(obj){this.mouseDown();var delta=obj.currentDelta();var deltaX=delta[0]+this.resizeHandleSize.width;var deltaY=delta[1]+this.resizeHandleSize.height;this.resize({width:deltaX,height:deltaY});},resize:function(newSize){this.innerDialogObj.resize(newSize);if(newSize.width){var outerWidth=newSize.width;Element.setBorderBoxSize(this.domObj,{width:outerWidth});Element.setBorderBoxSize(this.topImg,{width:outerWidth-this.decorationOffsets.top});Element.setBorderBoxSize(this.bottomImg,{width:outerWidth-this.decorationOffsets.bottom});}
-if(newSize.height){var outerHeight=newSize.height;Element.setBorderBoxSize(this.domObj,{height:outerHeight});Element.setBorderBoxSize(this.leftImg,{height:outerHeight-this.decorationOffsets.left});Element.setBorderBoxSize(this.rightImg,{height:outerHeight-this.decorationOffsets.right});if(this.help){Element.setBorderBoxSize(this.help,{height:newSize.height-this.titleHeight});}}},setTitle:function(title){this.title.childNodes[0].innerHTML=title;},setButtons:function(buttons){this.action.innerHTML='';for(var i=0;i<buttons.length;i++){var button=document.createElement('input');button.id=buttons[i];button.type='button';button.className='normalButton';button.name=buttons[i];button.value=buttons[i];button.onclick=this.buttonHandler.bind(this,button);this.action.appendChild(button);this.uniqueIdRefs[button.id]=button;}},processInputs:function(obj){for(var i=0;i<obj.childNodes.length;i++){var node=obj.childNodes[i];if(node.tagName=='INPUT'||node.tagName=='SELECT'||node.tagName=='TEXTAREA'){if(node.type=='button'){this.actions[node.id]=node;node.onclick=this.buttonHandler.bind(this,node);}else{this.values[node.id]=node;if(this.onChange){node.onchange=this.onChangeHandler.bind(this,node);}}}else{if(node.childNodes){this.processInputs(node);}}}},buttonHandler:function(input,event){if(this.handler){this.handler(input.value,this);}},onChangeHandler:function(input,event){if(this.onChange){this.onChange(input,this);}},getValue:function(name){var result='';var input=this.values[name];if(input){switch(input.tagName){case'INPUT':result=input.value;break;case'SELECT':result=input.options[input.selectedIndex].value;}}
-return result;},setValue:function(name,value){if(typeof this.values[name]!='undefined'){if(this.values[name].type=='text'||this.values[name].type=='hidden'){this.values[name].value=value;}}},show:function(){this.stack.push(this);if(this.modal){this.blanket.style.zIndex=this.zIndex[0]++;this.blanket.style.visibility='visible';this.blanket.style.display='block';}
-this.domObj.style.zIndex=this.zIndex[0]++;Effect.Appear(this.domObj,{duration:0.1});this.domObj.style.display='block';new Draggable(this.domObj,{handle:this.dragHandle,starteffect:false,endeffect:false});this.content.resize({forceResize:this.firstShow});this.firstShow=false;},hide:function(){for(var i=0;i<this.stack.length;i++){if(this.stack[i]==this){this.stack.splice(i,1);}}
-this.zIndex[0]--;Effect.Fade(this.domObj,{duration:0.3});if(this.modal){this.blanket.style.visibility='hidden';this.zIndex[0]--;}},open:function(){if(!this.bOpen){this.bOpen=true;}
-if(this.bContentLoaded){this.show();if(this.onOpen)this.onOpen();}},close:function(){this.bOpen=false;this.hide();if(this.onClose)this.onClose();},onDialogContentLoaded:function(){this.processInputs(this.content);if(this.onContentLoaded){this.onContentLoaded(this);}
-if(this.bOpen){this.open();this.bOpen=false;}},onHelpContentLoaded:function(){var img=document.createElement('img');img.className='jxDialogHelpCloseButton png24';img.src=this.imageBaseUrl+'help_close.png';img.onclick=this.toggleHelp.bind(this);img.alt='Close Help';img.title='Close Help';this.help.appendChild(img);},toggleHelp:function(){if(this.help.isVisible){Effect.Fade(this.help,{duration:0.3});}else{var actionSize=this.action?Element.getBorderBoxSize(this.action):{width:0,height:0};var contentSize=Element.getBorderBoxSize(this.content);Element.setBorderBoxSize(this.help,{height:contentSize.height+actionSize.height});Effect.Appear(this.help,{duration:0.3});}
-this.help.isVisible=!this.help.isVisible;}};Object.extend(Jx.Dialog.prototype,Jx.UniqueId.prototype);Object.extend(Jx.Dialog.prototype,Jx.ContentLoader.prototype);Jx.addStyleSheet('grid/grid.css');Jx.Grid=Class.create();Jx.Grid.prototype={domObj:null,model:null,initialize:function(domObj,options){this.domObj=$(domObj);if(!this.domObj.jxLayout){new Jx.Layout(this.domObj);}
-this.domObj.jxLayout.addSizeChangeListener(this);options=options||{};this.rowColObj=document.createElement('div');this.rowColObj.className='jxGridContainer';this.colObj=document.createElement('div');this.colObj.className='jxGridContainer';this.colTable=document.createElement('table');this.colTable.className='jxGridTable';this.colTableHead=document.createElement('thead');this.colTable.appendChild(this.colTableHead);this.colTableBody=document.createElement('tbody');this.colTable.appendChild(this.colTableBody);this.colObj.appendChild(this.colTable);this.rowObj=document.createElement('div');this.rowObj.className='jxGridContainer';this.rowTable=document.createElement('table');this.rowTable.className='jxGridTable';this.rowTableHead=document.createElement('thead');this.rowTable.appendChild(this.rowTableHead);this.rowObj.appendChild(this.rowTable);this.gridObj=document.createElement('div');this.gridObj.className='jxGridContainer';this.gridObj.style.overflow='scroll';this.gridTable=document.createElement('table');this.gridTable.className='jxGridTable';this.gridTableBody=document.createElement('tbody');this.gridTable.appendChild(this.gridTableBody);this.gridObj.appendChild(this.gridTable);this.domObj.appendChild(this.rowColObj);this.domObj.appendChild(this.rowObj);this.domObj.appendChild(this.colObj);this.domObj.appendChild(this.gridObj);this.bAlternateRowColors=options.alternateRowColors||false;this.showRowHeader=options.rowHeaders||false;this.showColumnHeader=options.columnHeaders||false;this.rowSelection=options.rowSelection||false;this.cellSelection=options.cellSelection||false;Event.observe(this.gridObj,'scroll',this.onScroll.bind(this));Event.observe(this.gridObj,'click',this.onClickGrid.bindAsEventListener(this));Event.observe(this.rowObj,'click',this.onClickRowHeader.bindAsEventListener(this));Event.observe(this.colObj,'click',this.onClickColumnHeader.bindAsEventListener(this));Event.observe(this.gridObj,'mousemove',this.onMouseMoveGrid.bindAsEventListener(this));Event.observe(this.rowObj,'mousemove',this.onMouseMoveRowHeader.bindAsEventListener(this));Event.observe(this.colObj,'mousemove',this.onMouseMoveColumnHeader.bindAsEventListener(this));},onScroll:function(){this.colObj.scrollLeft=this.gridObj.scrollLeft;this.rowObj.scrollTop=this.gridObj.scrollTop;},sizeChanged:function(){this.resize();},resize:function(){if(!this.model){return;}
-var colHeight=this.showColumnHeader?this.model.getColumnHeaderHeight():1;var rowWidth=this.showRowHeader?this.model.getRowHeaderWidth():1;var size=Element.getContentBoxSize(this.domObj);this.rowColObj.style.width=(rowWidth-1)+'px';this.rowColObj.style.height=(colHeight-1)+'px';this.rowObj.style.top=(colHeight)+'px';this.rowObj.style.left='0px';this.rowObj.style.width=(rowWidth-1)+'px';this.rowObj.style.height=(size.height-colHeight-1)+'px';this.colObj.style.top='0px';this.colObj.style.left=(rowWidth)+'px';this.colObj.style.width=(size.width-rowWidth-1)+'px';this.colObj.style.height=(colHeight-1)+'px';this.gridObj.style.top=(colHeight)+'px';this.gridObj.style.left=(rowWidth)+'px';this.gridObj.style.width=(size.width-rowWidth-1)+'px';this.gridObj.style.height=(size.height-colHeight-1)+'px';},setModel:function(model){if(this.model){this.model.removeGridListener(this);}
-this.model=model;if(this.model){this.domObj.jxLayout.resize();this.model.addGridListener(this);this.createGrid();this.resize();}else{this.destroyGrid();}},destroyGrid:function(){var n=this.colTableHead.cloneNode(false);this.colTable.replaceChild(n,this.colTableHead);this.colTableHead=n;n=this.colTableBody.cloneNode(false);this.colTable.replaceChild(n,this.colTableBody);this.colTableBody=n;n=this.rowTableHead.cloneNode(false);this.rowTable.replaceChild(n,this.rowTableHead);this.rowTableHead=n;n=this.gridTableBody.cloneNode(false);this.gridTable.replaceChild(n,this.gridTableBody);this.gridTableBody=n;},createGrid:function(){this.destroyGrid();if(this.model){var model=this.model;var nColumns=model.getColumnCount();var nRows=model.getRowCount();if(this.showColumnHeader){var colHeight=model.getColumnHeaderHeight();var trHead=document.createElement('tr');this.colTableHead.appendChild(trHead);var trBody=document.createElement('tr');this.colTableBody.appendChild(trBody);var th=document.createElement('th');th.style.width='0px';th.style.height='0px';trHead.appendChild(th);th=th.cloneNode(true);th.style.height=(colHeight)+'px';trBody.appendChild(th);for(var i=0;i<nColumns;i++){var colWidth=model.getColumnWidth(i);th=document.createElement('th');th.className='jxGridColHeadHide';th.style.width=(colWidth)+'px';var p=document.createElement('p');p.style.height='0px';p.style.width=(colWidth)+'px';th.appendChild(p);trHead.appendChild(th);th=document.createElement('th');th.className='jxGridColHead';th.innerHTML=model.getColumnHeaderHTML(i);trBody.appendChild(th);}
-var th=document.createElement('th');th.style.width='1000px';th.style.height='0px';trHead.appendChild(th);th=th.cloneNode(true);th.style.height=(colHeight-1)+'px';th.className='jxGridColHead';trBody.appendChild(th);}
-if(this.showRowHeader){var rowWidth=model.getRowHeaderWidth();var tr=document.createElement('tr');var td=document.createElement('td');td.style.width='0px';td.style.height='0px';tr.appendChild(td);var th=document.createElement('th');th.style.width=(rowWidth)+'px';th.style.height='0px';tr.appendChild(th);this.rowTableHead.appendChild(tr);for(var i=0;i<nRows;i++){var rowHeight=model.getRowHeight(i);var tr=document.createElement('tr');var td=document.createElement('td');td.className='jxGridRowHeadHide';td.style.width='0px';td.style.height=(rowHeight)+'px';var p=document.createElement('p');p.style.width='0px';p.style.height=(rowHeight)+'px';td.appendChild(p);tr.appendChild(td);var th=document.createElement('th');th.className='jxGridRowHead';th.innerHTML=model.getRowHeaderHTML(i);tr.appendChild(th);this.rowTableHead.appendChild(tr);}
-var tr=document.createElement('tr');var td=document.createElement('td');td.style.width='0px';td.style.height='1000px';tr.appendChild(td);var th=document.createElement('th');th.style.width=(rowWidth)+'px';th.style.height='1000px';th.className='jxGridRowHead';tr.appendChild(th);this.rowTableHead.appendChild(tr);}
-var colHeight=model.getColumnHeaderHeight();var trBody=document.createElement('tr');this.gridTableBody.appendChild(trBody);var td=document.createElement('td');td.style.width='0px';td.style.height='0px';trBody.appendChild(td);for(var i=0;i<nColumns;i++){var colWidth=model.getColumnWidth(i);td=document.createElement('td');td.className='jxGridColHeadHide';td.style.width=(colWidth)+'px';var p=document.createElement('p');p.style.height='0px';p.style.width=(colWidth)+'px';td.appendChild(p);trBody.appendChild(td);}
-for(var j=0;j<nRows;j++){var rowHeight=model.getRowHeight(j);var actualRowHeight=rowHeight;var tr=document.createElement('tr');this.gridTableBody.appendChild(tr);var td=document.createElement('td');td.className='jxGridRowHeadHide';td.style.width='0px';td.style.height=(rowHeight)+'px';var p=document.createElement('p');p.style.height=(rowHeight)+'px';td.appendChild(p);tr.appendChild(td);for(var i=0;i<nColumns;i++){var colWidth=model.getColumnWidth(i);td=document.createElement('td');td.className='jxGridCell';td.innerHTML=model.getValueAt(j,i);tr.appendChild(td);var tdSize=Element.getDimensions(td);if(tdSize.height>actualRowHeight){actualRowHeight=tdSize.height;}}
-if(document.all){actualRowHeight-=1;}
-if(this.showRowHeader){this.setRowHeaderHeight(j,actualRowHeight);}
-if(this.bAlternateRowColors){tr.className=(j%2)?'jxGridRowOdd':'jxGridRowEven';}else{tr.className='jxGridRowAll';}}}},setRowHeaderHeight:function(row,height){this.rowTableHead.childNodes[row+1].childNodes[0].childNodes[0].style.height=(height)+'px';},gridChanged:function(model,row,col,value){if(this.model==model){this.gridObj.childNodes[row].childNodes[col].innerHTML=value;}},prelightRowHeader:function(row){var cell=(row>=0&&row<this.rowTableHead.rows.length-1)?this.rowTableHead.rows[row+1].cells[1]:null;if(this.prelitRowHeader!=cell){if(this.prelitRowHeader){Element.removeClassName(this.prelitRowHeader,'jxGridRowHeaderPrelight');}
-this.prelitRowHeader=cell;if(this.prelitRowHeader){Element.addClassName(this.prelitRowHeader,'jxGridRowHeaderPrelight');}}},prelightColumnHeader:function(col){if(this.colTableBody.rows.length==0){return;}
-var cell=(col>=0&&col<this.colTableBody.rows[0].cells.length-1)?this.colTableBody.rows[0].cells[col+1]:null;if(this.prelitColumnHeader!=cell){if(this.prelitColumnHeader){Element.removeClassName(this.prelitColumnHeader,'jxGridColumnHeaderPrelight');}
-this.prelitColumnHeader=cell;if(this.prelitColumnHeader){Element.addClassName(this.prelitColumnHeader,'jxGridColumnHeaderPrelight');}}},prelightRow:function(row){var tr=(row>=0&&row<this.gridTableBody.rows.length-1)?this.gridTableBody.rows[row+1]:null;if(this.prelitRow!=row){if(this.prelitRow){Element.removeClassName(this.prelitRow,'jxGridRowPrelight');}
-this.prelitRow=tr;if(this.prelitRow&&!Element.hasClassName(this.prelitRow,'jxGridRowSelected')){this.prelightRowHeader(row);Element.addClassName(this.prelitRow,'jxGridRowPrelight');}}},prelightColumn:function(col){this.prelightColumnHeader(col);},prelightCell:function(row,col){var td=(row>=0&&col>=0&&row<this.gridTableBody.rows.length-1&&col<this.gridTableBody.rows[row+1].cells.length-1)?this.gridTableBody.rows[row+1].cells[col+1]:null;if(this.prelitCell!=td){if(this.prelitCell){Element.removeClassName(this.prelitCell,'jxGridCellPrelight');}
-this.prelitCell=td;if(this.prelitCell){Element.addClassName(this.prelitCell,'jxGridCellPrelight');this.prelightRow(row);this.prelightColumn(col);}}},selectCell:function(row,col){var td=(row>=0&&col>=0&&row<this.gridTableBody.rows.length-1&&col<this.gridTableBody.rows[row+1].cells.length-1)?this.gridTableBody.rows[row+1].cells[col+1]:null;if(!td){return;}
-if(this.selectedCell){Element.addClassName(this.selectedCell,'jxGridCellSelected');}else{Element.removeClassName(this.selectedCell,'jxGridCellSelected');}},selectRowHeader:function(row,selected){var cell=(row>=0&&row<this.rowTableHead.rows.length-1)?this.rowTableHead.rows[row+1].cells[1]:null;if(!cell){return;}
-if(selected){Element.addClassName(cell,'jxGridRowHeaderSelected');}else{Element.removeClassName(cell,'jxGridRowHeaderSelected');}},selectRow:function(row,selected){var tr=(row>=0&&row<this.gridTableBody.rows.length-1)?this.gridTableBody.rows[row+1]:null;if(tr){if(selected){Element.addClassName(tr,'jxGridRowSelected');}else{Element.removeClassName(tr,'jxGridRowSelected');}}
-this.selectRowHeader(row,selected);},selectColumnHeader:function(col,selected){if(this.colTableBody.rows.length==0){return;}
-var cell=(col>=0&&col<this.colTableBody.rows[0].cells.length-1)?this.colTableBody.rows[0].cells[col+1]:null;if(cell==null){return;}
-if(selected){Element.addClassName(cell,'jxGridColumnHeaderSelected');}else{Element.removeClassName(cell,'jxGridColumnHeaderSelected');}},selectColumn:function(col,selected){if(col>=0&&col<this.gridTable.rows[0].cells.length){if(selected){for(var i=0;i<this.gridTable.rows.length;i++){Element.removeClassName(this.gridTable.rows[i].cells[this.selectedColumn+1],'jxGridColumnSelected');}}else{for(var i=0;i<this.gridTable.rows.length;i++){Element.addClassName(this.gridTable.rows[i].cells[col+1],'jxGridColumnSelected');}}}
-this.selectColumnHeader(col,selected);},onMouseMoveGrid:function(e){var rc=this.getRowColumnFromEvent(e);this.prelightCell(rc.row,rc.column);},onMouseMoveRowHeader:function(e){var rc=this.getRowColumnFromEvent(e);this.prelightRow(rc.row);},onMouseMoveColumnHeader:function(e){var rc=this.getRowColumnFromEvent(e);this.prelightColumn(rc.column);},onClickGrid:function(e){var rc=this.getRowColumnFromEvent(e);if(this.model.cellSelected){this.model.cellSelected(this,rc.row,rc.column);}},onClickRowHeader:function(e){var rc=this.getRowColumnFromEvent(e);if(this.model.rowSelected){this.model.rowSelected(this,rc.row);}},onClickColumnHeader:function(e){var rc=this.getRowColumnFromEvent(e);if(this.model.columnSelected){this.model.columnSelected(this,rc.column);}},getRowColumnFromEvent:function(e){var td=Event.element(e);if(td.tagName!='TD'&&td.tagName!='TH'){return{row:-1,column:-1};}
-var tr=td.parentNode;var col=td.cellIndex-1;var row=tr.rowIndex-1;if(col==-1){for(var i=0;i<tr.childNodes.length;i++){if(tr.childNodes[i]==td){col=i-1;break;}}}
-return{row:row,column:col};}};Jx.Layout=Class.create();Jx.Layout.prototype={scl:null,initialize:function(domObj,options){options=options||{};this.options=new Jx.Constraint(options);this.domObj=$(domObj);this.domObj.resize=this.resize.bind(this);this.domObj.style.position=this.options.position;this.domObj.jxLayout=this;if(this.domObj.parentNode&&this.domObj.parentNode.tagName=='BODY'){Event.observe(window,'resize',this.windowResize.bind(this));}
-this.scl=[];},windowResize:function(){if(this.resizeTimer){window.clearTimeout(this.resizeTimer);this.resizeTimer=null;}
-this.resizeTimer=window.setTimeout(this.resize.bind(this),250);},resize:function(options){this.resizeTimer=null;var needsResize=false;if(options){for(var i in options){if(this.options[i]!=options[i]){needsResize=true;this.options[i]=options[i];}}
-if(options.forceResize){needsResize=true;}}
-var parentSize;if(this.domObj.parentNode.tagName=='BODY'){parentSize=Element.getPageDimensions();}else{parentSize=Element.getContentBoxSize(this.domObj.parentNode);}
-if(this.lastParentSize&&!needsResize){needsResize=(this.lastParentSize.width!=parentSize.width||this.lastParentSize.height!=parentSize.height);}else{needsResize=true;}
-this.lastParentSize=parentSize;if(!needsResize){return;}
-var l,t,w,h;if(this.options.left!=null){l=this.options.left;if(this.options.right==null){if(this.options.width==null){w=parentSize.width-l;if(w<this.options.minWidth){w=this.options.minWidth;}
-if(this.options.maxWidth>=0&&w>this.options.maxWidth){w=this.options.maxWidth;}}else{w=this.options.width;}}else{if(this.options.width==null){w=parentSize.width-l-this.options.right;if(w<this.options.minWidth){w=this.options.minWidth;}
-if(this.options.maxWidth>=0&&w>this.options.maxWidth){w=this.options.maxWidth;}}else{w=this.options.width;}}}else{if(this.options.right==null){if(this.options.width==null){l=0;w=parentSize.width;if(this.options.maxWidth>=0&&w>this.options.maxWidth){l=l+parseInt(w-this.options.maxWidth)/2;w=this.options.maxWidth;}}else{w=this.options.width;l=parseInt((parentSize.width-w)/2);if(l<0){l=0;}}}else{if(this.options.width!=null){w=this.options.width;l=parentSize.width-w-this.options.right;if(l<0){l=0;}}else{l=0;w=parentSize.width-this.options.right;if(w<this.options.minWidth){w=this.options.minWidth;}
-if(this.options.maxWidth>=0&&w>this.options.maxWidth){l=w-this.options.maxWidth-this.options.right;w=this.options.maxWidth;}}}}
-if(this.options.top!=null){t=this.options.top;if(this.options.bottom==null){if(this.options.height==null){h=parentSize.height-t;if(h<this.options.minHeight){h=this.options.minHeight;}
-if(this.options.maxHeight>=0&&h>this.options.maxHeight){h=this.options.maxHeight;}}else{h=this.options.height;if(this.options.maxHeight>=0&&h>this.options.maxHeight){t=h-this.options.maxHeight;h=this.options.maxHeight;}}}else{if(this.options.height==null){h=parentSize.height-t-this.options.bottom;if(h<this.options.minHeight){h=this.options.minHeight;}
-if(this.options.maxHeight>=0&&h>this.options.maxHeight){h=this.options.maxHeight;}}else{h=this.options.height;}}}else{if(this.options.bottom==null){if(this.options.height==null){t=0;h=parentSize.height;if(h<this.options.minHeight){h=this.options.minHeight;}
-if(this.options.maxHeight>=0&&h>this.options.maxHeight){t=parseInt((parentSize.height-this.options.maxHeight)/2);h=this.options.maxHeight;}}else{h=this.options.height;t=parseInt((parentSize.height-h)/2);if(t<0){t=0;}}}else{if(this.options.height!=null){h=this.options.height;t=parentSize.height-h-this.options.bottom;if(t<0){t=0;}}else{t=0;h=parentSize.height-this.options.bottom;if(h<this.options.minHeight){h=this.options.minHeight;}
-if(this.options.maxHeight>=0&&h>this.options.maxHeight){t=parentSize.height-this.options.maxHeight-this.options.bottom;h=this.options.maxHeight;}}}}
-this.domObj.style.position=this.options.position;if(this.options.position=='absolute'){var padding=Element.getPaddingSize(this.domObj.parentNode);this.domObj.style.left=(l+padding.left)+'px';this.domObj.style.top=(t+padding.top)+'px';Element.setBorderBoxSize(this.domObj,{width:w,height:h});}else{var sizeOpts={width:w};if(this.options.height){sizeOpts.height=this.options.height;}
-Element.setBorderBoxSize(this.domObj,sizeOpts);}
-var o={forceResize:options?options.forceResize:false};for(var i=0;i<this.domObj.childNodes.length;i++){var c=this.domObj.childNodes[i];if(c.resize){c.resize(o);}}
-this.processEvent(this.scl,'sizeChanged',this);},addSizeChangeListener:function(obj){this.addListener(this.scl,obj);},removeSizeChangeListener:function(o){this.removeListener(this.scl,o);}};Object.extend(Jx.Layout.prototype,Jx.Listener.prototype);Jx.Constraint=Class.create();Jx.Constraint.prototype={position:'absolute',left:0,right:0,top:0,bottom:0,width:null,height:null,minWidth:0,minHeight:0,maxWidth:-1,maxHeight:-1,initialize:function(o){for(var i in o){this[i]=o[i];}}};Jx.addStyleSheet('menu/menu.css');Jx.addStyleSheet('button/button.css');Jx.MenuItem=Class.create();Object.extend(Jx.MenuItem.prototype,Jx.Listener.prototype);Object.extend(Jx.MenuItem.prototype,{al:null,domObj:null,parent:null,enabled:false,button:null,initialize:function(action,options){this.initializeItem(options);action.bindTo(this);this.propertyChanged(action);},initializeItem:function(options){if(!options.image){options.image=Jx.baseURL+'images/a_pixel.png';}
-if(!options.label){options.label=' ';}
-this.label=options.label||' ';this.image=options.image||null;this.al=[];this.domObj=document.createElement('li');this.domObj.className='jxMenuItem';var action=new Jx.Action(this.processActionEvent.bindAsEventListener(this))
-this.button=new Jx.Button(action,options);Event.observe(this.button.domObj,'mouseover',this.onmouseover.bindAsEventListener(this),true);this.domObj.appendChild(this.button.domObj);},setParent:function(obj){this.parent=obj;},hide:function(){},show:function(){},addActionListener:function(obj){this.addListener(this.al,obj);},removeActionListener:function(obj){this.removeListener(this.al,obj);},processActionEvent:function(e){if(this.enabled){this.processEvent(this.al,'actionPerformed',this);if(this.parent&&this.parent.deactivate){this.parent.deactivate(e);}}},propertyChanged:function(obj){this.enabled=obj.isEnabled();if(this.enabled){Element.removeClassName(this.domObj.childNodes[0].childNodes[0],'jxDisabled');}else{Element.addClassName(this.domObj.childNodes[0].childNodes[0],'jxDisabled');}},onmouseover:function(e){var target=Event.element(e);if(this.parent&&this.parent.setVisibleItem){this.parent.setVisibleItem(this);}
-this.show();}});Jx.MenuSeparator=Class.create();Object.extend(Jx.MenuSeparator.prototype,{domObj:null,parent:null,initialize:function(){this.domObj=document.createElement('li');this.domObj.className='jxMenuItem';var span=document.createElement('span');span.className='jxMenuSeparator';span.innerHTML=' ';this.domObj.appendChild(span);},setParent:function(obj){this.parent=obj;},hide:function(){},show:function(){}});Jx.SubMenu=Class.create();Object.extend(Jx.SubMenu.prototype,Jx.MenuItem.prototype);Object.extend(Jx.SubMenu.prototype,{subDomObj:null,parent:null,visibleItem:null,items:null,initialize:function(options){this.open=false;this.items=[];this.initializeItem(options);Element.addClassName(this.domObj.childNodes[0].childNodes[0],'jxButtonSubMenu');this.iframe=document.createElement('iframe');this.iframe.className='jxMenuShim';this.iframe.scrolling='no';this.iframe.frameborder=0;this.subDomObj=document.createElement('ul');this.subDomObj.className='jxSubMenu';this.subDomObj.style.display='none';this.domObj.appendChild(this.subDomObj);},setParent:function(obj){this.parent=obj;},show:function(){if(this.open||this.items.length==0){return;}
-this.open=true;this.subDomObj.style.display='block';if(!window.opera){this.subDomObj.childNodes[0].appendChild(this.iframe);var size=Element.getBorderBoxSize(this.subDomObj);this.iframe.style.width=size.width+"px";this.iframe.style.height=size.height+"px";}
-this.setActive(true);},hide:function(){if(!this.open){return;}
-this.open=false;for(var i=0;i<this.items.length;i++){this.items[i].hide();}
-this.subDomObj.style.display='none';if(!window.opera&&this.iframe.parentNode){this.subDomObj.childNodes[0].removeChild(this.iframe);}
-this.visibleItem=null;},add:function(){for(var i=0;i<arguments.length;i++){var item=arguments[i];this.items.push(item);item.setParent(this);this.subDomObj.appendChild(item.domObj);}},insertBefore:function(newItem,targetItem){var bInserted=false;for(var i=0;i<this.items.length;i++){if(this.items[i]==targetItem){this.items.splice(i,0,newItem);this.subDomObj.insertBefore(newItem.domObj,targetItem.domObj);bInserted=true;break;}}
-if(!bInserted){this.add(newItem);}},remove:function(item){for(var i=0;i<this.items.length;i++){if(this.items[i]==item){this.items.splice(i,1);this.subDomObj.removeChild(item.domObj);break;}}},processActionEvent:function(e){if(this.open){this.hide();}else{this.show();}
-return Event.stop(e);},deactivate:function(e){if(this.parent){this.parent.deactivate(e);}},isActive:function(){if(this.parent){return this.parent.isActive();}else{return false;}},setActive:function(isActive){if(this.parent&&this.parent.setActive){this.parent.setActive(isActive);}},setVisibleItem:function(obj){if(this.visibleItem!=obj){if(this.visibleItem&&this.visibleItem.hide){this.visibleItem.hide();}
-this.visibleItem=obj;this.visibleItem.show();}}});Jx.Menu=Class.create();Jx.Menu.prototype={domObj:null,buttonObj:null,subDomObj:null,items:null,menus:[],initialize:function(options){this.items=[];this.iframe=document.createElement('iframe');this.iframe.className='jxMenuShim';this.iframe.scrolling='no';this.iframe.frameborder=0;this.subDomObj=document.createElement('ul');this.subDomObj.className='jxMenu';this.subDomObj.style.display='none';if(options){this.domObj=document.createElement('li');var action=new Jx.Action(this.show.bind(this));this.button=new Jx.Button(action,options);Element.addClassName(this.button.domObj.firstChild,'jxButtonMenu');this.domObj.appendChild(this.button.domObj);Event.observe(this.domObj,'mouseover',this.onMouseOver.bindAsEventListener(this));this.domObj.appendChild(this.subDomObj);}
-this.hideWatcher=this.hide.bindAsEventListener(this);},add:function(){for(var i=0;i<arguments.length;i++){var item=arguments[i];this.items.push(item);item.setParent(this);this.subDomObj.appendChild(item.domObj);}},deactivate:function(){this.hide();},actionPerformed:function(){this.hide();},onMouseOver:function(e){if(this.menus[0]&&this.menus[0]!=this){this.show(e);}},hide:function(e){if(e){var root=Event.findElement(e,'LI');if(root==this.domObj){return;}}
-if(this.menus[0]&&this.menus[0]==this){this.menus[0]=null;}
-for(var i=0;i<this.items.length;i++){this.items[i].hide(e);}
-Event.stopObserving(document,'click',this.hideWatcher,true);this.subDomObj.style.display='none';},show:function(e){if(this.menus[0]&&this.menus[0]!=this){this.menus[0].hide(e);}
-if(this.items.length==0){return;}
-this.menus[0]=this;this.subDomObj.style.display='block';this.subDomObj.style.visibility='visible';if(!window.opera){this.subDomObj.childNodes[0].appendChild(this.iframe);var size=Element.getContentBoxSize(this.subDomObj);this.iframe.style.width=size.width+"px";this.iframe.style.height=size.height+"px";}
-Event.stop(e);Event.observe(document,'click',this.hideWatcher,true);},setVisibleItem:function(obj){if(this.visibleItem!=obj){if(this.visibleItem&&this.visibleItem.hide){this.visibleItem.hide();}
-this.visibleItem=obj;this.visibleItem.show();}}};Jx.ContextMenu=Class.create();Object.extend(Jx.ContextMenu.prototype,Jx.Menu.prototype);Object.extend(Jx.ContextMenu.prototype,{initialize:function(id){Jx.Menu.prototype.initialize.apply(this,[]);document.getElementsByTagName('BODY')[0].appendChild(this.subDomObj);if($(id)){$(id).oncontextmenu=this.show.bindAsEventListener(this);;}},show:function(e){this.subDomObj.style.left=Event.pointerX(e)+"px";this.subDomObj.style.top=Event.pointerY(e)+"px";Jx.Menu.prototype.show.apply(this,[e]);}});Jx.addStyleSheet('panel/panel.css');Jx.PanelManager=Class.create();Jx.PanelManager.prototype={panels:null,height:null,firstLayout:true,initialize:function(domObj,panels){this.domObj=$(domObj);this.panels=panels;var d=document.createElement('div');d.style.position='absolute';new Jx.Layout(d,{minHeight:0,maxHeight:0,height:0});var elements=[d];for(var i=0;i<this.panels.length;i++){elements.push(this.panels[i].domObj);}
-this.splitter=new Jx.Splitter(this.domObj,{splitInto:panels.length+1,layout:'vertical',elements:elements});this.splitter.sizeChanged=this.sizeChanged.bind(this);for(var i=0;i<this.panels.length;i++){var panel=this.panels[i];this.splitter.bars[i].appendChild(panel.title);this.splitter.bars[i].style.height=Element.getBorderBoxSize(panel.title).height+'px';Element.removeClassName(this.splitter.bars[i],'jxSplitterBar');Element.addClassName(this.splitter.bars[i],'jxPanelBar');panel.manager=this;}},sizeChanged:function(){if(this.firstLayout){if(Element.getBorderBoxSize(this.panels[0].title).height!=0){for(var i=0;i<this.splitter.bars.length;i++){var panel=this.panels[i];this.splitter.bars[i].style.height=Element.getBorderBoxSize(panel.title).height+'px';this.splitter.bars[i].size=null;}
-this.firstLayout=false;Jx.Splitter.prototype.sizeChanged.apply(this.splitter,[]);}}else{Jx.Splitter.prototype.sizeChanged.apply(this.splitter,[]);}},maximizePanel:function(panel){var h=Element.getContentBoxSize(this.domObj).height;var t=0;for(var i=1;i<this.splitter.elements.length;i++){var p=this.splitter.elements[i];t+=Element.getBorderBoxSize(p.leftBar).height;if(p!==panel.domObj){p.jxLayout.resize({top:t,height:p.jxLayout.options.minHeight,bottom:null});t+=p.jxLayout.options.minHeight;p.rightBar.style.top=t+'px';}else{break;}}
-b=h;for(var i=this.splitter.elements.length-1;i>0;i--){p=this.splitter.elements[i];if(p!==panel.domObj){b-=p.jxLayout.options.minHeight;p.jxLayout.resize({top:b,height:p.jxLayout.options.minHeight,bottom:null});b-=Element.getBorderBoxSize(p.leftBar).height;p.leftBar.style.top=b+'px';}else{break;}}
-panel.domObj.jxLayout.resize({top:t,height:b-t,bottom:null});}};Jx.Panel=Class.create();Jx.Panel.prototype={labelObj:null,state:'open',busyCount:null,bContentReady:null,onContentReady:null,initialize:function(options){this.initUniqueId();this.title=document.createElement('div');this.title.className="jxPanelTitle";this.title.style.height='22px';this.labelObj=document.createElement('span');this.labelObj.className='jxPanelLabel';this.labelObj.innerHTML=options.label?options.label:'empty';this.imageBaseUrl=options.imageBaseUrl||Jx.baseURL+'images/';var a,img;if(options.helpCallback){a=document.createElement('a');a.className='jxPanelHelp';a.href='javascript:void(0)';Event.observe(a,'click',options.helpCallback);img=document.createElement('img');img.src=this.imageBaseUrl+"help.png";img.alt='Help on this panel';img.title='Help on this panel';a.appendChild(img);this.title.appendChild(a);}
-a=document.createElement('a');a.className='jxPanelMaximize';a.href='javascript:void(0)';Event.observe(a,'click',this.maximize.bindAsEventListener(this));img=document.createElement('img');img.src=this.imageBaseUrl+"maximize.png";img.alt='Maximize Panel';img.title='Maximize Panel';a.appendChild(img);this.title.appendChild(a);a=document.createElement('a');a.className='jxPanelLoading';a.href='javascript:void(0)';img=document.createElement('img');img.src=this.imageBaseUrl+"loading.gif";img.alt='Loading Panel';img.title='Loading Panel';a.appendChild(img);this.loadingObj={};this.loadingObj.link=a;this.loadingObj.img=img;this.title.appendChild(this.loadingObj.link);this.title.appendChild(this.labelObj);Event.observe(this.title,'dblclick',this.maximize.bindAsEventListener(this));this.domObj=document.createElement('div');this.domObj.className='jxPanel';this.jxLayout=new Jx.Layout(this.domObj,options.constraint||{});this.jxLayout.addSizeChangeListener(this);var top=0;var bottom=0;if(options.menubar){this.menubar=options.menubar;this.domObj.appendChild(options.menubar);var h=Element.getBorderBoxSize(options.menubar).height;new Jx.Layout(this.menubar,{top:top,height:h});top+=h;}
-if(options.toolbar){this.toolbar=options.toolbar;this.domObj.appendChild(options.toolbar);var h=Element.getBorderBoxSize(options.toolbar).height;new Jx.Layout(this.toolbar,{top:top,height:h});}
-if(options.statusbar){this.statusbar=options.statusbar;this.domObj.appendChild(options.statusbar);var h=Element.getBorderBoxSize(options.statusbar).height;new Jx.Layout(this.statusbar,{bottom:bottom,height:h,top:null});bottom+=h;}
-this.content=document.createElement('div');Element.addClassName(this.content,'jxPanelContent');new Jx.Layout(this.content,{top:top,bottom:bottom});this.domObj.appendChild(this.content);this.loadContent(this.content,options);this.busyCount=0;this.bContentReady=false;},setLabel:function(s){this.labelObj.innerHTML=s;},getLabel:function(){return this.labelObj.innerHTML;},finalize:function(){this.domObj=null;this.deregisterIds();},maximize:function(){if(this.manager){this.manager.maximizePanel(this);}},setContent:function(html){this.content.innerHTML=html;this.bContentReady=true;},setContentURL:function(url){this.bContentReady=false;this.setBusy(true);if(arguments[1]){this.onContentReady=arguments[1];}
-if(url.indexOf('?')==-1){url=url+'?';}
-var opts={method:'get',onComplete:this.panelContentLoaded.bind(this),requestHeaders:['If-Modified-Since','Sat, 1 Jan 2000 00:00:00 GMT']};var a=new Ajax.Request(url,opts);},panelContentLoaded:function(r){this.content.innerHTML=r.responseText;this.bContentReady=true;this.setBusy(false);if(this.onContentReady){window.setTimeout(this.onContentReady.bind(this),1);}},setBusy:function(isBusy){this.busyCount+=isBusy?1:-1;this.loadingObj.img.style.visibility=(this.busyCount>0)?'visible':'hidden';},sizeChanged:function(){var top=0;var bottom=0;if(this.menubar){this.menubar.style.height='';var size=Element.getBorderBoxSize(this.menubar);this.menubar.resize({height:size.height});top+=size.height;}
-if(this.toolbar){this.toolbar.style.height='';var size=Element.getBorderBoxSize(this.toolbar);this.toolbar.resize({height:size.height});top+=size.height;}
-if(this.statusbar){this.statusbar.style.height='';var size=Element.getBorderBoxSize(this.statusbar);this.statusbar.resize({height:size.height});bottom+=size.height;}
-if(top||bottom){this.content.resize({bottom:bottom,top:top});}}};Object.extend(Jx.Panel.prototype,Jx.UniqueId.prototype);Object.extend(Jx.Panel.prototype,Jx.ContentLoader.prototype);Jx.addStyleSheet('picker/picker.css');Jx.Picker=Class.create();Jx.Picker.prototype={sl:null,domObj:null,ul:null,currentSelection:null,isEditable:false,initialize:function(options){options=options||{};this.domObj=document.createElement('div');this.domObj.className='jxPicker';this.isEditable=options.editable||false;if(this.isEditable){this.domInput=document.createElement('input');this.domInput.type='text';Event.observe(this.domInput,'change',this.valueChanged.bind(this));Event.observe(this.domInput,'keydown',this.onKeyPress.bind(this));}else{this.domInput=document.createElement('span');}
-this.domInput.className='jxPickerInput';this.domObj.appendChild(this.domInput);this.domA=document.createElement('a');this.domA.href='javascript:void(0)';this.domA.className='jxPickerDiscloser';Event.observe(this.domA,'click',this.toggle.bind(this));this.domButton=document.createElement('img');this.domButton.src=Jx.baseURL+'images/disclose2.png';Element.addClassName(this.domButton,'png24');this.domA.appendChild(this.domButton);this.domObj.appendChild(this.domA);if(!window.opera){var iframe=document.createElement('iframe');iframe.className='jxDialogShim';iframe.scrolling='no';iframe.frameborder=0;this.domObj.appendChild(iframe);}
-this.domListDiv=document.createElement('div');this.domListDiv.className='jxPickerOptions';this.domListDiv.style.display='none';this.domObj.appendChild(this.domListDiv);this.domList=document.createElement('ul');this.domListDiv.appendChild(this.domList);this.sl=[];},onKeyPress:function(e){var charCode=(e.charCode)?e.charCode:((e.keyCode)?e.keyCode:e.which);if(charCode==Event.KEY_RETURN){this.valueChanged();}},valueChanged:function(){this.processEvent(this.sl,'selectionChanged',this);},add:function(domObj,idx){var li=document.createElement('li');var a=document.createElement('a');a.href="javascript:void(0)";if(typeof(domObj)=='string'){a.innerHTML=domObj;}else{a.appendChild(domObj);}
-Event.observe(a,'click',this.pick.bindAsEventListener(this));li.appendChild(a);if(arguments.length>1&&this.domList.childNodes.length>idx){this.domList.insertBefore(li,this.domList.childNodes[idx]);}else{this.domList.appendChild(li);}
-if(this.getValue()==''){this.setValue(a.childNodes[0]);}},remove:function(idx){if(idx>0&&idx<this.domList.childNodes.length){this.domList.removeChild(this.domList.childNodes[idx]);}},pick:function(e){var target=Event.element(e);if(target.tagName=='A'){this.currentSelection=target;this.setValue(this.currentSelection.childNodes[0]);this.valueChanged();}
-this.close();},setValue:function(value){if(this.isEditable){if(typeof(value)=='string'){this.domInput.value=value;}else if(value.nodeType&&value.nodeType==3){this.domInput.value=value.nodeValue;}else{this.domInput.value=value.innerHTML;}}else if(!this.isEditable){if(typeof(value)=='string'){this.domInput.innerHTML=value;}else if(value.nodeType&&value.nodeType==3){this.domInput.innerHTML=value.nodeValue;}else{this.domInput.appendChild(value);}}},getValue:function(){value='';if(this.isEditable){value=this.domInput.value;}else if(this.domInput.childNodes.length>0){if(this.domInput.childNodes[0].nodeType==3){value=this.domInput.innerHTML;}else{value=this.domInput.childNodes[0];}}
-return value;},toggle:function(){if(this.domListDiv.style.display=='block'){this.close();}else{this.open();}},open:function(){if(!this.keypressListener){this.keypressListener=this.keypress.bindAsEventListener(this);}
-this.domListDiv.style.display='block';Event.observe(document,'keypress',this.keypressListener);},keypress:function(e){var charCode=(e.charCode)?e.charCode:e.keyCode;if(charCode==Event.KEY_ESC){this.close();}},close:function(){this.domListDiv.style.display='none';Event.stopObserving(document,'keypress',this.keypressListener);},addSelectionListener:function(obj){this.addListener(this.sl,obj);},removeSelectionListener:function(obj){this.removeListener(this.sl,obj);},getSelection:function(){return this.currentSelection?this.currentSelection.name:'';}};Object.extend(Jx.Picker.prototype,Jx.Listener.prototype);Jx.Splitter=Class.create();Jx.Splitter.prototype={domObj:null,elements:null,bars:null,firstUpdate:true,initialize:function(domObj,options){options=options||{};this.domObj=$(domObj);this.domObj.style.overflow='hidden';if(this.domObj.jxLayout){this.domObj.jxLayout.addSizeChangeListener(this);}
-this.elements=[];this.bars=[];var nSplits=options.splitInto||(options.elements?options.elements.length:2);var aContainerOpts=options.containerOptions||[];for(var i=0;i<nSplits;i++){this.elements[i]=options.elements?options.elements[i]:this.prepareElement();this.domObj.appendChild(this.elements[i]);if(!this.elements[i].jxLayout){new Jx.Layout(this.elements[i],aContainerOpts[i]);}}
-for(var i=1;i<nSplits;i++){this.bars[i-1]=this.prepareBar();this.bars[i-1].leftSide=this.elements[i-1];this.bars[i-1].rightSide=this.elements[i];this.elements[i-1].rightBar=this.bars[i-1];this.elements[i].leftBar=this.bars[i-1];this.domObj.appendChild(this.bars[i-1]);}
-this.layout=options.layout||'horizontal';this.establishConstraints();if(options.snappers){for(var i=0;i<options.snappers.length;i++){if(options.snappers[i]){new Jx.Splitter.Snapper(options.snappers[i],this.elements[i],this);}}}},prepareElement:function(){var o=document.createElement('div');o.style.position='absolute';o.leftBar=null;o.rightBar=null;return o;},prepareBar:function(){var o=document.createElement('div');o.className='jxSplitterBar';o.style.position='absolute';o.title='drag this bar to resize';o.style.lineHeight='1px';o.splitterObj=this;return o;},establishConstraints:function(){if(this.layout=='horizontal'){for(var i=0;i<this.bars.length;i++){this.bars[i].style.top='0px';this.bars[i].style.height='100%';new Draggable(this.bars[i],{constraint:'horizontal',starteffect:function(element){element.style.backgroundColor='#eee';},endeffect:function(element){element.style.backgroundColor='';}});}}else{for(var i=0;i<this.bars.length;i++){this.bars[i].style.left='0px';this.bars[i].style.width='100%';new Draggable(this.bars[i],{constraint:'vertical',starteffect:function(element){element.style.backgroundColor='#eee';},endeffect:function(element){element.style.backgroundColor='';}});}}
-Draggables.addObserver(this);},onEnd:function(eventName,obj,event){if(obj.element.splitterObj!=this){return;}
-if(this.layout=='horizontal'){this.dragHorizontal(eventName,obj,event);}else{this.dragVertical(eventName,obj,event);}},dragHorizontal:function(eventName,obj,event){var leftEdge=parseInt(obj.element.style.left);var leftSide=obj.element.leftSide;var rightSide=obj.element.rightSide;var rsLeft,rsWidth,rsRight;if(!obj.element.size){obj.element.size=Element.getBorderBoxSize(obj.element);}
-var barSize=obj.element.size;rsLeft=leftEdge+barSize.width;var parentSize=Element.getContentBoxSize(this.domObj);if(rightSide.jxLayout.options.width!=null){rsWidth=rightSide.jxLayout.options.width+rightSide.jxLayout.options.left-rsLeft;rsRight=parentSize.width-rsLeft-rsWidth;}else{rsWidth=parentSize.width-rightSide.jxLayout.options.right-rsLeft;rsRight=rightSide.jxLayout.options.right;}
-if(rsWidth<0){rsWidth=0;}
-if(rsWidth<rightSide.jxLayout.options.minWidth){rsWidth=rightSide.jxLayout.options.minWidth;}
-if(rightSide.jxLayout.options.maxWidth>=0&&rsWidth>rightSide.jxLayout.options.maxWidth){rsWidth=rightSide.jxLayout.options.maxWidth;}
-rsLeft=parentSize.width-rsRight-rsWidth;leftEdge=rsLeft-barSize.width;var lsLeft,lsWidth;lsLeft=leftSide.jxLayout.options.left;lsWidth=leftEdge-lsLeft;if(lsWidth<0){lsWidth=0;}
-if(lsWidth<leftSide.jxLayout.options.minWidth){lsWidth=leftSide.jxLayout.options.minWidth;}
-if(leftSide.jxLayout.options.maxWidth>=0&&lsWidth>leftSide.jxLayout.options.maxWidth){lsWidth=leftSide.jxLayout.options.maxWidth;}
-if(lsLeft+lsWidth!=leftEdge){leftEdge=lsLeft+lsWidth;var delta=leftEdge+barSize.width-rsLeft;rsLeft+=delta;rsWidth-=delta;}
-obj.element.style.left=leftEdge+'px';if(leftSide.jxLayout.options.width==null){var parentSize=Element.getContentBoxSize(this.domObj);leftSide.jxLayout.resize({right:parentSize.width-lsLeft-lsWidth});}else{leftSide.jxLayout.resize({width:lsWidth});}
-if(rightSide.jxLayout.options.width==null){rightSide.jxLayout.resize({left:rsLeft});}else{rightSide.jxLayout.resize({left:rsLeft,width:rsWidth});}},dragVertical:function(eventName,obj,event){var topEdge=parseInt(obj.element.style.top);var topSide=obj.element.leftSide;var bottomSide=obj.element.rightSide;if(!obj.element.size){obj.element.size=Element.getBorderBoxSize(obj.element);}
-var barSize=obj.element.size;var parentSize=Element.getContentBoxSize(this.domObj);var bsTop,bsHeight,bsBottom;bsTop=topEdge+barSize.height;if(bottomSide.jxLayout.options.height!=null){bsHeight=bottomSide.jxLayout.options.height+bottomSide.jxLayout.options.top-bsTop;bsBottom=parentSize.height-bsTop-bsHeight;}else{bsHeight=parentSize.height-bottomSide.jxLayout.options.bottom-bsTop;bsBottom=bottomSide.jxLayout.options.bottom;}
-if(bsHeight<0){bsHeight=0;}
-if(bsHeight<bottomSide.jxLayout.options.minHeight){bsHeight=bottomSide.jxLayout.options.minHeight;}
-if(bottomSide.jxLayout.options.maxHeight>=0&&bsHeight>bottomSide.jxLayout.options.maxHeight){bsHeight=bottomSide.jxLayout.options.maxHeight;}
-bsTop=parentSize.height-bsBottom-bsHeight;topEdge=bsTop-barSize.height;var tsTop,tsHeight;tsTop=topSide.jxLayout.options.top;tsHeight=topEdge-tsTop;if(tsHeight<0){tsHeight=0;}
-if(tsHeight<topSide.jxLayout.options.minHeight){tsHeight=topSide.jxLayout.options.minHeight;}
-if(topSide.jxLayout.options.maxHeight>=0&&tsHeight>topSide.jxLayout.options.maxHeight){tsHeight=topSide.jxLayout.options.maxHeight;}
-if(tsTop+tsHeight!=topEdge){topEdge=tsTop+tsHeight;var delta=topEdge+barSize.height-bsTop;bsTop+=delta;bsHeight-=delta;}
-obj.element.style.top=topEdge+'px';if(topSide.jxLayout.options.height==null){topSide.jxLayout.resize({bottom:parentSize.height-tsTop-tsHeight});}else{topSide.jxLayout.resize({height:tsHeight});}
-if(bottomSide.jxLayout.options.height==null){bottomSide.jxLayout.resize({top:bsTop});}else{bottomSide.jxLayout.resize({top:bsTop,height:bsHeight});}},sizeChanged:function(){if(this.layout=='horizontal'){this.horizontalResize();}else{this.verticalResize();}},horizontalResize:function(){var availableSpace=Element.getContentBoxSize(this.domObj).width;var overallWidth=availableSpace;for(var i=0;i<this.bars.length;i++){var bar=this.bars[i];if(!bar.size){bar.size=Element.getBorderBoxSize(bar);}
-availableSpace-=bar.size.width;}
-var nVariable=0;var jxo;for(var i=0;i<this.elements.length;i++){var e=this.elements[i];jxo=e.jxLayout.options;if(jxo.width!=null){availableSpace-=parseInt(jxo.width);}else{var w=0;if(jxo.right!=0||jxo.left!=0){w=Element.getBorderBoxSize(e).width;}
-availableSpace-=w;nVariable++;}}
-if(nVariable==0){availableSpace+=jxo.width;jxo.width=null;nVariable=1;}
-var amount=parseInt(availableSpace/nVariable);var remainder=availableSpace%nVariable;var currentPosition=0;for(var i=0;i<this.elements.length;i++){var e=this.elements[i];var jxl=e.jxLayout;var jxo=jxl.options;if(jxo.width!=null){jxl.resize({left:currentPosition});currentPosition+=jxo.width;}else{var a=amount;if(nVariable==1){a+=remainder;}
-nVariable--;var w=0;if(jxo.right!=0||jxo.left!=0){w=Element.getBorderBoxSize(e).width+a;}else{w=a;}
-if(w<0){if(nVariable>0){amount=amount+w/nVariable;}
-w=0;}
-if(w<jxo.minWidth){if(nVariable>0){amount=amount+(w-jxo.minWidth)/nVariable;}
-w=jxo.minWidth;}
-if(jxo.maxWidth>=0&&w>jxo.maxWidth){if(nVariable>0){amount=amount+(w-jxo.maxWidth)/nVariable;}
-w=e.options.maxWidth;}
-var r=overallWidth-currentPosition-w;jxl.resize({left:currentPosition,right:r});currentPosition+=w;}
-if(e.rightBar){e.rightBar.style.left=currentPosition+'px';currentPosition+=e.rightBar.size.width;}}},verticalResize:function(){var availableSpace=Element.getContentBoxSize(this.domObj).height;var overallHeight=availableSpace;for(var i=0;i<this.bars.length;i++){var bar=this.bars[i];if(!bar.size){bar.size=Element.getBorderBoxSize(bar);}
-availableSpace-=bar.size.height;}
-var nVariable=0;var jxo;for(var i=0;i<this.elements.length;i++){var e=this.elements[i];jxo=e.jxLayout.options;if(jxo.height!=null){availableSpace-=parseInt(jxo.height);}else{var h=0;if(jxo.bottom!=0||jxo.top!=0){h=Element.getBorderBoxSize(e).height;}
-availableSpace-=h;nVariable++;}}
-if(nVariable==0){availableSpace+=jxo.height;jxo.height=null;nVariable=1;}
-var amount=parseInt(availableSpace/nVariable);var remainder=availableSpace%nVariable;var currentPosition=0;for(var i=0;i<this.elements.length;i++){var e=this.elements[i];var jxl=e.jxLayout;var jxo=jxl.options;if(jxo.height!=null){jxl.resize({top:currentPosition});currentPosition+=jxo.height;}else{var a=amount;if(nVariable==1){a+=remainder;}
-nVariable--;var h=0;if(jxo.bottom!=0||jxo.top!=0){h=Element.getBorderBoxSize(e).height+a;}else{h=a;}
-if(h<0){if(nVariable>0){amount=amount+h/nVariable;}
-h=0;}
-if(h<jxo.minHeight){if(nVariable>0){amount=amount+(h-jxo.minHeight)/nVariable;}
-h=jxo.minHeight;}
-if(jxo.maxHeight>=0&&h>jxo.maxHeight){if(nVariable>0){amount=amount+(h-jxo.maxHeight)/nVariable;}
-h=jxo.maxHeight;}
-var r=overallHeight-currentPosition-h;jxl.resize({top:currentPosition,bottom:r});currentPosition+=h;}
-if(e.rightBar){e.rightBar.style.top=currentPosition+'px';currentPosition+=e.rightBar.size.height;}}}};Jx.Splitter.Snapper=Class.create();Jx.Splitter.Snapper.prototype={snapper:null,element:null,splitter:null,layout:'vertical',initialize:function(snapper,element,splitter){this.snapper=snapper;this.element=element;element.jxLayout.addSizeChangeListener(this);this.splitter=splitter;this.layout=splitter.layout;var jxo=this.element.jxLayout.options;var size=Element.getBorderBoxSize(this.element);if(this.layout=='vertical'){this.originalSize=size.height;this.minimumSize=jxo.minHeight?jxo.minHeight:0;}else{this.originalSize=size.width;this.minimumSize=jxo.minWidth?jxo.minWidth:0;}
-Event.observe(snapper,'click',this.toggleElement.bind(this));},toggleElement:function(){var size=Element.getBorderBoxSize(this.element);var newSize={};if(this.layout=='vertical'){if(size.height==this.minimumSize){newSize.height=this.originalSize;}else{this.originalSize=size.height;newSize.height=this.minimumSize;}}else{if(size.width==this.minimumSize){newSize.width=this.originalSize;}else{this.originalSize=size.width;newSize.width=this.minimumSize;}}
-this.element.jxLayout.resize(newSize);this.splitter.sizeChanged();},sizeChanged:function(){var size=Element.getBorderBoxSize(this.element);if(this.layout=='vertical'){if(size.height==this.minimumSize){Element.addClassName(this.snapper,'jxSnapClosed');Element.removeClassName(this.snapper,'jxSnapOpened');}else{Element.addClassName(this.snapper,'jxSnapOpened');Element.removeClassName(this.snapper,'jxSnapClosed');}}else{if(size.width==this.minimumSize){Element.addClassName(this.snapper,'jxSnapClosed');Element.removeClassName(this.snapper,'jxSnapOpened');}else{Element.addClassName(this.snapper,'jxSnapOpened');Element.removeClassName(this.snapper,'jxSnapClosed');}}}};Jx.addStyleSheet('tab/tabs.css');Jx.addStyleSheet('tabs/tabs_ie.css',true);Jx.TabSet=Class.create();Jx.TabSet.prototype={domObj:null,sl:null,initialize:function(domObj){this.domObj=$(domObj);if(!Element.hasClassName(this.domObj,'jxTabSetContainer')){Element.addClassName(this.domObj,'jxTabSetContainer');}
-this.sl=[];},sizeChanged:function(){this.resizeTabBox();},resizeTabBox:function(){var parentSize=Element.getContentBoxSize(this.domObj.parentNode);Element.setBorderBoxSize(this.domObj,{width:parentSize.width,height:parentSize.height});for(var i=0;i<this.domObj.childNodes.length;i++){if(this.domObj.childNodes[i].nodeType==3){continue;}
-Element.setBorderBoxSize(this.domObj.childNodes[i],{height:parentSize.height});if(this.domObj.childNodes[i].resize){this.domObj.childNodes[i].resize({forceResize:true});}}},add:function(){for(var i=0;i<arguments.length;i++){var tab=arguments[i];tab.addSelectionListener(this);this.domObj.appendChild(tab.content);if(!this.activeTab){this.setActiveTab(tab);}}},remove:function(tab){},setActiveTab:function(tab){if(this.activeTab){Element.removeClassName(this.activeTab.domObj,'tabActive');Element.removeClassName(this.activeTab.content,'tabContentActive');}
-this.activeTab=tab;Element.addClassName(this.activeTab.domObj,'tabActive');Element.addClassName(this.activeTab.content,'tabContentActive');if(this.activeTab.content.resize){this.activeTab.content.resize({forceResize:true});}},selectionChanged:function(tab){this.setActiveTab(tab);this.processEvent(this.sl,'selectionChanged',tab);},addSelectionListener:function(obj){this.addListener(this.sl,obj);},removeSelectionListener:function(obj){this.removeListener(this.sl,obj);}};Object.extend(Jx.TabSet.prototype,Jx.Listener.prototype);Jx.Tab=Class.create();Jx.Tab.prototype={domObj:null,content:null,name:null,sl:null,initialize:function(name,options){this.sl=[];options=options||{};if(!options.label){options.label=name;}
-this.name=name;this.content=document.createElement('div');this.content.className='tabContent';this.loadContent(this.content,options);var a=new Jx.Action(this.clicked.bind(this));var b=new Jx.Button(a,options);this.domObj=b.domA;Element.addClassName(this.domObj,'jxTab');new Jx.Layout(this.content,options);},clicked:function(){this.processEvent(this.sl,'selectionChanged',this);this.domObj.childNodes[0].blur();},addSelectionListener:function(obj){this.addListener(this.sl,obj);},removeSelectionListener:function(obj){this.removeListener(this.sl,obj);}};Object.extend(Jx.Tab.prototype,Jx.Listener.prototype);Object.extend(Jx.Tab.prototype,Jx.ContentLoader.prototype);Jx.TabBox=Class.create();Jx.TabBox.prototype={tabBar:null,tabSet:null,initialize:function(domObj,position){var parent=$(domObj);position=position||'top';var tabBarDiv=document.createElement('div');parent.appendChild(tabBarDiv);this.tabBar=new Jx.Toolbar(tabBarDiv,position);this.tabSet=new Jx.TabSet(parent);switch(position){case'top':Element.addClassName(parent,'jxTabBoxTop');break;case'bottom':Element.addClassName(parent,'jxTabBoxBottom');break;case'left':Element.addClassName(parent,'jxTabBoxLeft');Element.addClassName(tabBarDiv,'verticalToolbar');break;case'right':Element.addClassName(parent,'jxTabBoxRight');Element.addClassName(tabBarDiv,'verticalToolbar');break;}
-this.sl=[];},sizeChanged:function(){this.tabSet.sizeChanged();},add:function(){this.tabBar.add.apply(this.tabBar,arguments);this.tabSet.add.apply(this.tabSet,arguments);},remove:function(tab){}};Object.extend(Jx.TabBox.prototype,Jx.Listener.prototype);Jx.addStyleSheet('toolbar/toolbar.css');Jx.addStyleSheet('button/button.css');Jx.Toolbar=Class.create();Jx.Toolbar.prototype={items:null,domObj:null,isActive:false,initialize:function(domObj,position){var parent=$(domObj);this.domObj=document.createElement('ul');Element.addClassName(this.domObj,'jxToolbar');if(!Element.hasClassName(parent,'jxToolbarContainer')){Element.addClassName(parent,'jxToolbarContainer');parent.appendChild(this.domObj);var clearer=document.createElement('div');clearer.className='jxClearer';parent.appendChild(clearer);}else{parent.insertBefore(this.domObj,parent.lastChild);}
-switch(position){case'top':Element.addClassName(parent,'jxBarTop');break;case'right':Element.addClassName(parent,'jxBarRight');break;case'bottom':Element.addClassName(parent,'jxBarBottom');break;case'left':Element.addClassName(parent,'jxBarLeft');break;default:Element.addClassName(parent,'jxBarTop');}
-this.deactivateWatcher=this.deactivate.bindAsEventListener(this);},add:function(){for(var i=0;i<arguments.length;i++){var thing=arguments[i];thing.toolbar=this;if(thing.domObj){thing=thing.domObj;}
-if(thing.tagName=='LI'){if(!Element.hasClassName(thing,'jxToolItem')){Element.addClassName(thing,'jxToolItem');}
-this.domObj.appendChild(thing);}else{var item=new Jx.ToolbarItem(thing);this.domObj.appendChild(item.domObj);}}},deactivate:function(){for(var i=0;i<this.items.length;i++){this.items[i].hide();}
-this.setActive(false);},isActive:function(){return this.isActive;},setActive:function(b){this.isActive=b;if(this.isActive){Event.observe(document,'click',this.deactivateWatcher);}else{Event.stopObserving(document,'click',this.deactivateWatcher);}},setVisibleItem:function(obj){if(this.visibleItem&&this.visibleItem.hide&&this.visibleItem!=obj){this.visibleItem.hide();}
-this.visibleItem=obj;if(this.isActive()){this.visibleItem.show();}}};Jx.ToolbarItem=Class.create();Jx.ToolbarItem.prototype={domObj:null,initialize:function(jxThing){this.al=[];this.domObj=document.createElement('li');this.domObj.className='jxToolItem';if(jxThing){if(jxThing.domObj){this.domObj.appendChild(jxThing.domObj);if(jxThing instanceof Jx.Tab){Element.addClassName(this.domObj,'jxTabItem');}}else{this.domObj.appendChild(jxThing);if(Element.hasClassName(jxThing,'jxTab')){Element.addClassName(this.domObj,'jxTabItem');}}}}};Jx.ToolbarSeparator=Class.create();Jx.ToolbarSeparator.prototype={domObj:null,initialize:function(){this.domObj=document.createElement('li');this.domObj.className='jxToolItem';this.domSpan=document.createElement('span');this.domSpan.className='separator';this.domObj.appendChild(this.domSpan);}};Jx.addStyleSheet('tree/tree.css');Jx.addStyleSheet('tree/tree_ie.css',true);Jx.TreeItem=Class.create();Jx.TreeItem.prototype={data:null,domObj:null,parent:null,currentClassName:null,onClick:null,sl:null,enabled:null,contextMenu:null,initialize:function(options){this.initializeItem(options);},initializeItem:function(options){options=options||{};this.sl=[];var label=options.label||'new node';this.data=options.data||null;this.contextMenu=options.contextMenu||null;this.imgNode=options.imgNode||Jx.baseURL+'images/tree_none.png';this.imgIcon=options.imgIcon||Jx.baseURL+'images/tree_page.png';this.domObj=document.createElement('li');this.domObj.className='jxTreeNode';this.currentClassName='jxTreeNode';var elm=document.createElement('img');elm.className='jxTreeNodeImage';Jx.addToImgQueue({domElement:elm,src:this.imgNode});this.domObj.appendChild(elm);elm=document.createElement('img');elm.className='jxTreeNodeIcon';Jx.addToImgQueue({domElement:elm,src:this.imgIcon});this.domObj.appendChild(elm);elm=document.createElement('a');elm.href='javascript:void(0)';elm.onclick=this.selected.bindAsEventListener(this);elm.ondblclick=this.selected.bindAsEventListener(this);elm.oncontextmenu=this.showMenu.bindAsEventListener(this);elm.innerHTML=label;this.domObj.appendChild(elm);this.domObj.jxTreeItem=this;this.domObj.childNodes[2].jxTreeItem=this;this.onClick=options.onClick||null;this.enabled=typeof options.enabled!='undefined'?options.enabled:true;if(this.enabled){Element.removeClassName(this.domObj,'jxDisabled');}else{Element.addClassName(this.domObj,'jxDisabled');}
-var clearer=document.createElement('span');clearer.className='jxClearer';this.domObj.appendChild(clearer);},finalize:function(){this.finalizeItem();},finalizeItem:function(){if(!this.domObj){return;}
-this.domObj.childNodes[2].onclick=null;this.domObj.childNodes[2].ondblclick=null;this.domObj.childNodes[2].oncontextmenu=null;this.contextMenu=null;this.onClick=null;for(var i=this.sl.length;i>=0;i--){this.removeSelectionListener(this.sl[i]);}
-this.parent=null;this.domObj.jxTreeItem=null;this.domObj=null;},clone:function(){var options={label:this.domObj.childNodes[2].innerHTML,data:this.data,onClick:this.onClick,imgNode:this.imgNode,imgIcon:this.imgIcon};var item=new Jx.TreeItem(options);return item;},update:function(shouldDescend){var isLast=(arguments.length>1)?arguments[1]:(this.parent&&this.parent.isLastNode(this));if(isLast){Element.removeClassName(this.domObj,'jxTreeNode');Element.addClassName(this.domObj,'jxTreeNodeLast');}else{Element.removeClassName(this.domObj,'jxTreeNodeLast');Element.addClassName(this.domObj,'jxTreeNode');}},selected:function(e){this.lastEvent=e?e:event;this.processEvent(this.sl,'selectionChanged',this);},showMenu:function(e){this.lastEvent=e?e:event;this.processEvent(this.sl,'selectionChanged',this);if(this.contextMenu){this.contextMenu.show(this.lastEvent);}
-Event.stop(e);},addSelectionListener:function(obj){this.addListener(this.sl,obj);},removeSelectionListener:function(obj){this.removeListener(this.sl,obj);},getName:function(){return this.domObj.childNodes[2].innerHTML;},setName:function(name){this.domObj.childNodes[2].innerHTML=name;},propertyChanged:function(obj){this.enabled=obj.isEnabled();if(this.enabled){Element.removeClassName(this.domObj,'jxDisabled');}else{Element.addClassName(this.domObj,'jxDisabled');}}};Object.extend(Jx.TreeItem.prototype,Jx.Listener.prototype);Jx.TreeFolder=Class.create();Object.extend(Jx.TreeFolder.prototype,Jx.TreeItem.prototype);Object.extend(Jx.TreeFolder.prototype,{subDomObj:null,nodes:null,isOpen:false,dl:null,initialize:function(options){this.initializeFolder(options);},initializeFolder:function(options){options=options||{};this.initializeItem(options);this.imgTreePlus=options.imgTreePlus||Jx.baseURL+'images/tree_plus.png';this.imgTreeMinus=options.imgTreeMinus||Jx.baseURL+'images/tree_minus.png';this.imgTreeFolder=options.imgTreeFolder||Jx.baseURL+'images/tree_folder.png';this.imgTreeFolderOpen=options.imgTreeFolderOpen||Jx.baseURL+'images/tree_folder_open.png';Jx.addToImgQueue({domElement:this.domObj.childNodes[0],src:this.imgTreePlus});Jx.addToImgQueue({domElement:this.domObj.childNodes[1],src:this.imgTreeFolder});this.domObj.childNodes[0].onclick=this.clicked.bindAsEventListener(this);this.nodes=[];this.subDomObj=document.createElement('ul');this.domObj.appendChild(this.subDomObj);this.subDomObj.className='jxTree';this.isOpen=options.isOpen||false;this.dl=[];if(this.isOpen){this.expand();}else{this.collapse();}},finalize:function(){this.finalizeFolder();this.finalizeItem();this.subDomObj=null;},finalizeFolder:function(){this.domObj.childNodes[0].onclick=null;for(var i=this.nodes.length-1;i>=0;i--){this.nodes[i].finalize();if(this.nodes[i].domObj)this.subDomObj.removeChild(this.nodes[i].domObj);this.nodes.pop();}
-for(var i=this.dl.length-1;i>=0;i--){this.removeDisclosureListener(this.dl[i]);}},clone:function(){var options={label:this.domObj.childNodes[2].innerHTML,data:this.data,onClick:this.onClick,imgTreePlus:this.imgTreePlus,imgTreeMinus:this.imgTreeMinus,imgTreeFolder:this.imgTreeFolder,imgTreeFolderOpen:this.imgTreeFolderOpen};var node=new Jx.TreeFolder(options);for(var i=0;i<this.nodes.length;i++){node.append(this.nodes[i].clone());}
-return node;},isLastNode:function(node){if(this.nodes.length==0){return false;}else{return this.nodes[this.nodes.length-1]==node;}},update:function(bDescend){if(!this.parent)return;var bLast=false;if(arguments.length>1){bLast=arguments[1];}else{bLast=(this.parent&&this.parent.isLastNode(this));}
-if(bLast){this.domObj.className='jxTreeNodeLast';this.subDomObj.className='jxTree';}else{this.domObj.className='jxTreeNode';this.subDomObj.className='jxTree jxTreeNest';}
-if(this.isOpen){Jx.addToImgQueue({domElement:this.domObj.childNodes[0],src:this.imgTreeMinus});Jx.addToImgQueue({domElement:this.domObj.childNodes[1],src:this.imgTreeFolderOpen});}else{Jx.addToImgQueue({domElement:this.domObj.childNodes[0],src:this.imgTreePlus});Jx.addToImgQueue({domElement:this.domObj.childNodes[1],src:this.imgTreeFolder});}
-if(this.nodes&&bDescend){for(var i=0;i<this.nodes.length;i++){this.nodes[i].update(false,i==this.nodes.length-1);}}},append:function(node){node.parent=this;this.nodes.push(node);this.subDomObj.appendChild(node.domObj);this.update(true);},insert:function(node,refNode){node.parent=this;if(!refNode){this.nodes.unshift(node);if(this.subDomObj.childNodes.length==0){this.subDomObj.appendChild(node.domObj);}else{this.subDomObj.insertBefore(node.domObj,this.subDomObj.childNodes[0]);}}else{var b=false;for(var i=0;i<this.nodes.length;i++){if(this.nodes[i]==refNode){i=i+1;if(i<this.nodes.length){this.nodes.splice(i,0,node);this.subDomObj.insertBefore(node.domObj,this.subDomObj.childNodes[i]);b=true;break;}}}
-if(!b){this.nodes.push(node);this.subDomObj.appendChild(node.domObj);}}
-this.update(true);},remove:function(node){node.parent=null;for(var i=0;i<this.nodes.length;i++){if(this.nodes[i]==node){this.nodes.splice(i,1);this.subDomObj.removeChild(this.subDomObj.childNodes[i]);break;}}
-this.update(true);},replace:function(newNode,refNode){var b=false;for(var i=0;i<this.nodes.length;i++){if(this.nodes[i]==refNode){if(i<this.nodes.length){newNode.parent=this;this.nodes.splice(i,1,newNode);this.subDomObj.replaceChild(newNode.domObj,refNode.domObj);return true;}}}
-return false;},clicked:function(e){e=e?e:event;if(this.isOpen){this.collapse();}else{this.expand();}},expand:function(){this.isOpen=true;this.subDomObj.style.display='block';this.update(true);this.processEvent(this.dl,'disclosed',this);},collapse:function(){this.isOpen=false;this.subDomObj.style.display='none';this.update(true);this.processEvent(this.dl,'disclosed',this);},addDisclosureListener:function(obj){this.addListener(this.dl,obj);},removeDisclosureListener:function(obj){this.removeListener(this.dl,obj);},findChild:function(path){if(path.length==0)
-return this;if(path.length==1)
-{for(var i=0;i<this.nodes.length;i++)
-{if(this.nodes[i].getName()==path[0])
-return this.nodes[i];}
-return null;}
-var childName=path.shift();for(var i=0;i<this.nodes.length;i++)
-{if(this.nodes[i].getName()==childName&&this.nodes[i].findChild)
-return this.nodes[i].findChild(path);}
-return null;}});Jx.Tree=Class.create();Object.extend(Jx.Tree.prototype,Jx.TreeFolder.prototype);Object.extend(Jx.Tree.prototype,{initialize:function(id){this.subDomObj=document.createElement('ul');this.subDomObj.className='jxTreeRoot';$(id).appendChild(this.subDomObj);this.nodes=[];this.dl=[];this.isOpen=true;},finalize:function(){this.clear();this.subDomObj.parentNode.removeChild(this.subDomObj);},clear:function(){for(var i=this.nodes.length-1;i>=0;i--){this.subDomObj.removeChild(this.nodes[i].domObj);this.nodes[i].finalize();this.nodes.pop();}},update:function(shouldDescend){var bLast=true;if(this.subDomObj)
-{if(bLast){Element.removeClassName(this.subDomObj,'jxTreeNest');}else{Element.addClassName(this.subDomObj,'jxTreeNest');}}
-if(this.nodes&&shouldDescend){this.nodes.each(function(n){n.update(false);});}},append:function(node){node.parent=this;this.nodes.push(node);this.subDomObj.appendChild(node.domObj);this.update(true);}});if(Jx.COMBINED_CSS){document.write('<link type="text/css" rel="stylesheet" href="'+Jx.baseURL+'lib/jx_combined.css" />\n');}else{for(var styleSheet in Jx.importRules){var url=Jx.baseURL+styleSheet;document.write('<link type="text/css" rel="stylesheet" href="'+url+'" />\n');}
-document.write('<!--[if IE]>');for(var styleSheet in Jx.importRulesIE){var url=Jx.baseURL+styleSheet;document.write('<link type="text/css" rel="stylesheet" href="'+url+'" />\n');}
-document.write('<![endif]-->\n');}
\ No newline at end of file
Added: sandbox/jx2/jx/lib/jxlib.js
===================================================================
--- sandbox/jx2/jx/lib/jxlib.js (rev 0)
+++ sandbox/jx2/jx/lib/jxlib.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -0,0 +1 @@
+var MooTools={version:"1.2dev",build:""};var Native=function(J){J=J||{};var F=J.afterImplement||function(){};var G=J.generics;G=(G!==false);var H=J.legacy;var E=J.initialize;var B=J.protect;var A=J.name;var C=E||H;C.constructor=Native;C.$family={name:"native"};if(H&&E){C.prototype=H.prototype}C.prototype.constructor=C;if(A){var D=A.toLowerCase();C.prototype.$family={name:D};Native.typize(C,D)}var I=function(M,K,N,L){if(!B||L||!M.prototype[K]){M.prototype[K]=N}if(G){Native.genericize(M,K,B)}F.call(M,K,N);return M};C.implement=function(L,K,N){if(typeof L=="string"){return I(this,L,K,N)}for(var M in L){I(this,M,L[M],K)}return this};C.alias=function(M,K,N){if(typeof M=="string"){M=this.prototype[M];if(M){I(this,K,M,N)}}else{for(var L in M){this.alias(L,M[L],K)}}return this};return C};Native.implement=function(D,C){for(var B=0,A=D.length;B<A;B++){D[B].implement(C)}};Native.genericize=function(B,C,A){if((!A||!B[C])&&typeof B.prototype[C]=="function"){B[C]=function(){var D=Array.prototype.slice.call(arguments);return B.prototype[C].apply(D.shift(),D)}}};Native.typize=function(A,B){if(!A.type){A.type=function(C){return($type(C)===B)}}};Native.alias=function(E,B,A,F){for(var D=0,C=E.length;D<C;D++){E[D].alias(B,A,F)}};(function(B){for(var A in B){Native.typize(B[A],A)}})({"boolean":Boolean,"native":Native,object:Object});(function(B){for(var A in B){new Native({name:A,initialize:B[A],protect:true})}})({String:String,Function:Function,Number:Number,Array:Array,RegExp:RegExp,Date:Date});(function(B,A){for(var C=A.length;C--;C){Native.genericize(B,A[C],true)}return arguments.callee})(Array,["pop","push","reverse","shift","sort","splice","unshift","concat","join","slice","toString","valueOf","indexOf","lastIndexOf"])(String,["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","replace","search","slice","split","substr","substring","toLowerCase","toUpperCase","valueOf"]);function $chk(A){return !!(A||A===0)}function $clear(A){clearTimeout(A);clearInterval(A);return null}function $defined(A){return(A!=undefined)}function $empty(){}function $arguments(A){return function(){return arguments[A]}}function $lambda(A){return(typeof A=="function")?A:function(){return A}}function $extend(C,A){for(var B in (A||{})){C[B]=A[B]}return C}function $unlink(C){var B;switch($type(C)){case"object":B={};for(var E in C){B[E]=$unlink(C[E])}break;case"hash":B=$unlink(C.getClean());break;case"array":B=[];for(var D=0,A=C.length;D<A;D++){B[D]=$unlink(C[D])}break;default:return C}return B}function $merge(){var E={};for(var D=0,A=arguments.length;D<A;D++){var B=arguments[D];if($type(B)!="object"){continue}for(var C in B){var G=B[C],F=E[C];E[C]=(F&&$type(G)=="object"&&$type(F)=="object")?$merge(F,G):$unlink(G)}}return E}function $pick(){for(var B=0,A=arguments.length;B<A;B++){if(arguments[B]!=undefined){return arguments[B]}}return null}function $random(B,A){return Math.floor(Math.random()*(A-B+1)+B)}function $splat(B){var A=$type(B);return(A)?((A!="array"&&A!="arguments")?[B]:B):[]}var $time=Date.now||function(){return new Date().getTime()};function $try(){for(var B=0,A=arguments.length;B<A;B++){try{return arguments[B]()}catch(C){}}return null}function $type(A){if(A==undefined){return false}if(A.$family){return(A.$family.name=="number"&&!isFinite(A))?false:A.$family.name}if(A.nodeName){switch(A.nodeType){case 1:return"element";case 3:return(/\S/).test(A.nodeValue)?"textnode":"whitespace"}}else{if(typeof A.length=="number"){if(A.callee){return"arguments"}else{if(A.item){return"collection"}}}}return typeof A}var Hash=new Native({name:"Hash",initialize:function(A){if($type(A)=="hash"){A=$unlink(A.getClean())}for(var B in A){this[B]=A[B]}return this}});Hash.implement({getLength:function(){var B=0;for(var A in this){if(this.hasOwnProperty(A)){B++}}return B},forEach:function(B,C){for(var A in this){if(this.hasOwnProperty(A)){B.call(C,this[A],A,this)}}},getClean:function(){var B={};for(var A in this){if(this.hasOwnProperty(A)){B[A]=this[A]}}return B}});Hash.alias("forEach","each");function $H(A){return new Hash(A)}Array.implement({forEach:function(C,D){for(var B=0,A=this.length;B<A;B++){C.call(D,this[B],B,this)}}});Array.alias("forEach","each");function $A(C){if(C.item){var D=[];for(var B=0,A=C.length;B<A;B++){D[B]=C[B]}return D}return Array.prototype.slice.call(C)}function $each(C,B,D){var A=$type(C);((A=="arguments"||A=="collection"||A=="array")?Array:Hash).each(C,B,D)}var Browser=new Hash({Engine:{name:"unknown",version:""},Platform:{name:(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase()},Features:{xpath:!!(document.evaluate),air:!!(window.runtime)},Plugins:{}});if(window.opera){Browser.Engine={name:"presto",version:(document.getElementsByClassName)?950:925}}else{if(window.ActiveXObject){Browser.Engine={name:"trident",version:(window.XMLHttpRequest)?5:4}}else{if(!navigator.taintEnabled){Browser.Engine={name:"webkit",version:(Browser.Features.xpath)?420:419}}else{if(document.getBoxObjectFor!=null){Browser.Engine={name:"gecko",version:(document.getElementsByClassName)?19:18}}}}}Browser.Engine[Browser.Engine.name]=Browser.Engine[Browser.Engine.name+Browser.Engine.version]=true;if(window.orientation!=undefined){Browser.Platform.name="ipod"}Browser.Platform[Browser.Platform.name]=true;Browser.Request=function(){return $try(function(){return new XMLHttpRequest()},function(){return new ActiveXObject("MSXML2.XMLHTTP")})};Browser.Features.xhr=!!(Browser.Request());Browser.Plugins.Flash=(function(){var A=($try(function(){return navigator.plugins["Shockwave Flash"].description},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version")})||"0 r0").match(/\d+/g);return{version:parseInt(A[0]||0+"."+A[1]||0),build:parseInt(A[2]||0)}})();function $exec(B){if(!B){return B}if(window.execScript){window.execScript(B)}else{var A=document.createElement("script");A.setAttribute("type","text/javascript");A.text=B;document.head.appendChild(A);document.head.removeChild(A)}return B}Native.UID=1;var $uid=(Browser.Engine.trident)?function(A){return(A.uid||(A.uid=[Native.UID++]))[0]}:function(A){return A.uid||(A.uid=Native.UID++)};var Window=new Native({name:"Window",legacy:(Browser.Engine.trident)?null:window.Window,initialize:function(A){$uid(A);if(!A.Element){A.Element=$empty;if(Browser.Engine.webkit){A.document.createElement("iframe")}A.Element.prototype=(Browser.Engine.webkit)?window["[[DOMElement.prototype]]"]:{}}return $extend(A,Window.Prototype)},afterImplement:function(B,A){window[B]=Window.Prototype[B]=A}});Window.Prototype={$family:{name:"window"}};new Window(window);var Document=new Native({name:"Document",legacy:(Browser.Engine.trident)?null:window.Document,initialize:function(A){$uid(A);A.head=A.getElementsByTagName("head")[0];A.html=A.getElementsByTagName("html")[0];A.window=A.defaultView||A.parentWindow;if(Browser.Engine.trident4){$try(function(){A.execCommand("BackgroundImageCache",false,true)})}return $extend(A,Document.Prototype)},afterImplement:function(B,A){document[B]=Document.Prototype[B]=A}});Document.Prototype={$family:{name:"document"}};new Document(document);Array.implement({every:function(C,D){for(var B=0,A=this.length;B<A;B++){if(!C.call(D,this[B],B,this)){return false}}return true},filter:function(D,E){var C=[];for(var B=0,A=this.length;B<A;B++){if(D.call(E,this[B],B,this)){C.push(this[B])}}return C},clean:function(){return this.filter($defined)},indexOf:function(C,D){var A=this.length;for(var B=(D<0)?Math.max(0,A+D):D||0;B<A;B++){if(this[B]===C){return B}}return -1},map:function(D,E){var C=[];for(var B=0,A=this.length;B<A;B++){C[B]=D.call(E,this[B],B,this)}return C},some:function(C,D){for(var B=0,A=this.length;B<A;B++){if(C.call(D,this[B],B,this)){return true}}return false},associate:function(C){var D={},B=Math.min(this.length,C.length);for(var A=0;A<B;A++){D[C[A]]=this[A]}return D},link:function(C){var A={};for(var E=0,B=this.length;E<B;E++){for(var D in C){if(C[D](this[E])){A[D]=this[E];delete C[D];break}}}return A},contains:function(A,B){return this.indexOf(A,B)!=-1},extend:function(C){for(var B=0,A=C.length;B<A;B++){this.push(C[B])}return this},getLast:function(){return(this.length)?this[this.length-1]:null},getRandom:function(){return(this.length)?this[$random(0,this.length-1)]:null},include:function(A){if(!this.contains(A)){this.push(A)}return this},combine:function(C){for(var B=0,A=C.length;B<A;B++){this.include(C[B])}return this},erase:function(B){for(var A=this.length;A--;A){if(this[A]===B){this.splice(A,1)}}return this},empty:function(){this.length=0;return this},flatten:function(){var D=[];for(var B=0,A=this.length;B<A;B++){var C=$type(this[B]);if(!C){continue}D=D.concat((C=="array"||C=="collection"||C=="arguments")?Array.flatten(this[B]):this[B])}return D},hexToRgb:function(B){if(this.length!=3){return null}var A=this.map(function(C){if(C.length==1){C+=C}return C.toInt(16)});return(B)?A:"rgb("+A+")"},rgbToHex:function(D){if(this.length<3){return null}if(this.length==4&&this[3]==0&&!D){return"transparent"}var B=[];for(var A=0;A<3;A++){var C=(this[A]-0).toString(16);B.push((C.length==1)?"0"+C:C)}return(D)?B:"#"+B.join("")}});Function.implement({extend:function(A){for(var B in A){this[B]=A[B]}return this},create:function(B){var A=this;B=B||{};return function(D){var C=B.arguments;C=(C!=undefined)?$splat(C):Array.slice(arguments,(B.event)?1:0);if(B.event){C=[D||window.event].extend(C)}var E=function(){return A.apply(B.bind||null,C)};if(B.delay){return setTimeout(E,B.delay)}if(B.periodical){return setInterval(E,B.periodical)}if(B.attempt){return $try(E)}return E()}},pass:function(A,B){return this.create({arguments:A,bind:B})},attempt:function(A,B){return this.create({arguments:A,bind:B,attempt:true})()},bind:function(B,A){return this.create({bind:B,arguments:A})},bindWithEvent:function(B,A){return this.create({bind:B,event:true,arguments:A})},delay:function(B,C,A){return this.create({delay:B,bind:C,arguments:A})()},periodical:function(A,C,B){return this.create({periodical:A,bind:C,arguments:B})()},run:function(A,B){return this.apply(B,$splat(A))}});Number.implement({limit:function(B,A){return Math.min(A,Math.max(B,this))},round:function(A){A=Math.pow(10,A||0);return Math.round(this*A)/A},times:function(B,C){for(var A=0;A<this;A++){B.call(C,A,this)}},toFloat:function(){return parseFloat(this)},toInt:function(A){return parseInt(this,A||10)}});Number.alias("times","each");(function(B){var A={};B.each(function(C){if(!Number[C]){A[C]=function(){return Math[C].apply(null,[this].concat($A(arguments)))}}});Number.implement(A)})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);String.implement({test:function(A,B){return((typeof A=="string")?new RegExp(A,B):A).test(this)},contains:function(A,B){return(B)?(B+this+B).indexOf(B+A+B)>-1:this.indexOf(A)>-1},trim:function(){return this.replace(/^\s+|\s+$/g,"")},clean:function(){return this.replace(/\s+/g," ").trim()},camelCase:function(){return this.replace(/-\D/g,function(A){return A.charAt(1).toUpperCase()})},hyphenate:function(){return this.replace(/[A-Z]/g,function(A){return("-"+A.charAt(0).toLowerCase())})},capitalize:function(){return this.replace(/\b[a-z]/g,function(A){return A.toUpperCase()})},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1")},toInt:function(A){return parseInt(this,A||10)},toFloat:function(){return parseFloat(this)},hexToRgb:function(B){var A=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);return(A)?A.slice(1).hexToRgb(B):null},rgbToHex:function(B){var A=this.match(/\d{1,3}/g);return(A)?A.rgbToHex(B):null},stripScripts:function(B){var A="";var C=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(){A+=arguments[1]+"\n";return""});if(B===true){$exec(A)}else{if($type(B)=="function"){B(A,C)}}return C},substitute:function(A,B){return this.replace(B||(/\\?\{([^}]+)\}/g),function(D,C){if(D.charAt(0)=="\\"){return D.slice(1)}return(A[C]!=undefined)?A[C]:""})}});Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(B){for(var A in this){if(this.hasOwnProperty(A)&&this[A]===B){return A}}return null},hasValue:function(A){return(Hash.keyOf(this,A)!==null)},extend:function(A){Hash.each(A,function(C,B){Hash.set(this,B,C)},this);return this},combine:function(A){Hash.each(A,function(C,B){Hash.include(this,B,C)},this);return this},erase:function(A){if(this.hasOwnProperty(A)){delete this[A]}return this},get:function(A){return(this.hasOwnProperty(A))?this[A]:null},set:function(A,B){if(!this[A]||this.hasOwnProperty(A)){this[A]=B}return this},empty:function(){Hash.each(this,function(B,A){delete this[A]},this);return this},include:function(B,C){var A=this[B];if(A==undefined){this[B]=C}return this},map:function(B,C){var A=new Hash;Hash.each(this,function(E,D){A.set(D,B.call(C,E,D,this))},this);return A},filter:function(B,C){var A=new Hash;Hash.each(this,function(E,D){if(B.call(C,E,D,this)){A.set(D,E)}},this);return A},every:function(B,C){for(var A in this){if(this.hasOwnProperty(A)&&!B.call(C,this[A],A)){return false}}return true},some:function(B,C){for(var A in this){if(this.hasOwnProperty(A)&&B.call(C,this[A],A)){return true}}return false},getKeys:function(){var A=[];Hash.each(this,function(C,B){A.push(B)});return A},getValues:function(){var A=[];Hash.each(this,function(B){A.push(B)});return A},toQueryString:function(A){var B=[];Hash.each(this,function(F,E){if(A){E=A+"["+E+"]"}var D;switch($type(F)){case"object":D=Hash.toQueryString(F,E);break;case"array":var C={};F.each(function(H,G){C[G]=H});D=Hash.toQueryString(C,E);break;default:D=E+"="+encodeURIComponent(F)}if(F!=undefined){B.push(D)}});return B.join("&")}});Hash.alias({keyOf:"indexOf",hasValue:"contains"});var Event=new Native({name:"Event",initialize:function(A,F){F=F||window;var K=F.document;A=A||F.event;if(A.$extended){return A}this.$extended=true;var J=A.type;var G=A.target||A.srcElement;while(G&&G.nodeType==3){G=G.parentNode}if(J.test(/key/)){var B=A.which||A.keyCode;var M=Event.Keys.keyOf(B);if(J=="keydown"){var D=B-111;if(D>0&&D<13){M="f"+D}}M=M||String.fromCharCode(B).toLowerCase()}else{if(J.match(/(click|mouse|menu)/i)){K=(!K.compatMode||K.compatMode=="CSS1Compat")?K.html:K.body;var I={x:A.pageX||A.clientX+K.scrollLeft,y:A.pageY||A.clientY+K.scrollTop};var C={x:(A.pageX)?A.pageX-F.pageXOffset:A.clientX,y:(A.pageY)?A.pageY-F.pageYOffset:A.clientY};if(J.match(/DOMMouseScroll|mousewheel/)){var H=(A.wheelDelta)?A.wheelDelta/120:-(A.detail||0)/3}var E=(A.which==3)||(A.button==2);var L=null;if(J.match(/over|out/)){switch(J){case"mouseover":L=A.relatedTarget||A.fromElement;break;case"mouseout":L=A.relatedTarget||A.toElement}if(!(function(){while(L&&L.nodeType==3){L=L.parentNode}return true}).create({attempt:Browser.Engine.gecko})()){L=false}}}}return $extend(this,{event:A,type:J,page:I,client:C,rightClick:E,wheel:H,relatedTarget:L,target:G,code:B,key:M,shift:A.shiftKey,control:A.ctrlKey,alt:A.altKey,meta:A.metaKey})}});Event.Keys=new Hash({enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46});Event.implement({stop:function(){return this.stopPropagation().preventDefault()},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation()}else{this.event.cancelBubble=true}return this},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault()}else{this.event.returnValue=false}return this}});var Class=new Native({name:"Class",initialize:function(B){B=B||{};var A=function(E){for(var D in this){this[D]=$unlink(this[D])}for(var F in Class.Mutators){if(!this[F]){continue}Class.Mutators[F](this,this[F]);delete this[F]}this.constructor=A;if(E===$empty){return this}var C=(this.initialize)?this.initialize.apply(this,arguments):this;if(this.options&&this.options.initialize){this.options.initialize.call(this)}return C};$extend(A,this);A.constructor=Class;A.prototype=B;return A}});Class.implement({implement:function(){Class.Mutators.Implements(this.prototype,Array.slice(arguments));return this}});Class.Mutators={Implements:function(A,B){$splat(B).each(function(C){$extend(A,($type(C)=="class")?new C($empty):C)})},Extends:function(self,klass){var instance=new klass($empty);delete instance.parent;delete instance.parentOf;for(var key in instance){var current=self[key],previous=instance[key];if(current==undefined){self[key]=previous;continue}var ctype=$type(current),ptype=$type(previous);if(ctype!=ptype){continue}switch(ctype){case"function":if(!arguments.callee.caller){self[key]=eval("("+String(current).replace(/\bthis\.parent\(\s*(\))?/g,function(full,close){return"arguments.callee._parent_.call(this"+(close||", ")})+")")}self[key]._parent_=previous;break;case"object":self[key]=$merge(previous,current)}}self.parent=function(){return arguments.callee.caller._parent_.apply(this,arguments)};self.parentOf=function(descendant){return descendant._parent_.apply(this,Array.slice(arguments,1))}}};var Chain=new Class({chain:function(){this.$chain=(this.$chain||[]).extend(arguments);return this},callChain:function(){return(this.$chain&&this.$chain.length)?this.$chain.shift().apply(this,arguments):false},clearChain:function(){if(this.$chain){this.$chain.empty()}return this}});var Events=new Class({addEvent:function(C,B,A){C=Events.removeOn(C);if(B!=$empty){this.$events=this.$events||{};this.$events[C]=this.$events[C]||[];this.$events[C].include(B);if(A){B.internal=true}}return this},addEvents:function(A){for(var B in A){this.addEvent(B,A[B])}return this},fireEvent:function(C,B,A){C=Events.removeOn(C);if(!this.$events||!this.$events[C]){return this}this.$events[C].each(function(D){D.create({bind:this,delay:A,"arguments":B})()},this);return this},removeEvent:function(B,A){B=Events.removeOn(B);if(!this.$events||!this.$events[B]){return this}if(!A.internal){this.$events[B].erase(A)}return this},removeEvents:function(C){for(var D in this.$events){if(C&&C!=D){continue}var B=this.$events[D];for(var A=B.length;A--;A){this.removeEvent(D,B[A])}}return this}});Events.removeOn=function(A){return A.replace(/^on([A-Z])/,function(B,C){return C.toLowerCase()})};var Options=new Class({setOptions:function(){this.options=$merge.run([this.options].extend(arguments));if(!this.addEvent){return this}for(var A in this.options){if($type(this.options[A])!="function"||!(/^on[A-Z]/).test(A)){continue}this.addEvent(A,this.options[A]);delete this.options[A]}return this}});Document.implement({newElement:function(A,B){if(Browser.Engine.trident&&B){["name","type","checked"].each(function(C){if(!B[C]){return }A+=" "+C+'="'+B[C]+'"';if(C!="checked"){delete B[C]}});A="<"+A+">"}return $.element(this.createElement(A)).set(B)},newTextNode:function(A){return this.createTextNode(A)},getDocument:function(){return this},getWindow:function(){return this.defaultView||this.parentWindow},purge:function(){var C=this.getElementsByTagName("*");for(var B=0,A=C.length;B<A;B++){Browser.freeMem(C[B])}}});var Element=new Native({name:"Element",legacy:window.Element,initialize:function(A,B){var C=Element.Constructors.get(A);if(C){return C(B)}if(typeof A=="string"){return document.newElement(A,B)}return $(A).set(B)},afterImplement:function(A,B){if(!Array[A]){Elements.implement(A,Elements.multi(A))}Element.Prototype[A]=B}});Element.Prototype={$family:{name:"element"}};Element.Constructors=new Hash;var IFrame=new Native({name:"IFrame",generics:false,initialize:function(){var E=Array.link(arguments,{properties:Object.type,iframe:$defined});var C=E.properties||{};var B=$(E.iframe)||false;var D=C.onload||$empty;delete C.onload;C.id=C.name=$pick(C.id,C.name,B.id,B.name,"IFrame_"+$time());B=new Element(B||"iframe",C);var A=function(){var F=$try(function(){return B.contentWindow.location.host});if(F&&F==window.location.host){var H=new Window(B.contentWindow);var G=new Document(B.contentWindow.document);$extend(H.Element.prototype,Element.Prototype)}D.call(B.contentWindow,B.contentWindow.document)};(!window.frames[C.id])?B.addListener("load",A):A();return B}});var Elements=new Native({initialize:function(F,B){B=$extend({ddup:true,cash:true},B);F=F||[];if(B.ddup||B.cash){var G={},E=[];for(var C=0,A=F.length;C<A;C++){var D=$.element(F[C],!B.cash);if(B.ddup){if(G[D.uid]){continue}G[D.uid]=true}E.push(D)}F=E}return(B.cash)?$extend(F,this):F}});Elements.implement({filter:function(A,B){if(!A){return this}return new Elements(Array.filter(this,(typeof A=="string")?function(C){return C.match(A)}:A,B))}});Elements.multi=function(A){return function(){var B=[];var F=true;for(var D=0,C=this.length;D<C;D++){var E=this[D][A].apply(this[D],arguments);B.push(E);if(F){F=($type(E)=="element")}}return(F)?new Elements(B):B}};Window.implement({$:function(B,C){if(B&&B.$family&&B.uid){return B}var A=$type(B);return($[A])?$[A](B,C,this.document):null},$$:function(A){if(arguments.length==1&&typeof A=="string"){return this.document.getElements(A)}var F=[];var C=Array.flatten(arguments);for(var D=0,B=C.length;D<B;D++){var E=C[D];switch($type(E)){case"element":E=[E];break;case"string":E=this.document.getElements(E,true);break;default:E=false}if(E){F.extend(E)}}return new Elements(F)},getDocument:function(){return this.document},getWindow:function(){return this}});$.string=function(C,B,A){C=A.getElementById(C);return(C)?$.element(C,B):null};$.element=function(A,D){$uid(A);if(!D&&!A.$family&&!(/^object|embed$/i).test(A.tagName)){var B=Element.Prototype;for(var C in B){A[C]=B[C]}}return A};$.object=function(B,C,A){if(B.toElement){return $.element(B.toElement(A),C)}return null};$.textnode=$.whitespace=$.window=$.document=$arguments(0);Native.implement([Element,Document],{getElement:function(A,B){return $(this.getElements(A,true)[0]||null,B)},getElements:function(A,D){A=A.split(",");var C=[];var B=(A.length>1);A.each(function(E){var F=this.getElementsByTagName(E.trim());(B)?C.extend(F):C=F},this);return new Elements(C,{ddup:B,cash:!D})}});Element.Storage={get:function(A){return(this[A]||(this[A]={}))}};Element.Inserters=new Hash({before:function(B,A){if(A.parentNode){A.parentNode.insertBefore(B,A)}},after:function(B,A){if(!A.parentNode){return }var C=A.nextSibling;(C)?A.parentNode.insertBefore(B,C):A.parentNode.appendChild(B)},bottom:function(B,A){A.appendChild(B)},top:function(B,A){var C=A.firstChild;(C)?A.insertBefore(B,C):A.appendChild(B)}});Element.Inserters.inside=Element.Inserters.bottom;Element.Inserters.each(function(C,B){var A=B.capitalize();Element.implement("inject"+A,function(D){C(this,$(D,true));return this});Element.implement("grab"+A,function(D){C($(D,true),this);return this})});Element.implement({getDocument:function(){return this.ownerDocument},getWindow:function(){return this.ownerDocument.getWindow()},getElementById:function(D,C){var B=this.ownerDocument.getElementById(D);if(!B){return null}for(var A=B.parentNode;A!=this;A=A.parentNode){if(!A){return null}}return $.element(B,C)},set:function(D,B){switch($type(D)){case"object":for(var C in D){this.set(C,D[C])}break;case"string":var A=Element.Properties.get(D);(A&&A.set)?A.set.apply(this,Array.slice(arguments,1)):this.setProperty(D,B)}return this},get:function(B){var A=Element.Properties.get(B);return(A&&A.get)?A.get.apply(this,Array.slice(arguments,1)):this.getProperty(B)},erase:function(B){var A=Element.Properties.get(B);(A&&A.erase)?A.erase.apply(this,Array.slice(arguments,1)):this.removeProperty(B);return this},match:function(A){return(!A||Element.get(this,"tag")==A)},inject:function(B,A){Element.Inserters.get(A||"bottom")(this,$(B,true));return this},wraps:function(B,A){B=$(B,true);return this.replaces(B).grab(B,A)},grab:function(B,A){Element.Inserters.get(A||"bottom")($(B,true),this);return this},appendText:function(B,A){return this.grab(this.getDocument().newTextNode(B),A)},adopt:function(){Array.flatten(arguments).each(function(A){A=$(A,true);if(A){this.appendChild(A)}},this);return this},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this},clone:function(D,C){switch($type(this)){case"element":var H={};for(var G=0,E=this.attributes.length;G<E;G++){var B=this.attributes[G],L=B.nodeName.toLowerCase();if(Browser.Engine.trident&&(/input/i).test(this.tagName)&&(/width|height/).test(L)){continue}var K=(L=="style"&&this.style)?this.style.cssText:B.nodeValue;if(!$chk(K)||L=="uid"||(L=="id"&&!C)){continue}if(K!="inherit"&&["string","number"].contains($type(K))){H[L]=K}}var J=new Element(this.nodeName.toLowerCase(),H);if(D!==false){for(var I=0,F=this.childNodes.length;I<F;I++){var A=Element.clone(this.childNodes[I],true,C);if(A){J.grab(A)}}}return J;case"textnode":return document.newTextNode(this.nodeValue)}return null},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this,A);return this},hasClass:function(A){return this.className.contains(A," ")},addClass:function(A){if(!this.hasClass(A)){this.className=(this.className+" "+A).clean()}return this},removeClass:function(A){this.className=this.className.replace(new RegExp("(^|\\s)"+A+"(?:\\s|$)"),"$1").clean();return this},toggleClass:function(A){return this.hasClass(A)?this.removeClass(A):this.addClass(A)},getComputedStyle:function(B){if(this.currentStyle){return this.currentStyle[B.camelCase()]}var A=this.getWindow().getComputedStyle(this,null);return(A)?A.getPropertyValue([B.hyphenate()]):null},empty:function(){$A(this.childNodes).each(function(A){Browser.freeMem(A);Element.empty(A);Element.dispose(A)},this);return this},destroy:function(){Browser.freeMem(this.empty().dispose());return null},getSelected:function(){return new Elements($A(this.options).filter(function(A){return A.selected}))},toQueryString:function(){var A=[];this.getElements("input, select, textarea").each(function(B){if(!B.name||B.disabled){return }var C=(B.tagName.toLowerCase()=="select")?Element.getSelected(B).map(function(D){return D.value}):((B.type=="radio"||B.type=="checkbox")&&!B.checked)?null:B.value;$splat(C).each(function(D){if(D){A.push(B.name+"="+encodeURIComponent(D))}})});return A.join("&")},getProperty:function(C){var B=Element.Attributes,A=B.Props[C];var D=(A)?this[A]:this.getAttribute(C,2);return(B.Bools[C])?!!D:(A)?D:D||null},getProperties:function(){var A=$A(arguments);return A.map(function(B){return this.getProperty(B)},this).associate(A)},setProperty:function(D,E){var C=Element.Attributes,B=C.Props[D],A=$defined(E);if(B&&C.Bools[D]){E=(E||!A)?true:false}else{if(!A){return this.removeProperty(D)}}(B)?this[B]=E:this.setAttribute(D,E);return this},setProperties:function(A){for(var B in A){this.setProperty(B,A[B])}return this},removeProperty:function(D){var C=Element.Attributes,B=C.Props[D],A=(B&&C.Bools[D]);(B)?this[B]=(A)?false:"":this.removeAttribute(D);return this},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this}});(function(){var A=function(D,B,I,C,F,H){var E=D[I||B];var G=[];while(E){if(E.nodeType==1&&(!C||Element.match(E,C))){G.push(E);if(!F){break}}E=E[B]}return(F)?new Elements(G,{ddup:false,cash:!H}):$(G[0],H)};Element.implement({getPrevious:function(B,C){return A(this,"previousSibling",null,B,false,C)},getAllPrevious:function(B,C){return A(this,"previousSibling",null,B,true,C)},getNext:function(B,C){return A(this,"nextSibling",null,B,false,C)},getAllNext:function(B,C){return A(this,"nextSibling",null,B,true,C)},getFirst:function(B,C){return A(this,"nextSibling","firstChild",B,false,C)},getLast:function(B,C){return A(this,"previousSibling","lastChild",B,false,C)},getParent:function(B,C){return A(this,"parentNode",null,B,false,C)},getParents:function(B,C){return A(this,"parentNode",null,B,true,C)},getChildren:function(B,C){return A(this,"nextSibling","firstChild",B,true,C)},hasChild:function(B){B=$(B,true);return(!!B&&$A(this.getElementsByTagName(B.tagName)).contains(B))}})})();Element.Properties=new Hash;Element.Properties.style={set:function(A){this.style.cssText=A},get:function(){return this.style.cssText},erase:function(){this.style.cssText=""}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase()}};Element.Properties.href={get:function(){return(!this.href)?null:this.href.replace(new RegExp("^"+document.location.protocol+"//"+document.location.host),"")}};Element.Properties.html={set:function(){return this.innerHTML=Array.flatten(arguments).join("")}};Native.implement([Element,Window,Document],{addListener:function(B,A){if(this.addEventListener){this.addEventListener(B,A,false)}else{this.attachEvent("on"+B,A)}return this},removeListener:function(B,A){if(this.removeEventListener){this.removeEventListener(B,A,false)}else{this.detachEvent("on"+B,A)}return this},retrieve:function(B,A){var D=Element.Storage.get(this.uid);var C=D[B];if($defined(A)&&!$defined(C)){C=D[B]=A}return $pick(C)},store:function(B,A){var C=Element.Storage.get(this.uid);C[B]=A;return this},eliminate:function(A){var B=Element.Storage.get(this.uid);delete B[A];return this}});Element.Attributes=new Hash({Props:{html:"innerHTML","class":"className","for":"htmlFor",text:(Browser.Engine.trident)?"innerText":"textContent"},Bools:["compact","nowrap","ismap","declare","noshade","checked","disabled","readonly","multiple","selected","noresize","defer"],Camels:["value","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","maxLength","readOnly","rowSpan","tabIndex","useMap"]});Browser.freeMem=function(A){if(!A){return }if(Browser.Engine.trident&&(/object/i).test(A.tagName)){for(var B in A){if(typeof A[B]=="function"){A[B]=$empty}}Element.dispose(A)}if(A.uid&&A.removeEvents){A.removeEvents()}};(function(B){var C=B.Bools,A=B.Camels;B.Bools=C=C.associate(C);Hash.extend(Hash.combine(B.Props,C),A.associate(A.map(function(D){return D.toLowerCase()})));B.erase("Camels")})(Element.Attributes);window.addListener("unload",function(){window.removeListener("unload",arguments.callee);document.purge();if(Browser.Engine.trident){CollectGarbage()}});Element.Properties.events={set:function(A){this.addEvents(A)}};Native.implement([Element,Window,Document],{addEvent:function(E,G){var H=this.retrieve("events",{});H[E]=H[E]||{keys:[],values:[]};if(H[E].keys.contains(G)){return this}H[E].keys.push(G);var F=E,A=Element.Events.get(E),C=G,I=this;if(A){if(A.onAdd){A.onAdd.call(this,G)}if(A.condition){C=function(J){if(A.condition.call(this,J)){return G.call(this,J)}return false}}F=A.base||F}var D=function(){return G.call(I)};var B=Element.NativeEvents[F]||0;if(B){if(B==2){D=function(J){J=new Event(J,I.getWindow());if(C.call(I,J)===false){J.stop()}}}this.addListener(F,D)}H[E].values.push(D);return this},removeEvent:function(D,C){var B=this.retrieve("events");if(!B||!B[D]){return this}var G=B[D].keys.indexOf(C);if(G==-1){return this}var A=B[D].keys.splice(G,1)[0];var F=B[D].values.splice(G,1)[0];var E=Element.Events.get(D);if(E){if(E.onRemove){E.onRemove.call(this,C)}D=E.base||D}return(Element.NativeEvents[D])?this.removeListener(D,F):this},addEvents:function(A){for(var B in A){this.addEvent(B,A[B])}return this},removeEvents:function(B){var A=this.retrieve("events");if(!A){return this}if(!B){for(var C in A){this.removeEvents(C)}A=null}else{if(A[B]){while(A[B].keys[0]){this.removeEvent(B,A[B].keys[0])}A[B]=null}}return this},fireEvent:function(D,B,A){var C=this.retrieve("events");if(!C||!C[D]){return this}C[D].keys.each(function(E){E.create({bind:this,delay:A,"arguments":B})()},this);return this},cloneEvents:function(D,A){D=$(D);var C=D.retrieve("events");if(!C){return this}if(!A){for(var B in C){this.cloneEvents(D,B)}}else{if(C[A]){C[A].keys.each(function(E){this.addEvent(A,E)},this)}}return this}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,load:1,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};(function(){var A=function(B){var C=B.relatedTarget;if(C==undefined){return true}if(C===false){return false}return($type(this)!="document"&&C!=this&&C.prefix!="xul"&&!this.hasChild(C))};Element.Events=new Hash({mouseenter:{base:"mouseover",condition:A},mouseleave:{base:"mouseout",condition:A},mousewheel:{base:(Browser.Engine.gecko)?"DOMMouseScroll":"mousewheel"}})})();Element.Properties.styles={set:function(A){this.setStyles(A)}};Element.Properties.opacity={set:function(A,B){if(!B){if(A==0){if(this.style.visibility!="hidden"){this.style.visibility="hidden"}}else{if(this.style.visibility!="visible"){this.style.visibility="visible"}}}if(!this.currentStyle||!this.currentStyle.hasLayout){this.style.zoom=1}if(Browser.Engine.trident){this.style.filter=(A==1)?"":"alpha(opacity="+A*100+")"}this.style.opacity=A;this.store("opacity",A)},get:function(){return this.retrieve("opacity",1)}};Element.implement({setOpacity:function(A){return this.set("opacity",A,true)},getOpacity:function(){return this.get("opacity")},setStyle:function(B,A){switch(B){case"opacity":return this.set("opacity",parseFloat(A));case"float":B=(Browser.Engine.trident)?"styleFloat":"cssFloat"}B=B.camelCase();if($type(A)!="string"){var C=(Element.Styles.get(B)||"@").split(" ");A=$splat(A).map(function(E,D){if(!C[D]){return""}return($type(E)=="number")?C[D].replace("@",Math.round(E)):E}).join(" ")}else{if(A==String(Number(A))){A=Math.round(A)}}this.style[B]=A;return this},getStyle:function(G){switch(G){case"opacity":return this.get("opacity");case"float":G=(Browser.Engine.trident)?"styleFloat":"cssFloat"}G=G.camelCase();var A=this.style[G];if(!$chk(A)){A=[];for(var F in Element.ShortStyles){if(G!=F){continue}for(var E in Element.ShortStyles[F]){A.push(this.getStyle(E))}return A.join(" ")}A=this.getComputedStyle(G)}if(A){A=String(A);var C=A.match(/rgba?\([\d\s,]+\)/);if(C){A=A.replace(C[0],C[0].rgbToHex())}}if(Browser.Engine.presto||(Browser.Engine.trident&&!$chk(parseInt(A)))){if(G.test(/^(height|width)$/)){var B=(G=="width")?["left","right"]:["top","bottom"],D=0;B.each(function(H){D+=this.getStyle("border-"+H+"-width").toInt()+this.getStyle("padding-"+H).toInt()},this);return this["offset"+G.capitalize()]-D+"px"}if(Browser.Engine.presto&&String(A).test("px")){return A}if(G.test(/(border(.+)Width|margin|padding)/)){return"0px"}}return A},setStyles:function(B){for(var A in B){this.setStyle(A,B[A])}return this},getStyles:function(){var A={};Array.each(arguments,function(B){A[B]=this.getStyle(B)},this);return A}});Element.Styles=new Hash({left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"});Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(G){var F=Element.ShortStyles;var B=Element.Styles;["margin","padding"].each(function(H){var I=H+G;F[H][I]=B[I]="@px"});var E="border"+G;F.border[E]=B[E]="@px @ rgb(@, @, @)";var D=E+"Width",A=E+"Style",C=E+"Color";F[E]={};F.borderWidth[D]=F[E][D]=B[D]="@px";F.borderStyle[A]=F[E][A]=B[A]="@";F.borderColor[C]=F[E][C]=B[C]="rgb(@, @, @)"});(function(){Element.implement({scrollTo:function(H,I){if(B(this)){this.getWindow().scrollTo(H,I)}else{this.scrollLeft=H;this.scrollTop=I}return this},getSize:function(){if(B(this)){return this.getWindow().getSize()}return{x:this.offsetWidth,y:this.offsetHeight}},getScrollSize:function(){if(B(this)){return this.getWindow().getScrollSize()}return{x:this.scrollWidth,y:this.scrollHeight}},getScroll:function(){if(B(this)){return this.getWindow().getScroll()}return{x:this.scrollLeft,y:this.scrollTop}},getScrolls:function(){var I=this,H={x:0,y:0};while(I&&!B(I)){H.x+=I.scrollLeft;H.y+=I.scrollTop;I=I.parentNode}return H},getOffsetParent:function(){var H=this;if(B(H)){return null}if(!Browser.Engine.trident){return H.offsetParent}while((H=H.parentNode)&&!B(H)){if(D(H,"position")!="static"){return H}}return null},getOffsets:function(){var I=this,H={x:0,y:0};if(B(this)){return H}while(I&&!B(I)){H.x+=I.offsetLeft;H.y+=I.offsetTop;if(Browser.Engine.gecko){if(!F(I)){H.x+=C(I);H.y+=G(I)}var J=I.parentNode;if(J&&D(J,"overflow")!="visible"){H.x+=C(J);H.y+=G(J)}}else{if(I!=this&&(Browser.Engine.trident||Browser.Engine.webkit)){H.x+=C(I);H.y+=G(I)}}I=I.offsetParent;if(Browser.Engine.trident){while(I&&!I.currentStyle.hasLayout){I=I.offsetParent}}}if(Browser.Engine.gecko&&!F(this)){H.x-=C(this);H.y-=G(this)}return H},getPosition:function(K){if(B(this)){return{x:0,y:0}}var L=this.getOffsets(),I=this.getScrolls();var H={x:L.x-I.x,y:L.y-I.y};var J=(K&&(K=$(K)))?K.getPosition():{x:0,y:0};return{x:H.x-J.x,y:H.y-J.y}},getCoordinates:function(J){if(B(this)){return this.getWindow().getCoordinates()}var H=this.getPosition(J),I=this.getSize();var K={left:H.x,top:H.y,width:I.x,height:I.y};K.right=K.left+K.width;K.bottom=K.top+K.height;return K},computePosition:function(H){return{left:H.x-E(this,"margin-left"),top:H.y-E(this,"margin-top")}},position:function(H){return this.setStyles(this.computePosition(H))}});Native.implement([Document,Window],{getSize:function(){var I=this.getWindow();if(Browser.Engine.presto||Browser.Engine.webkit){return{x:I.innerWidth,y:I.innerHeight}}var H=A(this);return{x:H.clientWidth,y:H.clientHeight}},getScroll:function(){var I=this.getWindow();var H=A(this);return{x:I.pageXOffset||H.scrollLeft,y:I.pageYOffset||H.scrollTop}},getScrollSize:function(){var I=A(this);var H=this.getSize();return{x:Math.max(I.scrollWidth,H.x),y:Math.max(I.scrollHeight,H.y)}},getPosition:function(){return{x:0,y:0}},getCoordinates:function(){var H=this.getSize();return{top:0,left:0,bottom:H.y,right:H.x,height:H.y,width:H.x}}});var D=Element.getComputedStyle;function E(H,I){return D(H,I).toInt()||0}function F(H){return D(H,"-moz-box-sizing")=="border-box"}function G(H){return E(H,"border-top-width")}function C(H){return E(H,"border-left-width")}function B(H){return(/^(?:body|html)$/i).test(H.tagName)}function A(H){var I=H.getDocument();return(!I.compatMode||I.compatMode=="CSS1Compat")?I.html:I.body}})();Native.implement([Window,Document,Element],{getHeight:function(){return this.getSize().y},getWidth:function(){return this.getSize().x},getScrollTop:function(){return this.getScroll().y},getScrollLeft:function(){return this.getScroll().x},getScrollHeight:function(){return this.getScrollSize().y},getScrollWidth:function(){return this.getScrollSize().x},getTop:function(){return this.getPosition().y},getLeft:function(){return this.getPosition().x}});Native.implement([Document,Element],{getElements:function(H,G){H=H.split(",");var C,E={};for(var D=0,B=H.length;D<B;D++){var A=H[D],F=Selectors.Utils.search(this,A,E);if(D!=0&&F.item){F=$A(F)}C=(D==0)?F:(C.item)?$A(C).concat(F):C.concat(F)}return new Elements(C,{ddup:(H.length>1),cash:!G})}});Element.implement({match:function(B){if(!B){return true}var D=Selectors.Utils.parseTagAndID(B);var A=D[0],E=D[1];if(!Selectors.Filters.byID(this,E)||!Selectors.Filters.byTag(this,A)){return false}var C=Selectors.Utils.parseSelector(B);return(C)?Selectors.Utils.filter(this,C,{}):true}});var Selectors={Cache:{nth:{},parsed:{}}};Selectors.RegExps={id:(/#([\w-]+)/),tag:(/^(\w+|\*)/),quick:(/^(\w+|\*)$/),splitter:(/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),combined:(/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)};Selectors.Utils={chk:function(B,C){if(!C){return true}var A=$uid(B);if(!C[A]){return C[A]=true}return false},parseNthArgument:function(F){if(Selectors.Cache.nth[F]){return Selectors.Cache.nth[F]}var C=F.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);if(!C){return false}var E=parseInt(C[1]);var B=(E||E===0)?E:1;var D=C[2]||false;var A=parseInt(C[3])||0;if(B!=0){A--;while(A<1){A+=B}while(A>=B){A-=B}}else{B=A;D="index"}switch(D){case"n":C={a:B,b:A,special:"n"};break;case"odd":C={a:2,b:0,special:"n"};break;case"even":C={a:2,b:1,special:"n"};break;case"first":C={a:0,special:"index"};break;case"last":C={special:"last-child"};break;case"only":C={special:"only-child"};break;default:C={a:(B-1),special:"index"}}return Selectors.Cache.nth[F]=C},parseSelector:function(E){if(Selectors.Cache.parsed[E]){return Selectors.Cache.parsed[E]}var D,H={classes:[],pseudos:[],attributes:[]};while((D=Selectors.RegExps.combined.exec(E))){var I=D[1],G=D[2],F=D[3],B=D[4],C=D[5],J=D[6];if(I){H.classes.push(I)}else{if(C){var A=Selectors.Pseudo.get(C);if(A){H.pseudos.push({parser:A,argument:J})}else{H.attributes.push({name:C,operator:"=",value:J})}}else{if(G){H.attributes.push({name:G,operator:F,value:B})}}}}if(!H.classes.length){delete H.classes}if(!H.attributes.length){delete H.attributes}if(!H.pseudos.length){delete H.pseudos}if(!H.classes&&!H.attributes&&!H.pseudos){H=null}return Selectors.Cache.parsed[E]=H},parseTagAndID:function(B){var A=B.match(Selectors.RegExps.tag);var C=B.match(Selectors.RegExps.id);return[(A)?A[1]:"*",(C)?C[1]:false]},filter:function(F,C,E){var D;if(C.classes){for(D=C.classes.length;D--;D){var G=C.classes[D];if(!Selectors.Filters.byClass(F,G)){return false}}}if(C.attributes){for(D=C.attributes.length;D--;D){var B=C.attributes[D];if(!Selectors.Filters.byAttribute(F,B.name,B.operator,B.value)){return false}}}if(C.pseudos){for(D=C.pseudos.length;D--;D){var A=C.pseudos[D];if(!Selectors.Filters.byPseudo(F,A.parser,A.argument,E)){return false}}}return true},getByTagAndID:function(B,A,D){if(D){var C=(B.getElementById)?B.getElementById(D,true):Element.getElementById(B,D,true);return(C&&Selectors.Filters.byTag(C,A))?[C]:[]}else{return B.getElementsByTagName(A)}},search:function(J,I,O){var B=[];var C=I.trim().replace(Selectors.RegExps.splitter,function(Z,Y,X){B.push(Y);return":)"+X}).split(":)");var K,F,E,V;for(var U=0,Q=C.length;U<Q;U++){var T=C[U];if(U==0&&Selectors.RegExps.quick.test(T)){K=J.getElementsByTagName(T);continue}var A=B[U-1];var L=Selectors.Utils.parseTagAndID(T);var W=L[0],M=L[1];if(U==0){K=Selectors.Utils.getByTagAndID(J,W,M)}else{var D={},H=[];for(var S=0,R=K.length;S<R;S++){H=Selectors.Getters[A](H,K[S],W,M,D)}K=H}var G=Selectors.Utils.parseSelector(T);if(G){E=[];for(var P=0,N=K.length;P<N;P++){V=K[P];if(Selectors.Utils.filter(V,G,O)){E.push(V)}}K=E}}return K}};Selectors.Getters={" ":function(H,G,I,A,E){var D=Selectors.Utils.getByTagAndID(G,I,A);for(var C=0,B=D.length;C<B;C++){var F=D[C];if(Selectors.Utils.chk(F,E)){H.push(F)}}return H},">":function(H,G,I,A,F){var C=Selectors.Utils.getByTagAndID(G,I,A);for(var E=0,D=C.length;E<D;E++){var B=C[E];if(B.parentNode==G&&Selectors.Utils.chk(B,F)){H.push(B)}}return H},"+":function(C,B,A,E,D){while((B=B.nextSibling)){if(B.nodeType==1){if(Selectors.Utils.chk(B,D)&&Selectors.Filters.byTag(B,A)&&Selectors.Filters.byID(B,E)){C.push(B)}break}}return C},"~":function(C,B,A,E,D){while((B=B.nextSibling)){if(B.nodeType==1){if(!Selectors.Utils.chk(B,D)){break}if(Selectors.Filters.byTag(B,A)&&Selectors.Filters.byID(B,E)){C.push(B)}}}return C}};Selectors.Filters={byTag:function(B,A){return(A=="*"||(B.tagName&&B.tagName.toLowerCase()==A))},byID:function(A,B){return(!B||(A.id&&A.id==B))},byClass:function(B,A){return(B.className&&B.className.contains(A," "))},byPseudo:function(A,D,C,B){return D.call(A,C,B)},byAttribute:function(C,D,B,E){var A=Element.prototype.getProperty.call(C,D);if(!A){return false}if(!B||E==undefined){return true}switch(B){case"=":return(A==E);case"*=":return(A.contains(E));case"^=":return(A.substr(0,E.length)==E);case"$=":return(A.substr(A.length-E.length)==E);case"!=":return(A!=E);case"~=":return A.contains(E," ");case"|=":return A.contains(E,"-")}return false}};Selectors.Pseudo=new Hash({empty:function(){return !(this.innerText||this.textContent||"").length},not:function(A){return !Element.match(this,A)},contains:function(A){return(this.innerText||this.textContent||"").contains(A)},"first-child":function(){return Selectors.Pseudo.index.call(this,0)},"last-child":function(){var A=this;while((A=A.nextSibling)){if(A.nodeType==1){return false}}return true},"only-child":function(){var B=this;while((B=B.previousSibling)){if(B.nodeType==1){return false}}var A=this;while((A=A.nextSibling)){if(A.nodeType==1){return false}}return true},"nth-child":function(G,E){G=(G==undefined)?"n":G;var C=Selectors.Utils.parseNthArgument(G);if(C.special!="n"){return Selectors.Pseudo[C.special].call(this,C.a,E)}var F=0;E.positions=E.positions||{};var D=$uid(this);if(!E.positions[D]){var B=this;while((B=B.previousSibling)){if(B.nodeType!=1){continue}F++;var A=E.positions[$uid(B)];if(A!=undefined){F=A+F;break}}E.positions[D]=F}return(E.positions[D]%C.a==C.b)},index:function(A){var B=this,C=0;while((B=B.previousSibling)){if(B.nodeType==1&&++C>A){return false}}return(C==A)},even:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n+1",A)},odd:function(B,A){return Selectors.Pseudo["nth-child"].call(this,"2n",A)}});Element.Events.domready={onAdd:function(A){if(Browser.loaded){A.call(this)}}};(function(){var B=function(){if(Browser.loaded){return }Browser.loaded=true;window.fireEvent("domready");document.fireEvent("domready")};switch(Browser.Engine.name){case"webkit":(function(){(["loaded","complete"].contains(document.readyState))?B():arguments.callee.delay(50)})();break;case"trident":var A=document.createElement("div");(function(){($try(function(){A.doScroll("left");return $(A).inject(document.body).set("html","temp").dispose()}))?B():arguments.callee.delay(50)})();break;default:window.addEvent("load",B);document.addEvent("DOMContentLoaded",B)}})();var JSON=new Hash({encode:function(B){switch($type(B)){case"string":return'"'+B.replace(/[\x00-\x1f\\"]/g,JSON.$replaceChars)+'"';case"array":return"["+String(B.map(JSON.encode).filter($defined))+"]";case"object":case"hash":var A=[];Hash.each(B,function(E,D){var C=JSON.encode(E);if(C){A.push(JSON.encode(D)+":"+C)}});return"{"+A+"}";case"number":case"boolean":return String(B);case false:return"null"}return null},$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(A){return JSON.$specialChars[A]||"\\u00"+Math.floor(A.charCodeAt()/16).toString(16)+(A.charCodeAt()%16).toString(16)},decode:function(string,secure){if($type(string)!="string"||!string.length){return null}if(secure&&!(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){return null}return eval("("+string+")")}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this)}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(B,A){this.key=B;this.setOptions(A)},write:function(B){B=encodeURIComponent(B);if(this.options.domain){B+="; domain="+this.options.domain}if(this.options.path){B+="; path="+this.options.path}if(this.options.duration){var A=new Date();A.setTime(A.getTime()+this.options.duration*24*60*60*1000);B+="; expires="+A.toGMTString()}if(this.options.secure){B+="; secure"}this.options.document.cookie=this.key+"="+B;return this},read:function(){var A=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");return(A)?decodeURIComponent(A[1]):null},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this}});Cookie.write=function(B,C,A){return new Cookie(B,A).write(C)};Cookie.read=function(A){return new Cookie(A).read()};Cookie.dispose=function(B,A){return new Cookie(B,A).dispose()};var Swiff=new Class({Implements:[Options],options:{id:null,height:1,width:1,container:null,properties:{},params:{quality:"high",allowScriptAccess:"always",wMode:"transparent",swLiveConnect:true},callBacks:{},vars:{}},toElement:function(){return this.object},initialize:function(L,M){this.instance="Swiff_"+$time();this.setOptions(M);M=this.options;var B=this.id=M.id||this.instance;var A=$(M.container);Swiff.CallBacks[this.instance]={};var E=M.params,G=M.vars,F=M.callBacks;var H=$extend({height:M.height,width:M.width},M.properties);var K=this;for(var D in F){Swiff.CallBacks[this.instance][D]=(function(N){return function(){return N.apply(K.object,arguments)}})(F[D]);G[D]="Swiff.CallBacks."+this.instance+"."+D}E.flashVars=Hash.toQueryString(G);if(Browser.Engine.trident){H.classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000";E.movie=L}else{H.type="application/x-shockwave-flash";H.data=L}var J='<object id="'+B+'"';for(var I in H){J+=" "+I+'="'+H[I]+'"'}J+=">";for(var C in E){if(E[C]){J+='<param name="'+C+'" value="'+E[C]+'" />'}}J+="</object>";this.object=((A)?A.empty():new Element("div")).set("html",J).firstChild},replaces:function(A){A=$(A,true);A.parentNode.replaceChild(this.toElement(),A);return this},inject:function(A){$(A,true).appendChild(this.toElement());return this},remote:function(){return Swiff.remote.apply(Swiff,[this.toElement()].extend(arguments))}});Swiff.CallBacks={};Swiff.remote=function(obj,fn){var rs=obj.CallFunction('<invoke name="'+fn+'" returntype="javascript">'+__flash__argumentsToXML(arguments,2)+"</invoke>");return eval(rs)};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore",transition:function(A){return -(Math.cos(Math.PI*A)-1)/2}},initialize:function(A){this.subject=this.subject||this;this.setOptions(A);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt();var B=this.options.wait;if(B===false){this.options.link="cancel"}},step:function(){var A=$time();if(A<this.time+this.options.duration){var B=this.options.transition((A-this.time)/this.options.duration);this.set(this.compute(this.from,this.to,B))}else{this.set(this.compute(this.from,this.to,1));this.complete()}},set:function(A){return A},compute:function(C,B,A){return Fx.compute(C,B,A)},check:function(A){if(!this.timer){return true}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));return false}return false},start:function(B,A){if(!this.check(arguments.callee,B,A)){return this}this.from=B;this.to=A;this.time=0;this.startTimer();this.onStart();return this},complete:function(){if(this.stopTimer()){this.onComplete()}return this},cancel:function(){if(this.stopTimer()){this.onCancel()}return this},onStart:function(){this.fireEvent("start",this.subject)},onComplete:function(){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject)}},onCancel:function(){this.fireEvent("cancel",this.subject).clearChain()},pause:function(){this.stopTimer();return this},resume:function(){this.startTimer();return this},stopTimer:function(){if(!this.timer){return false}this.time=$time()-this.time;this.timer=$clear(this.timer);return true},startTimer:function(){if(this.timer){return false}this.time=$time()-this.time;this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);return true}});Fx.compute=function(C,B,A){return(B-C)*A+C};Fx.Durations={"short":250,normal:500,"long":1000};Fx.CSS=new Class({Extends:Fx,prepare:function(D,E,B){B=$splat(B);var C=B[1];if(!$chk(C)){B[1]=B[0];B[0]=D.getStyle(E)}var A=B.map(this.parse);return{from:A[0],to:A[1]}},parse:function(A){A=$lambda(A)();A=(typeof A=="string")?A.split(" "):$splat(A);return A.map(function(C){C=String(C);var B=false;Fx.CSS.Parsers.each(function(F,E){if(B){return }var D=F.parse(C);if($chk(D)){B={value:D,parser:F}}});B=B||{value:C,parser:Fx.CSS.Parsers.String};return B})},compute:function(D,C,B){var A=[];(Math.min(D.length,C.length)).times(function(E){A.push({value:D[E].parser.compute(D[E].value,C[E].value,B),parser:D[E].parser})});A.$family={name:"fx:css:value"};return A},serve:function(C,B){if($type(C)!="fx:css:value"){C=this.parse(C)}var A=[];C.each(function(D){A=A.concat(D.parser.serve(D.value,B))});return A},render:function(A,D,C,B){A.setStyle(D,this.serve(C,B))},search:function(A){if(Fx.CSS.Cache[A]){return Fx.CSS.Cache[A]}var B={};Array.each(document.styleSheets,function(E,D){var C=E.href;if(C&&C.contains("://")&&!C.contains(document.domain)){return }var F=E.rules||E.cssRules;Array.each(F,function(I,G){if(!I.style){return }var H=(I.selectorText)?I.selectorText.replace(/^\w+/,function(J){return J.toLowerCase()}):null;if(!H||!H.test("^"+A+"$")){return }Element.Styles.each(function(K,J){if(!I.style[J]||Element.ShortStyles[J]){return }K=String(I.style[J]);B[J]=(K.test(/^rgb/))?K.rgbToHex():K})})});return Fx.CSS.Cache[A]=B}});Fx.CSS.Cache={};Fx.CSS.Parsers=new Hash({Color:{parse:function(A){if(A.match(/^#[0-9a-f]{3,6}$/i)){return A.hexToRgb(true)}return((A=A.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[A[1],A[2],A[3]]:false},compute:function(C,B,A){return C.map(function(E,D){return Math.round(Fx.compute(C[D],B[D],A))})},serve:function(A){return A.map(Number)}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(B,A){return(A)?B+A:B}},String:{parse:$lambda(false),compute:$arguments(1),serve:$arguments(0)}});Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(B,A){this.element=this.subject=$(B);this.parent(A)},set:function(B,A){if(arguments.length==1){A=B;B=this.property||this.options.property}this.render(this.element,B,A,this.options.unit);return this},start:function(C,E,D){if(!this.check(arguments.callee,C,E,D)){return this}var B=Array.flatten(arguments);this.property=this.options.property||B.shift();var A=this.prepare(this.element,this.property,B);return this.parent(A.from,A.to)}});Element.Properties.tween={set:function(A){var B=this.retrieve("tween");if(B){B.cancel()}return this.eliminate("tween").store("tween:options",$extend({link:"cancel"},A))},get:function(A){if(A||!this.retrieve("tween")){if(A||!this.retrieve("tween:options")){this.set("tween",A)}this.store("tween",new Fx.Tween(this,this.retrieve("tween:options")))}return this.retrieve("tween")}};Element.implement({tween:function(A,C,B){this.get("tween").start(arguments);return this},fade:function(C){var E=this.get("tween"),D="opacity",A;C=$pick(C,"toggle");switch(C){case"in":E.start(D,1);break;case"out":E.start(D,0);break;case"show":E.set(D,1);break;case"hide":E.set(D,0);break;case"toggle":var B=this.retrieve("fade:flag",this.get("opacity")==1);E.start(D,(B)?0:1);this.store("fade:flag",!B);A=true;break;default:E.start(D,arguments)}if(!A){this.eliminate("fade:flag")}return this},highlight:function(C,A){if(!A){A=this.retrieve("highlight:original",this.getStyle("background-color"));A=(A=="transparent")?"#fff":A}var B=this.get("tween");B.start("background-color",C||"#ffff88",A).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));B.callChain()}.bind(this));return this}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(B,A){this.element=this.subject=$(B);this.parent(A)},set:function(A){if(typeof A=="string"){A=this.search(A)}for(var B in A){this.render(this.element,B,A[B],this.options.unit)}return this},compute:function(E,D,C){var A={};for(var B in E){A[B]=this.parent(E[B],D[B],C)}return A},start:function(B){if(!this.check(arguments.callee,B)){return this}if(typeof B=="string"){B=this.search(B)}var E={},D={};for(var C in B){var A=this.prepare(this.element,C,B[C]);E[C]=A.from;D[C]=A.to}return this.parent(E,D)}});Element.Properties.morph={set:function(A){var B=this.retrieve("morph");if(B){B.cancel()}return this.eliminate("morph").store("morph:options",$extend({link:"cancel"},A))},get:function(A){if(A||!this.retrieve("morph")){if(A||!this.retrieve("morph:options")){this.set("morph",A)}this.store("morph",new Fx.Morph(this,this.retrieve("morph:options")))}return this.retrieve("morph")}};Element.implement({morph:function(A){this.get("morph").start(A);return this}});(function(){var A=Fx.prototype.initialize;Fx.prototype.initialize=function(B){A.call(this,B);var C=this.options.transition;if(typeof C=="string"&&(C=C.split(":"))){var D=Fx.Transitions;D=D[C[0]]||D[C[0].capitalize()];if(C[1]){D=D["ease"+C[1].capitalize()+(C[2]?C[2].capitalize():"")]}this.options.transition=D}}})();Fx.Transition=function(B,A){A=$splat(A);return $extend(B,{easeIn:function(C){return B(C,A)},easeOut:function(C){return 1-B(1-C,A)},easeInOut:function(C){return(C<=0.5)?B(2*C,A)/2:(2-B(2*(1-C),A))/2}})};Fx.Transitions=new Hash({linear:$arguments(0)});Fx.Transitions.extend=function(A){for(var B in A){Fx.Transitions[B]=new Fx.Transition(A[B])}};Fx.Transitions.extend({Pow:function(B,A){return Math.pow(B,A[0]||6)},Expo:function(A){return Math.pow(2,8*(A-1))},Circ:function(A){return 1-Math.sin(Math.acos(A))},Sine:function(A){return 1-Math.sin((1-A)*Math.PI/2)},Back:function(B,A){A=A[0]||1.618;return Math.pow(B,2)*((A+1)*B-A)},Bounce:function(D){var C;for(var B=0,A=1;1;B+=A,A/=2){if(D>=(7-4*B)/11){C=-Math.pow((11-6*B-11*D)/4,2)+A*A;break}}return C},Elastic:function(B,A){return Math.pow(2,10*--B)*Math.cos(20*B*Math.PI*(A[0]||1)/3)}});["Quad","Cubic","Quart","Quint"].each(function(B,A){Fx.Transitions[B]=new Fx.Transition(function(C){return Math.pow(C,[A+2])})});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false},initialize:function(A){this.xhr=new Browser.Request();this.setOptions(A);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers=new Hash(this.options.headers)},onStateChange:function(){if(this.xhr.readyState!=4||!this.running){return }this.running=false;this.status=0;$try(function(){this.status=this.xhr.status}.bind(this));if(this.options.isSuccess.call(this,this.status)){this.response={text:this.xhr.responseText,xml:this.xhr.responseXML};this.success(this.response.text,this.response.xml)}else{this.response={text:null,xml:null};this.failure()}this.xhr.onreadystatechange=$empty},isSuccess:function(){return((this.status>=200)&&(this.status<300))},processScripts:function(A){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return $exec(A)}return A.stripScripts(this.options.evalScripts)},success:function(B,A){this.onSuccess(this.processScripts(B),A)},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain()},failure:function(){this.onFailure()},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr)},setHeader:function(A,B){this.headers.set(A,B);return this},getHeader:function(A){return $try(function(){return this.xhr.getResponseHeader(A)}.bind(this))},check:function(A){if(!this.running){return true}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(A.bind(this,Array.slice(arguments,1)));return false}return false},send:function(I){if(!this.check(arguments.callee,I)){return this}this.running=true;var G=$type(I);if(G=="string"||G=="element"){I={data:I}}var D=this.options;I=$extend({data:D.data,url:D.url,method:D.method},I);var E=I.data,B=I.url,A=I.method;switch($type(E)){case"element":E=$(E).toQueryString();break;case"object":case"hash":E=Hash.toQueryString(E)}if(this.options.format){var H="format="+this.options.format;E=(E)?H+"&"+E:H}if(this.options.emulation&&["put","delete"].contains(A)){var F="_method="+A;E=(E)?F+"&"+E:F;A="post"}if(this.options.urlEncoded&&A=="post"){var C=(this.options.encoding)?"; charset="+this.options.encoding:"";this.headers.set("Content-type","application/x-www-form-urlencoded"+C)}if(E&&A=="get"){B=B+(B.contains("?")?"&":"?")+E;E=null}this.xhr.open(A.toUpperCase(),B,this.options.async);this.xhr.onreadystatechange=this.onStateChange.bind(this);this.headers.each(function(K,J){if(!$try(function(){this.xhr.setRequestHeader(J,K);return true}.bind(this))){this.fireEvent("exception",[J,K])}},this);this.fireEvent("request");this.xhr.send(E);if(!this.options.async){this.onStateChange()}return this},cancel:function(){if(!this.running){return this}this.running=false;this.xhr.abort();this.xhr.onreadystatechange=$empty;this.xhr=new Browser.Request();this.fireEvent("cancel");return this}});(function(){var A={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(B){A[B]=function(){var C=Array.link(arguments,{url:String.type,data:$defined});return this.send($extend(C,{method:B.toLowerCase()}))}});Request.implement(A)})();Element.Properties.send={set:function(A){var B=this.retrieve("send");if(B){B.cancel()}return this.eliminate("send").store("send:options",$extend({data:this,link:"cancel",method:this.get("method")||"post",url:this.get("action")},A))},get:function(A){if(A||!this.retrieve("send")){if(A||!this.retrieve("send:options")){this.set("send",A)}this.store("send",new Request(this.retrieve("send:options")))}return this.retrieve("send")}};Element.implement({send:function(A){var B=this.get("send");B.send({data:this,url:A||B.options.url});return this}});Request.HTML=new Class({Extends:Request,options:{update:false,evalScripts:true,filter:false},processHTML:function(C){var B=C.match(/<body[^>]*>([\s\S]*?)<\/body>/i);C=(B)?B[1]:C;var A=new Element("div");return $try(function(){var D="<root>"+C+"</root>",G;if(Browser.Engine.trident){G=new ActiveXObject("Microsoft.XMLDOM");G.async=false;G.loadXML(D)}else{G=new DOMParser().parseFromString(D,"text/xml")}D=G.getElementsByTagName("root")[0];for(var F=0,E=D.childNodes.length;F<E;F++){var H=Element.clone(D.childNodes[F],true,true);if(H){A.grab(H)}}return A})||A.set("html",C)},success:function(D){var C=this.options,B=this.response;B.html=D.stripScripts(function(E){B.javascript=E});var A=this.processHTML(B.html);B.tree=A.childNodes;B.elements=A.getElements("*");if(C.filter){B.tree=B.elements.filter(C.filter)}if(C.update){$(C.update).empty().adopt(B.tree)}if(C.evalScripts){$exec(B.javascript)}this.onSuccess(B.tree,B.elements,B.html,B.javascript)}});Element.Properties.load={set:function(A){var B=this.retrieve("load");if(B){send.cancel()}return this.eliminate("load").store("load:options",$extend({data:this,link:"cancel",update:this,method:"get"},A))},get:function(A){if(A||!this.retrieve("load")){if(A||!this.retrieve("load:options")){this.set("load",A)}this.store("load",new Request.HTML(this.retrieve("load:options")))}return this.retrieve("load")}};Element.implement({load:function(){this.get("load").send(Array.link(arguments,{data:Object.type,url:String.type}));return this}});Request.JSON=new Class({Extends:Request,options:{secure:true},initialize:function(A){this.parent(A);this.headers.extend({Accept:"application/json","X-Request":"JSON"})},success:function(A){this.response.json=JSON.decode(A,this.options.secure);this.onSuccess(this.response.json,A)}});Fx.Slide=new Class({Extends:Fx,options:{mode:"vertical"},initialize:function(B,A){this.addEvent("complete",function(){this.open=(this.wrapper["offset"+this.layout.capitalize()]!=0);if(this.open&&Browser.Engine.webkit419){this.element.dispose().inject(this.wrapper)}},true);this.element=this.subject=$(B);this.parent(A);var C=this.element.retrieve("wrapper");this.wrapper=C||new Element("div",{styles:$extend(this.element.getStyles("margin","position"),{overflow:"hidden"})}).wraps(this.element);this.element.store("wrapper",this.wrapper).setStyle("margin",0);this.now=[];this.open=true},vertical:function(){this.margin="margin-top";this.layout="height";this.offset=this.element.offsetHeight},horizontal:function(){this.margin="margin-left";this.layout="width";this.offset=this.element.offsetWidth},set:function(A){this.element.setStyle(this.margin,A[0]);this.wrapper.setStyle(this.layout,A[1]);return this},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B[F]=Fx.compute(E[F],D[F],C)});return B},start:function(B,E){if(!this.check(arguments.callee,B,E)){return this}this[E||this.options.mode]();var D=this.element.getStyle(this.margin).toInt();var C=this.wrapper.getStyle(this.layout).toInt();var A=[[D,C],[0,this.offset]];var G=[[D,C],[-this.offset,0]];var F;switch(B){case"in":F=A;break;case"out":F=G;break;case"toggle":F=(this.wrapper["offset"+this.layout.capitalize()]==0)?A:G}return this.parent(F[0],F[1])},slideIn:function(A){return this.start("in",A)},slideOut:function(A){return this.start("out",A)},hide:function(A){this[A||this.options.mode]();this.open=false;return this.set([-this.offset,0])},show:function(A){this[A||this.options.mode]();this.open=true;return this.set([0,this.offset])},toggle:function(A){return this.start("toggle",A)}});Element.Properties.slide={set:function(B){var A=this.retrieve("slide");if(A){A.cancel()}return this.eliminate("slide").store("slide:options",$extend({link:"cancel"},B))},get:function(A){if(A||!this.retrieve("slide")){if(A||!this.retrieve("slide:options")){this.set("slide",A)}this.store("slide",new Fx.Slide(this,this.retrieve("slide:options")))}return this.retrieve("slide")}};Element.implement({slide:function(D,E){D=D||"toggle";var B=this.get("slide"),A;switch(D){case"hide":B.hide(E);break;case"show":B.show(E);break;case"toggle":var C=this.retrieve("slide:flag",B.open);B[(C)?"slideOut":"slideIn"](E);this.store("slide:flag",!C);A=true;break;default:B.start(D,E)}if(!A){this.eliminate("slide:flag")}return this}});Fx.Scroll=new Class({Extends:Fx,options:{offset:{x:0,y:0},wheelStops:true},initialize:function(B,A){this.element=this.subject=$(B);this.parent(A);var D=this.cancel.bind(this,false);if($type(this.element)!="element"){this.element=$(this.element.getDocument().body)}var C=this.element;if(this.options.wheelStops){this.addEvent("start",function(){C.addEvent("mousewheel",D)},true);this.addEvent("complete",function(){C.removeEvent("mousewheel",D)},true)}},set:function(){var A=Array.flatten(arguments);this.element.scrollTo(A[0],A[1])},compute:function(E,D,C){var B=[];var A=2;A.times(function(F){B.push(Fx.compute(E[F],D[F],C))});return B},start:function(C,H){if(!this.check(arguments.callee,C,H)){return this}var E=this.element.getSize(),F=this.element.getScrollSize();var B=this.element.getScroll(),D={x:C,y:H};for(var G in D){var A=F[G]-E[G];if($chk(D[G])){D[G]=($type(D[G])=="number")?D[G].limit(0,A):A}else{D[G]=B[G]}D[G]+=this.options.offset[G]}return this.parent([B.x,B.y],[D.x,D.y])},toTop:function(){return this.start(false,0)},toLeft:function(){return this.start(0,false)},toRight:function(){return this.start("right",false)},toBottom:function(){return this.start(false,"bottom")},toElement:function(B){var A=$(B).getPosition(this.element);return this.start(A.x,A.y)}});Fx.Elements=new Class({Extends:Fx.CSS,initialize:function(B,A){this.elements=this.subject=$$(B);this.parent(A)},compute:function(G,H,I){var C={};for(var D in G){var A=G[D],E=H[D],F=C[D]={};for(var B in A){F[B]=this.parent(A[B],E[B],I)}}return C},set:function(B){for(var C in B){var A=B[C];for(var D in A){this.render(this.elements[C],D,A[D],this.options.unit)}}return this},start:function(C){if(!this.check(arguments.callee,C)){return this}var H={},I={};for(var D in C){var F=C[D],A=H[D]={},G=I[D]={};for(var B in F){var E=this.prepare(this.elements[D],B,F[B]);A[B]=E.from;G[B]=E.to}}return this.parent(H,I)}});var Drag=new Class({Implements:[Events,Options],options:{snap:6,unit:"px",grid:false,style:true,limit:false,handle:false,invert:false,preventDefault:false,modifiers:{x:"left",y:"top"}},initialize:function(){var B=Array.link(arguments,{options:Object.type,element:$defined});this.element=$(B.element);this.document=this.element.getDocument();this.setOptions(B.options||{});var A=$type(this.options.handle);this.handles=(A=="array"||A=="collection")?$$(this.options.handle):$(this.options.handle)||this.element;this.mouse={now:{},pos:{}};this.value={start:{},now:{}};this.selection=(Browser.Engine.trident)?"selectstart":"mousedown";this.bound={start:this.start.bind(this),check:this.check.bind(this),drag:this.drag.bind(this),stop:this.stop.bind(this),cancel:this.cancel.bind(this),eventStop:$lambda(false)};this.attach()},attach:function(){this.handles.addEvent("mousedown",this.bound.start);return this},detach:function(){this.handles.removeEvent("mousedown",this.bound.start);return this},start:function(C){if(this.options.preventDefault){C.preventDefault()}this.fireEvent("beforeStart",this.element);this.mouse.start=C.page;var A=this.options.limit;this.limit={x:[],y:[]};for(var D in this.options.modifiers){if(!this.options.modifiers[D]){continue}if(this.options.style){this.value.now[D]=this.element.getStyle(this.options.modifiers[D]).toInt()}else{this.value.now[D]=this.element[this.options.modifiers[D]]}if(this.options.invert){this.value.now[D]*=-1}this.mouse.pos[D]=C.page[D]-this.value.now[D];if(A&&A[D]){for(var B=2;B--;B){if($chk(A[D][B])){this.limit[D][B]=$lambda(A[D][B])()}}}}if($type(this.options.grid)=="number"){this.options.grid={x:this.options.grid,y:this.options.grid}}this.document.addEvents({mousemove:this.bound.check,mouseup:this.bound.cancel});this.document.addEvent(this.selection,this.bound.eventStop)},check:function(A){if(this.options.preventDefault){A.preventDefault()}var B=Math.round(Math.sqrt(Math.pow(A.page.x-this.mouse.start.x,2)+Math.pow(A.page.y-this.mouse.start.y,2)));if(B>this.options.snap){this.cancel();this.document.addEvents({mousemove:this.bound.drag,mouseup:this.bound.stop});this.fireEvent("start",this.element).fireEvent("snap",this.element)}},drag:function(A){if(this.options.preventDefault){A.preventDefault()}this.mouse.now=A.page;for(var B in this.options.modifiers){if(!this.options.modifiers[B]){continue}this.value.now[B]=this.mouse.now[B]-this.mouse.pos[B];if(this.options.invert){this.value.now[B]*=-1}if(this.options.limit&&this.limit[B]){if($chk(this.limit[B][1])&&(this.value.now[B]>this.limit[B][1])){this.value.now[B]=this.limit[B][1]}else{if($chk(this.limit[B][0])&&(this.value.now[B]<this.limit[B][0])){this.value.now[B]=this.limit[B][0]}}}if(this.options.grid[B]){this.value.now[B]-=(this.value.now[B]%this.options.grid[B])}if(this.options.style){this.element.setStyle(this.options.modifiers[B],this.value.now[B]+this.options.unit)}else{this.element[this.options.modifiers[B]]=this.value.now[B]}}this.fireEvent("drag",this.element)},cancel:function(A){this.document.removeEvent("mousemove",this.bound.check);this.document.removeEvent("mouseup",this.bound.cancel);if(A){this.document.removeEvent(this.selection,this.bound.eventStop);this.fireEvent("cancel",this.element)}},stop:function(A){this.document.removeEvent(this.selection,this.bound.eventStop);this.document.removeEvent("mousemove",this.bound.drag);this.document.removeEvent("mouseup",this.bound.stop);if(A){this.fireEvent("complete",this.element)}}});Element.implement({makeResizable:function(A){return new Drag(this,$merge({modifiers:{x:"width",y:"height"}},A))}});Drag.Move=new Class({Extends:Drag,options:{droppables:[],container:false},initialize:function(C,B){this.parent(C,B);this.droppables=$$(this.options.droppables);this.container=$(this.options.container);if(this.container&&$type(this.container)!="element"){this.container=$(this.container.getDocument().body)}C=this.element;var D=C.getStyle("position");var A=(D!="static")?D:"absolute";if(C.getStyle("left")=="auto"||C.getStyle("top")=="auto"){C.position(C.getPosition(C.offsetParent))}C.setStyle("position",A);this.addEvent("start",function(){this.checkDroppables()},true)},start:function(B){if(this.container){var D=this.element,J=this.container,E=J.getCoordinates(D.offsetParent),F={},A={};["top","right","bottom","left"].each(function(K){F[K]=J.getStyle("padding-"+K).toInt();A[K]=D.getStyle("margin-"+K).toInt()},this);var C=D.offsetWidth+A.left+A.right,I=D.offsetHeight+A.top+A.bottom;var H=[E.left+F.left,E.right-F.right-C];var G=[E.top+F.top,E.bottom-F.bottom-I];this.options.limit={x:H,y:G}}this.parent(B)},checkAgainst:function(B){B=B.getCoordinates();var A=this.mouse.now;return(A.x>B.left&&A.x<B.right&&A.y<B.bottom&&A.y>B.top)},checkDroppables:function(){var A=this.droppables.filter(this.checkAgainst,this).getLast();if(this.overed!=A){if(this.overed){this.fireEvent("leave",[this.element,this.overed])}if(A){this.overed=A;this.fireEvent("enter",[this.element,A])}else{this.overed=null}}},drag:function(A){this.parent(A);if(this.droppables.length){this.checkDroppables()}},stop:function(A){this.checkDroppables();this.fireEvent("drop",[this.element,this.overed]);this.overed=null;return this.parent(A)}});Element.implement({makeDraggable:function(A){return new Drag.Move(this,A)}});Hash.Cookie=new Class({Extends:Cookie,options:{autoSave:true},initialize:function(B,A){this.parent(B,A);this.load()},save:function(){var A=JSON.encode(this.hash);if(!A||A.length>4096){return false}if(A=="{}"){this.dispose()}else{this.write(A)}return true},load:function(){this.hash=new Hash(JSON.decode(this.read(),true));return this}});Hash.Cookie.implement((function(){var A={};Hash.each(Hash.prototype,function(C,B){A[B]=function(){var D=C.apply(this.hash,arguments);if(this.options.autoSave){this.save()}return D}});return A})());var Color=new Native({initialize:function(B,C){if(arguments.length>=3){C="rgb";B=Array.slice(arguments,0,3)}else{if(typeof B=="string"){if(B.match(/rgb/)){B=B.rgbToHex().hexToRgb(true)}else{if(B.match(/hsb/)){B=B.hsbToRgb()}else{B=B.hexToRgb(true)}}}}C=C||"rgb";switch(C){case"hsb":var A=B;B=B.hsbToRgb();B.hsb=A;break;case"hex":B=B.hexToRgb(true);break}B.rgb=B.slice(0,3);B.hsb=B.hsb||B.rgbToHsb();B.hex=B.rgbToHex();return $extend(B,this)}});Color.implement({mix:function(){var A=Array.slice(arguments);var C=($type(A.getLast())=="number")?A.pop():50;var B=this.slice();A.each(function(D){D=new Color(D);for(var E=0;E<3;E++){B[E]=Math.round((B[E]/100*(100-C))+(D[E]/100*C))}});return new Color(B,"rgb")},invert:function(){return new Color(this.map(function(A){return 255-A}))},setHue:function(A){return new Color([A,this.hsb[1],this.hsb[2]],"hsb")},setSaturation:function(A){return new Color([this.hsb[0],A,this.hsb[2]],"hsb")},setBrightness:function(A){return new Color([this.hsb[0],this.hsb[1],A],"hsb")}});function $RGB(C,B,A){return new Color([C,B,A],"rgb")}function $HSB(C,B,A){return new Color([C,B,A],"hsb")}function $HEX(A){return new Color(A,"hex")}Array.implement({rgbToHsb:function(){var B=this[0],C=this[1],J=this[2];var G,F,H;var I=Math.max(B,C,J),E=Math.min(B,C,J);var K=I-E;H=I/255;F=(I!=0)?K/I:0;if(F==0){G=0}else{var D=(I-B)/K;var A=(I-C)/K;var L=(I-J)/K;if(B==I){G=L-A}else{if(C==I){G=2+D-L}else{G=4+A-D}}G/=6;if(G<0){G++}}return[Math.round(G*360),Math.round(F*100),Math.round(H*100)]},hsbToRgb:function(){var C=Math.round(this[2]/100*255);if(this[1]==0){return[C,C,C]}else{var A=this[0]%360;var E=A%60;var F=Math.round((this[2]*(100-this[1]))/10000*255);var D=Math.round((this[2]*(6000-this[1]*E))/600000*255);var B=Math.round((this[2]*(6000-this[1]*(60-E)))/600000*255);switch(Math.floor(A/60)){case 0:return[C,B,F];case 1:return[D,C,F];case 2:return[F,C,B];case 3:return[F,D,C];case 4:return[B,F,C];case 5:return[C,F,D]}}return false}});String.implement({rgbToHsb:function(){var A=this.match(/\d{1,3}/g);return(A)?hsb.rgbToHsb():null},hsbToRgb:function(){var A=this.match(/\d{1,3}/g);return(A)?A.hsbToRgb():null}});var Group=new Class({initialize:function(){this.instances=Array.flatten(arguments);this.events={};this.checker={}},addEvent:function(B,A){this.checker[B]=this.checker[B]||{};this.events[B]=this.events[B]||[];if(this.events[B].contains(A)){return false}else{this.events[B].push(A)}this.instances.each(function(C,D){C.addEvent(B,this.check.bind(this,[B,C,D]))},this);return this},check:function(C,A,B){this.checker[C][B]=true;var D=this.instances.every(function(F,E){return this.checker[C][E]||false},this);if(!D){return }this.checker[C]={};this.events[C].each(function(E){E.call(this,this.instances,A)},this)}});var Asset=new Hash({javascript:function(F,D){D=$extend({onload:$empty,document:document,check:$lambda(true)},D);var B=new Element("script",{src:F,type:"text/javascript"});var E=D.onload.bind(B),A=D.check,G=D.document;delete D.onload;delete D.check;delete D.document;B.addEvents({load:E,readystatechange:function(){if(["loaded","complete"].contains(this.readyState)){E()}}}).setProperties(D);if(Browser.Engine.webkit419){var C=(function(){if(!$try(A)){return }$clear(C);E()}).periodical(50)}return B.inject(G.head)},css:function(B,A){return new Element("link",$merge({rel:"stylesheet",media:"screen",type:"text/css",href:B},A)).inject(document.head)},image:function(C,B){B=$merge({onload:$empty,onabort:$empty,onerror:$empty},B);var D=new Image();var A=$(D)||new Element("img");["load","abort","error"].each(function(E){var F="on"+E;var G=B[F];delete B[F];D[F]=function(){if(!D){return }if(!A.parentNode){A.width=D.width;A.height=D.height}D=D.onload=D.onabort=D.onerror=null;G.delay(1,A,A);A.fireEvent(E,A,1)}});D.src=A.src=C;if(D&&D.complete){D.onload.delay(1)}return A.setProperties(B)},images:function(D,C){C=$merge({onComplete:$empty,onProgress:$empty},C);if(!D.push){D=[D]}var A=[];var B=0;D.each(function(F){var E=new Asset.image(F,{onload:function(){C.onProgress.call(this,B,D.indexOf(F));B++;if(B==D.length){C.onComplete()}}});A.push(E)});return new Elements(A)}});var Sortables=new Class({Implements:[Events,Options],options:{snap:4,opacity:1,clone:false,revert:false,handle:false,constrain:false},initialize:function(A,B){this.setOptions(B);this.elements=[];this.lists=[];this.idle=true;this.addLists($$($(A)||A));if(!this.options.clone){this.options.revert=false}if(this.options.revert){this.effect=new Fx.Morph(null,$merge({duration:250,link:"cancel"},this.options.revert))}},attach:function(){this.addLists(this.lists);return this},detach:function(){this.lists=this.removeLists(this.lists);return this},addItems:function(){Array.flatten(arguments).each(function(A){this.elements.push(A);var B=A.retrieve("sortables:start",this.start.bindWithEvent(this,A));(this.options.handle?A.getElement(this.options.handle)||A:A).addEvent("mousedown",B)},this);return this},addLists:function(){Array.flatten(arguments).each(function(A){this.lists.push(A);this.addItems(A.getChildren())},this);return this},removeItems:function(){var A=[];Array.flatten(arguments).each(function(B){A.push(B);this.elements.erase(B);var C=B.retrieve("sortables:start");(this.options.handle?B.getElement(this.options.handle)||B:B).removeEvent("mousedown",C)},this);return $$(A)},removeLists:function(){var A=[];Array.flatten(arguments).each(function(B){A.push(B);this.lists.erase(B);this.removeItems(B.getChildren())},this);return $$(A)},getClone:function(B,A){if(!this.options.clone){return new Element("div").inject(document.body)}if($type(this.options.clone)=="function"){return this.options.clone.call(this,B,A,this.list)}return A.clone(true).setStyles({margin:"0px",position:"absolute",visibility:"hidden",width:A.getStyle("width")}).inject(this.list).position(A.getPosition(A.getOffsetParent()))},getDroppables:function(){var A=this.list.getChildren();if(!this.options.constrain){A=this.lists.concat(A).erase(this.list)}return A.erase(this.clone).erase(this.element)},insert:function(C,B){var A="inside";if(this.lists.contains(B)){this.list=B;this.drag.droppables=this.getDroppables()}else{A=this.element.getAllPrevious().contains(B)?"before":"after"}this.element.inject(B,A);this.fireEvent("sort",[this.element,this.clone])},start:function(B,A){if(!this.idle){return }this.idle=false;this.element=A;this.opacity=A.get("opacity");this.list=A.getParent();this.clone=this.getClone(B,A);this.drag=new Drag.Move(this.clone,{snap:this.options.snap,container:this.options.constrain&&this.element.getParent(),droppables:this.getDroppables(),onSnap:function(){B.stop();this.clone.setStyle("visibility","visible");this.element.set("opacity",this.options.opacity||0);this.fireEvent("start",[this.element,this.clone])}.bind(this),onEnter:this.insert.bind(this),onCancel:this.reset.bind(this),onComplete:this.end.bind(this)});this.clone.inject(this.element,"before");this.drag.start(B)},end:function(){this.drag.detach();this.element.set("opacity",this.opacity);if(this.effect){var A=this.element.getStyles("width","height");var B=this.clone.computePosition(this.element.getPosition(this.clone.offsetParent));this.effect.element=this.clone;this.effect.start({top:B.top,left:B.left,width:A.width,height:A.height,opacity:0.25}).chain(this.reset.bind(this))}else{this.reset()}},reset:function(){this.idle=true;this.clone.destroy();this.fireEvent("complete",this.element)},serialize:function(){var C=Array.link(arguments,{modifier:Function.type,index:$defined});var B=this.lists.map(function(D){return D.getChildren().map(C.modifier||function(E){return E.get("id")},this)},this);var A=C.index;if(this.lists.length==1){A=0}return $chk(A)&&A>=0&&A<this.lists.length?B[A]:B}});var Tips=new Class({Implements:[Events,Options],options:{onShow:function(A){A.setStyle("visibility","visible")},onHide:function(A){A.setStyle("visibility","hidden")},showDelay:100,hideDelay:100,className:null,offsets:{x:16,y:16},fixed:false},initialize:function(){var C=Array.link(arguments,{options:Object.type,elements:$defined});this.setOptions(C.options||null);this.tip=new Element("div").inject(document.body);if(this.options.className){this.tip.addClass(this.options.className)}var B=new Element("div",{"class":"tip-top"}).inject(this.tip);this.container=new Element("div",{"class":"tip"}).inject(this.tip);var A=new Element("div",{"class":"tip-bottom"}).inject(this.tip);this.tip.setStyles({position:"absolute",top:0,left:0,visibility:"hidden"});if(C.elements){this.attach(C.elements)}},attach:function(A){$$(A).each(function(D){var G=D.retrieve("tip:title",D.get("title"));var F=D.retrieve("tip:text",D.get("rel")||D.get("href"));var E=D.retrieve("tip:enter",this.elementEnter.bindWithEvent(this,D));var C=D.retrieve("tip:leave",this.elementLeave.bindWithEvent(this,D));D.addEvents({mouseenter:E,mouseleave:C});if(!this.options.fixed){var B=D.retrieve("tip:move",this.elementMove.bindWithEvent(this,D));D.addEvent("mousemove",B)}D.store("tip:native",D.get("title"));D.erase("title")},this);return this},detach:function(A){$$(A).each(function(C){C.removeEvent("mouseenter",C.retrieve("tip:enter")||$empty);C.removeEvent("mouseleave",C.retrieve("tip:leave")||$empty);C.removeEvent("mousemove",C.retrieve("tip:move")||$empty);C.eliminate("tip:enter").eliminate("tip:leave").eliminate("tip:move");var B=C.retrieve("tip:native");if(B){C.set("title",B)}});return this},elementEnter:function(B,A){$A(this.container.childNodes).each(Element.dispose);var D=A.retrieve("tip:title");if(D){this.titleElement=new Element("div",{"class":"tip-title"}).inject(this.container);this.fill(this.titleElement,D)}var C=A.retrieve("tip:text");if(C){this.textElement=new Element("div",{"class":"tip-text"}).inject(this.container);this.fill(this.textElement,C)}this.timer=$clear(this.timer);this.timer=this.show.delay(this.options.showDelay,this);this.position((!this.options.fixed)?B:{page:A.getPosition()})},elementLeave:function(A){$clear(this.timer);this.timer=this.hide.delay(this.options.hideDelay,this)},elementMove:function(A){this.position(A)},position:function(D){var B=window.getSize(),A=window.getScroll();var E={x:this.tip.offsetWidth,y:this.tip.offsetHeight};var C={x:"left",y:"top"};for(var F in C){var G=D.page[F]+this.options.offsets[F];if((G+E[F]-A[F])>B[F]){G=D.page[F]-this.options.offsets[F]-E[F]}this.tip.setStyle(C[F],G)}},fill:function(A,B){(typeof B=="string")?A.set("html",B):A.adopt(B)},show:function(){this.fireEvent("show",this.tip)},hide:function(){this.fireEvent("hide",this.tip)}});var SmoothScroll=new Class({Extends:Fx.Scroll,initialize:function(B,C){C=C||document;var E=C.getDocument(),D=C.getWindow();this.parent(E,B);this.links=(this.options.links)?$$(this.options.links):$$(E.links);var A=D.location.href.match(/^[^#]*/)[0]+"#";this.links.each(function(G){if(G.href.indexOf(A)!=0){return }var F=G.href.substr(A.length);if(F&&$(F)){this.useLink(G,F)}},this);if(!Browser.Engine.webkit419){this.addEvent("complete",function(){D.location.hash=this.anchor},true)}},useLink:function(B,A){B.addEvent("click",function(C){this.anchor=A;this.toElement(A);C.stop()}.bind(this))}});var Slider=new Class({Implements:[Events,Options],options:{onTick:function(A){if(this.options.snap){A=this.toPosition(this.step)}this.knob.setStyle(this.property,A)},snap:false,offset:0,range:false,wheel:false,steps:100,mode:"horizontal"},initialize:function(E,A,D){this.setOptions(D);this.element=$(E);this.knob=$(A);this.previousChange=this.previousEnd=this.step=-1;this.element.addEvent("mousedown",this.clickedElement.bind(this));if(this.options.wheel){this.element.addEvent("mousewheel",this.scrolledElement.bindWithEvent(this))}var F,B={},C={x:false,y:false};switch(this.options.mode){case"vertical":this.axis="y";this.property="top";F="offsetHeight";break;case"horizontal":this.axis="x";this.property="left";F="offsetWidth"}this.half=this.knob[F]/2;this.full=this.element[F]-this.knob[F]+(this.options.offset*2);this.min=$chk(this.options.range[0])?this.options.range[0]:0;this.max=$chk(this.options.range[1])?this.options.range[1]:this.options.steps;this.range=this.max-this.min;this.steps=this.options.steps||this.full;this.stepSize=Math.abs(this.range)/this.steps;this.stepWidth=this.stepSize*this.full/Math.abs(this.range);this.knob.setStyle("position","relative").setStyle(this.property,-this.options.offset);C[this.axis]=this.property;B[this.axis]=[-this.options.offset,this.full-this.options.offset];this.drag=new Drag(this.knob,{snap:0,limit:B,modifiers:C,onDrag:this.draggedKnob.bind(this),onStart:this.draggedKnob.bind(this),onComplete:function(){this.draggedKnob();this.end()}.bind(this)});if(this.options.snap){this.drag.options.grid=Math.ceil(this.stepWidth);this.drag.options.limit[this.axis][1]=this.full}},set:function(A){if(!((this.range>0)^(A<this.min))){A=this.min}if(!((this.range>0)^(A>this.max))){A=this.max}this.step=Math.round(A);this.checkStep();this.end();this.fireEvent("tick",this.toPosition(this.step));return this},clickedElement:function(C){var B=this.range<0?-1:1;var A=C.page[this.axis]-this.element.getPosition()[this.axis]-this.half;A=A.limit(-this.options.offset,this.full-this.options.offset);this.step=Math.round(this.min+B*this.toStep(A));this.checkStep();this.end();this.fireEvent("tick",A)},scrolledElement:function(A){var B=(this.options.mode=="horizontal")?(A.wheel<0):(A.wheel>0);this.set(B?this.step-this.stepSize:this.step+this.stepSize);A.stop()},draggedKnob:function(){var B=this.range<0?-1:1;var A=this.drag.value.now[this.axis];A=A.limit(-this.options.offset,this.full-this.options.offset);this.step=Math.round(this.min+B*this.toStep(A));this.checkStep()},checkStep:function(){if(this.previousChange!=this.step){this.previousChange=this.step;this.fireEvent("change",this.step)}},end:function(){if(this.previousEnd!==this.step){this.previousEnd=this.step;this.fireEvent("complete",this.step+"")}},toStep:function(A){var B=(A+this.options.offset)*this.stepSize/this.full*this.steps;return this.options.steps?Math.round(B-=B%this.stepSize):B},toPosition:function(A){return(this.full*Math.abs(this.min-A))/(this.steps*this.stepSize)-this.options.offset}});var Scroller=new Class({Implements:[Events,Options],options:{area:20,velocity:1,onChange:function(A,B){this.element.scrollTo(A,B)}},initialize:function(B,A){this.setOptions(A);this.element=$(B);this.listener=($type(this.element)!="element")?$(this.element.getDocument().body):this.element;this.timer=null;this.coord=this.getCoords.bind(this)},start:function(){this.listener.addEvent("mousemove",this.coord)},stop:function(){this.listener.removeEvent("mousemove",this.coord);this.timer=$clear(this.timer)},getCoords:function(A){this.page=(this.listener.get("tag")=="body")?A.client:A.page;if(!this.timer){this.timer=this.scroll.periodical(50,this)}},scroll:function(){var B=this.element.getSize(),A=this.element.getScroll(),E=this.element.getPosition(),D={x:0,y:0};for(var C in this.page){if(this.page[C]<(this.options.area+E[C])&&A[C]!=0){D[C]=(this.page[C]-this.options.area-E[C])*this.options.velocity}else{if(this.page[C]+this.options.area>(B[C]+E[C])&&B[C]+B[C]!=A[C]){D[C]=(this.page[C]-B[C]+this.options.area-E[C])*this.options.velocity}}}if(D.y||D.x){this.fireEvent("change",[A.x+D.x,A.y+D.y])}}});var Accordion=new Class({Extends:Fx.Elements,options:{display:0,show:false,height:true,width:false,opacity:true,fixedHeight:false,fixedWidth:false,wait:false,alwaysHide:false},initialize:function(){var C=Array.link(arguments,{container:Element.type,options:Object.type,togglers:$defined,elements:$defined});this.parent(C.elements,C.options);this.togglers=$$(C.togglers);this.container=$(C.container);this.previous=-1;if(this.options.alwaysHide){this.options.wait=true}if($chk(this.options.show)){this.options.display=false;this.previous=this.options.show}if(this.options.start){this.options.display=false;this.options.show=false}this.effects={};if(this.options.opacity){this.effects.opacity="fullOpacity"}if(this.options.width){this.effects.width=this.options.fixedWidth?"fullWidth":"offsetWidth"}if(this.options.height){this.effects.height=this.options.fixedHeight?"fullHeight":"scrollHeight"}for(var B=0,A=this.togglers.length;B<A;B++){this.addSection(this.togglers[B],this.elements[B])}this.elements.each(function(E,D){if(this.options.show===D){this.fireEvent("active",[this.togglers[D],E])}else{for(var F in this.effects){E.setStyle(F,0)}}},this);if($chk(this.options.display)){this.display(this.options.display)}},addSection:function(E,C,G){E=$(E);C=$(C);var F=this.togglers.contains(E);var B=this.togglers.length;this.togglers.include(E);this.elements.include(C);if(B&&(!F||G)){G=$pick(G,B-1);E.inject(this.togglers[G],"before");C.inject(E,"after")}else{if(this.container&&!F){E.inject(this.container);C.inject(this.container)}}var A=this.togglers.indexOf(E);E.addEvent("click",this.display.bind(this,A));if(this.options.height){C.setStyles({"padding-top":0,"border-top":"none","padding-bottom":0,"border-bottom":"none"})}if(this.options.width){C.setStyles({"padding-left":0,"border-left":"none","padding-right":0,"border-right":"none"})}C.fullOpacity=1;if(this.options.fixedWidth){C.fullWidth=this.options.fixedWidth}if(this.options.fixedHeight){C.fullHeight=this.options.fixedHeight}C.setStyle("overflow","hidden");if(!F){for(var D in this.effects){C.setStyle(D,0)}}return this},display:function(A){A=($type(A)=="element")?this.elements.indexOf(A):A;if((this.timer&&this.options.wait)||(A===this.previous&&!this.options.alwaysHide)){return this}this.previous=A;var B={};this.elements.each(function(E,D){B[D]={};var C=(D!=A)||(this.options.alwaysHide&&(E.offsetHeight>0));this.fireEvent(C?"background":"active",[this.togglers[D],E]);for(var F in this.effects){B[D][F]=C?0:E[this.effects[F]]}},this);return this.start(B)}});window.addEvent("load",function(){if(!("console" in window)||!("firebug" in window.console)){var B=["log","debug","info","warn","error","assert","dir","dirxml","group","groupEnd","time","timeEnd","count","trace","profile","profileEnd"];window.console={};for(var A=0;A<B.length;++A){window.console[B[A]]=function(){}}}});(function(){var A=navigator.userAgent.toLowerCase();var B=A.indexOf("msie")>-1,D=A.indexOf("msie 7")>-1;if(B&&!D){try{document.execCommand("BackgroundImageCache",false,true)}catch(C){}}})();if(typeof Jx=="undefined"){var Jx={};(function(){var C=document.getElementsByTagName("SCRIPT");for(var A=0;A<C.length;A++){var B=C[A].src;var D=/(.*)(js|lib\/)jxlib(.*)/.exec(B);if(D&&D[0]){Jx.aPixel=document.createElement("img");Jx.aPixel.src=D[1]+"/images/a_pixel.png";Jx.baseURL=Jx.aPixel.src.substring(0,Jx.aPixel.src.indexOf("images/a_pixel.png"))}}})()}Jx.applyPNGFilter=function(C){var A=Jx.baseURL+"images/a_pixel.png";if(C.src!=A){var B=C.src;C.src=A;C.runtimeStyle.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+B+"',sizingMethod='scale')"}};Jx.imgQueue=[];Jx.imgLoaded={};Jx.imagesLoading=0;Jx.addToImgQueue=function(A){if(Jx.imgLoaded[A.src]){A.element.src=A.src}else{Jx.imgQueue.push(A);Jx.imgLoaded[A.src]=true}Jx.checkImgQueue()};Jx.checkImgQueue=function(){while(Jx.imagesLoading<2&&Jx.imgQueue.length>0){Jx.loadNextImg()}};Jx.loadNextImg=function(){var A=Jx.imgQueue.shift();if(A){++Jx.imagesLoading;A.element.onload=function(){--Jx.imagesLoading;Jx.checkImgQueue()};A.element.onerror=function(){--Jx.imagesLoading;Jx.checkImgQueue()};A.element.src=A.src}};Jx.createIframeShim=function(){return new Element("iframe",{"class":"jxIframeShim",scrolling:"no",frameborder:0})};Jx.UniqueId=new Class({uniqueIdRefs:null,initUniqueId:function(){this.uniqueIdRefs=[]},deregisterIds:function(){this.uniqueIdRefs=[]},registerIds:function(C,A){if(C.indexOf(A.id)!=-1){this.uniqueIdRefs[A.id]=A}for(var B=0;B<A.childNodes.length;B++){this.registerIds(C,A.childNodes[B])}},getObj:function(A){return this.uniqueIdRefs[A]||null}});Element.implement({getBoxSizing:function(){var B="content-box";if(Browser.Engine.trident||Browser.Engine.presto){var A=document.compatMode;if(A=="BackCompat"||A=="QuirksMode"){B="border-box"}else{B="content-box"}}else{if(arguments.length==0){node=document.documentElement}var C=this.getStyle("-moz-box-sizing");if(!C){C=this.getStyle("box-sizing")}B=(C?C:"content-box")}return B},getContentBoxSize:function(){var A=this.offsetWidth;var C=this.offsetHeight;var D=this.getPaddingSize();var B=this.getBorderSize();A=A-D.left-D.right-B.left-B.right;C=C-D.bottom-D.top-B.bottom-B.top;return{width:A,height:C}},getBorderBoxSize:function(){var A=this.offsetWidth;var B=this.offsetHeight;return{width:A,height:B}},getMarginBoxSize:function(){var C=this.getMarginSize();var A=this.offsetWidth+C.left+C.right;var B=this.offsetHeight+C.top+C.bottom;return{width:A,height:B}},setContentBoxSize:function(C){if(this.getBoxSizing()=="border-box"){var E=this.getPaddingSize();var B=this.getBorderSize();if(typeof C.width!="undefined"){var D=(C.width+E.left+E.right+B.left+B.right);if(D<0){D=0}this.style.width=D+"px"}if(typeof C.height!="undefined"){var A=(C.height+E.top+E.bottom+B.top+B.bottom);if(A<0){A=0}this.style.height=A+"px"}}else{if(typeof C.width!="undefined"){this.style.width=C.width+"px"}if(typeof C.height!="undefined"){this.style.height=C.height+"px"}}},setBorderBoxSize:function(C){if(this.getBoxSizing()=="content-box"){var F=this.getPaddingSize();var B=this.getBorderSize();var E=this.getMarginSize();if(typeof C.width!="undefined"){var D=(C.width-F.left-F.right-B.left-B.right-E.left-E.right);if(D<0){D=0}this.style.width=D+"px"}if(typeof C.height!="undefined"){var A=(C.height-F.top-F.bottom-B.top-B.bottom-E.top-E.bottom);if(A<0){A=0}this.style.height=A+"px"}}else{if(typeof C.width!="undefined"&&C.width>=0){this.style.width=C.width+"px"}if(typeof C.height!="undefined"&&C.height>=0){this.style.height=C.height+"px"}}},getPaddingSize:function(){var B=this.getNumber(this.getStyle("padding-left"));var C=this.getNumber(this.getStyle("padding-top"));var D=this.getNumber(this.getStyle("padding-right"));var A=this.getNumber(this.getStyle("padding-bottom"));return{left:B,top:C,right:D,bottom:A}},getBorderSize:function(){var B=this.getNumber(this.getStyle("border-left-width"));var C=this.getNumber(this.getStyle("border-top-width"));var D=this.getNumber(this.getStyle("border-right-width"));var A=this.getNumber(this.getStyle("border-bottom-width"));return{left:B,top:C,right:D,bottom:A}},getMarginSize:function(){var B=this.getNumber(this.getStyle("margin-left"));var C=this.getNumber(this.getStyle("margin-top"));var D=this.getNumber(this.getStyle("margin-right"));var A=this.getNumber(this.getStyle("margin-bottom"));return{left:B,top:C,right:D,bottom:A}},getNumber:function(B){var A=B==null||isNaN(parseInt(B))?0:parseInt(B);return A},getPageDimensions:function(){return{width:window.getWidth(),height:window.getHeight()}},descendantOf:function(B){var A=$(this.parentNode);if(A==B){return true}else{if(!A||!A.parentNode){return null}else{if(A.parentNode===A){return null}else{return A.descendantOf(B)}}}},findElement:function(B){if(this.tagName==B){return this}var A=$(this.parentNode);if(A){if(A.tagName==B){return A}else{if(!A.parentNode||A.parentNode==A){return null}else{return A.findElement(B)}}}else{return null}}});Jx.ContentLoader=new Class({contentIsLoaded:false,contentLoaded:function(){this.contentIsLoaded=true;this.fireEvent("contentLoaded",this)},contentLoadFailed:function(A){this.contentIsLoaded=true;this.fireEvent("contentLoadFailed",this)},loadContent:function(A){A=$(A);if(this.options.content){var B;if(this.options.content.domObj){B=$(this.options.content.domObj)}else{B=$(this.options.content)}if(B){A.appendChild(B);this.contentIsLoaded=true}else{A.innerHTML=this.options.content;this.contentIsLoaded=true}}else{if(this.options.contentURL){this.contentIsLoaded=false;new Request.HTML({url:this.options.contentURL,method:"get",update:A,onSuccess:this.contentLoaded.bind(this),onFailure:this.contentLoadFailed.bind(this),headers:{"If-Modified-Since":"Sat, 1 Jan 2000 00:00:00 GMT"}}).send()}else{this.contentIsLoaded=true}}if(this.contentIsLoaded){this.fireEvent("contentLoaded",this)}},processContent:function(A){$A(A.childNodes).each(function(B){if(B.tagName=="INPUT"||B.tagName=="SELECT"||B.tagName=="TEXTAREA"){if(B.type=="button"){B.addEvent("click",function(){this.fireEvent("click",this,B)})}else{B.addEvent("change",function(){this.fireEvent("change",B)})}}else{if(B.childNodes){this.processContent(B)}}},this)}});Jx.AutoPosition=new Class({position:function(F,C,N){F=$(F);C=$(C);var B=$splat(N.horizontal||["center center"]);var G=$splat(N.vertical||["center center"]);var E=$merge({top:0,right:0,bottom:0,left:0},N.offsets||{});var I;if(!$(F.parentNode)||F.parentNode==document.body){I=Element.getPageDimensions()}else{I=$(F.parentNode).getContentBoxSize()}var K=C.getCoordinates();var M=F.getMarginBoxSize();var D;var L;var J;var A;if(!B.some(function(O){var P=O.split(" ");if(P.length!=2){return false}if(!isNaN(parseInt(P[0]))){D=parseInt(P[0])}else{switch(P[0]){case"right":D=K.left+K.width;break;case"center":D=K.left+Math.round(K.width/2);break;case"left":default:D=K.left}}switch(P[1]){case"left":D-=E.left;L=D+M.width;break;case"right":D+=E.right;L=D;D=D-M.width;break;case"center":default:D=D-Math.round(M.width/2);L=D+M.width}return(D>=0&&L<=I.width)})){if(L>I.width){D=I.width-M.width}if(D<0){D=0}}F.setStyle("left",D);if(!G.some(function(O){var P=O.split(" ");if(P.length!=2){return false}if(!isNaN(parseInt(P[0]))){J=parseInt(P[0])}else{switch(P[0]){case"bottom":J=K.top+K.height;break;case"center":J=K.top+Math.round(K.height/2);break;case"top":default:J=K.top}}switch(P[1]){case"top":J-=E.top;A=J+M.height;break;case"bottom":J+=E.bottom;A=J;J=J-M.height;break;case"center":default:J=J-Math.round(M.height/2);A=J+M.height}return(J>=0&&A<=I.height)})){if(A>I.height){J=I.height-M.height}if(J<0){J=0}}F.setStyle("top",J);var H=F.retrieve("jxLayout");if(H){H.options.left=D;H.options.top=J}}});Jx.Chrome=new Class({chrome:null,makeChrome:function(A){var C=new Element("div",{"class":"jxChrome"});A.adopt(C);this.chromeOffsets=C.getPaddingSize();C.setStyle("padding",0);var B=C.getStyle("backgroundImage");if(!B.contains("http://")){B=null}else{B=B.slice(4,-1);if(B.charAt(0)=='"'){B=B.slice(1,-1)}C.setStyle("backgroundImage","none");["TL","TR","BL","BR"].each(function(D){C.adopt(new Element("div",{"class":"jxChrome"+D}).adopt(new Element("img",{src:B})))},this)}if(!window.opera){C.adopt(Jx.createIframeShim())}C.dispose();this.chrome=C},showChrome:function(B){B=$(B);var A;if(!this.chromeResizeHandler){this.chromeResizeHandler=this.showChrome.bind(this)}if(!this.chrome){this.makeChrome(B)}if(B&&this.chrome.parentNode!==B){var C=$(this.chrome.parentNode);if(C){A=C.retrieve("jxLayout");if(A){A.removeEvent("sizeChange",this.chromeResizeHandler)}}B.adopt(this.chrome);A=B.retrieve("jxLayout");if(A){A.addEvent("sizeChange",this.chromeResizeHandler)}}this.resizeChrome()},resizeChrome:function(){},hideChrome:function(){if(this.chrome){if(this.chrome.parentNode){var A=this.chrome.parentNode.retrieve("jxLayout");if(A){A.removeEvent("sizeChange",this.chromeResizeHandler)}}this.chrome.dispose()}}});Jx.Button=new Class({Implements:[Options,Events],domObj:null,options:{id:"",type:"Button",image:"",tooltip:"",label:"",enabled:true,toggle:false,halign:"center",valign:"middle",isActive:false,container:"div"},initialize:function(B){this.setOptions(B);var E=new Element(this.options.container,{"class":"jx"+this.options.type+"Container"});if(this.options.toggle){E.addClass("jx"+this.options.type+"Toggle")}var A=new Element("a",{"class":"jx"+this.options.type,href:"javascript:void(0)",title:this.options.tooltip,alt:this.options.tooltip,events:{click:this.clicked.bindWithEvent(this)}});if(this.options.isActive){A.addClass("jx"+this.options.type+"Active")}E.appendChild(A);var D=new Element("span",{"class":"jx"+this.options.type+"Content"});A.appendChild(D);if(this.options.image||!this.options.label){var C=new Element("img",{"class":"jx"+this.options.type+"Icon",src:Jx.aPixel.src});if(this.options.image.indexOf("a_pixel.png")==-1){C.setStyle("backgroundImage","url("+this.options.image+")")}D.appendChild(C)}l=new Element("span",{html:this.options.label});if(this.options.label){l.addClass("jx"+this.options.type+"Label")}D.appendChild(l);if(this.options.id){E.id=this.options.id}if(this.options.halign=="left"){E.addClass("jx"+this.options.type+"ContentLeft")}if(this.options.valign=="top"){E.addClass("jx"+this.options.type+"ContentTop")}this.domA=A;this.domLabel=l;this.domObj=E;this.setEnabled(this.options.enabled)},clicked:function(A){if(this.options.enabled){if(this.options.toggle){this.setActive(!this.options.isActive)}else{this.fireEvent("click",{obj:this,event:A})}}},setEnabled:function(A){this.options.enabled=A;if(this.options.enabled){this.domObj.removeClass("jx"+this.options.type+"Disabled")}else{this.domObj.addClass("jx"+this.options.type+"Disabled")}},isActive:function(){return this.options.isActive},setActive:function(A){if(this.options.isActive==A){return }this.options.isActive=A;if(this.options.isActive){this.domA.addClass("jx"+this.options.type+"Active");this.fireEvent("down",this)}else{this.domA.removeClass("jx"+this.options.type+"Active");this.fireEvent("up",this)}},setImage:function(A){if(this.domImg){this.domImg.set("src",A)}},setLabel:function(A){if(this.domLabel){this.domLabel.set("html",A)}},setTooltip:function(A){if(this.domImg){this.domImg.set({title:A,alt:A})}},addTo:function(B,A){B=$(B);A=A?$(A):null;if(A&&A.parentNode==B){B.insertBefore(this.domObj,A)}else{B.appendChild(this.domObj)}}});Jx.Button.Flyout=new Class({Extends:Jx.Button,Implements:[Jx.ContentLoader,Jx.AutoPosition,Jx.Chrome],content:null,initialize:function(A){if(!Jx.Button.Flyout.Stack){Jx.Button.Flyout.Stack=[]}this.parent(A);this.domA.addClass("jx"+this.options.type+"Flyout");this.contentContainer=new Element("div",{"class":"jxFlyout"});this.content=new Element("div",{"class":"jxFlyoutContent"});this.contentContainer.adopt(this.content);this.content.store("jxFlyout",this);this.loadContent(this.content);this.keypressWatcher=this.keypressHandler.bindWithEvent(this);this.hideWatcher=this.clickHandler.bindWithEvent(this)},clicked:function(C){if(!this.owner){this.owner=document.body;var B=$(this.domObj.parentNode);while(B!=document.body&&this.owner==document.body){var A=B.retrieve("jxFlyout");if(A){this.owner=A;break}else{B=$(B.parentNode)}}}if(Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length-1]==this){this.hide();return }else{if(this.owner!=document.body){if(this.owner.currentFlyout==this){this.hide();return }else{if(this.owner.currentFlyout){this.owner.currentFlyout.hide()}}this.owner.currentFlyout=this}else{while(Jx.Button.Flyout.Stack.length){Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length-1].hide()}}}Jx.Button.Flyout.Stack.push(this);this.options.isActive=true;this.domA.addClass("jx"+this.options.type+"Active");this.contentContainer.setStyle("visibility","hidden");document.body.adopt(this.contentContainer);this.showChrome(this.contentContainer);this.position(this.contentContainer,this.domObj,{horizontal:["left left","right right"],vertical:["bottom top","top bottom"],offsets:this.chromeOffsets});this.contentContainer.setStyle("visibility","");window.addEvent("keypress",this.keypressWatcher);document.addEvent("click",this.hideWatcher);this.fireEvent("open",this)},hide:function(){if(this.owner!=document.body){this.owner.currentFlyout=null}Jx.Button.Flyout.Stack.pop();this.setActive(false);this.contentContainer.dispose();window.removeEvent("keypress",this.keypressWatcher);document.removeEvent("click",this.hideWatcher);this.fireEvent("close",this)},clickHandler:function(B){B=new Event(B);var C=$(B.target);var A=Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length-1];if(!C.descendantOf(A.content)&&!C.descendantOf(A.domObj)){A.hide()}},keypressHandler:function(A){A=new Event(A);if(A.key=="esc"){Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length-1].hide()}}});Jx.Button.Multi=new Class({activeButton:null,buttons:null,initialize:function(){this.buttons=[];var A=new Element("div");this.tb=new Jx.Toolbar({parent:A,position:"right"});this.flyout=new Jx.Button.Flyout({content:A});this.flyout.domObj.firstChild.addClass("jxButtonMulti");this.domObj=new Element("div",{"class":"jxButtonMultiContainer"});this.domObj.grab(this.flyout.domObj)},add:function(){$A(arguments).each(function(B){if(!B instanceof Jx.Button){return }this.buttons.push(B);var A=new Jx.Button($merge(B.options,{onClick:this.setButton.bind(this,B)}));B.multiButton=A;this.tb.add(A);if(!this.activeButton){this.domObj.grab(B.domObj,"top");this.activeButton=B}},this)},remove:function(A){if(!A||!A.multiButton){return }if(this.tb.remove(A.multiButton)){A.multiButton=null;if(this.activeButton==A){if(!this.buttons.some(function(B){if(B!=A){this.setActiveButton(B);return true}else{return false}},this)){this.setActiveButton(null)}}this.flyout.content.style.height="";this.flyout.content.style.width="";this.buttons.erase(A)}},addTo:function(B,A){B=$(B);A=A?$(A):null;if(A&&A.parentNode==B){B.grab(this.domObj,"top")}else{B.adopt(this.domObj)}},setActiveButton:function(A){if(this.activeButton){this.activeButton.domObj.dispose()}if(A&&A.domObj){this.domObj.grab(A.domObj,"top")}this.activeButton=A},setButton:function(A){this.setActiveButton(A);A.clicked();this.flyout.hide()}});Jx.ColorPalette=new Class({Implements:[Options,Events],domObj:null,options:{color:"#000000",alpha:1},hexColors:["00","33","66","99","CC","FF"],initialize:function(C){this.setOptions(C);this.domObj=new Element("div",{id:this.options.id,"class":"jxColorPalette"});var H=new Element("div",{"class":"jxColorBar"});var Q=new Element("div",{"class":"jxColorPreview"});this.selectedSwatch=new Element("div",{"class":"jxColorSelected"});this.previewSwatch=new Element("div",{"class":"jxColorHover"});Q.adopt(this.selectedSwatch);Q.adopt(this.previewSwatch);H.adopt(Q);this.colorInputLabel=new Element("label",{"class":"jxColorLabel",html:"#"});H.adopt(this.colorInputLabel);var K=this.changed.bind(this);this.colorInput=new Element("input",{"class":"jxHexInput",type:"text",maxLength:6,events:{keyup:K,blur:K,change:K}});H.adopt(this.colorInput);this.alphaLabel=new Element("label",{"class":"jxAlphaLabel",html:"alpha (%)"});H.adopt(this.alphaLabel);this.alphaInput=new Element("input",{"class":"jxAlphaInput",type:"text",maxLength:3,events:{keyup:this.alphaChanged.bind(this)}});H.adopt(this.alphaInput);this.domObj.adopt(H);Q=new Element("div",{"class":"jxClearer"});this.domObj.adopt(Q);var I=this.swatchClick.bindWithEvent(this);var G=this.swatchOver.bindWithEvent(this);var P=new Element("table",{"class":"jxColorGrid"});var A=new Element("tbody");P.adopt(A);for(var N=0;N<12;N++){var B=new Element("tr");for(var L=-3;L<18;L++){var F=false;var J,O,R;if(L<0){if(L==-3||L==-1){J=O=R=0;F=true}else{if(N<6){J=O=R=N}else{if(N==6){J=5;O=0;R=0}else{if(N==7){J=0;O=5;R=0}else{if(N==8){J=0;O=0;R=5}else{if(N==9){J=5;O=5;R=0}else{if(N==10){J=0;O=5;R=5}else{if(N==11){J=5;O=0;R=5}}}}}}}}}else{J=parseInt(N/6)*3+parseInt(L/6);O=L%6;R=N%6}var D="#"+this.hexColors[J]+this.hexColors[O]+this.hexColors[R];var E=new Element("td");if(!F){E.setStyle("backgroundColor",D);var S=new Element("a",{"class":"colorSwatch "+(((J>2&&O>2)||(J>2&&R>2)||(O>2&&R>2))?"borderBlack":"borderWhite"),href:"#",title:D,alt:D,events:{mouseover:G,click:I}});S.store("swatchColor",D);E.adopt(S)}else{var M=new Element("span",{"class":"emptyCell"});E.adopt(M)}B.adopt(E)}A.adopt(B)}this.domObj.adopt(P);this.updateSelected()},swatchOver:function(B){var A=B.target;this.previewSwatch.setStyle("backgroundColor",A.retrieve("swatchColor"))},swatchClick:function(B){var A=B.target;this.options.color=A.retrieve("swatchColor");this.updateSelected();this.fireEvent("click",this)},changed:function(){var A=this.colorInput.value;if(A.substring(0,1)=="#"){A=A.substring(1)}if(A.toLowerCase().match(/^[0-9a-f]{6}$/)){this.options.color="#"+A.toUpperCase();this.updateSelected()}},alphaChanged:function(){var A=this.alphaInput.value;if(A.match(/^[0-9]{1,3}$/)){this.options.alpha=parseFloat(A/100);this.updateSelected()}},setColor:function(A){this.colorInput.value=A;this.changed()},setAlpha:function(A){this.alphaInput.value=A;this.alphaChanged()},updateSelected:function(){var A={backgroundColor:this.options.color};this.colorInput.value=this.options.color.substring(1);this.alphaInput.value=parseInt(this.options.alpha*100);if(this.options.alpha<1){A.opacity=this.options.alpha;A.filter="Alpha(opacity="+(this.options.alpha*100)+")"}else{A.opacity="";A.filter=""}this.selectedSwatch.setStyles(A);this.previewSwatch.setStyles(A);this.fireEvent("change",this)}});Jx.Button.Color=new Class({Extends:Jx.Button.Flyout,swatch:null,options:{color:"#000000",alpha:100},initialize:function(A){if(!Jx.Button.Color.ColorPalette){Jx.Button.Color.ColorPalette=new Jx.ColorPalette(this.options)}var B=new Element("span",{"class":"jxButtonSwatch"});this.selectedSwatch=new Element("span");B.appendChild(this.selectedSwatch);this.colorChangeFn=this.changed.bind(this);this.hideFn=this.hide.bind(this);Jx.Button.Flyout.prototype.initialize.apply(this,[A]);$(this.domObj.firstChild).addClass("jxButtonColor");this.domObj.firstChild.firstChild.insertBefore(B,this.domObj.firstChild.firstChild.firstChild);this.updateSwatch()},clicked:function(){if(Jx.Button.Color.ColorPalette.currentButton){Jx.Button.Color.ColorPalette.currentButton.hide()}Jx.Button.Color.ColorPalette.currentButton=this;Jx.Button.Color.ColorPalette.addEvent("change",this.colorChangeFn);Jx.Button.Color.ColorPalette.addEvent("click",this.hideFn);this.content.appendChild(Jx.Button.Color.ColorPalette.domObj);Jx.Button.Color.ColorPalette.domObj.setStyle("display","block");Jx.Button.Flyout.prototype.clicked.apply(this,arguments);Jx.Button.Color.ColorPalette.options.color=this.options.color;Jx.Button.Color.ColorPalette.options.alpha=this.options.alpha/100;Jx.Button.Color.ColorPalette.updateSelected()},hide:function(){this.setActive(false);Jx.Button.Color.ColorPalette.removeEvent("change",this.colorChangeFn);Jx.Button.Color.ColorPalette.removeEvent("click",this.hideFn);Jx.Button.Flyout.prototype.hide.apply(this,arguments);Jx.Button.Color.ColorPalette.currentButton=null},setColor:function(A){this.options.color=A;this.updateSwatch()},setAlpha:function(A){this.options.alpha=A;this.updateSwatch()},changed:function(A){var B=false;if(this.options.color!=A.options.color){this.options.color=A.options.color;B=true}if(this.options.alpha!=A.options.alpha*100){this.options.alpha=A.options.alpha*100;B=true}if(B){this.updateSwatch();this.fireEvent("change",this)}},updateSwatch:function(){var A={backgroundColor:this.options.color};if(this.options.alpha<100){A.filter="Alpha(opacity="+(this.options.alpha)+")";A.opacity=this.options.alpha/100}else{A.opacity="";A.filter=""}this.selectedSwatch.setStyles(A)}});Jx.ButtonSet=new Class({Implements:[Options,Events],buttons:null,initialize:function(A){this.setOptions(A);this.buttons=[];this.buttonChangedHandler=this.buttonChanged.bind(this)},add:function(){$A(arguments).each(function(A){A.domObj.addClass("jx"+A.options.type+"Set");A.addEvent("down",this.buttonChangedHandler);if(!this.activeButton){A.setActive(true)}this.buttons.push(A)},this)},remove:function(A){this.buttons.erase(A);if(this.activeButton==A){if(this.buttons.length){this.buttons[0].setActive(true)}A.removeEvent("down",this.buttonChangedHandler)}},setActiveButton:function(A){if(this.activeButton&&this.activeButton!=A){this.activeButton.setActive(false)}this.activeButton=A},buttonChanged:function(A){this.setActiveButton(A);this.fireEvent("change",this)}});Jx.Grid=new Class({Implements:[Options],domObj:null,model:null,options:{alternateRowColors:false,rowHeaders:false,columnHeaders:false,rowSelection:false,cellSelection:false},initialize:function(B,A){this.setOptions(A);this.domObj=$(B);var C=this.domObj.retrieve("jxLayout");if(C){C.addEvent("sizeChange",this.resize.bind(this))}this.rowColObj=new Element("div",{"class":"jxGridContainer"});this.colObj=new Element("div",{"class":"jxGridContainer"});this.colTable=new Element("table",{"class":"jxGridTable"});this.colTableHead=new Element("thead");this.colTable.appendChild(this.colTableHead);this.colTableBody=new Element("tbody");this.colTable.appendChild(this.colTableBody);this.colObj.appendChild(this.colTable);this.rowObj=new Element("div",{"class":"jxGridContainer"});this.rowTable=new Element("table",{"class":"jxGridTable"});this.rowTableHead=new Element("thead");this.rowTable.appendChild(this.rowTableHead);this.rowObj.appendChild(this.rowTable);this.gridObj=new Element("div",{"class":"jxGridContainer",styles:{overflow:"scroll"}});this.gridTable=new Element("table",{"class":"jxGridTable"});this.gridTableBody=new Element("tbody");this.gridTable.appendChild(this.gridTableBody);this.gridObj.appendChild(this.gridTable);this.domObj.appendChild(this.rowColObj);this.domObj.appendChild(this.rowObj);this.domObj.appendChild(this.colObj);this.domObj.appendChild(this.gridObj);this.gridObj.addEvent("scroll",this.onScroll.bind(this));this.gridObj.addEvent("click",this.onClickGrid.bindWithEvent(this));this.rowObj.addEvent("click",this.onClickRowHeader.bindWithEvent(this));this.colObj.addEvent("click",this.onClickColumnHeader.bindWithEvent(this));this.gridObj.addEvent("mousemove",this.onMouseMoveGrid.bindWithEvent(this));this.rowObj.addEvent("mousemove",this.onMouseMoveRowHeader.bindWithEvent(this));this.colObj.addEvent("mousemove",this.onMouseMoveColumnHeader.bindWithEvent(this))},onScroll:function(){this.colObj.scrollLeft=this.gridObj.scrollLeft;this.rowObj.scrollTop=this.gridObj.scrollTop},resize:function(){if(!this.model){return }var C=this.options.columnHeaders?this.model.getColumnHeaderHeight():1;var A=this.options.rowHeaders?this.model.getRowHeaderWidth():1;var B=Element.getContentBoxSize(this.domObj);this.rowColObj.setStyles({width:A-1,height:C-1});this.rowObj.setStyles({top:C,left:0,width:A-1,height:B.height-C-1});this.colObj.setStyles({top:0,left:A,width:B.width-A-1,height:C-1});this.gridObj.setStyles({top:C,left:A,width:B.width-A-1,height:B.height-C-1})},setModel:function(A){if(this.model){this.model.removeGridListener(this)}this.model=A;if(this.model){if(this.domObj.resize){this.domObj.resize()}this.model.addGridListener(this);this.createGrid();this.resize()}else{this.destroyGrid()}},destroyGrid:function(){var A=this.colTableHead.cloneNode(false);this.colTable.replaceChild(A,this.colTableHead);this.colTableHead=A;A=this.colTableBody.cloneNode(false);this.colTable.replaceChild(A,this.colTableBody);this.colTableBody=A;A=this.rowTableHead.cloneNode(false);this.rowTable.replaceChild(A,this.rowTableHead);this.rowTableHead=A;A=this.gridTableBody.cloneNode(false);this.gridTable.replaceChild(A,this.gridTableBody);this.gridTableBody=A},createGrid:function(){this.destroyGrid();if(this.model){var L=this.model;var E=L.getColumnCount();var Q=L.getRowCount();if(this.options.columnHeaders){var N=L.getColumnHeaderHeight();var P=new Element("tr");this.colTableHead.appendChild(P);var M=new Element("tr");this.colTableBody.appendChild(M);var C=new Element("th",{styles:{width:0,height:0}});P.appendChild(C);C=C.cloneNode(true);C.setStyle("height",N);M.appendChild(C);for(var K=0;K<E;K++){var J=L.getColumnWidth(K);C=new Element("th",{"class":"jxGridColHeadHide",styles:{width:J}});var B=new Element("p",{styles:{height:0,width:J}});C.appendChild(B);P.appendChild(C);C=new Element("th",{"class":"jxGridColHead",html:L.getColumnHeaderHTML(K)});M.appendChild(C)}var C=new Element("th",{styles:{width:1000,height:0}});P.appendChild(C);C=C.cloneNode(true);C.setStyle("height",N-1);C.className="jxGridColHead";M.appendChild(C)}if(this.options.rowHeaders){var H=L.getRowHeaderWidth();var O=new Element("tr");var G=new Element("td",{styles:{width:0,height:0}});O.appendChild(G);var C=new Element("th",{styles:{width:H,height:0}});O.appendChild(C);this.rowTableHead.appendChild(O);for(var K=0;K<Q;K++){var A=L.getRowHeight(K);var O=new Element("tr");var G=new Element("td",{"class":"jxGridRowHeadHide",styles:{width:0,height:A}});var B=new Element("p",{styles:{width:0,height:A}});G.appendChild(B);O.appendChild(G);var C=new Element("th",{"class":"jxGridRowHead",html:L.getRowHeaderHTML(K)});O.appendChild(C);this.rowTableHead.appendChild(O)}var O=new Element("tr");var G=new Element("td",{styles:{width:0,height:1000}});O.appendChild(G);var C=new Element("th",{"class":"jxGridRowHead",styles:{width:H,height:1000}});O.appendChild(C);this.rowTableHead.appendChild(O)}var N=L.getColumnHeaderHeight();var M=new Element("tr");this.gridTableBody.appendChild(M);var G=new Element("td",{styles:{width:0,height:0}});M.appendChild(G);for(var K=0;K<E;K++){var J=L.getColumnWidth(K);G=new Element("td",{"class":"jxGridColHeadHide",styles:{width:J}});var B=new Element("p",{styles:{width:J,height:0}});G.appendChild(B);M.appendChild(G)}for(var I=0;I<Q;I++){var A=L.getRowHeight(I);var D=A;var O=new Element("tr");this.gridTableBody.appendChild(O);var G=new Element("td",{"class":"jxGridRowHeadHide",styles:{width:0,height:A}});var B=new Element("p",{styles:{height:A}});G.appendChild(B);O.appendChild(G);for(var K=0;K<E;K++){var J=L.getColumnWidth(K);G=new Element("td",{"class":"jxGridCell"});G.innerHTML=L.getValueAt(I,K);O.appendChild(G);var F=G.getSize();if(F.height>D){D=F.height}}if(document.all){D-=1}if(this.options.rowHeaders){this.setRowHeaderHeight(I,D)}if(this.options.alternateRowColors){O.className=(I%2)?"jxGridRowOdd":"jxGridRowEven"}else{O.className="jxGridRowAll"}}}},setRowHeaderHeight:function(B,A){this.rowTableHead.childNodes[B+1].childNodes[0].childNodes[0].style.height=(A)+"px"},gridChanged:function(B,D,A,C){if(this.model==B){this.gridObj.childNodes[D].childNodes[A].innerHTML=C}},prelightRowHeader:function(B){var A=(B>=0&&B<this.rowTableHead.rows.length-1)?this.rowTableHead.rows[B+1].cells[1]:null;if(this.prelitRowHeader!=A){if(this.prelitRowHeader){this.prelitRowHeader.removeClass("jxGridRowHeaderPrelight")}this.prelitRowHeader=A;if(this.prelitRowHeader){this.prelitRowHeader.addClass("jxGridRowHeaderPrelight")}}},prelightColumnHeader:function(B){if(this.colTableBody.rows.length==0){return }var A=(B>=0&&B<this.colTableBody.rows[0].cells.length-1)?this.colTableBody.rows[0].cells[B+1]:null;if(this.prelitColumnHeader!=A){if(this.prelitColumnHeader){this.prelitColumnHeader.removeClass("jxGridColumnHeaderPrelight")}this.prelitColumnHeader=A;if(this.prelitColumnHeader){this.prelitColumnHeader.addClass("jxGridColumnHeaderPrelight")}}},prelightRow:function(B){var A=(B>=0&&B<this.gridTableBody.rows.length-1)?this.gridTableBody.rows[B+1]:null;if(this.prelitRow!=B){if(this.prelitRow){this.prelitRow.removeClass("jxGridRowPrelight")}this.prelitRow=A;if(this.prelitRow&&!this.prelitRow.hasClass("jxGridRowSelected")){this.prelightRowHeader(B);this.prelitRow.addClass("jxGridRowPrelight")}}},prelightColumn:function(A){this.prelightColumnHeader(A)},prelightCell:function(B,A){var C=(B>=0&&A>=0&&B<this.gridTableBody.rows.length-1&&A<this.gridTableBody.rows[B+1].cells.length-1)?this.gridTableBody.rows[B+1].cells[A+1]:null;if(this.prelitCell!=C){if(this.prelitCell){this.prelitCell.removeClass("jxGridCellPrelight")}this.prelitCell=C;if(this.prelitCell){this.prelitCell.addClass("jxGridCellPrelight");this.prelightRow(B);this.prelightColumn(A)}}},selectCell:function(B,A){var C=(B>=0&&A>=0&&B<this.gridTableBody.rows.length-1&&A<this.gridTableBody.rows[B+1].cells.length-1)?this.gridTableBody.rows[B+1].cells[A+1]:null;if(!C){return }if(this.selectedCell){this.selectedCell.addClass("jxGridCellSelected")}else{this.selectedCell.removeClass("jxGridCellSelected")}},selectRowHeader:function(C,B){var A=(C>=0&&C<this.rowTableHead.rows.length-1)?this.rowTableHead.rows[C+1].cells[1]:null;if(!A){return }if(B){A.addClass("jxGridRowHeaderSelected")}else{A.removeClass("jxGridRowHeaderSelected")}},selectRow:function(C,A){var B=(C>=0&&C<this.gridTableBody.rows.length-1)?this.gridTableBody.rows[C+1]:null;if(B){if(A){B.addClass("jxGridRowSelected")}else{B.removeClass("jxGridRowSelected")}}this.selectRowHeader(C,A)},selectColumnHeader:function(B,C){if(this.colTableBody.rows.length==0){return }var A=(B>=0&&B<this.colTableBody.rows[0].cells.length-1)?this.colTableBody.rows[0].cells[B+1]:null;if(A==null){return }if(C){A.addClass("jxGridColumnHeaderSelected")}else{A.removeClass("jxGridColumnHeaderSelected")}},selectColumn:function(A,C){if(A>=0&&A<this.gridTable.rows[0].cells.length){if(C){for(var B=0;B<this.gridTable.rows.length;B++){this.gridTable.rows[B].cells[this.selectedColumn+1].removeClass("jxGridColumnSelected")}}else{for(var B=0;B<this.gridTable.rows.length;B++){this.gridTable.rows[B].cells[A+1].addClass("jxGridColumnSelected")}}}this.selectColumnHeader(A,C)},onMouseMoveGrid:function(B){var A=this.getRowColumnFromEvent(B);this.prelightCell(A.row,A.column)},onMouseMoveRowHeader:function(B){var A=this.getRowColumnFromEvent(B);this.prelightRow(A.row)},onMouseMoveColumnHeader:function(B){var A=this.getRowColumnFromEvent(B);this.prelightColumn(A.column)},onClickGrid:function(B){var A=this.getRowColumnFromEvent(B);if(this.model.cellSelected){this.model.cellSelected(this,A.row,A.column)}},onClickRowHeader:function(B){var A=this.getRowColumnFromEvent(B);if(this.model.rowSelected){this.model.rowSelected(this,A.row)}},onClickColumnHeader:function(B){var A=this.getRowColumnFromEvent(B);if(this.model.columnSelected){this.model.columnSelected(this,A.column)}},getRowColumnFromEvent:function(D){var F=D.target;if(F.tagName!="TD"&&F.tagName!="TH"){return{row:-1,column:-1}}var C=F.parentNode;var A=F.cellIndex-1;var E=C.rowIndex-1;if(A==-1){for(var B=0;B<C.childNodes.length;B++){if(C.childNodes[B]==F){A=B-1;break}}}return{row:E,column:A}}});Jx.Layout=new Class({Implements:[Options,Events],options:{propagate:true,position:"absolute",left:0,right:0,top:0,bottom:0,width:null,height:null,minWidth:0,minHeight:0,maxWidth:-1,maxHeight:-1},initialize:function(B,A){this.setOptions(A);this.domObj=$(B);this.domObj.resize=this.resize.bind(this);this.domObj.setStyle("position",this.options.position);this.domObj.store("jxLayout",this);if(document.body==this.domObj.parentNode){window.addEvent("resize",this.windowResize.bindWithEvent(this));window.addEvent("load",this.resize.bind(this))}},windowResize:function(){if(this.resizeTimer){$clear(this.resizeTimer);this.resizeTimer=null}this.resizeTimer=this.resize.delay(100,this)},resize:function(K){this.resizeTimer=null;var B=false;if(K){for(var F in K){if(F=="forceResize"){continue}if(this.options[F]!=K[F]){B=true;this.options[F]=K[F]}}if(K.forceResize){B=true}}if(!$(this.domObj.parentNode)){return }var C;if(this.domObj.parentNode.tagName=="BODY"){C=Element.getPageDimensions()}else{C=$(this.domObj.parentNode).getContentBoxSize()}if(this.lastParentSize&&!B){B=(this.lastParentSize.width!=C.width||this.lastParentSize.height!=C.height)}else{B=true}this.lastParentSize=C;if(!B){return }var D,J,I,G;if(this.options.left!=null){D=this.options.left;if(this.options.right==null){if(this.options.width==null){I=C.width-D;if(I<this.options.minWidth){I=this.options.minWidth}if(this.options.maxWidth>=0&&I>this.options.maxWidth){I=this.options.maxWidth}}else{I=this.options.width}}else{if(this.options.width==null){I=C.width-D-this.options.right;if(I<this.options.minWidth){I=this.options.minWidth}if(this.options.maxWidth>=0&&I>this.options.maxWidth){I=this.options.maxWidth}}else{I=this.options.width}}}else{if(this.options.right==null){if(this.options.width==null){D=0;I=C.width;if(this.options.maxWidth>=0&&I>this.options.maxWidth){D=D+parseInt(I-this.options.maxWidth)/2;I=this.options.maxWidth}}else{I=this.options.width;D=parseInt((C.width-I)/2);if(D<0){D=0}}}else{if(this.options.width!=null){I=this.options.width;D=C.width-I-this.options.right;if(D<0){D=0}}else{D=0;I=C.width-this.options.right;if(I<this.options.minWidth){I=this.options.minWidth}if(this.options.maxWidth>=0&&I>this.options.maxWidth){D=I-this.options.maxWidth-this.options.right;I=this.options.maxWidth}}}}if(this.options.top!=null){J=this.options.top;if(this.options.bottom==null){if(this.options.height==null){G=C.height-J;if(G<this.options.minHeight){G=this.options.minHeight}if(this.options.maxHeight>=0&&G>this.options.maxHeight){G=this.options.maxHeight}}else{G=this.options.height;if(this.options.maxHeight>=0&&G>this.options.maxHeight){J=G-this.options.maxHeight;G=this.options.maxHeight}}}else{if(this.options.height==null){G=C.height-J-this.options.bottom;if(G<this.options.minHeight){G=this.options.minHeight}if(this.options.maxHeight>=0&&G>this.options.maxHeight){G=this.options.maxHeight}}else{G=this.options.height}}}else{if(this.options.bottom==null){if(this.options.height==null){J=0;G=C.height;if(G<this.options.minHeight){G=this.options.minHeight}if(this.options.maxHeight>=0&&G>this.options.maxHeight){J=parseInt((C.height-this.options.maxHeight)/2);G=this.options.maxHeight}}else{G=this.options.height;J=parseInt((C.height-G)/2);if(J<0){J=0}}}else{if(this.options.height!=null){G=this.options.height;J=C.height-G-this.options.bottom;if(J<0){J=0}}else{J=0;G=C.height-this.options.bottom;if(G<this.options.minHeight){G=this.options.minHeight}if(this.options.maxHeight>=0&&G>this.options.maxHeight){J=C.height-this.options.maxHeight-this.options.bottom;G=this.options.maxHeight}}}}var E={width:I};if(this.options.position=="absolute"){var H=$(this.domObj.parentNode).getPaddingSize();this.domObj.setStyles({position:this.options.position,left:D+H.left,top:J+H.top});E.height=G}else{if(this.options.height){E.height=this.options.height}}this.domObj.setBorderBoxSize(E);if(this.options.propagate){var A={forceResize:K?K.forceResize:false};$A(this.domObj.childNodes).each(function(L){if(L.resize&&L.getStyle("display")!="none"){L.resize(A)}})}this.fireEvent("sizeChange",this)}});Jx.Menu=new Class({Implements:[Jx.AutoPosition,Jx.Chrome],domObj:null,button:null,subDomObj:null,items:null,initialize:function(A){if(!Jx.Menu.Menus){Jx.Menu.Menus=[]}this.items=[];this.contentContainer=new Element("div",{"class":"jxMenuContainer"});this.subDomObj=new Element("ul",{"class":"jxMenu"});this.contentContainer.adopt(this.subDomObj);if(A){this.domObj=new Element("li",{id:A.id,events:{mouseover:this.onMouseOver.bindWithEvent(this)}});this.button=new Jx.Button($merge(A,{onClick:this.show.bind(this)}));this.button.domA.addClass("jxButtonMenu");this.domObj.adopt(this.button.domObj)}this.hideWatcher=this.hide.bindWithEvent(this);this.keypressWatcher=this.keypressHandler.bindWithEvent(this)},add:function(){$A(arguments).each(function(A){this.items.push(A);A.setOwner(this);this.subDomObj.adopt(A.domObj)},this)},deactivate:function(){this.hide()},actionPerformed:function(){this.hide()},onMouseOver:function(A){if(Jx.Menu.Menus[0]&&Jx.Menu.Menus[0]!=this){this.show({event:A})}},hide:function(A){if(A){if(A.target.descendantOf(this.domObj)||A.target.descendantOf(this.subDomObj)){return }}if(Jx.Menu.Menus[0]&&Jx.Menu.Menus[0]==this){Jx.Menu.Menus[0]=null}if(this.domA){this.domA.removeClass("jx"+this.button.options.type+"Active")}this.contentContainer.dispose();this.items.each(function(B){B.hide(A)});document.removeEvent("mousedown",this.hideWatcher);document.removeEvent("keyup",this.keypressWatcher)},show:function(B){var A=B.event;if(Jx.Menu.Menus[0]&&Jx.Menu.Menus[0]!=this){Jx.Menu.Menus[0].hide(A)}if(this.items.length==0){return }Jx.Menu.Menus[0]=this;this.contentContainer.setStyle("visibility","hidden");document.body.adopt(this.contentContainer);this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());this.showChrome(this.contentContainer);this.position(this.contentContainer,this.button.domObj,{horizontal:["left left"],vertical:["bottom top","top bottom"],offsets:this.chromeOffsets});this.contentContainer.setStyle("visibility","");if(this.domA){this.domA.addClass("jx"+this.button.options.type+"Active")}if(A){A.stop()}document.addEvent("mousedown",this.hideWatcher);document.addEvent("keyup",this.keypressWatcher)},setVisibleItem:function(A){if(this.visibleItem!=A){if(this.visibleItem&&this.visibleItem.hide){this.visibleItem.hide()}this.visibleItem=A;this.visibleItem.show()}},keypressHandler:function(A){A=new Event(A);if(A.key=="esc"){this.hide()}}});Jx.Menu.Item=new Class({Implements:[Options,Events],Extends:Jx.Button,owner:null,button:null,options:{enabled:true,image:Jx.baseURL+"images/a_pixel.png",label:" "},initialize:function(A){this.parent($merge(A,{container:"li",type:"MenuItem"}));this.domObj.addEvent("mouseover",this.onMouseOver.bindWithEvent(this));if(!this.options.enabled){this.domObj.addClass("jxMenuItemDisabled")}},setOwner:function(A){this.owner=A},hide:$empty,show:$empty,clicked:function(A){if(this.options.enabled){if(this.options.toggle){this.setActive(!this.options.isActive)}this.fireEvent("click",this);if(this.owner&&this.owner.deactivate){this.owner.deactivate(A.event)}}},propertyChanged:function(A){this.options.enabled=A.isEnabled();if(this.options.enabled){this.domObj.removeClass("jxMenuItemDisabled")}else{if(!this.domObj.hadClass("jxMenuItemDisabled")){this.domObj.addClass("jxMenuItemDisabled")}}},onMouseOver:function(A){if(this.owner&&this.owner.setVisibleItem){this.owner.setVisibleItem(this)}this.show(A)}});Jx.Menu.Separator=new Class({domObj:null,owner:null,initialize:function(){this.domObj=new Element("li",{"class":"jxMenuItem"});var A=new Element("span",{"class":"jxMenuSeparator",html:" "});this.domObj.appendChild(A)},setOwner:function(A){this.owner=A},hide:$empty,show:$empty});Jx.Menu.SubMenu=new Class({Extends:Jx.Menu.Item,Implements:[Options,Events,Jx.AutoPosition,Jx.Chrome],subDomObj:null,owner:null,visibleItem:null,items:null,initialize:function(A){this.open=false;this.items=[];this.parent(A);this.domA.addClass("jxButtonSubMenu");this.contentContainer=new Element("div",{"class":"jxMenuContainer"});this.subDomObj=new Element("ul",{"class":"jxSubMenu"});this.contentContainer.adopt(this.subDomObj)},setOwner:function(A){this.owner=A},show:function(){if(this.open||this.items.length==0){return }this.contentContainer.setStyle("visibility","hidden");document.body.adopt(this.contentContainer);this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());this.showChrome(this.contentContainer);this.position(this.contentContainer,this.domObj,{horizontal:["right left","left right"],vertical:["top top"],offsets:this.chromeOffsets});this.open=true;this.contentContainer.setStyle("visibility","");this.setActive(true)},hide:function(){if(!this.open){return }this.open=false;this.items.each(function(A){A.hide()});this.contentContainer.dispose();this.visibleItem=null},add:function(){var A=this;$A(arguments).each(function(B){A.items.push(B);B.setOwner(A);A.subDomObj.adopt(B.domObj)})},insertBefore:function(C,D){var B=false;for(var A=0;A<this.items.length;A++){if(this.items[A]==D){this.items.splice(A,0,C);this.subDomObj.insertBefore(C.domObj,D.domObj);B=true;break}}if(!B){this.add(C)}},remove:function(B){for(var A=0;A<this.items.length;A++){if(this.items[A]==B){this.items.splice(A,1);this.subDomObj.removeChild(B.domObj);break}}},processActionEvent:function(A){if(this.open){this.hide()}else{this.show()}if(A&&A.event){A.event.stop()}},deactivate:function(A){if(this.owner){this.owner.deactivate(A)}},isActive:function(){if(this.owner){return this.owner.isActive()}else{return false}},setActive:function(A){if(this.owner&&this.owner.setActive){this.owner.setActive(A)}},setVisibleItem:function(A){if(this.visibleItem!=A){if(this.visibleItem&&this.visibleItem.hide){this.visibleItem.hide()}this.visibleItem=A;this.visibleItem.show()}}});Jx.Menu.Context=new Class({Extends:Jx.Menu,initialize:function(A){this.parent();if($(A)){$(A).addEvent("contextmenu",this.show.bindWithEvent(this))}},show:function(A){if(this.items.length==0){return }this.contentContainer.setStyle("visibility","hidden");document.body.adopt(this.contentContainer);this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());this.position(this.contentContainer,document.body,{horizontal:[A.page.x+" left"],vertical:[A.page.y+" top",A.page.y+" bottom"],offsets:this.chromeOffsets});this.contentContainer.setStyle("visibility","");this.showChrome(this.contentContainer);document.addEvent("mousedown",this.hideWatcher);document.addEvent("keyup",this.keypressWatcher);A.stop()}});Jx.Panel=new Class({Implements:[Options,Events,Jx.UniqueId,Jx.ContentLoader],toolbarContainers:{top:null,right:null,bottom:null,left:null},options:{label:" ",imageBaseUrl:Jx.baseURL+"images/",position:"absolute",height:null,collapse:true,detach:false,close:false,closed:false,hideTitle:false,type:"Panel"},initialize:function(O){this.toolbars=O.toolbars||[];this.setOptions(O);if($defined(this.options.height)&&!$defined(O.position)){this.options.position="relative"}this.initUniqueId();this.title=new Element("div",{"class":"jx"+this.options.type+"Title"});this.labelObj=new Element("span",{"class":"jx"+this.options.type+"Label",html:this.options.label});this.title.adopt(this.labelObj);var L=new Element("div",{"class":"jx"+this.options.type+"Controls"});var F=new Element("div");L.adopt(F);this.toolbar=new Jx.Toolbar({parent:F});this.title.adopt(L);var G=this;if(this.options.menu){this.menu=new Jx.Menu({image:Jx.baseURL+"images/panel_controls.png"});this.menu.domObj.addClass("jx"+this.options.type+"Menu");this.menu.domObj.addClass("jxButtonContentLeft");this.toolbar.add(this.menu)}if(this.options.collapse){var I=new Jx.Button({image:Jx.baseURL+"images/panel_controls.png",tooltip:"Collapse/Expand Panel",onClick:function(){G.toggleCollapse()}});I.domObj.addClass("jx"+this.options.type+"Collapse");this.toolbar.add(I);if(this.menu){var N=new Jx.Menu.Item({label:"Collapse",onClick:function(){G.toggleCollapse()}});var E=N.button;this.addEvent("collapse",function(){if(G.options.closed){E.setLabel("Expand")}else{E.setLabel("Collapse")}});this.menu.add(N)}}if(this.options.maximize){var I=new Jx.Button({image:Jx.baseURL+"images/panel_controls.png",tooltip:"Maximize Panel",onClick:function(){G.maximize()}});I.domObj.addClass("jx"+this.options.type+"Maximize");this.toolbar.add(I);if(this.menu){var N=new Jx.Menu.Item({label:"Maximize",onClick:function(){G.maximize()}});this.menu.add(N)}}if(this.options.close){var I=new Jx.Button({image:Jx.baseURL+"images/panel_controls.png",tooltip:"Close Panel",onClick:function(){G.close()}});I.domObj.addClass("jx"+this.options.type+"Close");this.toolbar.add(I);if(this.menu){var N=new Jx.Menu.Item({label:"Close",onClick:function(){G.close()}});this.menu.add(N)}}this.title.addEvent("dblclick",function(){G.toggleCollapse()});this.domObj=new Element("div",{"class":"jx"+this.options.type});if(this.options.id){this.domObj.id=this.options.id}if($(this.options.parent)){$(this.options.parent).adopt(this.domObj)}var H=new Jx.Layout(this.domObj,$merge(this.options,{propagate:false}));var M=this.layoutContent.bind(this);H.addEvent("sizeChange",M);if(!this.options.hideTitle){this.domObj.adopt(this.title)}this.contentContainer=new Element("div",{"class":"jx"+this.options.type+"ContentContainer"});this.domObj.adopt(this.contentContainer);for(var B=0;B<this.toolbars.length;B++){var A=this.toolbars[B];A.addEvent("add",M);A.addEvent("remove",M);var D=A.options.position;var K=this.toolbarContainers[D];if(!K){var K=new Element("div",{"class":"jxToolbarContainer jxBar"+D.capitalize()});new Jx.Layout(K);var C=new Element("div",{"class":"jxClearer"});K.appendChild(C);this.contentContainer.adopt(K);this.toolbarContainers[D]=K}var J=A.domObj;K.insertBefore(J,K.lastChild)}this.content=new Element("div",{"class":"jx"+this.options.type+"Content"});new Jx.Layout(this.contentContainer);new Jx.Layout(this.content);this.contentContainer.adopt(this.content);this.loadContent(this.content,O);this.toggleCollapse(this.options.closed)},layoutContent:function(){var G=0;var H=0;var A=0;var C=0;var J=0;var I;var D;var F;if(!this.options.hideTitle&&this.title.parentNode==this.domObj){G=this.title.getMarginBoxSize().height}var B=this.domObj.getContentBoxSize();if(B.height>G){this.contentContainer.setStyle("display","block");this.options.closed=false;this.contentContainer.resize({top:G,height:null,bottom:0});["left","right"].each(function(L){if(this.toolbarContainers[L]){this.toolbarContainers[L].style.width=""}},this);["top","bottom"].each(function(L){if(this.toolbarContainers[L]){this.toolbarContainers[L].style.height=""}},this);for(var E=0;E<this.toolbars.length;E++){D=this.toolbars[E];F=D.options.position;I=this.toolbarContainers[F];var K=I.getBorderBoxSize();switch(F){case"top":H=K.height;break;case"bottom":A=K.height;break;case"left":C=K.width;break;case"right":J=K.width;break}}I=this.toolbarContainers.top;if(I){I.resize({top:0,left:C,right:J,bottom:null,height:H,width:null})}I=this.toolbarContainers.bottom;if(I){I.resize({top:null,left:C,right:J,bottom:0,height:A,width:null})}I=this.toolbarContainers.left;if(I){I.resize({top:H,left:0,right:null,bottom:A,height:null,width:C})}I=this.toolbarContainers.right;if(I){I.resize({top:H,left:null,right:0,bottom:A,height:null,width:J})}this.content.resize({top:H,bottom:A,left:C,right:J})}else{this.contentContainer.setStyle("display","none");this.options.closed=true}},setLabel:function(A){this.labelObj.innerHTML=A},getLabel:function(){return this.labelObj.innerHTML},finalize:function(){this.domObj=null;this.deregisterIds()},maximize:function(){if(this.manager){this.manager.maximizePanel(this)}},setContent:function(A){this.content.innerHTML=A;this.bContentReady=true},setContentURL:function(B){this.bContentReady=false;this.setBusy(true);if(arguments[1]){this.onContentReady=arguments[1]}if(B.indexOf("?")==-1){B=B+"?"}var C={method:"get",onComplete:this.panelContentLoaded.bind(this),requestHeaders:["If-Modified-Since","Sat, 1 Jan 2000 00:00:00 GMT"]};var A=new Request(B,C).send()},panelContentLoaded:function(A){this.content.innerHTML=A.responseText;this.bContentReady=true;this.setBusy(false);if(this.onContentReady){window.setTimeout(this.onContentReady.bind(this),1)}},setBusy:function(A){this.busyCount+=A?1:-1;this.loadingObj.img.style.visibility=(this.busyCount>0)?"visible":"hidden"},addTo:function(B,A){B=$(B);A=A?$(A):null;if(A&&A.parentNode==B){B.insertBefore(this.domObj,A)}else{B.appendChild(this.domObj)}this.domObj.resize()},toggleCollapse:function(C){if($defined(C)){this.options.closed=C}else{this.options.closed=!this.options.closed}if(this.options.closed){if(!this.domObj.hasClass("jx"+this.options.type+"Min")){this.domObj.addClass("jx"+this.options.type+"Min");this.contentContainer.setStyle("display","none");var B=this.domObj.getMarginSize();var A=B.top+B.bottom;if(this.title.parentNode==this.domObj){A+=this.title.getMarginBoxSize().height}this.domObj.resize({height:A});this.fireEvent("collapse",this)}}else{if(this.domObj.hasClass("jx"+this.options.type+"Min")){this.domObj.removeClass("jx"+this.options.type+"Min");this.contentContainer.setStyle("display","block");this.domObj.resize({height:this.options.height});this.fireEvent("expand",this)}}},close:function(){this.domObj.dispose();this.fireEvent("close",this)}});Jx.Dialog=new Class({Extends:Jx.Panel,Implements:[Jx.AutoPosition,Jx.Chrome],blanket:null,options:{modal:true,position:"absolute",width:250,height:250,left:0,top:0,bottom:null,right:null,label:"New Dialog",id:"",parent:null,resize:false,move:true,close:true,collapse:true},initialize:function(A){if(!Jx.Dialog.Stack){Jx.Dialog.Stack=[];Jx.Dialog.ZIndex=[100]}this.isOpening=false;this.parent($merge({parent:document.body},A,{type:"Dialog",position:"absolute"}));this.options.parent=$(this.options.parent);if(!window.opera&&this.options.modal){this.blanket=new Element("div",{"class":"jxDialogModal",styles:{display:"none",zIndex:-1}});this.options.parent.adopt(this.blanket);(new Jx.Layout(this.blanket)).resize()}this.domObj.setStyle("display","none");this.options.parent.adopt(this.domObj);if(this.options.move){this.title.addClass("jxDialogMoveable");new Drag(this.domObj,{handle:this.title,onStart:(function(){this.contentContainer.setStyle("visibility","hidden")}).bind(this),onComplete:(function(){this.contentContainer.setStyle("visibility","");this.position(this.domObj,this.options.parent,{horizontal:[parseInt(this.domObj.style.left)+" left"],vertical:[parseInt(this.domObj.style.top)+" top"]});this.options.left=parseInt(this.domObj.style.left);this.options.top=parseInt(this.domObj.style.top);if(!this.options.closed){this.domObj.resize(this.options)}}).bind(this)})}if(this.options.resize){this.resizeHandle=new Element("div",{"class":"jxDialogResize",styles:{display:this.options.closed?"none":"block"}});this.domObj.appendChild(this.resizeHandle);this.resizeHandleSize=this.resizeHandle.getSize();this.resizeHandle.setStyles({bottom:this.resizeHandleSize.height,right:this.resizeHandleSize.width});this.domObj.makeResizable({handle:this.resizeHandle,onStart:(function(){this.contentContainer.setStyle("visibility","hidden")}).bind(this),onDrag:this.resizeChrome.bind(this),onComplete:(function(){var B=this.domObj.getMarginBoxSize();this.options.width=B.width;this.options.height=B.height;this.layoutContent();this.domObj.resize(this.options);this.contentContainer.setStyle("visibility","");this.fireEvent("resize")}).bind(this)})}this.domObj.addEvent("mousedown",(function(){Jx.Dialog.Stack.erase(this).push(this);Jx.Dialog.Stack.each(function(C,B){C.domObj.setStyle("zIndex",101+B)})}).bind(this))},sizeChanged:function(){if(!this.options.closed){this.layoutContent();this.resizeChrome()}},toggleCollapse:function(C){if($defined(C)){this.options.closed=C}else{this.options.closed=!this.options.closed}if(this.options.closed){if(!this.domObj.hasClass("jx"+this.options.type+"Min")){this.domObj.addClass("jx"+this.options.type+"Min")}this.contentContainer.setStyle("display","none");if(this.resizeHandle){this.resizeHandle.setStyle("display","none")}}else{if(this.domObj.hasClass("jx"+this.options.type+"Min")){this.domObj.removeClass("jx"+this.options.type+"Min")}this.contentContainer.setStyle("display","block");if(this.resizeHandle){this.resizeHandle.setStyle("display","block")}}if(this.options.closed){var B=this.domObj.getMarginSize();var A=this.title.getMarginBoxSize();this.domObj.resize({height:B.top+A.height+B.bottom});this.fireEvent("collapse")}else{this.domObj.resize(this.options);this.fireEvent("expand")}},setTitle:function(A){this.title.childNodes[0].innerHTML=A},show:function(){Jx.Dialog.Stack.push(this);if(this.options.modal){this.blanket.setStyles({zIndex:Jx.Dialog.ZIndex[0]++,visibility:"visible",display:"block"})}this.domObj.setStyles({zIndex:Jx.Dialog.ZIndex[0]++,display:"block"});if(this.options.closed){var B=this.domObj.getMarginSize();var A=this.title.getMarginBoxSize();this.domObj.resize({height:B.top+A.height+B.bottom})}else{this.domObj.resize(this.options)}this.showChrome(this.domObj);this.position(this.domObj,this.options.parent,{horizontal:[this.options.left+" left"],vertical:[this.options.top+" top"]});this.options.left=parseInt(this.domObj.style.left);this.options.top=parseInt(this.domObj.style.top)},hide:function(){Jx.Dialog.Stack.erase(this);Jx.Dialog.ZIndex[0]--;this.domObj.setStyle("display","none");if(this.options.modal){this.blanket.setStyle("visibility","hidden");Jx.Dialog.ZIndex[0]--}},open:function(){if(!this.isOpening){this.isOpening=true}if(this.contentIsLoaded){this.show();this.fireEvent("open",this);this.isOpening=false}},close:function(){this.isOpening=false;this.hide();this.fireEvent("close")},onContentLoaded:function(){if(this.isOpening){this.open()}}});Jx.PanelSet=new Class({panels:null,height:null,firstLayout:true,initialize:function(C,B){this.domObj=$(C);this.panels=B;var H=new Element("div",{styles:{position:"absolute"}});new Jx.Layout(H,{minHeight:0,maxHeight:0,height:0});var G=[H];B.each(function(I){G.push(I.domObj);I.options.hideTitle=true;I.contentContainer.resize({top:0});I.addEvent("expand",this.maximizePanel.bind(this,I));I.domObj.store("Jx.Panel",I)},this);this.splitter=new Jx.Splitter(this.domObj,{splitInto:B.length+1,layout:"vertical",elements:G});this.splitter.sizeChanged=this.sizeChanged.bind(this);for(var E=0;E<this.panels.length;E++){var A=this.panels[E];var F=this.splitter.bars[E];A.title.setStyle("visibility","hidden");document.body.adopt(A.title);var D=A.title.getBorderBoxSize();F.adopt(A.title);A.title.setStyle("visibility","");F.setStyle("height",D.height);F.removeClass("jxSplitterBar");F.addClass("jxPanelBar");A.manager=this}},sizeChanged:function(){if(this.firstLayout){if(this.panels[0].title.getBorderBoxSize().height!=0){for(var B=0;B<this.splitter.bars.length;B++){var A=this.panels[B];this.splitter.bars[B].style.height=A.title.getBorderBoxSize().height+"px";this.splitter.bars[B].store("size",null)}this.firstLayout=false;Jx.Splitter.prototype.sizeChanged.apply(this.splitter,[])}}else{Jx.Splitter.prototype.sizeChanged.apply(this.splitter,[])}},maximizePanel:function(A){var E=this.domObj.getContentBoxSize().height;var D=0;for(var C=1;C<this.splitter.elements.length;C++){var F=this.splitter.elements[C];D+=F.retrieve("leftBar").getBorderBoxSize().height;if(F!==A.domObj){var B=F.retrieve("Jx.Panel");var G=F.retrieve("jxLayout").options;F.resize({top:D,height:G.minHeight,bottom:null});D+=G.minHeight;F.retrieve("rightBar").style.top=D+"px"}else{break}}b=E;for(var C=this.splitter.elements.length-1;C>0;C--){F=this.splitter.elements[C];if(F!==A.domObj){var G=F.retrieve("jxLayout").options;b-=G.minHeight;F.resize({top:b,height:G.minHeight,bottom:null});b-=F.retrieve("leftBar").getBorderBoxSize().height;F.retrieve("leftBar").style.top=b+"px"}else{break}}A.domObj.resize({top:D,height:b-D,bottom:null})}});Jx.Combo=new Class({Implements:[Options,Events,Jx.AutoPosition],domObj:null,ul:null,currentSelection:null,initialize:function(A){this.setOptions(A);this.domObj=new Element("div",{"class":"jxCombo"});if(this.options.id){this.domObj.id=this.options.id}if(this.options.editable){this.domInput=new Element("input",{"class":"jxComboInput",type:"text",events:{change:this.valueChanged.bindWithEvent(this),keydown:this.onKeyPress.bindWithEvent(this)}})}else{this.domInput=new Element("span",{"class":"jxComboInput"})}this.domObj.appendChild(this.domInput);this.domA=new Element("a",{"class":"jxComboDiscloser",href:"javascript:void(0)",events:{click:this.toggle.bind(this)}});this.domButton=new Element("img",{"class":"png24",src:Jx.baseURL+"images/disclose2.png"});this.domA.appendChild(this.domButton);this.domObj.appendChild(this.domA);if(!window.opera){this.domObj.appendChild(Jx.createIframeShim())}this.domListDiv=new Element("div",{"class":"jxComboOptions"});this.domList=new Element("ul");this.domListDiv.appendChild(this.domList);this.keypressHandler=this.keypress.bindWithEvent(this);this.clickHandler=this.click.bindWithEvent(this)},onKeyPress:function(A){if(A.key=="enter"){this.valueChanged()}},valueChanged:function(){this.fireEvent("changed",this)},add:function(D,B){var A=new Element("li");var C=new Element("a",{href:"javascript:void(0)",events:{click:this.pick.bindWithEvent(this)}});if($type(D)=="string"){C.innerHTML=D}else{C.appendChild(D)}A.appendChild(C);if(arguments.length>1&&this.domList.childNodes.length>B){this.domList.insertBefore(A,this.domList.childNodes[B])}else{this.domList.appendChild(A)}if(this.getValue()==""){this.setValue(C.childNodes[0])}},remove:function(A){if(A>0&&A<this.domList.childNodes.length){this.domList.removeChild(this.domList.childNodes[A])}},pick:function(B){var A=B.target;if(A.tagName=="A"){this.currentSelection=A;this.setValue(this.currentSelection.childNodes[0]);this.valueChanged()}this.close()},setValue:function(A){if(this.options.editable){if(typeof (A)=="string"){this.domInput.value=A}else{if(A.nodeType&&A.nodeType==3){this.domInput.value=A.nodeValue}else{this.domInput.value=A.innerHTML}}}else{if(typeof (A)=="string"){this.domInput.innerHTML=A}else{if(A.nodeType&&A.nodeType==3){this.domInput.innerHTML=A.nodeValue}else{this.domInput.appendChild(A)}}}},getValue:function(){value="";if(this.options.editable){value=this.domInput.value}else{if(this.domInput.childNodes.length>0){if(this.domInput.childNodes[0].nodeType==3){value=this.domInput.innerHTML}else{value=this.domInput.childNodes[0]}}}return value},toggle:function(){if(this.domListDiv.style.display=="block"){this.close()}else{this.open()}},open:function(){this.position(this.domListDiv,this.domObj,{horizontal:["left left","right right"],vertical:["bottom top","top bottom"]});this.domListDiv.width="";this.domListDiv.setStyle("visibility","hidden");document.body.adopt(this.domListDiv);this.domListDiv.setBorderBoxSize({width:Math.max(this.domListDiv.getSize().x,this.domObj.getSize().x)});this.domListDiv.setStyle("visibility","");document.addEvents({keydown:this.keypressHandler,click:this.clickHandler})},keypress:function(A){if(A.key=="esc"){this.close()}},click:function(A){if(!A.target.descendantOf(this.domListDiv)&&!A.target.descendantOf(this.domObj)){this.close()}},close:function(){this.domListDiv.dispose();document.removeEvents({keydown:this.keypressHandler,click:this.clickHandler})},getSelection:function(){return this.currentSelection?this.currentSelection.name:""}});Jx.Splitter=new Class({Implements:[Options],domObj:null,elements:null,bars:null,firstUpdate:true,options:{useChildren:false,splitInto:2,elements:null,containerOptions:[],barOptions:[],layout:"horizontal",snaps:[]},initialize:function(A,I){this.setOptions(I);this.domObj=$(A);this.domObj.addClass("jxSplitContainer");this.domObj.setStyle("overflow","hidden");var H=this.domObj.retrieve("jxLayout");if(H){H.addEvent("sizeChange",this.sizeChanged.bind(this))}this.elements=[];this.bars=[];var G=2;if(this.options.useChildren){this.elements=this.domObj.getChildren();G=this.elements.length}else{G=this.options.elements?this.options.elements.length:this.options.splitInto;for(var E=0;E<G;E++){var C;if(this.options.elements&&this.options.elements[E]){C=$(this.options.elements[E]);if(!C){C=this.prepareElement();C.id=this.options.elements[E]}}else{C=this.prepareElement()}this.elements[E]=C;this.domObj.adopt(this.elements[E])}}this.elements.each(function(J){J.addClass("jxSplitArea")});for(var E=0;E<G;E++){if(!this.elements[E].retrieve("jxLayout")){new Jx.Layout(this.elements[E],this.options.containerOptions[E])}}for(var E=1;E<G;E++){this.bars[E-1]=this.prepareBar();this.bars[E-1].store("leftSide",this.elements[E-1]);this.bars[E-1].store("rightSide",this.elements[E]);this.elements[E-1].store("rightBar",this.bars[E-1]);this.elements[E].store("leftBar",this.bars[E-1]);this.domObj.adopt(this.bars[E-1])}this.establishConstraints();for(var E=0;E<this.options.barOptions.length;E++){if(!this.bars[E]){continue}var B=this.options.barOptions[E];if(B&&B.snap&&(B.snap=="before"||B.snap=="after")){var F;if(B.snap=="before"){F=this.bars[E].retrieve("leftSide")}else{if(B.snap=="after"){F=this.bars[E].retrieve("rightSide")}}var D=new Element("a",{"class":"jxSnap"+this.options.layout.capitalize()+B.snap.capitalize(),href:"javascript:void(0)"});this.bars[E].adopt(D);new Jx.Splitter.Snap(D,F,this)}}for(var E=0;E<this.options.snaps.length;E++){if(this.options.snaps[E]){new Jx.Splitter.Snap(this.options.snaps[E],this.elements[E],this)}}},prepareElement:function(){var A=new Element("div",{styles:{position:"absolute"}});return A},prepareBar:function(){var A=new Element("div",{"class":"jxSplitBar"+this.options.layout.capitalize(),title:"drag this bar to resize"});A.store("splitterObj",this);return A},establishConstraints:function(){var A={};var B;if(this.options.layout=="horizontal"){A.y=[0,0];B=this.dragHorizontal}else{A.x=[0,0];B=this.dragVertical}this.bars.each(function(C){new Drag(C,{limit:A,onSnap:function(D){D.addClass("jxSplitBarDrag")},onComplete:(function(D){D.removeClass("jxSplitBarDrag");if(D.retrieve("splitterObj")!=this){return }B.apply(this,[D])}).bind(this)})},this)},dragHorizontal:function(F){var A=parseInt(F.style.left);var H=F.retrieve("leftSide");var C=F.retrieve("rightSide");var D=H.retrieve("jxLayout");var G=C.retrieve("jxLayout");var E=this.domObj.getPaddingSize().left;var I,O,K;var N=F.retrieve("size");if(!N){N=F.getBorderBoxSize();F.store("size",N)}I=A+N.width-E;var B=this.domObj.getContentBoxSize();if(G.options.width!=null){O=G.options.width+G.options.left-I;K=B.width-I-O}else{O=B.width-G.options.right-I;K=G.options.right}if(O<0){O=0}if(O<G.options.minWidth){O=G.options.minWidth}if(G.options.maxWidth>=0&&O>G.options.maxWidth){O=G.options.maxWidth}I=B.width-K-O;A=I-N.width;var J,M;J=D.options.left;M=A-J;if(M<0){M=0}if(M<D.options.minWidth){M=D.options.minWidth}if(D.options.maxWidth>=0&&M>D.options.maxWidth){M=D.options.maxWidth}if(J+M!=A){A=J+M;var L=A+N.width-I;I+=L;O-=L}F.style.left=E+A+"px";if(D.options.width==null){var B=this.domObj.getContentBoxSize();H.resize({right:B.width-J-M})}else{H.resize({width:M})}if(G.options.width==null){C.resize({left:I})}else{C.resize({left:I,width:O})}},dragVertical:function(F){var J=parseInt(F.style.top);var D=F.retrieve("leftSide");var A=F.retrieve("rightSide");var E=D.retrieve("jxLayout");var H=A.retrieve("jxLayout");var N=this.domObj.getPaddingSize().top;var O=F.retrieve("size");if(!O){O=F.getBorderBoxSize();F.store("size",O)}var B=this.domObj.getContentBoxSize();var C,M,K;C=J+O.height-N;if(H.options.height!=null){M=H.options.height+H.options.top-C;K=B.height-C-M}else{M=B.height-H.options.bottom-C;K=H.options.bottom}if(M<0){M=0}if(M<H.options.minHeight){M=H.options.minHeight}if(H.options.maxHeight>=0&&M>H.options.maxHeight){M=H.options.maxHeight}C=B.height-K-M;J=C-O.height;var I,G;I=E.options.top;G=J-I;if(G<0){G=0}if(G<E.options.minHeight){G=E.options.minHeight}if(E.options.maxHeight>=0&&G>E.options.maxHeight){G=E.options.maxHeight}if(I+G!=J){J=I+G;var L=J+O.height-C;C+=L;M-=L}F.style.top=N+J+"px";if(E.options.height==null){D.resize({bottom:B.height-I-G})}else{D.resize({height:G})}if(H.options.height==null){A.resize({top:C})}else{A.resize({top:C,height:M})}},sizeChanged:function(){if(this.options.layout=="horizontal"){this.horizontalResize()}else{this.verticalResize()}},horizontalResize:function(){var O=this.domObj.getContentBoxSize().width;var D=O;for(var E=0;E<this.bars.length;E++){var L=this.bars[E];var Q=L.retrieve("size");if(!Q||Q.width==0){Q=L.getBorderBoxSize();L.store("size",Q)}O-=Q.width}var I=0;var H;for(var E=0;E<this.elements.length;E++){var K=this.elements[E];H=K.retrieve("jxLayout").options;if(H.width!=null){O-=parseInt(H.width)}else{var N=0;if(H.right!=0||H.left!=0){N=K.getBorderBoxSize().width}O-=N;I++}}if(I==0){O+=H.width;H.width=null;I=1}var G=parseInt(O/I);var P=O%I;var B=this.domObj.getPaddingSize().left;var C=0;for(var E=0;E<this.elements.length;E++){var K=this.elements[E];var J=K.retrieve("jxLayout");var H=J.options;if(H.width!=null){J.resize({left:C});C+=H.width}else{var M=G;if(I==1){M+=P}I--;var N=0;if(H.right!=0||H.left!=0){N=K.getBorderBoxSize().width+M}else{N=M}if(N<0){if(I>0){G=G+N/I}N=0}if(N<H.minWidth){if(I>0){G=G+(N-H.minWidth)/I}N=H.minWidth}if(H.maxWidth>=0&&N>H.maxWidth){if(I>0){G=G+(N-H.maxWidth)/I}N=K.options.maxWidth}var A=D-C-N;J.resize({left:C,right:A});C+=N}var F=K.retrieve("rightBar");if(F){F.setStyle("left",B+C);C+=F.retrieve("size").width}}},verticalResize:function(){var N=this.domObj.getContentBoxSize().height;var B=N;for(var D=0;D<this.bars.length;D++){var L=this.bars[D];var Q=L.retrieve("size");if(!Q||Q.height==0){Q=L.getBorderBoxSize();L.store("size",Q)}N-=Q.height}var I=0;var H;for(var D=0;D<this.elements.length;D++){var K=this.elements[D];H=K.retrieve("jxLayout").options;if(H.height!=null){N-=parseInt(H.height)}else{var G=0;if(H.bottom!=0||H.top!=0){G=K.getBorderBoxSize().height}N-=G;I++}}if(I==0){N+=H.height;H.height=null;I=1}var F=parseInt(N/I);var O=N%I;var P=this.domObj.getPaddingSize().top;var C=0;for(var D=0;D<this.elements.length;D++){var K=this.elements[D];var J=K.retrieve("jxLayout");var H=J.options;if(H.height!=null){J.resize({top:C});C+=H.height}else{var M=F;if(I==1){M+=O}I--;var G=0;if(H.bottom!=0||H.top!=0){G=K.getBorderBoxSize().height+M}else{G=M}if(G<0){if(I>0){F=F+G/I}G=0}if(G<H.minHeight){if(I>0){F=F+(G-H.minHeight)/I}G=H.minHeight}if(H.maxHeight>=0&&G>H.maxHeight){if(I>0){F=F+(G-H.maxHeight)/I}G=H.maxHeight}var A=B-C-G;J.resize({top:C,bottom:A});C+=G}var E=K.retrieve("rightBar");if(E){E.style.top=P+C+"px";C+=E.retrieve("size").height}}}});Jx.Splitter.Snap=new Class({snap:null,element:null,splitter:null,layout:"vertical",initialize:function(A,E,F){this.snap=A;this.element=E;var D=E.retrieve("jxLayout");D.addEvent("sizeChange",this.sizeChange.bind(this));this.splitter=F;this.layout=F.options.layout;var B=D.options;var C=this.element.getContentBoxSize();if(this.layout=="vertical"){this.originalSize=C.height;this.minimumSize=B.minHeight?B.minHeight:0}else{this.originalSize=C.width;this.minimumSize=B.minWidth?B.minWidth:0}A.addEvent("click",this.toggleElement.bind(this))},toggleElement:function(){var B=this.element.getContentBoxSize();var A={};if(this.layout=="vertical"){if(B.height==this.minimumSize){A.height=this.originalSize}else{this.originalSize=B.height;A.height=this.minimumSize}}else{if(B.width==this.minimumSize){A.width=this.originalSize}else{this.originalSize=B.width;A.width=this.minimumSize}}this.element.resize(A);this.splitter.sizeChanged()},sizeChange:function(){var A=this.element.getBorderBoxSize();if(this.layout=="vertical"){if(A.height==this.minimumSize){this.snap.addClass("jxSnapClosed");this.snap.removeClass("jxSnapOpened")}else{this.snap.addClass("jxSnapOpened");this.snap.removeClass("jxSnapClosed")}}else{if(A.width==this.minimumSize){this.snap.addClass("jxSnapClosed");this.snap.removeClass("jxSnapOpened")}else{this.snap.addClass("jxSnapOpened");this.snap.removeClass("jxSnapClosed")}}}});Jx.TabSet=new Class({Implements:[Options,Events],tabs:null,domObj:null,initialize:function(B,A){this.setOptions(A);this.tabs=[];this.domObj=$(B);if(!this.domObj.hasClass("jxTabSetContainer")){this.domObj.addClass("jxTabSetContainer")}this.selectionChangedFn=this.selectionChanged.bind(this)},resizeTabBox:function(){var B=Element.getContentBoxSize(this.domObj.parentNode);Element.setBorderBoxSize(this.domObj,{width:B.width,height:B.height});for(var A=0;A<this.domObj.childNodes.length;A++){if(this.domObj.childNodes[A].nodeType==3){continue}Element.setBorderBoxSize(this.domObj.childNodes[A],{height:B.height});if(this.domObj.childNodes[A].resize){this.domObj.childNodes[A].resize()}}},add:function(){$A(arguments).each(function(A){if(A instanceof Jx.Button.Tab){A.addEvent("down",this.selectionChangedFn);this.domObj.appendChild(A.content);if(!this.activeTab){A.setActive(true)}this.tabs.push(A)}},this)},remove:function(A){if(A instanceof Jx.Button.Tab&&this.tabs.indexOf(A)!=-1){this.tabs.erase(A);if(this.activeTab==A){if(this.tabs.length){this.tabs[0].setActive(true)}}A.removeEvent("down",this.selectionChangedFn);A.content.dispose()}},setActiveTab:function(A){if(this.activeTab&&this.activeTab!=A){this.activeTab.setActive(false)}this.activeTab=A;if(this.activeTab.content.resize){this.activeTab.content.resize()}},selectionChanged:function(A){this.setActiveTab(A);this.fireEvent("tabChange",this,A)}});Jx.TabSet=new Class({Implements:[Options,Events],tabs:null,domObj:null,initialize:function(B,A){this.setOptions(A);this.tabs=[];this.domObj=$(B);if(!this.domObj.hasClass("jxTabSetContainer")){this.domObj.addClass("jxTabSetContainer")}this.selectionChangedFn=this.selectionChanged.bind(this)},resizeTabBox:function(){var B=Element.getContentBoxSize(this.domObj.parentNode);Element.setBorderBoxSize(this.domObj,{width:B.width,height:B.height});for(var A=0;A<this.domObj.childNodes.length;A++){if(this.domObj.childNodes[A].nodeType==3){continue}Element.setBorderBoxSize(this.domObj.childNodes[A],{height:B.height});if(this.domObj.childNodes[A].resize){this.domObj.childNodes[A].resize()}}},add:function(){$A(arguments).each(function(A){if(A instanceof Jx.Button.Tab){A.addEvent("down",this.selectionChangedFn);this.domObj.appendChild(A.content);if(!this.activeTab){A.setActive(true)}this.tabs.push(A)}},this)},remove:function(A){if(A instanceof Jx.Button.Tab&&this.tabs.indexOf(A)!=-1){this.tabs.erase(A);if(this.activeTab==A){if(this.tabs.length){this.tabs[0].setActive(true)}}A.removeEvent("down",this.selectionChangedFn);A.content.dispose()}},setActiveTab:function(A){if(this.activeTab&&this.activeTab!=A){this.activeTab.setActive(false)}this.activeTab=A;if(this.activeTab.content.resize){this.activeTab.content.resize()}},selectionChanged:function(A){this.setActiveTab(A);this.fireEvent("tabChange",this,A)}});Jx.Button.Tab=new Class({Extends:Jx.Button,Implements:[Options,Events,Jx.ContentLoader],content:null,initialize:function(A){A=$merge(A,{type:"Tab",toggle:true});this.parent(A);this.content=new Element("div",{"class":"tabContent"});this.loadContent(this.content);new Jx.Layout(this.content,A);var B=this;this.addEvent("down",function(){B.content.addClass("tabContentActive")});this.addEvent("up",function(){B.content.removeClass("tabContentActive")})},clicked:function(A){this.setActive(true)}});Jx.Toolbar=new Class({Implements:[Options,Events],items:null,domObj:null,isActive:false,options:{position:"top",parent:null},initialize:function(B){this.setOptions(B);this.domObj=new Element("ul",{"class":"jxToolbar"});if(this.options.parent){var A=$(this.options.parent);if(!A.hasClass("jxToolbarContainer")){A.addClass("jxToolbarContainer");A.appendChild(this.domObj);var C=new Element("div",{"class":"jxClearer"});A.appendChild(C)}else{A.insertBefore(this.domObj,A.lastChild)}if(["top","right","bottom","left"].contains(this.options.position)){A.addClass("jxBar"+this.options.position.capitalize())}else{A.addClass("jxBarTop")}}this.deactivateWatcher=this.deactivate.bindWithEvent(this)},add:function(){for(var B=0;B<arguments.length;B++){var A=arguments[B];A.toolbar=this;if(A.domObj){A=A.domObj}if(A.tagName=="LI"){if(!A.hasClass("jxToolItem")){A.addClass("jxToolItem")}this.domObj.appendChild(A)}else{var C=new Jx.Toolbar.Item(A);this.domObj.appendChild(C.domObj)}}if(arguments.length>0){this.fireEvent("add",this)}},remove:function(B){if(B.domObj){B=B.domObj}var A=B.findElement("LI");if(A&&A.parentNode==this.domObj){B.dispose();this.fireEvent("remove",this)}else{return null}},deactivate:function(){this.items.each(function(A){A.hide()});this.setActive(false)},isActive:function(){return this.isActive},setActive:function(A){this.isActive=A;if(this.isActive){document.addEvent("click",this.deactivateWatcher);Event.observe(document,"click",this.deactivateWatcher)}else{document.removeEvent("click",this.deactivateWatcher)}},setVisibleItem:function(A){if(this.visibleItem&&this.visibleItem.hide&&this.visibleItem!=A){this.visibleItem.hide()}this.visibleItem=A;if(this.isActive()){this.visibleItem.show()}}});Jx.Toolbar.Item=new Class({domObj:null,initialize:function(A){this.al=[];this.domObj=new Element("li",{"class":"jxToolItem"});if(A){if(A.domObj){this.domObj.appendChild(A.domObj);if(A instanceof Jx.Tab){this.domObj.addClass("jxTabItem")}}else{this.domObj.appendChild(A);if(A.hasClass("jxTab")){this.domObj.addClass("jxTabItem")}}}}});Jx.Toolbar.Separator=new Class({domObj:null,initialize:function(){this.domObj=new Element("li",{"class":"jxToolItem"});this.domSpan=new Element("span",{"class":"separator"});this.domObj.appendChild(this.domSpan)}});Jx.TreeItem=new Class({Implements:[Options,Events],domObj:null,owner:null,options:{label:"",data:null,contextMenu:null,image:null,enabled:true,type:"Item",imageClass:""},initialize:function(A){this.setOptions(A);this.domObj=new Element("li",{"class":"jxTree"+this.options.type});if(this.options.id){this.domObj.id=this.options.id}this.domNode=new Element("img",{"class":"jxTreeImage",src:Jx.aPixel.src});this.domObj.appendChild(this.domNode);this.domImg=new Element("img",{"class":"jxTreeIcon",src:Jx.aPixel.src});if(this.options.image){this.domImg.setStyle("backgroundImage","url("+this.options.image+")")}if(this.options.imageClass){this.domImg.addClass(this.options.imageClass)}this.domA=new Element("a",{href:"javascript:void(0)",html:this.options.label,events:{click:this.selected.bindWithEvent(this),dblclick:this.selected.bindWithEvent(this),contextmenu:this.showMenu.bindWithEvent(this)}});this.domA.store("jxTreeItem",this);this.domA.appendChild(this.domImg);this.domObj.appendChild(this.domA);this.domObj.store("jxTreeItem",this);if(!this.options.enabled){this.domObj.addClass("jxDisabled")}},finalize:function(){this.finalizeItem()},finalizeItem:function(){if(!this.domObj){return }this.domA.removeEvents();this.options=null;this.domObj=null;this.owner=null},clone:function(){return new Jx.TreeItem(this.options)},update:function(B){var A=(arguments.length>1)?arguments[1]:(this.owner&&this.owner.isLastNode(this));if(A){this.domObj.removeClass("jxTree"+this.options.type);this.domObj.addClass("jxTree"+this.options.type+"Last")}else{this.domObj.removeClass("jxTree"+this.options.type+"Last");this.domObj.addClass("jxTree"+this.options.type)}},selected:function(A){this.lastEvent=A;this.fireEvent("click",this)},showMenu:function(A){this.lastEvent=A;this.fireEvent("click",this);if(this.contextMenu){this.contextMenu.show(this.lastEvent)}A.stop()},getName:function(){return this.options.label},setName:function(A){this.domA.set("html",A);this.options.label=A},propertyChanged:function(A){this.options.enabled=A.isEnabled();if(this.options.enabled){this.domObj.removeClass("jxDisabled")}else{this.domObj.addClass("jxDisabled")}}});Jx.TreeFolder=new Class({Extends:Jx.TreeItem,subDomObj:null,nodes:null,isOpen:false,options:{folderCloseImage:Jx.baseURL+"images/tree_folder.png",folderOpenImage:Jx.baseURL+"images/tree_folder_open.png"},initialize:function(A){this.parent($merge(A,{type:"Branch"}));this.domObj.childNodes[0].addEvent("click",this.clicked.bindWithEvent(this));this.nodes=[];this.subDomObj=new Element("ul",{"class":"jxTree"});this.domObj.appendChild(this.subDomObj);this.subDomObj.className="jxTree";if(this.options.isOpen){this.expand()}else{this.collapse()}},finalize:function(){this.finalizeFolder();this.finalizeItem();this.subDomObj=null},finalizeFolder:function(){this.domObj.childNodes[0].removeEvents();for(var A=this.nodes.length-1;A>=0;A--){this.nodes[A].finalize();if(this.nodes[A].domObj){this.subDomObj.removeChild(this.nodes[A].domObj)}this.nodes.pop()}},clone:function(){var A=new Jx.TreeFolder(this.options);this.nodes.each(function(B){A.append(B.clone())});return A},isLastNode:function(A){if(this.nodes.length==0){return false}else{return this.nodes[this.nodes.length-1]==A}},update:function(C){if(!this.parent){return }var B=false;if(arguments.length>1){B=arguments[1]}else{B=(this.owner&&this.owner.isLastNode(this))}var D="jxTree"+this.options.type;D+=B?"Last":"";D+=this.options.isOpen?"Open":"Closed";this.domObj.className=D;if(B){this.subDomObj.className="jxTree"}else{this.subDomObj.className="jxTree jxTreeNest"}if(this.nodes&&C){var A=this;this.nodes.each(function(F,E){F.update(false,E==A.nodes.length-1)})}},append:function(A){A.owner=this;this.nodes.push(A);this.subDomObj.appendChild(A.domObj);this.update(true)},insert:function(D,B){D.owner=this;if(!B){this.nodes.unshift(D);if(this.subDomObj.childNodes.length==0){this.subDomObj.appendChild(D.domObj)}else{this.subDomObj.insertBefore(D.domObj,this.subDomObj.childNodes[0])}}else{var A=false;for(var C=0;C<this.nodes.length;C++){if(this.nodes[C]==B){C=C+1;if(C<this.nodes.length){this.nodes.splice(C,0,D);this.subDomObj.insertBefore(D.domObj,this.subDomObj.childNodes[C]);A=true;break}}}if(!A){this.nodes.push(D);this.subDomObj.appendChild(D.domObj)}}this.update(true)},remove:function(B){B.owner=null;for(var A=0;A<this.nodes.length;A++){if(this.nodes[A]==B){this.nodes.splice(A,1);this.subDomObj.removeChild(this.subDomObj.childNodes[A]);break}}this.update(true)},replace:function(D,B){var A=false;for(var C=0;C<this.nodes.length;C++){if(this.nodes[C]==B){if(C<this.nodes.length){D.owner=this;this.nodes.splice(C,1,D);this.subDomObj.replaceChild(D.domObj,B.domObj);return true}}}return false},clicked:function(A){if(this.options.isOpen){this.collapse()}else{this.expand()}},expand:function(){this.options.isOpen=true;this.subDomObj.setStyle("display","block");this.update(true);this.fireEvent("disclosed",this)},collapse:function(){this.options.isOpen=false;this.subDomObj.setStyle("display","none");this.update(true);this.fireEvent("disclosed",this)},findChild:function(C){if(C.length==0){return this}if(C.length==1){for(var B=0;B<this.nodes.length;B++){if(this.nodes[B].getName()==C[0]){return this.nodes[B]}}return null}var A=C.shift();for(var B=0;B<this.nodes.length;B++){if(this.nodes[B].getName()==A&&this.nodes[B].findChild){return this.nodes[B].findChild(C)}}return null}});Jx.Tree=new Class({Extends:Jx.TreeFolder,initialize:function(A){this.parent();this.subDomObj=new Element("ul",{"class":"jxTreeRoot"});$(A).appendChild(this.subDomObj);this.nodes=[];this.isOpen=true},finalize:function(){this.clear();this.subDomObj.parentNode.removeChild(this.subDomObj)},clear:function(){for(var A=this.nodes.length-1;A>=0;A--){this.subDomObj.removeChild(this.nodes[A].domObj);this.nodes[A].finalize();this.nodes.pop()}},update:function(A){var B=true;if(this.subDomObj){if(B){this.subDomObj.removeClass("jxTreeNest")}else{this.subDomObj.addClass("jxTreeNest")}}if(this.nodes&&A){this.nodes.each(function(C){C.update(false)})}},append:function(A){A.owner=this;this.nodes.push(A);this.subDomObj.appendChild(A.domObj);this.update(true)}});
\ No newline at end of file
Added: sandbox/jx2/jx/lib/jxlib.uncompressed.js
===================================================================
--- sandbox/jx2/jx/lib/jxlib.uncompressed.js (rev 0)
+++ sandbox/jx2/jx/lib/jxlib.uncompressed.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -0,0 +1,13148 @@
+/*
+Script: Core.js
+ MooTools - My Object Oriented JavaScript Tools.
+
+License:
+ MIT-style license.
+
+Copyright:
+ Copyright (c) 2006-2007 [Valerio Proietti](http://mad4milk.net/).
+
+Code & Documentation:
+ [The MooTools production team](http://mootools.net/developers/).
+
+Inspiration:
+ - Class implementation inspired by [Base.js](http://dean.edwards.name/weblog/2006/03/base/) Copyright (c) 2006 Dean Edwards, [GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)
+ - Some functionality inspired by [Prototype.js](http://prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License](http://opensource.org/licenses/mit-license.php)
+*/
+
+var MooTools = {
+ 'version': '1.2dev',
+ 'build': ''
+};
+
+var Native = function(options){
+ options = options || {};
+
+ var afterImplement = options.afterImplement || function(){};
+ var generics = options.generics;
+ generics = (generics !== false);
+ var legacy = options.legacy;
+ var initialize = options.initialize;
+ var protect = options.protect;
+ var name = options.name;
+
+ var object = initialize || legacy;
+
+ object.constructor = Native;
+ object.$family = {name: 'native'};
+ if (legacy && initialize) object.prototype = legacy.prototype;
+ object.prototype.constructor = object;
+
+ if (name){
+ var family = name.toLowerCase();
+ object.prototype.$family = {name: family};
+ Native.typize(object, family);
+ }
+
+ var add = function(obj, name, method, force){
+ if (!protect || force || !obj.prototype[name]) obj.prototype[name] = method;
+ if (generics) Native.genericize(obj, name, protect);
+ afterImplement.call(obj, name, method);
+ return obj;
+ };
+
+ object.implement = function(a1, a2, a3){
+ if (typeof a1 == 'string') return add(this, a1, a2, a3);
+ for (var p in a1) add(this, p, a1[p], a2);
+ return this;
+ };
+
+ object.alias = function(a1, a2, a3){
+ if (typeof a1 == 'string'){
+ a1 = this.prototype[a1];
+ if (a1) add(this, a2, a1, a3);
+ } else {
+ for (var a in a1) this.alias(a, a1[a], a2);
+ }
+ return this;
+ };
+
+ return object;
+};
+
+Native.implement = function(objects, properties){
+ for (var i = 0, l = objects.length; i < l; i++) objects[i].implement(properties);
+};
+
+Native.genericize = function(object, property, check){
+ if ((!check || !object[property]) && typeof object.prototype[property] == 'function') object[property] = function(){
+ var args = Array.prototype.slice.call(arguments);
+ return object.prototype[property].apply(args.shift(), args);
+ };
+};
+
+Native.typize = function(object, family){
+ if (!object.type) object.type = function(item){
+ return ($type(item) === family);
+ };
+};
+
+Native.alias = function(objects, a1, a2, a3){
+ for (var i = 0, j = objects.length; i < j; i++) objects[i].alias(a1, a2, a3);
+};
+
+(function(objects){
+ for (var name in objects) Native.typize(objects[name], name);
+})({'boolean': Boolean, 'native': Native, 'object': Object});
+
+(function(objects){
+ for (var name in objects) new Native({name: name, initialize: objects[name], protect: true});
+})({'String': String, 'Function': Function, 'Number': Number, 'Array': Array, 'RegExp': RegExp, 'Date': Date});
+
+(function(object, methods){
+ for (var i = methods.length; i--; i) Native.genericize(object, methods[i], true);
+ return arguments.callee;
+})
+(Array, ['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift', 'concat', 'join', 'slice', 'toString', 'valueOf', 'indexOf', 'lastIndexOf'])
+(String, ['charAt', 'charCodeAt', 'concat', 'indexOf', 'lastIndexOf', 'match', 'replace', 'search', 'slice', 'split', 'substr', 'substring', 'toLowerCase', 'toUpperCase', 'valueOf']);
+
+function $chk(obj){
+ return !!(obj || obj === 0);
+};
+
+function $clear(timer){
+ clearTimeout(timer);
+ clearInterval(timer);
+ return null;
+};
+
+function $defined(obj){
+ return (obj != undefined);
+};
+
+function $empty(){};
+
+function $arguments(i){
+ return function(){
+ return arguments[i];
+ };
+};
+
+function $lambda(value){
+ return (typeof value == 'function') ? value : function(){
+ return value;
+ };
+};
+
+function $extend(original, extended){
+ for (var key in (extended || {})) original[key] = extended[key];
+ return original;
+};
+
+function $unlink(object){
+ var unlinked;
+
+ switch ($type(object)){
+ case 'object':
+ unlinked = {};
+ for (var p in object) unlinked[p] = $unlink(object[p]);
+ break;
+ case 'hash':
+ unlinked = $unlink(object.getClean());
+ break;
+ case 'array':
+ unlinked = [];
+ for (var i = 0, l = object.length; i < l; i++) unlinked[i] = $unlink(object[i]);
+ break;
+ default: return object;
+ }
+
+ return unlinked;
+};
+
+function $merge(){
+ var mix = {};
+ for (var i = 0, l = arguments.length; i < l; i++){
+ var object = arguments[i];
+ if ($type(object) != 'object') continue;
+ for (var key in object){
+ var op = object[key], mp = mix[key];
+ mix[key] = (mp && $type(op) == 'object' && $type(mp) == 'object') ? $merge(mp, op) : $unlink(op);
+ }
+ }
+ return mix;
+};
+
+function $pick(){
+ for (var i = 0, l = arguments.length; i < l; i++){
+ if (arguments[i] != undefined) return arguments[i];
+ }
+ return null;
+};
+
+function $random(min, max){
+ return Math.floor(Math.random() * (max - min + 1) + min);
+};
+
+function $splat(obj){
+ var type = $type(obj);
+ return (type) ? ((type != 'array' && type != 'arguments') ? [obj] : obj) : [];
+};
+
+var $time = Date.now || function(){
+ return new Date().getTime();
+};
+
+function $try(){
+ for (var i = 0, l = arguments.length; i < l; i++){
+ try {
+ return arguments[i]();
+ } catch(e){}
+ }
+ return null;
+};
+
+function $type(obj){
+ if (obj == undefined) return false;
+ if (obj.$family) return (obj.$family.name == 'number' && !isFinite(obj)) ? false : obj.$family.name;
+ if (obj.nodeName){
+ switch (obj.nodeType){
+ case 1: return 'element';
+ case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
+ }
+ } else if (typeof obj.length == 'number'){
+ if (obj.callee) return 'arguments';
+ else if (obj.item) return 'collection';
+ }
+ return typeof obj;
+};
+
+var Hash = new Native({
+
+ name: 'Hash',
+
+ initialize: function(object){
+ if ($type(object) == 'hash') object = $unlink(object.getClean());
+ for (var key in object) this[key] = object[key];
+ return this;
+ }
+
+});
+
+Hash.implement({
+
+ getLength: function(){
+ var length = 0;
+ for (var key in this){
+ if (this.hasOwnProperty(key)) length++;
+ }
+ return length;
+ },
+
+ forEach: function(fn, bind){
+ for (var key in this){
+ if (this.hasOwnProperty(key)) fn.call(bind, this[key], key, this);
+ }
+ },
+
+ getClean: function(){
+ var clean = {};
+ for (var key in this){
+ if (this.hasOwnProperty(key)) clean[key] = this[key];
+ }
+ return clean;
+ }
+
+});
+
+Hash.alias('forEach', 'each');
+
+function $H(object){
+ return new Hash(object);
+};
+
+Array.implement({
+
+ forEach: function(fn, bind){
+ for (var i = 0, l = this.length; i < l; i++) fn.call(bind, this[i], i, this);
+ }
+
+});
+
+Array.alias('forEach', 'each');
+
+function $A(iterable){
+ if (iterable.item){
+ var array = [];
+ for (var i = 0, l = iterable.length; i < l; i++) array[i] = iterable[i];
+ return array;
+ }
+ return Array.prototype.slice.call(iterable);
+};
+
+function $each(iterable, fn, bind){
+ var type = $type(iterable);
+ ((type == 'arguments' || type == 'collection' || type == 'array') ? Array : Hash).each(iterable, fn, bind);
+};
+
+
+/*
+Script: Browser.js
+ The Browser Core. Contains Browser initialization, Window and Document, and the Browser Hash.
+
+License:
+ MIT-style license.
+*/
+
+var Browser = new Hash({
+ Engine: {name: 'unknown', version: ''},
+ Platform: {name: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},
+ Features: {xpath: !!(document.evaluate), air: !!(window.runtime)},
+ Plugins: {}
+});
+
+if (window.opera) Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925};
+else if (window.ActiveXObject) Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4};
+else if (!navigator.taintEnabled) Browser.Engine = {name: 'webkit', version: (Browser.Features.xpath) ? 420 : 419};
+else if (document.getBoxObjectFor != null) Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18};
+Browser.Engine[Browser.Engine.name] = Browser.Engine[Browser.Engine.name + Browser.Engine.version] = true;
+
+if (window.orientation != undefined) Browser.Platform.name = 'ipod';
+
+Browser.Platform[Browser.Platform.name] = true;
+
+Browser.Request = function(){
+ return $try(function(){
+ return new XMLHttpRequest();
+ }, function(){
+ return new ActiveXObject('MSXML2.XMLHTTP');
+ });
+};
+
+Browser.Features.xhr = !!(Browser.Request());
+
+Browser.Plugins.Flash = (function(){
+ var version = ($try(function(){
+ return navigator.plugins['Shockwave Flash'].description;
+ }, function(){
+ return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
+ }) || '0 r0').match(/\d+/g);
+ return {version: parseInt(version[0] || 0 + '.' + version[1] || 0), build: parseInt(version[2] || 0)};
+})();
+
+function $exec(text){
+ if (!text) return text;
+ if (window.execScript){
+ window.execScript(text);
+ } else {
+ var script = document.createElement('script');
+ script.setAttribute('type', 'text/javascript');
+ script.text = text;
+ document.head.appendChild(script);
+ document.head.removeChild(script);
+ }
+ return text;
+};
+
+Native.UID = 1;
+
+var $uid = (Browser.Engine.trident) ? function(item){
+ return (item.uid || (item.uid = [Native.UID++]))[0];
+} : function(item){
+ return item.uid || (item.uid = Native.UID++);
+};
+
+var Window = new Native({
+
+ name: 'Window',
+
+ legacy: (Browser.Engine.trident) ? null: window.Window,
+
+ initialize: function(win){
+ $uid(win);
+ if (!win.Element){
+ win.Element = $empty;
+ if (Browser.Engine.webkit) win.document.createElement("iframe"); //fixes safari 2
+ win.Element.prototype = (Browser.Engine.webkit) ? window["[[DOMElement.prototype]]"] : {};
+ }
+ return $extend(win, Window.Prototype);
+ },
+
+ afterImplement: function(property, value){
+ window[property] = Window.Prototype[property] = value;
+ }
+
+});
+
+Window.Prototype = {$family: {name: 'window'}};
+
+new Window(window);
+
+var Document = new Native({
+
+ name: 'Document',
+
+ legacy: (Browser.Engine.trident) ? null: window.Document,
+
+ initialize: function(doc){
+ $uid(doc);
+ doc.head = doc.getElementsByTagName('head')[0];
+ doc.html = doc.getElementsByTagName('html')[0];
+ doc.window = doc.defaultView || doc.parentWindow;
+ if (Browser.Engine.trident4) $try(function(){
+ doc.execCommand("BackgroundImageCache", false, true);
+ });
+ return $extend(doc, Document.Prototype);
+ },
+
+ afterImplement: function(property, value){
+ document[property] = Document.Prototype[property] = value;
+ }
+
+});
+
+Document.Prototype = {$family: {name: 'document'}};
+
+new Document(document);
+
+/*
+Script: Array.js
+ Contains Array Prototypes like copy, each, contains, and remove.
+
+License:
+ MIT-style license.
+*/
+
+Array.implement({
+
+ every: function(fn, bind){
+ for (var i = 0, l = this.length; i < l; i++){
+ if (!fn.call(bind, this[i], i, this)) return false;
+ }
+ return true;
+ },
+
+ filter: function(fn, bind){
+ var results = [];
+ for (var i = 0, l = this.length; i < l; i++){
+ if (fn.call(bind, this[i], i, this)) results.push(this[i]);
+ }
+ return results;
+ },
+
+ clean: function() {
+ return this.filter($defined);
+ },
+
+ indexOf: function(item, from){
+ var len = this.length;
+ for (var i = (from < 0) ? Math.max(0, len + from) : from || 0; i < len; i++){
+ if (this[i] === item) return i;
+ }
+ return -1;
+ },
+
+ map: function(fn, bind){
+ var results = [];
+ for (var i = 0, l = this.length; i < l; i++) results[i] = fn.call(bind, this[i], i, this);
+ return results;
+ },
+
+ some: function(fn, bind){
+ for (var i = 0, l = this.length; i < l; i++){
+ if (fn.call(bind, this[i], i, this)) return true;
+ }
+ return false;
+ },
+
+ associate: function(keys){
+ var obj = {}, length = Math.min(this.length, keys.length);
+ for (var i = 0; i < length; i++) obj[keys[i]] = this[i];
+ return obj;
+ },
+
+ link: function(object){
+ var result = {};
+ for (var i = 0, l = this.length; i < l; i++){
+ for (var key in object){
+ if (object[key](this[i])){
+ result[key] = this[i];
+ delete object[key];
+ break;
+ }
+ }
+ }
+ return result;
+ },
+
+ contains: function(item, from){
+ return this.indexOf(item, from) != -1;
+ },
+
+ extend: function(array){
+ for (var i = 0, j = array.length; i < j; i++) this.push(array[i]);
+ return this;
+ },
+
+ getLast: function(){
+ return (this.length) ? this[this.length - 1] : null;
+ },
+
+ getRandom: function(){
+ return (this.length) ? this[$random(0, this.length - 1)] : null;
+ },
+
+ include: function(item){
+ if (!this.contains(item)) this.push(item);
+ return this;
+ },
+
+ combine: function(array){
+ for (var i = 0, l = array.length; i < l; i++) this.include(array[i]);
+ return this;
+ },
+
+ erase: function(item){
+ for (var i = this.length; i--; i){
+ if (this[i] === item) this.splice(i, 1);
+ }
+ return this;
+ },
+
+ empty: function(){
+ this.length = 0;
+ return this;
+ },
+
+ flatten: function(){
+ var array = [];
+ for (var i = 0, l = this.length; i < l; i++){
+ var type = $type(this[i]);
+ if (!type) continue;
+ array = array.concat((type == 'array' || type == 'collection' || type == 'arguments') ? Array.flatten(this[i]) : this[i]);
+ }
+ return array;
+ },
+
+ hexToRgb: function(array){
+ if (this.length != 3) return null;
+ var rgb = this.map(function(value){
+ if (value.length == 1) value += value;
+ return value.toInt(16);
+ });
+ return (array) ? rgb : 'rgb(' + rgb + ')';
+ },
+
+ rgbToHex: function(array){
+ if (this.length < 3) return null;
+ if (this.length == 4 && this[3] == 0 && !array) return 'transparent';
+ var hex = [];
+ for (var i = 0; i < 3; i++){
+ var bit = (this[i] - 0).toString(16);
+ hex.push((bit.length == 1) ? '0' + bit : bit);
+ }
+ return (array) ? hex : '#' + hex.join('');
+ }
+
+});
+
+/*
+Script: Function.js
+ Contains Function Prototypes like create, bind, pass, and delay.
+
+License:
+ MIT-style license.
+*/
+
+Function.implement({
+
+ extend: function(properties){
+ for (var property in properties) this[property] = properties[property];
+ return this;
+ },
+
+ create: function(options){
+ var self = this;
+ options = options || {};
+ return function(event){
+ var args = options.arguments;
+ args = (args != undefined) ? $splat(args) : Array.slice(arguments, (options.event) ? 1 : 0);
+ if (options.event) args = [event || window.event].extend(args);
+ var returns = function(){
+ return self.apply(options.bind || null, args);
+ };
+ if (options.delay) return setTimeout(returns, options.delay);
+ if (options.periodical) return setInterval(returns, options.periodical);
+ if (options.attempt) return $try(returns);
+ return returns();
+ };
+ },
+
+ pass: function(args, bind){
+ return this.create({arguments: args, bind: bind});
+ },
+
+ attempt: function(args, bind){
+ return this.create({arguments: args, bind: bind, attempt: true})();
+ },
+
+ bind: function(bind, args){
+ return this.create({bind: bind, arguments: args});
+ },
+
+ bindWithEvent: function(bind, args){
+ return this.create({bind: bind, event: true, arguments: args});
+ },
+
+ delay: function(delay, bind, args){
+ return this.create({delay: delay, bind: bind, arguments: args})();
+ },
+
+ periodical: function(interval, bind, args){
+ return this.create({periodical: interval, bind: bind, arguments: args})();
+ },
+
+ run: function(args, bind){
+ return this.apply(bind, $splat(args));
+ }
+
+});
+
+/*
+Script: Number.js
+ Contains Number Prototypes like limit, round, times, and ceil.
+
+License:
+ MIT-style license.
+*/
+
+Number.implement({
+
+ limit: function(min, max){
+ return Math.min(max, Math.max(min, this));
+ },
+
+ round: function(precision){
+ precision = Math.pow(10, precision || 0);
+ return Math.round(this * precision) / precision;
+ },
+
+ times: function(fn, bind){
+ for (var i = 0; i < this; i++) fn.call(bind, i, this);
+ },
+
+ toFloat: function(){
+ return parseFloat(this);
+ },
+
+ toInt: function(base){
+ return parseInt(this, base || 10);
+ }
+
+});
+
+Number.alias('times', 'each');
+
+(function(math){
+ var methods = {};
+ math.each(function(name){
+ if (!Number[name]) methods[name] = function(){
+ return Math[name].apply(null, [this].concat($A(arguments)));
+ };
+ });
+ Number.implement(methods);
+})(['abs', 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'exp', 'floor', 'log', 'max', 'min', 'pow', 'sin', 'sqrt', 'tan']);
+
+/*
+Script: String.js
+ Contains String Prototypes like camelCase, capitalize, test, and toInt.
+
+License:
+ MIT-style license.
+*/
+
+String.implement({
+
+ test: function(regex, params){
+ return ((typeof regex == 'string') ? new RegExp(regex, params) : regex).test(this);
+ },
+
+ contains: function(string, separator){
+ return (separator) ? (separator + this + separator).indexOf(separator + string + separator) > -1 : this.indexOf(string) > -1;
+ },
+
+ trim: function(){
+ return this.replace(/^\s+|\s+$/g, '');
+ },
+
+ clean: function(){
+ return this.replace(/\s+/g, ' ').trim();
+ },
+
+ camelCase: function(){
+ return this.replace(/-\D/g, function(match){
+ return match.charAt(1).toUpperCase();
+ });
+ },
+
+ hyphenate: function(){
+ return this.replace(/[A-Z]/g, function(match){
+ return ('-' + match.charAt(0).toLowerCase());
+ });
+ },
+
+ capitalize: function(){
+ return this.replace(/\b[a-z]/g, function(match){
+ return match.toUpperCase();
+ });
+ },
+
+ escapeRegExp: function(){
+ return this.replace(/([-.*+?^${}()|[\]\/\\])/g, '\\$1');
+ },
+
+ toInt: function(base){
+ return parseInt(this, base || 10);
+ },
+
+ toFloat: function(){
+ return parseFloat(this);
+ },
+
+ hexToRgb: function(array){
+ var hex = this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
+ return (hex) ? hex.slice(1).hexToRgb(array) : null;
+ },
+
+ rgbToHex: function(array){
+ var rgb = this.match(/\d{1,3}/g);
+ return (rgb) ? rgb.rgbToHex(array) : null;
+ },
+
+ stripScripts: function(option){
+ var scripts = '';
+ var text = this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi, function(){
+ scripts += arguments[1] + '\n';
+ return '';
+ });
+ if (option === true) $exec(scripts);
+ else if ($type(option) == 'function') option(scripts, text);
+ return text;
+ },
+
+ substitute: function(object, regexp){
+ return this.replace(regexp || (/\\?\{([^}]+)\}/g), function(match, name){
+ if (match.charAt(0) == '\\') return match.slice(1);
+ return (object[name] != undefined) ? object[name] : '';
+ });
+ }
+
+});
+
+/*
+Script: Hash.js
+ Contains Hash Prototypes. Provides a means for overcoming the JavaScript practical impossibility of extending native Objects.
+
+License:
+ MIT-style license.
+*/
+
+Hash.implement({
+
+ has: Object.prototype.hasOwnProperty,
+
+ keyOf: function(value){
+ for (var key in this){
+ if (this.hasOwnProperty(key) && this[key] === value) return key;
+ }
+ return null;
+ },
+
+ hasValue: function(value){
+ return (Hash.keyOf(this, value) !== null);
+ },
+
+ extend: function(properties){
+ Hash.each(properties, function(value, key){
+ Hash.set(this, key, value);
+ }, this);
+ return this;
+ },
+
+ combine: function(properties){
+ Hash.each(properties, function(value, key){
+ Hash.include(this, key, value);
+ }, this);
+ return this;
+ },
+
+ erase: function(key){
+ if (this.hasOwnProperty(key)) delete this[key];
+ return this;
+ },
+
+ get: function(key){
+ return (this.hasOwnProperty(key)) ? this[key] : null;
+ },
+
+ set: function(key, value){
+ if (!this[key] || this.hasOwnProperty(key)) this[key] = value;
+ return this;
+ },
+
+ empty: function(){
+ Hash.each(this, function(value, key){
+ delete this[key];
+ }, this);
+ return this;
+ },
+
+ include: function(key, value){
+ var k = this[key];
+ if (k == undefined) this[key] = value;
+ return this;
+ },
+
+ map: function(fn, bind){
+ var results = new Hash;
+ Hash.each(this, function(value, key){
+ results.set(key, fn.call(bind, value, key, this));
+ }, this);
+ return results;
+ },
+
+ filter: function(fn, bind){
+ var results = new Hash;
+ Hash.each(this, function(value, key){
+ if (fn.call(bind, value, key, this)) results.set(key, value);
+ }, this);
+ return results;
+ },
+
+ every: function(fn, bind){
+ for (var key in this){
+ if (this.hasOwnProperty(key) && !fn.call(bind, this[key], key)) return false;
+ }
+ return true;
+ },
+
+ some: function(fn, bind){
+ for (var key in this){
+ if (this.hasOwnProperty(key) && fn.call(bind, this[key], key)) return true;
+ }
+ return false;
+ },
+
+ getKeys: function(){
+ var keys = [];
+ Hash.each(this, function(value, key){
+ keys.push(key);
+ });
+ return keys;
+ },
+
+ getValues: function(){
+ var values = [];
+ Hash.each(this, function(value){
+ values.push(value);
+ });
+ return values;
+ },
+
+ toQueryString: function(base){
+ var queryString = [];
+ Hash.each(this, function(value, key){
+ if (base) key = base + '[' + key + ']';
+ var result;
+ switch ($type(value)){
+ case 'object': result = Hash.toQueryString(value, key); break;
+ case 'array':
+ var qs = {};
+ value.each(function(val, i){
+ qs[i] = val;
+ });
+ result = Hash.toQueryString(qs, key);
+ break;
+ default: result = key + '=' + encodeURIComponent(value);
+ }
+ if (value != undefined) queryString.push(result);
+ });
+
+ return queryString.join('&');
+ }
+
+});
+
+Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
+
+/*
+Script: Event.js
+ Contains the Event Native, to make the event object completely crossbrowser.
+
+License:
+ MIT-style license.
+*/
+
+var Event = new Native({
+
+ name: 'Event',
+
+ initialize: function(event, win){
+ win = win || window;
+ var doc = win.document;
+ event = event || win.event;
+ if (event.$extended) return event;
+ this.$extended = true;
+ var type = event.type;
+ var target = event.target || event.srcElement;
+ while (target && target.nodeType == 3) target = target.parentNode;
+
+ if (type.test(/key/)){
+ var code = event.which || event.keyCode;
+ var key = Event.Keys.keyOf(code);
+ if (type == 'keydown'){
+ var fKey = code - 111;
+ if (fKey > 0 && fKey < 13) key = 'f' + fKey;
+ }
+ key = key || String.fromCharCode(code).toLowerCase();
+ } else if (type.match(/(click|mouse|menu)/i)){
+ doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
+ var page = {
+ x: event.pageX || event.clientX + doc.scrollLeft,
+ y: event.pageY || event.clientY + doc.scrollTop
+ };
+ var client = {
+ x: (event.pageX) ? event.pageX - win.pageXOffset : event.clientX,
+ y: (event.pageY) ? event.pageY - win.pageYOffset : event.clientY
+ };
+ if (type.match(/DOMMouseScroll|mousewheel/)){
+ var wheel = (event.wheelDelta) ? event.wheelDelta / 120 : -(event.detail || 0) / 3;
+ }
+ var rightClick = (event.which == 3) || (event.button == 2);
+ var related = null;
+ if (type.match(/over|out/)){
+ switch (type){
+ case 'mouseover': related = event.relatedTarget || event.fromElement; break;
+ case 'mouseout': related = event.relatedTarget || event.toElement;
+ }
+ if (!(function(){
+ while (related && related.nodeType == 3) related = related.parentNode;
+ return true;
+ }).create({attempt: Browser.Engine.gecko})()) related = false;
+ }
+ }
+
+ return $extend(this, {
+ event: event,
+ type: type,
+
+ page: page,
+ client: client,
+ rightClick: rightClick,
+
+ wheel: wheel,
+
+ relatedTarget: related,
+ target: target,
+
+ code: code,
+ key: key,
+
+ shift: event.shiftKey,
+ control: event.ctrlKey,
+ alt: event.altKey,
+ meta: event.metaKey
+ });
+ }
+
+});
+
+Event.Keys = new Hash({
+ 'enter': 13,
+ 'up': 38,
+ 'down': 40,
+ 'left': 37,
+ 'right': 39,
+ 'esc': 27,
+ 'space': 32,
+ 'backspace': 8,
+ 'tab': 9,
+ 'delete': 46
+});
+
+Event.implement({
+
+ stop: function(){
+ return this.stopPropagation().preventDefault();
+ },
+
+ stopPropagation: function(){
+ if (this.event.stopPropagation) this.event.stopPropagation();
+ else this.event.cancelBubble = true;
+ return this;
+ },
+
+ preventDefault: function(){
+ if (this.event.preventDefault) this.event.preventDefault();
+ else this.event.returnValue = false;
+ return this;
+ }
+
+});
+
+/*
+Script: Class.js
+ Contains the Class Function for easily creating, extending, and implementing reusable Classes.
+
+License:
+ MIT-style license.
+*/
+
+var Class = new Native({
+
+ name: 'Class',
+
+ initialize: function(properties){
+ properties = properties || {};
+ var klass = function(empty){
+ for (var key in this) this[key] = $unlink(this[key]);
+ for (var mutator in Class.Mutators){
+ if (!this[mutator]) continue;
+ Class.Mutators[mutator](this, this[mutator]);
+ delete this[mutator];
+ }
+
+ this.constructor = klass;
+ if (empty === $empty) return this;
+
+ var self = (this.initialize) ? this.initialize.apply(this, arguments) : this;
+ if (this.options && this.options.initialize) this.options.initialize.call(this);
+ return self;
+ };
+
+ $extend(klass, this);
+ klass.constructor = Class;
+ klass.prototype = properties;
+ return klass;
+ }
+
+});
+
+Class.implement({
+
+ implement: function(){
+ Class.Mutators.Implements(this.prototype, Array.slice(arguments));
+ return this;
+ }
+
+});
+
+Class.Mutators = {
+
+ Implements: function(self, klasses){
+ $splat(klasses).each(function(klass){
+ $extend(self, ($type(klass) == 'class') ? new klass($empty) : klass);
+ });
+ },
+
+ Extends: function(self, klass){
+ var instance = new klass($empty);
+ delete instance.parent;
+ delete instance.parentOf;
+
+ for (var key in instance){
+ var current = self[key], previous = instance[key];
+ if (current == undefined){
+ self[key] = previous;
+ continue;
+ }
+
+ var ctype = $type(current), ptype = $type(previous);
+ if (ctype != ptype) continue;
+
+ switch (ctype){
+ case 'function':
+ // this code will be only executed if the current browser does not support function.caller (currently only opera).
+ // we replace the function code with brute force. Not pretty, but it will only be executed if function.caller is not supported.
+
+ if (!arguments.callee.caller) self[key] = eval('(' + String(current).replace(/\bthis\.parent\(\s*(\))?/g, function(full, close){
+ return 'arguments.callee._parent_.call(this' + (close || ', ');
+ }) + ')');
+
+ // end "opera" code
+ self[key]._parent_ = previous;
+ break;
+ case 'object': self[key] = $merge(previous, current);
+ }
+
+ }
+
+ self.parent = function(){
+ return arguments.callee.caller._parent_.apply(this, arguments);
+ };
+
+ self.parentOf = function(descendant){
+ return descendant._parent_.apply(this, Array.slice(arguments, 1));
+ };
+ }
+
+};
+
+
+/*
+Script: Class.Extras.js
+ Contains Utility Classes that can be implemented into your own Classes to ease the execution of many common tasks.
+
+License:
+ MIT-style license.
+*/
+
+var Chain = new Class({
+
+ chain: function(){
+ this.$chain = (this.$chain || []).extend(arguments);
+ return this;
+ },
+
+ callChain: function(){
+ return (this.$chain && this.$chain.length) ? this.$chain.shift().apply(this, arguments) : false;
+ },
+
+ clearChain: function(){
+ if (this.$chain) this.$chain.empty();
+ return this;
+ }
+
+});
+
+var Events = new Class({
+
+ addEvent: function(type, fn, internal){
+ type = Events.removeOn(type);
+ if (fn != $empty){
+ this.$events = this.$events || {};
+ this.$events[type] = this.$events[type] || [];
+ this.$events[type].include(fn);
+ if (internal) fn.internal = true;
+ }
+ return this;
+ },
+
+ addEvents: function(events){
+ for (var type in events) this.addEvent(type, events[type]);
+ return this;
+ },
+
+ fireEvent: function(type, args, delay){
+ type = Events.removeOn(type);
+ if (!this.$events || !this.$events[type]) return this;
+ this.$events[type].each(function(fn){
+ fn.create({'bind': this, 'delay': delay, 'arguments': args})();
+ }, this);
+ return this;
+ },
+
+ removeEvent: function(type, fn){
+ type = Events.removeOn(type);
+ if (!this.$events || !this.$events[type]) return this;
+ if (!fn.internal) this.$events[type].erase(fn);
+ return this;
+ },
+
+ removeEvents: function(type){
+ for (var e in this.$events){
+ if (type && type != e) continue;
+ var fns = this.$events[e];
+ for (var i = fns.length; i--; i) this.removeEvent(e, fns[i]);
+ }
+ return this;
+ }
+
+});
+
+Events.removeOn = function(string){
+ return string.replace(/^on([A-Z])/, function(full, first) {
+ return first.toLowerCase();
+ });
+};
+
+var Options = new Class({
+
+ setOptions: function(){
+ this.options = $merge.run([this.options].extend(arguments));
+ if (!this.addEvent) return this;
+ for (var option in this.options){
+ if ($type(this.options[option]) != 'function' || !(/^on[A-Z]/).test(option)) continue;
+ this.addEvent(option, this.options[option]);
+ delete this.options[option];
+ }
+ return this;
+ }
+
+});
+
+/*
+Script: Element.js
+ One of the most important items in MooTools. Contains the dollar function, the dollars function, and an handful of cross-browser,
+ time-saver methods to let you easily work with HTML Elements.
+
+License:
+ MIT-style license.
+*/
+
+Document.implement({
+
+ newElement: function(tag, props){
+ if (Browser.Engine.trident && props){
+ ['name', 'type', 'checked'].each(function(attribute){
+ if (!props[attribute]) return;
+ tag += ' ' + attribute + '="' + props[attribute] + '"';
+ if (attribute != 'checked') delete props[attribute];
+ });
+ tag = '<' + tag + '>';
+ }
+ return $.element(this.createElement(tag)).set(props);
+ },
+
+ newTextNode: function(text){
+ return this.createTextNode(text);
+ },
+
+ getDocument: function(){
+ return this;
+ },
+
+ getWindow: function(){
+ return this.defaultView || this.parentWindow;
+ },
+
+ purge: function(){
+ var elements = this.getElementsByTagName('*');
+ for (var i = 0, l = elements.length; i < l; i++) Browser.freeMem(elements[i]);
+ }
+
+});
+
+var Element = new Native({
+
+ name: 'Element',
+
+ legacy: window.Element,
+
+ initialize: function(tag, props){
+ var konstructor = Element.Constructors.get(tag);
+ if (konstructor) return konstructor(props);
+ if (typeof tag == 'string') return document.newElement(tag, props);
+ return $(tag).set(props);
+ },
+
+ afterImplement: function(key, value){
+ if (!Array[key]) Elements.implement(key, Elements.multi(key));
+ Element.Prototype[key] = value;
+ }
+
+});
+
+Element.Prototype = {$family: {name: 'element'}};
+
+Element.Constructors = new Hash;
+
+var IFrame = new Native({
+
+ name: 'IFrame',
+
+ generics: false,
+
+ initialize: function(){
+ var params = Array.link(arguments, {properties: Object.type, iframe: $defined});
+ var props = params.properties || {};
+ var iframe = $(params.iframe) || false;
+ var onload = props.onload || $empty;
+ delete props.onload;
+ props.id = props.name = $pick(props.id, props.name, iframe.id, iframe.name, 'IFrame_' + $time());
+ iframe = new Element(iframe || 'iframe', props);
+ var onFrameLoad = function(){
+ var host = $try(function(){
+ return iframe.contentWindow.location.host;
+ });
+ if (host && host == window.location.host){
+ var win = new Window(iframe.contentWindow);
+ var doc = new Document(iframe.contentWindow.document);
+ $extend(win.Element.prototype, Element.Prototype);
+ }
+ onload.call(iframe.contentWindow, iframe.contentWindow.document);
+ };
+ (!window.frames[props.id]) ? iframe.addListener('load', onFrameLoad) : onFrameLoad();
+ return iframe;
+ }
+
+});
+
+var Elements = new Native({
+
+ initialize: function(elements, options){
+ options = $extend({ddup: true, cash: true}, options);
+ elements = elements || [];
+ if (options.ddup || options.cash){
+ var uniques = {}, returned = [];
+ for (var i = 0, l = elements.length; i < l; i++){
+ var el = $.element(elements[i], !options.cash);
+ if (options.ddup){
+ if (uniques[el.uid]) continue;
+ uniques[el.uid] = true;
+ }
+ returned.push(el);
+ }
+ elements = returned;
+ }
+ return (options.cash) ? $extend(elements, this) : elements;
+ }
+
+});
+
+Elements.implement({
+
+ filter: function(filter, bind){
+ if (!filter) return this;
+ return new Elements(Array.filter(this, (typeof filter == 'string') ? function(item){
+ return item.match(filter);
+ } : filter, bind));
+ }
+
+});
+
+Elements.multi = function(property){
+ return function(){
+ var items = [];
+ var elements = true;
+ for (var i = 0, j = this.length; i < j; i++){
+ var returns = this[i][property].apply(this[i], arguments);
+ items.push(returns);
+ if (elements) elements = ($type(returns) == 'element');
+ }
+ return (elements) ? new Elements(items) : items;
+ };
+};
+
+Window.implement({
+
+ $: function(el, nocash){
+ if (el && el.$family && el.uid) return el;
+ var type = $type(el);
+ return ($[type]) ? $[type](el, nocash, this.document) : null;
+ },
+
+ $$: function(selector){
+ if (arguments.length == 1 && typeof selector == 'string') return this.document.getElements(selector);
+ var elements = [];
+ var args = Array.flatten(arguments);
+ for (var i = 0, l = args.length; i < l; i++){
+ var item = args[i];
+ switch ($type(item)){
+ case 'element': item = [item]; break;
+ case 'string': item = this.document.getElements(item, true); break;
+ default: item = false;
+ }
+ if (item) elements.extend(item);
+ }
+ return new Elements(elements);
+ },
+
+ getDocument: function(){
+ return this.document;
+ },
+
+ getWindow: function(){
+ return this;
+ }
+
+});
+
+$.string = function(id, nocash, doc){
+ id = doc.getElementById(id);
+ return (id) ? $.element(id, nocash) : null;
+};
+
+$.element = function(el, nocash){
+ $uid(el);
+ if (!nocash && !el.$family && !(/^object|embed$/i).test(el.tagName)){
+ var proto = Element.Prototype;
+ for (var p in proto) el[p] = proto[p];
+ };
+ return el;
+};
+
+$.object = function(obj, nocash, doc){
+ if (obj.toElement) return $.element(obj.toElement(doc), nocash);
+ return null;
+};
+
+$.textnode = $.whitespace = $.window = $.document = $arguments(0);
+
+Native.implement([Element, Document], {
+
+ getElement: function(selector, nocash){
+ return $(this.getElements(selector, true)[0] || null, nocash);
+ },
+
+ getElements: function(tags, nocash){
+ tags = tags.split(',');
+ var elements = [];
+ var ddup = (tags.length > 1);
+ tags.each(function(tag){
+ var partial = this.getElementsByTagName(tag.trim());
+ (ddup) ? elements.extend(partial) : elements = partial;
+ }, this);
+ return new Elements(elements, {ddup: ddup, cash: !nocash});
+ }
+
+});
+
+Element.Storage = {
+
+ get: function(uid){
+ return (this[uid] || (this[uid] = {}));
+ }
+
+};
+
+Element.Inserters = new Hash({
+
+ before: function(context, element){
+ if (element.parentNode) element.parentNode.insertBefore(context, element);
+ },
+
+ after: function(context, element){
+ if (!element.parentNode) return;
+ var next = element.nextSibling;
+ (next) ? element.parentNode.insertBefore(context, next) : element.parentNode.appendChild(context);
+ },
+
+ bottom: function(context, element){
+ element.appendChild(context);
+ },
+
+ top: function(context, element){
+ var first = element.firstChild;
+ (first) ? element.insertBefore(context, first) : element.appendChild(context);
+ }
+
+});
+
+Element.Inserters.inside = Element.Inserters.bottom;
+
+Element.Inserters.each(function(value, key){
+
+ var Key = key.capitalize();
+
+ Element.implement('inject' + Key, function(el){
+ value(this, $(el, true));
+ return this;
+ });
+
+ Element.implement('grab' + Key, function(el){
+ value($(el, true), this);
+ return this;
+ });
+
+});
+
+Element.implement({
+
+ getDocument: function(){
+ return this.ownerDocument;
+ },
+
+ getWindow: function(){
+ return this.ownerDocument.getWindow();
+ },
+
+ getElementById: function(id, nocash){
+ var el = this.ownerDocument.getElementById(id);
+ if (!el) return null;
+ for (var parent = el.parentNode; parent != this; parent = parent.parentNode){
+ if (!parent) return null;
+ }
+ return $.element(el, nocash);
+ },
+
+ set: function(prop, value){
+ switch ($type(prop)){
+ case 'object':
+ for (var p in prop) this.set(p, prop[p]);
+ break;
+ case 'string':
+ var property = Element.Properties.get(prop);
+ (property && property.set) ? property.set.apply(this, Array.slice(arguments, 1)) : this.setProperty(prop, value);
+ }
+ return this;
+ },
+
+ get: function(prop){
+ var property = Element.Properties.get(prop);
+ return (property && property.get) ? property.get.apply(this, Array.slice(arguments, 1)) : this.getProperty(prop);
+ },
+
+ erase: function(prop){
+ var property = Element.Properties.get(prop);
+ (property && property.erase) ? property.erase.apply(this, Array.slice(arguments, 1)) : this.removeProperty(prop);
+ return this;
+ },
+
+ match: function(tag){
+ return (!tag || Element.get(this, 'tag') == tag);
+ },
+
+ inject: function(el, where){
+ Element.Inserters.get(where || 'bottom')(this, $(el, true));
+ return this;
+ },
+
+ wraps: function(el, where){
+ el = $(el, true);
+ return this.replaces(el).grab(el, where);
+ },
+
+ grab: function(el, where){
+ Element.Inserters.get(where || 'bottom')($(el, true), this);
+ return this;
+ },
+
+ appendText: function(text, where){
+ return this.grab(this.getDocument().newTextNode(text), where);
+ },
+
+ adopt: function(){
+ Array.flatten(arguments).each(function(element){
+ element = $(element, true);
+ if (element) this.appendChild(element);
+ }, this);
+ return this;
+ },
+
+ dispose: function(){
+ return (this.parentNode) ? this.parentNode.removeChild(this) : this;
+ },
+
+ clone: function(contents, keepid){
+ switch ($type(this)){
+ case 'element':
+ var attributes = {};
+ for (var j = 0, l = this.attributes.length; j < l; j++){
+ var attribute = this.attributes[j], key = attribute.nodeName.toLowerCase();
+ if (Browser.Engine.trident && (/input/i).test(this.tagName) && (/width|height/).test(key)) continue;
+ var value = (key == 'style' && this.style) ? this.style.cssText : attribute.nodeValue;
+ if (!$chk(value) || key == 'uid' || (key == 'id' && !keepid)) continue;
+ if (value != 'inherit' && ['string', 'number'].contains($type(value))) attributes[key] = value;
+ }
+ var element = new Element(this.nodeName.toLowerCase(), attributes);
+ if (contents !== false){
+ for (var i = 0, k = this.childNodes.length; i < k; i++){
+ var child = Element.clone(this.childNodes[i], true, keepid);
+ if (child) element.grab(child);
+ }
+ }
+ return element;
+ case 'textnode': return document.newTextNode(this.nodeValue);
+ }
+ return null;
+ },
+
+ replaces: function(el){
+ el = $(el, true);
+ el.parentNode.replaceChild(this, el);
+ return this;
+ },
+
+ hasClass: function(className){
+ return this.className.contains(className, ' ');
+ },
+
+ addClass: function(className){
+ if (!this.hasClass(className)) this.className = (this.className + ' ' + className).clean();
+ return this;
+ },
+
+ removeClass: function(className){
+ this.className = this.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1').clean();
+ return this;
+ },
+
+ toggleClass: function(className){
+ return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
+ },
+
+ getComputedStyle: function(property){
+ if (this.currentStyle) return this.currentStyle[property.camelCase()];
+ var computed = this.getWindow().getComputedStyle(this, null);
+ return (computed) ? computed.getPropertyValue([property.hyphenate()]) : null;
+ },
+
+ empty: function(){
+ $A(this.childNodes).each(function(node){
+ Browser.freeMem(node);
+ Element.empty(node);
+ Element.dispose(node);
+ }, this);
+ return this;
+ },
+
+ destroy: function(){
+ Browser.freeMem(this.empty().dispose());
+ return null;
+ },
+
+ getSelected: function(){
+ return new Elements($A(this.options).filter(function(option){
+ return option.selected;
+ }));
+ },
+
+ toQueryString: function(){
+ var queryString = [];
+ this.getElements('input, select, textarea').each(function(el){
+ if (!el.name || el.disabled) return;
+ var value = (el.tagName.toLowerCase() == 'select') ? Element.getSelected(el).map(function(opt){
+ return opt.value;
+ }) : ((el.type == 'radio' || el.type == 'checkbox') && !el.checked) ? null : el.value;
+ $splat(value).each(function(val){
+ if (val) queryString.push(el.name + '=' + encodeURIComponent(val));
+ });
+ });
+ return queryString.join('&');
+ },
+
+ getProperty: function(attribute){
+ var EA = Element.Attributes, key = EA.Props[attribute];
+ var value = (key) ? this[key] : this.getAttribute(attribute, 2);
+ return (EA.Bools[attribute]) ? !!value : (key) ? value : value || null;
+ },
+
+ getProperties: function(){
+ var args = $A(arguments);
+ return args.map(function(attr){
+ return this.getProperty(attr);
+ }, this).associate(args);
+ },
+
+ setProperty: function(attribute, value){
+ var EA = Element.Attributes, key = EA.Props[attribute], hasValue = $defined(value);
+ if (key && EA.Bools[attribute]) value = (value || !hasValue) ? true : false;
+ else if (!hasValue) return this.removeProperty(attribute);
+ (key) ? this[key] = value : this.setAttribute(attribute, value);
+ return this;
+ },
+
+ setProperties: function(attributes){
+ for (var attribute in attributes) this.setProperty(attribute, attributes[attribute]);
+ return this;
+ },
+
+ removeProperty: function(attribute){
+ var EA = Element.Attributes, key = EA.Props[attribute], isBool = (key && EA.Bools[attribute]);
+ (key) ? this[key] = (isBool) ? false : '' : this.removeAttribute(attribute);
+ return this;
+ },
+
+ removeProperties: function(){
+ Array.each(arguments, this.removeProperty, this);
+ return this;
+ }
+
+});
+
+(function(){
+
+var walk = function(element, walk, start, match, all, nocash){
+ var el = element[start || walk];
+ var elements = [];
+ while (el){
+ if (el.nodeType == 1 && (!match || Element.match(el, match))){
+ elements.push(el);
+ if (!all) break;
+ }
+ el = el[walk];
+ }
+ return (all) ? new Elements(elements, {ddup: false, cash: !nocash}) : $(elements[0], nocash);
+};
+
+Element.implement({
+
+ getPrevious: function(match, nocash){
+ return walk(this, 'previousSibling', null, match, false, nocash);
+ },
+
+ getAllPrevious: function(match, nocash){
+ return walk(this, 'previousSibling', null, match, true, nocash);
+ },
+
+ getNext: function(match, nocash){
+ return walk(this, 'nextSibling', null, match, false, nocash);
+ },
+
+ getAllNext: function(match, nocash){
+ return walk(this, 'nextSibling', null, match, true, nocash);
+ },
+
+ getFirst: function(match, nocash){
+ return walk(this, 'nextSibling', 'firstChild', match, false, nocash);
+ },
+
+ getLast: function(match, nocash){
+ return walk(this, 'previousSibling', 'lastChild', match, false, nocash);
+ },
+
+ getParent: function(match, nocash){
+ return walk(this, 'parentNode', null, match, false, nocash);
+ },
+
+ getParents: function(match, nocash){
+ return walk(this, 'parentNode', null, match, true, nocash);
+ },
+
+ getChildren: function(match, nocash){
+ return walk(this, 'nextSibling', 'firstChild', match, true, nocash);
+ },
+
+ hasChild: function(el){
+ el = $(el, true);
+ return (!!el && $A(this.getElementsByTagName(el.tagName)).contains(el));
+ }
+
+});
+
+})();
+
+Element.Properties = new Hash;
+
+Element.Properties.style = {
+
+ set: function(style){
+ this.style.cssText = style;
+ },
+
+ get: function(){
+ return this.style.cssText;
+ },
+
+ erase: function(){
+ this.style.cssText = '';
+ }
+
+};
+
+Element.Properties.tag = {get: function(){
+ return this.tagName.toLowerCase();
+}};
+
+Element.Properties.href = {get: function(){
+ return (!this.href) ? null : this.href.replace(new RegExp('^' + document.location.protocol + '\/\/' + document.location.host), '');
+}};
+
+Element.Properties.html = {set: function(){
+ return this.innerHTML = Array.flatten(arguments).join('');
+}};
+
+Native.implement([Element, Window, Document], {
+
+ addListener: function(type, fn){
+ if (this.addEventListener) this.addEventListener(type, fn, false);
+ else this.attachEvent('on' + type, fn);
+ return this;
+ },
+
+ removeListener: function(type, fn){
+ if (this.removeEventListener) this.removeEventListener(type, fn, false);
+ else this.detachEvent('on' + type, fn);
+ return this;
+ },
+
+ retrieve: function(property, dflt){
+ var storage = Element.Storage.get(this.uid);
+ var prop = storage[property];
+ if ($defined(dflt) && !$defined(prop)) prop = storage[property] = dflt;
+ return $pick(prop);
+ },
+
+ store: function(property, value){
+ var storage = Element.Storage.get(this.uid);
+ storage[property] = value;
+ return this;
+ },
+
+ eliminate: function(property){
+ var storage = Element.Storage.get(this.uid);
+ delete storage[property];
+ return this;
+ }
+
+});
+
+Element.Attributes = new Hash({
+ Props: {'html': 'innerHTML', 'class': 'className', 'for': 'htmlFor', 'text': (Browser.Engine.trident) ? 'innerText' : 'textContent'},
+ Bools: ['compact', 'nowrap', 'ismap', 'declare', 'noshade', 'checked', 'disabled', 'readonly', 'multiple', 'selected', 'noresize', 'defer'],
+ Camels: ['value', 'accessKey', 'cellPadding', 'cellSpacing', 'colSpan', 'frameBorder', 'maxLength', 'readOnly', 'rowSpan', 'tabIndex', 'useMap']
+});
+
+Browser.freeMem = function(item){
+ if (!item) return;
+ if (Browser.Engine.trident && (/object/i).test(item.tagName)){
+ for (var p in item){
+ if (typeof item[p] == 'function') item[p] = $empty;
+ }
+ Element.dispose(item);
+ }
+ if (item.uid && item.removeEvents) item.removeEvents();
+};
+
+(function(EA){
+
+ var EAB = EA.Bools, EAC = EA.Camels;
+ EA.Bools = EAB = EAB.associate(EAB);
+ Hash.extend(Hash.combine(EA.Props, EAB), EAC.associate(EAC.map(function(v){
+ return v.toLowerCase();
+ })));
+ EA.erase('Camels');
+
+})(Element.Attributes);
+
+window.addListener('unload', function(){
+ window.removeListener('unload', arguments.callee);
+ document.purge();
+ if (Browser.Engine.trident) CollectGarbage();
+});
+
+/*
+Script: Element.Event.js
+ Contains Element methods for dealing with events, and custom Events.
+
+License:
+ MIT-style license.
+*/
+
+Element.Properties.events = {set: function(events){
+ this.addEvents(events);
+}};
+
+Native.implement([Element, Window, Document], {
+
+ addEvent: function(type, fn){
+ var events = this.retrieve('events', {});
+ events[type] = events[type] || {'keys': [], 'values': []};
+ if (events[type].keys.contains(fn)) return this;
+ events[type].keys.push(fn);
+ var realType = type, custom = Element.Events.get(type), condition = fn, self = this;
+ if (custom){
+ if (custom.onAdd) custom.onAdd.call(this, fn);
+ if (custom.condition){
+ condition = function(event){
+ if (custom.condition.call(this, event)) return fn.call(this, event);
+ return false;
+ };
+ }
+ realType = custom.base || realType;
+ }
+ var defn = function(){
+ return fn.call(self);
+ };
+ var nativeEvent = Element.NativeEvents[realType] || 0;
+ if (nativeEvent){
+ if (nativeEvent == 2){
+ defn = function(event){
+ event = new Event(event, self.getWindow());
+ if (condition.call(self, event) === false) event.stop();
+ };
+ }
+ this.addListener(realType, defn);
+ }
+ events[type].values.push(defn);
+ return this;
+ },
+
+ removeEvent: function(type, fn){
+ var events = this.retrieve('events');
+ if (!events || !events[type]) return this;
+ var pos = events[type].keys.indexOf(fn);
+ if (pos == -1) return this;
+ var key = events[type].keys.splice(pos, 1)[0];
+ var value = events[type].values.splice(pos, 1)[0];
+ var custom = Element.Events.get(type);
+ if (custom){
+ if (custom.onRemove) custom.onRemove.call(this, fn);
+ type = custom.base || type;
+ }
+ return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this;
+ },
+
+ addEvents: function(events){
+ for (var event in events) this.addEvent(event, events[event]);
+ return this;
+ },
+
+ removeEvents: function(type){
+ var events = this.retrieve('events');
+ if (!events) return this;
+ if (!type){
+ for (var evType in events) this.removeEvents(evType);
+ events = null;
+ } else if (events[type]){
+ while (events[type].keys[0]) this.removeEvent(type, events[type].keys[0]);
+ events[type] = null;
+ }
+ return this;
+ },
+
+ fireEvent: function(type, args, delay){
+ var events = this.retrieve('events');
+ if (!events || !events[type]) return this;
+ events[type].keys.each(function(fn){
+ fn.create({'bind': this, 'delay': delay, 'arguments': args})();
+ }, this);
+ return this;
+ },
+
+ cloneEvents: function(from, type){
+ from = $(from);
+ var fevents = from.retrieve('events');
+ if (!fevents) return this;
+ if (!type){
+ for (var evType in fevents) this.cloneEvents(from, evType);
+ } else if (fevents[type]){
+ fevents[type].keys.each(function(fn){
+ this.addEvent(type, fn);
+ }, this);
+ }
+ return this;
+ }
+
+});
+
+Element.NativeEvents = {
+ click: 2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2, //mouse buttons
+ mousewheel: 2, DOMMouseScroll: 2, //mouse wheel
+ mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2, //mouse movement
+ keydown: 2, keypress: 2, keyup: 2, //keyboard
+ focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2, //form elements
+ load: 1, unload: 1, beforeunload: 2, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1, //window
+ error: 1, abort: 1, scroll: 1 //misc
+};
+
+(function(){
+
+var $check = function(event){
+ var related = event.relatedTarget;
+ if (related == undefined) return true;
+ if (related === false) return false;
+ return ($type(this) != 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related));
+};
+
+Element.Events = new Hash({
+
+ mouseenter: {
+ base: 'mouseover',
+ condition: $check
+ },
+
+ mouseleave: {
+ base: 'mouseout',
+ condition: $check
+ },
+
+ mousewheel: {
+ base: (Browser.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel'
+ }
+
+});
+
+})();
+
+/*
+Script: Element.Style.js
+ Contains methods for interacting with the styles of Elements in a fashionable way.
+
+License:
+ MIT-style license.
+*/
+
+Element.Properties.styles = {set: function(styles){
+ this.setStyles(styles);
+}};
+
+Element.Properties.opacity = {
+
+ set: function(opacity, novisibility){
+ if (!novisibility){
+ if (opacity == 0){
+ if (this.style.visibility != 'hidden') this.style.visibility = 'hidden';
+ } else {
+ if (this.style.visibility != 'visible') this.style.visibility = 'visible';
+ }
+ }
+ if (!this.currentStyle || !this.currentStyle.hasLayout) this.style.zoom = 1;
+ if (Browser.Engine.trident) this.style.filter = (opacity == 1) ? '' : 'alpha(opacity=' + opacity * 100 + ')';
+ this.style.opacity = opacity;
+ this.store('opacity', opacity);
+ },
+
+ get: function(){
+ return this.retrieve('opacity', 1);
+ }
+
+};
+
+Element.implement({
+
+ setOpacity: function(value){
+ return this.set('opacity', value, true);
+ },
+
+ getOpacity: function(){
+ return this.get('opacity');
+ },
+
+ setStyle: function(property, value){
+ switch (property){
+ case 'opacity': return this.set('opacity', parseFloat(value));
+ case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
+ }
+ property = property.camelCase();
+ if ($type(value) != 'string'){
+ var map = (Element.Styles.get(property) || '@').split(' ');
+ value = $splat(value).map(function(val, i){
+ if (!map[i]) return '';
+ return ($type(val) == 'number') ? map[i].replace('@', Math.round(val)) : val;
+ }).join(' ');
+ } else if (value == String(Number(value))){
+ value = Math.round(value);
+ }
+ this.style[property] = value;
+ return this;
+ },
+
+ getStyle: function(property){
+ switch (property){
+ case 'opacity': return this.get('opacity');
+ case 'float': property = (Browser.Engine.trident) ? 'styleFloat' : 'cssFloat';
+ }
+ property = property.camelCase();
+ var result = this.style[property];
+ if (!$chk(result)){
+ result = [];
+ for (var style in Element.ShortStyles){
+ if (property != style) continue;
+ for (var s in Element.ShortStyles[style]) result.push(this.getStyle(s));
+ return result.join(' ');
+ }
+ result = this.getComputedStyle(property);
+ }
+ if (result){
+ result = String(result);
+ var color = result.match(/rgba?\([\d\s,]+\)/);
+ if (color) result = result.replace(color[0], color[0].rgbToHex());
+ }
+ if (Browser.Engine.presto || (Browser.Engine.trident && !$chk(parseInt(result)))){
+ if (property.test(/^(height|width)$/)){
+ var values = (property == 'width') ? ['left', 'right'] : ['top', 'bottom'], size = 0;
+ values.each(function(value){
+ size += this.getStyle('border-' + value + '-width').toInt() + this.getStyle('padding-' + value).toInt();
+ }, this);
+ return this['offset' + property.capitalize()] - size + 'px';
+ }
+ if (Browser.Engine.presto && String(result).test('px')) return result;
+ if (property.test(/(border(.+)Width|margin|padding)/)) return '0px';
+ }
+ return result;
+ },
+
+ setStyles: function(styles){
+ for (var style in styles) this.setStyle(style, styles[style]);
+ return this;
+ },
+
+ getStyles: function(){
+ var result = {};
+ Array.each(arguments, function(key){
+ result[key] = this.getStyle(key);
+ }, this);
+ return result;
+ }
+
+});
+
+Element.Styles = new Hash({
+ left: '@px', top: '@px', bottom: '@px', right: '@px',
+ width: '@px', height: '@px', maxWidth: '@px', maxHeight: '@px', minWidth: '@px', minHeight: '@px',
+ backgroundColor: 'rgb(@, @, @)', backgroundPosition: '@px @px', color: 'rgb(@, @, @)',
+ fontSize: '@px', letterSpacing: '@px', lineHeight: '@px', clip: 'rect(@px @px @px @px)',
+ margin: '@px @px @px @px', padding: '@px @px @px @px', border: '@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)',
+ borderWidth: '@px @px @px @px', borderStyle: '@ @ @ @', borderColor: 'rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)',
+ zIndex: '@', 'zoom': '@', fontWeight: '@', textIndent: '@px', opacity: '@'
+});
+
+Element.ShortStyles = {margin: {}, padding: {}, border: {}, borderWidth: {}, borderStyle: {}, borderColor: {}};
+
+['Top', 'Right', 'Bottom', 'Left'].each(function(direction){
+ var Short = Element.ShortStyles;
+ var All = Element.Styles;
+ ['margin', 'padding'].each(function(style){
+ var sd = style + direction;
+ Short[style][sd] = All[sd] = '@px';
+ });
+ var bd = 'border' + direction;
+ Short.border[bd] = All[bd] = '@px @ rgb(@, @, @)';
+ var bdw = bd + 'Width', bds = bd + 'Style', bdc = bd + 'Color';
+ Short[bd] = {};
+ Short.borderWidth[bdw] = Short[bd][bdw] = All[bdw] = '@px';
+ Short.borderStyle[bds] = Short[bd][bds] = All[bds] = '@';
+ Short.borderColor[bdc] = Short[bd][bdc] = All[bdc] = 'rgb(@, @, @)';
+});
+
+
+/*
+Script: Element.Dimensions.js
+ Contains methods to work with size, scroll, or positioning of Elements and the window object.
+
+License:
+ MIT-style license.
+
+Credits:
+ - Element positioning based on the [qooxdoo](http://qooxdoo.org/) code and smart browser fixes, [LGPL License](http://www.gnu.org/licenses/lgpl.html).
+ - Viewport dimensions based on [YUI](http://developer.yahoo.com/yui/) code, [BSD License](http://developer.yahoo.com/yui/license.html).
+*/
+
+(function(){
+
+Element.implement({
+
+ scrollTo: function(x, y){
+ if (isBody(this)){
+ this.getWindow().scrollTo(x, y);
+ } else {
+ this.scrollLeft = x;
+ this.scrollTop = y;
+ }
+ return this;
+ },
+
+ getSize: function(){
+ if (isBody(this)) return this.getWindow().getSize();
+ return {x: this.offsetWidth, y: this.offsetHeight};
+ },
+
+ getScrollSize: function(){
+ if (isBody(this)) return this.getWindow().getScrollSize();
+ return {x: this.scrollWidth, y: this.scrollHeight};
+ },
+
+ getScroll: function(){
+ if (isBody(this)) return this.getWindow().getScroll();
+ return {x: this.scrollLeft, y: this.scrollTop};
+ },
+
+ getScrolls: function(){
+ var element = this, position = {x: 0, y: 0};
+ while (element && !isBody(element)){
+ position.x += element.scrollLeft;
+ position.y += element.scrollTop;
+ element = element.parentNode;
+ }
+ return position;
+ },
+
+ getOffsetParent: function(){
+ var element = this;
+ if (isBody(element)) return null;
+ if (!Browser.Engine.trident) return element.offsetParent;
+ while ((element = element.parentNode) && !isBody(element)){
+ if (styleString(element, 'position') != 'static') return element;
+ }
+ return null;
+ },
+
+ getOffsets: function(){
+ var element = this, position = {x: 0, y: 0};
+ if (isBody(this)) return position;
+
+ while (element && !isBody(element)){
+ position.x += element.offsetLeft;
+ position.y += element.offsetTop;
+
+ if (Browser.Engine.gecko){
+ if (!borderBox(element)){
+ position.x += leftBorder(element);
+ position.y += topBorder(element);
+ }
+ var parent = element.parentNode;
+ if (parent && styleString(parent, 'overflow') != 'visible'){
+ position.x += leftBorder(parent);
+ position.y += topBorder(parent);
+ }
+ } else if (element != this && (Browser.Engine.trident || Browser.Engine.webkit)){
+ position.x += leftBorder(element);
+ position.y += topBorder(element);
+ }
+
+ element = element.offsetParent;
+ if (Browser.Engine.trident){
+ while (element && !element.currentStyle.hasLayout) element = element.offsetParent;
+ }
+ }
+ if (Browser.Engine.gecko && !borderBox(this)){
+ position.x -= leftBorder(this);
+ position.y -= topBorder(this);
+ }
+ return position;
+ },
+
+ getPosition: function(relative){
+ if (isBody(this)) return {x: 0, y: 0};
+ var offset = this.getOffsets(), scroll = this.getScrolls();
+ var position = {x: offset.x - scroll.x, y: offset.y - scroll.y};
+ var relativePosition = (relative && (relative = $(relative))) ? relative.getPosition() : {x: 0, y: 0};
+ return {x: position.x - relativePosition.x, y: position.y - relativePosition.y};
+ },
+
+ getCoordinates: function(element){
+ if (isBody(this)) return this.getWindow().getCoordinates();
+ var position = this.getPosition(element), size = this.getSize();
+ var obj = {left: position.x, top: position.y, width: size.x, height: size.y};
+ obj.right = obj.left + obj.width;
+ obj.bottom = obj.top + obj.height;
+ return obj;
+ },
+
+ computePosition: function(obj){
+ return {left: obj.x - styleNumber(this, 'margin-left'), top: obj.y - styleNumber(this, 'margin-top')};
+ },
+
+ position: function(obj){
+ return this.setStyles(this.computePosition(obj));
+ }
+
+});
+
+Native.implement([Document, Window], {
+
+ getSize: function(){
+ var win = this.getWindow();
+ if (Browser.Engine.presto || Browser.Engine.webkit) return {x: win.innerWidth, y: win.innerHeight};
+ var doc = getCompatElement(this);
+ return {x: doc.clientWidth, y: doc.clientHeight};
+ },
+
+ getScroll: function(){
+ var win = this.getWindow();
+ var doc = getCompatElement(this);
+ return {x: win.pageXOffset || doc.scrollLeft, y: win.pageYOffset || doc.scrollTop};
+ },
+
+ getScrollSize: function(){
+ var doc = getCompatElement(this);
+ var min = this.getSize();
+ return {x: Math.max(doc.scrollWidth, min.x), y: Math.max(doc.scrollHeight, min.y)};
+ },
+
+ getPosition: function(){
+ return {x: 0, y: 0};
+ },
+
+ getCoordinates: function(){
+ var size = this.getSize();
+ return {top: 0, left: 0, bottom: size.y, right: size.x, height: size.y, width: size.x};
+ }
+
+});
+
+// private methods
+
+var styleString = Element.getComputedStyle;
+
+function styleNumber(element, style){
+ return styleString(element, style).toInt() || 0;
+};
+
+function borderBox(element){
+ return styleString(element, '-moz-box-sizing') == 'border-box';
+};
+
+function topBorder(element){
+ return styleNumber(element, 'border-top-width');
+};
+
+function leftBorder(element){
+ return styleNumber(element, 'border-left-width');
+};
+
+function isBody(element){
+ return (/^(?:body|html)$/i).test(element.tagName);
+};
+
+function getCompatElement(element){
+ var doc = element.getDocument();
+ return (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.html : doc.body;
+};
+
+})();
+
+//aliases
+
+Native.implement([Window, Document, Element], {
+
+ getHeight: function(){
+ return this.getSize().y;
+ },
+
+ getWidth: function(){
+ return this.getSize().x;
+ },
+
+ getScrollTop: function(){
+ return this.getScroll().y;
+ },
+
+ getScrollLeft: function(){
+ return this.getScroll().x;
+ },
+
+ getScrollHeight: function(){
+ return this.getScrollSize().y;
+ },
+
+ getScrollWidth: function(){
+ return this.getScrollSize().x;
+ },
+
+ getTop: function(){
+ return this.getPosition().y;
+ },
+
+ getLeft: function(){
+ return this.getPosition().x;
+ }
+
+});
+
+/*
+Script: Selectors.js
+ Adds advanced CSS Querying capabilities for targeting elements. Also includes pseudoselectors support.
+
+License:
+ MIT-style license.
+*/
+
+Native.implement([Document, Element], {
+
+ getElements: function(expression, nocash){
+ expression = expression.split(',');
+ var items, local = {};
+ for (var i = 0, l = expression.length; i < l; i++){
+ var selector = expression[i], elements = Selectors.Utils.search(this, selector, local);
+ if (i != 0 && elements.item) elements = $A(elements);
+ items = (i == 0) ? elements : (items.item) ? $A(items).concat(elements) : items.concat(elements);
+ }
+ return new Elements(items, {ddup: (expression.length > 1), cash: !nocash});
+ }
+
+});
+
+Element.implement({
+
+ match: function(selector){
+ if (!selector) return true;
+ var tagid = Selectors.Utils.parseTagAndID(selector);
+ var tag = tagid[0], id = tagid[1];
+ if (!Selectors.Filters.byID(this, id) || !Selectors.Filters.byTag(this, tag)) return false;
+ var parsed = Selectors.Utils.parseSelector(selector);
+ return (parsed) ? Selectors.Utils.filter(this, parsed, {}) : true;
+ }
+
+});
+
+var Selectors = {Cache: {nth: {}, parsed: {}}};
+
+Selectors.RegExps = {
+ id: (/#([\w-]+)/),
+ tag: (/^(\w+|\*)/),
+ quick: (/^(\w+|\*)$/),
+ splitter: (/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),
+ combined: (/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)["']?(.*?)["']?)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)
+};
+
+Selectors.Utils = {
+
+ chk: function(item, uniques){
+ if (!uniques) return true;
+ var uid = $uid(item);
+ if (!uniques[uid]) return uniques[uid] = true;
+ return false;
+ },
+
+ parseNthArgument: function(argument){
+ if (Selectors.Cache.nth[argument]) return Selectors.Cache.nth[argument];
+ var parsed = argument.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);
+ if (!parsed) return false;
+ var inta = parseInt(parsed[1]);
+ var a = (inta || inta === 0) ? inta : 1;
+ var special = parsed[2] || false;
+ var b = parseInt(parsed[3]) || 0;
+ if (a != 0){
+ b--;
+ while (b < 1) b += a;
+ while (b >= a) b -= a;
+ } else {
+ a = b;
+ special = 'index';
+ }
+ switch (special){
+ case 'n': parsed = {a: a, b: b, special: 'n'}; break;
+ case 'odd': parsed = {a: 2, b: 0, special: 'n'}; break;
+ case 'even': parsed = {a: 2, b: 1, special: 'n'}; break;
+ case 'first': parsed = {a: 0, special: 'index'}; break;
+ case 'last': parsed = {special: 'last-child'}; break;
+ case 'only': parsed = {special: 'only-child'}; break;
+ default: parsed = {a: (a - 1), special: 'index'};
+ }
+
+ return Selectors.Cache.nth[argument] = parsed;
+ },
+
+ parseSelector: function(selector){
+ if (Selectors.Cache.parsed[selector]) return Selectors.Cache.parsed[selector];
+ var m, parsed = {classes: [], pseudos: [], attributes: []};
+ while ((m = Selectors.RegExps.combined.exec(selector))){
+ var cn = m[1], an = m[2], ao = m[3], av = m[4], pn = m[5], pa = m[6];
+ if (cn){
+ parsed.classes.push(cn);
+ } else if (pn){
+ var parser = Selectors.Pseudo.get(pn);
+ if (parser) parsed.pseudos.push({parser: parser, argument: pa});
+ else parsed.attributes.push({name: pn, operator: '=', value: pa});
+ } else if (an){
+ parsed.attributes.push({name: an, operator: ao, value: av});
+ }
+ }
+ if (!parsed.classes.length) delete parsed.classes;
+ if (!parsed.attributes.length) delete parsed.attributes;
+ if (!parsed.pseudos.length) delete parsed.pseudos;
+ if (!parsed.classes && !parsed.attributes && !parsed.pseudos) parsed = null;
+ return Selectors.Cache.parsed[selector] = parsed;
+ },
+
+ parseTagAndID: function(selector){
+ var tag = selector.match(Selectors.RegExps.tag);
+ var id = selector.match(Selectors.RegExps.id);
+ return [(tag) ? tag[1] : '*', (id) ? id[1] : false];
+ },
+
+ filter: function(item, parsed, local){
+ var i;
+ if (parsed.classes){
+ for (i = parsed.classes.length; i--; i){
+ var cn = parsed.classes[i];
+ if (!Selectors.Filters.byClass(item, cn)) return false;
+ }
+ }
+ if (parsed.attributes){
+ for (i = parsed.attributes.length; i--; i){
+ var att = parsed.attributes[i];
+ if (!Selectors.Filters.byAttribute(item, att.name, att.operator, att.value)) return false;
+ }
+ }
+ if (parsed.pseudos){
+ for (i = parsed.pseudos.length; i--; i){
+ var psd = parsed.pseudos[i];
+ if (!Selectors.Filters.byPseudo(item, psd.parser, psd.argument, local)) return false;
+ }
+ }
+ return true;
+ },
+
+ getByTagAndID: function(ctx, tag, id){
+ if (id){
+ var item = (ctx.getElementById) ? ctx.getElementById(id, true) : Element.getElementById(ctx, id, true);
+ return (item && Selectors.Filters.byTag(item, tag)) ? [item] : [];
+ } else {
+ return ctx.getElementsByTagName(tag);
+ }
+ },
+
+ search: function(self, expression, local){
+ var splitters = [];
+
+ var selectors = expression.trim().replace(Selectors.RegExps.splitter, function(m0, m1, m2){
+ splitters.push(m1);
+ return ':)' + m2;
+ }).split(':)');
+
+ var items, match, filtered, item;
+
+ for (var i = 0, l = selectors.length; i < l; i++){
+
+ var selector = selectors[i];
+
+ if (i == 0 && Selectors.RegExps.quick.test(selector)){
+ items = self.getElementsByTagName(selector);
+ continue;
+ }
+
+ var splitter = splitters[i - 1];
+
+ var tagid = Selectors.Utils.parseTagAndID(selector);
+ var tag = tagid[0], id = tagid[1];
+
+ if (i == 0){
+ items = Selectors.Utils.getByTagAndID(self, tag, id);
+ } else {
+ var uniques = {}, found = [];
+ for (var j = 0, k = items.length; j < k; j++) found = Selectors.Getters[splitter](found, items[j], tag, id, uniques);
+ items = found;
+ }
+
+ var parsed = Selectors.Utils.parseSelector(selector);
+
+ if (parsed){
+ filtered = [];
+ for (var m = 0, n = items.length; m < n; m++){
+ item = items[m];
+ if (Selectors.Utils.filter(item, parsed, local)) filtered.push(item);
+ }
+ items = filtered;
+ }
+
+ }
+
+ return items;
+
+ }
+
+};
+
+Selectors.Getters = {
+
+ ' ': function(found, self, tag, id, uniques){
+ var items = Selectors.Utils.getByTagAndID(self, tag, id);
+ for (var i = 0, l = items.length; i < l; i++){
+ var item = items[i];
+ if (Selectors.Utils.chk(item, uniques)) found.push(item);
+ }
+ return found;
+ },
+
+ '>': function(found, self, tag, id, uniques){
+ var children = Selectors.Utils.getByTagAndID(self, tag, id);
+ for (var i = 0, l = children.length; i < l; i++){
+ var child = children[i];
+ if (child.parentNode == self && Selectors.Utils.chk(child, uniques)) found.push(child);
+ }
+ return found;
+ },
+
+ '+': function(found, self, tag, id, uniques){
+ while ((self = self.nextSibling)){
+ if (self.nodeType == 1){
+ if (Selectors.Utils.chk(self, uniques) && Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
+ break;
+ }
+ }
+ return found;
+ },
+
+ '~': function(found, self, tag, id, uniques){
+
+ while ((self = self.nextSibling)){
+ if (self.nodeType == 1){
+ if (!Selectors.Utils.chk(self, uniques)) break;
+ if (Selectors.Filters.byTag(self, tag) && Selectors.Filters.byID(self, id)) found.push(self);
+ }
+ }
+ return found;
+ }
+
+};
+
+Selectors.Filters = {
+
+ byTag: function(self, tag){
+ return (tag == '*' || (self.tagName && self.tagName.toLowerCase() == tag));
+ },
+
+ byID: function(self, id){
+ return (!id || (self.id && self.id == id));
+ },
+
+ byClass: function(self, klass){
+ return (self.className && self.className.contains(klass, ' '));
+ },
+
+ byPseudo: function(self, parser, argument, local){
+ return parser.call(self, argument, local);
+ },
+
+ byAttribute: function(self, name, operator, value){
+ var result = Element.prototype.getProperty.call(self, name);
+ if (!result) return false;
+ if (!operator || value == undefined) return true;
+ switch (operator){
+ case '=': return (result == value);
+ case '*=': return (result.contains(value));
+ case '^=': return (result.substr(0, value.length) == value);
+ case '$=': return (result.substr(result.length - value.length) == value);
+ case '!=': return (result != value);
+ case '~=': return result.contains(value, ' ');
+ case '|=': return result.contains(value, '-');
+ }
+ return false;
+ }
+
+};
+
+Selectors.Pseudo = new Hash({
+
+ // w3c pseudo selectors
+
+ empty: function(){
+ return !(this.innerText || this.textContent || '').length;
+ },
+
+ not: function(selector){
+ return !Element.match(this, selector);
+ },
+
+ contains: function(text){
+ return (this.innerText || this.textContent || '').contains(text);
+ },
+
+ 'first-child': function(){
+ return Selectors.Pseudo.index.call(this, 0);
+ },
+
+ 'last-child': function(){
+ var element = this;
+ while ((element = element.nextSibling)){
+ if (element.nodeType == 1) return false;
+ }
+ return true;
+ },
+
+ 'only-child': function(){
+ var prev = this;
+ while ((prev = prev.previousSibling)){
+ if (prev.nodeType == 1) return false;
+ }
+ var next = this;
+ while ((next = next.nextSibling)){
+ if (next.nodeType == 1) return false;
+ }
+ return true;
+ },
+
+ 'nth-child': function(argument, local){
+ argument = (argument == undefined) ? 'n' : argument;
+ var parsed = Selectors.Utils.parseNthArgument(argument);
+ if (parsed.special != 'n') return Selectors.Pseudo[parsed.special].call(this, parsed.a, local);
+ var count = 0;
+ local.positions = local.positions || {};
+ var uid = $uid(this);
+ if (!local.positions[uid]){
+ var self = this;
+ while ((self = self.previousSibling)){
+ if (self.nodeType != 1) continue;
+ count ++;
+ var position = local.positions[$uid(self)];
+ if (position != undefined){
+ count = position + count;
+ break;
+ }
+ }
+ local.positions[uid] = count;
+ }
+ return (local.positions[uid] % parsed.a == parsed.b);
+ },
+
+ // custom pseudo selectors
+
+ index: function(index){
+ var element = this, count = 0;
+ while ((element = element.previousSibling)){
+ if (element.nodeType == 1 && ++count > index) return false;
+ }
+ return (count == index);
+ },
+
+ even: function(argument, local){
+ return Selectors.Pseudo['nth-child'].call(this, '2n+1', local);
+ },
+
+ odd: function(argument, local){
+ return Selectors.Pseudo['nth-child'].call(this, '2n', local);
+ }
+
+});
+
+/*
+Script: Domready.js
+ Contains the domready custom event.
+
+License:
+ MIT-style license.
+*/
+
+Element.Events.domready = {
+
+ onAdd: function(fn){
+ if (Browser.loaded) fn.call(this);
+ }
+
+};
+
+(function(){
+
+ var domready = function(){
+ if (Browser.loaded) return;
+ Browser.loaded = true;
+ window.fireEvent('domready');
+ document.fireEvent('domready');
+ };
+
+ switch (Browser.Engine.name){
+
+ case 'webkit': (function(){
+ (['loaded', 'complete'].contains(document.readyState)) ? domready() : arguments.callee.delay(50);
+ })(); break;
+
+ case 'trident':
+ var temp = document.createElement('div');
+ (function(){
+ ($try(function(){
+ temp.doScroll('left');
+ return $(temp).inject(document.body).set('html', 'temp').dispose();
+ })) ? domready() : arguments.callee.delay(50);
+ })();
+ break;
+
+ default:
+ window.addEvent('load', domready);
+ document.addEvent('DOMContentLoaded', domready);
+
+ }
+
+})();
+
+/*
+Script: JSON.js
+ JSON encoder and decoder.
+
+License:
+ MIT-style license.
+
+See Also:
+ <http://www.json.org/>
+*/
+
+var JSON = new Hash({
+
+ encode: function(obj){
+ switch ($type(obj)){
+ case 'string':
+ return '"' + obj.replace(/[\x00-\x1f\\"]/g, JSON.$replaceChars) + '"';
+ case 'array':
+ return '[' + String(obj.map(JSON.encode).filter($defined)) + ']';
+ case 'object': case 'hash':
+ var string = [];
+ Hash.each(obj, function(value, key){
+ var json = JSON.encode(value);
+ if (json) string.push(JSON.encode(key) + ':' + json);
+ });
+ return '{' + string + '}';
+ case 'number': case 'boolean': return String(obj);
+ case false: return 'null';
+ }
+ return null;
+ },
+
+ $specialChars: {'\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\'},
+
+ $replaceChars: function(chr){
+ return JSON.$specialChars[chr] || '\\u00' + Math.floor(chr.charCodeAt() / 16).toString(16) + (chr.charCodeAt() % 16).toString(16);
+ },
+
+ decode: function(string, secure){
+ if ($type(string) != 'string' || !string.length) return null;
+ if (secure && !(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''))) return null;
+ return eval('(' + string + ')');
+ }
+
+});
+
+Native.implement([Hash, Array, String, Number], {
+
+ toJSON: function(){
+ return JSON.encode(this);
+ }
+
+});
+
+
+/*
+Script: Cookie.js
+ Class for creating, loading, and saving browser Cookies.
+
+License:
+ MIT-style license.
+
+Credits:
+ Based on the functions by Peter-Paul Koch (http://quirksmode.org).
+*/
+
+var Cookie = new Class({
+
+ Implements: Options,
+
+ options: {
+ path: false,
+ domain: false,
+ duration: false,
+ secure: false,
+ document: document
+ },
+
+ initialize: function(key, options){
+ this.key = key;
+ this.setOptions(options);
+ },
+
+ write: function(value){
+ value = encodeURIComponent(value);
+ if (this.options.domain) value += '; domain=' + this.options.domain;
+ if (this.options.path) value += '; path=' + this.options.path;
+ if (this.options.duration){
+ var date = new Date();
+ date.setTime(date.getTime() + this.options.duration * 24 * 60 * 60 * 1000);
+ value += '; expires=' + date.toGMTString();
+ }
+ if (this.options.secure) value += '; secure';
+ this.options.document.cookie = this.key + '=' + value;
+ return this;
+ },
+
+ read: function(){
+ var value = this.options.document.cookie.match('(?:^|;)\\s*' + this.key.escapeRegExp() + '=([^;]*)');
+ return (value) ? decodeURIComponent(value[1]) : null;
+ },
+
+ dispose: function(){
+ new Cookie(this.key, $merge(this.options, {duration: -1})).write('');
+ return this;
+ }
+
+});
+
+Cookie.write = function(key, value, options){
+ return new Cookie(key, options).write(value);
+};
+
+Cookie.read = function(key){
+ return new Cookie(key).read();
+};
+
+Cookie.dispose = function(key, options){
+ return new Cookie(key, options).dispose();
+};
+
+/*
+Script: Swiff.js
+ Wrapper for embedding SWF movies. Supports (and fixes) External Interface Communication.
+
+License:
+ MIT-style license.
+
+Credits:
+ Flash detection & Internet Explorer + Flash Player 9 fix inspired by SWFObject.
+*/
+
+var Swiff = new Class({
+
+ Implements: [Options],
+
+ options: {
+ id: null,
+ height: 1,
+ width: 1,
+ container: null,
+ properties: {},
+ params: {
+ quality: 'high',
+ allowScriptAccess: 'always',
+ wMode: 'transparent',
+ swLiveConnect: true
+ },
+ callBacks: {},
+ vars: {}
+ },
+
+ toElement: function(){
+ return this.object;
+ },
+
+ initialize: function(path, options){
+ this.instance = 'Swiff_' + $time();
+
+ this.setOptions(options);
+ options = this.options;
+ var id = this.id = options.id || this.instance;
+ var container = $(options.container);
+
+ Swiff.CallBacks[this.instance] = {};
+
+ var params = options.params, vars = options.vars, callBacks = options.callBacks;
+ var properties = $extend({height: options.height, width: options.width}, options.properties);
+
+ var self = this;
+
+ for (var callBack in callBacks){
+ Swiff.CallBacks[this.instance][callBack] = (function(option){
+ return function(){
+ return option.apply(self.object, arguments);
+ };
+ })(callBacks[callBack]);
+ vars[callBack] = 'Swiff.CallBacks.' + this.instance + '.' + callBack;
+ }
+
+ params.flashVars = Hash.toQueryString(vars);
+ if (Browser.Engine.trident){
+ properties.classid = 'clsid:D27CDB6E-AE6D-11cf-96B8-444553540000';
+ params.movie = path;
+ } else {
+ properties.type = 'application/x-shockwave-flash';
+ properties.data = path;
+ }
+ var build = '<object id="' + id + '"';
+ for (var property in properties) build += ' ' + property + '="' + properties[property] + '"';
+ build += '>';
+ for (var param in params){
+ if (params[param]) build += '<param name="' + param + '" value="' + params[param] + '" />';
+ }
+ build += '</object>';
+ this.object = ((container) ? container.empty() : new Element('div')).set('html', build).firstChild;
+ },
+
+ replaces: function(element){
+ element = $(element, true);
+ element.parentNode.replaceChild(this.toElement(), element);
+ return this;
+ },
+
+ inject: function(element){
+ $(element, true).appendChild(this.toElement());
+ return this;
+ },
+
+ remote: function(){
+ return Swiff.remote.apply(Swiff, [this.toElement()].extend(arguments));
+ }
+
+});
+
+Swiff.CallBacks = {};
+
+Swiff.remote = function(obj, fn){
+ var rs = obj.CallFunction('<invoke name="' + fn + '" returntype="javascript">' + __flash__argumentsToXML(arguments, 2) + '</invoke>');
+ return eval(rs);
+};
+
+/*
+Script: Fx.js
+ Contains the basic animation logic to be extended by all other Fx Classes.
+
+License:
+ MIT-style license.
+*/
+
+var Fx = new Class({
+
+ Implements: [Chain, Events, Options],
+
+ options: {
+ /*
+ onStart: $empty,
+ onCancel: $empty,
+ onComplete: $empty,
+ */
+ fps: 50,
+ unit: false,
+ duration: 500,
+ link: 'ignore',
+ transition: function(p){
+ return -(Math.cos(Math.PI * p) - 1) / 2;
+ }
+ },
+
+ initialize: function(options){
+ this.subject = this.subject || this;
+ this.setOptions(options);
+ this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt();
+ var wait = this.options.wait;
+ if (wait === false) this.options.link = 'cancel';
+ },
+
+ step: function(){
+ var time = $time();
+ if (time < this.time + this.options.duration){
+ var delta = this.options.transition((time - this.time) / this.options.duration);
+ this.set(this.compute(this.from, this.to, delta));
+ } else {
+ this.set(this.compute(this.from, this.to, 1));
+ this.complete();
+ }
+ },
+
+ set: function(now){
+ return now;
+ },
+
+ compute: function(from, to, delta){
+ return Fx.compute(from, to, delta);
+ },
+
+ check: function(caller){
+ if (!this.timer) return true;
+ switch (this.options.link){
+ case 'cancel': this.cancel(); return true;
+ case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false;
+ }
+ return false;
+ },
+
+ start: function(from, to){
+ if (!this.check(arguments.callee, from, to)) return this;
+ this.from = from;
+ this.to = to;
+ this.time = 0;
+ this.startTimer();
+ this.onStart();
+ return this;
+ },
+
+ complete: function(){
+ if (this.stopTimer()) this.onComplete();
+ return this;
+ },
+
+ cancel: function(){
+ if (this.stopTimer()) this.onCancel();
+ return this;
+ },
+
+ onStart: function(){
+ this.fireEvent('start', this.subject);
+ },
+
+ onComplete: function(){
+ this.fireEvent('complete', this.subject);
+ if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
+ },
+
+ onCancel: function(){
+ this.fireEvent('cancel', this.subject).clearChain();
+ },
+
+ pause: function(){
+ this.stopTimer();
+ return this;
+ },
+
+ resume: function(){
+ this.startTimer();
+ return this;
+ },
+
+ stopTimer: function(){
+ if (!this.timer) return false;
+ this.time = $time() - this.time;
+ this.timer = $clear(this.timer);
+ return true;
+ },
+
+ startTimer: function(){
+ if (this.timer) return false;
+ this.time = $time() - this.time;
+ this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);
+ return true;
+ }
+
+});
+
+Fx.compute = function(from, to, delta){
+ return (to - from) * delta + from;
+};
+
+Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
+
+
+/*
+Script: Fx.CSS.js
+ Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements.
+
+License:
+ MIT-style license.
+*/
+
+Fx.CSS = new Class({
+
+ Extends: Fx,
+
+ //prepares the base from/to object
+
+ prepare: function(element, property, values){
+ values = $splat(values);
+ var values1 = values[1];
+ if (!$chk(values1)){
+ values[1] = values[0];
+ values[0] = element.getStyle(property);
+ }
+ var parsed = values.map(this.parse);
+ return {from: parsed[0], to: parsed[1]};
+ },
+
+ //parses a value into an array
+
+ parse: function(value){
+ value = $lambda(value)();
+ value = (typeof value == 'string') ? value.split(' ') : $splat(value);
+ return value.map(function(val){
+ val = String(val);
+ var found = false;
+ Fx.CSS.Parsers.each(function(parser, key){
+ if (found) return;
+ var parsed = parser.parse(val);
+ if ($chk(parsed)) found = {value: parsed, parser: parser};
+ });
+ found = found || {value: val, parser: Fx.CSS.Parsers.String};
+ return found;
+ });
+ },
+
+ //computes by a from and to prepared objects, using their parsers.
+
+ compute: function(from, to, delta){
+ var computed = [];
+ (Math.min(from.length, to.length)).times(function(i){
+ computed.push({value: from[i].parser.compute(from[i].value, to[i].value, delta), parser: from[i].parser});
+ });
+ computed.$family = {name: 'fx:css:value'};
+ return computed;
+ },
+
+ //serves the value as settable
+
+ serve: function(value, unit){
+ if ($type(value) != 'fx:css:value') value = this.parse(value);
+ var returned = [];
+ value.each(function(bit){
+ returned = returned.concat(bit.parser.serve(bit.value, unit));
+ });
+ return returned;
+ },
+
+ //renders the change to an element
+
+ render: function(element, property, value, unit){
+ element.setStyle(property, this.serve(value, unit));
+ },
+
+ //searches inside the page css to find the values for a selector
+
+ search: function(selector){
+ if (Fx.CSS.Cache[selector]) return Fx.CSS.Cache[selector];
+ var to = {};
+ Array.each(document.styleSheets, function(sheet, j){
+ var href = sheet.href;
+ if (href && href.contains('://') && !href.contains(document.domain)) return;
+ var rules = sheet.rules || sheet.cssRules;
+ Array.each(rules, function(rule, i){
+ if (!rule.style) return;
+ var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function(m){
+ return m.toLowerCase();
+ }) : null;
+ if (!selectorText || !selectorText.test('^' + selector + '$')) return;
+ Element.Styles.each(function(value, style){
+ if (!rule.style[style] || Element.ShortStyles[style]) return;
+ value = String(rule.style[style]);
+ to[style] = (value.test(/^rgb/)) ? value.rgbToHex() : value;
+ });
+ });
+ });
+ return Fx.CSS.Cache[selector] = to;
+ }
+
+});
+
+Fx.CSS.Cache = {};
+
+Fx.CSS.Parsers = new Hash({
+
+ Color: {
+ parse: function(value){
+ if (value.match(/^#[0-9a-f]{3,6}$/i)) return value.hexToRgb(true);
+ return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false;
+ },
+ compute: function(from, to, delta){
+ return from.map(function(value, i){
+ return Math.round(Fx.compute(from[i], to[i], delta));
+ });
+ },
+ serve: function(value){
+ return value.map(Number);
+ }
+ },
+
+ Number: {
+ parse: parseFloat,
+ compute: Fx.compute,
+ serve: function(value, unit){
+ return (unit) ? value + unit : value;
+ }
+ },
+
+ String: {
+ parse: $lambda(false),
+ compute: $arguments(1),
+ serve: $arguments(0)
+ }
+
+});
+
+
+/*
+Script: Fx.Tween.js
+ Formerly Fx.Style, effect to transition any CSS property for an element.
+
+License:
+ MIT-style license.
+*/
+
+Fx.Tween = new Class({
+
+ Extends: Fx.CSS,
+
+ initialize: function(element, options){
+ this.element = this.subject = $(element);
+ this.parent(options);
+ },
+
+ set: function(property, now){
+ if (arguments.length == 1){
+ now = property;
+ property = this.property || this.options.property;
+ }
+ this.render(this.element, property, now, this.options.unit);
+ return this;
+ },
+
+ start: function(property, from, to){
+ if (!this.check(arguments.callee, property, from, to)) return this;
+ var args = Array.flatten(arguments);
+ this.property = this.options.property || args.shift();
+ var parsed = this.prepare(this.element, this.property, args);
+ return this.parent(parsed.from, parsed.to);
+ }
+
+});
+
+Element.Properties.tween = {
+
+ set: function(options){
+ var tween = this.retrieve('tween');
+ if (tween) tween.cancel();
+ return this.eliminate('tween').store('tween:options', $extend({link: 'cancel'}, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('tween')){
+ if (options || !this.retrieve('tween:options')) this.set('tween', options);
+ this.store('tween', new Fx.Tween(this, this.retrieve('tween:options')));
+ }
+ return this.retrieve('tween');
+ }
+
+};
+
+Element.implement({
+
+ tween: function(property, from, to){
+ this.get('tween').start(arguments);
+ return this;
+ },
+
+ fade: function(how){
+ var fade = this.get('tween'), o = 'opacity', toggle;
+ how = $pick(how, 'toggle');
+ switch (how){
+ case 'in': fade.start(o, 1); break;
+ case 'out': fade.start(o, 0); break;
+ case 'show': fade.set(o, 1); break;
+ case 'hide': fade.set(o, 0); break;
+ case 'toggle':
+ var flag = this.retrieve('fade:flag', this.get('opacity') == 1);
+ fade.start(o, (flag) ? 0 : 1);
+ this.store('fade:flag', !flag);
+ toggle = true;
+ break;
+ default: fade.start(o, arguments);
+ }
+ if (!toggle) this.eliminate('fade:flag');
+ return this;
+ },
+
+ highlight: function(start, end){
+ if (!end){
+ end = this.retrieve('highlight:original', this.getStyle('background-color'));
+ end = (end == 'transparent') ? '#fff' : end;
+ }
+ var tween = this.get('tween');
+ tween.start('background-color', start || '#ffff88', end).chain(function(){
+ this.setStyle('background-color', this.retrieve('highlight:original'));
+ tween.callChain();
+ }.bind(this));
+ return this;
+ }
+
+});
+
+
+/*
+Script: Fx.Morph.js
+ Formerly Fx.Styles, effect to transition any number of CSS properties for an element using an object of rules, or CSS based selector rules.
+
+License:
+ MIT-style license.
+*/
+
+Fx.Morph = new Class({
+
+ Extends: Fx.CSS,
+
+ initialize: function(element, options){
+ this.element = this.subject = $(element);
+ this.parent(options);
+ },
+
+ set: function(now){
+ if (typeof now == 'string') now = this.search(now);
+ for (var p in now) this.render(this.element, p, now[p], this.options.unit);
+ return this;
+ },
+
+ compute: function(from, to, delta){
+ var now = {};
+ for (var p in from) now[p] = this.parent(from[p], to[p], delta);
+ return now;
+ },
+
+ start: function(properties){
+ if (!this.check(arguments.callee, properties)) return this;
+ if (typeof properties == 'string') properties = this.search(properties);
+ var from = {}, to = {};
+ for (var p in properties){
+ var parsed = this.prepare(this.element, p, properties[p]);
+ from[p] = parsed.from;
+ to[p] = parsed.to;
+ }
+ return this.parent(from, to);
+ }
+
+});
+
+Element.Properties.morph = {
+
+ set: function(options){
+ var morph = this.retrieve('morph');
+ if (morph) morph.cancel();
+ return this.eliminate('morph').store('morph:options', $extend({link: 'cancel'}, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('morph')){
+ if (options || !this.retrieve('morph:options')) this.set('morph', options);
+ this.store('morph', new Fx.Morph(this, this.retrieve('morph:options')));
+ }
+ return this.retrieve('morph');
+ }
+
+};
+
+Element.implement({
+
+ morph: function(props){
+ this.get('morph').start(props);
+ return this;
+ }
+
+});
+
+/*
+Script: Fx.Transitions.js
+ Contains a set of advanced transitions to be used with any of the Fx Classes.
+
+License:
+ MIT-style license.
+
+Credits:
+ Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>, modified and optimized to be used with MooTools.
+*/
+
+(function(){
+
+ var old = Fx.prototype.initialize;
+
+ Fx.prototype.initialize = function(options){
+ old.call(this, options);
+ var trans = this.options.transition;
+ if (typeof trans == 'string' && (trans = trans.split(':'))){
+ var base = Fx.Transitions;
+ base = base[trans[0]] || base[trans[0].capitalize()];
+ if (trans[1]) base = base['ease' + trans[1].capitalize() + (trans[2] ? trans[2].capitalize() : '')];
+ this.options.transition = base;
+ }
+ };
+
+})();
+
+Fx.Transition = function(transition, params){
+ params = $splat(params);
+ return $extend(transition, {
+ easeIn: function(pos){
+ return transition(pos, params);
+ },
+ easeOut: function(pos){
+ return 1 - transition(1 - pos, params);
+ },
+ easeInOut: function(pos){
+ return (pos <= 0.5) ? transition(2 * pos, params) / 2 : (2 - transition(2 * (1 - pos), params)) / 2;
+ }
+ });
+};
+
+Fx.Transitions = new Hash({
+
+ linear: $arguments(0)
+
+});
+
+Fx.Transitions.extend = function(transitions){
+ for (var transition in transitions) Fx.Transitions[transition] = new Fx.Transition(transitions[transition]);
+};
+
+Fx.Transitions.extend({
+
+ Pow: function(p, x){
+ return Math.pow(p, x[0] || 6);
+ },
+
+ Expo: function(p){
+ return Math.pow(2, 8 * (p - 1));
+ },
+
+ Circ: function(p){
+ return 1 - Math.sin(Math.acos(p));
+ },
+
+ Sine: function(p){
+ return 1 - Math.sin((1 - p) * Math.PI / 2);
+ },
+
+ Back: function(p, x){
+ x = x[0] || 1.618;
+ return Math.pow(p, 2) * ((x + 1) * p - x);
+ },
+
+ Bounce: function(p){
+ var value;
+ for (var a = 0, b = 1; 1; a += b, b /= 2){
+ if (p >= (7 - 4 * a) / 11){
+ value = - Math.pow((11 - 6 * a - 11 * p) / 4, 2) + b * b;
+ break;
+ }
+ }
+ return value;
+ },
+
+ Elastic: function(p, x){
+ return Math.pow(2, 10 * --p) * Math.cos(20 * p * Math.PI * (x[0] || 1) / 3);
+ }
+
+});
+
+['Quad', 'Cubic', 'Quart', 'Quint'].each(function(transition, i){
+ Fx.Transitions[transition] = new Fx.Transition(function(p){
+ return Math.pow(p, [i + 2]);
+ });
+});
+
+
+/*
+Script: Request.js
+ Powerful all purpose Request Class. Uses XMLHTTPRequest.
+
+License:
+ MIT-style license.
+*/
+
+var Request = new Class({
+
+ Implements: [Chain, Events, Options],
+
+ options: {
+ /*onRequest: $empty,
+ onSuccess: $empty,
+ onFailure: $empty,
+ onException: $empty,*/
+ url: '',
+ data: '',
+ headers: {
+ 'X-Requested-With': 'XMLHttpRequest',
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
+ },
+ async: true,
+ format: false,
+ method: 'post',
+ link: 'ignore',
+ isSuccess: null,
+ emulation: true,
+ urlEncoded: true,
+ encoding: 'utf-8',
+ evalScripts: false,
+ evalResponse: false
+ },
+
+ initialize: function(options){
+ this.xhr = new Browser.Request();
+ this.setOptions(options);
+ this.options.isSuccess = this.options.isSuccess || this.isSuccess;
+ this.headers = new Hash(this.options.headers);
+ },
+
+ onStateChange: function(){
+ if (this.xhr.readyState != 4 || !this.running) return;
+ this.running = false;
+ this.status = 0;
+ $try(function(){
+ this.status = this.xhr.status;
+ }.bind(this));
+ if (this.options.isSuccess.call(this, this.status)){
+ this.response = {text: this.xhr.responseText, xml: this.xhr.responseXML};
+ this.success(this.response.text, this.response.xml);
+ } else {
+ this.response = {text: null, xml: null};
+ this.failure();
+ }
+ this.xhr.onreadystatechange = $empty;
+ },
+
+ isSuccess: function(){
+ return ((this.status >= 200) && (this.status < 300));
+ },
+
+ processScripts: function(text){
+ if (this.options.evalResponse || (/(ecma|java)script/).test(this.getHeader('Content-type'))) return $exec(text);
+ return text.stripScripts(this.options.evalScripts);
+ },
+
+ success: function(text, xml){
+ this.onSuccess(this.processScripts(text), xml);
+ },
+
+ onSuccess: function(){
+ this.fireEvent('complete', arguments).fireEvent('success', arguments).callChain();
+ },
+
+ failure: function(){
+ this.onFailure();
+ },
+
+ onFailure: function(){
+ this.fireEvent('complete').fireEvent('failure', this.xhr);
+ },
+
+ setHeader: function(name, value){
+ this.headers.set(name, value);
+ return this;
+ },
+
+ getHeader: function(name){
+ return $try(function(){
+ return this.xhr.getResponseHeader(name);
+ }.bind(this));
+ },
+
+ check: function(caller){
+ if (!this.running) return true;
+ switch (this.options.link){
+ case 'cancel': this.cancel(); return true;
+ case 'chain': this.chain(caller.bind(this, Array.slice(arguments, 1))); return false;
+ }
+ return false;
+ },
+
+ send: function(options){
+ if (!this.check(arguments.callee, options)) return this;
+ this.running = true;
+
+ var type = $type(options);
+ if (type == 'string' || type == 'element') options = {data: options};
+
+ var old = this.options;
+ options = $extend({data: old.data, url: old.url, method: old.method}, options);
+ var data = options.data, url = options.url, method = options.method;
+
+ switch ($type(data)){
+ case 'element': data = $(data).toQueryString(); break;
+ case 'object': case 'hash': data = Hash.toQueryString(data);
+ }
+
+ if (this.options.format){
+ var format = 'format=' + this.options.format;
+ data = (data) ? format + '&' + data : format;
+ }
+
+ if (this.options.emulation && ['put', 'delete'].contains(method)){
+ var _method = '_method=' + method;
+ data = (data) ? _method + '&' + data : _method;
+ method = 'post';
+ }
+
+ if (this.options.urlEncoded && method == 'post'){
+ var encoding = (this.options.encoding) ? '; charset=' + this.options.encoding : '';
+ this.headers.set('Content-type', 'application/x-www-form-urlencoded' + encoding);
+ }
+
+ if (data && method == 'get'){
+ url = url + (url.contains('?') ? '&' : '?') + data;
+ data = null;
+ }
+
+ this.xhr.open(method.toUpperCase(), url, this.options.async);
+
+ this.xhr.onreadystatechange = this.onStateChange.bind(this);
+
+ this.headers.each(function(value, key){
+ if (!$try(function(){
+ this.xhr.setRequestHeader(key, value);
+ return true;
+ }.bind(this))) this.fireEvent('exception', [key, value]);
+ }, this);
+
+ this.fireEvent('request');
+ this.xhr.send(data);
+ if (!this.options.async) this.onStateChange();
+ return this;
+ },
+
+ cancel: function(){
+ if (!this.running) return this;
+ this.running = false;
+ this.xhr.abort();
+ this.xhr.onreadystatechange = $empty;
+ this.xhr = new Browser.Request();
+ this.fireEvent('cancel');
+ return this;
+ }
+
+});
+
+(function(){
+
+var methods = {};
+['get', 'post', 'put', 'delete', 'GET', 'POST', 'PUT', 'DELETE'].each(function(method){
+ methods[method] = function(){
+ var params = Array.link(arguments, {url: String.type, data: $defined});
+ return this.send($extend(params, {method: method.toLowerCase()}));
+ };
+});
+
+Request.implement(methods);
+
+})();
+
+Element.Properties.send = {
+
+ set: function(options){
+ var send = this.retrieve('send');
+ if (send) send.cancel();
+ return this.eliminate('send').store('send:options', $extend({
+ data: this, link: 'cancel', method: this.get('method') || 'post', url: this.get('action')
+ }, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('send')){
+ if (options || !this.retrieve('send:options')) this.set('send', options);
+ this.store('send', new Request(this.retrieve('send:options')));
+ }
+ return this.retrieve('send');
+ }
+
+};
+
+Element.implement({
+
+ send: function(url){
+ var sender = this.get('send');
+ sender.send({data: this, url: url || sender.options.url});
+ return this;
+ }
+
+});
+
+
+/*
+Script: Request.HTML.js
+ Extends the basic Request Class with additional methods for interacting with HTML responses.
+
+License:
+ MIT-style license.
+*/
+
+Request.HTML = new Class({
+
+ Extends: Request,
+
+ options: {
+ update: false,
+ evalScripts: true,
+ filter: false
+ },
+
+ processHTML: function(text){
+ var match = text.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
+ text = (match) ? match[1] : text;
+
+ var container = new Element('div');
+
+ return $try(function(){
+ var root = '<root>' + text + '</root>', doc;
+ if (Browser.Engine.trident){
+ doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = false;
+ doc.loadXML(root);
+ } else {
+ doc = new DOMParser().parseFromString(root, 'text/xml');
+ }
+ root = doc.getElementsByTagName('root')[0];
+ for (var i = 0, k = root.childNodes.length; i < k; i++){
+ var child = Element.clone(root.childNodes[i], true, true);
+ if (child) container.grab(child);
+ }
+ return container;
+ }) || container.set('html', text);
+ },
+
+ success: function(text){
+ var options = this.options, response = this.response;
+
+ response.html = text.stripScripts(function(script){
+ response.javascript = script;
+ });
+
+ var temp = this.processHTML(response.html);
+
+ response.tree = temp.childNodes;
+ response.elements = temp.getElements('*');
+
+ if (options.filter) response.tree = response.elements.filter(options.filter);
+ if (options.update) $(options.update).empty().adopt(response.tree);
+ if (options.evalScripts) $exec(response.javascript);
+
+ this.onSuccess(response.tree, response.elements, response.html, response.javascript);
+ }
+
+});
+
+Element.Properties.load = {
+
+ set: function(options){
+ var load = this.retrieve('load');
+ if (load) send.cancel();
+ return this.eliminate('load').store('load:options', $extend({data: this, link: 'cancel', update: this, method: 'get'}, options));
+ },
+
+ get: function(options){
+ if (options || ! this.retrieve('load')){
+ if (options || !this.retrieve('load:options')) this.set('load', options);
+ this.store('load', new Request.HTML(this.retrieve('load:options')));
+ }
+ return this.retrieve('load');
+ }
+
+};
+
+Element.implement({
+
+ load: function(){
+ this.get('load').send(Array.link(arguments, {data: Object.type, url: String.type}));
+ return this;
+ }
+
+});
+
+
+/*
+Script: Request.JSON.js
+ Extends the basic Request Class with additional methods for sending and receiving JSON data.
+
+License:
+ MIT-style license.
+*/
+
+Request.JSON = new Class({
+
+ Extends: Request,
+
+ options: {
+ secure: true
+ },
+
+ initialize: function(options){
+ this.parent(options);
+ this.headers.extend({'Accept': 'application/json', 'X-Request': 'JSON'});
+ },
+
+ success: function(text){
+ this.response.json = JSON.decode(text, this.options.secure);
+ this.onSuccess(this.response.json, text);
+ }
+
+});//MooTools More, <http://mootools.net/more>. Copyright (c) 2006-2008 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
+
+/*
+Script: Fx.Slide.js
+ Effect to slide an element in and out of view.
+
+License:
+ MIT-style license.
+*/
+
+Fx.Slide = new Class({
+
+ Extends: Fx,
+
+ options: {
+ mode: 'vertical'
+ },
+
+ initialize: function(element, options){
+ this.addEvent('complete', function(){
+ this.open = (this.wrapper['offset' + this.layout.capitalize()] != 0);
+ if (this.open && Browser.Engine.webkit419) this.element.dispose().inject(this.wrapper);
+ }, true);
+ this.element = this.subject = $(element);
+ this.parent(options);
+ var wrapper = this.element.retrieve('wrapper');
+ this.wrapper = wrapper || new Element('div', {
+ styles: $extend(this.element.getStyles('margin', 'position'), {'overflow': 'hidden'})
+ }).wraps(this.element);
+ this.element.store('wrapper', this.wrapper).setStyle('margin', 0);
+ this.now = [];
+ this.open = true;
+ },
+
+ vertical: function(){
+ this.margin = 'margin-top';
+ this.layout = 'height';
+ this.offset = this.element.offsetHeight;
+ },
+
+ horizontal: function(){
+ this.margin = 'margin-left';
+ this.layout = 'width';
+ this.offset = this.element.offsetWidth;
+ },
+
+ set: function(now){
+ this.element.setStyle(this.margin, now[0]);
+ this.wrapper.setStyle(this.layout, now[1]);
+ return this;
+ },
+
+ compute: function(from, to, delta){
+ var now = [];
+ var x = 2;
+ x.times(function(i){
+ now[i] = Fx.compute(from[i], to[i], delta);
+ });
+ return now;
+ },
+
+ start: function(how, mode){
+ if (!this.check(arguments.callee, how, mode)) return this;
+ this[mode || this.options.mode]();
+ var margin = this.element.getStyle(this.margin).toInt();
+ var layout = this.wrapper.getStyle(this.layout).toInt();
+ var caseIn = [[margin, layout], [0, this.offset]];
+ var caseOut = [[margin, layout], [-this.offset, 0]];
+ var start;
+ switch (how){
+ case 'in': start = caseIn; break;
+ case 'out': start = caseOut; break;
+ case 'toggle': start = (this.wrapper['offset' + this.layout.capitalize()] == 0) ? caseIn : caseOut;
+ }
+ return this.parent(start[0], start[1]);
+ },
+
+ slideIn: function(mode){
+ return this.start('in', mode);
+ },
+
+ slideOut: function(mode){
+ return this.start('out', mode);
+ },
+
+ hide: function(mode){
+ this[mode || this.options.mode]();
+ this.open = false;
+ return this.set([-this.offset, 0]);
+ },
+
+ show: function(mode){
+ this[mode || this.options.mode]();
+ this.open = true;
+ return this.set([0, this.offset]);
+ },
+
+ toggle: function(mode){
+ return this.start('toggle', mode);
+ }
+
+});
+
+Element.Properties.slide = {
+
+ set: function(options){
+ var slide = this.retrieve('slide');
+ if (slide) slide.cancel();
+ return this.eliminate('slide').store('slide:options', $extend({link: 'cancel'}, options));
+ },
+
+ get: function(options){
+ if (options || !this.retrieve('slide')){
+ if (options || !this.retrieve('slide:options')) this.set('slide', options);
+ this.store('slide', new Fx.Slide(this, this.retrieve('slide:options')));
+ }
+ return this.retrieve('slide');
+ }
+
+};
+
+Element.implement({
+
+ slide: function(how, mode){
+ how = how || 'toggle';
+ var slide = this.get('slide'), toggle;
+ switch (how){
+ case 'hide': slide.hide(mode); break;
+ case 'show': slide.show(mode); break;
+ case 'toggle':
+ var flag = this.retrieve('slide:flag', slide.open);
+ slide[(flag) ? 'slideOut' : 'slideIn'](mode);
+ this.store('slide:flag', !flag);
+ toggle = true;
+ break;
+ default: slide.start(how, mode);
+ }
+ if (!toggle) this.eliminate('slide:flag');
+ return this;
+ }
+
+});
+
+
+/*
+Script: Fx.Scroll.js
+ Effect to smoothly scroll any element, including the window.
+
+License:
+ MIT-style license.
+*/
+
+Fx.Scroll = new Class({
+
+ Extends: Fx,
+
+ options: {
+ offset: {'x': 0, 'y': 0},
+ wheelStops: true
+ },
+
+ initialize: function(element, options){
+ this.element = this.subject = $(element);
+ this.parent(options);
+ var cancel = this.cancel.bind(this, false);
+
+ if ($type(this.element) != 'element') this.element = $(this.element.getDocument().body);
+
+ var stopper = this.element;
+
+ if (this.options.wheelStops){
+ this.addEvent('start', function(){
+ stopper.addEvent('mousewheel', cancel);
+ }, true);
+ this.addEvent('complete', function(){
+ stopper.removeEvent('mousewheel', cancel);
+ }, true);
+ }
+ },
+
+ set: function(){
+ var now = Array.flatten(arguments);
+ this.element.scrollTo(now[0], now[1]);
+ },
+
+ compute: function(from, to, delta){
+ var now = [];
+ var x = 2;
+ x.times(function(i){
+ now.push(Fx.compute(from[i], to[i], delta));
+ });
+ return now;
+ },
+
+ start: function(x, y){
+ if (!this.check(arguments.callee, x, y)) return this;
+ var offsetSize = this.element.getSize(), scrollSize = this.element.getScrollSize();
+ var scroll = this.element.getScroll(), values = {x: x, y: y};
+ for (var z in values){
+ var max = scrollSize[z] - offsetSize[z];
+ if ($chk(values[z])) values[z] = ($type(values[z]) == 'number') ? values[z].limit(0, max) : max;
+ else values[z] = scroll[z];
+ values[z] += this.options.offset[z];
+ }
+ return this.parent([scroll.x, scroll.y], [values.x, values.y]);
+ },
+
+ toTop: function(){
+ return this.start(false, 0);
+ },
+
+ toLeft: function(){
+ return this.start(0, false);
+ },
+
+ toRight: function(){
+ return this.start('right', false);
+ },
+
+ toBottom: function(){
+ return this.start(false, 'bottom');
+ },
+
+ toElement: function(el){
+ var position = $(el).getPosition(this.element);
+ return this.start(position.x, position.y);
+ }
+
+});
+
+
+/*
+Script: Fx.Elements.js
+ Effect to change any number of CSS properties of any number of Elements.
+
+License:
+ MIT-style license.
+*/
+
+Fx.Elements = new Class({
+
+ Extends: Fx.CSS,
+
+ initialize: function(elements, options){
+ this.elements = this.subject = $$(elements);
+ this.parent(options);
+ },
+
+ compute: function(from, to, delta){
+ var now = {};
+ for (var i in from){
+ var iFrom = from[i], iTo = to[i], iNow = now[i] = {};
+ for (var p in iFrom) iNow[p] = this.parent(iFrom[p], iTo[p], delta);
+ }
+ return now;
+ },
+
+ set: function(now){
+ for (var i in now){
+ var iNow = now[i];
+ for (var p in iNow) this.render(this.elements[i], p, iNow[p], this.options.unit);
+ }
+ return this;
+ },
+
+ start: function(obj){
+ if (!this.check(arguments.callee, obj)) return this;
+ var from = {}, to = {};
+ for (var i in obj){
+ var iProps = obj[i], iFrom = from[i] = {}, iTo = to[i] = {};
+ for (var p in iProps){
+ var parsed = this.prepare(this.elements[i], p, iProps[p]);
+ iFrom[p] = parsed.from;
+ iTo[p] = parsed.to;
+ }
+ }
+ return this.parent(from, to);
+ }
+
+});
+
+/*
+Script: Drag.js
+ The base Drag Class. Can be used to drag and resize Elements using mouse events.
+
+License:
+ MIT-style license.
+*/
+
+var Drag = new Class({
+
+ Implements: [Events, Options],
+
+ options: {/*
+ onBeforeStart: $empty,
+ onStart: $empty,
+ onDrag: $empty,
+ onCancel: $empty,
+ onComplete: $empty,*/
+ snap: 6,
+ unit: 'px',
+ grid: false,
+ style: true,
+ limit: false,
+ handle: false,
+ invert: false,
+ preventDefault: false,
+ modifiers: {x: 'left', y: 'top'}
+ },
+
+ initialize: function(){
+ var params = Array.link(arguments, {'options': Object.type, 'element': $defined});
+ this.element = $(params.element);
+ this.document = this.element.getDocument();
+ this.setOptions(params.options || {});
+ var htype = $type(this.options.handle);
+ this.handles = (htype == 'array' || htype == 'collection') ? $$(this.options.handle) : $(this.options.handle) || this.element;
+ this.mouse = {'now': {}, 'pos': {}};
+ this.value = {'start': {}, 'now': {}};
+
+ this.selection = (Browser.Engine.trident) ? 'selectstart' : 'mousedown';
+
+ this.bound = {
+ start: this.start.bind(this),
+ check: this.check.bind(this),
+ drag: this.drag.bind(this),
+ stop: this.stop.bind(this),
+ cancel: this.cancel.bind(this),
+ eventStop: $lambda(false)
+ };
+ this.attach();
+ },
+
+ attach: function(){
+ this.handles.addEvent('mousedown', this.bound.start);
+ return this;
+ },
+
+ detach: function(){
+ this.handles.removeEvent('mousedown', this.bound.start);
+ return this;
+ },
+
+ start: function(event){
+ if (this.options.preventDefault) event.preventDefault();
+ this.fireEvent('beforeStart', this.element);
+ this.mouse.start = event.page;
+ var limit = this.options.limit;
+ this.limit = {'x': [], 'y': []};
+ for (var z in this.options.modifiers){
+ if (!this.options.modifiers[z]) continue;
+ if (this.options.style) this.value.now[z] = this.element.getStyle(this.options.modifiers[z]).toInt();
+ else this.value.now[z] = this.element[this.options.modifiers[z]];
+ if (this.options.invert) this.value.now[z] *= -1;
+ this.mouse.pos[z] = event.page[z] - this.value.now[z];
+ if (limit && limit[z]){
+ for (var i = 2; i--; i){
+ if ($chk(limit[z][i])) this.limit[z][i] = $lambda(limit[z][i])();
+ }
+ }
+ }
+ if ($type(this.options.grid) == 'number') this.options.grid = {'x': this.options.grid, 'y': this.options.grid};
+ this.document.addEvents({mousemove: this.bound.check, mouseup: this.bound.cancel});
+ this.document.addEvent(this.selection, this.bound.eventStop);
+ },
+
+ check: function(event){
+ if (this.options.preventDefault) event.preventDefault();
+ var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
+ if (distance > this.options.snap){
+ this.cancel();
+ this.document.addEvents({
+ mousemove: this.bound.drag,
+ mouseup: this.bound.stop
+ });
+ this.fireEvent('start', this.element).fireEvent('snap', this.element);
+ }
+ },
+
+ drag: function(event){
+ if (this.options.preventDefault) event.preventDefault();
+ this.mouse.now = event.page;
+ for (var z in this.options.modifiers){
+ if (!this.options.modifiers[z]) continue;
+ this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
+ if (this.options.invert) this.value.now[z] *= -1;
+ if (this.options.limit && this.limit[z]){
+ if ($chk(this.limit[z][1]) && (this.value.now[z] > this.limit[z][1])){
+ this.value.now[z] = this.limit[z][1];
+ } else if ($chk(this.limit[z][0]) && (this.value.now[z] < this.limit[z][0])){
+ this.value.now[z] = this.limit[z][0];
+ }
+ }
+ if (this.options.grid[z]) this.value.now[z] -= (this.value.now[z] % this.options.grid[z]);
+ if (this.options.style) this.element.setStyle(this.options.modifiers[z], this.value.now[z] + this.options.unit);
+ else this.element[this.options.modifiers[z]] = this.value.now[z];
+ }
+ this.fireEvent('drag', this.element);
+ },
+
+ cancel: function(event){
+ this.document.removeEvent('mousemove', this.bound.check);
+ this.document.removeEvent('mouseup', this.bound.cancel);
+ if (event){
+ this.document.removeEvent(this.selection, this.bound.eventStop);
+ this.fireEvent('cancel', this.element);
+ }
+ },
+
+ stop: function(event){
+ this.document.removeEvent(this.selection, this.bound.eventStop);
+ this.document.removeEvent('mousemove', this.bound.drag);
+ this.document.removeEvent('mouseup', this.bound.stop);
+ if (event) this.fireEvent('complete', this.element);
+ }
+
+});
+
+Element.implement({
+
+ makeResizable: function(options){
+ return new Drag(this, $merge({modifiers: {'x': 'width', 'y': 'height'}}, options));
+ }
+
+});
+
+/*
+Script: Drag.Move.js
+ A Drag extension that provides support for the constraining of draggables to containers and droppables.
+
+License:
+ MIT-style license.
+*/
+
+Drag.Move = new Class({
+
+ Extends: Drag,
+
+ options: {
+ droppables: [],
+ container: false
+ },
+
+ initialize: function(element, options){
+ this.parent(element, options);
+ this.droppables = $$(this.options.droppables);
+ this.container = $(this.options.container);
+ if (this.container && $type(this.container) != 'element') this.container = $(this.container.getDocument().body);
+ element = this.element;
+
+ var current = element.getStyle('position');
+ var position = (current != 'static') ? current : 'absolute';
+ if (element.getStyle('left') == 'auto' || element.getStyle('top') == 'auto') element.position(element.getPosition(element.offsetParent));
+
+ element.setStyle('position', position);
+
+ this.addEvent('start', function(){
+ this.checkDroppables();
+ }, true);
+ },
+
+ start: function(event){
+ if (this.container){
+ var el = this.element, cont = this.container, ccoo = cont.getCoordinates(el.offsetParent), cps = {}, ems = {};
+
+ ['top', 'right', 'bottom', 'left'].each(function(pad){
+ cps[pad] = cont.getStyle('padding-' + pad).toInt();
+ ems[pad] = el.getStyle('margin-' + pad).toInt();
+ }, this);
+
+ var width = el.offsetWidth + ems.left + ems.right, height = el.offsetHeight + ems.top + ems.bottom;
+ var x = [ccoo.left + cps.left, ccoo.right - cps.right - width];
+ var y = [ccoo.top + cps.top, ccoo.bottom - cps.bottom - height];
+
+ this.options.limit = {x: x, y: y};
+ }
+ this.parent(event);
+ },
+
+ checkAgainst: function(el){
+ el = el.getCoordinates();
+ var now = this.mouse.now;
+ return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
+ },
+
+ checkDroppables: function(){
+ var overed = this.droppables.filter(this.checkAgainst, this).getLast();
+ if (this.overed != overed){
+ if (this.overed) this.fireEvent('leave', [this.element, this.overed]);
+ if (overed){
+ this.overed = overed;
+ this.fireEvent('enter', [this.element, overed]);
+ } else {
+ this.overed = null;
+ }
+ }
+ },
+
+ drag: function(event){
+ this.parent(event);
+ if (this.droppables.length) this.checkDroppables();
+ },
+
+ stop: function(event){
+ this.checkDroppables();
+ this.fireEvent('drop', [this.element, this.overed]);
+ this.overed = null;
+ return this.parent(event);
+ }
+
+});
+
+Element.implement({
+
+ makeDraggable: function(options){
+ return new Drag.Move(this, options);
+ }
+
+});
+
+
+/*
+Script: Hash.Cookie.js
+ Class for creating, reading, and deleting Cookies in JSON format.
+
+License:
+ MIT-style license.
+*/
+
+Hash.Cookie = new Class({
+
+ Extends: Cookie,
+
+ options: {
+ autoSave: true
+ },
+
+ initialize: function(name, options){
+ this.parent(name, options);
+ this.load();
+ },
+
+ save: function(){
+ var value = JSON.encode(this.hash);
+ if (!value || value.length > 4096) return false; //cookie would be truncated!
+ if (value == '{}') this.dispose();
+ else this.write(value);
+ return true;
+ },
+
+ load: function(){
+ this.hash = new Hash(JSON.decode(this.read(), true));
+ return this;
+ }
+
+});
+
+Hash.Cookie.implement((function(){
+
+ var methods = {};
+
+ Hash.each(Hash.prototype, function(method, name){
+ methods[name] = function(){
+ var value = method.apply(this.hash, arguments);
+ if (this.options.autoSave) this.save();
+ return value;
+ };
+ });
+
+ return methods;
+
+})());
+
+/*
+Script: Color.js
+ Class for creating and manipulating colors in JavaScript. Supports HSB -> RGB Conversions and vice versa.
+
+License:
+ MIT-style license.
+*/
+
+var Color = new Native({
+
+ initialize: function(color, type){
+ if (arguments.length >= 3){
+ type = "rgb"; color = Array.slice(arguments, 0, 3);
+ } else if (typeof color == 'string'){
+ if (color.match(/rgb/)) color = color.rgbToHex().hexToRgb(true);
+ else if (color.match(/hsb/)) color = color.hsbToRgb();
+ else color = color.hexToRgb(true);
+ }
+ type = type || 'rgb';
+ switch (type){
+ case 'hsb':
+ var old = color;
+ color = color.hsbToRgb();
+ color.hsb = old;
+ break;
+ case 'hex': color = color.hexToRgb(true); break;
+ }
+ color.rgb = color.slice(0, 3);
+ color.hsb = color.hsb || color.rgbToHsb();
+ color.hex = color.rgbToHex();
+ return $extend(color, this);
+ }
+
+});
+
+Color.implement({
+
+ mix: function(){
+ var colors = Array.slice(arguments);
+ var alpha = ($type(colors.getLast()) == 'number') ? colors.pop() : 50;
+ var rgb = this.slice();
+ colors.each(function(color){
+ color = new Color(color);
+ for (var i = 0; i < 3; i++) rgb[i] = Math.round((rgb[i] / 100 * (100 - alpha)) + (color[i] / 100 * alpha));
+ });
+ return new Color(rgb, 'rgb');
+ },
+
+ invert: function(){
+ return new Color(this.map(function(value){
+ return 255 - value;
+ }));
+ },
+
+ setHue: function(value){
+ return new Color([value, this.hsb[1], this.hsb[2]], 'hsb');
+ },
+
+ setSaturation: function(percent){
+ return new Color([this.hsb[0], percent, this.hsb[2]], 'hsb');
+ },
+
+ setBrightness: function(percent){
+ return new Color([this.hsb[0], this.hsb[1], percent], 'hsb');
+ }
+
+});
+
+function $RGB(r, g, b){
+ return new Color([r, g, b], 'rgb');
+};
+
+function $HSB(h, s, b){
+ return new Color([h, s, b], 'hsb');
+};
+
+function $HEX(hex){
+ return new Color(hex, 'hex');
+};
+
+Array.implement({
+
+ rgbToHsb: function(){
+ var red = this[0], green = this[1], blue = this[2];
+ var hue, saturation, brightness;
+ var max = Math.max(red, green, blue), min = Math.min(red, green, blue);
+ var delta = max - min;
+ brightness = max / 255;
+ saturation = (max != 0) ? delta / max : 0;
+ if (saturation == 0){
+ hue = 0;
+ } else {
+ var rr = (max - red) / delta;
+ var gr = (max - green) / delta;
+ var br = (max - blue) / delta;
+ if (red == max) hue = br - gr;
+ else if (green == max) hue = 2 + rr - br;
+ else hue = 4 + gr - rr;
+ hue /= 6;
+ if (hue < 0) hue++;
+ }
+ return [Math.round(hue * 360), Math.round(saturation * 100), Math.round(brightness * 100)];
+ },
+
+ hsbToRgb: function(){
+ var br = Math.round(this[2] / 100 * 255);
+ if (this[1] == 0){
+ return [br, br, br];
+ } else {
+ var hue = this[0] % 360;
+ var f = hue % 60;
+ var p = Math.round((this[2] * (100 - this[1])) / 10000 * 255);
+ var q = Math.round((this[2] * (6000 - this[1] * f)) / 600000 * 255);
+ var t = Math.round((this[2] * (6000 - this[1] * (60 - f))) / 600000 * 255);
+ switch (Math.floor(hue / 60)){
+ case 0: return [br, t, p];
+ case 1: return [q, br, p];
+ case 2: return [p, br, t];
+ case 3: return [p, q, br];
+ case 4: return [t, p, br];
+ case 5: return [br, p, q];
+ }
+ }
+ return false;
+ }
+
+});
+
+String.implement({
+
+ rgbToHsb: function(){
+ var rgb = this.match(/\d{1,3}/g);
+ return (rgb) ? hsb.rgbToHsb() : null;
+ },
+
+ hsbToRgb: function(){
+ var hsb = this.match(/\d{1,3}/g);
+ return (hsb) ? hsb.hsbToRgb() : null;
+ }
+
+});
+
+
+/*
+Script: Group.js
+ Class for monitoring collections of events
+
+License:
+ MIT-style license.
+*/
+
+var Group = new Class({
+
+ initialize: function(){
+ this.instances = Array.flatten(arguments);
+ this.events = {};
+ this.checker = {};
+ },
+
+ addEvent: function(type, fn){
+ this.checker[type] = this.checker[type] || {};
+ this.events[type] = this.events[type] || [];
+ if (this.events[type].contains(fn)) return false;
+ else this.events[type].push(fn);
+ this.instances.each(function(instance, i){
+ instance.addEvent(type, this.check.bind(this, [type, instance, i]));
+ }, this);
+ return this;
+ },
+
+ check: function(type, instance, i){
+ this.checker[type][i] = true;
+ var every = this.instances.every(function(current, j){
+ return this.checker[type][j] || false;
+ }, this);
+ if (!every) return;
+ this.checker[type] = {};
+ this.events[type].each(function(event){
+ event.call(this, this.instances, instance);
+ }, this);
+ }
+
+});
+
+
+/*
+Script: Assets.js
+ Provides methods to dynamically load JavaScript, CSS, and Image files into the document.
+
+License:
+ MIT-style license.
+*/
+
+var Asset = new Hash({
+
+ javascript: function(source, properties){
+ properties = $extend({
+ onload: $empty,
+ document: document,
+ check: $lambda(true)
+ }, properties);
+
+ var script = new Element('script', {'src': source, 'type': 'text/javascript'});
+
+ var load = properties.onload.bind(script), check = properties.check, doc = properties.document;
+ delete properties.onload; delete properties.check; delete properties.document;
+
+ script.addEvents({
+ load: load,
+ readystatechange: function(){
+ if (['loaded', 'complete'].contains(this.readyState)) load();
+ }
+ }).setProperties(properties);
+
+
+ if (Browser.Engine.webkit419) var checker = (function(){
+ if (!$try(check)) return;
+ $clear(checker);
+ load();
+ }).periodical(50);
+
+ return script.inject(doc.head);
+ },
+
+ css: function(source, properties){
+ return new Element('link', $merge({
+ 'rel': 'stylesheet', 'media': 'screen', 'type': 'text/css', 'href': source
+ }, properties)).inject(document.head);
+ },
+
+ image: function(source, properties){
+ properties = $merge({
+ 'onload': $empty,
+ 'onabort': $empty,
+ 'onerror': $empty
+ }, properties);
+ var image = new Image();
+ var element = $(image) || new Element('img');
+ ['load', 'abort', 'error'].each(function(name){
+ var type = 'on' + name;
+ var event = properties[type];
+ delete properties[type];
+ image[type] = function(){
+ if (!image) return;
+ if (!element.parentNode){
+ element.width = image.width;
+ element.height = image.height;
+ }
+ image = image.onload = image.onabort = image.onerror = null;
+ event.delay(1, element, element);
+ element.fireEvent(name, element, 1);
+ };
+ });
+ image.src = element.src = source;
+ if (image && image.complete) image.onload.delay(1);
+ return element.setProperties(properties);
+ },
+
+ images: function(sources, options){
+ options = $merge({
+ onComplete: $empty,
+ onProgress: $empty
+ }, options);
+ if (!sources.push) sources = [sources];
+ var images = [];
+ var counter = 0;
+ sources.each(function(source){
+ var img = new Asset.image(source, {
+ 'onload': function(){
+ options.onProgress.call(this, counter, sources.indexOf(source));
+ counter++;
+ if (counter == sources.length) options.onComplete();
+ }
+ });
+ images.push(img);
+ });
+ return new Elements(images);
+ }
+
+});
+
+/*
+Script: Sortables.js
+ Class for creating a drag and drop sorting interface for lists of items.
+
+License:
+ MIT-style license.
+*/
+
+var Sortables = new Class({
+
+ Implements: [Events, Options],
+
+ options: {/*
+ onSort: $empty,
+ onStart: $empty,
+ onComplete: $empty,*/
+ snap: 4,
+ opacity: 1,
+ clone: false,
+ revert: false,
+ handle: false,
+ constrain: false
+ },
+
+ initialize: function(lists, options){
+ this.setOptions(options);
+ this.elements = [];
+ this.lists = [];
+ this.idle = true;
+
+ this.addLists($$($(lists) || lists));
+ if (!this.options.clone) this.options.revert = false;
+ if (this.options.revert) this.effect = new Fx.Morph(null, $merge({duration: 250, link: 'cancel'}, this.options.revert));
+ },
+
+ attach: function(){
+ this.addLists(this.lists);
+ return this;
+ },
+
+ detach: function(){
+ this.lists = this.removeLists(this.lists);
+ return this;
+ },
+
+ addItems: function(){
+ Array.flatten(arguments).each(function(element){
+ this.elements.push(element);
+ var start = element.retrieve('sortables:start', this.start.bindWithEvent(this, element));
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).addEvent('mousedown', start);
+ }, this);
+ return this;
+ },
+
+ addLists: function(){
+ Array.flatten(arguments).each(function(list){
+ this.lists.push(list);
+ this.addItems(list.getChildren());
+ }, this);
+ return this;
+ },
+
+ removeItems: function(){
+ var elements = [];
+ Array.flatten(arguments).each(function(element){
+ elements.push(element);
+ this.elements.erase(element);
+ var start = element.retrieve('sortables:start');
+ (this.options.handle ? element.getElement(this.options.handle) || element : element).removeEvent('mousedown', start);
+ }, this);
+ return $$(elements);
+ },
+
+ removeLists: function(){
+ var lists = [];
+ Array.flatten(arguments).each(function(list){
+ lists.push(list);
+ this.lists.erase(list);
+ this.removeItems(list.getChildren());
+ }, this);
+ return $$(lists);
+ },
+
+ getClone: function(event, element){
+ if (!this.options.clone) return new Element('div').inject(document.body);
+ if ($type(this.options.clone) == 'function') return this.options.clone.call(this, event, element, this.list);
+ return element.clone(true).setStyles({
+ 'margin': '0px',
+ 'position': 'absolute',
+ 'visibility': 'hidden',
+ 'width': element.getStyle('width')
+ }).inject(this.list).position(element.getPosition(element.getOffsetParent()));
+ },
+
+ getDroppables: function(){
+ var droppables = this.list.getChildren();
+ if (!this.options.constrain) droppables = this.lists.concat(droppables).erase(this.list);
+ return droppables.erase(this.clone).erase(this.element);
+ },
+
+ insert: function(dragging, element){
+ var where = 'inside';
+ if (this.lists.contains(element)){
+ this.list = element;
+ this.drag.droppables = this.getDroppables();
+ } else {
+ where = this.element.getAllPrevious().contains(element) ? 'before' : 'after';
+ }
+ this.element.inject(element, where);
+ this.fireEvent('sort', [this.element, this.clone]);
+ },
+
+ start: function(event, element){
+ if (!this.idle) return;
+ this.idle = false;
+ this.element = element;
+ this.opacity = element.get('opacity');
+ this.list = element.getParent();
+ this.clone = this.getClone(event, element);
+
+ this.drag = new Drag.Move(this.clone, {
+ snap: this.options.snap,
+ container: this.options.constrain && this.element.getParent(),
+ droppables: this.getDroppables(),
+ onSnap: function(){
+ event.stop();
+ this.clone.setStyle('visibility', 'visible');
+ this.element.set('opacity', this.options.opacity || 0);
+ this.fireEvent('start', [this.element, this.clone]);
+ }.bind(this),
+ onEnter: this.insert.bind(this),
+ onCancel: this.reset.bind(this),
+ onComplete: this.end.bind(this)
+ });
+
+ this.clone.inject(this.element, 'before');
+ this.drag.start(event);
+ },
+
+ end: function(){
+ this.drag.detach();
+ this.element.set('opacity', this.opacity);
+ if (this.effect){
+ var dim = this.element.getStyles('width', 'height');
+ var pos = this.clone.computePosition(this.element.getPosition(this.clone.offsetParent));
+ this.effect.element = this.clone;
+ this.effect.start({
+ top: pos.top,
+ left: pos.left,
+ width: dim.width,
+ height: dim.height,
+ opacity: 0.25
+ }).chain(this.reset.bind(this));
+ } else {
+ this.reset();
+ }
+ },
+
+ reset: function(){
+ this.idle = true;
+ this.clone.destroy();
+ this.fireEvent('complete', this.element);
+ },
+
+ serialize: function(){
+ var params = Array.link(arguments, {modifier: Function.type, index: $defined});
+ var serial = this.lists.map(function(list){
+ return list.getChildren().map(params.modifier || function(element){
+ return element.get('id');
+ }, this);
+ }, this);
+
+ var index = params.index;
+ if (this.lists.length == 1) index = 0;
+ return $chk(index) && index >= 0 && index < this.lists.length ? serial[index] : serial;
+ }
+
+});
+
+/*
+Script: Tips.js
+ Class for creating nice tips that follow the mouse cursor when hovering an element.
+
+License:
+ MIT-style license.
+*/
+
+var Tips = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ onShow: function(tip){
+ tip.setStyle('visibility', 'visible');
+ },
+ onHide: function(tip){
+ tip.setStyle('visibility', 'hidden');
+ },
+ showDelay: 100,
+ hideDelay: 100,
+ className: null,
+ offsets: {x: 16, y: 16},
+ fixed: false
+ },
+
+ initialize: function(){
+ var params = Array.link(arguments, {options: Object.type, elements: $defined});
+ this.setOptions(params.options || null);
+
+ this.tip = new Element('div').inject(document.body);
+
+ if (this.options.className) this.tip.addClass(this.options.className);
+
+ var top = new Element('div', {'class': 'tip-top'}).inject(this.tip);
+ this.container = new Element('div', {'class': 'tip'}).inject(this.tip);
+ var bottom = new Element('div', {'class': 'tip-bottom'}).inject(this.tip);
+
+ this.tip.setStyles({position: 'absolute', top: 0, left: 0, visibility: 'hidden'});
+
+ if (params.elements) this.attach(params.elements);
+ },
+
+ attach: function(elements){
+ $$(elements).each(function(element){
+ var title = element.retrieve('tip:title', element.get('title'));
+ var text = element.retrieve('tip:text', element.get('rel') || element.get('href'));
+ var enter = element.retrieve('tip:enter', this.elementEnter.bindWithEvent(this, element));
+ var leave = element.retrieve('tip:leave', this.elementLeave.bindWithEvent(this, element));
+ element.addEvents({mouseenter: enter, mouseleave: leave});
+ if (!this.options.fixed){
+ var move = element.retrieve('tip:move', this.elementMove.bindWithEvent(this, element));
+ element.addEvent('mousemove', move);
+ }
+ element.store('tip:native', element.get('title'));
+ element.erase('title');
+ }, this);
+ return this;
+ },
+
+ detach: function(elements){
+ $$(elements).each(function(element){
+ element.removeEvent('mouseenter', element.retrieve('tip:enter') || $empty);
+ element.removeEvent('mouseleave', element.retrieve('tip:leave') || $empty);
+ element.removeEvent('mousemove', element.retrieve('tip:move') || $empty);
+ element.eliminate('tip:enter').eliminate('tip:leave').eliminate('tip:move');
+ var original = element.retrieve('tip:native');
+ if (original) element.set('title', original);
+ });
+ return this;
+ },
+
+ elementEnter: function(event, element){
+
+ $A(this.container.childNodes).each(Element.dispose);
+
+ var title = element.retrieve('tip:title');
+
+ if (title){
+ this.titleElement = new Element('div', {'class': 'tip-title'}).inject(this.container);
+ this.fill(this.titleElement, title);
+ }
+
+ var text = element.retrieve('tip:text');
+ if (text){
+ this.textElement = new Element('div', {'class': 'tip-text'}).inject(this.container);
+ this.fill(this.textElement, text);
+ }
+
+ this.timer = $clear(this.timer);
+ this.timer = this.show.delay(this.options.showDelay, this);
+
+ this.position((!this.options.fixed) ? event : {page: element.getPosition()});
+ },
+
+ elementLeave: function(event){
+ $clear(this.timer);
+ this.timer = this.hide.delay(this.options.hideDelay, this);
+ },
+
+ elementMove: function(event){
+ this.position(event);
+ },
+
+ position: function(event){
+ var size = window.getSize(), scroll = window.getScroll();
+ var tip = {x: this.tip.offsetWidth, y: this.tip.offsetHeight};
+ var props = {x: 'left', y: 'top'};
+ for (var z in props){
+ var pos = event.page[z] + this.options.offsets[z];
+ if ((pos + tip[z] - scroll[z]) > size[z]) pos = event.page[z] - this.options.offsets[z] - tip[z];
+ this.tip.setStyle(props[z], pos);
+ }
+ },
+
+ fill: function(element, contents){
+ (typeof contents == 'string') ? element.set('html', contents) : element.adopt(contents);
+ },
+
+ show: function(){
+ this.fireEvent('show', this.tip);
+ },
+
+ hide: function(){
+ this.fireEvent('hide', this.tip);
+ }
+
+});
+
+/*
+Script: SmoothScroll.js
+ Class for creating a smooth scrolling effect to all internal links on the page.
+
+License:
+ MIT-style license.
+*/
+
+var SmoothScroll = new Class({
+
+ Extends: Fx.Scroll,
+
+ initialize: function(options, context){
+ context = context || document;
+ var doc = context.getDocument(), win = context.getWindow();
+ this.parent(doc, options);
+ this.links = (this.options.links) ? $$(this.options.links) : $$(doc.links);
+ var location = win.location.href.match(/^[^#]*/)[0] + '#';
+ this.links.each(function(link){
+ if (link.href.indexOf(location) != 0) return;
+ var anchor = link.href.substr(location.length);
+ if (anchor && $(anchor)) this.useLink(link, anchor);
+ }, this);
+ if (!Browser.Engine.webkit419) this.addEvent('complete', function(){
+ win.location.hash = this.anchor;
+ }, true);
+ },
+
+ useLink: function(link, anchor){
+ link.addEvent('click', function(event){
+ this.anchor = anchor;
+ this.toElement(anchor);
+ event.stop();
+ }.bind(this));
+ }
+
+});
+
+/*
+Script: Slider.js
+ Class for creating horizontal and vertical slider controls.
+
+License:
+ MIT-style license.
+*/
+
+var Slider = new Class({
+
+ Implements: [Events, Options],
+
+ options: {/*
+ onChange: $empty,
+ onComplete: $empty,*/
+ onTick: function(position){
+ if(this.options.snap) position = this.toPosition(this.step);
+ this.knob.setStyle(this.property, position);
+ },
+ snap: false,
+ offset: 0,
+ range: false,
+ wheel: false,
+ steps: 100,
+ mode: 'horizontal'
+ },
+
+ initialize: function(element, knob, options){
+ this.setOptions(options);
+ this.element = $(element);
+ this.knob = $(knob);
+ this.previousChange = this.previousEnd = this.step = -1;
+ this.element.addEvent('mousedown', this.clickedElement.bind(this));
+ if (this.options.wheel) this.element.addEvent('mousewheel', this.scrolledElement.bindWithEvent(this));
+ var offset, limit = {}, modifiers = {'x': false, 'y': false};
+ switch (this.options.mode){
+ case 'vertical':
+ this.axis = 'y';
+ this.property = 'top';
+ offset = 'offsetHeight';
+ break;
+ case 'horizontal':
+ this.axis = 'x';
+ this.property = 'left';
+ offset = 'offsetWidth';
+ }
+ this.half = this.knob[offset] / 2;
+ this.full = this.element[offset] - this.knob[offset] + (this.options.offset * 2);
+ this.min = $chk(this.options.range[0]) ? this.options.range[0] : 0;
+ this.max = $chk(this.options.range[1]) ? this.options.range[1] : this.options.steps;
+ this.range = this.max - this.min;
+ this.steps = this.options.steps || this.full;
+ this.stepSize = Math.abs(this.range) / this.steps;
+ this.stepWidth = this.stepSize * this.full / Math.abs(this.range) ;
+
+ this.knob.setStyle('position', 'relative').setStyle(this.property, - this.options.offset);
+ modifiers[this.axis] = this.property;
+ limit[this.axis] = [- this.options.offset, this.full - this.options.offset];
+ this.drag = new Drag(this.knob, {
+ snap: 0,
+ limit: limit,
+ modifiers: modifiers,
+ onDrag: this.draggedKnob.bind(this),
+ onStart: this.draggedKnob.bind(this),
+ onComplete: function(){
+ this.draggedKnob();
+ this.end();
+ }.bind(this)
+ });
+ if (this.options.snap) {
+ this.drag.options.grid = Math.ceil(this.stepWidth);
+ this.drag.options.limit[this.axis][1] = this.full;
+ }
+ },
+
+ set: function(step){
+ if (!((this.range > 0) ^ (step < this.min))) step = this.min;
+ if (!((this.range > 0) ^ (step > this.max))) step = this.max;
+
+ this.step = Math.round(step);
+ this.checkStep();
+ this.end();
+ this.fireEvent('tick', this.toPosition(this.step));
+ return this;
+ },
+
+ clickedElement: function(event){
+ var dir = this.range < 0 ? -1 : 1;
+ var position = event.page[this.axis] - this.element.getPosition()[this.axis] - this.half;
+ position = position.limit(-this.options.offset, this.full -this.options.offset);
+
+ this.step = Math.round(this.min + dir * this.toStep(position));
+ this.checkStep();
+ this.end();
+ this.fireEvent('tick', position);
+ },
+
+ scrolledElement: function(event){
+ var mode = (this.options.mode == 'horizontal') ? (event.wheel < 0) : (event.wheel > 0);
+ this.set(mode ? this.step - this.stepSize : this.step + this.stepSize);
+ event.stop();
+ },
+
+ draggedKnob: function(){
+ var dir = this.range < 0 ? -1 : 1;
+ var position = this.drag.value.now[this.axis];
+ position = position.limit(-this.options.offset, this.full -this.options.offset);
+ this.step = Math.round(this.min + dir * this.toStep(position));
+ this.checkStep();
+ },
+
+ checkStep: function(){
+ if (this.previousChange != this.step){
+ this.previousChange = this.step;
+ this.fireEvent('change', this.step);
+ }
+ },
+
+ end: function(){
+ if (this.previousEnd !== this.step){
+ this.previousEnd = this.step;
+ this.fireEvent('complete', this.step + '');
+ }
+ },
+
+ toStep: function(position){
+ var step = (position + this.options.offset) * this.stepSize / this.full * this.steps;
+ return this.options.steps ? Math.round(step -= step % this.stepSize) : step;
+ },
+
+ toPosition: function(step){
+ return (this.full * Math.abs(this.min - step)) / (this.steps * this.stepSize) - this.options.offset;
+ }
+
+});
+
+/*
+Script: Scroller.js
+ Class which scrolls the contents of any Element (including the window) when the mouse reaches the Element's boundaries.
+
+License:
+ MIT-style license.
+*/
+
+var Scroller = new Class({
+
+ Implements: [Events, Options],
+
+ options: {
+ area: 20,
+ velocity: 1,
+ onChange: function(x, y){
+ this.element.scrollTo(x, y);
+ }
+ },
+
+ initialize: function(element, options){
+ this.setOptions(options);
+ this.element = $(element);
+ this.listener = ($type(this.element) != 'element') ? $(this.element.getDocument().body) : this.element;
+ this.timer = null;
+ this.coord = this.getCoords.bind(this);
+ },
+
+ start: function(){
+ this.listener.addEvent('mousemove', this.coord);
+ },
+
+ stop: function(){
+ this.listener.removeEvent('mousemove', this.coord);
+ this.timer = $clear(this.timer);
+ },
+
+ getCoords: function(event){
+ this.page = (this.listener.get('tag') == 'body') ? event.client : event.page;
+ if (!this.timer) this.timer = this.scroll.periodical(50, this);
+ },
+
+ scroll: function(){
+ var size = this.element.getSize(), scroll = this.element.getScroll(), pos = this.element.getPosition(), change = {'x': 0, 'y': 0};
+ for (var z in this.page){
+ if (this.page[z] < (this.options.area + pos[z]) && scroll[z] != 0)
+ change[z] = (this.page[z] - this.options.area - pos[z]) * this.options.velocity;
+ else if (this.page[z] + this.options.area > (size[z] + pos[z]) && size[z] + size[z] != scroll[z])
+ change[z] = (this.page[z] - size[z] + this.options.area - pos[z]) * this.options.velocity;
+ }
+ if (change.y || change.x) this.fireEvent('change', [scroll.x + change.x, scroll.y + change.y]);
+ }
+
+});
+
+/*
+Script: Accordion.js
+ An Fx.Elements extension which allows you to easily create accordion type controls.
+
+License:
+ MIT-style license.
+*/
+
+var Accordion = new Class({
+
+ Extends: Fx.Elements,
+
+ options: {/*
+ onActive: $empty,
+ onBackground: $empty,*/
+ display: 0,
+ show: false,
+ height: true,
+ width: false,
+ opacity: true,
+ fixedHeight: false,
+ fixedWidth: false,
+ wait: false,
+ alwaysHide: false
+ },
+
+ initialize: function(){
+ var params = Array.link(arguments, {'container': Element.type, 'options': Object.type, 'togglers': $defined, 'elements': $defined});
+ this.parent(params.elements, params.options);
+ this.togglers = $$(params.togglers);
+ this.container = $(params.container);
+ this.previous = -1;
+ if (this.options.alwaysHide) this.options.wait = true;
+ if ($chk(this.options.show)){
+ this.options.display = false;
+ this.previous = this.options.show;
+ }
+ if (this.options.start){
+ this.options.display = false;
+ this.options.show = false;
+ }
+ this.effects = {};
+ if (this.options.opacity) this.effects.opacity = 'fullOpacity';
+ if (this.options.width) this.effects.width = this.options.fixedWidth ? 'fullWidth' : 'offsetWidth';
+ if (this.options.height) this.effects.height = this.options.fixedHeight ? 'fullHeight' : 'scrollHeight';
+ for (var i = 0, l = this.togglers.length; i < l; i++) this.addSection(this.togglers[i], this.elements[i]);
+ this.elements.each(function(el, i){
+ if (this.options.show === i){
+ this.fireEvent('active', [this.togglers[i], el]);
+ } else {
+ for (var fx in this.effects) el.setStyle(fx, 0);
+ }
+ }, this);
+ if ($chk(this.options.display)) this.display(this.options.display);
+ },
+
+ addSection: function(toggler, element, pos){
+ toggler = $(toggler);
+ element = $(element);
+ var test = this.togglers.contains(toggler);
+ var len = this.togglers.length;
+ this.togglers.include(toggler);
+ this.elements.include(element);
+ if (len && (!test || pos)){
+ pos = $pick(pos, len - 1);
+ toggler.inject(this.togglers[pos], 'before');
+ element.inject(toggler, 'after');
+ } else if (this.container && !test){
+ toggler.inject(this.container);
+ element.inject(this.container);
+ }
+ var idx = this.togglers.indexOf(toggler);
+ toggler.addEvent('click', this.display.bind(this, idx));
+ if (this.options.height) element.setStyles({'padding-top': 0, 'border-top': 'none', 'padding-bottom': 0, 'border-bottom': 'none'});
+ if (this.options.width) element.setStyles({'padding-left': 0, 'border-left': 'none', 'padding-right': 0, 'border-right': 'none'});
+ element.fullOpacity = 1;
+ if (this.options.fixedWidth) element.fullWidth = this.options.fixedWidth;
+ if (this.options.fixedHeight) element.fullHeight = this.options.fixedHeight;
+ element.setStyle('overflow', 'hidden');
+ if (!test){
+ for (var fx in this.effects) element.setStyle(fx, 0);
+ }
+ return this;
+ },
+
+ display: function(index){
+ index = ($type(index) == 'element') ? this.elements.indexOf(index) : index;
+ if ((this.timer && this.options.wait) || (index === this.previous && !this.options.alwaysHide)) return this;
+ this.previous = index;
+ var obj = {};
+ this.elements.each(function(el, i){
+ obj[i] = {};
+ var hide = (i != index) || (this.options.alwaysHide && (el.offsetHeight > 0));
+ this.fireEvent(hide ? 'background' : 'active', [this.togglers[i], el]);
+ for (var fx in this.effects) obj[i][fx] = hide ? 0 : el[this.effects[fx]];
+ }, this);
+ return this.start(obj);
+ }
+
+});// $Id: common.js 782 2008-08-26 17:36:11Z pspencer $
+/**
+ * Class: Jx
+ * Jx is a global singleton object that contains the entire Jx library
+ * within it. All Jx functions, attributes and classes are accessed
+ * through the global Jx object. Jx should not create any other
+ * global variables, if you discover that it does then please report
+ * it as a bug
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+
+/* firebug console supressor for IE/Safari/Opera */
+window.addEvent('load', function() {
+ if (!("console" in window) || !("firebug" in window.console)) {
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
+ "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
+
+ window.console = {};
+ for (var i = 0; i < names.length; ++i) {
+ window.console[names[i]] = function() {};
+ }
+ }
+});
+/* inspired by extjs, removes css image flicker and related problems in IE 6 */
+(function() {
+ var ua = navigator.userAgent.toLowerCase();
+ var isIE = ua.indexOf("msie") > -1,
+ isIE7 = ua.indexOf("msie 7") > -1;
+ if(isIE && !isIE7) {
+ try {
+ document.execCommand("BackgroundImageCache", false, true);
+ } catch(e) {}
+ }
+})();
+
+/* Setup global namespace
+ * If jxcore is loaded by jx.js, then the namespace and baseURL are
+ * already established
+ */
+if (typeof Jx == 'undefined') {
+ var Jx = {};
+ (function(){
+ var aScripts = document.getElementsByTagName('SCRIPT');
+ for (var i=0; i<aScripts.length; i++) {
+ var s = aScripts[i].src;
+ var matches = /(.*)(js|lib\/)jxlib(.*)/.exec(s);
+ if (matches && matches[0]) {
+ /**
+ * Property: {String} baseURL
+ * This is the URL that Jx was loaded from, it is
+ * automatically calculated from the script tag
+ * src property that included Jx.
+ *
+ * Note that this assumes that you are loading Jx
+ * from a js/ or lib/ folder in parallel to the
+ * images/ folder that contains the various images
+ * needed by Jx components. If you have a different
+ * folder structure, you can define Jx's base
+ * by including the following before including
+ * the jxlib javascript file:
+ *
+ * (code)
+ * Jx = {
+ * baseURL: 'some/path'
+ * }
+ * (end)
+ */
+ Jx.aPixel = document.createElement('img');
+ Jx.aPixel.src = matches[1]+'/images/a_pixel.png';
+ Jx.baseURL = Jx.aPixel.src.substring(0,
+ Jx.aPixel.src.indexOf('images/a_pixel.png'));
+
+ }
+ }
+ })();
+}
+
+/**
+ * Method: applyPNGFilter
+ *
+ * Static method that applies the PNG Filter Hack for IE browsers
+ * when showing 24bit PNG's. Used automatically for img tags with
+ * a class of png24.
+ *
+ * The filter is applied using a nifty feature of IE that allows javascript to
+ * be executed as part of a CSS style rule - this ensures that the hack only
+ * gets applied on IE browsers.
+ *
+ * Parameters:
+ *
+ * object {Object} the object (img) to which the filter needs to be applied.
+ */
+Jx.applyPNGFilter = function(o) {
+ var t=Jx.baseURL + "images/a_pixel.png";
+ if( o.src != t ) {
+ var s=o.src;
+ o.src = t;
+ o.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+s+"',sizingMethod='scale')";
+ }
+};
+
+Jx.imgQueue = []; //The queue of images to be loaded
+Jx.imgLoaded = {}; //a hash table of images that have been loaded and cached
+Jx.imagesLoading = 0; //counter for number of concurrent image loads
+
+/**
+ * Method: addToImgQueue
+ *
+ * request that an image be set to a DOM IMG element src attribute. This puts
+ * the image into a queue and there are private methods to manage that queue
+ * and limit image loading to 2 at a time.
+ *
+ * Parameters:
+ * obj - {Object} an object containing an element and src
+ * property, where element is the element to update and src
+ * is the url to the image.
+ */
+Jx.addToImgQueue = function(obj) {
+ if (Jx.imgLoaded[obj.src]) {
+ //if this image was already requested (i.e. it's in cache) just set it directly
+ obj.element.src = obj.src;
+ } else {
+ //otherwise stick it in the queue
+ Jx.imgQueue.push(obj);
+ Jx.imgLoaded[obj.src] = true;
+ }
+ //start the queue management process
+ Jx.checkImgQueue();
+};
+
+/**
+ * Method: checkImgQueue
+ *
+ * An internal method that ensures no more than 2 images are loading at a time.
+ */
+Jx.checkImgQueue = function() {
+ while (Jx.imagesLoading < 2 && Jx.imgQueue.length > 0) {
+ Jx.loadNextImg();
+ }
+};
+
+/**
+ * Method: loadNextImg
+ *
+ * An internal method actually populate the DOM element with the image source.
+ */
+Jx.loadNextImg = function() {
+ var obj = Jx.imgQueue.shift();
+ if (obj) {
+ ++Jx.imagesLoading;
+ obj.element.onload = function(){--Jx.imagesLoading; Jx.checkImgQueue();};
+ obj.element.onerror = function(){--Jx.imagesLoading; Jx.checkImgQueue();};
+ obj.element.src = obj.src;
+ }
+};
+
+/**
+ * Method: createIframeShim
+ * Creates a new iframe element that is intended to fill a container
+ * to mask out other operating system controls (scrollbars, inputs,
+ * buttons, etc) when HTML elements are supposed to be above them.
+ */
+Jx.createIframeShim = function() {
+ return new Element('iframe', {
+ 'class':'jxIframeShim',
+ 'scrolling':'no',
+ 'frameborder':0
+ });
+};
+
+/**
+ * Class: Jx.UniqueId
+ *
+ * Jx.UniqueId is used to assign unique ids to selected elements
+ * This is used to solve a problem where multiple external html
+ * fragments are loaded into the DOM via AJAX at runtime. It is
+ * not always possible to ensure that every element has a unique
+ * id. This is not a problem if you are using id for CSS styling
+ * but if you are using it to access elements using $() then
+ * you may get unexpected results.
+ *
+ * Jx.UniqueId is a mix-in class. Extend an existing class to
+ * enable it to handle unique ids. Register the ids that you
+ * want to be unique and then get a reference to those objects
+ * through the interface exposed by this class.
+ *
+ * The class retrieves the elements by id by walking a dom object
+ * and retains references to each of the actual DOM objects
+ * you have registered.
+ */
+Jx.UniqueId = new Class({
+ /**
+ * Property: {Array} uniqueIdRefs
+ *
+ * an array of references obtained from by registering ids
+ */
+ uniqueIdRefs: null,
+ /**
+ * Method: initUniqueId
+ *
+ * initialize the UniqueId object. This must be called prior to
+ * calling the <registerIds> function. Typically, it is called
+ * in the constructor of an object that includes Jx.UniqueId.
+ */
+ initUniqueId: function() {
+ this.uniqueIdRefs = [];
+ },
+ /**
+ * Method: deregisterIds
+ *
+ * removes all registered ids
+ */
+ deregisterIds: function() {
+ this.uniqueIdRefs = [];
+ },
+ /**
+ * Method: registerIds
+ *
+ * searches the domObj for each of the ids passed in and
+ * obtains a unique reference to them so that subsequent
+ * calls to <getObj> will return the right object.
+ *
+ * Parameters:
+ *
+ * aIds - {Array} an array of strings containing ids of DOM elements
+ * to register.
+ *
+ * domObj - {Object} an HTML element reference to search for unique
+ * ids within
+ */
+ registerIds: function (aIds, domObj) {
+ if (aIds.indexOf(domObj.id) != -1) {
+ this.uniqueIdRefs[domObj.id] = domObj;
+ }
+ for (var i=0; i<domObj.childNodes.length; i++) {
+ this.registerIds(aIds, domObj.childNodes[i]);
+ }
+ },
+ /**
+ * Method: getObj
+ *
+ * return an object by id if it was previously registered
+ *
+ * Parameters:
+ *
+ * id - {String} the original registered id to get the DOM object for
+ *
+ * Returns:
+ *
+ * {Object} returns an object or null if the requested id did not
+ * exist in the original DOM object or if the id was not registered.
+ */
+ getObj: function(id) {
+ return this.uniqueIdRefs[id] || null;
+ }
+});
+
+/**
+ * Class: Element
+ *
+ * Element is a global object provided by the mootools library. The
+ * functions documented here are extensions to the Element object provided
+ * by Jx to make cross-browser compatibility easier to achieve.
+ */
+Element.implement({
+ /**
+ * Method: getBoxSizing
+ *
+ * return the box sizing of an element, one of 'content-box' or
+ *'border-box'.
+ *
+ * Parameters:
+ *
+ * elem - {Object} the element to get the box sizing of.
+ *
+ * Returns:
+ * {String} the box sizing of the element.
+ */
+ getBoxSizing : function() {
+ var result = 'content-box';
+ if (Browser.Engine.trident || Browser.Engine.presto) {
+ var cm = document["compatMode"];
+ if (cm == "BackCompat" || cm == "QuirksMode") {
+ result = 'border-box';
+ } else {
+ result = 'content-box';
+ }
+ } else {
+ if (arguments.length == 0) {
+ node = document.documentElement;
+ }
+ var sizing = this.getStyle("-moz-box-sizing");
+ if (!sizing) {
+ sizing = this.getStyle("box-sizing");
+ }
+ result = (sizing ? sizing : 'content-box');
+ }
+ return result;
+ },
+ /**
+ * Method: getContentBoxSize
+ *
+ * return the size of the content area of an element. This is the size of
+ * the element less margins, padding, and borders.
+ *
+ * Parameters:
+ *
+ * elem - {Object} the element to get the content size of.
+ *
+ * Returns:
+ * {Object} an object with two properties, width and height, that
+ * are the size of the content area of the measured element.
+ */
+ getContentBoxSize : function() {
+ var w = this.offsetWidth;
+ var h = this.offsetHeight;
+ var padding = this.getPaddingSize();
+ var border = this.getBorderSize();
+ w = w - padding.left - padding.right - border.left - border.right;
+ h = h - padding.bottom - padding.top - border.bottom - border.top;
+ return {width: w, height: h};
+ },
+ /**
+ * Method: getBorderBoxSize
+ *
+ * return the size of the border area of an element. This is the size of
+ * the element less margins.
+ *
+ * Parameters:
+ *
+ * elem - {Object} the element to get the border sizing of.
+ *
+ * Returns:
+ * {Object} an object with two properties, width and height, that
+ * are the size of the border area of the measured element.
+ */
+ getBorderBoxSize: function() {
+ var w = this.offsetWidth;
+ var h = this.offsetHeight;
+ return {width: w, height: h};
+ },
+
+ /**
+ * Method: getMarginBoxSize
+ *
+ * return the size of the margin area of an element. This is the size of
+ * the element plus margins.
+ *
+ * Parameters:
+ *
+ * elem - {Object} the element to get the margin sizing of.
+ *
+ * Returns:
+ * {Object} an object with two properties, width and height, that
+ * are the size of the margin area of the measured element.
+ */
+ getMarginBoxSize: function() {
+ var margins = this.getMarginSize();
+ var w = this.offsetWidth + margins.left + margins.right;
+ var h = this.offsetHeight + margins.top + margins.bottom;
+ return {width: w, height: h};
+ },
+
+ /**
+ * Method: setContentBoxSize
+ *
+ * set either or both of the width and height of an element to
+ * the provided size. This function ensures that the content
+ * area of the element is the requested size and the resulting
+ * size of the element may be larger depending on padding and
+ * borders.
+ *
+ * Parameters:
+ *
+ * elem - {Object} the element to set the content area of.
+ *
+ * size - {Object} an object with a width and/or height property that is the size to set
+ * the content area of the element to.
+ */
+ setContentBoxSize : function(size) {
+ if (this.getBoxSizing() == 'border-box') {
+ var padding = this.getPaddingSize();
+ var border = this.getBorderSize();
+ if (typeof size.width != 'undefined') {
+ var width = (size.width + padding.left + padding.right + border.left + border.right);
+ if (width < 0) {
+ width = 0;
+ }
+ this.style.width = width + 'px';
+ }
+ if (typeof size.height != 'undefined') {
+ var height = (size.height + padding.top + padding.bottom + border.top + border.bottom);
+ if (height < 0) {
+ height = 0;
+ }
+ this.style.height = height + 'px';
+ }
+ } else {
+ if (typeof size.width != 'undefined') {
+ this.style.width = size.width + 'px';
+ }
+ if (typeof size.height != 'undefined') {
+ this.style.height = size.height + 'px';
+ }
+ }
+ },
+ /**
+ * Method: setBorderBoxSize
+ *
+ * set either or both of the width and height of an element to
+ * the provided size. This function ensures that the border
+ * size of the element is the requested size and the resulting
+ * content areaof the element may be larger depending on padding and
+ * borders.
+ *
+ * Parameters:
+ *
+ * elem - {Object} the element to set the border size of.
+ *
+ * size - {Object} an object with a width and/or height property that is the size to set
+ * the content area of the element to.
+ */
+ setBorderBoxSize : function(size) {
+ if (this.getBoxSizing() == 'content-box') {
+ var padding = this.getPaddingSize();
+ var border = this.getBorderSize();
+ var margin = this.getMarginSize();
+ if (typeof size.width != 'undefined') {
+ var width = (size.width - padding.left - padding.right - border.left - border.right - margin.left - margin.right);
+ if (width < 0) {
+ width = 0;
+ }
+ this.style.width = width + 'px';
+ }
+ if (typeof size.height != 'undefined') {
+ var height = (size.height - padding.top - padding.bottom - border.top - border.bottom - margin.top - margin.bottom);
+ if (height < 0) {
+ height = 0;
+ }
+ this.style.height = height + 'px';
+ }
+ } else {
+ if (typeof size.width != 'undefined' && size.width >= 0) {
+ this.style.width = size.width + 'px';
+ }
+ if (typeof size.height != 'undefined' && size.height >= 0) {
+ this.style.height = size.height + 'px';
+ }
+ }
+ },
+ /**
+ * Method: getPaddingSize
+ *
+ * returns the padding for each edge of an element
+ *
+ * Parameters:
+ *
+ * elem - {Object} The element to get the padding for.
+ *
+ * Returns:
+ * {Object} an object with properties left, top, right and bottom
+ * that contain the associated padding values.
+ */
+ getPaddingSize : function () {
+ var l = this.getNumber(this.getStyle('padding-left'));
+ var t = this.getNumber(this.getStyle('padding-top'));
+ var r = this.getNumber(this.getStyle('padding-right'));
+ var b = this.getNumber(this.getStyle('padding-bottom'));
+ return {left:l, top:t, right: r, bottom: b};
+ },
+ /**
+ * Method: getBorderSize
+ *
+ * returns the border size for each edge of an element
+ *
+ * Parameters:
+ *
+ * elem - {Object} The element to get the borders for.
+ *
+ * Returns:
+ * {Object} an object with properties left, top, right and bottom
+ * that contain the associated border values.
+ */
+ getBorderSize : function() {
+ var l = this.getNumber(this.getStyle('border-left-width'));
+ var t = this.getNumber(this.getStyle('border-top-width'));
+ var r = this.getNumber(this.getStyle('border-right-width'));
+ var b = this.getNumber(this.getStyle('border-bottom-width'));
+ return {left:l, top:t, right: r, bottom: b};
+ },
+ /**
+ * Method: getMarginSize
+ *
+ * returns the margin size for each edge of an element
+ *
+ * Parameters:
+ *
+ * elem - {Object} The element to get the margins for.
+ *
+ * Returns:
+ *: {Object} an object with properties left, top, right and bottom
+ * that contain the associated margin values.
+ */
+ getMarginSize : function() {
+ var l = this.getNumber(this.getStyle('margin-left'));
+ var t = this.getNumber(this.getStyle('margin-top'));
+ var r = this.getNumber(this.getStyle('margin-right'));
+ var b = this.getNumber(this.getStyle('margin-bottom'));
+ return {left:l, top:t, right: r, bottom: b};
+ },
+ /**
+ * Method: getNumber
+ *
+ * safely parse a number and return its integer value. A NaN value
+ * returns 0. CSS size values are also parsed correctly.
+ *
+ * Parameters:
+ *
+ * n - {Mixed} the string or object to parse.
+ *
+ * Returns:
+ * {Integer} the integer value that the parameter represents
+ */
+ getNumber: function(n) {
+ var result = n==null||isNaN(parseInt(n))?0:parseInt(n);
+ return result;
+ },
+ /**
+ * Method: getPageDimensions
+ *
+ * return the dimensions of the browser client area.
+ *
+ * Returns:
+ * {Object} an object containing a width and height property
+ * that represent the width and height of the browser client area.
+ */
+ getPageDimensions: function() {
+ return {width: window.getWidth(), height: window.getHeight()};
+ },
+
+ descendantOf: function(node) {
+ var parent = $(this.parentNode);
+ if (parent == node) {
+ return true;
+ } else if (!parent || !parent.parentNode) {
+ return null;
+ } else if (parent.parentNode === parent) {
+ return null;
+ } else {
+ return parent.descendantOf(node);
+ }
+ },
+
+ findElement: function(type) {
+ if (this.tagName == type) {
+ return this;
+ }
+ var parent = $(this.parentNode);
+ if (parent) {
+ if (parent.tagName == type) {
+ return parent;
+ } else if (!parent.parentNode || parent.parentNode == parent) {
+ return null;
+ } else {
+ return parent.findElement(type);
+ }
+ } else {
+ return null;
+ }
+ }
+} );
+
+/**
+ * Class: Jx.ContentLoader
+ *
+ * ContentLoader is a mix-in class that provides a consistent
+ * mechanism for other Jx controls to load content in one of
+ * four different ways:
+ *
+ * o using an existing element, by id
+ *
+ * o using an existing element, by object reference
+ *
+ * o using an HTML string
+ *
+ * o using a URL to get the content remotely
+ */
+Jx.ContentLoader = new Class ({
+ /**
+ * Property: contentIsLoaded
+ *
+ * tracks the load state of the content, specifically useful
+ * in the case of remote content.
+ */
+ contentIsLoaded: false,
+ /**
+ * Method: contentLoaded
+ *
+ * callback function that handles remote content
+ *
+ * Parameters:
+ *
+ * element - {Object} the element to put the content into
+ *
+ * options - {Object} the options that were passed to loadContent originally, only
+ * used to get the optional onContentLoaded callback function.
+ *
+ * r - {XmlHttpRequest} the XmlHttpRequest object that has the content.
+ */
+ contentLoaded: function() {
+ this.contentIsLoaded = true;
+ this.fireEvent('contentLoaded', this);
+ },
+ /**
+ * Method: contentLoadFailed
+ *
+ * callback function that handles failure to load remote content
+ *
+ * Parameters:
+ *
+ * options - {Object} the options that were passed to loadContent originally, only
+ * used to get the optional onContentLoadedFailed callback function.
+ *
+ * r - {XmlHttpRequest} the XmlHttpRequest object that has the failure code
+ */
+ contentLoadFailed: function(r) {
+ // we aren't waiting for content any more.
+ this.contentIsLoaded = true;
+ this.fireEvent('contentLoadFailed', this);
+ },
+ /**
+ * Method: loadContent
+ *
+ * triggers loading of content based on options set for the current
+ * object.
+ *
+ * Parameters:
+ * element - {Object} the element to insert the content into
+ *
+ * Options:
+ * content - {Mixed} content may be an HTML element reference, the
+ * id of an HTML element already in the DOM, or an HTML
+ * string that becomes the inner HTML of the element.
+ * contentURL - {String} the URL to load content from
+ *
+ * Events:
+ *
+ * ContentLoader adds the following events to an object. You can
+ * register for these events using the addEvent method or by providing
+ * callback functions via the on{EventName} properties in the options
+ * object
+ *
+ * contentLoaded - called when the content has been loaded. If the content
+ * is not asynchronous then this is called before loadContent returns.
+ * contentLoadFailed - called if the content fails to load, primarily
+ * useful when using the contentURL method of loading content.
+ */
+ loadContent: function(element) {
+ element = $(element);
+ if (this.options.content) {
+ var c;
+ if (this.options.content.domObj) {
+ c = $(this.options.content.domObj);
+ } else {
+ c = $(this.options.content);
+ }
+ if (c) {
+ element.appendChild(c);
+ this.contentIsLoaded = true;
+ } else {
+ element.innerHTML = this.options.content;
+ this.contentIsLoaded = true;
+ }
+ } else if (this.options.contentURL) {
+ this.contentIsLoaded = false;
+ new Request.HTML({
+ url: this.options.contentURL,
+ method:'get',
+ update: element,
+ onSuccess:this.contentLoaded.bind(this),
+ onFailure: this.contentLoadFailed.bind(this),
+ headers: {'If-Modified-Since': 'Sat, 1 Jan 2000 00:00:00 GMT'}
+ }).send();
+ } else {
+ this.contentIsLoaded = true;
+ }
+ if (this.contentIsLoaded) {
+ this.fireEvent('contentLoaded', this);
+ }
+ },
+
+ processContent: function(element) {
+ $A(element.childNodes).each(function(node){
+ if (node.tagName == 'INPUT' || node.tagName == 'SELECT' || node.tagName == 'TEXTAREA') {
+ if (node.type == 'button') {
+ node.addEvent('click', function(){
+ this.fireEvent('click', this, node);
+ });
+ } else {
+ node.addEvent('change', function(){
+ this.fireEvent('change',node);
+ });
+ }
+ } else {
+ if (node.childNodes) {
+ this.processContent(node);
+ }
+ }
+ }, this);
+ }
+});
+
+/**
+ * Class: Jx.AutoPosition
+ * Mix-in class that provides a method for positioning
+ * elements relative to other elements.
+ */
+Jx.AutoPosition = new Class({
+ /**
+ * Method: position
+ * positions an element relative to another element
+ * based on the provided options
+ *
+ * Parameters:
+ * element - the element to position
+ * relative - the element to position relative to
+ * options - the positioning options, see list below.
+ *
+ * Options:
+ * horizontal
+ * vertical
+ * offsets
+ */
+ position: function(element, relative, options) {
+ element = $(element);
+ relative = $(relative);
+ var hor = $splat(options.horizontal || ['center center']);
+ var ver = $splat(options.vertical || ['center center']);
+ var offsets = $merge({top:0,right:0,bottom:0,left:0}, options.offsets || {});
+
+ var page;
+ if (!$(element.parentNode) || element.parentNode == document.body) {
+ page = Element.getPageDimensions();
+ } else {
+ page = $(element.parentNode).getContentBoxSize(); //width, height
+ }
+ var coords = relative.getCoordinates(); //top, left, width, height
+ var size = element.getMarginBoxSize(); //width, height
+ var left;
+ var right;
+ var top;
+ var bottom;
+ if (!hor.some(function(opt) {
+ var parts = opt.split(' ');
+ if (parts.length != 2) {
+ return false;
+ }
+ if (!isNaN(parseInt(parts[0]))) {
+ left = parseInt(parts[0]);
+ } else {
+ switch(parts[0]) {
+ case 'right':
+ left = coords.left + coords.width;
+ break;
+ case 'center':
+ left = coords.left + Math.round(coords.width/2);
+ break;
+ case 'left':
+ default:
+ left = coords.left;
+ }
+ }
+ switch(parts[1]) {
+ case 'left':
+ left -= offsets.left;
+ right = left + size.width;
+ break;
+ case 'right':
+ left += offsets.right;
+ right = left;
+ left = left - size.width;
+ break;
+ case 'center':
+ default:
+ left = left - Math.round(size.width/2);
+ right = left + size.width;
+ }
+ return (left >= 0 && right <= page.width);
+ })) {
+ // all failed, snap the last position onto the page as best
+ // we can - can't do anything if the element is wider than the
+ // space available.
+ if (right > page.width) {
+ left = page.width - size.width;
+ }
+ if (left < 0) {
+ left = 0;
+ }
+ }
+ element.setStyle('left', left);
+
+ if (!ver.some(function(opt) {
+ var parts = opt.split(' ');
+ if (parts.length != 2) {
+ return false;
+ }
+ if (!isNaN(parseInt(parts[0]))) {
+ top = parseInt(parts[0]);
+ } else {
+ switch(parts[0]) {
+ case 'bottom':
+ top = coords.top + coords.height;
+ break;
+ case 'center':
+ top = coords.top + Math.round(coords.height/2);
+ break;
+ case 'top':
+ default:
+ top = coords.top;
+ }
+ }
+ switch(parts[1]) {
+ case 'top':
+ top -= offsets.top;
+ bottom = top + size.height;
+ break;
+ case 'bottom':
+ top += offsets.bottom;
+ bottom = top;
+ top = top - size.height;
+ break;
+ case 'center':
+ default:
+ top = top - Math.round(size.height/2);
+ bottom = top + size.height;
+ }
+ return (top >= 0 && bottom <= page.height);
+ })) {
+ // all failed, snap the last position onto the page as best
+ // we can - can't do anything if the element is higher than the
+ // space available.
+ if (bottom > page.height) {
+ top = page.height - size.height;
+ }
+ if (top < 0) {
+ top = 0;
+ }
+ }
+ element.setStyle('top', top);
+
+ /* update the jx layout if necessary */
+ var jxl = element.retrieve('jxLayout');
+ if (jxl) {
+ jxl.options.left = left;
+ jxl.options.top = top;
+ }
+ }
+});
+
+/**
+ * Class: Jx.Chrome
+ * A mix-in class that provides chrome helper functions. Chrome is the
+ * extraneous visual element that provides the look and feel to some elements
+ * i.e. dialogs. Chrome is added inside the element specified but may
+ * bleed outside the element to provide drop shadows etc. This is done by
+ * absolutely positioning the chrome objects in the container based on
+ * calculations using the margins, borders, and padding of the jxChrome
+ * class and the element it is added to.
+ *
+ * Chrome can consist of either pure CSS border and background colors, or
+ * a background-image on the jxChrome class. Using a background-image on
+ * the jxChrome class creates four images inside the chrome container that
+ * are positioned in the top-left, top-right, bottom-left and bottom-right
+ * corners of the chrome container and are sized to fill 50% of the width
+ * and height. The images are positioned and clipped such that the
+ * appropriate corners of the chrome image are displayed in those locations.
+ */
+Jx.Chrome = new Class({
+ /**
+ * Property: chrome
+ * the DOM element that contains the chrome
+ */
+ chrome: null,
+
+ /**
+ * Method: makeChrome
+ * create chrome on an element.
+ *
+ * Parameters:
+ * element - {HTMLElement} the element to put the chrome on.
+ */
+ makeChrome: function(element) {
+ var c = new Element('div', {
+ 'class':'jxChrome'
+ });
+
+ /* add to element so we can get the background image style */
+ element.adopt(c);
+
+ /* pick up any offset because of chrome, set
+ * through padding on the chrome object. Other code can then
+ * make use of these offset values to fix positioning.
+ */
+ this.chromeOffsets = c.getPaddingSize();
+ c.setStyle('padding', 0);
+
+ /* get the chrome image from the background image of the element */
+ var src = c.getStyle('backgroundImage');
+ if (!src.contains('http://')) {
+ src = null;
+ } else {
+ src = src.slice(4,-1);
+ /* this only seems to be IE and Opera, but they add quotes
+ * around the url - yuck
+ */
+ if (src.charAt(0) == '"') {
+ src = src.slice(1,-1);
+ }
+
+ /* and remove the background image */
+ c.setStyle('backgroundImage', 'none');
+
+ /* make chrome */
+ ['TL','TR','BL','BR'].each(function(s){
+ c.adopt(
+ new Element('div',{
+ 'class':'jxChrome'+s
+ }).adopt(
+ new Element('img',{
+ src:src
+ }))
+ );
+ }, this);
+ }
+ if (!window.opera) {
+ c.adopt(Jx.createIframeShim());
+ }
+
+ /* remove from DOM so the other resizing logic works as expected */
+ c.dispose();
+ this.chrome = c;
+ },
+ /**
+ * Method: showChrome
+ * show the chrome on an element. This creates the chrome if necessary.
+ * If the chrome has been previously created and not removed, you can
+ * call this without an element and it will just resize the chrome within
+ * its existing element. You can also pass in a different element from
+ * which the chrome was previously attached to and it will move the chrome
+ * to the new element.
+ *
+ * Parameters:
+ * element - {HTMLElement} the element to show the chrome on.
+ */
+ showChrome: function(element) {
+ element = $(element);
+ var jxl;
+ if (!this.chromeResizeHandler) {
+ this.chromeResizeHandler = this.showChrome.bind(this);
+ }
+ if (!this.chrome) {
+ this.makeChrome(element);
+ }
+ if (element && this.chrome.parentNode !== element) {
+ var p = $(this.chrome.parentNode);
+ if (p) {
+ jxl = p.retrieve('jxLayout');
+ if (jxl) {
+ jxl.removeEvent('sizeChange', this.chromeResizeHandler);
+ }
+ }
+ element.adopt(this.chrome);
+ jxl = element.retrieve('jxLayout');
+ if (jxl) {
+ jxl.addEvent('sizeChange', this.chromeResizeHandler);
+ }
+ }
+ this.resizeChrome();
+ },
+ /**
+ * Method: resizeChrome
+ * resizes the chrome to fit around its parent, should be called
+ * automatically if the parent is controlled by <Jx.Layout>,
+ * otherwise you will need to call this yourself if your chromed
+ * element changes size.
+ */
+ resizeChrome: function() {
+ // if (this.chrome && this.chrome.parentNode) {
+ // var p = $(this.chrome.parentNode);
+ // var padding = this.chrome.getPaddingSize();
+ // var chromeBorder = this.chrome.getBorderSize();
+ // var margin = p.getMarginSize();
+ // var border = p.getBorderSize();
+ // var size = p.getMarginBoxSize();
+ // this.chrome.setStyles({
+ // left: -(padding.left + chromeBorder.left + border.left + margin.left),
+ // top: -(padding.top + chromeBorder.top + border.top + margin.top)
+ // });
+ // this.chrome.setContentBoxSize(size);
+ // }
+ },
+ /**
+ * Method: hideChrome
+ * removes the chrome from the DOM. If you do this, you can't
+ * call showChrome with no arguments.
+ */
+ hideChrome: function() {
+ if (this.chrome) {
+ if (this.chrome.parentNode) {
+ var jxl = this.chrome.parentNode.retrieve('jxLayout');
+ if (jxl) {
+ jxl.removeEvent('sizeChange', this.chromeResizeHandler);
+ }
+ }
+ this.chrome.dispose();
+ }
+ }
+});// $Id: button.js 777 2008-08-25 15:20:23Z pspencer $
+/**
+ * Class: Jx.Button
+ * Jx.Button creates a clickable element that can be added to a web page.
+ * When the button is clicked, it fires a 'click' event.
+ *
+ * The CSS styling for a button is controlled by several classes related
+ * to the various objects in the button's HTML structure:
+ *
+ * (code)
+ * <div class="jxButtonContainer">
+ * <a class="jxButton">
+ * <span class="jxButtonContent">
+ * <img class="jxButtonIcon" src="image_url">
+ * <span class="jxButtonLabel">button label</span>
+ * </span>
+ * </a>
+ * </div>
+ * (end)
+ *
+ * The CSS classes will change depending on the type option passed to the
+ * constructor of the button. The default type is Button. Passing another
+ * value such as Tab will cause all the CSS classes to change from jxButton
+ * to jxTab. For example:
+ *
+ * (code)
+ * <div class="jxTabContainer">
+ * <a class="jxTab">
+ * <span class="jxTabContent">
+ * <img class="jxTabIcon" src="image_url">
+ * <span class="jxTabLabel">tab label</span>
+ * </span>
+ * </a>
+ * </div>
+ * (end)
+ *
+ * Visually, a Jx.Button consists of an <A> tag that may contain either
+ * an image, a label, or both (the label appears to the right of the button
+ * if both are present). The default styles for Jx.Button expect the
+ * image to be 16 x 16 pixels, with a padding of 4px and a border of 1px
+ * which results in an element that is 26 pixels high. The width of the
+ * button automatically accomodates the image and label as required.
+ *
+ * When you construct a new instance of Jx.Button, the button does not
+ * automatically get inserted into the web page. Typically a button
+ * is used as part of building another capability such as a Jx.Toolbar.
+ * However, if you want to manually insert the button into your application,
+ * you may use the addTo method to append or insert the button into the
+ * page.
+ *
+ * There are two types of buttons, normal and toggle. A toggle button
+ * has an active state analogous to a checkbox. A toggle button generates
+ * different events (down and up) from a normal button (click). To create
+ * a toggle button, pass type: 'toggle' to the Jx.Button constructor.
+ *
+ * To use a Jx.Button in an application, you need to register for the 'click'
+ * event. You can pass a function in the 'onClick' option when constructing
+ * a button or you can call the addEvent('click', myFunction) method. The
+ * addEvent method can be called several times, allowing more than one function
+ * to be called when a button is clicked. You can use the
+ * removeEvent('click', myFunction) method to stop receiving click events.
+ *
+ * Example:
+ *
+ * (code)
+ * var button = new Jx.Button(options);
+ * button.addTo('myListItem'); // the id of an LI in the page.
+ * (end)
+ *
+ * (code)
+ * Example:
+ * var options = {
+ * imgPath: 'images/mybutton.png',
+ * tooltip: 'click me!',
+ * label: 'click me',
+ * onClick: function() {
+ * alert('you clicked me');
+ * }
+ * };
+ * var button = new Jx.Button(options);
+ * button.addEvent('click', anotherFunction);
+ *
+ * function anotherFunction() {
+ * alert('a second alert for a single click');
+ * }
+ * (end)
+ *
+ * Events:
+ * click - the button was pressed and released (only if type is not 'toggle').
+ * down - the button is down (only if type is 'toggle')
+ * up - the button is up (only if the type is 'toggle').
+ *
+ * Implements:
+ * Options - from MooTools Class.Extras
+ * Events - from MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+
+Jx.Button = new Class({
+ Implements: [Options,Events],
+
+ /**
+ * Property: {Object} domObj
+ * the HTML element that is inserted into the DOM for this button. You
+ * may reference this object to append it to the DOM or remove it from
+ * the DOM if necessary.
+ */
+ domObj: null,
+
+ /**
+ * Property: {Object} options
+ * default options for a button.
+ */
+ options: {
+ id: '',
+ type: 'Button',
+ image: '',
+ tooltip: '',
+ label: '',
+ enabled: true,
+ toggle: false,
+ halign: 'center',
+ valign: 'middle',
+ isActive: false,
+ container: 'div'
+ },
+ /**
+ * Constructor: Jx.Button
+ * create a new button.
+ *
+ * Parameters:
+ * options - {Object} an object containing optional properties for this
+ * button as below.
+ *
+ * Options:
+ * id - optional. A string value to use as the ID of the button
+ * container.
+ * type - optional. A string value that indicates what type of button
+ * this is. The default value is Button. The type is used to form
+ * the CSS class names used for various HTML elements within the
+ * button.
+ * image - optional. A string value that is the url to load the image to
+ * display in this button. The default styles size this image to
+ * 16 x 16.
+ * If not provided, then the button will have no icon.
+ * tooltip - optional. A string value to use as the alt/title attribute
+ * of the <A> tag that wraps the button, resulting in a tooltip that
+ * appears when the user hovers the mouse over a button in most
+ * browsers. If not provided, the button will have no tooltip.
+ * label - {String} optional, default is no label. A string value
+ * that is used as a label on the button.
+ * enabled - {Boolean} whether the button is enabled or not.
+ * halign - {String} horizontal alignment of the button label, 'center' by
+ * default. Other values are 'left' and 'right'.
+ * valign - {String} vertical alignment of the button label, 'middle' by
+ * default. Other values are 'top' and 'bottom'.
+ * isActive - {Boolean} optional, default false. Controls the initial
+ * state of toggle buttons.
+ * container - {String} the tag name of the HTML element that should be
+ * created to contain the button, by default this is 'div'.
+ */
+ initialize : function( options ) {
+ this.setOptions(options);
+
+ // the main container for the button
+ var d = new Element(this.options.container, {'class': 'jx'+this.options.type+'Container'});
+ if (this.options.toggle) {
+ d.addClass('jx'+this.options.type+'Toggle');
+ }
+ // the clickable part of the button
+ var a = new Element('a', {
+ 'class': 'jx'+this.options.type,
+ href: 'javascript:void(0)',
+ title: this.options.tooltip,
+ alt: this.options.tooltip,
+ events: {
+ click: this.clicked.bindWithEvent(this)
+ }
+ });
+ if (this.options.isActive) {
+ a.addClass('jx'+this.options.type+'Active');
+ }
+ d.appendChild(a);
+
+ var s = new Element('span', {'class': 'jx'+this.options.type+'Content'});
+ a.appendChild(s);
+
+ if (this.options.image || !this.options.label) {
+ var i = new Element('img', {
+ 'class':'jx'+this.options.type+'Icon',
+ 'src': Jx.aPixel.src
+ });
+ //if image is not a_pixel, set the background image of the image
+ //otherwise let the default css take over.
+ if (this.options.image.indexOf('a_pixel.png') == -1) {
+ i.setStyle('backgroundImage',"url("+this.options.image+")");
+ }
+ s.appendChild(i);
+ }
+
+ l = new Element('span', {
+ html: this.options.label
+ });
+ if (this.options.label) {
+ l.addClass('jx'+this.options.type+'Label');
+ }
+ s.appendChild(l);
+
+ if (this.options.id) {
+ d.id = this.options.id;
+ }
+ if (this.options.halign == 'left') {
+ d.addClass('jx'+this.options.type+'ContentLeft');
+ }
+
+ if (this.options.valign == 'top') {
+ d.addClass('jx'+this.options.type+'ContentTop');
+ }
+
+ this.domA = a;
+ this.domLabel = l;
+ this.domObj = d;
+
+ //update the enabled state
+ this.setEnabled(this.options.enabled);
+ },
+ /**
+ * Method: clicked
+ * triggered when the user clicks the button, processes the
+ * actionPerformed event
+ *
+ * Parameters:
+ * evt - {Event} the user click event
+ */
+ clicked : function(evt) {
+ if (this.options.enabled) {
+ if (this.options.toggle) {
+ this.setActive(!this.options.isActive);
+ } else {
+ this.fireEvent('click', {obj: this, event: evt});
+ }
+ }
+ //return false;
+ },
+ /**
+ * Method: setEnabled
+ * enable or disable the button.
+ *
+ * Parameters:
+ * enabled - {Boolean} the new enabled state of the button
+ */
+ setEnabled: function(enabled) {
+ this.options.enabled = enabled;
+ if (this.options.enabled) {
+ this.domObj.removeClass('jx'+this.options.type+'Disabled');
+ } else {
+ this.domObj.addClass('jx'+this.options.type+'Disabled');
+ }
+ },
+ /**
+ * Method: isActive
+ * For toggle buttons, this returns true if the toggle button is
+ * currently active and false otherwise.
+ *
+ * Returns:
+ * {Boolean} the active state of a toggle button
+ */
+ isActive: function() {
+ return this.options.isActive;
+ },
+ /**
+ * Method: setActive
+ * Set the active state of the button
+ */
+ setActive: function(isActive) {
+ if (this.options.isActive == isActive) {
+ return;
+ }
+ this.options.isActive = isActive;
+ if (this.options.isActive) {
+ this.domA.addClass('jx'+this.options.type+'Active');
+ this.fireEvent('down', this);
+ } else {
+ this.domA.removeClass('jx'+this.options.type+'Active');
+ this.fireEvent('up', this);
+ }
+ },
+ /**
+ * Method: setImage
+ * set the image of this button to a new image URL
+ *
+ * Parameters:
+ * path - {String} the new url to use as the image for this button
+ */
+ setImage: function(path) {
+ if (this.domImg) {
+ this.domImg.set('src', path);
+ }
+ },
+ /**
+ * Method: setLabel
+ *
+ * sets the text of the button. Only works if a label was supplied
+ * when the button was constructed
+ *
+ * Parameters:
+ *
+ * label - {String} the new label for the button
+ */
+ setLabel: function(label) {
+ if (this.domLabel) {
+ this.domLabel.set('html', label);
+ }
+ },
+ /**
+ * Method: setTooltip
+ * sets the tooltip displayed by the button
+ *
+ * Parameters:
+ * tooltip - {String} the new tooltip
+ */
+ setTooltip: function(tooltip) {
+ if (this.domImg) {
+ this.domImg.set({
+ 'title':tooltip,
+ 'alt':tooltip
+ });
+ }
+ },
+ /**
+ * Method: addTo
+ * adds the button to a DOM element using appendChild if sibling
+ * is not specified or sibling's parent is not the specified parent,
+ * otherwise uses insertBefore.
+ *
+ * Parameters:
+ * parent - {Object} the DOM element or id of a DOM element
+ * to append the button to.
+ * sibling - {Object} the DOM element or id of a DOM element
+ * to insert the button before. If not specified, then the
+ * button is appended to the parent.
+ */
+ addTo: function(parent, sibling) {
+ parent = $(parent);
+ sibling = sibling ? $(sibling) : null;
+ if (sibling && sibling.parentNode == parent) {
+ parent.insertBefore(this.domObj, sibling);
+ } else {
+ parent.appendChild(this.domObj);
+ }
+ }
+});// $Id: button.flyout.js 782 2008-08-26 17:36:11Z pspencer $
+/**
+ * Class: Jx.Button.Flyout
+ * Flyout buttons expose a panel when the user clicks the button. The
+ * panel can have arbitrary content. You must provide any necessary
+ * code to hook up elements in the panel to your application.
+ *
+ * When the panel is opened, the 'open' event is fired. When the panel is
+ * closed, the 'close' event is fired. You can register functions to handle
+ * these events in the options passed to the constructor (onOpen, onClose).
+ *
+ * The user can close the flyout panel by clicking the button again, by
+ * clicking anywhere outside the panel and other buttons, or by pressing the
+ * 'esc' key.
+ *
+ * A flyout is structure the same way as a normal <Jx.Button> except that an
+ * extra div is appended to the jxButtonContainer element and given a class
+ * of jxFlyout.
+ *
+ * Flyout buttons implement <Jx.ContentLoader> which provides the hooks to
+ * insert content into the jxFlyout element. Note that the jxFlyout element
+ * is not appended to the DOM until the first time it is opened.
+ *
+ * It is generally best to specify a width and height for your flyout content
+ * area through CSS to ensure that it works correctly across all browsers.
+ * To do this, make sure to provide a unique 'id' in the options when
+ * constructing your button and then provide some CSS:
+ *
+ * (code)
+ * #myFlyout .jxFlyout {
+ * width: 200px;
+ * height: 100px;
+ * }
+ * (end)
+ *
+ * A flyout closes other flyouts when it is opened. It is possible to embed
+ * flyout buttons inside the content area of another flyout button. In this
+ * case, opening the inner flyout will not close the outer flyout but it will
+ * close any other flyouts that are siblings.
+ *
+ * Example:
+ * (code)
+ * var flyout = new Jx.Button.Flyout({
+ * label: 'flyout',
+ * content: 'flyoutContent',
+ * onOpen: function(flyout) {
+ * console.log('flyout opened');
+ * },
+ * onClose: function(flyout) {
+ * console.log('flyout closed');
+ * }
+ * });
+ * (end)
+ *
+ * Events:
+ * open - this event is triggered when the flyout is opened.
+ * close - this event is triggered when the flyout is closed.
+ *
+ * Extends:
+ * <Jx.Button>
+ *
+ * Implements:
+ * <Jx.ContentLoader>
+ * <Jx.AutoPosition>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Button.Flyout = new Class({
+ Extends: Jx.Button,
+ Implements: [Jx.ContentLoader, Jx.AutoPosition, Jx.Chrome],
+
+ /**
+ * Property: content
+ * the HTML element that contains the flyout content
+ */
+ content: null,
+ /**
+ * Constructor: initialize
+ *
+ * construct a new instance of a flyout button. The single options
+ * argument takes the same parameters as <Jx.Button::initialize> plus
+ * content loading options as per <Jx.ContentLoader>.
+ *
+ * Parameters: {Object} options
+ *
+ * an options object used to initialize the button
+ */
+ initialize: function(options) {
+ if (!Jx.Button.Flyout.Stack) {
+ Jx.Button.Flyout.Stack = [];
+ }
+ this.parent(options);
+ this.domA.addClass('jx'+this.options.type+'Flyout');
+
+ this.contentContainer = new Element('div',{
+ 'class':'jxFlyout'
+ });
+
+ this.content = new Element('div', {
+ 'class': 'jxFlyoutContent'
+ });
+ this.contentContainer.adopt(this.content);
+
+ this.content.store('jxFlyout', this);
+ this.loadContent(this.content);
+ this.keypressWatcher = this.keypressHandler.bindWithEvent(this);
+ this.hideWatcher = this.clickHandler.bindWithEvent(this);
+ },
+ /**
+ * Method: clicked
+ * Override <Jx.Button::clicked> to hide/show the content area of the
+ * flyout.
+ *
+ * Parameters:
+ * e - {Event} the user event
+ */
+ clicked: function(e) {
+ /* find out what we are contained by if we don't already know */
+ if (!this.owner) {
+ this.owner = document.body;
+ var node = $(this.domObj.parentNode);
+ while (node != document.body && this.owner == document.body) {
+ var flyout = node.retrieve('jxFlyout');
+ if (flyout) {
+ this.owner = flyout;
+ break;
+ } else {
+ node = $(node.parentNode);
+ }
+ }
+ }
+ if (Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1] == this) {
+ this.hide();
+ return;
+ } else if (this.owner != document.body) {
+ /* if we are part of another flyout, close any open flyouts
+ * inside the parent and register this as the current flyout
+ */
+ if (this.owner.currentFlyout == this) {
+ /* if the flyout to close is this flyout,
+ * hide this and return */
+ this.hide();
+ return;
+ } else if (this.owner.currentFlyout) {
+ this.owner.currentFlyout.hide();
+ }
+ this.owner.currentFlyout = this;
+ } else {
+ /* if we are at the top level, close the entire stack before
+ * we open
+ */
+ while (Jx.Button.Flyout.Stack.length) {
+ Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1].hide();
+ }
+ }
+ // now we go on the stack.
+ Jx.Button.Flyout.Stack.push(this);
+
+ this.options.isActive = true;
+ this.domA.addClass('jx'+this.options.type+'Active');
+ this.contentContainer.setStyle('visibility','hidden');
+ document.body.adopt(this.contentContainer);
+ this.showChrome(this.contentContainer);
+
+ this.position(this.contentContainer, this.domObj, {
+ horizontal: ['left left', 'right right'],
+ vertical: ['bottom top', 'top bottom'],
+ offsets: this.chromeOffsets
+ });
+ this.contentContainer.setStyle('visibility','');
+
+ window.addEvent('keypress', this.keypressWatcher);
+ document.addEvent('click', this.hideWatcher);
+ this.fireEvent('open', this);
+ },
+ /**
+ * Method: hide
+ * Closes the flyout if open
+ */
+ hide: function() {
+ if (this.owner != document.body) {
+ this.owner.currentFlyout = null;
+ }
+ Jx.Button.Flyout.Stack.pop();
+ this.setActive(false);
+ this.contentContainer.dispose();
+ window.removeEvent('keypress', this.keypressWatcher);
+ document.removeEvent('click', this.hideWatcher);
+ this.fireEvent('close', this);
+ },
+ /* hide flyout if the user clicks outside of the flyout */
+ clickHandler: function(e) {
+ e = new Event(e);
+ var elm = $(e.target);
+ var flyout = Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1];
+ if (!elm.descendantOf(flyout.content) &&
+ !elm.descendantOf(flyout.domObj)) {
+ flyout.hide();
+ }
+ },
+ /* hide flyout if the user presses the ESC key */
+ keypressHandler: function(e) {
+ e = new Event(e);
+ if (e.key == 'esc') {
+ Jx.Button.Flyout.Stack[Jx.Button.Flyout.Stack.length - 1].hide();
+ }
+ }
+});// $Id: button.multi.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Button.Multi
+ * Multi buttons are used to contain multiple buttons in a drop down list
+ * where only one button is actually visible and clickable in the interface.
+ *
+ * When the user clicks the active button, it performs its normal action.
+ * The user may also click a drop-down arrow to the right of the button and
+ * access the full list of buttons. Clicking a button in the list causes
+ * that button to replace the active button in the toolbar and performs
+ * the button's regular action.
+ *
+ * Other buttons can be added to the Multi button using the add method.
+ *
+ * This is not really a button, but rather a container for buttons. The
+ * button structure is a div containing two buttons, a normal button and
+ * a flyout button. The flyout contains a toolbar into which all the
+ * added buttons are placed. The main button content is cloned from the
+ * last button clicked (or first button added).
+ *
+ * The Multi button does not trigger any events itself, only the contained
+ * buttons trigger events.
+ *
+ * Example:
+ * (code)
+ * var b1 = new Jx.Button({
+ * label: 'b1',
+ * onClick: function(button) {
+ * console.log('b1 clicked');
+ * }
+ * });
+ * var b2 = new Jx.Button({
+ * label: 'b2',
+ * onClick: function(button) {
+ * console.log('b2 clicked');
+ * }
+ * });
+ * var b3 = new Jx.Button({
+ * label: 'b3',
+ * onClick: function(button) {
+ * console.log('b3 clicked');
+ * }
+ * });
+ * var multiButton = new Jx.Button.Multi();
+ * multiButton.add(b1, b2, b3);
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Button.Multi = new Class({
+ /**
+ * Property: {<Jx.Button>} activeButton
+ * the currently selected button
+ */
+ activeButton: null,
+ /**
+ * Property: buttons
+ * {Array} the buttons added to this multi button
+ */
+ buttons: null,
+ /**
+ * Constructor: Jx.Button.Multi
+ * construct a new instance of Jx.Button.Multi.
+ */
+ initialize: function() {
+ this.buttons = [];
+ var d = new Element('div');
+ this.tb = new Jx.Toolbar({parent: d, position:'right'});
+ this.flyout = new Jx.Button.Flyout({content: d});
+ this.flyout.domObj.firstChild.addClass('jxButtonMulti');
+ this.domObj = new Element('div', {'class': 'jxButtonMultiContainer'});
+ this.domObj.grab(this.flyout.domObj);
+ },
+ /**
+ * Method: add
+ * adds one or more buttons to the Multi button. The first button
+ * added becomes the active button initialize. This function
+ * takes a variable number of arguments, each of which is expected
+ * to be an instance of <Jx.Button>.
+ *
+ * Parameters:
+ * button - {<Jx.Button>} a <Jx.Button> instance, may be repeated in the parameter list
+ */
+ add: function() {
+ $A(arguments).each(function(theButton){
+ if (!theButton instanceof Jx.Button) {
+ return;
+ }
+ this.buttons.push(theButton);
+ var button = new Jx.Button($merge(
+ theButton.options,
+ {onClick: this.setButton.bind(this, theButton)}
+ ));
+ theButton.multiButton = button;
+ this.tb.add(button);
+ if (!this.activeButton) {
+ this.domObj.grab(theButton.domObj, 'top');
+ this.activeButton = theButton;
+ }
+ }, this);
+ },
+ /**
+ * Method: remove
+ * remove a button from a multi button
+ *
+ * Parameters:
+ * button - {<Jx.Button>} the button to remove
+ */
+ remove: function(button) {
+ if (!button || !button.multiButton) {
+ return;
+ }
+ // the toolbar will only remove the li.toolItem, which is
+ // the parent node of the multiButton's domObj.
+ if (this.tb.remove(button.multiButton)) {
+ button.multiButton = null;
+ if (this.activeButton == button) {
+ // if any buttons are left that are not this button
+ // then set the first one to be the active button
+ // otherwise set the active button to nothing
+ if (!this.buttons.some(function(b) {
+ if (b != button) {
+ this.setActiveButton(b);
+ return true;
+ } else {
+ return false;
+ }
+ }, this)) {
+ this.setActiveButton(null);
+ };
+ }
+ /* force the flyout to recalculate its size */
+ this.flyout.content.style.height = '';
+ this.flyout.content.style.width = '';
+ this.buttons.erase(button);
+ }
+ },
+ /**
+ * Method: addTo
+ * adds the button to a DOM element using appendChild if sibling
+ * is not specified or sibling's parent is not the specified parent,
+ * otherwise uses insertBefore.
+ *
+ * Parameters:
+ * parent - {Object} the DOM element or id of a DOM element
+ * to append the button to.
+ * sibling - {Object} the DOM element or id of a DOM element
+ * to insert the button before. If not specified, then the
+ * button is appended to the parent.
+ */
+ addTo: function(parent, sibling) {
+ parent = $(parent);
+ sibling = sibling ? $(sibling) : null;
+ if (sibling && sibling.parentNode == parent) {
+ parent.grab(this.domObj, 'top');
+ } else {
+ parent.adopt(this.domObj);
+ }
+ },
+ /**
+ * Method: setActiveButton
+ * update the menu item to be the requested button.
+ *
+ * Parameters:
+ * button - {<Jx.Button>} a <Jx.Button> instance that was added to this multi button.
+ */
+ setActiveButton: function(button) {
+ if (this.activeButton) {
+ this.activeButton.domObj.dispose();
+ }
+ if (button && button.domObj) {
+ this.domObj.grab(button.domObj, 'top');
+ }
+ this.activeButton = button;
+ },
+ /**
+ * Method: setButton
+ * update the active button in the menu item, trigger the button's action
+ * and hide the flyout that contains the buttons.
+ *
+ * Parameters:
+ * button - {<Jx.Button>} The button to set as the active button
+ */
+ setButton: function(button) {
+ this.setActiveButton(button);
+ button.clicked();
+ this.flyout.hide();
+ }
+});// $Id: colorpalette.js 763 2008-08-21 13:18:11Z pspencer $
+/**
+ * Class: Jx.ColorPalette
+ * A Jx.ColorPalette presents a user interface for selecting colors. Currently,
+ * the user can either enter a HEX colour value or select from a palette of
+ * web-safe colours. The user can also enter an opacity value.
+ *
+ * A Jx.ColorPalette can be embedded anywhere in a web page by appending its
+ * <Jx.ColorPalette.domObj> property to an HTML element. However, a
+ * a <Jx.Button> subclass is provided ( <Jx.Button.Color> ) that embeds a
+ * colour panel inside a button for easy use in toolbars.
+ *
+ * Colour changes are propogated via a changed event. To
+ * be notified of changes in a Jx.ColorPalette, use the addEvent method.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * change - triggered when the color changes.
+ * click - the user clicked on a color swatch (emitted after a change event)
+ *
+ * Implements:
+ * Options - MooTools Class.Extras
+ * Events - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+
+Jx.ColorPalette = new Class({
+ Implements: [Options, Events],
+ /**
+ * Property: {HTMLElement} domObj
+ * the HTML element representing the color panel
+ */
+ domObj: null,
+ options: {
+ color: '#000000',
+ alpha: 1
+ },
+ /**
+ * Property: {Array} hexColors
+ * an array of valid hex values that are used to build a web-safe
+ * palette
+ */
+ hexColors: ['00', '33', '66', '99', 'CC', 'FF'],
+ /**
+ * Constructor: Jx.ColorPalette
+ * initialize a new instance of Jx.ColorPalette
+ *
+ * Parameters:
+ * options - {Object} an object containing a variable list of optional initialization
+ * parameters.
+ *
+ * Options:
+ * color - a colour to initialize the panel with, defaults to #000000
+ * (black) if not specified.
+ * alpha - an alpha value to initialize the panel with, defaults to 1
+ * (opaque) if not specified.
+ */
+ initialize: function(options) {
+ this.setOptions(options);
+
+ this.domObj = new Element('div', {
+ id: this.options.id,
+ 'class':'jxColorPalette'
+ });
+
+ var top = new Element('div', {'class':'jxColorBar'});
+ var d = new Element('div', {'class':'jxColorPreview'});
+
+ this.selectedSwatch = new Element('div', {'class':'jxColorSelected'});
+ this.previewSwatch = new Element('div', {'class':'jxColorHover'});
+ d.adopt(this.selectedSwatch);
+ d.adopt(this.previewSwatch);
+
+ top.adopt(d);
+
+ this.colorInputLabel = new Element('label', {'class':'jxColorLabel', html:'#'});
+ top.adopt(this.colorInputLabel);
+
+ var cc = this.changed.bind(this);
+ this.colorInput = new Element('input', {
+ 'class':'jxHexInput',
+ 'type':'text',
+ 'maxLength':6,
+ events: {
+ 'keyup':cc,
+ 'blur':cc,
+ 'change':cc
+ }
+ });
+
+ top.adopt(this.colorInput);
+
+ this.alphaLabel = new Element('label', {'class':'jxAlphaLabel', 'html':'alpha (%)'});
+ top.adopt(this.alphaLabel);
+
+ this.alphaInput = new Element('input', {
+ 'class':'jxAlphaInput',
+ 'type':'text',
+ 'maxLength':3,
+ events: {
+ 'keyup': this.alphaChanged.bind(this)
+ }
+ });
+ top.adopt(this.alphaInput);
+
+ this.domObj.adopt(top);
+
+ d = new Element('div', {'class':'jxClearer'});
+ this.domObj.adopt(d);
+
+ var swatchClick = this.swatchClick.bindWithEvent(this);
+ var swatchOver = this.swatchOver.bindWithEvent(this);
+
+ var table = new Element('table', {'class':'jxColorGrid'});
+ var tbody = new Element('tbody');
+ table.adopt(tbody);
+ for (var i=0; i<12; i++) {
+ var tr = new Element('tr');
+ for (var j=-3; j<18; j++) {
+ var bSkip = false;
+ var r, g, b;
+ /* hacky approach to building first three columns
+ * because I couldn't find a good way to do it
+ * programmatically
+ */
+
+ if (j < 0) {
+ if (j == -3 || j == -1) {
+ r = g = b = 0;
+ bSkip = true;
+ } else {
+ if (i<6) {
+ r = g = b = i;
+ } else {
+ if (i == 6) {
+ r = 5; g = 0; b = 0;
+ } else if (i == 7) {
+ r = 0; g = 5; b = 0;
+ } else if (i == 8) {
+ r = 0; g = 0; b = 5;
+ } else if (i == 9) {
+ r = 5; g = 5; b = 0;
+ } else if (i == 10) {
+ r = 0; g = 5; b = 5;
+ } else if (i == 11) {
+ r = 5; g = 0; b = 5;
+ }
+ }
+ }
+ } else {
+ /* remainder of the columns are built
+ * based on the current row/column
+ */
+ r = parseInt(i/6)*3 + parseInt(j/6);
+ g = j%6;
+ b = i%6;
+ }
+ var bgColor = '#'+this.hexColors[r]+this.hexColors[g]+this.hexColors[b];
+
+ var td = new Element('td');
+ if (!bSkip) {
+ td.setStyle('backgroundColor', bgColor);
+
+ var a = new Element('a', {
+ 'class': 'colorSwatch ' + (((r > 2 && g > 2) || (r > 2 && b > 2) || (g > 2 && b > 2)) ? 'borderBlack': 'borderWhite'),
+ 'href':'#',
+ 'title':bgColor,
+ 'alt':bgColor,
+ events: {
+ 'mouseover': swatchOver,
+ 'click': swatchClick
+ }
+ });
+ a.store('swatchColor', bgColor);
+ td.adopt(a);
+ } else {
+ var span = new Element('span', {'class':'emptyCell'});
+ td.adopt(span);
+ }
+ tr.adopt(td);
+ }
+ tbody.adopt(tr);
+ }
+ this.domObj.adopt(table);
+ this.updateSelected();
+ },
+
+ /**
+ * Method: swatchOver
+ * handle the mouse moving over a colour swatch by updating the preview
+ *
+ * Parameters:
+ * e - {Event} the mousemove event object
+ */
+ swatchOver: function(e) {
+ var a = e.target;
+
+ this.previewSwatch.setStyle('backgroundColor', a.retrieve('swatchColor'));
+ },
+
+ /**
+ * Method: swatchClick
+ * handle mouse click on a swatch by updating the color and hiding the
+ * panel.
+ *
+ * Parameters:
+ * e - {Event} the mouseclick event object
+ */
+ swatchClick: function(e) {
+ var a = e.target;
+
+ this.options.color = a.retrieve('swatchColor');
+ this.updateSelected();
+ this.fireEvent('click', this);
+ },
+
+ /**
+ * Method: changed
+ * handle the user entering a new colour value manually by updating the
+ * selected colour if the entered value is valid HEX.
+ */
+ changed: function() {
+ var color = this.colorInput.value;
+ if (color.substring(0,1) == '#') {
+ color = color.substring(1);
+ }
+ if (color.toLowerCase().match(/^[0-9a-f]{6}$/)) {
+ this.options.color = '#' +color.toUpperCase();
+ this.updateSelected();
+ }
+ },
+
+ /**
+ * Method: alphaChanged
+ * handle the user entering a new alpha value manually by updating the
+ * selected alpha if the entered value is valid alpha (0-100).
+ */
+ alphaChanged: function() {
+ var alpha = this.alphaInput.value;
+ if (alpha.match(/^[0-9]{1,3}$/)) {
+ this.options.alpha = parseFloat(alpha/100);
+ this.updateSelected();
+ }
+ },
+
+ /**
+ * Method: setColor
+ * set the colour represented by this colour panel
+ *
+ * Parameters:
+ * color - {String} the new hex color value
+ */
+ setColor: function( color ) {
+ this.colorInput.value = color;
+ this.changed();
+ },
+
+ /**
+ * Method: setAlpha
+ * set the alpha represented by this colour panel
+ *
+ * Parameters:
+ * alpha - {Integer} the new alpha value (between 0 and 100)
+ */
+ setAlpha: function( alpha ) {
+ this.alphaInput.value = alpha;
+ this.alphaChanged();
+ },
+
+ /**
+ * Method: updateSelected
+ * update the colour panel user interface based on the current
+ * colour and alpha values
+ */
+ updateSelected: function() {
+ var styles = {'backgroundColor':this.options.color};
+
+ this.colorInput.value = this.options.color.substring(1);
+
+ this.alphaInput.value = parseInt(this.options.alpha*100);
+ if (this.options.alpha < 1) {
+ styles.opacity = this.options.alpha;
+ styles.filter = 'Alpha(opacity='+(this.options.alpha*100)+')';
+ } else {
+ styles.opacity = '';
+ styles.filter = '';
+ }
+ this.selectedSwatch.setStyles(styles);
+ this.previewSwatch.setStyles(styles);
+ this.fireEvent('change', this);
+ }
+});
+
+// $Id: button.color.js 763 2008-08-21 13:18:11Z pspencer $
+/**
+ * Class: Jx.Button.Color
+ * A <Jx.ColorPalette> wrapped up in a Jx.Button. The button includes a
+ * preview of the currently selected color. Clicking the button opens
+ * the color panel.
+ *
+ * A color button is essentially a <Jx.Button.Flyout> where the content
+ * of the flyout is a <Jx.ColorPalette>.
+ *
+ * Example:
+ * (code)
+ * var colorButton = new Jx.Button.Color({
+ * onChange: function(button) {
+ * console.log('color:' + button.options.color + ' alpha: ' + button.options.alpha);
+ * }
+ * });
+ * (end)
+ *
+ * Events:
+ * change - fired when the color is changed.
+ *
+ * Extends:
+ * <Jx.Button.Flyout>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Button.Color = new Class({
+ Extends: Jx.Button.Flyout,
+ /**
+ * Property: {HTMLElement} swatch
+ * a div used to represent the current colour in the button.
+ */
+ swatch: null,
+ options: {
+ color: '#000000',
+ alpha: 100
+ },
+ /**
+ * Constructor: Jx.Button.Color
+ * initialize a new colour button.
+ *
+ * Parameters:
+ * options - {Object} an object containing a variable list of optional initialization
+ * parameters.
+ *
+ * Options:
+ * color - a colour to initialize the panel with, defaults to #000000
+ * (black) if not specified.
+ * alpha - an alpha value to initialize the panel with, defaults to 1
+ * (opaque) if not specified.
+ */
+
+ initialize: function(options) {
+ // this.parent($merge({label:' '},options));
+
+ if (!Jx.Button.Color.ColorPalette) {
+ Jx.Button.Color.ColorPalette = new Jx.ColorPalette(this.options);
+ }
+ var d = new Element('span', {'class':'jxButtonSwatch'});
+
+ this.selectedSwatch = new Element('span');
+ d.appendChild(this.selectedSwatch);
+
+ this.colorChangeFn = this.changed.bind(this);
+ this.hideFn = this.hide.bind(this);
+
+ /* create a button with a label so it doesn't get an empty label class
+ and then replace the label text with the swatch */
+ Jx.Button.Flyout.prototype.initialize.apply(this, [options]);
+ $(this.domObj.firstChild).addClass('jxButtonColor');
+ this.domObj.firstChild.firstChild.insertBefore(d, this.domObj.firstChild.firstChild.firstChild);
+ this.updateSwatch();
+ },
+
+ /**
+ * Method: show
+ * show the color panel when the user clicks the button
+ */
+ clicked: function() {
+ if (Jx.Button.Color.ColorPalette.currentButton) {
+ Jx.Button.Color.ColorPalette.currentButton.hide();
+ }
+ Jx.Button.Color.ColorPalette.currentButton = this;
+ Jx.Button.Color.ColorPalette.addEvent('change', this.colorChangeFn);
+ Jx.Button.Color.ColorPalette.addEvent('click', this.hideFn);
+ this.content.appendChild(Jx.Button.Color.ColorPalette.domObj);
+ Jx.Button.Color.ColorPalette.domObj.setStyle('display', 'block');
+ Jx.Button.Flyout.prototype.clicked.apply(this, arguments);
+ /* setting these before causes an update problem when clicking on
+ * a second color button when another one is open - the color
+ * wasn't updating properly
+ */
+
+ Jx.Button.Color.ColorPalette.options.color = this.options.color;
+ Jx.Button.Color.ColorPalette.options.alpha = this.options.alpha/100;
+ Jx.Button.Color.ColorPalette.updateSelected();
+},
+
+ /**
+ * Method: hide
+ * hide the colour panel
+ */
+ hide: function() {
+ this.setActive(false);
+ Jx.Button.Color.ColorPalette.removeEvent('change', this.colorChangeFn);
+ Jx.Button.Color.ColorPalette.removeEvent('click', this.hideFn);
+ Jx.Button.Flyout.prototype.hide.apply(this, arguments);
+ Jx.Button.Color.ColorPalette.currentButton = null;
+ },
+
+ /**
+ * Method: setColor
+ * set the colour represented by this colour panel
+ *
+ * Parameters:
+ * color - {String} the new hex color value
+ */
+ setColor: function(color) {
+ this.options.color = color;
+ this.updateSwatch();
+ },
+
+ /**
+ * Method: setAlpha
+ * set the alpha represented by this colour panel
+ *
+ * Parameters:
+ * alpha - {Integer} the new alpha value (between 0 and 100)
+ */
+ setAlpha: function(alpha) {
+ this.options.alpha = alpha;
+ this.updateSwatch();
+ },
+
+ /**
+ * Method: changed
+ * colorChangeListener callback function when the user changes
+ * the colour in the panel (just update the preview).
+ */
+ changed: function(panel) {
+ var changed = false;
+ if (this.options.color != panel.options.color) {
+ this.options.color = panel.options.color;
+ changed = true;
+ }
+ if (this.options.alpha != panel.options.alpha * 100) {
+ this.options.alpha = panel.options.alpha * 100;
+ changed = true;
+ }
+ if (changed) {
+ this.updateSwatch();
+ this.fireEvent('change',this);
+ }
+ },
+
+ /**
+ * Method: updateSwatch
+ * Update the swatch color for the current color
+ */
+ updateSwatch: function() {
+ var styles = {'backgroundColor':this.options.color};
+ if (this.options.alpha < 100) {
+ styles.filter = 'Alpha(opacity='+(this.options.alpha)+')';
+ styles.opacity = this.options.alpha / 100;
+
+ } else {
+ styles.opacity = '';
+ styles.filter = '';
+ }
+ this.selectedSwatch.setStyles(styles);
+ }
+});
+// $Id: $
+/**
+ * Class: Jx.ButtonSet
+ * A ButtonSet manages a set of <Jx.Button> instances by ensuring that only one
+ * of the buttons is active.
+ *
+ * Example:
+ * (code)
+ * var toolbar = new Jx.Toolbar('bar');
+ * var buttonSet = new Jx.ButtonSet();
+ *
+ * var tab1 = new Jx.Button({label: 'b1', toggle:true, contentID: 'content1'});
+ * var tab2 = new Jx.Button({label: 'b2', toggle:true, contentID: 'content2'});
+ * var tab3 = new Jx.Button({label: 'b3', toggle:true, contentID: 'content3'});
+ * var tab4 = new Jx.Button({label: 'b4', toggle:true, contentURL: 'test_content.html'});
+ *
+ * buttonSet.add(b1,b2,b3,b4);
+ * (end)
+ *
+ * Events:
+ * change - the current button has changed
+ *
+ * Implements:
+ * Events - MooTools Class.Extras
+ * Options - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.ButtonSet = new Class({
+ Implements: [Options,Events],
+ /**
+ * Property: buttons
+ * {Array} array of buttons that are managed by this button set
+ */
+ buttons: null,
+ /**
+ * Constructor: Jx.ButtonSet
+ * Create a new instance of <Jx.ButtonSet>
+ *
+ * Parameters:
+ * options - an options object, only event handlers are supported
+ * as options at this time.
+ */
+ initialize : function(options) {
+ this.setOptions(options);
+ this.buttons = [];
+ this.buttonChangedHandler = this.buttonChanged.bind(this);
+
+ },
+
+ /**
+ * Method: add
+ * Add one or more <Jx.Button>s to the ButtonSet.
+ *
+ * Parameters:
+ * button - {<Jx.Button>} an instance of <Jx.Button> to add to the button set. More
+ * than one button can be added by passing extra parameters to this method.
+ */
+ add : function() {
+ $A(arguments).each(function(button) {
+ button.domObj.addClass('jx'+button.options.type+'Set');
+ button.addEvent('down',this.buttonChangedHandler);
+ if (!this.activeButton) {
+ button.setActive(true);
+ }
+ this.buttons.push(button);
+ }, this);
+ },
+ /**
+ * Method: remove
+ * Remove a button from this Button.
+ *
+ * Parameters:
+ * button - {<Jx.Button>} the button to remove.
+ */
+ remove : function(button) {
+ this.buttons.erase(button);
+ if (this.activeButton == button) {
+ if (this.buttons.length) {
+ this.buttons[0].setActive(true);
+ }
+ button.removeEvent('down',this.buttonChangedHandler);
+ }
+ },
+ /**
+ * Method: setActiveButton
+ * Set the active button to the one passed to this method
+ *
+ * Parameters:
+ * button - {<Jx.Button>} the button to make active.
+ */
+ setActiveButton: function(button) {
+ if (this.activeButton && this.activeButton != button) {
+ this.activeButton.setActive(false);
+ }
+ this.activeButton = button;
+ },
+ /**
+ * Method: selectionChanged
+ * Handle selection changing on the buttons themselves and activate the
+ * appropriate button in response.
+ *
+ * Parameters:
+ * button - {<Jx.Button>} the button to make active.
+ */
+ buttonChanged: function(button) {
+ this.setActiveButton(button);
+ this.fireEvent('change', this);
+ }
+});
+
+
+
+// $Id: grid.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Grid
+ * A tabular control that has fixed scrolling headers on the rows and columns
+ * like a spreadsheet.
+ *
+ * Jx.Grid is a tabular control with convenient controls for resizing columns,
+ * sorting, and inline editing. It is created inside another element, typically a
+ * div. If the div is resizable (for instance it fills the page or there is a
+ * user control allowing it to be resized), you must call the resize() method
+ * of the grid to let it know that its container has been resized.
+ *
+ * When creating a new Jx.Grid, you can specify a number of options for the grid
+ * that control its appearance and functionality.
+ *
+ * Jx.Grid renders data that comes from an external source. This external
+ * source, called the model, must implement the following interface.
+ *
+ * Jx.Grid Model Interface:
+ *
+ * addGridListener(l) - mandatory
+ * mandatory. This function accepts one argument, l, which is the listener
+ * to add. The model can then call the gridChanged() method on the grid
+ * listener object when something in the model changes.
+ *
+ * removeGridListener(l) - mandatory
+ * mandatory. This function accepts one argument, l, which is the listener
+ * to remove. The listener should have been previously added using
+ * addGridListener.
+ *
+ * getColumnCount() - mandatory
+ * mandatory. This function returns the number of columns of data in the
+ * model as an integer value.
+ *
+ * getColumnHeaderHTML(column) - mandatory
+ * mandatory. This function returns an HTML string to be placed in the
+ * column header for the given column index.
+ *
+ * getColumnHeaderHeight() - mandatory
+ * mandatory. This function returns an integer which is the height of the
+ * column header row in pixels.
+ *
+ * getColumnWidth(column) - mandatory
+ * mandatory. This function returns an integer which is the width of the
+ * given column in pixels.
+ *
+ * getRowHeaderHTML(row) - mandatory
+ * mandatory. This function returns an HTML string to be placed in the row
+ * header for the given row index
+ *
+ * getRowHeaderWidth() - mandatory
+ * mandatory. This function returns an integer which is the width of the row
+ * header column in pixels.
+ *
+ * getRowHeight(row) - mandatory
+ * mandatory. This function returns an integer which is the height of the
+ * given row in pixels.
+ *
+ * getRowCount() - mandatory
+ * mandatory. This function returns the number of rows of data in the model
+ * as an integer value.
+ *
+ * getValueAt(row, column) - mandatory
+ * mandatory. This function returns an HTML string which is the text to place
+ * in the cell at the given row and column.
+ *
+ * isCellEditable(row, column) - mandatory
+ * mandatory. This function returns a boolean value to indicate if a given
+ * cell is editable by the user.
+ *
+ * *Optional Functions*
+ *
+ * setColumnWidth(column, width) - optional
+ * optional. This function is called with a column index and width in pixels
+ * when a column is resized. This function is only required if the grid
+ * allows resizeable columns.
+ *
+ * setValueAt(row, column, value) - optional
+ * optional. This function is called with the row and column of a cell and a
+ * new value for the cell. It is mandatory to provide this function if any of
+ * the cells in the model are editable.
+ *
+ * rowSelected(row) - optional
+ * optional. This function is called by the grid to indicate that the user
+ * has selected a row by clicking on the row header.
+ *
+ * columnSelected(column) - optional
+ * optional. This function is called by the grid to indicate that the user
+ * has selected a column by clicking on the column header.
+ *
+ * cellSelected(row, column) - optional
+ * optional. This function is called by the grid to indicate that the user
+ * has selected a cell by clicking on the cell in the grid.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Implements:
+ * Options - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Grid = new Class({
+ Implements: [Options],
+ domObj : null,
+ model : null,
+ options: {
+ alternateRowColors: false,
+ rowHeaders: false,
+ columnHeaders: false,
+ rowSelection: false,
+ cellSelection: false
+ },
+ /**
+ * Constructor: Jx.Grid
+ * construct a new instance of Jx.Grid within the domObj
+ *
+ * Parameters:
+ * domObj - {HTMLElement} the HTML element to create the grid inside.
+ * The grid will resize to fill the domObj.
+ * options - you can specify some options as attributes of a
+ * generic object.
+ *
+ * Options:
+ * alternateRowColors - defaults to false. If set to true, then
+ * alternating CSS classes are used for rows
+ * rowHeaders - defaults to false. If set to true, then a column
+ * of row header cells are displayed.
+ * columnHeaders - defaults to false. If set to true, then a column
+ * of row header cells are displayed.
+ * rowSelection - defaults to false. If set to true, allow the
+ * user to select rows.
+ * cellSelection - defaults to false. If set to true, allow the
+ * user to select cells.
+ */
+ initialize : function( domObj, options ) {
+ this.setOptions(options);
+ this.domObj = $(domObj);
+ /* if this grid is the content of a Jx Panel, this will
+ allow the grid to resize when the panel resizes
+ */
+ var jxl = this.domObj.retrieve('jxLayout');
+ if (jxl) {
+ jxl.addEvent('sizeChange', this.resize.bind(this));
+ }
+
+
+ this.rowColObj = new Element('div', {'class':'jxGridContainer'});
+
+ this.colObj = new Element('div', {'class':'jxGridContainer'});
+ this.colTable = new Element('table', {'class':'jxGridTable'});
+ this.colTableHead = new Element('thead');
+ this.colTable.appendChild(this.colTableHead);
+ this.colTableBody = new Element('tbody');
+ this.colTable.appendChild(this.colTableBody);
+ this.colObj.appendChild(this.colTable);
+
+ this.rowObj = new Element('div', {'class':'jxGridContainer'});
+ this.rowTable = new Element('table', {'class':'jxGridTable'});
+ this.rowTableHead = new Element('thead');
+ this.rowTable.appendChild(this.rowTableHead);
+ this.rowObj.appendChild(this.rowTable);
+
+ this.gridObj = new Element('div', {'class':'jxGridContainer',styles:{overflow:'scroll'}});
+ this.gridTable = new Element('table', {'class':'jxGridTable'});
+ this.gridTableBody = new Element('tbody');
+ this.gridTable.appendChild(this.gridTableBody);
+ this.gridObj.appendChild(this.gridTable);
+
+ this.domObj.appendChild(this.rowColObj);
+ this.domObj.appendChild(this.rowObj);
+ this.domObj.appendChild(this.colObj);
+ this.domObj.appendChild(this.gridObj);
+
+ this.gridObj.addEvent('scroll', this.onScroll.bind(this));
+ this.gridObj.addEvent('click', this.onClickGrid.bindWithEvent(this));
+ this.rowObj.addEvent('click', this.onClickRowHeader.bindWithEvent(this));
+ this.colObj.addEvent('click', this.onClickColumnHeader.bindWithEvent(this));
+ this.gridObj.addEvent('mousemove', this.onMouseMoveGrid.bindWithEvent(this));
+ this.rowObj.addEvent('mousemove', this.onMouseMoveRowHeader.bindWithEvent(this));
+ this.colObj.addEvent('mousemove', this.onMouseMoveColumnHeader.bindWithEvent(this));
+ },
+
+ /**
+ * Method: onScroll
+ * handle the grid scrolling by updating the position of the headers
+ */
+ onScroll: function() {
+ this.colObj.scrollLeft = this.gridObj.scrollLeft;
+ this.rowObj.scrollTop = this.gridObj.scrollTop;
+ },
+
+ /**
+ * Method: resize
+ * resize the grid to fit inside its container. This involves knowing something
+ * about the model it is displaying (the height of the column header and the
+ * width of the row header) so nothing happens if no model is set
+ */
+ resize: function() {
+ if (!this.model) {
+ return;
+ }
+
+ /* TODO: Jx.Grid.resize
+ * if not showing column or row, should we handle the resize differently
+ */
+ var colHeight = this.options.columnHeaders ? this.model.getColumnHeaderHeight() : 1;
+ var rowWidth = this.options.rowHeaders ? this.model.getRowHeaderWidth() : 1;
+
+ var size = Element.getContentBoxSize(this.domObj);
+
+ /* -1 because of the right/bottom borders */
+ this.rowColObj.setStyles({
+ width: rowWidth-1,
+ height: colHeight-1
+ });
+ this.rowObj.setStyles({
+ top:colHeight,
+ left:0,
+ width:rowWidth-1,
+ height:size.height-colHeight-1
+ });
+
+ this.colObj.setStyles({
+ top: 0,
+ left: rowWidth,
+ width: size.width - rowWidth - 1,
+ height: colHeight - 1
+ });
+
+ this.gridObj.setStyles({
+ top: colHeight,
+ left: rowWidth,
+ width: size.width - rowWidth - 1,
+ height: size.height - colHeight - 1
+ });
+ },
+
+ /**
+ * Method: setModel
+ * set the model for the grid to display. If a model is attached to the grid
+ * it is removed and the new model is displayed.
+ *
+ * Parameters:
+ * model - {Object} the model to use for this grid
+ */
+ setModel: function(model) {
+ if (this.model) {
+ this.model.removeGridListener(this);
+ }
+ this.model = model;
+ if (this.model) {
+ if (this.domObj.resize) {
+ this.domObj.resize();
+ }
+ this.model.addGridListener(this);
+ this.createGrid();
+ this.resize();
+ } else {
+ this.destroyGrid();
+ }
+ },
+
+ /**
+ * Method: destroyGrid
+ * destroy the contents of the grid safely
+ */
+ destroyGrid: function() {
+ var n = this.colTableHead.cloneNode(false);
+ this.colTable.replaceChild(n, this.colTableHead);
+ this.colTableHead = n;
+
+ n = this.colTableBody.cloneNode(false);
+ this.colTable.replaceChild(n, this.colTableBody);
+ this.colTableBody = n;
+
+ n = this.rowTableHead.cloneNode(false);
+ this.rowTable.replaceChild(n, this.rowTableHead);
+ this.rowTableHead = n;
+
+ n = this.gridTableBody.cloneNode(false);
+ this.gridTable.replaceChild(n, this.gridTableBody);
+ this.gridTableBody = n;
+
+ },
+
+ /**
+ * Method: createGrid
+ * create the grid for the current model
+ */
+ createGrid: function() {
+ this.destroyGrid();
+ if (this.model) {
+ var model = this.model;
+ var nColumns = model.getColumnCount();
+ var nRows = model.getRowCount();
+
+ /* create header if necessary */
+ if (this.options.columnHeaders) {
+ var colHeight = model.getColumnHeaderHeight();
+ var trHead = new Element('tr');
+ this.colTableHead.appendChild(trHead);
+ var trBody = new Element('tr');
+ this.colTableBody.appendChild(trBody);
+
+ var th = new Element('th', {styles:{width:0,height:0}});
+ trHead.appendChild(th);
+ th = th.cloneNode(true);
+ th.setStyle('height',colHeight);
+ trBody.appendChild(th);
+ for (var i=0; i<nColumns; i++) {
+ var colWidth = model.getColumnWidth(i);
+ th = new Element('th', {'class':'jxGridColHeadHide',styles:{width:colWidth}});
+ var p = new Element('p', {styles:{height:0,width:colWidth}});
+ th.appendChild(p);
+ trHead.appendChild(th);
+ th = new Element('th', {
+ 'class':'jxGridColHead',
+ html:model.getColumnHeaderHTML(i)
+ });
+ trBody.appendChild(th);
+ }
+ /* one extra column at the end for filler */
+ var th = new Element('th',{styles:{width:1000,height:0}});
+ trHead.appendChild(th);
+ th = th.cloneNode(true);
+ th.setStyle('height',colHeight - 1);
+ th.className = 'jxGridColHead';
+ trBody.appendChild(th);
+
+ }
+
+ if (this.options.rowHeaders) {
+ var rowWidth = model.getRowHeaderWidth();
+ var tr = new Element('tr');
+ var td = new Element('td', {styles:{width:0,height:0}});
+ tr.appendChild(td);
+ var th = new Element('th', {styles:{width:rowWidth,height:0}});
+ tr.appendChild(th);
+ this.rowTableHead.appendChild(tr);
+ for (var i=0; i<nRows; i++) {
+ var rowHeight = model.getRowHeight(i);
+ var tr = new Element('tr');
+ var td = new Element('td', {'class':'jxGridRowHeadHide', styles:{width:0,height:rowHeight}});
+ var p = new Element('p', {styles:{width:0,height:rowHeight}});
+ td.appendChild(p);
+ tr.appendChild(td);
+ var th = new Element('th', {'class':'jxGridRowHead', html:model.getRowHeaderHTML(i)});
+ tr.appendChild(th);
+ this.rowTableHead.appendChild(tr);
+ }
+ /* one extra row at the end for filler */
+ var tr = new Element('tr');
+ var td = new Element('td',{
+ styles:{
+ width:0,
+ height:1000
+ }
+ });
+ tr.appendChild(td);
+ var th = new Element('th',{
+ 'class':'jxGridRowHead',
+ styles:{
+ width:rowWidth,
+ height:1000
+ }
+ });
+ tr.appendChild(th);
+ this.rowTableHead.appendChild(tr);
+ }
+
+ var colHeight = model.getColumnHeaderHeight();
+ var trBody = new Element('tr');
+ this.gridTableBody.appendChild(trBody);
+
+ var td = new Element('td', {styles:{width:0,height:0}});
+ trBody.appendChild(td);
+ for (var i=0; i<nColumns; i++) {
+ var colWidth = model.getColumnWidth(i);
+ td = new Element('td', {'class':'jxGridColHeadHide', styles:{width:colWidth}});
+ var p = new Element('p', {styles:{width:colWidth,height:0}});
+ td.appendChild(p);
+ trBody.appendChild(td);
+ }
+
+ for (var j=0; j<nRows; j++) {
+ var rowHeight = model.getRowHeight(j);
+ var actualRowHeight = rowHeight;
+ var tr = new Element('tr');
+ this.gridTableBody.appendChild(tr);
+
+ var td = new Element('td', {
+ 'class':'jxGridRowHeadHide',
+ styles: {
+ width: 0,
+ height:rowHeight
+ }
+ });
+ var p = new Element('p',{styles:{height:rowHeight}});
+ td.appendChild(p);
+ tr.appendChild(td);
+ for (var i=0; i<nColumns; i++) {
+ var colWidth = model.getColumnWidth(i);
+ td = new Element('td', {'class':'jxGridCell'});
+ td.innerHTML = model.getValueAt(j,i);
+ tr.appendChild(td);
+ var tdSize = td.getSize();
+ if (tdSize.height > actualRowHeight) {
+ actualRowHeight = tdSize.height;
+ }
+ }
+ /* some notes about row sizing
+ * In Safari, the height of a TR is always returned as 0
+ * In Safari, the height of any given TD is the height it would
+ * render at, not the actual height of the row
+ * In IE, the height is returned 1px bigger than any other browser
+ * Firefox just works
+ *
+ * So, for Safari, we have to measure every TD and take the highest one
+ * and if its IE, we subtract 1 from the overall height, making all
+ * browsers identical
+ *
+ * Using document.all is not a good hack for this
+ */
+ if (document.all) {
+ actualRowHeight -= 1;
+ }
+ if (this.options.rowHeaders) {
+ this.setRowHeaderHeight(j, actualRowHeight);
+ }
+ /* if we apply the class before adding content, it
+ * causes a rendering error in IE (off by 1) that is 'fixed'
+ * when another class is applied to the row, causing dynamic
+ * shifting of the row heights
+ */
+ if (this.options.alternateRowColors) {
+ tr.className = (j%2) ? 'jxGridRowOdd' : 'jxGridRowEven';
+ } else {
+ tr.className = 'jxGridRowAll';
+ }
+ }
+
+ }
+ },
+
+ /**
+ * Method: setRowHeaderHeight
+ * set the height of a row. This is used internally to adjust the height of
+ * the row header when cell contents wrap. A limitation of the table structure
+ * is that overflow: hidden on a td will work horizontally but not vertically
+ *
+ * Parameters:
+ * row - {Integer} the row to set the height for
+ * height - {Integer} the height to set the row (in pixels)
+ */
+ setRowHeaderHeight: function(row, height) {
+ //this.rowTableHead.childNodes[row+1].childNodes[0].style.height = (height) + 'px';
+ this.rowTableHead.childNodes[row+1].childNodes[0].childNodes[0].style.height = (height) + 'px';
+ },
+
+ /**
+ * Method: gridChanged
+ * called through the grid listener interface when data has changed in the
+ * underlying model
+ *
+ * Parameters:
+ * model - {Object} the model that changed
+ * row - {Integer} the row that changed
+ * col - {Integer} the column that changed
+ * value - {Mixed} the new value
+ */
+ gridChanged: function(model, row, col, value) {
+ if (this.model == model) {
+ this.gridObj.childNodes[row].childNodes[col].innerHTML = value;
+ }
+ },
+
+ /**
+ * Method: prelightRowHeader
+ * apply the jxGridRowHeaderPrelight style to the header cell of a row.
+ * This removes the style from the previously pre-lit row header.
+ *
+ * Parameters:
+ * row - {Integer} the row to pre-light the header cell of
+ */
+ prelightRowHeader: function(row) {
+ var cell = (row >= 0 && row < this.rowTableHead.rows.length-1) ? this.rowTableHead.rows[row+1].cells[1] : null;
+ if (this.prelitRowHeader != cell) {
+ if (this.prelitRowHeader) {
+ this.prelitRowHeader.removeClass('jxGridRowHeaderPrelight');
+ }
+ this.prelitRowHeader = cell;
+ if (this.prelitRowHeader) {
+ this.prelitRowHeader.addClass('jxGridRowHeaderPrelight');
+ }
+ }
+ },
+
+ /**
+ * Method: prelightColumnHeader
+ * apply the jxGridColumnHeaderPrelight style to the header cell of a column.
+ * This removes the style from the previously pre-lit column header.
+ *
+ * Parameters:
+ * col - {Integer} the column to pre-light the header cell of
+ */
+ prelightColumnHeader: function(col) {
+ if (this.colTableBody.rows.length == 0) {
+ return;
+ }
+ var cell = (col >= 0 && col < this.colTableBody.rows[0].cells.length-1) ? this.colTableBody.rows[0].cells[col+1] : null;
+ if (this.prelitColumnHeader != cell) {
+ if (this.prelitColumnHeader) {
+ this.prelitColumnHeader.removeClass('jxGridColumnHeaderPrelight');
+ }
+ this.prelitColumnHeader = cell;
+ if (this.prelitColumnHeader) {
+ this.prelitColumnHeader.addClass('jxGridColumnHeaderPrelight');
+ }
+ }
+ },
+
+ /**
+ * Method: prelightRow
+ * apply the jxGridRowPrelight style to row.
+ * This removes the style from the previously pre-lit row.
+ *
+ * Parameters:
+ * row - {Integer} the row to pre-light
+ */
+ prelightRow: function(row) {
+ var tr = (row >= 0 && row < this.gridTableBody.rows.length-1) ? this.gridTableBody.rows[row+1] : null;
+
+ if (this.prelitRow != row) {
+ if (this.prelitRow) {
+ this.prelitRow.removeClass('jxGridRowPrelight');
+ }
+ this.prelitRow = tr;
+ if (this.prelitRow && !this.prelitRow.hasClass('jxGridRowSelected')) {
+ this.prelightRowHeader(row);
+ this.prelitRow.addClass('jxGridRowPrelight');
+ }
+ }
+ },
+
+ /**
+ * Method: prelightColumn
+ * apply the jxGridColumnPrelight style to a column.
+ * This removes the style from the previously pre-lit column.
+ *
+ * Parameters:
+ * col - {Integer} the column to pre-light
+ *
+ * TODO: Jx.Grid.prelightColumn
+ * Not Yet Implemented.
+ */
+ prelightColumn: function(col) {
+ /* TODO: Jx.Grid.prelightColumn
+ * implement column prelighting (possibly)
+ */
+ this.prelightColumnHeader(col);
+ },
+
+ /**
+ * Method: prelightCell
+ * apply the jxGridCellPrelight style to a cell.
+ * This removes the style from the previously pre-lit cell.
+ *
+ * Parameters:
+ * row - {Integer} the row of the cell to pre-light
+ * col - {Integer} the column of the cell to pre-light
+ */
+ prelightCell: function(row, col) {
+ var td = (row >=0 && col >=0 && row < this.gridTableBody.rows.length - 1 && col < this.gridTableBody.rows[row+1].cells.length - 1) ? this.gridTableBody.rows[row+1].cells[col+1] : null;
+ if (this.prelitCell != td) {
+ if (this.prelitCell) {
+ this.prelitCell.removeClass('jxGridCellPrelight');
+ }
+ this.prelitCell = td;
+ if (this.prelitCell) {
+ this.prelitCell.addClass('jxGridCellPrelight');
+ this.prelightRow(row);
+ this.prelightColumn(col);
+ }
+ }
+ },
+
+ /**
+ * Method: selectCell
+ * Select a cell and apply the jxGridCellSelected style to it.
+ * This deselects a previously selected cell.
+ *
+ * If the model supports cell selection, it should implement
+ * a cellSelected function to receive notification of the selection.
+ *
+ * Parameters:
+ * row - {Integer} the row of the cell to select
+ * col - {Integer} the column of the cell to select
+ */
+ selectCell: function(row, col) {
+ var td = (row >=0 && col >=0 && row < this.gridTableBody.rows.length - 1 && col < this.gridTableBody.rows[row+1].cells.length - 1) ? this.gridTableBody.rows[row+1].cells[col+1] : null;
+ if (!td) {
+ return;
+ }
+
+ if (this.selectedCell) {
+ this.selectedCell.addClass('jxGridCellSelected');
+ } else {
+ this.selectedCell.removeClass('jxGridCellSelected');
+ }
+ },
+
+ /**
+ * Method: selectRowHeader
+ * Apply the jxGridRowHeaderSelected style to the row header cell of a
+ * selected row.
+ *
+ * Parameters:
+ * row - {Integer} the row header to select
+ * selected - {Boolean} the new state of the row header
+ */
+ selectRowHeader: function(row, selected) {
+ var cell = (row >= 0 && row < this.rowTableHead.rows.length-1) ? this.rowTableHead.rows[row+1].cells[1] : null;
+ if (!cell) {
+ return;
+ }
+ if (selected) {
+ cell.addClass('jxGridRowHeaderSelected');
+ } else {
+ cell.removeClass('jxGridRowHeaderSelected');
+ }
+ },
+
+ /**
+ * Method: selectRow
+ * Select a row and apply the jxGridRowSelected style to it.
+ *
+ * If the model supports row selection, it should implement
+ * a rowSelected function to receive notification of the selection.
+ *
+ * Parameters:
+ * row - {Integer} the row to select
+ * selected - {Boolean} the new state of the row
+ */
+ selectRow: function(row, selected) {
+ var tr = (row >= 0 && row < this.gridTableBody.rows.length - 1) ? this.gridTableBody.rows[row+1] : null;
+ if (tr) {
+ if (selected) {
+ tr.addClass('jxGridRowSelected');
+ } else {
+ tr.removeClass('jxGridRowSelected');
+ }
+ }
+ this.selectRowHeader(row, selected);
+ },
+
+ /**
+ * method: selectColumnHeader
+ * Apply the jxGridColumnHeaderSelected style to the column header cell of a
+ * selected column.
+ *
+ * Parameters:
+ * col - {Integer} the column header to select
+ * selected - {Boolean} the new state of the column header
+ */
+ selectColumnHeader: function(col, selected) {
+ if (this.colTableBody.rows.length == 0) {
+ return;
+ }
+ var cell = (col >= 0 && col < this.colTableBody.rows[0].cells.length-1) ? this.colTableBody.rows[0].cells[col+1] : null;
+ if (cell == null) {
+ return;
+ }
+
+ if (selected) {
+ cell.addClass('jxGridColumnHeaderSelected');
+ } else {
+ cell.removeClass('jxGridColumnHeaderSelected');
+ }
+ },
+
+ /**
+ * Method: selectColumn
+ * Select a column.
+ * This deselects a previously selected column.
+ *
+ * Parameters:
+ * col - {Integer} the column to select
+ * selected - {Boolean} the new state of the column
+ */
+ selectColumn: function(col, selected) {
+ /* todo: implement column selection */
+ if (col >= 0 && col < this.gridTable.rows[0].cells.length) {
+ if (selected) {
+ for (var i=0; i<this.gridTable.rows.length; i++) {
+ this.gridTable.rows[i].cells[this.selectedColumn + 1].removeClass('jxGridColumnSelected');
+ }
+ } else {
+ for (var i=0; i<this.gridTable.rows.length; i++) {
+ this.gridTable.rows[i].cells[col+1].addClass('jxGridColumnSelected');
+ }
+
+ }
+ }
+ this.selectColumnHeader(col, selected);
+ },
+
+ /**
+ * Method: onMouseMoveGrid
+ * handle the mouse moving over the main grid. This pre-lights the cell,
+ * and subsquently the row and column (and headers).
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ */
+ onMouseMoveGrid: function(e) {
+ var rc = this.getRowColumnFromEvent(e);
+ this.prelightCell(rc.row, rc.column);
+ },
+
+ /**
+ * Method: onMouseMoveRowHeader
+ * handle the mouse moving over the row header cells. This pre-lights
+ * the row and subsequently the row header.
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ */
+ onMouseMoveRowHeader: function(e) {
+ var rc = this.getRowColumnFromEvent(e);
+ this.prelightRow(rc.row);
+ },
+
+ /**
+ * Method: onMouseMoveColumnHeader
+ * handle the mouse moving over the column header cells. This pre-lights
+ * the column and subsequently the column header.
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ */
+ onMouseMoveColumnHeader: function(e) {
+ var rc = this.getRowColumnFromEvent(e);
+ this.prelightColumn(rc.column);
+ },
+
+ /**
+ * Method: onClickGrid
+ * handle the user clicking on the grid. This triggers an
+ * event to the model (if a cellSelected function is provided).
+ *
+ * The following is an example of a function in the model that selects
+ * a row when the cellSelected function is called and deselects any rows
+ * that are currently selected.
+ *
+ * (code)
+ * cellSelected: function(grid, row,col) {
+ * if (this.selectedRow != null) {
+ * grid.selectRow(this.selectedRow, false);
+ * }
+ * this.selectedRow = row;
+ * grid.selectRow(row, true);
+ * }
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ */
+ onClickGrid: function(e) {
+ var rc = this.getRowColumnFromEvent(e);
+ //this.selectCell(rc.row, rc.column);
+
+ if (this.model.cellSelected) {
+ this.model.cellSelected(this, rc.row, rc.column);
+ }
+ },
+
+ /**
+ * Method: onClickRowHeader
+ * handle the user clicking on the row header. This triggers an
+ * event to the model (if a rowSelected function is provided) which
+ * can then select the row if desired.
+ *
+ * The following is an example of a function in the model that selects
+ * a row when the rowSelected function is called and deselects any rows
+ * that are currently selected. More complex code could be written to
+ * allow the user to select multiple rows.
+ *
+ * (code)
+ * rowSelected: function(grid, row) {
+ * if (this.selectedRow != null) {
+ * grid.selectRow(this.selectedRow, false);
+ * }
+ * this.selectedRow = row;
+ * grid.selectRow(row, true);
+ * }
+ * (end)
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ */
+ onClickRowHeader: function(e) {
+ var rc = this.getRowColumnFromEvent(e);
+
+ if (this.model.rowSelected) {
+ this.model.rowSelected(this, rc.row);
+ }
+ },
+
+ /**
+ * Method: onClickColumnHeader
+ * handle the user clicking on the column header. This triggers column
+ * selection and column (and header) styling changes and an
+ * event to the model (if a columnSelected function is provided)
+ *
+ * The following is an example of a function in the model that selects
+ * a column when the columnSelected function is called and deselects any
+ * columns that are currently selected. More complex code could be written
+ * to allow the user to select multiple columns.
+ *
+ * (code)
+ * colSelected: function(grid, col) {
+ * if (this.selectedColumn != null) {
+ * grid.selectColumn(this.selectedColumn, false);
+ * }
+ * this.selectedColumn = col;
+ * grid.selectColumn(col, true);
+ * }
+ * (end)
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ */
+ onClickColumnHeader: function(e) {
+ var rc = this.getRowColumnFromEvent(e);
+
+ if (this.model.columnSelected) {
+ this.model.columnSelected(this, rc.column);
+ }
+ },
+
+ /**
+ * method: getRowColumnFromEvent
+ * retrieve the row and column indexes from an event click.
+ * This function is used by the grid, row header and column
+ * header to safely get these numbers.
+ *
+ * If the event isn't valid (i.e. it wasn't on a TD or TH) then
+ * the returned values will be -1, -1
+ *
+ * Parameters:
+ * e - {Event} the browser event object
+ *
+ * @return Object an object with two properties, row and column,
+ * that contain the row and column that was clicked
+ */
+ getRowColumnFromEvent: function(e) {
+ var td = e.target;
+ if (td.tagName != 'TD' && td.tagName != 'TH') {
+ return {row:-1,column:-1};
+ }
+ var tr = td.parentNode;
+ var col = td.cellIndex - 1; /* because of hidden spacer column */
+ var row = tr.rowIndex - 1; /* because of hidden spacer row */
+
+ if (col == -1) {
+ /* bug in safari returns 0 for cellIndex - only choice seems
+ * to be to loop through the row
+ */
+ for (var i=0; i<tr.childNodes.length; i++) {
+ if (tr.childNodes[i] == td) {
+ col = i - 1;
+ break;
+ }
+ }
+ }
+ return {row:row,column:col};
+ }
+});// $Id: layout.js 746 2008-08-16 00:30:25Z pspencer $
+/**
+ * Class: Jx.Layout
+ * Jx.Layout is used to provide more flexible layout options for applications
+ *
+ * Jx.Layout wraps an existing DOM element (typically a div) and provides
+ * extra functionality for sizing that element within its parent and sizing
+ * elements contained within it that have a 'resize' function attached to them.
+ *
+ * To create a Jx.Layout, pass the element or id plus an options object to
+ * the constructor.
+ *
+ * Example:
+ * (code)
+ * var myContainer = new Jx.Layout('myDiv', options);
+ * (end)
+ *
+ * Events:
+ * sizeChange - fired when the size of the container changes
+ *
+ * Implements:
+ * Options - MooTools Class.Extras
+ * Events - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+
+Jx.Layout = new Class({
+ Implements: [Options,Events],
+
+ options: {
+ propagate: true,
+ position: 'absolute',
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0,
+ width: null,
+ height: null,
+ minWidth: 0,
+ minHeight: 0,
+ maxWidth: -1,
+ maxHeight: -1
+ },
+ /**
+ * Constructor: Jx.Layout
+ * Create a new instance of Jx.Layout.
+ *
+ * Parameters:
+ * domObj - {HTMLElement} element or id to apply the layout to
+ * options - {Object} options can be passed to the Jx.Layout as an object
+ * with some, all, or none of the options below.
+ *
+ * Options:
+ * propagate - boolean, controls propogation of resize to child nodes.
+ * True by default. If set to false, changes in size will not be
+ * propogated to child nodes.
+ * position - how to position the element, either 'absolute' or 'relative'.
+ * The default (if not passed) is 'absolute'. When using
+ * 'absolute' positioning, both the width and height are
+ * controlled by Jx.Layout. If 'relative' positioning is used
+ * then only the width is controlled, allowing the height to
+ * be controlled by its content.
+ * left - the distance (in pixels) to maintain the left edge of the element
+ * from its parent element. The default value is 0. If this is set
+ * to 'null', then the left edge can be any distance from its parent
+ * based on other parameters.
+ * right - the distance (in pixels) to maintain the right edge of the element
+ * from its parent element. The default value is 0. If this is set
+ * to 'null', then the right edge can be any distance from its parent
+ * based on other parameters.
+ * top - the distance (in pixels) to maintain the top edge of the element
+ * from its parent element. The default value is 0. If this is set
+ * to 'null', then the top edge can be any distance from its parent
+ * based on other parameters.
+ * bottom - the distance (in pixels) to maintain the bottom edge of the element
+ * from its parent element. The default value is 0. If this is set
+ * to 'null', then the bottom edge can be any distance from its parent
+ * based on other parameters.
+ * width - the width (in pixels) of the element. The default value is null.
+ * If this is set to 'null', then the width can be any value based on
+ * other parameters.
+ * height - the height (in pixels) of the element. The default value is null.
+ * If this is set to 'null', then the height can be any value based on
+ * other parameters.
+ * minWidth - the minimum width that the element can be sized to. The default
+ * value is 0.
+ * minHeight - the minimum height that the element can be sized to. The
+ * default value is 0.
+ * maxWidth - the maximum width that the element can be sized to. The default
+ * value is -1, which means no maximum.
+ * maxHeight - the maximum height that the element can be sized to. The
+ * default value is -1, which means no maximum.
+ */
+ initialize: function(domObj, options) {
+ this.setOptions(options);
+ this.domObj = $(domObj);
+ this.domObj.resize = this.resize.bind(this);
+ this.domObj.setStyle('position', this.options.position);
+ this.domObj.store('jxLayout', this);
+
+ if (document.body == this.domObj.parentNode) {
+ window.addEvent('resize', this.windowResize.bindWithEvent(this));
+ window.addEvent('load', this.resize.bind(this));
+ }
+ //this.resize();
+ },
+
+ /**
+ * Method: windowResize
+ * when the window is resized, any Jx.Layout controlled elements that are
+ * direct children of the BODY element are resized
+ */
+ windowResize: function() {
+ if (this.resizeTimer) {
+ $clear(this.resizeTimer);
+ this.resizeTimer = null;
+ }
+ this.resizeTimer = this.resize.delay(100, this);
+ },
+
+ /**
+ * Method: resize
+ * resize the element controlled by this Jx.Layout object.
+ *
+ * Parameters:
+ * options - new options to apply, see <Jx.Layout::Jx.Layout>
+ */
+ resize: function(options) {
+ /* this looks like a really big function but actually not
+ * much code gets executed in the two big if statements
+ */
+ this.resizeTimer = null;
+ var needsResize = false;
+ if (options) {
+ for (var i in options) {
+ //prevent forceResize: false from causing a resize
+ if (i == 'forceResize') {
+ continue;
+ }
+ if (this.options[i] != options[i]) {
+ needsResize = true;
+ this.options[i] = options[i];
+ }
+ }
+ if (options.forceResize) {
+ needsResize = true;
+ }
+ }
+ if (!$(this.domObj.parentNode)) {
+ return;
+ }
+
+ var parentSize;
+ if (this.domObj.parentNode.tagName == 'BODY') {
+ parentSize = Element.getPageDimensions();
+ } else {
+ parentSize = $(this.domObj.parentNode).getContentBoxSize();
+ }
+
+ if (this.lastParentSize && !needsResize) {
+ needsResize = (this.lastParentSize.width != parentSize.width ||
+ this.lastParentSize.height != parentSize.height);
+ } else {
+ needsResize = true;
+ }
+ this.lastParentSize = parentSize;
+
+ if (!needsResize) {
+ return;
+ }
+
+ var l, t, w, h;
+
+ /* calculate left and width */
+ if (this.options.left != null) {
+ /* fixed left */
+ l = this.options.left;
+ if (this.options.right == null) {
+ /* variable right */
+ if (this.options.width == null) {
+ /* variable right and width
+ * set right to min, stretch width */
+ w = parentSize.width - l;
+ if (w < this.options.minWidth ) {
+ w = this.options.minWidth;
+ }
+ if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
+ w = this.options.maxWidth;
+ }
+ } else {
+ /* variable right, fixed width
+ * use width
+ */
+ w = this.options.width;
+ }
+ } else {
+ /* fixed right */
+ if (this.options.width == null) {
+ /* fixed right, variable width
+ * stretch width
+ */
+ w = parentSize.width - l - this.options.right;
+ if (w < this.options.minWidth) {
+ w = this.options.minWidth;
+ }
+ if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
+ w = this.options.maxWidth;
+ }
+ } else {
+ /* fixed right, fixed width
+ * respect left and width, allow right to stretch
+ */
+ w = this.options.width;
+ }
+ }
+
+ } else {
+ if (this.options.right == null) {
+ if (this.options.width == null) {
+ /* variable left, width and right
+ * set left, right to min, stretch width
+ */
+ l = 0;
+ w = parentSize.width;
+ if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
+ l = l + parseInt(w - this.options.maxWidth)/2;
+ w = this.options.maxWidth;
+ }
+ } else {
+ /* variable left, fixed width, variable right
+ * distribute space between left and right
+ */
+ w = this.options.width;
+ l = parseInt((parentSize.width - w)/2);
+ if (l < 0) {
+ l = 0;
+ }
+ }
+ } else {
+ if (this.options.width != null) {
+ /* variable left, fixed width, fixed right
+ * left is calculated directly
+ */
+ w = this.options.width;
+ l = parentSize.width - w - this.options.right;
+ if (l < 0) {
+ l = 0;
+ }
+ } else {
+ /* variable left and width, fixed right
+ * set left to min value and stretch width
+ */
+ l = 0;
+ w = parentSize.width - this.options.right;
+ if (w < this.options.minWidth) {
+ w = this.options.minWidth;
+ }
+ if (this.options.maxWidth >= 0 && w > this.options.maxWidth) {
+ l = w - this.options.maxWidth - this.options.right;
+ w = this.options.maxWidth;
+ }
+ }
+ }
+ }
+
+ /* calculate the top and height */
+ if (this.options.top != null) {
+ /* fixed top */
+ t = this.options.top;
+ if (this.options.bottom == null) {
+ /* variable bottom */
+ if (this.options.height == null) {
+ /* variable bottom and height
+ * set bottom to min, stretch height */
+ h = parentSize.height - t;
+ if (h < this.options.minHeight) {
+ h = this.options.minHeight;
+ }
+ if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
+ h = this.options.maxHeight;
+ }
+ } else {
+ /* variable bottom, fixed height
+ * stretch height
+ */
+ h = this.options.height;
+ if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
+ t = h - this.options.maxHeight;
+ h = this.options.maxHeight;
+ }
+ }
+ } else {
+ /* fixed bottom */
+ if (this.options.height == null) {
+ /* fixed bottom, variable height
+ * stretch height
+ */
+ h = parentSize.height - t - this.options.bottom;
+ if (h < this.options.minHeight) {
+ h = this.options.minHeight;
+ }
+ if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
+ h = this.options.maxHeight;
+ }
+ } else {
+ /* fixed bottom, fixed height
+ * respect top and height, allow bottom to stretch
+ */
+ h = this.options.height;
+ }
+ }
+ } else {
+ if (this.options.bottom == null) {
+ if (this.options.height == null) {
+ /* variable top, height and bottom
+ * set top, bottom to min, stretch height
+ */
+ t = 0;
+ h = parentSize.height;
+ if (h < this.options.minHeight) {
+ h = this.options.minHeight;
+ }
+ if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
+ t = parseInt((parentSize.height - this.options.maxHeight)/2);
+ h = this.options.maxHeight;
+ }
+ } else {
+ /* variable top, fixed height, variable bottom
+ * distribute space between top and bottom
+ */
+ h = this.options.height;
+ t = parseInt((parentSize.height - h)/2);
+ if (t < 0) {
+ t = 0;
+ }
+ }
+ } else {
+ if (this.options.height != null) {
+ /* variable top, fixed height, fixed bottom
+ * top is calculated directly
+ */
+ h = this.options.height;
+ t = parentSize.height - h - this.options.bottom;
+ if (t < 0) {
+ t = 0;
+ }
+ } else {
+ /* variable top and height, fixed bottom
+ * set top to min value and stretch height
+ */
+ t = 0;
+ h = parentSize.height - this.options.bottom;
+ if (h < this.options.minHeight) {
+ h = this.options.minHeight;
+ }
+ if (this.options.maxHeight >= 0 && h > this.options.maxHeight) {
+ t = parentSize.height - this.options.maxHeight - this.options.bottom;
+ h = this.options.maxHeight;
+ }
+ }
+ }
+ }
+
+ //TODO: check left, top, width, height against current styles
+ // and only apply changes if they are not the same.
+
+ /* apply the new sizes */
+ var sizeOpts = {width: w};
+ if (this.options.position == 'absolute') {
+ var padding = $(this.domObj.parentNode).getPaddingSize();
+ this.domObj.setStyles({
+ position: this.options.position,
+ left: l+padding.left,
+ top: t+padding.top
+ });
+ sizeOpts.height = h;
+ } else {
+ if (this.options.height) {
+ sizeOpts.height = this.options.height;
+ }
+ }
+ this.domObj.setBorderBoxSize(sizeOpts);
+
+ if (this.options.propagate) {
+ // propogate changes to children
+ var o = {forceResize: options ? options.forceResize : false};
+ $A(this.domObj.childNodes).each(function(child){
+ if (child.resize && child.getStyle('display') != 'none') {
+ child.resize(o);
+ }
+ });
+
+ }
+
+ this.fireEvent('sizeChange',this);
+ }
+});// $Id: menu.js 782 2008-08-26 17:36:11Z pspencer $
+/**
+ * Class: Jx.Menu
+ * A main menu as opposed to a sub menu that lives inside the menu.
+ *
+ * TODO: Jx.Menu
+ * revisit this to see if Jx.Menu and Jx.SubMenu can be merged into
+ * a single implementation.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Menu = new Class({
+ Implements: [Jx.AutoPosition, Jx.Chrome],
+ /**
+ * Property: domObj
+ * {HTMLElement} The HTML element containing the menu.
+ */
+ domObj : null,
+ /**
+ * Property: button
+ * {<Jx.Button>} The button that represents this menu in a toolbar and
+ * opens the menu.
+ */
+ button : null,
+ /**
+ * Property: subDomObj
+ * {HTMLElement} the HTML element that contains the menu items
+ * within the menu.
+ */
+ subDomObj : null,
+ /**
+ * Property: items
+ * {Array} the items in this menu
+ */
+ items : null,
+ /**
+ * Constructor: Jx.Menu
+ * Create a new instance of Jx.Menu.
+ *
+ * Parameters:
+ * options - {Object} an options object passed directly to the
+ * <Jx.Button> when creating the button that triggers this menu.
+ * If options is not passed, then no button is created.
+ */
+ initialize : function(options) {
+ /* */
+ if (!Jx.Menu.Menus) {
+ Jx.Menu.Menus = [];
+ }
+ /* stores menu items and sub menus */
+ this.items = [];
+
+ this.contentContainer = new Element('div',{
+ 'class':'jxMenuContainer'
+ });
+
+ /* the DOM element that holds the actual menu */
+ this.subDomObj = new Element('ul',{
+ 'class':'jxMenu'
+ });
+
+ this.contentContainer.adopt(this.subDomObj);
+
+ /* if options are passed, make a button inside an LI so the
+ menu can be embedded inside a toolbar */
+ if (options) {
+ this.domObj = new Element('li',{
+ id: options.id,
+ events: {
+ 'mouseover': this.onMouseOver.bindWithEvent(this)
+ }
+ });
+
+ this.button = new Jx.Button($merge(options,{
+ onClick:this.show.bind(this)
+ }));
+ this.button.domA.addClass('jxButtonMenu');
+
+ this.domObj.adopt(this.button.domObj);
+
+ }
+
+ /* pre-bind the hide function for efficiency */
+ this.hideWatcher = this.hide.bindWithEvent(this);
+ this.keypressWatcher = this.keypressHandler.bindWithEvent(this);
+ },
+ /**
+ * Method: add
+ * Add menu items to the sub menu.
+ *
+ * Parameters:
+ * item - {<Jx.MenuItem>} the menu item to add. Multiple menu items
+ * can be added by passing multiple arguments to this function.
+ */
+ add : function() {
+ $A(arguments).each(function(item){
+ this.items.push(item);
+ item.setOwner(this);
+ this.subDomObj.adopt(item.domObj);
+ }, this);
+ },
+ /**
+ * Method: deactivate
+ * Deactivate the menu by hiding it.
+ */
+ deactivate: function() {this.hide();},
+ /**
+ * Method: actionPerformed
+ * Any action performed in the menu ultimately calls this
+ * method to hide the menu.
+ */
+ actionPerformed : function() {this.hide();},
+ /**
+ * Method: onMouseOver
+ * Handle the user moving the mouse over the button for this menu
+ * by showing this menu and hiding the other menu.
+ *
+ * Parameters:
+ * e - {Event} the mouse event
+ */
+ onMouseOver: function(e) {
+ if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] != this) {
+ this.show({event:e});
+ }
+ },
+ /**
+ * Method: hide
+ * Hide the menu.
+ *
+ * Parameters:
+ * e - {Event} the mouse event
+ */
+ hide: function(e) {
+ if (e) {
+ if (e.target.descendantOf(this.domObj) ||
+ e.target.descendantOf(this.subDomObj)) {
+ return;
+ }
+ }
+ if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] == this) {
+ Jx.Menu.Menus[0] = null;
+ }
+ if (this.domA) {
+ this.domA.removeClass('jx'+this.button.options.type+'Active');
+ }
+ this.contentContainer.dispose();
+ this.items.each(function(item){item.hide(e);});
+ document.removeEvent('mousedown', this.hideWatcher);
+ document.removeEvent('keyup', this.keypressWatcher);
+ },
+ /**
+ * Method: show
+ * Show the menu
+ *
+ * Parameters:
+ * e - {Event} the mouse event
+ */
+ show : function(o) {
+ var e = o.event;
+ if (Jx.Menu.Menus[0] && Jx.Menu.Menus[0] != this) {
+ Jx.Menu.Menus[0].hide(e);
+ }
+ if (this.items.length ==0) {
+ return;
+ }
+ Jx.Menu.Menus[0] = this;
+
+ this.contentContainer.setStyle('visibility','hidden');
+ document.body.adopt(this.contentContainer);
+ /* we have to size the container for IE to render the chrome correctly
+ * but just in the menu/sub menu case - there is some horrible peekaboo
+ * bug in IE related to ULs that we just couldn't figure out
+ */
+ this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());
+ this.showChrome(this.contentContainer);
+
+ this.position(this.contentContainer, this.button.domObj, {
+ horizontal: ['left left'],
+ vertical: ['bottom top', 'top bottom'],
+ offsets: this.chromeOffsets
+ });
+
+ this.contentContainer.setStyle('visibility','');
+
+ if (this.domA) {
+ this.domA.addClass('jx'+this.button.options.type+'Active');
+ }
+ if (e) {
+ e.stop();
+ }
+ /* fix bug in IE that closes the menu as it opens because of bubbling */
+ document.addEvent('mousedown', this.hideWatcher);
+ document.addEvent('keyup', this.keypressWatcher);
+
+ },
+ /**
+ * Method: setVisibleItem
+ * Set the sub menu that is currently open
+ *
+ * Parameters:
+ * obj- {<Jx.SubMenu>} the sub menu that just became visible
+ */
+ setVisibleItem: function(obj) {
+ if (this.visibleItem != obj) {
+ if (this.visibleItem && this.visibleItem.hide) {
+ this.visibleItem.hide();
+ }
+ this.visibleItem = obj;
+ this.visibleItem.show();
+ }
+ },
+
+ /* hide flyout if the user presses the ESC key */
+ keypressHandler: function(e) {
+ e = new Event(e);
+ if (e.key == 'esc') {
+ this.hide();
+ }
+ }
+});
+
+// $Id: menu.item.js 777 2008-08-25 15:20:23Z pspencer $
+/**
+ * Class: Jx.Menu.Item
+ * A menu item is a single entry in a menu. It is typically composed of
+ * a label and an optional icon. Selecting the menu item emits an event.
+ *
+ * Jx.Menu.Item is represented by a <Jx.Button> with type MenuItem and the
+ * associated CSS changes noted in <Jx.Button>. The container of a MenuItem
+ * is an 'li' element.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * click - fired when the menu item is clicked.
+ *
+ * Implements:
+ * Options - MooTools Class.Extras
+ * Events - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Menu.Item = new Class({
+ Implements: [Options, Events],
+ Extends: Jx.Button,
+ /**
+ * Property: owner
+ * {<Jx.SubMenu> or <Jx.Menu>} the menu that contains the menu item.
+ */
+ owner: null,
+ /**
+ * Property: button
+ * {<Jx.Button>} the clickable part of the menu item is managed as a
+ * <Jx.Button>
+ */
+ button: null,
+ options: {
+ enabled: true,
+ image: Jx.baseURL + 'images/a_pixel.png',
+ label: ' '
+ },
+ /**
+ * Constructor: Jx.Menu.Item
+ * Create a new instance of Jx.Menu.Item
+ *
+ * Parameters:
+ * options - {Object} an object containing options as below.
+ *
+ * Options:
+ * enabled - {Boolean} whether the menu item starts enabled or not (default true)
+ *
+ * See <Jx.Button> for other options
+ */
+ initialize: function(options) {
+ this.parent($merge(options, {
+ container:'li',
+ type:'MenuItem'
+ }));
+ this.domObj.addEvent('mouseover', this.onMouseOver.bindWithEvent(this));
+ if (!this.options.enabled) {
+ this.domObj.addClass('jxMenuItemDisabled');
+ }
+ },
+ /**
+ * Method: setOwner
+ * Set the owner of this menu item
+ *
+ * Parameters:
+ * obj - {Object} the new owner
+ */
+ setOwner: function(obj) {
+ this.owner = obj;
+ },
+ /**
+ * Method: hide
+ * Hide the menu item.
+ */
+ hide: $empty,
+ /**
+ * Method: show
+ * Show the menu item
+ */
+ show: $empty,
+ clicked: function(o) {
+ if (this.options.enabled) {
+ if (this.options.toggle) {
+ this.setActive(!this.options.isActive);
+ }
+ this.fireEvent('click', this);
+ if (this.owner && this.owner.deactivate) {
+ this.owner.deactivate(o.event);
+ }
+ }
+ },
+ /**
+ * Method: propertyChanged
+ * Track when a property of the action changes and update the state of the
+ * menu item accordingly.
+ *
+ * Parameters:
+ * obj - {<Jx.Action>} the action object
+ */
+ propertyChanged: function(obj) {
+ this.options.enabled = obj.isEnabled();
+ if (this.options.enabled) {
+ this.domObj.removeClass('jxMenuItemDisabled' );
+ } else {
+ if (!this.domObj.hadClass('jxMenuItemDisabled')) {
+ this.domObj.addClass('jxMenuItemDisabled' );
+ }
+ }
+ },
+ /**
+ * Method: onmouseover
+ * handle the mouse moving over the menu item
+ *
+ * Parameters:
+ * e - {Event} the mousemove event
+ */
+ onMouseOver: function(e) {
+ if (this.owner && this.owner.setVisibleItem) {
+ this.owner.setVisibleItem(this);
+ }
+ this.show(e);
+ }
+});
+
+// $Id: menu.separator.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Menu.Separator
+ * A convenience class to create a visual separator in a menu.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Menu.Separator = new Class({
+ /**
+ * Property: domObj
+ * {HTMLElement} the HTML element that the separator is contained
+ * within
+ */
+ domObj: null,
+ /**
+ * Property: owner
+ * {<Jx.Menu>, <Jx.Menu.SubMenu>} the menu that the separator is in.
+ */
+ owner: null,
+ /**
+ * Constructor: Jx.Menu.Separator
+ * Create a new instance of a menu separator
+ */
+ initialize: function() {
+ this.domObj = new Element('li',{'class':'jxMenuItem'});
+ var span = new Element('span', {'class':'jxMenuSeparator','html':' '});
+ this.domObj.appendChild(span);
+ },
+ /**
+ * Method: setOwner
+ * Set the ownder of this menu item
+ *
+ * Parameters:
+ * obj - {Object} the new owner
+ */
+ setOwner: function(obj) {
+ this.owner = obj;
+ },
+ /**
+ * Method: hide
+ * Hide the menu item.
+ */
+ hide: $empty,
+ /**
+ * Method: show
+ * Show the menu item
+ */
+ show: $empty
+});// $Id: menu.submenu.js 782 2008-08-26 17:36:11Z pspencer $
+/**
+ * Class: Jx.Menu.SubMenu
+ * A sub menu contains menu items within a main menu or another
+ * sub menu.
+ *
+ * The structure of a SubMenu is the same as a <Jx.Menu.Item> with
+ * an additional unordered list element appended to the container.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Extends:
+ * <Jx.Menu.Item>
+ *
+ * Implements:
+ * Options - MooTools Class.Extra
+ * Events - MooTools Class.Extra
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Menu.SubMenu = new Class({
+ Extends: Jx.Menu.Item,
+ Implements: [Options, Events, Jx.AutoPosition, Jx.Chrome],
+ /**
+ * Property: subDomObj
+ * {HTMLElement} the HTML container for the sub menu.
+ */
+ subDomObj: null,
+ /**
+ * Property: owner
+ * {<Jx.Menu> or <Jx.SubMenu>} the menu or sub menu that this sub menu
+ * belongs
+ */
+ owner: null,
+ /**
+ * Property: visibleItem
+ * {<Jx.MenuItem>} the visible item within the menu
+ */
+ visibleItem: null,
+ /**
+ * Property: items
+ * {Array} the menu items that are in this sub menu.
+ */
+ items: null,
+ /**
+ * Constructor: Jx.SubMenu
+ * Create a new instance of Jx.SubMenu
+ *
+ * Parameters:
+ * options - see <Jx.MenuItem::Jx.MenuItem>
+ */
+ initialize: function(options) {
+ this.open = false;
+ this.items = [];
+ this.parent(options);
+ this.domA.addClass('jxButtonSubMenu');
+
+ this.contentContainer = new Element('div', {
+ 'class': 'jxMenuContainer'
+ });
+ this.subDomObj = new Element('ul', {
+ 'class':'jxSubMenu'
+ });
+ this.contentContainer.adopt(this.subDomObj);
+ },
+ /**
+ * Method: setOwner
+ * Set the owner of this sub menu
+ *
+ * Parameters:
+ * obj - {Object} the owner
+ */
+ setOwner: function(obj) {
+ this.owner = obj;
+ },
+ /**
+ * Method: show
+ * Show the sub menu
+ */
+ show: function() {
+ if (this.open || this.items.length == 0) {
+ return;
+ }
+
+ this.contentContainer.setStyle('visibility','hidden');
+ document.body.adopt(this.contentContainer);
+ /* we have to size the container for IE to render the chrome correctly
+ * but just in the menu/sub menu case - there is some horrible peekaboo
+ * bug in IE related to ULs that we just couldn't figure out
+ */
+ this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());
+ this.showChrome(this.contentContainer);
+
+ this.position(this.contentContainer, this.domObj, {
+ horizontal: ['right left', 'left right'],
+ vertical: ['top top'],
+ offsets: this.chromeOffsets
+ });
+
+ this.open = true;
+ this.contentContainer.setStyle('visibility','');
+
+ this.setActive(true);
+ },
+ /**
+ * Method: hide
+ * Hide the sub menu
+ */
+ hide: function() {
+ if (!this.open) {
+ return;
+ }
+ this.open = false;
+ this.items.each(function(item){item.hide();});
+ this.contentContainer.dispose();
+ this.visibleItem = null;
+ },
+ /**
+ * Method: add
+ * Add menu items to the sub menu.
+ *
+ * Parameters:
+ * item - {<Jx.MenuItem>} the menu item to add. Multiple menu items
+ * can be added by passing multiple arguments to this function.
+ */
+ add : function() { /* menu */
+ var that = this;
+ $A(arguments).each(function(item){
+ that.items.push(item);
+ item.setOwner(that);
+ that.subDomObj.adopt(item.domObj);
+ });
+ },
+ /**
+ * Method: insertBefore
+ * Insert a menu item before another menu item.
+ *
+ * Parameters:
+ * newItem - {<Jx.MenuItem>} the menu item to insert
+ * targetItem - {<Jx.MenuItem>} the menu item to insert before
+ */
+ insertBefore: function(newItem, targetItem) {
+ var bInserted = false;
+ for (var i=0; i<this.items.length; i++) {
+ if (this.items[i] == targetItem) {
+ this.items.splice(i, 0, newItem);
+ this.subDomObj.insertBefore(newItem.domObj, targetItem.domObj);
+ bInserted = true;
+ break;
+ }
+ }
+ if (!bInserted) {
+ this.add(newItem);
+ }
+ },
+ /**
+ * Method: remove
+ * Remove a single menu item from the menu.
+ *
+ * Parameters:
+ * item - {<Jx.MenuItem} the menu item to remove.
+ */
+ remove: function(item) {
+ for (var i=0; i<this.items.length; i++) {
+ if (this.items[i] == item) {
+ this.items.splice(i,1);
+ this.subDomObj.removeChild(item.domObj);
+ break;
+ }
+ }
+ },
+ /**
+ * Method: processActionEvent
+ * Process an action event coming from the menu item that
+ * represents the sub menu in its owner by showing or hiding
+ * the sub menu.
+ */
+ processActionEvent: function(e) {
+ if (this.open) {
+ this.hide();
+ } else {
+ this.show();
+ }
+ if (e && e.event) {
+ e.event.stop();
+ }
+ },
+ /**
+ * Method: deactivate
+ * Deactivate the sub menu
+ *
+ * Parameters:
+ * e - {Event} the event that triggered the menu being
+ * deactivated.
+ */
+ deactivate: function(e) {
+ if (this.owner) {
+ this.owner.deactivate(e);
+ }
+ },
+ /**
+ * Method: isActive
+ * Indicate if this sub menu is active
+ *
+ * Returns:
+ * {Boolean} true if the <Jx.Menu> that ultimately contains
+ * this sub menu is active, false otherwise.
+ */
+ isActive: function() {
+ if (this.owner) {
+ return this.owner.isActive();
+ } else {
+ return false;
+ }
+ },
+ /**
+ * Method: setActive
+ * Set the active state of the <Jx.Menu> that contains this sub menu
+ *
+ * Parameters:
+ * isActive - {Boolean} the new active state
+ */
+ setActive: function(isActive) {
+ if (this.owner && this.owner.setActive) {
+ this.owner.setActive(isActive);
+ }
+ },
+ /**
+ * Method: setVisibleItem
+ * Set a sub menu of this menu to be visible and hide the previously
+ * visible one.
+ *
+ * Parameters:
+ * obj - {<Jx.SubMenu>} the sub menu that should be visible
+ */
+ setVisibleItem: function(obj) {
+ if (this.visibleItem != obj) {
+ if (this.visibleItem && this.visibleItem.hide) {
+ this.visibleItem.hide();
+ }
+ this.visibleItem = obj;
+ this.visibleItem.show();
+ }
+ }
+});// $Id: menu.context.js 788 2008-08-27 15:07:01Z pspencer $
+/**
+ * Class: Jx.Menu.Context
+ * A <Jx.Menu> that has no button but can be opened at a specific
+ * browser location to implement context menus (for instance).
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * TODO - add open/close events?
+ *
+ * Extends:
+ * <Jx.Menu>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Menu.Context = new Class({
+ Extends: Jx.Menu,
+ /**
+ * Constructor: Jx.ContextMenu
+ * create a new context menu
+ *
+ * Parameters:
+ * id - {HTMLElement} element or id to make this the context menu
+ * for. The menu hooks the oncontextmenu event of the element
+ * and shows itself at the mouse position where the right-click
+ * happened.
+ */
+ initialize : function(id) {
+ this.parent();
+ if ($(id)) {
+ $(id).addEvent('contextmenu', this.show.bindWithEvent(this));
+ }
+ },
+ /**
+ * Method: show
+ * Show the context menu at the location of the mouse click
+ *
+ * Parameters:
+ * e - {Event} the mouse event
+ */
+ show : function(e) {
+ if (this.items.length ==0) {
+ return;
+ }
+
+ this.contentContainer.setStyle('visibility','hidden');
+ document.body.adopt(this.contentContainer);
+ /* we have to size the container for IE to render the chrome correctly
+ * but just in the menu/sub menu case - there is some horrible peekaboo
+ * bug in IE related to ULs that we just couldn't figure out
+ */
+ this.contentContainer.setContentBoxSize(this.subDomObj.getMarginBoxSize());
+
+ this.position(this.contentContainer, document.body, {
+ horizontal: [e.page.x + ' left'],
+ vertical: [e.page.y + ' top', e.page.y + ' bottom'],
+ offsets: this.chromeOffsets
+ });
+
+ this.contentContainer.setStyle('visibility','');
+ this.showChrome(this.contentContainer);
+
+ document.addEvent('mousedown', this.hideWatcher);
+ document.addEvent('keyup', this.keypressWatcher);
+
+ e.stop();
+ }
+});// $Id: panel.js 780 2008-08-26 14:54:47Z pspencer $
+/**
+ * Class: Jx.Panel
+ * A panel is a fundamental container object that has a content
+ * area and optional toolbars around the content area. It also
+ * has a title bar area that contains an optional label and
+ * some user controls as determined by the options passed to the
+ * constructor.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * close - fired when the panel is closed
+ * collapse - fired when the panel is collapsed
+ * expand - fired when the panel is opened
+ *
+ * Implements:
+ * * <Jx.UniqueId>
+ * * <Jx.ContentLoader>
+ * * Options
+ * * Events
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Panel = new Class({
+ Implements: [Options, Events, Jx.UniqueId, Jx.ContentLoader],
+
+ toolbarContainers: {
+ top: null,
+ right: null,
+ bottom: null,
+ left: null
+ },
+
+ options: {
+ label: ' ',
+ imageBaseUrl: Jx.baseURL + 'images/',
+ position: 'absolute',
+ height: null,
+ collapse: true,
+ detach: false,
+ close: false,
+ closed: false,
+ hideTitle: false,
+ type: 'Panel'
+ },
+
+ /**
+ * Constructor: Jx.Panel
+ * Initialize a new Jx.Panel instance
+ *
+ * Options:
+ *
+ * id - String, an id to assign to the panel's container
+ * label - String, the title of the Jx Panel
+ * hideTitle - Boolean, hide the title bar if true. False by default.
+ * toolbars - array of Jx.Toolbar objects to put in the panel. The position
+ * of each toolbar is used to position the toolbar within the panel.
+ * content - element to use as the content. A content area is created
+ * if none is provided. Otherwise, the content element is moved
+ * in the DOM
+ * collapse - boolean, determine if the panel can be collapsed and expanded
+ * by the user. This puts a control into the title bar for the user
+ * to control the state of the panel.
+ * detach - boolean, determine if the panel can be turned into a dialog
+ * by the user. If a panel is floated as a dialog, it can be docked back
+ * to where it came from. This option puts a control in the title bar
+ * of the panel.
+ * close - boolean, determine if the panel can be closed (hidden) by the user.
+ * The application needs to provide a way to re-open the panel after it is
+ * closed. The closeable property extends to dialogs created by floating
+ * panels. This option puts a control in the title bar of the panel.
+ * closed - boolean, initial state of the panel (true to start the panel
+ closed), default is false
+ * content options - See <Jx.ContentLoader::loadContent> for content related
+ * options.
+ * layout options - See <Jx.Layout::Jx.Layout> for layout related options.
+ * The default layout is to use height: null which causes the panel to
+ * fill its container (and resize if the container is a <Jx.Layout>
+ * controlled object). If you specify a height then the panel will
+ * occupy only that much space vertically and will fill the
+ * container's width (using the relative option in <Jx.Layout>).
+ *
+ * Inherits From:
+ * <Jx.UniqueId>, <Jx.ContentLoader>
+ */
+ initialize : function(options){
+ this.toolbars = options.toolbars || [];
+ this.setOptions(options);
+ if ($defined(this.options.height) && !$defined(options.position)) {
+ this.options.position = 'relative';
+ }
+ this.initUniqueId();
+
+ /* set up the title object */
+ this.title = new Element('div', {
+ 'class': 'jx'+this.options.type+'Title'
+ });
+
+ this.labelObj = new Element('span', {
+ 'class': 'jx'+this.options.type+'Label',
+ html: this.options.label
+ });
+ this.title.adopt(this.labelObj);
+
+ var controls = new Element('div', {
+ 'class': 'jx'+this.options.type+'Controls'
+ });
+ var tbDiv = new Element('div');
+ controls.adopt(tbDiv);
+ this.toolbar = new Jx.Toolbar({parent:tbDiv});
+ this.title.adopt(controls);
+
+ var that = this;
+
+ if (this.options.menu) {
+ this.menu = new Jx.Menu({
+ image: Jx.baseURL + 'images/panel_controls.png'
+ });
+ this.menu.domObj.addClass('jx'+this.options.type+'Menu');
+ this.menu.domObj.addClass('jxButtonContentLeft');
+ this.toolbar.add(this.menu);
+ }
+
+ if (this.options.collapse) {
+ var b = new Jx.Button({
+ image: Jx.baseURL + 'images/panel_controls.png',
+ tooltip: 'Collapse/Expand Panel',
+ onClick: function() {
+ that.toggleCollapse();
+ }
+ });
+ b.domObj.addClass('jx'+this.options.type+'Collapse');
+ this.toolbar.add(b);
+ if (this.menu) {
+ var item = new Jx.Menu.Item({
+ label: 'Collapse',
+ onClick: function() { that.toggleCollapse(); }
+ });
+ var button = item.button;
+ this.addEvent('collapse', function() {
+ if (that.options.closed) {
+ button.setLabel('Expand');
+ } else {
+ button.setLabel('Collapse');
+ }
+ });
+ this.menu.add(item);
+ }
+ }
+
+ if (this.options.maximize) {
+ var b = new Jx.Button({
+ image: Jx.baseURL + 'images/panel_controls.png',
+ tooltip: 'Maximize Panel',
+ onClick: function() {
+ that.maximize();
+ }
+ });
+ b.domObj.addClass('jx'+this.options.type+'Maximize');
+ this.toolbar.add(b);
+ if (this.menu) {
+ var item = new Jx.Menu.Item({
+ label: 'Maximize',
+ onClick: function() { that.maximize(); }
+ });
+ this.menu.add(item);
+ }
+ }
+
+ if (this.options.close) {
+ var b = new Jx.Button({
+ image: Jx.baseURL + 'images/panel_controls.png',
+ tooltip: 'Close Panel',
+ onClick: function() {
+ that.close();
+ }
+ });
+ b.domObj.addClass('jx'+this.options.type+'Close');
+ this.toolbar.add(b);
+ if (this.menu) {
+ var item = new Jx.Menu.Item({
+ label: 'Close',
+ onClick: function() {
+ that.close();
+ }
+ });
+ this.menu.add(item);
+ }
+
+ }
+
+ this.title.addEvent('dblclick', function() {
+ that.toggleCollapse();
+ });
+
+ this.domObj = new Element('div', {
+ 'class': 'jx'+this.options.type
+ });
+ if (this.options.id) {
+ this.domObj.id = this.options.id;
+ }
+ if ($(this.options.parent)) {
+ $(this.options.parent).adopt(this.domObj);
+ }
+ var jxl = new Jx.Layout(this.domObj, $merge(this.options, {propagate:false}));
+ var layoutHandler = this.layoutContent.bind(this);
+ jxl.addEvent('sizeChange', layoutHandler);
+
+ if (!this.options.hideTitle) {
+ this.domObj.adopt(this.title);
+ }
+
+ this.contentContainer = new Element('div', {
+ 'class': 'jx'+this.options.type+'ContentContainer'
+ });
+ this.domObj.adopt(this.contentContainer);
+
+ for (var i=0; i<this.toolbars.length; i++) {
+ var tb = this.toolbars[i];
+ tb.addEvent('add', layoutHandler);
+ tb.addEvent('remove', layoutHandler);
+ var position = tb.options.position;
+ var tbc = this.toolbarContainers[position];
+ if (!tbc) {
+ var tbc = new Element('div', {
+ 'class':'jxToolbarContainer '+'jxBar'+position.capitalize()
+ });
+ new Jx.Layout(tbc);
+ var clearer = new Element('div', {'class':'jxClearer'});
+ tbc.appendChild(clearer);
+ this.contentContainer.adopt(tbc);
+ this.toolbarContainers[position] = tbc;
+ }
+ var tbObj = tb.domObj;
+ tbc.insertBefore(tbObj, tbc.lastChild);
+ }
+
+ this.content = new Element('div', {
+ 'class': 'jx'+this.options.type+'Content'
+ });
+
+ new Jx.Layout(this.contentContainer);
+ new Jx.Layout(this.content);
+ this.contentContainer.adopt(this.content);
+ this.loadContent(this.content, options);
+
+ this.toggleCollapse(this.options.closed);
+ },
+
+ layoutContent: function() {
+ var titleHeight = 0;
+ var top = 0;
+ var bottom = 0;
+ var left = 0;
+ var right = 0;
+ var tbc;
+ var tb;
+ var position;
+ if (!this.options.hideTitle && this.title.parentNode == this.domObj) {
+ titleHeight = this.title.getMarginBoxSize().height;
+ }
+ var domSize = this.domObj.getContentBoxSize();
+ if (domSize.height > titleHeight) {
+ this.contentContainer.setStyle('display','block');
+ this.options.closed = false;
+ this.contentContainer.resize({top: titleHeight, height: null, bottom: 0});
+ ['left','right'].each(function(position){
+ if (this.toolbarContainers[position]) {
+ this.toolbarContainers[position].style.width = '';
+ }
+ }, this);
+ ['top','bottom'].each(function(position){
+ if (this.toolbarContainers[position]) {
+ this.toolbarContainers[position].style.height = '';
+ }
+ }, this);
+ for (var i=0; i<this.toolbars.length; i++) {
+ tb = this.toolbars[i];
+ position = tb.options.position;
+ tbc = this.toolbarContainers[position];
+ var size = tbc.getBorderBoxSize();
+ switch(position) {
+ case 'top':
+ top = size.height;
+ break;
+ case 'bottom':
+ bottom = size.height;
+ break;
+ case 'left':
+ left = size.width;
+ break;
+ case 'right':
+ right = size.width;
+ break;
+ }
+
+ }
+ tbc = this.toolbarContainers['top'];
+ if (tbc) {
+ tbc.resize({top: 0, left: left, right: right, bottom: null, height: top, width: null});
+ }
+ tbc = this.toolbarContainers['bottom'];
+ if (tbc) {
+ tbc.resize({top: null, left: left, right: right, bottom: 0, height: bottom, width: null});
+ }
+ tbc = this.toolbarContainers['left'];
+ if (tbc) {
+ tbc.resize({top: top, left: 0, right: null, bottom: bottom, height: null, width: left});
+ }
+ tbc = this.toolbarContainers['right'];
+ if (tbc) {
+ tbc.resize({top: top, left: null, right: 0, bottom: bottom, height: null, width: right});
+ }
+ this.content.resize({top: top, bottom: bottom, left: left, right: right});
+ } else {
+ this.contentContainer.setStyle('display','none');
+ this.options.closed = true;
+ }
+ },
+
+ /**
+ * Method: setLabel
+ * Set the label in the title bar of this panel
+ *
+ * Parameters:
+ * s - {String} the new label
+ */
+ setLabel: function(s) {
+ this.labelObj.innerHTML = s;
+ },
+ /**
+ * Method: getLabel
+ * Get the label of the title bar of this panel
+ *
+ * Returns:
+ * {String} the label
+ */
+ getLabel: function() {
+ return this.labelObj.innerHTML;
+ },
+ /**
+ * Method: finalize
+ * Clean up the panel
+ */
+ finalize: function() {
+ this.domObj = null;
+ this.deregisterIds();
+ },
+ /**
+ * Method: maximize
+ * Maximize this panel
+ */
+ maximize: function() {
+ if (this.manager) {
+ this.manager.maximizePanel(this);
+ }
+ },
+ /**
+ * Method: setContent
+ * set the content of this panel to some HTML
+ *
+ * Parameters:
+ * html - {String} the new HTML to go in the panel
+ */
+ setContent : function (html) {
+ //console.log('Jx.Panel::setContent()');
+ this.content.innerHTML = html;
+ this.bContentReady = true;
+ },
+ /**
+ * Method: setContentURL
+ * Set the content of this panel to come from some URL.
+ *
+ * Parameters:
+ * url - {String} URL to some HTML content for this panel
+ */
+ setContentURL : function (url) {
+ this.bContentReady = false;
+ this.setBusy(true);
+ if (arguments[1]) {
+ this.onContentReady = arguments[1];
+ }
+ if (url.indexOf('?') == -1) {
+ url = url + '?';
+ }
+ //var ts = (new Date()).getTime();
+ //url = url + 'ts='+ts;
+ var opts = { method: 'get',
+ onComplete:this.panelContentLoaded.bind(this),
+ requestHeaders: ['If-Modified-Since', 'Sat, 1 Jan 2000 00:00:00 GMT']};
+ var a = new Request(url, opts).send();
+ },
+ /**
+ * Method: panelContentLoaded
+ * When the content of the panel is loaded from a remote URL, this
+ * method is called when the ajax request returns.
+ *
+ * Parameters:
+ * r - {XmlHttpRequest} the XmlHttpRequest object
+ */
+ panelContentLoaded: function(r) {
+ this.content.innerHTML = r.responseText;
+ this.bContentReady = true;
+ this.setBusy(false);
+ if (this.onContentReady) {
+ window.setTimeout(this.onContentReady.bind(this),1);
+ }
+ },
+ /**
+ * Method: setBusy
+ * Set the panel as busy or not busy, which displays a loading image
+ * in the title bar.
+ *
+ * Parameters:
+ * isBusy - {Boolean} the busy state
+ */
+ setBusy : function(isBusy) {
+ this.busyCount += isBusy?1:-1;
+ this.loadingObj.img.style.visibility = (this.busyCount>0)?'visible':'hidden';
+ },
+
+ /**
+ * Method: addTo
+ * adds the panel to a DOM element using appendChild if sibling
+ * is not specified or sibling's parent is not the specified parent,
+ * otherwise uses insertBefore.
+ *
+ * Parameters:
+ * parent - {Object} the DOM element or id of a DOM element
+ * to append the panel to.
+ * sibling - {Object} the DOM element or id of a DOM element
+ * to insert the panel before. If not specified, then the
+ * panel is appended to the parent.
+ */
+ addTo: function(parent, sibling) {
+ parent = $(parent);
+ sibling = sibling ? $(sibling) : null;
+ if (sibling && sibling.parentNode == parent) {
+ parent.insertBefore(this.domObj, sibling);
+ } else {
+ parent.appendChild(this.domObj);
+ }
+ this.domObj.resize();
+ },
+
+ /**
+ * Method: toggleCollapse
+ * sets or toggles the collapsed state of the panel. If a
+ * new state is passed, it is used, otherwise the current
+ * state is toggled.
+ *
+ * Parameters:
+ * state - optional, if passed then the state is used,
+ * otherwise the state is toggled.
+ */
+ toggleCollapse: function(state) {
+ if ($defined(state)) {
+ this.options.closed = state;
+ } else {
+ this.options.closed = !this.options.closed;
+ }
+ if (this.options.closed) {
+ if (!this.domObj.hasClass('jx'+this.options.type+'Min')) {
+ this.domObj.addClass('jx'+this.options.type+'Min');
+ this.contentContainer.setStyle('display','none');
+ var margin = this.domObj.getMarginSize();
+ var height = margin.top + margin.bottom;
+ if (this.title.parentNode == this.domObj) {
+ height += this.title.getMarginBoxSize().height;
+ }
+ this.domObj.resize({height: height});
+ this.fireEvent('collapse', this);
+ }
+ } else {
+ if (this.domObj.hasClass('jx'+this.options.type+'Min')) {
+ this.domObj.removeClass('jx'+this.options.type+'Min');
+ this.contentContainer.setStyle('display','block');
+ this.domObj.resize({height: this.options.height});
+ this.fireEvent('expand', this);
+ }
+ }
+ },
+
+ /**
+ * Method: close
+ * Closes the panel (completely hiding it).
+ */
+ close: function() {
+ this.domObj.dispose();
+ this.fireEvent('close', this);
+ }
+
+});// $Id: dialog.js 782 2008-08-26 17:36:11Z pspencer $
+/**
+ * Class: Jx.Dialog
+ * A Jx.Dialog implements a floating dialog. Dialogs represent a useful way
+ * to present users with certain information or application controls.
+ * Jx.Dialog is designed to provide the same types of features as traditional
+ * operating system dialog boxes, including:
+ *
+ * - dialogs may be modal (user must dismiss the dialog to continue) or
+ * non-modal
+ *
+ * - dialogs are movable (user can drag the title bar to move the dialog
+ * around)
+ *
+ * - dialogs may be a fixed size or allow user resizing.
+ *
+ * Jx.Dialog uses <Jx.ContentLoader> to load content into the content area
+ * of the dialog. Refer to the <Jx.ContentLoader> documentation for details
+ * on content options.
+ *
+ * Example:
+ * (code)
+ * var dialog = new Jx.Dialog();
+ * (end)
+ *
+ * Events:
+ * open - triggered when the dialog is opened
+ * close - triggered when the dialog is closed
+ * change - triggered when the value of an input in the dialog is changed
+ * resize - triggered when the dialog is resized
+ *
+ * Extends:
+ * <Jx.Panel>
+ *
+ * Implements:
+ * <Jx.AutoPosition>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Dialog = new Class({
+ Extends: Jx.Panel,
+ Implements: [Jx.AutoPosition, Jx.Chrome],
+
+ /**
+ * Property: {HTMLElement} blanket
+ * modal dialogs prevent interaction with the rest of the application
+ * while they are open, this element is displayed just under the
+ * dialog to prevent the user from clicking anything.
+ */
+ blanket: null,
+
+ options: {
+ modal: true,
+ position: 'absolute',
+ width: 250,
+ height: 250,
+ left: 0,
+ top: 0,
+ bottom: null,
+ right: null,
+ label: 'New Dialog',
+ id: '',
+ parent: null,
+ resize: false,
+ move: true,
+ close: true,
+ collapse: true
+ },
+ /**
+ * Constructor: Jx.Dialog
+ * Construct a new instance of Jx.Dialog
+ *
+ * Parameters:
+ * options - {Object} an object containing options for the dialog.
+ *
+ * Options:
+ * modal - (optional) {Boolean} controls whether the dialog will be modal
+ * or not. The default is to create modal dialogs.
+ * top - (optional) {Integer} the distance in pixels to initially place
+ * the dialog from the top edge of its container. Default is 0 unless
+ * bottom is specified, in which case the top value is not used.
+ * bottom - (optional) {Integer} the distance in pixels to initially place
+ * the dialog from the bottom edge of its container. Default is null, which
+ * means that the dialog is not positioned relative to the bottom of its
+ * container. If top and bottom are specified, top is used.
+ * left - (optional) {Integer} the distance in pixels to initially place
+ * the dialog from the left edge of its container.
+ * right - (optional) {Integer} the distance in pixels to initially place
+ * the dialog from the right edge of its container. Default is null, which
+ * means that the dialog is not positioned relative to the right of its
+ * container. If left and right are specified, left is used.
+ * width - (optional) {Integer} the initial width in pixels of the dialog.
+ * The default value is 250 if not specified.
+ * height - (optional) {Integer} the initial height in pixels of the
+ * dialog. The default value is 250 if not specified.
+ * label - (optional) {String} the title of the dialog box. "New Dialog"
+ * is the default value.
+ * content - (optional) {Mixed} passed to <Jx.ContentLoader> for loading
+ * dialog content.
+ * contentURL - (optional) {String} passed to <Jx.ContentLoader> for loading
+ * dialog content.
+ * id - (optional) {String} an HTML ID to assign to the dialog, primarily
+ * used for applying CSS styles to specific dialogs
+ * parent - (optional) {HTMLElement} a reference to an HTML element that
+ * the dialog is to be contained by. The default value is for the dialog
+ * to be contained by the body element.
+ * resize - (optional) {Boolean} determines whether the dialog is
+ * resizeable by the user or not. Default is false.
+ * move - (optional) {Boolean} determines whether the dialog is
+ * moveable by the user or not. Default is true.
+ */
+ initialize: function(options) {
+ /* initialize class-wide singleton that holds the current z-order
+ * of all dialogs
+ */
+ if (!Jx.Dialog.Stack) {
+ Jx.Dialog.Stack = [];
+ Jx.Dialog.ZIndex = [100];
+ }
+
+ this.isOpening = false;
+
+ /* initialize the panel overriding the type and position */
+ this.parent($merge(
+ {parent:document.body}, // these are defaults that can be overridden
+ options,
+ {type:'Dialog', position: 'absolute'} // these override anything passed to the options
+ ));
+ this.options.parent = $(this.options.parent);
+
+ if (!window.opera && this.options.modal) {
+ this.blanket = new Element('div',{
+ 'class':'jxDialogModal',
+ styles:{
+ display:'none',
+ zIndex: -1
+ }
+ });
+
+ this.options.parent.adopt(this.blanket);
+ (new Jx.Layout(this.blanket)).resize();
+ }
+
+ this.domObj.setStyle('display','none');
+ this.options.parent.adopt(this.domObj);
+
+ /* the dialog is moveable by its title bar */
+ if (this.options.move) {
+ this.title.addClass('jxDialogMoveable');
+ new Drag(this.domObj, {
+ handle: this.title,
+ onStart: (function() {
+ this.contentContainer.setStyle('visibility','hidden');
+ }).bind(this),
+ onComplete: (function() {
+ this.contentContainer.setStyle('visibility','');
+ this.position(this.domObj, this.options.parent, {
+ horizontal:[parseInt(this.domObj.style.left)+' left'],
+ vertical: [parseInt(this.domObj.style.top)+' top']
+ });
+ this.options.left = parseInt(this.domObj.style.left);
+ this.options.top = parseInt(this.domObj.style.top);
+ if (!this.options.closed) {
+ this.domObj.resize(this.options);
+ }
+ }).bind(this)
+ });
+ }
+
+ /* the dialog is resizeable */
+ if (this.options.resize) {
+ this.resizeHandle = new Element('div', {
+ 'class':'jxDialogResize',
+ styles: {
+ 'display':this.options.closed?'none':'block'
+ }
+ });
+ this.domObj.appendChild(this.resizeHandle);
+
+ this.resizeHandleSize = this.resizeHandle.getSize();
+ this.resizeHandle.setStyles({
+ bottom: this.resizeHandleSize.height,
+ right: this.resizeHandleSize.width
+ });
+ this.domObj.makeResizable({
+ handle:this.resizeHandle,
+ onStart: (function() {
+ this.contentContainer.setStyle('visibility','hidden');
+ }).bind(this),
+ onDrag: this.resizeChrome.bind(this),
+ onComplete: (function() {
+ var size = this.domObj.getMarginBoxSize();
+ this.options.width = size.width;
+ this.options.height = size.height;
+ this.layoutContent();
+ this.domObj.resize(this.options);
+ this.contentContainer.setStyle('visibility','');
+ this.fireEvent('resize');
+ }).bind(this)
+ });
+ }
+ /* this adjusts the z-index of the dialogs when activated */
+ this.domObj.addEvent('mousedown', (function(){
+ Jx.Dialog.Stack.erase(this).push(this);
+ Jx.Dialog.Stack.each(function(d, i) {
+ d.domObj.setStyle('zIndex',101+i);
+ });
+ }).bind(this));
+ },
+
+ /**
+ * Method: sizeChanged
+ * overload panel
+ */
+ sizeChanged: function() {
+ if (!this.options.closed) {
+ this.layoutContent();
+ this.resizeChrome();
+ }
+ },
+
+ /**
+ * Method: toggleCollapse
+ * sets or toggles the collapsed state of the panel. If a
+ * new state is passed, it is used, otherwise the current
+ * state is toggled.
+ *
+ * Parameters:
+ * state - optional, if passed then the state is used,
+ * otherwise the state is toggled.
+ */
+ toggleCollapse: function(state) {
+ if ($defined(state)) {
+ this.options.closed = state;
+ } else {
+ this.options.closed = !this.options.closed;
+ }
+ if (this.options.closed) {
+ if (!this.domObj.hasClass('jx'+this.options.type+'Min')) {
+ this.domObj.addClass('jx'+this.options.type+'Min');
+ }
+ this.contentContainer.setStyle('display','none');
+ if (this.resizeHandle) {
+ this.resizeHandle.setStyle('display','none');
+ }
+ } else {
+ if (this.domObj.hasClass('jx'+this.options.type+'Min')) {
+ this.domObj.removeClass('jx'+this.options.type+'Min');
+ }
+ this.contentContainer.setStyle('display','block');
+ if (this.resizeHandle) {
+ this.resizeHandle.setStyle('display','block');
+ }
+ }
+
+ if (this.options.closed) {
+ var margin = this.domObj.getMarginSize();
+ var size = this.title.getMarginBoxSize();
+ this.domObj.resize({height: margin.top + size.height + margin.bottom});
+ this.fireEvent('collapse');
+ } else {
+ this.domObj.resize(this.options);
+ this.fireEvent('expand');
+ }
+ },
+
+ /**
+ * Method: setTitle
+ * set the text of the dialog title.
+ *
+ * Parameters:
+ * title - {String} the new title
+ */
+ setTitle: function( title ) {
+ this.title.childNodes[0].innerHTML = title;
+ },
+
+ /**
+ * Method: show
+ * show the dialog
+ */
+ show : function( ) {
+
+ /* get the z-index right */
+ Jx.Dialog.Stack.push(this);
+ /* do the modal thing */
+ if (this.options.modal) {
+ this.blanket.setStyles({
+ zIndex: Jx.Dialog.ZIndex[0]++,
+ visibility: 'visible',
+ display: 'block'
+ });
+ }
+ /* display the dialog */
+ this.domObj.setStyles({
+ zIndex: Jx.Dialog.ZIndex[0]++,
+ display: 'block'
+ });
+ if (this.options.closed) {
+ var margin = this.domObj.getMarginSize();
+ var size = this.title.getMarginBoxSize();
+ this.domObj.resize({height: margin.top + size.height + margin.bottom});
+ } else {
+ this.domObj.resize(this.options);
+ }
+ /* update or create the chrome */
+ this.showChrome(this.domObj);
+ /* put it in the right place using auto-positioning */
+ this.position(this.domObj, this.options.parent, {
+ horizontal: [this.options.left+' left'],
+ vertical: [this.options.top+' top']
+ });
+ this.options.left = parseInt(this.domObj.style.left);
+ this.options.top = parseInt(this.domObj.style.top);
+ },
+ /**
+ * Method: hide
+ * hide the dialog
+ */
+ hide : function() {
+ Jx.Dialog.Stack.erase(this);
+ Jx.Dialog.ZIndex[0]--;
+ this.domObj.setStyle('display','none');
+ if (this.options.modal) {
+ this.blanket.setStyle('visibility', 'hidden');
+ Jx.Dialog.ZIndex[0]--;
+ }
+
+ },
+ /**
+ * Method: open
+ * open the dialog. This may be delayed depending on the
+ * asynchronous loading of dialog content. The onOpen
+ * callback function is called when the dialog actually
+ * opens
+ */
+ open: function() {
+ if (!this.isOpening) {
+ this.isOpening = true;
+ }
+ if (this.contentIsLoaded) {
+ this.show();
+ this.fireEvent('open', this);
+ this.isOpening = false;
+ }
+ },
+ /**
+ * Method: close
+ * close the dialog and trigger the onClose callback function
+ * if necessary
+ */
+ close: function() {
+ this.isOpening = false;
+ this.hide();
+ this.fireEvent('close');
+ },
+ /**
+ * Method: onContentLoaded
+ * handle the dialog content being loaded. This triggers
+ * processing of inputs and the onContentLoaded callback
+ * function (if necessary). Also, if the dialog was previously
+ * requested to be opened, this will actually open it.
+ */
+ onContentLoaded : function() {
+ if (this.isOpening) {
+ this.open();
+ }
+ }
+});
+// $Id: panelset.js 762 2008-08-20 20:59:40Z pspencer $
+/**
+ * Class: Jx.PanelSet
+ *
+ * Example:
+ * A panel set manages a set of panels within a DOM element. The PanelSet fills
+ * its container by resizing the panels in the set to fill the width and then
+ * distributing the height of the container across all the panels. Panels
+ * can be resized by dragging their respective title bars to make them taller
+ * or shorter. The maximize button on the panel title will cause all other
+ * panels to be closed and the target panel to be expanded to fill the remaining
+ * space. In this respect, PanelSet works like a traditional Accordion control.
+ *
+ * When creating panels for use within a panel set, it is important to use the
+ * proper options. You must override the collapse option and set it to false
+ * and add a maximize option set to true. You must also not include options
+ * for menu and close.
+ *
+ * (code)
+ * var p1 = new Jx.Panel({collapse: false, maximize: true, content: 'content1'});
+ * var p2 = new Jx.Panel({collapse: false, maximize: true, content: 'content2'});
+ * var p3 = new Jx.Panel({collapse: false, maximize: true, content: 'content3'});
+ * var panelSet = new Jx.PanelSet('panels', [p1,p2,p3]);
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.PanelSet = new Class({
+ /**
+ * Property: panels
+ * {Array} the panels being managed by the set
+ */
+ panels: null,
+ /**
+ * Property: height
+ * {Integer} the height of the container, cached for speed
+ */
+ height: null,
+ /**
+ * Property: firstLayout
+ * {Boolean} true until the panel set has first been resized
+ */
+ firstLayout: true,
+ /**
+ * Constructor: Jx.PanelSet
+ * Create a new instance of Jx.PanelSet.
+ *
+ * Parameters:
+ * domObj - {HTMLElement} the HTML element that will contain the panels
+ * panels - {Array} the panels to go into the PanelSet
+ *
+ * TODO: Jx.PanelSet.initialize
+ * Remove the panels parameter in favour of an add method.
+ */
+ initialize: function(domObj, panels) {
+ this.domObj = $(domObj);
+ this.panels = panels;
+ var d = new Element('div', {styles:{position:'absolute'}});
+ new Jx.Layout(d, {minHeight:0,maxHeight:0,height:0});
+ var elements = [d];
+ panels.each(function(panel){
+ elements.push(panel.domObj);
+ panel.options.hideTitle = true;
+ panel.contentContainer.resize({top:0});
+ panel.addEvent('expand', this.maximizePanel.bind(this, panel));
+ panel.domObj.store('Jx.Panel', panel);
+ }, this);
+
+ this.splitter = new Jx.Splitter(this.domObj, {splitInto: panels.length+1,
+ layout: 'vertical',
+ elements: elements });
+ /* redirect splitter sizeChanged so we can capture the first time the
+ * splitter is layed out in the client in a way that we can measure
+ * the title bar heights
+ */
+ this.splitter.sizeChanged = this.sizeChanged.bind(this);
+ /* create the bars for the panel set */
+ for (var i=0; i<this.panels.length; i++) {
+ var panel = this.panels[i];
+ var bar = this.splitter.bars[i];
+ panel.title.setStyle('visibility', 'hidden');
+ document.body.adopt(panel.title);
+ var size = panel.title.getBorderBoxSize();
+ bar.adopt(panel.title);
+ panel.title.setStyle('visibility','');
+ bar.setStyle('height', size.height);
+ bar.removeClass('jxSplitterBar');
+ bar.addClass('jxPanelBar');
+ panel.manager = this;
+ }
+ },
+ /**
+ * Method: sizeChanged
+ * called when the size of the container of the splitter changes. This tracks the
+ * first time the panel titles have a non-zero height (i.e. they are put in the
+ * DOM and are visible) and recalculates the panel title height then.
+ */
+ sizeChanged: function() {
+ if (this.firstLayout) {
+ if (this.panels[0].title.getBorderBoxSize().height != 0) {
+ for (var i=0; i<this.splitter.bars.length; i++) {
+ var panel = this.panels[i];
+ this.splitter.bars[i].style.height = panel.title.getBorderBoxSize().height + 'px';
+ this.splitter.bars[i].store('size', null);
+ }
+ this.firstLayout = false;
+ Jx.Splitter.prototype.sizeChanged.apply(this.splitter, []);
+ }
+ } else {
+ Jx.Splitter.prototype.sizeChanged.apply(this.splitter, []);
+ }
+ },
+
+ /**
+ * Method: maximizePanel
+ * Maximize the panel, taking up all available space (taking into
+ * consideration any minimum or maximum values)
+ */
+ maximizePanel: function(panel) {
+ var h = this.domObj.getContentBoxSize().height;
+
+ var t = 0;
+ for (var i=1; i<this.splitter.elements.length; i++) {
+ var p = this.splitter.elements[i];
+ t += p.retrieve('leftBar').getBorderBoxSize().height;
+ if (p !== panel.domObj) {
+ var thePanel = p.retrieve('Jx.Panel');
+ var o = p.retrieve('jxLayout').options;
+ p.resize({top: t, height: o.minHeight, bottom: null});
+ t += o.minHeight;
+ p.retrieve('rightBar').style.top = t + 'px';
+ } else {
+ break;
+ }
+ }
+
+ b = h;
+ for (var i=this.splitter.elements.length - 1; i > 0; i--) {
+ p = this.splitter.elements[i];
+ if (p !== panel.domObj) {
+ var o = p.retrieve('jxLayout').options;
+ b -= o.minHeight;
+ p.resize({top: b, height: o.minHeight, bottom: null});
+ b -= p.retrieve('leftBar').getBorderBoxSize().height;
+ p.retrieve('leftBar').style.top = b + 'px';
+
+ } else {
+ break;
+ }
+ }
+ panel.domObj.resize({top: t, height:b - t, bottom: null});
+ }
+});// $Id: combo.js 751 2008-08-16 13:15:37Z pspencer $
+/**
+ * Class: Jx.Combo
+ * A drop down list of selectable items that can be any HTML.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * changed - the main item has changed
+ *
+ * Implements:
+ * * Options
+ * * Events
+ * * <Jx.AutoPosition>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Combo = new Class({
+ Implements: [Options,Events,Jx.AutoPosition],
+ /**
+ * Property: domObj
+ * {HTMLElement} the div that contains the control,
+ * used to show/hide the control
+ */
+ domObj : null,
+ /**
+ * Property: ul
+ * {HTMLElement} the ul that contains the selectable items
+ */
+ ul : null,
+ /**
+ * Property: currentSelection
+ * {Object} current selection in the list
+ */
+ currentSelection : null,
+
+ /**
+ * Constructor: Jx.Combo
+ * create a new instance of Jx.Combo
+ *
+ * Options:
+ * editable - {Boolean} defaults to false. If true, then the selected item
+ * is editable.
+ */
+ initialize: function(options) {
+ this.setOptions(options);
+
+ this.domObj = new Element('div',{
+ 'class':'jxCombo'
+ });
+ if (this.options.id) {
+ this.domObj.id = this.options.id;
+ }
+
+ if (this.options.editable) {
+ this.domInput = new Element('input',{
+ 'class':'jxComboInput',
+ type:'text',
+ events:{
+ change: this.valueChanged.bindWithEvent(this),
+ keydown: this.onKeyPress.bindWithEvent(this)
+ }
+ });
+ } else {
+ this.domInput = new Element('span', {
+ 'class':'jxComboInput'
+ });
+ }
+
+ this.domObj.appendChild(this.domInput);
+
+ this.domA = new Element('a',{
+ 'class':'jxComboDiscloser',
+ href: 'javascript:void(0)',
+ events:{
+ click: this.toggle.bind(this)
+ }
+ });
+
+ this.domButton = new Element('img', {
+ 'class':'png24',
+ src: Jx.baseURL + 'images/disclose2.png'
+ });
+ this.domA.appendChild(this.domButton);
+ this.domObj.appendChild(this.domA);
+
+ if (!window.opera) {
+ //insert iframeShim for IE to cover other controls in the page.
+ this.domObj.appendChild(Jx.createIframeShim());
+ }
+
+ this.domListDiv = new Element('div',{
+ 'class':'jxComboOptions'
+ });
+ this.domList = new Element('ul');
+ this.domListDiv.appendChild(this.domList);
+
+ this.keypressHandler = this.keypress.bindWithEvent(this);
+ this.clickHandler = this.click.bindWithEvent(this);
+ },
+
+ /**
+ * Method: onKeyPress
+ * Handle the user pressing a key by looking for an ENTER key to set the
+ * value.
+ *
+ * Parameters:
+ * e - {Event} the keypress event
+ */
+ onKeyPress: function(e) {
+ if (e.key == 'enter') {
+ this.valueChanged();
+ }
+ },
+
+ /**
+ * Method: valueChanged
+ * When the value is changed, propogate the change to the selection
+ * listeners
+ */
+ valueChanged: function() {
+ this.fireEvent('changed', this);
+ },
+
+ /**
+ * Method: add
+ * add a new item to the pick list
+ *
+ * Parameters:
+ * domObj - {HTMLElement} the element to add
+ * idx - {Integer} the index to add the element add
+ */
+ add: function(domObj, idx) {
+ var li = new Element('li');
+ var a = new Element('a', {
+ href: 'javascript:void(0)',
+ events: {
+ click: this.pick.bindWithEvent(this)
+ }
+ });
+
+ if ($type(domObj) == 'string') {
+ a.innerHTML = domObj;
+ } else {
+ a.appendChild(domObj);
+ }
+ li.appendChild(a);
+
+ if (arguments.length > 1 && this.domList.childNodes.length > idx) {
+ this.domList.insertBefore(li, this.domList.childNodes[idx]);
+ } else {
+ this.domList.appendChild(li);
+ }
+ if (this.getValue() == '') {
+ this.setValue(a.childNodes[0]);
+ }
+ },
+
+ /**
+ * Method: remove
+ * Remove the item at the given index
+ *
+ * Parameters:
+ * idx - {Integer} the item to remove.
+ */
+ remove: function(idx) {
+ if (idx > 0 && idx < this.domList.childNodes.length) {
+ this.domList.removeChild(this.domList.childNodes[idx]);
+ }
+ },
+
+ /**
+ * Method: pick
+ * user has clicked something in the list, select it
+ *
+ * Parameters:
+ * e - {Event} the mouse event from the user's click
+ */
+ pick: function(e) {
+ var target = e.target;
+ if (target.tagName == 'A') {
+ this.currentSelection = target;
+ this.setValue(this.currentSelection.childNodes[0]);
+ this.valueChanged();
+ }
+ this.close();
+ },
+ /**
+ * Method: setValue
+ * set the value of the Combo
+ *
+ * Parameters:
+ * value - {Object} the new value. May be a string, a text node, or
+ * another DOM element.
+ */
+ setValue: function(value) {
+ if (this.options.editable) {
+ if (typeof(value) == 'string') {
+ this.domInput.value = value;
+ } else if (value.nodeType && value.nodeType == 3) {
+ this.domInput.value = value.nodeValue;
+ } else {
+ this.domInput.value = value.innerHTML;
+ }
+ } else {
+ if (typeof(value) == 'string') {
+ this.domInput.innerHTML = value;
+ } else if (value.nodeType && value.nodeType == 3) {
+ this.domInput.innerHTML = value.nodeValue;
+ } else {
+ this.domInput.appendChild(value);
+ }
+ }
+ },
+
+ /**
+ * Method: getValue
+ * Return the current value
+ *
+ * Returns:
+ * {Object} returns the currently selected item
+ */
+ getValue: function() {
+ value = '';
+ if (this.options.editable) {
+ value = this.domInput.value;
+ } else if (this.domInput.childNodes.length > 0) {
+ if (this.domInput.childNodes[0].nodeType == 3) {
+ value = this.domInput.innerHTML;
+ } else {
+ value = this.domInput.childNodes[0];
+ }
+ }
+ return value;
+ },
+
+ /**
+ * Method: toggle
+ * Toggle the display of the list associated with the Combo
+ */
+ toggle: function() {
+ if (this.domListDiv.style.display == 'block') {
+ this.close();
+ } else {
+ this.open();
+ }
+ },
+
+ /**
+ * Method: open
+ * Open the pick list
+ */
+ open: function() {
+ this.position(this.domListDiv, this.domObj, {
+ horizontal: ['left left', 'right right'],
+ vertical: ['bottom top', 'top bottom']
+ });
+ this.domListDiv.width = '';
+ this.domListDiv.setStyle('visibility','hidden');
+ document.body.adopt(this.domListDiv);
+ this.domListDiv.setBorderBoxSize({width: Math.max(this.domListDiv.getSize().x, this.domObj.getSize().x)});
+ this.domListDiv.setStyle('visibility','');
+ document.addEvents({
+ keydown: this.keypressHandler,
+ click: this.clickHandler
+ });
+ },
+ /**
+ * Method: keypress
+ * Handle a key press event when the list is open so we can close it if the
+ * user hits the ESC key.
+ *
+ * Parameters:
+ * e - {Event} the keypress event
+ */
+ keypress: function(e) {
+ if (e.key == 'esc') {
+ this.close();
+ }
+ },
+ /**
+ * Method: click
+ * Handle the user clicking on the page, close the picker if it is not
+ * us that was clicked on
+ */
+ click: function(e) {
+ if (!e.target.descendantOf(this.domListDiv) &&
+ !e.target.descendantOf(this.domObj)) {
+ this.close();
+ }
+ },
+ /**
+ * Method: close
+ * Close the Combo.
+ */
+ close: function() {
+ this.domListDiv.dispose();
+ document.removeEvents({
+ keydown: this.keypressHandler,
+ click: this.clickHandler
+ });
+ },
+ /**
+ * Method: getSelection
+ * return the current selection
+ *
+ * Returns:
+ * {Object} the current selection or an empty string.
+ */
+ getSelection: function() {
+ return this.currentSelection ? this.currentSelection.name : '';
+ }
+});// $Id: splitter.js 775 2008-08-22 14:27:26Z pspencer $
+/**
+ * Class: Jx.Splitter
+ * a Jx.Splitter creates two or more containers within a parent container
+ * and provides user control over the size of the containers. The split
+ * can be made horizontally or vertically.
+ *
+ * A horizontal split creates containers that divide the space horizontally
+ * with vertical bars between the containers. A vertical split divides
+ * the space vertically and creates horizontal bars between the containers.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+
+Jx.Splitter = new Class({
+ Implements: [Options],
+ /**
+ * Property: domObj
+ * {HTMLElement} the element being split
+ */
+ domObj: null,
+ /**
+ * Property: elements
+ * {Array} an array of elements that are displayed in each of the split
+ * areas
+ */
+ elements: null,
+ /**
+ * Property: bars
+ * {Array} an array of the bars between each of the elements used to
+ * resize the split areas.
+ */
+ bars: null,
+ /**
+ * Property: firstUpdate
+ * {Boolean} track the first resize event so that unexposed Jx things
+ * can be forced to calculate their size the first time they are exposed.
+ */
+ firstUpdate: true,
+ options: {
+ useChildren: false,
+ splitInto: 2,
+ elements: null,
+ containerOptions: [],
+ barOptions: [],
+ layout: 'horizontal',
+ snaps: []
+ },
+ /**
+ * Constructor: Jx.Splitter
+ * Create a new instance of Jx.Splitter
+ *
+ * Parameters:
+ * domObj - {HTMLElement} the element or id of the element to split
+ * options - {Object} optional arguments specified as properties of
+ * this object are as below.
+ *
+ * Options:
+ * useChildren - {Boolean} if set to true, then the children of the
+ * element to be split are used as the elements. The default value is
+ * false. If this is set, then the elements and splitInto options
+ * are ignored.
+ * elements - {Array} an array of elements to put into the split areas.
+ * If splitInto is not set, then it is calculated from the length of
+ * this array.
+ * splitInto - {Integer} the number of elements to split the domObj into.
+ * If not set, then the length of the elements option is used, or 2 if
+ * elements is not specified. If splitInto is specified and elements
+ * is specified, then splitInto is used. If there are more elements than
+ * splitInto specifies, then the extras are ignored. If there are less
+ * elements than splitInto specifies, then extras are created.
+ * containerOptions - {Array} an array of objects that provide options
+ * for the <Jx.Layout> constraints on each element.
+ * barOptions - {Array} an array of object that provide options for the bars,
+ * this array should be one less than the number of elements in the
+ * splitter. The barOptions objects can contain a snap property indicating
+ * that a default snap object should be created in the bar and the value
+ * of 'before' or 'after' indicates which element it snaps open/shut.
+ * layout - {String} either 'horizontal' or 'vertical', indicating the
+ * direction in which the domObj is to be split.
+ * snaps - {Array} an array of objects which can be used to snap
+ * elements open or closed.
+ */
+ initialize: function(domObj, options) {
+ this.setOptions(options);
+
+ this.domObj = $(domObj);
+ this.domObj.addClass('jxSplitContainer');
+ this.domObj.setStyle('overflow', 'hidden')
+ var jxLayout = this.domObj.retrieve('jxLayout');
+ if (jxLayout) {
+ jxLayout.addEvent('sizeChange', this.sizeChanged.bind(this));
+ }
+
+ this.elements = [];
+ this.bars = [];
+
+ var nSplits = 2;
+ if (this.options.useChildren) {
+ this.elements = this.domObj.getChildren();
+ nSplits = this.elements.length;
+ } else {
+ nSplits = this.options.elements ?
+ this.options.elements.length :
+ this.options.splitInto;
+ for (var i=0; i<nSplits; i++) {
+ var el;
+ if (this.options.elements && this.options.elements[i]) {
+ el = $(this.options.elements[i]);
+ if (!el) {
+ el = this.prepareElement();
+ el.id = this.options.elements[i];
+ }
+ } else {
+ el = this.prepareElement();
+ }
+ this.elements[i] = el;
+ this.domObj.adopt(this.elements[i]);
+ }
+ }
+ this.elements.each(function(el) { el.addClass('jxSplitArea'); });
+ for (var i=0; i<nSplits; i++) {
+ if (!this.elements[i].retrieve('jxLayout')) {
+ new Jx.Layout(this.elements[i], this.options.containerOptions[i]);
+ }
+ }
+
+ for (var i=1; i<nSplits; i++) {
+ this.bars[i-1] = this.prepareBar();
+ this.bars[i-1].store('leftSide',this.elements[i-1]);
+ this.bars[i-1].store('rightSide', this.elements[i]);
+ this.elements[i-1].store('rightBar', this.bars[i-1]);
+ this.elements[i].store('leftBar', this.bars[i-1]);
+ this.domObj.adopt(this.bars[i-1]);
+ }
+
+ this.establishConstraints();
+
+ for (var i=0; i<this.options.barOptions.length; i++) {
+ if (!this.bars[i]) {
+ continue;
+ }
+ var opt = this.options.barOptions[i];
+ if (opt && opt.snap && (opt.snap == 'before' || opt.snap == 'after')) {
+ var element;
+ if (opt.snap == 'before') {
+ element = this.bars[i].retrieve('leftSide');
+ } else if (opt.snap == 'after') {
+ element = this.bars[i].retrieve('rightSide');
+ }
+ var snap = new Element('a',{
+ 'class':'jxSnap'+this.options.layout.capitalize()+opt.snap.capitalize(),
+ 'href':'javascript:void(0)'
+ });
+ this.bars[i].adopt(snap);
+ new Jx.Splitter.Snap(snap, element, this);
+ }
+ }
+
+ for (var i=0; i<this.options.snaps.length; i++) {
+ if (this.options.snaps[i]) {
+ new Jx.Splitter.Snap(this.options.snaps[i], this.elements[i], this);
+ }
+ }
+
+
+ },
+ /**
+ * Method: prepareElement
+ * Prepare a new, empty element to go into a split area.
+ *
+ * Returns:
+ * {HTMLElement} an HTMLElement that goes into a split area.
+ */
+ prepareElement: function(){
+ var o = new Element('div', {styles:{position:'absolute'}});
+ return o;
+ },
+
+ /**
+ * Method: prepareBar
+ * Prepare a new, empty bar to go into between split areas.
+ *
+ * Returns:
+ * {HTMLElement} an HTMLElement that becomes a bar.
+ */
+ prepareBar: function() {
+ var o = new Element('div', {
+ 'class': 'jxSplitBar'+this.options.layout.capitalize(),
+ 'title': 'drag this bar to resize'
+ });
+ o.store('splitterObj', this);
+ return o;
+ },
+
+ /**
+ * Method: establishConstraints
+ * Setup the initial set of constraints that set the behaviour of the
+ * bars between the elements in the split area.
+ */
+ establishConstraints: function() {
+ var limit = {};
+ var fn;
+ if (this.options.layout == 'horizontal') {
+ limit.y = [0,0];
+ fn = this.dragHorizontal;
+ } else {
+ limit.x = [0,0];
+ fn = this.dragVertical;
+ }
+ this.bars.each(function(bar){
+ new Drag(bar, {
+ limit: limit,
+ onSnap : function(obj) {
+ obj.addClass('jxSplitBarDrag');
+ },
+ onComplete : (function(obj) {
+ obj.removeClass('jxSplitBarDrag');
+ if (obj.retrieve('splitterObj') != this) {
+ return;
+ }
+ fn.apply(this,[obj]);
+ }).bind(this)
+ });
+ }, this);
+ },
+
+ /**
+ * Method: dragHorizontal
+ * In a horizontally split container, handle a bar being dragged left or
+ * right by resizing the elements on either side of the bar.
+ *
+ * Parameters:
+ * obj - {HTMLElement} the bar that was dragged
+ */
+ dragHorizontal: function(obj) {
+ var leftEdge = parseInt(obj.style.left);
+ var leftSide = obj.retrieve('leftSide');
+ var rightSide = obj.retrieve('rightSide');
+ var leftJxl = leftSide.retrieve('jxLayout');
+ var rightJxl = rightSide.retrieve('jxLayout');
+
+ var paddingLeft = this.domObj.getPaddingSize().left;
+
+ /* process right side first */
+ var rsLeft, rsWidth, rsRight;
+
+ var size = obj.retrieve('size');
+ if (!size) {
+ size = obj.getBorderBoxSize();
+ obj.store('size',size);
+ }
+ rsLeft = leftEdge + size.width - paddingLeft;
+
+ var parentSize = this.domObj.getContentBoxSize();
+
+ if (rightJxl.options.width != null) {
+ rsWidth = rightJxl.options.width + rightJxl.options.left - rsLeft;
+ rsRight = parentSize.width - rsLeft - rsWidth;
+ } else {
+ rsWidth = parentSize.width - rightJxl.options.right - rsLeft;
+ rsRight = rightJxl.options.right;
+ }
+
+ /* enforce constraints on right side */
+ if (rsWidth < 0) {
+ rsWidth = 0;
+ }
+
+ if (rsWidth < rightJxl.options.minWidth) {
+ rsWidth = rightJxl.options.minWidth;
+ }
+ if (rightJxl.options.maxWidth >= 0 && rsWidth > rightJxl.options.maxWidth) {
+ rsWidth = rightJxl.options.maxWidth;
+ }
+
+ rsLeft = parentSize.width - rsRight - rsWidth;
+ leftEdge = rsLeft - size.width;
+
+ /* process left side */
+ var lsLeft, lsWidth;
+ lsLeft = leftJxl.options.left;
+ lsWidth = leftEdge - lsLeft;
+
+ /* enforce constraints on left */
+ if (lsWidth < 0) {
+ lsWidth = 0;
+ }
+ if (lsWidth < leftJxl.options.minWidth) {
+ lsWidth = leftJxl.options.minWidth;
+ }
+ if (leftJxl.options.maxWidth >= 0 &&
+ lsWidth > leftJxl.options.maxWidth) {
+ lsWidth = leftJxl.options.maxWidth;
+ }
+
+ /* update the leftEdge to accomodate constraints */
+ if (lsLeft + lsWidth != leftEdge) {
+ /* need to update right side, ignoring constraints because left side
+ constraints take precedence (arbitrary decision)
+ */
+ leftEdge = lsLeft + lsWidth;
+ var delta = leftEdge + size.width - rsLeft;
+ rsLeft += delta;
+ rsWidth -= delta;
+ }
+
+ /* put bar in its final location based on constraints */
+ obj.style.left = paddingLeft + leftEdge + 'px';
+
+ /* update leftSide positions */
+ if (leftJxl.options.width == null) {
+ var parentSize = this.domObj.getContentBoxSize();
+ leftSide.resize({right: parentSize.width - lsLeft-lsWidth});
+ } else {
+ leftSide.resize({width: lsWidth});
+ }
+
+ /* update rightSide position */
+ if (rightJxl.options.width == null) {
+ rightSide.resize({left:rsLeft});
+ } else {
+ rightSide.resize({left: rsLeft, width: rsWidth});
+ }
+ },
+
+ /**
+ * Method: dragVertical
+ * In a vertically split container, handle a bar being dragged up or
+ * down by resizing the elements on either side of the bar.
+ *
+ * Parameters:
+ * obj - {HTMLElement} the bar that was dragged
+ */
+ dragVertical: function(obj) {
+ /* top edge of the bar */
+ var topEdge = parseInt(obj.style.top);
+
+ /* the containers on either side of the bar */
+ var topSide = obj.retrieve('leftSide');
+ var bottomSide = obj.retrieve('rightSide');
+ var topJxl = topSide.retrieve('jxLayout');
+ var bottomJxl = bottomSide.retrieve('jxLayout');
+
+ var paddingTop = this.domObj.getPaddingSize().top;
+
+ /* measure the bar and parent container for later use */
+ var size = obj.retrieve('size');
+ if (!size) {
+ size = obj.getBorderBoxSize();
+ obj.store('size', size);
+ }
+ var parentSize = this.domObj.getContentBoxSize();
+
+ /* process top side first */
+ var bsTop, bsHeight, bsBottom;
+
+ /* top edge of bottom side is the top edge of bar plus the height of the bar */
+ bsTop = topEdge + size.height - paddingTop;
+
+ if (bottomJxl.options.height != null) {
+ /* bottom side height is fixed */
+ bsHeight = bottomJxl.options.height + bottomJxl.options.top - bsTop;
+ bsBottom = parentSize.height - bsTop - bsHeight;
+ } else {
+ /* bottom side height is not fixed. */
+ bsHeight = parentSize.height - bottomJxl.options.bottom - bsTop;
+ bsBottom = bottomJxl.options.bottom;
+ }
+
+ /* enforce constraints on bottom side */
+ if (bsHeight < 0) {
+ bsHeight = 0;
+ }
+
+ if (bsHeight < bottomJxl.options.minHeight) {
+ bsHeight = bottomJxl.options.minHeight;
+ }
+
+ if (bottomJxl.options.maxHeight >= 0 && bsHeight > bottomJxl.options.maxHeight) {
+ bsHeight = bottomJxl.options.maxHeight;
+ }
+
+ /* recalculate the top of the bottom side in case it changed
+ due to a constraint. The bar may have moved also.
+ */
+ bsTop = parentSize.height - bsBottom - bsHeight;
+ topEdge = bsTop - size.height;
+
+ /* process left side */
+ var tsTop, tsHeight;
+ tsTop = topJxl.options.top;
+ tsHeight = topEdge - tsTop;
+
+ /* enforce constraints on left */
+ if (tsHeight < 0) {
+ tsHeight = 0;
+ }
+ if (tsHeight < topJxl.options.minHeight) {
+ tsHeight = topJxl.options.minHeight;
+ }
+ if (topJxl.options.maxHeight >= 0 &&
+ tsHeight > topJxl.options.maxHeight) {
+ tsHeight = topJxl.options.maxHeight;
+ }
+
+ /* update the topEdge to accomodate constraints */
+ if (tsTop + tsHeight != topEdge) {
+ /* need to update right side, ignoring constraints because left side
+ constraints take precedence (arbitrary decision)
+ */
+ topEdge = tsTop + tsHeight;
+ var delta = topEdge + size.height - bsTop;
+ bsTop += delta;
+ bsHeight -= delta;
+ }
+
+ /* put bar in its final location based on constraints */
+ obj.style.top = paddingTop + topEdge + 'px';
+
+ /* update topSide positions */
+ if (topJxl.options.height == null) {
+ topSide.resize({bottom: parentSize.height - tsTop-tsHeight});
+ } else {
+ topSide.resize({height: tsHeight});
+ }
+
+ /* update bottomSide position */
+ if (bottomJxl.options.height == null) {
+ bottomSide.resize({top:bsTop});
+ } else {
+ bottomSide.resize({top: bsTop, height: bsHeight});
+ }
+ },
+
+ /**
+ * Method: sizeChanged
+ * handle the size of the container being changed.
+ */
+ sizeChanged: function() {
+ if (this.options.layout == 'horizontal') {
+ this.horizontalResize();
+ } else {
+ this.verticalResize();
+ }
+ },
+
+ /**
+ * Method: horizontalResize
+ * Resize a horizontally layed-out container
+ */
+ horizontalResize: function() {
+ var availableSpace = this.domObj.getContentBoxSize().width;
+ var overallWidth = availableSpace;
+
+ for (var i=0; i<this.bars.length; i++) {
+ var bar = this.bars[i];
+ var size = bar.retrieve('size');
+ if (!size || size.width == 0) {
+ size = bar.getBorderBoxSize();
+ bar.store('size',size);
+ }
+ availableSpace -= size.width;
+ }
+
+ var nVariable = 0;
+ var jxo;
+ for (var i=0; i<this.elements.length; i++) {
+ var e = this.elements[i];
+ jxo = e.retrieve('jxLayout').options;
+ if (jxo.width != null) {
+ availableSpace -= parseInt(jxo.width);
+ } else {
+ var w = 0;
+ if (jxo.right != 0 ||
+ jxo.left != 0) {
+ w = e.getBorderBoxSize().width;
+ }
+
+ availableSpace -= w;
+ nVariable++;
+ }
+ }
+
+ if (nVariable == 0) { /* all fixed */
+ /* stick all available space in the last one */
+ availableSpace += jxo.width;
+ jxo.width = null;
+ nVariable = 1;
+ }
+
+ var amount = parseInt(availableSpace / nVariable);
+ /* account for rounding errors */
+ var remainder = availableSpace % nVariable;
+
+ var leftPadding = this.domObj.getPaddingSize().left;
+
+ var currentPosition = 0;
+
+ for (var i=0; i<this.elements.length; i++) {
+ var e = this.elements[i];
+ var jxl = e.retrieve('jxLayout');
+ var jxo = jxl.options;
+ if (jxo.width != null) {
+ jxl.resize({left: currentPosition});
+ currentPosition += jxo.width;
+ } else {
+ var a = amount;
+ if (nVariable == 1) {
+ a += remainder;
+ }
+ nVariable--;
+
+ var w = 0;
+ if (jxo.right != 0 || jxo.left != 0) {
+ w = e.getBorderBoxSize().width + a;
+ } else {
+ w = a;
+ }
+
+ if (w < 0) {
+ if (nVariable > 0) {
+ amount = amount + w/nVariable;
+ }
+ w = 0;
+ }
+ if (w < jxo.minWidth) {
+ if (nVariable > 0) {
+ amount = amount + (w - jxo.minWidth)/nVariable;
+ }
+ w = jxo.minWidth;
+ }
+ if (jxo.maxWidth >= 0 && w > jxo.maxWidth) {
+ if (nVariable > 0) {
+ amount = amount + (w - jxo.maxWidth)/nVariable;
+ }
+ w = e.options.maxWidth;
+ }
+
+ var r = overallWidth - currentPosition - w;
+ jxl.resize({left: currentPosition, right: r});
+ currentPosition += w;
+ }
+ var rightBar = e.retrieve('rightBar');
+ if (rightBar) {
+ rightBar.setStyle('left', leftPadding + currentPosition);
+ currentPosition += rightBar.retrieve('size').width;
+ }
+ }
+ },
+
+ /**
+ * Method: verticalResize
+ * Resize a vertically layed out container.
+ */
+ verticalResize: function() {
+ var availableSpace = this.domObj.getContentBoxSize().height;
+ var overallHeight = availableSpace;
+
+ for (var i=0; i<this.bars.length; i++) {
+ var bar = this.bars[i];
+ var size = bar.retrieve('size');
+ if (!size || size.height == 0) {
+ size = bar.getBorderBoxSize();
+ bar.store('size', size);
+ }
+ availableSpace -= size.height;
+ }
+
+ var nVariable = 0;
+
+ var jxo;
+ for (var i=0; i<this.elements.length; i++) {
+ var e = this.elements[i];
+ jxo = e.retrieve('jxLayout').options;
+ if (jxo.height != null) {
+ availableSpace -= parseInt(jxo.height);
+ } else {
+ var h = 0;
+ if (jxo.bottom != 0 || jxo.top != 0) {
+ h = e.getBorderBoxSize().height;
+ }
+
+ availableSpace -= h;
+ nVariable++;
+ }
+ }
+
+ if (nVariable == 0) { /* all fixed */
+ /* stick all available space in the last one */
+ availableSpace += jxo.height;
+ jxo.height = null;
+ nVariable = 1;
+ }
+
+ var amount = parseInt(availableSpace / nVariable);
+ /* account for rounding errors */
+ var remainder = availableSpace % nVariable;
+
+ var paddingTop = this.domObj.getPaddingSize().top;
+
+ var currentPosition = 0;
+
+ for (var i=0; i<this.elements.length; i++) {
+ var e = this.elements[i];
+ var jxl = e.retrieve('jxLayout');
+ var jxo = jxl.options;
+ if (jxo.height != null) {
+ jxl.resize({top: currentPosition});
+ currentPosition += jxo.height;
+ } else {
+ var a = amount;
+ if (nVariable == 1) {
+ a += remainder;
+ }
+ nVariable--;
+
+ var h = 0;
+ if (jxo.bottom != 0 ||
+ jxo.top != 0) {
+ h = e.getBorderBoxSize().height + a;
+ } else {
+ h = a;
+ }
+
+ if (h < 0) {
+ if (nVariable > 0) {
+ amount = amount + h/nVariable;
+ }
+ h = 0;
+ }
+ if (h < jxo.minHeight) {
+ if (nVariable > 0) {
+ amount = amount + (h - jxo.minHeight)/nVariable;
+ }
+ h = jxo.minHeight;
+ }
+ if (jxo.maxHeight >= 0 && h > jxo.maxHeight) {
+ if (nVariable > 0) {
+ amount = amount + (h - jxo.maxHeight)/nVariable;
+ }
+ h = jxo.maxHeight;
+ }
+
+ var r = overallHeight - currentPosition - h;
+ jxl.resize({top: currentPosition, bottom: r});
+ currentPosition += h;
+ }
+ var rightBar = e.retrieve('rightBar');
+ if (rightBar) {
+ rightBar.style.top = paddingTop + currentPosition + 'px';
+ currentPosition += rightBar.retrieve('size').height;
+ }
+ }
+ }
+});// $Id: splitter.snap.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Splitter.Snap
+ * A helper class to create an element that can snap a split panel open or
+ * closed.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Splitter.Snap = new Class({
+ /**
+ * Property: snap
+ * {HTMLElement} the DOM element of the snap (the thing that gets
+ * clicked).
+ */
+ snap: null,
+ /**
+ * Property: element
+ * {HTMLElement} An element of the <Jx.Splitter> that gets controlled
+ * by this snap
+ */
+ element: null,
+ /**
+ * Property: splitter
+ * {<Jx.Splitter>} the splitter that this snap is associated with.
+ */
+ splitter: null,
+ /**
+ * Property: layout
+ * {String} track the layout of the splitter for convenience.
+ */
+ layout: 'vertical',
+ /**
+ * Constructor: Jx.Splitter.Snap
+ * Create a new Jx.Splitter.Snap
+ *
+ * Parameters:
+ * snap - {HTMLElement} the clickable thing that snaps the element
+ * open and closed
+ * element - {HTMLElement} the element that gets controlled by the snap
+ * splitter - {<Jx.Splitter>} the splitter that this all happens inside of.
+ */
+ initialize: function(snap, element, splitter) {
+ this.snap = snap;
+ this.element = element;
+ var jxl = element.retrieve('jxLayout');
+ jxl.addEvent('sizeChange', this.sizeChange.bind(this));
+ this.splitter = splitter;
+ this.layout = splitter.options.layout;
+ var jxo = jxl.options;
+ var size = this.element.getContentBoxSize();
+ if (this.layout == 'vertical') {
+ this.originalSize = size.height;
+ this.minimumSize = jxo.minHeight ? jxo.minHeight : 0;
+ } else {
+ this.originalSize = size.width;
+ this.minimumSize = jxo.minWidth ? jxo.minWidth : 0;
+ }
+ snap.addEvent('click', this.toggleElement.bind(this));
+ },
+
+ /**
+ * Method: toggleElement
+ * Snap the element open or closed.
+ */
+ toggleElement: function() {
+ var size = this.element.getContentBoxSize();
+ var newSize = {};
+ if (this.layout == 'vertical') {
+ if (size.height == this.minimumSize) {
+ newSize.height = this.originalSize;
+ } else {
+ this.originalSize = size.height;
+ newSize.height = this.minimumSize;
+ }
+ } else {
+ if (size.width == this.minimumSize) {
+ newSize.width = this.originalSize;
+ } else {
+ this.originalSize = size.width;
+ newSize.width = this.minimumSize;
+ }
+ }
+ this.element.resize(newSize);
+ this.splitter.sizeChanged();
+ },
+
+ /**
+ * Method: sizeChanged
+ * Handle the size of the element changing to see if the
+ * toggle state has changed.
+ */
+ sizeChange: function() {
+ var size = this.element.getBorderBoxSize();
+ if (this.layout == 'vertical') {
+ if (size.height == this.minimumSize) {
+ this.snap.addClass('jxSnapClosed');
+ this.snap.removeClass('jxSnapOpened');
+ } else {
+ this.snap.addClass('jxSnapOpened');
+ this.snap.removeClass('jxSnapClosed');
+ }
+ } else {
+ if (size.width == this.minimumSize) {
+ this.snap.addClass('jxSnapClosed');
+ this.snap.removeClass('jxSnapOpened');
+ } else {
+ this.snap.addClass('jxSnapOpened');
+ this.snap.removeClass('jxSnapClosed');
+ }
+ }
+ }
+});// $Id: tabset.js 758 2008-08-19 02:35:50Z pspencer $
+/**
+ * Class: Jx.TabSet
+ * A TabSet manages a set of <Jx.Button.Tab> content areas by ensuring that only one
+ * of the content areas is visible (i.e. the active tab). TabSet does not
+ * manage the actual tabs. The instances of <Jx.Button.Tab> that are to be managed
+ * as a set have to be added to both a TabSet and a <Jx.Toolbar>. The content
+ * areas of the <Jx.Button.Tab>s are sized to fit the content area that the TabSet
+ * is managing.
+ *
+ * Example:
+ * (code)
+ * var tabBar = new Jx.Toolbar('tabBar');
+ * var tabSet = new Jx.TabSet('tabArea');
+ *
+ * var tab1 = new Jx.Button.Tab('tab 1', {contentID: 'content1'});
+ * var tab2 = new Jx.Button.Tab('tab 2', {contentID: 'content2'});
+ * var tab3 = new Jx.Button.Tab('tab 3', {contentID: 'content3'});
+ * var tab4 = new Jx.Button.Tab('tab 4', {contentURL: 'test_content.html'});
+ *
+ * tabSet.add(t1, t2, t3, t4);
+ * tabBar.add(t1, t2, t3, t4);
+ * (end)
+ *
+ * Events:
+ * tabChange - the current tab has changed
+ *
+ * Implements:
+ * Events - MooTools Class.Extras
+ * Options - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.TabSet = new Class({
+ Implements: [Options,Events],
+ /**
+ * Property: tabs
+ * {Array} array of tabs that are managed by this tab set
+ */
+ tabs: null,
+ /**
+ * Property: domObj
+ * {HTMLElement} The HTML element that represents this tab set in the DOM.
+ * The content areas of each tab are sized to fill the domObj.
+ */
+ domObj : null,
+ /**
+ * Constructor: Jx.TabSet
+ * Create a new instance of <Jx.TabSet> within a specific element of
+ * the DOM.
+ *
+ * Parameters:
+ * domObj - {HTMLElement} an element or id of an element to put the
+ * content of the tabs into.
+ * options - an options object, only event handlers are supported
+ * as options at this time.
+ */
+ initialize : function(domObj, options) {
+ this.setOptions(options);
+ this.tabs = [];
+ this.domObj = $(domObj);
+ if (!this.domObj.hasClass('jxTabSetContainer')) {
+ this.domObj.addClass('jxTabSetContainer');
+ }
+ this.selectionChangedFn = this.selectionChanged.bind(this);
+ },
+ /**
+ * Method: resizeTabBox
+ * Resize the tab set content area and propogate the changes to
+ * each of the tabs managed by the tab set.
+ */
+ resizeTabBox: function() {
+
+ var parentSize = Element.getContentBoxSize(this.domObj.parentNode);
+ Element.setBorderBoxSize(this.domObj, {width: parentSize.width, height: parentSize.height});
+ // this is a bullshit hack for IE. We need to set the tab content height
+ // for IE when the tabs are in a snap panel, otherwise the tab content
+ // doesn't collapse with the panel and no scrollbars appear. This only
+ // affects the height. In fact, setting the width breaks tab placement
+
+ for (var i=0; i<this.domObj.childNodes.length; i++) {
+ // don't try to set the height on a text node
+ if (this.domObj.childNodes[i].nodeType == 3) {
+ continue;
+ }
+ Element.setBorderBoxSize(this.domObj.childNodes[i], {height: parentSize.height});
+ if (this.domObj.childNodes[i].resize) {
+ this.domObj.childNodes[i].resize();
+ }
+ }
+ },
+
+ /**
+ * Method: add
+ * Add one or more <Jx.Button.Tab>s to the TabSet.
+ *
+ * Parameters:
+ * tab - {<Jx.Tab>} an instance of <Jx.Tab> to add to the tab set. More
+ * than one tab can be added by passing extra parameters to this method.
+ */
+ add : function() {
+ $A(arguments).each(function(tab) {
+ if (tab instanceof Jx.Button.Tab) {
+ tab.addEvent('down',this.selectionChangedFn);
+ this.domObj.appendChild(tab.content);
+ if (!this.activeTab) {
+ tab.setActive(true);
+ }
+ this.tabs.push(tab);
+ }
+ }, this);
+ },
+ /**
+ * Method: remove
+ * Remove a tab from this TabSet. Note that it is the caller's responsibility
+ * to remove the tab from the <Jx.Toolbar>.
+ *
+ * Parameters:
+ * tab - {<Jx.Tab>} the tab to remove.
+ */
+ remove : function(tab) {
+ if (tab instanceof Jx.Button.Tab && this.tabs.indexOf(tab) != -1) {
+ this.tabs.erase(tab);
+ if (this.activeTab == tab) {
+ if (this.tabs.length) {
+ this.tabs[0].setActive(true);
+ }
+ }
+ tab.removeEvent('down',this.selectionChangedFn);
+ tab.content.dispose();
+ }
+ },
+ /**
+ * Method: setActiveTab
+ * Set the active tab to the one passed to this method
+ *
+ * Parameters:
+ * tab - {<Jx.Button.Tab>} the tab to make active.
+ */
+ setActiveTab: function(tab) {
+ if (this.activeTab && this.activeTab != tab) {
+ this.activeTab.setActive(false);
+ }
+ this.activeTab = tab;
+ if (this.activeTab.content.resize) {
+ this.activeTab.content.resize();
+ }
+ },
+ /**
+ * Method: selectionChanged
+ * Handle selection changing on the tabs themselves and activate the
+ * appropriate tab in response.
+ *
+ * Parameters:
+ * tab - {<Jx.Button.Tab>} the tab to make active.
+ */
+ selectionChanged: function(tab) {
+ this.setActiveTab(tab);
+ this.fireEvent('tabChange', this, tab);
+ }
+});
+
+
+
+// $Id: tabset.js 758 2008-08-19 02:35:50Z pspencer $
+/**
+ * Class: Jx.TabSet
+ * A TabSet manages a set of <Jx.Button.Tab> content areas by ensuring that only one
+ * of the content areas is visible (i.e. the active tab). TabSet does not
+ * manage the actual tabs. The instances of <Jx.Button.Tab> that are to be managed
+ * as a set have to be added to both a TabSet and a <Jx.Toolbar>. The content
+ * areas of the <Jx.Button.Tab>s are sized to fit the content area that the TabSet
+ * is managing.
+ *
+ * Example:
+ * (code)
+ * var tabBar = new Jx.Toolbar('tabBar');
+ * var tabSet = new Jx.TabSet('tabArea');
+ *
+ * var tab1 = new Jx.Button.Tab('tab 1', {contentID: 'content1'});
+ * var tab2 = new Jx.Button.Tab('tab 2', {contentID: 'content2'});
+ * var tab3 = new Jx.Button.Tab('tab 3', {contentID: 'content3'});
+ * var tab4 = new Jx.Button.Tab('tab 4', {contentURL: 'test_content.html'});
+ *
+ * tabSet.add(t1, t2, t3, t4);
+ * tabBar.add(t1, t2, t3, t4);
+ * (end)
+ *
+ * Events:
+ * tabChange - the current tab has changed
+ *
+ * Implements:
+ * Events - MooTools Class.Extras
+ * Options - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.TabSet = new Class({
+ Implements: [Options,Events],
+ /**
+ * Property: tabs
+ * {Array} array of tabs that are managed by this tab set
+ */
+ tabs: null,
+ /**
+ * Property: domObj
+ * {HTMLElement} The HTML element that represents this tab set in the DOM.
+ * The content areas of each tab are sized to fill the domObj.
+ */
+ domObj : null,
+ /**
+ * Constructor: Jx.TabSet
+ * Create a new instance of <Jx.TabSet> within a specific element of
+ * the DOM.
+ *
+ * Parameters:
+ * domObj - {HTMLElement} an element or id of an element to put the
+ * content of the tabs into.
+ * options - an options object, only event handlers are supported
+ * as options at this time.
+ */
+ initialize : function(domObj, options) {
+ this.setOptions(options);
+ this.tabs = [];
+ this.domObj = $(domObj);
+ if (!this.domObj.hasClass('jxTabSetContainer')) {
+ this.domObj.addClass('jxTabSetContainer');
+ }
+ this.selectionChangedFn = this.selectionChanged.bind(this);
+ },
+ /**
+ * Method: resizeTabBox
+ * Resize the tab set content area and propogate the changes to
+ * each of the tabs managed by the tab set.
+ */
+ resizeTabBox: function() {
+
+ var parentSize = Element.getContentBoxSize(this.domObj.parentNode);
+ Element.setBorderBoxSize(this.domObj, {width: parentSize.width, height: parentSize.height});
+ // this is a bullshit hack for IE. We need to set the tab content height
+ // for IE when the tabs are in a snap panel, otherwise the tab content
+ // doesn't collapse with the panel and no scrollbars appear. This only
+ // affects the height. In fact, setting the width breaks tab placement
+
+ for (var i=0; i<this.domObj.childNodes.length; i++) {
+ // don't try to set the height on a text node
+ if (this.domObj.childNodes[i].nodeType == 3) {
+ continue;
+ }
+ Element.setBorderBoxSize(this.domObj.childNodes[i], {height: parentSize.height});
+ if (this.domObj.childNodes[i].resize) {
+ this.domObj.childNodes[i].resize();
+ }
+ }
+ },
+
+ /**
+ * Method: add
+ * Add one or more <Jx.Button.Tab>s to the TabSet.
+ *
+ * Parameters:
+ * tab - {<Jx.Tab>} an instance of <Jx.Tab> to add to the tab set. More
+ * than one tab can be added by passing extra parameters to this method.
+ */
+ add : function() {
+ $A(arguments).each(function(tab) {
+ if (tab instanceof Jx.Button.Tab) {
+ tab.addEvent('down',this.selectionChangedFn);
+ this.domObj.appendChild(tab.content);
+ if (!this.activeTab) {
+ tab.setActive(true);
+ }
+ this.tabs.push(tab);
+ }
+ }, this);
+ },
+ /**
+ * Method: remove
+ * Remove a tab from this TabSet. Note that it is the caller's responsibility
+ * to remove the tab from the <Jx.Toolbar>.
+ *
+ * Parameters:
+ * tab - {<Jx.Tab>} the tab to remove.
+ */
+ remove : function(tab) {
+ if (tab instanceof Jx.Button.Tab && this.tabs.indexOf(tab) != -1) {
+ this.tabs.erase(tab);
+ if (this.activeTab == tab) {
+ if (this.tabs.length) {
+ this.tabs[0].setActive(true);
+ }
+ }
+ tab.removeEvent('down',this.selectionChangedFn);
+ tab.content.dispose();
+ }
+ },
+ /**
+ * Method: setActiveTab
+ * Set the active tab to the one passed to this method
+ *
+ * Parameters:
+ * tab - {<Jx.Button.Tab>} the tab to make active.
+ */
+ setActiveTab: function(tab) {
+ if (this.activeTab && this.activeTab != tab) {
+ this.activeTab.setActive(false);
+ }
+ this.activeTab = tab;
+ if (this.activeTab.content.resize) {
+ this.activeTab.content.resize();
+ }
+ },
+ /**
+ * Method: selectionChanged
+ * Handle selection changing on the tabs themselves and activate the
+ * appropriate tab in response.
+ *
+ * Parameters:
+ * tab - {<Jx.Button.Tab>} the tab to make active.
+ */
+ selectionChanged: function(tab) {
+ this.setActiveTab(tab);
+ this.fireEvent('tabChange', this, tab);
+ }
+});
+
+
+
+// $Id: button.tab.js 758 2008-08-19 02:35:50Z pspencer $
+/**
+ * Class: Jx.Button.Tab
+ * A single tab in a tab set. A tab has a label (displayed in the tab) and a
+ * content area that is displayed when the tab is active. A tab has to be
+ * added to both a <Jx.TabSet> (for the content) and <Jx.Toolbar> (for the
+ * actual tab itself) in order to be useful. Alternately, you can use
+ * a <Jx.TabBox> which combines both into a single control at the cost of
+ * some flexibility in layout options.
+ *
+ * A tab is a <Jx.ContentLoader> and you can specify the initial content of
+ * the tab using any of the methods supported by
+ * <Jx.ContentLoader::loadContent>. You can acccess the actual DOM element
+ * that contains the content (if you want to dynamically insert content
+ * for instance) via the <Jx.Tab::content> property.
+ *
+ * A tab is a button of type *toggle* which means that it emits the *up*
+ * and *down* events.
+ *
+ * Example:
+ * (code)
+ * var tab1 = new Jx.Button.Tab({
+ * label: 'tab 1',
+ * content: 'content1',
+ * onDown: function(tab) {
+ * console.log('tab became active');
+ * },
+ * onUp: function(tab) {
+ * console.log('tab became inactive');
+ * }
+ * });
+ * (end)
+ *
+ * Extends:
+ * <Jx.Button>
+ *
+ * Implements:
+ * Options - MooTools Class.Extras
+ * Events - MooTools Class.Extras
+ * <Jx.ContentLoader> - for loading content into a tab
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Button.Tab = new Class({
+ Extends: Jx.Button,
+ Implements: [Options, Events, Jx.ContentLoader],
+ /**
+ * Property: content
+ * {HTMLElement} The content area that is displayed when the tab is active.
+ */
+ content: null,
+ /**
+ * Constructor: Jx.Button.Tab
+ * Create a new instance of Jx.Button.Tab.
+ *
+ * Parameters:
+ * options - {Object} an object containing options that are used
+ * to control the appearance of the tab. See <Jx.Button>,
+ * <Jx.ContentLoader::loadContent> and <Jx.Layout::Jx.Layout> for
+ * valid options.
+ */
+ initialize : function( options) {
+ options = $merge(options, {type:'Tab', toggle:true});
+ this.parent(options);
+ this.content = new Element('div', {'class':'tabContent'});
+ this.loadContent(this.content);
+ new Jx.Layout(this.content, options);
+ var that = this;
+ this.addEvent('down', function(){that.content.addClass('tabContentActive');});
+ this.addEvent('up', function(){that.content.removeClass('tabContentActive');});
+ },
+ /**
+ * Method: clicked
+ * triggered when the user clicks the button, processes the
+ * actionPerformed event
+ */
+ clicked : function(evt) {
+ this.setActive(true);
+ }
+});// $Id: toolbar.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Toolbar
+ * A toolbar is a container object that contains other objects such as
+ * buttons. The toolbar organizes the objects it contains automatically,
+ * wrapping them as necessary. Multiple toolbars may be placed within
+ * the same containing object.
+ *
+ * Jx.Toolbar includes CSS classes for styling the appearance of a
+ * toolbar to be similar to traditional desktop application toolbars.
+ *
+ * There is one special object, Jx.ToolbarSeparator, that provides
+ * a visual separation between objects in a toolbar.
+ *
+ * While a toolbar is generally a *dumb* container, it serves a special purpose
+ * for menus by providing some infrastructure so that menus can behave
+ * properly.
+ *
+ * In general, almost anything can be placed in a Toolbar, and mixed with
+ * anything else.
+ *
+ * Example:
+ * The following example shows how to create a Jx.Toolbar instance and place two objects in it.
+ * (code)
+ * //myToolbarContainer is the id of a <div> in the HTML page.
+ * function myFunction() {}
+ * var myToolbar = new Jx.Toolbar('myToolbarContainer');
+ *
+ * var myButton = new Jx.Button(buttonOptions);
+ *
+ * var myElement = document.createElement('select');
+ *
+ * myToolbar.add(myButton, new Jx.ToolbarSeparator(), myElement);
+ * (end)
+ *
+ * Events:
+ * add - fired when one or more buttons are added to a toolbar
+ * remove - fired when on eor more buttons are removed from a toolbar
+ *
+ * Implements:
+ * Options
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Toolbar = new Class({
+ Implements: [Options,Events],
+ /**
+ * Property: items
+ * {Array} an array of the things in the toolbar.
+ */
+ items : null,
+ /**
+ * Property: domObj
+ * {HTMLElement} the HTML element that the toolbar lives in
+ */
+ domObj : null,
+ /**
+ * Property: isActive
+ * When a toolbar contains <Jx.Menu> instances, they want to know
+ * if any menu in the toolbar is active and this is how they
+ * find out.
+ */
+ isActive : false,
+ options: {
+ position: 'top',
+ parent: null
+ },
+ /**
+ * Constructor: Jx.Toolbar
+ * Create a new instance of Jx.Toolbar.
+ *
+ * Parameters:
+ * options - an options object as documented below
+ *
+ * Options:
+ * parent - {HTMLElement} object reference or id to place the toolbar in.
+ * position - one of 'top', 'right', 'bottom', or 'left', indicates how
+ * the toolbar is being placed in the page and may influence the behaviour
+ * of items in the toolbar that open sub panels, they will tend to open
+ * them towards the center of the page. Default is top.
+ */
+ initialize : function(options) {
+ this.setOptions(options);
+
+ this.domObj = new Element('ul', {'class':'jxToolbar'});
+
+ if (this.options.parent) {
+ var owner = $(this.options.parent);
+ if (!owner.hasClass('jxToolbarContainer')) {
+ owner.addClass('jxToolbarContainer');
+ owner.appendChild(this.domObj);
+ var clearer = new Element('div', {'class':'jxClearer'});
+ owner.appendChild(clearer);
+ } else {
+ owner.insertBefore(this.domObj, owner.lastChild);
+ }
+ if (['top','right','bottom','left'].contains(this.options.position)) {
+ owner.addClass('jxBar'+this.options.position.capitalize());
+ } else {
+ owner.addClass('jxBarTop');
+ }
+ }
+ this.deactivateWatcher = this.deactivate.bindWithEvent(this);
+ },
+ /**
+ * Method: add
+ * Add an item to the toolbar. If the item being added is a Jx component
+ * with a domObj property, the domObj is added. If the item being added
+ * is an LI element, then it is given a CSS class of *jxToolItem*.
+ * Otherwise, the thing is wrapped in a <Jx.ToolbarItem>.
+ *
+ * Parameters:
+ * thing - {Object} the thing to add. More than one thing can be added
+ * by passing multiple arguments.
+ */
+ add: function( ) {
+ for (var i=0; i<arguments.length; i++) {
+ var thing = arguments[i];
+ thing.toolbar = this;
+ if (thing.domObj) {
+ thing = thing.domObj;
+ }
+ if (thing.tagName == 'LI') {
+ if (!thing.hasClass('jxToolItem')) {
+ thing.addClass('jxToolItem');
+ }
+ this.domObj.appendChild(thing);
+ } else {
+ var item = new Jx.Toolbar.Item(thing);
+ this.domObj.appendChild(item.domObj);
+ }
+ }
+ if (arguments.length > 0) {
+ this.fireEvent('add', this);
+ }
+ },
+ /**
+ * Method: remove
+ * remove an item from a toolbar. If the item is not in this toolbar
+ * nothing happens
+ *
+ * Parameters:
+ * item - {Object} the object to remove
+ *
+ * Returns:
+ * {Object} the item that was removed, or null if the item was not
+ * removed.
+ */
+ remove: function(item) {
+ if (item.domObj) {
+ item = item.domObj;
+ }
+ var li = item.findElement('LI');
+ if (li && li.parentNode == this.domObj) {
+ item.dispose();
+ this.fireEvent('remove', this);
+ } else {
+ return null;
+ }
+ },
+ /**
+ * Method: deactivate
+ * Deactivate the Toolbar (when it is acting as a menu bar).
+ */
+ deactivate: function() {
+ this.items.each(function(o){o.hide();});
+ this.setActive(false);
+ },
+ /**
+ * Method: isActive
+ * Indicate if the toolbar is currently active (as a menu bar)
+ *
+ * Returns:
+ * {Boolean}
+ */
+ isActive: function() {
+ return this.isActive;
+ },
+ /**
+ * Method: setActive
+ * Set the active state of the toolbar (for menus)
+ *
+ * Parameters:
+ * b - {Boolean} the new state
+ */
+ setActive: function(b) {
+ this.isActive = b;
+ if (this.isActive) {
+ document.addEvent('click', this.deactivateWatcher);
+ Event.observe(document, 'click', this.deactivateWatcher);
+ } else {
+ document.removeEvent('click', this.deactivateWatcher);
+ }
+ },
+ /**
+ * Method: setVisibleItem
+ * For menus, they want to know which menu is currently open.
+ *
+ * Parameters:
+ * obj - {<Jx.Menu>} the menu that just opened.
+ */
+ setVisibleItem: function(obj) {
+ if (this.visibleItem && this.visibleItem.hide && this.visibleItem != obj) {
+ this.visibleItem.hide();
+ }
+ this.visibleItem = obj;
+ if (this.isActive()) {
+ this.visibleItem.show();
+ }
+ }
+});
+// $Id: toolbar.item.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Toolbar.Item
+ * A helper class to provide a container for something to go into
+ * a <Jx.Toolbar>.
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Toolbar.Item = new Class( {
+ /**
+ * Property: domObj
+ * {HTMLElement} an element to contain the thing to be placed in the
+ * toolbar.
+ */
+ domObj: null,
+ /**
+ * Constructor: Jx.Toolbar.Item
+ * Create a new instance of Jx.Toolbar.Item.
+ *
+ * Parameters:
+ * jxThing - {Object} the thing to be contained.
+ */
+ initialize : function( jxThing ) {
+ this.al = [];
+ this.domObj = new Element('li', {'class':'jxToolItem'});
+ if (jxThing) {
+ if (jxThing.domObj) {
+ this.domObj.appendChild(jxThing.domObj);
+ if (jxThing instanceof Jx.Tab) {
+ this.domObj.addClass('jxTabItem');
+ }
+ } else {
+ this.domObj.appendChild(jxThing);
+ if (jxThing.hasClass('jxTab')) {
+ this.domObj.addClass('jxTabItem');
+ }
+ }
+ }
+ }
+});// $Id: toolbar.separator.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Toolbar.Separator
+ * A helper class that represents a visual separator in a <Jx.Toolbar>
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Toolbar.Separator = new Class({
+ /**
+ * Property: domObj
+ * {HTMLElement} The DOM element that goes in the <Jx.Toolbar>
+ */
+ domObj: null,
+ /**
+ * Constructor: Jx.Toolbar.Separator
+ * Create a new Jx.Toolbar.Separator
+ */
+ initialize: function() {
+ this.domObj = new Element('li', {'class':'jxToolItem'});
+ this.domSpan = new Element('span', {'class':'separator'});
+ this.domObj.appendChild(this.domSpan);
+ }
+});
+// $Id: treeitem.js 786 2008-08-27 15:03:41Z pspencer $
+/**
+ * Class: Jx.TreeItem
+ * An item in a tree. An item is a leaf node that has no children.
+ *
+ * Jx.TreeItem supports selection via the click event. The application
+ * is responsible for changing the style of the selected item in the tree
+ * and for tracking selection if that is important.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Events:
+ * click - triggered when the tree item is clicked
+ *
+ * Implements:
+ * Events - MooTools Class.Extras
+ * Options - MooTools Class.Extras
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.TreeItem = new Class ({
+ Implements: [Options,Events],
+ /**
+ * Property: domObj
+ * {HTMLElement} a reference to the HTML element that is the TreeItem
+ * in the DOM
+ */
+ domObj : null,
+ /**
+ * Property: owner
+ * {Object} the folder or tree that this item belongs to
+ */
+ owner: null,
+ options: {
+ label: '',
+ data: null,
+ contextMenu: null,
+ image: null,
+ enabled: true,
+ type: 'Item',
+ imageClass: ''
+ },
+ /**
+ * Constructor: Jx.TreeItem
+ * Create a new instance of Jx.TreeItem with the associated options
+ *
+ * Parameters:
+ * options - {Object} an object containing the below optional
+ * attributes that control how the TreeItem functions.
+ *
+ * Options:
+ * label - {String} the label to display for the TreeItem
+ * data - {Object} any arbitrary data to be associated with the TreeItem
+ * contextMenu - {<Jx.ContextMenu>} the context menu to trigger if there
+ * is a right click on the node
+ * image - {String} URL to an image to use as the icon next to the
+ * label of this TreeItem
+ * enabled - {Boolean} the initial state of the TreeItem. If the
+ * TreeItem is not enabled, it cannot be clicked.
+ */
+ initialize : function( options ) {
+ this.setOptions(options);
+
+ this.domObj = new Element('li', {'class':'jxTree'+this.options.type});
+ if (this.options.id) {
+ this.domObj.id = this.options.id;
+ }
+
+ this.domNode = new Element('img',{'class': 'jxTreeImage', src: Jx.aPixel.src});
+ this.domObj.appendChild(this.domNode);
+
+ this.domImg = new Element('img',{'class':'jxTreeIcon', src: Jx.aPixel.src});
+ if (this.options.image) {
+ this.domImg.setStyle('backgroundImage', 'url('+this.options.image+')');
+ }
+ if (this.options.imageClass) {
+ this.domImg.addClass(this.options.imageClass);
+ }
+ this.domA = new Element('a',{
+ href:'javascript:void(0)',
+ html: this.options.label,
+ events: {
+ click: this.selected.bindWithEvent(this),
+ dblclick: this.selected.bindWithEvent(this),
+ contextmenu: this.showMenu.bindWithEvent(this)
+ }
+ });
+ this.domA.store('jxTreeItem', this);
+ this.domA.appendChild(this.domImg);
+ this.domObj.appendChild(this.domA);
+ this.domObj.store('jxTreeItem', this);
+
+ if (!this.options.enabled) {
+ this.domObj.addClass('jxDisabled');
+ }
+ },
+ /**
+ * Method: finalize
+ * Clean up the TreeItem and remove all DOM references
+ */
+ finalize: function() { this.finalizeItem(); },
+ /**
+ * Method: finalizeItem
+ * Clean up the TreeItem and remove all DOM references
+ */
+ finalizeItem: function() {
+ if (!this.domObj) {
+ return;
+ }
+ this.domA.removeEvents();
+ this.options = null;
+ this.domObj = null;
+ this.owner = null;
+ },
+ /**
+ * Method: clone
+ * Create a clone of the TreeItem
+ *
+ * Returns:
+ * {<Jx.TreeItem>} a copy of the TreeItem
+ */
+ clone : function() {
+ return new Jx.TreeItem(this.options);
+ },
+ /**
+ * Method: update
+ * Update the CSS of the TreeItem's DOM element in case it has changed
+ * position
+ *
+ * Parameters:
+ * shouldDescend - {Boolean} propagate changes to child nodes?
+ */
+ update : function(shouldDescend) {
+ var isLast = (arguments.length > 1) ? arguments[1] :
+ (this.owner && this.owner.isLastNode(this));
+ if (isLast) {
+ this.domObj.removeClass('jxTree'+this.options.type);
+ this.domObj.addClass('jxTree'+this.options.type+'Last');
+ } else {
+ this.domObj.removeClass('jxTree'+this.options.type+'Last');
+ this.domObj.addClass('jxTree'+this.options.type);
+ }
+ },
+ /**
+ * Method: selected
+ * Called when the DOM element for the TreeItem is clicked, the
+ * node is selected.
+ *
+ * Parameters:
+ * e - {Event} the DOM event
+ */
+ selected : function(e) {
+ this.lastEvent = e;
+ this.fireEvent('click', this);
+ },
+ /**
+ * Method: showMenu
+ * Called when the DOM element for the TreeItem is right-clicked. The
+ * node is selected and the context menu displayed (if there is one).
+ *
+ * Parameters:
+ * e - {Event} the DOM event
+ */
+ showMenu: function(e) {
+ this.lastEvent = e;
+ this.fireEvent('click',this);
+ if (this.contextMenu) {
+ this.contextMenu.show(this.lastEvent);
+ }
+ e.stop();;
+ },
+ /**
+ * Method: getName
+ * Get the label associated with a TreeItem
+ *
+ * Returns:
+ * {String} the name
+ */
+ getName : function() { return this.options.label; },
+ /**
+ * Method: setName
+ * Set the label of a TreeItem
+ *
+ * Parameters:
+ * name - {String} the new label
+ */
+ setName : function(name) {
+ this.domA.set('html', name);
+ this.options.label = name;
+ },
+ /**
+ * Method: propertyChanged
+ * A property of an object has changed, synchronize the state of the
+ * TreeItem with the state of the object
+ *
+ * Parameters:
+ * obj - {Object} the object whose state has changed
+ */
+ propertyChanged : function(obj) {
+ this.options.enabled = obj.isEnabled();
+ if (this.options.enabled) {
+ this.domObj.removeClass('jxDisabled');
+ } else {
+ this.domObj.addClass('jxDisabled');
+ }
+ }
+});// $Id: treefolder.js 785 2008-08-26 21:28:39Z pspencer $
+/**
+ * Class: Jx.TreeFolder
+ * A Jx.TreeFolder is an item in a tree that can contain other items. It is
+ * expandable and collapsible.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Extends:
+ * <Jx.TreeItem>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.TreeFolder = new Class({
+ Extends: Jx.TreeItem,
+ /**
+ * Property: subDomObj
+ * {HTMLElement} an HTML container for the things inside the folder
+ */
+ subDomObj : null,
+ /**
+ * Property: nodes
+ * {Array} an array of references to the javascript objects that are
+ * children of this folder
+ */
+ nodes : null,
+ /**
+ * Property: isOpen
+ * {Boolean} is the folder open or not?
+ */
+ isOpen : false,
+ options: {
+ folderCloseImage: Jx.baseURL + 'images/tree_folder.png',
+ folderOpenImage: Jx.baseURL + 'images/tree_folder_open.png'
+ },
+ /**
+ * Constructor: Jx.TreeFolder
+ * Create a new instance of Jx.TreeFolder
+ *
+ * Parameters:
+ * options - {Object} an object containing any of the options of a
+ * <Jx.TreeItem> (see <Jx.TreeItem::Jx.TreeItem>) plus the following
+ * optional attributes that control how the TreeFolder functions.
+ *
+ * Options:
+ * openImage - {String} a URL to an image for opening the folder
+ * closeImage - {String} a URL to an image for closing the folder
+ * folderCloseImage - {String} a URL to an image to represent the folder
+ * when it is closed
+ * folderOpenImage - {String} a URL to an image to represent the folder
+ * when it is open
+ */
+ initialize : function( options ) {
+ this.parent($merge(options,{type:'Branch'}));
+
+ this.domObj.childNodes[0].addEvent('click', this.clicked.bindWithEvent(this));
+
+ this.nodes = [];
+ this.subDomObj = new Element('ul', {'class':'jxTree'});
+ this.domObj.appendChild(this.subDomObj);
+ this.subDomObj.className = 'jxTree';
+ if (this.options.isOpen) {
+ this.expand();
+ } else {
+ this.collapse();
+ }
+ },
+ /**
+ * Method: finalize
+ * Clean up a TreeFolder.
+ */
+ finalize: function() {
+ this.finalizeFolder();
+ this.finalizeItem();
+ this.subDomObj = null;
+ },
+ /**
+ * Method: finalizeFolder
+ * Internal method to clean up folder-related stuff.
+ */
+ finalizeFolder: function() {
+ this.domObj.childNodes[0].removeEvents();
+ for (var i=this.nodes.length-1; i>=0; i--) {
+ this.nodes[i].finalize();
+ if (this.nodes[i].domObj) this.subDomObj.removeChild(this.nodes[i].domObj);
+ this.nodes.pop();
+ }
+
+ },
+
+ /**
+ * Method: clone
+ * Create a clone of the TreeFolder
+ *
+ * Returns:
+ * {<Jx.TreeFolder>} a copy of the TreeFolder
+ */
+ clone : function() {
+ var node = new Jx.TreeFolder(this.options);
+ this.nodes.each(function(n){node.append(n.clone());});
+ return node;
+ },
+ /**
+ * Method: isLastNode
+ * Indicates if a node is the last thing in the folder.
+ *
+ * Parameters:
+ * node - {Jx.TreeItem} the node to check
+ *
+ * Returns:
+ *
+ * {Boolean}
+ */
+ isLastNode : function(node) {
+ if (this.nodes.length == 0) {
+ return false;
+ } else {
+ return this.nodes[this.nodes.length-1] == node;
+ }
+ },
+ /**
+ * Method: update
+ * Update the CSS of the TreeFolder's DOM element in case it has changed
+ * position.
+ *
+ * Parameters:
+ * shouldDescend - {Boolean} propagate changes to child nodes?
+ */
+ update : function(shouldDescend) {
+ /* avoid update if not attached to tree yet */
+ if (!this.parent) return;
+ var isLast = false;
+ if (arguments.length > 1) {
+ isLast = arguments[1];
+ } else {
+ isLast = (this.owner && this.owner.isLastNode(this));
+ }
+
+ var c = 'jxTree'+this.options.type;
+ c += isLast ? 'Last' : '';
+ c += this.options.isOpen ? 'Open' : 'Closed';
+ this.domObj.className = c;
+
+ if (isLast) {
+ this.subDomObj.className = 'jxTree';
+ } else {
+ this.subDomObj.className = 'jxTree jxTreeNest';
+ }
+
+ if (this.nodes && shouldDescend) {
+ var that = this;
+ this.nodes.each(function(n,i){
+ n.update(false, i==that.nodes.length-1);
+ });
+ }
+ },
+ /**
+ * Method: append
+ * append a node at the end of the sub-tree
+ *
+ * Parameters:
+ * node - {Object} the node to append.
+ */
+ append : function( node ) {
+ node.owner = this;
+ this.nodes.push(node);
+ this.subDomObj.appendChild( node.domObj );
+ this.update(true);
+ },
+ /**
+ * Method: insert
+ * insert a node after refNode. If refNode is null, insert at beginning
+ *
+ * Parameters:
+ * node - {Object} the node to insert
+ * refNode - {Object} the node to insert before
+ */
+ insert : function( node, refNode ) {
+ node.owner = this;
+ //if refNode is not supplied, insert at the beginning.
+ if (!refNode) {
+ this.nodes.unshift(node);
+ //sanity check to make sure there is actually something there
+ if (this.subDomObj.childNodes.length ==0) {
+ this.subDomObj.appendChild(node.domObj);
+ } else {
+ this.subDomObj.insertBefore(node.domObj, this.subDomObj.childNodes[0]);
+ }
+ } else {
+ //walk all nodes looking for the ref node. Track if it actually
+ //happens so we can append if it fails.
+ var b = false;
+ for(var i=0;i<this.nodes.length;i++) {
+ if (this.nodes[i] == refNode) {
+ //increment to append after ref node. If this pushes us
+ //past the end, it'll get appended below anyway
+ i = i + 1;
+ if (i < this.nodes.length) {
+ this.nodes.splice(i, 0, node);
+ this.subDomObj.insertBefore(node.domObj, this.subDomObj.childNodes[i]);
+ b = true;
+ break;
+ }
+ }
+ }
+ //if the node wasn't inserted, it is because refNode didn't exist
+ //and so the fallback is to just append the node.
+ if (!b) {
+ this.nodes.push(node);
+ this.subDomObj.appendChild(node.domObj);
+ }
+ }
+ this.update(true);
+ },
+ /**
+ * Method: remove
+ * remove the specified node from the tree
+ *
+ * Parameters:
+ * node - {Object} the node to remove
+ */
+ remove : function(node) {
+ node.owner = null;
+ for(var i=0;i<this.nodes.length;i++) {
+ if (this.nodes[i] == node) {
+ this.nodes.splice(i, 1);
+ this.subDomObj.removeChild(this.subDomObj.childNodes[i]);
+ break;
+ }
+ }
+ this.update(true);
+ },
+ /**
+ * Method: replace
+ * Replace a node with another node
+ *
+ * Parameters:
+ * newNode - {Object} the node to put into the tree
+ * refNode - {Object} the node to replace
+ *
+ * Returns:
+ * {Boolean} true if the replacement was successful.
+ */
+ replace: function( newNode, refNode ) {
+ //walk all nodes looking for the ref node.
+ var b = false;
+ for(var i=0;i<this.nodes.length;i++) {
+ if (this.nodes[i] == refNode) {
+ if (i < this.nodes.length) {
+ newNode.owner = this;
+ this.nodes.splice(i, 1, newNode);
+ this.subDomObj.replaceChild(newNode.domObj, refNode.domObj);
+ return true;
+ }
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Method: clicked
+ * handle the user clicking on this folder by expanding or
+ * collapsing it.
+ *
+ * Parameters:
+ * e - {Event} the event object
+ */
+ clicked : function(e) {
+ if (this.options.isOpen) {
+ this.collapse();
+ } else {
+ this.expand();
+ }
+ },
+ /**
+ * Method: expand
+ * Expands the folder
+ */
+ expand : function() {
+ this.options.isOpen = true;
+ this.subDomObj.setStyle('display', 'block');
+ this.update(true);
+ this.fireEvent('disclosed', this);
+ },
+ /**
+ * Method: collapse
+ * Collapses the folder
+ */
+ collapse : function() {
+ this.options.isOpen = false;
+ this.subDomObj.setStyle('display', 'none');
+ this.update(true);
+ this.fireEvent('disclosed', this);
+ },
+ /**
+ * Method: findChild
+ * Get a reference to a child node by recursively searching the tree
+ *
+ * Parameters:
+ * path - {Array} an array of labels of nodes to search for
+ *
+ * Returns:
+ * {Object} the node or null if the path was not found
+ */
+ findChild : function(path) {
+ //path is empty - we are asking for this node
+ if (path.length == 0)
+ return this;
+
+ //path has only one thing in it - looking for something in this folder
+ if (path.length == 1)
+ {
+ for (var i=0; i<this.nodes.length; i++)
+ {
+ if (this.nodes[i].getName() == path[0])
+ return this.nodes[i];
+ }
+ return null;
+ }
+ //path has more than one thing in it, find a folder and descend into it
+ var childName = path.shift();
+ for (var i=0; i<this.nodes.length; i++)
+ {
+ if (this.nodes[i].getName() == childName && this.nodes[i].findChild)
+ return this.nodes[i].findChild(path);
+ }
+ return null;
+ }
+});// $Id: tree.js 711 2008-08-13 20:38:33Z pspencer $
+/**
+ * Class: Jx.Tree
+ * Jx.Tree displays hierarchical data in a tree structure of folders and nodes.
+ *
+ * Example:
+ * (code)
+ * (end)
+ *
+ * Extends: <Jx.TreeFolder>
+ *
+ * License:
+ * Copyright (c) 2008, DM Solutions Group Inc.
+ *
+ * This file is licensed under an MIT style license
+ */
+Jx.Tree = new Class({
+ Extends: Jx.TreeFolder,
+ /**
+ * Constructor: Jx.Tree
+ * Create a new instance of Jx.Tree
+ *
+ * Parameters:
+ * id - {String} the id of the DOM element to create the tree inside.
+ */
+ initialize : function( id ) {
+ this.parent();
+ this.subDomObj = new Element('ul',{
+ 'class':'jxTreeRoot'
+ });
+ $(id).appendChild(this.subDomObj);
+ this.nodes = [];
+ this.isOpen = true;
+ },
+ /**
+ * Method: finalize
+ * Clean up a Jx.Tree instance
+ */
+ finalize: function() {
+ this.clear();
+ this.subDomObj.parentNode.removeChild(this.subDomObj);
+ },
+ /**
+ * Method: clear
+ * Clear the tree of all child nodes
+ */
+ clear: function() {
+ for (var i=this.nodes.length-1; i>=0; i--) {
+ this.subDomObj.removeChild(this.nodes[i].domObj);
+ this.nodes[i].finalize();
+ this.nodes.pop();
+ }
+ },
+ /**
+ * Method: update
+ * Update the CSS of the Tree's DOM element in case it has changed
+ * position
+ *
+ * Parameters:
+ * shouldDescend - {Boolean} propagate changes to child nodes?
+ */
+ update: function(shouldDescend) {
+ var bLast = true;
+ if (this.subDomObj)
+ {
+ if (bLast) {
+ this.subDomObj.removeClass('jxTreeNest');
+ } else {
+ this.subDomObj.addClass('jxTreeNest');
+ }
+ }
+ if (this.nodes && shouldDescend) {
+ this.nodes.each(function(n){n.update(false);});
+ }
+ },
+ /**
+ * Method: append
+ * Append a node at the end of the sub-tree
+ *
+ * Parameters:
+ * node - {Object} the node to append.
+ */
+ append: function( node ) {
+ node.owner = this;
+ this.nodes.push(node);
+ this.subDomObj.appendChild( node.domObj );
+ this.update(true);
+ }
+});
\ No newline at end of file
Added: sandbox/jx2/jx/lib/jxskin_border.css
===================================================================
--- sandbox/jx2/jx/lib/jxskin_border.css (rev 0)
+++ sandbox/jx2/jx/lib/jxskin_border.css 2008-08-28 12:29:20 UTC (rev 1482)
@@ -0,0 +1 @@
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}a{outline:none;}.png24{filter:expression(Jx.applyPNGFilter(this));}.jxClearer{display:block;position:relative;float:none;clear:both;font-size:0;line-height:0;width:0;height:0;margin:0;padding:0;}.jxDisabled{opacity:.4;filter:Alpha(opacity=40);}iframe.jxIframeShim{position:absolute;top:0;left:0;width:100%;height:100%;filter:Alpha(opacity:0);opacity:0;z-index:-1;}div.jxButtonContainer{display:block;position:relative;float:left;margin:1px;padding:0;border:none;}a.jxButton{display:block;position:relative;float:left;margin:0;padding:4px;border:1px solid #d9d9d9;background-repeat:no-repeat;text-decoration:none;}a.jxButton:hover{border-top:1px solid #fff;border-left:1px solid #fff;border-bottom:1px solid #999;border-right:1px solid #999;}a.jxButton:active{border-bottom:1px solid #fff;border-right:1px solid #fff;border-top:1px solid #999;border-left:1px solid #999;}a.jxButtonActive{background-color:#f0f0f0;border-bottom:1px solid #fff;border-right:1px solid #fff;border-top:1px solid #999;border-left:1px solid #999;}a.jxButtonActive:hover{border-bottom:1px solid #fff;border-right:1px solid #fff;border-top:1px solid #999;border-left:1px solid #999;}a.jxButtonActive:active{border-bottom:1px solid #fff;border-right:1px solid #fff;border-top:1px solid #999;border-left:1px solid #999;}.jxButtonDisabled a.jxButton:hover,.jxButtonDisabled a.jxButton:active{border:1px solid #d9d9d9;}span.jxButtonContent{display:block;position:relative;float:left;font-size:0;line-height:0;margin:0;padding:0;background-repeat:no-repeat;}span.jxButtonContent span{font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:16px;}img.jxButtonIcon{position:relative;float:left;width:16px;height:16px;background-position:center center;background-repeat:no-repeat;}span.jxButtonContent span.jxButtonLabel{display:block;position:relative;float:left;cursor:pointer;margin:0;padding:0 4px;color:#000;background-position:right center;background-repeat:no-repeat;font-size:11px;}a.jxButtonMenu span.jxButtonContent,a.jxButtonFlyout span.jxButtonContent{background-image:url(../images/menu_item_arrow_d2.png);background-position:right center;background-repeat:no-repeat;}a.jxButtonMenu span.jxButtonContent span,a.jxButtonFlyout span.jxButtonContent span{padding-right:16px;}a.jxButtonMulti span.jxButtonLabel{padding-left:0;padding-right:0;}.jxFlyout{position:absolute;display:block;clear:both;float:none;z-index:100;margin:0;padding:0;border:1px solid #999;background-color:#fff;font-size:12px;line-height:14px;}.jxFlyout .jxBarRight,.jxFlyout .jxBarLeft{float:left;height:auto;width:auto;}.jxChrome{position:absolute;display:block;font-size:0;line-height:0;z-index:0;}.jxChromeTL{position:absolute;overflow:hidden;left:0;top:0;width:50%;height:50%;}.jxChromeTR{position:absolute;overflow:hidden;left:50%;top:0;width:50%;height:50%;}.jxChromeBL{position:absolute;overflow:hidden;left:0;top:50%;width:50%;height:50%;}.jxChromeBR{position:absolute;overflow:hidden;left:50%;top:50%;width:50%;height:50%;}.jxChromeTL img{position:absolute;top:0;left:0;}.jxChromeTR img{position:absolute;top:0;right:0;}.jxChromeBL img{position:absolute;bottom:0;left:0;}.jxChromeBR img{position:absolute;bottom:0;right:0;}.jxColorBar{position:relative;}table.jxColorGrid{position:relative;border-collapse:collapse;empty-cells:show;clear:both;}.jxColorGrid td{border:1px solid #000;}.jxColorGrid td.emptyCell{border:0 solid #000;}.jxColorGrid td.emptyCell span{display:block;width:7px;height:7px;line-height:0;font-size:0;border:0 solid #000;padding:1px;margin:0;}.jxColorGrid a.colorSwatch{display:block;width:7px;height:7px;line-height:0;font-size:0;border:0 solid #000;margin:0;padding:1px;}.jxColorGrid a.borderWhite:hover{border:1px solid #fff;padding:0;}.jxColorGrid a.borderBlack:hover{border:1px solid #000;padding:0;}input.jxHexInput{width:55px;vertical-align:middle;}input.jxAlphaInput{width:30px;vertical-align:middle;}div.jxColorPreview{float:left;position:relative;width:20px;height:20px;border:1px solid #000;margin:2px;vertical-align:middle;background-image:url('../images/grid.png');}span.jxButtonContent span.jxButtonSwatch{display:block;float:left;width:14px;height:14px;border:1px solid #000;background-image:url('../images/grid.png');padding-right:0!important;}span.jxButtonContent span.jxButtonSwatch span{display:block;width:14px;height:14px;position:absolute;padding-right:0;}div.jxColorPreview img{position:absolute;z-index:0;}div.jxColorPreview div.jxColorSelected{width:20px;height:10px;position:absolute;z-index:1;}div.jxColorPreview div.jxColorHover{width:20px;height:10px;position:absolute;bottom:0;z-index:1;}label.jxColorLabel,label.jxAlphaLabel{width:auto;font-family:Arial,sans-serif;font-size:12px;line-height:24px;padding:2px;vertical-align:middle;}a.jxColorClose{position:absolute;top:0;right:0;width:16px;height:16px;}a.jxColorClose img{width:16px;height:16px;}div.jxCombo{position:relative;display:block;padding:0;padding-right:22px;margin:0;border:0;font-family:Arial,Helvetica,sans-serif;font-size:11px;z-index:1;line-height:24px;float:left;}.jxComboDiscloser{position:absolute;right:3px;top:3px;}.jxComboDiscloser img{width:16px;height:16px;border:0;}.jxComboInput{position:relative;display:block;float:left;line-height:14px;height:14px;padding:5px 10px;border:1px solid #d9d9d9;}div.jxComboOptions{position:absolute;height:auto;background-color:#fff;overflow:auto;border:1px solid #333;color:#000;z-index:1;font-family:Arial,Helvetica,sans-serif;font-size:11px;line-height:24px;}div.jxComboOptions ul{position:relative;display:block;margin:0;padding:0;border:none;list-style-type:none;}div.jxComboOptions li{position:relative;display:block;margin:0;padding:0;border:none;height:20px;}div.jxComboOptions a{position:relative;display:block;text-decoration:none;white-space:nowrap;line-height:20px;height:20px;color:#000;background-position:right top;background-repeat:no-repeat;padding:0 4px;}div.jxComboOptions a:hover{background-color:#E1EDFA;}div.jxComboOptions a.selected{font-weight:bold;background-color:#ffffb3;}.jxDialog .jxChrome{background-color:#000;padding:1px 3px 3px 1px;opacity:.2;}.jxDialog{display:block;z-index:1;border:1px solid #666;}.jxDialogContentContainer{z-index:1;background-color:#ccc;}.jxDialogModal{position:absolute;display:block;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.2;filter:Alpha(opacity=20);}.jxDialogContent{display:block;position:relative;overflow:auto;border-top:1px solid #fff;border-left:1px solid #fff;padding:0;z-index:1;}.jxDialogTitle{display:block;position:relative;text-align:center;background-color:#ccc;border-top:1px solid #fff;border-left:1px solid #fff;border-bottom:1px solid #999;height:22px;margin:0;padding:0;z-index:1;}.jxDialogMoveable{cursor:move;}.jxDialogLabel{font-family:Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;line-height:21px;color:#000;white-space:nowrap;}.jxDialogResize{position:absolute;bottom:0;right:0;width:22px;height:22px;z-index:2;border:0;cursor:se-resize;background-image:url(../images/dialog_resize.png);z-index:1;}.jxDialogControls{position:absolute;top:3px;right:2px;height:16px;width:80px;}.jxDialogControls img{background-image:url('../images/panel_controls.png');background-repeat:no-repeat;border:0;margin:0;width:16px;height:16px;}.jxDialogClose img{background-position:0 -32px;}.jxDialogMenu img{background-position:0 -48px;}.jxDialogHelp img{background-position:0 -64px;}.jxDialogCollapse img{background-position:0 -16px;}.jxDialogMin .jxDialogCollapse img{background-position:0 0;}.jxDialogMax .jxDialogCollapse img{background-position:0 -16px;}.jxDialogLoading img{border:0;margin:0;width:16px;height:16px;visibility:hidden;position:absolute;top:1px;left:2px;}.jxDialogControls .jxButtonContainer,.jxDialogControls span.jxButtonContent,.jxDialogControls a.jxButton:hover span.jxButtonContent,.jxDialogControls a.jxButton:active span.jxButtonContent,.jxDialogControls a.jxButtonActive span.jxButtonContent,.jxDialogControls a.jxButtonActive:hover span.jxButtonContent,.jxDialogControls a.jxButtonActive:active span.jxButtonContent,.jxDialogControls .jxButtonDisabled a.jxButton span.jxButtonContent,.jxDialogControls .jxButtonDisabled a.jxButton:hover span.jxButtonContent,.jxDialogControls .jxButtonDisabled a.jxButton:active span.jxButtonContent,.jxDialogControls a.jxButton,.jxDialogControls a.jxButton:hover,.jxDialogControls a.jxButton:active,.jxDialogControls a.jxButtonActive,.jxDialogControls a.jxButtonActive:hover,.jxDialogControls a.jxButtonActive:active,.jxDialogControls .jxButtonDisabled a.jxButton,.jxDialogControls .jxButtonDisabled a.jxButton:hover,.jxDialogControls .jxButtonDisabled a.jxButton:active{padding:0;margin:0;border:none;background-color:transparent;background-image:none;}.jxDialogControls a.jxButtonMenu span.jxButtonContent,.jxDialogControls a.jxButtonFlyout span.jxButtonContent{background-image:none;}.jxDialogControls a.jxButtonMenu span.jxButtonContent span,.jxDialogControls a.jxButtonFlyout span.jxButtonContent span{padding-right:0;}.jxDialogControls .jxToolbarContainer{position:absolute;right:0;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxDialogControls ul.jxToolbar{float:right;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxDialogControls .jxBarTop,.jxDialogControls .jxBarBottom,.jxDialogControls .jxBarLeft,.jxDialogControls .jxBarRight{width:auto;height:auto;}.jxDialogControls .jxBarTop ul.jxToolbar,.jxDialogControls .jxBarBottom ul.jxToolbar,.jxDialogControls .jxBarLeft ul.jxToolbar,.jxDialogControls .jxBarRight ul.jxToolbar,.jxDialogControls .jxBarTop li.jxToolItem,.jxDialogControls .jxBarBottom li.jxToolItem,.jxDialogControls .jxBarLeft li.jxToolItem,.jxDialogControls .jxBarRight li.jxToolItem{background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxGridContainer{position:absolute;top:0;left:0;border-left:0 solid #96a7b4;border-top:0 solid #96a7b4;border-right:1px solid #96a7b4;border-bottom:1px solid #96a7b4;overflow:hidden;font-family:Arial,Verdana,sans-serif;font-size:12px;font-weight:normal;}.jxGridTable{position:relative;table-layout:fixed;border-collapse:collapse;border-style:none;width:0;}.jxGridColHeadHide{height:0;line-height:0;font-size:0;background-color:#fff;white-space:normal;}.jxGridColHeadHide p,.jxGridRowHeadHide p{font-size:0;line-height:0;height:0;margin:0;padding:0;}.jxGridRowHeadHide{width:0;white-space:normal;}.jxGridCell{border-right:1px solid #cecece;border-bottom:1px solid #cecece;overflow:hidden;padding-left:3px;padding-right:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.jxGridColHead{border-top:0 solid #96a7b4;border-right:1px solid #96a7b4;border-bottom:1px solid #96a7b4;border-left:0 solid #96a7b4;background-color:#ebebeb;text-align:center;font-weight:bold;color:#45525f;}.jxGridRowHead{border-top:0 solid #96a7b4;border-right:1px solid #96a7b4;border-bottom:1px solid #96a7b4;border-left:0 solid #96a7b4;background-color:#ebebeb;text-align:center;font-weight:bold;color:#45525f;}.jxGridRowAll{background-color:#fff;}.jxGridRowOdd td{border-right:1px solid #999;border-bottom:1px solid #999;}.jxGridRowEven td{border-right:1px solid #999;border-bottom:1px solid #999;}.jxGridRowSelected{background-color:#dae6f2;}.jxGridColumnSelected{background-color:#dae6f2;}.jxGridCellSelected{background-color:#dae6f2;}.jxGridRowPrelight{background-color:#f2f2f2;}.jxGridRowHeaderPrelight{background-color:#dfdfdf;}.jxGridColumnHeaderPrelight{background-color:#dfdfdf;}.jxGridRowHeaderSelected{background-color:#6d7f8e;color:#fff;}.jxGridColumnHeaderSelected{background-color:#6d7f8e;color:#fff;}a.jxButtonMenu span.jxMenuItemSpan{padding-right:16px;}ul.jxMenu,ul.jxSubMenu{position:absolute;display:block;clear:both;float:none;z-index:100;list-style-type:none;margin:0;padding:0;border:1px solid #999;background-color:#fff;}li.jxMenuItemContainer{display:block;position:relative;margin:0;padding:0;}a.jxMenuItem{display:block;position:relative;text-decoration:none;background-image:none;border:1px solid #fff;font-family:Arial,Helvetica,sans-serif;font-size:11px;text-decoration:none;margin:0;padding:0;color:#000;}a.jxMenuItem:hover{background-image:none;border:1px solid #E1EDFA;background-color:#E1EDFA;}a.jxMenuItem:hover span.jxMenuItemContent{border:1px solid #E1EDFA;}span.jxMenuItemContent{display:block;position:relative;font-family:Arial,Helvetica,sans-serif;font-size:0;line-height:0;white-space:nowrap;padding:0;margin:0;border:1px solid #fff;}a.jxButtonSubMenu span.jxMenuItemContent,a.jxButtonSubMenu:hover span.jxMenuItemContent{background-image:url(../images/menu_item_arrow_r2.png);background-position:right top;background-repeat:no-repeat;padding-right:20px;}img.jxMenuItemIcon{position:absolute;top:0;left:0;display:inline;width:16px;height:16px;background-position:left center;background-repeat:no-repeat;}span.jxMenuItemContent span{display:block;position:relative;cursor:pointer;margin:0;padding:0 0 0 20px;font-size:16px;line-height:16px;}span.jxMenuItemContent span.jxMenuItemLabel{color:#000;font-size:12px;}ul.jxMenu a.jxMenuItemSelected{background-image:url(../images/menu_item_radio.png);background-position:2px top;background-repeat:no-repeat;}li.jxMenuItemDisabled span.jxMenuItemLabel{color:#ccc;}li.jxMenuItemDisabled a.jxMenuItem:hover{background-color:#fff;border:1px solid #fff;}ul.jxMenu span.jxMenuSeparator{display:block;font-size:10px;line-height:10px;background-image:url(../images/toolbar_separator_v.png);background-repeat:repeat-x;background-position:left center;}.jxPanel{display:block;position:relative;}.jxPanelContentContainer{overflow:hidden;}.jxPanelContent{position:relative;display:block;overflow:auto;border-top:1px solid #fff;border-bottom:1px solid #999;margin:0;padding:0;border-top:none;background-color:#fff;}.jxPanelTitle{display:block;position:relative;background-color:#ccc;border-top:1px solid #fff;border-bottom:1px solid #999;height:22px;margin:0;padding:0;}.jxPanelLabel{padding-left:25px;font-family:Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;line-height:21px;color:#000;white-space:nowrap;}.jxPanelControls{position:absolute;top:3px;right:2px;height:16px;width:80px;}.jxPanelControls img{background-image:url('../images/panel_controls.png');background-repeat:no-repeat;border:0;margin:0;width:16px;height:16px;}.jxPanelClose img{background-position:0 -32px;}.jxPanelMenu img{background-position:0 -48px;}.jxPanelHelp img{background-position:0 -64px;}.jxPanelCollapse img{background-position:0 -16px;}.jxPanelMin .jxPanelCollapse img{background-position:0 0;}.jxPanelMax .jxPanelCollapse img{background-position:0 -16px;}.jxPanelMaximize img{background-position:0 0;}.jxPanelLoading img{border:0;margin:0;width:16px;height:16px;visibility:hidden;position:absolute;top:1px;left:2px;}.jxPanelControls .jxButtonContainer,.jxPanelControls span.jxButtonContent,.jxPanelControls a.jxButton:hover span.jxButtonContent,.jxPanelControls a.jxButton:active span.jxButtonContent,.jxPanelControls a.jxButtonActive span.jxButtonContent,.jxPanelControls a.jxButtonActive:hover span.jxButtonContent,.jxPanelControls a.jxButtonActive:active span.jxButtonContent,.jxPanelControls .jxButtonDisabled a.jxButton span.jxButtonContent,.jxPanelControls .jxButtonDisabled a.jxButton:hover span.jxButtonContent,.jxPanelControls .jxButtonDisabled a.jxButton:active span.jxButtonContent,.jxPanelControls a.jxButton,.jxPanelControls a.jxButton:hover,.jxPanelControls a.jxButton:active,.jxPanelControls a.jxButtonActive,.jxPanelControls a.jxButtonActive:hover,.jxPanelControls a.jxButtonActive:active,.jxPanelControls .jxButtonDisabled a.jxButton,.jxPanelControls .jxButtonDisabled a.jxButton:hover,.jxPanelControls .jxButtonDisabled a.jxButton:active{padding:0;margin:0;border:none;background-color:transparent;background-image:none;}.jxPanelControls a.jxButtonMenu span.jxButtonContent,.jxPanelControls a.jxButtonFlyout span.jxButtonContent{background-image:none;}.jxPanelControls a.jxButtonMenu span.jxButtonContent span,.jxPanelControls a.jxButtonFlyout span.jxButtonContent span{padding-right:0;}.jxPanelControls .jxToolbarContainer{position:absolute;right:0;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxPanelControls ul.jxToolbar{background-image:none;background-color:transparent;margin:0;padding:0;border:none;float:right;}.jxPanelControls .jxBarTop,.jxPanelControls .jxBarBottom,.jxPanelControls .jxBarLeft,.jxPanelControls .jxBarRight{width:auto;height:auto;}.jxPanelControls .jxBarTop ul.jxToolbar,.jxPanelControls .jxBarBottom ul.jxToolbar,.jxPanelControls .jxBarLeft ul.jxToolbar,.jxPanelControls .jxBarRight ul.jxToolbar,.jxPanelControls .jxBarTop li.jxToolItem,.jxPanelControls .jxBarBottom li.jxToolItem,.jxPanelControls .jxBarLeft li.jxToolItem,.jxPanelControls .jxBarRight li.jxToolItem{background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxSplitBarHorizontal{position:absolute;display:block;line-height:1px;width:10px;top:0;height:100%;background-color:#d9d9d9;cursor:col-resize;}.jxSplitBarVertical{position:absolute;display:block;line-height:1px;width:100%;left:0;height:10px;background-color:#d9d9d9;cursor:row-resize;}.jxSplitArea{overflow:hidden;border-top:1px solid #999;border-left:1px solid #999;border-right:1px solid #fff;border-bottom:1px solid #fff;background-color:#eee;}.jxSplitBarDrag{background-color:#c9c9c9;}.jxSnapHorizontalBefore{position:absolute;display:block;top:50%;left:0;margin-top:-25px;width:10px;height:50px;z-index:1;overflow:hidden;background-color:#eee;}.jxSnapHorizontalAfter{position:absolute;display:block;top:50%;left:0;margin-top:-25px;width:10px;height:50px;z-index:1;overflow:hidden;background-color:#eee;}.jxSnapVerticalBefore{position:absolute;display:block;top:0;left:50%;margin-left:-25px;width:50px;height:10px;z-index:1;overflow:hidden;background-color:#eee;}.jxSnapVerticalAfter{position:absolute;display:block;top:0;left:50%;margin-left:-25px;width:50px;height:10px;z-index:1;overflow:hidden;background-color:#eee;}.jxTabSetContainer{position:relative;display:block;width:200px;height:200px;margin:0;padding:0;border:1px solid #999;}.jxTabSetContainer .jxToolbarContainer,.jxTabSetContainer ul.jxToolbar{z-index:auto;border:none;}.tabContent{display:none;position:relative;width:100%;height:100%;overflow:auto;}.tabContentActive{display:block;}.jxTabBoxTop,.jxTabBoxBottom,.jxTabBoxLeft,.jxTabBoxRight{overflow:visible;}.jxTabBoxTop .jxBarTop,.jxTabBoxBottom .jxBarBottom,.jxTabBoxLeft .jxBarLeft,.jxTabBoxRight .jxBarRight{position:absolute;}li.jxTabItem{margin:0;padding:0;}.jxBarTop li.jxTabItem,.jxBarBottom li.jxTabItem{border:none;}.jxBarLeft li.jxTabItem,.jxBarRight li.jxTabItem{border:none;}a.jxTab{display:block;position:relative;margin:0;padding:0;border:1px solid #999;background-repeat:no-repeat;text-decoration:none;color:#000;}a.jxTab:hover{background-color:#ccc;}a.jxTab:active{background-color:#fff;}a.jxTabActive{background-color:#fff;}span.jxTabContent{display:block;font-size:0;line-height:0;margin:0;padding:0;}img.jxTabIcon{position:relative;width:16px;height:16px;background-position:center center;background-repeat:no-repeat;}span.jxTabLabel{display:block;position:relative;cursor:pointer;margin:0;padding:0;color:#000;font-family:Arial,Helvetica,sans-serif;font-size:11px;line-height:16px;}.jxTabBoxTop{margin-top:27px;}.jxTabBoxTop .jxBarTop{top:-27px;}.jxBarTop a.jxTab{float:left;margin:0 1px;padding:4px;}.jxBarTop span.jxTabContent{float:left;}.jxBarTop img.jxTabIcon{float:left;}.jxBarTop span.jxTabLabel{float:left;padding:0 4px 0 4px;}.jxBarTop a.jsTabActive{border-bottom:1px solid #fff;}.jxTabBoxBottom{margin-bottom:27px;}.jxTabBoxBottom .jxBarBottom{bottom:-27px;background-position:top;}.jxBarBottom a.jxTab{float:left;margin:0 1px;padding:4px;}.jxBarTop span.jxTabContent{float:left;}.jxBarTop img.jxTabIcon{float:left;}.jxBarTop span.jxTabLabel{float:left;padding:0 4px 0 4px;}.jxBarBottom a.jxTabActive{border-top:1px solid #fff;}.jxTabBoxLeft{margin-left:27px;}.jxTabBoxLeft .jxBarLeft{left:-27px;}.jxBarLeft a.jxTab{margin:1px 0 1px 2px;padding:4px;}.jxBarLeft a.jxTabActive{border-right:1px solid #fff;}.jxTabBoxRight{margin-right:27px;}.jxTabBoxRight .jxBarRight{right:-27px;background-position:left;}.jxBarRight a.jxTab{margin:1px 2px 1px 0;padding:7px;}.jxBarRight a.jxTabActive{border-left:1px solid #fff;}.jxToolbarContainer{display:block;position:relative;z-index:1;margin:0;padding:0;border:0;background-color:#d9d9d9;}.jxBarTop,.jxBarBottom{width:100%;height:auto;background-repeat:repeat-x;background-position:bottom;}.jxBarLeft,.jxBarRight{width:auto;height:100%;background-repeat:repeat-y;background-position:right;}.toolbarLabel{display:block;position:relative;float:left;margin:0;padding:0;font-family:Arial,Hevetica,sans-serif;font-size:11px;line-height:24px;color:#000;}ul.jxToolbar{display:block;position:relative;float:left;list-style-type:none;margin:0;padding:0;}.jxBarTop ul.jxToolbar,.jxBarBottom ul.jxToolbar{border-left:1px solid #fff;border-right:1px solid #999;border-top:1px solid #fff;}.jxBarLeft ul.jxToolbar,.jxBarRight ul.jxToolbar{border-left:1px solid #fff;border-top:1px solid #fff;border-bottom:1px solid #999;}li.jxToolItem{display:block;position:relative;float:left;font-size:0;line-height:0;padding:0;margin:0;}.jxBarTop li.jxToolItem,.jxBarBottom li.jxToolItem{border-top:none;border-right:none;border-bottom:1px solid #999;border-left:none;}.jxBarLeft li.jxToolItem,.jxBarRight li.jxToolItem{border-top:none;border-right:1px solid #999;border-bottom:none;border-left:none;}li.jxToolItem .separator{display:block;position:relative;float:left;font-size:0;line-height:0;width:8px;height:18px;border:0;margin:0;padding:4px;background-repeat:no-repeat;background-position:center center;}.jxBarTop li.jxToolItem span.separator,.jxBarBottom li.jxToolItem span.separator{background-image:url(../images/toolbar_separator_h.png);}.jxBarLeft li.jxToolItem span.separator,.jxBarRight li.jxToolItem span.separator{background-image:url(../images/toolbar_separator_v.png);}.jxBarLeft label.toolbarLabel,.jxBarLeft ul.jxToolbar,.jxBarLeft li.jxToolItem,.jxBarRight label.toolbarLabel,.jxBarRight ul.jxToolbar,.jxBarRight li.jxToolItem{clear:both;}.verticalToolbar{width:auto;}.verticalToolbar label.toolbarLabel,.verticalToolbar ul.jxToolbar,.verticalToolbar li.jxToolItem{clear:both;}.jxTree,.jxTreeRoot{position:relative;list-style:none;margin:0;padding:0;}.jxTreeNest{list-style:none;margin:0;padding:0;background-repeat:repeat-y;background-position:left top;}.jxTree li,.jxTreeRoot li{position:relative;margin:0;padding:0;background-repeat:no-repeat;background-position:left top;white-space:nowrap;width:100%;}.jxTree li{margin-left:16px;}.jxTree li.jxDisabled,.jxTreeRoot li.jxDisabled{opacity:.4;-moz-opacity:.4;filter:Alpha(opacity=40);}.jxTree a,.jxTreeRoot a{margin:0;padding:0;padding-left:2px;font-family:Arial,Helvetica,sans-serif;font-size:11px;color:#000;text-decoration:none;line-height:20px;}.jxTree a:hover,.jxTreeRoot a:hover{background-color:#E1EDFA;}.jxTree img,.jxTreeRoot img{border:0;width:16px;height:16px;}.jxTreeNest{background-image:url(../images/tree_vert_line.png);}.jxTreeNode{background-image:url(../images/tree_node.png);}.jxTreeNodeLast{background-image:url(../images/tree_last_node.png);}.jxTreeDropzone{text-decoration:underline;font-weight:bold;}.jxTreeSelectedNode{background-color:#AFD4FA;font-weight:bold;}.jxTreeCutNode{opacity:.4;-moz-opacity:.4;filter:Alpha(opacity=40);}.jxTreeCutNode a:hover{background-color:#fff;}.jxTreeNode a,.jxTreeNode img,.jxTreeNode input{vertical-align:middle;}.jxTreeNodeLast a,.jxTreeNodeLast img,.jxTreeNodeLast input{vertical-align:middle;}.jxTreeNodeIcon{margin:0;}
\ No newline at end of file
Added: sandbox/jx2/jx/lib/jxskin_delicious.css
===================================================================
--- sandbox/jx2/jx/lib/jxskin_delicious.css (rev 0)
+++ sandbox/jx2/jx/lib/jxskin_delicious.css 2008-08-28 12:29:20 UTC (rev 1482)
@@ -0,0 +1 @@
+body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}ol,ul{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;}q:before,q:after{content:'';}a{outline:none;}.png24{filter:expression(Jx.applyPNGFilter(this));}.jxClearer{display:block;position:relative;float:none;clear:both;font-size:0;line-height:0;width:0;height:0;margin:0;padding:0;}.jxDisabled{opacity:.4;filter:Alpha(opacity=40);}iframe.jxIframeShim{position:absolute;top:0;left:0;width:100%;height:100%;filter:Alpha(opacity:0);opacity:0;z-index:-1;}div.jxButtonContainer{display:block;position:relative;float:left;margin:2px;padding:0;border:none;}a.jxButton{display:block;position:relative;float:left;margin:0;padding:0 0 0 3px;border:none;background-image:url(../images/delicious/button_bg.png);background-position:left -56px;background-repeat:no-repeat;text-decoration:none;}ul.jxToolbar a.jxButton{background-position:left top;}span.jxButtonContent{display:block;position:relative;float:left;font-size:0;line-height:0;margin:0;padding:6px 6px 6px 3px;border:none;background-image:url(../images/delicious/button_bg.png);background-position:right -56px;background-repeat:no-repeat;}ul.jxToolbar span.jxButtonContent{background-position:right top;}a.jxButton:hover{background-position:left -224px;}ul.jxToolbar a.jxButton:hover{background-position:left -56px;}a.jxButton:hover span.jxButtonContent{background-position:right -224px;}ul.jxToolbar a.jxButton:hover span.jxButtonContent{background-position:right -56px;}ul.jxToolbar a.jxButtonActive,a.jxButtonActive{background-position:left -168px;}ul.jxToolbar a.jxButtonActive span.jxButtonContent,a.jxButtonActive span.jxButtonContent{background-position:right -168px;}ul.jxToolbar a.jxButtonActive:hover,a.jxButtonActive:hover{background-position:left -224px;}ul.jxToolbar a.jxButtonActive:hover span.jxButtonContent,a.jxButtonActive:hover span.jxButtonContent{background-position:right -224px;}ul.jxToolbar a.jxButton:active,a.jxButton:active,ul.jxToolbar a.jxButtonActive:active,a.jxButtonActive:active{background-position:left -112px;}ul.jxToolbar a.jxButton:active span.jxButtonContent,a.jxButton:active span.jxButtonContent,ul.jxToolbar a.jxButtonActive:active span.jxButtonContent,a.jxButtonActive:active span.jxButtonContent{background-position:right -112px;}ul.jxToolbar .jxDisabled a.jxButton:hover,ul.jxToolbar .jxDisabled a.jxButton:active,.jxDisabled a.jxButton:hover,.jxDisabled a.jxButton:active{background-position:left top;}ul.jxToolbar .jxDisabled a.jxButton:hover span.jxButtonContent,ul.jxToolbar .jxDisabled a.jxButton:active span.jxButtonContent,.jxDisabled a.jxButton:hover span.jxButtonContent,.jxDisabled a.jxButton:active span.jxButtonContent{background-position:right top;}img.jxButtonIcon{position:relative;float:left;width:16px;height:16px;background-position:center center;background-repeat:no-repeat;}span.jxButtonContent span{font-family:Arial,Helvetica,sans-serif;font-size:16px;line-height:16px;}span.jxButtonContent span.jxButtonLabel{display:block;position:relative;float:left;cursor:pointer;margin:0;padding:0 4px 0 4px;color:#000;font-size:11px;}a.jxButtonMenu span.jxButtonContent span,a.jxButtonFlyout span.jxButtonContent span{padding-right:16px;background-image:url(../images/delicious/emblems.png);background-position:right -16px;background-repeat:no-repeat;}a.jxButtonMulti span.jxButtonContent,a.jxButtonFlyout span.jxButtonContent{padding-left:0;padding-right:0;}a.jxButtonMulti span.jxButtonLabel{padding-left:0;padding-right:0;}.jxFlyout .jxChrome{background-image:url(../images/delicious/flyout_chrome.png);padding:5px 5px 7px 6px;}.jxFlyout{position:absolute;display:block;clear:both;float:none;z-index:100;margin:0;padding:0;font-size:12px;line-height:14px;}.jxFlyoutContent{position:relative;display:block;overflow:auto;margin:6px 6px 8px 7px;}.jxFlyout .jxBarRight,.jxFlyout .jxBarLeft{float:left;height:auto;width:auto;}.jxChrome{position:absolute;display:block;font-size:0;line-height:0;z-index:-1;width:100%;height:100%;top:0;left:0;}.jxChromeTL{position:absolute;overflow:hidden;left:0;top:0;width:50%;height:50%;}.jxChromeTR{position:absolute;overflow:hidden;left:50%;top:0;width:50%;height:50%;}.jxChromeBL{position:absolute;overflow:hidden;left:0;top:50%;width:50%;height:50%;}.jxChromeBR{position:absolute;overflow:hidden;left:50%;top:50%;width:50%;height:50%;}.jxChromeTL img{position:absolute;top:0;left:0;}.jxChromeTR img{position:absolute;top:0;right:0;}.jxChromeBL img{position:absolute;bottom:0;left:0;}.jxChromeBR img{position:absolute;bottom:0;right:0;}.jxColorBar{position:relative;}table.jxColorGrid{position:relative;border-collapse:collapse;empty-cells:show;clear:both;}.jxColorGrid td{border:1px solid #000;}.jxColorGrid td.emptyCell{border:0 solid #000;}.jxColorGrid td.emptyCell span{display:block;width:7px;height:7px;line-height:0;font-size:0;border:0 solid #000;padding:1px;margin:0;}.jxColorGrid a.colorSwatch{display:block;width:7px;height:7px;line-height:0;font-size:0;border:0 solid #000;margin:0;padding:1px;}.jxColorGrid a.borderWhite:hover{border:1px solid #fff;padding:0;}.jxColorGrid a.borderBlack:hover{border:1px solid #000;padding:0;}input.jxHexInput{width:55px;vertical-align:middle;}input.jxAlphaInput{width:30px;vertical-align:middle;}div.jxColorPreview{float:left;position:relative;width:20px;height:20px;border:1px solid #000;margin:2px;vertical-align:middle;background-image:url('../images/grid.png');}span.jxButtonContent span.jxButtonSwatch{display:block;float:left;width:14px;height:14px;border:1px solid #000;background-image:url('../images/grid.png');padding-right:0!important;}span.jxButtonContent span.jxButtonSwatch span{display:block;width:14px;height:14px;position:absolute;padding-right:0;}div.jxColorPreview img{position:absolute;z-index:0;}div.jxColorPreview div.jxColorSelected{width:20px;height:10px;position:absolute;z-index:1;}div.jxColorPreview div.jxColorHover{width:20px;height:10px;position:absolute;bottom:0;z-index:1;}label.jxColorLabel,label.jxAlphaLabel{width:auto;font-family:Arial,sans-serif;font-size:12px;line-height:24px;padding:2px;vertical-align:middle;}a.jxColorClose{position:absolute;top:0;right:0;width:16px;height:16px;}a.jxColorClose img{width:16px;height:16px;}div.jxCombo{position:relative;display:block;padding:0;padding-right:22px;margin:0;border:0;font-family:Arial,Helvetica,sans-serif;font-size:11px;z-index:1;line-height:24px;float:left;}.jxComboDiscloser{position:absolute;right:3px;top:3px;}.jxComboDiscloser img{width:16px;height:16px;border:0;}.jxComboInput{position:relative;display:block;float:left;line-height:14px;height:14px;padding:5px 10px;border:1px solid #f0f0f0;}div.jxComboOptions{position:absolute;height:auto;background-color:#fff;overflow:auto;border:1px solid #333;color:#000;z-index:1;font-family:Arial,Helvetica,sans-serif;font-size:11px;line-height:24px;}div.jxComboOptions ul{position:relative;display:block;margin:0;padding:0;border:none;list-style-type:none;}div.jxComboOptions li{position:relative;display:block;margin:0;padding:0;border:none;height:20px;}div.jxComboOptions a{position:relative;display:block;text-decoration:none;white-space:nowrap;line-height:20px;height:20px;color:#000;background-image:none;border:1px solid #fff;padding:0 4px;}div.jxComboOptions a:hover{background-image:url(../images/graphic/menu_bg.png);background-repeat:repeat-x;border:1px solid #C5E0FF;background-color:#CDE5FF;}div.jxComboOptions a.selected{font-weight:bold;background-color:#ffffb3;}.jxDialog .jxChrome{background-image:url(../images/delicious/dialog_chrome.png);}.jxDialog{display:block;z-index:1;}.jxDialogContentContainer{z-index:1;margin:0 11px 13px 12px;border:1px solid #b7b7b7;background-color:#f0f0f0;}.jxDialogModal{position:absolute;display:block;top:0;left:0;width:100%;height:100%;background-color:#000;opacity:.2;filter:Alpha(opacity=20);}.jxDialogContent{display:block;position:relative;overflow:auto;padding:0;z-index:1;}.jxDialogTitle{display:block;position:relative;background-image:url(../images/a_pixel.png);text-align:center;height:24px;line-height:24px;z-index:1;margin:6px 6px 0 7px;}.jxDialogMin .jxDialogTitle{margin-bottom:8px;}.jxDialogMoveable{cursor:move;}.jxDialogLabel{font-family:Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;line-height:21px;color:#000;white-space:nowrap;}.jxDialogResize{position:absolute;bottom:7px;right:6px;width:16px;height:16px;z-index:2;border:0;cursor:se-resize;background-image:url(../images/delicious/dialog_resize.png);}.jxDialogControls{position:absolute;top:3px;right:2px;height:16px;width:80px;}.jxDialogControls img{background-image:url('../images/panel_controls.png');background-repeat:no-repeat;border:0;margin:0;width:16px;height:16px;}.jxDialogClose img{background-position:0 -32px;}.jxDialogMenu img{background-position:0 -48px;}.jxDialogHelp img{background-position:0 -64px;}.jxDialogCollapse img{background-position:0 -16px;}.jxDialogMin .jxDialogCollapse img{background-position:0 0;}.jxDialogMax .jxDialogCollapse img{background-position:0 -16px;}.jxDialogLoading img{border:0;margin:0;width:16px;height:16px;visibility:hidden;position:absolute;top:1px;left:2px;}.jxDialogControls .jxButtonContainer,.jxDialogControls span.jxButtonContent,.jxDialogControls a.jxButton:hover span.jxButtonContent,.jxDialogControls a.jxButton:active span.jxButtonContent,.jxDialogControls a.jxButtonActive span.jxButtonContent,.jxDialogControls a.jxButtonActive:hover span.jxButtonContent,.jxDialogControls a.jxButtonActive:active span.jxButtonContent,.jxDialogControls .jxButtonDisabled a.jxButton span.jxButtonContent,.jxDialogControls .jxButtonDisabled a.jxButton:hover span.jxButtonContent,.jxDialogControls .jxButtonDisabled a.jxButton:active span.jxButtonContent,.jxDialogControls a.jxButton,.jxDialogControls a.jxButton:hover,.jxDialogControls a.jxButton:active,.jxDialogControls a.jxButtonActive,.jxDialogControls a.jxButtonActive:hover,.jxDialogControls a.jxButtonActive:active,.jxDialogControls .jxButtonDisabled a.jxButton,.jxDialogControls .jxButtonDisabled a.jxButton:hover,.jxDialogControls .jxButtonDisabled a.jxButton:active{padding:0;margin:0;border:none;background-color:transparent;background-image:none;}.jxDialogControls a.jxButtonMenu span.jxButtonContent,.jxDialogControls a.jxButtonFlyout span.jxButtonContent{background-image:none;}.jxDialogControls a.jxButtonMenu span.jxButtonContent span,.jxDialogControls a.jxButtonFlyout span.jxButtonContent span{padding-right:0;}.jxDialogControls .jxToolbarContainer{position:absolute;right:0;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxDialogControls ul.jxToolbar{float:right;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxDialogControls .jxBarTop,.jxDialogControls .jxBarBottom,.jxDialogControls .jxBarLeft,.jxDialogControls .jxBarRight{width:auto;height:auto;}.jxDialogControls .jxBarTop ul.jxToolbar,.jxDialogControls .jxBarBottom ul.jxToolbar,.jxDialogControls .jxBarLeft ul.jxToolbar,.jxDialogControls .jxBarRight ul.jxToolbar,.jxDialogControls .jxBarTop li.jxToolItem,.jxDialogControls .jxBarBottom li.jxToolItem,.jxDialogControls .jxBarLeft li.jxToolItem,.jxDialogControls .jxBarRight li.jxToolItem{background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxGridContainer{position:absolute;top:0;left:0;border-left:0 solid #96a7b4;border-top:0 solid #96a7b4;border-right:1px solid #96a7b4;border-bottom:1px solid #96a7b4;overflow:hidden;font-family:Arial,Verdana,sans-serif;font-size:12px;font-weight:normal;}.jxGridTable{position:relative;table-layout:fixed;border-collapse:collapse;border-style:none;width:0;}.jxGridColHeadHide{height:0;line-height:0;font-size:0;background-color:#fff;white-space:normal;}.jxGridColHeadHide p,.jxGridRowHeadHide p{font-size:0;line-height:0;height:0;margin:0;padding:0;}.jxGridRowHeadHide{width:0;white-space:normal;}.jxGridCell{border-right:1px solid #cecece;border-bottom:1px solid #cecece;overflow:hidden;padding-left:3px;padding-right:3px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.jxGridColHead{border-top:0 solid #96a7b4;border-right:1px solid #96a7b4;border-bottom:1px solid #96a7b4;border-left:0 solid #96a7b4;background-color:#ebebeb;text-align:center;font-weight:bold;color:#45525f;}.jxGridRowHead{border-top:0 solid #96a7b4;border-right:1px solid #96a7b4;border-bottom:1px solid #96a7b4;border-left:0 solid #96a7b4;background-color:#ebebeb;text-align:center;font-weight:bold;color:#45525f;}.jxGridRowAll{background-color:#fff;}.jxGridRowOdd td{border-right:1px solid #999;border-bottom:1px solid #999;}.jxGridRowEven td{border-right:1px solid #999;border-bottom:1px solid #999;}.jxGridRowSelected{background-color:#dae6f2;}.jxGridColumnSelected{background-color:#dae6f2;}.jxGridCellSelected{background-color:#dae6f2;}.jxGridRowPrelight{background-color:#f2f2f2;}.jxGridRowHeaderPrelight{background-color:#dfdfdf;}.jxGridColumnHeaderPrelight{background-color:#dfdfdf;}.jxGridRowHeaderSelected{background-color:#6d7f8e;color:#fff;}.jxGridColumnHeaderSelected{background-color:#6d7f8e;color:#fff;}.jxMenuContainer .jxChrome{background-image:url(../images/delicious/flyout_chrome.png);padding:5px 5px 7px 6px;}a.jxButtonMenu span.jxMenuItemSpan{padding-right:16px;}.jxMenuContainer{position:absolute;display:block;z-index:200;padding:0;}ul.jxMenu,ul.jxSubMenu{display:block;position:relative;list-style-type:none;margin:0;padding:6px 6px 8px 7px;}li.jxMenuItemContainer{display:block;position:relative;margin:0;padding:0;}a.jxMenuItem{display:block;position:relative;text-decoration:none;border:1px solid #fff;font-family:Arial,Helvetica,sans-serif;font-size:11px;text-decoration:none;margin:2px 2px;padding:0;color:#000;}a.jxMenuItem:hover{background-image:url(../images/graphic/menu_bg.png);border:1px solid #C5E0FF;background-color:#CDE5FF;}a.jxMenuItem:hover span.jxMenuItemContent{border:1px solid #F4F9FF;border-bottom:1px solid #E4F0FF;}span.jxMenuItemContent{display:block;position:relative;font-family:Arial,Helvetica,sans-serif;font-size:0;line-height:0;white-space:nowrap;padding:0;margin:0;border:1px solid #fff;}a.jxButtonSubMenu span.jxMenuItemContent,a.jxButtonSubMenu:hover span.jxMenuItemContent{background-image:url(../images/delicious/emblems.png);background-position:right -48px;background-repeat:no-repeat;padding-right:20px;}img.jxMenuItemIcon{position:absolute;top:0;left:0;display:inline;width:16px;height:16px;background-position:left center;background-repeat:no-repeat;}span.jxMenuItemContent span{display:block;position:relative;cursor:pointer;margin:0;padding:0 0 0 20px;font-size:16px;line-height:16px;}span.jxMenuItemContent span.jxMenuItemLabel{color:#000;font-size:12px;}a.jxMenuItemActive img.jxMenuItemIcon{background-image:url(../images/delicious/emblems.png);background-position:2px -64px;background-repeat:no-repeat;}.jxMenuItemSet a.jxMenuItemActive img.jxMenuItemIcon{background-image:url(../images/delicious/emblems.png);background-position:2px -80px;background-repeat:no-repeat;}li.jxMenuItemDisabled span.jxMenuItemLabel{color:#ccc;}li.jxMenuItemDisabled a.jxMenuItem:hover{background-color:#fff;border:1px solid #fff;}ul.jxMenu span.jxMenuSeparator{display:block;font-size:10px;line-height:10px;background-image:url(../images/toolbar_separator_v.png);background-repeat:repeat-x;background-position:left center;}.jxPanel{display:block;position:relative;}.jxPanelContentContainer{overflow:hidden;background-color:#f0f0f0;}.jxPanelContent{position:relative;display:block;overflow:auto;background-color:#fff;margin:0;padding:0;}.jxPanelTitle{display:block;position:relative;background-image:url(../images/graphic/snap_bg.png);background-repeat:repeat-x;background-position:left top;height:22px;margin:0;padding:0;}.jxPanelLabel{padding-left:25px;font-family:Arial,Helvetica,sans-serif;font-size:12px;font-weight:bold;line-height:21px;color:#000;white-space:nowrap;}.jxPanelControls{position:absolute;top:3px;right:2px;height:16px;width:80px;}.jxPanelControls img{background-image:url('../images/panel_controls.png');background-repeat:no-repeat;border:0;margin:0;width:16px;height:16px;}.jxPanelClose img{background-position:0 -32px;}.jxPanelMenu img{background-position:0 -48px;}.jxPanelHelp img{background-position:0 -64px;}.jxPanelCollapse img{background-position:0 -16px;}.jxPanelMin .jxPanelCollapse img{background-position:0 0;}.jxPanelMax .jxPanelCollapse img{background-position:0 -16px;}.jxPanelMaximize img{background-position:0 0;}.jxPanelLoading img{border:0;margin:0;width:16px;height:16px;visibility:hidden;position:absolute;top:1px;left:2px;}.jxPanelControls .jxButtonContainer,.jxPanelControls span.jxButtonContent,.jxPanelControls a.jxButton:hover span.jxButtonContent,.jxPanelControls a.jxButton:active span.jxButtonContent,.jxPanelControls a.jxButtonActive span.jxButtonContent,.jxPanelControls a.jxButtonActive:hover span.jxButtonContent,.jxPanelControls a.jxButtonActive:active span.jxButtonContent,.jxPanelControls .jxButtonDisabled a.jxButton span.jxButtonContent,.jxPanelControls .jxButtonDisabled a.jxButton:hover span.jxButtonContent,.jxPanelControls .jxButtonDisabled a.jxButton:active span.jxButtonContent,.jxPanelControls a.jxButton,.jxPanelControls a.jxButton:hover,.jxPanelControls a.jxButton:active,.jxPanelControls a.jxButtonActive,.jxPanelControls a.jxButtonActive:hover,.jxPanelControls a.jxButtonActive:active,.jxPanelControls .jxButtonDisabled a.jxButton,.jxPanelControls .jxButtonDisabled a.jxButton:hover,.jxPanelControls .jxButtonDisabled a.jxButton:active{padding:0;margin:0;border:none;background-color:transparent;background-image:none;}.jxPanelControls a.jxButtonMenu span.jxButtonContent,.jxPanelControls a.jxButtonFlyout span.jxButtonContent{background-image:none;}.jxPanelControls a.jxButtonMenu span.jxButtonContent span,.jxPanelControls a.jxButtonFlyout span.jxButtonContent span{padding-right:0;}.jxPanelControls .jxToolbarContainer{position:absolute;right:0;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxPanelControls ul.jxToolbar{float:right;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxPanelControls .jxBarTop,.jxPanelControls .jxBarBottom,.jxPanelControls .jxBarLeft,.jxPanelControls .jxBarRight{width:auto;height:auto;}.jxPanelControls .jxBarTop ul.jxToolbar,.jxPanelControls .jxBarBottom ul.jxToolbar,.jxPanelControls .jxBarLeft ul.jxToolbar,.jxPanelControls .jxBarRight ul.jxToolbar,.jxPanelControls .jxBarTop li.jxToolItem,.jxPanelControls .jxBarBottom li.jxToolItem,.jxPanelControls .jxBarLeft li.jxToolItem,.jxPanelControls .jxBarRight li.jxToolItem{border:none;background-image:none;background-color:transparent;margin:0;padding:0;border:none;}.jxSplitBarHorizontal{position:absolute;line-height:1px;width:5px;height:100%;cursor:col-resize;background-color:#f0f0f0;}.jxSplitBarVertical{position:absolute;line-height:1px;width:100%;height:5px;cursor:row-resize;background-color:#f0f0f0;}.jxSplitContainer{margin:0;}.jxSplitArea{overflow:hidden;}.jxSplitBarDrag{background-color:#eee;}.jxTabSetContainer{position:relative;display:block;width:200px;height:200px;margin:0;padding:0;border:1px solid #d8d8d8;background-color:#fff;}.jxTabSetContainer .jxToolbarContainer{z-index:auto;}.tabContent{display:none;position:relative;width:100%;height:100%;overflow:auto;}.tabContentActive{display:block;}.jxTabBoxTop,.jxTabBoxBottom,.jxTabBoxLeft,.jxTabBoxRight{overflow:visible;}.jxTabBoxTop .jxBarTop,.jxTabBoxBottom .jxBarBottom,.jxTabBoxLeft .jxBarLeft,.jxTabBoxRight .jxBarRight{position:absolute;}li.jxTabItem{margin:0;padding:0;}.jxBarTop li.jxTabItem,.jxBarBottom li.jxTabItem{border:none;}.jxBarLeft li.jxTabItem,.jxBarRight li.jxTabItem{border:none;}a.jxTab{display:block;position:relative;margin:0;padding:0;border:none;background-repeat:no-repeat;text-decoration:none;color:#000;}a.jxTab:hover,a.jxTab:active,a.jxTabActive,a.jxTabActive:hover,a.jxTabActive:active,.jxDisabled a.jxButton:hover,.jxDisabled a.jxButton:active{border:none;}span.jxTabContent{display:block;font-size:0;line-height:0;margin:0;padding:0;background-repeat:no-repeat;}img.jxTabIcon{position:relative;width:16px;height:16px;background-position:center center;background-repeat:no-repeat;}span.jxTabLabel{display:block;position:relative;cursor:pointer;margin:0;padding:0;color:#000;font-family:Arial,Helvetica,sans-serif;font-size:11px;line-height:16px;}.jxTabBoxTop{margin-top:27px;}.jxTabBoxTop .jxBarTop{top:-27px;}.jxBarTop a.jxTab{float:left;padding-left:6px;background-image:url(../images/graphic/tab_top_bg.png);background-position:left 2px;border-bottom:1px solid #999;}.jxBarTop span.jxTabContent{float:left;padding:6px 6px 6px 0;background-image:url(../images/graphic/tab_top_bg.png);background-position:right 2px;}.jxBarTop img.jxTabIcon{float:left;}.jxBarTop span.jxTabLabel{float:left;padding:0 4px 0 4px;}.jxBarTop a.jxTab:hover{background-position:left top;}.jxBarTop a.jxTab:hover span.jxTabContent{background-position:right top;}.jxBarTop a.jxTabActive{background-position:left -56px;border-bottom:1px solid #fff;}.jxBarTop a.jxTabActive span.jxTabContent{background-position:right -56px;}.jxTabBoxBottom{margin-bottom:27px;}.jxTabBoxBottom .jxBarBottom{bottom:-27px;}.jxBarBottom li.jxTabItem{float:left;}.jxBarBottom a.jxTab{float:left;padding-left:6px;background-image:url(../images/graphic/tab_bottom_bg.png);background-position:left -2px;border-top:1px solid #999;}.jxBarBottom span.jxTabContent{float:left;padding:6px 6px 6px 0;background-image:url(../images/graphic/tab_bottom_bg.png);background-position:right -2px;}.jxBarBottom img.jxTabIcon{float:left;}.jxBarBottom span.jxTabLabel{float:left;padding:0 4px 0 4px;}.jxBarBottom a.jxTab:hover{background-position:left top;}.jxBarBottom a.jxTab:hover span.jxTabContent{background-position:right top;}.jxBarBottom a.jxTabActive{background-position:left -56px;border-top:1px solid #fff;}.jxBarBottom a.jxTabActive span.jxTabContent{background-position:right -56px;}.jxTabBoxLeft{margin-left:27px;}.jxTabBoxLeft .jxBarLeft{left:-27px;}.jxBarLeft a.jxTab{padding-top:6px;background-image:url(../images/graphic/tab_left_bg.png);background-position:2px top;border-right:1px solid #999;}.jxBarLeft span.jxTabContent{padding:0 6px 6px 6px;background-image:url(../images/graphic/tab_left_bg.png);background-position:2px bottom;}.jxBarLeft a.jxTab:hover{background-position:left top;}.jxBarLeft a.jxTab:hover span.jxTabContent{background-position:left bottom;}.jxBarLeft a.jxTabActive{background-position:-56px top;border-right:1px solid #fff;}.jxBarLeft a.jxTabActive span.jxTabContent{background-position:-56px bottom;}.jxTabBoxRight{margin-right:27px;}.jxTabBoxRight .jxBarRight{right:-27px;}.jxBarRight a.jxTab{padding-top:6px;background-image:url(../images/graphic/tab_right_bg.png);background-position:-2px top;border-left:1px solid #999;}.jxBarRight span.jxTabContent{padding:0 6px 6px 6px;background-image:url(../images/graphic/tab_right_bg.png);background-position:-2px bottom;}.jxBarRight a.jxTab:hover{background-position:left top;}.jxBarRight a.jxTab:hover span.jxTabContent{background-position:left bottom;}.jxBarRight a.jxTabActive{background-position:-56px top;border-left:1px solid #fff;}.jxBarRight a.jxTabActive span.jxTabContent{background-position:-56px bottom;}.jxToolbarContainer{display:block;position:relative;z-index:1;margin:0;padding:0;border:0;background-color:#f0f0f0;}.jxBarTop,.jxBarBottom{width:100%;height:auto;background-repeat:repeat-x;background-position:bottom;}.jxBarLeft,.jxBarRight{width:auto;height:100%;background-repeat:repeat-y;background-position:right;}.toolbarLabel{display:block;position:relative;float:left;margin:0;padding:0;font-family:Arial,Hevetica,sans-serif;font-size:11px;line-height:24px;color:#000;}ul.jxToolbar{display:block;position:relative;float:left;list-style-type:none;margin:0;padding:0;}.jxBarTop ul.jxToolbar,.jxBarBottom ul.jxToolbar,.jxBarLeft ul.jxToolbar,.jxBarRight ul.jxToolbar{border:none;}li.jxToolItem{display:block;position:relative;float:left;font-size:0;line-height:0;padding:0;margin:0;}.jxBarTop li.jxToolItem,.jxBarBottom li.jxToolItem,.jxBarLeft li.jxToolItem,.jxBarRight li.jxToolItem{border:none;}li.jxToolItem .separator{display:block;position:relative;float:left;font-size:0;line-height:0;width:8px;height:20px;border:0;margin:0;padding:4px;background-repeat:no-repeat;background-position:center center;}.jxBarTop li.jxToolItem span.separator,.jxBarBottom li.jxToolItem span.separator{background-image:url(../images/toolbar_separator_h.png);}.jxBarLeft li.jxToolItem span.separator,.jxBarRight li.jxToolItem span.separator{background-image:url(../images/toolbar_separator_v.png);}.jxBarLeft label.toolbarLabel,.jxBarLeft ul.jxToolbar,.jxBarLeft li.jxToolItem,.jxBarRight label.toolbarLabel,.jxBarRight ul.jxToolbar,.jxBarRight li.jxToolItem{clear:both;}.verticalToolbar{width:auto;}.verticalToolbar label.toolbarLabel,.verticalToolbar ul.jxToolbar,.verticalToolbar li.jxToolItem{clear:both;}.jxTree,.jxTreeRoot{position:relative;display:block;list-style:none;margin:0;padding:0;}.jxTreeNest{list-style:none;margin:0;padding:0;background-repeat:repeat-y;background-position:left top;}.jxTree li,.jxTreeRoot li{position:relative;display:block;margin:0;padding:0;background-repeat:no-repeat;background-position:left top;white-space:nowrap;width:100%;font-size:0;line-height:0;}.jxTree li{margin-left:16px;}.jxTree li.jxDisabled,.jxTreeRoot li.jxDisabled{opacity:.4;-moz-opacity:.4;filter:Alpha(opacity=40);}.jxTree a,.jxTreeRoot a{position:relative;display:block;margin:0 0 0 14px;padding:0 0 0 20px;z-index:0;font-family:Arial,Helvetica,sans-serif;font-size:11px;color:#000;text-decoration:none;line-height:20px;height:20px;}.jxTree a:hover,.jxTreeRoot a:hover{background-image:url(../images/graphic/menu_bg.png);background-color:#CDE5FF;}.jxTreeNest{background-image:url(../images/tree_vert_line.png);}.jxTreeImage,.jxTreeIcon{position:absolute;display:inline;left:0;top:0;width:16px;height:20px;z-index:1;background-image:url(../images/delicious/tree.png);background-repeat:no-repeat;border:0;margin:0;}.jxTreeIcon{left:2px;}.jxTreeBranchOpen .jxTreeIcon,.jxTreeBranchLastOpen .jxTreeIcon{background-position:left -40px;}.jxTreeBranchOpen .jxTreeImage{background-position:left -100px;}.jxTreeBranchLastOpen .jxTreeImage{background-position:left -160px;}.jxTreeBranchClosed .jxTreeIcon,.jxTreeBranchLastClosed .jxTreeIcon{background-position:left -20px;}.jxTreeBranchClosed .jxTreeImage{background-position:left -80px;}.jxTreeBranchLastClosed .jxTreeImage{background-position:left -140px;}.jxTreeItem .jxTreeIcon,.jxTreeItemLast .jxTreeIcon{background-position:left 0;}.jxTreeItem .jxTreeImage{background-position:left -60px;}.jxTreeItemLast .jxTreeImage{background-position:left -120px;}.jxTreeItemSelected{background-color:#AFD4FA;font-weight:bold;}.jxTreeItem a,.jxTreeItem img,.jxTreeItem input,.jxTreeItemLast a,.jxTreeItemLast img,.jxTreeItemLast input,.jxTreeBranch a,.jxTreeBranch img,.jxTreeBranch input,.jxTreeBranchLast a,.jxTreeBranchLast img,.jxTreeBranchLast input{vertical-align:middle;}
\ No newline at end of file
Modified: sandbox/jx2/lib/ApplicationDefinition.js
===================================================================
--- sandbox/jx2/lib/ApplicationDefinition.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/lib/ApplicationDefinition.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -703,7 +703,7 @@
var container;
if (this.type == 'Toolbar' || this.type == 'Statusbar') {
if ($(this.name)) {
- container = new Jx.Toolbar(this.name, this.position);
+ container = new Jx.Toolbar({parent: this.name, position: this.position});
$(this.name).container = container;
}
this.createWidgets(widgetSet, container);
@@ -860,15 +860,15 @@
this.uniqueId[0]++;
if (container instanceof Jx.Toolbar) {
/* create a button for the widget */
- var tbItem = new Jx.ToolbarItem();
+ var tbItem = new Jx.Toolbar.Item();
tbItem.domObj.id = name;
container.add(tbItem);
widgetTag.create(widgetSet, name);
} else if (container instanceof Jx.Splitter) {
var widget = widgetTag.create(widgetSet, idx);
} else if (container instanceof Jx.Menu ||
- container instanceof Jx.ContextMenu ||
- container instanceof Jx.SubMenu) {
+ container instanceof Jx.Menu.Context ||
+ container instanceof Jx.Menu.SubMenu) {
var widget = widgetTag.create(widgetSet, '');
widget.id = name;
if (widget.oMenu) { //for widgets that extend MenuBase
@@ -876,11 +876,11 @@
widget.oMenu.domObj.widget = widget;
container.add(widget.oMenu);
} else {
- var action = new Jx.Action(OpenLayers.Function.bind(widget.activateTool, widget));
- var opt = {};
- opt.label = widgetTag.label;
- opt.image = widgetTag.imageUrl;
- var menuItem = new Jx.MenuItem(action, opt);
+ var menuItem = new Jx.Menu.Item({
+ label: widgetTag.label,
+ image: widgetTag.imageUrl,
+ onClick: OpenLayers.Function.bind(widget.activateTool, widget)
+ });
menuItem.domObj.id = name;
menuItem.domObj.widget = widget;
container.add(menuItem);
@@ -894,17 +894,18 @@
case 'Flyout':
/* create a menu */
var menu;
- var opt = {};
- opt.label = this.flyout.label;
- opt.tooltip = this.flyout.tooltip;
- opt.image = this.flyout.imageUrl;
- opt.imageClass = this.flyout.imageClass;
+ var opt = {
+ label: this.flyout.label,
+ tooltip: this.flyout.tooltip,
+ image: this.flyout.imageUrl,
+ imageClass: this.flyout.imageClass
+ };
if (container instanceof Jx.Toolbar) {
menu = new Jx.Menu(opt);
} else if (container instanceof Jx.Menu ||
- container instanceof Jx.ContextMenu ||
- container instanceof Jx.SubMenu) {
- menu = new Jx.SubMenu(opt);
+ container instanceof Jx.Menu.Context ||
+ container instanceof Jx.Menu.SubMenu) {
+ menu = new Jx.Menu.SubMenu(opt);
}
container.add(menu);
this.flyout.create(widgetSet, menu);
@@ -912,11 +913,11 @@
break;
case 'Separator':
if (container instanceof Jx.Toolbar) {
- container.add(new Jx.ToolbarSeparator());
+ container.add(new Jx.Toolbar.Separator());
} else if (container instanceof( Jx.Menu) ||
- container instanceof(Jx.SubMenu) ||
- container instanceof(Jx.ContextMenu)) {
- container.add(new Jx.MenuSeparator());
+ container instanceof(Jx.Menu.SubMenu) ||
+ container instanceof(Jx.Menu.Context)) {
+ container.add(new Jx.Menu.Separator());
}
break;
}
Modified: sandbox/jx2/lib/ButtonTool.js
===================================================================
--- sandbox/jx2/lib/ButtonTool.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/lib/ButtonTool.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -31,21 +31,19 @@
Fusion.Tool.Button = OpenLayers.Class({
bActive: null,
- sActiveClass: 'jxButtonActive',
- sDisabledClass: 'jxButtonDisabled',
initialize : function(domObj, widgetTag) {
//console.log('Fusion.Tool.Button.initialize');
var json = widgetTag.extension;
-
- this.buttonAction = new Jx.Action(OpenLayers.Function.bind(this.buttonClicked, this));
if (domObj) {
- var options = {};
- options.imgPath = widgetTag.imageUrl;
- options.imgClass = widgetTag.imageClass;
- options.tooltip = widgetTag.tooltip;
- options.label = widgetTag.label;
- this._oButton = new Jx.Button(this.buttonAction, options);
+ var options = {
+ image: widgetTag.imageUrl,
+ imageClass: widgetTag.imageClass,
+ tooltip: widgetTag.tooltip,
+ label: widgetTag.label,
+ onClick: OpenLayers.Function.bind(this.buttonClicked, this)
+ };
+ this._oButton = new Jx.Button(options);
domObj.appendChild(this._oButton.domObj);
}
this.bActive = false;
@@ -62,22 +60,26 @@
observeEvent : function(sEvent, fnCB) {
if (this._oButton) {
- Event.observe(this._oButton.domObj, sEvent, fnCB);
+ OpenLayers.Event.observe(this._oButton.domObj, sEvent, fnCB);
}
},
stopObserveEvent : function(sEvent, fnCB) {
if (this._oButton) {
- Event.stopObserving(this._oButton.domObj, sEvent, fnCB);
+ OpenLayers.Event.stopObserving(this._oButton.domObj, sEvent, fnCB);
}
},
enableTool : function() {
- this.buttonAction.setEnabled(true);
+ if (this._oButton) {
+ this._oButton.setEnabled(true);
+ }
},
disableTool : function() {
- this.buttonAction.setEnabled(false);
+ if (this._oButton) {
+ this._oButton.setEnabled(false);
+ }
},
activateTool : function() {
@@ -89,9 +91,6 @@
if (this._sImageURL != null && this._sImageURL.length > 0) {
this._oButton.setImage(this._sImageURL);
}
- if (this.sActiveClass != '') {
- Element.addClassName(this._oButton.domA, this.sActiveClass);
- }
},
deactivateTool : function() {
@@ -100,9 +99,6 @@
if (!this._oButton) {
return;
}
- if (this.sActiveClass != '') {
- Element.removeClassName(this._oButton.domA, this.sActiveClass);
- }
},
clickCB : function(e) { this.activateTool(); },
Modified: sandbox/jx2/lib/Map.js
===================================================================
--- sandbox/jx2/lib/Map.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/lib/Map.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -172,7 +172,7 @@
setMenu: function() {
if (this.widgetTag.extension.MenuContainer) {
- var contextMenu = new Jx.ContextMenu();
+ var contextMenu = new Jx.Menu.Context();
var container = this.widgetSet.getContainerByName(this.widgetTag.extension.MenuContainer[0]);
if (container) {
container.createWidgets(this.widgetSet, contextMenu);
@@ -910,7 +910,7 @@
onContextMenu: function(e) {
//console.log('oncontextmenu');
if (this.oContextMenu && !this.bSupressContextMenu && this.isLoaded()) {
- this.oContextMenu.show(e);
+ this.oContextMenu.show(new Event(e));
this.contextMenuPosition = this.getEventPosition(e);
OpenLayers.Event.stop(e);
}
Modified: sandbox/jx2/lib/MenuBase.js
===================================================================
--- sandbox/jx2/lib/MenuBase.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/lib/MenuBase.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,60 +1,61 @@
-/**
- * Fusion.Tool.MenuBase
- *
- * $Id$
- *
- * Copyright (c) 2007, DM Solutions Group Inc.
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
- /****************************************************************************
- * Class: Fusion.Tool.MenuBase
- *
- * generic base class for implementing widgets that incorporate a menu
- * **********************************************************************/
-
-Fusion.Tool.MenuBase = OpenLayers.Class({
- /**
- * constructor
- */
- initialize : function() {
- //console.log('Fusion.Tool.MenuBase.initialize');
- var options = {};
- options.imgPath = this.widgetTag.imageUrl;
- options.imgClass = this.widgetTag.imageClass;
- options.tooltip = this.widgetTag.tooltip;
- options.label = this.widgetTag.label;
-
- if ( $(this.widgetTag.name) ) {
- this.oMenu = new Jx.Menu(options);
- $(this.widgetTag.name).appendChild(this.oMenu.domObj);
- } else {
- this.oMenu = new Jx.SubMenu(options);
- }
- },
-
- enable: function() {
- //TODO: figure out how to enable and disable menu widgets
- Fusion.Widget.prototype.enable.apply(this,[]);
- },
-
- disable: function() {
- Fusion.Widget.prototype.disable.apply(this,[]);
- }
-});
+/**
+ * Fusion.Tool.MenuBase
+ *
+ * $Id$
+ *
+ * Copyright (c) 2007, DM Solutions Group Inc.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+ /****************************************************************************
+ * Class: Fusion.Tool.MenuBase
+ *
+ * generic base class for implementing widgets that incorporate a menu
+ * **********************************************************************/
+
+Fusion.Tool.MenuBase = OpenLayers.Class({
+ /**
+ * constructor
+ */
+ initialize : function() {
+ //console.log('Fusion.Tool.MenuBase.initialize');
+ var options = {
+ image: this.widgetTag.imageUrl,
+ imageClass: this.widgetTag.imageClass,
+ tooltip: this.widgetTag.tooltip,
+ label: this.widgetTag.label
+ };
+
+ if ( $(this.widgetTag.name) ) {
+ this.oMenu = new Jx.Menu(options);
+ $(this.widgetTag.name).appendChild(this.oMenu.domObj);
+ } else {
+ this.oMenu = new Jx.Menu.SubMenu(options);
+ }
+ },
+
+ enable: function() {
+ //TODO: figure out how to enable and disable menu widgets
+ Fusion.Widget.prototype.enable.apply(this,[]);
+ },
+
+ disable: function() {
+ Fusion.Widget.prototype.disable.apply(this,[]);
+ }
+});
Modified: sandbox/jx2/lib/fusion.js
===================================================================
--- sandbox/jx2/lib/fusion.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/lib/fusion.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1046,9 +1046,10 @@
/* actual bootstrap execution code follows */
Fusion._singleFile = singleFile;
- var host = Fusion._getScriptLocation();
+ var host = Fusion._getScriptLocation();
+ Jx.aPixel = document.createElement('img');
+ Jx.aPixel.src = '../jx/images/a_pixel.png';
Jx.baseURL = host + 'jx/';
- Jx.COMBINED_CSS = true;
//determine the language to use and add resource bundles to be loaded to the core scripts
var locale = navigator.language ?
@@ -1064,12 +1065,12 @@
if (!Fusion._singleFile) {
if (useCompressed) {
var coreScripts = ['lib/OpenLayers/OpenLayers.js',
- 'jx/lib/jx_compressed.js',
+ 'jx/lib/jxlib.js',
'lib/fusion-compressed.js',
'lib/excanvas/excanvas-compressed.js'];
} else {
var coreScripts = ['lib/OpenLayers/OpenLayers.js',
- 'jx/lib/jx_combined.js',
+ 'jx/lib/jxlib.uncompressed.js',
'lib/excanvas/excanvas-compressed.js',
'lib/EventMgr.js',
'lib/Error.js',
Modified: sandbox/jx2/templates/mapguide/standard/index.html
===================================================================
--- sandbox/jx2/templates/mapguide/standard/index.html 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/templates/mapguide/standard/index.html 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,157 +1,157 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<title>Sample Fusion Application</title>
-<!-- change the source of the following tag to point to your fusion installation -->
-<script type="text/javascript" src="../../../lib/fusion.js"></script>
-
-<style type="text/css">
- @import url(../../../jx/css/jxskin-border.css);
-
- .jxSplitterBar {
- width: 2px;
- background-color: #999;
- cursor: 'col-resize';
- }
-
- body {
- overflow: hidden;
- }
-
- #Toolbar .jxToolbar {
- /*width: 100%;*/
- }
-
- #TaskPane .jxPanelContent {
- border-left: 1px solid #fff;
- }
-
- #Map {
- position: relative;
- border-right: 1px solid #999;
- border-bottom: 1px solid #999;
- }
-
- #Statusbar {
- overflow: hidden;
- background-color: #d9d9d9;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 11px;
- }
-
- #Statusbar .jxSplitterBar {
- width: 1px;
- border-left: 1px solid #999;
- border-right: 1px solid #fff;
- cursor: 'col-resize';
- }
-
- #Statusbar .spanCursorPosition,
- #Statusbar .inputEditableScale,
- #Statusbar .spanViewSize,
- #Statusbar .spanSelectionInfo {
- background-color: #fff;
- padding: 2px 4px;
- line-height: 18px;
- }
-
- #Scalebar {
- position: absolute;
- bottom: 5px;
- left: 5px;
- z-index: 1001;
- }
-
-
- li.jxToolItem.activityIndicator {
- float: right;
- padding: 6px 3px;
- }
-
-</style>
-<!--[if IE]>
-<style>
-</style>
-<![endif]-->
-<script type="text/javascript">
-window.onload = function() {
- /* make 'thePage' just fill the browser window and resize automagically
- the user resizes the browser */
- new Jx.Layout('thePage');
- /* the height of toolbars. For jxskin-border,
- * its 28 and for jxskin-graphic its 30 */
- var h = 28;
- new Jx.Layout('Main', {bottom: 22, right: 250});
- new Jx.Layout('Statusbar', {height: 22, top: null});
- new Jx.Layout('TaskPane', {bottom: 22, width: 250, left: null});
- new Jx.Layout('Toolbar', {height: h, bottom: null});
- new Jx.Layout('Splitter', {top: h});
-
- var splitter = new Jx.Splitter('Splitter', {elements: [$('PanelPane'), $('Map')], containerOptions: [{width: 200}, {}]});
-
- //new Jx.Splitter('Statusbar', {elements: [$('CursorPosition'), $('SelectionInfo'), $('EditableScale'), $('ViewSize'), $('PoweredBy')], containerOptions: [{}, {}, {}, {}, {width: 143, maxWidth: 143, minWidth: 143}]});
-
- var p1 = new Jx.Panel({label: 'Legend'});
- p1.content.id = 'Legend';
- var p2 = new Jx.Panel({label: 'Selection'});
- p2.content.id = 'SelectionPanel';
- var p3 = new Jx.Panel({label: 'Overview Map'});
- p3.content.id = 'OverviewMap';
- var pm = new Jx.PanelManager('PanelPane', [p1, p2, p3]);
-
- $('thePage').resize();
- $('thePage').style.visibility = 'visible';
-
- Fusion.registerForEvent(Fusion.Event.FUSION_INITIALIZED, fusionInitialized);
- Fusion.registerForEvent(Fusion.Event.FUSION_ERROR, fusionError);
- Fusion.initialize();
-}
-
-function fusionError(eventId, error) {
- console.log('Fusion Error: \n' + error.toString());
-}
-
-function fusionInitialized() {
- $('thePage').jxLayout.resize({forceResize:true});
- $('Toolbar').jxLayout.resize({forceResize:true});
- //var map = Fusion.getWidgetById('Map');
- //var l = new Jx.Layout($('Toolbar').childNodes[0]);
- //l.resize();
-}
-
-</script>
-</head>
-
-<body>
-
-<div id="thePage" style="visibility: hidden">
-
- <div id="Main">
- <div id="Toolbar"></div>
- <div id="Splitter">
- <div id="PanelPane"></div>
- <div id="Map">
- <div id="Navigator"></div>
- <div id="Scalebar"></div>
- </div>
- </div>
- </div>
-
- <div id="TaskPane"></div>
- <div id="Statusbar"></div>
- <div id="MapTip"></div>
- <div id="PoweredBy" class="statusBarItem">
- <a href="http://mapserver.gis.umn.edu.org/" target="_blank">
- <img src="images/PoweredBy_MapServer.gif" width="137" height="18" border="0">
- </a>
- </div>
-
-</div>
-
-<div id="BusyIndicator" style="visibility: hidden;">
- <img src="images/icon_loading.gif" width="30" height="14">
-</div>
-
-</body>
-</html>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Sample Fusion Application</title>
+<!-- change the source of the following tag to point to your fusion installation -->
+<script type="text/javascript" src="../../../lib/fusion.js"></script>
+
+<style type="text/css">
+ @import url(../../../jx/css/jxskin-border.css);
+
+ .jxSplitterBar {
+ width: 2px;
+ background-color: #999;
+ cursor: 'col-resize';
+ }
+
+ body {
+ overflow: hidden;
+ }
+
+ #Toolbar .jxToolbar {
+ /*width: 100%;*/
+ }
+
+ #TaskPane .jxPanelContent {
+ border-left: 1px solid #fff;
+ }
+
+ #Map {
+ position: relative;
+ border-right: 1px solid #999;
+ border-bottom: 1px solid #999;
+ }
+
+ #Statusbar {
+ overflow: hidden;
+ background-color: #d9d9d9;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ }
+
+ #Statusbar .jxSplitterBar {
+ width: 1px;
+ border-left: 1px solid #999;
+ border-right: 1px solid #fff;
+ cursor: 'col-resize';
+ }
+
+ #Statusbar .spanCursorPosition,
+ #Statusbar .inputEditableScale,
+ #Statusbar .spanViewSize,
+ #Statusbar .spanSelectionInfo {
+ background-color: #fff;
+ padding: 2px 4px;
+ line-height: 18px;
+ }
+
+ #Scalebar {
+ position: absolute;
+ bottom: 5px;
+ left: 5px;
+ z-index: 1001;
+ }
+
+
+ li.jxToolItem.activityIndicator {
+ float: right;
+ padding: 6px 3px;
+ }
+
+</style>
+<!--[if IE]>
+<style>
+</style>
+<![endif]-->
+<script type="text/javascript">
+window.onload = function() {
+ /* make 'thePage' just fill the browser window and resize automagically
+ the user resizes the browser */
+ new Jx.Layout('thePage');
+ /* the height of toolbars. For jxskin-border,
+ * its 28 and for jxskin-graphic its 30 */
+ var h = 28;
+ new Jx.Layout('Main', {bottom: 22, right: 250});
+ new Jx.Layout('Statusbar', {height: 22, top: null});
+ new Jx.Layout('TaskPane', {bottom: 22, width: 250, left: null});
+ new Jx.Layout('Toolbar', {height: h, bottom: null});
+ new Jx.Layout('Splitter', {top: h});
+
+ var splitter = new Jx.Splitter('Splitter', {elements: [$('PanelPane'), $('Map')], containerOptions: [{width: 200}, {}]});
+
+ //new Jx.Splitter('Statusbar', {elements: [$('CursorPosition'), $('SelectionInfo'), $('EditableScale'), $('ViewSize'), $('PoweredBy')], containerOptions: [{}, {}, {}, {}, {width: 143, maxWidth: 143, minWidth: 143}]});
+
+ var p1 = new Jx.Panel({label: 'Legend'});
+ p1.content.id = 'Legend';
+ var p2 = new Jx.Panel({label: 'Selection'});
+ p2.content.id = 'SelectionPanel';
+ var p3 = new Jx.Panel({label: 'Overview Map'});
+ p3.content.id = 'OverviewMap';
+ var pm = new Jx.PanelSet('PanelPane', [p1, p2, p3]);
+
+ $('thePage').resize();
+ $('thePage').style.visibility = 'visible';
+
+ Fusion.registerForEvent(Fusion.Event.FUSION_INITIALIZED, fusionInitialized);
+ Fusion.registerForEvent(Fusion.Event.FUSION_ERROR, fusionError);
+ Fusion.initialize();
+}
+
+function fusionError(eventId, error) {
+ console.log('Fusion Error: \n' + error.toString());
+}
+
+function fusionInitialized() {
+ $('thePage').jxLayout.resize({forceResize:true});
+ $('Toolbar').jxLayout.resize({forceResize:true});
+ //var map = Fusion.getWidgetById('Map');
+ //var l = new Jx.Layout($('Toolbar').childNodes[0]);
+ //l.resize();
+}
+
+</script>
+</head>
+
+<body>
+
+<div id="thePage" style="visibility: hidden">
+
+ <div id="Main">
+ <div id="Toolbar"></div>
+ <div id="Splitter">
+ <div id="PanelPane"></div>
+ <div id="Map">
+ <div id="Navigator"></div>
+ <div id="Scalebar"></div>
+ </div>
+ </div>
+ </div>
+
+ <div id="TaskPane"></div>
+ <div id="Statusbar"></div>
+ <div id="MapTip"></div>
+ <div id="PoweredBy" class="statusBarItem">
+ <a href="http://mapserver.gis.umn.edu.org/" target="_blank">
+ <img src="images/PoweredBy_MapServer.gif" width="137" height="18" border="0">
+ </a>
+ </div>
+
+</div>
+
+<div id="BusyIndicator" style="visibility: hidden;">
+ <img src="images/icon_loading.gif" width="30" height="14">
+</div>
+
+</body>
+</html>
Modified: sandbox/jx2/templates/mapserver/standard/ApplicationDefinition.xml
===================================================================
--- sandbox/jx2/templates/mapserver/standard/ApplicationDefinition.xml 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/templates/mapserver/standard/ApplicationDefinition.xml 2008-08-28 12:29:20 UTC (rev 1482)
@@ -923,11 +923,11 @@
<!-- LEGEND -->
- <Widget xsi:type="WidgetType">
+ <!-- <Widget xsi:type="WidgetType">
<Name>Legend</Name>
<Type>Legend</Type>
<StatusItem/>
- </Widget>
+ </Widget> -->
<!-- SELECTION -->
Modified: sandbox/jx2/templates/mapserver/standard/index.html
===================================================================
--- sandbox/jx2/templates/mapserver/standard/index.html 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/templates/mapserver/standard/index.html 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,144 +1,138 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
- "http://www.w3.org/TR/html4/strict.dtd">
-<html>
-<head>
-<title>Sample Fusion Application</title>
-<!-- change the source of the following tag to point to your fusion installation -->
-<script type="text/javascript" src="../../../lib/fusion.js"></script>
-
-<style type="text/css">
- @import url(../../../jx/css/jxskin-border.css);
-
- .jxSplitterBar {
- width: 2px;
- background-color: #999;
- cursor: 'col-resize';
- }
-
- #Toolbar .jxToolbar {
- /*width: 100%;*/
- }
-
- #TaskPane .jxPanelContent {
- border-left: 1px solid #fff;
- }
-
- #Map {
- position: relative;
- border-right: 1px solid #999;
- border-bottom: 1px solid #999;
- }
-
- #Statusbar {
- overflow: hidden;
- background-color: #d9d9d9;
- font-family: Arial, Helvetica, sans-serif;
- font-size: 11px;
- }
-
- #Statusbar .jxSplitterBar {
- width: 1px;
- border-left: 1px solid #999;
- border-right: 1px solid #fff;
- cursor: 'col-resize';
- }
-
- #Statusbar .spanCursorPosition,
- #Statusbar .inputEditableScale,
- #Statusbar .spanViewSize,
- #Statusbar .spanSelectionInfo {
- background-color: #fff;
- padding: 2px 4px;
- line-height: 18px;
- }
-
-
- li.jxToolItem.activityIndicator {
- float: right;
- padding: 6px 3px;
- }
-
-</style>
-<!--[if IE]>
-<style>
-</style>
-<![endif]-->
-<script type="text/javascript">
-window.onload = function() {
- /* make 'thePage' just fill the browser window and resize automagically
- the user resizes the browser */
- new Jx.Layout('thePage');
- /* the height of toolbars. For jxskin-border,
- * its 28 and for jxskin-graphic its 30 */
- var h = 28;
- new Jx.Layout('Main', {bottom: 22, right: 250});
- new Jx.Layout('Statusbar', {height: 22, top: null});
- new Jx.Layout('TaskPane', {bottom: 22, width: 250, left: null});
- new Jx.Layout('Toolbar', {height: h, bottom: null});
- new Jx.Layout('Splitter', {top: h});
-
- var splitter = new Jx.Splitter('Splitter', {elements: [$('PanelPane'), $('Map')], containerOptions: [{width: 200}, {}]});
-
- //new Jx.Splitter('Statusbar', {elements: [$('CursorPosition'), $('SelectionInfo'), $('EditableScale'), $('ViewSize'), $('PoweredBy')], containerOptions: [{}, {}, {}, {}, {width: 143, maxWidth: 143, minWidth: 143}]});
-
- var p1 = new Jx.Panel({label: 'Legend'});
- p1.content.id = 'Legend';
- var p2 = new Jx.Panel({label: 'Selection'});
- p2.content.id = 'SelectionPanel';
- var p3 = new Jx.Panel({label: 'Overview Map'});
- p3.content.id = 'OverviewMap';
- var pm = new Jx.PanelManager('PanelPane', [p1, p2, p3]);
-
- $('thePage').resize();
- $('thePage').style.visibility = 'visible';
-
- Fusion.registerForEvent(Fusion.Event.FUSION_INITIALIZED, fusionInitialized);
- Fusion.registerForEvent(Fusion.Event.FUSION_ERROR, fusionError);
- Fusion.initialize();
-}
-
-function fusionError(eventId, error) {
- console.log('Fusion Error: \n' + error.toString());
-}
-
-function fusionInitialized() {
- $('thePage').jxLayout.resize({forceResize:true});
- $('Toolbar').jxLayout.resize({forceResize:true});
- //var map = Fusion.getWidgetById('Map');
- //var l = new Jx.Layout($('Toolbar').childNodes[0]);
- //l.resize();
-}
-
-</script>
-</head>
-
-<body>
-
-<div id="thePage" style="visibility: hidden">
-
- <div id="Main">
- <div id="Toolbar"></div>
- <div id="Splitter">
- <div id="PanelPane"></div>
- <div id="Map">
- <div id="Navigator"></div>
- </div>
- </div>
- </div>
-
- <div id="TaskPane"></div>
- <div id="Statusbar"></div>
- <div id="PoweredBy" class="statusBarItem">
- <a href="http://mapserver.gis.umn.edu.org/" target="_blank">
- <img src="images/PoweredBy_MapServer.gif" width="137" height="18" border="0">
- </a>
- </div>
-
-</div>
-
-<div id="BusyIndicator" style="visibility: hidden;">
- <img src="images/icon_loading.gif" width="30" height="14">
-</div>
-
-</body>
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+ "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+<title>Sample Fusion Application</title>
+<!-- change the source of the following tag to point to your fusion installation -->
+<script type="text/javascript" src="../../../lib/fusion.js"></script>
+
+<style type="text/css">
+ @import url(../../../jx/lib/jxskin_delicious.css);
+
+ #Toolbar .jxToolbar {
+ /*width: 100%;*/
+ }
+
+ #TaskPane .jxPanelContent {
+ border-left: 1px solid #fff;
+ }
+
+ #Map {
+ position: relative;
+ border-right: 1px solid #999;
+ border-bottom: 1px solid #999;
+ }
+
+ #Statusbar {
+ overflow: hidden;
+ background-color: #d9d9d9;
+ font-family: Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ }
+
+ #Statusbar .jxSplitterBar {
+ width: 1px;
+ border-left: 1px solid #999;
+ border-right: 1px solid #fff;
+ cursor: 'col-resize';
+ }
+
+ #Statusbar .spanCursorPosition,
+ #Statusbar .inputEditableScale,
+ #Statusbar .spanViewSize,
+ #Statusbar .spanSelectionInfo {
+ background-color: #fff;
+ padding: 2px 4px;
+ line-height: 18px;
+ }
+
+
+ li.jxToolItem.activityIndicator {
+ float: right;
+ padding: 6px 3px;
+ }
+
+</style>
+<!--[if IE]>
+<style>
+</style>
+<![endif]-->
+<script type="text/javascript">
+window.onload = function() {
+ /* make 'thePage' just fill the browser window and resize automagically
+ the user resizes the browser */
+ new Jx.Layout('thePage');
+ /* the height of toolbars. For jxskin-border,
+ * its 28 and for jxskin-graphic its 30 */
+ var h = 28;
+ new Jx.Layout('Main', {bottom: 22, right: 250});
+ new Jx.Layout('Statusbar', {height: 22, top: null});
+ new Jx.Layout('TaskPane', {bottom: 22, width: 250, left: null});
+ new Jx.Layout('Toolbar', {height: h, bottom: null});
+ new Jx.Layout('Splitter', {top: h});
+
+ var splitter = new Jx.Splitter('Splitter', {elements: [$('PanelPane'), $('Map')], containerOptions: [{width: 200}, {}]});
+
+ //new Jx.Splitter('Statusbar', {elements: [$('CursorPosition'), $('SelectionInfo'), $('EditableScale'), $('ViewSize'), $('PoweredBy')], containerOptions: [{}, {}, {}, {}, {width: 143, maxWidth: 143, minWidth: 143}]});
+
+ var p1 = new Jx.Panel({label: 'Legend'});
+ p1.content.id = 'Legend';
+ var p2 = new Jx.Panel({label: 'Selection'});
+ p2.content.id = 'SelectionPanel';
+ var p3 = new Jx.Panel({label: 'Overview Map'});
+ p3.content.id = 'OverviewMap';
+ var pm = new Jx.PanelSet('PanelPane', [p1, p2, p3]);
+
+ $('thePage').resize();
+ $('thePage').style.visibility = 'visible';
+
+ Fusion.registerForEvent(Fusion.Event.FUSION_INITIALIZED, fusionInitialized);
+ Fusion.registerForEvent(Fusion.Event.FUSION_ERROR, fusionError);
+ Fusion.initialize();
+}
+
+function fusionError(eventId, error) {
+ console.log('Fusion Error: \n' + error.toString());
+}
+
+function fusionInitialized() {
+ $('thePage').resize({forceResize:true});
+ $('Toolbar').resize({forceResize:true});
+ //var map = Fusion.getWidgetById('Map');
+ //var l = new Jx.Layout($('Toolbar').childNodes[0]);
+ //l.resize();
+}
+
+</script>
+</head>
+
+<body>
+
+<div id="thePage" style="visibility: hidden">
+
+ <div id="Main">
+ <div id="Toolbar"></div>
+ <div id="Splitter">
+ <div id="PanelPane"></div>
+ <div id="Map">
+ <div id="Navigator"></div>
+ </div>
+ </div>
+ </div>
+
+ <div id="TaskPane"></div>
+ <div id="Statusbar"></div>
+ <div id="PoweredBy" class="statusBarItem">
+ <a href="http://mapserver.gis.umn.edu.org/" target="_blank">
+ <img src="images/PoweredBy_MapServer.gif" width="137" height="18" border="0">
+ </a>
+ </div>
+
+</div>
+
+<div id="BusyIndicator" style="visibility: hidden;">
+ <img src="images/icon_loading.gif" width="30" height="14">
+</div>
+
+</body>
</html>
\ No newline at end of file
Modified: sandbox/jx2/widgets/ColorPicker.js
===================================================================
--- sandbox/jx2/widgets/ColorPicker.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/ColorPicker.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -59,8 +59,13 @@
this.colorInput.widget = this;
}
- this.colorButton = new Jx.Button.Color({color: this.color, alpha: this.alpha, label: widgetTag.label, tooltip: widgetTag.tooltip});
- this.colorButton.addColorChangeListener(this);
+ this.colorButton = new Jx.Button.Color({
+ color: this.color,
+ alpha: this.alpha,
+ label: widgetTag.label,
+ tooltip: widgetTag.tooltip
+ });
+ this.colorButton.addEvent('colorChange', OpenLayers.Function.bind(this.colorChanged, this));
if (this.domObj) {
this.domObj.appendChild(this.colorButton.domObj);
Modified: sandbox/jx2/widgets/EditableScale.js
===================================================================
--- sandbox/jx2/widgets/EditableScale.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/EditableScale.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -45,7 +45,7 @@
this.domScale = document.createElement('input');
this.domScale.className = 'inputEditableScale';
this.domObj.appendChild(this.domScale);
- Event.observe(this.domScale, 'keypress',
+ OpenLayers.Event.observe(this.domScale, 'keypress',
OpenLayers.Function.bindAsEventListener(this.keyPressHandler, this));
this.precision = json.Precision ? parseInt(json.Precision[0]) : this.precision;
Modified: sandbox/jx2/widgets/LayerManager.js
===================================================================
--- sandbox/jx2/widgets/LayerManager.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/LayerManager.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -1,272 +1,272 @@
-/**
- * Fusion.Widget.LayerManager
- *
- * $Id$
- *
- * Copyright (c) 2007, DM Solutions Group Inc.
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
- /***************************************************************************
- * Class: Fusion.Widget.LayerManager
- *
- * Displays a LayerManager of all the layers in the map as a collapsable tree.
- *
- * ShowRootFolder (boolean, optional)
- *
- * This controls whether the tree will have a single root node that
- * contains the name of the map as its label. By default, the root
- * node does not appear. Set to "true" or "1" to make the root node
- * appear.
- *
- * RootFolderIcon: (string, optional)
- *
- * The url to an image to use for the root folder. This only has an
- * affect if ShowRootFolder is set to show the root folder.
- *
- * LayerThemeIcon: (string, optional)
- *
- * The url to an image to use for layers that are currently themed.
- *
- * DisabledLayerIcon: (string, optional)
- *
- * The url to an image to use for layers that are out of scale.
- *
- * **********************************************************************/
-
-Fusion.Widget.LayerManager = OpenLayers.Class(Fusion.Widget, {
- currentNode: null,
- bIsDrawn: false,
- initialize : function(widgetTag) {
- //console.log('LayerManager.initialize');
-
- Fusion.Widget.prototype.initialize.apply(this, [widgetTag, true]);
-
- var json = widgetTag.extension;
- this.delIconSrc = json.DeleteIcon ? json.DeleteIcon[0] : 'images/icons/select-delete.png';
-
- Fusion.addWidgetStyleSheet(widgetTag.location + 'LayerManager/LayerManager.css');
- this.cursorNormal = ["url('images/grab.cur'),move", 'grab', '-moz-grab', 'move'];
- this.cursorDrag = ["url('images/grabbing.cur'),move", 'grabbing', '-moz-grabbing', 'move'];
-
- this.getMap().registerForEvent(Fusion.Event.MAP_LOADED, OpenLayers.Function.bind(this.mapLoaded, this));
- this.getMap().registerForEvent(Fusion.Event.MAP_RELOADED, OpenLayers.Function.bind(this.mapLoaded, this));
- },
-
-
- mapLoaded: function() {
- this.draw();
- },
-
-
- /**
- * remove the dom objects representing the legend layers and groups
- */
- clear: function(node) {
- while (node.childNodes.length > 0) {
- this.clear(node.childNodes[0]);
- node.remove(node.childNodes[0]);
- }
- },
-
- /**
- * Draws the layer manager
- *
- * @param r Object the reponse xhr object
- */
- draw: function(r) {
- if (this.mapList) {
- //this.clear(this.mapList);
- this.mapList.remove();
- this.mapList = null;
- }
-
- //create the master UL element to hold the list of layers
- this.mapList = document.createElement('ul');
- Element.addClassName(this.mapList, 'jxLman');
- this.domObj.appendChild(this.mapList);
-
- //this processes the OL layers
- var map = this.getMap();
- for (var i=0; i<map.aMaps.length; ++i) {
- var mapBlock = document.createElement('li');
- Element.addClassName(this.mapBlock, 'jxLmanMap');
- mapBlock.id = 'mapBlock_'+i;
-
- //add a handle so the map blocks can be re-arranged
- var handle = document.createElement('a');
- handle.innerHTML = map.aMaps[i]._sMapTitle;
- Element.addClassName(handle, 'jxLmanHandle');
- mapBlock.appendChild(handle);
-
- this.mapList.appendChild(mapBlock);
- this.processMapBlock(mapBlock, map.aMaps[i]);
- }
-
- if (map.aMaps.length >1) {
- var options = [];
- options.onUpdate = OpenLayers.Function.bind(this.updateMapBlock, this, map);
- options.handle = 'jxLmanHandle';
- options.scroll = this.domObj.id;
- Sortable.create(this.mapList.id, options);
- }
- },
-
- processMapBlock: function(blockDom, map) {
- var mapBlockList = document.createElement('ul');
- Element.addClassName(mapBlockList, 'jxLmanSet');
- mapBlockList.id = 'fusionLayerManager_'+map.getMapName();
- blockDom.appendChild(mapBlockList);
- map.layerPrefix = 'layer_'; //TODO make this unique for each block
-
- //this process all layers within an OL layer
- var processArray = map.aLayers;
- if (map.bLayersReversed) {
- processArray.reverse();
- }
- for (var i=0; i<processArray.length; ++i) {
- var blockItem = document.createElement('li');
- Element.addClassName(blockItem, 'jxLmanLayer');
- blockItem.id = map.layerPrefix+i;
- mapBlockList.appendChild(blockItem);
- this.createItemHtml(blockItem, processArray[i]);
- blockItem.layer = processArray[i];
- }
-
- var options = [];
- options.onUpdate = OpenLayers.Function.bind(this.updateLayer, this, map);
- options.scroll = this.domObj.id; //docs for this at: http://wiki.script.aculo.us/scriptaculous/show/Sortable.create
- Position.includeScrollOffsets = true;
- Sortable.create(mapBlockList.id, options);
- },
-
- createItemHtml: function(parent, layer) {
- var delIcon = document.createElement('img');
- delIcon.src = this.delIconSrc;
- Event.observe(delIcon, 'click', OpenLayers.Function.bind(this.deleteLayer, this, layer));
- delIcon.style.visibility = 'hidden';
- parent.appendChild(delIcon);
-
- var visSelect = document.createElement('input');
- visSelect.type = 'checkbox';
- Event.observe(visSelect, 'click', OpenLayers.Function.bind(this.visChanged, this, layer));
- parent.appendChild(visSelect);
- if (layer.visible) {
- visSelect.checked = true;
- } else {
- visSelect.checked = false;
- }
-
- var label = document.createElement('a');
- label.innerHTML = layer.legendLabel;
- Event.observe(label, 'mouseover', OpenLayers.Function.bind(this.setGrabCursor, this));
- Event.observe(label, 'mousedown', OpenLayers.Function.bind(this.setDragCursor, this));
- Event.observe(label, 'mouseout', OpenLayers.Function.bind(this.setNormalCursor, this));
- parent.appendChild(label);
-
- Event.observe(parent, 'mouseover', OpenLayers.Function.bind(this.setHandleVis, this, delIcon));
- Event.observe(parent, 'mouseout', OpenLayers.Function.bind(this.setHandleHide, this, delIcon));
- },
-
- setHandleVis: function(delIcon) {
- delIcon.style.visibility = 'visible';
- },
-
- setHandleHide: function(delIcon) {
- delIcon.style.visibility = 'hidden';
- },
-
- setGrabCursor: function(ev) {
- this.setCursor(this.cursorNormal, Event.element(ev) );
- },
-
- setDragCursor: function(ev) {
- this.setCursor(this.cursorDrag, Event.element(ev) );
- },
-
- setNormalCursor: function(ev) {
- this.setCursor('auto', Event.element(ev) );
- },
-
- setCursor : function(cursor, domObj) {
- this.cursor = cursor;
- if (cursor && cursor.length && typeof cursor == 'object') {
- for (var i = 0; i < cursor.length; i++) {
- domObj.style.cursor = cursor[i];
- if (domObj.style.cursor == cursor[i]) {
- break;
- }
- }
- } else if (typeof cursor == 'string') {
- domObj.style.cursor = cursor;
- } else {
- domObj.style.cursor = 'auto';
- }
- },
-
- updateLayer: function(map, ul) {
- //reorder the layers in the client as well as the session
- var aLayerIndex = [];
- var aIds = [];
- var nLayers = ul.childNodes.length;
- for (var i=0; i<nLayers; ++i) {
- aIds[i] = ul.childNodes[i].id.split('_');
- var index = parseInt(aIds[i].pop());
- if (map.bLayersReversed) {
- index = nLayers - (index+1);
- }
- aLayerIndex.push(index);
- ul.childNodes[i].id = '';
- }
-
- //reset the ID's on the LI elements to be in order
- for (var i=0; i<ul.childNodes.length; ++i) {
- var node = ul.childNodes[i];
- aIds[i].push(i);
- node.id = aIds[i].join('_');
- node.childNodes[1].checked = node.layer.isVisible()
- }
- if (map.bLayersReversed) {
- aLayerIndex.reverse();
- }
- map.reorderLayers(aLayerIndex);
- },
-
- updateMapBlock: function(map, ul) {
- //reorder the OL layers
- },
-
- deleteLayer: function(layer, ev) {
- var targetLI = Event.element(ev).parentNode;
- var ul = targetLI.parentNode;
- Element.remove(targetLI.id);
- this.updateLayer(layer.oMap, ul);
- },
-
- visChanged: function(layer2, ev) {
- var target = Event.element(ev);
- var layer = target.parentNode.layer;
- if (target.checked) {
- layer.show();
- } else {
- layer.hide();
- }
- }
-
-});
+/**
+ * Fusion.Widget.LayerManager
+ *
+ * $Id$
+ *
+ * Copyright (c) 2007, DM Solutions Group Inc.
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+ /***************************************************************************
+ * Class: Fusion.Widget.LayerManager
+ *
+ * Displays a LayerManager of all the layers in the map as a collapsable tree.
+ *
+ * ShowRootFolder (boolean, optional)
+ *
+ * This controls whether the tree will have a single root node that
+ * contains the name of the map as its label. By default, the root
+ * node does not appear. Set to "true" or "1" to make the root node
+ * appear.
+ *
+ * RootFolderIcon: (string, optional)
+ *
+ * The url to an image to use for the root folder. This only has an
+ * affect if ShowRootFolder is set to show the root folder.
+ *
+ * LayerThemeIcon: (string, optional)
+ *
+ * The url to an image to use for layers that are currently themed.
+ *
+ * DisabledLayerIcon: (string, optional)
+ *
+ * The url to an image to use for layers that are out of scale.
+ *
+ * **********************************************************************/
+
+Fusion.Widget.LayerManager = OpenLayers.Class(Fusion.Widget, {
+ currentNode: null,
+ bIsDrawn: false,
+ initialize : function(widgetTag) {
+ //console.log('LayerManager.initialize');
+
+ Fusion.Widget.prototype.initialize.apply(this, [widgetTag, true]);
+
+ var json = widgetTag.extension;
+ this.delIconSrc = json.DeleteIcon ? json.DeleteIcon[0] : 'images/icons/select-delete.png';
+
+ Fusion.addWidgetStyleSheet(widgetTag.location + 'LayerManager/LayerManager.css');
+ this.cursorNormal = ["url('images/grab.cur'),move", 'grab', '-moz-grab', 'move'];
+ this.cursorDrag = ["url('images/grabbing.cur'),move", 'grabbing', '-moz-grabbing', 'move'];
+
+ this.getMap().registerForEvent(Fusion.Event.MAP_LOADED, OpenLayers.Function.bind(this.mapLoaded, this));
+ this.getMap().registerForEvent(Fusion.Event.MAP_RELOADED, OpenLayers.Function.bind(this.mapLoaded, this));
+ },
+
+
+ mapLoaded: function() {
+ this.draw();
+ },
+
+
+ /**
+ * remove the dom objects representing the legend layers and groups
+ */
+ clear: function(node) {
+ while (node.childNodes.length > 0) {
+ this.clear(node.childNodes[0]);
+ node.remove(node.childNodes[0]);
+ }
+ },
+
+ /**
+ * Draws the layer manager
+ *
+ * @param r Object the reponse xhr object
+ */
+ draw: function(r) {
+ if (this.mapList) {
+ //this.clear(this.mapList);
+ this.mapList.remove();
+ this.mapList = null;
+ }
+
+ //create the master UL element to hold the list of layers
+ this.mapList = document.createElement('ul');
+ this.mapList.className = 'jxLman';
+ this.domObj.appendChild(this.mapList);
+
+ //this processes the OL layers
+ var map = this.getMap();
+ for (var i=0; i<map.aMaps.length; ++i) {
+ var mapBlock = document.createElement('li');
+ this.mapBlock.className = 'jxLmanMap';
+ mapBlock.id = 'mapBlock_'+i;
+
+ //add a handle so the map blocks can be re-arranged
+ var handle = document.createElement('a');
+ handle.innerHTML = map.aMaps[i]._sMapTitle;
+ handle.className = 'jxLmanHandle';
+ mapBlock.appendChild(handle);
+
+ this.mapList.appendChild(mapBlock);
+ this.processMapBlock(mapBlock, map.aMaps[i]);
+ }
+
+ if (map.aMaps.length >1) {
+ var options = [];
+ options.onUpdate = OpenLayers.Function.bind(this.updateMapBlock, this, map);
+ options.handle = 'jxLmanHandle';
+ options.scroll = this.domObj.id;
+ Sortable.create(this.mapList.id, options);
+ }
+ },
+
+ processMapBlock: function(blockDom, map) {
+ var mapBlockList = document.createElement('ul');
+ mapBlockList.className = 'jxLmanSet';
+ mapBlockList.id = 'fusionLayerManager_'+map.getMapName();
+ blockDom.appendChild(mapBlockList);
+ map.layerPrefix = 'layer_'; //TODO make this unique for each block
+
+ //this process all layers within an OL layer
+ var processArray = map.aLayers;
+ if (map.bLayersReversed) {
+ processArray.reverse();
+ }
+ for (var i=0; i<processArray.length; ++i) {
+ var blockItem = document.createElement('li');
+ blockItem.className = 'jxLmanLayer';
+ blockItem.id = map.layerPrefix+i;
+ mapBlockList.appendChild(blockItem);
+ this.createItemHtml(blockItem, processArray[i]);
+ blockItem.layer = processArray[i];
+ }
+
+ var options = [];
+ options.onUpdate = OpenLayers.Function.bind(this.updateLayer, this, map);
+ options.scroll = this.domObj.id; //docs for this at: http://wiki.script.aculo.us/scriptaculous/show/Sortable.create
+ Position.includeScrollOffsets = true;
+ Sortable.create(mapBlockList.id, options);
+ },
+
+ createItemHtml: function(parent, layer) {
+ var delIcon = document.createElement('img');
+ delIcon.src = this.delIconSrc;
+ Event.observe(delIcon, 'click', OpenLayers.Function.bind(this.deleteLayer, this, layer));
+ delIcon.style.visibility = 'hidden';
+ parent.appendChild(delIcon);
+
+ var visSelect = document.createElement('input');
+ visSelect.type = 'checkbox';
+ Event.observe(visSelect, 'click', OpenLayers.Function.bind(this.visChanged, this, layer));
+ parent.appendChild(visSelect);
+ if (layer.visible) {
+ visSelect.checked = true;
+ } else {
+ visSelect.checked = false;
+ }
+
+ var label = document.createElement('a');
+ label.innerHTML = layer.legendLabel;
+ Event.observe(label, 'mouseover', OpenLayers.Function.bind(this.setGrabCursor, this));
+ Event.observe(label, 'mousedown', OpenLayers.Function.bind(this.setDragCursor, this));
+ Event.observe(label, 'mouseout', OpenLayers.Function.bind(this.setNormalCursor, this));
+ parent.appendChild(label);
+
+ Event.observe(parent, 'mouseover', OpenLayers.Function.bind(this.setHandleVis, this, delIcon));
+ Event.observe(parent, 'mouseout', OpenLayers.Function.bind(this.setHandleHide, this, delIcon));
+ },
+
+ setHandleVis: function(delIcon) {
+ delIcon.style.visibility = 'visible';
+ },
+
+ setHandleHide: function(delIcon) {
+ delIcon.style.visibility = 'hidden';
+ },
+
+ setGrabCursor: function(ev) {
+ this.setCursor(this.cursorNormal, Event.element(ev) );
+ },
+
+ setDragCursor: function(ev) {
+ this.setCursor(this.cursorDrag, Event.element(ev) );
+ },
+
+ setNormalCursor: function(ev) {
+ this.setCursor('auto', Event.element(ev) );
+ },
+
+ setCursor : function(cursor, domObj) {
+ this.cursor = cursor;
+ if (cursor && cursor.length && typeof cursor == 'object') {
+ for (var i = 0; i < cursor.length; i++) {
+ domObj.style.cursor = cursor[i];
+ if (domObj.style.cursor == cursor[i]) {
+ break;
+ }
+ }
+ } else if (typeof cursor == 'string') {
+ domObj.style.cursor = cursor;
+ } else {
+ domObj.style.cursor = 'auto';
+ }
+ },
+
+ updateLayer: function(map, ul) {
+ //reorder the layers in the client as well as the session
+ var aLayerIndex = [];
+ var aIds = [];
+ var nLayers = ul.childNodes.length;
+ for (var i=0; i<nLayers; ++i) {
+ aIds[i] = ul.childNodes[i].id.split('_');
+ var index = parseInt(aIds[i].pop());
+ if (map.bLayersReversed) {
+ index = nLayers - (index+1);
+ }
+ aLayerIndex.push(index);
+ ul.childNodes[i].id = '';
+ }
+
+ //reset the ID's on the LI elements to be in order
+ for (var i=0; i<ul.childNodes.length; ++i) {
+ var node = ul.childNodes[i];
+ aIds[i].push(i);
+ node.id = aIds[i].join('_');
+ node.childNodes[1].checked = node.layer.isVisible()
+ }
+ if (map.bLayersReversed) {
+ aLayerIndex.reverse();
+ }
+ map.reorderLayers(aLayerIndex);
+ },
+
+ updateMapBlock: function(map, ul) {
+ //reorder the OL layers
+ },
+
+ deleteLayer: function(layer, ev) {
+ var targetLI = Event.element(ev).parentNode;
+ var ul = targetLI.parentNode;
+ Element.remove(targetLI.id);
+ this.updateLayer(layer.oMap, ul);
+ },
+
+ visChanged: function(layer2, ev) {
+ var target = Event.element(ev);
+ var layer = target.parentNode.layer;
+ if (target.checked) {
+ layer.show();
+ } else {
+ layer.hide();
+ }
+ }
+
+});
Modified: sandbox/jx2/widgets/Legend.js
===================================================================
--- sandbox/jx2/widgets/Legend.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/Legend.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -242,19 +242,29 @@
this.hideInvisibleLayers = (json.HideInvisibleLayers && json.HideInvisibleLayers[0]) == 'true' ? true : false;
- this.refreshAction = new Jx.Action(OpenLayers.Function.bind(this.update, this));
- this.refreshItem = new Jx.MenuItem(this.refreshAction, {label: OpenLayers.i18n('refresh')});
- this.expandAllAction = new Jx.Action(OpenLayers.Function.bind(this.expandAll, this));
- this.expandAllItem = new Jx.MenuItem(this.expandAllAction, {label: OpenLayers.i18n('expandAll')});
- this.expandBranchAction = new Jx.Action(OpenLayers.Function.bind(this.expandBranch, this));
- this.expandBranchItem = new Jx.MenuItem(this.expandBranchAction, {label: OpenLayers.i18n('expand')});
- this.collapseAllAction = new Jx.Action(OpenLayers.Function.bind(this.collapseAll, this));
- this.collapseAllItem = new Jx.MenuItem(this.collapseAllAction, {label: OpenLayers.i18n('collapseAll')});
- this.collapseBranchAction = new Jx.Action(OpenLayers.Function.bind(this.collapseBranch, this));
- this.collapseBranchItem = new Jx.MenuItem(this.collapseBranchAction, {label: OpenLayers.i18n('collapse')});
+ this.refreshItem = new Jx.Menu.Item({
+ label: OpenLayers.i18n('refresh'),
+ onClick: OpenLayers.Function.bind(this.update, this)
+ });
+ this.expandAllItem = new Jx.Menu.Item({
+ label: OpenLayers.i18n('expandAll'),
+ onClick: OpenLayers.Function.bind(this.expandAll, this)
+ });
+ this.expandBranchItem = new Jx.Menu.Item({
+ label: OpenLayers.i18n('expand'),
+ onClick: OpenLayers.Function.bind(this.expandBranch, this)
+ });
+ this.collapseAllItem = new Jx.Menu.Item({
+ label: OpenLayers.i18n('collapseAll'),
+ onClick: OpenLayers.Function.bind(this.collapseAll, this)
+ });
+ this.collapseBranchItem = new Jx.Menu.Item({
+ label: OpenLayers.i18n('collapse'),
+ onClick: OpenLayers.Function.bind(this.collapseBranch, this)
+ });
//this.collapseBranchItem.disable();
- this.contextMenu = new Jx.ContextMenu(this.sName);
+ this.contextMenu = new Jx.Menu.Context(this.sName);
this.contextMenu.add(this.collapseBranchItem,
this.expandBranchItem,
this.refreshItem,
@@ -263,11 +273,11 @@
this.showRootFolder = (json.ShowRootFolder && json.ShowRootFolder[0] == 'false') ? false:true;
this.showMapFolder = (json.ShowMapFolder && json.ShowMapFolder[0] == 'false') ? false:true;
if (this.showRootFolder) {
- var opt = {};
- opt.label = OpenLayers.i18n('defaultMapTitle');
- opt.data = null;
- opt.imgTreeFolder = json.RootFolderIcon ? json.RootFolderIcon[0] : this.defRootFolderIcon;
- opt.imgTreeFolderOpen = opt.imgTreeFolder;
+ var opt = {
+ label: OpenLayers.i18n('defaultMapTitle'),
+ isOpen: true,
+ contextMenu: this.contextMenu
+ };
opt.isOpen = true;
opt.contextMenu = this.contextMenu;
this.oRoot = new Jx.TreeFolder(opt);
@@ -388,11 +398,11 @@
if (group.displayInLegend) {
/* make a 'namespace' on the group object to store legend-related info */
group.legend = {};
- var opt = {};
- opt.label = group.legendLabel;
- opt.data = group;
- opt.contextMenu = this.contextMenu;
- opt.isOpen = group.expandInLegend;
+ var opt = {
+ label: group.legendLabel,
+ contextMenu: this.contextMenu,
+ isOpen: group.expandInLegend
+ };
group.legend.treeItem = new Jx.TreeFolder(opt);
folder.append(group.legend.treeItem);
group.legend.checkBox = document.createElement('input');
@@ -471,10 +481,10 @@
},
selectionChanged: function(o) {
if (this.currentNode) {
- Element.removeClassName(this.currentNode.domObj.childNodes[3], 'jxTreeSelectedNode');
+ $(this.currentNode.domObj.childNodes[3]).addClass('jxTreeSelectedNode');
}
this.currentNode = o;
- Element.addClassName(this.currentNode.domObj.childNodes[3], 'jxTreeSelectedNode');
+ $(this.currentNode.domObj.childNodes[3]).addClass('jxTreeSelectedNode');
if (o.data instanceof Fusion.Widget.Map.Group) {
this.getMap().setActiveLayer(null);
@@ -571,13 +581,12 @@
},
createFolderItem: function(layer) {
- var opt = {};
- opt.label = layer.legendLabel == '' ? ' ' : layer.legendLabel;
- opt.data = layer;
- opt.isOpen = layer.expandInLegend;
- opt.contextMenu = this.contextMenu;
- opt.imgTreeFolderOpen = this.imgLayerThemeIcon;
- opt.imgTreeFolder = this.imgLayerThemeIcon;
+ var opt = {
+ label: layer.legendLabel == '' ? ' ' : layer.legendLabel,
+ isOpen: layer.expandInLegend,
+ contextMenu: this.contextMenu,
+ // image overrides
+ };
var folder = new Jx.TreeFolder(opt);
folder.domObj.insertBefore(layer.legend.checkBox, folder.domObj.childNodes[1]);
var layerInfo = layer.oMap.getLayerInfoUrl(layer.layerName);
@@ -605,20 +614,19 @@
} else {
opt.label = style.legendLabel == '' ? ' ' : style.legendLabel;
}
- opt.data = layer;
opt.contextMenu = this.contextMenu;
if (!style) {
- opt.imgIcon = this.imgDisabledLayerIcon;
+ opt.image = this.imgDisabledLayerIcon;
opt.enabled = false;
} else {
if (style.staticIcon) {
if (style.staticIcon == Fusion.Constant.LAYER_DWF_TYPE) {
- opt.imgIcon = this.imgLayerDWFIcon;
+ opt.image = this.imgLayerDWFIcon;
} else {
- opt.imgIcon = this.imgLayerRasterIcon;
+ opt.image = this.imgLayerRasterIcon;
}
} else {
- opt.imgIcon = style.getLegendImageURL(scale, layer);
+ opt.image = style.getLegendImageURL(scale, layer);
}
}
Modified: sandbox/jx2/widgets/MapMenu.js
===================================================================
--- sandbox/jx2/widgets/MapMenu.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/MapMenu.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -60,11 +60,11 @@
if (json.Folder) {
this.mapGroupData[mapGroup.maps[0].resourceId] = mapGroup;
} else {
- var opt = {};
- opt.label = mapGroup.mapId;
- var data = mapGroup;
- var action = new Jx.Action(this.switchMap.bind(this, data));
- var menuItem = new Jx.MenuItem(action,opt);
+ var opt = {
+ label: mapGroup.mapId,
+ onClick: OpenLayers.Function.bind(this.switchMap, this, data)
+ };
+ var menuItem = new Jx.Menu.Item(opt);
this.oMenu.add(menuItem);
}
}
@@ -120,8 +120,8 @@
return this.initialView;
};
}
- var action = new Jx.Action(this.switchMap.bind(this, data));
- var menuItem = new Jx.MenuItem(action,opt);
+ opt.onClick = OpenLayers.Function.bind(this.switchMap, this, data);
+ var menuItem = new Jx.Menu.Item(opt);
if (sPath == '') {
this.oMenu.add(menuItem);
Modified: sandbox/jx2/widgets/Measure.js
===================================================================
--- sandbox/jx2/widgets/Measure.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/Measure.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -198,7 +198,7 @@
this.totalDistanceMarker.domObj.parentNode != oDomElem) {
oDomElem.appendChild(this.totalDistanceMarker.domObj);
}
- Element.addClassName(this.totalDistanceMarker.domObj, 'divMeasureTotal');
+ this.totalDistanceMarker.domObj.className = 'divMeasureTotal';
this.totalDistanceMarker.domObj.style.display = 'none';
this.registerForEvent(Fusion.Event.MEASURE_CLEAR, OpenLayers.Function.bind(this.clearTotalDistance, this));
this.registerForEvent(Fusion.Event.MEASURE_SEGMENT_UPDATE, OpenLayers.Function.bind(this.updateTotalDistance, this));
Modified: sandbox/jx2/widgets/Navigator.js
===================================================================
--- sandbox/jx2/widgets/Navigator.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/Navigator.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -48,7 +48,7 @@
a.title = OpenLayers.i18n('panEast');
a.coords = '27,176, 27,177, 40,190, 44,182, 44,159';
var panEast = OpenLayers.Function.bind(this.pan, this, this.panAmount/100, 0);
- Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panEast, this));
+ OpenLayers.Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panEast, this));
m.appendChild(a);
var a = document.createElement('area');
@@ -57,7 +57,7 @@
a.title = OpenLayers.i18n('panWest');
a.coords = '24,177, 24,176, 7,159, 7,182, 11,190';
var panWest = OpenLayers.Function.bind(this.pan, this, -this.panAmount/100, 0);
- Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panWest, this) );
+ OpenLayers.Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panWest, this) );
m.appendChild(a);
var a = document.createElement('area');
@@ -66,7 +66,7 @@
a.title = OpenLayers.i18n('panSouth');
a.coords = '25,178, 12,191, 21,197, 30,197, 39,191, 26,178';
var panSouth = OpenLayers.Function.bind(this.pan, this, 0, -this.panAmount/100 );
- Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panSouth, this) );
+ OpenLayers.Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panSouth, this) );
m.appendChild(a);
var a = document.createElement('area');
@@ -75,7 +75,7 @@
a.title = OpenLayers.i18n('panNorth');
a.coords = '26,175, 43,158, 8,158, 25,175';
var panNorth = OpenLayers.Function.bind(this.pan, this, 0, this.panAmount/100 );
- Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panNorth, this) );
+ OpenLayers.Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(panNorth, this) );
m.appendChild(a);
var a = document.createElement('area');
@@ -84,7 +84,7 @@
a.title = OpenLayers.i18n('zoomOut');
a.coords = '25,142,8';
var zoomOut = OpenLayers.Function.bind(this.zoom, this, 1/this.zoomOutFactor);
- Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(zoomOut, this) );
+ OpenLayers.Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(zoomOut, this) );
m.appendChild(a);
var a = document.createElement('area');
@@ -93,7 +93,7 @@
a.title = OpenLayers.i18n('zoomIn');
a.coords = '25,34,8';
var zoomIn = OpenLayers.Function.bind(this.zoom, this, this.zoomInFactor);
- Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(zoomIn, this) );
+ OpenLayers.Event.observe(a, 'mouseup', OpenLayers.Function.bindAsEventListener(zoomIn, this) );
m.appendChild(a);
this.domObj.appendChild(m);
@@ -153,7 +153,7 @@
var checkPosition = OpenLayers.Function.bind(this.checkPosition, this);
//set up the navigator as draggable
- new Draggable(this.domObj, {handle: handleDiv, starteffect: false, endeffect: false});
+ //new Draggable(this.domObj, {handle: handleDiv, starteffect: false, endeffect: false});
//this observer pins the navigator to the top right after a drag so
//that it moves if the window is resized
var observer = {
@@ -163,15 +163,15 @@
};
//this should position the nav tool by the right rather than the left,
//but it is broken in IE
- Draggables.addObserver(observer);
+ //Draggables.addObserver(observer);
var options = {};
options.axis = 'vertical';
- options.range = $R(1, 91);
+ options.range = {}; //$R(1, 91);
options.sliderValue = 91;
options.onChange = OpenLayers.Function.bind(this.scaleChanged, this);
- this.slider = new Control.Slider(sliderHandle,sliderDiv, options);
- this.slider.setDisabled();
+ //this.slider = new Control.Slider(sliderHandle,sliderDiv, options);
+ //this.slider.setDisabled();
this.getMap().registerForEvent(Fusion.Event.MAP_LOADED, OpenLayers.Function.bind(this.updateSlider, this));
this.getMap().registerForEvent(Fusion.Event.MAP_RESIZED, OpenLayers.Function.bind(this.checkPosition, this));
this.getMap().registerForEvent(Fusion.Event.MAP_EXTENTS_CHANGED, OpenLayers.Function.bind(this.updateValue, this));
@@ -228,30 +228,30 @@
updateSlider: function() {
var olMap = this.getMap().oMapOL;
if (olMap.baseLayer.singleTile) {
- this.slider.values = [];
- this.slider.range = $R(olMap.baseLayer.minResolution,olMap.baseLayer.maxResolution);
+ //this.slider.values = [];
+ //this.slider.range = $R(olMap.baseLayer.minResolution,olMap.baseLayer.maxResolution);
this.bInternalChange = true;
- this.slider.setValue(olMap.getResolution());
+ //this.slider.setValue(olMap.getResolution());
this.bInternalChange = false;
} else {
var res = olMap.baseLayer.resolutions;
var n = res.length;
var max = res[0];
var min = res[n-1];
- this.slider.values = [];
- this.slider.range = $R(1,91);
+ //this.slider.values = [];
+ //this.slider.range = $R(1,91);
for (var i=0; i<n; i++) {
var r = res[i];
- this.slider.values.push(parseInt((r/max)*91));
+ //this.slider.values.push(parseInt((r/max)*91));
}
}
- this.slider.setEnabled();
+ //this.slider.setEnabled();
},
updateValue: function() {
var olMap = this.getMap().oMapOL;
this.bInternalChange = true;
- this.slider.setValue(olMap.getResolution());
+ //this.slider.setValue(olMap.getResolution());
this.bInternalChange = false;
},
Modified: sandbox/jx2/widgets/Print.js
===================================================================
--- sandbox/jx2/widgets/Print.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/Print.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -83,21 +83,34 @@
if (!this.dialog) {
var size = Element.getPageDimensions();
+ var toolbar = new Jx.Toolbar({position: 'bottom'});
var o = {
- title: OpenLayers.i18n('printTitle'),
+ label: OpenLayers.i18n('printTitle'),
id: 'printablePage',
contentURL : this.dialogContentURL,
- onContentLoaded: OpenLayers.Function.bind(this.contentLoaded, this),
+ onContentLoad: OpenLayers.Function.bind(this.contentLoaded, this),
imageBaseUrl: this.imageBaseUrl,
width: 350,
height: 250,
- resizeable: true,
+ resize: true,
top: (size.height-250)/2,
left: (size.width-350)/2,
- buttons: ['generate', 'cancel'],
- handler: OpenLayers.Function.bind(this.handler, this)
+ toolbars: [toolbar]
};
- this.dialog = new Jx.Dialog(o);
+ var d = new Jx.Dialog(o);
+ toolbar.add(
+ new Jx.Button({
+ label: 'Generate',
+ onClick: OpenLayers.Function.bind(this.generate, this)
+ }),
+ new Jx.Button({
+ label: 'Cancel',
+ onClick: function() {
+ d.close();
+ }
+ })
+ );
+ this.dialog = d;
}
this.dialog.open();
@@ -139,16 +152,12 @@
},
- handler: function(button) {
- if (button == 'generate') {
- this.showTitle = this.dialog.getObj('dialogPrintShowtitle').checked;
- this.pageTitle = this.dialog.getObj('dialogPrintTitle').value;
- this.showLegend = this.dialog.getObj('dialogPrintShowlegend').checked;
- this.showNorthArrow = this.dialog.getObj('dialogPrintShowNorthArrow').checked;
- this.openPrintable();
-
- }
- this.dialog.close();
+ generate: function() {
+ this.showTitle = this.dialog.getObj('dialogPrintShowtitle').checked;
+ this.pageTitle = this.dialog.getObj('dialogPrintTitle').value;
+ this.showLegend = this.dialog.getObj('dialogPrintShowlegend').checked;
+ this.showNorthArrow = this.dialog.getObj('dialogPrintShowNorthArrow').checked;
+ this.openPrintable();
},
openPrintable: function() {
Modified: sandbox/jx2/widgets/SaveMap.js
===================================================================
--- sandbox/jx2/widgets/SaveMap.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/SaveMap.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -61,8 +61,9 @@
var layouts = json.PrintLayout;
for (var i = 0; i < layouts.length; i++) {
var layout = layouts[i];
- var opt = {};
- opt.label = layout.Name[0];
+ var opt = {
+ label: layout.Name[0]
+ };
var data = {rid:layout.ResourceId[0]};
if (layout.PageHeight) {
data.pageHeight = layout.PageHeight[0];
@@ -79,23 +80,28 @@
var menuItem = null;
if (layout.Scale) {
//create entries for weblayout specified scales
- menuItem = new Jx.SubMenu(opt);
+ menuItem = new Jx.Menu.SubMenu(opt);
data.scales = [];
for (var j=0; j < layout.Scale.length; j++) {
data.scales.push(layout.Scale[j]);
- var scaleAction = new Jx.Action(this.setLayout.bind(this, data, j));
- var subMenuItem = new Jx.MenuItem(scaleAction,{label:layout.Scale[j]});
- menuItem.add(subMenuItem);
+ menuItem.add(
+ new Jx.Menu.Item({
+ label:layout.Scale[j],
+ onClick: OpenLayers.Function.bind(this.setLayout, this, data, j)
+ })
+ );
}
//add an entry for current scale
- var currentScaleAction = new Jx.Action(this.setLayout.bind(this, data));
- var currentScaleItem = new Jx.MenuItem(currentScaleAction,
- {label:'Current Scale'});
- menuItem.add(currentScaleItem);
+ menuItem.add(
+ new Jx.Menu.Item({
+ label:'Current Scale',
+ onClick: OpenLayers.Function.bind(this.setLayout, this, data)
+ })
+ );
} else {
//if there are no scales, the layout is used with current scale
- var action = new Jx.Action(this.setLayout.bind(this, data));
- menuItem = new Jx.MenuItem(action,opt);
+ opt.onClick = OpenLayers.Function.bind(this.setLayout, this, data);
+ menuItem = new Jx.Menu.Item(opt);
};
this.oMenu.add(menuItem);
}
Modified: sandbox/jx2/widgets/SelectionPanel.js
===================================================================
--- sandbox/jx2/widgets/SelectionPanel.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/SelectionPanel.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -288,13 +288,13 @@
this.layerList = document.createElement('select');
this.layerList.className = 'layerSelector';
this.toolbar.appendChild(this.layerList);
- Event.observe(this.layerList, 'change',
+ OpenLayers.Event.observe(this.layerList, 'change',
OpenLayers.Function.bind(this.renderSelectionFeatures, this));
this.featureList = document.createElement('select');
this.featureList.className = 'featureSelector';
this.toolbar.appendChild(this.featureList);
- Event.observe(this.featureList, 'change',
+ OpenLayers.Event.observe(this.featureList, 'change',
OpenLayers.Function.bind(this.renderFeature, this));
this.featureDiv = document.createElement('div');
@@ -317,7 +317,7 @@
this.layerList.options.length = 0;
this.featureList.options.length = 0;
this.oSelection = null;
- Element.addClassName(this.featureDiv, 'noSelection');
+ this.featureDiv.className = 'selectionPanelContent noSelection';
this.featureDiv.innerHTML = OpenLayers.i18n('noSelection');
},
@@ -334,7 +334,7 @@
}
//clear the layer list select box of any previous selections
- Element.removeClassName(this.featureDiv, 'noSelection');
+ this.featureDiv.className = 'selectionPanelContent';
while (this.layerList.length>0) {
this.layerList.remove(this.layerList.options[0]);
}
@@ -400,7 +400,7 @@
for (var i=0; i<nProperties; i++) {
var tr = document.createElement('tr');
if (i%2) {
- Element.addClassName(tr, 'oddRow');
+ tr.className = 'oddRow';
}
var th = document.createElement('th');
th.innerHTML = aNames[i];
@@ -432,7 +432,7 @@
var d = document.createElement('div');
this.featureDiv = document.createElement('div');
this.featureDiv.innerHTML = 'No Selection';
- Element.addClassName(this.featureDiv, 'noSelection');
+ this.featureDiv.className = 'selectionPanelContent noSelection';
d.appendChild(this.featureDiv);
if (this.iResultsPerPage != 0) {
@@ -441,21 +441,20 @@
this.previousButton.style.position = "absolute";
this.previousButton.style.left = "0px";
this.previousButton.style.padding = "3px";
- Event.observe(this.previousButton, 'click',
+ OpenLayers.Event.observe(this.previousButton, 'click',
OpenLayers.Function.bind(this.renderLayers, this, 'prev'));
this.nextButton = document.createElement('img');
this.nextButton.src = this.oSelectionPanel.nextIcon;
this.nextButton.style.position = "absolute";
this.nextButton.style.right = "0px";
this.nextButton.style.padding = "3px";
- Event.observe(this.nextButton, 'click',
+ OpenLayers.Event.observe(this.nextButton, 'click',
OpenLayers.Function.bind(this.renderLayers, this, 'next'));
d.appendChild(this.previousButton);
d.appendChild(this.nextButton);
}
- Element.addClassName(this.featureDiv, 'selectionPanelContent');
Fusion.addWidgetStyleSheet(this.oSelectionPanel.getLocation() + 'SelectionPanel/SelectionPanel.css');
this.oSelectionPanel.domObj.appendChild(d);
},
@@ -467,7 +466,7 @@
clearSelection: function() {
this.oSelection = null;
- Element.addClassName(this.featureDiv, 'noSelection');
+ this.featureDiv.className = 'selectionPanelContent noSelection';
this.featureDiv.innerHTML = OpenLayers.i18n('noSelection');
},
@@ -540,7 +539,7 @@
for (var i=0; i<page.length; i++) {
var tr = document.createElement('tr');
if (i%2) {
- Element.addClassName(tr, 'oddRow');
+ tr.className = 'oddRow';
}
for (var j=0; j<page[i].length; j++) {
var td = document.createElement('td');
Modified: sandbox/jx2/widgets/TaskPane.js
===================================================================
--- sandbox/jx2/widgets/TaskPane.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/TaskPane.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -70,35 +70,34 @@
tmpDiv.setAttribute('id', divName);
this.toolbar = new Jx.Toolbar(tmpDiv,{left:0});
- this.homeAction = new Jx.Action(OpenLayers.Function.bind(this.goHome, this));
- this.toolbar.add(new Jx.Button(this.homeAction,
- {
+ this.homeButton = new Jx.Button({
image: this.defHomeIcon,
- tooltip: OpenLayers.i18n('taskHome')
- }
- ));
-
- this.prevAction = new Jx.Action(OpenLayers.Function.bind(this.gotoPrevTask, this));
- this.toolbar.add(new Jx.Button(this.prevAction,
- {
+ tooltip: OpenLayers.i18n('taskHome'),
+ onClick: OpenLayers.Function.bind(this.goHome, this)
+ });
+ this.prevButton = new Jx.Button({
image: this.defPrevTaskIcon,
- tooltip: OpenLayers.i18n('prevTask')
- }
- ));
-
- this.nextAction = new Jx.Action(OpenLayers.Function.bind(this.gotoNextTask, this));
- this.toolbar.add(new Jx.Button(this.nextAction,
- {
+ tooltip: OpenLayers.i18n('prevTask'),
+ onClick: OpenLayers.Function.bind(this.gotoPrevTask, this)
+ });
+ this.nextButton = new Jx.Button({
image: this.defNextTaskIcon,
- tooltip: OpenLayers.i18n('nextTask')
- }
- ));
+ tooltip: OpenLayers.i18n('nextTask'),
+ onClick: OpenLayers.Function.bind(this.gotoNextTask, this)
+ });
+ this.toolbar.add(
+ this.homeButton,
+ this.prevButton,
+ this.nextButton
+ );
- this.taskMenu = new Jx.Menu({image: this.defTaskListIcon,
- label: OpenLayers.i18n('taskList'),
- right:0});
- Element.addClassName(this.taskMenu.domObj, 'taskMenu');
- Element.addClassName(this.taskMenu.button.domObj, 'jxButtonContentLeft');
+ this.taskMenu = new Jx.Menu({
+ image: this.defTaskListIcon,
+ label: OpenLayers.i18n('taskList'),
+ right:0
+ });
+ //Element.addClassName(this.taskMenu.domObj, 'taskMenu');
+ //Element.addClassName(this.taskMenu.button.domObj, 'jxButtonContentLeft');
this.toolbar.add(this.taskMenu);
var iframeName = this.sName+'_IFRAME';
@@ -108,11 +107,12 @@
this.iframe.setAttribute('id', iframeName);
this.iframe.setAttribute('frameborder', 0);
this.iframe.style.border = '0px solid #fff';
- this.oTaskPane = new Jx.Panel({toolbar: tmpDiv,
- label: OpenLayers.i18n('taskPane'),
- content: this.iframe
+ this.oTaskPane = new Jx.Panel({
+ toolbar: tmpDiv,
+ label: OpenLayers.i18n('taskPane'),
+ content: this.iframe
});
- Element.addClassName(this.domObj, 'taskPanePanel');
+ //Element.addClassName(this.domObj, 'taskPanePanel');
Fusion.addWidgetStyleSheet(widgetTag.location + 'TaskPane/TaskPane.css');
this.domObj.appendChild(this.oTaskPane.domObj);
@@ -125,8 +125,8 @@
},
updateButtons: function() {
- this.prevAction.setEnabled(this.nCurrentTask > 0);
- this.nextAction.setEnabled(this.nCurrentTask < this.aExecutedTasks.length - 1);
+ this.prevButton.setEnabled(this.nCurrentTask > 0);
+ this.nextButton.setEnabled(this.nCurrentTask < this.aExecutedTasks.length - 1);
},
gotoPrevTask: function() {
Modified: sandbox/jx2/widgets/ViewOptions.js
===================================================================
--- sandbox/jx2/widgets/ViewOptions.js 2008-08-27 18:16:28 UTC (rev 1481)
+++ sandbox/jx2/widgets/ViewOptions.js 2008-08-28 12:29:20 UTC (rev 1482)
@@ -51,9 +51,11 @@
//set up the root menu
for (var key in this.options) {
- var action = new Jx.Action(OpenLayers.Function.bind(this.setViewOptions, this, this.options[key]));
- var menuItem = new Jx.MenuItem(action, {label: OpenLayers.i18n(key)} );
- this.oMenu.add(menuItem);
+ var menuItem = new Jx.Menu.Item({
+ label: OpenLayers.i18n(key),
+ onClick: OpenLayers.Function.bind(this.setViewOptions, this, this.options[key])
+ });
+ this.oMenu.add(menuItem);
}
this.displayUnits = json.DisplayUnits ? json.DisplayUnits[0] : false;
More information about the fusion-commits
mailing list