/**-----------------------------------------------------------------------------
 * Imagery's slideshow.
 * (C) 2006 AKS <aksus-69@yandex.ru>
 * Thanks to all of members of dklab forum for wasting their time on me ;)
 *
 * This code is free software, so you can redistribute it and/or
 * modify it (even eat) under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation. 
 * See http://www.gnu.org/copyleft/lesser.html (or inclusion of this package).
 *
 * This code is distributed 'cause it may be useful, but WITHOUT ANY WARRANTY!!!
 *
 *------------------------------------------------------------------------------/

/**
 * applyHandler
 *
 * It's just a wrapper for standard methods of registration of event listeners
 *
 * @scope public
 * @param {Object} Pointer to the object that will be event target
 * @param {String}or{Array} String or Array of two strings that specifies the standard events
 * @param {Function} Pointer to the function that supposed to be event listener
 * @returns {Function} Returns one of the specific method of registration of event listeners on 
 *   the event target, if browser doesn't support one of these methods, returns false
 */

function applyHandler(o, e, f) { 
  e = (e instanceof Array) ? (arguments.callee(o, e[1], f), e[0]) : e; 
  return (o.attachEvent) ? o.attachEvent(e, f) : (o.addEventListener) ? 
    o.addEventListener(e.substr(2), f, false) : false;
}

/**
 * initScroller 
 * 
 * Initializes all objects this program needs
 * Creates some important properties (see comments below)
 *   Note: these properties are public and applied straight off to DOM nodes, 
 *         avoid using the same names in another scenario for the same page!!!
 *
 * @scope public
 * @see applyHandler
 * @returns {Function} Returns method to add an event listener(s)
 */
 
function initScroller() { 

/**
 * c
 * 
 * @type {Object} Pointer to a 'control' object
 */

  var c = document.getElementById('control2'), 

/**
 * s 
 * 
 * @type {Object} Pointer to a 'scroller' object
 *   Note: also it'll be available in a scroll_obj property of the 'control' object (c)
 */

  s = document.getElementById('scroller2'); 

/** 
 * back_control
 *
 * @type {Object} Pointer to the object that is considered as back scroll switcher 
 *   Actually it's a <span> which contains 'back' text (later just <span>back)
 */

  c.back_control = c.getElementsByTagName('span')[0];

/**
 * scroll_position 
 * 
 * @type {Number} Provides a digital value (in pixels) for positioning the 'scroller' object
 *  (by default it's zero)
 * 
 * scroll_active
 * 
 * @type {Boolean} Indicates which one of the events fires on the 'control' object
 *   mouseover - it'll be true
 *   mouseout - false
 */
 
  (c.scroll_obj = s).scroll_position = s.scroll_active = 0; 

/**
 * scroll_range
 * 
 * @type {Number} Digital value (in pixels) that determines the maximum scrolling range
 */

  s.scroll_range = s.offsetWidth - s.parentNode.offsetWidth;
  return applyHandler(c, ['onmouseover', 'onmouseout'], scrollControl);
}

/**
 * scrollControl
 *
 * Initializes the only target that is needed for call scrollProcess function
 * 
 * @scope public
 * @param {Object} Pointer to the event object that fires on the 'control' object
 * @see scrollProcess
 * @returns {Function}or{Boolean} Returns scrollProcess function or false
 */

function scrollControl(e) {

 /**
  * Get the target of the event
  */

  var el = (e = e || event).target || e.srcElement,

 /**
  * Get the tag name of the target
  */

  t = el.tagName.toLowerCase(), p, b; 

 /**
  * Go on if only the target's tag name is 'span'
  */

  if(t == 'span') { 

   /**
    * Get the pointer to the 'scroller' object
    */

    p = el.parentNode.scroll_obj;

   /** 
    * The next operation requires a bit of explanation:
    * 
    *   When a mouseover event fires on the target then the property of the 'scroller' scroll_active will 
    *     be true and it'll cause the function named scrollProcess to be call
    *   scrollProcess'll deal with b (boolean) that could be true (if target is <span>back) 
    *     or false (if target is <span>forward)
    *
    *   In other case (mouseout event) this operation returns false
    */

    return (p.scroll_active = !p.scroll_active) ? 
      (b = (el == el.parentNode.back_control), scrollProcess(p, b)) : false;
  }
  else return false;
}

/**
 * scrollProcess
 * 
 * The method that operates with an attitude of the 'scroller' object.
 * 
 * @scope public
 * @param {Object} Pointer to the object ('scroller') that intended to be moved
 * @param {Boolean} Boolean value that indicates the direction of movement
 * @returns {Number}or{Boolean} Returns timeout for call scrollProcess function recursively or false
 */
 
function scrollProcess(o, b) {

 /**
  * Create a pointer to the scroll_position property of the 'scroller'.
  * Applied to avoid of several look-ups for this property in local scope.
  */

  var p = o.scroll_position;

 /**
  * The next operation requires a bit of explanation:
  * 
  *   The scroll_position value depends on a few conditions: 
  *
  *     If the 'scroller' moves forward (b == false) and reaches no limit (scroll_range)
  *       then it's value will be decreased by 5px
  *     Note: 'forward' is just a visual performance of the movement
  *       Indeed we move 'scroller's' left corner to the left and it's left position value 
  *       grows in negative dimention until it's bigger then negative scroll_range!!!
  *
  *     If the 'scroller' moves back (b == true) and it's position still remains 
  *       lesser than zero, it's value will be increased by 5px.
  * 
  *     In other case the scroll_active property will be false, indicating that scrolling process is done
  *       Value of the scroll_position property will set to default or will be left as it is (it depends on b)
  */ 
  
  o.scroll_position = (!b && p > -o.scroll_range) ? p - 5 : 
    (b && p < 0) ? p + 5 : (o.scroll_active = 0, b) ? 0 : p;

 /**
  * Set position of the left corner of the 'scroller' object
  */

  o.style.left = o.scroll_position + 'px';
 
 /** 
  * If scrolling process is active, executes scrollProcess function after delay
  *   or returns false
  */

  return (o.scroll_active) ? window.setTimeout(function() {
    return scrollProcess(o, b); }, 10) : false; 
}

/**
 * Call applyHandler function to add an event listener for onload event of the window
 */

applyHandler(window, 'onload', initScroller);
applyHandler(window, 'resize', initScroller);