123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- if (!dojo._hasResource["dojox.presentation._base"]) { // _hasResource checks
- // added by build. Do
- // not use _hasResource
- // directly in your
- // code.
- dojo._hasResource["dojox.presentation._base"] = true;
- dojo.provide("dojox.presentation._base");
- dojo.experimental("dojox.presentation");
- dojo.require("dijit._Widget");
- dojo.require("dijit._Container");
- dojo.require("dijit._Templated");
- dojo.require("dijit.layout.StackContainer");
- dojo.require("dijit.layout.ContentPane");
- dojo.require("dojo.fx");
- dojo.declare("dojox.presentation.Deck", [dijit.layout.StackContainer,
- dijit._Templated], {
- // summary:
- // dojox.presentation class
- // basic powerpoint esque engine for handling transitons and
- // control
- // in a page-by-page and part-by-part way
- //
- // FIXME: parsing part(s)/widget(s) in href="" Slides not
- // working
- // TODO: make auto actions progress.
- // FIXME: Safari keydown/press/up listener not working.
- // noClick=true prevents progression of slides in that broweser
- //
- // fullScreen: Boolean
- // unsupported (that i know of) just yet. Default it to take
- // control
- // of window. Would be nice to be able to contain presentation
- // in a
- // styled container, like StackContainer ... theoretically
- // possible.
- // [and may not need this variable?]
- fullScreen : true,
- // useNav: Boolean
- // true to allow navigation popup, false to disallow
- useNav : true,
- // navDuration: Integer
- // time in MS fadein/out of popup nav [default: 250]
- navDuration : 250,
- // noClick: Boolean
- // if true, prevents _any_ click events to propagate actions
- // (limiting control to keyboard and/or action.on="auto" or
- // action.delay=""
- // actions.
- noClick : false,
- // setHash: Boolean
- // if true, window location bar will get a #link to slide for
- // direct
- // access to a particular slide number.
- setHash : true,
- // just to over-ride:
- templateString : null,
- templateString : "<div class=\"dojoShow\" dojoAttachPoint=\"showHolder\">\n\t<div class=\"dojoShowNav\" dojoAttachPoint=\"showNav\" dojoAttachEvent=\"onmouseover: _showNav, onmouseout: _hideNav\">\n\t<div class=\"dojoShowNavToggler\" dojoAttachPoint=\"showToggler\">\n\t\t<img dojoAttachPoint=\"prevNode\" src=\"${prevIcon}\" dojoAttachEvent=\"onclick:previousSlide\">\n\t\t<select dojoAttachEvent=\"onchange:_onEvent\" dojoAttachPoint=\"select\">\n\t\t\t<option dojoAttachPoint=\"_option\">Title</option>\n\t\t</select>\n\t\t<img dojoAttachPoint=\"nextNode\" src=\"${nextIcon}\" dojoAttachEvent=\"onclick:nextSlide\">\n\t</div>\n\t</div>\n\t<div dojoAttachPoint=\"containerNode\"></div>\n</div>\n",
- // nextIcon: String
- // icon for navigation "next" button
- nextIcon : dojo.moduleUrl('dojox.presentation',
- 'resources/icons/next.png'),
- // prevIcon: String
- // icon for navigation "previous" button
- prevIcon : dojo.moduleUrl('dojox.presentation',
- 'resources/icons/prev.png'),
- _navOpacMin : 0,
- _navOpacMax : 0.85,
- _slideIndex : 0,
- // Private:
- _slides : [],
- _navShowing : true,
- _inNav : false,
- startup : function() {
- // summary: connect to the various handlers and controls for
- // this presention
- dojox.presentation.Deck.superclass.startup.call(this);
- if (this.useNav) {
- this._hideNav();
- } else {
- this.showNav.style.display = "none";
- }
- this.connect(document, 'onclick', '_onEvent');
- this.connect(document, 'onkeypress', '_onEvent');
- // only if this.fullScreen == true?
- this.connect(window, 'onresize', '_resizeWindow');
- this._resizeWindow();
- this._updateSlides();
- this._readHash();
- this._setHash();
- },
- moveTo : function(/* Integer */number) {
- // summary: jump to slide based on param
- var slideIndex = number - 1;
- if (slideIndex < 0)
- slideIndex = 0;
- if (slideIndex > this._slides.length - 1)
- slideIndex = this._slides.length - 1;
- this._gotoSlide(slideIndex);
- },
- onMove : function(number) {
- // summary: stub function? TODOC: ?
- },
- nextSlide : function(/* Event */evt) {
- // summary: transition to the next slide.
- if (!this.selectedChildWidget.isLastChild) {
- this._gotoSlide(this._slideIndex + 1);
- }
- if (evt) {
- evt.stopPropagation();
- }
- },
- previousSlide : function(/* Event */evt) {
- // summary: transition to the previous slide
- if (!this.selectedChildWidget.isFirstChild) {
- this._gotoSlide(this._slideIndex - 1);
- } else {
- this.selectedChildWidget._reset();
- }
- if (evt) {
- evt.stopPropagation();
- }
- },
- getHash : function(id) {
- // summary: get the current hash to set in localtion
- return this.id + "_SlideNo_" + id;
- },
- _hideNav : function(evt) {
- // summary: hides navigation
- if (this._navAnim) {
- this._navAnim.stop();
- }
- this._navAnim = dojo.animateProperty({
- node : this.showNav,
- duration : this.navDuration,
- properties : {
- opacity : {
- end : this._navOpacMin
- }
- }
- }).play();
- },
- _showNav : function(evt) {
- // summary: shows navigation
- if (this._navAnim) {
- this._navAnim.stop();
- }
- this._navAnim = dojo.animateProperty({
- node : this.showNav,
- duration : this.navDuration,
- properties : {
- opacity : {
- end : this._navOpacMax
- }
- }
- }).play();
- },
- _handleNav : function(evt) {
- // summary: does nothing? _that_ seems useful.
- evt.stopPropagation();
- },
- _updateSlides : function() {
- // summary:
- // populate navigation select list with refs to slides call
- // this
- // if you add a node to your presentation dynamically.
- this._slides = this.getChildren();
- if (this.useNav) {
- // populate the select box with top-level slides
- var i = 0;
- dojo.forEach(this._slides, dojo.hitch(this, function(
- slide) {
- i++;
- var tmp = this._option
- .cloneNode(true);
- tmp.text = slide.title + " (" + i
- + ") ";
- this._option.parentNode
- .insertBefore(tmp,
- this._option);
- }));
- if (this._option.parentNode) {
- this._option.parentNode.removeChild(this._option);
- }
- // dojo._destroyElement(this._option);
- }
- },
- _onEvent : function(/* Event */evt) {
- // summary:
- // main presentation function, determines next 'best action'
- // for a
- // specified event.
- var _node = evt.target;
- var _type = evt.type;
- if (_type == "click" || _type == "change") {
- if (_node.index && _node.parentNode == this.select) {
- this._gotoSlide(_node.index);
- } else if (_node == this.select) {
- this._gotoSlide(_node.selectedIndex);
- } else {
- if (this.noClick
- || this.selectedChildWidget.noClick
- || this._isUnclickable(evt))
- return;
- this.selectedChildWidget._nextAction(evt);
- }
- } else if (_type == "keydown" || _type == "keypress") {
- // FIXME: safari doesn't report keydown/keypress?
- var key = (evt.charCode == dojo.keys.SPACE
- ? dojo.keys.SPACE
- : evt.keyCode);
- switch (key) {
- case dojo.keys.DELETE :
- case dojo.keys.BACKSPACE :
- case dojo.keys.LEFT_ARROW :
- case dojo.keys.UP_ARROW :
- case dojo.keys.PAGE_UP :
- case 80 : // key 'p'
- this.previousSlide(evt);
- break;
- case dojo.keys.ENTER :
- case dojo.keys.SPACE :
- case dojo.keys.RIGHT_ARROW :
- case dojo.keys.DOWN_ARROW :
- case dojo.keys.PAGE_DOWN :
- case 78 : // key 'n'
- this.selectedChildWidget._nextAction(evt);
- break;
- case dojo.keys.HOME :
- this._gotoSlide(0);
- }
- }
- this._resizeWindow();
- evt.stopPropagation();
- },
- _gotoSlide : function(/* Integer */slideIndex) {
- // summary: goes to slide
- this.selectChild(this._slides[slideIndex]);
- this.selectedChildWidget._reset();
- this._slideIndex = slideIndex;
- if (this.useNav) {
- this.select.selectedIndex = slideIndex;
- }
- if (this.setHash) {
- this._setHash();
- }
- this.onMove(this._slideIndex + 1);
- },
- _isUnclickable : function(/* Event */evt) {
- // summary: returns true||false base of a nodes
- // click-ability
- var nodeName = evt.target.nodeName.toLowerCase();
- // TODO: check for noClick='true' in target attrs & return
- // true
- // TODO: check for relayClick='true' in target attrs &
- // return false
- switch (nodeName) {
- case 'a' :
- case 'input' :
- case 'textarea' :
- return true;
- break;
- }
- return false;
- },
- _readHash : function() {
- var th = window.location.hash;
- if (th.length && this.setHash) {
- var parts = ("" + window.location).split(this
- .getHash(''));
- if (parts.length > 1) {
- this._gotoSlide(parseInt(parts[1]) - 1);
- }
- }
- },
- _setHash : function() {
- // summary: sets url #mark to direct slide access
- if (this.setHash) {
- var slideNo = this._slideIndex + 1;
- window.location.href = "#" + this.getHash(slideNo);
- }
- },
- _resizeWindow : function(/* Event */evt) {
- // summary: resize this and children to fix this
- // window/container
- // only if this.fullScreen?
- dojo.body().style.height = "auto";
- var wh = dijit.getViewport();
- var h = Math.max(document.documentElement.scrollHeight
- || dojo.body().scrollHeight, wh.h);
- var w = wh.w;
- this.selectedChildWidget.domNode.style.height = h + 'px';
- this.selectedChildWidget.domNode.style.width = w + 'px';
- },
- _transition : function(newWidget, oldWidget) {
- // summary: over-ride stackcontainers _transition method
- // but atm, i find it to be ugly with not way to call
- // _showChild() without over-riding it too. hopefull
- // basic toggles in superclass._transition will be available
- // in dijit, and this won't be necessary.
- var anims = [];
- if (oldWidget) {
- /*
- * anims.push(dojo.fadeOut({ node: oldWidget.domNode,
- * duration:250, onEnd: dojo.hitch(this,function(){
- * this._hideChild(oldWidget); }) }));
- */
- this._hideChild(oldWidget);
- }
- if (newWidget) {
- /*
- * anims.push(dojo.fadeIn({ node:newWidget.domNode,
- * start:0, end:1, duration:300, onEnd:
- * dojo.hitch(this,function(){
- * this._showChild(newWidget); newWidget._reset(); }) }) );
- */
- this._showChild(newWidget);
- newWidget._reset();
- }
- // dojo.fx.combine(anims).play();
- }
- });
- dojo.declare("dojox.presentation.Slide", [dijit.layout.ContentPane,
- dijit._Contained, dijit._Container, dijit._Templated], {
- // summary:
- // a Comonent of a dojox.presentation, and container for each
- // 'Slide'
- // made up of direct HTML (no part/action relationship), and
- // dojox.presentation.Part(s),
- // and their attached Actions.
- // templatPath: String
- // make a ContentPane templated, and style the 'titleNode'
- templateString : "<div dojoAttachPoint=\"showSlide\" class=\"dojoShowPrint dojoShowSlide\">\n\t<h1 class=\"showTitle\" dojoAttachPoint=\"slideTitle\"><span class=\"dojoShowSlideTitle\" dojoAttachPoint=\"slideTitleText\">${title}</span></h1>\n\t<div class=\"dojoShowBody\" dojoAttachPoint=\"containerNode\"></div>\n</div>\n",
- // title: String
- // string to insert into titleNode, title of Slide
- title : "",
- // inherited from ContentPane FIXME: don't seem to work ATM?
- refreshOnShow : true,
- preLoad : false,
- doLayout : true,
- parseContent : true,
- // noClick: Boolean
- // true on slide tag prevents clicking, false allows
- // (can also be set on base presentation for global control)
- noClick : false,
- // private holders:
- _parts : [],
- _actions : [],
- _actionIndex : 0,
- _runningDelay : false,
- startup : function() {
- // summary: setup this slide with actions and components
- // (Parts)
- this.slideTitleText.innerHTML = this.title;
- var children = this.getChildren();
- this._actions = [];
- dojo.forEach(children, function(child) {
- var tmpClass = child.declaredClass
- .toLowerCase();
- switch (tmpClass) {
- case "dojox.presentation.part" :
- this._parts.push(child);
- break;
- case "dojox.presentation.action" :
- this._actions.push(child);
- break;
- }
- }, this);
- },
- _nextAction : function(evt) {
- // summary: gotoAndPlay current cached action
- var tmpAction = this._actions[this._actionIndex] || 0;
- if (tmpAction) {
- // is this action a delayed action? [auto? thoughts?]
- if (tmpAction.on == "delay") {
- this._runningDelay = setTimeout(dojo.hitch(
- tmpAction, "_runAction"),
- tmpAction.delay);
- console.debug('started delay action',
- this._runningDelay);
- } else {
- tmpAction._runAction();
- }
- // FIXME: it gets hairy here. maybe runAction should
- // call _actionIndex++ onEnd? if a delayed action is
- // running, do
- // we want to prevent action++?
- var tmpNext = this._getNextAction();
- this._actionIndex++;
- if (tmpNext.on == "delay") {
- // FIXME: yeah it looks like _runAction() onend
- // should report
- // _actionIndex++
- console.debug('started delay action',
- this._runningDelay);
- setTimeout(dojo.hitch(tmpNext, "_runAction"),
- tmpNext.delay);
- }
- } else {
- // no more actions in this slide
- this.getParent().nextSlide(evt);
- }
- },
- _getNextAction : function() {
- // summary: returns the _next action in this sequence
- return this._actions[this._actionIndex + 1] || 0;
- },
- _reset : function() {
- // summary: set action chain back to 0 and re-init each Part
- this._actionIndex = [0];
- dojo.forEach(this._parts, function(part) {
- part._reset();
- }, this);
- }
- });
- dojo.declare("dojox.presentation.Part", [dijit._Widget, dijit._Contained],
- {
- // summary:
- // a node in a presentation.Slide that inherits control from a
- // dojox.presentation.Action
- // can be any element type, and requires styling before parsing
- //
- // as: String
- // like an ID, attach to Action via (part) as="" / (action)
- // forSlide="" tags
- // this should be unique identifier?
- as : null,
- // startVisible: boolean
- // true to leave in page on slide startup/reset
- // false to hide on slide startup/reset
- startVisible : false,
- // isShowing: Boolean,
- // private holder for _current_ state of Part
- _isShowing : false,
- postCreate : function() {
- // summary: override and init() this component
- this._reset();
- },
- _reset : function() {
- // summary: set part back to initial calculate state
- // these _seem_ backwards, but quickToggle flips it
- this._isShowing = !this.startVisible;
- this._quickToggle();
- },
- _quickToggle : function() {
- // summary: ugly [unworking] fix to test setting state of
- // component
- // before/after an animation. display:none prevents fadeIns?
- if (this._isShowing) {
- dojo.style(this.domNode, 'display', 'none');
- dojo.style(this.domNode, 'visibility', 'hidden');
- dojo.style(this.domNode, 'opacity', 0);
- } else {
- dojo.style(this.domNode, 'display', '');
- dojo.style(this.domNode, 'visibility', 'visible');
- dojo.style(this.domNode, 'opacity', 1);
- }
- this._isShowing = !this._isShowing;
- }
- });
- dojo.declare("dojox.presentation.Action",
- [dijit._Widget, dijit._Contained], {
- // summary:
- // a widget to attach to a dojox.presentation.Part to control
- // it's properties based on an inherited chain of events ...
- //
- //
- // on: String
- // FIXME: only 'click' supported ATM. plans include on="delay",
- // on="end" of="", and on="auto". those should make semantic
- // sense
- // to you.
- on : 'click',
- // forSlide: String
- // attach this action to a dojox.presentation.Part with a
- // matching 'as' attribute
- forSlide : null,
- // toggle: String
- // will toggle attached [matching] node(s) via forSlide/as
- // relationship(s)
- toggle : 'fade',
- // delay: Integer
- //
- delay : 0,
- // duration: Integer
- // default time in MS to run this action effect on it's
- // 'forSlide' node
- duration : 1000,
- // private holders:
- _attached : [],
- _nullAnim : false,
- _runAction : function() {
- // summary: runs this action on attached node(s)
- var anims = [];
- // executes the action for each attached 'Part'
- dojo.forEach(this._attached, function(node) {
- // FIXME: this is ugly, and where is toggle
- // class? :(
- var dir = (node._isShowing) ? "Out" : "In";
- // node._isShowing =! node._isShowing;
- node._quickToggle(); // (?) this is annoying
- // var _anim = dojox.fx[ this.toggle ?
- // this.toggle+dir : "fade"+dir]({
- var _anim = dojo.fadeIn({
- node : node.domNode,
- duration : this.duration
- // beforeBegin:
- // dojo.hitch(node,"_quickToggle")
- });
- anims.push(_anim);
- }, this);
- var _anim = dojo.fx.combine(anims);
- if (_anim) {
- _anim.play();
- }
- },
- _getSiblingsByType : function(/* String */declaredClass) {
- // summary: quick replacement for
- // getChildrenByType("class"), but in
- // a child here ... so it's getSiblings. courtesy bill in
- // #dojo
- // could be moved into parent, and just call
- // this.getChildren(),
- // which makes more sense.
- var siblings = dojo.filter(this.getParent().getChildren(),
- function(widget) {
- return widget.declaredClass == declaredClass;
- });
- return siblings; // dijit._Widget
- },
- postCreate : function() {
- // summary: run this once, should this be startup:
- // function()?
- // prevent actions from being visible, _always_
- dojo.style(this.domNode, "display", "none");
- var parents = this
- ._getSiblingsByType('dojox.presentation.Part');
- // create a list of "parts" we are attached to via
- // forSlide/as
- this._attached = [];
- dojo.forEach(parents, function(parentPart) {
- if (this.forSlide == parentPart.as) {
- this._attached.push(parentPart);
- }
- }, this);
- }
- });
- }
|