Subversion Repositories Applications.papyrus

Compare Revisions

Ignore whitespace Rev 2149 → Rev 2150

/trunk/api/js/dojo1.0/dijit/layout/StackContainer.js
New file
0,0 → 1,451
if(!dojo._hasResource["dijit.layout.StackContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.StackContainer"] = true;
dojo.provide("dijit.layout.StackContainer");
 
dojo.require("dijit._Templated");
dojo.require("dijit.layout._LayoutWidget");
dojo.require("dijit.form.Button");
 
dojo.declare(
"dijit.layout.StackContainer",
dijit.layout._LayoutWidget,
 
// summary
// A container that has multiple children, but shows only
// one child at a time (like looking at the pages in a book one by one).
//
// Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild
//
// Can be base class for container, Wizard, Show, etc.
{
// doLayout: Boolean
// if true, change the size of my currently displayed child to match my size
doLayout: true,
 
_started: false,
 
// selectedChildWidget: Widget
// References the currently selected child widget, if any
 
postCreate: function(){
dijit.setWaiRole((this.containerNode || this.domNode), "tabpanel");
this.connect(this.domNode, "onkeypress", this._onKeyPress);
},
startup: function(){
if(this._started){ return; }
 
var children = this.getChildren();
 
// Setup each page panel
dojo.forEach(children, this._setupChild, this);
 
// Figure out which child to initially display
dojo.some(children, function(child){
if(child.selected){
this.selectedChildWidget = child;
}
return child.selected;
}, this);
 
var selected = this.selectedChildWidget;
 
// Default to the first child
if(!selected && children[0]){
selected = this.selectedChildWidget = children[0];
selected.selected = true;
}
if(selected){
this._showChild(selected);
}
 
// Now publish information about myself so any StackControllers can initialize..
dojo.publish(this.id+"-startup", [{children: children, selected: selected}]);
this.inherited("startup",arguments);
this._started = true;
},
 
_setupChild: function(/*Widget*/ page){
// Summary: prepare the given child
 
page.domNode.style.display = "none";
 
// since we are setting the width/height of the child elements, they need
// to be position:relative, or IE has problems (See bug #2033)
page.domNode.style.position = "relative";
 
return page; // dijit._Widget
},
 
addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
// summary: Adds a widget to the stack
dijit._Container.prototype.addChild.apply(this, arguments);
child = this._setupChild(child);
 
if(this._started){
// in case the tab titles have overflowed from one line to two lines
this.layout();
 
dojo.publish(this.id+"-addChild", [child, insertIndex]);
 
// if this is the first child, then select it
if(!this.selectedChildWidget){
this.selectChild(child);
}
}
},
 
removeChild: function(/*Widget*/ page){
// summary: Removes the pane from the stack
 
dijit._Container.prototype.removeChild.apply(this, arguments);
 
// If we are being destroyed than don't run the code below (to select another page), because we are deleting
// every page one by one
if(this._beingDestroyed){ return; }
 
if(this._started){
// this will notify any tablists to remove a button; do this first because it may affect sizing
dojo.publish(this.id+"-removeChild", [page]);
 
// in case the tab titles now take up one line instead of two lines
this.layout();
}
 
if(this.selectedChildWidget === page){
this.selectedChildWidget = undefined;
if(this._started){
var children = this.getChildren();
if(children.length){
this.selectChild(children[0]);
}
}
}
},
 
selectChild: function(/*Widget*/ page){
// summary:
// Show the given widget (which must be one of my children)
 
page = dijit.byId(page);
 
if(this.selectedChildWidget != page){
// Deselect old page and select new one
this._transition(page, this.selectedChildWidget);
this.selectedChildWidget = page;
dojo.publish(this.id+"-selectChild", [page]);
}
},
 
_transition: function(/*Widget*/newWidget, /*Widget*/oldWidget){
if(oldWidget){
this._hideChild(oldWidget);
}
this._showChild(newWidget);
 
// Size the new widget, in case this is the first time it's being shown,
// or I have been resized since the last time it was shown.
// page must be visible for resizing to work
if(this.doLayout && newWidget.resize){
newWidget.resize(this._containerContentBox || this._contentBox);
}
},
 
_adjacent: function(/*Boolean*/ forward){
// summary: Gets the next/previous child widget in this container from the current selection
var children = this.getChildren();
var index = dojo.indexOf(children, this.selectedChildWidget);
index += forward ? 1 : children.length - 1;
return children[ index % children.length ]; // dijit._Widget
},
 
forward: function(){
// Summary: advance to next page
this.selectChild(this._adjacent(true));
},
 
back: function(){
// Summary: go back to previous page
this.selectChild(this._adjacent(false));
},
 
_onKeyPress: function(e){
dojo.publish(this.id+"-containerKeyPress", [{ e: e, page: this}]);
},
 
layout: function(){
if(this.doLayout && this.selectedChildWidget && this.selectedChildWidget.resize){
this.selectedChildWidget.resize(this._contentBox);
}
},
 
_showChild: function(/*Widget*/ page){
var children = this.getChildren();
page.isFirstChild = (page == children[0]);
page.isLastChild = (page == children[children.length-1]);
page.selected = true;
 
page.domNode.style.display="";
if(page._loadCheck){
page._loadCheck(); // trigger load in ContentPane
}
if(page.onShow){
page.onShow();
}
},
 
_hideChild: function(/*Widget*/ page){
page.selected=false;
page.domNode.style.display="none";
if(page.onHide){
page.onHide();
}
},
 
closeChild: function(/*Widget*/ page){
// summary
// callback when user clicks the [X] to remove a page
// if onClose() returns true then remove and destroy the childd
var remove = page.onClose(this, page);
if(remove){
this.removeChild(page);
// makes sure we can clean up executeScripts in ContentPane onUnLoad
page.destroy();
}
},
 
destroy: function(){
this._beingDestroyed = true;
this.inherited("destroy",arguments);
}
});
 
dojo.declare(
"dijit.layout.StackController",
[dijit._Widget, dijit._Templated, dijit._Container],
{
// summary:
// Set of buttons to select a page in a page list.
// Monitors the specified StackContainer, and whenever a page is
// added, deleted, or selected, updates itself accordingly.
 
templateString: "<span wairole='tablist' dojoAttachEvent='onkeypress' class='dijitStackController'></span>",
 
// containerId: String
// the id of the page container that I point to
containerId: "",
 
// buttonWidget: String
// the name of the button widget to create to correspond to each page
buttonWidget: "dijit.layout._StackButton",
 
postCreate: function(){
dijit.setWaiRole(this.domNode, "tablist");
 
this.pane2button = {}; // mapping from panes to buttons
this._subscriptions=[
dojo.subscribe(this.containerId+"-startup", this, "onStartup"),
dojo.subscribe(this.containerId+"-addChild", this, "onAddChild"),
dojo.subscribe(this.containerId+"-removeChild", this, "onRemoveChild"),
dojo.subscribe(this.containerId+"-selectChild", this, "onSelectChild"),
dojo.subscribe(this.containerId+"-containerKeyPress", this, "onContainerKeyPress")
];
},
 
onStartup: function(/*Object*/ info){
// summary: called after StackContainer has finished initializing
dojo.forEach(info.children, this.onAddChild, this);
this.onSelectChild(info.selected);
},
 
destroy: function(){
dojo.forEach(this._subscriptions, dojo.unsubscribe);
this.inherited("destroy",arguments);
},
 
onAddChild: function(/*Widget*/ page, /*Integer?*/ insertIndex){
// summary:
// Called whenever a page is added to the container.
// Create button corresponding to the page.
 
// add a node that will be promoted to the button widget
var refNode = document.createElement("span");
this.domNode.appendChild(refNode);
// create an instance of the button widget
var cls = dojo.getObject(this.buttonWidget);
var button = new cls({label: page.title, closeButton: page.closable}, refNode);
this.addChild(button, insertIndex);
this.pane2button[page] = button;
page.controlButton = button; // this value might be overwritten if two tabs point to same container
dojo.connect(button, "onClick", dojo.hitch(this,"onButtonClick",page));
dojo.connect(button, "onClickCloseButton", dojo.hitch(this,"onCloseButtonClick",page));
if(!this._currentChild){ // put the first child into the tab order
button.focusNode.setAttribute("tabIndex","0");
this._currentChild = page;
}
},
 
onRemoveChild: function(/*Widget*/ page){
// summary:
// Called whenever a page is removed from the container.
// Remove the button corresponding to the page.
if(this._currentChild === page){ this._currentChild = null; }
var button = this.pane2button[page];
if(button){
// TODO? if current child { reassign }
button.destroy();
}
this.pane2button[page] = null;
},
 
onSelectChild: function(/*Widget*/ page){
// summary:
// Called when a page has been selected in the StackContainer, either by me or by another StackController
 
if(!page){ return; }
 
if(this._currentChild){
var oldButton=this.pane2button[this._currentChild];
oldButton.setChecked(false);
oldButton.focusNode.setAttribute("tabIndex", "-1");
}
 
var newButton=this.pane2button[page];
newButton.setChecked(true);
this._currentChild = page;
newButton.focusNode.setAttribute("tabIndex", "0");
},
 
onButtonClick: function(/*Widget*/ page){
// summary:
// Called whenever one of my child buttons is pressed in an attempt to select a page
var container = dijit.byId(this.containerId); // TODO: do this via topics?
container.selectChild(page);
},
 
onCloseButtonClick: function(/*Widget*/ page){
// summary:
// Called whenever one of my child buttons [X] is pressed in an attempt to close a page
var container = dijit.byId(this.containerId);
container.closeChild(page);
var b = this.pane2button[this._currentChild];
if(b){
dijit.focus(b.focusNode || b.domNode);
}
},
// TODO: this is a bit redundant with forward, back api in StackContainer
adjacent: function(/*Boolean*/ forward){
// find currently focused button in children array
var children = this.getChildren();
var current = dojo.indexOf(children, this.pane2button[this._currentChild]);
// pick next button to focus on
var offset = forward ? 1 : children.length - 1;
return children[ (current + offset) % children.length ]; // dijit._Widget
},
 
onkeypress: function(/*Event*/ e){
// summary:
// Handle keystrokes on the page list, for advancing to next/previous button
// and closing the current page if the page is closable.
 
if(this.disabled || e.altKey ){ return; }
var forward = true;
if(e.ctrlKey || !e._djpage){
var k = dojo.keys;
switch(e.keyCode){
case k.LEFT_ARROW:
case k.UP_ARROW:
case k.PAGE_UP:
forward = false;
// fall through
case k.RIGHT_ARROW:
case k.DOWN_ARROW:
case k.PAGE_DOWN:
this.adjacent(forward).onClick();
dojo.stopEvent(e);
break;
case k.DELETE:
if(this._currentChild.closable){
this.onCloseButtonClick(this._currentChild);
}
dojo.stopEvent(e);
break;
default:
if(e.ctrlKey){
if(e.keyCode == k.TAB){
this.adjacent(!e.shiftKey).onClick();
dojo.stopEvent(e);
}else if(e.keyChar == "w"){
if(this._currentChild.closable){
this.onCloseButtonClick(this._currentChild);
}
dojo.stopEvent(e); // avoid browser tab closing.
}
}
}
}
},
 
onContainerKeyPress: function(/*Object*/ info){
info.e._djpage = info.page;
this.onkeypress(info.e);
}
});
 
dojo.declare("dijit.layout._StackButton",
dijit.form.ToggleButton,
{
// summary
// Internal widget used by StackContainer.
// The button-like or tab-like object you click to select or delete a page
tabIndex: "-1", // StackContainer buttons are not in the tab order by default
postCreate: function(/*Event*/ evt){
dijit.setWaiRole((this.focusNode || this.domNode), "tab");
this.inherited("postCreate", arguments);
},
onClick: function(/*Event*/ evt){
// summary: This is for TabContainer where the tabs are <span> rather than button,
// so need to set focus explicitly (on some browsers)
dijit.focus(this.focusNode);
 
// ... now let StackController catch the event and tell me what to do
},
 
onClickCloseButton: function(/*Event*/ evt){
// summary
// StackContainer connects to this function; if your widget contains a close button
// then clicking it should call this function.
evt.stopPropagation();
}
});
 
// These arguments can be specified for the children of a StackContainer.
// Since any widget can be specified as a StackContainer child, mix them
// into the base widget class. (This is a hack, but it's effective.)
dojo.extend(dijit._Widget, {
// title: String
// Title of this widget. Used by TabContainer to the name the tab, etc.
title: "",
 
// selected: Boolean
// Is this child currently selected?
selected: false,
 
// closable: Boolean
// True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
closable: false, // true if user can close this tab pane
 
onClose: function(){
// summary: Callback if someone tries to close the child, child will be closed if func returns true
return true;
}
});
 
}
/trunk/api/js/dojo1.0/dijit/layout/TabContainer.js
New file
0,0 → 1,146
if(!dojo._hasResource["dijit.layout.TabContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.TabContainer"] = true;
dojo.provide("dijit.layout.TabContainer");
 
dojo.require("dijit.layout.StackContainer");
dojo.require("dijit._Templated");
 
dojo.declare("dijit.layout.TabContainer",
[dijit.layout.StackContainer, dijit._Templated],
{
// summary:
// A Container with Title Tabs, each one pointing at a pane in the container.
// description:
// A TabContainer is a container that has multiple panes, but shows only
// one pane at a time. There are a set of tabs corresponding to each pane,
// where each tab has the title (aka title) of the pane, and optionally a close button.
//
// Publishes topics <widgetId>-addChild, <widgetId>-removeChild, and <widgetId>-selectChild
// (where <widgetId> is the id of the TabContainer itself.
//
// tabPosition: String
// Defines where tabs go relative to tab content.
// "top", "bottom", "left-h", "right-h"
tabPosition: "top",
 
templateString: null, // override setting in StackContainer
templateString:"<div class=\"dijitTabContainer\">\n\t<div dojoAttachPoint=\"tablistNode\"></div>\n\t<div class=\"dijitTabPaneWrapper\" dojoAttachPoint=\"containerNode\"></div>\n</div>\n",
 
postCreate: function(){
dijit.layout.TabContainer.superclass.postCreate.apply(this, arguments);
// create the tab list that will have a tab (a.k.a. tab button) for each tab panel
this.tablist = new dijit.layout.TabController(
{
id: this.id + "_tablist",
tabPosition: this.tabPosition,
doLayout: this.doLayout,
containerId: this.id
}, this.tablistNode);
},
 
_setupChild: function(/* Widget */tab){
dojo.addClass(tab.domNode, "dijitTabPane");
this.inherited("_setupChild",arguments);
return tab; // Widget
},
 
startup: function(){
if(this._started){ return; }
 
// wire up the tablist and its tabs
this.tablist.startup();
this.inherited("startup",arguments);
 
if(dojo.isSafari){
// sometimes safari 3.0.3 miscalculates the height of the tab labels, see #4058
setTimeout(dojo.hitch(this, "layout"), 0);
}
},
 
layout: function(){
// Summary: Configure the content pane to take up all the space except for where the tabs are
if(!this.doLayout){ return; }
 
// position and size the titles and the container node
var titleAlign=this.tabPosition.replace(/-h/,"");
var children = [
{domNode: this.tablist.domNode, layoutAlign: titleAlign},
{domNode: this.containerNode, layoutAlign: "client"}
];
dijit.layout.layoutChildren(this.domNode, this._contentBox, children);
 
// Compute size to make each of my children.
// children[1] is the margin-box size of this.containerNode, set by layoutChildren() call above
this._containerContentBox = dijit.layout.marginBox2contentBox(this.containerNode, children[1]);
 
if(this.selectedChildWidget){
this._showChild(this.selectedChildWidget);
if(this.doLayout && this.selectedChildWidget.resize){
this.selectedChildWidget.resize(this._containerContentBox);
}
}
},
 
destroy: function(){
this.tablist.destroy();
this.inherited("destroy",arguments);
}
});
 
//TODO: make private?
dojo.declare("dijit.layout.TabController",
dijit.layout.StackController,
{
// summary:
// Set of tabs (the things with titles and a close button, that you click to show a tab panel).
// description:
// Lets the user select the currently shown pane in a TabContainer or StackContainer.
// TabController also monitors the TabContainer, and whenever a pane is
// added or deleted updates itself accordingly.
 
templateString: "<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'></div>",
 
// tabPosition: String
// Defines where tabs go relative to the content.
// "top", "bottom", "left-h", "right-h"
tabPosition: "top",
 
// doLayout: Boolean
// TODOC: deprecate doLayout? not sure.
doLayout: true,
 
// buttonWidget: String
// the name of the tab widget to create to correspond to each page
buttonWidget: "dijit.layout._TabButton",
 
postMixInProperties: function(){
this["class"] = "dijitTabLabels-" + this.tabPosition + (this.doLayout ? "" : " dijitTabNoLayout");
this.inherited("postMixInProperties",arguments);
}
});
 
dojo.declare("dijit.layout._TabButton",
dijit.layout._StackButton,
{
// summary:
// A tab (the thing you click to select a pane).
// description:
// Contains the title of the pane, and optionally a close-button to destroy the pane.
// This is an internal widget and should not be instantiated directly.
 
baseClass: "dijitTab",
 
templateString:"<div dojoAttachEvent='onclick:onClick,onmouseenter:_onMouse,onmouseleave:_onMouse'>\n <div class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>\n <span dojoAttachPoint='containerNode,focusNode'>${!label}</span>\n <span dojoAttachPoint='closeButtonNode' class='closeImage' dojoAttachEvent='onmouseenter:_onMouse, onmouseleave:_onMouse, onclick:onClickCloseButton' stateModifier='CloseButton'>\n <span dojoAttachPoint='closeText' class='closeText'>x</span>\n </span>\n </div>\n</div>\n",
 
postCreate: function(){
if(this.closeButton){
dojo.addClass(this.innerDiv, "dijitClosable");
} else {
this.closeButtonNode.style.display="none";
}
this.inherited("postCreate",arguments);
dojo.setSelectable(this.containerNode, false);
}
});
 
}
/trunk/api/js/dojo1.0/dijit/layout/ContentPane.js
New file
0,0 → 1,409
if(!dojo._hasResource["dijit.layout.ContentPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.ContentPane"] = true;
dojo.provide("dijit.layout.ContentPane");
 
dojo.require("dijit._Widget");
dojo.require("dijit.layout._LayoutWidget");
 
dojo.require("dojo.parser");
dojo.require("dojo.string");
dojo.requireLocalization("dijit", "loading", null, "ko,zh,ja,zh-tw,ru,it,ROOT,hu,fr,pt,pl,es,de,cs");
 
dojo.declare(
"dijit.layout.ContentPane",
dijit._Widget,
{
// summary:
// A widget that acts as a Container for other widgets, and includes a ajax interface
// description:
// A widget that can be used as a standalone widget
// or as a baseclass for other widgets
// Handles replacement of document fragment using either external uri or javascript
// generated markup or DOM content, instantiating widgets within that content.
// Don't confuse it with an iframe, it only needs/wants document fragments.
// It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
// But note that those classes can contain any widget as a child.
// example:
// Some quick samples:
// To change the innerHTML use .setContent('<b>new content</b>')
//
// Or you can send it a NodeList, .setContent(dojo.query('div [class=selected]', userSelection))
// please note that the nodes in NodeList will copied, not moved
//
// To do a ajax update use .setHref('url')
//
// href: String
// The href of the content that displays now.
// Set this at construction if you want to load data externally when the
// pane is shown. (Set preload=true to load it immediately.)
// Changing href after creation doesn't have any effect; see setHref();
href: "",
 
// extractContent: Boolean
// Extract visible content from inside of <body> .... </body>
extractContent: false,
 
// parseOnLoad: Boolean
// parse content and create the widgets, if any
parseOnLoad: true,
 
// preventCache: Boolean
// Cache content retreived externally
preventCache: false,
 
// preload: Boolean
// Force load of data even if pane is hidden.
preload: false,
 
// refreshOnShow: Boolean
// Refresh (re-download) content when pane goes from hidden to shown
refreshOnShow: false,
 
// loadingMessage: String
// Message that shows while downloading
loadingMessage: "<span class='dijitContentPaneLoading'>${loadingState}</span>",
 
// errorMessage: String
// Message that shows if an error occurs
errorMessage: "<span class='dijitContentPaneError'>${errorState}</span>",
 
// isLoaded: Boolean
// Tells loading status see onLoad|onUnload for event hooks
isLoaded: false,
 
// class: String
// Class name to apply to ContentPane dom nodes
"class": "dijitContentPane",
 
postCreate: function(){
// remove the title attribute so it doesn't show up when i hover
// over a node
this.domNode.title = "";
 
if(this.preload){
this._loadCheck();
}
 
var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
 
// for programatically created ContentPane (with <span> tag), need to muck w/CSS
// or it's as though overflow:visible is set
dojo.addClass(this.domNode, this["class"]);
},
 
startup: function(){
if(this._started){ return; }
this._checkIfSingleChild();
if(this._singleChild){
this._singleChild.startup();
}
this._loadCheck();
this._started = true;
},
 
_checkIfSingleChild: function(){
// summary:
// Test if we have exactly one widget as a child, and if so assume that we are a container for that widget,
// and should propogate startup() and resize() calls to it.
var childNodes = dojo.query(">", this.containerNode || this.domNode),
childWidgets = childNodes.filter("[widgetId]");
 
if(childNodes.length == 1 && childWidgets.length == 1){
this.isContainer = true;
this._singleChild = dijit.byNode(childWidgets[0]);
}else{
delete this.isContainer;
delete this._singleChild;
}
},
 
refresh: function(){
// summary:
// Force a refresh (re-download) of content, be sure to turn off cache
 
// we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPane
return this._prepareLoad(true);
},
 
setHref: function(/*String|Uri*/ href){
// summary:
// Reset the (external defined) content of this pane and replace with new url
// Note: It delays the download until widget is shown if preload is false
// href:
// url to the page you want to get, must be within the same domain as your mainpage
this.href = href;
 
// we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPane
return this._prepareLoad();
},
 
setContent: function(/*String|DomNode|Nodelist*/data){
// summary:
// Replaces old content with data content, include style classes from old content
// data:
// the new Content may be String, DomNode or NodeList
//
// if data is a NodeList (or an array of nodes) nodes are copied
// so you can import nodes from another document implicitly
 
// clear href so we cant run refresh and clear content
// refresh should only work if we downloaded the content
if(!this._isDownloaded){
this.href = "";
this._onUnloadHandler();
}
 
this._setContent(data || "");
 
this._isDownloaded = false; // must be set after _setContent(..), pathadjust in dojox.layout.ContentPane
 
if(this.parseOnLoad){
this._createSubWidgets();
}
 
this._checkIfSingleChild();
if(this._singleChild && this._singleChild.resize){
this._singleChild.resize(this._contentBox);
}
 
this._onLoadHandler();
},
 
cancel: function(){
// summary:
// Cancels a inflight download of content
if(this._xhrDfd && (this._xhrDfd.fired == -1)){
this._xhrDfd.cancel();
}
delete this._xhrDfd; // garbage collect
},
 
destroy: function(){
// if we have multiple controllers destroying us, bail after the first
if(this._beingDestroyed){
return;
}
// make sure we call onUnload
this._onUnloadHandler();
this._beingDestroyed = true;
this.inherited("destroy",arguments);
},
 
resize: function(size){
dojo.marginBox(this.domNode, size);
 
// Compute content box size in case we [later] need to size child
// If either height or width wasn't specified by the user, then query node for it.
// But note that setting the margin box and then immediately querying dimensions may return
// inaccurate results, so try not to depend on it.
var node = this.containerNode || this.domNode,
mb = dojo.mixin(dojo.marginBox(node), size||{});
 
this._contentBox = dijit.layout.marginBox2contentBox(node, mb);
 
// If we have a single widget child then size it to fit snugly within my borders
if(this._singleChild && this._singleChild.resize){
this._singleChild.resize(this._contentBox);
}
},
 
_prepareLoad: function(forceLoad){
// sets up for a xhrLoad, load is deferred until widget onShow
// cancels a inflight download
this.cancel();
this.isLoaded = false;
this._loadCheck(forceLoad);
},
 
_loadCheck: function(forceLoad){
// call this when you change onShow (onSelected) status when selected in parent container
// it's used as a trigger for href download when this.domNode.display != 'none'
 
// sequence:
// if no href -> bail
// forceLoad -> always load
// this.preload -> load when download not in progress, domNode display doesn't matter
// this.refreshOnShow -> load when download in progress bails, domNode display !='none' AND
// this.open !== false (undefined is ok), isLoaded doesn't matter
// else -> load when download not in progress, if this.open !== false (undefined is ok) AND
// domNode display != 'none', isLoaded must be false
 
var displayState = ((this.open !== false) && (this.domNode.style.display != 'none'));
 
if(this.href &&
(forceLoad ||
(this.preload && !this._xhrDfd) ||
(this.refreshOnShow && displayState && !this._xhrDfd) ||
(!this.isLoaded && displayState && !this._xhrDfd)
)
){
this._downloadExternalContent();
}
},
 
_downloadExternalContent: function(){
this._onUnloadHandler();
 
// display loading message
this._setContent(
this.onDownloadStart.call(this)
);
 
var self = this;
var getArgs = {
preventCache: (this.preventCache || this.refreshOnShow),
url: this.href,
handleAs: "text"
};
if(dojo.isObject(this.ioArgs)){
dojo.mixin(getArgs, this.ioArgs);
}
 
var hand = this._xhrDfd = (this.ioMethod || dojo.xhrGet)(getArgs);
 
hand.addCallback(function(html){
try{
self.onDownloadEnd.call(self);
self._isDownloaded = true;
self.setContent.call(self, html); // onload event is called from here
}catch(err){
self._onError.call(self, 'Content', err); // onContentError
}
delete self._xhrDfd;
return html;
});
 
hand.addErrback(function(err){
if(!hand.cancelled){
// show error message in the pane
self._onError.call(self, 'Download', err); // onDownloadError
}
delete self._xhrDfd;
return err;
});
},
 
_onLoadHandler: function(){
this.isLoaded = true;
try{
this.onLoad.call(this);
}catch(e){
console.error('Error '+this.widgetId+' running custom onLoad code');
}
},
 
_onUnloadHandler: function(){
this.isLoaded = false;
this.cancel();
try{
this.onUnload.call(this);
}catch(e){
console.error('Error '+this.widgetId+' running custom onUnload code');
}
},
 
_setContent: function(cont){
this.destroyDescendants();
 
try{
var node = this.containerNode || this.domNode;
while(node.firstChild){
dojo._destroyElement(node.firstChild);
}
if(typeof cont == "string"){
// dijit.ContentPane does only minimal fixes,
// No pathAdjustments, script retrieval, style clean etc
// some of these should be available in the dojox.layout.ContentPane
if(this.extractContent){
match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
if(match){ cont = match[1]; }
}
node.innerHTML = cont;
}else{
// domNode or NodeList
if(cont.nodeType){ // domNode (htmlNode 1 or textNode 3)
node.appendChild(cont);
}else{// nodelist or array such as dojo.Nodelist
dojo.forEach(cont, function(n){
node.appendChild(n.cloneNode(true));
});
}
}
}catch(e){
// check if a domfault occurs when we are appending this.errorMessage
// like for instance if domNode is a UL and we try append a DIV
var errMess = this.onContentError(e);
try{
node.innerHTML = errMess;
}catch(e){
console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
}
}
},
 
_onError: function(type, err, consoleText){
// shows user the string that is returned by on[type]Error
// overide on[type]Error and return your own string to customize
var errText = this['on' + type + 'Error'].call(this, err);
if(consoleText){
console.error(consoleText, err);
}else if(errText){// a empty string won't change current content
this._setContent.call(this, errText);
}
},
 
_createSubWidgets: function(){
// summary: scan my contents and create subwidgets
var rootNode = this.containerNode || this.domNode;
try{
dojo.parser.parse(rootNode, true);
}catch(e){
this._onError('Content', e, "Couldn't create widgets in "+this.id
+(this.href ? " from "+this.href : ""));
}
},
 
// EVENT's, should be overide-able
onLoad: function(e){
// summary:
// Event hook, is called after everything is loaded and widgetified
},
 
onUnload: function(e){
// summary:
// Event hook, is called before old content is cleared
},
 
onDownloadStart: function(){
// summary:
// called before download starts
// the string returned by this function will be the html
// that tells the user we are loading something
// override with your own function if you want to change text
return this.loadingMessage;
},
 
onContentError: function(/*Error*/ error){
// summary:
// called on DOM faults, require fault etc in content
// default is to display errormessage inside pane
},
 
onDownloadError: function(/*Error*/ error){
// summary:
// Called when download error occurs, default is to display
// errormessage inside pane. Overide function to change that.
// The string returned by this function will be the html
// that tells the user a error happend
return this.errorMessage;
},
 
onDownloadEnd: function(){
// summary:
// called when download is finished
}
});
 
}
/trunk/api/js/dojo1.0/dijit/layout/SplitContainer.js
New file
0,0 → 1,537
if(!dojo._hasResource["dijit.layout.SplitContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.SplitContainer"] = true;
dojo.provide("dijit.layout.SplitContainer");
 
//
// FIXME: make it prettier
// FIXME: active dragging upwards doesn't always shift other bars (direction calculation is wrong in this case)
//
 
dojo.require("dojo.cookie");
dojo.require("dijit.layout._LayoutWidget");
 
dojo.declare("dijit.layout.SplitContainer",
dijit.layout._LayoutWidget,
{
// summary:
// A Container widget with sizing handles in-between each child
// description:
// Contains multiple children widgets, all of which are displayed side by side
// (either horizontally or vertically); there's a bar between each of the children,
// and you can adjust the relative size of each child by dragging the bars.
//
// You must specify a size (width and height) for the SplitContainer.
//
// activeSizing: Boolean
// If true, the children's size changes as you drag the bar;
// otherwise, the sizes don't change until you drop the bar (by mouse-up)
activeSizing: false,
 
// sizerWidth: Integer
// Size in pixels of the bar between each child
sizerWidth: 7, // FIXME: this should be a CSS attribute (at 7 because css wants it to be 7 until we fix to css)
 
// orientation: String
// either 'horizontal' or vertical; indicates whether the children are
// arranged side-by-side or up/down.
orientation: 'horizontal',
 
// persist: Boolean
// Save splitter positions in a cookie
persist: true,
 
postMixInProperties: function(){
this.inherited("postMixInProperties",arguments);
this.isHorizontal = (this.orientation == 'horizontal');
},
 
postCreate: function(){
this.inherited("postCreate",arguments);
this.sizers = [];
dojo.addClass(this.domNode, "dijitSplitContainer");
// overflow has to be explicitly hidden for splitContainers using gekko (trac #1435)
// to keep other combined css classes from inadvertantly making the overflow visible
if(dojo.isMozilla){
this.domNode.style.overflow = '-moz-scrollbars-none'; // hidden doesn't work
}
 
// create the fake dragger
if(typeof this.sizerWidth == "object"){
try{ //FIXME: do this without a try/catch
this.sizerWidth = parseInt(this.sizerWidth.toString());
}catch(e){ this.sizerWidth = 7; }
}
var sizer = this.virtualSizer = document.createElement('div');
sizer.style.position = 'relative';
 
// #1681: work around the dreaded 'quirky percentages in IE' layout bug
// If the splitcontainer's dimensions are specified in percentages, it
// will be resized when the virtualsizer is displayed in _showSizingLine
// (typically expanding its bounds unnecessarily). This happens because
// we use position: relative for .dijitSplitContainer.
// The workaround: instead of changing the display style attribute,
// switch to changing the zIndex (bring to front/move to back)
 
sizer.style.zIndex = 10;
sizer.className = this.isHorizontal ? 'dijitSplitContainerVirtualSizerH' : 'dijitSplitContainerVirtualSizerV';
this.domNode.appendChild(sizer);
dojo.setSelectable(sizer, false);
},
 
startup: function(){
if(this._started){ return; }
dojo.forEach(this.getChildren(), function(child, i, children){
// attach the children and create the draggers
this._injectChild(child);
 
if(i < children.length-1){
this._addSizer();
}
}, this);
 
if(this.persist){
this._restoreState();
}
this.inherited("startup",arguments);
this._started = true;
},
 
_injectChild: function(child){
child.domNode.style.position = "absolute";
dojo.addClass(child.domNode, "dijitSplitPane");
},
 
_addSizer: function(){
var i = this.sizers.length;
 
// TODO: use a template for this!!!
var sizer = this.sizers[i] = document.createElement('div');
sizer.className = this.isHorizontal ? 'dijitSplitContainerSizerH' : 'dijitSplitContainerSizerV';
 
// add the thumb div
var thumb = document.createElement('div');
thumb.className = 'thumb';
sizer.appendChild(thumb);
 
// FIXME: are you serious? why aren't we using mover start/stop combo?
var self = this;
var handler = (function(){ var sizer_i = i; return function(e){ self.beginSizing(e, sizer_i); } })();
dojo.connect(sizer, "onmousedown", handler);
 
this.domNode.appendChild(sizer);
dojo.setSelectable(sizer, false);
},
 
removeChild: function(widget){
// summary: Remove sizer, but only if widget is really our child and
// we have at least one sizer to throw away
if(this.sizers.length && dojo.indexOf(this.getChildren(), widget) != -1){
var i = this.sizers.length - 1;
dojo._destroyElement(this.sizers[i]);
this.sizers.length--;
}
 
// Remove widget and repaint
this.inherited("removeChild",arguments);
if(this._started){
this.layout();
}
},
 
addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
// summary: Add a child widget to the container
// child: a widget to add
// insertIndex: postion in the "stack" to add the child widget
this.inherited("addChild",arguments);
 
if(this._started){
// Do the stuff that startup() does for each widget
this._injectChild(child);
var children = this.getChildren();
if(children.length > 1){
this._addSizer();
}
 
// and then reposition (ie, shrink) every pane to make room for the new guy
this.layout();
}
},
 
layout: function(){
// summary:
// Do layout of panels
 
// base class defines this._contentBox on initial creation and also
// on resize
this.paneWidth = this._contentBox.w;
this.paneHeight = this._contentBox.h;
 
var children = this.getChildren();
if(!children.length){ return; }
 
//
// calculate space
//
 
var space = this.isHorizontal ? this.paneWidth : this.paneHeight;
if(children.length > 1){
space -= this.sizerWidth * (children.length - 1);
}
 
//
// calculate total of SizeShare values
//
var outOf = 0;
dojo.forEach(children, function(child){
outOf += child.sizeShare;
});
 
//
// work out actual pixels per sizeshare unit
//
var pixPerUnit = space / outOf;
 
//
// set the SizeActual member of each pane
//
var totalSize = 0;
dojo.forEach(children.slice(0, children.length - 1), function(child){
var size = Math.round(pixPerUnit * child.sizeShare);
child.sizeActual = size;
totalSize += size;
});
 
children[children.length-1].sizeActual = space - totalSize;
 
//
// make sure the sizes are ok
//
this._checkSizes();
 
//
// now loop, positioning each pane and letting children resize themselves
//
 
var pos = 0;
var size = children[0].sizeActual;
this._movePanel(children[0], pos, size);
children[0].position = pos;
pos += size;
 
// if we don't have any sizers, our layout method hasn't been called yet
// so bail until we are called..TODO: REVISIT: need to change the startup
// algorithm to guaranteed the ordering of calls to layout method
if(!this.sizers){
return;
}
 
dojo.some(children.slice(1), function(child, i){
// error-checking
if(!this.sizers[i]){
return true;
}
// first we position the sizing handle before this pane
this._moveSlider(this.sizers[i], pos, this.sizerWidth);
this.sizers[i].position = pos;
pos += this.sizerWidth;
 
size = child.sizeActual;
this._movePanel(child, pos, size);
child.position = pos;
pos += size;
}, this);
},
 
_movePanel: function(panel, pos, size){
if(this.isHorizontal){
panel.domNode.style.left = pos + 'px'; // TODO: resize() takes l and t parameters too, don't need to set manually
panel.domNode.style.top = 0;
var box = {w: size, h: this.paneHeight};
if(panel.resize){
panel.resize(box);
}else{
dojo.marginBox(panel.domNode, box);
}
}else{
panel.domNode.style.left = 0; // TODO: resize() takes l and t parameters too, don't need to set manually
panel.domNode.style.top = pos + 'px';
var box = {w: this.paneWidth, h: size};
if(panel.resize){
panel.resize(box);
}else{
dojo.marginBox(panel.domNode, box);
}
}
},
 
_moveSlider: function(slider, pos, size){
if(this.isHorizontal){
slider.style.left = pos + 'px';
slider.style.top = 0;
dojo.marginBox(slider, { w: size, h: this.paneHeight });
}else{
slider.style.left = 0;
slider.style.top = pos + 'px';
dojo.marginBox(slider, { w: this.paneWidth, h: size });
}
},
 
_growPane: function(growth, pane){
if(growth > 0){
if(pane.sizeActual > pane.sizeMin){
if((pane.sizeActual - pane.sizeMin) > growth){
 
// stick all the growth in this pane
pane.sizeActual = pane.sizeActual - growth;
growth = 0;
}else{
// put as much growth in here as we can
growth -= pane.sizeActual - pane.sizeMin;
pane.sizeActual = pane.sizeMin;
}
}
}
return growth;
},
 
_checkSizes: function(){
 
var totalMinSize = 0;
var totalSize = 0;
var children = this.getChildren();
 
dojo.forEach(children, function(child){
totalSize += child.sizeActual;
totalMinSize += child.sizeMin;
});
 
// only make adjustments if we have enough space for all the minimums
 
if(totalMinSize <= totalSize){
 
var growth = 0;
 
dojo.forEach(children, function(child){
if(child.sizeActual < child.sizeMin){
growth += child.sizeMin - child.sizeActual;
child.sizeActual = child.sizeMin;
}
});
 
if(growth > 0){
var list = this.isDraggingLeft ? children.reverse() : children;
dojo.forEach(list, function(child){
growth = this._growPane(growth, child);
}, this);
}
}else{
dojo.forEach(children, function(child){
child.sizeActual = Math.round(totalSize * (child.sizeMin / totalMinSize));
});
}
},
 
beginSizing: function(e, i){
var children = this.getChildren();
this.paneBefore = children[i];
this.paneAfter = children[i+1];
 
this.isSizing = true;
this.sizingSplitter = this.sizers[i];
 
if(!this.cover){
this.cover = dojo.doc.createElement('div');
this.domNode.appendChild(this.cover);
var s = this.cover.style;
s.position = 'absolute';
s.zIndex = 1;
s.top = 0;
s.left = 0;
s.width = "100%";
s.height = "100%";
}else{
this.cover.style.zIndex = 1;
}
this.sizingSplitter.style.zIndex = 2;
 
// TODO: REVISIT - we want MARGIN_BOX and core hasn't exposed that yet (but can't we use it anyway if we pay attention? we do elsewhere.)
this.originPos = dojo.coords(children[0].domNode, true);
if(this.isHorizontal){
var client = (e.layerX ? e.layerX : e.offsetX);
var screen = e.pageX;
this.originPos = this.originPos.x;
}else{
var client = (e.layerY ? e.layerY : e.offsetY);
var screen = e.pageY;
this.originPos = this.originPos.y;
}
this.startPoint = this.lastPoint = screen;
this.screenToClientOffset = screen - client;
this.dragOffset = this.lastPoint - this.paneBefore.sizeActual - this.originPos - this.paneBefore.position;
 
if(!this.activeSizing){
this._showSizingLine();
}
 
//
// attach mouse events
//
this._connects = [];
this._connects.push(dojo.connect(document.documentElement, "onmousemove", this, "changeSizing"));
this._connects.push(dojo.connect(document.documentElement, "onmouseup", this, "endSizing"));
 
dojo.stopEvent(e);
},
 
changeSizing: function(e){
if(!this.isSizing){ return; }
this.lastPoint = this.isHorizontal ? e.pageX : e.pageY;
this.movePoint();
if(this.activeSizing){
this._updateSize();
}else{
this._moveSizingLine();
}
dojo.stopEvent(e);
},
 
endSizing: function(e){
if(!this.isSizing){ return; }
if(this.cover){
this.cover.style.zIndex = -1;
}
if(!this.activeSizing){
this._hideSizingLine();
}
 
this._updateSize();
 
this.isSizing = false;
 
if(this.persist){
this._saveState(this);
}
 
dojo.forEach(this._connects,dojo.disconnect);
},
 
movePoint: function(){
 
// make sure lastPoint is a legal point to drag to
var p = this.lastPoint - this.screenToClientOffset;
 
var a = p - this.dragOffset;
a = this.legaliseSplitPoint(a);
p = a + this.dragOffset;
 
this.lastPoint = p + this.screenToClientOffset;
},
 
legaliseSplitPoint: function(a){
 
a += this.sizingSplitter.position;
 
this.isDraggingLeft = !!(a > 0);
 
if(!this.activeSizing){
var min = this.paneBefore.position + this.paneBefore.sizeMin;
if(a < min){
a = min;
}
 
var max = this.paneAfter.position + (this.paneAfter.sizeActual - (this.sizerWidth + this.paneAfter.sizeMin));
if(a > max){
a = max;
}
}
 
a -= this.sizingSplitter.position;
 
this._checkSizes();
 
return a;
},
 
_updateSize: function(){
//FIXME: sometimes this.lastPoint is NaN
var pos = this.lastPoint - this.dragOffset - this.originPos;
 
var start_region = this.paneBefore.position;
var end_region = this.paneAfter.position + this.paneAfter.sizeActual;
 
this.paneBefore.sizeActual = pos - start_region;
this.paneAfter.position = pos + this.sizerWidth;
this.paneAfter.sizeActual = end_region - this.paneAfter.position;
 
dojo.forEach(this.getChildren(), function(child){
child.sizeShare = child.sizeActual;
});
 
if(this._started){
this.layout();
}
},
 
_showSizingLine: function(){
 
this._moveSizingLine();
 
dojo.marginBox(this.virtualSizer,
this.isHorizontal ? { w: this.sizerWidth, h: this.paneHeight } : { w: this.paneWidth, h: this.sizerWidth });
 
this.virtualSizer.style.display = 'block';
},
 
_hideSizingLine: function(){
this.virtualSizer.style.display = 'none';
},
 
_moveSizingLine: function(){
var pos = (this.lastPoint - this.startPoint) + this.sizingSplitter.position;
dojo.style(this.virtualSizer,(this.isHorizontal ? "left" : "top"),pos+"px");
// this.virtualSizer.style[ this.isHorizontal ? "left" : "top" ] = pos + 'px'; // FIXME: remove this line if the previous is better
},
 
_getCookieName: function(i){
return this.id + "_" + i;
},
 
_restoreState: function(){
dojo.forEach(this.getChildren(), function(child, i){
var cookieName = this._getCookieName(i);
var cookieValue = dojo.cookie(cookieName);
if(cookieValue){
var pos = parseInt(cookieValue);
if(typeof pos == "number"){
child.sizeShare = pos;
}
}
}, this);
},
 
_saveState: function(){
dojo.forEach(this.getChildren(), function(child, i){
dojo.cookie(this._getCookieName(i), child.sizeShare);
}, this);
}
});
 
// These arguments can be specified for the children of a SplitContainer.
// Since any widget can be specified as a SplitContainer child, mix them
// into the base widget class. (This is a hack, but it's effective.)
dojo.extend(dijit._Widget, {
// sizeMin: Integer
// Minimum size (width or height) of a child of a SplitContainer.
// The value is relative to other children's sizeShare properties.
sizeMin: 10,
 
// sizeShare: Integer
// Size (width or height) of a child of a SplitContainer.
// The value is relative to other children's sizeShare properties.
// For example, if there are two children and each has sizeShare=10, then
// each takes up 50% of the available space.
sizeShare: 10
});
 
}
/trunk/api/js/dojo1.0/dijit/layout/LayoutContainer.js
New file
0,0 → 1,71
if(!dojo._hasResource["dijit.layout.LayoutContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.LayoutContainer"] = true;
dojo.provide("dijit.layout.LayoutContainer");
 
dojo.require("dijit.layout._LayoutWidget");
 
dojo.declare(
"dijit.layout.LayoutContainer",
dijit.layout._LayoutWidget,
{
// summary
// Provides Delphi-style panel layout semantics.
//
// details
// A LayoutContainer is a box with a specified size (like style="width: 500px; height: 500px;"),
// that contains children widgets marked with "layoutAlign" of "left", "right", "bottom", "top", and "client".
// It takes it's children marked as left/top/bottom/right, and lays them out along the edges of the box,
// and then it takes the child marked "client" and puts it into the remaining space in the middle.
//
// Left/right positioning is similar to CSS's "float: left" and "float: right",
// and top/bottom positioning would be similar to "float: top" and "float: bottom", if there were such
// CSS.
//
// Note that there can only be one client element, but there can be multiple left, right, top,
// or bottom elements.
//
// usage
// <style>
// html, body{ height: 100%; width: 100%; }
// </style>
// <div dojoType="dijit.layout.LayoutContainer" style="width: 100%; height: 100%">
// <div dojoType="dijit.layout.ContentPane" layoutAlign="top">header text</div>
// <div dojoType="dijit.layout.ContentPane" layoutAlign="left" style="width: 200px;">table of contents</div>
// <div dojoType="dijit.layout.ContentPane" layoutAlign="client">client area</div>
// </div>
//
// Lays out each child in the natural order the children occur in.
// Basically each child is laid out into the "remaining space", where "remaining space" is initially
// the content area of this widget, but is reduced to a smaller rectangle each time a child is added.
//
 
layout: function(){
dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
},
 
addChild: function(/*Widget*/ child, /*Integer?*/ insertIndex){
dijit._Container.prototype.addChild.apply(this, arguments);
if(this._started){
dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
}
},
 
removeChild: function(/*Widget*/ widget){
dijit._Container.prototype.removeChild.apply(this, arguments);
if(this._started){
dijit.layout.layoutChildren(this.domNode, this._contentBox, this.getChildren());
}
}
});
 
// This argument can be specified for the children of a LayoutContainer.
// Since any widget can be specified as a LayoutContainer child, mix it
// into the base widget class. (This is a hack, but it's effective.)
dojo.extend(dijit._Widget, {
// layoutAlign: String
// "none", "left", "right", "bottom", "top", and "client".
// See the LayoutContainer description for details on this parameter.
layoutAlign: 'none'
});
 
}
/trunk/api/js/dojo1.0/dijit/layout/_LayoutWidget.js
New file
0,0 → 1,187
if(!dojo._hasResource["dijit.layout._LayoutWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout._LayoutWidget"] = true;
dojo.provide("dijit.layout._LayoutWidget");
 
dojo.require("dijit._Widget");
dojo.require("dijit._Container");
 
dojo.declare("dijit.layout._LayoutWidget",
[dijit._Widget, dijit._Container, dijit._Contained],
{
// summary
// Mixin for widgets that contain a list of children like SplitContainer.
// Widgets which mixin this code must define layout() to lay out the children
 
isLayoutContainer: true,
 
postCreate: function(){
dojo.addClass(this.domNode, "dijitContainer");
},
 
startup: function(){
// summary:
// Called after all the widgets have been instantiated and their
// dom nodes have been inserted somewhere under document.body.
//
// Widgets should override this method to do any initialization
// dependent on other widgets existing, and then call
// this superclass method to finish things off.
//
// startup() in subclasses shouldn't do anything
// size related because the size of the widget hasn't been set yet.
 
if(this._started){ return; }
this._started=true;
 
if(this.getChildren){
dojo.forEach(this.getChildren(), function(child){ child.startup(); });
}
 
// If I am a top level widget
if(!this.getParent || !this.getParent()){
// Do recursive sizing and layout of all my descendants
// (passing in no argument to resize means that it has to glean the size itself)
this.resize();
 
// since my parent isn't a layout container, and my style is width=height=100% (or something similar),
// then I need to watch when the window resizes, and size myself accordingly
// (passing in no argument to resize means that it has to glean the size itself)
this.connect(window, 'onresize', function(){this.resize();});
}
},
 
resize: function(args){
// summary:
// Explicitly set this widget's size (in pixels),
// and then call layout() to resize contents (and maybe adjust child widgets)
//
// args: Object?
// {w: int, h: int, l: int, t: int}
 
var node = this.domNode;
 
// set margin box size, unless it wasn't specified, in which case use current size
if(args){
dojo.marginBox(node, args);
 
// set offset of the node
if(args.t){ node.style.top = args.t + "px"; }
if(args.l){ node.style.left = args.l + "px"; }
}
// If either height or width wasn't specified by the user, then query node for it.
// But note that setting the margin box and then immediately querying dimensions may return
// inaccurate results, so try not to depend on it.
var mb = dojo.mixin(dojo.marginBox(node), args||{});
 
// Save the size of my content box.
this._contentBox = dijit.layout.marginBox2contentBox(node, mb);
 
// Callback for widget to adjust size of it's children
this.layout();
},
 
layout: function(){
// summary
// Widgets override this method to size & position their contents/children.
// When this is called this._contentBox is guaranteed to be set (see resize()).
//
// This is called after startup(), and also when the widget's size has been
// changed.
}
}
);
 
dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
// summary:
// Given the margin-box size of a node, return it's content box size.
// Functions like dojo.contentBox() but is more reliable since it doesn't have
// to wait for the browser to compute sizes.
var cs = dojo.getComputedStyle(node);
var me=dojo._getMarginExtents(node, cs);
var pb=dojo._getPadBorderExtents(node, cs);
return {
l: dojo._toPixelValue(node, cs.paddingLeft),
t: dojo._toPixelValue(node, cs.paddingTop),
w: mb.w - (me.w + pb.w),
h: mb.h - (me.h + pb.h)
};
};
 
(function(){
var capitalize = function(word){
return word.substring(0,1).toUpperCase() + word.substring(1);
};
 
var size = function(widget, dim){
// size the child
widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim);
 
// record child's size, but favor our own numbers when we have them.
// the browser lies sometimes
dojo.mixin(widget, dojo.marginBox(widget.domNode));
dojo.mixin(widget, dim);
};
 
dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
/**
* summary
* Layout a bunch of child dom nodes within a parent dom node
* container:
* parent node
* dim:
* {l, t, w, h} object specifying dimensions of container into which to place children
* children:
* an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
*/
 
// copy dim because we are going to modify it
dim = dojo.mixin({}, dim);
 
dojo.addClass(container, "dijitLayoutContainer");
 
// Move "client" elements to the end of the array for layout. a11y dictates that the author
// needs to be able to put them in the document in tab-order, but this algorithm requires that
// client be last.
children = dojo.filter(children, function(item){ return item.layoutAlign != "client"; })
.concat(dojo.filter(children, function(item){ return item.layoutAlign == "client"; }));
 
// set positions/sizes
dojo.forEach(children, function(child){
var elm = child.domNode,
pos = child.layoutAlign;
 
// set elem to upper left corner of unused space; may move it later
var elmStyle = elm.style;
elmStyle.left = dim.l+"px";
elmStyle.top = dim.t+"px";
elmStyle.bottom = elmStyle.right = "auto";
 
dojo.addClass(elm, "dijitAlign" + capitalize(pos));
 
// set size && adjust record of remaining space.
// note that setting the width of a <div> may affect it's height.
if(pos=="top" || pos=="bottom"){
size(child, { w: dim.w });
dim.h -= child.h;
if(pos=="top"){
dim.t += child.h;
}else{
elmStyle.top = dim.t + dim.h + "px";
}
}else if(pos=="left" || pos=="right"){
size(child, { h: dim.h });
dim.w -= child.w;
if(pos=="left"){
dim.l += child.w;
}else{
elmStyle.left = dim.l + dim.w + "px";
}
}else if(pos=="client"){
size(child, dim);
}
});
};
 
})();
 
}
/trunk/api/js/dojo1.0/dijit/layout/LinkPane.js
New file
0,0 → 1,36
if(!dojo._hasResource["dijit.layout.LinkPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.LinkPane"] = true;
dojo.provide("dijit.layout.LinkPane");
 
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit._Templated");
 
dojo.declare("dijit.layout.LinkPane",
[dijit.layout.ContentPane, dijit._Templated],
{
// summary:
// A ContentPane that loads data remotely
// description:
// LinkPane is just a ContentPane that loads data remotely (via the href attribute),
// and has markup similar to an anchor. The anchor's body (the words between <a> and </a>)
// become the title of the widget (used for TabContainer, AccordionContainer, etc.)
// example:
// <a href="foo.html">my title</a>
 
// I'm using a template because the user may specify the input as
// <a href="foo.html">title</a>, in which case we need to get rid of the
// <a> because we don't want a link.
templateString: '<div class="dijitLinkPane"></div>',
 
postCreate: function(){
 
// If user has specified node contents, they become the title
// (the link must be plain text)
if(this.srcNodeRef){
this.title += this.srcNodeRef.innerHTML;
}
this.inherited("postCreate",arguments);
}
});
 
}
/trunk/api/js/dojo1.0/dijit/layout/templates/TabContainer.html
New file
0,0 → 1,4
<div class="dijitTabContainer">
<div dojoAttachPoint="tablistNode"></div>
<div class="dijitTabPaneWrapper" dojoAttachPoint="containerNode"></div>
</div>
/trunk/api/js/dojo1.0/dijit/layout/templates/TooltipDialog.html
New file
0,0 → 1,7
<div class="dijitTooltipDialog" >
<div class="dijitTooltipContainer">
<div class ="dijitTooltipContents dijitTooltipFocusNode" dojoAttachPoint="containerNode" tabindex="0" waiRole="dialog"></div>
</div>
<span dojoAttachPoint="tabEnd" tabindex="0" dojoAttachEvent="focus:_cycleFocus"></span>
<div class="dijitTooltipConnector" ></div>
</div>
/trunk/api/js/dojo1.0/dijit/layout/templates/_TabButton.html
New file
0,0 → 1,8
<div dojoAttachEvent='onclick:onClick,onmouseenter:_onMouse,onmouseleave:_onMouse'>
<div class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>
<span dojoAttachPoint='containerNode,focusNode'>${!label}</span>
<span dojoAttachPoint='closeButtonNode' class='closeImage' dojoAttachEvent='onmouseenter:_onMouse, onmouseleave:_onMouse, onclick:onClickCloseButton' stateModifier='CloseButton'>
<span dojoAttachPoint='closeText' class='closeText'>x</span>
</span>
</div>
</div>
/trunk/api/js/dojo1.0/dijit/layout/templates/AccordionPane.html
New file
0,0 → 1,11
<div class='dijitAccordionPane'
><div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus'
class='dijitAccordionTitle' wairole="tab"
><div class='dijitAccordionArrow'></div
><div class='arrowTextUp' waiRole="presentation">&#9650;</div
><div class='arrowTextDown' waiRole="presentation">&#9660;</div
><div dojoAttachPoint='titleTextNode' class='dijitAccordionText'>${title}</div></div
><div><div dojoAttachPoint='containerNode' style='overflow: hidden; height: 1px; display: none'
class='dijitAccordionBody' wairole="tabpanel"
></div></div>
</div>
/trunk/api/js/dojo1.0/dijit/layout/AccordionContainer.js
New file
0,0 → 1,209
if(!dojo._hasResource["dijit.layout.AccordionContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dijit.layout.AccordionContainer"] = true;
dojo.provide("dijit.layout.AccordionContainer");
 
dojo.require("dojo.fx");
 
dojo.require("dijit._Container");
dojo.require("dijit._Templated");
dojo.require("dijit.layout.StackContainer");
dojo.require("dijit.layout.ContentPane");
 
dojo.declare(
"dijit.layout.AccordionContainer",
dijit.layout.StackContainer,
{
// summary:
// Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,
// and switching between panes is visualized by sliding the other panes up/down.
// usage:
// <div dojoType="dijit.layout.AccordionContainer">
// <div dojoType="dijit.layout.AccordionPane" title="pane 1">
// <div dojoType="dijit.layout.ContentPane">...</div>
// </div>
// <div dojoType="dijit.layout.AccordionPane" title="pane 2">
// <p>This is some text</p>
// ...
// </div>
 
// duration: Integer
// Amount of time (in ms) it takes to slide panes
duration: 250,
 
_verticalSpace: 0,
 
postCreate: function(){
this.domNode.style.overflow="hidden";
this.inherited("postCreate",arguments);
dijit.setWaiRole(this.domNode, "tablist");
dojo.addClass(this.domNode,"dijitAccordionContainer");
},
 
startup: function(){
if(this._started){ return; }
this.inherited("startup",arguments);
if(this.selectedChildWidget){
var style = this.selectedChildWidget.containerNode.style;
style.display = "";
style.overflow = "auto";
this.selectedChildWidget._setSelectedState(true);
}
},
 
layout: function(){
// summary
// Set the height of the open pane based on what room remains
// get cumulative height of all the title bars, and figure out which pane is open
var totalCollapsedHeight = 0;
var openPane = this.selectedChildWidget;
dojo.forEach(this.getChildren(), function(child){
totalCollapsedHeight += child.getTitleHeight();
});
var mySize = this._contentBox;
this._verticalSpace = (mySize.h - totalCollapsedHeight);
if(openPane){
openPane.containerNode.style.height = this._verticalSpace + "px";
/***
TODO: this is wrong. probably you wanted to call resize on the SplitContainer
inside the AccordionPane??
if(openPane.resize){
openPane.resize({h: this._verticalSpace});
}
***/
}
},
 
_setupChild: function(/*Widget*/ page){
// Summary: prepare the given child
return page;
},
 
_transition: function(/*Widget?*/newWidget, /*Widget?*/oldWidget){
//TODO: should be able to replace this with calls to slideIn/slideOut
if(this._inTransition){ return; }
this._inTransition = true;
var animations = [];
var paneHeight = this._verticalSpace;
if(newWidget){
newWidget.setSelected(true);
var newContents = newWidget.containerNode;
newContents.style.display = "";
 
animations.push(dojo.animateProperty({
node: newContents,
duration: this.duration,
properties: {
height: { start: "1", end: paneHeight }
},
onEnd: function(){
newContents.style.overflow = "auto";
}
}));
}
if(oldWidget){
oldWidget.setSelected(false);
var oldContents = oldWidget.containerNode;
oldContents.style.overflow = "hidden";
animations.push(dojo.animateProperty({
node: oldContents,
duration: this.duration,
properties: {
height: { start: paneHeight, end: "1" }
},
onEnd: function(){
oldContents.style.display = "none";
}
}));
}
 
this._inTransition = false;
 
dojo.fx.combine(animations).play();
},
 
// note: we are treating the container as controller here
_onKeyPress: function(/*Event*/ e){
if(this.disabled || e.altKey ){ return; }
var k = dojo.keys;
switch(e.keyCode){
case k.LEFT_ARROW:
case k.UP_ARROW:
case k.PAGE_UP:
this._adjacent(false)._onTitleClick();
dojo.stopEvent(e);
break;
case k.RIGHT_ARROW:
case k.DOWN_ARROW:
case k.PAGE_DOWN:
this._adjacent(true)._onTitleClick();
dojo.stopEvent(e);
break;
default:
if(e.ctrlKey && e.keyCode == k.TAB){
this._adjacent(e._dijitWidget, !e.shiftKey)._onTitleClick();
dojo.stopEvent(e);
}
}
}
}
);
 
dojo.declare(
"dijit.layout.AccordionPane",
[dijit.layout.ContentPane, dijit._Templated, dijit._Contained],
{
// summary
// AccordionPane is a ContentPane with a title that may contain another widget.
// Nested layout widgets, such as SplitContainer, are not supported at this time.
 
templateString:"<div class='dijitAccordionPane'\n\t><div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='ondijitclick:_onTitleClick,onkeypress:_onTitleKeyPress,onfocus:_handleFocus,onblur:_handleFocus'\n\t\tclass='dijitAccordionTitle' wairole=\"tab\"\n\t\t><div class='dijitAccordionArrow'></div\n\t\t><div class='arrowTextUp' waiRole=\"presentation\">&#9650;</div\n\t\t><div class='arrowTextDown' waiRole=\"presentation\">&#9660;</div\n\t\t><div dojoAttachPoint='titleTextNode' class='dijitAccordionText'>${title}</div></div\n\t><div><div dojoAttachPoint='containerNode' style='overflow: hidden; height: 1px; display: none'\n\t\tclass='dijitAccordionBody' wairole=\"tabpanel\"\n\t></div></div>\n</div>\n",
 
postCreate: function(){
this.inherited("postCreate",arguments)
dojo.setSelectable(this.titleNode, false);
this.setSelected(this.selected);
},
 
getTitleHeight: function(){
// summary: returns the height of the title dom node
return dojo.marginBox(this.titleNode).h; // Integer
},
 
_onTitleClick: function(){
// summary: callback when someone clicks my title
var parent = this.getParent();
if(!parent._inTransition){
parent.selectChild(this);
dijit.focus(this.focusNode);
}
},
 
_onTitleKeyPress: function(/*Event*/ evt){
evt._dijitWidget = this;
return this.getParent()._onKeyPress(evt);
},
 
_setSelectedState: function(/*Boolean*/ isSelected){
this.selected = isSelected;
dojo[(isSelected ? "addClass" : "removeClass")](this.domNode,"dijitAccordionPane-selected");
this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1");
},
_handleFocus: function(/*Event*/e){
// summary: handle the blur and focus state of this widget
dojo[(e.type=="focus" ? "addClass" : "removeClass")](this.focusNode,"dijitAccordionPaneFocused");
},
 
setSelected: function(/*Boolean*/ isSelected){
// summary: change the selected state on this pane
this._setSelectedState(isSelected);
if(isSelected){ this.onSelected(); }
},
 
onSelected: function(){
// summary: called when this pane is selected
}
});
 
}