/**
* Lloyds TSB 2012
* @version 1.0
* @requires jQuery Core 1.4+ - http://www.jquery.com/
*/

/*jslint white: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true */


/**
* @namespace Root namespace for holding all objects created for LTSB
*/

var LTSB = window.LTSB || {};

/**
* @namespace Manage the animated Countdown page widget
* The countdown widget alternates between two visible panels. If the browser supports CSS 3D Transforms, and has hardware accleration enabled, the animation is handled by CSS3. Otherwise the panels are animated horizontally through JavaScript.
*/

LTSB.countdown = {
    animationInterval: 5000,
    animationDuration: 300,
    countdown: null, // reference to the containing DOM element
    panels: null, // reference to the two alternating panels


    /**
    * Determine if CSS 3D transforms are available in the browser
    * @returns {boolean} TRUE if CSS 3D is supported
    */
    css3DEnabled: function () {
        if (this._css3D == undefined) {
            // test if the perspective has been set in thte stylesheet: use feature detections instead of browser sniffing
            var perspective = this.countdown.css('Perspective') || this.countdown.css('WebkitPerspective');
            this._css3D = !(perspective == undefined || perspective == "" || perspective == 'none');
        }

        return this._css3D;
    },


    /**
    * Animate the current visible panel inwards
    */
    squeeze: function () { // support for browsers without CSS 3D transforms
        var self = this;

        $(this.panels[0]).animate({
            marginLeft: "50%",
            width: 0
        }, {
            duration: self.animationDuration,
            complete: function () {
                self.panels.reverse();
                self.expand();
            }
        });
    },

    /**
    * Animate the current visible panel outwards
    */
    expand: function () {
        var self = this;
        $(this.panels[0]).animate({
            marginLeft: 0,
            width: "100%"
        }, {
            duration: this.animationDuration
        });
    },


    /**
    * Initialise the Countdown module
    * @param {Element} countdown The container element of the countdown module
    */
    init: function (countdown) {
        var self = this;

        this.countdown = $(countdown); // save references to important elements
        this.panels = this.countdown.find('div').toArray();

        try {  // Prevent cursor flicker during animation in IE6
            document.execCommand("BackgroundImageCache", false, true);
        } catch (e) { /* do nothing */ };

        setInterval(function () { // set up the timer to fire the animation
            if (self.css3DEnabled()) {
                self.countdown.toggleClass('flip');
            } else {
                self.squeeze();
            };
        }, self.animationInterval);
    }
};

/**
* @namespace Trivia slideshow, with user interface controls
*/

LTSB.ticker = {
    _delay: 10000,
    _interval: null,
    _panes: null,
    _controls: null,

    /**
    * Find the current visible pane
    * @returns {jQuery instance} the current visible pane
    */
    _currentVisible: function () {
        return this._panes.filter('.select');
    },


    /**
    * Set a specific pane to be visible
    * @param {Element} elm The element to become visible. Must be one of LTSB.ticker.panes
    */
    _swapVisibleTo: function (elm) {
        this._currentVisible().removeClass('select');
        elm.addClass('select');
    },

    /** 
    * Handle user interaction with the module
    * @param {event} e The click event 
    */
    _clickHandler: function (e) {
        var self = LTSB.ticker;

        e.preventDefault();

        var command = e.currentTarget.className.match(/play|next|prev/i); // detect which button was activated
        if (command) {
            command = command[0];
            self[command]();

        }

        if (command != 'play') {
            self.stop(); // any user interaction except play pauses playback
        }
    },

    /**
    * Switch the play button between the pause and play visual states
    */
    _togglePlayButtonState: function () {
        this._controls.find('.stop, .play').toggleClass('stop play');
    },

    /**
    * Advance to the next pane
    */
    next: function () {
        this._swapVisibleTo(this._currentVisible().next().length > 0 ?
                                this._currentVisible().next() :
                                this._panes.eq(0));
    },

    /**
    * Step back to the previous pane
    */
    prev: function () {
        this._swapVisibleTo(this._currentVisible().index(this._panes) == 0 ?
                                this._panes.last() :
                                this._currentVisible().prev());
    },

    /**
    * Stop on the current visible pane
    */
    stop: function () {
        if (this._interval) {
            clearInterval(this._interval);
            this._interval = null;

            this._togglePlayButtonState();
        }
    },

    /**
    * Start playback 
    * @param {boolean} [toggleButton=TRUE] Set to FALSE to prevent the play button toggling state
    */
    play: function (toggleButton) {
        if (!this._interval) {
            this._interval = setInterval(function () {
                LTSB.ticker.next();
            }, this._delay);

            if (toggleButton !== false) {
                this._togglePlayButtonState();
            }

        }
    },

    /**
    * Initialise the ticker widget
    * @param {Element} containerElm the container element
    */
    init: function (containerElm) {
        var self = this,
            container = $(containerElm),
            tallestPaneHeight;

        this._panes = container.find('.content > *');

        this._controls = container.find('.controls')
                                        .delegate('li', 'click', this._clickHandler);

        // set the height to the largest of all content panes
        tallestPaneHeight = this._panes.map(function () {
            return $(this).height();
        })
                                            .get()
                                            .sort(function (a, b) {
                                                return b - a;
                                            })[0];

        container.find('.content').css('height', function () {
            return (tallestPaneHeight / parseInt($(this).css('fontSize'), 10)) + 'em';
        });

        this.play(false); // start playback, without affecting play button state
    }
};

/**
* @namespace Expandable details widget
*
*/

LTSB.details = {
    _closedClassName: 'closedAccordeon',

    /**
    * Open the details widget
    * @param {Element} elm The container element of the details widget
    */
    open: function (elm) {
        $(elm).removeClass(this._closedClassName).find('ul').slideDown();
    },

    /**
    * Set the widget to the closed state
    * @param {Element} elm 
    * @param {Boolean} [withoutAnimation=FALSE]
    */
    close: function (elm, withoutAnimation) {
        if (withoutAnimation) {
            $(elm).find('ul').hide();
        } else {
            $(elm).find('ul').slideUp();
        }

        $(elm).addClass(this._closedClassName);
    },

    /**
    * Initialise the widget 
    * @param {Element} containerElm The parent element of the widget
    */

    init: function (containerElm) {
        var self = this;

        containerElm = $(containerElm); // ensure a jQuery object

        containerElm.toggle(function () { // bind event handlers for opening/closing
            self.open(containerElm);
            return false;
        }, function () {
            self.close(containerElm);
            return false;
        });

        this.close(containerElm, true); // set to closed by default, without animation
    }

};


/** 
* @namespace Carousel/Gallery widget, used on the homepage 
* @requires jQuery Tools Tabs plugin, with slideshow features - http://flowplayer.org/tools/tabs/index.html
*/
LTSB.carousel = {
    opts: { // settings for the jQuery tools plugins
        tabs: {
            effect: 'default', // set the initial effect to the default to stop the fade in on the first panel onload - change to effect to fade once the tabs have been configured
            rotate: true,
            fadeOutSpeed: 500,
            fadeInSpeed: 500
        },
        slideshow: {
            autoplay: true,
            clickable: false,
            autopause: false,
            interval: 10000
        }
    },

    _slideshowAPI: null,  // reference points for jQuery tools API
    _carouselAPI: null,
    _controls: null, //refernece to the playback controls element

    /**
    * Handle user interaction
    * @param {Event} e The click event
    */
    _clickHandler: function (e) {
        var action;

        action = e.currentTarget.className.match(/prev|next|stop|play/i);
        if (action) {
            action = action[0];
            this[action]();
        }
    },

    /**
    * Stop playback on the current visible slide
    */
    stop: function () {
        this._slideshowAPI.stop();
    },

    /**
    * Start playback
    */

    play: function () {
        this._carouselAPI.next(); // skip immediately to provide user feedback
        this._slideshowAPI.play();
    },

    /**
    * Advance to the next slide 
    */
    next: function () {
        this._carouselAPI.next();
        this.stop();
    },

    /**
    * Step back to the previous slide
    */
    prev: function () {
        this._carouselAPI.prev();
        this.stop();
    },


    /**
    * Initialise the carousel widget
    * @param {Element} containerElm
    */
    init: function (containerElm) {
        var self = this,
            container = $(containerElm),
            tabs = container.find('.tabs'), // save references to important elements
            panels = container.find('.panel');


        $(tabs).tabs(panels, this.opts.tabs) // setup tabs plugin
                  .slideshow(this.opts.slideshow) // setup slideshow plugin for auto-play
                  .parent()
                  .delegate('.controls > li', 'click', function (e) { // bind handlers for playback controls
                      e.preventDefault();
                      e.stopPropagation();

                      self._clickHandler(e);
                  })
                  .click(function (e) { // ensure the playback stops when there is any user interaction
                      if (!e.isPropagationStopped()) {
                          self.stop();
                      }
                  });

        $(tabs).bind('onPlay', function () { // bind to playback events to set the playback button state
            self._controls.find('.stop, .play').addClass('stop').removeClass('play');
        })
                  .bind('onPause', function () {
                      self._controls.find('.stop, .play').addClass('play').removeClass('stop');
                  });

        this._carouselAPI = $(tabs).data('tabs'); // find references to APIs
        this._slideshowAPI = $(tabs).data('slideshow');
        this._controls = container.find('.controls');

        // set the effect to fade as the tabs have been configured - this is to stop the fade in on the first panel onload
        this._carouselAPI.getConf().effect = 'fade';
    }
};


/**
* @namespace Basic form validation
*/
LTSB.validate = {
    _errorNotice: null,
    /**
    * Rules available to validate a field against.
    * Fields declare their requirements by including the name of the rules in their data-validate attribute
    */
    _rules: {
        /**
        * @params {string} str The value to validate
        * @returns {boolean} TRUE if the string is a valid postcode
        */
        ukPostcode: function (str) {
            // ensure this regex matches the one used on the server side validation
            var postcodeMatcher = /^[A-Za-z]{1,2}[0-9Rr][0-9A-Za-z]? ?[0-9][AaBbJjLlNnD-Hd-hP-Up-uW-Zw-z]{2}$/;

            return (str.match(postcodeMatcher) != null);
        },

        required: function (str) {
            return ($.trim(str).length > 0);
        }
    },

    /**
    * Show or hide the error header
    * @param {boolean} show TRUE if the error header should be set to visible
    */
    toggleErrorHeader: function (show) {
        if (!this._errorNotice) {
            this._errorNotice = $('div.error').eq(0);
        }

        $(this._errorNotice).toggle(show);
        $('.error .errorNotice').toggle(show);

    },

    /** 
    * Center the error message relative to he input
    * @param {Element} field The input field owner of the error message to be positioned
    */

    layoutErrorMessage: function (field) {

        var field = $(field),
			message = field.nextAll('.errorMessage'),
			widthDiff = (field.outerWidth() - message.outerWidth()) / 2,
			parentLeft = field.parent().offset().left,
			rightMargin = field.offsetParent().outerWidth() - (field.outerWidth() + field.position().left);

        message.css('right', rightMargin + widthDiff);

        if (message.offset().left < parentLeft) {
            message.css('left', field.offset().left - parentLeft);
        }

        return true;
    },


    /** 
    * Validate all fields that are children the specified container element
    * @param {DOMElement} containerElm
    * @returns {boolean} TRUE if all fields passed validation
    */

    check: function (containerElm) {
        var self = this,
            success = true; // pass/fail status of the container element

        $(containerElm).find('input[data-validate], select[data-validate]').each(function () {
            var rules = $(this).attr('data-validate').split(), // detect the rules applicable to this field
                field = this;

            $.each(rules, function (i, r) {
                var valid = self._rules[r](field.value);
                $(field).closest('p').toggleClass('error', !valid); // show the contextual error message if test failed
                if (!valid) self.layoutErrorMessage(field);
                success = (success && valid);
            });

        });

        this.toggleErrorHeader(!success); // show or hide the errorHeader


        return success;
    },

    init: function () {
        var self = this;

        $('input[type=submit]').click(function (e) {
            if ($(this).parent().parent().attr("className").indexOf("enter_now") == -1) {
                return self.check($(e.target).closest('fieldset'));
            } else {
                /*  dont invoke this validation procedure on the competition forms */
                return true;
            }
        });
    }
};

/** 
* @namespace  Enable placeholders on fields for browsers which do not support HTML5
*/

LTSB.placeholder = {
    /**
    * Check for HMTL5 placeholder support
    * @returns {boolean} TRUE if the browser supports the placeholder attribute
    */
    supported: function () {
        return ('placeholder' in document.createElement('input')); // test for HTML5 placeholder support
    },

    /**
    * Setup event handlers on a field to mimic placeholder support
    * The field will have a value equivalent to the placeholder attribute, unless a default value is already set
    * @param {DOMElement[]} inputElm input field(s) to provide support to
    * @returns {jQuery Set} The input element(s) passed in
    */

    enable: function (inputElm) {

        var setupInput = (this.supported()) ?
                             function () { // clear the textfield and let the browser handle the placeholder
                                 if (this.value == $(this).attr('placeholder')) {
                                     this.value = "";
                                 }
                             } :
                             function () { // simulate placeholder support
                                 var maxlength = $(this).attr('maxlength');
                                 maxlength = maxlength > 0 ? maxlength : null;
                                 $(this).blur(function () {
                                     if (this.value.length < 1) {
                                         $(this).attr('maxlength', null);
                                         this.value = $(this).attr('placeholder');
                                     }
                                 })
                                 .focus(function () {
                                     if (this.value == $(this).attr('placeholder')) {
                                         $(this).attr('maxlength', maxlength);
                                         this.value = "";
                                     }
                                 }).blur();
                             };


        return $(inputElm).each(function () {
            setupInput.apply(this);
        });
    }
};

/**
* @namespace Dropdown menu behaviour
*/

LTSB.dropdown = {
    _htmlOverlay: null, // private reference to the overlay element

    /**
    * Find the height needed for the overlay
    * @returns {integer} Height in pixels of the page area the overlay should cover.
    */
    _overlayHeight: function () {
        return $('.breadcrumb').outerHeight()
        		+ $('#wrapper').outerHeight()
                + $('#footer').outerHeight();
    },

    /**
    * Hide the dropdown menus
    */
    _hideMenu: function () {
        $('ul.subNavigation li div').hide();
        $('ul.subNavigation').find('li a.dropDown, li.dropDownPosition').removeClass('dropDownPosition');
    },

    /**
    * Hide the overlay, and hide any visible menus
    */
    _hideOverlay: function () {
        this._hideMenu();
        this._htmlOverlay.fadeOut('fast');
    },

    /**
    * Handle user interaction
    * @param {Event} e The click event
    */
    _clickHandler: function (e) {
        var self = this,
            enabledClass = 'dropDownPosition';

        if ($(e.target).hasClass(enabledClass)) {
            self._hideOverlay();
            return;
        }

        self._htmlOverlay = $('body').find('.overlay');

        if (self._htmlOverlay.length === 0) { // create the overlay on demand

            self._htmlOverlay = $('<div class="overlay"></div>')
                            .css({
                                'height': self._overlayHeight,
                                'opacity': '0.75'
                            })
                            .hide()
                            .appendTo('body')
                            .fadeIn('fast')
                            .click(function () {
                                self._hideOverlay();
                            });

        } else {
            self._htmlOverlay.fadeIn('fast');
        }

        self._hideMenu();

        $(e.target).addClass(enabledClass) // show the dropdown
                    .next().show();
        $(e.target).parent().addClass(enabledClass);
    },


    /** 
    * Initialise the dropdown menu
    */
    init: function () {
        var self = this;
        $('a.dropDown').click(function (e) {
            self._clickHandler(e);
            return false;
        });
    }
};

//Check for if the Social Media Container is present to control the width of the BreadCrumb
LTSB.socialMedia = {
    init: function () {
        $("#socialmediaWrapper").addClass("show");
        if ($("#breadcrumb").find("#socialmediaWrapper")) {
            $("#breadcrumb ul").css("width", "410px");
        } else {
            $("#breadcrumb ul").css("width", "100%");
        }
    }
};

// Trackside V2 - Add .selected to competition Latest Poll - radiogrup  

LTSB.selectedRadiogroup = {
	init: function (){
		              
		
		$('.question .radiogroup').each(function () {  
			var self = $(this);
			
			//check if the radioButton is selected  
			$('input:checked', self).parents('.option').addClass('selected');
			
			$('.option', self).click(function () {
			   $('.option', self).removeClass('selected');
			   $(this).addClass('selected'); 
			
			   //check the radioButton if is not selected
			   $('input[type=radio]', this).attr('checked', 'checked');
				
			});
		})

	} 
};

$(document).ready(function () {
    LTSB.countdown.init($('.countdown'));

    $('.tabbed.carousel').each(function () {
        LTSB.carousel.init(this);
    });

    $('.ticker').each(function () {
        LTSB.ticker.init(this);
    });

    $('.accordeon').each(function () {
        LTSB.details.init(this);
    });

    if ($('input[type=submit]').length > 0) {
        LTSB.validate.init();
    }

    LTSB.dropdown.init();
    LTSB.socialMedia.init();
	LTSB.selectedRadiogroup.init();

    if ($.browser.msie && $.browser.version < 7) { // Remove the Social Plugin for IE6
        $("#socialmediaWrapper").removeClass("show");
        $("#breadcrumb ul").css("width", "100%");
    }

    /* Support big hit area on the headshots module */
    $('.headshots li div').click(function (e) {
        window.location = $(this).siblings('a:first').attr('href');
    });

    if ($.browser.msie && $.browser.version < 7) {
	
		// provide hover state for headshots in IE6
        $('.localHeroes .headshots li').hover(function () {
            $(this).find('div').show();
        }, function () {
            $(this).find('div').hide();
        });
		
		// provide hover state for options
		$('.compQuestion .question .radiogroup .option').hover(function() {
			$(this).css('background-position', '-168px 0');
		}, function () {
			$(this).css('background-position', '0 0');
		});
    };

    LTSB.placeholder.enable($('input[placeholder]'));


    /* Enable the media video player */

    if ($.fn.mediaelementplayer) {
        $('p.videoError').css({ 'visibility': 'hidden' });
        $('audio,video').mediaelementplayer({
            plugins: ['flash'] // only use Flash plugin
        });
    }

    if (typeof FormValSettings != "undefined" && typeof FormValidation != "undefined") {
        FormValidation.init($('form').eq(0), {
            onValidationResult: function (e, data) {
                $(e.target).toggleClass('error', !data.IsValid).find('.errorMessage span').eq(0).text(data.Message);
            }
        });
    }


    /* Enable the media video player */
    // clears error on top of the page if you are clicking a different tab.
    $('.tabbed .tabs li a').bind('click', function () {
        $('.errorNotice').hide();
    });

    // clear fix for ie to correct layout issues when validating
    if ($.browser.msie && $.browser.version < 8) {
        $('<div class="clearfix" />').appendTo('#main');
    }

    // clear fix for ie to correct layout issues when validating
    if ($.browser.msie && $.browser.version < 7) {
        $('.cta input').hover(
       function () { $(this).css('text-decoration', 'underline'); },
       function () { $(this).css('text-decoration', ''); }
    )
    }

});


// disabled the click events of any "disabled" elements
$('.disabled').live('click', function (e) { e.preventDefault(); });

// open social media sharing links in new windows
$('.popup').live('click', function (e) { e.preventDefault(); if ($(this).attr('disabled')) { return; } window.open($(this).attr('href'), 'win', 'width=600,height=400'); });

// add print functionality to links
$('.print').live('click', function (e) { e.preventDefault(); window.print(); })  

