/*!
 * Erskine Design JavaScript (EDJ)
 *
 * http://erskinedesign.com/
 */

// Set up our global Erskine Design Javascript object
var EDJ = {
    debug: false,
    STATIC_URL: '/assets/',
    is_touch: false,
    run_list: [
        'navigation',
        'equal_heights',
        'accordions',
        'tabs',
        'carousels',
        'slideshows',
        'fixed_menu',
        'faqs',
        'website_feedback',
        'page_actions',
        'scroll_to',
        'google_maps'
    ],
    $body: {}
};

// Global variables for the Derby Council JW Player embed library
var jwplayerfolder = 'http://www.derby.gov.uk/jwplayer/',
    mediaserver = 'av.derby.gov.uk',
    skin = 'skins/bekle.zip',
    fullscreen = 'true',
    autostart = 'false',
    logo = 'logos/logowh.png',
    logohide = 'false',
    logoposition = 'top-left',
    controlbarposition = 'over',
    googleanalyticsid = 'UA-1161625-6',
    shadowopacity = '0.8',
    shadowmodal = true,
    shadowanimate = true,
    shadowanimatefade = true,
    shadowfadeduration = '0.5',
    shadowanimatesequence = 'wh';

/**
 * On ready
 *
 * Called when document is ready
 *
 * Used on: all pages
 *
 * @namespace EDJ
 * @class on_ready
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.on_ready = function() {
    var i = 0;
    var functions_to_run = EDJ.run_list.length;

    // Cache the body object for use later
    EDJ.$body = $('body');
    
    // Check for a touch device
    EDJ.is_touch = this.is_touch_device();

    // Loop through our functions and run those that exist and said they should
    for (i=0; i<functions_to_run; i++) {
        // If the init function exists, and the run key is set to true
        if (typeof EDJ[EDJ.run_list[i]].init === 'function' && ( 
            (typeof EDJ[EDJ.run_list[i]].run === 'function' && EDJ[EDJ.run_list[i]].run() === true) ||
            (typeof EDJ[EDJ.run_list[i]].run === 'boolean' && EDJ[EDJ.run_list[i]].run === true)
        )) {
            // Log that we've called the init function
            EDJ.log('initialising EDJ.'+EDJ.run_list[i]);

            // Call the init function!
            EDJ[EDJ.run_list[i]].init();

            // Log that we've finished the init function
            EDJ.log('finished running EDJ.'+EDJ.run_list[i]);

        }

    }

};

/**
 * Is touch device
 *
 * Checks to see if the agent is a touch device
 *
 * Used on: all pages
 *
 * @namespace EDJ
 * @return boolean
 * @class on_ready
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.is_touch_device = function() {
  try {
    document.createEvent("TouchEvent");
    return true;
  } catch (e) {
    return false;
  }
}


/**
 * Log
 *
 * Will log any arguments (arrays, objects, strings etc.) to the console
 * if it exists, and EDJ.debug is set to true
 *
 * Used on: all pages
 *
 * @namespace EDJ
 * @class log
 * @param anything!
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.log = function() {
    if (EDJ.debug === true && typeof(console) !== 'undefined') {
        console.log('[EDJ] ' + Array.prototype.join.call(arguments, ' '));
    }
};

/**
 * Page actions
 *
 * Various helpers for naviation
 *
 * Used on: all pages
 *
 * @namespace EDJ
 * @class page_actions
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.page_actions = {
    $page_actions: {},

    run: function() {
        this.$page_actions = EDJ.$body.find('div.page_actions > div > ul > li');
        return this.$page_actions.length > 0;
    },

    init: function() {
        // Delegate functions to each action in the UL
        this.$page_actions.delegate('.print a', 'click', function() {
            window.print();
        });

    }
};

/**
 * Navigation
 *
 * Various helpers for naviation
 *
 * Used on: all pages
 *
 * @namespace EDJ
 * @class navigation
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.navigation = {
    run: true,

    init: function() {
        this.access();
        this.nav_pri_drops();

    },

    /**
     * Accessability links
     *
     * Gives cross browser support to the accessability links to navigation and content
     *
     * @method access
     *
     */
    access: function() {
        var $access_links = EDJ.$body.find('ul#nav_access li a');

        $access_links.focus(function(){ 
            $(this).addClass('focus');
        });

        $access_links.blur(function(){ 
            $(this).removeClass('focus'); 
        });

    },

    /**
     * Navigation drop down menus
     *
     * On hover, sub menus are shown (after an intent delay)
     *
     * @method nav_pri_drops
     *
     */
    nav_pri_drops: function() {
        var $navigation_pri = EDJ.$body.find('#navigation_pri'),
            $navigation_sec = EDJ.$body.find('#navigation_sec li a'),
            $dropdown = $navigation_pri.find('ul.dropdown'),
            drop_options = {
                dropdownSelector: '.dropdown',
                dropdownShowDelay: 280,
                dropdownHideDelay: 500
            };

        /* Primary navigation
        ---------------------------------------- */        
        $dropdown.hover(
            function() {
                $(this).parent().attr('id', 'active');
            },
            function() {
                $(this).parent().removeAttr('id');
            }
        );

        $navigation_pri.dropem(drop_options);

        /* Secondary navigation
        ---------------------------------------- */
        $navigation_sec.hover(
            function() {
                $(this).parent().next().addClass('hover_next');
            },
            function() {
                $(this).parent().next().removeClass('hover_next');
            }

        );

    }

};

/**
 * Equal heights
 *
 * Uses the equalHeights jquery plugin to set matched element's heights the same
 * http://linktoplugin/
 *
 * Used on: all pages
 *
 * @namespace EDJ
 * @class equal_heights
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.equal_heights = {
    run: true,

    init: function() {
        EDJ.$body.find('#footer_pri div.service_lists_col div').equalHeights();
        EDJ.$body.find('#footer_pri div.service_lists_col').equalHeights();
    }

};

/**
 * Accordions
 * 
 * Uses the accordion jQuery UI plugin
 * http://jqueryui.com/demos/accordion/
 *  
 * Used on: pages with a div#accordion
 *
 * @namespace EDJ
 * @class accordions
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.accordions = {
    $accordions: {},

    run: function() {
         this.$accordions = EDJ.$body.find('div#accordion');
         return this.$accordions.length > 0;
    },

    init: function() {

        this.$accordions.accordion({
            autoHeight: false
        });

    }

};

/**
 * Tabs
 * 
 * Uses the tabs jQuery UI plugin
 * http://linktoplugin/
 * 
 * Used on: all pages with div.ui-tabs
 *
 * @namespace EDJ
 * @class tabs
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.tabs = {
    $tabs: {},

    run: function() {
        this.$tabs = EDJ.$body.find('div.ui-tabs');
        $('div.ui-tabs > ul').addClass('horizontal');
        return this.$tabs.length > 0;
    },

    init: function() {
        this.$tabs.tabs();
    }

};

/**
 * Carousels
 * 
 * Uses the carousel plugin
 * http://linktoplugin/
 * 
 * Used on: all pages
 *
 * @namespace EDJ
 * @class carousels
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.carousels = {
    $carousels: {},

    run: function() {
        this.$carousels = EDJ.$body.find('.carousel');
        return ( this.$carousels.length > 0 && !($.browser.msie && $.browser.version.substr(0,1) < 7));
    },

    init: function() {
        // We can explicitly set this to save time and power
        // because they're only run on one page
        var visible = 4;

        this.$carousels.each(function() {
            var $carousel = $(this);
            $(this).jcarousel({
                scroll: visible,
                wrap: 'both',
                initCallback: function(carousel) {
                    var $controls = $('<ul class="controls horizontal" />'),
                        num_controls = Math.ceil(this.size / visible),
                        i = 0;

                    for (i; i<num_controls; i++) {
                        $controls.append('<li><a href="#' + i + '">' + ((i * visible) + 1) + '</a></li>');
                    }

                    $controls.find('li a ').bind('click', function(event) {
                        event.preventDefault();
                        carousel.scroll($.jcarousel.intval($(this).text()));
                    });

                    $carousel.closest('.jcarousel-container').before($controls);
                },
                itemLastInCallback: function(carousel, item, idx, state) {
                    var page = Math.ceil(idx / visible) - 1,
                        $controls = $carousel.closest('.carousel_wrapper').find('.controls li');

                    // Add a class of cur to the current page on controls
                    $controls.removeClass('cur');
                    $controls.filter(':eq(' + page + ')').addClass('cur');
                }
            });
        });

    }

};

/**
 * Slideshows
 * 
 * Uses the jQuery cycle plugin and the jQuery carousel plugin
 * http://jquery.malsup.com/cycle/
 *
 * Also uses the jQuery jcarousel plugin
 *
 * Used on: all pages with div.slideshow
 *
 * @namespace EDJ
 * @class slideshows
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.slideshows = {
    $slideshows: {},
    $controls: {},

    run: function() {
        this.$slideshows = EDJ.$body.find('div.slideshow');
        return this.$slideshows.length > 0;
    },

    init: function() {
        var $more_info_btn = $('div.ss_type3 div.more_info'),
            $less_info_btn = $('div.ss_type3 div.less_info');

        this.$slides = this.$slideshows.find('div.slides ol');
        this.$controls = EDJ.$body.find('div.slideshow div.controls ol li a');

        this.$slides.cycle({
            speed: 500,
            timeout: 0,
            activePagerClass: 'cur',
            pagerAnchorBuilder: function(index, slide) { 
                var $control = {};

                // only build the pager and mega parent objects once
                if ( this.pager === null ) {
                    this.$mega_parent = $(slide).closest('.slideshow');
                    this.pager = '#' + this.$mega_parent.attr('id') + ' .controls ol';
                }

                $control = this.$mega_parent.find('div.controls ol li:eq(' + index + ')');

                // return the object for each relatively indexed li
                return $control;
            },
            after: function(current, next) {
                $(current).find('div.media_player').remove();
            }
        });

        // Add the less and more info actions to ss_type3
        if ($less_info_btn.length > 0) {
            // Less info fades itself out and the info in
            $less_info_btn.live('click', function(event) {
                event.preventDefault();
                $(this).closest('.slideshow').find('li:not(.audio, .video) .info').css('display', 'none');
                $(this).closest('.slideshow').find('.more_info').css('display', 'block');
            });
            $more_info_btn.live('click', function(event) {
                event.preventDefault();
                $(this).closest('.slideshow').find('.info').css('display', 'block');
                $(this).closest('.slideshow').find('.more_info').css('display', 'none');
            });
        }

        // Load in extra slides asynchronously
        this.load_slides();
        // Build media player actions and insertions
        this.media_players();
        // Add tooltips on the fly and position them
        this.tooltips();
        // Carousels for the pager functions
        this.carousels();
        // Lightboxes for 'enlarge' buttons
        //this.lightboxes();

    },

    /**
     * Lightbox
     *
     * Launch the slideshow from the enlarge button
     *
     * @method lightboxes
     *
     */
     lightboxes: function() {
        EDJ.slideshows.$slideshows.find('p.enlarge a').colorbox({
            inline: true,
            width: '609',
            height: '500',
            rel: 'ss_0'
        });
     },
    /**
     * Load slides
     *
     * Only the first two slides are loaded on the front end,
     * now we asynchronously load the rest
     *
     * @method load_slides
     *
     */
     load_slides: function() {

     },

    /**
     * Tooltips
     *
     * When we hover over controls, we wan't to see a tooltip
     *
     * @method tooltips
     *
     */
    tooltips: function() {
        if (EDJ.is_touch) {
            return;
        }

        var $tooltip = $('<div class="tooltip"><span class="text">&nbsp;</span><span class="arrow">&nbsp;</span></div>'),
            position = [];

        // The tooltip will be position absolutely with JavaScript
        EDJ.$body.append($tooltip);
        this.$controls.each(function() {
            this.span_text = $(this).attr('title');
            $(this).removeAttr('title');
        });

        this.$controls.hoverIntent(
            function() {
                // Find the type of slideshow from the controls parent (div.slideshow) class
                var ss_type = $(this).closest('.slideshow').attr('class').replace('slideshow ', ''),
                // The dimensions go into an array for each item (dimension[width,height])
                    control_dimensions = [$(this).outerWidth(true), $(this).outerHeight(true)],
                    tooltip_dimensions = [$tooltip.outerWidth(true), 0];

                // Set the title from the controls title attribute
                EDJ.slideshows.tooltips.title = this.span_text;
                $tooltip.find('.text').html(EDJ.slideshows.tooltips.title);

                // Give the tooltip the correct class
                $tooltip.addClass(ss_type);

                // Now we can find the height
                tooltip_dimensions[1] = $tooltip.outerHeight(true);

                // positioning is dependant on the type of slideshow (to the right or below)
                switch(ss_type) {
                    case 'ss_type1':
                        // Left position is just right of the control
                        position[0] = $(this).offset().left + control_dimensions[0] + 4;
                        // Top position is the mid y point of the control + the mid height point of the tooltip
                        position[1] = ($(this).offset().top + (control_dimensions[1] / 2)) - (tooltip_dimensions[1] / 2);
                        break;
                    case 'ss_type2':
                    case 'ss_type2b':
                    case 'ss_type3':
                        // Left position in the centre of the control
                        position[0] = $(this).offset().left - (tooltip_dimensions[0] / 4);
                        // Top position just above
                        position[1] = $(this).offset().top - control_dimensions[1] - 4;
                        break;
                }
                $tooltip.css({
                    'top': position[1],
                    'left': position[0]
                });
                $tooltip.fadeIn(80);
            },
            // Hover out, hide the tooltip again
            function() {
                $tooltip.css('display', 'none');
            }
        );

    },

    /**
     * Carousels
     *
     * Carousels for pagers with more controls than are visible
     *
     * @method carousels
     *
     */
     carousels: function() {
            EDJ.slideshows.$slideshows.each(function(){
                var blanking = '<li class="blanking" />',
                    filler = '',
                    $controls = {}
                    num_add = 0,
                    num_visible = 6;


                if ($(this).hasClass('ss_type1')) {
                    return false;
                }

                $controls = $(this).find('.controls ol');
                if ($controls.find('li').length < num_visible) {
                    return false;
                }

                $controls.parent().addClass('with_pager');

                if ($(this).hasClass('ss_type3')) {
                    num_visible = 5;
                }

                num_add = num_visible - ($controls.find('li').length % num_visible);
                while (num_add--) {
                    filler += blanking + "\n";
                }
                $controls.append(filler);

                $controls.jcarousel({
                    scroll: num_visible,
                    wrap: 'both'
                });


            });
     },

    /**
     * Media player
     *
     * Embed media players, and deal with their activation
     *
     * @method media_player
     *
     */
     media_players: function() {
        var $media_triggers = EDJ.slideshows.$slideshows.find('p.media_video');

        $media_triggers.delegate('a', 'click', function(event) {
            var $slide = $(this).closest('li'),
                width = $slide.width(),
                height = $slide.height(),
                article_url = $slide.find('.info a:first').attr('href'),
                media_url = $(this).attr('href'),
                media_title = $(this).attr('title'),
                $transcript = $slide.find('.info a.transcript'),
                $media_player = {},
                media_id = 'player_' + $(this).attr('id'),
                image = $slide.find('img:first-child').attr('src'),
                media_holder = '';
                EDJ.log(article_url);

                // Build the holder with JavaScript
                media_holder = '<div class="media_player">' +
                                    '<div class="media_player_inner" id="' + media_id  + '" >'+
                                        '<p>Cannot play media.You do not have the correct version of Adobe Flash Player. <a href="http://get.adobe.com/flashplayer/">Download the correct version</a></p>' + 
                                    '</div>' +
                                    '<div class="access">';
                // If the article url isn't empty, and it's not the media url
                // build a link to it in the access bar
                if (article_url != '' && article_url != media_url) {
                    media_holder +=     '<p class="read_more"><a href="' + article_url +'">More on ' + $(this).attr('title') + ' here</a></p>';
                }
                // If the transcript url isn't empty add that (too)
                if ($transcript.length > 0) {
                    media_holder +=     '<p class="transcript"><a href="' + $transcript.attr('href') + '">' + $transcript.html() + '</a></p>';
                }

                media_holder +=     '</div>' + 
                                '</div>';

            $media_player = $(media_holder);

            event.preventDefault();

            $(this).closest('li').prepend($media_player);
            // The height is the whole slide - the height of the access links
            height -= $media_player.find('div.access').outerHeight(true);

            $media_player.find('.media_player_inner').width(width).height(height);

            // Focus the keyboard on the access links
            $media_player.find('a:first').focus();

            embedPlayerWithFlashvars(
                'vodsecure',
                'rtmpe',
                media_url,
                media_id,
                width,
                height,
                image,
                $(this).attr('title'),
                'false',
                {
                    'autostart': true,
                    'controlbar.position': 'over',
                    'image': image,
                    'stretching': 'fill'
                }
            );

            // Immediately redirect to the player for touch devices
            if (EDJ.is_touch && media_url != '') {
                window.location = 'http://' + mediaserver + '/vodsecure/' + media_url + '/playlist.m3u8';
            }

        });

     }

};

EDJ.media_players = {
    $media_players: {},

    run: function() {
        this.$media_players = $('div.media_video');
        return this.$media_players.length > 0;
    },

    init: function() {

        this.$media_players.append('<div />');
    }
};

/**
 * Website feedback
 * 
 * Custom website feedback widget
 * 
 * Used on: all pages
 *
 * @namespace EDJ
 * @class website_feedback
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.website_feedback = {
    $rate_page: {},

    run: function() {
        this.$rate_page = EDJ.$body.find('div#rate_page');
        return this.$rate_page.length > 0;
    },

    init: function() {
        var $cancel = $('<a class="action_micro cancel">Cancel</a>'),
            $comment_wrapper = this.$rate_page.find('fieldset#rate_comment_wrapper'),
            $span = this.$rate_page.find('ul#happiness_labels span');

        // Add cancel button dynamically
        $cancel.bind('click', function() {
            $comment_wrapper.hide();
        });
        // Now add the cancel button to the form
        this.$rate_page.find('div.submit').append($cancel);

        // Loop through each happiness label and create click events
        $span.bind('click', function() {
            var mood = '';

            $comment_wrapper.removeClass();

            // Regex out the mood from the id
            mood = $(this).parent().attr('id').match(/rate_([^_]+)_label/)[1];
            // Give the box the mood as a class
            $comment_wrapper.addClass(mood);
            // Fade it in quickly
            $comment_wrapper.show();
            // Focus the control to the first input / textarea
            $comment_wrapper.find(':input:first').focus();

        });

        // Simulate click on enter press
        $span.bind('keyup', function(event) {
            if (event.keyCode == 13) {
                $(this).trigger('click');
            }
        });

        // Hitting escape will also close the form
        $comment_wrapper.find('textarea').bind('keyup', function(event) {
            if (event.keyCode == 27) {
                $comment_wrapper.hide();
            }
        });

        // Don't close dialog if you click inside dialog
        $("fieldset#rate_comment_wrapper").mouseup(function() { return false; });

        // Close dialog if clicked outside dialog
        $(document).mouseup(function(e) {
            if($(e.target).parent("fieldset#rate_comment_wrapper").length === 0) {
                $("fieldset#rate_comment_wrapper").hide();
            }
        });

    }

};

/**
 * Fixed menu
 *
 * Fix the menu in place below a certain scroll height
 * 
 * Used on: all pages with the menu
 *
 * @namespace EDJ
 * @class fixed_menu
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.fixed_menu = {
    $menu: {},
    $content_pri_sub2: {},

    run: function() {
        this.$menu = EDJ.$body.find('#side_menu');
        return this.$menu.length > 0 && !EDJ.is_touch;
    },

    init: function() {
        var offset = this.$menu.offset(),
            fix_y = offset.top - 20,
            fix_x = offset.left;

        this.$content_pri_sub2 = this.$menu.parent();

        // If they scroll past our start point, then fix it
        $(window).bind('scroll resize', function() {
            var scroll_y = $(this).scrollTop(),
                css_position = EDJ.fixed_menu.$menu.css('position'),
                fix_x = EDJ.fixed_menu.$content_pri_sub2.offset().left,
                pos_x = EDJ.fixed_menu.$menu.css('left');

            if(scroll_y > fix_y && css_position == 'fixed' && fix_x != pos_x) {
                EDJ.fixed_menu.$menu.css('left', fix_x);
            } else if(scroll_y > fix_y && css_position != 'fixed') {
                EDJ.fixed_menu.$menu.css({
                    'position': 'fixed',
                    'marginTop': 20,
                    'top': '0',
                    'left': fix_x + 'px'
                });
            } else if (scroll_y < fix_y && css_position == 'fixed') {
                EDJ.fixed_menu.$menu.css({
                    'position': 'static',
                    'marginTop': '0',
                    'top': 'auto'
                });
            }
        });

    }
};


/**
 * FAQs
 *
 * Drop down the answer on clicking the question (and vice versa)
 *
 * Used on: FAQs
 *
 * @namespace EDJ
 * @class faqs 
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.faqs= {
    $faqs: {},

    run: function() {
        this.$faqs = EDJ.$body.find('ul.faq_listing');
        return this.$faqs.length > 0;
    },

    init: function() {
        var $questions = this.$faqs.find('h4.question'),
            $linked_question = {};

        // Open the FAQ when we click the header
        $questions.live('click', function() {
            $(this).parent('li').toggleClass('open');
            $(this).next('.answer').slideToggle(100);
            return false;
        });

        // Auto open the FAQ if there is a corresponding hashtag
        if (window.location.hash) {
            $linked_question = this.$faqs.find(window.location.hash + ' > h4');
            $.scrollTo(
                window.location.hash,
                350,
                { 'axis': 'y' }
            );
            $linked_question.trigger('click');
        }
    }
};

/**
 * Scroll to
 *
 * Smooth scrolling to an anchor
 * 
 * Uses the jQuery ScrollTo plugin
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 *
 * Used on: on this page menu on detail
 *
 * @namespace EDJ
 * @class scroll_to
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.scroll_to = {
    $on_this_page: {},
    
    run: function() {
        this.$on_this_page = $('#on_this_page ul li a');
        return this.$on_this_page.length > 0;
    },

    init: function() {
        this.$on_this_page.bind('click', function(event) {
            event.preventDefault();
            $.scrollTo(
                $(this).attr('href'), 
                350,
                { 'axis': 'y' }
            );
        });
    }
};

/**
 * Google maps
 *
 * Inserts a Google map into a div using a postcode rel
 * 
 * Uses the jQuery gMap plugin
 * https://github.com/marioestrada/jQuery-gMap
 *
 * Used on: on pages that have a .google_map div
 * 
 * @namespace EDJ
 * @class google_maps
 * ---------------------------------------------------------------------------------------------------
*/
EDJ.google_maps = {
    $maps: {},

    run: function() {
        this.$maps = $('div.google_map');
        return this.$maps.length > 0;
    },

    init: function() {
        var options = {
            controls: {
                       panControl: true,
                       zoomControl: true,
                       mapTypeControl: true,
                       scaleControl: true,
                       streetViewControl: true,
                       overviewMapControl: true
                   },
                scrollwheel: false,
                maptype: 'ROADMAP',
                zoom: 14
            };

        this.$maps.each(function() {
            var address = $(this).attr('title'),
                content = $(this).html();

            // If we can't find the address, quit now
            if (address == '') {
                return;
            }

            options.address = address;

            // If there is content, add it to a marker
            if (content != '') {
                options.markers = [{
                    address: address,
                    html: content
                }];
            }

            // Build the map
            $(this).gMap(options);

        });
    }
};

