📄 pagecontainer.js
字号:
/* 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; }});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -