<commit_before>var detailsLat, detailsLon;

// Handlebars helpers

Handlebars.registerHelper('carouselimages', function(spacedata) {
    var space_id = spacedata.id;
    var elements = new Array;
    for (i=0; i < spacedata.images.length; i++) {
        image_id = spacedata.images[i].id;
        elements.push('

');
    }
    return new Handlebars.SafeString(elements.join('\n'));
});

Handlebars.registerHelper('compare', function(lvalue, rvalue, options) {

    if (arguments.length < 3)
        throw new Error("Handlerbars Helper 'compare' needs 2 parameters");

    operator = options.hash.operator || "==";

    var operators = {
        '==':       function(l,r) { return l == r; },
        '===':      function(l,r) { return l === r; },
        '!=':       function(l,r) { return l != r; },
        '<':        function(l,r) { return l < r; },
        '>':        function(l,r) { return l > r; },
        '<=':       function(l,r) { return l <= r; },
        '>=':       function(l,r) { return l >= r; },
        'typeof':   function(l,r) { return typeof l == r; }
    }

    if (!operators[operator])
        throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+operator);

    var result = operators[operator](lvalue,rvalue);

    if( result ) {
        return options.fn(this);
    } else {
        return options.inverse(this);
    }

});

(function(m) {

    var deviceAgent = navigator.userAgent.toLowerCase();

    // detect ios versions
	var iphone = deviceAgent.match(/(ipad|iphone)/);
	var ios56 = navigator.userAgent.match(/OS [56](_\d)+ like Mac OS X/i);

    // detect android versions
    var android = deviceAgent.match(/(android)/);
    var gingerbread = deviceAgent.match(/android 2\.3/i);
    var gingerbreadOrNewer = deviceAgent.match(/android [2-9]/i);
    var honeycombOrNewer = deviceAgent.match(/android [3-9]/i);
    var froyoOrOlder = android && !gingerbread && !honeycombOrNewer;

	$(document).ready(function() {

		mobileContent();

		// initialize the carousel for mobile standalone space page
        initializeCarousel();
        resizeCarouselMapContainer();

        // scroll to the top of page
        $('#top_link').click(function(e){
              // Prevent a page reload when a link is pressed
              e.preventDefault();
              // Call the scroll function
              scrollTo('top');
        });

        // scroll to top of filter list
        $('#filter_link').click(function(e){
              // Prevent a page reload when a link is pressed
              e.preventDefault();
              // Call the scroll function
              scrollTo('info_list');
        });

        // back to spaces button on mobile space details page
        $('#back_home_button').click(function() {
            location.href = '/';
        });

        // for iphones (ios5-6) - check if they have the ios detector cookie, if they don't give them one and show the popup
        // otherwise, don't do anything since they've already seen the popup
        if (iphone && ios56) {
            if (!$.cookie('showSpaceScoutiOS')){
                $.cookie('showSpaceScoutiOS', 'true');
                showIosCallout();
            }
        }

		// Toggle Filter display
		$('#filter_button').click(function() {

    		resizeFilterBlock();

    		if ($("#filter_block").is(":hidden")) {

                $("#filter_block").slideDown('slow');

                $('#filter_button').hide();
                $('#view_results_button').show();
                $('#cancel_results_button').show();

                // if mobile
                $('#main_content').hide();
                $('#footer').hide();
                $('.back-top').hide();

                // handle scrolling for android froyo or newer
        		if (android || gingerbreadOrNewer) {
            		touchScroll("filter_block");
        		}

            } else {

                // if mobile
                $('#main_content').show();
                $('#footer').show();
                $('.back-top').show();

                $('#filter_button').show();
                $('#view_results_button').hide();
                $('#cancel_results_button').hide();

                $("#filter_block").slideUp('slow');
            }
        });

        // Close the filter display using Cancel button
        $('#cancel_results_button').click(function() {

            // reset the map
            clear_custom_search();

            // if mobile
            $('#main_content').show();
            $('#footer').show();
            $('.back-top').show();

            $('#filter_button').show();
            $('#view_results_button').hide();
            $('#cancel_results_button').hide();

            $("#filter_block").slideUp('slow', function() {
                // Animation complete.
                mobileContent();
            });

            // reset checkboxes
            $('input[type=checkbox]').each(function() {
                if ($(this).attr('checked')) {
                    $(this).attr('checked', false);
                    $(this).parent().removeClass("selected");
                }
            });

            // reset capacity
            $('#capacity').val('1');

            // reset hours
            $('#open_now').prop('checked', true);
            $('#open_now').parent().removeClass("selected");
            $('#hours_list_container').hide();
            $('#hours_list_input').parent().removeClass("selected");
            var date = new Date();
            var hour = date.getHours();
            var min = date.getMinutes();

            if (min < 16) {
                min = "00";
            }else if (min < 46) {
                min = "30";
            }else {
                min = "00";
                hour++;
            }

            if (hour > 11) {
                $("#ampm-from").val("PM");
            }else {
                $("#ampm-from").val("AM");
            }
            if (hour > 12) {
                hour = hour-12;
            }
            hour = ""+hour+":"+min;
            $("#day-from").val(weekdays[date.getDay()])
            $("#hour-from").val(hour)

            $("#day-until").val("No pref")
            $("#hour-until").val("No pref")
            $("#ampm-until").val("AM")

            // reset location
            $('#entire_campus').prop('checked', true);
            $('#entire_campus').parent().removeClass("selected");
            $('#building_list_container').hide();
            $('#building_list_input').parent().removeClass("selected");
            $('#building_list_container').children().children().children(".select2-search-choice").remove();
            $('#building_list_container').children().children().children().children().val('Select Building(s)');
            $('#building_list_container').children().children().children().children().attr('style', "");

        });
        var weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
        var date = new Date();
        var hour = date.getHours();
        var min = date.getMinutes();

        if (min < 16) {
            min = "00";
        }else if (min < 46) {
            min = "30";
        }else {
            min = "00";
            hour++;
        }

        if (hour > 11) {
            $("#ampm-from").val("PM");
        }else {
            $("#ampm-from").val("AM");
        }
        if (hour > 12) {
            hour = hour-12;
        }
        hour = ""+hour+":"+min;
        $("#day-from").val(weekdays[date.getDay()])
        $("#hour-from").val(hour)

        // handle view details click
        $('.view-details').live('click', function(e){

            // get the space id
            id =  $(this).find('.space-detail-list-item').attr('id');

            e.preventDefault();

            //clear any unneded pending ajax window.requests
            for (i = 0; i < window.requests.length; i++) {
                window.requests[i].abort();
            }
            window.requests.push(
                $.ajax({
                    url: '/space/'+id+'/json/',
                    success: showSpaceDetails
                })
            );

        });

        // handle checkbox and radio button clicks
        $('.checkbox input:checkbox').click(function() {
            if(this.checked) {
                $(this).parent().addClass("selected");
            }
            else {
                $(this).parent().removeClass("selected");
            }
        });

        $('#filter_hours input:radio').change(function() {
            $(this).parent().addClass("selected");
            $(this).parent().siblings().removeClass("selected");

            if ($('#hours_list_input').is(':checked')) {
                $('#hours_list_container').show();
            }
            else {
                $('#hours_list_container').hide();
            }
        });

        $('#filter_location input:radio').change(function() {
            $(this).parent().addClass("selected");
            $(this).parent().siblings().removeClass("selected");

            if ($('#building_list_input').is(':checked')) {
                $('#building_list_container').show();
            }
            else {
                $('#building_list_container').hide();
            }

        });

        // Toggle between carousel and map
        $('.space-image-map-buttons button').live('click', function(e){

            if ($('#carouselControl').hasClass('active')) { // show the carousel
                $('#spaceCarouselContainer').show();
                $('#spaceMap').hide();
            }
            else { //show the map
                $('#spaceCarouselContainer').hide();
                $('#spaceMap').show();
                getSpaceMap(detailsLat, detailsLon);
            }
        });

	});

	// Update dimensions on resize
	$(m).resize(function(){

	   mobileContent();
	   resizeCarouselMapContainer();

	   if ($('#filter_block').is(":visible")) {
    	   resizeFilterBlock();
	   }

	});

	// Show space details (sliding transition)
	function showSpaceDetails(data) {
    	// change url
    	location.href = '/space/' + data.id;
	}

	// ScrollTo a spot on the UI
	function scrollTo(id) {
        // Scroll
        $('html,body').animate({ scrollTop: $("#"+id).offset().top},'fast');
    }

    // Mobile display defaults
    function mobileContent() {

        var windowH = $(window).height();
        var headerH = $('#nav').height();
        //var contentH = windowH - headerH;
        //var mainContentH = windowH - headerH + 35;
        var mapH = windowH - headerH - 35; // enough to show the loading spinner at the bottom of the viewport

        $('#map_canvas').height(mapH);
        $('#map_canvas').css({ minHeight: mapH })
        $('#info_list').height('auto');

    }

    function initializeCarousel() {

        $('.carousel').each(function(){
            $(this).carousel({
                interval: false
            });

            //set the first item as active
            $(this).find(".item:first-child").addClass("active");

            // hide the controls if only 1 picture exists
            if ($(this).find('.item').length == 1) {
                 $(this).find('.carousel-control').hide();
            }
        });

    }

    function resizeFilterBlock() {
        var winH = $(window).height();
        $("#filter_block").height(winH - 110);
    }

    function resizeCarouselMapContainer() {
        // get the width
        var containerW = $('.image-container').width();

        // calcuate height based on 3:2 aspect ratio
        var containerH = containerW / 1.5;

        $('.carousel').height(containerH);
        $('.map-container').height(containerH);
    }

    // callout for ios5-6 native app
    function showIosCallout() {

        $('#ios_callout').show(0, function() {
            // Animation complete.
            $('.ios-inner-container').show("slide", { direction: "down" }, 700);
            // disable the iphone scroll
            document.ontouchmove = function(event){ event.preventDefault(); }
        });

        $('#continue_webapp').click(function() {
            // close the modal
            $('#ios_callout').hide();
            // enable scrolling
            document.ontouchmove = function(event){ return true; }
        });

        $('#download_native').click(function() {
            // redirect to app store
            window.location = "http://itunes.apple.com/us/app/spacescout/id551472160";
            // enable scrolling
            document.ontouchmove = function(event){ return true; }
        });
    }

    // enable div overflow scrolling for android
    function touchScroll(id) {

		var el=document.getElementById(id);
		var scrollStartPos=0;

		document.getElementById(id).addEventListener("touchstart", function(event) {
			scrollStartPos=this.scrollTop+event.touches[0].pageY;
		},false);

		document.getElementById(id).addEventListener("touchmove", function(event) {
			this.scrollTop=scrollStartPos-event.touches[0].pageY;
		},false);

    }

})(this);
<commit_msg>clear filter button fix for mobile<commit_after>var detailsLat, detailsLon;

// Handlebars helpers

Handlebars.registerHelper('carouselimages', function(spacedata) {
    var space_id = spacedata.id;
    var elements = new Array;
    for (i=0; i < spacedata.images.length; i++) {
        image_id = spacedata.images[i].id;
        elements.push('

');
    }
    return new Handlebars.SafeString(elements.join('\n'));
});

Handlebars.registerHelper('compare', function(lvalue, rvalue, options) {

    if (arguments.length < 3)
        throw new Error("Handlerbars Helper 'compare' needs 2 parameters");

    operator = options.hash.operator || "==";

    var operators = {
        '==':       function(l,r) { return l == r; },
        '===':      function(l,r) { return l === r; },
        '!=':       function(l,r) { return l != r; },
        '<':        function(l,r) { return l < r; },
        '>':        function(l,r) { return l > r; },
        '<=':       function(l,r) { return l <= r; },
        '>=':       function(l,r) { return l >= r; },
        'typeof':   function(l,r) { return typeof l == r; }
    }

    if (!operators[operator])
        throw new Error("Handlerbars Helper 'compare' doesn't know the operator "+operator);

    var result = operators[operator](lvalue,rvalue);

    if( result ) {
        return options.fn(this);
    } else {
        return options.inverse(this);
    }

});

(function(m) {

    var deviceAgent = navigator.userAgent.toLowerCase();

    // detect ios versions
	var iphone = deviceAgent.match(/(ipad|iphone)/);
	var ios56 = navigator.userAgent.match(/OS [56](_\d)+ like Mac OS X/i);

    // detect android versions
    var android = deviceAgent.match(/(android)/);
    var gingerbread = deviceAgent.match(/android 2\.3/i);
    var gingerbreadOrNewer = deviceAgent.match(/android [2-9]/i);
    var honeycombOrNewer = deviceAgent.match(/android [3-9]/i);
    var froyoOrOlder = android && !gingerbread && !honeycombOrNewer;

	$(document).ready(function() {

		mobileContent();

		// initialize the carousel for mobile standalone space page
        initializeCarousel();
        resizeCarouselMapContainer();

        // scroll to the top of page
        $('#top_link').click(function(e){
              // Prevent a page reload when a link is pressed
              e.preventDefault();
              // Call the scroll function
              scrollTo('top');
        });

        // scroll to top of filter list
        $('#filter_link').click(function(e){
              // Prevent a page reload when a link is pressed
              e.preventDefault();
              // Call the scroll function
              scrollTo('info_list');
        });

        // back to spaces button on mobile space details page
        $('#back_home_button').click(function() {
            location.href = '/';
        });

        // for iphones (ios5-6) - check if they have the ios detector cookie, if they don't give them one and show the popup
        // otherwise, don't do anything since they've already seen the popup
        if (iphone && ios56) {
            if (!$.cookie('showSpaceScoutiOS')){
                $.cookie('showSpaceScoutiOS', 'true');
                showIosCallout();
            }
        }

		// Toggle Filter display
		$('#filter_button').click(function() {

    		resizeFilterBlock();

    		if ($("#filter_block").is(":hidden")) {

                $("#filter_block").slideDown('slow');

                $('#filter_button').hide();
                $('#view_results_button').show();
                $('#cancel_results_button').show();

                // if mobile
                $('#main_content').hide();
                $('#footer').hide();
                $('.back-top').hide();

                // handle scrolling for android froyo or newer
        		if (android || gingerbreadOrNewer) {
            		touchScroll("filter_block");
        		}

            } else {

                // if mobile
                $('#main_content').show();
                $('#footer').show();
                $('.back-top').show();

                $('#filter_button').show();
                $('#view_results_button').hide();
                $('#cancel_results_button').hide();

                $("#filter_block").slideUp('slow');
            }
        });

        // Close the filter display using Cancel button
        $('#cancel_results_button').click(function() {

            // reset the map
            //clear_custom_search();

            // if mobile
            /*$('#main_content').show();
            $('#footer').show();
            $('.back-top').show();

            $('#filter_button').show();
            $('#view_results_button').hide();
            $('#cancel_results_button').hide();

            $("#filter_block").slideUp('slow', function() {
                // Animation complete.
                mobileContent();
            });*/

            // reset checkboxes
            $('input[type=checkbox]').each(function() {
                if ($(this).attr('checked')) {
                    $(this).attr('checked', false);
                    $(this).parent().removeClass("selected");
                }
            });

            // reset capacity
            $('#capacity').val('1');

            // reset hours
            $('#open_now').prop('checked', true);
            $('#open_now').parent().removeClass("selected");
            $('#hours_list_container').hide();
            $('#hours_list_input').parent().removeClass("selected");
            var date = new Date();
            var hour = date.getHours();
            var min = date.getMinutes();

            if (min < 16) {
                min = "00";
            }else if (min < 46) {
                min = "30";
            }else {
                min = "00";
                hour++;
            }

            if (hour > 11) {
                $("#ampm-from").val("PM");
            }else {
                $("#ampm-from").val("AM");
            }
            if (hour > 12) {
                hour = hour-12;
            }
            hour = ""+hour+":"+min;
            $("#day-from").val(weekdays[date.getDay()])
            $("#hour-from").val(hour)

            $("#day-until").val("No pref")
            $("#hour-until").val("No pref")
            $("#ampm-until").val("AM")

            // reset location
            $('#entire_campus').prop('checked', true);
            $('#entire_campus').parent().removeClass("selected");
            $('#building_list_container').hide();
            $('#building_list_input').parent().removeClass("selected");
            $('#building_list_container').children().children().children(".select2-search-choice").remove();
            $('#building_list_container').children().children().children().children().val('Select Building(s)');
            $('#building_list_container').children().children().children().children().attr('style', "");

        });
        var weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
        var date = new Date();
        var hour = date.getHours();
        var min = date.getMinutes();

        if (min < 16) {
            min = "00";
        }else if (min < 46) {
            min = "30";
        }else {
            min = "00";
            hour++;
        }

        if (hour > 11) {
            $("#ampm-from").val("PM");
        }else {
            $("#ampm-from").val("AM");
        }
        if (hour > 12) {
            hour = hour-12;
        }
        hour = ""+hour+":"+min;
        $("#day-from").val(weekdays[date.getDay()])
        $("#hour-from").val(hour)

        // handle view details click
        $('.view-details').live('click', function(e){

            // get the space id
            id =  $(this).find('.space-detail-list-item').attr('id');

            e.preventDefault();

            //clear any unneded pending ajax window.requests
            for (i = 0; i < window.requests.length; i++) {
                window.requests[i].abort();
            }
            window.requests.push(
                $.ajax({
                    url: '/space/'+id+'/json/',
                    success: showSpaceDetails
                })
            );

        });

        // handle checkbox and radio button clicks
        $('.checkbox input:checkbox').click(function() {
            if(this.checked) {
                $(this).parent().addClass("selected");
            }
            else {
                $(this).parent().removeClass("selected");
            }
        });

        $('#filter_hours input:radio').change(function() {
            $(this).parent().addClass("selected");
            $(this).parent().siblings().removeClass("selected");

            if ($('#hours_list_input').is(':checked')) {
                $('#hours_list_container').show();
            }
            else {
                $('#hours_list_container').hide();
            }
        });

        $('#filter_location input:radio').change(function() {
            $(this).parent().addClass("selected");
            $(this).parent().siblings().removeClass("selected");

            if ($('#building_list_input').is(':checked')) {
                $('#building_list_container').show();
            }
            else {
                $('#building_list_container').hide();
            }

        });

        // Toggle between carousel and map
        $('.space-image-map-buttons button').live('click', function(e){

            if ($('#carouselControl').hasClass('active')) { // show the carousel
                $('#spaceCarouselContainer').show();
                $('#spaceMap').hide();
            }
            else { //show the map
                $('#spaceCarouselContainer').hide();
                $('#spaceMap').show();
                getSpaceMap(detailsLat, detailsLon);
            }
        });

	});

	// Update dimensions on resize
	$(m).resize(function(){

	   mobileContent();
	   resizeCarouselMapContainer();

	   if ($('#filter_block').is(":visible")) {
    	   resizeFilterBlock();
	   }

	});

	// Show space details (sliding transition)
	function showSpaceDetails(data) {
    	// change url
    	location.href = '/space/' + data.id;
	}

	// ScrollTo a spot on the UI
	function scrollTo(id) {
        // Scroll
        $('html,body').animate({ scrollTop: $("#"+id).offset().top},'fast');
    }

    // Mobile display defaults
    function mobileContent() {

        var windowH = $(window).height();
        var headerH = $('#nav').height();
        //var contentH = windowH - headerH;
        //var mainContentH = windowH - headerH + 35;
        var mapH = windowH - headerH - 35; // enough to show the loading spinner at the bottom of the viewport

        $('#map_canvas').height(mapH);
        $('#map_canvas').css({ minHeight: mapH })
        $('#info_list').height('auto');

    }

    function initializeCarousel() {

        $('.carousel').each(function(){
            $(this).carousel({
                interval: false
            });

            //set the first item as active
            $(this).find(".item:first-child").addClass("active");

            // hide the controls if only 1 picture exists
            if ($(this).find('.item').length == 1) {
                 $(this).find('.carousel-control').hide();
            }
        });

    }

    function resizeFilterBlock() {
        var winH = $(window).height();
        $("#filter_block").height(winH - 110);
    }

    function resizeCarouselMapContainer() {
        // get the width
        var containerW = $('.image-container').width();

        // calcuate height based on 3:2 aspect ratio
        var containerH = containerW / 1.5;

        $('.carousel').height(containerH);
        $('.map-container').height(containerH);
    }

    // callout for ios5-6 native app
    function showIosCallout() {

        $('#ios_callout').show(0, function() {
            // Animation complete.
            $('.ios-inner-container').show("slide", { direction: "down" }, 700);
            // disable the iphone scroll
            document.ontouchmove = function(event){ event.preventDefault(); }
        });

        $('#continue_webapp').click(function() {
            // close the modal
            $('#ios_callout').hide();
            // enable scrolling
            document.ontouchmove = function(event){ return true; }
        });

        $('#download_native').click(function() {
            // redirect to app store
            window.location = "http://itunes.apple.com/us/app/spacescout/id551472160";
            // enable scrolling
            document.ontouchmove = function(event){ return true; }
        });
    }

    // enable div overflow scrolling for android
    function touchScroll(id) {

		var el=document.getElementById(id);
		var scrollStartPos=0;

		document.getElementById(id).addEventListener("touchstart", function(event) {
			scrollStartPos=this.scrollTop+event.touches[0].pageY;
		},false);

		document.getElementById(id).addEventListener("touchmove", function(event) {
			this.scrollTop=scrollStartPos-event.touches[0].pageY;
		},false);

    }

})(this);
<|endoftext|>


<commit_before>function Socket(url) {
    this.url = url;
    this._is_open = false;
    this._is_authenticated = false;
    this._send_queue = [];
    this._next_req_id = 0;
    this._requests = {};
    this._connection_failures = 0;

    this._is_unloading = false;
    $(window).on("unload", function () {
        this._is_unloading = true;
    });

    this._supported_protocols = ['websocket', 'xdr-streaming', 'xhr-streaming',
                                 'xdr-polling', 'xhr-polling', 'jsonp-polling'];
    if (page_params.test_suite) {
        this._supported_protocols = _.reject(this._supported_protocols,
                                             function (x) { return x === 'xhr-streaming'; });
    }

    this._sockjs = new SockJS(url, null, {protocols_whitelist: this._supported_protocols});
    this._setup_sockjs_callbacks(this._sockjs);
}

Socket.prototype = {
    send: function Socket_send(msg, success, error) {
        if (! this._can_send()) {
            this._send_queue.push({msg: msg, success: success, error: error});
            return;
        }

        this._do_send('request', msg, success, error);
    },

    _do_send: function Socket__do_send(type, msg, success, error) {
        var req_id = this._next_req_id;
        this._next_req_id++;
        this._requests[req_id] = {success: success, error: error};
        // TODO: I think we might need to catch exceptions here for certain transports
        this._sockjs.send(JSON.stringify({client_meta: {req_id: req_id},
                                          type: type, request: msg}));
    },

    _can_send: function Socket__can_send() {
        return this._is_open && this._is_authenticated;
    },

    _drain_queue_send: function Socket__drain_queue_send() {
        var that = this;
        var queue = this._send_queue;
        this._send_queue = [];
        _.each(queue, function (elem) {
            that.send(elem.msg, elem.success, elem.error);
        });
    },

    _drain_queue_error: function Socket__drain_queue_error() {
        var that = this;
        var queue = this._send_queue;
        this._send_queue = [];
        _.each(queue, function (elem) {
            elem.error('connection');
        });
    },

    _setup_sockjs_callbacks: function Socket__setup_sockjs_callbacks(sockjs) {
        var that = this;
        sockjs.onopen = function Socket__sockjs_onopen() {
            blueslip.info("Socket connected.");
            that._is_open = true;

            // We can only authenticate after the DOM has loaded because we need
            // the CSRF token
            $(function () {
                that._do_send('auth', {csrf_token: csrf_token},
                              function () {
                                  that._is_authenticated = true;
                                  that._connection_failures = 0;
                                  that._drain_queue_send();
                              },
                              function (type, resp) {
                                  blueslip.info("Could not authenticate with server: " + resp.msg);
                                  that._try_to_reconnect();
                              });
            });
        };

        sockjs.onmessage = function Socket__sockjs_onmessage(event) {
            var req_info = that._requests[event.data.client_meta.req_id];
            if (req_info === undefined) {
                blueslip.error("Got a response for an unknown request");
                return;
            }

            if (event.data.response.result === 'success') {
                req_info.success(event.data.response);
            } else {
                req_info.error('response', event.data.response);
            }
        };

        sockjs.onclose = function Socket__sockjs_onclose() {
            if (that._is_unloading) {
                return;
            }
            blueslip.info("SockJS connection lost.  Attempting to reconnect soon.");
            that._try_to_reconnect();
        };
    },

    _try_to_reconnect: function Socket__try_to_reconnect() {
        var that = this;
        this._is_open = false;
        this._is_authenticated = false;
        this._connection_failures++;
        this._drain_queue_error();

        var wait_time;
        if (this._connection_failures === 1) {
            // We specify a non-zero timeout here so that we don't try to
            // immediately reconnect when the page is refreshing
            wait_time = 30;
        } else {
            wait_time = Math.min(90, Math.exp(this._connection_failures/2)) * 1000;
        }

        setTimeout(function () {
            blueslip.info("Attempting socket reconnect.");
            that._sockjs = new SockJS(that.url, null, {protocols_whitelist: that._supported_protocols});
            that._setup_sockjs_callbacks(that._sockjs);
        }, wait_time);
    }
};
<commit_msg>socket: Remove old requests<commit_after>function Socket(url) {
    this.url = url;
    this._is_open = false;
    this._is_authenticated = false;
    this._send_queue = [];
    this._next_req_id = 0;
    this._requests = {};
    this._connection_failures = 0;

    this._is_unloading = false;
    $(window).on("unload", function () {
        this._is_unloading = true;
    });

    this._supported_protocols = ['websocket', 'xdr-streaming', 'xhr-streaming',
                                 'xdr-polling', 'xhr-polling', 'jsonp-polling'];
    if (page_params.test_suite) {
        this._supported_protocols = _.reject(this._supported_protocols,
                                             function (x) { return x === 'xhr-streaming'; });
    }

    this._sockjs = new SockJS(url, null, {protocols_whitelist: this._supported_protocols});
    this._setup_sockjs_callbacks(this._sockjs);
}

Socket.prototype = {
    send: function Socket_send(msg, success, error) {
        if (! this._can_send()) {
            this._send_queue.push({msg: msg, success: success, error: error});
            return;
        }

        this._do_send('request', msg, success, error);
    },

    _do_send: function Socket__do_send(type, msg, success, error) {
        var req_id = this._next_req_id;
        this._next_req_id++;
        this._requests[req_id] = {success: success, error: error};
        // TODO: I think we might need to catch exceptions here for certain transports
        this._sockjs.send(JSON.stringify({client_meta: {req_id: req_id},
                                          type: type, request: msg}));
    },

    _can_send: function Socket__can_send() {
        return this._is_open && this._is_authenticated;
    },

    _drain_queue_send: function Socket__drain_queue_send() {
        var that = this;
        var queue = this._send_queue;
        this._send_queue = [];
        _.each(queue, function (elem) {
            that.send(elem.msg, elem.success, elem.error);
        });
    },

    _drain_queue_error: function Socket__drain_queue_error() {
        var that = this;
        var queue = this._send_queue;
        this._send_queue = [];
        _.each(queue, function (elem) {
            elem.error('connection');
        });
    },

    _setup_sockjs_callbacks: function Socket__setup_sockjs_callbacks(sockjs) {
        var that = this;
        sockjs.onopen = function Socket__sockjs_onopen() {
            blueslip.info("Socket connected.");
            that._is_open = true;

            // We can only authenticate after the DOM has loaded because we need
            // the CSRF token
            $(function () {
                that._do_send('auth', {csrf_token: csrf_token},
                              function () {
                                  that._is_authenticated = true;
                                  that._connection_failures = 0;
                                  that._drain_queue_send();
                              },
                              function (type, resp) {
                                  blueslip.info("Could not authenticate with server: " + resp.msg);
                                  that._try_to_reconnect();
                              });
            });
        };

        sockjs.onmessage = function Socket__sockjs_onmessage(event) {
            var req_id = event.data.client_meta.req_id;
            var req_info = that._requests[req_id];
            if (req_info === undefined) {
                blueslip.error("Got a response for an unknown request");
                return;
            }

            if (event.data.response.result === 'success') {
                req_info.success(event.data.response);
            } else {
                req_info.error('response', event.data.response);
            }
            delete that._requests[req_id];
        };

        sockjs.onclose = function Socket__sockjs_onclose() {
            if (that._is_unloading) {
                return;
            }
            blueslip.info("SockJS connection lost.  Attempting to reconnect soon.");
            that._try_to_reconnect();
        };
    },

    _try_to_reconnect: function Socket__try_to_reconnect() {
        var that = this;
        this._is_open = false;
        this._is_authenticated = false;
        this._connection_failures++;
        this._drain_queue_error();

        var wait_time;
        if (this._connection_failures === 1) {
            // We specify a non-zero timeout here so that we don't try to
            // immediately reconnect when the page is refreshing
            wait_time = 30;
        } else {
            wait_time = Math.min(90, Math.exp(this._connection_failures/2)) * 1000;
        }

        setTimeout(function () {
            blueslip.info("Attempting socket reconnect.");
            that._sockjs = new SockJS(that.url, null, {protocols_whitelist: that._supported_protocols});
            that._setup_sockjs_callbacks(that._sockjs);
        }, wait_time);
    }
};
<|endoftext|>


<commit_before>var cp437 = {};

cp437.codepage = "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜ¢£¥₧ƒáíóúñÑªº¿⌐¬½¼¡«»░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀αßΓπΣσµτΦΘΩδ∞φε∩≡±≥≤⌠⌡÷≈°∙·√ⁿ²■ "

cp437.encode = function(codePoint) {
    return cp437.codepage.charAt(codePoint);
}

cp437.decode = function(c) {
    return cp437.codepage.indexOf(c);
}

function genChar() {
	var code = prompt("Generate CP437 Character:");
    if(!code)
        return;
	$('#code').val($('#code').val() + cp437.encode(parseInt(code)));
	updateByteCount();
};

function getByteCount(s) {
    var count = 0, stringLength = s.length;
    s = String(s || "");
    for (var i = 0; i < stringLength; i++) {
        var partCount = encodeURI(s[i]).split("%").length;
        count += partCount == 1 ? 1 : partCount - 1;
    }
    return count;
}

function updateByteCount() {
	var c = $('#code').val();
	var byteCount = c.length;
	var charCount = c.length;
	var s = byteCount + " bytes and " + charCount + " chars long.";
	$('#byteCount').html(s);
}

function getExplanation() {
    var string = false;
    var codeBlock = false;
    var listBlock = false;
    var numBlock = false;
    var code = $('#code').val();
    var explain = '';
    for(var x=0; x < code.length; x++) {
        var c = code.charAt(x);
        if(c === '"') {
            if(string) {
                var prev = code.lastIndexOf('"',x-1);
                var strval = code.slice(prev+1,x);
                explain += 'push the string value "'+strval+'"\r\n'
            }
            string = !string;
            continue;
        } else if(c === '`') {
            if(codeBlock) {
                var prev = code.lastIndexOf('`',x-1);
                var strval = code.slice(prev+1,x);
                explain += 'push the function value `'+strval+'`\r\n'
            }
            codeBlock = !codeBlock;
            continue;
        } else if(c === '[') {
            listBlock = true;
            continue;
        } else if(c === ':') {
            if(numBlock) {
                var prev = code.lastIndexOf(':',x-1);
                var strval = code.slice(prev+1,x);
                explain += 'push the numeric value "'+strval+'"\r\n'
            }
            numBlock = !numBlock;
            continue;
        } else if(c === ']') {
            listBlock = false;
            var prev = code.lastIndexOf('[',x-1);
            var strval = code.slice(prev+1,x);
            explain += 'push the list value "'+strval+'"\r\n'
            continue;
        }
        if(codeBlock || string || listBlock || numBlock) {
            continue;
        }
        if(cp437.decode(c) > -1)
            explain += explanations[cp437.decode(c)] +'\r\n';
    }
    if(string) {
        var prev = code.lastIndexOf('"',x-1);
        var strval = code.slice(prev+1,x);
        explain += 'push the string value "'+strval+'"\r\n'
    } else if(codeBlock) {
        var prev = code.lastIndexOf('"',x-1);
        var strval = code.slice(prev+1,x);
        explain += 'push the function value `'+strval+'`\r\n'
    } else if(listBlock) {
        var prev = code.lastIndexOf('[',x-1);
        var strval = code.slice(prev+1,x);
        explain += 'push the list value "'+strval+'"\r\n'
    } else if(numBlock) {
        var prev = code.lastIndexOf(':',x-1);
        var strval = code.slice(prev+1,x);
        explain += 'push the numeric value "'+strval+'"\r\n'
    }
    $('#explanation').html(explain);
}

function updateUtils() {
	updateByteCount();
	getExplanation();
}

updateUtils();

$(document).ready(
		function() {
			$("#permalink").click(
					function() {
						var code = encodeURIComponent($('#code').val());
						var	input = encodeURIComponent($('#input').val());
						var resp = prompt("Permalink:", "http://"
								+ window.location.hostname + "/link/" + code + "/" + input);
                        if(resp != null)
                            window.location.pathname = "/link/" + code + "/" + input;
					});
			$('#code').on('input propertychange paste', function() {
				updateUtils();
			});
            $("input").keypress(function(e){
                var charCode = !e.charCode ? e.which : e.charCode;
                var c = String.fromCharCode(charCode);
                if(cp437.decode(c) < 0)
                    e.preventDefault();
            });
		});<commit_msg>prepare for rollback<commit_after><|endoftext|>


<commit_before>(function(jQuery, undefined) {
    jQuery.widget('Midgard.midgardCreate', {
        options: {
            statechange: function() {},
            toolbar: 'full',
            saveButton: null,
            state: 'browse',
            highlightColor: '#67cc08'
        },

        _create: function() {
            this.vie = new VIE({classic: true});
            this._checkSession();
            this._enableToolbar();
            this._saveButton();
            this._editButton();
            this.element.midgardStorage({vie: this.vie});
        },

        _init: function() {
            if (this.options.state === 'edit') {
                this._enableEdit();
            } else {
                this._disableEdit();
            }
        },

        _checkSession: function() {
            if (!Modernizr.sessionstorage) {
                return;
            }

            if (sessionStorage.getItem('Midgard.create.toolbar')) {
                this._setOption('toolbar', sessionStorage.getItem('Midgard.create.toolbar'));
            }

            if (sessionStorage.getItem('Midgard.create.state')) {
                this._setOption('state', sessionStorage.getItem('Midgard.create.state'));
            }

            this.element.bind('midgardcreatestatechange', function(event, state) {
                sessionStorage.setItem('Midgard.create.state', state);
            });
        },

        _saveButton: function() {
            if (this.options.saveButton) {
                return this.options.saveButton;
            }

            jQuery('#midgard-bar .toolbarcontent-right').append(jQuery('<button id="midgardcreate-save">Save</button>'));
            this.options.saveButton = jQuery('#midgardcreate-save');
            this.options.saveButton.button({disabled: true})
            return this.options.saveButton;
        },

        _editButton: function() {
            var widget = this;
            jQuery('#midgard-bar .toolbarcontent-right').append(jQuery('<input type="checkbox" id="midgardcreate-edit" />Edit'));
            var editButton = jQuery('#midgardcreate-edit').button();
            if (this.options.state === 'edit') {
                editButton.attr('checked', true);
                editButton.button('refresh');
            }
            editButton.bind('change', function() {
                if (editButton.attr('checked')) {
                    widget._enableEdit();
                    return;
                }
                widget._disableEdit();
            });
        },

        _enableToolbar: function() {
            var widget = this;
            this.element.bind('midgardtoolbarstatechange', function(event, options) {
                if (Modernizr.sessionstorage) {
                    sessionStorage.setItem('Midgard.create.toolbar', options.display);
                }
                widget._setOption('toolbar', options.display);
            });

            this.element.midgardToolbar({display: this.options.toolbar, vie: this.vie});
        },

        _enableEdit: function() {
            var widget = this;
            jQuery('[about]').each(function() {
                var element = this;
                var highlightEditable = function(event, options) {
                    if (options.entityElement.get(0) !== element) {
                        // Propagated event from another entity, ignore
                        return;
                    }

                    // Highlight the editable
                    options.element.effect('highlight', {color: widget.options.highlightColor}, 3000);
                };

                jQuery(this).bind('midgardeditableenableproperty', highlightEditable);
                jQuery(this).bind('midgardeditabledisable', function() {
                    jQuery(this).unbind('midgardeditableenableproperty', highlightEditable);
                });
                jQuery(this).midgardEditable({disabled: false, vie: widget.vie});
            });
            this._setOption('state', 'edit');
            this._trigger('statechange', null, 'edit');
        },

        _disableEdit: function() {
            var widget = this;
            jQuery('[about]').each(function() {
                jQuery(this).midgardEditable({disabled: true, vie: widget.vie}).removeClass('ui-state-disabled');
            });
            this._setOption('state', 'browse');
            this._trigger('statechange', null, 'browse');
        }
    })
})(jQuery);
<commit_msg>Expose editor selection in midgardCreate widget options, fixes #3<commit_after>(function(jQuery, undefined) {
    jQuery.widget('Midgard.midgardCreate', {
        options: {
            statechange: function() {},
            toolbar: 'full',
            saveButton: null,
            state: 'browse',
            highlightColor: '#67cc08',
            editor: 'hallo'
        },

        _create: function() {
            this.vie = new VIE({classic: true});
            this._checkSession();
            this._enableToolbar();
            this._saveButton();
            this._editButton();
            this.element.midgardStorage({vie: this.vie});
        },

        _init: function() {
            if (this.options.state === 'edit') {
                this._enableEdit();
            } else {
                this._disableEdit();
            }
        },

        _checkSession: function() {
            if (!Modernizr.sessionstorage) {
                return;
            }

            if (sessionStorage.getItem('Midgard.create.toolbar')) {
                this._setOption('toolbar', sessionStorage.getItem('Midgard.create.toolbar'));
            }

            if (sessionStorage.getItem('Midgard.create.state')) {
                this._setOption('state', sessionStorage.getItem('Midgard.create.state'));
            }

            this.element.bind('midgardcreatestatechange', function(event, state) {
                sessionStorage.setItem('Midgard.create.state', state);
            });
        },

        _saveButton: function() {
            if (this.options.saveButton) {
                return this.options.saveButton;
            }

            jQuery('#midgard-bar .toolbarcontent-right').append(jQuery('<button id="midgardcreate-save">Save</button>'));
            this.options.saveButton = jQuery('#midgardcreate-save');
            this.options.saveButton.button({disabled: true})
            return this.options.saveButton;
        },

        _editButton: function() {
            var widget = this;
            jQuery('#midgard-bar .toolbarcontent-right').append(jQuery('<input type="checkbox" id="midgardcreate-edit" />Edit'));
            var editButton = jQuery('#midgardcreate-edit').button();
            if (this.options.state === 'edit') {
                editButton.attr('checked', true);
                editButton.button('refresh');
            }
            editButton.bind('change', function() {
                if (editButton.attr('checked')) {
                    widget._enableEdit();
                    return;
                }
                widget._disableEdit();
            });
        },

        _enableToolbar: function() {
            var widget = this;
            this.element.bind('midgardtoolbarstatechange', function(event, options) {
                if (Modernizr.sessionstorage) {
                    sessionStorage.setItem('Midgard.create.toolbar', options.display);
                }
                widget._setOption('toolbar', options.display);
            });

            this.element.midgardToolbar({display: this.options.toolbar, vie: this.vie});
        },

        _enableEdit: function() {
            var widget = this;
            jQuery('[about]').each(function() {
                var element = this;
                var highlightEditable = function(event, options) {
                    if (options.entityElement.get(0) !== element) {
                        // Propagated event from another entity, ignore
                        return;
                    }

                    // Highlight the editable
                    options.element.effect('highlight', {color: widget.options.highlightColor}, 3000);
                };

                jQuery(this).bind('midgardeditableenableproperty', highlightEditable);
                jQuery(this).bind('midgardeditabledisable', function() {
                    jQuery(this).unbind('midgardeditableenableproperty', highlightEditable);
                });
                jQuery(this).midgardEditable({disabled: false, vie: widget.vie, editor: widget.options.editor});
            });
            this._setOption('state', 'edit');
            this._trigger('statechange', null, 'edit');
        },

        _disableEdit: function() {
            var widget = this;
            jQuery('[about]').each(function() {
                jQuery(this).midgardEditable({disabled: true, vie: widget.vie, editor: widget.options.editor}).removeClass('ui-state-disabled');
            });
            this._setOption('state', 'browse');
            this._trigger('statechange', null, 'browse');
        }
    })
})(jQuery);
<|endoftext|>


<commit_before>/*
 *  Event Based Animation v1.0 - jQuery plugin
 *
 *  Copyright (c) 2012 Deux Huit Huit (http://www.deuxhuithuit.com/)
 *  Licensed under the MIT (https://raw.github.com/DeuxHuitHuit/jQuery-event-based-animation/master/LICENSE.txt)
 */
(function ($, undefined) {

	"use strict";

	if (!$.isFunction($.isString)) {
		$.isString = function (object) {
			return $.type(object) === 'string';
		};
	}

	$.fn.eventAnimate = function (options) {

		var

		// the target DOMElement
		t = $(this),

		// Window object
		win = $(window),

		// Quick timestamp
		now = $.now,

		// Safe division
		sdiv = function (n, d) {
			if (!n || !d) {
				return 0;
			}
			return n/d;
		},

		// Quick iterator
		_forEach = function (o, iterator) {
			$.each(o.properties, iterator);
		},

		// Quick setter
		_setEach = function (o, object, values) {
			_forEach(o, function (index, key) {
				object[key] = $.isFunction(values) ?
								values(key) :
								($.isArray(values) ? values[key] : values);
			});
		},

		// Quick validator
		_validateEach = function (o, validator, operation) {
			// Fix arguments
			if ($.isFunction(operation)) {
				var oldVal = validator;
				validator = operation;
				operation = oldVal;
			} else if (operation !== '||') {
				operation = '&&';
			}
			var
			isAnd = operation === '&&',
			and = function (a,b) { return a && b; },
			or = function (a,b) { return a && b; },
			fx = isAnd ? and : or,
			result = isAnd; // add true if and, false if or

			_forEach(o, function (index, key) {
				result = fx(result, validator(key));
				if ((isAnd && result) || (!isAnd && !result)) {
					return false; // exit
				}
			});

			return result;
		}

		// Last event triggered
		eventTimeStamp = now(),

		// Last animation frame
		lastAnimatedTimeStamp = eventTimeStamp,

		// Current running animation duration
		currentAnimationDuration = {},

		// Current animation start values
		currentStartAnimationPosition = {},

		// Save the target position (updated by the event)
		targetPosition = {},

		// Save the distance between current position and the target (Refreshed at every tick)
		targetDistance = {},

		// Save the current ghost position (Refreshed when tick apply animation)
		currentPosition = {},

		_initVariables = function (o) {
			_setEach(o, currentAnimationDuration, 0);
			_setEach(o, currentStartAnimationPosition, 0);
			_setEach(o, targetPosition, 0);
			_setEach(o, targetDistance, 0);
			_setEach(o, currentPosition, 0);
		},

		_setTimeout = function (fx, delay) {
			var w = window,
				frm = w.requestAnimationFrame || w.mozRequestAnimationFrame ||
					w.webkitRequestAnimationFrame || w.msRequestAnimationFrame ||
					w.oRequestAnimationFrame || w.setTimeout;

			return frm(fx, frm === w.setTimeout ? delay : o.container.get(0));
		},

		_clearTimeout = function (timeout) {
			var w = window,
				frm = w.cancelAnimationFrame || w.webkitCancelRequestAnimationFrame ||
					w.mozCancelRequestAnimationFrame || w.oCancelRequestAnimationFrame ||
					w.msCancelRequestAnimationFrame  || w.clearTimeout;

			return frm(timeout);
		},

		//Reference the current timer
		timer = null,

		isMoving = false,

		defaultOffset = {left:0,top:0},

		// Event Strategies implementation
		_handleScroll = function (e, o, targetPosition) {
			targetPosition.x = o.container.scrollLeft();
			targetPosition.y = o.container.scrollTop();
		},

		_handleMouse = function (e, o, targetPosition) {
			var offset = o.container.offset() || defaultOffset;
			targetPosition.x = e.pageX - offset.left;
			targetPosition.y = e.pageY - offset.top;
		},

		_handleTouch = function (e, o, targetPosition) {
			var offset = o.container.offset() || defaultOffset,
				touch = e.originalEvent.touches[0];
			targetPosition.x = touch.pageX - offset.left;
			targetPosition.y = touch.pageY - offset.top;
		},

		// Defaults Event Strategies
		_eventStrategies = {
			scroll: _handleScroll,
			click: _handleMouse,
			mouseover: _handleMouse,
			mousemove: _handleMouse,
			touchmove: _handleTouch
		},

		// Handle the container event
		_handleEvent = function (e) {
			var
			eventName = e.type || o.event,
			strategy = _eventStrategies[eventName];

			if ($.isFunction(strategy)) {
				// Call the strategy
				strategy.call(t, e, o, targetPosition);

				// Update the event time
				if (!isMoving || !!o.restartOnEvent) {
					eventTimeStamp = now()-1; // make it in the past
				}

				//  Schedule frame if not moving
				if (!isMoving) {

					// Only schedule for frame
					if (!!o.delayStart) {
						startTimer();
					}
					// Start the animation right now
					else {
						_nextFrame();
					}
				}

			} else if (!!window.console) {
				console.err('No strategy found for event "' + eventName + '"');
			}
		},

		// Start a new timer
		startTimer = function () {
			if (!_checkStop(o)) {
				timer = _setTimeout(_nextFrame, o.tick);
			}
			// animation stopped, so no timer is allowed
			else {
				_clearTimeout(timer);
				timer = null;
			}
			return timer;
		},

		// Parses the duration options
		_getDuration = function(o, targetDistance, startValues, targetValues) {
			var r = {};
			if ($.isFunction(o.duration)) {
				var result = o.duration.call(t, o, targetDistance);
				_setEach(o, r, function (key) {
					return Math.abs(result[key] || result || targetDistance[key]) * o.durationRatio;
				});
			} else {
				_setEach(o, r, function (key) {
					return Math.abs(o.duration[key] || o.duration || targetDistance[key]) * o.durationRatio;
				});
			}
			return r;
		},

		// parses the startValue options
		_getStartValues = function (o) {
			var startValues = null;
			if ($.isFunction(o.startValues)) {
				startValues = o.startValues(o);
			}
			if (!startValues) {
				startValues = currentPosition;
			}
			return startValues;
		},

		// Calculate the first "legacy" easing parameter
		_getLegacyEasingValue = function (o, currentAnimationTime) {
			var e = {};
			_setEach(o, e, function (key) {
				return currentStartAnimationPosition[key] + (Math.min(1, sdiv(currentAnimationTime, currentAnimationDuration[key])) * (targetPosition[key] - currentStartAnimationPosition[key]));
			});
			return e;
		},

		_debugOutput = function (o, linearPosition, easingCurPosition, currentAnimationTime) {
			if (!!window.console && console.log && !!o.debug) {
				_forEach(o, function (index, key) {
					if (o.debug === true || o.debug[key] === true) {
						console.log(lastAnimatedTimeStamp +
								' Target ' + key + ' ' + parseInt(targetPosition[key],10) +
								' - Start ' + parseInt(currentStartAnimationPosition[key],10) +
								' - Linear ' + parseInt(linearPosition[key],10) +
								' - Eased ' + parseInt(easingCurPosition[key],10) +
								' - Time ' + Math.min(currentAnimationTime, currentAnimationDuration[key]) +
								' - Duration ' + currentAnimationDuration[key]);
					}
				});
			}
		},

		// Allow to stop the animation
		_checkStop = function (o) {
			if (!$.isFunction(o.stop)) {
				return false;
			}
			return o.stop(o);
		},

		// Called at every tick
		_nextFrame = function () {

			if(!_checkStop(o)) {

				// save travel distance needed
				_setEach(o, targetDistance, function (key) {
					return targetPosition[key] - currentPosition[key];
				});

				// animation : Do we have something to travel
				if (targetDistance.x !== 0 || targetDistance.y !== 0) {

					// if the value changed since lass pass,
					// i.e. an event occur between two frames
					// or before the current one
					if (eventTimeStamp > lastAnimatedTimeStamp) {

						// Save the start point of the animation
						var startValues = _getStartValues(o);

						// Update target distances
						targetDistance.x = targetPosition.x - startValues.x;
						targetDistance.y = targetPosition.y - startValues.y;

						// Update current duration
						currentAnimationDuration = _getDuration(o, targetDistance, startValues, targetPosition);

						// Set start as current
						currentStartAnimationPosition = startValues;

						// Set Last Animated Time Stamp to the new scroll Event Time Stamp
						// This acts as the new animation start
						if (!isMoving || !!o.restartOnEvent) {
							lastAnimatedTimeStamp = now();
						}
					} // if scrolled

					// Begin Var
					var

					// Current animation time (where are we rith now)
					currentAnimationTime = now() - lastAnimatedTimeStamp,

					// Linear/swing algorigthm
					linearPosition = _getLegacyEasingValue(o, currentAnimationTime),
					easingFx = o.easing || $.easing.def || 'linear',
					easingCurPosition = {
						// We documented the parameter names and logic, since there is an error on
						// the main doc: http://gsgd.co.uk/sandbox/jquery/easing/. end_value is actually a diff.
						//                    old_fx,           current_time,                                               start_value,                     end_value-start_value,                             duration
						x: $.easing[easingFx](linearPosition.x, Math.min(currentAnimationTime, currentAnimationDuration.x), currentStartAnimationPosition.x, targetPosition.x-currentStartAnimationPosition.x, currentAnimationDuration.x),
						y: $.easing[easingFx](linearPosition.y, Math.min(currentAnimationTime, currentAnimationDuration.y), currentStartAnimationPosition.y, targetPosition.y-currentStartAnimationPosition.y, currentAnimationDuration.y)
					};

					// end var

					// DEBUG
					_debugOutput(o, linearPosition, easingCurPosition, currentAnimationTime);

					if ($.isNumeric(easingCurPosition.x) && $.isNumeric(easingCurPosition.y)) {
						// update currentPosition state
						currentPosition = easingCurPosition;
					}

					// Start Callback
					if (!isMoving && $.isFunction(o.start)) {
						o.start.call(t, currentAnimationTime, currentPosition);
					}

					// Assure moving flag is on
					isMoving = true;

					// if we still have time left on the animation
					if (currentAnimationTime < currentAnimationDuration.x ||
						currentAnimationTime < currentAnimationDuration.y) {
						// queue next frame
						startTimer();
					} else {
						// animation stopped
						timer = null;
						isMoving = false;
					}

					// call callback with new ghost position
					if ($.isFunction(o.step)) {
						o.step.call(t, currentAnimationTime, currentPosition);
					}

					// End Callback
					if (timer === null) {
						if ($.isFunction(o.complete)) {
							o.complete.call(t, currentAnimationTime, currentPosition);
						}
						// reset if we have to
						currentPosition = _getStartValues(o);
					}

				}
				// no distance found
				else {
					// animation won't run
					timer = null;
					isMoving = false;
				}
			}
			// animation stopped
			else {
				// we stop, no timer is needed
				timer = null;
				isMoving = false;
			}
		},

		// assure minimal option object
		o = $.extend({
			container: null, // The DOMElement where to listen the event. Target if omitted.
			tick: 16, // Default timeout when requestAnimationFrame is not available. In ms.
			event: 'scroll', // The event(s) to listen for changes
			properties: 'x y', // The properties that we are animating (array or string)
			delayStart: false, // Make the event schedule next frame instead of calling it
			duration: 0, // Both axis animation duration. Numeric, object (x:1,y:1} or function
			durationRatio: 1, // Duration modifier. Particularly usefull when duration depends on distance
			restartOnEvent: false, // creates an absolute start time instead of relative to the last event
			stop: null, // A stop function to stop the animation. Your logic, your rules.
			step: null, // A function to call at each step of the animation.
			complete: null, // A callback function called when the animation ends.
			start: null, // A callback function called when the animation begins.
			easing: null, // A easing function to use. $.easing.def or linear if omitted.
			strategy: null, // A strategy function for your custom event.
			startValues: null, // A function that permits override of the stating values
			debug: false // Set to true to get extra data in the console. Can be set per axis {x:false, y:true}
		}, options);

		// If not container is set, use the target
		o.container = $(o.container || t);

		// Add the new strategy if needed
		if ($.isFunction(o.strategy)) {
			_eventStrategies[o.event] = o.strategy;
		}
		// If strategy is a string, try code re-use
		else if ($.isString(o.strategy)) {
			_eventStrategies[o.event] = _eventStrategies[o.strategy];
		}
		// If strategy is an object, add multiple events
		else if ($.isPlainObject(o.strategy)) {
			$.each(o.strategy, function _importStrategy(key, s) {
				_eventStrategies[key] = s;
			});
		}

		// Split into array if it is a string
		if ($.isString(o.properties)) {
			o.properties = o.properties.split(' ');
		}

		// If no animatable properties have been found
		if (!$.isArray(o.properties) || o.properties.length < 1) {
			// Cannot continue
			return t;
		}

		// Init "globals"
		_initVariables(o);

		// Hook up on event
		o.container.on(o.event, _handleEvent);

		// Always return jQuery object
		return t;

	}; // end $.fn.extend
})(jQuery);
<commit_msg>Get rid of index param in _forEach callback<commit_after>/*
 *  Event Based Animation v1.0 - jQuery plugin
 *
 *  Copyright (c) 2012 Deux Huit Huit (http://www.deuxhuithuit.com/)
 *  Licensed under the MIT (https://raw.github.com/DeuxHuitHuit/jQuery-event-based-animation/master/LICENSE.txt)
 */
(function ($, undefined) {

	"use strict";

	if (!$.isFunction($.isString)) {
		$.isString = function (object) {
			return $.type(object) === 'string';
		};
	}

	$.fn.eventAnimate = function (options) {

		var

		// the target DOMElement
		t = $(this),

		// Window object
		win = $(window),

		// Quick timestamp
		now = $.now,

		// Safe division
		sdiv = function (n, d) {
			if (!n || !d) {
				return 0;
			}
			return n/d;
		},

		// Quick iterator
		_forEach = function (o, iterator) {
			$.each(o.properties, function _each(index, key) {
				iterator(key);
			});
		},

		// Quick setter
		_setEach = function (o, object, values) {
			_forEach(o, function (key) {
				object[key] = $.isFunction(values) ?
								values(key) :
								($.isArray(values) ? values[key] : values);
			});
		},

		// Quick validator
		_validateEach = function (o, validator, operation) {
			// Fix arguments
			if ($.isFunction(operation)) {
				var oldVal = validator;
				validator = operation;
				operation = oldVal;
			} else if (operation !== '||') {
				operation = '&&';
			}
			var
			isAnd = operation === '&&',
			and = function (a,b) { return a && b; },
			or = function (a,b) { return a && b; },
			fx = isAnd ? and : or,
			result = isAnd; // add true if and, false if or

			_forEach(o, function (key) {
				result = fx(result, validator(key));
				if ((isAnd && result) || (!isAnd && !result)) {
					return false; // exit
				}
			});

			return result;
		}

		// Last event triggered
		eventTimeStamp = now(),

		// Last animation frame
		lastAnimatedTimeStamp = eventTimeStamp,

		// Current running animation duration
		currentAnimationDuration = {},

		// Current animation start values
		currentStartAnimationPosition = {},

		// Save the target position (updated by the event)
		targetPosition = {},

		// Save the distance between current position and the target (Refreshed at every tick)
		targetDistance = {},

		// Save the current ghost position (Refreshed when tick apply animation)
		currentPosition = {},

		_initVariables = function (o) {
			_setEach(o, currentAnimationDuration, 0);
			_setEach(o, currentStartAnimationPosition, 0);
			_setEach(o, targetPosition, 0);
			_setEach(o, targetDistance, 0);
			_setEach(o, currentPosition, 0);
		},

		_setTimeout = function (fx, delay) {
			var w = window,
				frm = w.requestAnimationFrame || w.mozRequestAnimationFrame ||
					w.webkitRequestAnimationFrame || w.msRequestAnimationFrame ||
					w.oRequestAnimationFrame || w.setTimeout;

			return frm(fx, frm === w.setTimeout ? delay : o.container.get(0));
		},

		_clearTimeout = function (timeout) {
			var w = window,
				frm = w.cancelAnimationFrame || w.webkitCancelRequestAnimationFrame ||
					w.mozCancelRequestAnimationFrame || w.oCancelRequestAnimationFrame ||
					w.msCancelRequestAnimationFrame  || w.clearTimeout;

			return frm(timeout);
		},

		//Reference the current timer
		timer = null,

		isMoving = false,

		defaultOffset = {left:0,top:0},

		// Event Strategies implementation
		_handleScroll = function (e, o, targetPosition) {
			targetPosition.x = o.container.scrollLeft();
			targetPosition.y = o.container.scrollTop();
		},

		_handleMouse = function (e, o, targetPosition) {
			var offset = o.container.offset() || defaultOffset;
			targetPosition.x = e.pageX - offset.left;
			targetPosition.y = e.pageY - offset.top;
		},

		_handleTouch = function (e, o, targetPosition) {
			var offset = o.container.offset() || defaultOffset,
				touch = e.originalEvent.touches[0];
			targetPosition.x = touch.pageX - offset.left;
			targetPosition.y = touch.pageY - offset.top;
		},

		// Defaults Event Strategies
		_eventStrategies = {
			scroll: _handleScroll,
			click: _handleMouse,
			mouseover: _handleMouse,
			mousemove: _handleMouse,
			touchmove: _handleTouch
		},

		// Handle the container event
		_handleEvent = function (e) {
			var
			eventName = e.type || o.event,
			strategy = _eventStrategies[eventName];

			if ($.isFunction(strategy)) {
				// Call the strategy
				strategy.call(t, e, o, targetPosition);

				// Update the event time
				if (!isMoving || !!o.restartOnEvent) {
					eventTimeStamp = now()-1; // make it in the past
				}

				//  Schedule frame if not moving
				if (!isMoving) {

					// Only schedule for frame
					if (!!o.delayStart) {
						startTimer();
					}
					// Start the animation right now
					else {
						_nextFrame();
					}
				}

			} else if (!!window.console) {
				console.err('No strategy found for event "' + eventName + '"');
			}
		},

		// Start a new timer
		startTimer = function () {
			if (!_checkStop(o)) {
				timer = _setTimeout(_nextFrame, o.tick);
			}
			// animation stopped, so no timer is allowed
			else {
				_clearTimeout(timer);
				timer = null;
			}
			return timer;
		},

		// Parses the duration options
		_getDuration = function(o, targetDistance, startValues, targetValues) {
			var r = {};
			if ($.isFunction(o.duration)) {
				var result = o.duration.call(t, o, targetDistance);
				_setEach(o, r, function (key) {
					return Math.abs(result[key] || result || targetDistance[key]) * o.durationRatio;
				});
			} else {
				_setEach(o, r, function (key) {
					return Math.abs(o.duration[key] || o.duration || targetDistance[key]) * o.durationRatio;
				});
			}
			return r;
		},

		// parses the startValue options
		_getStartValues = function (o) {
			var startValues = null;
			if ($.isFunction(o.startValues)) {
				startValues = o.startValues(o);
			}
			if (!startValues) {
				startValues = currentPosition;
			}
			return startValues;
		},

		// Calculate the first "legacy" easing parameter
		_getLegacyEasingValue = function (o, currentAnimationTime) {
			var e = {};
			_setEach(o, e, function (key) {
				return currentStartAnimationPosition[key] + (Math.min(1, sdiv(currentAnimationTime, currentAnimationDuration[key])) * (targetPosition[key] - currentStartAnimationPosition[key]));
			});
			return e;
		},

		_debugOutput = function (o, linearPosition, easingCurPosition, currentAnimationTime) {
			if (!!window.console && console.log && !!o.debug) {
				_forEach(o, function (key) {
					if (o.debug === true || o.debug[key] === true) {
						console.log(lastAnimatedTimeStamp +
								' Target ' + key + ' ' + parseInt(targetPosition[key],10) +
								' - Start ' + parseInt(currentStartAnimationPosition[key],10) +
								' - Linear ' + parseInt(linearPosition[key],10) +
								' - Eased ' + parseInt(easingCurPosition[key],10) +
								' - Time ' + Math.min(currentAnimationTime, currentAnimationDuration[key]) +
								' - Duration ' + currentAnimationDuration[key]);
					}
				});
			}
		},

		// Allow to stop the animation
		_checkStop = function (o) {
			if (!$.isFunction(o.stop)) {
				return false;
			}
			return o.stop(o);
		},

		// Called at every tick
		_nextFrame = function () {

			if(!_checkStop(o)) {

				// save travel distance needed
				_setEach(o, targetDistance, function (key) {
					return targetPosition[key] - currentPosition[key];
				});

				// animation : Do we have something to travel
				if (targetDistance.x !== 0 || targetDistance.y !== 0) {

					// if the value changed since lass pass,
					// i.e. an event occur between two frames
					// or before the current one
					if (eventTimeStamp > lastAnimatedTimeStamp) {

						// Save the start point of the animation
						var startValues = _getStartValues(o);

						// Update target distances
						targetDistance.x = targetPosition.x - startValues.x;
						targetDistance.y = targetPosition.y - startValues.y;

						// Update current duration
						currentAnimationDuration = _getDuration(o, targetDistance, startValues, targetPosition);

						// Set start as current
						currentStartAnimationPosition = startValues;

						// Set Last Animated Time Stamp to the new scroll Event Time Stamp
						// This acts as the new animation start
						if (!isMoving || !!o.restartOnEvent) {
							lastAnimatedTimeStamp = now();
						}
					} // if scrolled

					// Begin Var
					var

					// Current animation time (where are we rith now)
					currentAnimationTime = now() - lastAnimatedTimeStamp,

					// Linear/swing algorigthm
					linearPosition = _getLegacyEasingValue(o, currentAnimationTime),
					easingFx = o.easing || $.easing.def || 'linear',
					easingCurPosition = {
						// We documented the parameter names and logic, since there is an error on
						// the main doc: http://gsgd.co.uk/sandbox/jquery/easing/. end_value is actually a diff.
						//                    old_fx,           current_time,                                               start_value,                     end_value-start_value,                             duration
						x: $.easing[easingFx](linearPosition.x, Math.min(currentAnimationTime, currentAnimationDuration.x), currentStartAnimationPosition.x, targetPosition.x-currentStartAnimationPosition.x, currentAnimationDuration.x),
						y: $.easing[easingFx](linearPosition.y, Math.min(currentAnimationTime, currentAnimationDuration.y), currentStartAnimationPosition.y, targetPosition.y-currentStartAnimationPosition.y, currentAnimationDuration.y)
					};

					// end var

					// DEBUG
					_debugOutput(o, linearPosition, easingCurPosition, currentAnimationTime);

					if ($.isNumeric(easingCurPosition.x) && $.isNumeric(easingCurPosition.y)) {
						// update currentPosition state
						currentPosition = easingCurPosition;
					}

					// Start Callback
					if (!isMoving && $.isFunction(o.start)) {
						o.start.call(t, currentAnimationTime, currentPosition);
					}

					// Assure moving flag is on
					isMoving = true;

					// if we still have time left on the animation
					if (currentAnimationTime < currentAnimationDuration.x ||
						currentAnimationTime < currentAnimationDuration.y) {
						// queue next frame
						startTimer();
					} else {
						// animation stopped
						timer = null;
						isMoving = false;
					}

					// call callback with new ghost position
					if ($.isFunction(o.step)) {
						o.step.call(t, currentAnimationTime, currentPosition);
					}

					// End Callback
					if (timer === null) {
						if ($.isFunction(o.complete)) {
							o.complete.call(t, currentAnimationTime, currentPosition);
						}
						// reset if we have to
						currentPosition = _getStartValues(o);
					}

				}
				// no distance found
				else {
					// animation won't run
					timer = null;
					isMoving = false;
				}
			}
			// animation stopped
			else {
				// we stop, no timer is needed
				timer = null;
				isMoving = false;
			}
		},

		// assure minimal option object
		o = $.extend({
			container: null, // The DOMElement where to listen the event. Target if omitted.
			tick: 16, // Default timeout when requestAnimationFrame is not available. In ms.
			event: 'scroll', // The event(s) to listen for changes
			properties: 'x y', // The properties that we are animating (array or string)
			delayStart: false, // Make the event schedule next frame instead of calling it
			duration: 0, // Both axis animation duration. Numeric, object (x:1,y:1} or function
			durationRatio: 1, // Duration modifier. Particularly usefull when duration depends on distance
			restartOnEvent: false, // creates an absolute start time instead of relative to the last event
			stop: null, // A stop function to stop the animation. Your logic, your rules.
			step: null, // A function to call at each step of the animation.
			complete: null, // A callback function called when the animation ends.
			start: null, // A callback function called when the animation begins.
			easing: null, // A easing function to use. $.easing.def or linear if omitted.
			strategy: null, // A strategy function for your custom event.
			startValues: null, // A function that permits override of the stating values
			debug: false // Set to true to get extra data in the console. Can be set per axis {x:false, y:true}
		}, options);

		// If not container is set, use the target
		o.container = $(o.container || t);

		// Add the new strategy if needed
		if ($.isFunction(o.strategy)) {
			_eventStrategies[o.event] = o.strategy;
		}
		// If strategy is a string, try code re-use
		else if ($.isString(o.strategy)) {
			_eventStrategies[o.event] = _eventStrategies[o.strategy];
		}
		// If strategy is an object, add multiple events
		else if ($.isPlainObject(o.strategy)) {
			$.each(o.strategy, function _importStrategy(key, s) {
				_eventStrategies[key] = s;
			});
		}

		// Split into array if it is a string
		if ($.isString(o.properties)) {
			o.properties = o.properties.split(' ');
		}

		// If no animatable properties have been found
		if (!$.isArray(o.properties) || o.properties.length < 1) {
			// Cannot continue
			return t;
		}

		// Init "globals"
		_initVariables(o);

		// Hook up on event
		o.container.on(o.event, _handleEvent);

		// Always return jQuery object
		return t;

	}; // end $.fn.extend
})(jQuery);
<|endoftext|>


<commit_before>/**
 * Tests card component.
 */

// React
import React, {Component, PropTypes} from 'react';

// Material UI
import {Card, CardActions, CardHeader, CardText, CardMedia, CardTitle} from 'material-ui/Card';

const cardTitleStyles = {
  paddingBottom: 0
};

const cardTitleTitleStyles = {
  fontSize: 16,
  fontWeight: 400
};

const cardTextStyles = {
  paddingTop: 6,
  lineHeight: 1.5
};

export default class TestCard extends Component {

  static propTypes = {
    job: PropTypes.object.isRequired,
    onClick: PropTypes.func,
    styles: PropTypes.object
  };

  render() {
    const job = this.props.job;
    if (!job.tests) {
      return null;
    }

    const testPassRate = (job.tests.passed / job.tests.total * 100).toFixed(1);
    const styles = this.props.styles || {};

    return (
      <Card className={styles['item-card']}>
        <CardMedia>
          <img
            src="images/crash.png"
            onClick={this._onClick}
            className={styles['item-media']}
          />
        </CardMedia>
        <CardTitle
          title="Tests"
          style={cardTitleStyles}
          titleStyle={cardTitleTitleStyles}
        />
        <CardText style={cardTextStyles}>
          Pass rate: {testPassRate}%,
          Coverage: {job.tests.coverage}%
        </CardText>
      </Card>
    );
  }

  _onClick = () => {
    if (this.props.onClick) {
      this.props.onClick();
    }
  };

};
<commit_msg>Test card formatting fix<commit_after>/**
 * Tests card component.
 */

// React
import React, {Component, PropTypes} from 'react';

// Material UI
import {Card, CardActions, CardHeader, CardText, CardMedia, CardTitle} from 'material-ui/Card';

const cardTitleStyles = {
  paddingBottom: 0
};

const cardTitleTitleStyles = {
  fontSize: 16,
  fontWeight: 400
};

const cardTextStyles = {
  paddingTop: 6,
  lineHeight: 1.5
};

export default class TestCard extends Component {

  static propTypes = {
    job: PropTypes.object.isRequired,
    onClick: PropTypes.func,
    styles: PropTypes.object
  };

  render() {
    const job = this.props.job;
    if (!job.tests) {
      return null;
    }

    const testPassRate = (job.tests.passed / job.tests.total * 100).toFixed(1);
    const styles = this.props.styles || {};

    return (
      <Card className={styles['item-card']}>
        <CardMedia>
          <img
            src="images/crash.png"
            onClick={this._onClick}
            className={styles['item-media']}
          />
        </CardMedia>
        <CardTitle
          title="Tests"
          style={cardTitleStyles}
          titleStyle={cardTitleTitleStyles}
        />
        <CardText style={cardTextStyles}>
          Pass rate: {testPassRate}%, <br/>
          Coverage: {job.tests.coverage}%
        </CardText>
      </Card>
    );
  }

  _onClick = () => {
    if (this.props.onClick) {
      this.props.onClick();
    }
  };

};
<|endoftext|>