// begin the slider object
var slider = {
    required: ["windowWidth", "windowHeight"],
    itemList: [],
    slList: [],

    create: function(SL, id) {
                if (!slider.checkBrowser(id)) return;

                // assign the variables to the list
                slider.slList[id] = SL;

                // check to make sure we have everything we need
                if (!slider.hasRequired(id)) {
                    return;
                }

                slider.main(id);
    },

    checkBrowser: function(id) {
                // check to make sure the browser has the basics
                if (!document.getElementsByTagName ||
                    !document.getElementById) {
                    return false;
                } else {
                    return true;
                }
    },

    main: function(id) {
                // set the visibility of this guy to hidden
                var _s = document.getElementById(id);
                _s.style.visibility = "hidden";

                // compute the new width of the slider, keeping track of
                // the width of each item so that we can reference that later
                var _w = slider.computeWidth(id, _s);
                _s.style.width = _w + "px";

                // add a window for this slider
                slider.createWindow(id, _s);

                // with the window created, let's unhide the slider's
                // elements
                _s.style.visibility = "visible";

                // check to see if the total container width is less than 
                // or equal to the window width, and if so, just leave now
                // without doing anything
                if (_w <= parseInt(slider.slList[id]["windowWidth"])) {
                    return;
                }

                // assign all necessary styles to the slider element
                slider.assignStyles(_s);

                // add links to either side of the slider to act as scrollers
                slider.addScrollLinks(id, _s);
    },

    createWindow: function(id, el) {
                var _w = document.createElement("div");
                _w.setAttribute("id", id + "-window");

                // assign width and height of window based on required
                // variables
                _w.style.width = slider.slList[id]["windowWidth"];
                _w.style.height = slider.slList[id]["windowHeight"];

                // add this window as a child of the parent node, and then
                // move the slider as a child of this new window
                el.parentNode.insertBefore(_w, el);
                _w.appendChild(el);
    },

    computeWidth: function(id, el) {
                // set up the array of item widths
                slider.itemList[id] = [];
                var _ew = 0;

                // first get all the children nodes in the designated
                // slider element
                var _c = el.childNodes;
                var _d = [];
                var _dinc = 0;
                var _l = 0;

                // get a listing of all the node types that we care about
                for (var i=0; i<_c.length; i++) {
                    if (_c[i].nodeType == 1) {
                        _d[_dinc] = _c[i];
                        _dinc++;
                    }
                }

                // loop through all these useful elements
                for (var i=0; i<_d.length; i++) {

                    // reset margin left on the first node to zero
                    if (i == 0) {
                        _d[i].style.marginLeft = "0px";
                    }

                    // current node
                    var _nl = slider.getNodeOffset(_d[i]);

                    if (i != _d.length-1) {
                        // next node
                        var _nnl = slider.getNodeOffset(_d[i+1]);

                        // distance between two nodes (margins only)
                        var _co = _nnl - _nl - _d[i].offsetWidth;

                        if (i == 0) {
                            _l = _nl + _co + _d[i].offsetWidth;
                        } else {
                            _l += _co + _d[i].offsetWidth;
                        }

                        // now let's calculate the true width of the element
                        // and assign it to the itemList array
                        if (i == 0) {
                            _ew = _d[i].offsetWidth + _nl;
                        } else {
                            // we need to fix the width of the first
                            // item, since we don't know what the right
                            // margin is
                            if (i == 1) {
                                slider.itemList[id][0] =
                                    slider.itemList[id][0] + (_co - _nl);
                            }

                            _ew = _d[i].offsetWidth + _co;
                        }

                        slider.itemList[id][i] = _ew;

                        // set the item to display: none to avoid wrapping
                        _d[i].style.display = "none";
                    } else {
                        // only one node left
                        _l += _d[i].offsetWidth;

                        // set last margin to zero
                        _d[i].style.marginRight = "0px";

                        // add the width
                        _ew = _d[i].offsetWidth + _nl;
                        slider.itemList[id][i] = _ew;
                    }
                }

                // done calculating, so make everything display as normal
                for (var i=0; i<_d.length; i++) {
                    _d[i].style.display = "";
                }

                return _l;
    },

    getNodeOffset: function(el) {
                // in all later browsers, in standards-compliance mode,
                // the parentOffset is the BODY tag
                var _l = el.offsetLeft;
                var _pol = el.parentNode.offsetLeft;
                _l -= _pol;
                return _l;
    },

    assignStyles: function(el) {
                // just remove all padding, margins and borders from the
                // slider element
                el.style.paddingLeft = "0px";
                el.style.paddingRight = "0px";
                el.style.marginLeft = "0px";
                el.style.marginRight = "0px";
                el.style.borderLeftWidth = "0px";
                el.style.borderRightWidth = "0px";

                // we need to assign a relative position to the slider
                // element as well
                el.style.position = "relative";
    },

    addScrollLinks: function(id, el) {
                // first create a wrapper div to encompass the whole thing
                var _wr = document.createElement("div");
                _wr.setAttribute("id", id + "-wrapper");

                // left scroller
                var _l = document.createElement("div");
                _l.className = "slide-scroller";
                var _ll = document.createElement("a");
                _ll.setAttribute("href", ".");
                _ll.setAttribute("id", id + "-scroll-left");

                _ll.onclick = function() {
                    slider.assignMoveHandler(el, this.getAttribute("id"));
                    return false;
                }

                var _llt = document.createTextNode("Left");
                _ll.appendChild(_llt);
                _l.appendChild(_ll);

                // right scroller
                var _r = document.createElement("div");
                _r.className = "slide-scroller";
                var _rl = document.createElement("a");
                _rl.setAttribute("href", ".");
                _rl.setAttribute("id", id + "-scroll-right");

                _rl.onclick = function() {
                    slider.assignMoveHandler(el, this.getAttribute("id"));
                    return false;
                }

                var _rlt = document.createTextNode("Right");
                _rl.appendChild(_rlt);
                _r.appendChild(_rl);

                // add this wrapper as a child of the parent node, and then
                // move everything else into this wrapper
                var _w = document.getElementById(id + "-window");
                _w.parentNode.insertBefore(_wr, _w);
                _wr.appendChild(_l);
                _wr.appendChild(_w);
                _wr.appendChild(_r);
    },

    assignMoveHandler: function(el, scrollId) {
                // using the ID of the link, find out which element we are
                // trying to slide
                var _e = scrollId.split("-");
                var _ei = _e[0];
                var _d = _e[2];

                // check direction and move appropriately
                var _m = slider.calculateMove(_ei, el, _d);
                slider.moveElement(_ei, _m);
    },

    calculateMove: function(id, el, dir) {
                var _dist = 0;

                // calculate based on direction and distance what the
                // new x value will be for the container
                if (!el.style.left) {
                    el.style.left = "0px";
                }

                var xpos = parseInt(el.style.left);

                // we need to find out what the amount of space to the left
                // is to add to the window width
                // var _so = slider.getNodeOffset(document.getElementById(id));
                var _so = xpos;

                if (_so == 0 && dir == 'left') {
                    // no place to go!
                    return 0;
                }

                // let's find out how many elements have been scrolled 
                // through right now
                var _items = 0;
                var _spill = false;
                var _spillNoVis = 0;

                if (dir == 'right') {
                    var _sum =
                        parseInt(slider.slList[id]["windowWidth"]) - _so;
                } else {
                    var _sum = _so;
                }

                if (dir == 'right') {
                    while (_sum > 0) {
                        _sum = _sum - slider.itemList[id][_items];
                        _items++;

                        // is the last item partially visible?
                        if (_sum < 0) {
                            _spill = true;
                            _spillNoVis = -1 * _sum;
                        }
                    }
                } else {
                    while (_sum < 0) {
                        _sum = _sum + slider.itemList[id][_items];
                        _items++;

                        // is the last item partially visible?
                        if (_sum > 0) {
                            _spill = true;
                            _spillNoVis = slider.itemList[id][_items-1] - _sum;
                        }
                    }
                }

                // let's move over either one item, or whatever spill there
                // was from the last cutoff visible item, unless we are at the
                // last item, in which case we don't move at all
                if (_spill) {
                    _dist = _spillNoVis;
                } else if (_items == slider.itemList[id].length)  {
                    _dist = 0;
                } else {
                    if (dir == 'right') {
                        _dist = slider.itemList[id][_items];
                    } else {
                        _dist = slider.itemList[id][_items-1];
                    }
                }

                if (dir == 'right') {
                    xpos = xpos - _dist;
                } else {
                    xpos = xpos + _dist;
                }

                return xpos;
    },

    moveElement: function(id, max_x) {

                // This function is adapted from the moveElement function
                // from Jeremy Keith's book, DOM Scripting by Friends of ED
                var _el = document.getElementById(id);

                if (_el.movement) {
                    clearTimeout(_el.movement);
                }

                if (!_el.style.left) {
                    _el.style.left = "0px";
                }

                var xpos = parseInt(_el.style.left);

                if (xpos == max_x) {
                    return true;
                }

                if (xpos < max_x) {
                    var dist = Math.ceil((max_x - xpos)/10);
                    xpos = xpos + dist;
                }

                if (xpos > max_x) {
                    var dist = Math.ceil((xpos - max_x)/10);
                    xpos = xpos - dist;
                }

                _el.style.left = xpos + "px";

                var repeat = "slider.moveElement('" + id + "', " + max_x + ")"; 
                _el.movement = setTimeout(repeat, 10);
    },

    hasRequired: function(id) {
                // loop through all required items, checking to see if they
                // are in the list
                var _len = slider.required.length;
                for (var i=0; i<_len; i++) {
                    if (typeof slider.slList[id][slider.required[i]] ==
                        "undefined") {
                        return false;
                    }
                }

                return true;
    }
};
