gnomeweb-wml r6323 - in trunk: . www.gnome.org/projects/cheese www.gnome.org/projects/cheese/data/images www.gnome.org/projects/cheese/data/screenshots www.gnome.org/projects/cheese/data/shadowbox www.gnome.org/projects/cheese/data/shadowbox/css www.gnome.org/projects/cheese/data/shadowbox/images www.gnome.org/projects/cheese/data/shadowbox/js www.gnome.org/projects/cheese/data/themes/cheese www.gnome.org/projects/cheese/data/tour



Author: dgsiegel
Date: Sun Sep 21 14:16:52 2008
New Revision: 6323
URL: http://svn.gnome.org/viewvc/gnomeweb-wml?rev=6323&view=rev

Log:
add the new cheese tour for 2.24


Added:
   trunk/www.gnome.org/projects/cheese/data/images/cheese-2.24.png   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-countdown.jpg   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-effects.jpg   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-fullscreen.jpg   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-main.jpg   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-share.jpg   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/shadowbox/
   trunk/www.gnome.org/projects/cheese/data/shadowbox/css/
   trunk/www.gnome.org/projects/cheese/data/shadowbox/css/shadowbox-light.css
   trunk/www.gnome.org/projects/cheese/data/shadowbox/images/
   trunk/www.gnome.org/projects/cheese/data/shadowbox/images/loading-light.gif   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/shadowbox/js/
   trunk/www.gnome.org/projects/cheese/data/shadowbox/js/shadowbox-yui.js   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/shadowbox/js/shadowbox.js
   trunk/www.gnome.org/projects/cheese/data/shadowbox/js/yui-utilities.js   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-fullscreen.jpg   (contents, props changed)
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-prefs.jpg   (contents, props changed)
Modified:
   trunk/ChangeLog
   trunk/www.gnome.org/projects/cheese/Makefile.am
   trunk/www.gnome.org/projects/cheese/data/themes/cheese/document.screen.css
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-about.jpg
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-countdown.jpg
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-effects.jpg
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-main.jpg
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-share.jpg
   trunk/www.gnome.org/projects/cheese/data/tour/cheese-video.jpg
   trunk/www.gnome.org/projects/cheese/download.html
   trunk/www.gnome.org/projects/cheese/index.html
   trunk/www.gnome.org/projects/cheese/screenshots.html
   trunk/www.gnome.org/projects/cheese/tour.html

Modified: trunk/www.gnome.org/projects/cheese/Makefile.am
==============================================================================
--- trunk/www.gnome.org/projects/cheese/Makefile.am	(original)
+++ trunk/www.gnome.org/projects/cheese/Makefile.am	Sun Sep 21 14:16:52 2008
@@ -8,7 +8,7 @@
 page_SCRIPTS= \
 	index.html \
 	download.html \
-	screenshots.html \
+#	screenshots.html \
 	tour.html \
 	detect.py \
 	$(NULL)
@@ -39,6 +39,11 @@
 	data/screenshots/cheese-0.3.0.jpg \
 	data/screenshots/cheese-2.22.0.jpg \
 	data/screenshots/cheese-2.22.0_2.jpg \
+	data/screenshots/cheese-2.24.0-countdown.jpg \
+	data/screenshots/cheese-2.24.0-effects.jpg \
+	data/screenshots/cheese-2.24.0-fullscreen.jpg \
+	data/screenshots/cheese-2.24.0-main.jpg \
+	data/screenshots/cheese-2.24.0-share.jpg \
 	$(NULL)
 
 imagesdir = $(pagedir)/data/images
@@ -47,26 +52,46 @@
 	data/images/gnome-favicon.png \
 	data/images/package-x-generic.png \
 	data/images/preferences-desktop-wallpaper.png \
-  data/images/internet-group-chat.png \
-  data/images/system-users.png \
-  data/images/video-x-generic.png \
-  data/images/applications-development.png \
-  data/images/package-x-generic.png \
-  data/images/dialog-information.png \
-  data/images/application-x-executable.png \
-  data/images/dialog-warning.png \
-  data/images/cheese-tour.png \
-  data/images/cheese-birthday.png \
+	data/images/internet-group-chat.png \
+	data/images/system-users.png \
+	data/images/video-x-generic.png \
+	data/images/applications-development.png \
+	data/images/package-x-generic.png \
+	data/images/dialog-information.png \
+	data/images/application-x-executable.png \
+	data/images/dialog-warning.png \
+	data/images/cheese-tour.png \
+	data/images/cheese-birthday.png \
+	data/images/cheese-2.24.png \
 	$(NULL)
 
 tourdir = $(pagedir)/data/tour
 tour_DATA =\
-  data/tour/cheese-video.jpg \
-  data/tour/cheese-about.jpg \
-  data/tour/cheese-effects.jpg \
-  data/tour/cheese-countdown.jpg \
-  data/tour/cheese-share.jpg \
-  data/tour/cheese-main.jpg \
+	data/tour/cheese-video.jpg \
+	data/tour/cheese-about.jpg \
+	data/tour/cheese-effects.jpg \
+	data/tour/cheese-countdown.jpg \
+	data/tour/cheese-share.jpg \
+	data/tour/cheese-main.jpg \
+	data/tour/cheese-prefs.jpg \
+	data/tour/cheese-fullscreen.jpg \
+	$(NULL)
+
+shadowboximagesdir = $(pagedir)/data/shadowbox/images
+shadowboximages_DATA =\
+	data/shadowbox/images/loading-light.gif \
+	$(NULL)
+
+shadowboxcssdir = $(pagedir)/data/shadowbox/css
+shadowboximages_DATA =\
+	data/shadowbox/css/shadowbox-light.css \
+	$(NULL)
+
+shadowboxjsdir = $(pagedir)/data/shadowbox/js
+shadowboximages_DATA =\
+	data/shadowbox/js/shadowbox.js \
+	data/shadowbox/js/yui-utilities.js \
+	data/shadowbox/js/shadowbox-yui.js \
 	$(NULL)
 
 include $(top_srcdir)/rules.common

Added: trunk/www.gnome.org/projects/cheese/data/images/cheese-2.24.png
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-countdown.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-effects.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-fullscreen.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-main.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/screenshots/cheese-2.24.0-share.jpg
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/shadowbox/css/shadowbox-light.css
==============================================================================
--- (empty file)
+++ trunk/www.gnome.org/projects/cheese/data/shadowbox/css/shadowbox-light.css	Sun Sep 21 14:16:52 2008
@@ -0,0 +1,215 @@
+/**
+ * The CSS for Shadowbox.
+ *
+ * This file is part of Shadowbox.
+ *
+ * Shadowbox is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Shadowbox is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Shadowbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author      Michael J. I. Jackson <mjijackson gmail com>
+ * @copyright   2007 Michael J. I. Jackson
+ * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
+ * @version     SVN: $Id: shadowbox.js 150 2007-12-04 18:42:03Z michael $
+ */
+
+/*_________________________________________________________________  Overlay  */
+#shadowbox_overlay {
+  visibility: hidden;
+  position: absolute;
+  display: block;
+  margin: 0;
+  padding: 0;
+  top: 0;
+  left: 0;
+  z-index: 998;
+}
+
+/*_______________________________________________________________  Container  */
+#shadowbox_container {
+  position: fixed;
+  height: 0px;
+  width: 100%;
+  margin: 0;
+  padding: 0;
+  top: 0;
+  left: 0;
+  z-index: 999;
+  text-align: center; /* centers in quirks and IE */
+}
+
+/*_______________________________________________________________  Shadowbox  */
+#shadowbox {
+  display: none;
+  visibility: hidden;
+  margin: 0 auto;
+  position: relative;
+  font-family: 'Lucida Grande', Tahoma, sans-serif;
+  text-align: left; /* reset left alignment */
+  /*color: #888;*/
+}
+
+/*___________________________________________________________________  Title  */
+/*
+HTML snapshot:
+<div id="shadowbox_title">
+  <div id="shadowbox_title_inner">Title Here</div>
+</div>
+*/
+#shadowbox_title {
+  height: 30px;
+  padding: 0;
+  overflow: hidden;
+}
+#shadowbox_title_inner {
+  height: 16px;
+  font-size: 16px;
+  line-height: 16px;
+  white-space: nowrap;
+  padding: 10px 0 4px 10px;
+  background-color: #fff;
+  text-transform: lowercase;
+}
+
+/*____________________________________________________________________  Body  */
+/*
+HTML snapsnot:
+<div id="shadowbox_body">
+  <div id="shadowbox_body_inner">
+    <img src="my_image.jpg" id="shadowbox_content" height="350" width="580">
+  </div>
+  <div id="shadowbox_loading">
+    <div id="shadowbox_loading_img"></div>
+    <span><a href="javascript:Shadowbox.close();">Cancel</a></span>
+  </div>
+</div>
+*/
+#shadowbox_body {
+  position: relative;
+  overflow: hidden;
+  margin: 0;
+  padding: 0;
+  border: 10px solid #fff;
+  background-color: #eee;
+}
+#shadowbox_body_inner {
+  position: relative;
+  overflow: hidden;
+}
+#shadowbox_loading {
+  position: absolute;
+  top: 0;
+  left: 0;
+  height: 10000px; /* overflow:hidden will clip this */
+  width: 100%;
+  background-color: #ccc;
+}
+#shadowbox_loading img {
+  float: left;
+  margin: 10px 10px 0 10px;
+}
+#shadowbox_loading span {
+  float: left;
+  margin-top: 16px;
+  font-size: 10px;
+  text-transform: lowercase;
+}
+#shadowbox_loading span a,
+#shadowbox_loading span a:link,
+#shadowbox_loading span a:visited {
+  color: #fff;
+}
+#shadowbox_content.html { /* make html content scrollable */
+  height: 100%;
+  width: 100%;
+  overflow: auto;
+}
+
+/*_________________________________________________________________  Toolbar  */
+/*
+HTML snapshot:
+<div id="shadowbox_toolbar">
+  <div id="shadowbox_toolbar_inner">
+    <div id="shadowbox_nav_close">
+      <a href="javascript:Shadowbox.close();"><span class="shortcut">C</span>lose</a>
+    </div>
+    <div id="shadowbox_nav_next">
+      <a href="javascript:Shadowbox.next();"><span class="shortcut">N</span>ext</a>
+    </div>
+    <div id="shadowbox_nav_previous">
+      <a href="javascript:Shadowbox.previous();"><span class="shortcut">P</span>revious</a>
+    </div>
+    <div id="shadowbox_counter">
+      <a href="javascript:Shadowbox.change(0);">1</a>
+      <a href="javascript:Shadowbox.change(1);" class="shadowbox_counter_current">2</a>
+      <a href="javascript:Shadowbox.change(2);">3</a>
+    </div>
+  </div>
+</div>
+*/
+#shadowbox_toolbar {
+  margin: 0;
+  padding: 0;
+  height: 26px;
+  overflow: hidden;
+}
+#shadowbox_toolbar_inner {
+  height: 26px;
+  background-color: #fff;
+}
+#shadowbox_toolbar_inner div {
+  padding-top: 6px;
+  font-size: 10px;
+  height: 10px;
+  line-height: 10px;
+}
+#shadowbox_toolbar_inner div span.shortcut {
+  text-decoration: underline;
+  font-weight: bold;
+  text-transform: lowercase;
+}
+#shadowbox_toolbar_inner div a {
+  text-decoration: none;
+  color: #000;
+}
+#shadowbox_nav_close,
+#shadowbox_nav_previous,
+#shadowbox_nav_next {
+  float: right;
+  padding-right: 10px;
+}
+#shadowbox_counter {
+  float: left;
+  padding-left: 10px;
+}
+#shadowbox_counter a {
+  padding: 0 4px 0 0;
+}
+#shadowbox_counter a.shadowbox_counter_current {
+  text-decoration: underline;
+  font-weight: bold;
+}
+
+/*________________________________________________________________  Messages  */
+div.shadowbox_message {
+  text-align: center;
+  padding: 10px;
+}
+div.shadowbox_message a:link,
+div.shadowbox_message a:visited {
+  text-decoration: none;
+  color: #bed333;
+}
+div.shadowbox_message a:hover,
+div.shadowbox_message a:focus {
+  text-decoration: underline;
+}

Added: trunk/www.gnome.org/projects/cheese/data/shadowbox/images/loading-light.gif
==============================================================================
Binary file. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/shadowbox/js/shadowbox-yui.js
==============================================================================
--- (empty file)
+++ trunk/www.gnome.org/projects/cheese/data/shadowbox/js/shadowbox-yui.js	Sun Sep 21 14:16:52 2008
@@ -0,0 +1,181 @@
+/**
+ * An adapter for the Shadowbox media viewer and the Yahoo! User Interface (YUI)
+ * JavaScript library.
+ *
+ * This file is part of Shadowbox.
+ *
+ * Shadowbox is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Shadowbox is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Shadowbox.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author      Michael J. I. Jackson <mjijackson gmail com>
+ * @copyright   2007 Michael J. I. Jackson
+ * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
+ * @version     SVN: $Id: shadowbox-yui.js 48 2008-01-26 09:58:25Z mjijackson $
+ */
+
+if(typeof YAHOO == 'undefined'){
+    throw 'Unable to load Shadowbox, core YUI utilities (yahoo, dom, event, anim) not found.';
+}
+
+// create the Shadowbox object first
+var Shadowbox = {};
+
+Shadowbox.lib = function(){
+
+    var E = YAHOO.util.Event;
+    var D = YAHOO.util.Dom;
+
+    return {
+
+        /**
+         * Gets the value of the style on the given element.
+         *
+         * @param   {HTMLElement}   el      The DOM element
+         * @param   {String}        style   The name of the style (e.g. margin-top)
+         * @return  {mixed}                 The value of the given style
+         * @public
+         */
+        getStyle: function(el, style){
+            return D.getStyle(el, style);
+        },
+
+        /**
+         * Sets the style on the given element to the given value. May be an
+         * object to specify multiple values.
+         *
+         * @param   {HTMLElement}   el      The DOM element
+         * @param   {String/Object} style   The name of the style to set if a
+         *                                  string, or an object of name =>
+         *                                  value pairs
+         * @param   {String}        value   The value to set the given style to
+         * @return  void
+         * @public
+         */
+        setStyle: function(el, style, value){
+            if(typeof style != 'object'){
+                var temp = {};
+                temp[style] = value;
+                style = temp;
+            }
+            for(var s in style){
+                D.setStyle(el, s, style[s]);
+            }
+        },
+
+        /**
+         * Gets a reference to the given element.
+         *
+         * @param   {String/HTMLElement}    el      The element to fetch
+         * @return  {HTMLElement}                   A reference to the element
+         * @public
+         */
+        get: function(el){
+            return D.get(el);
+        },
+
+        /**
+         * Removes an element from the DOM.
+         *
+         * @param   {HTMLElement}           el      The element to remove
+         * @return  void
+         * @public
+         */
+        remove: function(el){
+            el.parentNode.removeChild(el);
+        },
+
+        /**
+         * Gets the target of the given event. The event object passed will be
+         * the same object that is passed to listeners registered with
+         * addEvent().
+         *
+         * @param   {mixed}                 e       The event object
+         * @return  {HTMLElement}                   The event's target element
+         * @public
+         */
+        getTarget: function(e){
+            return E.getTarget(e.browserEvent || e);
+        },
+
+        /**
+         * Prevents the event's default behavior. The event object passed will
+         * be the same object that is passed to listeners registered with
+         * addEvent().
+         *
+         * @param   {mixed}                 e       The event object
+         * @return  void
+         * @public
+         */
+        preventDefault: function(e){
+            E.preventDefault(e.browserEvent || e);
+        },
+
+        /**
+         * Adds an event listener to the given element. It is expected that this
+         * function will be passed the event as its first argument.
+         *
+         * @param   {HTMLElement}   el          The DOM element to listen to
+         * @param   {String}        name        The name of the event to register
+         *                                      (i.e. 'click', 'scroll', etc.)
+         * @param   {Function}      handler     The event handler function
+         * @return  void
+         * @public
+         */
+        addEvent: function(el, name, handler){
+            E.addListener(el, name, handler);
+        },
+
+        /**
+         * Removes an event listener from the given element.
+         *
+         * @param   {HTMLElement}   el          The DOM element to stop listening to
+         * @param   {String}        name        The name of the event to stop
+         *                                      listening for (i.e. 'click')
+         * @param   {Function}      handler     The event handler function
+         * @return  void
+         * @public
+         */
+        removeEvent: function(el, name, handler){
+            E.removeListener(el, name, handler);
+        },
+
+        /**
+         * Animates numerous styles of the given element. The second parameter
+         * of this function will be an object of the type that is expected by
+         * YAHOO.util.Anim. See http://developer.yahoo.com/yui/docs/YAHOO.util.Anim.html
+         * for more information.
+         *
+         * @param   {HTMLElement}   el          The DOM element to animate
+         * @param   {Object}        obj         The animation attributes/parameters
+         * @param   {Number}        duration    The duration of the animation
+         *                                      (in seconds)
+         * @param   {Function}      callback    A callback function to call when
+         *                                      the animation completes
+         * @return  void
+         * @public
+         */
+        animate: function(el, obj, duration, callback){
+            var anim = new YAHOO.util.Anim(el, obj, duration, YAHOO.util.Easing.easeOut);
+            if(typeof callback == 'function'){
+                var f = function(){
+                    anim.onComplete.unsubscribe(f);
+                    callback.call(anim, anim);
+                };
+                anim.onComplete.subscribe(f, anim, true);
+            }
+            anim.animate();
+        }
+
+    };
+
+}();

Added: trunk/www.gnome.org/projects/cheese/data/shadowbox/js/shadowbox.js
==============================================================================
--- (empty file)
+++ trunk/www.gnome.org/projects/cheese/data/shadowbox/js/shadowbox.js	Sun Sep 21 14:16:52 2008
@@ -0,0 +1,2537 @@
+/**
+ * A media-viewer script for web pages that allows content to be viewed without
+ * navigating away from the original linking page.
+ *
+ * This file is part of Shadowbox.
+ *
+ * Shadowbox is free software: you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option)
+ * any later version.
+ *
+ * Shadowbox is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Shadowbox. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @author      Michael J. I. Jackson <mjijackson gmail com>
+ * @copyright   2007 Michael J. I. Jackson
+ * @license     http://www.gnu.org/licenses/lgpl-3.0.txt GNU LGPL 3.0
+ * @version     SVN: $Id: shadowbox.js 75 2008-02-21 16:51:29Z mjijackson $
+ */
+
+if(typeof Shadowbox == 'undefined'){
+    throw 'Unable to load Shadowbox, no base library adapter found.';
+}
+
+/**
+ * The Shadowbox class. Used to display different media on a web page using a
+ * Lightbox-like effect.
+ *
+ * Useful resources:
+ * - http://www.alistapart.com/articles/byebyeembed
+ * - http://www.w3.org/TR/html401/struct/objects.html
+ * - http://www.dyn-web.com/dhtml/iframes/
+ * - http://support.microsoft.com/kb/316992
+ * - http://www.apple.com/quicktime/player/specs.html
+ * - http://www.howtocreate.co.uk/wrongWithIE/?chapter=navigator.plugins
+ *
+ * @class       Shadowbox
+ * @author      Michael J. I. Jackson <mjijackson gmail com>
+ * @singleton
+ */
+(function(){
+
+    /**
+     * The current version of Shadowbox.
+     *
+     * @property    {String}    version
+     * @private
+     */
+    var version = '1.0';
+
+    /**
+     * Contains the default options for Shadowbox. This object is almost
+     * entirely customizable.
+     *
+     * @property    {Object}    options
+     * @private
+     */
+    var options = {
+
+        /**
+         * A base URL that will be prepended to the loadingImage, flvPlayer, and
+         * overlayBgImage options to save on typing.
+         *
+         * @var     {String}    assetURL
+         */
+        assetURL:           '',
+
+        /**
+         * The path to the image to display while loading.
+         *
+         * @var     {String}    loadingImage
+         */
+        loadingImage:       'images/loading.gif',
+
+        /**
+         * Enable animations.
+         *
+         * @var     {Boolean}   animate
+         */
+        animate:            true,
+
+        /**
+         * Specifies the sequence of the height and width animations. May be
+         * 'wh' (width then height), 'hw' (height then width), or 'sync' (both
+         * at the same time). Of course this will only work if animate is true.
+         *
+         * @var     {String}    animSequence
+         */
+        animSequence:       'wh',
+
+        /**
+         * The path to flvplayer.swf.
+         *
+         * @var     {String}    flvPlayer
+         */
+        flvPlayer:          'flvplayer.swf',
+
+        /**
+         * The background color and opacity of the overlay. Note: When viewing
+         * movie files on FF Mac, the default background image will be used
+         * because that browser has problems displaying movies above layers
+         * that aren't 100% opaque.
+         *
+         * @var     {String}    overlayColor
+         */
+        overlayColor:       '#000',
+
+        /**
+         * The background opacity to use for the overlay.
+         *
+         * @var     {Number}    overlayOpacity
+         */
+        overlayOpacity:     0.85,
+
+        /**
+         * A background image to use for browsers such as FF Mac that don't
+         * support displaying movie content over backgrounds that aren't 100%
+         * opaque.
+         *
+         * @var     {String}    overlayBgImage
+         */
+        overlayBgImage:     'images/overlay-85.png',
+
+        /**
+         * Listen to the overlay for clicks. If the user clicks the overlay,
+         * it will trigger Shadowbox.close().
+         *
+         * @var     {Boolean}   listenOverlay
+         */
+        listenOverlay:      true,
+
+        /**
+         * Automatically play movies.
+         *
+         * @var     {Boolean}   autoplayMovies
+         */
+        autoplayMovies:     true,
+
+        /**
+         * Enable movie controllers on movie players.
+         *
+         * @var     {Boolean}   showMovieControls
+         */
+        showMovieControls:  true,
+
+        /**
+         * The duration of the resizing animations (in seconds).
+         *
+         * @var     {Number}    resizeDuration
+         */
+        resizeDuration:     0.35,
+
+        /**
+         * The duration of the overlay fade animation (in seconds).
+         *
+         * @var     {Number}    fadeDuration
+         */
+        fadeDuration:       0.35,
+
+        /**
+         * Show the navigation controls.
+         *
+         * @var     {Boolean}   displayNav
+         */
+        displayNav:         true,
+
+        /**
+         * Enable continuous galleries. When this is true, users will be able
+         * to skip to the first gallery image from the last using next and vice
+         * versa.
+         *
+         * @var     {Boolean}   continuous
+         */
+        continuous:         false,
+
+        /**
+         * Display the gallery counter.
+         *
+         * @var     {Boolean}   displayCounter
+         */
+        displayCounter:     true,
+
+        /**
+         * This option may be either 'default' or 'skip'. The default counter is
+         * a simple '1 of 5' message. The skip counter displays a link for each
+         * piece in the gallery that enables a user to skip directly to any
+         * piece.
+         *
+         * @var     {String}    counterType
+         */
+        counterType:        'default',
+
+        /**
+         * The amount of padding to maintain around the viewport edge (in
+         * pixels). This only applies when the image is very large and takes up
+         * the entire viewport.
+         *
+         * @var     {Number}    viewportPadding
+         */
+        viewportPadding:    20,
+
+        /**
+         * How to handle images that are too large for the viewport. 'resize'
+         * will resize the image while preserving aspect ratio and display it at
+         * the smaller resolution. 'drag' will display the image at its native
+         * resolution but it will be draggable within the Shadowbox. 'none' will
+         * display the image at its native resolution but it may be cropped.
+         *
+         * @var     {String}    handleLgImages
+         */
+        handleLgImages:     'resize',
+
+        /**
+         * The initial height of Shadowbox (in pixels).
+         *
+         * @var     {Number}    initialHeight
+         */
+        initialHeight:      160,
+
+        /**
+         * The initial width of Shadowbox (in pixels).
+         *
+         * @var     {Number}    initialWidth
+         */
+        initialWidth:       320,
+
+        /**
+         * Enable keyboard control. Note: If you disable the keys, you may want
+         * to change the visual styles for the navigation elements that suggest
+         * keyboard shortcuts.
+         *
+         * @var     {Boolean}   enableKeys
+         */
+        enableKeys:         true,
+
+        /**
+         * The keys used to control Shadowbox. Note: In order to use these,
+         * enableKeys must be true. Key values or key codes may be used.
+         *
+         * @var     {Array}
+         */
+        keysClose:          ['c', 'q', 27], // c, q, or esc
+        keysNext:           ['n', 39],      // n or right arrow
+        keysPrev:           ['p', 37],      // p or left arrow
+
+        /**
+         * A hook function to be fired when Shadowbox opens. The single argument
+         * will be the current gallery element.
+         *
+         * @var     {Function}
+         */
+        onOpen:             null,
+
+        /**
+         * A hook function to be fired when Shadowbox finishes loading its
+         * content. The single argument will be the current gallery element on
+         * display.
+         *
+         * @var     {Function}
+         */
+        onFinish:           null,
+
+        /**
+         * A hook function to be fired when Shadowbox changes from one gallery
+         * element to the next. The single argument will be the current gallery
+         * element that is about to be displayed.
+         *
+         * @var     {Function}
+         */
+        onChange:           null,
+
+        /**
+         * A hook function that will be fired when Shadowbox closes. The single
+         * argument will be the gallery element most recently displayed.
+         *
+         * @var     {Function}
+         */
+        onClose:            null,
+
+        /**
+         * The mode to use when handling unsupported media. May be either
+         * 'remove' or 'link'. If it is 'remove', the unsupported gallery item
+         * will merely be removed from the gallery. If it is the only item in
+         * the gallery, the link will simply be followed. If it is 'link', a
+         * link will be provided to the appropriate plugin page in place of the
+         * gallery element.
+         *
+         * @var     {String}    handleUnsupported
+         */
+        handleUnsupported:  'link',
+
+        /**
+         * Skips calling Shadowbox.setup() in init(). This means that it must
+         * be called later manually.
+         *
+         * @var     {Boolean}   skipSetup
+         */
+        skipSetup:          false,
+
+        /**
+         * Text messages to use for Shadowbox. These are provided so they may be
+         * translated into different languages.
+         *
+         * @var     {Object}    text
+         */
+        text:           {
+
+            cancel:     'Cancel',
+
+            loading:    'loading',
+
+            close:      '<span class="shortcut">C</span>lose',
+
+            next:       '<span class="shortcut">N</span>ext',
+
+            prev:       '<span class="shortcut">P</span>revious',
+
+            errors:     {
+                single: 'You must install the <a href="{0}">{1}</a> browser plugin to view this content.',
+                shared: 'You must install both the <a href="{0}">{1}</a> and <a href="{2}">{3}</a> browser plugins to view this content.',
+                either: 'You must install either the <a href="{0}">{1}</a> or the <a href="{2}">{3}</a> browser plugin to view this content.'
+            }
+
+        },
+
+        /**
+         * An object containing names of plugins and links to their respective
+         * download pages.
+         *
+         * @var     {Object}    errors
+         */
+        errors:         {
+
+            fla:        {
+                name:   'Flash',
+                url:    'http://www.adobe.com/products/flashplayer/'
+            },
+
+            qt:         {
+                name:   'QuickTime',
+                url:    'http://www.apple.com/quicktime/download/'
+            },
+
+            wmp:        {
+                name:   'Windows Media Player',
+                url:    'http://www.microsoft.com/windows/windowsmedia/'
+            },
+
+            f4m:        {
+                name:   'Flip4Mac',
+                url:    'http://www.flip4mac.com/wmv_download.htm'
+            }
+
+        },
+
+        /**
+         * The HTML markup to use for Shadowbox. Note: The script depends on
+         * most of these elements being present, so don't modify this variable
+         * unless you know what you're doing.
+         *
+         * @var     {Object}    skin
+         */
+        skin:           {
+
+            main:       '<div id="shadowbox_overlay"></div>' +
+                        '<div id="shadowbox_container">' +
+                            '<div id="shadowbox">' +
+                                '<div id="shadowbox_title">' +
+                                    '<div id="shadowbox_title_inner"></div>' +
+                                '</div>' +
+                                '<div id="shadowbox_body">' +
+                                    '<div id="shadowbox_body_inner"></div>' +
+                                    '<div id="shadowbox_loading"></div>' +
+                                '</div>' +
+                                '<div id="shadowbox_toolbar">' +
+                                    '<div id="shadowbox_toolbar_inner"></div>' +
+                                '</div>' +
+                            '</div>' +
+                        '</div>',
+
+            loading:    '<img src="{0}" alt="{1}" />' +
+                        '<span><a href="javascript:Shadowbox.close();">{2}</a></span>',
+
+            counter:    '<div id="shadowbox_counter">{0}</div>',
+
+            close:      '<div id="shadowbox_nav_close">' +
+                            '<a href="javascript:Shadowbox.close();">{0}</a>' +
+                        '</div>',
+
+            next:       '<div id="shadowbox_nav_next">' +
+                            '<a href="javascript:Shadowbox.next();">{0}</a>' +
+                        '</div>',
+
+            prev:       '<div id="shadowbox_nav_previous">' +
+                            '<a href="javascript:Shadowbox.previous();">{0}</a>' +
+                        '</div>'
+
+        },
+
+        /**
+         * An object containing arrays of all supported file extensions. Each
+         * property of this object contains an array. If this object is to be
+         * modified, it must be done before calling init().
+         *
+         * - img: Supported image file extensions
+         * - qt: Movie file extensions supported by QuickTime
+         * - wmp: Movie file extensions supported by Windows Media Player
+         * - qtwmp: Movie file extensions supported by both QuickTime and Windows Media Player
+         * - iframe: File extensions that will be display in an iframe
+         *
+         * @var     {Object}    ext
+         */
+        ext:     {
+            img:        ['png', 'jpg', 'jpeg', 'gif', 'bmp'],
+            qt:         ['dv', 'mov', 'moov', 'movie', 'mp4'],
+            wmp:        ['asf', 'wm', 'wmv'],
+            qtwmp:      ['avi', 'mpg', 'mpeg'],
+            iframe:     ['asp', 'aspx', 'cgi', 'cfm', 'htm', 'html', 'pl', 'php',
+                        'php3', 'php4', 'php5', 'phtml', 'rb', 'rhtml', 'shtml',
+                        'txt', 'vbs']
+        }
+
+    };
+
+    /**
+     * Stores the default set of options in case a custom set of options is used
+     * on a link-by-link basis so we can restore them later.
+     *
+     * @property    {Object}    default_options
+     * @private
+     */
+    var default_options = null;
+
+    /**
+     * Shorthand for Shadowbox.lib.
+     *
+     * @property    {Object}        SL
+     * @private
+     */
+    var SL = Shadowbox.lib;
+
+    /**
+     * An object containing some regular expressions we'll need later. Compiled
+     * up front for speed.
+     *
+     * @property    {Object}        RE
+     * @private
+     */
+    var RE = {
+        resize:         /(img|swf|flv)/, // file types to resize
+        overlay:        /(img|iframe|html|inline)/, // content types to not use an overlay image for on FF Mac
+        swf:            /\.swf\s*$/i, // swf file extension
+        flv:            /\.flv\s*$/i, // flv file extension
+        domain:         /:\/\/(.*?)[:\/]/, // domain prefix
+        inline:         /#(.+)$/, // inline element id
+        rel:            /^(light|shadow)box/i, // rel attribute format
+        gallery:        /^(light|shadow)box\[(.*?)\]/i, // rel attribute format for gallery link
+        unsupported:    /^unsupported-(\w+)/, // unsupported media type
+        param:          /\s*([a-z_]*?)\s*=\s*(.+)\s*/, // rel string parameter
+        empty:          /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i // elements that don't have children
+    };
+
+    /**
+     * A cache of options for links that have been set up for use with
+     * Shadowbox.
+     *
+     * @property    {Array}         cache
+     * @private
+     */
+    var cache = [];
+
+    /**
+     * An array of pieces currently being viewed. In the case of non-gallery
+     * pieces, this will only hold one object.
+     *
+     * @property    {Array}         current_gallery
+     * @private
+     */
+    var current_gallery;
+
+    /**
+     * The array index of the current_gallery that is currently being viewed.
+     *
+     * @property    {Number}        current
+     * @private
+     */
+    var current;
+
+    /**
+     * Keeps track of the current optimal height of the box. We use this so that
+     * if the user resizes the browser window to get a better view, and we're
+     * currently at a size smaller than the optimal, we can resize easily.
+     *
+     * @see         resizeContent()
+     * @property    {Number}        optimal_height
+     * @private
+     */
+    var optimal_height = options.initialHeight;
+
+    /**
+     * Keeps track of the current optimal width of the box. See optimal_height
+     * explanation (above).
+     *
+     * @property    {Number}        optimal_width
+     * @private
+     */
+    var optimal_width = options.initialWidth;
+
+    /**
+     * Keeps track of the current height of the box. This is useful in drag
+     * calculations.
+     *
+     * @property    {Number}        current_height
+     * @private
+     */
+    var current_height = 0;
+
+    /**
+     * Keeps track of the current width of the box. Useful in drag calculations.
+     *
+     * @property    {Number}        current_width
+     * @private
+     */
+    var current_width = 0;
+
+    /**
+     * Resource used to preload images. It's class-level so that when a new
+     * image is requested, the same resource can be reassigned, cancelling
+     * the original's callback.
+     *
+     * @property    {HTMLElement}   preloader
+     * @private
+     */
+    var preloader;
+
+    /**
+     * Keeps track of whether or not Shadowbox has been initialized. We never
+     * want to initialize twice.
+     *
+     * @property    {Boolean}       initialized
+     * @private
+     */
+    var initialized = false;
+
+    /**
+     * Keeps track of whether or not Shadowbox is activated.
+     *
+     * @property    {Boolean}       activated
+     * @private
+     */
+    var activated = false;
+
+    /**
+     * Keeps track of 4 floating values (x, y, start_x, & start_y) that are used
+     * in the drag calculations.
+     *
+     * @property    {Object}        drag
+     * @private
+     */
+    var drag;
+
+    /**
+     * Holds the draggable element so we don't have to fetch it every time
+     * the mouse moves.
+     *
+     * @property    {HTMLElement}   draggable
+     * @private
+     */
+    var draggable;
+
+    /**
+     * Keeps track of whether or not we're currently using the overlay
+     * background image to display the current gallery. We do this because we
+     * use different methods for fading the overlay in and out. The color fill
+     * overlay fades in and out nicely, but the image overlay stutters. By
+     * keeping track of the type of overlay in use, we don't have to check again
+     * what type of overlay we're using when it's time to get rid of it later.
+     *
+     * @property    {Boolean}       overlay_img_needed
+     * @private
+     */
+    var overlay_img_needed;
+
+    /**
+     * These parameters for simple browser detection. Used in Ext.js.
+     *
+     * @ignore
+     */
+    var ua = navigator.userAgent.toLowerCase();
+    var isStrict = document.compatMode == 'CSS1Compat',
+        isOpera = ua.indexOf("opera") > -1,
+        isIE = ua.indexOf('msie') > -1,
+        isIE7 = ua.indexOf('msie 7') > -1,
+        isBorderBox = isIE && !isStrict,
+        isSafari = (/webkit|khtml/).test(ua),
+        isSafari3 = isSafari && !!(document.evaluate),
+        isGecko = !isSafari && ua.indexOf('gecko') > -1,
+        isWindows = (ua.indexOf('windows') != -1 || ua.indexOf('win32') != -1),
+        isMac = (ua.indexOf('macintosh') != -1 || ua.indexOf('mac os x') != -1),
+        isLinux = (ua.indexOf('linux') != -1);
+
+    /**
+     * Do we need to hack the position to make Shadowbox appear fixed? We could
+     * hack this using CSS, but let's just get over all the hacks and let IE6
+     * users get what they deserve! Down with hacks! Hmm...now that I think
+     * about it, I should just flash all kinds of alerts and annoying popups on
+     * their screens, and then redirect them to some foreign spyware site that
+     * will upload a nasty virus...
+     *
+     * @property    {Boolean}   absolute_pos
+     * @private
+     */
+    var absolute_pos = isIE && !isIE7;
+
+    /**
+     * Contains plugin support information. Each property of this object is a
+     * boolean indicating whether that plugin is supported.
+     *
+     * - fla: Flash player
+     * - qt: QuickTime player
+     * - wmp: Windows Media player
+     * - f4m: Flip4Mac plugin
+     *
+     * @property    {Object}    plugins
+     * @private
+     */
+    var plugins = null;
+
+    // detect plugin support
+    if(navigator.plugins && navigator.plugins.length){
+        var detectPlugin = function(plugin_name){
+            var detected = false;
+            for (var i = 0, len = navigator.plugins.length; i < len; ++i){
+                if(navigator.plugins[i].name.indexOf(plugin_name) > -1){
+                    detected = true;
+                    break;
+                }
+            }
+            return detected;
+        };
+        var f4m = detectPlugin('Flip4Mac');
+        var plugins = {
+            fla:    detectPlugin('Shockwave Flash'),
+            qt:     detectPlugin('QuickTime'),
+            wmp:    !f4m && detectPlugin('Windows Media'), // if it's Flip4Mac, it's not really WMP
+            f4m:    f4m
+        };
+    }else{
+        var detectPlugin = function(plugin_name){
+            var detected = false;
+            try {
+                var axo = new ActiveXObject(plugin_name);
+                if(axo){
+                    detected = true;
+                }
+            } catch (e) {}
+            return detected;
+        };
+        var plugins = {
+            fla:    detectPlugin('ShockwaveFlash.ShockwaveFlash'),
+            qt:     detectPlugin('QuickTime.QuickTime'),
+            wmp:    detectPlugin('wmplayer.ocx'),
+            f4m:    false
+        };
+    }
+
+    /**
+     * Applies all properties of e to o. This function is recursive so that if
+     * any properties of e are themselves objects, those objects will be applied
+     * to objects with the same key that may exist in o.
+     *
+     * @param   {Object}    o       The original object
+     * @param   {Object}    e       The extension object
+     * @return  {Object}            The original object with all properties
+     *                              of the extension object applied (deep)
+     * @private
+     */
+    var apply = function(o, e){
+        for(var p in e) o[p] = e[p];
+        return o;
+    };
+
+    /**
+     * Determines if the given object is an anchor/area element.
+     *
+     * @param   {mixed}     el      The object to check
+     * @return  {Boolean}           True if the object is a link element
+     * @private
+     */
+    var isLink = function(el){
+        return typeof el.tagName == 'string' && (el.tagName.toUpperCase() == 'A' || el.tagName.toUpperCase() == 'AREA');
+    };
+
+    /**
+     * Gets the height of the viewport in pixels. Note: This function includes
+     * scrollbars in Safari 3.
+     *
+     * @return  {Number}        The height of the viewport
+     * @public
+     * @static
+     */
+    SL.getViewportHeight = function(){
+        var height = window.innerHeight; // Safari
+        var mode = document.compatMode;
+        if((mode || isIE) && !isOpera){
+            height = isStrict ? document.documentElement.clientHeight : document.body.clientHeight;
+        }
+        return height;
+    };
+
+    /**
+     * Gets the width of the viewport in pixels. Note: This function includes
+     * scrollbars in Safari 3.
+     *
+     * @return  {Number}        The width of the viewport
+     * @public
+     * @static
+     */
+    SL.getViewportWidth = function(){
+        var width = window.innerWidth; // Safari
+        var mode = document.compatMode;
+        if(mode || isIE){
+            width = isStrict ? document.documentElement.clientWidth : document.body.clientWidth;
+        }
+        return width;
+    };
+
+    /**
+     * Gets the height of the document (body and its margins) in pixels.
+     *
+     * @return  {Number}        The height of the document
+     * @public
+     * @static
+     */
+    SL.getDocumentHeight = function(){
+        var scrollHeight = isStrict ? document.documentElement.scrollHeight : document.body.scrollHeight;
+        return Math.max(scrollHeight, SL.getViewportHeight());
+    };
+
+    /**
+     * Gets the width of the document (body and its margins) in pixels.
+     *
+     * @return  {Number}        The width of the document
+     * @public
+     * @static
+     */
+    SL.getDocumentWidth = function(){
+        var scrollWidth = isStrict ? document.documentElement.scrollWidth : document.body.scrollWidth;
+        return Math.max(scrollWidth, SL.getViewportWidth());
+    };
+
+    /**
+     * A utility function used by the fade functions to clear the opacity
+     * style setting of the given element. Required in some cases for IE.
+     * Based on Ext.Element's clearOpacity.
+     *
+     * @param   {HTMLElement}   el      The DOM element
+     * @return  void
+     * @private
+     */
+    var clearOpacity = function(el){
+        if(isIE){
+            if(typeof el.style.filter == 'string' && (/alpha/i).test(el.style.filter)){
+                el.style.filter = '';
+            }
+        }else{
+            el.style.opacity = '';
+            el.style['-moz-opacity'] = '';
+            el.style['-khtml-opacity'] = '';
+        }
+    };
+
+    /**
+     * Fades the given element from 0 to the specified opacity.
+     *
+     * @param   {HTMLElement}   el              The DOM element to fade
+     * @param   {Number}        endingOpacity   The final opacity to animate to
+     * @param   {Number}        duration        The duration of the animation
+     *                                          (in seconds)
+     * @param   {Function}      callback        A callback function to call
+     *                                          when the animation completes
+     * @return  void
+     * @private
+     */
+    var fadeIn = function(el, endingOpacity, duration, callback){
+        if(options.animate){
+            SL.setStyle(el, 'opacity', 0);
+            el.style.visibility = 'visible';
+            SL.animate(el, {
+                opacity: { to: endingOpacity }
+            }, duration, function(){
+                if(endingOpacity == 1) clearOpacity(el);
+                if(typeof callback == 'function') callback();
+            });
+        }else{
+            if(endingOpacity == 1){
+                clearOpacity(el);
+            }else{
+                SL.setStyle(el, 'opacity', endingOpacity);
+            }
+            el.style.visibility = 'visible';
+            if(typeof callback == 'function') callback();
+        }
+    };
+
+    /**
+     * Fades the given element from its current opacity to 0.
+     *
+     * @param   {HTMLElement}   el          The DOM element to fade
+     * @param   {Number}        duration    The duration of the fade animation
+     * @param   {Function}      callback    A callback function to call when
+     *                                      the animation completes
+     * @return  void
+     * @private
+     */
+    var fadeOut = function(el, duration, callback){
+        var cb = function(){
+            el.style.visibility = 'hidden';
+            clearOpacity(el);
+            if(typeof callback == 'function') callback();
+        };
+        if(options.animate){
+            SL.animate(el, {
+                opacity: { to: 0 }
+            }, duration, cb);
+        }else{
+            cb();
+        }
+    };
+
+    /**
+     * Appends an HTML fragment to the given element.
+     *
+     * @param   {String/HTMLElement}    el      The element to append to
+     * @param   {String}                html    The HTML fragment to use
+     * @return  {HTMLElement}                   The newly appended element
+     * @private
+     */
+    var appendHTML = function(el, html){
+        el = SL.get(el);
+        if(el.insertAdjacentHTML){
+            el.insertAdjacentHTML('BeforeEnd', html);
+            return el.lastChild;
+        }
+        if(el.lastChild){
+            var range = el.ownerDocument.createRange();
+            range.setStartAfter(el.lastChild);
+            var frag = range.createContextualFragment(html);
+            el.appendChild(frag);
+            return el.lastChild;
+        }else{
+            el.innerHTML = html;
+            return el.lastChild;
+        }
+    };
+
+    /**
+     * Overwrites the HTML of the given element.
+     *
+     * @param   {String/HTMLElement}    el      The element to overwrite
+     * @param   {String}                html    The new HTML to use
+     * @return  {HTMLElement}                   The new firstChild element
+     * @private
+     */
+    var overwriteHTML = function(el, html){
+        el = SL.get(el);
+        el.innerHTML = html;
+        return el.firstChild;
+    };
+
+    /**
+     * Gets either the offsetHeight or the height of the given element plus
+     * padding and borders (when offsetHeight is not available). Based on
+     * Ext.Element's getComputedHeight.
+     *
+     * @return  {Number}            The computed height of the element
+     * @private
+     */
+    var getComputedHeight = function(el){
+        var h = Math.max(el.offsetHeight, el.clientHeight);
+        if(!h){
+            h = parseInt(SL.getStyle(el, 'height'), 10) || 0;
+            if(!isBorderBox){
+                h += parseInt(SL.getStyle(el, 'padding-top'), 10)
+                    + parseInt(SL.getStyle(el, 'padding-bottom'), 10)
+                    + parseInt(SL.getStyle(el, 'border-top-width'), 10)
+                    + parseInt(SL.getStyle(el, 'border-bottom-width'), 10);
+            }
+        }
+        return h;
+    };
+
+    /**
+     * Gets either the offsetWidth or the width of the given element plus
+     * padding and borders (when offsetWidth is not available). Based on
+     * Ext.Element's getComputedWidth.
+     *
+     * @return  {Number}            The computed width of the element
+     * @private
+     */
+    var getComputedWidth = function(el){
+        var w = Math.max(el.offsetWidth, el.clientWidth);
+        if(!w){
+            w = parseInt(SL.getStyle(el, 'width'), 10) || 0;
+            if(!isBorderBox){
+                w += parseInt(SL.getStyle(el, 'padding-left'), 10)
+                    + parseInt(SL.getStyle(el, 'padding-right'), 10)
+                    + parseInt(SL.getStyle(el, 'border-left-width'), 10)
+                    + parseInt(SL.getStyle(el, 'border-right-width'), 10);
+            }
+        }
+        return w;
+    };
+
+    /**
+     * Determines the player needed to display the file at the given URL. If
+     * the file type is not supported, the return value will be 'unsupported'.
+     * If the file type is not supported but the correct player can be
+     * determined, the return value will be 'unsupported-*' where * will be the
+     * player abbreviation (e.g. 'qt' = QuickTime).
+     *
+     * @param   {String}        url     The url of the file
+     * @return  {String}                The name of the player to use
+     * @private
+     */
+    var getPlayerType = function(url){
+        if(RE.img.test(url)) return 'img';
+        var match = url.match(RE.domain);
+        var this_domain = match ? document.domain == match[1] : false;
+        if(url.indexOf('#') > -1 && this_domain) return 'inline';
+        var q_index = url.indexOf('?');
+        if(q_index > -1) url = url.substring(0, q_index); // strip query string for player detection purposes
+        if(RE.swf.test(url)) return plugins.fla ? 'swf' : 'unsupported-swf';
+        if(RE.flv.test(url)) return plugins.fla ? 'flv' : 'unsupported-flv';
+        if(RE.qt.test(url)) return plugins.qt ? 'qt' : 'unsupported-qt';
+        if(RE.wmp.test(url)){
+            if(plugins.wmp){
+                return 'wmp';
+            }else if(plugins.f4m){
+                return 'qt';
+            }else{
+                return isMac ? (plugins.qt ? 'unsupported-f4m' : 'unsupported-qtf4m') : 'unsupported-wmp';
+            }
+        }else if(RE.qtwmp.test(url)){
+            if(plugins.qt){
+                return 'qt';
+            }else if(plugins.wmp){
+                return 'wmp';
+            }else{
+                return isMac ? 'unsupported-qt' : 'unsupported-qtwmp';
+            }
+        }else if(!this_domain || RE.iframe.test(url)){
+            return 'iframe';
+        }
+        return 'unsupported';
+    };
+
+    /**
+     * Handles all clicks on links that have been set up to work with Shadowbox
+     * and cancels the default event behavior when appropriate.
+     *
+     * @param   {Event}         ev          The click event object
+     * @return  void
+     * @private
+     */
+    var handleClick = function(ev){
+        // get anchor/area element
+        var link;
+        if(isLink(this)){
+            link = this; // jQuery, Prototype, YUI
+        }else{
+            link = SL.getTarget(ev); // Ext
+            while(!isLink(link) && link.parentNode){
+                link = link.parentNode;
+            }
+        }
+
+        Shadowbox.open(link);
+        if(current_gallery.length) SL.preventDefault(ev);
+    };
+
+    /**
+     * Sets up the current gallery for the given object. Modifies the current
+     * and current_gallery variables to contain the appropriate information.
+     * Also, checks to see if there are any gallery pieces that are not
+     * supported by the client's browser/plugins. If there are, they will be
+     * handled according to the handleUnsupported option.
+     *
+     * @param   {Object}    obj         The content to get the gallery for
+     * @return  void
+     * @private
+     */
+    var setupGallery = function(obj){
+        // create a copy so it doesn't get modified later
+        var copy = apply({}, obj);
+
+        // is it part of a gallery?
+        if(!obj.gallery){ // single item, no gallery
+            current_gallery = [copy];
+            current = 0;
+        }else{
+            current_gallery = []; // clear the current gallery
+            var index, ci;
+            for(var i = 0, len = cache.length; i < len; ++i){
+                ci = cache[i];
+                if(ci.gallery){
+                    if(ci.content == obj.content
+                        && ci.gallery == obj.gallery
+                        && ci.title == obj.title){ // compare content, gallery, & title
+                            index = current_gallery.length; // key element found
+                    }
+                    if(ci.gallery == obj.gallery){
+                        current_gallery.push(apply({}, ci));
+                    }
+                }
+            }
+            // if not found in cache, prepend to front of gallery
+            if(index == null){
+                current_gallery.unshift(copy);
+                index = 0;
+            }
+            current = index;
+        }
+
+        // are any media in the current gallery supported?
+        var match, r;
+        for(var i = 0, len = current_gallery.length; i < len; ++i){
+            r = false;
+            if(current_gallery[i].type == 'unsupported'){ // don't support this at all
+                r = true;
+            }else if(match = RE.unsupported.exec(current_gallery[i].type)){ // handle unsupported elements
+                if(options.handleUnsupported == 'link'){
+                    current_gallery[i].type = 'html';
+                    // generate a link to the appropriate plugin download page(s)
+                    var m;
+                    switch(match[1]){
+                        case 'qtwmp':
+                            m = String.format(options.text.errors.either,
+                                options.errors.qt.url, options.errors.qt.name,
+                                options.errors.wmp.url, options.errors.wmp.name);
+                        break;
+                        case 'qtf4m':
+                            m = String.format(options.text.errors.shared,
+                                options.errors.qt.url, options.errors.qt.name,
+                                options.errors.f4m.url, options.errors.f4m.name);
+                        break;
+                        default:
+                            if(match[1] == 'swf' || match[1] == 'flv') match[1] = 'fla';
+                            m = String.format(options.text.errors.single,
+                                options.errors[match[1]].url, options.errors[match[1]].name);
+                    }
+                    current_gallery[i] = apply(current_gallery[i], {
+                        height:     160, // error messages are short so they
+                        width:      320, // only need a small box to display properly
+                        content:    '<div class="shadowbox_message">' + m + '</div>'
+                    });
+                }else{
+                    r = true;
+                }
+            }else if(current_gallery[i].type == 'inline'){ // handle inline elements
+                // retrieve the innerHTML of the inline element
+                var match = RE.inline.exec(current_gallery[i].content);
+                if(match){
+                    var el;
+                    if(el = SL.get(match[1])){
+                        current_gallery[i].content = el.innerHTML;
+                    }else{
+                        throw 'No element found with id ' + match[1];
+                    }
+                }else{
+                    throw 'No element id found for inline content';
+                }
+            }
+            if(r){
+                // remove the element from the gallery
+                current_gallery.splice(i, 1);
+                if(i < current) --current;
+                --i;
+            }
+        }
+    };
+
+    /**
+     * Hides the title bar and toolbar and populates them with the proper
+     * content.
+     *
+     * @return  void
+     * @private
+     */
+    var buildBars = function(){
+        var link = current_gallery[current];
+        if(!link) return; // nothing to build
+
+        // build the title
+        var title_i = SL.get('shadowbox_title_inner');
+        title_i.innerHTML = (link.title) ? link.title : '';
+        // empty the toolbar
+        var tool_i = SL.get('shadowbox_toolbar_inner');
+        tool_i.innerHTML = '';
+
+        // build the nav
+        if(options.displayNav){
+            tool_i.innerHTML = String.format(options.skin.close, options.text.close);
+            if(current_gallery.length > 1){
+                if(options.continuous){
+                    // show both
+                    appendHTML(tool_i, String.format(options.skin.next, options.text.next));
+                    appendHTML(tool_i, String.format(options.skin.prev, options.text.prev));
+                }else{
+                    // not last in the gallery, show the next link
+                    if((current_gallery.length - 1) > current){
+                        appendHTML(tool_i, String.format(options.skin.next, options.text.next));
+                    }
+                    // not first in the gallery, show the previous link
+                    if(current > 0){
+                        appendHTML(tool_i, String.format(options.skin.prev, options.text.prev));
+                    }
+                }
+            }
+        }
+
+        // build the counter
+        if(current_gallery.length > 1 && options.displayCounter){
+            // append the counter div
+            var counter = '';
+            if(options.counterType == 'skip'){
+                for(var i = 0, len = current_gallery.length; i < len; ++i){
+                    counter += '<a href="javascript:Shadowbox.change(' + i + ');"';
+                    if(i == current){
+                        counter += ' class="shadowbox_counter_current"';
+                    }
+                    counter += '>' + (i + 1) + '</a>';
+                }
+            }else{
+                counter = (current + 1) + ' of ' + current_gallery.length;
+            }
+            appendHTML(tool_i, String.format(options.skin.counter, counter));
+        }
+    };
+
+    /**
+     * Hides the title and tool bars.
+     *
+     * @param   {Function}  callback        A function to call on finish
+     * @return  void
+     * @private
+     */
+    var hideBars = function(callback){
+        var title_m = getComputedHeight(SL.get('shadowbox_title'));
+        var tool_m = 0 - getComputedHeight(SL.get('shadowbox_toolbar'));
+        var title_i = SL.get('shadowbox_title_inner');
+        var tool_i = SL.get('shadowbox_toolbar_inner');
+
+        if(options.animate && callback){
+            // animate the transition
+            SL.animate(title_i, {
+                marginTop: { to: title_m }
+            }, 0.2);
+            SL.animate(tool_i, {
+                marginTop: { to: tool_m }
+            }, 0.2, callback);
+        }else{
+            SL.setStyle(title_i, 'marginTop', title_m + 'px');
+            SL.setStyle(tool_i, 'marginTop', tool_m + 'px');
+        }
+    };
+
+    /**
+     * Shows the title and tool bars.
+     *
+     * @param   {Function}  callback        A callback function to execute after
+     *                                      the animation completes
+     * @return  void
+     * @private
+     */
+    var showBars = function(callback){
+        var title_i = SL.get('shadowbox_title_inner');
+        if(options.animate){
+            if(title_i.innerHTML != ''){
+                SL.animate(title_i, { marginTop: { to: 0 } }, 0.35);
+            }
+            SL.animate(SL.get('shadowbox_toolbar_inner'), {
+                marginTop: { to: 0 }
+            }, 0.35, callback);
+        }else{
+            if(title_i.innerHTML != ''){
+                SL.setStyle(title_i, 'margin-top', '0px');
+            }
+            SL.setStyle(SL.get('shadowbox_toolbar_inner'), 'margin-top', '0px');
+            callback();
+        }
+    };
+
+    /**
+     * Resets the class drag variable.
+     *
+     * @return  void
+     * @private
+     */
+    var resetDrag = function(){
+        drag = {
+            x:          0,
+            y:          0,
+            start_x:    null,
+            start_y:    null
+        };
+    };
+
+    /**
+     * Toggles the drag function on and off.
+     *
+     * @param   {Boolean}   on      True to toggle on, false to toggle off
+     * @return  void
+     * @private
+     */
+    var toggleDrag = function(on){
+        if(on){
+            resetDrag();
+            // add drag layer to prevent browser dragging of actual image
+            var styles = [
+                'position:absolute',
+                'cursor:' + (isGecko ? '-moz-grab' : 'move')
+            ];
+            // make drag layer transparent
+            styles.push(isIE ? 'background-color:#fff;filter:alpha(opacity=0)' : 'background-color:transparent');
+            appendHTML('shadowbox_body_inner', '<div id="shadowbox_drag_layer" style="' + styles.join(';') + '"></div>');
+            SL.addEvent(SL.get('shadowbox_drag_layer'), 'mousedown', listenDrag);
+        }else{
+            var d = SL.get('shadowbox_drag_layer');
+            if(d){
+                SL.removeEvent(d, 'mousedown', listenDrag);
+                SL.remove(d);
+            }
+        }
+    };
+
+    /**
+     * Sets up a drag listener on the document. Called when the mouse button is
+     * pressed (mousedown).
+     *
+     * @param   {mixed}     ev      The mousedown event
+     * @return  void
+     * @private
+     */
+    var listenDrag = function(ev){
+        drag.start_x = ev.clientX;
+        drag.start_y = ev.clientY;
+        draggable = SL.get('shadowbox_content');
+        SL.addEvent(document, 'mousemove', positionDrag);
+        SL.addEvent(document, 'mouseup', unlistenDrag);
+        if(isGecko) SL.setStyle(SL.get('shadowbox_drag_layer'), 'cursor', '-moz-grabbing');
+    };
+
+    /**
+     * Removes the drag listener. Called when the mouse button is released
+     * (mouseup).
+     *
+     * @return  void
+     * @private
+     */
+    var unlistenDrag = function(){
+        SL.removeEvent(document, 'mousemove', positionDrag);
+        SL.removeEvent(document, 'mouseup', unlistenDrag); // clean up
+        if(isGecko) SL.setStyle(SL.get('shadowbox_drag_layer'), 'cursor', '-moz-grab');
+    };
+
+    /**
+     * Positions an oversized image on drag.
+     *
+     * @param   {mixed}     ev      The drag event
+     * @return  void
+     * @private
+     */
+    var positionDrag = function(ev){
+        var move_y = ev.clientY - drag.start_y;
+        drag.start_y = drag.start_y + move_y;
+        drag.y = Math.max(Math.min(0, drag.y + move_y), current_height - optimal_height); // y boundaries
+        SL.setStyle(draggable, 'top', drag.y + 'px');
+        var move_x = ev.clientX - drag.start_x;
+        drag.start_x = drag.start_x + move_x;
+        drag.x = Math.max(Math.min(0, drag.x + move_x), current_width - optimal_width); // x boundaries
+        SL.setStyle(draggable, 'left', drag.x + 'px');
+    };
+
+    /**
+     * Loads the Shadowbox with the current piece.
+     *
+     * @return  void
+     * @private
+     */
+    var loadContent = function(){
+        var obj = current_gallery[current];
+        if(!obj) return; // invalid
+
+        buildBars();
+
+        switch(obj.type){
+            case 'img':
+                // preload the image
+                preloader = new Image();
+                preloader.onload = function(){
+                    // images default to image height and width
+                    var h = obj.height ? parseInt(obj.height, 10) : preloader.height;
+                    var w = obj.width ? parseInt(obj.width, 10) : preloader.width;
+                    resizeContent(h, w, function(dims){
+                        showBars(function(){
+                            setContent({
+                                tag:    'img',
+                                height: dims.i_height,
+                                width:  dims.i_width,
+                                src:    obj.content,
+                                style:  'position:absolute'
+                            });
+                            if(dims.enableDrag && options.handleLgImages == 'drag'){
+                                // listen for drag
+                                toggleDrag(true);
+                                SL.setStyle(SL.get('shadowbox_drag_layer'), {
+                                    height:     dims.i_height + 'px',
+                                    width:      dims.i_width + 'px'
+                                });
+                            }
+                            finishContent();
+                        });
+                    });
+
+                    preloader.onload = function(){}; // clear onload for IE
+                };
+                preloader.src = obj.content;
+            break;
+
+            case 'swf':
+            case 'flv':
+            case 'qt':
+            case 'wmp':
+                var markup = Shadowbox.movieMarkup(obj);
+                resizeContent(markup.height, markup.width, function(){
+                    showBars(function(){
+                        setContent(markup);
+                        finishContent();
+                    });
+                });
+            break;
+
+            case 'iframe':
+                // iframes default to full viewport height and width
+                var h = obj.height ? parseInt(obj.height, 10) : SL.getViewportHeight();
+                var w = obj.width ? parseInt(obj.width, 10) : SL.getViewportWidth();
+                var content = {
+                    tag:            'iframe',
+                    name:           'shadowbox_content',
+                    height:         '100%',
+                    width:          '100%',
+                    frameborder:    '0',
+                    marginwidth:    '0',
+                    marginheight:   '0',
+                    scrolling:      'auto'
+                };
+
+                resizeContent(h, w, function(dims){
+                    showBars(function(){
+                        setContent(content);
+                        var win = (isIE)
+                            ? SL.get('shadowbox_content').contentWindow
+                            : window.frames['shadowbox_content'];
+                        win.location = obj.content;
+                        finishContent();
+                    });
+                });
+            break;
+
+            case 'html':
+            case 'inline':
+                // HTML content defaults to full viewport height and width
+                var h = obj.height ? parseInt(obj.height, 10) : SL.getViewportHeight();
+                var w = obj.width ? parseInt(obj.width, 10) : SL.getViewportWidth();
+                var content = {
+                    tag:    'div',
+                    cls:    'html', /* give special class to make scrollable */
+                    html:   obj.content
+                };
+                resizeContent(h, w, function(){
+                    showBars(function(){
+                        setContent(content);
+                        finishContent();
+                    });
+                });
+            break;
+
+            default:
+                // should never happen
+                throw 'Shadowbox cannot open content of type ' + obj.type;
+        }
+
+        // preload neighboring images
+        if(current_gallery.length > 0){
+            var next = current_gallery[current + 1];
+            if(!next){
+                next = current_gallery[0];
+            }
+            if(next.type == 'img'){
+                var preload_next = new Image();
+                preload_next.src = next.href;
+            }
+
+            var prev = current_gallery[current - 1];
+            if(!prev){
+                prev = current_gallery[current_gallery.length - 1];
+            }
+            if(prev.type == 'img'){
+                var preload_prev = new Image();
+                preload_prev.src = prev.href;
+            }
+        }
+    };
+
+    /**
+     * Removes old content and sets the new content of the Shadowbox.
+     *
+     * @param   {Object}        obj     The content to set (appropriate to pass
+     *                                  directly to Shadowbox.createHTML())
+     * @return  {HTMLElement}           The newly appended element (or null if
+     *                                  none is provided)
+     * @private
+     */
+    var setContent = function(obj){
+        var id = 'shadowbox_content';
+        var content = SL.get(id);
+        if(content){
+            // remove old content first
+            switch(content.tagName.toUpperCase()){
+                case 'OBJECT':
+                    // if we're in a gallery (i.e. changing and there's a new
+                    // object) we want the LAST link object
+                    var link = current_gallery[(obj ? current - 1 : current)];
+                    if(link.type == 'wmp' && isIE){
+                        try{
+                            shadowbox_content.controls.stop(); // stop the movie
+                            shadowbox_content.URL = 'non-existent.wmv'; // force player refresh
+                            window.shadowbox_content = function(){}; // remove from window
+                        }catch(e){}
+                    }else if(link.type == 'qt' && isSafari){
+                        try{
+                            document.shadowbox_content.Stop(); // stop QT movie
+                        }catch(e){}
+                        // stop QT audio stream for movies that have not yet loaded
+                        content.innerHTML = '';
+                        // console.log(document.shadowbox_content);
+                    }
+                    setTimeout(function(){ // using setTimeout prevents browser crashes with WMP
+                        SL.remove(content);
+                    }, 10);
+                break;
+                case 'IFRAME':
+                    SL.remove(content);
+                    if(isGecko) delete window.frames[id]; // needed for Firefox
+                break;
+                default:
+                    SL.remove(content);
+            }
+        }
+        if(obj){
+            if(!obj.id) obj.id = id;
+            return appendHTML('shadowbox_body_inner', Shadowbox.createHTML(obj));
+        }
+        return null;
+    };
+
+    /**
+     * This function is used as the callback after the Shadowbox has been
+     * positioned, resized, and loaded with content.
+     *
+     * @return  void
+     * @private
+     */
+    var finishContent = function(){
+        var obj = current_gallery[current];
+        if(!obj) return; // invalid
+        hideLoading(function(){
+            listenKeyboard(true);
+            // fire onFinish handler
+            if(options.onFinish && typeof options.onFinish == 'function'){
+                options.onFinish(obj);
+            }
+        });
+    };
+
+    /**
+     * Resizes and positions the content box using the given height and width.
+     * If the callback parameter is missing, the transition will not be
+     * animated. If the callback parameter is present, it will be passed the
+     * new calculated dimensions object as its first parameter. Note: the height
+     * and width here should represent the optimal height and width of the box.
+     *
+     * @param   {Function}  callback    A callback function to use when the
+     *                                  resize completes
+     * @return  void
+     * @private
+     */
+    var resizeContent = function(height, width, callback){
+        // update optimal height and width
+        optimal_height = height;
+        optimal_width = width;
+        var resizable = RE.resize.test(current_gallery[current].type);
+        var dims = getDimensions(optimal_height, optimal_width, resizable);
+        if(callback){
+            var cb = function(){ callback(dims); };
+            switch(options.animSequence){
+                case 'hw':
+                    adjustHeight(dims.height, dims.top, true, function(){
+                        adjustWidth(dims.width, true, cb);
+                    });
+                break;
+                case 'wh':
+                    adjustWidth(dims.width, true, function(){
+                        adjustHeight(dims.height, dims.top, true, cb);
+                    });
+                break;
+                default: // sync
+                    adjustWidth(dims.width, true);
+                    adjustHeight(dims.height, dims.top, true, cb);
+            }
+        }else{ // window resize
+            adjustWidth(dims.width, false);
+            adjustHeight(dims.height, dims.top, false);
+            // resize content images & flash in 'resize' mode
+            if(options.handleLgImages == 'resize' && resizable){
+                var content = SL.get('shadowbox_content');
+                if(content){ // may be animating, not present
+                    content.height = dims.i_height;
+                    content.width = dims.i_width;
+                }
+            }
+        }
+    };
+
+    /**
+     * Calculates the dimensions for Shadowbox, taking into account the borders,
+     * margins, and surrounding elements of the shadowbox_body. If the image
+     * is still to large for Shadowbox, and options.handleLgImages is 'resize',
+     * the resized dimensions will be returned (preserving the original aspect
+     * ratio). Otherwise, the originally calculated dimensions will be returned.
+     * The returned object will have the following properties:
+     *
+     * - height: The height to use for shadowbox_body_inner
+     * - width: The width to use for shadowbox
+     * - i_height: The height to use for resizable content
+     * - i_width: The width to use for resizable content
+     * - top: The top to use for shadowbox
+     * - enableDrag: True if dragging should be enabled (image is oversized)
+     *
+     * @param   {Number}    o_height    The optimal height
+     * @param   {Number}    o_width     The optimal width
+     * @param   {Boolean}   resizable   True if the content is able to be
+     *                                  resized. Defaults to false.
+     * @return  {Object}                The resize dimensions (see above)
+     * @private
+     */
+    var getDimensions = function(o_height, o_width, resizable){
+        if(typeof resizable == 'undefined') resizable = false;
+
+        var height = o_height = parseInt(o_height);
+        var width = o_width = parseInt(o_width);
+        var shadowbox_b = SL.get('shadowbox_body');
+
+        // calculate the max height
+        var view_height = SL.getViewportHeight();
+        var extra_height = parseInt(SL.getStyle(shadowbox_b, 'border-top-width'), 10)
+            + parseInt(SL.getStyle(shadowbox_b, 'border-bottom-width'), 10)
+            + parseInt(SL.getStyle(shadowbox_b, 'margin-top'), 10)
+            + parseInt(SL.getStyle(shadowbox_b, 'margin-bottom'), 10)
+            + getComputedHeight(SL.get('shadowbox_title'))
+            + getComputedHeight(SL.get('shadowbox_toolbar'))
+            + (2 * options.viewportPadding);
+        if((height + extra_height) >= view_height){
+            height = view_height - extra_height;
+        }
+
+        // calculate the max width
+        var view_width = SL.getViewportWidth();
+        var extra_body_width = parseInt(SL.getStyle(shadowbox_b, 'border-left-width'), 10)
+            + parseInt(SL.getStyle(shadowbox_b, 'border-right-width'), 10)
+            + parseInt(SL.getStyle(shadowbox_b, 'margin-left'), 10)
+            + parseInt(SL.getStyle(shadowbox_b, 'margin-right'), 10);
+        var extra_width = extra_body_width + (2 * options.viewportPadding);
+        if((width + extra_width) >= view_width){
+            width = view_width - extra_width;
+        }
+
+        // handle oversized images & flash
+        var enableDrag = false;
+        var i_height = o_height;
+        var i_width = o_width;
+        var handle = options.handleLgImages;
+        if(resizable && (handle == 'resize' || handle == 'drag')){
+            var change_h = (o_height - height) / o_height;
+            var change_w = (o_width - width) / o_width;
+            if(handle == 'resize'){
+                if(change_h > change_w){
+                    width = Math.round((o_width / o_height) * height);
+                }else if(change_w > change_h){
+                    height = Math.round((o_height / o_width) * width);
+                }
+                // adjust image height or width accordingly
+                i_width = width;
+                i_height = height;
+            }else{
+                // drag on oversized images only
+                var link = current_gallery[current];
+                if(link) enableDrag = link.type == 'img' && (change_h > 0 || change_w > 0);
+            }
+        }
+
+        return {
+            height: height,
+            width: width + extra_body_width,
+            i_height: i_height,
+            i_width: i_width,
+            top: ((view_height - (height + extra_height)) / 2) + options.viewportPadding,
+            enableDrag: enableDrag
+        };
+    };
+
+    /**
+     * Centers Shadowbox vertically in the viewport. Needs to be called on
+     * scroll in IE6 because it does not support fixed positioning.
+     *
+     * @return  void
+     * @private
+     */
+    var centerVertically = function(){
+        var shadowbox = SL.get('shadowbox');
+        var scroll = document.documentElement.scrollTop;
+        var s_top = scroll + Math.round((SL.getViewportHeight() - (shadowbox.offsetHeight || 0)) / 2);
+        SL.setStyle(shadowbox, 'top', s_top + 'px');
+    };
+
+    /**
+     * Adjusts the height of shadowbox_body_inner and centers Shadowbox
+     * vertically in the viewport.
+     *
+     * @param   {Number}    height      The height of shadowbox_body_inner
+     * @param   {Number}    top         The top of the Shadowbox
+     * @param   {Boolean}   animate     True to animate the transition
+     * @param   {Function}  callback    A callback to use when the animation completes
+     * @return  void
+     * @private
+     */
+    var adjustHeight = function(height, top, animate, callback){
+        height = parseInt(height);
+
+        // update current_height
+        current_height = height;
+
+        // adjust the height
+        var sbi = SL.get('shadowbox_body_inner');
+        if(animate && options.animate){
+            SL.animate(sbi, {
+                height: { to: height }
+            }, options.resizeDuration, callback);
+        }else{
+            SL.setStyle(sbi, 'height', height + 'px');
+            if(typeof callback == 'function') callback();
+        }
+
+        // manually adjust the top because we're using fixed positioning in IE6
+        if(absolute_pos){
+            // listen for scroll so we can adjust
+            centerVertically();
+            SL.addEvent(window, 'scroll', centerVertically);
+
+            // add scroll to top
+            top += document.documentElement.scrollTop;
+        }
+
+        // adjust the top
+        var shadowbox = SL.get('shadowbox');
+        if(animate && options.animate){
+            SL.animate(shadowbox, {
+                top: { to: top }
+            }, options.resizeDuration);
+        }else{
+            SL.setStyle(shadowbox, 'top', top + 'px');
+        }
+    };
+
+    /**
+     * Adjusts the width of shadowbox.
+     *
+     * @param   {Number}    width       The width to use
+     * @param   {Boolean}   animate     True to animate the transition
+     * @param   {Function}  callback    A callback to use when the animation completes
+     * @return  void
+     * @private
+     */
+    var adjustWidth = function(width, animate, callback){
+        width = parseInt(width);
+
+        // update current_width
+        current_width = width;
+
+        var shadowbox = SL.get('shadowbox');
+        if(animate && options.animate){
+            SL.animate(shadowbox, {
+                width: { to: width }
+            }, options.resizeDuration, callback);
+        }else{
+            SL.setStyle(shadowbox, 'width', width + 'px');
+            if(typeof callback == 'function') callback();
+        }
+    };
+
+    /**
+     * Sets up a listener on the document for keystrokes.
+     *
+     * @param   {Boolean}   on      True to enable the listner, false to turn
+     *                              it off
+     * @return  void
+     * @private
+     */
+    var listenKeyboard = function(on){
+        if(!options.enableKeys) return;
+        if(on){
+            document.onkeydown = handleKey;
+        }else{
+            document.onkeydown = '';
+        }
+    };
+
+    /**
+     * Asserts the given key or code is present in the array of valid keys.
+     *
+     * @param   {Array}     valid       An array of valid keys and codes
+     * @param   {String}    key         The character that was pressed
+     * @param   {Number}    code        The key code that was pressed
+     * @return  {Boolean}               True if the key is valid
+     * @private
+     */
+    var assertKey = function(valid, key, code){
+        return (valid.indexOf(key) != -1 || valid.indexOf(code) != -1);
+    };
+
+    /**
+     * A listener function that will act on a key pressed.
+     *
+     * @param   {Event}     e       The event object
+     * @return  void
+     * @private
+     */
+    var handleKey = function(e){
+        var code = e ? e.which : event.keyCode;
+        var key = String.fromCharCode(code).toLowerCase();
+        if(assertKey(options.keysClose, key, code)){
+            Shadowbox.close();
+        }else if(assertKey(options.keysPrev, key, code)){
+            Shadowbox.previous();
+        }else if(assertKey(options.keysNext, key, code)){
+            Shadowbox.next();
+        }
+    };
+
+    /**
+     * Shows and hides elements that are troublesome for modal overlays.
+     *
+     * @param   {Boolean}   on      True to show the elements, false otherwise
+     * @return  void
+     * @private
+     */
+    var toggleTroubleElements = function(on){
+        var vis = (on ? 'visible' : 'hidden');
+        var selects = document.getElementsByTagName('select');
+        for(i = 0, len = selects.length; i < len; ++i){
+            selects[i].style.visibility = vis;
+        }
+        var objects = document.getElementsByTagName('object');
+        for(i = 0, len = objects.length; i < len; ++i){
+            objects[i].style.visibility = vis;
+        }
+        var embeds = document.getElementsByTagName('embed');
+        for(i = 0, len = embeds.length; i < len; ++i){
+            embeds[i].style.visibility = vis;
+        }
+    };
+
+    /**
+     * Fills the Shadowbox with the loading skin.
+     *
+     * @return  void
+     * @private
+     */
+    var showLoading = function(){
+        var loading = SL.get('shadowbox_loading');
+        overwriteHTML(loading, String.format(options.skin.loading,
+            options.assetURL + options.loadingImage,
+            options.text.loading,
+            options.text.cancel));
+        loading.style.visibility = 'visible';
+    };
+
+    /**
+     * Hides the Shadowbox loading skin.
+     *
+     * @param   {Function}  callback        The callback function to call after
+     *                                      hiding the loading skin
+     * @return  void
+     * @private
+     */
+    var hideLoading = function(callback){
+        var t = current_gallery[current].type;
+        var anim = (t == 'img' || t == 'html'); // fade on images & html
+        var loading = SL.get('shadowbox_loading');
+        if(anim){
+            fadeOut(loading, 0.35, callback);
+        }else{
+            loading.style.visibility = 'hidden';
+            callback();
+        }
+    };
+
+    /**
+     * Sets the size of the overlay to the size of the document.
+     *
+     * @return  void
+     * @private
+     */
+    var resizeOverlay = function(){
+        var overlay = SL.get('shadowbox_overlay');
+        SL.setStyle(overlay, {
+            height: '100%',
+            width: '100%'
+        });
+        SL.setStyle(overlay, 'height', SL.getDocumentHeight() + 'px');
+        if(!isSafari3){
+            // Safari3 includes vertical scrollbar in SL.getDocumentWidth()!
+            // Leave overlay width at 100% for now...
+            SL.setStyle(overlay, 'width', SL.getDocumentWidth() + 'px');
+        }
+    };
+
+    /**
+     * Used to determine if the pre-made overlay background image is needed
+     * instead of using the trasparent background overlay. A pre-made background
+     * image is used for all but image pieces in FF Mac because it has problems
+     * displaying correctly if the background layer is not 100% opaque. When
+     * displaying a gallery, if any piece in the gallery meets these criteria,
+     * the pre-made background image will be used.
+     *
+     * @return  {Boolean}       Whether or not an overlay image is needed
+     * @private
+     */
+    var checkOverlayImgNeeded = function(){
+        if(!(isGecko && isMac)) return false;
+        for(var i = 0, len = current_gallery.length; i < len; ++i){
+            if(!RE.overlay.exec(current_gallery[i].type)) return true;
+        }
+        return false;
+    };
+
+    /**
+     * Activates (or deactivates) the Shadowbox overlay. If a callback function
+     * is provided, we know we're activating. Otherwise, deactivate the overlay.
+     *
+     * @param   {Function}  callback    A callback to call after activation
+     * @return  void
+     * @private
+     */
+    var toggleOverlay = function(callback){
+        var overlay = SL.get('shadowbox_overlay');
+        if(overlay_img_needed == null){
+            overlay_img_needed = checkOverlayImgNeeded();
+        }
+
+        if(callback){
+            resizeOverlay(); // size the overlay before showing
+            if(overlay_img_needed){
+                SL.setStyle(overlay, {
+                    visibility:         'visible',
+                    backgroundColor:    'transparent',
+                    backgroundImage:    'url(' + options.assetURL + options.overlayBgImage + ')',
+                    backgroundRepeat:   'repeat',
+                    opacity:            1
+                });
+                callback();
+            }else{
+                SL.setStyle(overlay, {
+                    visibility:         'visible',
+                    backgroundColor:    options.overlayColor,
+                    backgroundImage:    'none'
+                });
+                fadeIn(overlay, options.overlayOpacity, options.fadeDuration,
+                    callback);
+            }
+        }else{
+            if(overlay_img_needed){
+                SL.setStyle(overlay, 'visibility', 'hidden');
+            }else{
+                fadeOut(overlay, options.fadeDuration);
+            }
+
+            // reset for next time
+            overlay_img_needed = null;
+        }
+    };
+
+    /**
+     * Initializes the Shadowbox environment. Appends Shadowbox' HTML to the
+     * document and sets up listeners on the window and overlay element.
+     *
+     * @param   {Object}    opts    The default options to use
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.init = function(opts){
+        if(initialized) return; // don't initialize twice
+        options = apply(options, opts || {});
+
+        // add markup
+        appendHTML(document.body, options.skin.main);
+
+        // compile file type regular expressions here for speed
+        RE.img = new RegExp('\.(' + options.ext.img.join('|') + ')\s*$', 'i');
+        RE.qt = new RegExp('\.(' + options.ext.qt.join('|') + ')\s*$', 'i');
+        RE.wmp = new RegExp('\.(' + options.ext.wmp.join('|') + ')\s*$', 'i');
+        RE.qtwmp = new RegExp('\.(' + options.ext.qtwmp.join('|') + ')\s*$', 'i');
+        RE.iframe = new RegExp('\.(' + options.ext.iframe.join('|') + ')\s*$', 'i');
+
+        // handle window resize events
+        var id = null;
+        var resize = function(){
+            clearInterval(id);
+            id = null;
+            resizeOverlay();
+            resizeContent(optimal_height, optimal_width);
+        };
+        SL.addEvent(window, 'resize', function(){
+            if(activated){
+                // use event buffering to prevent jerky window resizing
+                if(id){
+                    clearInterval(id);
+                    id = null;
+                }
+                if(!id) id = setInterval(resize, 50);
+            }
+        });
+
+        if(options.listenOverlay){
+            // add a listener to the overlay
+            SL.addEvent(SL.get('shadowbox_overlay'), 'click', Shadowbox.close);
+        }
+
+        // adjust some positioning if needed
+        if(absolute_pos){
+            // give the container absolute positioning
+            SL.setStyle(SL.get('shadowbox_container'), 'position', 'absolute');
+            // give shadowbox_body "layout"...whatever that is
+            SL.setStyle('shadowbox_body', 'zoom', 1);
+            // need to listen to the container element because it covers the top
+            // half of the page
+            SL.addEvent(SL.get('shadowbox_container'), 'click', function(e){
+                var target = SL.getTarget(e);
+                if(target.id && target.id == 'shadowbox_container') Shadowbox.close();
+            });
+        }
+
+        // skip setup, will need to be done manually later
+        if(!options.skipSetup) Shadowbox.setup();
+        initialized = true;
+    };
+
+    /**
+     * Sets up listeners on the given links that will trigger Shadowbox. If no
+     * links are given, this method will set up every anchor element on the page
+     * with the appropriate rel attribute. Note: Because AREA elements do not
+     * support the rel attribute, they must be explicitly passed to this method.
+     *
+     * @param   {Array}     links       An array (or array-like) list of anchor
+     *                                  and/or area elements to set up
+     * @param   {Object}    opts        Some options to use for the given links
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.setup = function(links, opts){
+        // get links if none specified
+        if(!links){
+            var links = [];
+            var a = document.getElementsByTagName('a'), rel;
+            for(var i = 0, len = a.length; i < len; ++i){
+                rel = a[i].getAttribute('rel');
+                if(rel && RE.rel.test(rel)) links[links.length] = a[i];
+            }
+        }else if(!links.length){
+            links = [links]; // one link
+        }
+
+        var link;
+        for(var i = 0, len = links.length; i < len; ++i){
+            link = links[i];
+            if(typeof link.shadowboxCacheKey == 'undefined'){
+                // assign cache key expando
+                // use integer primitive to avoid memory leak in IE
+                link.shadowboxCacheKey = cache.length;
+                SL.addEvent(link, 'click', handleClick); // add listener
+            }
+            cache[link.shadowboxCacheKey] = this.buildCacheObj(link, opts);
+        }
+    };
+
+    /**
+     * Builds an object from the original link element data to store in cache.
+     * These objects contain (most of) the following keys:
+     *
+     * - el: the link element
+     * - title: the linked file title
+     * - type: the linked file type
+     * - content: the linked file's URL
+     * - gallery: the gallery the file belongs to (optional)
+     * - height: the height of the linked file (only necessary for movies)
+     * - width: the width of the linked file (only necessary for movies)
+     * - options: custom options to use (optional)
+     *
+     * @param   {HTMLElement}   link    The link element to process
+     * @return  {Object}                An object representing the link
+     * @public
+     * @static
+     */
+    Shadowbox.buildCacheObj = function(link, opts){
+        var href = link.href; // don't use getAttribute() here
+        var o = {
+            el:         link,
+            title:      link.getAttribute('title'),
+            type:       getPlayerType(href),
+            options:    apply({}, opts || {}), // break the reference
+            content:    href
+        };
+
+        // remove link-level options from top-level options
+        var opt, l_opts = ['title', 'type', 'height', 'width', 'gallery'];
+        for(var i = 0, len = l_opts.length; i < len; ++i){
+            opt = l_opts[i];
+            if(typeof o.options[opt] != 'undefined'){
+                o[opt] = o.options[opt];
+                delete o.options[opt];
+            }
+        }
+
+        // HTML options always trump JavaScript options, so do these last
+        var rel = link.getAttribute('rel');
+        if(rel){
+            // extract gallery name from shadowbox[name] format
+            var match = rel.match(RE.gallery);
+            if(match) o.gallery = escape(match[2]);
+
+            // other parameters
+            var params = rel.split(';');
+            for(var i = 0, len = params.length; i < len; ++i){
+                match = params[i].match(RE.param);
+                if(match){
+                    if(match[1] == 'options'){
+                        eval('o.options = apply(o.options, ' + match[2] + ')');
+                    }else{
+                        o[match[1]] = match[2];
+                    }
+                }
+            }
+        }
+
+        return o;
+    };
+
+    /**
+     * Applies the given set of options to those currently in use. Note: Options
+     * will be reset on Shadowbox.open() so this function is only useful after
+     * it has already been called (while Shadowbox is open).
+     *
+     * @param   {Object}    opts        The options to apply
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.applyOptions = function(opts){
+        if(opts){
+            // use apply here to break references
+            default_options = apply({}, options); // store default options
+            options = apply(options, opts); // apply options
+        }
+    };
+
+    /**
+     * Reverts Shadowbox' options to the last default set in use before
+     * Shadowbox.applyOptions() was called.
+     *
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.revertOptions = function(){
+        if(default_options){
+            options = default_options; // revert to default options
+            default_options = null; // erase for next time
+        }
+    };
+
+    /**
+     * Opens the given object in Shadowbox. This object may be either an
+     * anchor/area element, or an object similar to the one created by
+     * Shadowbox.buildCacheObj().
+     *
+     * @param   {mixed}     obj         The object or link element that defines
+     *                                  what to display
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.open = function(obj, opts){
+        if(activated) return; // already open
+        activated = true;
+
+        // is it a link?
+        if(isLink(obj)){
+            if(typeof obj.shadowboxCacheKey == 'undefined' || typeof cache[obj.shadowboxCacheKey] == 'undefined'){
+                // link element that hasn't been set up before
+                // create an object on-the-fly
+                obj = this.buildCacheObj(obj, opts);
+            }else{
+                // link element that has been set up before, get from cache
+                obj = cache[obj.shadowboxCacheKey];
+            }
+        }
+
+        this.revertOptions();
+        if(obj.options || opts){
+            // use apply here to break references
+            this.applyOptions(apply(apply({}, obj.options || {}), opts || {}));
+        }
+
+        // update current & current_gallery
+        setupGallery(obj);
+
+        // anything to display?
+        if(current_gallery.length){
+            // fire onOpen hook
+            if(options.onOpen && typeof options.onOpen == 'function'){
+                options.onOpen(obj);
+            }
+
+            // display:block here helps with correct dimension calculations
+            SL.setStyle(SL.get('shadowbox'), 'display', 'block');
+
+            toggleTroubleElements(false);
+            var dims = getDimensions(options.initialHeight, options.initialWidth);
+            adjustHeight(dims.height, dims.top);
+            adjustWidth(dims.width);
+            hideBars(false);
+
+            // show the overlay and load the content
+            toggleOverlay(function(){
+                SL.setStyle(SL.get('shadowbox'), 'visibility', 'visible');
+                showLoading();
+                loadContent();
+            });
+        }
+    };
+
+    /**
+     * Jumps to the piece in the current gallery with index num.
+     *
+     * @param   {Number}    num     The gallery index to view
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.change = function(num){
+        if(!current_gallery) return; // no current gallery
+        if(!current_gallery[num]){ // index does not exist
+            if(!options.continuous){
+                return;
+            }else{
+                num = (num < 0) ? (current_gallery.length - 1) : 0; // loop
+            }
+        }
+
+        // update current
+        current = num;
+
+        // stop listening for drag
+        toggleDrag(false);
+        // empty the content
+        setContent(null);
+        // turn this back on when done
+        listenKeyboard(false);
+
+        // fire onChange handler
+        if(options.onChange && typeof options.onChange == 'function'){
+            options.onChange(current_gallery[current]);
+        }
+
+        showLoading();
+        hideBars(loadContent);
+    };
+
+    /**
+     * Jumps to the next piece in the gallery.
+     *
+     * @return  {Boolean}       True if the gallery changed to next item, false
+     *                          otherwise
+     * @public
+     * @static
+     */
+    Shadowbox.next = function(){
+        return this.change(current + 1);
+    };
+
+    /**
+     * Jumps to the previous piece in the gallery.
+     *
+     * @return  {Boolean}       True if the gallery changed to previous item,
+     *                          false otherwise
+     * @public
+     * @static
+     */
+    Shadowbox.previous = function(){
+        return this.change(current - 1);
+    };
+
+    /**
+     * Deactivates Shadowbox.
+     *
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.close = function(){
+        if(!activated) return; // already closed
+
+        // stop listening for keys
+        listenKeyboard(false);
+        // hide
+        SL.setStyle(SL.get('shadowbox'), {
+            display: 'none',
+            visibility: 'hidden'
+        });
+        // stop listening for scroll on IE
+        if(absolute_pos) SL.removeEvent(window, 'scroll', centerVertically);
+        // stop listening for drag
+        toggleDrag(false);
+        // empty the content
+        setContent(null);
+        // prevent old image requests from loading
+        if(preloader){
+            preloader.onload = function(){};
+            preloader = null;
+        }
+        // hide the overlay
+        toggleOverlay(false);
+        // turn on trouble elements
+        toggleTroubleElements(true);
+
+        // fire onClose handler
+        if(options.onClose && typeof options.onClose == 'function'){
+            options.onClose(current_gallery[current]);
+        }
+
+        activated = false;
+    };
+
+    /**
+     * Clears Shadowbox' cache and removes listeners and expandos from all
+     * cached link elements. May be used to completely reset Shadowbox in case
+     * links on a page change.
+     *
+     * @return  void
+     * @public
+     * @static
+     */
+    Shadowbox.clearCache = function(){
+        for(var i = 0, len = cache.length; i < len; ++i){
+            if(cache[i].el){
+                SL.removeEvent(cache[i].el, 'click', handleClick);
+                delete cache[i].shadowboxCacheKey;
+            }
+        }
+        cache = [];
+    };
+
+    /**
+     * Generates the markup necessary to embed the movie file with the given
+     * link element. This markup will be browser-specific. Useful for generating
+     * the media test suite.
+     *
+     * @param   {HTMLElement}   link        The link to the media file
+     * @return  {Object}                    The proper markup to use (see above)
+     * @public
+     * @static
+     */
+    Shadowbox.movieMarkup = function(obj){
+        // movies default to 300x300 pixels
+        var h = obj.height ? parseInt(obj.height, 10) : 300;
+        var w = obj.width ? parseInt(obj.width, 10) : 300;
+
+        var autoplay = options.autoplayMovies;
+        var controls = options.showMovieControls;
+        if(obj.options){
+            if(obj.options.autoplayMovies != null){
+                autoplay = obj.options.autoplayMovies;
+            }
+            if(obj.options.showMovieControls != null){
+                controls = obj.options.showMovieControls;
+            }
+        }
+
+        var markup = {
+            tag:    'object',
+            name:   'shadowbox_content'
+        };
+
+        switch(obj.type){
+            case 'swf':
+                var dims = getDimensions(h, w, true);
+                h = dims.height;
+                w = dims.width;
+                markup.type = 'application/x-shockwave-flash';
+                markup.data = obj.content;
+                markup.children = [
+                    { tag: 'param', name: 'movie', value: obj.content }
+                ];
+            break;
+            case 'flv':
+                autoplay = autoplay ? 'true' : 'false';
+                var showicons = 'false';
+                var a = h/w; // aspect ratio
+                if(controls){
+                    showicons = 'true';
+                    h += 20; // height of JW FLV player controller
+                }
+                var dims = getDimensions(h, h/a, true); // resize
+                h = dims.height;
+                w = (h-(controls?20:0))/a; // maintain aspect ratio
+                var flashvars = [
+                    'file=' + obj.content,
+                    'height=' + h,
+                    'width=' + w,
+                    'autostart=' + autoplay,
+                    'displayheight=' + (h - (controls?20:0)),
+                    'showicons=' + showicons,
+                    'backcolor=0x000000&amp;frontcolor=0xCCCCCC&amp;lightcolor=0x557722'
+                ];
+                markup.type = 'application/x-shockwave-flash';
+                markup.data = options.assetURL + options.flvPlayer;
+                markup.children = [
+                    { tag: 'param', name: 'movie', value: options.assetURL + options.flvPlayer },
+                    { tag: 'param', name: 'flashvars', value: flashvars.join('&amp;') },
+                    { tag: 'param', name: 'allowfullscreen', value: 'true' }
+                ];
+            break;
+            case 'qt':
+                autoplay = autoplay ? 'true' : 'false';
+                if(controls){
+                    controls = 'true';
+                    h += 16; // height of QuickTime controller
+                }else{
+                    controls = 'false';
+                }
+                markup.children = [
+                    { tag: 'param', name: 'src', value: obj.content },
+                    { tag: 'param', name: 'scale', value: 'aspect' },
+                    { tag: 'param', name: 'controller', value: controls },
+                    { tag: 'param', name: 'autoplay', value: autoplay }
+                ];
+                if(isIE){
+                    markup.classid = 'clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B';
+                    markup.codebase = 'http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0';
+                }else{
+                    markup.type = 'video/quicktime';
+                    markup.data = obj.content;
+                }
+            break;
+            case 'wmp':
+                autoplay = autoplay ? 1 : 0;
+                markup.children = [
+                    { tag: 'param', name: 'autostart', value: autoplay }
+                ];
+                if(isIE){
+                    if(controls){
+                        controls = 'full';
+                        h += 70; // height of WMP controller in IE
+                    }else{
+                        controls = 'none';
+                    }
+                    // markup.type = 'application/x-oleobject';
+                    markup.classid = 'clsid:6BF52A52-394A-11d3-B153-00C04F79FAA6';
+                    markup.children[markup.children.length] = { tag: 'param', name: 'url', value: obj.content };
+                    markup.children[markup.children.length] = { tag: 'param', name: 'uimode', value: controls };
+                }else{
+                    if(controls){
+                        controls = 1;
+                        h += 45; // height of WMP controller in non-IE
+                    }else{
+                        controls = 0;
+                    }
+                    markup.type = 'video/x-ms-wmv';
+                    markup.data = obj.content;
+                    markup.children[markup.children.length] = { tag: 'param', name: 'showcontrols', value: controls };
+                }
+            break;
+        }
+
+        markup.height = h; // new height includes controller
+        markup.width = w;
+
+        return markup;
+    };
+
+    /**
+     * Creates an HTML string from an object representing HTML elements. Based
+     * on Ext.DomHelper's createHtml.
+     *
+     * @param   {Object}    obj     The HTML definition object
+     * @return  {String}            An HTML string
+     * @public
+     * @static
+     */
+    Shadowbox.createHTML = function(obj){
+        var html = '<' + obj.tag;
+        for(var attr in obj){
+            if(attr == 'tag' || attr == 'html' || attr == 'children') continue;
+            if(attr == 'cls'){
+                html += ' class="' + obj['cls'] + '"';
+            }else{
+                html += ' ' + attr + '="' + obj[attr] + '"';
+            }
+        }
+        if(RE.empty.test(obj.tag)){
+            html += '/>\n';
+        }else{
+            html += '>\n';
+            var cn = obj.children;
+            if(cn){
+                for(var i = 0, len = cn.length; i < len; ++i){
+                    html += this.createHTML(cn[i]);
+                }
+            }
+            if(obj.html) html += obj.html;
+            html += '</' + obj.tag + '>\n';
+        }
+        return html;
+    };
+
+    /**
+     * Gets an object that lists which plugins are supported by the client. The
+     * keys of this object will be:
+     *
+     * - fla: Adobe Flash Player
+     * - qt: QuickTime Player
+     * - wmp: Windows Media Player
+     * - f4m: Flip4Mac QuickTime Player
+     *
+     * @return  {Object}        The plugins object
+     * @public
+     * @static
+     */
+    Shadowbox.getPlugins = function(){
+        return plugins;
+    };
+
+    /**
+     * Gets the current options object in use.
+     *
+     * @return  {Object}        The options object
+     * @public
+     * @static
+     */
+    Shadowbox.getOptions = function(){
+        return options;
+    };
+
+    /**
+     * Gets the current gallery object.
+     *
+     * @return  {Object}        The current gallery item
+     * @public
+     * @static
+     */
+    Shadowbox.getCurrent = function(){
+        return current_gallery[current];
+    };
+
+    /**
+     * Gets the current version number of Shadowbox.
+     *
+     * @return  {String}        The current version
+     * @public
+     * @static
+     */
+    Shadowbox.getVersion = function(){
+        return version;
+    };
+
+})();
+
+/**
+ * Finds the index of the given object in this array.
+ *
+ * @param   {mixed}     o   The object to search for
+ * @return  {Number}        The index of the given object
+ * @public
+ */
+Array.prototype.indexOf = Array.prototype.indexOf || function(o){
+    for(var i = 0, len = this.length; i < len; ++i){
+        if(this[i] == o) return i;
+    }
+    return -1;
+};
+
+/**
+ * Formats a string with the given parameters. The string for format must have
+ * placeholders that correspond to the numerical index of the arguments passed
+ * in surrounded by curly braces (e.g. 'Some {0} string {1}').
+ *
+ * @param   {String}    format      The string to format
+ * @param   ...                     The parameters to put inside the string
+ * @return  {String}                The string with the specified parameters
+ *                                  replaced
+ * @public
+ * @static
+ */
+String.format = String.format || function(format){
+    var args = Array.prototype.slice.call(arguments, 1);
+    return format.replace(/\{(\d+)\}/g, function(m, i){
+        return args[i];
+    });
+};

Added: trunk/www.gnome.org/projects/cheese/data/shadowbox/js/yui-utilities.js
==============================================================================
--- (empty file)
+++ trunk/www.gnome.org/projects/cheese/data/shadowbox/js/yui-utilities.js	Sun Sep 21 14:16:52 2008
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2007, Yahoo! Inc. All rights reserved.
+Code licensed under the BSD License: http://developer.yahoo.net/yui/license.txt
+version: 2.4.1
+
+Note: This file includes yahoo, dom, event, and anim
+
+*/
+if(typeof YAHOO=="undefined"||!YAHOO){var YAHOO={};}YAHOO.namespace=function(){var A=arguments,E=null,C,B,D;for(C=0;C<A.length;C=C+1){D=A[C].split(".");E=YAHOO;for(B=(D[0]=="YAHOO")?1:0;B<D.length;B=B+1){E[D[B]]=E[D[B]]||{};E=E[D[B]];}}return E;};YAHOO.log=function(D,A,C){var B=YAHOO.widget.Logger;if(B&&B.log){return B.log(D,A,C);}else{return false;}};YAHOO.register=function(A,E,D){var I=YAHOO.env.modules;if(!I[A]){I[A]={versions:[],builds:[]};}var B=I[A],H=D.version,G=D.build,F=YAHOO.env.listeners;B.name=A;B.version=H;B.build=G;B.versions.push(H);B.builds.push(G);B.mainClass=E;for(var C=0;C<F.length;C=C+1){F[C](B);}if(E){E.VERSION=H;E.BUILD=G;}else{YAHOO.log("mainClass is undefined for module "+A,"warn");}};YAHOO.env=YAHOO.env||{modules:[],listeners:[]};YAHOO.env.getVersion=function(A){return YAHOO.env.modules[A]||null;};YAHOO.env.ua=function(){var C={ie:0,opera:0,gecko:0,webkit:0,mobile:null};var B=navigator.userAgent,A;if((/KHTML/).test(B)){C.webkit=1;}A=B.match(/AppleWeb
 Kit\/([^\s]*)/);if(A&&A[1]){C.webkit=parseFloat(A[1]);if(/ Mobile\//.test(B)){C.mobile="Apple";}else{A=B.match(/NokiaN[^\/]*/);if(A){C.mobile=A[0];}}}if(!C.webkit){A=B.match(/Opera[\s\/]([^\s]*)/);if(A&&A[1]){C.opera=parseFloat(A[1]);A=B.match(/Opera Mini[^;]*/);if(A){C.mobile=A[0];}}else{A=B.match(/MSIE\s([^;]*)/);if(A&&A[1]){C.ie=parseFloat(A[1]);}else{A=B.match(/Gecko\/([^\s]*)/);if(A){C.gecko=1;A=B.match(/rv:([^\s\)]*)/);if(A&&A[1]){C.gecko=parseFloat(A[1]);}}}}}return C;}();(function(){YAHOO.namespace("util","widget","example");if("undefined"!==typeof YAHOO_config){var B=YAHOO_config.listener,A=YAHOO.env.listeners,D=true,C;if(B){for(C=0;C<A.length;C=C+1){if(A[C]==B){D=false;break;}}if(D){A.push(B);}}}})();YAHOO.lang=YAHOO.lang||{isArray:function(B){if(B){var A=YAHOO.lang;return A.isNumber(B.length)&&A.isFunction(B.splice);}return false;},isBoolean:function(A){return typeof A==="boolean";},isFunction:function(A){return typeof A==="function";},isNull:function(A){return A=
 ==null;},isNumber:function(A){return typeof A==="number"&&isFinite(A);},isObject:function(A){return(A&&(typeof A==="object"||YAHOO.lang.isFunction(A)))||false;},isString:function(A){return typeof A==="string";},isUndefined:function(A){return typeof A==="undefined";},hasOwnProperty:function(A,B){if(Object.prototype.hasOwnProperty){return A.hasOwnProperty(B);}return !YAHOO.lang.isUndefined(A[B])&&A.constructor.prototype[B]!==A[B];},_IEEnumFix:function(C,B){if(YAHOO.env.ua.ie){var E=["toString","valueOf"],A;for(A=0;A<E.length;A=A+1){var F=E[A],D=B[F];if(YAHOO.lang.isFunction(D)&&D!=Object.prototype[F]){C[F]=D;}}}},extend:function(D,E,C){if(!E||!D){throw new Error("YAHOO.lang.extend failed, please check that all dependencies are included.");}var B=function(){};B.prototype=E.prototype;D.prototype=new B();D.prototype.constructor=D;D.superclass=E.prototype;if(E.prototype.constructor==Object.prototype.constructor){E.prototype.constructor=E;}if(C){for(var A in C){D.prototype[A]=C[A];
 }YAHOO.lang._IEEnumFix(D.prototype,C);}},augmentObject:function(E,D){if(!D||!E){throw new Error("Absorb failed, verify dependencies.");}var A=arguments,C,F,B=A[2];if(B&&B!==true){for(C=2;C<A.length;C=C+1){E[A[C]]=D[A[C]];}}else{for(F in D){if(B||!E[F]){E[F]=D[F];}}YAHOO.lang._IEEnumFix(E,D);}},augmentProto:function(D,C){if(!C||!D){throw new Error("Augment failed, verify dependencies.");}var A=[D.prototype,C.prototype];for(var B=2;B<arguments.length;B=B+1){A.push(arguments[B]);}YAHOO.lang.augmentObject.apply(this,A);},dump:function(A,G){var C=YAHOO.lang,D,F,I=[],J="{...}",B="f(){...}",H=", ",E=" => ";if(!C.isObject(A)){return A+"";}else{if(A instanceof Date||("nodeType" in A&&"tagName" in A)){return A;}else{if(C.isFunction(A)){return B;}}}G=(C.isNumber(G))?G:3;if(C.isArray(A)){I.push("[");for(D=0,F=A.length;D<F;D=D+1){if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}if(I.length>1){I.pop();}I.push("]");}else{I.push("{");for(D in A){if(C.hasO
 wnProperty(A,D)){I.push(D+E);if(C.isObject(A[D])){I.push((G>0)?C.dump(A[D],G-1):J);}else{I.push(A[D]);}I.push(H);}}if(I.length>1){I.pop();}I.push("}");}return I.join("");},substitute:function(Q,B,J){var G,F,E,M,N,P,D=YAHOO.lang,L=[],C,H="dump",K=" ",A="{",O="}";for(;;){G=Q.lastIndexOf(A);if(G<0){break;}F=Q.indexOf(O,G);if(G+1>=F){break;}C=Q.substring(G+1,F);M=C;P=null;E=M.indexOf(K);if(E>-1){P=M.substring(E+1);M=M.substring(0,E);}N=B[M];if(J){N=J(M,N,P);}if(D.isObject(N)){if(D.isArray(N)){N=D.dump(N,parseInt(P,10));}else{P=P||"";var I=P.indexOf(H);if(I>-1){P=P.substring(4);}if(N.toString===Object.prototype.toString||I>-1){N=D.dump(N,parseInt(P,10));}else{N=N.toString();}}}else{if(!D.isString(N)&&!D.isNumber(N)){N="~-"+L.length+"-~";L[L.length]=C;}}Q=Q.substring(0,G)+N+Q.substring(F+1);}for(G=L.length-1;G>=0;G=G-1){Q=Q.replace(new RegExp("~-"+G+"-~"),"{"+L[G]+"}","g");}return Q;},trim:function(A){try{return A.replace(/^\s+|\s+$/g,"");}catch(B){return A;}},merge:function(){var
  D={},B=arguments;for(var C=0,A=B.length;C<A;C=C+1){YAHOO.lang.augmentObject(D,B[C],true);}return D;},later:function(H,B,I,D,E){H=H||0;B=B||{};var C=I,G=D,F,A;if(YAHOO.lang.isString(I)){C=B[I];}if(!C){throw new TypeError("method undefined");}if(!YAHOO.lang.isArray(G)){G=[D];}F=function(){C.apply(B,G);};A=(E)?setInterval(F,H):setTimeout(F,H);return{interval:E,cancel:function(){if(this.interval){clearInterval(A);}else{clearTimeout(A);}}};},isValue:function(B){var A=YAHOO.lang;return(A.isObject(B)||A.isString(B)||A.isNumber(B)||A.isBoolean(B));}};YAHOO.util.Lang=YAHOO.lang;YAHOO.lang.augment=YAHOO.lang.augmentProto;YAHOO.augment=YAHOO.lang.augmentProto;YAHOO.extend=YAHOO.lang.extend;YAHOO.register("yahoo",YAHOO,{version:"2.4.1",build:"742"});(function(){var B=YAHOO.util,L,J,H=0,K={},F={},N=window.document;var C=YAHOO.env.ua.opera,M=YAHOO.env.ua.webkit,A=YAHOO.env.ua.gecko,G=YAHOO.env.ua.ie;var E={HYPHEN:/(-[a-z])/i,ROOT_TAG:/^body|html$/i};var O=function(Q){if(!E.HYPHEN.test(Q)
 ){return Q;}if(K[Q]){return K[Q];}var R=Q;while(E.HYPHEN.exec(R)){R=R.replace(RegExp.$1,RegExp.$1.substr(1).toUpperCase());}K[Q]=R;return R;};var P=function(R){var Q=F[R];if(!Q){Q=new RegExp("(?:^|\\s+)"+R+"(?:\\s+|$)");F[R]=Q;}return Q;};if(N.defaultView&&N.defaultView.getComputedStyle){L=function(Q,T){var S=null;if(T=="float"){T="cssFloat";}var R=N.defaultView.getComputedStyle(Q,"");if(R){S=R[O(T)];}return Q.style[T]||S;};}else{if(N.documentElement.currentStyle&&G){L=function(Q,S){switch(O(S)){case"opacity":var U=100;try{U=Q.filters["DXImageTransform.Microsoft.Alpha"].opacity;}catch(T){try{U=Q.filters("alpha").opacity;}catch(T){}}return U/100;case"float":S="styleFloat";default:var R=Q.currentStyle?Q.currentStyle[S]:null;return(Q.style[S]||R);}};}else{L=function(Q,R){return Q.style[R];};}}if(G){J=function(Q,R,S){switch(R){case"opacity":if(YAHOO.lang.isString(Q.style.filter)){Q.style.filter="alpha(opacity="+S*100+")";if(!Q.currentStyle||!Q.currentStyle.hasLayout){Q.style.zoo
 m=1;}}break;case"float":R="styleFloat";default:Q.style[R]=S;}};}else{J=function(Q,R,S){if(R=="float"){R="cssFloat";}Q.style[R]=S;};}var D=function(Q,R){return Q&&Q.nodeType==1&&(!R||R(Q));};YAHOO.util.Dom={get:function(S){if(S&&(S.tagName||S.item)){return S;}if(YAHOO.lang.isString(S)||!S){return N.getElementById(S);}if(S.length!==undefined){var T=[];for(var R=0,Q=S.length;R<Q;++R){T[T.length]=B.Dom.get(S[R]);}return T;}return S;},getStyle:function(Q,S){S=O(S);var R=function(T){return L(T,S);};return B.Dom.batch(Q,R,B.Dom,true);},setStyle:function(Q,S,T){S=O(S);var R=function(U){J(U,S,T);};B.Dom.batch(Q,R,B.Dom,true);},getXY:function(Q){var R=function(S){if((S.parentNode===null||S.offsetParent===null||this.getStyle(S,"display")=="none")&&S!=S.ownerDocument.body){return false;}return I(S);};return B.Dom.batch(Q,R,B.Dom,true);},getX:function(Q){var R=function(S){return B.Dom.getXY(S)[0];};return B.Dom.batch(Q,R,B.Dom,true);},getY:function(Q){var R=function(S){return B.Dom.getXY
 (S)[1];};return B.Dom.batch(Q,R,B.Dom,true);},setXY:function(Q,T,S){var R=function(W){var V=this.getStyle(W,"position");if(V=="static"){this.setStyle(W,"position","relative");V="relative";}var Y=this.getXY(W);if(Y===false){return false;}var X=[parseInt(this.getStyle(W,"left"),10),parseInt(this.getStyle(W,"top"),10)];if(isNaN(X[0])){X[0]=(V=="relative")?0:W.offsetLeft;}if(isNaN(X[1])){X[1]=(V=="relative")?0:W.offsetTop;}if(T[0]!==null){W.style.left=T[0]-Y[0]+X[0]+"px";}if(T[1]!==null){W.style.top=T[1]-Y[1]+X[1]+"px";}if(!S){var U=this.getXY(W);if((T[0]!==null&&U[0]!=T[0])||(T[1]!==null&&U[1]!=T[1])){this.setXY(W,T,true);}}};B.Dom.batch(Q,R,B.Dom,true);},setX:function(R,Q){B.Dom.setXY(R,[Q,null]);},setY:function(Q,R){B.Dom.setXY(Q,[null,R]);},getRegion:function(Q){var R=function(S){if((S.parentNode===null||S.offsetParent===null||this.getStyle(S,"display")=="none")&&S!=N.body){return false;}var T=B.Region.getRegion(S);return T;};return B.Dom.batch(Q,R,B.Dom,true);},getClientWid
 th:function(){return B.Dom.getViewportWidth();},getClientHeight:function(){return B.Dom.getViewportHeight();},getElementsByClassName:function(U,Y,V,W){Y=Y||"*";V=(V)?B.Dom.get(V):null||N;if(!V){return[];}var R=[],Q=V.getElementsByTagName(Y),X=P(U);for(var S=0,T=Q.length;S<T;++S){if(X.test(Q[S].className)){R[R.length]=Q[S];if(W){W.call(Q[S],Q[S]);}}}return R;},hasClass:function(S,R){var Q=P(R);var T=function(U){return Q.test(U.className);};return B.Dom.batch(S,T,B.Dom,true);},addClass:function(R,Q){var S=function(T){if(this.hasClass(T,Q)){return false;}T.className=YAHOO.lang.trim([T.className,Q].join(" "));return true;};return B.Dom.batch(R,S,B.Dom,true);},removeClass:function(S,R){var Q=P(R);var T=function(U){if(!this.hasClass(U,R)){return false;}var V=U.className;U.className=V.replace(Q," ");if(this.hasClass(U,R)){this.removeClass(U,R);}U.className=YAHOO.lang.trim(U.className);return true;};return B.Dom.batch(S,T,B.Dom,true);},replaceClass:function(T,R,Q){if(!Q||R===Q){retu
 rn false;}var S=P(R);var U=function(V){if(!this.hasClass(V,R)){this.addClass(V,Q);return true;}V.className=V.className.replace(S," "+Q+" ");if(this.hasClass(V,R)){this.replaceClass(V,R,Q);}V.className=YAHOO.lang.trim(V.className);return true;};return B.Dom.batch(T,U,B.Dom,true);},generateId:function(Q,S){S=S||"yui-gen";var R=function(T){if(T&&T.id){return T.id;}var U=S+H++;if(T){T.id=U;}return U;};return B.Dom.batch(Q,R,B.Dom,true)||R.apply(B.Dom,arguments);},isAncestor:function(Q,R){Q=B.Dom.get(Q);R=B.Dom.get(R);if(!Q||!R){return false;}if(Q.contains&&R.nodeType&&!M){return Q.contains(R);}else{if(Q.compareDocumentPosition&&R.nodeType){return !!(Q.compareDocumentPosition(R)&16);}else{if(R.nodeType){return !!this.getAncestorBy(R,function(S){return S==Q;});}}}return false;},inDocument:function(Q){return this.isAncestor(N.documentElement,Q);},getElementsBy:function(X,R,S,U){R=R||"*";S=(S)?B.Dom.get(S):null||N;if(!S){return[];}var T=[],W=S.getElementsByTagName(R);for(var V=0,Q=W
 .length;V<Q;++V){if(X(W[V])){T[T.length]=W[V];if(U){U(W[V]);}}}return T;},batch:function(U,X,W,S){U=(U&&(U.tagName||U.item))?U:B.Dom.get(U);if(!U||!X){return false;}var T=(S)?W:window;if(U.tagName||U.length===undefined){return X.call(T,U,W);}var V=[];for(var R=0,Q=U.length;R<Q;++R){V[V.length]=X.call(T,U[R],W);}return V;},getDocumentHeight:function(){var R=(N.compatMode!="CSS1Compat")?N.body.scrollHeight:N.documentElement.scrollHeight;var Q=Math.max(R,B.Dom.getViewportHeight());return Q;},getDocumentWidth:function(){var R=(N.compatMode!="CSS1Compat")?N.body.scrollWidth:N.documentElement.scrollWidth;var Q=Math.max(R,B.Dom.getViewportWidth());return Q;},getViewportHeight:function(){var Q=self.innerHeight;var R=N.compatMode;if((R||G)&&!C){Q=(R=="CSS1Compat")?N.documentElement.clientHeight:N.body.clientHeight;
+}return Q;},getViewportWidth:function(){var Q=self.innerWidth;var R=N.compatMode;if(R||G){Q=(R=="CSS1Compat")?N.documentElement.clientWidth:N.body.clientWidth;}return Q;},getAncestorBy:function(Q,R){while(Q=Q.parentNode){if(D(Q,R)){return Q;}}return null;},getAncestorByClassName:function(R,Q){R=B.Dom.get(R);if(!R){return null;}var S=function(T){return B.Dom.hasClass(T,Q);};return B.Dom.getAncestorBy(R,S);},getAncestorByTagName:function(R,Q){R=B.Dom.get(R);if(!R){return null;}var S=function(T){return T.tagName&&T.tagName.toUpperCase()==Q.toUpperCase();};return B.Dom.getAncestorBy(R,S);},getPreviousSiblingBy:function(Q,R){while(Q){Q=Q.previousSibling;if(D(Q,R)){return Q;}}return null;},getPreviousSibling:function(Q){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getPreviousSiblingBy(Q);},getNextSiblingBy:function(Q,R){while(Q){Q=Q.nextSibling;if(D(Q,R)){return Q;}}return null;},getNextSibling:function(Q){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getNextSiblingBy(Q);},ge
 tFirstChildBy:function(Q,S){var R=(D(Q.firstChild,S))?Q.firstChild:null;return R||B.Dom.getNextSiblingBy(Q.firstChild,S);},getFirstChild:function(Q,R){Q=B.Dom.get(Q);if(!Q){return null;}return B.Dom.getFirstChildBy(Q);},getLastChildBy:function(Q,S){if(!Q){return null;}var R=(D(Q.lastChild,S))?Q.lastChild:null;return R||B.Dom.getPreviousSiblingBy(Q.lastChild,S);},getLastChild:function(Q){Q=B.Dom.get(Q);return B.Dom.getLastChildBy(Q);},getChildrenBy:function(R,T){var S=B.Dom.getFirstChildBy(R,T);var Q=S?[S]:[];B.Dom.getNextSiblingBy(S,function(U){if(!T||T(U)){Q[Q.length]=U;}return false;});return Q;},getChildren:function(Q){Q=B.Dom.get(Q);if(!Q){}return B.Dom.getChildrenBy(Q);},getDocumentScrollLeft:function(Q){Q=Q||N;return Math.max(Q.documentElement.scrollLeft,Q.body.scrollLeft);},getDocumentScrollTop:function(Q){Q=Q||N;return Math.max(Q.documentElement.scrollTop,Q.body.scrollTop);},insertBefore:function(R,Q){R=B.Dom.get(R);Q=B.Dom.get(Q);if(!R||!Q||!Q.parentNode){return nul
 l;}return Q.parentNode.insertBefore(R,Q);},insertAfter:function(R,Q){R=B.Dom.get(R);Q=B.Dom.get(Q);if(!R||!Q||!Q.parentNode){return null;}if(Q.nextSibling){return Q.parentNode.insertBefore(R,Q.nextSibling);}else{return Q.parentNode.appendChild(R);}},getClientRegion:function(){var S=B.Dom.getDocumentScrollTop(),R=B.Dom.getDocumentScrollLeft(),T=B.Dom.getViewportWidth()+R,Q=B.Dom.getViewportHeight()+S;return new B.Region(S,T,Q,R);}};var I=function(){if(N.documentElement.getBoundingClientRect){return function(R){var S=R.getBoundingClientRect();var Q=R.ownerDocument;return[S.left+B.Dom.getDocumentScrollLeft(Q),S.top+B.Dom.getDocumentScrollTop(Q)];};}else{return function(S){var T=[S.offsetLeft,S.offsetTop];var R=S.offsetParent;var Q=(M&&B.Dom.getStyle(S,"position")=="absolute"&&S.offsetParent==S.ownerDocument.body);if(R!=S){while(R){T[0]+=R.offsetLeft;T[1]+=R.offsetTop;if(!Q&&M&&B.Dom.getStyle(R,"position")=="absolute"){Q=true;}R=R.offsetParent;}}if(Q){T[0]-=S.ownerDocument.body.
 offsetLeft;T[1]-=S.ownerDocument.body.offsetTop;}R=S.parentNode;while(R.tagName&&!E.ROOT_TAG.test(R.tagName)){if(B.Dom.getStyle(R,"display").search(/^inline|table-row.*$/i)){T[0]-=R.scrollLeft;T[1]-=R.scrollTop;}R=R.parentNode;}return T;};}}();})();YAHOO.util.Region=function(C,D,A,B){this.top=C;this[1]=C;this.right=D;this.bottom=A;this.left=B;this[0]=B;};YAHOO.util.Region.prototype.contains=function(A){return(A.left>=this.left&&A.right<=this.right&&A.top>=this.top&&A.bottom<=this.bottom);};YAHOO.util.Region.prototype.getArea=function(){return((this.bottom-this.top)*(this.right-this.left));};YAHOO.util.Region.prototype.intersect=function(E){var C=Math.max(this.top,E.top);var D=Math.min(this.right,E.right);var A=Math.min(this.bottom,E.bottom);var B=Math.max(this.left,E.left);if(A>=C&&D>=B){return new YAHOO.util.Region(C,D,A,B);}else{return null;}};YAHOO.util.Region.prototype.union=function(E){var C=Math.min(this.top,E.top);var D=Math.max(this.right,E.right);var A=Math.max(this
 .bottom,E.bottom);var B=Math.min(this.left,E.left);return new YAHOO.util.Region(C,D,A,B);};YAHOO.util.Region.prototype.toString=function(){return("Region {top: "+this.top+", right: "+this.right+", bottom: "+this.bottom+", left: "+this.left+"}");};YAHOO.util.Region.getRegion=function(D){var F=YAHOO.util.Dom.getXY(D);var C=F[1];var E=F[0]+D.offsetWidth;var A=F[1]+D.offsetHeight;var B=F[0];return new YAHOO.util.Region(C,E,A,B);};YAHOO.util.Point=function(A,B){if(YAHOO.lang.isArray(A)){B=A[1];A=A[0];}this.x=this.right=this.left=this[0]=A;this.y=this.top=this.bottom=this[1]=B;};YAHOO.util.Point.prototype=new YAHOO.util.Region();YAHOO.register("dom",YAHOO.util.Dom,{version:"2.4.1",build:"742"});YAHOO.util.CustomEvent=function(D,B,C,A){this.type=D;this.scope=B||window;this.silent=C;this.signature=A||YAHOO.util.CustomEvent.LIST;this.subscribers=[];if(!this.silent){}var E="_YUICEOnSubscribe";if(D!==E){this.subscribeEvent=new YAHOO.util.CustomEvent(E,this,true);}this.lastError=null;};
 YAHOO.util.CustomEvent.LIST=0;YAHOO.util.CustomEvent.FLAT=1;YAHOO.util.CustomEvent.prototype={subscribe:function(B,C,A){if(!B){throw new Error("Invalid callback for subscriber to '"+this.type+"'");}if(this.subscribeEvent){this.subscribeEvent.fire(B,C,A);}this.subscribers.push(new YAHOO.util.Subscriber(B,C,A));},unsubscribe:function(D,F){if(!D){return this.unsubscribeAll();}var E=false;for(var B=0,A=this.subscribers.length;B<A;++B){var C=this.subscribers[B];if(C&&C.contains(D,F)){this._delete(B);E=true;}}return E;},fire:function(){var D=this.subscribers.length;if(!D&&this.silent){return true;}var H=[],F=true,C,I=false;for(C=0;C<arguments.length;++C){H.push(arguments[C]);}if(!this.silent){}for(C=0;C<D;++C){var L=this.subscribers[C];if(!L){I=true;}else{if(!this.silent){}var K=L.getScope(this.scope);if(this.signature==YAHOO.util.CustomEvent.FLAT){var A=null;if(H.length>0){A=H[0];}try{F=L.fn.call(K,A,L.obj);}catch(E){this.lastError=E;}}else{try{F=L.fn.call(K,this.type,H,L.obj);}c
 atch(G){this.lastError=G;}}if(false===F){if(!this.silent){}return false;}}}if(I){var J=[],B=this.subscribers;for(C=0,D=B.length;C<D;C=C+1){J.push(B[C]);}this.subscribers=J;}return true;},unsubscribeAll:function(){for(var B=0,A=this.subscribers.length;B<A;++B){this._delete(A-1-B);}this.subscribers=[];return B;},_delete:function(A){var B=this.subscribers[A];if(B){delete B.fn;delete B.obj;}this.subscribers[A]=null;},toString:function(){return"CustomEvent: '"+this.type+"', scope: "+this.scope;}};YAHOO.util.Subscriber=function(B,C,A){this.fn=B;this.obj=YAHOO.lang.isUndefined(C)?null:C;this.override=A;};YAHOO.util.Subscriber.prototype.getScope=function(A){if(this.override){if(this.override===true){return this.obj;}else{return this.override;}}return A;};YAHOO.util.Subscriber.prototype.contains=function(A,B){if(B){return(this.fn==A&&this.obj==B);}else{return(this.fn==A);}};YAHOO.util.Subscriber.prototype.toString=function(){return"Subscriber { obj: "+this.obj+", override: "+(this.ov
 erride||"no")+" }";};if(!YAHOO.util.Event){YAHOO.util.Event=function(){var H=false;var I=[];var J=[];var G=[];var E=[];var C=0;var F=[];var B=[];var A=0;var D={63232:38,63233:40,63234:37,63235:39,63276:33,63277:34,25:9};return{POLL_RETRYS:4000,POLL_INTERVAL:10,EL:0,TYPE:1,FN:2,WFN:3,UNLOAD_OBJ:3,ADJ_SCOPE:4,OBJ:5,OVERRIDE:6,lastError:null,isSafari:YAHOO.env.ua.webkit,webkit:YAHOO.env.ua.webkit,isIE:YAHOO.env.ua.ie,_interval:null,_dri:null,DOMReady:false,startInterval:function(){if(!this._interval){var K=this;var L=function(){K._tryPreloadAttach();};this._interval=setInterval(L,this.POLL_INTERVAL);}},onAvailable:function(P,M,Q,O,N){var K=(YAHOO.lang.isString(P))?[P]:P;for(var L=0;L<K.length;L=L+1){F.push({id:K[L],fn:M,obj:Q,override:O,checkReady:N});}C=this.POLL_RETRYS;this.startInterval();},onContentReady:function(M,K,N,L){this.onAvailable(M,K,N,L,true);},onDOMReady:function(K,M,L){if(this.DOMReady){setTimeout(function(){var N=window;if(L){if(L===true){N=M;}else{N=L;}}K.call
 (N,"DOMReady",[],M);},0);}else{this.DOMReadyEvent.subscribe(K,M,L);}},addListener:function(M,K,V,Q,L){if(!V||!V.call){return false;}if(this._isValidCollection(M)){var W=true;for(var R=0,T=M.length;R<T;++R){W=this.on(M[R],K,V,Q,L)&&W;}return W;}else{if(YAHOO.lang.isString(M)){var P=this.getEl(M);if(P){M=P;}else{this.onAvailable(M,function(){YAHOO.util.Event.on(M,K,V,Q,L);});return true;}}}if(!M){return false;}if("unload"==K&&Q!==this){J[J.length]=[M,K,V,Q,L];return true;}var Y=M;if(L){if(L===true){Y=Q;}else{Y=L;}}var N=function(Z){return V.call(Y,YAHOO.util.Event.getEvent(Z,M),Q);};var X=[M,K,V,N,Y,Q,L];var S=I.length;I[S]=X;if(this.useLegacyEvent(M,K)){var O=this.getLegacyIndex(M,K);if(O==-1||M!=G[O][0]){O=G.length;B[M.id+K]=O;G[O]=[M,K,M["on"+K]];E[O]=[];M["on"+K]=function(Z){YAHOO.util.Event.fireLegacyEvent(YAHOO.util.Event.getEvent(Z),O);};}E[O].push(X);}else{try{this._simpleAdd(M,K,N,false);}catch(U){this.lastError=U;this.removeListener(M,K,V);return false;}}return true;
 },fireLegacyEvent:function(O,M){var Q=true,K,S,R,T,P;S=E[M];for(var L=0,N=S.length;L<N;++L){R=S[L];if(R&&R[this.WFN]){T=R[this.ADJ_SCOPE];P=R[this.WFN].call(T,O);Q=(Q&&P);}}K=G[M];if(K&&K[2]){K[2](O);}return Q;},getLegacyIndex:function(L,M){var K=this.generateId(L)+M;if(typeof B[K]=="undefined"){return -1;}else{return B[K];}},useLegacyEvent:function(L,M){if(this.webkit&&("click"==M||"dblclick"==M)){var K=parseInt(this.webkit,10);if(!isNaN(K)&&K<418){return true;}}return false;},removeListener:function(L,K,T){var O,R,V;if(typeof L=="string"){L=this.getEl(L);}else{if(this._isValidCollection(L)){var U=true;for(O=0,R=L.length;O<R;++O){U=(this.removeListener(L[O],K,T)&&U);}return U;}}if(!T||!T.call){return this.purgeElement(L,false,K);}if("unload"==K){for(O=0,R=J.length;O<R;O++){V=J[O];if(V&&V[0]==L&&V[1]==K&&V[2]==T){J[O]=null;return true;}}return false;}var P=null;var Q=arguments[3];if("undefined"===typeof Q){Q=this._getCacheIndex(L,K,T);}if(Q>=0){P=I[Q];}if(!L||!P){return fals
 e;}if(this.useLegacyEvent(L,K)){var N=this.getLegacyIndex(L,K);var M=E[N];if(M){for(O=0,R=M.length;O<R;++O){V=M[O];if(V&&V[this.EL]==L&&V[this.TYPE]==K&&V[this.FN]==T){M[O]=null;break;}}}}else{try{this._simpleRemove(L,K,P[this.WFN],false);}catch(S){this.lastError=S;return false;}}delete I[Q][this.WFN];delete I[Q][this.FN];I[Q]=null;return true;},getTarget:function(M,L){var K=M.target||M.srcElement;return this.resolveTextNode(K);},resolveTextNode:function(K){if(K&&3==K.nodeType){return K.parentNode;}else{return K;}},getPageX:function(L){var K=L.pageX;if(!K&&0!==K){K=L.clientX||0;if(this.isIE){K+=this._getScrollLeft();}}return K;},getPageY:function(K){var L=K.pageY;if(!L&&0!==L){L=K.clientY||0;if(this.isIE){L+=this._getScrollTop();}}return L;},getXY:function(K){return[this.getPageX(K),this.getPageY(K)];
+},getRelatedTarget:function(L){var K=L.relatedTarget;if(!K){if(L.type=="mouseout"){K=L.toElement;}else{if(L.type=="mouseover"){K=L.fromElement;}}}return this.resolveTextNode(K);},getTime:function(M){if(!M.time){var L=new Date().getTime();try{M.time=L;}catch(K){this.lastError=K;return L;}}return M.time;},stopEvent:function(K){this.stopPropagation(K);this.preventDefault(K);},stopPropagation:function(K){if(K.stopPropagation){K.stopPropagation();}else{K.cancelBubble=true;}},preventDefault:function(K){if(K.preventDefault){K.preventDefault();}else{K.returnValue=false;}},getEvent:function(M,K){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break;}N=N.caller;}}return L;},getCharCode:function(L){var K=L.keyCode||L.charCode||0;if(YAHOO.env.ua.webkit&&(K in D)){K=D[K];}return K;},_getCacheIndex:function(O,P,N){for(var M=0,L=I.length;M<L;++M){var K=I[M];if(K&&K[this.FN]==N&&K[this.EL]==O&&K[this.TYPE]==P){return M;}}return -
 1;},generateId:function(K){var L=K.id;if(!L){L="yuievtautoid-"+A;++A;K.id=L;}return L;},_isValidCollection:function(L){try{return(L&&typeof L!=="string"&&L.length&&!L.tagName&&!L.alert&&typeof L[0]!=="undefined");}catch(K){return false;}},elCache:{},getEl:function(K){return(typeof K==="string")?document.getElementById(K):K;},clearCache:function(){},DOMReadyEvent:new YAHOO.util.CustomEvent("DOMReady",this),_load:function(L){if(!H){H=true;var K=YAHOO.util.Event;K._ready();K._tryPreloadAttach();}},_ready:function(L){var K=YAHOO.util.Event;if(!K.DOMReady){K.DOMReady=true;K.DOMReadyEvent.fire();K._simpleRemove(document,"DOMContentLoaded",K._ready);}},_tryPreloadAttach:function(){if(this.locked){return false;}if(this.isIE){if(!this.DOMReady){this.startInterval();return false;}}this.locked=true;var P=!H;if(!P){P=(C>0);}var O=[];var Q=function(S,T){var R=S;if(T.override){if(T.override===true){R=T.obj;}else{R=T.override;}}T.fn.call(R,T.obj);};var L,K,N,M;for(L=0,K=F.length;L<K;++L){N
 =F[L];if(N&&!N.checkReady){M=this.getEl(N.id);if(M){Q(M,N);F[L]=null;}else{O.push(N);}}}for(L=0,K=F.length;L<K;++L){N=F[L];if(N&&N.checkReady){M=this.getEl(N.id);if(M){if(H||M.nextSibling){Q(M,N);F[L]=null;}}else{O.push(N);}}}C=(O.length===0)?0:C-1;if(P){this.startInterval();}else{clearInterval(this._interval);this._interval=null;}this.locked=false;return true;},purgeElement:function(O,P,R){var M=(YAHOO.lang.isString(O))?this.getEl(O):O;var Q=this.getListeners(M,R),N,K;if(Q){for(N=0,K=Q.length;N<K;++N){var L=Q[N];this.removeListener(M,L.type,L.fn,L.index);}}if(P&&M&&M.childNodes){for(N=0,K=M.childNodes.length;N<K;++N){this.purgeElement(M.childNodes[N],P,R);}}},getListeners:function(M,K){var P=[],L;if(!K){L=[I,J];}else{if(K==="unload"){L=[J];}else{L=[I];}}var R=(YAHOO.lang.isString(M))?this.getEl(M):M;for(var O=0;O<L.length;O=O+1){var T=L[O];if(T&&T.length>0){for(var Q=0,S=T.length;Q<S;++Q){var N=T[Q];if(N&&N[this.EL]===R&&(!K||K===N[this.TYPE])){P.push({type:N[this.TYPE],fn:
 N[this.FN],obj:N[this.OBJ],adjust:N[this.OVERRIDE],scope:N[this.ADJ_SCOPE],index:Q});}}}}return(P.length)?P:null;},_unload:function(R){var Q=YAHOO.util.Event,O,N,L,K,M;for(O=0,K=J.length;O<K;++O){L=J[O];if(L){var P=window;if(L[Q.ADJ_SCOPE]){if(L[Q.ADJ_SCOPE]===true){P=L[Q.UNLOAD_OBJ];}else{P=L[Q.ADJ_SCOPE];}}L[Q.FN].call(P,Q.getEvent(R,L[Q.EL]),L[Q.UNLOAD_OBJ]);J[O]=null;L=null;P=null;}}J=null;if(YAHOO.env.ua.ie&&I&&I.length>0){N=I.length;while(N){M=N-1;L=I[M];if(L){Q.removeListener(L[Q.EL],L[Q.TYPE],L[Q.FN],M);}N--;}L=null;}G=null;Q._simpleRemove(window,"unload",Q._unload);},_getScrollLeft:function(){return this._getScroll()[1];},_getScrollTop:function(){return this._getScroll()[0];},_getScroll:function(){var K=document.documentElement,L=document.body;if(K&&(K.scrollTop||K.scrollLeft)){return[K.scrollTop,K.scrollLeft];}else{if(L){return[L.scrollTop,L.scrollLeft];}else{return[0,0];}}},regCE:function(){},_simpleAdd:function(){if(window.addEventListener){return function(M,N,L,
 K){M.addEventListener(N,L,(K));};}else{if(window.attachEvent){return function(M,N,L,K){M.attachEvent("on"+N,L);};}else{return function(){};}}}(),_simpleRemove:function(){if(window.removeEventListener){return function(M,N,L,K){M.removeEventListener(N,L,(K));};}else{if(window.detachEvent){return function(L,M,K){L.detachEvent("on"+M,K);};}else{return function(){};}}}()};}();(function(){var A=YAHOO.util.Event;A.on=A.addListener;if(A.isIE){YAHOO.util.Event.onDOMReady(YAHOO.util.Event._tryPreloadAttach,YAHOO.util.Event,true);A._dri=setInterval(function(){var C=document.createElement("p");try{C.doScroll("left");clearInterval(A._dri);A._dri=null;A._ready();C=null;}catch(B){C=null;}},A.POLL_INTERVAL);}else{if(A.webkit){A._dri=setInterval(function(){var B=document.readyState;if("loaded"==B||"complete"==B){clearInterval(A._dri);A._dri=null;A._ready();}},A.POLL_INTERVAL);}else{A._simpleAdd(document,"DOMContentLoaded",A._ready);}}A._simpleAdd(window,"load",A._load);A._simpleAdd(window,"u
 nload",A._unload);A._tryPreloadAttach();})();}YAHOO.util.EventProvider=function(){};YAHOO.util.EventProvider.prototype={__yui_events:null,__yui_subscribers:null,subscribe:function(A,C,F,E){this.__yui_events=this.__yui_events||{};var D=this.__yui_events[A];if(D){D.subscribe(C,F,E);}else{this.__yui_subscribers=this.__yui_subscribers||{};var B=this.__yui_subscribers;if(!B[A]){B[A]=[];}B[A].push({fn:C,obj:F,override:E});}},unsubscribe:function(C,E,G){this.__yui_events=this.__yui_events||{};var A=this.__yui_events;if(C){var F=A[C];if(F){return F.unsubscribe(E,G);}}else{var B=true;for(var D in A){if(YAHOO.lang.hasOwnProperty(A,D)){B=B&&A[D].unsubscribe(E,G);}}return B;}return false;},unsubscribeAll:function(A){return this.unsubscribe(A);},createEvent:function(G,D){this.__yui_events=this.__yui_events||{};var A=D||{};var I=this.__yui_events;if(I[G]){}else{var H=A.scope||this;var E=(A.silent);var B=new YAHOO.util.CustomEvent(G,H,E,YAHOO.util.CustomEvent.FLAT);I[G]=B;if(A.onSubscribeC
 allback){B.subscribeEvent.subscribe(A.onSubscribeCallback);}this.__yui_subscribers=this.__yui_subscribers||{};
+var F=this.__yui_subscribers[G];if(F){for(var C=0;C<F.length;++C){B.subscribe(F[C].fn,F[C].obj,F[C].override);}}}return I[G];},fireEvent:function(E,D,A,C){this.__yui_events=this.__yui_events||{};var G=this.__yui_events[E];if(!G){return null;}var B=[];for(var F=1;F<arguments.length;++F){B.push(arguments[F]);}return G.fire.apply(G,B);},hasEvent:function(A){if(this.__yui_events){if(this.__yui_events[A]){return true;}}return false;}};YAHOO.util.KeyListener=function(A,F,B,C){if(!A){}else{if(!F){}else{if(!B){}}}if(!C){C=YAHOO.util.KeyListener.KEYDOWN;}var D=new YAHOO.util.CustomEvent("keyPressed");this.enabledEvent=new YAHOO.util.CustomEvent("enabled");this.disabledEvent=new YAHOO.util.CustomEvent("disabled");if(typeof A=="string"){A=document.getElementById(A);}if(typeof B=="function"){D.subscribe(B);}else{D.subscribe(B.fn,B.scope,B.correctScope);}function E(J,I){if(!F.shift){F.shift=false;}if(!F.alt){F.alt=false;}if(!F.ctrl){F.ctrl=false;}if(J.shiftKey==F.shift&&J.altKey==F.alt&&
 J.ctrlKey==F.ctrl){var G;if(F.keys instanceof Array){for(var H=0;H<F.keys.length;H++){G=F.keys[H];if(G==J.charCode){D.fire(J.charCode,J);break;}else{if(G==J.keyCode){D.fire(J.keyCode,J);break;}}}}else{G=F.keys;if(G==J.charCode){D.fire(J.charCode,J);}else{if(G==J.keyCode){D.fire(J.keyCode,J);}}}}}this.enable=function(){if(!this.enabled){YAHOO.util.Event.addListener(A,C,E);this.enabledEvent.fire(F);}this.enabled=true;};this.disable=function(){if(this.enabled){YAHOO.util.Event.removeListener(A,C,E);this.disabledEvent.fire(F);}this.enabled=false;};this.toString=function(){return"KeyListener ["+F.keys+"] "+A.tagName+(A.id?"["+A.id+"]":"");};};YAHOO.util.KeyListener.KEYDOWN="keydown";YAHOO.util.KeyListener.KEYUP="keyup";YAHOO.util.KeyListener.KEY={ALT:18,BACK_SPACE:8,CAPS_LOCK:20,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,META:224,NUM_LOCK:144,PAGE_DOWN:34,PAGE_UP:33,PAUSE:19,PRINTSCREEN:44,RIGHT:39,SCROLL_LOCK:145,SHIFT:16,SPACE:32,TAB:9,UP:38};YAHOO.r
 egister("event",YAHOO.util.Event,{version:"2.4.1",build:"742"});YAHOO.register("yahoo-dom-event", YAHOO, {version: "2.4.1", build: "742"});
+YAHOO.util.Anim=function(B,A,C,D){if(!B){}this.init(B,A,C,D);};YAHOO.util.Anim.prototype={toString:function(){var A=this.getEl();var B=A.id||A.tagName||A;return("Anim "+B);},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(A,C,B){return this.method(this.currentFrame,C,B-C,this.totalFrames);},setAttribute:function(A,C,B){if(this.patterns.noNegatives.test(A)){C=(C>0)?C:0;}YAHOO.util.Dom.setStyle(this.getEl(),A,C+B);},getAttribute:function(A){var C=this.getEl();var E=YAHOO.util.Dom.getStyle(C,A);if(E!=="auto"&&!this.patterns.offsetUnit.test(E)){return parseFloat(E);}var B=this.patterns.offsetAttribute.exec(A)||[];var F=!!(B[3]);var D=!!(B[2]);if(D||(YAHOO.util.Dom.getStyle(C,"position")=="absolute"&&F)){E=C["offset"+B[0].charAt(0).toUpperCase()+B[0].substr(1)];}else{E=0;}return E;},getDefaultUnit:function(A){
 if(this.patterns.defaultUnit.test(A)){return"px";}return"";},setRuntimeAttribute:function(B){var G;var C;var D=this.attributes;this.runtimeAttributes[B]={};var F=function(H){return(typeof H!=="undefined");};if(!F(D[B]["to"])&&!F(D[B]["by"])){return false;}G=(F(D[B]["from"]))?D[B]["from"]:this.getAttribute(B);if(F(D[B]["to"])){C=D[B]["to"];}else{if(F(D[B]["by"])){if(G.constructor==Array){C=[];for(var E=0,A=G.length;E<A;++E){C[E]=G[E]+D[B]["by"][E]*1;}}else{C=G+D[B]["by"]*1;}}}this.runtimeAttributes[B].start=G;this.runtimeAttributes[B].end=C;this.runtimeAttributes[B].unit=(F(D[B].unit))?D[B]["unit"]:this.getDefaultUnit(B);return true;},init:function(C,H,G,A){var B=false;var D=null;var F=0;C=YAHOO.util.Dom.get(C);this.attributes=H||{};this.duration=!YAHOO.lang.isUndefined(G)?G:1;this.method=A||YAHOO.util.Easing.easeNone;this.useSeconds=true;this.currentFrame=0;this.totalFrames=YAHOO.util.AnimMgr.fps;this.setEl=function(K){C=YAHOO.util.Dom.get(K);};this.getEl=function(){return C
 ;};this.isAnimated=function(){return B;};this.getStartTime=function(){return D;};this.runtimeAttributes={};this.animate=function(){if(this.isAnimated()){return false;}this.currentFrame=0;this.totalFrames=(this.useSeconds)?Math.ceil(YAHOO.util.AnimMgr.fps*this.duration):this.duration;if(this.duration===0&&this.useSeconds){this.totalFrames=1;}YAHOO.util.AnimMgr.registerElement(this);return true;};this.stop=function(K){if(!this.isAnimated()){return false;}if(K){this.currentFrame=this.totalFrames;this._onTween.fire();}YAHOO.util.AnimMgr.stop(this);};var J=function(){this.onStart.fire();this.runtimeAttributes={};for(var K in this.attributes){this.setRuntimeAttribute(K);}B=true;F=0;D=new Date();};var I=function(){var M={duration:new Date()-this.getStartTime(),currentFrame:this.currentFrame};M.toString=function(){return("duration: "+M.duration+", currentFrame: "+M.currentFrame);};this.onTween.fire(M);var L=this.runtimeAttributes;for(var K in L){this.setAttribute(K,this.doMethod(K,L
 [K].start,L[K].end),L[K].unit);}F+=1;};var E=function(){var K=(new Date()-D)/1000;var L={duration:K,frames:F,fps:F/K};L.toString=function(){return("duration: "+L.duration+", frames: "+L.frames+", fps: "+L.fps);};B=false;F=0;this.onComplete.fire(L);};this._onStart=new YAHOO.util.CustomEvent("_start",this,true);this.onStart=new YAHOO.util.CustomEvent("start",this);this.onTween=new YAHOO.util.CustomEvent("tween",this);this._onTween=new YAHOO.util.CustomEvent("_tween",this,true);this.onComplete=new YAHOO.util.CustomEvent("complete",this);this._onComplete=new YAHOO.util.CustomEvent("_complete",this,true);this._onStart.subscribe(J);this._onTween.subscribe(I);this._onComplete.subscribe(E);}};YAHOO.util.AnimMgr=new function(){var C=null;var B=[];var A=0;this.fps=1000;this.delay=1;this.registerElement=function(F){B[B.length]=F;A+=1;F._onStart.fire();this.start();};this.unRegister=function(G,F){F=F||E(G);if(!G.isAnimated()||F==-1){return false;}G._onComplete.fire();B.splice(F,1);A-=1;
 if(A<=0){this.stop();}return true;};this.start=function(){if(C===null){C=setInterval(this.run,this.delay);}};this.stop=function(H){if(!H){clearInterval(C);for(var G=0,F=B.length;G<F;++G){this.unRegister(B[0],0);}B=[];C=null;A=0;}else{this.unRegister(H);}};this.run=function(){for(var H=0,F=B.length;H<F;++H){var G=B[H];if(!G||!G.isAnimated()){continue;}if(G.currentFrame<G.totalFrames||G.totalFrames===null){G.currentFrame+=1;if(G.useSeconds){D(G);}G._onTween.fire();}else{YAHOO.util.AnimMgr.stop(G,H);}}};var E=function(H){for(var G=0,F=B.length;G<F;++G){if(B[G]==H){return G;}}return -1;};var D=function(G){var J=G.totalFrames;var I=G.currentFrame;var H=(G.currentFrame*G.duration*1000/G.totalFrames);var F=(new Date()-G.getStartTime());var K=0;if(F<G.duration*1000){K=Math.round((F/H-1)*G.currentFrame);}else{K=J-(I+1);}if(K>0&&isFinite(K)){if(G.currentFrame+K>=J){K=J-(I+1);}G.currentFrame+=K;}};};YAHOO.util.Bezier=new function(){this.getPosition=function(E,D){var F=E.length;var C=[]
 ;for(var B=0;B<F;++B){C[B]=[E[B][0],E[B][1]];}for(var A=1;A<F;++A){for(B=0;B<F-A;++B){C[B][0]=(1-D)*C[B][0]+D*C[parseInt(B+1,10)][0];C[B][1]=(1-D)*C[B][1]+D*C[parseInt(B+1,10)][1];}}return[C[0][0],C[0][1]];};};(function(){YAHOO.util.ColorAnim=function(E,D,F,G){YAHOO.util.ColorAnim.superclass.constructor.call(this,E,D,F,G);};YAHOO.extend(YAHOO.util.ColorAnim,YAHOO.util.Anim);var B=YAHOO.util;var C=B.ColorAnim.superclass;var A=B.ColorAnim.prototype;A.toString=function(){var D=this.getEl();var E=D.id||D.tagName;return("ColorAnim "+E);};A.patterns.color=/color$/i;A.patterns.rgb=/^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;A.patterns.hex=/^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;A.patterns.hex3=/^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;A.patterns.transparent=/^transparent|rgba\(0, 0, 0, 0\)$/;A.parseColor=function(D){if(D.length==3){return D;}var E=this.patterns.hex.exec(D);if(E&&E.length==4){return[parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16)];}E=this.pa
 tterns.rgb.exec(D);if(E&&E.length==4){return[parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10)];
+}E=this.patterns.hex3.exec(D);if(E&&E.length==4){return[parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16)];}return null;};A.getAttribute=function(D){var F=this.getEl();if(this.patterns.color.test(D)){var G=YAHOO.util.Dom.getStyle(F,D);if(this.patterns.transparent.test(G)){var E=F.parentNode;G=B.Dom.getStyle(E,D);while(E&&this.patterns.transparent.test(G)){E=E.parentNode;G=B.Dom.getStyle(E,D);if(E.tagName.toUpperCase()=="HTML"){G="#fff";}}}}else{G=C.getAttribute.call(this,D);}return G;};A.doMethod=function(E,I,F){var H;if(this.patterns.color.test(E)){H=[];for(var G=0,D=I.length;G<D;++G){H[G]=C.doMethod.call(this,E,I[G],F[G]);}H="rgb("+Math.floor(H[0])+","+Math.floor(H[1])+","+Math.floor(H[2])+")";}else{H=C.doMethod.call(this,E,I,F);}return H;};A.setRuntimeAttribute=function(E){C.setRuntimeAttribute.call(this,E);if(this.patterns.color.test(E)){var G=this.attributes;var I=this.parseColor(this.runtimeAttributes[E].start);var F=this.parseColor(this.runtimeAttri
 butes[E].end);if(typeof G[E]["to"]==="undefined"&&typeof G[E]["by"]!=="undefined"){F=this.parseColor(G[E].by);for(var H=0,D=I.length;H<D;++H){F[H]=I[H]+F[H];}}this.runtimeAttributes[E].start=I;this.runtimeAttributes[E].end=F;}};})();YAHOO.util.Easing={easeNone:function(B,A,D,C){return D*B/C+A;},easeIn:function(B,A,D,C){return D*(B/=C)*B+A;},easeOut:function(B,A,D,C){return -D*(B/=C)*(B-2)+A;},easeBoth:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B+A;}return -D/2*((--B)*(B-2)-1)+A;},easeInStrong:function(B,A,D,C){return D*(B/=C)*B*B*B+A;},easeOutStrong:function(B,A,D,C){return -D*((B=B/C-1)*B*B*B-1)+A;},easeBothStrong:function(B,A,D,C){if((B/=C/2)<1){return D/2*B*B*B*B+A;}return -D/2*((B-=2)*B*B*B-2)+A;},elasticIn:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return -(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;},elasticOut:function(C,A,G,F,B,E){i
 f(C==0){return A;}if((C/=F)==1){return A+G;}if(!E){E=F*0.3;}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}return B*Math.pow(2,-10*C)*Math.sin((C*F-D)*(2*Math.PI)/E)+G+A;},elasticBoth:function(C,A,G,F,B,E){if(C==0){return A;}if((C/=F/2)==2){return A+G;}if(!E){E=F*(0.3*1.5);}if(!B||B<Math.abs(G)){B=G;var D=E/4;}else{var D=E/(2*Math.PI)*Math.asin(G/B);}if(C<1){return -0.5*(B*Math.pow(2,10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E))+A;}return B*Math.pow(2,-10*(C-=1))*Math.sin((C*F-D)*(2*Math.PI)/E)*0.5+G+A;},backIn:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*(B/=D)*B*((C+1)*B-C)+A;},backOut:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}return E*((B=B/D-1)*B*((C+1)*B+C)+1)+A;},backBoth:function(B,A,E,D,C){if(typeof C=="undefined"){C=1.70158;}if((B/=D/2)<1){return E/2*(B*B*(((C*=(1.525))+1)*B-C))+A;}return E/2*((B-=2)*B*(((C*=(1.525))+1)*B+C)+2)+A;},bounceIn:function(B,A,D,C){return D-YAHOO.util.Easing.bounceOut(C-B,0,D
 ,C)+A;},bounceOut:function(B,A,D,C){if((B/=C)<(1/2.75)){return D*(7.5625*B*B)+A;}else{if(B<(2/2.75)){return D*(7.5625*(B-=(1.5/2.75))*B+0.75)+A;}else{if(B<(2.5/2.75)){return D*(7.5625*(B-=(2.25/2.75))*B+0.9375)+A;}}}return D*(7.5625*(B-=(2.625/2.75))*B+0.984375)+A;},bounceBoth:function(B,A,D,C){if(B<C/2){return YAHOO.util.Easing.bounceIn(B*2,0,D,C)*0.5+A;}return YAHOO.util.Easing.bounceOut(B*2-C,0,D,C)*0.5+D*0.5+A;}};(function(){YAHOO.util.Motion=function(G,F,H,I){if(G){YAHOO.util.Motion.superclass.constructor.call(this,G,F,H,I);}};YAHOO.extend(YAHOO.util.Motion,YAHOO.util.ColorAnim);var D=YAHOO.util;var E=D.Motion.superclass;var B=D.Motion.prototype;B.toString=function(){var F=this.getEl();var G=F.id||F.tagName;return("Motion "+G);};B.patterns.points=/^points$/i;B.setAttribute=function(F,H,G){if(this.patterns.points.test(F)){G=G||"px";E.setAttribute.call(this,"left",H[0],G);E.setAttribute.call(this,"top",H[1],G);}else{E.setAttribute.call(this,F,H,G);}};B.getAttribute=functi
 on(F){if(this.patterns.points.test(F)){var G=[E.getAttribute.call(this,"left"),E.getAttribute.call(this,"top")];}else{G=E.getAttribute.call(this,F);}return G;};B.doMethod=function(F,J,G){var I=null;if(this.patterns.points.test(F)){var H=this.method(this.currentFrame,0,100,this.totalFrames)/100;I=D.Bezier.getPosition(this.runtimeAttributes[F],H);}else{I=E.doMethod.call(this,F,J,G);}return I;};B.setRuntimeAttribute=function(O){if(this.patterns.points.test(O)){var G=this.getEl();var I=this.attributes;var F;var K=I["points"]["control"]||[];var H;var L,N;if(K.length>0&&!(K[0] instanceof Array)){K=[K];}else{var J=[];for(L=0,N=K.length;L<N;++L){J[L]=K[L];}K=J;}if(D.Dom.getStyle(G,"position")=="static"){D.Dom.setStyle(G,"position","relative");}if(C(I["points"]["from"])){D.Dom.setXY(G,I["points"]["from"]);}else{D.Dom.setXY(G,D.Dom.getXY(G));}F=this.getAttribute("points");if(C(I["points"]["to"])){H=A.call(this,I["points"]["to"],F);var M=D.Dom.getXY(this.getEl());for(L=0,N=K.length;L<N
 ;++L){K[L]=A.call(this,K[L],F);}}else{if(C(I["points"]["by"])){H=[F[0]+I["points"]["by"][0],F[1]+I["points"]["by"][1]];for(L=0,N=K.length;L<N;++L){K[L]=[F[0]+K[L][0],F[1]+K[L][1]];}}}this.runtimeAttributes[O]=[F];if(K.length>0){this.runtimeAttributes[O]=this.runtimeAttributes[O].concat(K);}this.runtimeAttributes[O][this.runtimeAttributes[O].length]=H;}else{E.setRuntimeAttribute.call(this,O);}};var A=function(F,H){var G=D.Dom.getXY(this.getEl());F=[F[0]-G[0]+H[0],F[1]-G[1]+H[1]];return F;};var C=function(F){return(typeof F!=="undefined");};})();(function(){YAHOO.util.Scroll=function(E,D,F,G){if(E){YAHOO.util.Scroll.superclass.constructor.call(this,E,D,F,G);}};YAHOO.extend(YAHOO.util.Scroll,YAHOO.util.ColorAnim);var B=YAHOO.util;var C=B.Scroll.superclass;var A=B.Scroll.prototype;A.toString=function(){var D=this.getEl();var E=D.id||D.tagName;return("Scroll "+E);};A.doMethod=function(D,G,E){var F=null;if(D=="scroll"){F=[this.method(this.currentFrame,G[0],E[0]-G[0],this.totalFram
 es),this.method(this.currentFrame,G[1],E[1]-G[1],this.totalFrames)];
+}else{F=C.doMethod.call(this,D,G,E);}return F;};A.getAttribute=function(D){var F=null;var E=this.getEl();if(D=="scroll"){F=[E.scrollLeft,E.scrollTop];}else{F=C.getAttribute.call(this,D);}return F;};A.setAttribute=function(D,G,F){var E=this.getEl();if(D=="scroll"){E.scrollLeft=G[0];E.scrollTop=G[1];}else{C.setAttribute.call(this,D,G,F);}};})();YAHOO.register("animation",YAHOO.util.Anim,{version:"2.4.1",build:"742"});

Modified: trunk/www.gnome.org/projects/cheese/data/themes/cheese/document.screen.css
==============================================================================
--- trunk/www.gnome.org/projects/cheese/data/themes/cheese/document.screen.css	(original)
+++ trunk/www.gnome.org/projects/cheese/data/themes/cheese/document.screen.css	Sun Sep 21 14:16:52 2008
@@ -193,18 +193,18 @@
 .imagel
 {
   float:left;
-  margin: 5px 2em 5px 5px;
+  margin: 5px 2em 5px 0px;
 }
 
 .imager
 {
   float:right;
-  margin: 5px 5px 5px 2em;
+  margin: 5px 0px 5px 2em;
 }
 
 .tour-item
 {
-  min-height: 170px;
+  min-height: 200px;
 }
 
 #warningbox

Modified: trunk/www.gnome.org/projects/cheese/data/tour/cheese-about.jpg
==============================================================================
Binary files. No diff available.

Modified: trunk/www.gnome.org/projects/cheese/data/tour/cheese-countdown.jpg
==============================================================================
Binary files. No diff available.

Modified: trunk/www.gnome.org/projects/cheese/data/tour/cheese-effects.jpg
==============================================================================
Binary files. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/tour/cheese-fullscreen.jpg
==============================================================================
Binary file. No diff available.

Modified: trunk/www.gnome.org/projects/cheese/data/tour/cheese-main.jpg
==============================================================================
Binary files. No diff available.

Added: trunk/www.gnome.org/projects/cheese/data/tour/cheese-prefs.jpg
==============================================================================
Binary file. No diff available.

Modified: trunk/www.gnome.org/projects/cheese/data/tour/cheese-share.jpg
==============================================================================
Binary files. No diff available.

Modified: trunk/www.gnome.org/projects/cheese/data/tour/cheese-video.jpg
==============================================================================
Binary files. No diff available.

Modified: trunk/www.gnome.org/projects/cheese/download.html
==============================================================================
--- trunk/www.gnome.org/projects/cheese/download.html	(original)
+++ trunk/www.gnome.org/projects/cheese/download.html	Sun Sep 21 14:16:52 2008
@@ -18,7 +18,6 @@
       <ul>
         <li class="current"><a href="index.html">Home</a>
         <ul>
-          <li><a href="screenshots.html">Screenshots</a> </li>
           <li><a href="tour.html">Tour</a> </li>
           <li><a href="download.html">Download</a> </li>
           <li><a href="http://live.gnome.org/Cheese/FAQ";>FAQ</a> </li>

Modified: trunk/www.gnome.org/projects/cheese/index.html
==============================================================================
--- trunk/www.gnome.org/projects/cheese/index.html	(original)
+++ trunk/www.gnome.org/projects/cheese/index.html	Sun Sep 21 14:16:52 2008
@@ -18,7 +18,6 @@
       <ul>
         <li class="current"><a href="index.html">Home</a>
         <ul>
-          <li><a href="screenshots.html">Screenshots</a> </li>
           <li><a href="tour.html">Tour</a> </li>
           <li><a href="download.html">Download</a> </li>
           <li><a href="http://live.gnome.org/Cheese/FAQ";>FAQ</a> </li>
@@ -34,7 +33,8 @@
       <div id="top">
         <!--  <a href="screenshots.html"> <img src="data/images/cheese-big.png" alt="cheese!"/> </a> -->
         <!-- <a href="tour.html"> <img src="data/images/cheese-tour.png" alt="cheese tour"/> </a> -->
-        <a href="http://home.cs.tum.edu/~siegel/news/2008_06_12-awesomeness";> <img src="data/images/cheese-birthday.png" alt="cheese birthday"/> </a>
+        <!-- <a href="http://home.cs.tum.edu/~siegel/news/2008_06_12-awesomeness";> <img src="data/images/cheese-birthday.png" alt="cheese birthday"/> </a> -->
+        <a href="tour.html"> <img src="data/images/cheese-2.24.png" alt="cheese tour"/> </a>
       </div><!-- top -->
 
       <!--
@@ -66,7 +66,7 @@
             It was written as part of Google's 2007 Summer of Code lead by
             <a href="http://home.cs.tum.edu/~siegel";>daniel g. siegel</a> and
             mentored by <a href="http://raphael.slinckx.net";>RaphaÃl
-              Slinckx</a>
+              Slinckx</a>.
             Under the hood, Cheese uses GStreamer to apply fancy
             effects to photos and videos. With Cheese it is easy to take photos
             of you, your friends, pets or whatever you want and share them with
@@ -80,19 +80,18 @@
             <img src="data/images/application-x-executable.png" alt="icon" />
             </div>
             <ul>
-              <li>GNOME 2.22</li>
+              <li>GNOME 2.24</li>
               <li>GStreamer 0.10</li>
-              <li>postr for Flickr export (optional)</li>
-              <li>f-spot for F-Spot export (optional)</li>
+              <li><a href="http://burtonini.com/blog/computers/postr";>postr</a> for Flickr export (optional)</li>
+              <li><a href="http://f-spot.org";>f-spot</a> for F-Spot export (optional)</li>
+              <li><a href="https://launchpad.net/nautilus-sendto";>nautilus-sendto</a> for improved export (optional)</li>
               <li>a webcam</li>
               <li>a brain</li>
             </ul>
-            <!--
             <p>
-            For a more detailed list of requirements, have a look at the 
-            <a href="http://live.gnome.org/Cheese/FAQ#head-4f22b89894cd849cab949b97f7fb8a81a8ca0d98";>FAQ</a>
+            For a more detailed list of requirements, have a look at the
+            <a href="http://svn.gnome.org/svn/cheese/trunk/README";>README file</a>
             </p>
-            -->
 
             <h2>Bugs</h2>
             <div class="iconl">
@@ -194,21 +193,6 @@
           <a href="download.html">Download it</a>
           (<a href="http://mail.gnome.org/archives/gnome-announce-list/2008-August/msg00056.html";>full release notes</a>)
 
-          <h3>August 5th 2008</h3>
-          <p>
-          <b>Unstable</b>
-          version 2.23.6 was released!
-          New in this release
-          </p>
-          <ul>
-            <li>add a fullscreen mode for kiosks</li>
-            <li>display a loading icon while generating thumbnail and a fallback icon if thumbnail fails</li>
-            <li>resolve sluggish video and out-of-sync audio</li>
-            <li>added/updated translations</li>
-          </ul>
-          <a href="download.html">Download it</a>
-          (<a href="http://mail.gnome.org/archives/gnome-announce-list/2008-August/msg00021.html";>full release notes</a>)
-
         </div>
       </div><!-- bottom -->
     </div><!-- body -->

Modified: trunk/www.gnome.org/projects/cheese/screenshots.html
==============================================================================
--- trunk/www.gnome.org/projects/cheese/screenshots.html	(original)
+++ trunk/www.gnome.org/projects/cheese/screenshots.html	Sun Sep 21 14:16:52 2008
@@ -43,6 +43,22 @@
 
       <div id="bottom">
 
+        <div class="screenshot" style="width:100%;">
+          <h2>Screenshots for 2.24.0</h2>
+          <a href="data/screenshots/cheese-2.24.0-main.jpg">
+            <img src="data/screenshots/cheese-2.24.0-main.jpg" alt="cheese 2.24.0" height="300px" />
+          </a>
+          <a href="data/screenshots/cheese-2.24.0-effects.jpg">
+            <img src="data/screenshots/cheese-2.24.0-effects.jpg" alt="cheese 2.24.0" height="300px" />
+          </a>
+          <a href="data/screenshots/cheese-2.24.0-countdown.jpg">
+            <img src="data/screenshots/cheese-2.24.0-countdown.jpg" alt="cheese 2.24.0" height="300px" />
+          </a>
+          <a href="data/screenshots/cheese-2.24.0-fullscreen.jpg">
+            <img src="data/screenshots/cheese-2.24.0-fullscreen.jpg" alt="cheese 2.24.0" height="300px" />
+          </a>
+        </div>
+
         <div class="screenshot">
           <h2>Screenshots for 2.22.0</h2>
           <a href="data/screenshots/cheese-2.22.0.jpg">

Modified: trunk/www.gnome.org/projects/cheese/tour.html
==============================================================================
--- trunk/www.gnome.org/projects/cheese/tour.html	(original)
+++ trunk/www.gnome.org/projects/cheese/tour.html	Sun Sep 21 14:16:52 2008
@@ -7,6 +7,21 @@
     <link rel="stylesheet" media="screen" href="data/themes/cheese/document.screen.css" title="Gnome"/>
 
     <meta name="description" content="Cheese" />
+
+
+   <link rel="stylesheet" media="all" href="data/shadowbox/css/shadowbox-light.css"/>
+    <script type="text/javascript" src="data/shadowbox/js/yui-utilities.js"></script>
+    <script type="text/javascript" src="data/shadowbox/js/shadowbox-yui.js"></script>
+    <script type="text/javascript" src="data/shadowbox/js/shadowbox.js"></script>
+    <script type="text/javascript"><!--
+    window.onload = function(){
+      var options = {
+        handleUnsupported:  'remove',
+        loadingImage:       'data/shadowbox/images/loading-light.gif'
+      };
+      Shadowbox.init(options);
+    };
+    --></script>
   </head>
   <body>
 
@@ -18,7 +33,6 @@
       <ul>
         <li class="current"><a href="index.html">Home</a>
         <ul>
-          <li><a href="screenshots.html">Screenshots</a> </li>
           <li><a href="tour.html">Tour</a> </li>
           <li><a href="download.html">Download</a> </li>
           <li><a href="http://live.gnome.org/Cheese/FAQ";>FAQ</a> </li>
@@ -33,17 +47,20 @@
 
       <div id="top">
         <!--  <a href="screenshots.html"> <img src="data/images/cheese-big.png" alt="cheese!"/></a> -->
-        <a href="tour.html"> <img src="data/images/cheese-tour.png" alt="cheese tour"/></a>
+        <!-- <a href="tour.html"> <img src="data/images/cheese-tour.png" alt="cheese tour"/></a> -->
+        <a href="tour.html"> <img src="data/images/cheese-2.24.png" alt="cheese tour"/></a>
       </div><!-- top -->
 
       <div id="bottom">
 
         <div id="left" style="padding-left: 1%;">
 
-          <div class="tour-item" style="min-height: 140px;">
+          <div class="tour-item">
             <h2>Cheese!</h2>
             <div class="imager">
-              <img src="data/tour/cheese-main.jpg" alt="icon" />
+              <a rel="shadowbox" href="data/screenshots/cheese-2.24.0-main.jpg">
+                <img src="data/tour/cheese-main.jpg" alt="icon" />
+              </a>
             </div>
             <p>
             Cheese is an program for the Gnome Desktop which allows you to take
@@ -55,10 +72,12 @@
             </p>
           </div>
 
-          <div class="tour-item">
+          <div class="tour-item" style="min-height: 275px;">
             <h2>Add Cheesy Effects</h2>
             <div class="imagel">
-              <img src="data/tour/cheese-effects.jpg" alt="icon" />
+              <a rel="shadowbox" href="data/screenshots/cheese-2.24.0-effects.jpg">
+                <img src="data/tour/cheese-effects.jpg" alt="icon" />
+              </a>
             </div>
             <p>
             Sick and tired of looking at the same face over and over again,
@@ -86,14 +105,34 @@
             </p>
           </div>
 
+          <div class="tour-item">
+            <h2>Kiosk/Fullscreen mode</h2>
+            <div class="imagel">
+              <a rel="shadowbox" href="data/screenshots/cheese-2.24.0-fullscreen.jpg">
+                <img src="data/tour/cheese-fullscreen.jpg" alt="icon" />
+              </a>
+            </div>
+            <p>
+            Did you ever want to set up a computer with Cheese on it in the
+            lobby of your office? Did you ever want to have Cheese running at a
+            party with a lot of people? This and much more is just a click
+            away: enter the fullscreen mode and enjoy Cheese on the whole
+            display! Attention: If you try this at a party, this can lead to
+            Cheese-affection, which means that everybody will be standing in front
+            of your webcam and not drinking your beer anymore ;)
+            </p>
+          </div>
+
         </div>
 
         <div id="right" style="padding-right: 1%;">
 
-          <div class="tour-item" style="min-height: 140px;">
+          <div class="tour-item">
             <h2>3... 2... 1... Cheese!</h2>
             <div class="imager">
+              <a rel="shadowbox" href="data/screenshots/cheese-2.24.0-countdown.jpg">
               <img src="data/tour/cheese-countdown.jpg" alt="icon" />
+              </a>
             </div>
             <p>
             The countdown widget will let you get into
@@ -108,21 +147,44 @@
           <div class="tour-item">
             <h2>Share your Photos and Videos</h2>
             <div class="imagel">
+              <a rel="shadowbox" href="data/screenshots/cheese-2.24.0-share.jpg">
               <img src="data/tour/cheese-share.jpg" alt="icon" />
+              </a>
             </div>
             <p>
-            Finished taking pictures and movies? Then go ahead and share your files to your
+            Finished taking photos and movies? Then go ahead and share your files to your
             friends and family! You can export them to F-Spot, put them on Flickr, mail
             them or use them as your account photo in GNOME. You can also save them to your
             disk to do anything you want with them, the possibilities are endless.
+            With nautilus-sendto installed, you even have further
+            possibilieties to share your photos and movies!
             Cheese makes it super easy to share yor photos and videos.
             </p>
           </div>
 
+          <div class="tour-item" style="min-height: 291px;">
+            <h2>Addicted to webcams?</h2>
+            <div class="imagel">
+              <img src="data/tour/cheese-prefs.jpg" alt="icon" />
+            </div>
+            <p>
+            You have several webcams? You can't stop taking photos of yourself
+            and your friends? The only reason you have USB-Ports is to attach
+            Webcams?<br/>
+            With Cheese 2.24, you now can switch between your installed webcams
+            with just one click! Just open the shiny new preference dialog and
+            choose your favoured webcam. You can also set the resolution of
+            your webcam there! So, get all your webcams out of your locker,
+            attach them to your computer and play with them!
+            </p>
+          </div>
+
           <div class="tour-item">
             <h2>Endless Possibilities</h2>
             <div class="imager">
-              <img src="data/tour/cheese-about.jpg" alt="icon" />
+              <a rel="shadowbox" href="data/screenshots/cheese-2.24.0-countdown.jpg">
+                <img src="data/tour/cheese-about.jpg" alt="icon" />
+              </a>
             </div>
             <p>
             Don't stop there, find out what you can do with Cheese today! Install
@@ -133,7 +195,7 @@
             </p>
           </div>
 
-          <div style="position: absolute; right: 1em; margin-top: 30px; font-size: 0.85em; font-style: italic;">
+          <div style="position: absolute; right: 1em; margin-top: 105px; font-size: 0.85em; font-style: italic;">
             Text by Joshua Henderson and daniel g. siegel
           </div>
         </div>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]