123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- if (!dojo._hasResource["dojox.image.SlideShow"]) { // _hasResource checks added
- // by build. Do not use
- // _hasResource directly in
- // your code.
- dojo._hasResource["dojox.image.SlideShow"] = true;
- dojo.provide("dojox.image.SlideShow");
- //
- // dojox.image.SlideShow courtesy Shane O Sullivan, licensed under a Dojo
- // CLA
- // For a sample usage, see http://www.skynet.ie/~sos/photos.php
- //
- // @author Copyright 2007 Shane O Sullivan (shaneosullivan1@gmail.com)
- // @license Licensed under the Academic Free License 3.0
- // http://www.opensource.org/licenses/afl-3.0.php
- //
- // TODO: more cleanups
- //
- dojo.require("dojo.fx");
- dojo.require("dijit._Widget");
- dojo.require("dijit._Templated");
- dojo.declare("dojox.image.SlideShow", [dijit._Widget, dijit._Templated], {
- // imageHeight: Number
- // The maximum height of an image
- imageHeight : 375,
- // imageWidth: Number
- // The maximum width of an image.
- imageWidth : 500,
- // title: String
- // the initial title of the SlideShow
- title : "",
- // titleTemplate: String
- // a way to customize the wording in the title. supported tags to be
- // populated are:
- // @title = the passed title of the image
- // @current = the current index of the image
- // @total = the total number of images in the SlideShow
- //
- // should add more?
- titleTemplate : '@title <span class="slideShowCounterText">(@current of @total)</span>',
- // noLink: Boolean
- // Prevents the slideshow from putting an anchor link around the
- // displayed image
- // enables if true, though still will not link in absence of a url to
- // link to
- noLink : false,
- // loop: Boolean
- // true/false - make the slideshow loop
- loop : true,
- // hasNav: Boolean
- // toggle to enable/disable the visual navigation controls
- hasNav : true,
- // images: Array
- // Contains the DOM nodes that individual images are stored in when
- // loaded or loading.
- images : [],
- // pageSize: Number
- // The number of images to request each time.
- pageSize : 20,
- // autoLoad: Boolean
- // If true, then images are preloaded, before the user navigates to view
- // them.
- // If false, an image is not loaded until the user views it.
- autoLoad : true,
- // fixedHeight: Boolean
- // If true, the widget does not resize itself to fix the displayed
- // image.
- fixedHeight : false,
- // imageStore: Object
- // Implementation of the dojo.data.api.Read API, which provides data on
- // the images
- // to be displayed.
- imageStore : null,
- // linkAttr: String
- // Defines the name of the attribute to request from the store to
- // retrieve the
- // URL to link to from an image, if any.
- linkAttr : "link",
- // imageLargeAttr: String
- // Defines the name of the attribute to request from the store to
- // retrieve the
- // URL to the image.
- imageLargeAttr : "imageUrl",
- // titleAttr: String
- // Defines the name of the attribute to request from the store to
- // retrieve the
- // title of the picture, if any.
- titleAttr : "title",
- // slideshowInterval: Number
- // Time, in seconds, between image transitions during a slideshow.
- slideshowInterval : 3,
- templateString : "<div dojoAttachPoint=\"outerNode\" class=\"slideShowWrapper\">\n\t<div style=\"position:relative;\" dojoAttachPoint=\"innerWrapper\">\n\t\t<div class=\"slideShowNav\" dojoAttachEvent=\"onclick: _handleClick\">\n\t\t\t<div class=\"dijitInline slideShowTitle\" dojoAttachPoint=\"titleNode\">${title}</div>\n\t\t</div>\n\t\t<div dojoAttachPoint=\"navNode\" class=\"slideShowCtrl\" dojoAttachEvent=\"onclick: _handleClick\">\n\t\t\t<span dojoAttachPoint=\"navPrev\" class=\"slideShowCtrlPrev\"></span>\n\t\t\t<span dojoAttachPoint=\"navPlay\" class=\"slideShowCtrlPlay\"></span>\n\t\t\t<span dojoAttachPoint=\"navNext\" class=\"slideShowCtrlNext\"></span>\n\t\t</div>\n\t\t<div dojoAttachPoint=\"largeNode\" class=\"slideShowImageWrapper\"></div>\t\t\n\t\t<div dojoAttachPoint=\"hiddenNode\" class=\"slideShowHidden\"></div>\n\t</div>\n</div>\n",
- // _tempImgPath: URL
- // URL to the image to display when an image is not yet fully loaded.
- _tempImgPath : dojo.moduleUrl("dojox.image",
- "resources/images/1pixel.gif"),
- // _imageCounter: Number
- // A counter to keep track of which index image is to be loaded next
- _imageCounter : 0,
- // _tmpImage: DomNode
- // The temporary image to show when a picture is loading.
- _tmpImage : null,
- // _request: Object
- // Implementation of the dojo.data.api.Request API, which defines the
- // query
- // parameters for accessing the store.
- _request : null,
- postCreate : function() {
- // summary: Initilizes the widget, sets up listeners and shows the
- // first image
- this.inherited("postCreate", arguments);
- var img = document.createElement("img");
- // FIXME: should API be to normalize an image to fit in the
- // specified height/width?
- img.setAttribute("width", this.imageWidth);
- img.setAttribute("height", this.imageHeight);
- if (this.hasNav) {
- dojo.connect(this.outerNode, "onmouseover", function(evt) {
- try {
- _this._showNav();
- } catch (e) {
- }
- });
- dojo.connect(this.outerNode, "onmouseout", function(evt) {
- try {
- _this._hideNav(evt);
- } catch (e) {
- }
- });
- }
- this.outerNode.style.width = this.imageWidth + "px";
- img.setAttribute("src", this._tempImgPath);
- var _this = this;
- this.largeNode.appendChild(img);
- this._tmpImage = img;
- this._currentImage = img;
- this._fitSize(true);
- this._loadImage(0, function() {
- _this.showImage(0);
- });
- this._calcNavDimensions();
- },
- setDataStore : function(dataStore, request, /* optional */paramNames) {
- // summary: Sets the data store and request objects to read data
- // from.
- // dataStore:
- // An implementation of the dojo.data.api.Read API. This accesses
- // the image
- // data.
- // request:
- // An implementation of the dojo.data.api.Request API. This
- // specifies the
- // query and paging information to be used by the data store
- // paramNames:
- // An object defining the names of the item attributes to fetch from
- // the
- // data store. The three attributes allowed are 'linkAttr',
- // 'imageLargeAttr' and 'titleAttr'
- this.reset();
- var _this = this;
- this._request = {
- query : {},
- start : ((request.start) ? request.start : 0),
- count : ((request.count) ? request.count : this.pageSize),
- onBegin : function(count, request) {
- _this.maxPhotos = count;
- }
- };
- if (request.query) {
- dojo.mixin(this._request.query, request.query);
- }
- if (paramNames && paramNames.imageLargeAttr) {
- this.imageLargeAttr = paramNames.imageLargeAttr;
- }
- var _this = this;
- var _complete = function(items) {
- _this.showImage(0);
- _this._request.onComplete = null;
- };
- this.imageStore = dataStore;
- this._request.onComplete = _complete;
- this._request.start = 0;
- this.imageStore.fetch(this._request);
- },
- reset : function() {
- // summary: Resets the widget to its initial state
- // description: Removes all previously loaded images, and clears all
- // caches.
- while (this.largeNode.firstChild) {
- this.largeNode.removeChild(this.largeNode.firstChild);
- }
- this.largeNode.appendChild(this._tmpImage);
- while (this.hiddenNode.firstChild) {
- this.hiddenNode.removeChild(this.hiddenNode.firstChild);
- }
- var img;
- for (var pos = 0; pos < this.images.length; pos++) {
- img = this.images[pos];
- if (img && img.parentNode) {
- img.parentNode.removeChild(img);
- }
- }
- this.images = [];
- this.isInitialized = false;
- this._imageCounter = 0;
- },
- isImageLoaded : function(idx) {
- // summary: Returns true if image at the specified index is loaded,
- // false otherwise.
- // idx:
- // The number index in the data store to check if it is loaded.
- return this.images && this.images.length > index
- && this.images[idx];
- },
- moveImageLoadingPointer : function(idx) {
- // summary: If 'autoload' is true, this tells the widget to start
- // loading
- // images from the specified pointer.
- // idx:
- // The number index in the data store to start loading images from.
- this._imageCounter = idx;
- },
- destroy : function() {
- // summary: Cleans up the widget when it is being destroyed
- if (this._slideId) {
- this._stop();
- }
- this.inherited("destroy", arguments);
- },
- showNextImage : function(inTimer, forceLoop) {
- // summary: Changes the image being displayed to the next image in
- // the data store
- // inTimer: Boolean
- // If true, a slideshow is active, otherwise the slideshow is
- // inactive.
- if (inTimer && this._timerCancelled) {
- return false;
- }
- if (this.imageIndex + 1 >= this.maxPhotos) {
- if (inTimer && (this.loop || forceLoop)) {
- this.imageIndex = -1;
- } else {
- if (this._slideId) {
- this._stop();
- }
- return false;
- }
- }
- var _this = this;
- this.showImage(this.imageIndex + 1, function() {
- if (inTimer) {
- _this._startTimer();
- }
- });
- return true;
- },
- toggleSlideShow : function() {
- // summary: Switches the slideshow mode on and off.
- if (this._slideId) {
- this._stop();
- } else {
- dojo.toggleClass(this.domNode, "slideShowPaused");
- this._timerCancelled = false;
- var success = this.showNextImage(true, true);
- if (!success) {
- this._stop();
- }
- }
- },
- getShowTopicName : function() {
- // summary: Returns the topic id published to when an image is shown
- // description:
- // The information published is: index, title and url
- return (this.widgetId ? this.widgetId : this.id) + "/imageShow";
- },
- getLoadTopicName : function() {
- // summary: Returns the topic id published to when an image finishes
- // loading.
- // description:
- // The information published is the index position of the image
- // loaded.
- return (this.widgetId ? this.widgetId : this.id) + "/imageLoad";
- },
- showImage : function(idx, /* Function? */callback) {
- // summary: Shows the image at index 'idx'.
- // idx: Number
- // The position of the image in the data store to display
- // callback: Function
- // Optional callback function to call when the image has finished
- // displaying.
- if (!callback && this._slideId) {
- this.toggleSlideShow();
- }
- var _this = this;
- var current = this.largeNode.getElementsByTagName("div");
- this.imageIndex = idx;
- var showOrLoadIt = function() {
- // If the image is already loaded, then show it.
- if (_this.images[idx]) {
- while (_this.largeNode.firstChild) {
- _this.largeNode.removeChild(_this.largeNode.firstChild);
- }
- _this.images[idx].style.opacity = 0;
- _this.largeNode.appendChild(_this.images[idx]);
- _this._currentImage = _this.images[idx]._img;
- _this._fitSize();
- var onEnd = function(a, b, c) {
- var img = _this.images[idx].firstChild;
- if (img.tagName.toLowerCase() != "img") {
- img = img.firstChild;
- }
- title = img.getAttribute("title");
- if (_this._navShowing) {
- _this._showNav(true);
- }
- dojo.publish(_this.getShowTopicName(), [{
- index : idx,
- title : title,
- url : img.getAttribute("src")
- }]);
- if (callback) {
- callback(a, b, c);
- }
- _this._setTitle(title);
- };
- dojo.fadeIn({
- node : _this.images[idx],
- duration : 300,
- onEnd : onEnd
- }).play();
- } else {
- // If the image is not loaded yet, load it first, then show
- // it.
- _this._loadImage(idx, function() {
- dojo.publish(_this.getLoadTopicName(), [idx]);
- _this.showImage(idx, callback);
- });
- }
- };
- // If an image is currently showing, fade it out, then show
- // the new image. Otherwise, just show the new image.
- if (current && current.length > 0) {
- dojo.fadeOut({
- node : current[0],
- duration : 300,
- onEnd : function() {
- _this.hiddenNode.appendChild(current[0]);
- showOrLoadIt();
- }
- }).play();
- } else {
- showOrLoadIt();
- }
- },
- _fitSize : function(force) {
- // summary: Fits the widget size to the size of the image being
- // shown,
- // or centers the image, depending on the value of 'fixedHeight'
- // force: Boolean
- // If true, the widget is always resized, regardless of the value of
- // 'fixedHeight'
- if (!this.fixedHeight || force) {
- var height = (this._currentImage.height + (this.hasNav ? 20 : 0));
- dojo.style(this.innerWrapper, "height", height + "px");
- return;
- }
- dojo.style(this.largeNode, "paddingTop", this._getTopPadding()
- + "px");
- },
- _getTopPadding : function() {
- if (!this.fixedHeight) {
- return 0;
- }
- // summary: Returns the padding to place at the top of the image to
- // center it vertically.
- return (this.imageHeight - this._currentImage.height) / 2;
- },
- _loadNextImage : function() {
- // summary: Load the next unloaded image.
- if (!this.autoLoad) {
- return;
- }
- while (this.images.length >= this._imageCounter
- && this.images[this._imageCounter]) {
- this._imageCounter++;
- }
- this._loadImage(this._imageCounter);
- },
- _loadImage : function(idx, callbackFn) {
- // summary: Load image at specified index
- // description:
- // This function loads the image at position 'idx' into the
- // internal cache of images. This does not cause the image to be
- // displayed.
- // idx:
- // The position in the data store to load an image from.
- // callbackFn:
- // An optional function to execute when the image has finished
- // loading.
- if (this.images[idx] || !this._request) {
- return;
- }
- var pageStart = idx - (idx % this.pageSize);
- this._request.start = pageStart;
- this._request.onComplete = function(items) {
- var diff = idx - pageStart;
- if (items && items.length > diff) {
- loadIt(items[diff]);
- } else { /*
- * Squelch - console.log("Got an empty set of
- * items");
- */
- }
- }
- var _this = this;
- var loadIt = function(item) {
- var url = _this.imageStore.getValue(item, _this.imageLargeAttr);
- var img = document.createElement("img");
- var div = document.createElement("div");
- div._img = img;
- var link = _this.imageStore.getValue(item, _this.linkAttr);
- if (!link || _this.noLink) {
- div.appendChild(img);
- } else {
- var a = document.createElement("a");
- a.setAttribute("href", link);
- a.setAttribute("target", "_blank");
- div.appendChild(a);
- a.appendChild(img);
- }
- div.setAttribute("id", _this.id + "_imageDiv" + idx);
- dojo.connect(img, "onload", function() {
- _this._fitImage(img);
- div.setAttribute("width", _this.imageWidth);
- div.setAttribute("height", _this.imageHeight);
- dojo.publish(_this.getLoadTopicName(), [idx]);
- _this._loadNextImage();
- if (callbackFn) {
- callbackFn();
- }
- });
- _this.hiddenNode.appendChild(div);
- var titleDiv = document.createElement("div");
- dojo.addClass(titleDiv, "slideShowTitle");
- div.appendChild(titleDiv);
- _this.images[idx] = div;
- img.setAttribute("src", url);
- var title = _this.imageStore.getValue(item, _this.titleAttr);
- if (title) {
- img.setAttribute("title", title);
- }
- }
- this.imageStore.fetch(this._request);
- },
- _stop : function() {
- // summary: Stops a running slide show.
- if (this._slideId) {
- clearTimeout(this._slideId);
- }
- this._slideId = null;
- this._timerCancelled = true;
- dojo.removeClass(this.domNode, "slideShowPaused");
- },
- _prev : function() {
- // summary: Show the previous image.
- // FIXME: either pull code from showNext/prev, or call it here
- if (this.imageIndex < 1) {
- return;
- }
- this.showImage(this.imageIndex - 1);
- },
- _next : function() {
- // summary: Show the next image
- this.showNextImage();
- },
- _startTimer : function() {
- // summary: Starts a timeout to show the next image when a slide
- // show is active
- this._slideId = setTimeout("dijit.byId('" + this.id
- + "').showNextImage(true);", this.slideshowInterval
- * 1000);
- },
- _calcNavDimensions : function() {
- // summary:
- // Calculates the dimensions of the navigation controls
- dojo.style(this.navNode, "position", "absolute");
- // Place the navigation controls far off screen
- dojo.style(this.navNode, "left", "-10000px");
- // Make the navigation controls visible
- dojo._setOpacity(this.navNode, 99);
- this.navPlay._size = dojo.marginBox(this.navPlay);
- this.navPrev._size = dojo.marginBox(this.navPrev);
- this.navNext._size = dojo.marginBox(this.navNext);
- dojo._setOpacity(this.navNode, 0);
- dojo.style(this.navNode, "position", "");
- dojo.style(this.navNode, "left", "");
- },
- _setTitle : function(title) {
- // summary: Sets the title of the image to be displayed
- // title: String
- // The String title of the image
- this.titleNode.innerHTML = this.titleTemplate.replace('@title',
- title).replace('@current',
- String(Number(this.imageIndex) + 1)).replace('@total',
- String(this.maxPhotos));
- },
- _fitImage : function(img) {
- // summary: Ensures that the image width and height do not exceed
- // the maximum.
- // img: Node
- // The image DOM node to optionally resize
- var width = img.width
- var height = img.height;
- if (width > this.imageWidth) {
- height = Math.floor(height * (this.imageWidth / width));
- img.setAttribute("height", height + "px");
- img.setAttribute("width", this.imageWidth + "px");
- }
- if (height > this.imageHeight) {
- width = Math.floor(width * (this.imageHeight / height));
- img.setAttribute("height", this.imageHeight + "px");
- img.setAttribute("width", width + "px");
- }
- },
- _handleClick : function(/* Event */e) {
- // summary: Performs navigation on the images based on users mouse
- // clicks
- // e:
- // An Event object
- switch (e.target) {
- case this.navNext :
- this._next();
- break;
- case this.navPrev :
- this._prev();
- break;
- case this.navPlay :
- this.toggleSlideShow();
- break;
- }
- },
- _showNav : function(force) {
- // summary:
- // Shows the navigation controls
- // force: Boolean
- // If true, the navigation controls are repositioned even if they
- // are
- // currently visible.
- if (this._navShowing && !force) {
- return;
- }
- dojo.style(this.navNode, "marginTop", "0px");
- dojo.style(this.navPlay, "marginLeft", "0px");
- var wrapperSize = dojo.marginBox(this.outerNode);
- var margin = this._currentImage.height - this.navPlay._size.h - 10
- + this._getTopPadding();
- if (margin > this._currentImage.height) {
- margin += 10;
- }
- dojo[this.imageIndex < 1 ? "addClass" : "removeClass"](
- this.navPrev, "slideShowCtrlHide");
- dojo[this.imageIndex + 1 >= this.maxPhotos
- ? "addClass"
- : "removeClass"](this.navNext, "slideShowCtrlHide");
- var _this = this;
- if (this._navAnim) {
- this._navAnim.stop();
- }
- if (this._navShowing) {
- return;
- }
- this._navAnim = dojo.fadeIn({
- node : this.navNode,
- duration : 300,
- onEnd : function() {
- _this._navAnim = null;
- }
- });
- this._navAnim.play();
- this._navShowing = true;
- },
- _hideNav : function(/* Event */e) {
- // summary: Hides the navigation controls
- // e: Event
- // The DOM Event that triggered this function
- if (!e || !this._overElement(this.outerNode, e)) {
- var _this = this;
- if (this._navAnim) {
- this._navAnim.stop();
- }
- this._navAnim = dojo.fadeOut({
- node : this.navNode,
- duration : 300,
- onEnd : function() {
- _this._navAnim = null;
- }
- });
- this._navAnim.play();
- this._navShowing = false;
- }
- },
- _overElement : function(/* DomNode */element, /* Event */e) {
- // summary:
- // Returns whether the mouse is over the passed element.
- // Element must be display:block (ie, not a <span>)
- // When the page is unloading, if this method runs it will throw an
- // exception.
- if (typeof(dojo) == "undefined") {
- return false;
- }
- element = dojo.byId(element);
- var m = {
- x : e.pageX,
- y : e.pageY
- };
- var bb = dojo._getBorderBox(element);
- var absl = dojo.coords(element, true);
- var left = absl.x;
- return (m.x >= left && m.x <= (left + bb.w) && m.y >= absl.y && m.y <= (top + bb.h)); // boolean
- }
- });
- }
|