mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-14 17:58:59 +00:00
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5282 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
415 lines
13 KiB
JavaScript
415 lines
13 KiB
JavaScript
/*
|
|
Copyright (c) 2004-2006, The Dojo Foundation
|
|
All Rights Reserved.
|
|
|
|
Licensed under the Academic Free License version 2.1 or above OR the
|
|
modified BSD license. For more information on Dojo licensing, see:
|
|
|
|
http://dojotoolkit.org/community/licensing.shtml
|
|
*/
|
|
|
|
dojo.provide("dojo.widget.PageContainer");
|
|
|
|
dojo.require("dojo.lang.func");
|
|
dojo.require("dojo.widget.*");
|
|
dojo.require("dojo.event.*");
|
|
dojo.require("dojo.html.selection");
|
|
|
|
dojo.widget.defineWidget("dojo.widget.PageContainer", dojo.widget.HtmlWidget, {
|
|
// 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.
|
|
|
|
isContainer: true,
|
|
|
|
// doLayout: Boolean
|
|
// if true, change the size of my currently displayed child to match my size
|
|
doLayout: true,
|
|
|
|
templateString: "<div dojoAttachPoint='containerNode'></div>",
|
|
|
|
// selectedChild: String
|
|
// id of the currently shown page
|
|
selectedChild: "",
|
|
|
|
fillInTemplate: function(args, frag) {
|
|
// Copy style info from input node to output node
|
|
var source = this.getFragNodeRef(frag);
|
|
dojo.html.copyStyle(this.domNode, source);
|
|
dojo.widget.PageContainer.superclass.fillInTemplate.apply(this, arguments);
|
|
},
|
|
|
|
postCreate: function(args, frag) {
|
|
if(this.children.length){
|
|
// Setup each page panel
|
|
dojo.lang.forEach(this.children, this._setupChild, this);
|
|
|
|
// Figure out which child to initially display
|
|
var initialChild;
|
|
if(this.selectedChild){
|
|
this.selectChild(this.selectedChild);
|
|
}else{
|
|
for(var i=0; i<this.children.length; i++){
|
|
if(this.children[i].selected){
|
|
this.selectChild(this.children[i]);
|
|
break;
|
|
}
|
|
}
|
|
if(!this.selectedChildWidget){
|
|
this.selectChild(this.children[0]);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
addChild: function(child){
|
|
dojo.widget.PageContainer.superclass.addChild.apply(this, arguments);
|
|
this._setupChild(child);
|
|
|
|
// in case the tab labels have overflowed from one line to two lines
|
|
this.onResized();
|
|
|
|
// if this is the first child, then select it
|
|
if(!this.selectedChildWidget){
|
|
this.selectChild(child);
|
|
}
|
|
},
|
|
|
|
_setupChild: function(/*Widget*/ page){
|
|
// Summary: Add the given child to this page container
|
|
|
|
page.hide();
|
|
|
|
// 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";
|
|
|
|
// publish the addChild event for panes added via addChild(), and the original panes too
|
|
dojo.event.topic.publish(this.widgetId+"-addChild", page);
|
|
},
|
|
|
|
removeChild: function(/*Widget*/ page){
|
|
dojo.widget.PageContainer.superclass.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; }
|
|
|
|
// this will notify any tablists to remove a button; do this first because it may affect sizing
|
|
dojo.event.topic.publish(this.widgetId+"-removeChild", page);
|
|
|
|
// in case the tab labels now take up one line instead of two lines
|
|
this.onResized();
|
|
|
|
if (this.selectedChildWidget === page) {
|
|
this.selectedChildWidget = undefined;
|
|
if (this.children.length > 0) {
|
|
this.selectChild(this.children[0], true);
|
|
}
|
|
}
|
|
},
|
|
|
|
selectChild: function(/*Widget*/ page, /*Widget*/ callingWidget){
|
|
// summary
|
|
// Show the given widget (which must be one of my children)
|
|
page = dojo.widget.byId(page);
|
|
this.correspondingPageButton = callingWidget;
|
|
|
|
// Deselect old page and select new one
|
|
if(this.selectedChildWidget){
|
|
this._hideChild(this.selectedChildWidget);
|
|
}
|
|
this.selectedChildWidget = page;
|
|
this.selectedChild = page.widgetId;
|
|
this._showChild(page);
|
|
page.isFirstChild = (page == this.children[0]);
|
|
page.isLastChild = (page == this.children[this.children.length-1]);
|
|
dojo.event.topic.publish(this.widgetId+"-selectChild", page);
|
|
},
|
|
|
|
forward: function(){
|
|
// Summary: advance to next page
|
|
var index = dojo.lang.find(this.children, this.selectedChildWidget);
|
|
this.selectChild(this.children[index+1]);
|
|
},
|
|
|
|
back: function(){
|
|
// Summary: go back to previous page
|
|
var index = dojo.lang.find(this.children, this.selectedChildWidget);
|
|
this.selectChild(this.children[index-1]);
|
|
},
|
|
|
|
onResized: function(){
|
|
// Summary: called when any page is shown, to make it fit the container correctly
|
|
if(this.doLayout && this.selectedChildWidget){
|
|
with(this.selectedChildWidget.domNode.style){
|
|
top = dojo.html.getPixelValue(this.containerNode, "padding-top", true);
|
|
left = dojo.html.getPixelValue(this.containerNode, "padding-left", true);
|
|
}
|
|
var content = dojo.html.getContentBox(this.containerNode);
|
|
this.selectedChildWidget.resizeTo(content.width, content.height);
|
|
}
|
|
},
|
|
|
|
_showChild: function(/*Widget*/ page) {
|
|
// size the current page (in case this is the first time it's being shown, or I have been resized)
|
|
if(this.doLayout){
|
|
var content = dojo.html.getContentBox(this.containerNode);
|
|
page.resizeTo(content.width, content.height);
|
|
}
|
|
|
|
page.selected=true;
|
|
page.show();
|
|
},
|
|
|
|
_hideChild: function(/*Widget*/ page) {
|
|
page.selected=false;
|
|
page.hide();
|
|
},
|
|
|
|
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;
|
|
dojo.event.topic.destroy(this.widgetId+"-addChild");
|
|
dojo.event.topic.destroy(this.widgetId+"-removeChild");
|
|
dojo.event.topic.destroy(this.widgetId+"-selectChild");
|
|
dojo.widget.PageContainer.superclass.destroy.apply(this, arguments);
|
|
}
|
|
});
|
|
|
|
|
|
dojo.widget.defineWidget(
|
|
"dojo.widget.PageController",
|
|
dojo.widget.HtmlWidget,
|
|
{
|
|
// summary
|
|
// Set of buttons to select a page in a page list.
|
|
// Monitors the specified PageContaine, and whenever a page is
|
|
// added, deleted, or selected, updates itself accordingly.
|
|
|
|
templateString: "<span wairole='tablist' dojoAttachEvent='onKey'></span>",
|
|
isContainer: true,
|
|
|
|
// 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: "PageButton",
|
|
|
|
// class: String
|
|
// Class name to apply to the top dom node
|
|
"class": "dojoPageController",
|
|
|
|
fillInTemplate: function() {
|
|
dojo.html.addClass(this.domNode, this["class"]); // "class" is a reserved word in JS
|
|
dojo.widget.wai.setAttr(this.domNode, "waiRole", "role", "tablist");
|
|
},
|
|
|
|
postCreate: function(){
|
|
this.pane2button = {}; // mapping from panes to buttons
|
|
|
|
// If children have already been added to the page container then create buttons for them
|
|
var container = dojo.widget.byId(this.containerId);
|
|
if(container){
|
|
dojo.lang.forEach(container.children, this.onAddChild, this);
|
|
}
|
|
|
|
dojo.event.topic.subscribe(this.containerId+"-addChild", this, "onAddChild");
|
|
dojo.event.topic.subscribe(this.containerId+"-removeChild", this, "onRemoveChild");
|
|
dojo.event.topic.subscribe(this.containerId+"-selectChild", this, "onSelectChild");
|
|
},
|
|
|
|
destroy: function(){
|
|
dojo.event.topic.unsubscribe(this.containerId+"-addChild", this, "onAddChild");
|
|
dojo.event.topic.unsubscribe(this.containerId+"-removeChild", this, "onRemoveChild");
|
|
dojo.event.topic.unsubscribe(this.containerId+"-selectChild", this, "onSelectChild");
|
|
dojo.widget.PageController.superclass.destroy.apply(this, arguments);
|
|
},
|
|
|
|
onAddChild: function(/*Widget*/ page){
|
|
// summary
|
|
// Called whenever a page is added to the container.
|
|
// Create button corresponding to the page.
|
|
var button = dojo.widget.createWidget(this.buttonWidget,
|
|
{
|
|
label: page.label,
|
|
closeButton: page.closable
|
|
});
|
|
this.addChild(button);
|
|
this.domNode.appendChild(button.domNode);
|
|
this.pane2button[page]=button;
|
|
page.controlButton = button; // this value might be overwritten if two tabs point to same container
|
|
|
|
var _this = this;
|
|
dojo.event.connect(button, "onClick", function(){ _this.onButtonClick(page); });
|
|
dojo.event.connect(button, "onCloseButtonClick", function(){ _this.onCloseButtonClick(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){
|
|
button.destroy();
|
|
}
|
|
this.pane2button[page] = null;
|
|
},
|
|
|
|
onSelectChild: function(/*Widget*/ page){
|
|
// Summary
|
|
// Called when a page has been selected in the PageContainer, either by me or by another PageController
|
|
if(this._currentChild){
|
|
var oldButton=this.pane2button[this._currentChild];
|
|
oldButton.clearSelected();
|
|
}
|
|
var newButton=this.pane2button[page];
|
|
newButton.setSelected();
|
|
this._currentChild=page;
|
|
},
|
|
|
|
onButtonClick: function(/*Widget*/ page){
|
|
// summary
|
|
// Called whenever one of my child buttons is pressed in an attempt to select a page
|
|
var container = dojo.widget.byId(this.containerId); // TODO: do this via topics?
|
|
container.selectChild(page, false, this);
|
|
},
|
|
|
|
onCloseButtonClick: function(/*Widget*/ page){
|
|
// summary
|
|
// Called whenever one of my child buttons [X] is pressed in an attempt to close a page
|
|
var container = dojo.widget.byId(this.containerId);
|
|
container.closeChild(page);
|
|
},
|
|
|
|
onKey: function(/*Event*/ evt){
|
|
// summary:
|
|
// Handle keystrokes on the page list, for advancing to next/previous button
|
|
|
|
if( (evt.keyCode == evt.KEY_RIGHT_ARROW)||
|
|
(evt.keyCode == evt.KEY_LEFT_ARROW) ){
|
|
var current = 0;
|
|
var next = null; // the next button to focus on
|
|
|
|
// find currently focused button in children array
|
|
var current = dojo.lang.find(this.children, this.pane2button[this._currentChild]);
|
|
|
|
// pick next button to focus on
|
|
if(evt.keyCode == evt.KEY_RIGHT_ARROW){
|
|
next = this.children[ (current+1) % this.children.length ];
|
|
}else{ // is LEFT_ARROW
|
|
next = this.children[ (current+ (this.children.length-1)) % this.children.length ];
|
|
}
|
|
|
|
dojo.event.browser.stopEvent(evt);
|
|
next.onClick();
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
dojo.widget.defineWidget("dojo.widget.PageButton", dojo.widget.HtmlWidget,
|
|
{
|
|
// summary
|
|
// Internal widget used by PageList.
|
|
// The button-like or tab-like object you click to select or delete a page
|
|
|
|
templateString: "<span class='item'>" +
|
|
"<span dojoAttachEvent='onClick' dojoAttachPoint='titleNode' class='selectButton'>${this.label}</span>" +
|
|
"<span dojoAttachEvent='onClick:onCloseButtonClick' class='closeButton'>[X]</span>" +
|
|
"</span>",
|
|
|
|
// label: String
|
|
// Name to print on the button
|
|
label: "foo",
|
|
|
|
// closeButton: Boolean
|
|
// true iff we should also print a close icon to destroy corresponding page
|
|
closeButton: false,
|
|
|
|
onClick: function(){
|
|
// summary
|
|
// Basically this is the attach point PageController listens to, to select the page
|
|
this.focus();
|
|
},
|
|
|
|
onCloseButtonMouseOver: function(){
|
|
// summary
|
|
// The close button changes color a bit when you mouse over
|
|
dojo.html.addClass(this.closeButtonNode, "closeHover");
|
|
},
|
|
|
|
onCloseButtonMouseOut: function(){
|
|
// summary
|
|
// Revert close button to normal color on mouse out
|
|
dojo.html.removeClass(this.closeButtonNode, "closeHover");
|
|
},
|
|
|
|
onCloseButtonClick: function(/*Event*/ evt){
|
|
// summary
|
|
// Handle clicking the close button for this tab
|
|
},
|
|
|
|
setSelected: function(){
|
|
// summary
|
|
// This is run whenever the page corresponding to this button has been selected
|
|
dojo.html.addClass(this.domNode, "current");
|
|
this.titleNode.setAttribute("tabIndex","0");
|
|
},
|
|
|
|
clearSelected: function(){
|
|
// summary
|
|
// This function is run whenever the page corresponding to this button has been deselected (and another page has been shown)
|
|
dojo.html.removeClass(this.domNode, "current");
|
|
this.titleNode.setAttribute("tabIndex","-1");
|
|
},
|
|
|
|
focus: function(){
|
|
// summary
|
|
// This will focus on the this button (for accessibility you need to do this when the button is selected)
|
|
if(this.titleNode.focus){ // mozilla 1.7 doesn't have focus() func
|
|
this.titleNode.focus();
|
|
}
|
|
}
|
|
});
|
|
|
|
// These arguments can be specified for the children of a PageContainer.
|
|
// Since any widget can be specified as a PageContainer child, mix them
|
|
// into the base widget class. (This is a hack, but it's effective.)
|
|
dojo.lang.extend(dojo.widget.Widget, {
|
|
// label: String
|
|
// Label or title of this widget. Used by TabContainer to the name the tab, etc.
|
|
label: "",
|
|
|
|
// 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;
|
|
}
|
|
});
|