<commit_before>/**
 * fullPage 1.0
 * https://github.com/alvarotrigo/fullPage.js
 * MIT licensed
 *
 * Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
 */
(function(a){a.fn.fullpage=function(c){function r(){return function(b){if(c.autoScrolling){b=window.event||b;b=Math.max(-1,Math.min(1,b.wheelDelta||-b.detail));if(!k){var e=a(".section.active").find(".scrollable");if(0>b)if(0<e.length)if(m("bottom",e))a.fn.fullpage.moveSlideDown();else return!0;else a.fn.fullpage.moveSlideDown();else if(0<e.length)if(m("top",e))a.fn.fullpage.moveSlideUp();else return!0;else a.fn.fullpage.moveSlideUp()}return!1}}}function f(b,e){var d={},g;g=b.position();var s=null!==
g?g.top:null,v=u(b),f=b.data("anchor"),h=b.index(".section");b.addClass("active").siblings().removeClass("active");k=!0;a.isFunction(e)||(location.hash="undefined"!==typeof f?f:"");c.autoScrolling?(d.top=-s,g="#superContainer"):(d.scrollTop=s,g="html, body");c.css3&&c.autoScrolling?(a.isFunction(c.onLeave)&&c.onLeave.call(this,h,v),d="translate3d(0px, -"+s+"px, 0px)",a("#superContainer").addClass("easing").css({"-webkit-transform":d,"-moz-transform":d,"-ms-transform":d,transform:d}),a.isFunction(c.afterLoad)&&
c.afterLoad.call(this,f,h+1),setTimeout(function(){k=!1;a.isFunction(e)&&e.call(this)},700)):(a.isFunction(c.onLeave)&&c.onLeave.call(this,h,v),a(g).animate(d,c.scrollingSpeed,c.easing,function(){a.isFunction(c.afterLoad)&&c.afterLoad.call(this,f,h+1);setTimeout(function(){k=!1;a.isFunction(e)&&e.call(this)},700)}));w=f;x(f);C(f,h)}function D(){var b=window.location.hash.replace("#","").split("/"),c=b[0],d=b[1];if(c){var g=a('[data-anchor="'+c+'"]');f(g,function(){if("undefined"!=typeof d){var a=
g.find(".slides"),b=a.find('[data-anchor="'+d+'"]');b.length||(b=a.find(".slide").eq(d));a.find(".slide").first().removeClass("active");n(a,b);b.addClass("active")}})}}function n(a,e){var d=e.position(),g=a.find(".slidesContainer").parent(),f=e.data("anchor");"undefined"===typeof f&&(f=e.index(".slide"));location.hash=location.hash.split("/")[0]+"/"+f;c.css3?(d="translate3d(-"+d.left+"px, 0px, 0px)",a.find(".slidesContainer").addClass("easing").css({"-webkit-transform":d,"-moz-transform":d,"-ms-transform":d,
transform:d}),setTimeout(function(){p=!0},c.scrollingSpeed)):g.animate({scrollLeft:d.left},c.scrollingSpeed,function(){p=!0})}function y(){var b=a(window).width(),e=a(window).height();c.resize&&E(e,b);a(".section").each(function(){c.scrollOverflow&&a(this).find(".scrollable").css("height",e+"px").parent().css("height",e+"px");c.verticalCentered&&a(this).find(".tableCell").css("height",e+"px");a(this).css("height",e+"px");var b=a(this).find(".slides");0b||900>c?(900>c&&(g=c,d=900),d=(100*g/d).toFixed(2),a("body").css("font-size",d+"%")):a("body").css("font-size","100%")}function C(b,e){c.navigation&&(a("#fullPage-nav").find(".active").removeClass("active"),b?a("#fullPage-nav").find('a[href="#'+b+'"]').addClass("active"):a("#fullPage-nav").find("li").eq(e).find("a").addClass("active"))}function x(b){c.menu&&(a(c.menu).find(".active").removeClass("active"),a(c.menu).find('[data-menuanchor="'+
b+'"]').addClass("active"))}function m(a,c){if("top"===a)return!c.scrollTop();if("bottom"===a)return c.scrollTop()+c.innerHeight()>=c[0].scrollHeight}function u(b){var c=a(".section.active").index(".section");b=b.index(".section");return c>b?"up":"down"}c=a.extend({verticalCentered:!0,resize:!0,slidesColor:[],anchors:[],scrollingSpeed:700,easing:"easeInQuart",menu:!1,navigation:!1,navigationPosition:"right",navigationColor:"#000",controlArrowColor:"#fff",loopBottom:!1,loopTop:!1,autoScrolling:!0,
scrollOverflow:!1,css3:!1,afterLoad:null,onLeave:null,afterRender:null},c);a.fn.fullpage.setAutoScrolling=function(b){c.autoScrolling=b;c.autoScrolling?a("html, body").css({overflow:"hidden",height:"100%"}):(a("html, body").css({overflow:"auto",height:"auto"}),a("#superContainer").css("top","0px"))};var p=!0,t=navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|Windows Phone)/),q=a(window).height(),k=!1,w;a.fn.fullpage.setAutoScrolling(c.autoScrolling);c.verticalCentered&&a(".section").addClass("table").wrapInner('
');a("body").wrapInner('
');if(c.navigation){a("body").append('

');var h=a("#fullPage-nav");h.css("color",c.navigationColor);"right"===c.navigationPosition?h.css("right","17px"):h.css("left","17px")}a(".section").each(function(b){var e=a(this).find(".slide"),d=e.length;b||a(this).addClass("active");a(this).css("height",q+"px");"undefined"!==typeof c.slidesColor[b]&&a(this).css("background-color",c.slidesColor[b]);"undefined"!==
typeof c.anchors[b]&&a(this).attr("data-anchor",c.anchors[b]);if(c.navigation){var g="";c.anchors.length&&(g=c.anchors[b]);h.find("ul").append('

')}if(0<d){b=100*d;var f=100/d;e.wrapAll('
');e.parent().wrap('
');a(this).find(".slidesContainer").css("width",b+"%");a(this).find(".slides").after('

');a(".controlArrow.next").css("border-color",
"transparent transparent transparent "+c.controlArrowColor);a(".controlArrow.prev").css("border-color","transparent "+c.controlArrowColor+" transparent transparent");e.each(function(b){b||a(this).addClass("active");a(this).css("width",f+"%")})}}).promise().done(function(){a.isFunction(c.afterRender)&&c.afterRender.call(this);c.navigation&&(h.css("margin-top","-"+h.height()/2+"px"),h.find("li").first().find("a").addClass("active"));c.menu&&c.css3&&a(c.menu).appendTo("body");if(c.scrollOverflow)a(window).on("load",
function(){a(".section").each(function(){a(this).height()>q&&(c.verticalCentered?a(this).find(".tableCell").wrapInner('
'):a(this).wrapInner('
'),a(this).find(".scrollable").slimScroll({height:q+"px",size:"10px",alwaysVisible:!0}))})});a(window).on("load",function(){D()})});a(window).scroll(function(b){if(!c.autoScrolling){var e=a(window).scrollTop();b=a(".section").map(function(){if(a(this).offset().top<e+100)return a(this)});b=b[b.length-1];if(!b.hasClass("active")){var d=
u(b);a(".section.active").removeClass("active");b.addClass("active");var f=b.data("anchor");a.isFunction(c.onLeave)&&c.onLeave.call(this,b.index(".section"),d);a.isFunction(c.afterLoad)&&c.afterLoad.call(this,f,b.index(".section")+1);x(f)}}});var z=0,A=0;a(document).on("touchmove",function(b){if(c.autoScrolling&&t&&(b.preventDefault(),b=b.originalEvent,!k)){var e=a(".section.active").find(".scrollable");A=b.touches[0].pageY;if(z>A)if(0<e.length)if(m("bottom",e))a.fn.fullpage.moveSlideDown();else return!0;
else a.fn.fullpage.moveSlideDown();else if(0<e.length)if(m("top",e))a.fn.fullpage.moveSlideUp();else return!0;else a.fn.fullpage.moveSlideUp()}});a(document).on("touchstart",function(a){c.autoScrolling&&t&&(z=a.originalEvent.touches[0].pageY)});var l={},l=document;l.addEventListener?(l.addEventListener("mousewheel",r(),!1),l.addEventListener("DOMMouseScroll",r(),!1)):l.attachEvent("onmousewheel",r());a.fn.fullpage.moveSlideUp=function(){var b=a(".section.active").prev(".section");c.loopTop&&!b.length&&
(b=a(".section").last());(0<b.length||!b.length&&c.loopTop)&&f(b)};a.fn.fullpage.moveSlideDown=function(){var b=a(".section.active").next(".section");c.loopBottom&&!b.length&&(b=a(".section").first());(0<b.length||!b.length&&c.loopBottom)&&f(b)};a.fn.fullpage.moveToSlide=function(b){var c="",c=isNaN(b)?a('[data-anchor="'+b+'"]'):a(".section").eq(b-1);0<c.length&&f(c)};a(window).on("hashchange",function(){var b=window.location.hash.replace("#","").split("/")[0];b!==w&&(b=a('[data-anchor="'+b+'"]'),
f(b))});a(document).keydown(function(b){if(!k)switch(b.which){case 38:case 33:a.fn.fullpage.moveSlideUp();break;case 40:case 34:a.fn.fullpage.moveSlideDown();break;case 37:a(".section.active").find(".controlArrow.prev").trigger("click");break;case 39:a(".section.active").find(".controlArrow.next").trigger("click")}});a(document).on("click","#fullPage-nav a",function(b){b.preventDefault();b=a(this).parent().index("li");f(a(".section").eq(b))});a(".section").on("click",".controlArrow",function(){if(p){p=
!1;var b=a(this).closest(".section").find(".slides"),c=b.find(".slide.active"),d=null;c.removeClass("active");d=a(this).hasClass("prev")?c.prev(".slide"):c.next(".slide");d.length||(d=a(this).hasClass("prev")?c.siblings(":last"):c.siblings(":first"));n(b,d);d.addClass("active")}});a(".section").on("click",".toSlide",function(b){b.preventDefault();b=a(this).closest(".section").find(".slides");var c=b.find(".slide.active"),d=null,d=b.find(".slide").eq(a(this).data("index")-1);0<d.length&&(c.removeClass("active"),
n(b,d),d.addClass("active"))});if(!t){var B;a(window).resize(function(){clearTimeout(B);B=setTimeout(y,500)})}a(window).bind("orientationchange",function(){y()})}})(jQuery);<commit_msg>- Solved bug: `active class of menu links is jumping back and forth` when autoScrolling is set to false. #54<commit_after>/**
 * fullPage 1.0
 * https://github.com/alvarotrigo/fullPage.js
 * MIT licensed
 *
 * Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
 */
(function(a){a.fn.fullpage=function(c){function r(){return function(b){if(c.autoScrolling){b=window.event||b;b=Math.max(-1,Math.min(1,b.wheelDelta||-b.detail));if(!k){var e=a(".section.active").find(".scrollable");if(0>b)if(0<e.length)if(m("bottom",e))a.fn.fullpage.moveSlideDown();else return!0;else a.fn.fullpage.moveSlideDown();else if(0<e.length)if(m("top",e))a.fn.fullpage.moveSlideUp();else return!0;else a.fn.fullpage.moveSlideUp()}return!1}}}function f(b,e){var d={},g;g=b.position();var s=null!==
g?g.top:null,v=u(b),f=b.data("anchor"),h=b.index(".section");b.addClass("active").siblings().removeClass("active");k=!0;a.isFunction(e)||(location.hash="undefined"!==typeof f?f:"");c.autoScrolling?(d.top=-s,g="#superContainer"):(d.scrollTop=s,g="html, body");c.css3&&c.autoScrolling?(a.isFunction(c.onLeave)&&c.onLeave.call(this,h,v),d="translate3d(0px, -"+s+"px, 0px)",a("#superContainer").addClass("easing").css({"-webkit-transform":d,"-moz-transform":d,"-ms-transform":d,transform:d}),a.isFunction(c.afterLoad)&&
c.afterLoad.call(this,f,h+1),setTimeout(function(){k=!1;a.isFunction(e)&&e.call(this)},700)):(a.isFunction(c.onLeave)&&c.onLeave.call(this,h,v),a(g).animate(d,c.scrollingSpeed,c.easing,function(){a.isFunction(c.afterLoad)&&c.afterLoad.call(this,f,h+1);setTimeout(function(){k=!1;a.isFunction(e)&&e.call(this)},700)}));w=f;c.autoScrolling&&(x(f),y(f,h))}function D(){var b=window.location.hash.replace("#","").split("/"),c=b[0],d=b[1];if(c){var g=a('[data-anchor="'+c+'"]');f(g,function(){if("undefined"!=
typeof d){var a=g.find(".slides"),b=a.find('[data-anchor="'+d+'"]');b.length||(b=a.find(".slide").eq(d));a.find(".slide").first().removeClass("active");n(a,b);b.addClass("active")}})}}function n(a,e){var d=e.position(),g=a.find(".slidesContainer").parent(),f=e.data("anchor");"undefined"===typeof f&&(f=e.index(".slide"));location.hash=location.hash.split("/")[0]+"/"+f;c.css3?(d="translate3d(-"+d.left+"px, 0px, 0px)",a.find(".slidesContainer").addClass("easing").css({"-webkit-transform":d,"-moz-transform":d,
"-ms-transform":d,transform:d}),setTimeout(function(){p=!0},c.scrollingSpeed)):g.animate({scrollLeft:d.left},c.scrollingSpeed,function(){p=!0})}function z(){var b=a(window).width(),e=a(window).height();c.resize&&E(e,b);a(".section").each(function(){c.scrollOverflow&&a(this).find(".scrollable").css("height",e+"px").parent().css("height",e+"px");c.verticalCentered&&a(this).find(".tableCell").css("height",e+"px");a(this).css("height",e+"px");var b=a(this).find(".slides");0b||900>c?(900>c&&(g=c,d=900),d=(100*g/d).toFixed(2),a("body").css("font-size",d+"%")):a("body").css("font-size","100%")}function y(b,e){c.navigation&&(a("#fullPage-nav").find(".active").removeClass("active"),b?a("#fullPage-nav").find('a[href="#'+b+'"]').addClass("active"):a("#fullPage-nav").find("li").eq(e).find("a").addClass("active"))}function x(b){c.menu&&(a(c.menu).find(".active").removeClass("active"),a(c.menu).find('[data-menuanchor="'+
b+'"]').addClass("active"))}function m(a,c){if("top"===a)return!c.scrollTop();if("bottom"===a)return c.scrollTop()+c.innerHeight()>=c[0].scrollHeight}function u(b){var c=a(".section.active").index(".section");b=b.index(".section");return c>b?"up":"down"}c=a.extend({verticalCentered:!0,resize:!0,slidesColor:[],anchors:[],scrollingSpeed:700,easing:"easeInQuart",menu:!1,navigation:!1,navigationPosition:"right",navigationColor:"#000",controlArrowColor:"#fff",loopBottom:!1,loopTop:!1,autoScrolling:!0,
scrollOverflow:!1,css3:!1,afterLoad:null,onLeave:null,afterRender:null},c);a.fn.fullpage.setAutoScrolling=function(b){c.autoScrolling=b;c.autoScrolling?a("html, body").css({overflow:"hidden",height:"100%"}):(a("html, body").css({overflow:"auto",height:"auto"}),a("#superContainer").css("top","0px"))};var p=!0,t=navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|Windows Phone)/),q=a(window).height(),k=!1,w;a.fn.fullpage.setAutoScrolling(c.autoScrolling);c.verticalCentered&&a(".section").addClass("table").wrapInner('
');a("body").wrapInner('
');if(c.navigation){a("body").append('

');var h=a("#fullPage-nav");h.css("color",c.navigationColor);"right"===c.navigationPosition?h.css("right","17px"):h.css("left","17px")}a(".section").each(function(b){var e=a(this).find(".slide"),d=e.length;b||a(this).addClass("active");a(this).css("height",q+"px");"undefined"!==typeof c.slidesColor[b]&&a(this).css("background-color",c.slidesColor[b]);"undefined"!==
typeof c.anchors[b]&&a(this).attr("data-anchor",c.anchors[b]);if(c.navigation){var g="";c.anchors.length&&(g=c.anchors[b]);h.find("ul").append('

')}if(0<d){b=100*d;var f=100/d;e.wrapAll('
');e.parent().wrap('
');a(this).find(".slidesContainer").css("width",b+"%");a(this).find(".slides").after('

');a(".controlArrow.next").css("border-color",
"transparent transparent transparent "+c.controlArrowColor);a(".controlArrow.prev").css("border-color","transparent "+c.controlArrowColor+" transparent transparent");e.each(function(b){b||a(this).addClass("active");a(this).css("width",f+"%")})}}).promise().done(function(){a.isFunction(c.afterRender)&&c.afterRender.call(this);c.navigation&&(h.css("margin-top","-"+h.height()/2+"px"),h.find("li").first().find("a").addClass("active"));c.menu&&c.css3&&a(c.menu).appendTo("body");if(c.scrollOverflow)a(window).on("load",
function(){a(".section").each(function(){a(this).height()>q&&(c.verticalCentered?a(this).find(".tableCell").wrapInner('
'):a(this).wrapInner('
'),a(this).find(".scrollable").slimScroll({height:q+"px",size:"10px",alwaysVisible:!0}))})});a(window).on("load",function(){D()})});a(window).scroll(function(b){if(!c.autoScrolling){var e=a(window).scrollTop();b=a(".section").map(function(){if(a(this).offset().top<e+100)return a(this)});b=b[b.length-1];if(!b.hasClass("active")){var d=
u(b);a(".section.active").removeClass("active");b.addClass("active");var f=b.data("anchor");a.isFunction(c.onLeave)&&c.onLeave.call(this,b.index(".section"),d);a.isFunction(c.afterLoad)&&c.afterLoad.call(this,f,b.index(".section")+1);x(f);y(f,0)}}});var A=0,B=0;a(document).on("touchmove",function(b){if(c.autoScrolling&&t&&(b.preventDefault(),b=b.originalEvent,!k)){var e=a(".section.active").find(".scrollable");B=b.touches[0].pageY;if(A>B)if(0<e.length)if(m("bottom",e))a.fn.fullpage.moveSlideDown();
else return!0;else a.fn.fullpage.moveSlideDown();else if(0<e.length)if(m("top",e))a.fn.fullpage.moveSlideUp();else return!0;else a.fn.fullpage.moveSlideUp()}});a(document).on("touchstart",function(a){c.autoScrolling&&t&&(A=a.originalEvent.touches[0].pageY)});var l={},l=document;l.addEventListener?(l.addEventListener("mousewheel",r(),!1),l.addEventListener("DOMMouseScroll",r(),!1)):l.attachEvent("onmousewheel",r());a.fn.fullpage.moveSlideUp=function(){var b=a(".section.active").prev(".section");c.loopTop&&
!b.length&&(b=a(".section").last());(0<b.length||!b.length&&c.loopTop)&&f(b)};a.fn.fullpage.moveSlideDown=function(){var b=a(".section.active").next(".section");c.loopBottom&&!b.length&&(b=a(".section").first());(0<b.length||!b.length&&c.loopBottom)&&f(b)};a.fn.fullpage.moveToSlide=function(b){var c="",c=isNaN(b)?a('[data-anchor="'+b+'"]'):a(".section").eq(b-1);0<c.length&&f(c)};a(window).on("hashchange",function(){var b=window.location.hash.replace("#","").split("/")[0];b!==w&&(b=a('[data-anchor="'+
b+'"]'),f(b))});a(document).keydown(function(b){if(!k)switch(b.which){case 38:case 33:a.fn.fullpage.moveSlideUp();break;case 40:case 34:a.fn.fullpage.moveSlideDown();break;case 37:a(".section.active").find(".controlArrow.prev").trigger("click");break;case 39:a(".section.active").find(".controlArrow.next").trigger("click")}});a(document).on("click","#fullPage-nav a",function(b){b.preventDefault();b=a(this).parent().index("li");f(a(".section").eq(b))});a(".section").on("click",".controlArrow",function(){if(p){p=
!1;var b=a(this).closest(".section").find(".slides"),c=b.find(".slide.active"),d=null;c.removeClass("active");d=a(this).hasClass("prev")?c.prev(".slide"):c.next(".slide");d.length||(d=a(this).hasClass("prev")?c.siblings(":last"):c.siblings(":first"));n(b,d);d.addClass("active")}});a(".section").on("click",".toSlide",function(b){b.preventDefault();b=a(this).closest(".section").find(".slides");var c=b.find(".slide.active"),d=null,d=b.find(".slide").eq(a(this).data("index")-1);0<d.length&&(c.removeClass("active"),
n(b,d),d.addClass("active"))});if(!t){var C;a(window).resize(function(){clearTimeout(C);C=setTimeout(z,500)})}a(window).bind("orientationchange",function(){z()})}})(jQuery);<|endoftext|>


<commit_before>App.addChild('ProjectShow', _.extend({
  el: 'body[data-action="show"][data-controller-name="projects"]',

  activate: function(){

    $videos = $("iframe[src^='//player.vimeo.com'], iframe[src^='//www.youtube.com']"),

    $container = $(".project-about");

    this.makeVideosResponsive($videos, $container);

  },

  events: {
    'resize window' : 'updateVideoSize'
  },

  makeVideosResponsive: function($videos){

    $videos.each(function() {

      $(this)
        .data('aspectRatio', this.height / this.width)
        .removeAttr('height')
        .removeAttr('width');

    });

  },

  updateVideoSize: function(e){

    var newWidth = this.$container.width();

    this.$allVideos.each(function() {

      var $el = $(this);

      $el
        .width(newWidth)
        .height(newWidth * $el.data('aspectRatio'));

    });

    window.dispatchEvent(e);

  }

}));

<commit_msg>Deletes duplicated file<commit_after><|endoftext|>


<commit_before>'use strict';

angular.module('quakeStatsApp', ['ngResource', 'googlechart'])
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/flags', {
                templateUrl: 'views/flags.html',
                controller: 'FlagsCtrl',
                resolve: {
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/maps/:flagsmapindex', {
                templateUrl: 'views/maps.html',
                controller: 'MapsCtrl',
                resolve: {
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/kills', {
                templateUrl: 'views/kills.html',
                controller: 'KillsCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/players', {
                templateUrl: 'views/players.html',
                controller: 'PlayersCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/players/:id', {
                templateUrl: 'views/player.html',
                controller: 'PlayerCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }],
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/dashboard', {
                templateUrl: 'views/dashboard.html',
                controller: 'DashboardCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }],
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .otherwise({
                redirectTo: '/flags'
            });

        // TODO: resolve error handling
    }]);
<commit_msg>Ongoing: Make the Dashboard the default screen<commit_after>'use strict';

angular.module('quakeStatsApp', ['ngResource', 'googlechart'])
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/flags', {
                templateUrl: 'views/flags.html',
                controller: 'FlagsCtrl',
                resolve: {
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/maps/:flagsmapindex', {
                templateUrl: 'views/maps.html',
                controller: 'MapsCtrl',
                resolve: {
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/kills', {
                templateUrl: 'views/kills.html',
                controller: 'KillsCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/players', {
                templateUrl: 'views/players.html',
                controller: 'PlayersCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/players/:id', {
                templateUrl: 'views/player.html',
                controller: 'PlayerCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }],
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .when('/dashboard', {
                templateUrl: 'views/dashboard.html',
                controller: 'DashboardCtrl',
                resolve: {
                    gamesLog: ['$q', 'GamesLogService', function($q, GamesLogService) {
                        var dfd = $q.defer();
                        GamesLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }],
                    qconsoleLog: ['$q', 'QConsoleLogService', function($q, QConsoleLogService) {
                        var dfd = $q.defer();
                        QConsoleLogService.loadLog().then(
                            function(result) {
                                dfd.resolve({
                                    success: true,
                                    result : result
                                });
                            }, function(error) {
                                dfd.resolve({
                                    success : false,
                                    reason : error
                                });
                            });
                        return dfd.promise;
                    }]
                }
            })
            .otherwise({
                redirectTo: '/dashboard'
            });

        // TODO: resolve error handling
    }]);
<|endoftext|>


<commit_before>(function($){

    var heatColors = {};

    $.mouseTracker = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base;
        if(typeof options === "string"){
            base = $(el).data("mouseTracker");
            switch(options){
                case 'drawLiveContent':
                    base.drawLiveContent();
                    break;
                case 'drawHeatMap':
                    base.drawHeatMap();
                    break;
                case 'saveData':
                    base.saveData();
                    break;
            }
        } else {
            base = this;
            // Access to jQuery and DOM versions of element
            base.el = el;
            base.$el = $(el);
            // Add a reverse reference to the DOM object
            base.$el.data("mouseTracker",base);
        }

        base.init = function(){
            base.options = $.extend({},$.mouseTracker.defaultOptions, options);
            base.movements = [];
            base.max = 0;
            base.movementLocations = [];
            base.url = location.href;
            base.baseTime = 0;
            base.needsRedraw = false;

            window.unload = base.saveMouseData;

            base.$el.mousemove(function(event){
               base.logMouse(event);
            });

            if(jQuery.isEmptyObject(heatColors)){
                for(var colorIndex = 0; colorIndex < 101; colorIndex++){
                    if(colorIndex <= 50){
                        heatColors[100-colorIndex] = {color: (colorIndex * 5 < 16 ? "#FF0" : "#FF") + base.decToHex(colorIndex * 5) + "00" };
                    } else {
                        heatColors[100-colorIndex] = {color: ((colorIndex - 50) * 5 < 239 ? "#" : "#0") + base.decToHex((colorIndex - 50) * 5) + "FF00" };
                    }
                }
            }
        };

        base.saveData = function(){
            console.log("TODO: Implement AJAX save of data on window.unload");
        };

        base.drawHeatMap = function(){
            if(base.needsRedraw){
                var height = base.$el.height();
                var width = base.$el.width();

                var heatMapCanvas = base.$el.find('.heatMapCanvas')[0];
                if(typeof heatMapCanvas === 'undefined'){
                    base.el.style.position = 'relative';
                    heatMapCanvas = document.createElement('CANVAS');
                    heatMapCanvas.className = 'heatMapCanvas';
                    heatMapCanvas.style.position = 'absolute';
                    heatMapCanvas.style.top = 0;
                    heatMapCanvas.style.left = 0;
                    heatMapCanvas.style.width = width;
                    heatMapCanvas.style.height = height;
                    heatMapCanvas.height = height;
                    heatMapCanvas.width = width;
                    heatMapCanvas.style.zIndex = 999999;
                    base.$el.append(heatMapCanvas);
                }

                var ctx = heatMapCanvas.getContext("2d");
                var movementLocations = base.movementLocations;

                ctx.clearRect(0, 0, width, height);
                for(var xID in movementLocations){
                    for(var yID in movementLocations[xID]){
                        var count = movementLocations[xID][yID];
                        colorNdx = Math.round((count/base.max)*100);
                        ctx.fillStyle = heatColors[colorNdx].color;
                        ctx.fillRec(xID,yID,1,1);
                    }
                }
            }
            base.needsRedraw = false;
        }

        base.logMouse = function(e){
            var x = (Math.round(e.clientX - base.$el.offset().left));
            var y = (Math.round(e.clientY - base.$el.offset().top));
            base.movements.push({x:x, y:y, time: Date.now()});

            var movementLocations = base.movementLocations;
            for(var horMove = -3; horMove <= 3; horMove++){
                for(var vertMove = -3; vertMove <= 3; vertMove++){
                    var xID = x + horMove;
                    var yID = y + vertMove;
                    if(typeof movementLocations[xID] === "undefined")
                        movementLocations[xID] = [];
                    if(typeof movementLocations[xID][yID] === "undefined")
                        movementLocations[xID][yID] = 1;
                    else
                        movementLocations[xID][yID]++;

                    if(movementLocations[xID][yID] > base.max)
                        base.max = movementLocations[xID][yID];
                }
            }
            base.needsRedraw = true;
        };

        base.drawLiveContent = function(ticks, curNdx){
            var movements = base.movements;
            if(movements.length > 0){ // ensure we have movements to draw
                if(typeof ticks === "undefined")
                    ticks = 0;
                else
                    ticks++;
                if(typeof curNdx === "undefined")
                    curNdx = 0;

                var img = base.$el.find('.mouseImage')[0];
                if(typeof img === "undefined"){
                    img = document.createElement("IMG");
                    img.className = "mouseImage";
                    img.src = ""; //TODO: move to global options
                    img.style.position = "absolute";
                    base.$el.append(img);
                }
                img.style.left = movements[curNdx].x;
                img.style.top = movements[curNdx].y;

                if(base.baseTime === 0){
                    base.baseTime = movements[0].time;
                }
                if(typeof movements[curNdx+1] !== "undefined"){ //check that we have more data to display
                    if(movements[curNdx+1].time <= baseTime + ticks){ //check if we have spent the appropriate amount of time displaying cur position, if so
                        curNdx++; //move to next elements
                    }
                } else {
                    alert("End of recorded data."); //inform user that recorded mouse movements have ended
                    return; //end loop
                }

                setTimeout(function(){
                    base.drawLiveContent(ticks, curNdx);
                },1);
            }
        }

        base.decToHex = function(dec){
            var hexVals = ["A","B","C","D","E","F"];
            var base = 16;
            var quotient = dec;
            var result = "";
            if(quotient === 0){
                return "0";
            }
            while(quotient !== 0){
                var mod = quotient % base;
                quotient = Math.floor(quotient / base);
                if(mod > 9)
                    mod = hexVals[mod-10]
                result = mod + result;
            }
            return result;
        }

        if(typeof options !== "string")
            base.init();
    };

    $.mouseTracker.defaultOptions = {
        url: ''
    };

    $.fn.mouseTracker = function(options){
        return this.each(function(){
            (new $.mouseTracker(this, options));
        });
    };

})(jQuery);
<commit_msg>Update jquery.mousetracker.js<commit_after>(function($){

    var heatColors = {};

    $.mouseTracker = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base;
        if(typeof options === "string"){
            base = $(el).data("mouseTracker");
            switch(options){
                case 'drawLiveContent':
                    base.drawLiveContent();
                    break;
                case 'drawHeatMap':
                    base.drawHeatMap();
                    break;
                case 'saveData':
                    base.saveData();
                    break;
            }
        } else {
            base = this;
            // Access to jQuery and DOM versions of element
            base.el = el;
            base.$el = $(el);
            // Add a reverse reference to the DOM object
            base.$el.data("mouseTracker",base);
        }

        base.init = function(){
            base.options = $.extend({},$.mouseTracker.defaultOptions, options);
            base.movements = [];
            base.max = 0;
            base.movementLocations = [];
            base.url = location.href;
            base.baseTime = 0;
            base.needsRedraw = false;

            window.unload = base.saveMouseData;

            base.$el.mousemove(function(event){
               base.logMouse(event);
            });

            if(jQuery.isEmptyObject(heatColors)){
                for(var colorIndex = 0; colorIndex < 101; colorIndex++){
                    if(colorIndex <= 50){
                        heatColors[100-colorIndex] = {color: (colorIndex * 5 < 16 ? "#FF0" : "#FF") + base.decToHex(colorIndex * 5) + "00" };
                    } else {
                        heatColors[100-colorIndex] = {color: ((colorIndex - 50) * 5 < 239 ? "#" : "#0") + base.decToHex((colorIndex - 50) * 5) + "FF00" };
                    }
                }
            }
        };

        base.saveData = function(){
            if(base.options.url.length > 0 && base.options.saveTrackerData){
                $.ajax({
                    type: "POST",
                    url: base.options.url,
                    data: { mouseTracker: base }
                });
            }
        };

        base.drawHeatMap = function(){
            if(base.needsRedraw){
                var height = base.$el.height();
                var width = base.$el.width();

                var heatMapCanvas = base.$el.find('.heatMapCanvas')[0];
                if(typeof heatMapCanvas === 'undefined'){
                    base.el.style.position = 'relative';
                    heatMapCanvas = document.createElement('CANVAS');
                    heatMapCanvas.className = 'heatMapCanvas';
                    heatMapCanvas.style.position = 'absolute';
                    heatMapCanvas.style.top = 0;
                    heatMapCanvas.style.left = 0;
                    heatMapCanvas.style.width = width;
                    heatMapCanvas.style.height = height;
                    heatMapCanvas.height = height;
                    heatMapCanvas.width = width;
                    heatMapCanvas.style.zIndex = 999999;
                    base.$el.append(heatMapCanvas);
                }

                var ctx = heatMapCanvas.getContext("2d");
                var movementLocations = base.movementLocations;

                ctx.clearRect(0, 0, width, height);
                for(var xID in movementLocations){
                    for(var yID in movementLocations[xID]){
                        var count = movementLocations[xID][yID];
                        colorNdx = Math.round((count/base.max)*100);
                        ctx.fillStyle = heatColors[colorNdx].color;
                        ctx.fillRec(xID,yID,1,1);
                    }
                }
            }
            base.needsRedraw = false;
        }

        base.logMouse = function(e){
            var x = (Math.round(e.clientX - base.$el.offset().left));
            var y = (Math.round(e.clientY - base.$el.offset().top));
            base.movements.push({x:x, y:y, time: Date.now()});

            var movementLocations = base.movementLocations;
            for(var horMove = -3; horMove <= 3; horMove++){
                for(var vertMove = -3; vertMove <= 3; vertMove++){
                    var xID = x + horMove;
                    var yID = y + vertMove;
                    if(typeof movementLocations[xID] === "undefined")
                        movementLocations[xID] = [];
                    if(typeof movementLocations[xID][yID] === "undefined")
                        movementLocations[xID][yID] = 1;
                    else
                        movementLocations[xID][yID]++;

                    if(movementLocations[xID][yID] > base.max)
                        base.max = movementLocations[xID][yID];
                }
            }
            base.needsRedraw = true;
        };

        base.drawLiveContent = function(ticks, curNdx){
            var movements = base.movements;
            if(movements.length > 0){ // ensure we have movements to draw
                if(typeof ticks === "undefined")
                    ticks = 0;
                else
                    ticks++;
                if(typeof curNdx === "undefined")
                    curNdx = 0;

                var img = base.$el.find('.mouseImage')[0];
                if(typeof img === "undefined"){
                    img = document.createElement("IMG");
                    img.className = "mouseImage";
                    img.src = base.options.cursorUrl; //TODO: move to global options
                    img.style.position = "absolute";
                    base.$el.append(img);
                }
                img.style.left = movements[curNdx].x;
                img.style.top = movements[curNdx].y;

                if(base.baseTime === 0){
                    base.baseTime = movements[0].time;
                }
                if(typeof movements[curNdx+1] !== "undefined"){ //check that we have more data to display
                    if(movements[curNdx+1].time <= baseTime + ticks){ //check if we have spent the appropriate amount of time displaying cur position, if so
                        curNdx++; //move to next elements
                    }
                } else {
                    alert("End of recorded data."); //inform user that recorded mouse movements have ended
                    return; //end loop
                }

                setTimeout(function(){
                    base.drawLiveContent(ticks, curNdx);
                },1);
            }
        }

        base.decToHex = function(dec){
            var hexVals = ["A","B","C","D","E","F"];
            var base = 16;
            var quotient = dec;
            var result = "";
            if(quotient === 0){
                return "0";
            }
            while(quotient !== 0){
                var mod = quotient % base;
                quotient = Math.floor(quotient / base);
                if(mod > 9)
                    mod = hexVals[mod-10]
                result = mod + result;
            }
            return result;
        }

        if(typeof options !== "string")
            base.init();
    };

    $.mouseTracker.defaultOptions = {
        url: '',
        cursorUrl: '',
        saveTrackerData: true
    };

    $.fn.mouseTracker = function(options){
        return this.each(function(){
            (new $.mouseTracker(this, options));
        });
    };

})(jQuery);
<|endoftext|>


<commit_before>mumuki.load(function () {
  var $bubble = $('.mu-kids-character-speech-bubble').children('.mu-kids-character-speech-bubble-normal');
  if(!$bubble.length) return;

  var availableTabs = ['.description', '.hint'];
  var $speechParagraphs, paragraphHeight, scrollHeight, nextSpeechBlinking;
  var currentParagraphIndex = 0;
  var paragraphCount = 1;
  var paragraphsLines = 2;
  var $prevSpeech = $('.mu-kids-character-speech-bubble-normal > .mu-kids-prev-speech').hide();
  var $nextSpeech = $('.mu-kids-character-speech-bubble-normal > .mu-kids-next-speech');
  var $speechTabs = $('.mu-kids-character-speech-bubble-tabs > li:not(.separator)');
  var $defaultSpeechTabName = 'description';
  var $texts = $bubble.children(availableTabs.join(", "));

  function floatFromPx(value) {
    return parseFloat(value.substring(0, value.length - 2));
  }

  function resizeSpeechParagraphs(paragraphIndex) {
    var previousParagraphCount = paragraphCount;
    scrollHeight = $bubble[0].scrollHeight;
    paragraphHeight = floatFromPx($speechParagraphs.css('line-height')) * paragraphsLines;
    paragraphCount = Math.ceil(scrollHeight / paragraphHeight);
    var newParagraphIndex = Math.floor((paragraphCount / previousParagraphCount) * currentParagraphIndex);
    showParagraph(paragraphIndex || newParagraphIndex);
  }

  availableTabs.forEach(function (tabSelector) {
    tabParagraphs(tabSelector).contents().unwrap().wrapAll('<p>');
  });

  function tabParagraphs(selector) {
    return $('.mu-kids-character-speech-bubble > .mu-kids-character-speech-bubble-normal > div' + selector + ' > p');
  }

  updateSpeechParagraphs();
  function updateSpeechParagraphs() {
    $speechParagraphs = tabParagraphs('.' + getSelectedTabName());
    resizeSpeechParagraphs(0);
  }

  resizeSpeechParagraphs();

  $speechTabs.each(function (i) {
    var $tab = $($speechTabs[i]);
    $tab.click(function () {
      $speechTabs.removeClass('active');
      $tab.addClass('active');
      $texts.hide();
      $bubble.children('.' + $tab.data('target')).show();
      updateSpeechParagraphs();
    })
  });

  if(paragraphCount > 1) {
    nextSpeechBlinking = setInterval(() => $nextSpeech.fadeTo('slow', 0.1).fadeTo('slow', 1.0), 1000);
  }

  $nextSpeech.click(showNextParagraph);

  $prevSpeech.click(showPrevParagraph);

  function getSelectedTabName() {
    return $speechTabs.filter(".active").data('target') || $defaultSpeechTabName;
  }

  function showParagraph(index) {
    $bubble[0].scrollTop = index * paragraphHeight;
    currentParagraphIndex = index;
    checkArrowsSpeechVisibility();
  }

  function checkArrowsSpeechVisibility() {
    setVisibility($prevSpeech, currentParagraphIndex !== 0);
    setVisibility($nextSpeech, currentParagraphIndex !== paragraphCount - 1);
  }

  function setVisibility(element, isVisible) {
    isVisible ? element.show() : element.hide();
  }

  mumuki.resize(function () {
    var margin = 15;
    var fullMargin = margin * 2;

    var $muKidsStatesContainer = $('.mu-kids-states');
    var $muKidsStates = $('.mu-kids-state');

    var dimension = $muKidsStatesContainer.height() / 2 * 1.25 - fullMargin;
    $muKidsStatesContainer.width(dimension);

    var $muKidsExercise = $('.mu-kids-exercise');
    var $muKidsExerciseDescription = $('.mu-kids-exercise-description');

    $muKidsExerciseDescription.width($muKidsExercise.width() - $muKidsStatesContainer.width() - margin);

    $muKidsStates.each((index, board) => scaleStates($(board)));

    var $muKidsBlocks = $('.mu-kids-blocks');
    var $blockArea = $muKidsBlocks.find('#blocklyDiv');
    var $blockSvg = $muKidsBlocks.find('.blocklySvg');

    $blockArea.width($muKidsBlocks.width());
    $blockArea.height($muKidsBlocks.height());

    $blockSvg.width($muKidsBlocks.width());
    $blockSvg.height($muKidsBlocks.height());

    function scaleStates($element) {
      var $table = $element.find('gs-board > table');
      if(!$table.length) return setTimeout(() => scaleStates($element));
      $table.css('transform', 'scale(1)');
      var scaleX = ($element.width() - fullMargin * 2) / $table.width();
      var scaleY = ($element.height() - fullMargin * 2) / $table.height();
      $table.css('transform', 'scale(' + Math.min(scaleX, scaleY) + ')');
    }

    resizeSpeechParagraphs();
  });

  mumuki.kids = {

    getResultsModal: function () {
      return $('#kids-results');
    },

    getResultsAbortedModal: function () {
      return $('#kids-results-aborted');
    },

    getCharaterImage: function () {
      return $('.mu-kids-character > img');
    },

    getCharacterBubble: function () {
      return $('.mu-kids-character-speech-bubble');
    },

    getSubmissionResult: function () {
      return $('.submission-results');
    },

    getOverlay: function () {
      return $('.mu-kids-overlay');
    },

    showResult: function (data) {  // This function is called by the custom runner
      mumuki.updateProgressBarAndShowModal(data);
      if (data.guide_finished_by_solution) return;
      mumuki.kids.resultAction[data.status](data);
    },

    restart: function () {  // This function is called by the custom runner
      mumuki.kids._hideMessageOnCharacterBubble();
      var $bubble = mumuki.kids.getCharacterBubble();
      Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
      mumuki.presenterCharacter.playAnimation('jump', mumuki.kids.getCharaterImage());
    },

    _hideMessageOnCharacterBubble: function () {
      var $bubble = mumuki.kids.getCharacterBubble();
      $bubble.find('.mu-kids-character-speech-bubble-tabs').show();
      $bubble.find('.mu-kids-character-speech-bubble-normal').show();
      $bubble.find('.mu-kids-character-speech-bubble-failed').hide();
      Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
      mumuki.kids.getOverlay().hide();
    },

    _showMessageOnCharacterBubble: function (data) {
      var $bubble = mumuki.kids.getCharacterBubble();
      $bubble.find('.mu-kids-character-speech-bubble-tabs').hide();
      $bubble.find('.mu-kids-character-speech-bubble-normal').hide();
      $bubble.find('.mu-kids-character-speech-bubble-failed').show().html(data.title_html);
      $bubble.addClass(data.status);
      if (data.status === 'passed_with_warnings') {
        $bubble.find('.mu-kids-character-speech-bubble-failed').append(data.expectations_html);
      }
      mumuki.kids.getOverlay().show();
    },

    _showOnSuccessPopup: function (data) {
      mumuki.kids.getSubmissionResult().html(data.html);
      mumuki.presenterCharacter.playAnimation('success_l', mumuki.kids.getCharaterImage());
      mumuki.kids._showMessageOnCharacterBubble(data);
      mumuki.presenterCharacter.playAnimation('success2_l', $('.mu-kids-character-success'));
      setTimeout(function () {
        var results_kids_modal = mumuki.kids.getResultsModal();
        if (results_kids_modal) {
          results_kids_modal.modal({
            backdrop: 'static',
            keyboard: false
          });
          results_kids_modal.find('.modal-header').first().html(data.title_html);
          results_kids_modal.find('.modal-footer').first().html(data.button_html);
          mumuki.kids._showCorollaryCharacter();
          $('.mu-close-modal').click(() => $('#kids-results').modal('hide'));
        }
      }, 1000 * 4);
    },

    _showOnFailurePopup: function () {
      mumuki.kids.submitButton.disable();
      mumuki.kids.getResultsAbortedModal().modal();
      mumuki.submission.animateTimeoutError(mumuki.kids.submitButton);
    },

    _showOnCharacterBubble: function (data) {
      mumuki.presenterCharacter.playAnimation('failure', mumuki.kids.getCharaterImage());
      mumuki.kids._showMessageOnCharacterBubble(data);
    },

    _showCorollaryCharacter: function () {
      mumuki.characters.magnifying_glass.playAnimation('show', $('.mu-kids-corollary-animation'));
    },

    resultAction: {}

  };

  const _createSubmitButton = function () {
    var submitButton = $('#kids-btn-retry');
    var submissionControl = $('.submission_control');
    return new mumuki.submission.SubmitButton(submitButton, submissionControl);
  };

  mumuki.kids.submitButton = _createSubmitButton();

  function showPrevParagraph() {
    animateSpeech();
    showParagraph(currentParagraphIndex - 1);
  }

  function showNextParagraph() {
    animateSpeech();
    showParagraph(currentParagraphIndex + 1);
    clearInterval(nextSpeechBlinking);
  }

  function animateSpeech() {
    mumuki.presenterCharacter.playAnimation('talk', mumuki.kids.getCharaterImage());
  }

  mumuki.showKidsResult = function (data) {
    mumuki.updateProgressBarAndShowModal(data);
    if (data.guide_finished_by_solution) return;
    mumuki.kids.getSubmissionResult().html(data.html);

    var results_kids_modal = mumuki.kids.getResultsModal();
    if (results_kids_modal) {
      results_kids_modal.modal();
      results_kids_modal.find('.modal-header').first().html(data.title_html);
      results_kids_modal.find('.modal-footer').first().html(data.button_html);
    }
  };

  mumuki.kids.resultAction.passed = mumuki.kids._showOnSuccessPopup;
  mumuki.kids.resultAction.passed_with_warnings = mumuki.kids._showOnCharacterBubble;

  mumuki.kids.resultAction.aborted = mumuki.kids._showOnFailurePopup;

  mumuki.kids.resultAction.failed = mumuki.kids._showOnCharacterBubble;
  mumuki.kids.resultAction.errored = mumuki.kids._showOnCharacterBubble;
  mumuki.kids.resultAction.pending = mumuki.kids._showOnCharacterBubble;
});
<commit_msg>Introducing statesScaler<commit_after>mumuki.load(function () {
  var $bubble = $('.mu-kids-character-speech-bubble').children('.mu-kids-character-speech-bubble-normal');
  if(!$bubble.length) return;

  var availableTabs = ['.description', '.hint'];
  var $speechParagraphs, paragraphHeight, scrollHeight, nextSpeechBlinking;
  var currentParagraphIndex = 0;
  var paragraphCount = 1;
  var paragraphsLines = 2;
  var $prevSpeech = $('.mu-kids-character-speech-bubble-normal > .mu-kids-prev-speech').hide();
  var $nextSpeech = $('.mu-kids-character-speech-bubble-normal > .mu-kids-next-speech');
  var $speechTabs = $('.mu-kids-character-speech-bubble-tabs > li:not(.separator)');
  var $defaultSpeechTabName = 'description';
  var $texts = $bubble.children(availableTabs.join(", "));

  function floatFromPx(value) {
    return parseFloat(value.substring(0, value.length - 2));
  }

  function resizeSpeechParagraphs(paragraphIndex) {
    var previousParagraphCount = paragraphCount;
    scrollHeight = $bubble[0].scrollHeight;
    paragraphHeight = floatFromPx($speechParagraphs.css('line-height')) * paragraphsLines;
    paragraphCount = Math.ceil(scrollHeight / paragraphHeight);
    var newParagraphIndex = Math.floor((paragraphCount / previousParagraphCount) * currentParagraphIndex);
    showParagraph(paragraphIndex || newParagraphIndex);
  }

  availableTabs.forEach(function (tabSelector) {
    tabParagraphs(tabSelector).contents().unwrap().wrapAll('<p>');
  });

  function tabParagraphs(selector) {
    return $('.mu-kids-character-speech-bubble > .mu-kids-character-speech-bubble-normal > div' + selector + ' > p');
  }

  updateSpeechParagraphs();
  function updateSpeechParagraphs() {
    $speechParagraphs = tabParagraphs('.' + getSelectedTabName());
    resizeSpeechParagraphs(0);
  }

  resizeSpeechParagraphs();

  $speechTabs.each(function (i) {
    var $tab = $($speechTabs[i]);
    $tab.click(function () {
      $speechTabs.removeClass('active');
      $tab.addClass('active');
      $texts.hide();
      $bubble.children('.' + $tab.data('target')).show();
      updateSpeechParagraphs();
    })
  });

  if(paragraphCount > 1) {
    nextSpeechBlinking = setInterval(() => $nextSpeech.fadeTo('slow', 0.1).fadeTo('slow', 1.0), 1000);
  }

  $nextSpeech.click(showNextParagraph);

  $prevSpeech.click(showPrevParagraph);

  function getSelectedTabName() {
    return $speechTabs.filter(".active").data('target') || $defaultSpeechTabName;
  }

  function showParagraph(index) {
    $bubble[0].scrollTop = index * paragraphHeight;
    currentParagraphIndex = index;
    checkArrowsSpeechVisibility();
  }

  function checkArrowsSpeechVisibility() {
    setVisibility($prevSpeech, currentParagraphIndex !== 0);
    setVisibility($nextSpeech, currentParagraphIndex !== paragraphCount - 1);
  }

  function setVisibility(element, isVisible) {
    isVisible ? element.show() : element.hide();
  }

  mumuki.resize(function () {
    var margin = 15;
    var fullMargin = margin * 2;

    var $muKidsStatesContainer = $('.mu-kids-states');
    var $muKidsStates = $('.mu-kids-state');

    var dimension = $muKidsStatesContainer.height() / 2 * 1.25 - fullMargin;
    $muKidsStatesContainer.width(dimension);

    var $muKidsExercise = $('.mu-kids-exercise');
    var $muKidsExerciseDescription = $('.mu-kids-exercise-description');

    $muKidsExerciseDescription.width($muKidsExercise.width() - $muKidsStatesContainer.width() - margin);

    $muKidsStates.each((index, state) => mumuki.kids.scaleStates($(state), fullMargin));

    var $muKidsBlocks = $('.mu-kids-blocks');
    var $blockArea = $muKidsBlocks.find('#blocklyDiv');
    var $blockSvg = $muKidsBlocks.find('.blocklySvg');

    $blockArea.width($muKidsBlocks.width());
    $blockArea.height($muKidsBlocks.height());

    $blockSvg.width($muKidsBlocks.width());
    $blockSvg.height($muKidsBlocks.height());

    resizeSpeechParagraphs();
  });

  mumuki.kids = {
    registerStatesScaler: function(scaler) {
      this._statesScaler = scaler;
    },

    scaleStates: function ($state, fullMargin) {
      const preferredWidth = $state.width() - fullMargin * 2;
      const preferredHeight = $state.height() - fullMargin * 2;
      this._statesScaler($state, fullMargin, preferredWidth, preferredHeight);
    },

    getResultsModal: function () {
      return $('#kids-results');
    },

    getResultsAbortedModal: function () {
      return $('#kids-results-aborted');
    },

    getCharaterImage: function () {
      return $('.mu-kids-character > img');
    },

    getCharacterBubble: function () {
      return $('.mu-kids-character-speech-bubble');
    },

    getSubmissionResult: function () {
      return $('.submission-results');
    },

    getOverlay: function () {
      return $('.mu-kids-overlay');
    },

    showResult: function (data) {  // This function is called by the custom runner
      mumuki.updateProgressBarAndShowModal(data);
      if (data.guide_finished_by_solution) return;
      mumuki.kids.resultAction[data.status](data);
    },

    restart: function () {  // This function is called by the custom runner
      mumuki.kids._hideMessageOnCharacterBubble();
      var $bubble = mumuki.kids.getCharacterBubble();
      Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
      mumuki.presenterCharacter.playAnimation('jump', mumuki.kids.getCharaterImage());
    },

    _hideMessageOnCharacterBubble: function () {
      var $bubble = mumuki.kids.getCharacterBubble();
      $bubble.find('.mu-kids-character-speech-bubble-tabs').show();
      $bubble.find('.mu-kids-character-speech-bubble-normal').show();
      $bubble.find('.mu-kids-character-speech-bubble-failed').hide();
      Object.keys(mumuki.kids.resultAction).forEach($bubble.removeClass.bind($bubble));
      mumuki.kids.getOverlay().hide();
    },

    _showMessageOnCharacterBubble: function (data) {
      var $bubble = mumuki.kids.getCharacterBubble();
      $bubble.find('.mu-kids-character-speech-bubble-tabs').hide();
      $bubble.find('.mu-kids-character-speech-bubble-normal').hide();
      $bubble.find('.mu-kids-character-speech-bubble-failed').show().html(data.title_html);
      $bubble.addClass(data.status);
      if (data.status === 'passed_with_warnings') {
        $bubble.find('.mu-kids-character-speech-bubble-failed').append(data.expectations_html);
      }
      mumuki.kids.getOverlay().show();
    },

    _showOnSuccessPopup: function (data) {
      mumuki.kids.getSubmissionResult().html(data.html);
      mumuki.presenterCharacter.playAnimation('success_l', mumuki.kids.getCharaterImage());
      mumuki.kids._showMessageOnCharacterBubble(data);
      mumuki.presenterCharacter.playAnimation('success2_l', $('.mu-kids-character-success'));
      setTimeout(function () {
        var results_kids_modal = mumuki.kids.getResultsModal();
        if (results_kids_modal) {
          results_kids_modal.modal({
            backdrop: 'static',
            keyboard: false
          });
          results_kids_modal.find('.modal-header').first().html(data.title_html);
          results_kids_modal.find('.modal-footer').first().html(data.button_html);
          mumuki.kids._showCorollaryCharacter();
          $('.mu-close-modal').click(() => $('#kids-results').modal('hide'));
        }
      }, 1000 * 4);
    },

    _showOnFailurePopup: function () {
      mumuki.kids.submitButton.disable();
      mumuki.kids.getResultsAbortedModal().modal();
      mumuki.submission.animateTimeoutError(mumuki.kids.submitButton);
    },

    _showOnCharacterBubble: function (data) {
      mumuki.presenterCharacter.playAnimation('failure', mumuki.kids.getCharaterImage());
      mumuki.kids._showMessageOnCharacterBubble(data);
    },

    _showCorollaryCharacter: function () {
      mumuki.characters.magnifying_glass.playAnimation('show', $('.mu-kids-corollary-animation'));
    },

    _statesScaler: function ($state, fullMargin, preferredWidth, preferredHeight) {
      console.warn("You are using the default scaler, which is gobstones-specific");
      console.warn("Please register your own scaler in the future");
      var $table = $state.find('gs-board > table');
      if(!$table.length) return setTimeout(() => this.scaleStates($state, fullMargin));
      $table.css('transform', 'scale(1)');
      var scaleX = preferredWidth / $table.width();
      var scaleY = preferredHeight / $table.height();
      $table.css('transform', 'scale(' + Math.min(scaleX, scaleY) + ')');
    },

    resultAction: {}

  };

  const _createSubmitButton = function () {
    var submitButton = $('#kids-btn-retry');
    var submissionControl = $('.submission_control');
    return new mumuki.submission.SubmitButton(submitButton, submissionControl);
  };

  mumuki.kids.submitButton = _createSubmitButton();

  function showPrevParagraph() {
    animateSpeech();
    showParagraph(currentParagraphIndex - 1);
  }

  function showNextParagraph() {
    animateSpeech();
    showParagraph(currentParagraphIndex + 1);
    clearInterval(nextSpeechBlinking);
  }

  function animateSpeech() {
    mumuki.presenterCharacter.playAnimation('talk', mumuki.kids.getCharaterImage());
  }

  mumuki.showKidsResult = function (data) {
    mumuki.updateProgressBarAndShowModal(data);
    if (data.guide_finished_by_solution) return;
    mumuki.kids.getSubmissionResult().html(data.html);

    var results_kids_modal = mumuki.kids.getResultsModal();
    if (results_kids_modal) {
      results_kids_modal.modal();
      results_kids_modal.find('.modal-header').first().html(data.title_html);
      results_kids_modal.find('.modal-footer').first().html(data.button_html);
    }
  };

  mumuki.kids.resultAction.passed = mumuki.kids._showOnSuccessPopup;
  mumuki.kids.resultAction.passed_with_warnings = mumuki.kids._showOnCharacterBubble;

  mumuki.kids.resultAction.aborted = mumuki.kids._showOnFailurePopup;

  mumuki.kids.resultAction.failed = mumuki.kids._showOnCharacterBubble;
  mumuki.kids.resultAction.errored = mumuki.kids._showOnCharacterBubble;
  mumuki.kids.resultAction.pending = mumuki.kids._showOnCharacterBubble;
});
<|endoftext|>


<commit_before>/*!
 * Flickr Downloadr
 * Copyright: 2007-2014 Sondre Bjellås. http://sondreb.com/
 * License: MIT
 */

'use strict';

(function () {

    // Create the app module and dependencies.
    var downloadr = angular.module('downloadr', [
        'ngRoute',
        'cfp.hotkeys',
        'downloadr.filters',
        'downloadr.services',
        'downloadr.directives',
        'downloadr.controllers'
    ]);

    downloadr.value('version', '3.0');
    downloadr.value('author', 'Sondre Bjellås');
    downloadr.value('config_socket_server', 'http://downloadr.azurewebsites.net');
    //downloadr.value('config_socket_server', 'http://localhost:3000');

    downloadr.run(['$rootScope', '$location', 'searchProvider', 'socket', 'flickr', 'settings', function($rootScope, $location, searchProvider, socket, flickr, settings)
    {
        console.log('downloadr.run: ', flickr);

        // i18n example:
        var resourceText = chrome.i18n.getMessage("settings_title");

        console.log('Resource Text: ', resourceText);

        $rootScope.state = {

            isAnonymous: true,

            isConnecting: true,

            // Used to see if we're running inside Chrome Packaged App.
            packaged: chrome.runtime !== undefined,

            background: 'wallpaper',

            showActions: false,

            actionTarget: 'folder',

            targetPath: '',

            targetEntry: null,

            searchText: '',

            loginUrl: '',

            selectedPhotos: [],

            debug: false,

            photoSize: 'o'

        };

        $rootScope.$on("$routeChangeStart", function (event, next, current) {

          var path = $location.path();

          // Whenever the user navigate, we'll hide the actions bar.
          // It will manually be re-enabled by controllers that use it.
          $rootScope.state.showActions = false;

          if (path == "/" || path == "")
          {
            $rootScope.state.isOnStartScreen = true;
          }
          else
          {
            $rootScope.state.isOnStartScreen = false;
          }

        });

        $rootScope.performSearch = function(){

          if ($rootScope.state.searchText === null || $rootScope.state.searchText === '')
          {
            $rootScope.state.searchText = 'Kittens';
          }

          console.log('CLICK PERFORM SEARCH: ', $rootScope.state.searchText);

          $rootScope.$broadcast('Event:Search', { value: $rootScope.state.searchText });

        };

        $rootScope.$broadcast('status', { message: 'Starting...' });

        // Whenever the search directive raises the search event,
        // we'll update the rootScope.state.
        /*$rootScope.$on('Event:Search', function (event, data) {

          $rootScope.state.searchText = data.value;

        });*/

        //$rootScope.$broadcast('Event:Search', { value: 'Sweeet' });

        $rootScope.$on('Event:Logout', function () {

            console.log('Logout Initialized...');

            chrome.storage.sync.set({'token': null}, function() {
              // Notify that we saved.
              message('Settings saved');
            });

            flickr.removeToken();

            $rootScope.state.isAnonymous = true;
            //$rootScope.state.isConnecting = true;

            // Make sure we get a new login url.
            socket.emit('getUrl');

            //$scope.authenticatingEvent(null);
        });

        // Make sure we listen to whenever the local storage value have changed.
        chrome.storage.onChanged.addListener(function(changes, namespace) {
              for (key in changes) {
                var storageChange = changes[key];
                console.log('Storage key "%s" in namespace "%s" changed. ' +
                            'Old value was "%s", new value is "%s".',
                            key,
                            namespace,
                            storageChange.oldValue,
                            storageChange.newValue);

                if (key == 'token')
                {
                  //flickr.parseToken(storageChange.newValue);
                }
              }
        });

        // Try to find existing token.
        chrome.storage.sync.get('token', function(result){

          if (result === undefined || result === null)
          {
            console.log('No existing token found.');

            // When no token is found, we'll issue a command to get login url.
            socket.emit('getUrl');
          }
          else if (result.token === undefined || result.token === null)
          {
            console.log('No existing token found.');

            // When no token is found, we'll issue a command to get login url.
            socket.emit('getUrl');
          }
          else
          {
            console.log('Found in local storage: ', result.token);
            flickr.parseToken(result.token);
            $rootScope.state.isAnonymous = false;
            $rootScope.state.isConnecting = false;
            $rootScope.$broadcast('status', { message: 'Authenticated. Hi ' + result.token.userName + '!' });
          }
        });

        // Whenever login URL is received, we will update the UI and enable
        // the login button.
        socket.on('url', function(message) {

          console.log('Flickr auth URL: ', message.url);

          $rootScope.state.loginUrl = message.url;
          $rootScope.state.isConnecting = false;
          $rootScope.$broadcast('status', { message: 'Connected.' });

        });

        // When we receive access token, make sure we store it permanently.
        socket.on('token', function(message) {

          // Save it using the Chrome extension storage API.
          // This will ensure the token is synced across devices.
          chrome.storage.sync.set({'token': message}, function() {
            // Notify that we saved.
            message('Settings saved');
          });

          console.log('Received Access Token: ', message);
          flickr.parseToken(message);

          $rootScope.state.isAnonymous = false;
          $rootScope.$broadcast('status', { message: 'Authenticated. Hi ' + message.userName + '!' });

        });

        // This will read oauth_token from local storage if it exists, if not, it will
        // connect to the WebSocket service and notify a request for authentication URL.
        // After the URL is generated, we'll show it to the user. When returned, it will
        // return to the WebSocket service, which in return will return the answers.
        //Flickr.Authenticate();
    }]);

    downloadr.config(['$routeProvider', function($routeProvider)
    {
        $routeProvider.when('/', { templateUrl: '/views/home.html', controller: 'HomeController' });
        $routeProvider.when('/about', { templateUrl: '/views/about.html', controller: 'AboutController' });
        $routeProvider.when('/login', { templateUrl: '/views/login.html', controller: 'LoginController' });
        $routeProvider.when('/logout', { templateUrl: '/views/logout.html', controller: 'LogoutController' });
        $routeProvider.when('/search', { templateUrl: '/views/search.html', controller: 'SearchController' });
        $routeProvider.when('/settings', { templateUrl: '/views/settings.html', controller: 'SettingsController' });
        $routeProvider.when('/profile', { templateUrl: '/views/profile.html', controller: 'ProfileController' });
        $routeProvider.when('/folder', { templateUrl: '/views/folder.html', controller: 'FolderController' });
        $routeProvider.when('/download', { templateUrl: '/views/download.html', controller: 'DownloadController' });
        $routeProvider.when('/debug', { templateUrl: '/views/debug.html', controller: 'DebugController' });
        $routeProvider.when('/tests', { templateUrl: '/views/tests.html', controller: 'TestController' });

        $routeProvider.otherwise({ redirectTo: '/' });

    }]);

    downloadr.config( ['$compileProvider', function($compileProvider)
    {
      // This has to be done or else Angular will append "unsafe:" to URLs.
      //$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|chrome-extension|blob:chrome-extension):\//);
      $compileProvider.aHrefSanitizationWhitelist (/^\s*(https?|ftp|mailto|file|tel|chrome-extension):/);

      //var oldWhiteList = $compileProvider.imgSrcSanitizationWhitelist();
      $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|chrome-extension):|data:image\//);

    }]);

})();

// Check whether new version is installed
/* Keeping for future use.
chrome.runtime.onInstalled.addListener(function(details){
    if(details.reason == "install"){
        console.log("This is a first install!");
    }else if(details.reason == "update"){
        var thisVersion = chrome.runtime.getManifest().version;
        console.log("Updated from " + details.previousVersion + " to " + thisVersion + "!");
    }
});
*/
<commit_msg>Add production URL<commit_after>/*!
 * Flickr Downloadr
 * Copyright: 2007-2014 Sondre Bjellås. http://sondreb.com/
 * License: MIT
 */

'use strict';

(function () {

    // Create the app module and dependencies.
    var downloadr = angular.module('downloadr', [
        'ngRoute',
        'cfp.hotkeys',
        'downloadr.filters',
        'downloadr.services',
        'downloadr.directives',
        'downloadr.controllers'
    ]);

    downloadr.value('version', '3.0');
    downloadr.value('author', 'Sondre Bjellås');
    downloadr.value('config_socket_server', 'http://flickr-downloadr.com');
    //downloadr.value('config_socket_server', 'http://localhost:3000');

    downloadr.run(['$rootScope', '$location', 'searchProvider', 'socket', 'flickr', 'settings', function($rootScope, $location, searchProvider, socket, flickr, settings)
    {
        console.log('downloadr.run: ', flickr);

        // i18n example:
        var resourceText = chrome.i18n.getMessage("settings_title");

        console.log('Resource Text: ', resourceText);

        $rootScope.state = {

            isAnonymous: true,

            isConnecting: true,

            // Used to see if we're running inside Chrome Packaged App.
            packaged: chrome.runtime !== undefined,

            background: 'wallpaper',

            showActions: false,

            actionTarget: 'folder',

            targetPath: '',

            targetEntry: null,

            searchText: '',

            loginUrl: '',

            selectedPhotos: [],

            debug: false,

            photoSize: 'o'

        };

        $rootScope.$on("$routeChangeStart", function (event, next, current) {

          var path = $location.path();

          // Whenever the user navigate, we'll hide the actions bar.
          // It will manually be re-enabled by controllers that use it.
          $rootScope.state.showActions = false;

          if (path == "/" || path == "")
          {
            $rootScope.state.isOnStartScreen = true;
          }
          else
          {
            $rootScope.state.isOnStartScreen = false;
          }

        });

        $rootScope.performSearch = function(){

          if ($rootScope.state.searchText === null || $rootScope.state.searchText === '')
          {
            $rootScope.state.searchText = 'Kittens';
          }

          console.log('CLICK PERFORM SEARCH: ', $rootScope.state.searchText);

          $rootScope.$broadcast('Event:Search', { value: $rootScope.state.searchText });

        };

        $rootScope.$broadcast('status', { message: 'Starting...' });

        // Whenever the search directive raises the search event,
        // we'll update the rootScope.state.
        /*$rootScope.$on('Event:Search', function (event, data) {

          $rootScope.state.searchText = data.value;

        });*/

        //$rootScope.$broadcast('Event:Search', { value: 'Sweeet' });

        $rootScope.$on('Event:Logout', function () {

            console.log('Logout Initialized...');

            chrome.storage.sync.set({'token': null}, function() {
              // Notify that we saved.
              message('Settings saved');
            });

            flickr.removeToken();

            $rootScope.state.isAnonymous = true;
            //$rootScope.state.isConnecting = true;

            // Make sure we get a new login url.
            socket.emit('getUrl');

            //$scope.authenticatingEvent(null);
        });

        // Make sure we listen to whenever the local storage value have changed.
        chrome.storage.onChanged.addListener(function(changes, namespace) {
              for (key in changes) {
                var storageChange = changes[key];
                console.log('Storage key "%s" in namespace "%s" changed. ' +
                            'Old value was "%s", new value is "%s".',
                            key,
                            namespace,
                            storageChange.oldValue,
                            storageChange.newValue);

                if (key == 'token')
                {
                  //flickr.parseToken(storageChange.newValue);
                }
              }
        });

        // Try to find existing token.
        chrome.storage.sync.get('token', function(result){

          if (result === undefined || result === null)
          {
            console.log('No existing token found.');

            // When no token is found, we'll issue a command to get login url.
            socket.emit('getUrl');
          }
          else if (result.token === undefined || result.token === null)
          {
            console.log('No existing token found.');

            // When no token is found, we'll issue a command to get login url.
            socket.emit('getUrl');
          }
          else
          {
            console.log('Found in local storage: ', result.token);
            flickr.parseToken(result.token);
            $rootScope.state.isAnonymous = false;
            $rootScope.state.isConnecting = false;
            $rootScope.$broadcast('status', { message: 'Authenticated. Hi ' + result.token.userName + '!' });
          }
        });

        // Whenever login URL is received, we will update the UI and enable
        // the login button.
        socket.on('url', function(message) {

          console.log('Flickr auth URL: ', message.url);

          $rootScope.state.loginUrl = message.url;
          $rootScope.state.isConnecting = false;
          $rootScope.$broadcast('status', { message: 'Connected.' });

        });

        // When we receive access token, make sure we store it permanently.
        socket.on('token', function(message) {

          // Save it using the Chrome extension storage API.
          // This will ensure the token is synced across devices.
          chrome.storage.sync.set({'token': message}, function() {
            // Notify that we saved.
            message('Settings saved');
          });

          console.log('Received Access Token: ', message);
          flickr.parseToken(message);

          $rootScope.state.isAnonymous = false;
          $rootScope.$broadcast('status', { message: 'Authenticated. Hi ' + message.userName + '!' });

        });

        // This will read oauth_token from local storage if it exists, if not, it will
        // connect to the WebSocket service and notify a request for authentication URL.
        // After the URL is generated, we'll show it to the user. When returned, it will
        // return to the WebSocket service, which in return will return the answers.
        //Flickr.Authenticate();
    }]);

    downloadr.config(['$routeProvider', function($routeProvider)
    {
        $routeProvider.when('/', { templateUrl: '/views/home.html', controller: 'HomeController' });
        $routeProvider.when('/about', { templateUrl: '/views/about.html', controller: 'AboutController' });
        $routeProvider.when('/login', { templateUrl: '/views/login.html', controller: 'LoginController' });
        $routeProvider.when('/logout', { templateUrl: '/views/logout.html', controller: 'LogoutController' });
        $routeProvider.when('/search', { templateUrl: '/views/search.html', controller: 'SearchController' });
        $routeProvider.when('/settings', { templateUrl: '/views/settings.html', controller: 'SettingsController' });
        $routeProvider.when('/profile', { templateUrl: '/views/profile.html', controller: 'ProfileController' });
        $routeProvider.when('/folder', { templateUrl: '/views/folder.html', controller: 'FolderController' });
        $routeProvider.when('/download', { templateUrl: '/views/download.html', controller: 'DownloadController' });
        $routeProvider.when('/debug', { templateUrl: '/views/debug.html', controller: 'DebugController' });
        $routeProvider.when('/tests', { templateUrl: '/views/tests.html', controller: 'TestController' });

        $routeProvider.otherwise({ redirectTo: '/' });

    }]);

    downloadr.config( ['$compileProvider', function($compileProvider)
    {
      // This has to be done or else Angular will append "unsafe:" to URLs.
      //$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|chrome-extension|blob:chrome-extension):\//);
      $compileProvider.aHrefSanitizationWhitelist (/^\s*(https?|ftp|mailto|file|tel|chrome-extension):/);

      //var oldWhiteList = $compileProvider.imgSrcSanitizationWhitelist();
      $compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|ftp|file|blob|chrome-extension):|data:image\//);

    }]);

})();

// Check whether new version is installed
/* Keeping for future use.
chrome.runtime.onInstalled.addListener(function(details){
    if(details.reason == "install"){
        console.log("This is a first install!");
    }else if(details.reason == "update"){
        var thisVersion = chrome.runtime.getManifest().version;
        console.log("Updated from " + details.previousVersion + " to " + thisVersion + "!");
    }
});
*/
<|endoftext|>


<commit_before>(function(global) {
  "use strict";

  var queues = {};
  var morphdom = global.GOVUK.vendor.morphdom;
  var defaultInterval = 2000;
  var interval = 0;

  var calculateBackoff = responseTime => parseInt(Math.max(
      (250 * Math.sqrt(responseTime)) - 1000,
      1000
  ));

  // Methods to ensure the DOM fragment is clean of classes added by JS before diffing
  // and that they are replaced afterwards.
  //
  // Added to allow the use of JS, in main.js, to apply styles which in future could be
  // achieved with the :has pseudo-class. If :has is available in our supported browsers,
  // this can be removed in favour of a CSS-only solution.
  var classesPersister = {
    _classNames: [],
    _classesTo$ElsMap: {},
    addClassName: function (className) {
      if (this._classNames.indexOf(className) === -1) {
        this._classNames.push(className);
      }
    },
    remove: function () {
      // Store references to any elements with class names to persist
      this._classNames.forEach(className => {
        var $elsWithClassName = $('.' + className).removeClass(className);

        if ($elsWithClassName.length > 0) {
          this._classesTo$ElsMap[className] = $elsWithClassName;
        }
      });
    },
    replace: function () {
      var className;

      for (className in this._classesTo$ElsMap) {
        this._classesTo$ElsMap[className].each((idx, el) => {

          // Avoid updating elements that are no longer present.
          // elements removed will still exist in memory but won't be attached to the DOM any more
          if (global.document.body.contains(el)) {
            $(el).addClass(className);
          }

        });
      }

      // remove references to elements
      this._classesTo$ElsMap = {};
    }
  };

  var getRenderer = ($contents, key) => response => {
    classesPersister.remove();
    morphdom(
      $contents.get(0),
      $(response[key]).get(0)
    );
    classesPersister.replace();
  };

  var getQueue = resource => (
    queues[resource] = queues[resource] || []
  );

  var flushQueue = function(queue, response) {
    while(queue.length) queue.shift()(response);
  };

  var clearQueue = queue => (queue.length = 0);

  var poll = function(renderer, resource, queue, form) {

    let startTime = Date.now();

    if (document.visibilityState !== "hidden" && queue.push(renderer) === 1) $.ajax(
      resource,
      {
        'method': form ? 'post' : 'get',
        'data': form ? $('#' + form).serialize() : {}
      }
    ).done(
      response => {
        flushQueue(queue, response);
        if (response.stop === 1) {
          poll = function(){};
        }
        interval = calculateBackoff(Date.now() - startTime);
      }
    ).fail(
      () => poll = function(){}
    );

    setTimeout(
      () => poll.apply(window, arguments), interval
    );
  };

  global.GOVUK.Modules.UpdateContent = function() {

    this.start = component => {
      var $component = $(component);
      var $contents = $component.children().eq(0);
      var key = $component.data('key');
      var resource = $component.data('resource');
      var form = $component.data('form');

      // Replace component with contents.
      // The renderer does this anyway when diffing against the first response
      $component.replaceWith($contents);

      // Store any classes that should persist through updates
      //
      // Added to allow the use of JS, in main.js, to apply styles which in future could be
      // achieved with the :has pseudo-class. If :has is available in our supported browsers,
      // this can be removed in favour of a CSS-only solution.
      if ($contents.data('classesToPersist') !== undefined) {
        $contents.data('classesToPersist')
          .split(' ')
          .forEach(className => classesPersister.addClassName(className));
      }

      setTimeout(
        () => poll(
          getRenderer($contents, key),
          resource,
          getQueue(resource),
          form
        ),
        defaultInterval
      );
    };

  };

  global.GOVUK.Modules.UpdateContent.calculateBackoff = calculateBackoff;

})(window);
<commit_msg>Make a classesPersister per component instance<commit_after>(function(global) {
  "use strict";

  var queues = {};
  var morphdom = global.GOVUK.vendor.morphdom;
  var defaultInterval = 2000;
  var interval = 0;

  var calculateBackoff = responseTime => parseInt(Math.max(
      (250 * Math.sqrt(responseTime)) - 1000,
      1000
  ));

  // Methods to ensure the DOM fragment is clean of classes added by JS before diffing
  // and that they are replaced afterwards.
  //
  // Added to allow the use of JS, in main.js, to apply styles which in future could be
  // achieved with the :has pseudo-class. If :has is available in our supported browsers,
  // this can be removed in favour of a CSS-only solution.
  var ClassesPersister = function ($contents) {
    this._$contents = $contents;
    this._classNames = [];
    this._classesTo$ElsMap = {};
  };
  ClassesPersister.prototype.addClassName = function (className) {
    if (this._classNames.indexOf(className) === -1) {
      this._classNames.push(className);
    }
  };
  ClassesPersister.prototype.remove = function () {
    // Store references to any elements with class names to persist
    this._classNames.forEach(className => {
      var $elsWithClassName = $('.' + className, this._$contents).removeClass(className);

      if ($elsWithClassName.length > 0) {
        this._classesTo$ElsMap[className] = $elsWithClassName;
      }
    });
  };
  ClassesPersister.prototype.replace = function () {
    var className;

    for (className in this._classesTo$ElsMap) {
      this._classesTo$ElsMap[className].each((idx, el) => {

        // Avoid updating elements that are no longer present.
        // elements removed will still exist in memory but won't be attached to the DOM any more
        if (global.document.body.contains(el)) {
          $(el).addClass(className);
        }

      });
    }

    // remove references to elements
    this._classesTo$ElsMap = {};
  };

  var getRenderer = ($contents, key, classesPersister) => response => {
    classesPersister.remove();
    morphdom(
      $contents.get(0),
      $(response[key]).get(0)
    );
    classesPersister.replace();
  };

  var getQueue = resource => (
    queues[resource] = queues[resource] || []
  );

  var flushQueue = function(queue, response) {
    while(queue.length) queue.shift()(response);
  };

  var clearQueue = queue => (queue.length = 0);

  var poll = function(renderer, resource, queue, form) {

    let startTime = Date.now();

    if (document.visibilityState !== "hidden" && queue.push(renderer) === 1) $.ajax(
      resource,
      {
        'method': form ? 'post' : 'get',
        'data': form ? $('#' + form).serialize() : {}
      }
    ).done(
      response => {
        flushQueue(queue, response);
        if (response.stop === 1) {
          poll = function(){};
        }
        interval = calculateBackoff(Date.now() - startTime);
      }
    ).fail(
      () => poll = function(){}
    );

    setTimeout(
      () => poll.apply(window, arguments), interval
    );
  };

  global.GOVUK.Modules.UpdateContent = function() {

    this.start = component => {
      var $component = $(component);
      var $contents = $component.children().eq(0);
      var key = $component.data('key');
      var resource = $component.data('resource');
      var form = $component.data('form');
      var classesPersister = new ClassesPersister($contents);

      // Replace component with contents.
      // The renderer does this anyway when diffing against the first response
      $component.replaceWith($contents);

      // Store any classes that should persist through updates
      //
      // Added to allow the use of JS, in main.js, to apply styles which in future could be
      // achieved with the :has pseudo-class. If :has is available in our supported browsers,
      // this can be removed in favour of a CSS-only solution.
      if ($contents.data('classesToPersist') !== undefined) {
        $contents.data('classesToPersist')
          .split(' ')
          .forEach(className => classesPersister.addClassName(className));
      }

      setTimeout(
        () => poll(
          getRenderer($contents, key, classesPersister),
          resource,
          getQueue(resource),
          form
        ),
        defaultInterval
      );
    };

  };

  global.GOVUK.Modules.UpdateContent.calculateBackoff = calculateBackoff;

})(window);
<|endoftext|>