123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- /*
- Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
- Available via Academic Free License >= 2.1 OR the modified BSD license.
- see: http://dojotoolkit.org/license for details
- */
- if(!dojo._hasResource["dojox.layout.RotatorContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
- dojo._hasResource["dojox.layout.RotatorContainer"] = true;
- dojo.provide("dojox.layout.RotatorContainer");
- dojo.require("dojo.fx");
- dojo.require("dijit.layout.StackContainer");
- dojo.require("dijit.layout.StackController");
- dojo.require("dijit._Widget");
- dojo.require("dijit._Templated");
- dojo.require("dijit._Contained");
- dojo.declare("dojox.layout.RotatorContainer",
- [dijit.layout.StackContainer, dijit._Templated], {
- // summary:
- // Extends a StackContainer to automatically transition between children
- // and display navigation in the form of tabs or a pager.
- //
- // description:
- // The RotatorContainer cycles through the children with a transition.
- //
- // published topics:
- // [widgetId]-update - Notifies pager(s) that a child has changed.
- // Parameters:
- // /*boolean*/ playing - true if playing, false if paused
- // /*int*/ current - current selected child
- // /*int*/ total - total number of children
- //
- // example:
- // | <div dojoType="dojox.layout.RotatorContainer" id="myRotator" showTabs="true" autoStart="true" transitionDelay="5000">
- // | <div id="pane1" dojoType="dijit.layout.ContentPane" title="1">
- // | Pane 1!
- // | </div>
- // | <div id="pane2" dojoType="dijit.layout.ContentPane" title="2">
- // | Pane 2!
- // | </div>
- // | <div id="pane3" dojoType="dijit.layout.ContentPane" title="3" transitionDelay="10000">
- // | Pane 3 with overrided transitionDelay!
- // | </div>
- // | </div>
- templateString: '<div class="dojoxRotatorContainer"><div dojoAttachPoint="tabNode"></div><div class="dojoxRotatorPager" dojoAttachPoint="pagerNode"></div><div class="dojoxRotatorContent" dojoAttachPoint="containerNode"></div></div>',
- // showTabs: Boolean
- // Sets the display of the tabs. The tabs are actually a StackController.
- // The child's title is used for the tab's label.
- showTabs: true,
- // transitionDelay: int
- // The delay in milliseconds before transitioning to the next child.
- transitionDelay: 5000,
- // transition: String
- // The type of transition to perform when switching children.
- // A null transition will transition instantly.
- transition: "fade",
- // transitionDuration: int
- // The duration of the transition in milliseconds.
- transitionDuration: 1000,
- // autoStart: Boolean
- // Starts the timer to transition children upon creation.
- autoStart: true,
- // suspendOnHover: Boolean
- // Pause the rotator when the mouse hovers over it.
- suspendOnHover: false,
- // pauseOnManualChange: Boolean
- // Pause the rotator when the tab is changed or the pager's next/previous
- // buttons are clicked.
- pauseOnManualChange: null,
- // reverse: Boolean
- // Causes the rotator to rotate in reverse order.
- reverse: false,
- // pagerId: String
- // ID the pager widget.
- pagerId: "",
- // cycles: int
- // Number of cycles before pausing.
- cycles: -1,
- // pagerClass: String
- // The declared Class of the Pager used for this Widget
- pagerClass: "dojox.layout.RotatorPager",
- postCreate: function(){
- // summary: Initializes the DOM nodes, tabs, and transition stuff.
- this.inherited(arguments);
- // force this DOM node to a relative position and make sure the children are absolute positioned
- dojo.style(this.domNode, "position", "relative");
- // validate the cycles counter
- if(this.cycles-0 == this.cycles && this.cycles != -1){
- // we need to add 1 because we decrement cycles before the animation starts
- this.cycles++;
- }else{
- this.cycles = -1;
- }
- // if they didn't specify the pauseOnManualChange, then we want it to be the opposite of
- // the suspendOnHover since it doesn't make sense to do both, unless you really want to
- if(this.pauseOnManualChange === null){
- this.pauseOnManualChange = !this.suspendOnHover;
- }
- // create the stack controller if we are using tabs
- var id = this.id || "rotator"+(new Date()).getTime(),
- sc = new dijit.layout.StackController({ containerId:id }, this.tabNode);
- this.tabNode = sc.domNode;
- this._stackController = sc;
- dojo.style(this.tabNode, "display", this.showTabs ? "" : "none");
- // if the controller's tabs are clicked, check if we should pause and reset the cycle counter
- this.connect(sc, "onButtonClick","_manualChange");
- // set up our topic listeners
- this._subscriptions = [
- dojo.subscribe(this.id+"-cycle", this, "_cycle"),
- dojo.subscribe(this.id+"-state", this, "_state")
- ];
- // make sure the transition duration isn't less than the transition delay
- var d = Math.round(this.transitionDelay * 0.75);
- if(d < this.transitionDuration){
- this.transitionDuration = d;
- }
- // wire up the mouse hover events
- if(this.suspendOnHover){
- this.connect(this.domNode, "onmouseover", "_onMouseOver");
- this.connect(this.domNode, "onmouseout", "_onMouseOut");
- }
- },
- startup: function(){
- // summary: Initializes the pagers.
- if(this._started){ return; }
- // check if the pager is defined within the rotator container
- var c = this.getChildren();
- for(var i=0, len=c.length; i<len; i++){
- if(c[i].declaredClass == this.pagerClass){
- this.pagerNode.appendChild(c[i].domNode);
- break;
- }
- }
- // process the child widgets
- this.inherited(arguments);
- // check if we should start automatically
- if(this.autoStart){
- // start playing
- setTimeout(dojo.hitch(this, "_play"), 10);
- }else{
- // update the pagers with the initial state
- this._updatePager();
- }
- },
- destroy: function(){
- // summary: Unsubscribe to all of our topics
- dojo.forEach(this._subscriptions, dojo.unsubscribe);
- this.inherited(arguments);
- },
- _setShowTabsAttr: function(/*anything*/value){
- this.showTabs = value;
- dojo.style(this.tabNode, "display", value ? "" : "none");
- },
- _updatePager: function(){
- // summary: Notify the pager's current and total numbers.
- var c = this.getChildren();
- dojo.publish(this.id+"-update", [this._playing, dojo.indexOf(c, this.selectedChildWidget)+1, c.length]);
- },
- _onMouseOver: function(){
- // summary: Triggered when the mouse is moved over the rotator container.
- // temporarily suspend the cycling, but don't officially pause it
- this._resetTimer();
- this._over = true;
- },
- _onMouseOut: function(){
- // summary: Triggered when the mouse is moved off the rotator container.
- this._over = false;
- // if we were playing, resume playback in 200ms
- // we need to wait because we may be moused over again right away
- if(this._playing){
- clearTimeout(this._timer);
- this._timer = setTimeout(dojo.hitch(this, "_play", true), 200);
- }
- },
- _resetTimer: function(){
- // summary: Resets the timer used to start the next transition.
- clearTimeout(this._timer);
- this._timer = null;
- },
- _cycle: function(/*boolean or int*/next){
- // summary: Cycles to the next/previous child.
- // if next is an int, then _cycle() was called via a timer
- // if next is a boolean, then _cycle() was called via the next/prev buttons, stop playing and reset cycles
- if(next instanceof Boolean || typeof next == "boolean"){
- this._manualChange();
- }
- var c = this.getChildren(),
- len = c.length,
- i = dojo.indexOf(c, this.selectedChildWidget) + (next === false || (next !== true && this.reverse) ? -1 : 1);
- this.selectChild(c[(i < len ? (i < 0 ? len-1 : i) : 0)]);
- this._updatePager();
- },
- _manualChange: function(){
- // summary: This function is only called when a manual change occurs in which
- // case we may need to stop playing and we need to reset the cycle counter
- if(this.pauseOnManualChange){
- this._playing = false;
- }
- this.cycles = -1;
- },
- _play: function(skip){
- // summary: Schedules the next transition.
- this._playing = true;
- this._resetTimer();
- if(skip !== true && this.cycles>0){
- this.cycles--;
- }
- if(this.cycles==0){
- this._pause();
- }else if((!this.suspendOnHover || !this._over) && this.transitionDelay){
- // check if current pane has a delay
- this._timer = setTimeout(dojo.hitch(this, "_cycle"), this.selectedChildWidget.domNode.getAttribute("transitionDelay") || this.transitionDelay);
- }
- this._updatePager();
- },
- _pause: function(){
- // summary: Clears the transition timer and pauses the rotator.
- this._playing = false;
- this._resetTimer();
- },
- _state: function(playing){
- // summary: Fired when the play/pause pager button is toggled.
- if(playing){
- // since we were manually changed, disable the cycle counter
- this.cycles = -1;
- this._play();
- }else{
- this._pause();
- }
- },
- _transition: function(/*dijit._Widget*/ next, /*dijit._Widget*/ prev){
- // summary: Dispatches the appropriate transition.
- this._resetTimer();
- // check if we have anything to transition
- if(prev && this.transitionDuration){
- switch(this.transition){
- case "fade": this._fade(next, prev); return;
- }
- }
- this._transitionEnd();
- this.inherited(arguments);
- },
- _transitionEnd: function(){
- if(this._playing){
- this._play();
- }else{
- this._updatePager();
- }
- },
- _fade: function(/*dijit._Widget*/ next, /*dijit._Widget*/ prev){
- // summary: Crossfades two children.
- this._styleNode(prev.domNode, 1, 1);
- this._styleNode(next.domNode, 0, 2);
- // show the next child and make sure it's sized properly
- this._showChild(next);
- if(this.doLayout && next.resize){
- next.resize(this._containerContentBox || this._contentBox);
- }
- // create the crossfade animation
- var args = { duration:this.transitionDuration },
- anim = dojo.fx.combine([
- dojo["fadeOut"](dojo.mixin({node:prev.domNode}, args)),
- dojo["fadeIn"](dojo.mixin({node:next.domNode}, args))
- ]);
- this.connect(anim, "onEnd", dojo.hitch(this,function(){
- this._hideChild(prev);
- this._transitionEnd();
- }));
- anim.play();
- },
- _styleNode: function(/*DOMnode*/node, /*number*/opacity, /*int*/zIndex){
- // summary: Helper function to style the children.
- dojo.style(node, "opacity", opacity);
- dojo.style(node, "zIndex", zIndex);
- dojo.style(node, "position", "absolute");
- }
- });
- dojo.declare("dojox.layout.RotatorPager", [dijit._Widget, dijit._Templated, dijit._Contained], {
- // summary:
- // Defines controls used to manipulate a RotatorContainer
- //
- // description:
- // A pager can be defined one of two ways:
- // * Externally of the RotatorContainer's template and tell the
- // RotatorPager the rotatorId of the RotatorContainer
- // * As a direct descendant of the RotatorContainer (i.e. inside the
- // RotatorContainer's template)
- //
- // The pager can contain the following components:
- // * Previous button
- // - Must be a dijit.form.Button
- // - dojoAttachPoint must be named "previous"
- // * Next button
- // - Must be a dijit.form.Button
- // - dojoAttachPoint must be named "next"
- // * Play/Pause toggle button
- // - Must be a dijit.form.ToggleButton
- // - dojoAttachPoint must be named "playPause"
- // - Use iconClass to specify toggled state
- // * Current child #
- // - dojoAttachPoint must be named "current"
- // * Total # of children
- // - dojoAttachPoint must be named "total"
- //
- // You can choose to exclude specific controls as well as add elements
- // for styling.
- //
- // Should you need a pager, but don't want to use Dijit buttons, you can
- // write your own pager widget and just wire it into the topics. The
- // topic names are prefixed with the widget ID of the RotatorContainer.
- // Notifications are received from and sent to the RotatorContainer as
- // well as other RotatorPagers.
- //
- // published topics:
- // [widgetId]-cycle - Notify that the next or previous button was pressed.
- // Parameters:
- // /*boolean*/ next - true if next, false if previous
- // [widgetId]-state - Notify that the play/pause button was toggled.
- // Parameters:
- // /*boolean*/ playing - true if playing, false if paused
- //
- // example:
- // A pager with the current/total children and previous/next buttons.
- // | <div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
- // | <button dojoType="dijit.form.Button" dojoAttachPoint="previous">Prev</button>
- // | <span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
- // | <button dojoType="dijit.form.Button" dojoAttachPoint="next">Next</button>
- // | </div>
- //
- // example:
- // A pager with only a play/pause toggle button.
- // | <div dojoType="dojox.layout.RotatorPager" rotatorId="myRotator">
- // | <button dojoType="dijit.form.ToggleButton" dojoAttachPoint="playPause"></button>
- // | </div>
- //
- // example:
- // A pager styled with iconClass.
- // | <div dojoType="dojox.layout.RotatorPager" class="rotatorIcons" rotatorId="myRotator">
- // | <button dojoType="dijit.form.Button" iconClass="previous" dojoAttachPoint="previous">Prev</button>
- // | <button dojoType="dijit.form.ToggleButton" iconClass="playPause" dojoAttachPoint="playPause"></button>
- // | <button dojoType="dijit.form.Button" iconClass="next" dojoAttachPoint="next">Next</button>
- // | <span dojoAttachPoint="current"></span> / <span dojoAttachPoint="total"></span>
- // | </div>
- widgetsInTemplate: true,
- // rotatorId: int
- // The ID of the rotator this pager is tied to.
- // Only required if defined outside of the RotatorContainer's container.
- rotatorId: "",
- postMixInProperties: function(){
- this.templateString = "<div>" + this.srcNodeRef.innerHTML + "</div>";
- },
- postCreate: function(){
- var p = dijit.byId(this.rotatorId) || this.getParent();
- if(p && p.declaredClass == "dojox.layout.RotatorContainer"){
- if(this.previous){
- dojo.connect(this.previous, "onClick", function(){
- dojo.publish(p.id+"-cycle", [false]);
- });
- }
- if(this.next){
- dojo.connect(this.next, "onClick", function(){
- dojo.publish(p.id+"-cycle", [true]);
- });
- }
- if(this.playPause){
- dojo.connect(this.playPause, "onClick", function(){
- this.set('label', this.checked ? "Pause" : "Play");
- dojo.publish(p.id+"-state", [this.checked]);
- });
- }
- this._subscriptions = [
- dojo.subscribe(p.id+"-state", this, "_state"),
- dojo.subscribe(p.id+"-update", this, "_update")
- ];
- }
- },
- destroy: function(){
- // summary: Unsubscribe to all of our topics
- dojo.forEach(this._subscriptions, dojo.unsubscribe);
- this.inherited(arguments);
- },
- _state: function(/*boolean*/playing){
- // summary: Updates the display of the play/pause button
- if(this.playPause && this.playPause.checked != playing){
- this.playPause.set("label", playing ? "Pause" : "Play");
- this.playPause.set("checked", playing);
- }
- },
- _update: function(/*boolean*/playing, /*int*/current, /*int*/total){
- // summary: Updates the pager's play/pause button, current child, and total number of children.
- this._state(playing);
- if(this.current && current){
- this.current.innerHTML = current;
- }
- if(this.total && total){
- this.total.innerHTML = total;
- }
- }
- });
- }
|