<commit_before>/* -*- mode: espresso; espresso-indent-level: 4; indent-tabs-mode: nil -*-
 * fixmystreet.js
 * FixMyStreet JavaScript
 */

function form_category_onchange() {
    var cat = $('#form_category');
    var args = {
        category: cat.val()
    };

    if ( typeof fixmystreet !== 'undefined' ) {
        args.latitude = fixmystreet.latitude;
        args.longitude = fixmystreet.longitude;
    } else {
        args.latitude = $('input[name="latitude"]').val();
        args.longitude = $('input[name="longitude"]').val();
    }

    $.getJSON( CONFIG.FMS_URL + 'report/new/category_extras', args, function(data) {
        if ( data.category_extra ) {
            if ( $('#category_meta').size() ) {
                $('#category_meta').html( data.category_extra);
            } else {
                $('#form_category_row').after( data.category_extra );
            }
        } else {
            $('#category_meta').empty();
        }
    });
}

/*
 * general height fixing function
 *
 * elem1: element to check against
 * elem2: target element
 * offset: this will be added (if present) to the final value, useful for height errors
 */
function heightFix(elem1, elem2, offset){
    var h1 = $(elem1).height(),
        h2 = $(elem2).height();
    if(offset === undefined){
        offset = 0;
    }
    if(h1 > h2){
        $(elem2).css({'min-height':h1+offset});
    }
}


/*
 * very simple tab function
 *
 * elem: trigger element, must have an href attribute (so probably needs to be an <a>)
 */
function tabs(elem, indirect) {
    var href = elem.attr('href');
    //stupid IE sometimes adds the full uri into the href attr, so trim
    var start = href.indexOf('#'),
        target = href.slice(start, href.length);

    if (indirect) {
        elem = $(target + '_tab');
    }

    if(!$(target).hasClass('open'))
    {
        //toggle class on nav
        $('.tab-nav .active').removeClass('active');
        elem.addClass('active');
 
        //hide / show the right tab
        $('.tab.open').hide().removeClass('open');
        $(target).show().addClass('open');
    }
}


$(document).delegate( '#front-page', 'pageshow', function(event, ui) {
    if (geo_position_js.init() && !$('#geolocate_link').length) {
        $('#postcodeForm').after('<a href="#" id="geolocate_link">&hellip; or locate me automatically</a>');
        $('#geolocate_link').click(getPosition);
    }
});

$(document).bind('pageshow', function(){
    var $html = $('html');

    $html.removeClass('no-js').addClass('js');

    // Preload the new report pin
    document.createElement('img').src = '../i/pin-green.png';

    $('input[type=submit]').removeAttr('disabled');

    // FIXME - needs to use translated string
    jQuery.validator.addMethod('validCategory', function(value, element) {
        return this.optional(element) || value != '-- Pick a category --'; }, validation_strings.category );

    jQuery.validator.addMethod('validName', function(value, element) {
        var validNamePat = /\ba\s*n+on+((y|o)mo?u?s)?(ly)?\b/i;
        return this.optional(element) || value.length > 5 && value.match( /\S/ ) && !value.match( validNamePat ); }, validation_strings.category );

    var form_submitted = 0;
    var submitted = false;

    $("form.validate").validate({
        rules: {
            title: { required: true },
            detail: { required: true },
            email: { required: true },
            update: { required: true },
            rznvy: { required: true }
        },
        messages: validation_strings,
        onkeyup: false,
        onfocusout: false,
        errorElement: 'div',
        errorClass: 'form-error',
        // we do this to stop things jumping around on blur
        success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( '&nbsp;' ); } else { err.addClass('label-valid-hidden'); } },
        errorPlacement: function( error, element ) {
            element.before( error );
        },
        submitHandler: function(form) {
            if (form.submit_problem) {
                $('input[type=submit]', form).prop("disabled", true);
            }

            // this needs to be disabled otherwise it submits the form normally rather than
            // over AJAX. This comment is to make this more likely to happen when updating
            // this code.
            //form.submit();
        },
        // make sure we can see the error message when we focus on invalid elements
        showErrors: function( errorMap, errorList ) {
            if ( submitted && errorList.length ) {
               $(window).scrollTop( $(errorList[0].element).offset().top - 120 );
            }
            this.defaultShowErrors();
            submitted = false;
        },
        invalidHandler: function(form, validator) { submitted = true; }
    });

    $('input[type=submit]').click( function(e) { form_submitted = 1; } );

    /* set correct required status depending on what we submit 
    * NB: need to add things to form_category as the JS updating 
    * of this we do after a map click removes them */
    $('#submit_sign_in').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').removeClass();
    } );

    $('#submit_register').click( function(e) { 
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required validName');
    } );

    $('#problem_submit > input[type="submit"]').click( function(e) { 
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required validName');
    } );

    $('#update_post').click( function(e) { 
        $('#form_name').addClass('required').removeClass('valid');
    } );

    $('#form_category').change( form_category_onchange );

    /* 
     * Report a problem page 
     */
    //desktop
    if ($('#report-a-problem-sidebar').is(':visible')) {
        heightFix('#report-a-problem-sidebar', '.content', 26);
    }

    //show/hide notes on mobile
    $('.mobile #report-a-problem-sidebar').after('<a href="#" class="rap-notes-trigger button-right">How to send successful reports</a>').hide();
    $('.rap-notes-trigger').click(function(e){
        e.preventDefault();
        //check if we've already moved the notes
        if($('.rap-notes').length > 0){
            //if we have, show and hide .content
            $('.content').hide();
            $('.rap-notes').show();
        }else{
            //if not, move them and show, hiding .content
            $('.content').after('<div class="content rap-notes"></div>').hide();
            $('#report-a-problem-sidebar').appendTo('.rap-notes').show().after('<a href="#" class="rap-notes-close button-left">Back</a>');
        }
        $('html, body').scrollTop($('#report-a-problem-sidebar').offset().top);
        location.hash = 'rap-notes';
    });
    $('.mobile').on('click', '.rap-notes-close', function(e){
        e.preventDefault();
        //hide notes, show .content
        $('.content').show();
        $('.rap-notes').hide();
        $('html, body').scrollTop($('#mob_ok').offset().top);
        location.hash = 'report';
    });

    //move 'skip this step' link on mobile
    $('.mobile #skip-this-step').hide();
    $('.mobile #skip-this-step a').addClass('chevron').wrap('<li>').appendTo('#key-tools');

    /*
     * Tabs
     */
    //make initial tab active
    $('.tab-nav a').first().addClass('active');
    $('.tab').first().addClass('open');

    //hide other tabs
    $('.tab').not('.open').hide();

    //set up click event
    $(".tab-nav").on('click', 'a', function(e){
        e.preventDefault();
        tabs($(this));
    });
    $('.tab_link').click(function(e) {
        e.preventDefault();
        tabs($(this), 1);
    });

    /*
     * Skip to nav on mobile
     */
    $('.mobile').on('click', '#nav-link', function(e){
        e.preventDefault();
        var offset = $('#main-nav').offset().top;
        $('html, body').animate({scrollTop:offset}, 1000);
    });


    /*
     * Show stuff on input focus
     */
    $('.form-focus-trigger').on('focus', function(){
        $('.form-focus-hidden').fadeIn(500);
    });

    /*
     * Show on click - pretty generic
     */
    $('.hideshow-trigger').on('click', function(e){
        e.preventDefault();
        var href = $(this).attr('href'),
            //stupid IE sometimes adds the full uri into the href attr, so trim
            start = href.indexOf('#'),
            target = href.slice(start, href.length);

        $(target).removeClass('hidden-js');

        $(this).hide();
    });

    /*
     * nicetable - on mobile shift 'name' col to be a row
     */
    $('.mobile .nicetable th.title').remove();
    $('.mobile .nicetable td.title').each(function(i){
        $(this).attr('colspan', 5).insertBefore($(this).parent('tr')).wrap('<tr class="heading" />');
    });
    // $('.mobile .nicetable tr.heading > td.title').css({'min-width':'300px'});
    // $('.mobile .nicetable tr > td.data').css({'max-width':'12%'});

    /*
     * Map controls prettiness
     */
    //add links container (if its not there)
    if($('#sub_map_links').length === 0){
        $('<p id="sub_map_links" />').insertAfter($('#map'));
    }

// A sliding drawer from the bottom of the page, small version
// that doesn't change the main content at all.
$.fn.small_drawer = function(id) {
    this.toggle(function(){
        var $this = $(this), d = $('#' + id);
        if (!$this.addClass('hover').data('setup')) {
            d.hide().removeClass('hidden-js').css({
                padding: '1em',
                background: '#fff'
            });
            $this.data('setup', true);
        }
        d.slideDown();
    }, function(e){
        var $this = $(this), d = $('#' + id);
        $this.removeClass('hover');
        d.slideUp();
    });
};

// A sliding drawer from the bottom of the page, large version
$.fn.drawer = function(id, ajax) {
    // IE7 positions the fixed tool bar 1em to the left unless it comes after
    // the full-width section, ho-hum. Move it to where it would be after an
    // open/close anyway
    if ($('html.ie7').length) {
        var $sw = $('.shadow-wrap'), $content = $('.content[role="main"]');
        $sw.appendTo($content);
    }
    this.toggle(function(){
        var $this = $(this), d = $('#' + id), $content = $('.content[role="main"]');
        if (!$this.addClass('hover').data('setup')) {
            // make a drawer div with an innerDiv
            if (!d.length) {
                d = $('<div id="' + id + '">');
            }
            var innerDiv = $('<div>');
            d.wrapInner(innerDiv);

            // if ajax, load it with a spinner
            if (ajax) {
                var href = $this.attr('href') + ';ajax=1';
                $this.prepend(' <img class="spinner" src="/cobrands/fixmystreet/images/spinner-black-333.gif" style="margin-right:2em;">');
                innerDiv.load(href, function(){
                    $('.spinner').remove();
                });
            }

            // Tall drawer - put after .content for scrolling to work okay.
            // position over the top of the main .content in precisely the right location
            d.insertAfter($content).addClass('content').css({
                position: 'absolute',
                zIndex: '1100',
                marginTop: $('html.ie6, html.ie7').length ? '-3em' : 0, // IE6/7 otherwise include the 3em padding and stay too low
                left: 0,
                top: $(window).height() - $content.offset().top
            }).removeClass('hidden-js').find('h2').css({ marginTop: 0 });
            $this.data('setup', true);
        }

        //do the animation
        $('.shadow-wrap').prependTo(d).addClass('static');
        d.show().animate({top:'3em'}, 1000, function(){
            $content.fadeOut(function() {
                d.css({ position: 'relative' });
            });
        });
    }, function(e){
        var $this = $(this), d = $('#' + id), $sw = $('.shadow-wrap'),
            $content = $('.content[role="main"]'),
            tot_height = $(window).height() - d.offset().top;
        $this.removeClass('hover');
        d.css({ position: 'absolute' }).animate({ top: tot_height }, 1000, function(){
            d.hide();
            $sw.appendTo($content).removeClass('static');
        });
        $content.show();
    });
};

    if ($('html.mobile').length) {
        $('#council_wards').hide().removeClass('hidden-js').find('h2').hide();
        $('#key-tool-wards').click(function(e){
            e.preventDefault();
            $('#council_wards').slideToggle('800', function(){
              $('#key-tool-wards').toggleClass('active');
            });
        });
    } else {
        $('#key-tool-wards').drawer('council_wards', false);
        $('#key-tool-around-updates').drawer('updates_ajax', true);
    }
    $('#key-tool-report-updates').small_drawer('report-updates-data');

    // Go directly to RSS feed if RSS button clicked on alert page
    // (due to not wanting around form to submit, though good thing anyway)
    $('.container').on('click', '#alert_rss_button', function(e){
        e.preventDefault();
        var feed = $('input[name=feed][type=radio]:checked').nextAll('a').attr('href');
        window.location.href = feed;
    });
    $('.container').on('click', '#alert_email_button', function(e){
        e.preventDefault();
        var form = $('<form/>').attr({ method:'post', action:"/alert/subscribe" });
        form.append($('<input name="alert" value="Subscribe me to an email alert" type="hidden" />'));
        $('#alerts input[type=text], #alerts input[type=hidden], #alerts input[type=radio]:checked').each(function() {
            var $v = $(this);
            $('<input/>').attr({ name:$v.attr('name'), value:$v.val(), type:'hidden' }).appendTo(form);
        });
        form.submit();
    });

    //add permalink on desktop, force hide on mobile
    $('#sub_map_links').append('<a href="#" id="map_permalink">Permalink</a>');
    if($('.mobile').length){
        $('#map_permalink').hide();
        $('#key-tools a.feed').appendTo('#sub_map_links');
        $('#key-tools li:empty').remove();
        $('#report-updates-data').insertAfter($('#map_box'));
    }
    //add open/close toggle button on desk
    $('#sub_map_links').prepend('<span id="map_links_toggle">&nbsp;</span>');

    //set up map_links_toggle click event
    $('#map_links_toggle').on('click', function(){
        var maplinks_width = $('#sub_map_links').width();

        if($(this).hasClass('closed')){
            $(this).removeClass('closed');
            $('#sub_map_links').animate({'right':'0'}, 1200);
        }else{
            $(this).addClass('closed');
            $('#sub_map_links').animate({'right':-maplinks_width}, 1200);
        }
    });


    /*
     * Add close buttons for .promo's
     */
    if($('.promo').length){
        $('.promo').append('<a href="#" class="close-promo">x</a>');
    }
    //only close its own parent
    $('.promo').on('click', '.close-promo', function(e){
        e.preventDefault();
        $(this).parent('.promo').animate({
            'height':0,
            'margin-bottom':0,
            'padding-top':0,
            'padding-bottom':0
        },{
            duration:500,
            queue:false
        }).fadeOut(500);
    });



    /*
     * Fancybox fullscreen images
     */
    if (typeof $.fancybox == 'function') {
        $('a[rel=fancy]').fancybox({
            'overlayColor': '#000000'
        });
    }

    /*
     * heightfix the desktop .content div
     *
     * this must be kept near the end so that the
     * rendered height is used after any page manipulation (such as tabs)
     */
    if (!$('html.mobile').length) {
        if (!($('body').hasClass('frontpage'))){
            heightFix(window, '.content', -176);
        }
    }
});
<commit_msg>we never display this link so remove code for doing so<commit_after>/* -*- mode: espresso; espresso-indent-level: 4; indent-tabs-mode: nil -*-
 * fixmystreet.js
 * FixMyStreet JavaScript
 */

function form_category_onchange() {
    var cat = $('#form_category');
    var args = {
        category: cat.val()
    };

    if ( typeof fixmystreet !== 'undefined' ) {
        args.latitude = fixmystreet.latitude;
        args.longitude = fixmystreet.longitude;
    } else {
        args.latitude = $('input[name="latitude"]').val();
        args.longitude = $('input[name="longitude"]').val();
    }

    $.getJSON( CONFIG.FMS_URL + 'report/new/category_extras', args, function(data) {
        if ( data.category_extra ) {
            if ( $('#category_meta').size() ) {
                $('#category_meta').html( data.category_extra);
            } else {
                $('#form_category_row').after( data.category_extra );
            }
        } else {
            $('#category_meta').empty();
        }
    });
}

/*
 * general height fixing function
 *
 * elem1: element to check against
 * elem2: target element
 * offset: this will be added (if present) to the final value, useful for height errors
 */
function heightFix(elem1, elem2, offset){
    var h1 = $(elem1).height(),
        h2 = $(elem2).height();
    if(offset === undefined){
        offset = 0;
    }
    if(h1 > h2){
        $(elem2).css({'min-height':h1+offset});
    }
}


/*
 * very simple tab function
 *
 * elem: trigger element, must have an href attribute (so probably needs to be an <a>)
 */
function tabs(elem, indirect) {
    var href = elem.attr('href');
    //stupid IE sometimes adds the full uri into the href attr, so trim
    var start = href.indexOf('#'),
        target = href.slice(start, href.length);

    if (indirect) {
        elem = $(target + '_tab');
    }

    if(!$(target).hasClass('open'))
    {
        //toggle class on nav
        $('.tab-nav .active').removeClass('active');
        elem.addClass('active');
 
        //hide / show the right tab
        $('.tab.open').hide().removeClass('open');
        $(target).show().addClass('open');
    }
}


$(document).bind('pageshow', function(){
    var $html = $('html');

    $html.removeClass('no-js').addClass('js');

    // Preload the new report pin
    document.createElement('img').src = '../i/pin-green.png';

    $('input[type=submit]').removeAttr('disabled');

    // FIXME - needs to use translated string
    jQuery.validator.addMethod('validCategory', function(value, element) {
        return this.optional(element) || value != '-- Pick a category --'; }, validation_strings.category );

    jQuery.validator.addMethod('validName', function(value, element) {
        var validNamePat = /\ba\s*n+on+((y|o)mo?u?s)?(ly)?\b/i;
        return this.optional(element) || value.length > 5 && value.match( /\S/ ) && !value.match( validNamePat ); }, validation_strings.category );

    var form_submitted = 0;
    var submitted = false;

    $("form.validate").validate({
        rules: {
            title: { required: true },
            detail: { required: true },
            email: { required: true },
            update: { required: true },
            rznvy: { required: true }
        },
        messages: validation_strings,
        onkeyup: false,
        onfocusout: false,
        errorElement: 'div',
        errorClass: 'form-error',
        // we do this to stop things jumping around on blur
        success: function (err) { if ( form_submitted ) { err.addClass('label-valid').removeClass('label-valid-hidden').html( '&nbsp;' ); } else { err.addClass('label-valid-hidden'); } },
        errorPlacement: function( error, element ) {
            element.before( error );
        },
        submitHandler: function(form) {
            if (form.submit_problem) {
                $('input[type=submit]', form).prop("disabled", true);
            }

            // this needs to be disabled otherwise it submits the form normally rather than
            // over AJAX. This comment is to make this more likely to happen when updating
            // this code.
            //form.submit();
        },
        // make sure we can see the error message when we focus on invalid elements
        showErrors: function( errorMap, errorList ) {
            if ( submitted && errorList.length ) {
               $(window).scrollTop( $(errorList[0].element).offset().top - 120 );
            }
            this.defaultShowErrors();
            submitted = false;
        },
        invalidHandler: function(form, validator) { submitted = true; }
    });

    $('input[type=submit]').click( function(e) { form_submitted = 1; } );

    /* set correct required status depending on what we submit 
    * NB: need to add things to form_category as the JS updating 
    * of this we do after a map click removes them */
    $('#submit_sign_in').click( function(e) {
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').removeClass();
    } );

    $('#submit_register').click( function(e) { 
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required validName');
    } );

    $('#problem_submit > input[type="submit"]').click( function(e) { 
        $('#form_category').addClass('required validCategory').removeClass('valid');
        $('#form_name').addClass('required validName');
    } );

    $('#update_post').click( function(e) { 
        $('#form_name').addClass('required').removeClass('valid');
    } );

    $('#form_category').change( form_category_onchange );

    /* 
     * Report a problem page 
     */
    //desktop
    if ($('#report-a-problem-sidebar').is(':visible')) {
        heightFix('#report-a-problem-sidebar', '.content', 26);
    }

    //show/hide notes on mobile
    $('.mobile #report-a-problem-sidebar').after('<a href="#" class="rap-notes-trigger button-right">How to send successful reports</a>').hide();
    $('.rap-notes-trigger').click(function(e){
        e.preventDefault();
        //check if we've already moved the notes
        if($('.rap-notes').length > 0){
            //if we have, show and hide .content
            $('.content').hide();
            $('.rap-notes').show();
        }else{
            //if not, move them and show, hiding .content
            $('.content').after('<div class="content rap-notes"></div>').hide();
            $('#report-a-problem-sidebar').appendTo('.rap-notes').show().after('<a href="#" class="rap-notes-close button-left">Back</a>');
        }
        $('html, body').scrollTop($('#report-a-problem-sidebar').offset().top);
        location.hash = 'rap-notes';
    });
    $('.mobile').on('click', '.rap-notes-close', function(e){
        e.preventDefault();
        //hide notes, show .content
        $('.content').show();
        $('.rap-notes').hide();
        $('html, body').scrollTop($('#mob_ok').offset().top);
        location.hash = 'report';
    });

    //move 'skip this step' link on mobile
    $('.mobile #skip-this-step').hide();
    $('.mobile #skip-this-step a').addClass('chevron').wrap('<li>').appendTo('#key-tools');

    /*
     * Tabs
     */
    //make initial tab active
    $('.tab-nav a').first().addClass('active');
    $('.tab').first().addClass('open');

    //hide other tabs
    $('.tab').not('.open').hide();

    //set up click event
    $(".tab-nav").on('click', 'a', function(e){
        e.preventDefault();
        tabs($(this));
    });
    $('.tab_link').click(function(e) {
        e.preventDefault();
        tabs($(this), 1);
    });

    /*
     * Skip to nav on mobile
     */
    $('.mobile').on('click', '#nav-link', function(e){
        e.preventDefault();
        var offset = $('#main-nav').offset().top;
        $('html, body').animate({scrollTop:offset}, 1000);
    });


    /*
     * Show stuff on input focus
     */
    $('.form-focus-trigger').on('focus', function(){
        $('.form-focus-hidden').fadeIn(500);
    });

    /*
     * Show on click - pretty generic
     */
    $('.hideshow-trigger').on('click', function(e){
        e.preventDefault();
        var href = $(this).attr('href'),
            //stupid IE sometimes adds the full uri into the href attr, so trim
            start = href.indexOf('#'),
            target = href.slice(start, href.length);

        $(target).removeClass('hidden-js');

        $(this).hide();
    });

    /*
     * nicetable - on mobile shift 'name' col to be a row
     */
    $('.mobile .nicetable th.title').remove();
    $('.mobile .nicetable td.title').each(function(i){
        $(this).attr('colspan', 5).insertBefore($(this).parent('tr')).wrap('<tr class="heading" />');
    });
    // $('.mobile .nicetable tr.heading > td.title').css({'min-width':'300px'});
    // $('.mobile .nicetable tr > td.data').css({'max-width':'12%'});

    /*
     * Map controls prettiness
     */
    //add links container (if its not there)
    if($('#sub_map_links').length === 0){
        $('<p id="sub_map_links" />').insertAfter($('#map'));
    }

// A sliding drawer from the bottom of the page, small version
// that doesn't change the main content at all.
$.fn.small_drawer = function(id) {
    this.toggle(function(){
        var $this = $(this), d = $('#' + id);
        if (!$this.addClass('hover').data('setup')) {
            d.hide().removeClass('hidden-js').css({
                padding: '1em',
                background: '#fff'
            });
            $this.data('setup', true);
        }
        d.slideDown();
    }, function(e){
        var $this = $(this), d = $('#' + id);
        $this.removeClass('hover');
        d.slideUp();
    });
};

// A sliding drawer from the bottom of the page, large version
$.fn.drawer = function(id, ajax) {
    // IE7 positions the fixed tool bar 1em to the left unless it comes after
    // the full-width section, ho-hum. Move it to where it would be after an
    // open/close anyway
    if ($('html.ie7').length) {
        var $sw = $('.shadow-wrap'), $content = $('.content[role="main"]');
        $sw.appendTo($content);
    }
    this.toggle(function(){
        var $this = $(this), d = $('#' + id), $content = $('.content[role="main"]');
        if (!$this.addClass('hover').data('setup')) {
            // make a drawer div with an innerDiv
            if (!d.length) {
                d = $('<div id="' + id + '">');
            }
            var innerDiv = $('<div>');
            d.wrapInner(innerDiv);

            // if ajax, load it with a spinner
            if (ajax) {
                var href = $this.attr('href') + ';ajax=1';
                $this.prepend(' <img class="spinner" src="/cobrands/fixmystreet/images/spinner-black-333.gif" style="margin-right:2em;">');
                innerDiv.load(href, function(){
                    $('.spinner').remove();
                });
            }

            // Tall drawer - put after .content for scrolling to work okay.
            // position over the top of the main .content in precisely the right location
            d.insertAfter($content).addClass('content').css({
                position: 'absolute',
                zIndex: '1100',
                marginTop: $('html.ie6, html.ie7').length ? '-3em' : 0, // IE6/7 otherwise include the 3em padding and stay too low
                left: 0,
                top: $(window).height() - $content.offset().top
            }).removeClass('hidden-js').find('h2').css({ marginTop: 0 });
            $this.data('setup', true);
        }

        //do the animation
        $('.shadow-wrap').prependTo(d).addClass('static');
        d.show().animate({top:'3em'}, 1000, function(){
            $content.fadeOut(function() {
                d.css({ position: 'relative' });
            });
        });
    }, function(e){
        var $this = $(this), d = $('#' + id), $sw = $('.shadow-wrap'),
            $content = $('.content[role="main"]'),
            tot_height = $(window).height() - d.offset().top;
        $this.removeClass('hover');
        d.css({ position: 'absolute' }).animate({ top: tot_height }, 1000, function(){
            d.hide();
            $sw.appendTo($content).removeClass('static');
        });
        $content.show();
    });
};

    if ($('html.mobile').length) {
        $('#council_wards').hide().removeClass('hidden-js').find('h2').hide();
        $('#key-tool-wards').click(function(e){
            e.preventDefault();
            $('#council_wards').slideToggle('800', function(){
              $('#key-tool-wards').toggleClass('active');
            });
        });
    } else {
        $('#key-tool-wards').drawer('council_wards', false);
        $('#key-tool-around-updates').drawer('updates_ajax', true);
    }
    $('#key-tool-report-updates').small_drawer('report-updates-data');

    // Go directly to RSS feed if RSS button clicked on alert page
    // (due to not wanting around form to submit, though good thing anyway)
    $('.container').on('click', '#alert_rss_button', function(e){
        e.preventDefault();
        var feed = $('input[name=feed][type=radio]:checked').nextAll('a').attr('href');
        window.location.href = feed;
    });
    $('.container').on('click', '#alert_email_button', function(e){
        e.preventDefault();
        var form = $('<form/>').attr({ method:'post', action:"/alert/subscribe" });
        form.append($('<input name="alert" value="Subscribe me to an email alert" type="hidden" />'));
        $('#alerts input[type=text], #alerts input[type=hidden], #alerts input[type=radio]:checked').each(function() {
            var $v = $(this);
            $('<input/>').attr({ name:$v.attr('name'), value:$v.val(), type:'hidden' }).appendTo(form);
        });
        form.submit();
    });

    //add permalink on desktop, force hide on mobile
    $('#sub_map_links').append('<a href="#" id="map_permalink">Permalink</a>');
    if($('.mobile').length){
        $('#map_permalink').hide();
        $('#key-tools a.feed').appendTo('#sub_map_links');
        $('#key-tools li:empty').remove();
        $('#report-updates-data').insertAfter($('#map_box'));
    }
    //add open/close toggle button on desk
    $('#sub_map_links').prepend('<span id="map_links_toggle">&nbsp;</span>');

    //set up map_links_toggle click event
    $('#map_links_toggle').on('click', function(){
        var maplinks_width = $('#sub_map_links').width();

        if($(this).hasClass('closed')){
            $(this).removeClass('closed');
            $('#sub_map_links').animate({'right':'0'}, 1200);
        }else{
            $(this).addClass('closed');
            $('#sub_map_links').animate({'right':-maplinks_width}, 1200);
        }
    });


    /*
     * Add close buttons for .promo's
     */
    if($('.promo').length){
        $('.promo').append('<a href="#" class="close-promo">x</a>');
    }
    //only close its own parent
    $('.promo').on('click', '.close-promo', function(e){
        e.preventDefault();
        $(this).parent('.promo').animate({
            'height':0,
            'margin-bottom':0,
            'padding-top':0,
            'padding-bottom':0
        },{
            duration:500,
            queue:false
        }).fadeOut(500);
    });



    /*
     * Fancybox fullscreen images
     */
    if (typeof $.fancybox == 'function') {
        $('a[rel=fancy]').fancybox({
            'overlayColor': '#000000'
        });
    }

    /*
     * heightfix the desktop .content div
     *
     * this must be kept near the end so that the
     * rendered height is used after any page manipulation (such as tabs)
     */
    if (!$('html.mobile').length) {
        if (!($('body').hasClass('frontpage'))){
            heightFix(window, '.content', -176);
        }
    }
});

{'fraction_non_alphanumeric': 0.19419579760670874, 'fraction_numerical': 0.006470052451396087, 'mean_word_length': 2.3015346329323934, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4473910', 'n_tokens_mistral': 9495, 'n_tokens_neox': 9209, 'n_words': 2066}