var togBasket = {
    // namespace wrapper for the shopping basket
    contents: Cookie.read("basket"),
    add: function(product, version, qtty) {
        // add a product to basket
        if (this.contents !== false) {
            // basket has items?
            var basketItems = this.contents.split(","), newBasket = '';

            for (ii = 0; ii < basketItems.length-1; ii++)
                newBasket += basketItems[ii] + ',';

            // already in there?
            if (!basketItems.toString().contains(product + "-" + version + "-"))
                this.contents = product + "-" + version + "-" + qtty + "," + this.contents;
        }
        else {
            // make a new one
            this.contents = product + "-" + version + "-" + qtty + ",";
        }

        // save this
        this.freshen();
        return this;
    },
    freshen: function() {
        // commit to cookie
        Cookie.dispose("basket");
        Cookie.set("basket", this.contents, {path: "/", duration: 365});
        return this;
    },
    remove: function(product, version, qtty) {
        // remove an exact product from basket
        this.contents = this.contents.replace(product + "-" + version + "-" + qtty + ",", "");
        this.freshen();
        return this;
    }
};

var mooPlaceholder = new Class({
    // behaviour for default values of inputs class
    Implements: [Options],
    options: {
        // default options
        htmlPlaceholder: "placeholder",
        // the element attribute, eg, data-placeholder="MM/YY" -> "data-placeholder"
        unmoddedClass: "unchanged",
        // apply a class to the unmodded input, say, to grey it out
        parentNode: document,
        // limit to a particular set of child nodes
        defaultSelector: "input[placeholder]"
    }, initialize: function (options) {
        this.setOptions(options);
        this.nativeSupport = 'placeholder' in document.createElement('input');
    }, attachToElements: function (selector) {
        // basic function example that uses a class selector to
        var inputs = this.options.parentNode.getElements(selector || this.options.defaultSelector);
        if (inputs.length) {
            inputs.each(function (el) {
                this.attachEvents(el);
            }, this);
        }
    }, // end attachToElements
    attachEvents: function (el, placeholder) {
        // method that attaches the events to an input element.
        var placeholder = placeholder || el.get(this.options.htmlPlaceholder);
        if (this.nativeSupport || !$(el) || !placeholder || !placeholder.length) return;
        el.set("value", placeholder).store("placeholder", placeholder);
        // append unmodded class to input at start
        if (this.options.unmoddedClass) el.addClass(this.options.unmoddedClass);
        // now cater for the events
        el.addEvents({
            change: function () {
                // when value changes
                var value = el.get("value").trim(),
                    placeholder = el.retrieve("placeholder");
                if (value != placeholder) {
                    // once it changes, remove this check and remove the unmoddedClass
                    el.removeClass(this.options.unmoddedClass).removeEvents("change");
                }
            }.bind(this),
            focus: function () {
                var value = el.get("value").trim(),
                    placeholder = el.retrieve("placeholder");
                if (value == placeholder) {
                    el.set("value", "").removeClass(this.options.unmoddedClass);
                }
            }.bind(this),
            blur: function () {
                var value = el.get("value").trim(),
                    placeholder = el.retrieve("placeholder");
                if (value == placeholder || value == "") {
                    el.set("value", placeholder).addClass(this.options.unmoddedClass);
                }
            }.bind(this)
        });
    }
});

var Scroller;

(function() {
    // scroller closure.
var moveTimer, moveStatus = false, prdScrolling = false, productScroll;
Scroller = new Class({
    images: [],
    options: {
        cats: [],
        productContainer: $empty(),
        totalProducts: 0,
        moveDelay: 10,
        moveSteps: 5,
        moveDirection: "Right",
        productToScrollTo: $empty(),
        arrowLeft: $empty(),
        arrowRight: $empty(),
        product_: $empty(),
        loadedImages: [],
        startCoords: {
            left: 0,
            top: 0
        }
    },
    Implements: [Options, Events],
    initialize: function(options) {
        this.setOptions(options);
        this.element = this.get("productContainer").setStyle("opacity", "0");

        this.products = this.options.products.getChildren();

        this.set("totalProducts", this.products.length);
        this.getData();
        this.attach();
    },
    getData: function() {
        this.products.each(function(el) {
            var foo = {};
            var link = el.getFirst();
            if (link) {
                foo.image = el.get("data-thumb");
                foo.url = link.get("href");
                foo.title = link.get("text");
                foo.price = el.getLast().get("html");
                foo.brand = el.get("data-brand");
                this.images.push(foo);
            }
        }, this);

    },
    attach: function() {
        this.loadImages();
        this.setEvents();
    },
    set: function() {
        // internal setter for options that can take a json or a simple pair
        switch ($type(arguments[0])) {
            case "object":
                this.setOptions(arguments[0]);
            break;
            default:
                if (arguments.length == 2) {
                    var newo = {}
                        newo[arguments[0]] = arguments[1];

                    this.setOptions(newo);
                } else {
                    C.log("incorrect number of arguments");
                }
            break;
            case "false":
                return false;
            break;
        }
    },
    get: function(key) {
        // this.options getter, 1.2 stylee...
        return this.options[key];
    },
    goToProduct: function(i) {
        // go to product with index i.
        prdScrolling = true; // added to recall productScrolling state due to window.scroll

        window.addEvent("scroll", function() {
            if (prdScrolling) {
                // need a fix, if window.scroll fires, it stops the instance of our Fx.Scroll (productScroll)

                // go w/o
                this.element.scrollTo(this.get("moveSteps")*i);
                this.element.setStyle("opacity", 1);
                this.setButtons(); // fix scrolling left/right buttons as per scroll state
                moveStatus = false;
                prdScrolling = false;
            }
        }.bind(this));

        productScroll = new Fx.Scroll(this.get("productContainer"), {
            transition: Fx.Transitions.Elastic.easeOut,
            duration: 1500,
            wait: true,
            onComplete: function() {
                moveStatus = false;
                prdScrolling = false;
                this.element.setStyle("opacity", 1);
                this.setButtons();
            }.bind(this)
        });

        var el = this.element.getSize2();

        moveStatus = true;
        productScroll.start(el.scroll.x+this.get("moveSteps")*i, 0);
    },
    setButtons: function() {
        var el = this.get("productContainer").getSize2();
        if (this.get("totalProducts") <= 10) {
            this.get("arrowRight").set("src", "/img/scroll-right-off.jpg");
            this.get("arrowLeft").set("src", "/img/scroll-left-off.jpg");
            return false;
        }
        if ((el.scroll.x + el.size.x)>= el.scrollSize.x - 1) {
            this.get("arrowRight").set("src", "/img/scroll-right-off.jpg");
        }
        else {
            this.get("arrowRight").set("src", "/img/scroll-right.jpg");
        }

        if (el.scroll.x <= 0) {
            this.get("arrowLeft").set("src", "/img/scroll-left-off.jpg");
        }
        else {
            this.get("arrowLeft").set("src", "/img/scroll-left.jpg");
        }
    },
    move: function(fn) {

        if (moveStatus)
            return false;

        var _this = this;
        productScroll = new Fx.Scroll(this.get("productContainer"), {
            offset: {
                x:0,
                y:0
            },
            transition: Fx.Transitions.Cubic.easeOut,
            duration: this.get("moveDelay"),
            onComplete: function() {
                moveStatus = false;
                _this.get("productContainer").setStyle("opacity", 1);
                _this.setButtons();
                if (fn)
                    fn.pass(this)();
            }
        });
        var el = this.get("productContainer").getSize2();
        if (this.get("moveDirection") == "Right") {
            if ((el.scroll.x + el.size.x)>= el.scrollSize.x - 1) {
                $clear(moveTimer);
                this.get("arrowRight").set("src", "/img/scroll-right-off.jpg");
                return;
            }
            this.get("productContainer").setStyle("opacity", .8);

            moveStatus = true;
            productScroll.start(el.scroll.x+this.get("moveSteps"), 0);

        }
        else {
            var el = this.get("productContainer").getSize2();
            if (el.scroll.x <= 0) {
                $clear(moveTimer);
                this.get("arrowLeft").set("src", "/img/scroll-left-off.jpg");
                return;
            }
            this.get("productContainer").setStyle("opacity", .8);

            moveStatus = true;
            productScroll.start(el.scroll.x-this.get("moveSteps"), 0);
        }

    }, // end mover
    stop: function() {
        $clear(moveTimer);
    },
    moveResume: function() {
        if ($("zoomer"))
            $("zoomer").fade(1,0);
        if (this.get("totalProducts") <= 10)
            return;
        moveTimer = (function() {
            if (moveStatus == false)
                this.move();
        }).periodical(this.get("moveDelay"), this);
    },
    loadImages: function() {
        // pre-load them
        var _this = this;
        this.get("product_").empty();
        this.images.each(function(im, c) {
            // need to make a containing layer.
            if (im.url == "") return;

            var prod_layer = new Element('div', {
                "class": "scrollImage curImage",
                styles: {
                    "text-align": "center",
                    float: "left",
                    opacity: 1,
                    width: 78,
                    height: 84,
                    padding: 2,
                    "margin-right": 1,
                    border: (im.url == "#") ? "1px solid #c6d9d3" : "1px solid #fff",
                    background: (im.url == "#") ? "#fff url(/img/prodScrollCurrent.gif) repeat-x bottom left" : "#fff url(/img/tiny_red.gif) no-repeat center center"
                }
            }).inject(_this.get("product_")); // add to dom within the product_ object

            if (im.url != "#") {
                prod_layer.addEvent("click", function() {
                    window.location.href = im.url;
                }); // addEvent etc.
            }
            else {
                _this.set("productToScrollTo", c);
                prod_layer.removeClass("curImage");
            }

            new Asset.image(im.image, {
                title: im.title,
                onload: function(img) {
                    if (!img.width) {
                        img = new Asset.image("/img/noimageyet.gif").setStyles({height: 70, width: 70});
                    }
                    img.inject(prod_layer);

                    this.addProdEvents(prod_layer, im, img);


                }.bind(this)
            }).setStyles({height: 70, width: 70});
        }, this); // each
    },
    addProdEvents: function(prod_layer, im, thumb) {
        var _this = this;

        new Element("div").set("html", "<div style='text-align: center; font-weight: bold;'>" +im.price+"</div>").inject(prod_layer);

        var mytime, showtime;

        prod_layer.addEvents({
            mouseenter: function() {
                var __this = this;
                $clear(mytime);
                $clear(showtime);
                if (moveStatus)
                    return false;

                showtime = (function() {
                    _this.set("mouseOverDelay", 200);
                    if ($("zoomer")) {
                        $("zoomer").destroy();
                    }
                    var coords = __this.getPosition();
                    var parentScroll = _this.get("productContainer").getScroll();

                    var newCoordinates = {
                        left: (_this.get("startCoords").left == 0) ? coords.x - 36 : _this.get("startCoords").left,
                        top: coords.y - 36,
                        newLeft: coords.x - parentScroll.x - 36
                    };

                    var zoomer = new Element("div", {
                        id: "zoomer",
                        "class": "shadowy",
                        styles: {
                            left: newCoordinates.left,
                            top: newCoordinates.top,
                            opacity: .5
                        },
                        events: {
                            mouseleave: function() {
                                startCoords = this.getCoordinates();
                                mytime = (function() {
                                    _this.set("startCoords", {
                                        left: 0
                                    });
                                }).delay(500);
                                this.dispose();
                                _this.zoomed = false;
                                if ($("wheeltip"))
                                    this.tipaway();
                            },
                            mouseenter: function() {
                                _this.zoomed = true;
                                if (!_this.get("shown") && _this.images.length > 10) {
                                    /*this.tooltip("You can use your mousewheel to scroll between different products", {
                                        delay: 5000,
                                        topOffset: 82,
                                        id: "wheeltip",
                                        opacity: 1
                                    });*/
                                    _this.set("shown", true);
                                }
                            },
                            mousewheel: function(e) {
                                var e = new Event(e).stop();

                                _this.set("moveDirection", (e.wheel >= 0) ? "Left" : "Right");
                                _this.move((function() {
                                    this.dispose();
                                    _this.set("mouseOverDelay", 0);
                                }).bind(this));
                            }
                        }
                    }).adopt(thumb.clone().addClass((im.url != "#") ? "curImage" : "").setStyles({height: 129, width: 129}).addEvents({
                        click: function() {
                            prod_layer.fireEvent("click");
                        }
                    })).inject(document.body).fade(.5, 1, {remove: false});


                    if (_this.get("startCoords").left != 0) {
                        var adjust = new Fx.Style(zoomer, "left", {duration: 300, transition: Fx.Transitions.Expo.easeOut});
                        adjust.start(newCoordinates.left, newCoordinates.newLeft);
                    }

                    new Element("div").setStyles({"text-align": "center", "font-size": "10px"}).set("html", "<a href='"+im.url+"'>"+im.title+"</a><br /><span style='color: #C11A2C'>"+im.price+"</span>").inject(zoomer);
                }).delay(_this.get("mouseOverDelay"));

                // showtime();
            },
            mouseleave: function() {
                $clear(showtime);
            }
        });


        // load has completed, show the layer
        this.get("productContainer").setStyle("visibility", "visible");

        this.setButtons();
        var fx = new Fx.Styles(this.get("productContainer"), {duration: 500}).start({opacity: 1});

        // if not in view, we need to go there...
        // where?
        if (this.get("productToScrollTo") < this.get("totalProducts") || this.get("productToScrollTo") >= 10) {
            this.goToProduct(this.get("productToScrollTo") - 4);
        }
        else {
            this.set("productToScrollTo", 0);
            this.element.setStyle("opacity", 1);

            this.goToProduct(0);
        }

    }, // end loadImages
    setEvents: function() {
        // define events for arrows and the likes.
        var _this = this;
        this.get("arrowRight").addEvents({
            mouseenter: function() {
                _this.set("moveDirection", "Right");
                _this.moveResume();
            },
            mouseleave: function() {
                _this.stop();
            }
        });

        this.get("arrowLeft").addEvents({
            mouseenter: function() {
                _this.set("moveDirection", "Left");
                _this.moveResume();
            },
            mouseleave: function() {
                _this.stop();
            }
        });


    } // end setEvents
}); // end togs_scroller
})();


var Form = {
    // wrapper class for form element values
    getValue: function(name) {
        if ($type(name) == "object")
            return name.get("value");

        var elems = $$('input[name='+name+'], select[name='+name+'], textarea[name='+name+']');
        var value = false;
        elems.each(function(el) {
            if ($(el).get("value")) {
                value = $(el).get("value");
            }
        });
        return value;
    },
    setValue: function(name, value) {
        if ($type(name) == "object")
            name.set("value", value);

        var elems = $$('input[name='+name+'], select[name='+name+'], textarea[name='+name+']');
        elems.each(function(el) {
            if (value != false)
                $(el).set("value", value);
        });
    }
};



$F = Form.getValue;
$f = Form.setValue;

var Empty = {
    // wrapper class for element innerHTML emptying workaround for IE
    doEmpty: function(obj) {
        if ($type(obj) == false)
            return false;

        if (!Browser.Engine.trident) {
            obj.empty();
        }
        else {
            obj.setStyles({"display": "inline", "float": "left", "margin": "0px"}).empty();
        }
    }
}

$empty = Empty.doEmpty;

var AjaxLoader = new Class({
    options: {
        zIndex: 1000000,
        loaderImage: "/img/ajax-loader.gif",
        background: "#fff",
        opacity: .7,
        loaderLeft: "center",
        loaderTop: "center",
        loaderAutoTop: true,
        loaderAutoTopMargin: "140px"
    },
    Implements: [Options, Events],
    initialize: function(options) {
        this.setOptions(options);
        new Asset.image(this.options.loaderImage); // cache it.
    },
    make: function(el) {
        this.element = $(el);
        this.coords = this.element.getCoordinates();
        if (this.options.loaderAutoTop === true)
            this.options.loaderTop = (this.coords.height > 434) ? this.options.loaderAutoTopMargin : "center";

        this.loader = new Element("div").setStyles($merge({
            position: "absolute",
            zIndex: this.options.zIndex,
            opacity: this.options.opacity,
            background: this.options.background + " url(" + this.options.loaderImage + ") no-repeat " + this.options.loaderLeft + " " + this.options.loaderTop
        }, this.coords)).inject($(document.body));

        el.loader = this.loader;
    },
    remove: function() {
        if (this.loader)
            this.loader.dispose();
    },
    removeFromElement: function(el) {
        if (el.loader)
            el.loader.dispose();
    }
});



var winSizes = {};
var menuEvents = function() {
    if ($("SC")) {
        $("SC").addEvent("click", function(e) {
            new Event(e).stop();
            ShowCategories();
        });
    }

    if ($("PC")) {
        $("PC").addEvent("click", function(e) {
            new Event(e).stop();
            ShowPage();
        });
    }

    var searchField = $("searchfield");
    if (searchField) {
         searchField.addEvents({
            "focus": function() {
                if (this.get("value") == 'Type your search here...') {
                    this.set("value", '').setStyle('fontStyle', 'normal');
                }
            },
            click: function() {
                if (this.get("value") == 'Type your search here...') {
                    this.set("value", '').setStyle('fontStyle', 'normal');
                }
            }
         });

         $("searchButton").addEvents({

            "click": function() {
                if (searchField.get("value").length) {
                     if (searchField.get("value") == 'Type your search here...' || searchField.get("value").trim() == '') {
                         simpleBubble(searchField, "Please type<br />keywords here");
                         searchField.set("value", "").fireEvent("focus");

                         return false;
                     }

                     $("searchForm").submit();
                } else {
                     return false;
                }
            }
        }).addClass("curImage");

        var completer = new Autocompleter.Ajax.Json(searchField, "/searchAjax.php", {
            customTarget: $("searchSuggest"),
            ajaxOptions: {
                "method": "get"
            },
            "minLength": 3,
            'postVar': 'q',
            'onRequest': function(el) {
                searchField.addClass("search_ing");
            },
            'onComplete': function(el) {
                searchField.removeClass("search_ing");
            },
            "onSelect": function(el, choice) {
                var choiceURL = choice.get("rel");

                if (choiceURL)
                if (choiceURL.length) {
                    toggleModal("#fff");
                    window.location.href = choiceURL;
                    return false;
                }

                $("searchButton").fireEvent("click");

            }
        });

        if (Browser.Engine.trident4 && $("main")) {
            var sorter = $("main").getElement("div.sorter");

            if (sorter)
            sorter.setStyles({
                "float": "left",
                "margin-left": 10
            });
        }

    }

    var knobRail = document.id("knobRail");
    if (knobRail) {
        (function() {
            var rangeData = JSON.decode(knobRail.get("data-pos"));
            var range = [rangeData.min.toInt(), rangeData.max.toInt()];
            var start = [knobRail.getFirst().get("data-pos").toInt(), knobRail.getLast().get("data-pos").toInt()];
            var allowSubmit = false;
            document.getElements("div.knobs").set("title", "Drag slider to adjust");


            var moneyEls = {
                min: document.id('minMoney'),
                max: document.id('maxMoney')
            };

            var showMoney = function(min, max) {
                moneyEls.min.set("html", "&pound;" + min);
                moneyEls.max.set("html", "&pound;" + max);
            };

            new DoubleSlider(knobRail, {
                range: range,
                start: start,
                onChange: function(pos) {
                    allowSubmit = true;
                    showMoney(pos.knob_left, pos.knob_right);
                },
                onComplete: function(pos) {
                    $data = {
                        a: "applyPriceFilter",
                        t: $("priceHeading").get("data-type"),
                        min: pos.knob_left,
                        max: pos.knob_right,
                        filters: knobRail.get("data-filters"),
                        price: (pos.knob_left == rangeData.min && pos.knob_right == rangeData.max) ? false : true
                    };

                    ajl.make(document.id("main"));

                    new Request({
                        url: "/accountAjax.php",
                        method: "get",
                        data: $data,
                        onComplete: function() {
                             window.location.href = this.response.text;
                        }
                    }).send();

                }
            });

            showMoney(start[0], start[1]);
        })();
    }

    if ($("priceHeading")) {
        $("priceHeading").addEvents({
            click: function(e) {
                new Event(e).stop();

                if (this.hasClass("catChoiceOn"))
                    return false;

                this.addClass("catChoiceOn");

                ajl.make($("main"));
                window.location.href = this.get("data-any");
            }
        });

    }
};


// sex icons
var icons = ["/img/icons/male.gif", "/img/icons/female.gif"];


var doSeal = function(targetObject) {
    // show thawte seal code w/o the reference to their exe in a dom compliant way
    var loc     = window.location.href, sealLoc = "https://sealinfo.thawte.com/thawtesplash?form_file=fdf/thawtesplash.fdf&dn=WWW.WEBTOGS.CO.UK&lang=en";
    var targetObject = $(targetObject);
    if (!targetObject)
        return false;

    new Asset.image("https://seal.thawte.com/getthawteseal?at=0&sealid=0&dn=WWW.WEBTOGS.CO.UK&lang=en&gmtoff=0", {
        onload: function() {
            this.injectInside(targetObject).addClass("curImage").set("title", "click to verify").addEvent("click", function() {
                window.open(sealLoc,'ga3ef4eb41dcac740b918440eb9cd19c8','height=500,width=516,scrollbars=yes,status=1');
            })
        },
        onerror: function() {

        }
    });
}; // end doSeal



var basketEvents = function() {
    if ($("SBL"))
        $("SBL")
        .addEvent("mouseenter", showBasket)
        .addEvent("mouseleave", function() {
            (function() {
                if ($("flyBasketC").get("rel") != "inline") hideBasket();
            }).delay(2000);
        })
} // end basketEvents;


var fadeGender = function(gender) {
    $$("."+gender).each(function(el) {
        var fakeDiv = new Element('div', {"class": "polka"});
        var pos     = el.getCoordinates();

        // dots animation is slow on ie, just fade out.
        if (Browser.Engine.trident)
            fakeDiv.setStyle("opacity", 0.3).setStyle("background", "#fff");
        else
            fakeDiv.setStyle("background-image", "url(/img/polka.gif)");

        fakeDiv.setStyles({
            "z-index": 1000,
            "position": "absolute",
            "top": pos["top"],
            "left": pos["left"],
            "width": el.getStyle("width"),
            "height": el.getStyle("height")
        }).injectAfter(el);
    });
}; // end fadeGender

var genderEvents = function(sURL) {
    // setup gender change

    $$("a.genderPick").each(function(el) {
        if (el.getNext().getText() == "(0)") {

            var safer = new Element("span").set("text", el.getText()).setStyles({
                color: "#777"
            }).injectBefore(el)
            el.dispose();
            return;
        }

        el.addEvents({
            click: function(e) {
                new Event(e).stop();
                ajl.make($("main"));

                var newGender = this.getText(), cookieVal = (newGender == "Women's") ? "female" : "male";

                var goToURL = window.location.href;
                goToURL = goToURL.replace(/Womens_/i, "");
                goToURL = goToURL.replace(/Mens_/i, "");
                goToURL = (cookieVal == "male") ? goToURL.replace(".co.uk/", ".co.uk/Mens_") : goToURL.replace(".co.uk/", ".co.uk/Womens_")


                window.location.href = goToURL;
            }
        });
    });

    if ($("uniselect"))
        $("uniselect").addEvents({
            click: function(e) {
                new Event(e).stop();
                if (this.hasClass("catChoiceOn"))
                    return;

                this.addClass("catChoiceOn");
                ajl.make($("main"));

                var cookieVal = "unisex";
                Cookie.dispose("gender");
                Cookie.set("gender", cookieVal, {duration: 365, path: "/"});

                var goToURL = window.location.href;
                goToURL = goToURL.replace(/Womens_/i, "");
                goToURL = goToURL.replace(/Mens_/i, "");
                window.location.href = goToURL;
            }

        });

} // end genderEvents

var ShowCategories = function() {
    // display the categories and hide search...
    $("page_navigation").setStyle("display", "block");
    $("result_interpretation").setStyle("display", "none");
    $("SM").setStyle("display", 'none');
    $("SB").setStyle("display", 'none');
    $("PM").setStyle("display", 'block');
    if ($("top10sellers"))
        $("top10sellers").setStyle("display", "none");

} // end ShowCategories

var ShowPage = function() {
    // show the page results and hide the category
    $("page_navigation").setStyle("display", "none");
    $("result_interpretation").setStyle("display", "block");
    $("SM").setStyle("display", 'block');
    $("SB").setStyle("display", 'none');
    $("PM").setStyle("display", 'none');
    if ($("top10sellers"))
        $("top10sellers").setStyle("display", "block");

} // end ShowPage


var toggleModal = function(backgroundColour, options) {
    // modal view for the whole screen
    // ver 2.02 for 1.11, 20/08/2009 10:55:11
    // returns the $("modal") div as element.
    if ($("modal")) {
        $("modal").dispose();
        return false;
    }

    var options = $merge({
        zIndex: 1000000,
        opacity: .8,
        events: $empty()
    }, options);

    if (!$type(backgroundColour) && !$("modal"))
        return false;

    return new Element("div", {
        id: "modal"
    }).setStyles({
        position: "absolute",
        top: 0,
        left: 0,
        width: window.getScrollWidth(),
        height: window.getScrollHeight(),
        background: backgroundColour,
        "z-index": options.zIndex
    }).setStyle("opacity", options.opacity).addEvents(options.events).inject(document.body);
}; // end toggleModal

var getABasket = function() {
    // get ajax basket
    var mj = new Ajax("/BasketAjax.php?a=reload", {method: "get", update: $("flyBasketC")}).request();
} // end getABasket

var basketSummary = function() {
    // prints the basket summary
    var mj = new Ajax("/BasketAjax.php?a=summary", {
        update: $("FB"),
        method: "get",
        onComplete: function() {
            basketEvents();
        }
    }).request();
} // end basketSummary

var continueShopping = function() {
    // gets a page via ajax and redirects to it.
    new Ajax("/index.php?a=continue", {
        method: "get",
        onComplete: function() {
            window.location.href = unescape(this.response.text.replace("https", "http"));
        }
    }).request();
} // end continueShopping


var myWhat = function(what, message, options) {
    var options = $merge({
        offsetY: 16,
        offsetX: 0,
        width: 260
    }, options);

    // open up a popup for text
    var coords  = what.getCoordinates();
    new Element("div", {"class": "what", id: "myWhat"}).setStyles({
        top: coords.top+options.offsetY,
        left: coords.left+options.offsetX,
        width: 260
    }).set("html", message).inject(document.body);

    what.addEvent("mouseleave", function() {
        //what.removeEvents();
        myDestroy("myWhat");
    });
} // end myWhat

var myImage = function(what) {
    // open up a popup for a larger image
    myDestroy("myImage");

    var coords  = what.getCoordinates();
    var popup   = new Element("div");
        popup.setStyles({
            "position": "absolute",
            "top": parseInt(coords["top"]+20)+"px",
            "left": parseInt(coords["left"]+184)+"px",
            "border": "1px solid #000",
            "background": "#ffffff",
            "display": "none",
            "z-index": 100000
        })
        .set("id", "myImage")
        .inject(document.body);

    var image = new Element("img");
        image.set("src", what.get("rel")).setStyle("border", 0).injectInside(popup);

    popup.setStyle("display", "block");

    // var mw = what.get("id");
    what.addEvent("mouseleave", function() {
        myDestroy("myImage");
    });
} // end myImage

var myDestroy = function(what) {
    // remove any image layers left out
    if ($(what)) {
        $(what).destroy();
    }
}

var myEventBubble = function(what, message) {
    // open up a pink bubble popup for text
    myDestroy("myBubble");


    var coords  = what.getCoordinates();
    var popup   = new Element("div");
    popup.setStyles({
        "position": "absolute",
        "top": parseInt(coords["top"]-56)+"px",
        "left": parseInt(coords["left"]-118)+"px",
        "display": "inline"
    })
    .addClass("bubble")
    .set("id", "myBubble")
    .set("html", message)
    .inject(document.body);

    what.addEvent("mouseleave", function() {
        myDestroy("myBubble");
    });
} // end myEventBubble

var simpleBubble = function(what, message, dobg) {
    // open up a pink bubble popup for text
    var $existing = $("myBubble");
    if ($existing)
        $existing.destroy();

    var coords  = what.getCoordinates();
    new Element("div", {
        id: "myBubble",
        "class": "bubble",
        html: message,
        styles: {
            "position": "absolute",
            "top": coords.top - 56,
            "left": coords.left- 118,
            "display": "inline",
            "zIndex": 100000000
        }
    }).inject(document.body);

    (function() {
        myDestroy("myBubble");
        if (dobg != false)
            what.setStyle('background', '#fff');
    }).delay(3000);

} // end simpleBubble

Element.implement({
    Watermark: function(options) {
        if (!options.esource)
            return;

        var coords = this.getCoordinates();

        var options = $merge({
            xoffset: coords.width,
            yoffset: 60,
            zIndex: 20000000,
            styles: {
                border: 0
            }
        }, options);

        var foo = options.esource.clone().cloneEvents(options.esource).set({
            styles: {
                position: "absolute",
                float: "left",
                "z-index": options.zIndex,
                marginLeft: coords.width - options.xoffset,
                marginTop: options.yoffset
            }
        }).setStyles(options.styles).inject(this.getParent(), "top");
    },
    getHTML: function() {
        return this.innerHTML;
    },
    modalBox: function(options) {
        var options = $merge({
            width: 400,
            height: 300,
            title: "",
            titleClass: "modalTitle",
            close: true,
            modal: true,
            shadow: true,
            scroll: false,
            modalColour: "#fff",
            text: "",
            textFunction: false,
            id: "modalBox",
            innerPadding: 10,
            movable: false,
            callback: function() {

            },
            onClose: function() {

            }
        }, options);



        // make the box.
        var coords = this.getCoordinates(), modalBox = new Element("div", {
            id: options.id
        }).setStyles({
            width: coords.width,
            height: coords.height, // + "px !important",
            left: coords.left,
            top: coords.top,
            position: "absolute",
            border: "1px solid #000",
            background: "#fff url(/img/top_grad_2.gif) repeat-x",
            "z-index": 10000000
        }).injectInside(document.body), myfx = new Fx.Styles(modalBox, {
                transition: Fx.Transitions.Sine.easeOut,
                duration: 300
        }), modalPos = centerBox(options.width,options.height);


        var closeModalBox = function() {
            myfx.stop();
            if (options.modal && $("modal")) {
                // $("modal").fade(.8, 0);
                $("modal").smartDispose();
            }

            if ($(options.id))
                 $(options.id).smartDispose();


            $$(".what3").smartDispose();

            options.onClose.attempt();
        };

        if (options.modal)
            toggleModal(options.modalColour).addEvents({
                click: function() {
                    closeModalBox();
                }
            });

        var modalTitle = new Element("div", {
            id: "modalTitle",
            "class": "left " + options.titleClass
        }).injectTop(modalBox);

        var modalBody = new Element("div", {
            id: "modalBody"
        }).setStyles({
            height: options.height - 48
        }).injectInside(modalBox);



        myfx.start({
            height: options.height,
            width: options.width,
            left: modalPos.left,
            top: modalPos.top
        }).chain(function() {
            if (options.scroll) {
                modalBody.setStyles({
                    "overflow-y": "scroll",
                    "overflow-x": "none"
                });
            }

            if (options.shadow) {
                if (Browser.Engine.trident)
                    modalBox.dropShadow();
                else
                    modalBox.addClass("shadowy");
            }

            if (options.close)
                new Asset.image("/img/modal_close2.gif", {
                    onload: function() {
                        this.injectTop(modalBox).addClass("curImage").addClass("right").setStyle("opacity", 1).setStyles({
                            paddingTop: 3, paddingRight: 3, border: 0
                        }).setProperties({
                            "title": "click to close",
                            "id": "modalClose"
                        }).addEvents({
                            click: function() {
                                this.destroy();

                                //(function() {
                                    closeModalBox();
                                //}).delay(500);
                            } /*,
                            mouseenter: function() {
                                this.fade(.6, 1, {reclaim: false, remove: false});
                            },
                            mouseleave: function() {
                                this.fade(1, .6, {reclaim: false, remove: false});
                            }
                            */
                        });
                    }
                });

            var adjustedWidth = (options.close) ? 58 : 0;
            modalTitle.set("html", options.title).setStyles({
                width: options.width - adjustedWidth,
                cursor: (options.movable) ? "move" : "default"
            });

            // new Element("br").setStyles({"clear": "both"}).injectAfter(modalTitle);

            modalBody.setStyles({padding: options.innerPadding, clear: "both"}).set("html", options.text);
            options.callback();

            // movable.
            if (options.movable) {
                new Drag.Move(modalBox, {
                    handle: modalTitle,
                    onStart: function() {
                        if (options.shadow && Browser.Engine.trident) {
                            var rel = modalBox.get("data-related");
                            if ($(rel))
                                $(rel).remove();
                        }
                    },
                    onComplete: function() {
                        if (options.shadow && Browser.Engine.trident) {
                            modalBox.dropShadow();
                        }
                    }
                });
            }
        });

    }, // end modalBox...
    smartDispose: function() {
        // dispose of an element and its dropShadow (if there is one)
        var rel = this.retrieve("shadow");
        if (rel) {
            rel.dispose();
        }

        if (this.parentNode)
            this.dispose();
    }, // end smartDispose
    dropShadow: function(options) {
        // creates a shadow effect to a rectangular element

        // define defaults
        var options = $merge({
            id: "dropShadow" + $random(100,1000),
            x: 3, // offset from parent
            y: 3,
            border: "1px solid #000",
            background: "#555",
            opacity: .5,
            zIndex: this.getStyle("z-index").toInt() - 1 // behind parent
        }, options);

        // only apply shadow on absolutely positioned elements
        if (this.getStyle("position") != "absolute")
            return this;

        var c = this.getCoordinates();

        this.store("shadow", new Element("div", {
            id: options.id
        }).setStyles({
            position: "absolute",
            left: c.left + options.x,
            top: c.top + options.y,
            width: c.width,
            height: c.height,
            background: options.background,
            zIndex: options.zIndex
        }).setStyle("opacity", 0).injectBefore(this).fade(0, options.opacity, {reclaim: false, remove: false}));

        return this;
    }, // end dropShadow
    simpleBox: function(message, options) {
        var options = $merge({
            offsetY: 16,
            offsetX: 0,
            width: 260,
            closeEvent: "mouseleave",
            background: "#fff"
        }, options);

        // open up a popup for text
        var coords  = this.getCoordinates();
        new Element("div", {"class": "what", id: "myWhat"}).setStyles({
            top: coords.top+options.offsetY,
            left: coords.left+options.offsetX,
            width: options.width,
            background: options.background,
            position: "absolute"
        }).set("html", message).inject(document.body);

        if (options.closeEvent != false)
            this.addEvent(options.closeEvent, function() {
                if ($("myWhat"))
                    $("myWhat").dispose();
            });
    },
    tooltip: function(what, options) {
        // apple style tooltip
        var _this = this, coords = _this.getCoordinates(), options = $merge({
            eventEnd: "mouseleave",
            eventEndTrigger: _this,     // parent element or self
            topOffset: 90,              // offset when in full view
            leftOffset: 0,
            topStartOffset: 100,        // offset for animation start
            opacity: .8,                // target opacity in full view
            className: "tooltip",       // linked to css
            morphOptions: {
                duration: 300,
                transition: Fx.Transitions.Sine.easeOut
            },
            style: $empty(),
            delay: 0,                    // can dispose on a timer, in seconds
            id: "tt_" + $random(100, 1000),
            innerStyle: "padding:20px; line-height: 18px"
        }, options);

        if ($type(_this.tip) != "element") {
            this.tip = new Element("div", {
                "class": options.className,
                id: options.id
            });
        }

        options.style = $merge({
            left: coords.left + coords.width / 2 +options.leftOffset
        }, options.style);
        this.tip.setStyles(options.style).setStyle("opacity", 0).set("html", "<div style='"+ options.innerStyle + "'>"+what+"</div>").inject(document.body);

        this.store("morph", new Fx.Styles(this.tip, options.morphOptions).start({
            opacity: options.opacity,
            top: [coords.top - _this.tip.getSize().size.y - options.topStartOffset, coords.top - options.topOffset]
        }));

        var closeAnimation = {
            opacity: 0,
            top: coords.top - _this.tip.getSize().size.y - options.topStartOffset
        }

        this.tip.store("data-close", Json.toString(closeAnimation));
        if (options.delay === 0) {
            options.eventEndTrigger.addEvent(options.eventEnd, function(e) {
                this.retrieve("morph").stop();
                _this.tipaway(closeAnimation);
            });
        }
        else {
            (function() {
                if (this.tipaway)
                    this.tipaway(closeAnimation);
            }).delay(options.delay, this);
        }
        return this;
    },
    tipaway: function(options) {
        if (this.tip) {
            this.retrieve("morph").start(JSON.decode(this.tip.retrieve("data-close")));
        }

        return this;
    },
    disposeRelatives: function() {
        var rels = this.retrieve("relatives");
        if (!rels.length)
            return;

        rels.each(function(el) {
            el.dispose();
        });

        return this;
    },
    slowFocus: function(options) {
        // don't focus straight away so user can read error bubble
        el = this;
        options = $merge({delay: 3000}, options);
        (function() {
            el.focus();

        }).delay(options.delay);
        return el;
    },
    newFade: function(options) {
        var options = $merge({
            from: 1,
            to: 0,
            reclaim: true,
            remove: true
        }, options);

        var fadeobj = this;
        fadeobj.set("removed", true);
        if (fadeobj.getStyle("display") == "none")
            fadeobj.setStyle("display", "inline");

        var fx = new Fx.Style(this, "opacity", {duration: 500, onComplete: function() {

            if (options.to == 0 && options.reclaim) {
                fadeobj.setStyle("display", "none");
            }
            if (options.remove == true) {
                return fadeobj.remove();
            }
        }});
        fx.start(options.from, options.to);
        return this;
    },
    fieldError: function(error_title, body, options) {
        if ($("error"+this.get("id")))
            $("error"+this.get("id")).smartDispose();

        var options = $merge({
            left: 0,
            top: -12,
            position: "relative",
            marginLeft: 0,
            errorClass: "myinputFocusedError",
            doEvents: true
        }, options);

        var el = this;
        var error_message = new Element("div", {
            "id": "error"+this.get("id"),
            "class": "error_state_wrap"
        }).set("html", '<div class="error_state"><div class="large">' + error_title + '</div><div class="small">' + body + '</div></div>')
        .setStyles({
            left: options.left,
            "margin-top": options.top,
            "margin-left": options.marginLeft
        })
        .injectAfter(this);

        if (options.doEvents == false)
            return this;

        this.addClass(options.errorClass);
        (function() {
            error_message.smartDispose();
        }).delay(4000, this);
        return this;
    },
    getSize2: function() {
        // based on mootools 1.11 getSize, gets the subcontainer size and scroll data
        return {
            'scroll': {'x': this.scrollLeft, 'y': this.scrollTop},
            'size': {'x': this.offsetWidth, 'y': this.offsetHeight},
            'scrollSize': {'x': this.scrollWidth, 'y': this.scrollHeight}
        };
    },
    facetip: function(message, options) {
        // a quick 'facebook' style tooltip
        // function version 2.2, 21/06/2009 20:04:16

        if (!$type(message))
            return false;

        if ($type(this.retrieve("tipbody"))== "element")
            this.retrieve("tipbody").destroy();

        var options = $merge({
            eventStart: "mouseenter",
            eventEnd: "mouseleave",
            topOffset: 20,
            opacity: 1,
            zIndex: 10000000
        }, options);

        var coords = this.getCoordinates();

        this.store("tipbody", new Element("div", {
            styles: {
                background: "transparent url(/images/point_down.gif) no-repeat center bottom",
                float: "left",
                position: "absolute",
                left: 0,
                top: -100,
                opacity: options.opacity,
                height: 20,
                zIndex: options.zIndex
            }
        }).adopt(new Element("div", {
            styles: {
                background: "#4c4c4c",
                color: "#ffffe5",
                padding: 0,
                "padding-top": 2,
                "line-height": 10,
                margin: 0,
                "padding-left": 9,
                "padding-right": 9,
                display: "block",
                "margin-left": "auto",
                "margin-right": "auto",
                overflow: "hidden",
                "font-size": "10px",
                "font-family": "verdana",
                float: "left",
                height: 13
            },
            html: message.replace(/ /g, "&nbsp;")
        })).inject(document.body));

        this.addEvent(options.eventEnd, function() {
            if ($type(this.retrieve("tipbody")) == "element") {
                this.retrieve("tipbody").destroy();
                this.removeEvent(options.eventEnd);
            }
        }.bind(this));

        // var tipWidth = tipbody.getCoordinates();
        var t = this.retrieve("tipbody").getSize();

        this.retrieve("tipbody").setStyles({
            left: coords.left + (coords.width / 2).round() - (t.x / 2).round(),
            top: coords.top - options.topOffset,
            width: t.x
        });

        return this;
    }
}); // element

var IEactivateFlash = function() {
    $$("embed").each(function(el) {
        el.outerHTML = el.outerHTML;
    });
} // activate all embed controls.


var centerBox = function(width, height) {
    // returns coordinates for positioning
    var winSize = window.getSize(), winScroll = winSize.scroll, winSize = winSize.size, windowHeight = window.getScrollHeight()-1, coords = {
        top: winScroll.y + (winSize.y / 2) - (height / 2),
        left: winSize.x / 2 - width / 2,
        width: width,
        height: height
    }

    if (coords.top + height + 20 > windowHeight)
        coords.top = windowHeight - 20 - height;

    if (coords.top <= 0) {
        coords.top = 20;
    }

    return coords;
};


Number.implement({
    money: function(currency) {
        var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "." : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
	    return (currency || "") + s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
    }
});// end number extend

var validEmailRegex = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, isValid = function(email) {
    return email.test(validEmailRegex);
};

var C = {
    // console wrapper
    debug: true, // global debug on|off
    quietDismiss: false, // may want to just drop, or alert instead
    log: function() {
        if (!C.debug) return false;


        if (typeof console == 'object' && typeof console.log != "undefined")
            try {
                console.log.apply(this, arguments); // safari's console.log can't accept scope...
            } catch(e) {
                // so we loop instead.
                for (var i = 0, l = arguments.length; i < l; i++)
                    console.log(arguments[i]);
            }
        else
            if (!C.quietDismiss) {
                var result = "";
                for (var i = 0, l = arguments.length; i < l; i++)
                    result += arguments[i] + " ("+typeof arguments[i]+") ";

                alert(result);
            }
    }
}; // end console wrapper.


// currency change
var currencySwap = {
    changed: false,
    isOpen: false,
    initialize: function() {
        this.changer = $("currencySwapper");
        if (!this.changer)
            return;

        this.source = $("ASDASD");
        if (!this.source)
            return;

        this.content = this.source.innerHTML;
        var _this = this;
        this.changer.getFirst().addEvents({
            click: function(e) {
                e.preventDefault();

                if (_this.isOpen)
                    return false;

                _this.openSwapper(this);
            }
        }); // events
    },
    openSwapper: function(el) {
        this.isOpen = true;
        var _this = this;

        el.modalBox({
            width: 800,
            height: 170,
            title: "Set your currency and delivery preferences",
            titleClass: "modalTitle",
            close: true,
            modal: true,
            shadow: true,
            scroll: false,
            modalColour: "#fff",
            text: "",
            textFunction: false,
            id: "modalBox",
            innerPadding: 10,
            movable: !false,
            callback: function() {
                // load content
                $("modalBody").set("html", _this.content).setStyles({
                    textAlign: "center"
                });

                $("ASDASD").empty();

                $("currencyNotice").addEvents({
                    mouseenter: function() {
                        this.tooltip($("currencyTip").innerHTML, {
                            className: "what2 shadowy",
                            topOffset: -16,
                            topStartOffset: -250,
                            opacity: 1,
                            style: {
                                zIndex: 10000000,
                                background: "#ffffcf"
                            },
                            innerStyle: "padding: 5px;line-height: 1.3"
                        });
                    },
                    click: function(e) {
                        e.preventDefault();
                    }
                });

                _this.addEvents();
            },
            onClose: function() {
                _this.isOpen = false;
                if (_this.changed === true) {
                    if ($("main"))
                        ajl.make($("main"));
                    else
                        toggleModal("#fff");
                    window.location.href = window.location.href;
                }
            }
        });
    },
    addEvents: function() {
        // currency change...
        var _this = this;
        $("priceSwap").addEvents({
            change: function() {
                var target = this.get("value");
                Cookie.dispose("currency");
                Cookie.set("currency", target, {duration: 7, path: "/"});
                _this.changed = true;
            }
        }); // end priceSwap change

        // target country change
        $("deliveryCountry").addEvents({
            change: function() {
                var newId = this.get("value");
                if (newId == 0) {
                    Cookie.dispose("deliveryCountry");
                    return false;
                }

                Cookie.dispose("deliveryCountry");
                Cookie.set("deliveryCountry", newId, {duration: 7, path: "/"});
                _this.changed = true;
            }
        });
    }
}; // end currency changer namespace



// ajax loader class
ajl = new AjaxLoader();


var toggleInputs = function(classOff, classOn, options) {

    var options = $merge({
        off: "#f60",
        on: "#070",
        over: "#fa6"
    }, options);

    $$("input."+classOff, "select."+classOff).addEvents({
        focus: function() {
            this.removeClass("myinputFocusedError").removeClass("myinputShortFocusedError").addClass(classOn).store("focused", true);
            document.getElement("label[for="+this.id+"]").setStyle("color", options.on);
            if (this.tip)
                tipper.tipaway(this);
        },
        blur: function() {
            this.removeClass(classOn).store("focused", false);
            document.getElement("label[for="+this.id+"]").setStyle("color", options.off);
        },
        mouseenter: function() {
            if (this.retrieve("focused") === false) {
                this.addClass(classOn);
                document.getElement("label[for="+this.id+"]").setStyle("color", options.over);
            }
        },
        mouseleave: function() {
            if (this.retrieve("focused") === false) {
                this.removeClass(classOn);
                document.getElement("label[for="+this.id+"]").setStyle("color", options.off);
            }
        }
    }).store("focused", false);
};

function toggleEl(el) {
    // for dodgy IE crap with block/none collapse
    if (!Browser.Engine.trident) {
        if (el.retrieve("hidden")) {
            el.store("hidden", false).setStyle("display", "block");
        }
        else {
            el.store("hidden", true).setStyle("display", "none");
        }
        return;
    }

    if (el.retrieve("hidden")) {
        el.setStyles({"visibility":  "visible", height: el.retrieve("height")});
        el.store("hidden", false);
    }
    else {
        el.store("height", el.getStyle("height"));
        el.store("hidden", true);
        el.setStyles({"visibility":  "hidden", height: 0});
    }
}

var mooSelecta = new Class({

    version: 1.1,

    Implements: [Options, Events],

    updated: "30/03/2010 11:57:42",
    // default options
    // don't change these here but on the instance (unless you want to)
    options: {
        selector: "selecta",                            // class / selector for selects to convert
        triggerClass: "selectaTrigger",                 // class of the replacement div
        triggerPadding: 30+5,                           // compensate for left/right padding of text
        triggerBeforeImage: "",                         // advanced styling of trigger like a round image
        triggerBeforeImageWidth: 0,                     // need to compensate width
        triggerBeforeImageHeight: 0,                    // and know height.
        wrapperClass: "selectaWrapper",                 // popup wrapper class
        wrapperWidthAdjustment: 0,                      // you can add or substract to width if not matching, use +/- value
        wrapperShadow: "shadowy",                       // extra class applied to wrapper, like one with box-shadow
        wrapperHeight: 0,                               // maximum allowed height for dropdown before it scrolls
        optionClass: "selectaOption",                   // base class of indivdual options
        optionClassSelected: "selectaOptionSelected",   // pre-selected value class
        optionClassOver: "selectaOptionOver",           // onmouseover option class
        allowTextSelect: false,                         // experimental to stop accdiental text selection
        // these are keycodes that correspond to alpha numerics on most ISO keyboards for index lookups of options
        allowedKeyboardCodes: [48,49,50,51,52,53,54,55,56,57,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90],
        useClickListener: true,                         // binds click events to check for clicks away from dropdown.
        off: "#f60",
        on: "#070",
        over: "#fa6"
    },

    Binds: ["_bindClickListener"],

    // internal hashed collection of managed selects
    selects: {},

    // hash that references options per select for keycode lookups
    optionList: {},

    // false or contains a pointer to the last select that has opened the menu
    focused: false,

    initialize: function(options) {
        // start everything.
        this.setOptions(options);

        // locate and apply selects to all required ones.
        var selects = $$('select.'+this.options.selector);

        if (!selects.length)
            return "nothing to do, selector came up empty!";

        selects.each(this.replaceSelect.bind(this));

        // convert object to hash
        this.selects = new Hash(this.selects);

        // bind mouseclicks and keytyping
        this.bindListeners();
    },

    replaceSelect: function(el) {
        // public method that replaces selects
        var el = $(el); // adds uid.

        if (!el) return;

        // gets existing element's width to use
        var width = el.getSize().size.x;

        // default selected to go into wrapper
        var selectedOption = el.getElements("option").filter(function(op) {
            return op.get("selected");
        });

        // clean up old instances.
        if (el.retrieve("triggerElement"))
            el.retrieve("triggerElement").dispose();
        if (el.retrieve("wrapper"))
            el.retrieve("wrapper").dispose();


        // build the top visible element
        el.store("triggerElement", new Element("div", {
            "class": this.options.triggerClass
        }).setStyles({
            width: width - this.options.triggerPadding
        }).injectAfter(el).addClass("cur")); // cur is a class that changes cursor to a clicky one.

        // re-adjust width after the trigger has been done so wrapper can match it.
        width = el.retrieve("triggerElement").getSize().size.x - 2 - this.options.triggerBeforeImageWidth + this.options.wrapperWidthAdjustment;

        // build the menu wrapper

        // if we have an image to pre-pend, add it.
        if (this.options.triggerBeforeImage.length) {
            new Element("div").setStyles({
                float: "left",
                position: (Browser.Engine.trident4) ? "absolute" : "relative",
                background: "url("+this.options.triggerBeforeImage+") no-repeat",
                width: this.options.triggerBeforeImageWidth,
                height: this.options.triggerBeforeImageHeight
            }).injectBefore(el.retrieve("triggerElement"));
        }

        // create the options wrapper
        el.store("wrapper", new Element("div", {
            "class": this.options.wrapperClass
        }).setStyles({
            width: width,
            zIndex: 10000
        }).injectAfter(el.retrieve("triggerElement")).addClass(this.options.wrapperShadow));

        // now hide the original selects off-screen
        // this is so the tab indexing and by-label focus works and hands us back contol.
        el.setStyles({
            position: "absolute",
            top: -10000
        }).addEvents({
            focus: function() {
                if (this.focused)
                    this._hideOptions();

                this.focused = el;
                this._toggleOptions(el);

                var lbl = document.getElement("label[for="+el.id+"]");
                if (!lbl)
                    return;
                lbl.setStyle("color", this.options.on);

            }.bind(this),
            blur: function(e) {
                if (this.focused == el)
                    this._toggleOptions(el);

                var lbl = document.getElement("label[for="+el.id+"]");
                if (!lbl)
                    return;

                lbl.setStyle("color", this.options.off);
            }.bind(this),
            change: function() {
                var lbl = document.getElement("label[for="+el.id+"]");
                if (!lbl)
                    return;

                lbl.setStyle("color", this.options.off);

                // through scripting this can backfire, need to update option visible.
                el.retrieve("triggerElement").set("html", el.getElements("option").filter(function(el) {
                    return el.get("selected");
                })[0].getText());
            }.bind(this)
        });

        // handle labels so they don't interfere by launching a semi-full event.
        var lbl = document.getElement("label[for="+el.get("id")+"]");
        if (el.get("id") && lbl) {
            lbl.addEvent("click", function(e) {
                new Event(e).stop();
                el.fireEvent("focus");
            });
        }

        // get all options and port them to wrapper
        el.getElements('option').each(function(option) {
            var selected = false;
            if (option.get("selected")) {
                el.retrieve("triggerElement").set("html", option.getText());
                selected = true;
            }
            this._addOption(option, el, selected);
        }, this);

        // figure out height of wrapper and reduce if needed
        if (this.options.wrapperHeight) { // if greater than 0 care about this
            var height = el.retrieve("wrapper").getSize().size.y;
            if (height > this.options.wrapperHeight) {
                el.retrieve("wrapper").setStyles({
                    height: this.options.wrapperHeight
                });
            }
        }

        // hide the menu by default.
        el.retrieve("wrapper").setStyle("display", "none");

        // attach a click event to trigger element
        el.retrieve("triggerElement").addEvents({
            click: function(e) {
                new Event(e).stop();
                // toggler, click on opened closes it.
                el.fireEvent((this.focused == el) ? "blur" : "focus");
            }.bind(this),
            mouseenter: function() {
                var lbl = document.getElement("label[for="+el.id+"]");
                if (!lbl)
                    return;

                if (!this.focused) {
                    lbl.setStyle("color", this.options.over);
                }
            }.bind(this),
            mouseleave: function() {
                var lbl = document.getElement("label[for="+el.id+"]");
                if (!lbl)
                    return;

                if (!this.focused) {
                    lbl.setStyle("color", this.options.off);
                }
            }.bind(this)
        });

        // export the managed select to the hash
        if (el.uid && el)
            this.selects[el.uid] = el;

    }, // end .replaceSelect();

    bindListeners: function() {
        // setup valrious click / key events

        if (this.options.useClickListener)
            document.addEvent("click", this._bindClickListener.bind(this));

        document.addEvents({
            // keyboard listener
            keydown: function(e) {
                var e = new Event(e);

                // if no menu is currently open, don't do anything.
                if (!this.focused)
                    return;

                switch(e.code) {
                    case 40: // down arrow option navigation
                        new Event(e).stop();
                        // ops should really be cached outside here
                        var ops = this.focused.retrieve("wrapper").getElements("div."+this.options.optionClass), done = false;

                        ops.each(function(el, i) {
                            if (ops.length-1 == i || done)
                                return;

                            if (el.hasClass(this.options.optionClassSelected)) {
                                ops.removeClass(this.options.optionClassOver);
                                ops[i+1].addClass(this.options.optionClassSelected).addClass(this.options.optionClassOver);
                                el.removeClass(this.options.optionClassSelected);
                                done = true;
                            }
                        }, this);


                    break;
                    case 38: // up arrow option navigation
                        new Event(e).stop();
                        var ops = this.focused.retrieve("wrapper").getElements("div."+this.options.optionClass), done = false;

                        ops.each(function(el, i) {
                            if (done)
                                return;

                            if (el.hasClass(this.options.optionClassSelected)) {
                                if (i > 0) {
                                    ops.removeClass(this.options.optionClassOver);
                                    ops[i-1].addClass(this.options.optionClassSelected).addClass(this.options.optionClassOver);
                                    el.removeClass(this.options.optionClassSelected);
                                }
                                done = true;
                            }
                        }, this);


                    break;
                    case 13: // enter
                        new Event(e).stop();
                        this.focused.retrieve("wrapper").getElements("div."+this.options.optionClassSelected).fireEvent("click");
                    break;
                    case 9: // tabbed out, blur auto...
                        this._hideOptions(this.focused);
                    break;
                    case 34:
                    case 35:
                        // go to last option via pgdn or end
                        new Event(e).stop();
                        var old = this.focused;
                        this.focused.retrieve("wrapper").getElements("div."+this.options.optionClass).getLast().fireEvent("click");
                        old.fireEvent("focus");

                    break;
                    case 33:
                    case 36:
                        // go to first option via pgup or home
                        new Event(e).stop();
                        var old = this.focused;
                        this.focused.retrieve("wrapper").getElement("div."+this.options.optionClass).fireEvent("click");
                        old.fireEvent("focus");

                    break;
                    default:
                        // the "other" keys.

                        var old = this.focused, ops = this.focused.retrieve("wrapper").getElements("div."+this.options.optionClass);

                        // is is alpha numeric allowed?
                        if (this.options.allowedKeyboardCodes.contains(e.code)) {
                            // loop through current option texts array cache for matches
                            var matchingKeys = [];
                            var selected = false;

                            var applicable = this.optionList["k"+this.focused.uid].filter(function(el, index) {
                                if (ops[index].hasClass(this.options.optionClassSelected)) selected = index;
                                var match = el.indexOf(e.key) == 0;
                                if (match)
                                    matchingKeys.push(index);
                                return match;
                            }, this);

                            if (applicable.length) {
                                if (!matchingKeys.contains(selected)) {
                                    selected = matchingKeys[0];
                                }
                                else {
                                    if (ops[selected+1] && matchingKeys.contains(selected+1)) {
                                        selected++;
                                    }
                                    else {
                                        selected = matchingKeys[0];
                                    }

                                }

                                ops[selected].fireEvent("click");
                                old.fireEvent("focus");
                                done = true;
                            }
                        }
                        else {
                            // do nothing or disable comment to see other keys you may like to bind.
                            // console.log(e.code, e.key);
                            e.stop();
                        }
                    break;
                }
            }.bind(this)
        });
    }, // end .bindListeners()

    _bindClickListener: function(e) {
        // listens for client clicks away from triggers and closes like real selects do when user loses interest
        var e = new Event(e);

        // using a collection which saves a click on an element that's not extended with .hasClass
        if ($$(e.target).hasClass(this.options.triggerClass).contains(false)) {
            this._hideOptions();
        }
    },

    _addOption: function(option, el, selected) {
        // internal method called by replaceSelect that adds each option as a div within the wrapper
        var text = option.getText().trim();
        if (!text.length)
            text = "&nbsp;";

        // store options relevant to element uid.
        var oldList = this.optionList["k" + el.uid] || [];
        oldList.push(text.toLowerCase());
        var tempObj = {};
        tempObj["k" + el.uid] = oldList;
        $extend(this.optionList, tempObj);
        // end store


        var opDiv = new Element("div", {
            "class": this.options.optionClass
        }).set("html", text).addEvents({
            mouseenter: function() {
                opDiv.addClass(this.options.optionClassOver);
            }.bind(this),
            mouseleave: function() {
                opDiv.removeClass(this.options.optionClassOver);
            }.bind(this),
            click: function(e) {
                if (e && e.type && e.stop)
                    new Event(e).stop();

                // menu stuff visual
                el.retrieve("wrapper").getChildren().removeClass(this.options.optionClassSelected);
                opDiv.addClass(this.options.optionClassSelected);
                el.retrieve("triggerElement").set("html", opDiv.getText());

                // now handle change in the real select
                el.set("value", opDiv.retrieve("value")).fireEvent("change", e);
                this._toggleOptions(el);
            }.bind(this)
        }).store("value", option.get("value")).inject(el.retrieve("wrapper")).addClass("cur");

        if (selected)
            opDiv.addClass(this.options.optionClassSelected);

    }, // end _addOption

    _toggleOptions: function(el) {
        // toggles visibility on click
        var vis = el.retrieve("wrapper").getStyle("display");
        el.retrieve("wrapper").setStyle("display", (vis == "none") ? "block" : "none").getChildren().removeClass(this.options.optionClassOver);
        this.focused = (vis != "none") ? false : el;

        // scroll to selected from .toElement in core but w/o a fx.slide instance
        var parent = el.retrieve("wrapper").getPosition(this.options.overflown);
		var target = el.retrieve("wrapper").getElement("div." + this.options.optionClassSelected).getPosition(this.options.overflown);
        el.retrieve("wrapper").scrollTo(target.x - parent.x, target.y - parent.y);
        this._clearSelection();
    },

    _hideOptions: function() {
        // private called on cleanup / away click
        this.selects.values().each(function(el) {
            if (el.retrieve("wrapper").getStyle("display") != "none")
                el.fireEvent("blur");
            el.retrieve("wrapper").setStyle("display", "none");
            el.focused = false;
        });
    },

    _clearSelection: function() {
        // removes document selection
        if (this.options.allowTextSelect || Browser.Engine.trident4) // not sure how IE6 does this
            return;

        if (document.selection && document.selection.empty) {
            // document.selection.empty();
        } else if (window.getSelection) {
            window.getSelection().removeAllRanges();
        }
    }
}); // endClass


/////////////////////////////////////////////////////////////////////////////////////////////
// execute on domready

// var load_method = (Browser.Engine.trident4) ? 'load' : 'domready';
var load_method = "domready";

window.addEvent(load_method, function() {
    // support for placeholder= property for older browsers
    new mooPlaceholder().attachToElements();


    var gender = Cookie.read("gender");
    if (gender != "male" && gender != "female") {
        var myStyleBorder = {border: "1px solid #ddd"};

        // 20/06/2010 22:08:32 refactored for absolute pos.
        new Asset.image(icons[0], {
            title: "Suitable for men",
            onload: function() {
                this.set({
                    "class": "curImage",
                    opacity: .7,
                    events: {
                        mouseenter: function() {
                            this.setStyle("opacity", 1);
                        },
                        mouseleave: function() {
                            this.setStyle("opacity", .7);
                        }
                    }
                });

                document.getElements("img.male").Watermark({
                    xoffset: 20,
                    yoffset: 3,
                    esource: this,
                    styles: {
                        border: "1px solid #ddd",
                        width: this.width,
                        height: this.height
                    }
                });

            }
        });

        new Asset.image(icons[1], {
            title: "Suitable for women",
            onload: function() {
                this.set({
                    "class": "curImage",
                    opacity: .7,
                    events: {
                        mouseenter: function() {
                            this.setStyle("opacity", 1);
                        },
                        mouseleave: function() {
                            this.setStyle("opacity", .7);
                        }
                    }
                });

                document.getElements("img.female").Watermark({
                    xoffset: 20,
                    yoffset: 3,
                    esource: this,
                    styles: {
                        border: "1px solid #ddd",
                        width: this.width,
                        height: this.height
                    }
                });

            }
        });
       // end refactored
    }

    var SI = document.getElements("img.sale");
    if (SI.length > 0) {
        new Asset.image("/img/icons/sale2.gif", {
            title: "Item is on sale",
            onload: function() {
                SI.Watermark({
                    yoffset: 1,
                    esource: this,
                    styles: {
                        width: this.width,
                        height: this.height
                    }
                });

            }
        });
    }
/*
    var SI = $$("img.sale20");
    if (SI.length > 0) {
        var SMark = new Asset.image("/img/icons/sale20.gif", {title: "Item is on sale with 20% off RRP"});
        SI.each(function(el) { $W(el, SMark, {xoffset: el.width, yoffset: 0}); }); // end each
    }

    var SI = $$("img.sale30");
    if (SI.length > 0) {
        var SMark = new Asset.image("/img/icons/sale30.gif", {title: "Item is on sale with 30% off RRP"});
        SI.each(function(el) { $W(el, SMark, {xoffset: el.width, yoffset: 0}); }); // end each
    }

    var SI = $$("img.sale40");
    if (SI.length > 0) {
        var SMark = new Asset.image("/img/icons/sale40.gif", {title: "Item is on sale with 40% off RRP"});
        SI.each(function(el) { $W(el, SMark, {xoffset: el.width, yoffset: 0}); }); // end each
    }
*/

    if (Browser.Engine.trident4) {
        //  css selector of all images with a property src ending on "png"
        $$('img[src$=png]').each(function(img, i) {
            var oldParent = img.getParent();
            var oldId = img.id;
            img.set("id", "old"+i);
            var imgID = "id='clone" + i + "' ";
            var imgClass = (img.className) ? "class='" + img.className + "' " : ""
            var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt + "' "
            var imgStyle = "display:inline-block;" + img.style.cssText
            if (img.align == "left") imgStyle = "float:left;" + imgStyle
            if (img.align == "right") imgStyle = "float:right;" + imgStyle
            if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
            var strNewHTML = "<span " + imgID + imgClass + imgTitle
            + " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
            + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
            + "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"
            img.outerHTML = strNewHTML;
            $("clone"+i).cloneEvents(img).setProperties(img.getProperties('alt','rel','title','id'));
        }); // each
    }

    var subscribeEmail = $("subscribe_email");
    if (subscribeEmail) {
        $("subscribe_email_go").addEvent("click", function() {
            if (subscribeEmail.get("value") == subscribeEmail.get("placeholder") || subscribeEmail.get("value").clean() == "") {
                simpleBubble(subscribeEmail, "Please enter a<br />valid email");
                return false;
            }

            new Request({
                url: "/accountAjax.php",
                method: "get",
                evalResponse: true
            }).send("a=bh&id="+subscribeEmail.get("value").clean());
        });
    }



    if (Browser.Engine.trident) {
        (function() {
            menuEvents();
        }).delay(1000);
    }
    else {
        menuEvents();
    }

    if (Cookie.read("EDM") == "show") {
        (function() {
            var topEffect = new Fx.Styles(new Element("div", {
                id: "topnotice"
            }).set("html", "<div style='float: left; text-align: center; font-weight: bold; padding-top: 5px;padding-left: 5px;'>Hi there, you can shop at webtogs as normal and we'll apply your 11% discount during checkout.</div><div id='closeNotice' class='closeNotice' style='float: right'>close</div><br clear='all'/>").injectTop(document.body), {
                duration: 1000,
                transition: Fx.Transitions.Sine.easeOut
            }).start({
                opacity: [0,1],
                top: [-150, 0]
            });
            // Watermark.move();

            $("closeNotice").addEvents({
                click: function() {
                    topEffect.start({
                        opacity: [1,0],
                        top: [0, -20]
                    }).chain(function() {
                        Cookie.set("EDM", "hidden", {path: "/"});
                        $("topnotice").dispose();
                    });
                },
                mouseenter: function() {
                    this.addClass("closeNoticeOn");
                },
                mouseleave: function() {
                    this.removeClass("closeNoticeOn");
                }
            }).addClass("curImage");
        }).delay(500);
    }


    // sidemenu expand
    var $mytime;

    $$("div.catExpand").each(function(el) {
        var myId = el.get("rel");
        el.addEvents({
            mouseenter: function() {
                $mytime = (function() {
                    this.addClass("catDown").removeEvents();

                    $$("div.catHide[rel="+myId+"]").each(function(sub) {
                        sub.setStyles({
                            "display": "block"
                        }).setStyle("opacity", 0).fade(0,1, {remove: false, reclaim: false});
                    });
                }).delay(500, this);

            },
            mouseleave: function() {
                $clear($mytime);
            }
        });

    });

    if ($("allsubs"))
        $("allsubs").addEvents({
            click: function(e) {
                this.getFirst().addClass("catChoiceOn");
                ajl.make($("main"));
            }
        });

    if ($("allbrands"))
        $("allbrands").addEvents({
            click: function() {
                this.getFirst().addClass("catChoiceOn");
                ajl.make($("main"));
            }
        });

    (function() {
        // sizes
        var hybrids = document.getElements("div.hybrid");
        var sizeHeading = document.id("sizeHeading");
        var bc = document.getElement("div.trail_nav");

        var navSizes = document.getElements("div.navSize");
        var cookieSize = Cookie.read("thumbSize");


        navSizes.each(function(el) {
            var size = el.getText();

            el.addEvents({
                click: function() {
                    // ajl.make($("main"));
                    document.getElements("div.navSizeOn").removeClass("navSizeOn");

                    this.addClass("navSizeOn").fade(0,1, {remove:0,reclaim:0});

                    var currentSize = this.get("text").clean();
                    hybrids.removeClass("hide");

                    hybrids.filter(function(el) {
                        var sis = el.get("data-sis");
                        if (!sis)
                            return true;
                        var sisArray = sis.split(",");
                        return !sisArray.contains(currentSize);
                    }).addClass("hide");
                    sizeHeading.removeClass("catChoiceOn");

                    // breadcrumb
                    bc.getElements("span.sizeFilter").destroy();

                    var sizeFilter = new Element("span", {
                        "class": "sizeFilter",
                        html: " > <a href='#' title=''><img src='/img/close-filter.gif'></a> size '" + currentSize + "'"
                    }).inject(bc);

                    sizeFilter.getElement("a").addEvents({
                        click: function(e) {
                            e.stop();
                            sizeHeading.getParent().fireEvent("click", e);
                        }
                    });

                    Cookie.write("thumbSize", currentSize, {
                        path: "/"
                    });
                },
                mouseenter: function() {
                    this.addClass("navSizeOver");
                },
                mouseleave: function() {
                    this.removeClass("navSizeOver");
                }
            }).addClass("cur"); //.set("html", size);
        });

        if (sizeHeading) {
            sizeHeading.getParent().addEvents({
                click: function(e) {
                    e.stop();
                    hybrids.removeClass("hide");
                    $$("div.navSizeOn").removeClass("navSizeOn");
                    sizeHeading.addClass("catChoiceOn");
                    bc.getElements("span.sizeFilter").destroy();
                    Cookie.dispose("thumbSize", {
                        path: "/"
                    });

                }
            });
        }

        if (cookieSize) {
            var isSizeAvailable = navSizes.filter(function(el) {
                return el.get("text").clean() == cookieSize;
            });

            if (isSizeAvailable.length) {
                ajl.make($("main"));
                (function() {
                    isSizeAvailable[0].fireEvent("click");
                    ajl.remove();
                }).delay(1000);
            }
        }

    })(); // end sizes

    currencySwap.initialize();

    var rel = document.id("relatedProds");
    // product Scroller
    if (rel) {

        var scr = new Scroller({
            products: rel,
            cats: [],
            productContainer: document.id("productC"),
            moveDelay: 200,
            moveSteps: 85,
            product_: document.id("product_"),
            arrowLeft: document.id("arrowL"),
            arrowRight: document.id("arrowR")
        });
    }

    if (Browser.Engine.trident)
        // activate flash
        IEactivateFlash();

}); // domready
