// This is open source, based on GNU's General Public License (GPL).
// See http://www.gnu.org/copyleft for further details about the GNU GPL.


var slideShowConfig =                   // configurable parameters
{
    repeat:             false,          // default repetition mode
    delay:              5000,           // default delay between slides
    gray:               "#606060",      // font color for grayed-out controls
    prefix:            "_slideshow",    // base identifier for displayed images
    scrollBars:                         // dimension of potential scroll bars
    {
        width:          20,             // supposed width of vertical scroll bar
        height:         20              // supposed height or horizontal scroll bar
    },
    fading:                             // fading effect parameters
    {
        cycles:         10,             // number of fading iterations
        delay:          20              // percentage of full opacity
    },
	timeout:			10000			// timeout for loading an image
};

var slideShow =                         // descriptor of the slide show
{
    name:               "slideShow",    // show name for calling the event function
    images:             undefined,      // list of images to display sequentially
    index:              undefined,      // currently displayed image
    repeat:             undefined,      // continuous repetition (wrap-around)
    sections:                           // entities hosting slide-show constituents
    {
        host:           undefined,      // element hosting the slide show
        screen:         undefined,      // element hosting the image and controls
        controls:       undefined,      // element hosting the control buttons
        slides:         [],             // set of overlaid slides (image plus caption)
        next:           undefined       // index of slide section to be filled next
    },
    controls:                           // entities controlling the slide show
    {
        first:          undefined,      // button to select the first image
        previous:       undefined,      // button to select the previous image
        start:          undefined,      // button to resume the slide show
        pause:          undefined,      // button to pause the slide show
        stop:           undefined,      // button to terminate the slide show
        next:           undefined,      // button to select the next image
        last:           undefined,      // button to select the last image
        repeat:         undefined,      // button to control the repetition
        slow:           undefined,      // button to decrease the interval
        fast:           undefined,      // button to increase the interval
        delay:          undefined       // selector for the update interval
    },
    advance:                            // entities controlling the timing
    {
        delay:          undefined,      // last chosen interval between images
		command:		undefined,		// last requested expiration command
        timer:          undefined       // reference of timer controlling the interval
    },
    effects:
    {
        timer:          undefined,      // reference of timer controlling visual effects
        cycles:         undefined,      // number of iterations remaining
        iteration:      undefined,      // command to execute per iteration
        termination:    undefined       // command to execute at last iteration
    }
}



// Slide Show 1.2.1, Copyright (c) 2011, Stefan Hofmann

// This script implements a slide show for images contained in a particular 
// HTML element ("gallery") of a web page. When setting up the slide show,
// ideally upon loading the web page, the script first scans the gallery
// for eligible images ("slides") and collects them for use within the slide 
// show. Eligible images are those being enclosed by an anchor tag ('<a>') 
// whose 'href' attribute points to another (supposedly larger) variant of the 
// image to be displayed during the slide show. The 'href' tag of such links 
// is further replaced by a JavaScript command to start the slide show at the 
// particular image. If JavaScript should be disabled, this approach has the 
// advantage that the larger images can still be displayed by clicking their 
// original links and returning to the gallery with the browser's back button.

// The slide show starts as soon as an image pertaining to the slide show is
// clicked. The slide show – actually its display area ("screen") – needs to
// be tied to a freely configurable HTML element ("host"). The slide show's 
// HTML code will be inserted at the beginning of the hosting element's HTML 
// code upon start of the show and be removed upon its termination. For best 
// results and least "cross-talk" with other page elements, in particular with
// form fields, a dedicated empty '<div>' element should be provided for hosting 
// the show.

// When started, the slide show occupies the web page's complete client area.
// The slide show can be controlled by a series of buttons that allow to pause,
// resume, and stop the slide show. Further buttons allow to manually navigate
// to the first, previous, next, or last slide; these can be used at any time,
// even if the slide show automatically iterates through the slides. Futhermore,
// a timing selector allows to adjust the interval between slides in predefined 
// steps, including pausing the show; the selector's default entry determines 
// the operation mode when starting the show. Changing the timing selector either 
// causes the show to pause or to resume the show with the next slide and the
// new iteration interval. Buttons that cannot be used, e.g. the pause button
// because of a an already paused show, are disabled and marked accordingly.

// When terminating the show by means of the stop button, the client area is
// redisplayed and the slide show's HTML elements are removed from the web page.

// TODO: object-oriented refactorization



// --------------------------------------------------------------------------------
// SetupSlideShow()
// --------------------------------------------------------------------------------
// This function scans a particular HTML element ("gallery") for eligible images 
// ("slides") and collects them for use within the slide show. The links to the 
// respective larger images are replaced by JavaScript commands to start the slide 
// show at the particular image.
//
// This function should be called right upon loading a web page.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> hostId = identifier of the element to host the slide show
// <> galleryId = identifier of the element hosting the image gallery
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show is ready to start
// --------------------------------------------------------------------------------

function SetupSlideShow( hostId, galleryId )
{
    // determine the HTML code to be scanned for eligible images
    var gallery = document.getElementById( galleryId );
	var html = ( gallery )? gallery.innerHTML : "" ;
	// record the object to host the slide show and start screening
    slideShow.sections.host = document.getElementById( hostId );
	if( slideShow.sections.host && html != "" )
	{
    	var newHtml = "";
    	slideShow.images = [];
    	while( true )
    	{
    		// try matching a link tag enclosing an image tag
    		var start = html.search( /<a\s/i );
    		var end = html.search( /<\/a\s*>/i );
    		if( start >= 0 && end >= 0 && start < end )
    		{
    		    // isolate the parts relevant for further processing
    			var link = html.substring( start, end + 4 );
				var next = link.search( />/ ) + 1;
				var href = link.substring( 0, next );
				var url = href.replace( /^.*\s+href="([^"">]*)".*$/i, "$1" );
				// check whether the link embraces an image tag and whether it refers to another image
    			if( link.search( /<img\s/i ) >= 0 && url.search( /\.tiff?|\.jpe?g|.\png|\.gif/i ) >= 0 )
    			{
    				// collect the image attributes, substituting the title for an empty alt tag and vice versa
    				var img = link.substring( next );
    				var title = img.replace( /^(.|\n)*\s+title="([^"">]*)"(.|\n)*$/mi, "$2" );
    				var alt = img.replace( /^(.|\n)*\s+alt="([^"">]*)"(.|\n)*$/mi, "$2" );
    				alt = ( ! alt || alt == img )? title : alt;
    				title = ( ! title || title == img )? alt : title;
    				// record the found image and its attributes
    			    var index = slideShow.images.length;
    				slideShow.images[ index ] = { url: url, title: title, alt: alt };
    				// modify the image's link to start the slide show at that image and save the original
    				// link in a specially-formatted name attribute
        		    newHtml += html.substring( 0, start );
    				newHtml += link.replace( /^(.*\s+)href="([^"">]*)"(.*)$/mi, "$1name=\"''$2''\" href=\"javascript: StartSlideShow( "+ index +" )\"$3" );
    				html = html.substring( end + 4 );
    			}
    			else
    			{
    				// no image within link, so ignore the link
    				newHtml += html.substring( 0, end + 4 );
    				html = html.substring( end + 4 );
    			}
    		}
    		else
    		{
    			// stop parsing if no more image tags
    			newHtml += html;
    			break;
    		}
    	}
    	// Adjust MSIE6 browser settings to allow affixing the slide show within the window
        if( BrowserIsIE6() )
        {
            // apply tweaks to emulate "position: fixed" by "position: absolute";
            // CSS equivalents (see "http://www.cssplay.co.uk/layouts/fixed.html"):
            // html { overflow-x: auto; overflow-y: hidden; }
            // body { height: 100%; zoom: 1; }
            document.body.parentNode.style.overflowX = "auto";
            document.body.parentNode.style.overflowY = "hidden";
            document.body.style.overflowX = "auto";
            document.body.style.overflowY = "auto";
            document.body.style.height = "100%";
            document.body.style.zoom = "1";
        }
    	// replace the gallery's HTML code with the modified one
    	gallery.innerHTML = newHtml;
    	return( slideShow.images.length > 0 );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// StartSlideShow()
// --------------------------------------------------------------------------------
// This function creates the slide show's display area ("screen") with control, 
// slide, and caption sections. The function further fades the slide show in, 
// starts the show with the slide at the given image index and sets the auto-
// advance interval as given by the default value of the timing selector.
// --------------------------------------------------------------------------------
// Optional Parameters:
// >> index = index of the slide to display first
// >> paused = true to start the slide show without auto-advance
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has started without errors
// --------------------------------------------------------------------------------

function StartSlideShow( index, paused )
{
    var exception;
    var success = true;
    // check whether the slide show is ready to start
    if( slideShow.images && slideShow.images.length > 0 )
    {
        // set the screen's parameters to cover the document's whole client area;
        // since the screen section is much larger than current monitors, we don't 
        // have to bother with window resize events
        var screenId = slideShowConfig.prefix + "Screen";
        var screenClass = "slideshow-screen";
        var screenStyle = 
            // for Internet Explorer
            "-ms-filter: 'progid: DXImageTransform.Microsoft.Alpha( Opacity = 0 )';" +
            "filter: alpha( opacity = 0 );" +
            // CSS3 standard
            "opacity: 0.0;";
        // set the slide controls' parameters
        var controlsId = slideShowConfig.prefix + "SectionControls";
        var controlsClass = "slideshow-section-controls";
        var controlsStyle = "";
        // set the control-group divider's parameters
        var groupDividerClass = "slideshow-group-divider";
        var groupDividerStyle = "";
        // set the slide-advance controls' parameters
        var buttonFirstId = slideShowConfig.prefix + "ButtonFirst";
        var buttonPreviousId = slideShowConfig.prefix + "ButtonPrevious";
        var buttonStartId = slideShowConfig.prefix + "ButtonStart";
        var buttonPauseId = slideShowConfig.prefix + "ButtonPause";
        var buttonStopId = slideShowConfig.prefix + "ButtonStop";
        var buttonNextId = slideShowConfig.prefix + "ButtonNext";
        var buttonLastId = slideShowConfig.prefix + "ButtonLast";
        var buttonAdvanceClass = "slideshow-button-advance";
        var buttonAdvanceStyle = "";
        // set the show-repeat parameters
        var buttonRepeatId = slideShowConfig.prefix + "ButtonRepeat";
        var buttonRepeatClass = "slideshow-button-repeat";
        var buttonRepeatStyle = "";
        // set the timing controls' parameters
        var choiceTimingId = slideShowConfig.prefix + "ChoiceTiming";
        var choiceTimingClass = "slideshow-choice-timing";
        var choiceTimingStyle = "";
        var buttonSlowId = slideShowConfig.prefix + "ButtonSlow";
        var buttonFastId = slideShowConfig.prefix + "ButtonFast";
        var buttonTimingClass = "slideshow-button-timing";
        var buttonTimingStyle = "";
        // set the slide's parameters
        var slideId = slideShowConfig.prefix + "SectionSlide";
        var slideId0 = slideId + "0";
        var slideId1 = slideId + "1";
        var slideClass = "slideshow-section-slide";
        var slideStyle = 
            "position: fixed;" +
            // for Internet Explorer
            "-ms-filter: 'progid: DXImageTransform.Microsoft.Alpha( Opacity = 0 )'; " +
            "filter: alpha( opacity = 0 );" +
            // CSS3 standard
            "opacity: 0.0;";
        // set the image's parameters
        var frameId = slideShowConfig.prefix + "SectionSlideFrame";
        var frameId0 = frameId+ "0";
        var frameId1 = frameId+ "1";
        var frameClass = "slideshow-section-slide-frame";
        var frameStyle = "";
        // set the caption's parameters, limiting the width to the (supposedly maximum)
        // image width
        var captionId = slideShowConfig.prefix + "SectionSlideCaption";
        var captionId0 = captionId + "0";
        var captionId1 = captionId + "1";
        var captionClass = "slideshow-section-slide-caption";
        var captionStyle = "";
        // generate the symbols for the control buttons
        var symbolFirst = "&#x2590;&#x25C4;";
        var symbolPrevious = "&#x25C4;&#x25C4;";
        var symbolStart = "&#x25BA;";
        var symbolPause = "&#x2590;&thinsp;&#x258C;";
        var symbolStop = "&#x2588;";
        var symbolNext = "&#x25BA;&#x25BA;";
        var symbolLast = "&#x25BA;&#x258C;";
        var symbolRepeat = "&#x25BA;&#x2502;&#x25BA;";
        var symbolSlow = "&#x25B2;";
        var symbolFast = "&#x25BC;";
        // make adjustments for Internet Explorer 6 and below
        if( BrowserIsIE6() )
        {
            // apply tweaks to emulate "position: fixed" by "position: absolute";
            // CSS equivalents:
            // .slideshow-screen { position: absolute; }
            // .slideshow-section-slide { position: absolute; }
            screenStyle += "position: absolute;";
            slideStyle += "position: absolute;";
            // replace button symbols by ordinary bold text characters
            symbolFirst = "|<";
            symbolPrevious = "<<";
            symbolStart = ">";
            symbolPause = "||";
            symbolStop = "[]";
            symbolNext = ">>";
            symbolLast = ">|";
            buttonAdvanceStyle += "font-weight: bolder;";
            symbolRepeat = ">> | >>";
            buttonRepeatStyle += "font-weight: bolder;";
            symbolSlow = "&uarr;";
            symbolFast = "&darr;";
            buttonTimingStyle += "font-weight: bolder;";
        }
        // generate the HTML code for the slide show's screen
        var screen = 
            "<div id=\""+ screenId +"\" class=\""+ screenClass +"\" style=\""+ screenStyle +"\">\n" +
                "<div id=\""+ controlsId +"\" class=\""+ controlsClass +"\" style=\""+ controlsStyle +"\">\n" +
                        "<input id=\""+ buttonFirstId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"Erstes Bild\" value=\""+ symbolFirst +"\" onclick=\"AdvanceSlide( 0 )\">\n" +
                        "<input id=\""+ buttonPreviousId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"Vorheriges Bild\" value=\""+ symbolPrevious +"\" onclick=\"AdvanceSlide( -1, true )\">\n" +
                        "<input id=\""+ buttonStartId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"Fortsetzung\" value=\""+ symbolStart +"\" onclick=\"ResumeSlideShow()\">\n" +
                        "<input id=\""+ buttonPauseId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"Pause\" value=\""+ symbolPause +"\" onclick=\"PauseSlideShow()\">\n" +
                        "<input id=\""+ buttonStopId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"Stopp: Zur&uuml;ck zur Fotogalerie\" value=\""+ symbolStop +"\" onclick=\"StopSlideShow()\">\n" +
                        "<input id=\""+ buttonNextId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"N&auml;chstes Bild\" value=\""+ symbolNext +"\" onclick=\"AdvanceSlide( 1, true )\">\n" +
                        "<input id=\""+ buttonLastId +"\" type=\"button\" class=\""+ buttonAdvanceClass +"\" style=\""+ buttonAdvanceStyle +"\" " +
                            "title=\"Letztes Bild\" value=\""+ symbolLast +"\" onclick=\"AdvanceSlide( -1 )\">" +
                        "<span class=\""+ groupDividerClass +"\" style=\"display: inline-block;"+ groupDividerStyle +"\"></span>" +
                        "<input id=\""+ buttonRepeatId +"\" type=\"button\" class=\""+ buttonRepeatClass +"\" style=\""+ buttonRepeatStyle +"\" " +
                            "title=\"Wiederholung\" value=\""+ symbolRepeat +"\" onclick=\"SetRepeatMode()\">" +
                        "<span class=\""+ groupDividerClass +"\" style=\"display: inline-block;"+ groupDividerStyle +"\"></span>" +
                        "<input id=\""+ buttonSlowId +"\" type=\"button\" class=\""+ buttonTimingClass +"\" style=\""+ buttonTimingStyle +"\" " +
                            "title=\"Langsamer\" value=\""+ symbolSlow +"\" onclick=\"DecreaseDelay()\">\n" +
                    	"<select id=\""+ choiceTimingId +"\" class=\""+ choiceTimingClass +"\" style=\""+ choiceTimingStyle +"\" " +
                    	    "title=\"Automatischer Bildwechsel\" onchange=\"ResumeSlideShow( this.value )\">\n" +
                        	"<option value=\"0\" selected=\"selected\">Pause</option>\n" +
                        	"<option value=\"1000\">1 Sekunde</option>\n" +
                        	"<option value=\"2000\">2 Sekunden</option>\n" +
                        	"<option value=\"3000\">3 Sekunden</option>\n" +
                        	"<option value=\"4000\">4 Sekunden</option>\n" +
                        	"<option value=\"5000\">5 Sekunden</option>\n" +
                        	"<option value=\"10000\">10 Sekunden</option>\n" +
                        	"<option value=\"15000\">15 Sekunden</option>\n" +
                        	"<option value=\"20000\">20 Sekunden</option>\n" +
                        	"<option value=\"25000\">25 Sekunden</option>\n" +
                        	"<option value=\"30000\">30 Sekunden</option>\n" +
                        	"<option value=\"40000\">40 Sekunden</option>\n" +
                        	"<option value=\"50000\">50 Sekunden</option>\n" +
                        	"<option value=\"60000\">60 Sekunden</option>\n" +
                    	"</select>\n" +
                        "<input id=\""+ buttonFastId +"\" type=\"button\" class=\""+ buttonTimingClass +"\" style=\""+ buttonTimingStyle +"\" " +
                            "title=\"Schneller\" value=\""+ symbolFast +"\" onclick=\"IncreaseDelay()\">\n" +
                "</div>\n" +
                "<div id=\""+ slideId0 +"\" class=\""+ slideClass +"\" style=\""+ slideStyle +"\">\n" +
                    "<div id=\""+ frameId0 +"\" class=\""+ frameClass +"\" style=\""+ frameStyle +"\">\n" +
                    "</div>\n" +
                    "<div id=\""+ captionId0 +"\" class=\""+ captionClass +"\" style=\""+ captionStyle +"\">\n" +
                    "</div>\n" +
                "</div>\n" +
                "<div id=\""+ slideId1 +"\" class=\""+ slideClass +"\" style=\""+ slideStyle +"\">\n" +
                    "<div id=\""+ frameId1 +"\" class=\""+ frameClass +"\" style=\""+ frameStyle +"\">\n" +
                    "</div>\n" +
                    "<div id=\""+ captionId1 +"\" class=\""+ captionClass +"\" style=\""+ captionStyle +"\">\n" +
                    "</div>\n" +
                "</div>\n" +
            "</div>\n";
        // store the slide-show settings in the descriptor and start the show
        try
        {
            // insert the slide show's screen into its hosting element
            slideShow.sections.host.innerHTML = screen + slideShow.sections.host.innerHTML;
            // record references to the slide show's sections
            slideShow.sections.screen = document.getElementById( screenId );
            slideShow.sections.controls = document.getElementById( controlsId );
            slideShow.sections.slides.push(
                { slide: document.getElementById( slideId0 ),
                  frame: document.getElementById( frameId0 ),
                  caption: document.getElementById( captionId0 ),
                  image: undefined
                } );
            slideShow.sections.slides.push(
                { slide: document.getElementById( slideId1 ),
                  frame: document.getElementById( frameId1 ),
                  caption: document.getElementById( captionId1 ),
                  image: undefined
                } );
            slideShow.sections.next = 0;
            // record references to the slide show's controls
            slideShow.controls.first = document.getElementById( buttonFirstId );
            slideShow.controls.previous = document.getElementById( buttonPreviousId );
            slideShow.controls.start = document.getElementById( buttonStartId );
            slideShow.controls.pause = document.getElementById( buttonPauseId );
            slideShow.controls.stop = document.getElementById( buttonStopId );
            slideShow.controls.next = document.getElementById( buttonNextId );
            slideShow.controls.last = document.getElementById( buttonLastId );
            slideShow.controls.repeat = document.getElementById( buttonRepeatId );
            slideShow.controls.slow = document.getElementById( buttonSlowId );
            slideShow.controls.fast = document.getElementById( buttonFastId );
            slideShow.controls.delay = document.getElementById( choiceTimingId );
            // initialize configurable parameters
            slideShow.advance.delay = slideShowConfig.delay;
            slideShow.repeat = slideShowConfig.repeat;
            // determine the starting slide
            slideShow.index = ( index )? index : 0;
            // adjust the controls according to the paused state and display 
            // the desired starting slide
            var delay = ( paused )? 0 : slideShow.controls.delay.value;
            // fade the slide show in
            var fading = StartEffectsTimer( slideShow,
                slideShowConfig.fading.cycles, slideShowConfig.fading.delay,
                "FadeObject( slideShow.sections.screen, "+ (100 / slideShowConfig.fading.cycles) +" )",
                "PauseResumeSlideShow( slideShow, "+ delay +", 0 )" );
            // trigger the subsequent processing manually if the effects timer 
            // should have failed
            if( ! fading )
            {
                success &= FadeObject( slideShow.sections.screen, 100 );
                success &= PauseResumeSlideShow( slideShow, delay, 0 );
            }
        }
        catch( exception )
        {
            success = false;
        }
    }
    return;
}



// --------------------------------------------------------------------------------
// AdvanceSlide()
// --------------------------------------------------------------------------------
// This function replaces the currently displayed slide either by the slide at
// a particular image index or the slide at a particular offset. Negative image
// indexes refer to index positions from the end of the image list.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> next = image index or offset to current slide
// Optional Parameters:
// >> isOffset = true for relative positioning, false for image index
// --------------------------------------------------------------------------------
// Return Value:
// << true if the desired slide has successfully been loaded 
// --------------------------------------------------------------------------------

function AdvanceSlide( next, isOffset )
{
    return( ShowSlide( slideShow, next, isOffset ) );
}



// --------------------------------------------------------------------------------
// SetRepeatMode()
// --------------------------------------------------------------------------------
// This function sets or toggles the slide show's continuous repetition mode and
// updates its control accordingly.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> None
// Optional Parameters:
// >> mode = true for continuous repetition, false for stop, undefined for toggle
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has successfully paused/resumed with the new interval 
// --------------------------------------------------------------------------------

function SetRepeatMode( mode )
{
    // set or toggle the repeat mode
    slideShow.repeat = ( mode != undefined )? mode : !( slideShow.repeat );
    return( AdjustControls( slideShow ) );
}



// --------------------------------------------------------------------------------
// DecreaseDelay()
// --------------------------------------------------------------------------------
// This function decreases the auto-advance interval to the next smaller value
// defined in the timing selector and updates the show's controls accordingly.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> None
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has successfully paused/resumed with the new interval 
// --------------------------------------------------------------------------------

function DecreaseDelay()
{
    var excpetion;
    var success = true;
    try
    {
        if( slideShow.controls.delay.selectedIndex > 0 )
        {
            slideShow.controls.delay.selectedIndex--;
            success &= PauseResumeSlideShow( slideShow, slideShow.controls.delay.value );
        }
    }
    catch( exception )
    {
        success = false;
    }
    return( success );
}



// --------------------------------------------------------------------------------
// IncreaseDelay()
// --------------------------------------------------------------------------------
// This function increases the auto-advance interval to the next larger value
// defined in the timing selector and updates the show's controls accordingly.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> None
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has successfully paused/resumed with the new interval 
// --------------------------------------------------------------------------------

function IncreaseDelay()
{
    var excpetion;
    var success = true;
    try
    {
        if( slideShow.controls.delay.selectedIndex + 1 < slideShow.controls.delay.options.length )
        {
            slideShow.controls.delay.selectedIndex++;
            success &= PauseResumeSlideShow( slideShow, slideShow.controls.delay.value );
        }
    }
    catch( exception )
    {
        success = false;
    }
    return( success );
}



// --------------------------------------------------------------------------------
// PauseSlideShow()
// --------------------------------------------------------------------------------
// This function pauses the slide show by stopping the auto-advance timer and
// updating the show's controls accordingly.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> None
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has successfully paused
// --------------------------------------------------------------------------------

function PauseSlideShow()
{
    return( PauseResumeSlideShow( slideShow, 0 ) );
}



// --------------------------------------------------------------------------------
// ResumeSlideShow()
// --------------------------------------------------------------------------------
// This function resumes the slide show by restarting the auto-advance timer,
// displaying the desired next slide, and updating the show's controls accordingly.
// --------------------------------------------------------------------------------
// Optional Parameters:
// >> delay = desired auto-advance interval
// >> step = increment to the next slide
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has successfully resumed with the desired parameters
// --------------------------------------------------------------------------------

function ResumeSlideShow( delay, step )
{
    return( PauseResumeSlideShow( slideShow, delay, step ) );
}



// --------------------------------------------------------------------------------
// StopSlideShow()
// --------------------------------------------------------------------------------
// This function stops the slide show, fades the screen out, and removes its 
// display area from the client window.
// --------------------------------------------------------------------------------
// Optional Parameters:
// >> None
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has terminated without errors
// --------------------------------------------------------------------------------

function StopSlideShow()
{
    // pause the slide show in order to disable all timing provisions
    var success = StopEffectsTimer( slideShow );
    success &= PauseResumeSlideShow( slideShow, 0 );
    // fade the slide show out
    var fading = StartEffectsTimer( slideShow,
        slideShowConfig.fading.cycles, slideShowConfig.fading.delay,
        "FadeObject( slideShow.sections.screen, "+ (-100 / slideShowConfig.fading.cycles) +" )",
        "CloseSlideShow( slideShow )" );
    // trigger the subsequent processing manually if the effects timer 
    // should have failed
    if( ! fading )
    {
        success &= CloseSlideShow( slideShow );
    }
    return( success );
}



// --------------------------------------------------------------------------------
// Supplemental Internal Functions
// --------------------------------------------------------------------------------



// --------------------------------------------------------------------------------
// CloseSlideShow()
// --------------------------------------------------------------------------------
// This function closes the slide show and removes its display area from the client
// window.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show was closed without errors
// --------------------------------------------------------------------------------

function CloseSlideShow( show )
{
    if( show )
    {
        // remove the slide show's screen from the document
        if( slideShow.sections.screen )
        {
            var success = true;
            try
            {
                slideShow.sections.screen.parentNode.removeChild( slideShow.sections.screen );
            }
            catch( exception )
            {
                success = false;
            }
        }
        // remove references to the slide show's sections
        slideShow.sections.screen = undefined;
        slideShow.sections.controls = undefined;
        slideShow.sections.slides.splice( 0, slideShow.sections.slides.length );
        slideShow.sections.next = undefined;
        // remove references to the slide show's controls
        slideShow.controls.first = undefined;
        slideShow.controls.previous = undefined;
        slideShow.controls.start = undefined;
        slideShow.controls.pause = undefined;
        slideShow.controls.stop = undefined;
        slideShow.controls.next = undefined;
        slideShow.controls.last = undefined;
        slideShow.controls.repeat = undefined;
        slideShow.controls.slow = undefined;
        slideShow.controls.fast = undefined;
        slideShow.controls.delay = undefined;
        return( success );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// PauseResumeSlideShow()
// --------------------------------------------------------------------------------
// This function pauses or resumes the slide show by stopping or restarting the 
// auto-advance timer, displaying the desired (next) slide, and updating the show's 
// controls accordingly.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// Optional Parameters:
// >> delay = desired auto-advance interval
// >> step = increment to the next slide
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide show has successfully paused/resumed
// --------------------------------------------------------------------------------

function PauseResumeSlideShow( show, delay, step )
{
    var exception;
    // pause the slide show timer, preserving the previous interval settings
    var success = StopSlideShowTimer( show );
    if( delay != undefined && delay <= 0 )
    {
        // display the starting slide if show has just been started,
        // i.e. if slide area is still empty
        if( show.sections.slides[ 0 ].frame.innerHTML.search( /<img\s/i ) < 0 )
        {
            for( var i = 0; i < show.sections.slides.length; i++ )
            {
                success &= FadeObject( show.sections.slides[ i ].slide, -100 );
            }
            success &= ShowSlide( show, 0, true );
        }
        // adjust the slide show's controls
        success &= SelectOptionByValue( show.controls.delay, 0 );
        success &= AdjustControls( show );
    }
    else 
    {
        // start or resume the show at the desired (successor) slide 
        // with the desired auto-advance interval
        show.advance.delay = ( delay != undefined && delay > 0 )? delay : show.advance.delay;
        if( show.advance.delay != undefined && show.advance.delay > 0 )
        {
            // advance to the next slide if no particular increment is given
            step = ( step != undefined )? step : 1;
            success &= ShowSlide( show, step, true );
            if( show.repeat || show.index + 1 < show.images.length )
            {
                // start the auto-advance timer (the advance-slide function won't start
                // an inactive timer)
                success &= StartSlideShowTimer( show, show.advance.delay );
                success &= StartSlideShowTimer( show, -slideShowConfig.timeout, "PauseResumeSlideShow( "+ show.name +", 0 )" );
                // adjust the slide show's controls
                success &= SelectOptionByValue( show.controls.delay, show.advance.delay );
                success &= AdjustControls( show );
            }
            else
            {
                // adjust the slide show's controls
                success &= SelectOptionByValue( show.controls.delay, 0 );
                success &= AdjustControls( show );
            }
        }
        else
        {
            success = false;
        }
    }
    return( success );
}



// --------------------------------------------------------------------------------
// SelectOptionByValue()
// --------------------------------------------------------------------------------
// This function selects a choice's option that matches the supplied value.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> choice = DOM object to be updated
// >> value = value to be selected
// --------------------------------------------------------------------------------
// Return Value:
// << true if the selector could be updated successfully
// --------------------------------------------------------------------------------

function SelectOptionByValue( choice, value )
{
    if( choice && choice.options.length > 0 )
    {
        for( var i = 0; i < choice.options.length; i++ )
        {
            if( choice.options[ i ].value == value )
            {
                choice.selectedIndex = i;
                return( true );
            }
        }
    }
    return( false );
}



// --------------------------------------------------------------------------------
// ShowSlide()
// --------------------------------------------------------------------------------
// This function stops the slide show's auto-advance timer, loads a particular
// slide, and restarts the timer with a potentially new interval. The slide to 
// be loaded can be specified either by its image index, where negative indexes 
// count from the end of the image list, or relative to the currently displayed 
// slide. If repeat mode is enabled, an offset can wrap around the start or end
// of the image list. The function will further respect a previously inactive 
// auto-advance timer and not create a new one.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// >> next = image index or offset to current slide
// Optional Parameters:
// >> isOffset = true for relative positioning, false for image index
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide was loaded without errors
// --------------------------------------------------------------------------------

function ShowSlide( show, next, isOffset )
{
    // advance slide if slide show is defined
    if( show && show.sections.slides[ show.sections.next ] && show.images && show.images.length > 0 && next != undefined )
    {
        // skip update if there's only one slide, except for a zero offset (meaning refresh)
        if( ( isOffset && next == 0 ) || show.images.length > 1 )
        {
            var success = true;
            // pause a running slide-show timer, preserving the previous state and interval
            var advance = StopSlideShowTimer( show );
            // without wrap-around, check whether the index points to a valid image-list entry
            if( show.repeat
            ||  ! isOffset && -show.images.length <= next && next < show.images.length 
            ||  isOffset && 0 <= show.index + next && show.index + next < show.images.length )
            {
                // determine the next slide, wrapping around at the first/last image
                var index = ( isOffset )? show.index + next : next;
                index %= show.images.length;    // this brings us into ±images.length
                index += show.images.length;    // this brings us into the positive range
                index %= show.images.length;    // this finally yields a positive index
                // create an appropriate image tag in the slide section, avoiding
                // unnecessary updates to prevent from flickering
                if( ( isOffset && next == 0 ) || index != show.index )
                {
                    // remove the previous caption to avoid flickering while the image is being loaded
                    var exception;
                    try
                    {
                        var slide = show.sections.slides[ show.sections.next ];
                        var imageId = slideShowConfig.prefix + "Image" + show.sections.next;
                        slide.caption.innerHTML = "<p>&nbsp;</p>\n";
                        slide.frame.innerHTML = 
                            "<img id=\""+ imageId +"\" src=\""+ show.images[ index ].url +"\" class=\"slideshow-slide-image\" " +
                            // alt tag intentionally left empty to avoid flickering text upon image load
                            "title=\""+ show.images[ index ].title +"\" alt=\"\" " +
                            "onload=\"AdjustSlide( "+ show.name +" )\">\n";
                        slide.image = document.getElementById( imageId );
                    }
                    catch( exception )
                    {
                        success = false;
                    }
                }
                show.index = index;
                advance &= ( show.repeat || show.index + 1 < show.images.length );
            }
            // restart the slide-show timer with a potentially different delay and
            // adjust the slide show's controls
            if( advance )
            {
                success &= StartSlideShowTimer( show, -slideShowConfig.timeout, "PauseResumeSlideShow( "+ show.name +", 0 )" );
                success &= AdjustControls( show );
            }
            else
            {
                success &= PauseResumeSlideShow( show, 0 );
            }
            return( success );
        }
    }
    return( false );
}



// --------------------------------------------------------------------------------
// AdjustSlide()
// --------------------------------------------------------------------------------
// This function makes adjustments to the slide or supplemental sections once the
// image has been fully loaded. In particular, the function adusts the caption to
// either the slide or windows width. After scaling the image to completely fit
// into the window's client area, it cross-fades the old into the new image.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << true if the slide adjustments were completed without errors
// --------------------------------------------------------------------------------

function AdjustSlide( show )
{
    var exception;
    var success = true;
    try
    {
        var slide = show.sections.slides[ show.sections.next ];
        // determine the image's original dimensions
        var imageWidth = slide.image.width;
        var imageHeight = slide.image.height;
        // determine the dimensions of the client window; this requires a particular
        // approach depending on the type of the browser
        var clientWidth;
        var clientHeight;
        if( typeof( window.innerWidth ) != "undefined" )
        {
            clientWidth = window.innerWidth;
            clientHeight = window.innerHeight;
        }
        else if( typeof( document.documentElement.clientHeight ) != "undefined" )
        {
            clientWidth = document.documentElement.clientWidth;
            clientHeight = document.documentElement.clientHeight ;
        }
        if( clientHeight <= 0 && typeof( document.documentElement.innerWidth ) != "undefined" )
        {
            clientWidth = document.documentElement.innerWidth;
            clientHeight = document.documentElement.innerHeight;
        }
        // determine the usable dimensions of the client window, summing up the
        // offsets of all parent elements
        var offsetLeft = 0;
        var offsetTop = 0;
        for( var element = slide.frame; element != null; element = element.parentNode )
        {
            offsetLeft += element.offsetLeft;
            offsetTop += element.offsetTop;
            if( element == show.sections.screen )
            {
                break;
            }
        }
        var maxWidth = clientWidth - offsetLeft - slideShowConfig.scrollBars.width;
        var maxHeight = clientHeight - offsetTop - slideShowConfig.scrollBars.height;
        // add the image's title as caption; if this would be done before the image
        // has been loaded completely, the caption would jump up (when starting to 
        // load the image) and down (when finished loading) and thus cause a nasty
        // "flickering" upon image switch-over - but currently such "flickering" is
        // invisible due to the transparency before the actual switch-over
        slide.caption.innerHTML = "<p class=\"slideshow-caption\">"+ show.images[ show.index ].title +"</p>";
        slide.caption.style.width = maxWidth + "px";
        // check whether the image is too wide and adjust its dimensions accordingly
        if( imageWidth > maxWidth )
        {
            imageHeight = Math.round( imageHeight / imageWidth * maxWidth );
            imageWidth = maxWidth;
        }
        // check whether the image is too high and adjust its dimensions accordingly; 
        // since the caption's section may have changed its height when it got a new 
        // width assigned, we cannot take its height into account earlier
        maxHeight -= slide.caption.clientHeight;
        if( imageHeight > maxHeight )
        {
            imageWidth = Math.round( imageWidth / imageHeight * maxHeight );
            imageHeight = maxHeight;
        }
        // finally scale the image
        if( imageWidth != slide.image.width || imageHeight != slide.image.height )
        {
            slide.image.style.width = imageWidth + "px";
            slide.image.style.height = imageHeight + "px";
        }
    }
    catch( exception )
    {
        success = false;
    }
    finally
    {
        // fade the previous slide out and the new slide in
        var nextSlide = "show.sections.slides[ "+ show.sections.next +" ].slide";
        show.sections.next = ( show.sections.next != 0 )? 0 : 1;
        var lastSlide = "show.sections.slides[ "+ show.sections.next +" ].slide";
        var delta = 100 / slideShowConfig.fading.cycles;
        var fading = StartEffectsTimer( slideShow,
            slideShowConfig.fading.cycles, slideShowConfig.fading.delay,
            "FadeObject( "+ lastSlide +", "+ (-delta) +" ); FadeObject( "+ nextSlide +", "+ delta +" )" );
        // switch the slides manually if fading should have failed
        if( ! fading )
        {
            success &= eval( "FadeObject( "+ lastSlide +", -100 )" );
            success &= eval( "FadeObject( "+ nextSlide +", 100 )" );
        }
		// start the timer image's display interval and adjust controls
		if( SlideShowTimerIsRunning( show ) )
		{
			success &= StartSlideShowTimer( show, show.advance.delay, "ShowSlide( "+ show.name +", 1, true )" );
			success &= AdjustControls( show );
		}
    }
    return( success );
}



// --------------------------------------------------------------------------------
// AdjustControls()
// --------------------------------------------------------------------------------
// This function adjusts the slide show's control to reflect the operational
// capabiltiies the user has according to the shows current status. This means
// that the function disables controls that cannot be used, e.g. a paused button
// for an already paused show, or (re-)enables controls that can be used (again).
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << true if the controls were adjusted without errors
// --------------------------------------------------------------------------------

function AdjustControls( show )
{
    var success = true;
    try
    {
        // update the repeat-mode button
        show.repeat = ( show.images.length > 1 )? show.repeat : 0;
        if( show.repeat )
        {
            // ungray the repeat-mode button
            show.controls.repeat.style.color = "";
        }
        else
        {
            // gray out the repeat-mode button
            show.controls.repeat.style.color = slideShowConfig.gray;
        }
        // update the first-slide button
        if( show.index > 0 )
        {
            // not at first slide or wrap-around permitted
            // enable and ungray the first-slide button
            show.controls.first.disabled = false;
            show.controls.first.style.color = "";
        }
        else
        {
            // at first slide and wrap-around prohibited
            // disable and gray out the first-slide button
            show.controls.first.disabled = true;
            show.controls.first.style.color = slideShowConfig.gray;
        }
        // update the previous-slide button
        if( show.repeat || show.index > 0 )
        {
            // not at first slide or wrap-around permitted
            // enable and ungray the previous-slide button
            show.controls.previous.disabled = false;
            show.controls.previous.style.color = "";
        }
        else
        {
            // at first slide and wrap-around prohibited
            // disable and gray out the previous-slide button
            show.controls.previous.disabled = true;
            show.controls.previous.style.color = slideShowConfig.gray;
        }
        // update the next-slide button
        if( show.repeat || show.index + 1 < show.images.length )
        {
            // not at last slide or wrap-around permitted
            // enable and ungray the next-slide button
            show.controls.next.disabled = false;
            show.controls.next.style.color = "";
        }
        else
        {
            // at last slide and wrap-around prohibited
            // disable and gray out the next-slide button
            show.controls.next.disabled = true;
            show.controls.next.style.color = slideShowConfig.gray;
        }
        // update the last-slide button
        if( show.index + 1 < show.images.length )
        {
            // not at last slide or wrap-around permitted
            // enable and ungray the last-slide button
            show.controls.last.disabled = false;
            show.controls.last.style.color = "";
        }
        else
        {
            // at last slide and wrap-around prohibited
            // disable and gray out the last-slide button
            show.controls.last.disabled = true;
            show.controls.last.style.color = slideShowConfig.gray;
        }
        // update the start button
        if( show.advance.timer != undefined || ! show.repeat && show.index + 1 >= show.images.length )
        {
            // show is running or at end
            // disable and gray out the start button
            show.controls.start.disabled = true;
            show.controls.start.style.color = slideShowConfig.gray;
        }
        else
        {
            // show is paused
            // enable and ungray the start button
            show.controls.start.disabled = false;
            show.controls.start.style.color = "";
        }
        // update the pause button
        if( show.advance.timer == undefined || ! show.repeat && show.index + 1 >= show.images.length )
        {
            // show is paused
            // disable and gray out the pause button
            show.controls.pause.disabled = true;
            show.controls.pause.style.color = slideShowConfig.gray;
        }
        else
        {
            // show is running or at end
            // enable and ungray the pause button
            show.controls.pause.disabled = false;
            show.controls.pause.style.color = "";
        }
        // update the slow button
        if( show.controls.delay.selectedIndex == 0 )
        {
            // disable and gray out the slow button
            show.controls.slow.disabled = true;
            show.controls.slow.style.color = slideShowConfig.gray;
        }
        else
        {
            // enable and ungray the slow button
            show.controls.slow.disabled = false;
            show.controls.slow.style.color = "";
        }
        // update the fast button
        if( show.images.length <= 1 || ! show.repeat && show.index + 1 >= show.images.length 
        ||  show.controls.delay.selectedIndex >= show.controls.delay.options.length - 1 )
        {
            // disable and gray out the fast button
            show.controls.fast.disabled = true;
            show.controls.fast.style.color = slideShowConfig.gray;
        }
        else
        {
            // enable and ungray the fast button
            show.controls.fast.disabled = false;
            show.controls.fast.style.color = "";
        }
    }
    catch( exception )
    {
        success = false;
    }
    return( success );
}



// --------------------------------------------------------------------------------
// StartSlideShowTimer()
// --------------------------------------------------------------------------------
// This function starts the timer controlling the auto-advance to the next slide.
// The timer has a two-fold meaning: A negative delay value refers to the time-out
// for loading an image, while a positive delay value refers to the time the loaded 
// image is to be displayed. Without command, the only the image-display interval
// is recorded.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// >> delay = desired auto-advance interval
// >> command = command to execute upon expiration
// --------------------------------------------------------------------------------
// Return Value:
// << true if the timer started without errors
// --------------------------------------------------------------------------------

function StartSlideShowTimer( show, delay, command )
{
    // stop a potentially running timer; we don't have to bother with the success
    // of this operation because there may have been no running timer
    StopSlideShowTimer( show );
    // restart the timer with the desired interval
    if( delay != undefined && delay != 0 )
    {
        var exception;
        var success = true;
        try
        {
			// determine and record desired delay
			if( delay > 0 )
			{
				// positive delays means display time, so record
				show.advance.delay = delay;
			}
			else
			{
				// negative delay means timeout, so consider volatile
				delay = -delay;
			}
			// start timer if command has been supplied
			if( command )
			{
				show.advance.command = command;
				show.advance.timer = setInterval( command, delay );
			}
        }
        catch( exception )
        {
            show.advance.delay = undefined;
            success = false;
        }
        return( success );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// StopSlideShowTimer()
// --------------------------------------------------------------------------------
// This function stops the timer controlling the auto-advance to the next slide.
// --------------------------------------------------------------------------------
// Optional Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << true if the timer stopped without errors, false if no timer was active
// --------------------------------------------------------------------------------

function StopSlideShowTimer( show )
{
    var exception;
    // stop the slide-advance timer
    if( show.advance.timer )
    {
        var success = true;
        try
        {
            clearInterval( show.advance.timer );
        }
        catch( exception )
        {
            success = false;
        }
        finally
        {
            show.advance.timer = undefined;
        }
        return( success );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// SlideShowTimerIsRunning()
// --------------------------------------------------------------------------------
// This function checks whether the timer controlling the auto-advance to the next 
// slide is currently running.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << true if the timer is running
// --------------------------------------------------------------------------------

function SlideShowTimerIsRunning( show )
{
    return( show.advance.timer != undefined );
}



// --------------------------------------------------------------------------------
// StartEffectsTimer()
// --------------------------------------------------------------------------------
// This function starts an effects timer that executes a particular command upon
// each iteration plus an additional command upon termination, i.e. right after
// the last iteration. If an effects timer could not be started, the function
// executes the termination command for triggering the subsequent processing.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// >> cycles = number of desired iterations
// >> delay = interval between iterations
// Optional Parameters:
// >> iteration = command to be executed per iteration
// >> termination = command to be execution right after last iteration
// --------------------------------------------------------------------------------
// Return Value:
// << true if the effects timer could be started successfully, or the return value 
//    of the termination function otherwise
// --------------------------------------------------------------------------------

function StartEffectsTimer( show, cycles, delay, iteration, termination )
{
    if( show )
    {
        if( cycles != undefined && cycles > 0
        &&  delay != undefined && delay > 0 )
        {
            show.effects.cycles = cycles;
            show.effects.iteration = iteration;
            show.effects.termination = termination;
            show.effects.timer = setInterval( "HandleEffectsTimer( "+ show.name +" )", delay );
            return( show.effects.timer != undefined );
        }
        return( eval( termination ) );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// HandleEffectsTimer()
// --------------------------------------------------------------------------------
// This function handles the iterations of a previously started effects timer. 
// The function first executes an iteration command to stimulate an effect. In 
// case of the last iteration, the function clears the effects timer and executes 
// a termination command for triggering the subsequent processing.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << the return value of the iteration or termination command, or false in case
//    of an error
// --------------------------------------------------------------------------------

function HandleEffectsTimer( show )
{
    if( show )
    {
		var success = eval( show.effects.iteration );
        if( --show.effects.cycles <= 0 )
        {
            clearInterval( show.effects.timer );
            if( show.effects.termination )
			{
				success &= eval( show.effects.termination );
			}
            show.effects.timer = undefined;
            show.effects.cycles = undefined;
            show.effects.iteration = undefined;
            show.effects.termination = undefined;
        }
        return( success );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// StopEffectsTimer()
// --------------------------------------------------------------------------------
// This function stops an effects timer. The function does neither fake the pending 
// iterations or execute the termination command. It is the callers responsibility
// to clean up.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> show = the slide show's descriptor
// --------------------------------------------------------------------------------
// Return Value:
// << true if the effects timer could be stopped successfully
// --------------------------------------------------------------------------------

function StopEffectsTimer( show )
{
    if( show )
    {
        if( show.effects.timer )
        {
            clearInterval( show.effects.timer );
            show.effects.timer = undefined;
            show.effects.cycles = undefined;
            show.effects.iteration = undefined;
            show.effects.termination = undefined;
        }
        return( true );
    }
    return( false );
}



// --------------------------------------------------------------------------------
// FadeObject()
// --------------------------------------------------------------------------------
// This function adjusts the opacity of a DOM object (HTML element) by a 
// particular increment or decrement.
// --------------------------------------------------------------------------------
// Required Parameters:
// <> object = DOM object to be faded
// >> delta = increment or decrement
// --------------------------------------------------------------------------------
// Return Value:
// << true if the fading step completed successfully 
// --------------------------------------------------------------------------------

function FadeObject( object, delta )
{
    var exception;
    var opacity;
    var success = true;
    try
    {
        // adjusting the opacity requires varying strategies depending on the type
        // of the browser
        if( typeof( object.style.filter ) != "undefined" )
        {
            // Microsoft Internet Explorer
            // unfortunately, IE does not allow to fade in the background
            opacity = object.style.filter;
            opacity = opacity.replace( /^.*opacity\s+=\s+(\d+)[^\d]*$/, "$1" );
            opacity = parseInt( opacity );
            opacity = ( opacity )? opacity + delta : delta;
			// to overcome ghost images due to computing imprecisions, opactiy values
			// close to their extremes "snap" to their end positions
            if( opacity < 1 )
            {
                opacity = 0;
            }
            else if( opacity > 99 )
            {
                opacity = 100;
            }
            object.style.filter = "alpha( opacity = "+ opacity +" )";
        }
        if( typeof( object.style.opacity ) != "undefined" )
        {
            // basically all the rest, in particular browsers that control the opacity 
            // in a CSS-style manner
            opacity = ( object.style.opacity )? parseFloat( object.style.opacity ) : 0.0;
            opacity += delta / 100;
			// to overcome ghost images due to computing imprecisions, opactiy values
			// close to their extremes "snap" to their end positions
            if( opacity < 0.01 )
            {
                opacity = 0.0;
            }
            else if( opacity > 0.99 )
            {
                opacity = 1.0;
            }
            object.style.opacity = opacity;
        }
    }
    catch( exception )
    {
        success = false;
    }
    return( success );
}



// --------------------------------------------------------------------------------
// BrowserIsIE6()
// --------------------------------------------------------------------------------
// This function checks whether Microsoft Internet Explorer 6 is used for
// browsing the page.
// --------------------------------------------------------------------------------
// Required Parameters:
// >> None
// --------------------------------------------------------------------------------
// Return Value:
// << true if MSIE6 is used for browsing
// --------------------------------------------------------------------------------

function BrowserIsIE6()
{
    // http://msdn.microsoft.com/en-us/library/ms537509%28v=vs.85%29.aspx
    return( navigator.appName == 'Microsoft Internet Explorer' 
    &&      parseFloat( navigator.userAgent.replace( /^.*MSIE\s+([0-9]+[\.0-9]*).*$/, "$1" ) ) < 7.0 );

}
