<commit_before>// $(document).ready(function() {
//   var imageUrl = $('body').find('img').attr('src');
//   var imgTag = [""].join('');
//   for (var i=1;i<40;i++) {$('#images').append(imgTag);}
// });

// $(function() {

//   console.log("whee!")

//   // event handler
//   $(".heart-click").click(function(e) {
//   	$("#heart-append").append("");
//   });

// });

$(function() {

  var endDate = "February 12, 2014 10:54:00";
  $('.end').countdown({
    date: endDate,
    render: function(data) {
      $(this.el).html("
" + this.leadingZeros(data.days, 3) + " days

" + this.leadingZeros(data.hours, 2) + " hrs

" + this.leadingZeros(data.min, 2) + " min

" + this.leadingZeros(data.sec, 2) + " sec
");
    }
  });

  $('.search').on('keyup', function(e){
    if(e.keyCode === 13) {
      var num = $(this).val();
      var out = ""
      console.log(num)
      for (var i = 0; i < num; i++) {
        out = out + "kiss "
      };
      // var out = parameters * "kiss "
      $('.results').html(out);
    };
  });

});

<commit_msg>error handler<commit_after>// $(document).ready(function() {
//   var imageUrl = $('body').find('img').attr('src');
//   var imgTag = [""].join('');
//   for (var i=1;i<40;i++) {$('#images').append(imgTag);}
// });

// $(function() {

//   console.log("whee!")

//   // event handler
//   $(".heart-click").click(function(e) {
//   	$("#heart-append").append("");
//   });

// });

$(function() {

  var endDate = "February 12, 2014 10:54:00";
  $('.end').countdown({
    date: endDate,
    render: function(data) {
      $(this.el).html("
" + this.leadingZeros(data.days, 3) + " days

" + this.leadingZeros(data.hours, 2) + " hrs

" + this.leadingZeros(data.min, 2) + " min

" + this.leadingZeros(data.sec, 2) + " sec
");
    }
  });

  $('.search').on('keyup', function(e){
    if(e.keyCode === 13) {
      var num = $(this).val();
      var out = ""
      if (num > 100) {
        num = 100
        console.log("handle that")
        out = out + "Sorry. I can only handle 100 kisses at once." + "

"
      };
      for (var i = 0; i < num; i++) {
        out = out + "kiss "
        $('.results').html(out);
      };
    };
  });

});

<|endoftext|>


<commit_before>
/*!
 * Includedeck.
 *
 * Copyright (c) 2013 Rémi Emonet.
 * Dual licensed under the MIT license and GPL license.
 * https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
 * https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
 *
 * The goal of this extension is to simplify include of deck.js,
 * its profiles/themes and the extensions.
 *
 * The first goal is not performance of loading (still it should
 * allow the display of a message while loading) but on ease of
 * use and extensibility (i.e., includedeck does not need to know
 * about all existing extensions, even if by default it does know
 * some of them).
 *
 */

var head_conf = {

};

// this is head.load.min.js (v0.99)
/*!
 * HeadJS     The only script in your <HEAD>
 * Author     Tero Piirainen  (tipiirai)
 * Maintainer Robert Hoffmann (itechnology)
 * License    MIT / http://bit.ly/mit-license
 *
 * Version 0.99
 * http://headjs.com
 */
(function(f,w){function m(){}function g(a,b){if(a){"object"===typeof a&&(a=[].slice.call(a));for(var c=0,d=a.length;c<d;c++)b.call(a,a[c],c)}}function v(a,b){var c=Object.prototype.toString.call(b).slice(8,-1);return b!==w&&null!==b&&c===a}function k(a){return v("Function",a)}function h(a){a=a||m;a._done||(a(),a._done=1)}function n(a){var b={};if("object"===typeof a)for(var c in a)a[c]&&(b={name:c,url:a[c]});else b=a.split("/"),b=b[b.length-1],c=b.indexOf("?"),b={name:-1!==c?b.substring(0,c):b,url:a};
return(a=p[b.name])&&a.url===b.url?a:p[b.name]=b}function q(a){var a=a||p,b;for(b in a)if(a.hasOwnProperty(b)&&a[b].state!==r)return!1;return!0}function s(a,b){b=b||m;a.state===r?b():a.state===x?d.ready(a.name,b):a.state===y?a.onpreload.push(function(){s(a,b)}):(a.state=x,z(a,function(){a.state=r;b();g(l[a.name],function(a){h(a)});j&&q()&&g(l.ALL,function(a){h(a)})}))}function z(a,b){var b=b||m,c;/\.css[^\.]*$/.test(a.url)?(c=e.createElement("link"),c.type="text/"+(a.type||"css"),c.rel="stylesheet",
c.href=a.url):(c=e.createElement("script"),c.type="text/"+(a.type||"javascript"),c.src=a.url);c.onload=c.onreadystatechange=function(a){a=a||f.event;if("load"===a.type||/loaded|complete/.test(c.readyState)&&(!e.documentMode||9>e.documentMode))c.onload=c.onreadystatechange=c.onerror=null,b()};c.onerror=function(){c.onload=c.onreadystatechange=c.onerror=null;b()};c.async=!1;c.defer=!1;var d=e.head||e.getElementsByTagName("head")[0];d.insertBefore(c,d.lastChild)}function i(){e.body?j||(j=!0,g(A,function(a){h(a)})):
(f.clearTimeout(d.readyTimeout),d.readyTimeout=f.setTimeout(i,50))}function t(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",t,!1),i()):"complete"===e.readyState&&(e.detachEvent("onreadystatechange",t),i())}var e=f.document,A=[],B=[],l={},p={},E="async"in e.createElement("script")||"MozAppearance"in e.documentElement.style||f.opera,C,j,D=f.head_conf&&f.head_conf.head||"head",d=f[D]=f[D]||function(){d.ready.apply(null,arguments)},y=1,x=3,r=4;d.load=E?function(){var a=arguments,b=a[a.length-
1],c={};k(b)||(b=null);g(a,function(d,e){d!==b&&(d=n(d),c[d.name]=d,s(d,b&&e===a.length-2?function(){q(c)&&h(b)}:null))});return d}:function(){var a=arguments,b=[].slice.call(a,1),c=b[0];if(!C)return B.push(function(){d.load.apply(null,a)}),d;c?(g(b,function(a){if(!k(a)){var b=n(a);b.state===w&&(b.state=y,b.onpreload=[],z({url:b.url,type:"cache"},function(){b.state=2;g(b.onpreload,function(a){a.call()})}))}}),s(n(a[0]),k(c)?c:function(){d.load.apply(null,b)})):s(n(a[0]));return d};d.js=d.load;d.test=
function(a,b,c,e){a="object"===typeof a?a:{test:a,success:b?v("Array",b)?b:[b]:!1,failure:c?v("Array",c)?c:[c]:!1,callback:e||m};(b=!!a.test)&&a.success?(a.success.push(a.callback),d.load.apply(null,a.success)):!b&&a.failure?(a.failure.push(a.callback),d.load.apply(null,a.failure)):e();return d};d.ready=function(a,b){if(a===e)return j?h(b):A.push(b),d;k(a)&&(b=a,a="ALL");if("string"!==typeof a||!k(b))return d;var c=p[a];if(c&&c.state===r||"ALL"===a&&q()&&j)return h(b),d;(c=l[a])?c.push(b):l[a]=[b];
return d};d.ready(e,function(){q()&&g(l.ALL,function(a){h(a)});d.feature&&d.feature("domloaded",!0)});if("complete"===e.readyState)i();else if(e.addEventListener)e.addEventListener("DOMContentLoaded",t,!1),f.addEventListener("load",i,!1);else{e.attachEvent("onreadystatechange",t);f.attachEvent("onload",i);var u=!1;try{u=null==f.frameElement&&e.documentElement}catch(F){}u&&u.doScroll&&function b(){if(!j){try{u.doScroll("left")}catch(c){f.clearTimeout(d.readyTimeout);d.readyTimeout=f.setTimeout(b,50);
return}i()}}()}setTimeout(function(){C=!0;g(B,function(b){b()})},300)})(window);

// this is the actual includedeck

function includedeck(m, c) {
    var modules = m || [];
    var conf = c || {};
    var atExit = conf.ATEXIT || (function(){});
    var deckSelector = conf.DECK || '.slide';

    if (typeof(modules) == "string") {
        modules = modules.split(/ +/);
    }

    // todo: make this externally extensible
    // todo: maybe have a mechanism to load a list of dependency (e.g., mymodule-files.js)

    var prefix = conf.PREFIX || "deck.js";
    var info = {
        //
        // core (differerent possible cores)
        "deck-core-dependencies": [
            prefix + "/jquery-1.7.2.min.js",
            prefix + "/modernizr.custom.js"
        ],
        "deck": [
            "@_deck-core-dependencies",
	    prefix + "/core/deck.core.css",
            prefix + "/core/deck.core.js"
        ],
        "newdeck": [
            "@_deck-core-dependencies",
	    prefix + "/extensions/style-chunks/core.css",
            prefix + "/core/deck.core.js"
        ],
        //
        // extensions
        "fit": [ prefix + "/extensions/fit/deck.fit.js" ],
        "fit-fs": [
            prefix + "/extensions/fit/deck.fit-fs.css",
            "@_fit"
        ],
        "simplemath": [
            prefix + "/libs/display-latex2.user.js",
            prefix + "/extensions/simplemath/deck.simplemath.js"
        ],
        "smartsyntax": [ prefix + "/extensions/smartsyntax/deck.smartsyntax.js" ],
        "clone": [ prefix + "/extensions/clone/deck.clone.js" ],
        "goto": [
            prefix + "/extensions/goto/deck.goto.css",
            prefix + "/extensions/goto/deck.goto.js"
        ],
        "status": [
            prefix + "/extensions/status/deck.status.css",
            prefix + "/extensions/status/deck.status.js"
        ],
        "navigation": [
            prefix + "/extensions/navigation/deck.navigation.css",
            prefix + "/extensions/navigation/deck.navigation.js"
        ],
        "menu": [
            prefix + "/extensions/menu/deck.menu.css",
            prefix + "/extensions/menu/deck.menu.js"
        ],
        "hash": [
            prefix + "/extensions/hash/deck.hash.css",
            prefix + "/extensions/hash/deck.hash.js"
        ],
        "step": [ prefix + "/extensions/step/deck.step.js" ],
        "events": [ prefix + "/extensions/events/deck.events.js" ],
        "anim": [ prefix + "/extensions/anim/deck.anim.js" ],
        "svg": [
            prefix + "/libs/jquerysvg/jquery.svg.min.js" ,
            prefix + "/libs/jquerysvg/jquery.svganim.min.js",
            prefix + "/extensions/svg/deck.svg.js"
        ],
        //
        // Themes
        // // by convention, "theme:blabla" will load the default blabla theme
        //
        // Some default profiles
        //
        /// profile-1: default deck with most extensions and no theme
        "profile-1": ["@_deck", "@_smartsyntax", "@_fit-fs", "@_simplemath", "@_clone", "@_goto", "@_status", "@_navigation", "@_menu", "@_hash", "@_step", "@_events", "@_anim", "@_svg"],
        /// profile-2: new deck (cleaner css) with most extensions and no theme
        "profile-2": ["@_newdeck", "@_smartsyntax", "@_fit-fs", "@_simplemath", "@_clone", "@_goto", "@_status", "@_navigation", "@_menu", "@_hash", "@_step", "@_events", "@_anim", "@_svg"],
        dummy: {} // TODO add a newdeck (remove the in-adapted default css from deck core)
    };

    var endsInJsOrCss = /\.(css|js)$/;

    // Defensive check that there are no *.js/*.css in the info (as they won't be useable anyways)
    for (k in info) {
        if (endsInJsOrCss.test(k)) {
            alert("Internal problem detected in includedeck: '" + k + "' won't be useable.");
        }
    }

    // todo: handle default extensions (deck.js/extensions/N/deck.N.{js,css}
    // TODO: some should come before others, e.g. anim before svg, (or before any (deck) or before most (loading...))

    var toLoad = [];
    var addInfo = function(k) {
        if (k.substring(0, 6) == "theme:") {
            toLoad = toLoad.concat(prefix + "/themes/style/" + k.substring(6) + ".css");
            return;
        }
        if (endsInJsOrCss.test(k)) {
            toLoad = toLoad.concat(k);
            return;
        }
        for (i in info[k]) {
            if (info[k][i].substring(0,2) == "@_") {
                addInfo(info[k][i].substring(2));
            } else {
                toLoad = toLoad.concat(info[k][i]);
            }
        }
    }

    for (i in modules) {
        addInfo(modules[i]);
    }

    { // First insert a CSS, just to fit modernizr
        var c = document.createElement("style");
        c.type = "text/css";
        document.getElementsByTagName("head")[0].appendChild(c);
    }

    head.js.apply(head,toLoad.concat(function() {
        $(function() {
            $.deck(deckSelector, conf);
            atExit();
        });
    }));
}

<commit_msg>[includedeck] fix/workaround for head.js not invoking the callback when the last element is a css file<commit_after>
/*!
 * Includedeck.
 *
 * Copyright (c) 2013 Rémi Emonet.
 * Dual licensed under the MIT license and GPL license.
 * https://github.com/imakewebthings/deck.js/blob/master/MIT-license.txt
 * https://github.com/imakewebthings/deck.js/blob/master/GPL-license.txt
 *
 * The goal of this extension is to simplify include of deck.js,
 * its profiles/themes and the extensions.
 *
 * The first goal is not performance of loading (still it should
 * allow the display of a message while loading) but on ease of
 * use and extensibility (i.e., includedeck does not need to know
 * about all existing extensions, even if by default it does know
 * some of them).
 *
 */

var head_conf = {

};

// this is head.load.min.js (v0.99)
/*!
 * HeadJS     The only script in your <HEAD>
 * Author     Tero Piirainen  (tipiirai)
 * Maintainer Robert Hoffmann (itechnology)
 * License    MIT / http://bit.ly/mit-license
 *
 * Version 0.99
 * http://headjs.com
 */
(function(f,w){function m(){}function g(a,b){if(a){"object"===typeof a&&(a=[].slice.call(a));for(var c=0,d=a.length;c<d;c++)b.call(a,a[c],c)}}function v(a,b){var c=Object.prototype.toString.call(b).slice(8,-1);return b!==w&&null!==b&&c===a}function k(a){return v("Function",a)}function h(a){a=a||m;a._done||(a(),a._done=1)}function n(a){var b={};if("object"===typeof a)for(var c in a)a[c]&&(b={name:c,url:a[c]});else b=a.split("/"),b=b[b.length-1],c=b.indexOf("?"),b={name:-1!==c?b.substring(0,c):b,url:a};
return(a=p[b.name])&&a.url===b.url?a:p[b.name]=b}function q(a){var a=a||p,b;for(b in a)if(a.hasOwnProperty(b)&&a[b].state!==r)return!1;return!0}function s(a,b){b=b||m;a.state===r?b():a.state===x?d.ready(a.name,b):a.state===y?a.onpreload.push(function(){s(a,b)}):(a.state=x,z(a,function(){a.state=r;b();g(l[a.name],function(a){h(a)});j&&q()&&g(l.ALL,function(a){h(a)})}))}function z(a,b){var b=b||m,c;/\.css[^\.]*$/.test(a.url)?(c=e.createElement("link"),c.type="text/"+(a.type||"css"),c.rel="stylesheet",
c.href=a.url):(c=e.createElement("script"),c.type="text/"+(a.type||"javascript"),c.src=a.url);c.onload=c.onreadystatechange=function(a){a=a||f.event;if("load"===a.type||/loaded|complete/.test(c.readyState)&&(!e.documentMode||9>e.documentMode))c.onload=c.onreadystatechange=c.onerror=null,b()};c.onerror=function(){c.onload=c.onreadystatechange=c.onerror=null;b()};c.async=!1;c.defer=!1;var d=e.head||e.getElementsByTagName("head")[0];d.insertBefore(c,d.lastChild)}function i(){e.body?j||(j=!0,g(A,function(a){h(a)})):
(f.clearTimeout(d.readyTimeout),d.readyTimeout=f.setTimeout(i,50))}function t(){e.addEventListener?(e.removeEventListener("DOMContentLoaded",t,!1),i()):"complete"===e.readyState&&(e.detachEvent("onreadystatechange",t),i())}var e=f.document,A=[],B=[],l={},p={},E="async"in e.createElement("script")||"MozAppearance"in e.documentElement.style||f.opera,C,j,D=f.head_conf&&f.head_conf.head||"head",d=f[D]=f[D]||function(){d.ready.apply(null,arguments)},y=1,x=3,r=4;d.load=E?function(){var a=arguments,b=a[a.length-
1],c={};k(b)||(b=null);g(a,function(d,e){d!==b&&(d=n(d),c[d.name]=d,s(d,b&&e===a.length-2?function(){q(c)&&h(b)}:null))});return d}:function(){var a=arguments,b=[].slice.call(a,1),c=b[0];if(!C)return B.push(function(){d.load.apply(null,a)}),d;c?(g(b,function(a){if(!k(a)){var b=n(a);b.state===w&&(b.state=y,b.onpreload=[],z({url:b.url,type:"cache"},function(){b.state=2;g(b.onpreload,function(a){a.call()})}))}}),s(n(a[0]),k(c)?c:function(){d.load.apply(null,b)})):s(n(a[0]));return d};d.js=d.load;d.test=
function(a,b,c,e){a="object"===typeof a?a:{test:a,success:b?v("Array",b)?b:[b]:!1,failure:c?v("Array",c)?c:[c]:!1,callback:e||m};(b=!!a.test)&&a.success?(a.success.push(a.callback),d.load.apply(null,a.success)):!b&&a.failure?(a.failure.push(a.callback),d.load.apply(null,a.failure)):e();return d};d.ready=function(a,b){if(a===e)return j?h(b):A.push(b),d;k(a)&&(b=a,a="ALL");if("string"!==typeof a||!k(b))return d;var c=p[a];if(c&&c.state===r||"ALL"===a&&q()&&j)return h(b),d;(c=l[a])?c.push(b):l[a]=[b];
return d};d.ready(e,function(){q()&&g(l.ALL,function(a){h(a)});d.feature&&d.feature("domloaded",!0)});if("complete"===e.readyState)i();else if(e.addEventListener)e.addEventListener("DOMContentLoaded",t,!1),f.addEventListener("load",i,!1);else{e.attachEvent("onreadystatechange",t);f.attachEvent("onload",i);var u=!1;try{u=null==f.frameElement&&e.documentElement}catch(F){}u&&u.doScroll&&function b(){if(!j){try{u.doScroll("left")}catch(c){f.clearTimeout(d.readyTimeout);d.readyTimeout=f.setTimeout(b,50);
return}i()}}()}setTimeout(function(){C=!0;g(B,function(b){b()})},300)})(window);

// this is the actual includedeck

function includedeck(m, c) {
    var modules = m || [];
    var conf = c || {};
    var atExit = conf.ATEXIT || (function(){});
    var deckSelector = conf.DECK || '.slide';

    if (typeof(modules) == "string") {
        modules = modules.split(/ +/);
    }

    // todo: make this externally extensible
    // todo: maybe have a mechanism to load a list of dependency (e.g., mymodule-files.js)

    var prefix = conf.PREFIX || "deck.js";
    var info = {
        //
        // core (differerent possible cores)
        "deck-core-dependencies": [
            prefix + "/jquery-1.7.2.min.js",
            prefix + "/modernizr.custom.js"
        ],
        "deck": [
            "@_deck-core-dependencies",
	    prefix + "/core/deck.core.css",
            prefix + "/core/deck.core.js"
        ],
        "newdeck": [
            "@_deck-core-dependencies",
	    prefix + "/extensions/style-chunks/core.css",
            prefix + "/core/deck.core.js"
        ],
        //
        // extensions
        "fit": [ prefix + "/extensions/fit/deck.fit.js" ],
        "fit-fs": [
            prefix + "/extensions/fit/deck.fit-fs.css",
            "@_fit"
        ],
        "simplemath": [
            prefix + "/libs/display-latex2.user.js",
            prefix + "/extensions/simplemath/deck.simplemath.js"
        ],
        "smartsyntax": [ prefix + "/extensions/smartsyntax/deck.smartsyntax.js" ],
        "clone": [ prefix + "/extensions/clone/deck.clone.js" ],
        "goto": [
            prefix + "/extensions/goto/deck.goto.css",
            prefix + "/extensions/goto/deck.goto.js"
        ],
        "status": [
            prefix + "/extensions/status/deck.status.css",
            prefix + "/extensions/status/deck.status.js"
        ],
        "navigation": [
            prefix + "/extensions/navigation/deck.navigation.css",
            prefix + "/extensions/navigation/deck.navigation.js"
        ],
        "menu": [
            prefix + "/extensions/menu/deck.menu.css",
            prefix + "/extensions/menu/deck.menu.js"
        ],
        "hash": [
            prefix + "/extensions/hash/deck.hash.css",
            prefix + "/extensions/hash/deck.hash.js"
        ],
        "step": [ prefix + "/extensions/step/deck.step.js" ],
        "events": [ prefix + "/extensions/events/deck.events.js" ],
        "anim": [ prefix + "/extensions/anim/deck.anim.js" ],
        "svg": [
            prefix + "/libs/jquerysvg/jquery.svg.min.js" ,
            prefix + "/libs/jquerysvg/jquery.svganim.min.js",
            prefix + "/extensions/svg/deck.svg.js"
        ],
        //
        // Themes
        // // by convention, "theme:blabla" will load the default blabla theme
        //
        // Some default profiles
        //
        /// profile-1: default deck with most extensions and no theme
        "profile-1": ["@_deck", "@_smartsyntax", "@_fit-fs", "@_simplemath", "@_clone", "@_goto", "@_status", "@_navigation", "@_menu", "@_hash", "@_step", "@_events", "@_anim", "@_svg"],
        /// profile-2: new deck (cleaner css) with most extensions and no theme
        "profile-2": ["@_newdeck", "@_smartsyntax", "@_fit-fs", "@_simplemath", "@_clone", "@_goto", "@_status", "@_navigation", "@_menu", "@_hash", "@_step", "@_events", "@_anim", "@_svg"],
        dummy: {} // TODO add a newdeck (remove the in-adapted default css from deck core)
    };

    var endsInJsOrCss = /\.(css|js)$/;

    // Defensive check that there are no *.js/*.css in the info (as they won't be useable anyways)
    for (k in info) {
        if (endsInJsOrCss.test(k)) {
            alert("Internal problem detected in includedeck: '" + k + "' won't be useable.");
        }
    }

    // todo: handle default extensions (deck.js/extensions/N/deck.N.{js,css}
    // TODO: some should come before others, e.g. anim before svg, (or before any (deck) or before most (loading...))

    var toLoad = [];
    var addInfo = function(k) {
        if (k.substring(0, 6) == "theme:") {
            toLoad = toLoad.concat(prefix + "/themes/style/" + k.substring(6) + ".css");
            return;
        }
        if (endsInJsOrCss.test(k)) {
            toLoad = toLoad.concat(k);
            return;
        }
        for (i in info[k]) {
            if (info[k][i].substring(0,2) == "@_") {
                addInfo(info[k][i].substring(2));
            } else {
                toLoad = toLoad.concat(info[k][i]);
            }
        }
    }

    for (i in modules) {
        addInfo(modules[i]);
    }

    { // First insert a CSS, just to fit modernizr
        var c = document.createElement("style");
        c.type = "text/css";
        document.getElementsByTagName("head")[0].appendChild(c);
    }

    // the dummy js file below is to workaround a problem in headjs that does not fire the callback when the last thing is a css
    head.js.apply(head, toLoad.concat("___dummy___auto___.js").concat(function() {
        $(function() {
            $.deck(deckSelector, conf);
            atExit();
        });
    }));
}

<|endoftext|>


<commit_before>(function () {
  'use strict';
  var badwords = '';
  jQuery('document') .ready(function () {
    $.get(RELATIVE_PATH + '/api/plugins/beep') .success(function (banned_words) {
      badwords = banned_words.split(',');
    }) .fail(function () {
      badwords = [
        'anal',
        'anus',
        'arse',
        'ass',
        'ballsack',
        'balls',
        'bastard',
        'bitch',
        'biatch',
        'bloody',
        'blowjob',
        'blow job',
        'bollock',
        'bollok',
        'boner',
        'boob',
        'bugger',
        'bum',
        'butt',
        'buttplug',
        'clitoris',
        'cock',
        'coon',
        'crap',
        'cunt',
        'damn',
        'dick',
        'dildo',
        'dyke',
        'fag',
        'feck',
        'fellate',
        'fellatio',
        'felching',
        'fuck',
        'f u c k',
        'fudgepacker',
        'fudge packer',
        'flange',
        'homo',
        'jerk',
        'jizz',
        'knobend',
        'knob end',
        'labia',
        'muff',
        'nigger',
        'nigga',
        'penis',
        'piss',
        'poop',
        'prick',
        'pube',
        'pussy',
        'queer',
        'sex',
        'shit',
        's hit',
        'sh1t',
        'slut',
        'smegma',
        'spunk',
        'tit',
        'tosser',
        'turd',
        'twat',
        'vagina',
        'wank',
        'whore'
      ];
    });
    $(window) .on('action:ajaxify.end', function (ev, data) {
      if (data.url.match(/^category/) || data.url.match(/^unread/) || data.url.match(/^recent/) || data.url.match(/^popular/)) {
        censorTopics();
      }
      if (data.url.match(/^topic/)) $(window) .on('scroll', censorTopics);
    });
    $(window) .on('action:categories.loaded', censorTopics);
    $(window) .on('action:categories.new_topic.loaded', censorTopics);
    $(window) .on('action:topic.loaded', censorTopics);
    socket.on('event:post_edited', function () {
      setTimeout(censorTopics, 270);
    });
  });
  function censorTopics() {
    for (var w in badwords) {
      var re = new RegExp(badwords[w], 'ig');
      var hidesting = '';
      for (var i = 0; i < badwords[w].length - 2; i++) {
        hidesting += '*';
      }
      var re2 = new RegExp(badwords[w].substring(1, badwords[w].length - 1), 'ig');
      var hashword = badwords[w].replace(re2, hidesting);

      var match = $(this) .html() .match(re);
      var hashword = match[0].replace(re2, hidesting);

      //Change topic title on topic list
      $('.category-item .topic-title') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });
      //Change topic title on topic
      $('h3.topic-title p.topic-title') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });
      //Change Breadcrump
      $('ol.breadcrumb li.active span') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });
      //Change header information
      $('.header-topic-title span') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });

      if (document.title.match(re)) {
        document.title = document.title.replace(re, hashword);
      }

    }
  }
}());
<commit_msg>comment out<commit_after>(function () {
  'use strict';
  var badwords = '';
  jQuery('document') .ready(function () {
    $.get(RELATIVE_PATH + '/api/plugins/beep') .success(function (banned_words) {
      badwords = banned_words.split(',');
    }) .fail(function () {
      badwords = [
        'anal',
        'anus',
        'arse',
        'ass',
        'ballsack',
        'balls',
        'bastard',
        'bitch',
        'biatch',
        'bloody',
        'blowjob',
        'blow job',
        'bollock',
        'bollok',
        'boner',
        'boob',
        'bugger',
        'bum',
        'butt',
        'buttplug',
        'clitoris',
        'cock',
        'coon',
        'crap',
        'cunt',
        'damn',
        'dick',
        'dildo',
        'dyke',
        'fag',
        'feck',
        'fellate',
        'fellatio',
        'felching',
        'fuck',
        'f u c k',
        'fudgepacker',
        'fudge packer',
        'flange',
        'homo',
        'jerk',
        'jizz',
        'knobend',
        'knob end',
        'labia',
        'muff',
        'nigger',
        'nigga',
        'penis',
        'piss',
        'poop',
        'prick',
        'pube',
        'pussy',
        'queer',
        'sex',
        'shit',
        's hit',
        'sh1t',
        'slut',
        'smegma',
        'spunk',
        'tit',
        'tosser',
        'turd',
        'twat',
        'vagina',
        'wank',
        'whore'
      ];
    });
    $(window) .on('action:ajaxify.end', function (ev, data) {
      if (data.url.match(/^category/) || data.url.match(/^unread/) || data.url.match(/^recent/) || data.url.match(/^popular/)) {
        censorTopics();
      }
      if (data.url.match(/^topic/)) $(window) .on('scroll', censorTopics);
    });
    $(window) .on('action:categories.loaded', censorTopics);
    $(window) .on('action:categories.new_topic.loaded', censorTopics);
    $(window) .on('action:topic.loaded', censorTopics);
    socket.on('event:post_edited', function () {
      setTimeout(censorTopics, 270);
    });
  });
  function censorTopics() {
    for (var w in badwords) {
      var re = new RegExp(badwords[w], 'ig');
      var hidesting = '';
      for (var i = 0; i < badwords[w].length - 2; i++) {
        hidesting += '*';
      }
      var re2 = new RegExp(badwords[w].substring(1, badwords[w].length - 1), 'ig');
      var hashword = badwords[w].replace(re2, hidesting);

      //var match = $(this) .html() .match(re);
      //var hashword = match[0].replace(re2, hidesting);

      //Change topic title on topic list
      $('.category-item .topic-title') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });
      //Change topic title on topic
      $('h3.topic-title p.topic-title') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });
      //Change Breadcrump
      $('ol.breadcrumb li.active span') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });
      //Change header information
      $('.header-topic-title span') .each(function () {
        if ($(this) .html() .match(re)) {
          $(this) .html($(this) .html() .replace(re, hashword));
        }
      });

      if (document.title.match(re)) {
        document.title = document.title.replace(re, hashword);
      }

    }
  }
}());
<|endoftext|>


<commit_before>/**
 * applications.module.js
 * Created by anonymous on 08/12/15 17:07.
 */

(function() {
    'use strict';

    /* Application */
    angular.module('applications', ['app']);

    angular.module('app', [
        /* Shared */
        'appFoundation',
        'widgets',

        /* service components */
        'dashboard',
        'client'
    ]);

})();

<commit_msg>Modified applications.module<commit_after>/**
 * applications.module.js
 * Created by anonymous on 08/12/15 17:07.
 */

(function() {
    'use strict';

    /* Application */
    angular.module('applications', ['app']);

    angular.module('app', [
        /* Themes */
        'quetzalcoatl',

        /* Shared */
        'appFoundation',
        'widgets',

        /* Components */
        'seneschal',
        'dashboard',
        'pages',
        'posts',
        'client'
    ]);

})();

<|endoftext|>


<commit_before>debug = true
GAME = {
  moveKeys: {
    65: [-1, null], //'left',
    87: [null, -1], //'up',
    68: [ 1, null], //'right',
    83: [null, 1], //'down',
    37: [-1, null], //'left',
    38: [null, -1], //'up',
    39: [ 1, null], //'right',
    40: [null, 1], //'down'
  },
  rotKeys: {
    74: -Math.PI/100,
    75: Math.PI/100
  },
  inputRot: 0,
  inputX: 0,
  inputY: 0,
  bullets: [],
  enemies: [],
  score: 0
}

function init() {
  // add canvas
  GAME.canv = document.createElement('canvas')
  GAME.w = 600 //window.innerWidth
  GAME.h = 400 //window.innerHeight
  GAME.canv.width = GAME.w
  GAME.canv.height = GAME.h

  GAME.ctx = GAME.canv.getContext('2d')

  GAME.outCanv = document.createElement('canvas')
  GAME.outCanv.width = GAME.w
  GAME.outCanv.height = GAME.h
  GAME.outCtx = GAME.outCanv.getContext('2d')
  document.body.appendChild(GAME.outCanv)

  GAME.player = new Player(GAME.w/2, GAME.h/2, 20, 0, 0)
  GAME.spawner = new Spawner()
  requestAnimationFrame(animate)
}

function Entity(x, y, size, rot, vx, vy) {
  this.x = x || 0
  this.y = y || 0
  this.size = size || 10
  this.rot = rot || 0
  this.vx = vx || 0
  this.vy = vy || 0
}

Entity.prototype.physics = function() {
  this.x += this.vx * Math.cos(this.rot)
  this.y += this.vy * Math.sin(this.rot)
}

Entity.prototype.draw = function(ctx) {
  if(this.size <= 0) return
  var cX = Math.abs(this.x + Math.cos(this.rot)/2)
  var cY = Math.abs(this.y + Math.sin(this.rot)/2)
  var grad = ctx.createRadialGradient(cX, cY, 1, cX, cY, this.size)
  grad.addColorStop(0, 'rgba(55,55,255,1)')
  grad.addColorStop(1, 'rgba(55,55,255,0)')

  ctx.fillStyle = grad //'#008080'
  ctx.beginPath()
  ctx.arc(this.x, this.y, this.size, 0, Math.PI*2, true)
  ctx.closePath()
  ctx.fill()

  if(debug) {
    ctx.beginPath()
    ctx.moveTo(this.x, this.y)
    ctx.lineTo(this.x+10*Math.cos(this.rot), this.y+10*Math.sin(this.rot))
    ctx.closePath()
    ctx.stroke()
  }
}

function Spawner() {
  this.frame = 0
  this.threshold = 150
}

Spawner.prototype.physics = function() {
  if (this.frame % 100 === 0) {
    this.spawn()
  }

  this.frame++
}

Spawner.prototype.spawn = function() {
  var x, y
  if(Math.random() > .5) {
    // top or bottom side
    y = Math.random() > .5 ? GAME.h : -20
    x = Math.floor(Math.random() * GAME.w)
  } else {
    // left or right size
    x = Math.random() > .5 ? GAME.w : -20
    y = Math.floor(Math.random() * GAME.h)
  }

  GAME.enemies.push(new Enemy(x, y, 20, null, 0, 0, GAME.player))
}

Spawner.prototype.draw = function(ctx) {
  // metabolize ctx
  var data = ctx.getImageData(0, 0, GAME.w, GAME.h)
  var pix = data.data
  for(var i=0, l=pix.length; i<l; i+=4) {
    if(pix[i+3] < this.threshold) {
      pix[i+3] /= 5
      if(pix[i+3] > this.threshold/4) {
        pix[i+3] = 0
      }
    }
  }
  ctx.putImageData(data, 0, 0)
}

function dirTowards(to, from) {
  return Math.atan2(to.y-from.y, to.x-from.x)
}

function Enemy(x, y, size, rot, vx, vy, target) {
  Entity.call(this, x, y, size, rot, vx, vy)
  this.target = target
}
Enemy.prototype = Object.create(Entity.prototype)

Enemy.prototype.physics = function() {
  var dir = dirTowards(this.target, this)
  this.x += 1*Math.cos(dir)
  this.y += Math.sin(dir)
}

Enemy.prototype.draw = function(ctx) {
  ctx.beginPath()
  var grad = ctx.createRadialGradient(this.x, this.y, 1, this.x, this.y, this.size)
  grad.addColorStop(0, 'rgba(255,55,255,1)')
  grad.addColorStop(1, 'rgba(255,55,255,0)')
  ctx.fillStyle = grad
  ctx.arc(this.x, this.y, this.size, 0, Math.PI*2)
  ctx.closePath()
  ctx.fill()
}

function Player(x, y, size, rot, vx, vy, weapon) {
  Entity.call(this, x, y, size, rot, vx, vy)
  this.weapon = weapon || 0
  this.cooldown = 0
}
Player.prototype = Object.create(Entity.prototype)

Player.prototype.physics = function(dx, dy, dr) {
  this.x += dx
  this.y += dy
  if(this.x - this.size < 0 || this.x+this.size > GAME.w){
    this.x -= dx
  }
  if(this.y - this.size < 0 || this.y+this.size > GAME.h){
    this.y -= dy
  }
  this.rot += dr

   if (this.weapon === 0) {
    this.cooldown--
    if (this.cooldown <= 0) {
      this.cooldown = 10
      var speed = 5
      var size = 10
      GAME.bullets.push(new Bullet(this.x, this.y, size, this.rot, speed, speed))
      GAME.bullets.push(new Bullet(this.x, this.y, size, this.rot + 2, speed, speed))
      GAME.bullets.push(new Bullet(this.x, this.y, size, this.rot - 2, speed, speed))
    }
  }
}

function Bullet(x, y, size, rot, vx, vy) {
  Entity.call(this, x, y, size, rot, vx, vy)
}
Bullet.prototype = Object.create(Entity.prototype)

/*Bullet.prototype.draw = function(ctx) {
  var grad = ctx.createRadialGradient(this.x+20*this.vx/2, this.y+20*this.vy/2, 1, this.x+20*this.vx/2,
                                      this.y+20*this.vy/2, this.size)
  grad.addColorStop(0, 'rgba(255,55,255,1)')
  grad.addColorStop(1, 'rgba(255,55,255,0)')

  ctx.lineWidth = 5
  ctx.strokeStyle = grad //'#71eeb8'
  ctx.beginPath()
  ctx.moveTo(this.x, this.y)
  ctx.lineTo(this.x+this.size*Math.cos(this.rot), this.y+this.size*Math.sin(this.rot))
  ctx.closePath()
  ctx.stroke()
}*/

/*Bullet.prototype.physics = function() {
  this.x += this.vx * Math.cos(this.rot)
  this.y += this.vy * Math.sin(this.rot)
}*/

function outSize(enemy, x,y,w,h) {
  if (enemy.x - enemy.size < x || enemy.x + enemy.size > w+100 ||
        enemy.y - enemy.size < y || enemy.y + enemy.size > h+100) {
      return true
    }
  return false
}

function collide(a, b) {
  return distance(a, b) <= a.size //+ b.size
}

function distance(a, b) {
  return Math.sqrt(Math.pow(a.x-b.x, 2) + Math.pow(a.y - b.y, 2))
}

function animate() {
  requestAnimationFrame(animate)
  GAME.outCtx.fillStyle = '#111'
  GAME.ctx.clearRect(0, 0, GAME.w, GAME.h)
  GAME.outCtx.fillRect(0, 0, GAME.w, GAME.h)

  GAME.spawner.physics()
  for(var i=GAME.enemies.length-1; i>=0; i--){
    var enemy = GAME.enemies[i]
    enemy.physics()
    enemy.draw(GAME.ctx)
    if(collide(enemy, GAME.player)){
      enemy.size -= 2
    }
    for(var j=GAME.bullets.length-1; j>=0; j--){
      var collided = collide(enemy, GAME.bullets[j])
      if(!GAME.bullets[j].used && collided){
        enemy.size -= 2
        GAME.bullets[j].used = true
        GAME.score += 20
      } else if(collided) {
        GAME.bullets[j].size -= 5
      }
    }
    if(outSize(enemy, -100, -100, GAME.w + 100, GAME.h + 100) || enemy.size <= 5) {
      GAME.enemies.splice(i,1)
      GAME.score += 100
    }

  }

  GAME.player.physics(GAME.inputX, GAME.inputY, GAME.inputRot)
  for(var i=GAME.bullets.length-1; i>=0; i--){
    var bullet = GAME.bullets[i]
    bullet.physics()
    bullet.draw(GAME.ctx)
    if(outSize(bullet, -100, -100, GAME.w + 100, GAME.h + 100)) {
      GAME.bullets.splice(i,1)
    }
  }

  GAME.player.draw(GAME.ctx)
  GAME.spawner.draw(GAME.ctx)

}

$(init)

<commit_msg>added score counter<commit_after>debug = true
GAME = {
  moveKeys: {
    65: [-1, null], //'left',
    87: [null, -1], //'up',
    68: [ 1, null], //'right',
    83: [null, 1], //'down',
    37: [-1, null], //'left',
    38: [null, -1], //'up',
    39: [ 1, null], //'right',
    40: [null, 1], //'down'
  },
  rotKeys: {
    74: -Math.PI/100,
    75: Math.PI/100
  },
  inputRot: 0,
  inputX: 0,
  inputY: 0,
  bullets: [],
  enemies: [],
  score: 0
}

function init() {
  // add canvas
  GAME.canv = document.createElement('canvas')
  GAME.w = 600 //window.innerWidth
  GAME.h = 400 //window.innerHeight
  GAME.canv.width = GAME.w
  GAME.canv.height = GAME.h

  GAME.ctx = GAME.canv.getContext('2d')

  GAME.outCanv = document.createElement('canvas')
  GAME.outCanv.width = GAME.w
  GAME.outCanv.height = GAME.h
  GAME.outCtx = GAME.outCanv.getContext('2d')
  document.body.appendChild(GAME.outCanv)

  GAME.player = new Player(GAME.w/2, GAME.h/2, 20, 0, 0)
  GAME.spawner = new Spawner()
  requestAnimationFrame(animate)
}

function Entity(x, y, size, rot, vx, vy) {
  this.x = x || 0
  this.y = y || 0
  this.size = size || 10
  this.rot = rot || 0
  this.vx = vx || 0
  this.vy = vy || 0
}

Entity.prototype.physics = function() {
  this.x += this.vx * Math.cos(this.rot)
  this.y += this.vy * Math.sin(this.rot)
}

Entity.prototype.draw = function(ctx) {
  if(this.size <= 0) return
  var cX = Math.abs(this.x + Math.cos(this.rot)/2)
  var cY = Math.abs(this.y + Math.sin(this.rot)/2)
  var grad = ctx.createRadialGradient(cX, cY, 1, cX, cY, this.size)
  grad.addColorStop(0, 'rgba(55,55,255,1)')
  grad.addColorStop(1, 'rgba(55,55,255,0)')

  ctx.fillStyle = grad //'#008080'
  ctx.beginPath()
  ctx.arc(this.x, this.y, this.size, 0, Math.PI*2, true)
  ctx.closePath()
  ctx.fill()

  if(debug) {
    ctx.beginPath()
    ctx.moveTo(this.x, this.y)
    ctx.lineTo(this.x+10*Math.cos(this.rot), this.y+10*Math.sin(this.rot))
    ctx.closePath()
    ctx.stroke()
  }
}

function Spawner() {
  this.frame = 0
  this.threshold = 150
}

Spawner.prototype.physics = function() {
  if (this.frame % 100 === 0) {
    this.spawn()
  }

  this.frame++
}

Spawner.prototype.spawn = function() {
  var x, y
  if(Math.random() > .5) {
    // top or bottom side
    y = Math.random() > .5 ? GAME.h : -20
    x = Math.floor(Math.random() * GAME.w)
  } else {
    // left or right size
    x = Math.random() > .5 ? GAME.w : -20
    y = Math.floor(Math.random() * GAME.h)
  }

  GAME.enemies.push(new Enemy(x, y, 20, null, 0, 0, GAME.player))
}

Spawner.prototype.draw = function(ctx) {
  // metabolize ctx
  var data = ctx.getImageData(0, 0, GAME.w, GAME.h)
  var pix = data.data
  for(var i=0, l=pix.length; i<l; i+=4) {
    if(pix[i+3] < this.threshold) {
      pix[i+3] /= 5
      if(pix[i+3] > this.threshold/4) {
        pix[i+3] = 0
      }
    }
  }
  ctx.putImageData(data, 0, 0)
}

function dirTowards(to, from) {
  return Math.atan2(to.y-from.y, to.x-from.x)
}

function Enemy(x, y, size, rot, vx, vy, target) {
  Entity.call(this, x, y, size, rot, vx, vy)
  this.target = target
}
Enemy.prototype = Object.create(Entity.prototype)

Enemy.prototype.physics = function() {
  var dir = dirTowards(this.target, this)
  this.x += 1*Math.cos(dir)
  this.y += Math.sin(dir)
}

Enemy.prototype.draw = function(ctx) {
  ctx.beginPath()
  var grad = ctx.createRadialGradient(this.x, this.y, 1, this.x, this.y, this.size)
  grad.addColorStop(0, 'rgba(255,55,255,1)')
  grad.addColorStop(1, 'rgba(255,55,255,0)')
  ctx.fillStyle = grad
  ctx.arc(this.x, this.y, this.size, 0, Math.PI*2)
  ctx.closePath()
  ctx.fill()
}

function Player(x, y, size, rot, vx, vy, weapon) {
  Entity.call(this, x, y, size, rot, vx, vy)
  this.weapon = weapon || 0
  this.cooldown = 0
}
Player.prototype = Object.create(Entity.prototype)

Player.prototype.physics = function(dx, dy, dr) {
  this.x += dx
  this.y += dy
  if(this.x - this.size < 0 || this.x+this.size > GAME.w){
    this.x -= dx
  }
  if(this.y - this.size < 0 || this.y+this.size > GAME.h){
    this.y -= dy
  }
  this.rot += dr

   if (this.weapon === 0) {
    this.cooldown--
    if (this.cooldown <= 0) {
      this.cooldown = 10
      var speed = 5
      var size = 10
      GAME.bullets.push(new Bullet(this.x, this.y, size, this.rot, speed, speed))
      GAME.bullets.push(new Bullet(this.x, this.y, size, this.rot + 2, speed, speed))
      GAME.bullets.push(new Bullet(this.x, this.y, size, this.rot - 2, speed, speed))
    }
  }
}

function Bullet(x, y, size, rot, vx, vy) {
  Entity.call(this, x, y, size, rot, vx, vy)
}
Bullet.prototype = Object.create(Entity.prototype)

/*Bullet.prototype.draw = function(ctx) {
  var grad = ctx.createRadialGradient(this.x+20*this.vx/2, this.y+20*this.vy/2, 1, this.x+20*this.vx/2,
                                      this.y+20*this.vy/2, this.size)
  grad.addColorStop(0, 'rgba(255,55,255,1)')
  grad.addColorStop(1, 'rgba(255,55,255,0)')

  ctx.lineWidth = 5
  ctx.strokeStyle = grad //'#71eeb8'
  ctx.beginPath()
  ctx.moveTo(this.x, this.y)
  ctx.lineTo(this.x+this.size*Math.cos(this.rot), this.y+this.size*Math.sin(this.rot))
  ctx.closePath()
  ctx.stroke()
}*/

/*Bullet.prototype.physics = function() {
  this.x += this.vx * Math.cos(this.rot)
  this.y += this.vy * Math.sin(this.rot)
}*/

function outSize(enemy, x,y,w,h) {
  if (enemy.x - enemy.size < x || enemy.x + enemy.size > w+100 ||
        enemy.y - enemy.size < y || enemy.y + enemy.size > h+100) {
      return true
    }
  return false
}

function collide(a, b) {
  return distance(a, b) <= a.size //+ b.size
}

function distance(a, b) {
  return Math.sqrt(Math.pow(a.x-b.x, 2) + Math.pow(a.y - b.y, 2))
}

function animate() {
  requestAnimationFrame(animate)
  GAME.outCtx.fillStyle = '#111'
  GAME.ctx.clearRect(0, 0, GAME.w, GAME.h)
  GAME.outCtx.fillRect(0, 0, GAME.w, GAME.h)

  GAME.spawner.physics()
  for(var i=GAME.enemies.length-1; i>=0; i--){
    var enemy = GAME.enemies[i]
    enemy.physics()
    enemy.draw(GAME.ctx)
    if(collide(enemy, GAME.player)){
      enemy.size -= 2
    }
    for(var j=GAME.bullets.length-1; j>=0; j--){
      var collided = collide(enemy, GAME.bullets[j])
      if(!GAME.bullets[j].used && collided){
        enemy.size -= 2
        GAME.bullets[j].used = true
        GAME.score += 20
      } else if(collided) {
        GAME.bullets[j].size -= 5
      }
    }
    if(outSize(enemy, -100, -100, GAME.w + 100, GAME.h + 100) || enemy.size <= 5) {
      GAME.enemies.splice(i,1)
      GAME.score += 100
    }

  }

  GAME.player.physics(GAME.inputX, GAME.inputY, GAME.inputRot)
  for(var i=GAME.bullets.length-1; i>=0; i--){
    var bullet = GAME.bullets[i]
    bullet.physics()
    bullet.draw(GAME.ctx)
    if(outSize(bullet, -100, -100, GAME.w + 100, GAME.h + 100)) {
      GAME.bullets.splice(i,1)
    }
  }

  GAME.player.draw(GAME.ctx)
  GAME.spawner.draw(GAME.ctx)

  GAME.outCtx.drawImage(GAME.canv, 0, 0)
  GAME.outCtx.font = '16px Monospace bold'
  GAME.outCtx.fillStyle = '#cff'
  GAME.outCtx.fillText(GAME.score, 30, 16)
}

$(init)

<|endoftext|>


<commit_before>// DOF
'use strict'

/*************************************************************************
//
// CONFIGURATION
// User editable options (global variables)
//
// ***********************************************************************/

var MAPBOX_ID           = 'codeforamerica.map-wzcm8dk0',
	MAPBOX_ID_RETINA    = 'codeforamerica.map-dfs3qfso'

var MAP_INIT_LATLNG     = [36.1665, -115.1479],
	MAP_INIT_ZOOM       = 16,
	MAP_FIT_PADDING     = 0.25,
	MAP_MAX_PADDING     = 6

var DEBUG_ALLOW         = true

/*************************************************************************
//
// INITIALIZE APP
//
// ***********************************************************************/

var propertyAddress = '495 S. Main Street',
	businessType = 'Beer Garden'

/*************************************************************************
//
// INITIALIZE MAP
// Sets initial location, view, attribution, marker types
//
// ***********************************************************************/
/*
var map = L.mapbox.map('map', MAPBOX_ID, {
	minZoom: MAP_INIT_ZOOM,
	maxZoom: MAP_INIT_ZOOM
})*/
var map = L.mapbox.map('map', MAPBOX_ID, {
	doubleClickZoom: false
}).setView(MAP_INIT_LATLNG, MAP_INIT_ZOOM)
	// This will be overridden later when map bounds are set based on available markers.

// Use normal map
/*
map.addLayer(L.mapbox.tileLayer(MAPBOX_ID, {
	detectRetina: true,
	retinaVersion: MAPBOX_ID_RETINA
}))
*/

// Map imagery attribution
// Note that mapbox.js provides its own separate attribution, which I don't
// know how to edit, so I've hidden it with CSS (super hacky!)
var control = L.control.attribution({
	prefix: 'Map imagery by MapBox. Data © OpenStreetMap contributors.'
}).addTo(map)

// Set up icons for markers
var markerIconSize =    [36, 62], // size of the icon
	markerIconAnchor =  [18, 50], // point of the icon which will correspond to marker's location
	markerPopupAnchor = [0, -55]  // point from which the popup should open relative to the iconAnchor

var vendorMarker = L.icon({
	iconUrl: 'img/pin-food-on.png',

	iconSize:     markerIconSize,
	iconAnchor:   markerIconAnchor,
	popupAnchor:  markerPopupAnchor
})

var vendorMarkerOff = L.icon({
	iconUrl: 'img/pin-food-off.png',

	iconSize:     markerIconSize,
	iconAnchor:   markerIconAnchor,
	popupAnchor:  markerPopupAnchor
})

// Not used - currently using Mapbox version of this icon.
var hereMarker = L.icon({
	iconUrl: 'img/pin-here.png',

	iconSize:     markerIconSize,
	iconAnchor:   markerIconAnchor,
	popupAnchor:  markerPopupAnchor
});

var propertyMarker
var popupOpen = false
map.on('click', function (e) {
    var containerPoint = e.containerPoint.toString()
    var clickLatLng = e.latlng

    // add a marker on the point someone just clicked

    var markerHTML = document.getElementById('markerHTML').innerHTML

	if (popupOpen == true) {
//		propertyMarker.closePopup()
		popupOpen = false
		return
	}
	if (propertyMarker) {
		map.removeLayer(propertyMarker)
		propertyMarker = ''
	}

	propertyMarker = L.marker(clickLatLng).addTo(map)
	propertyMarker.bindPopup(markerHTML, {
		closeButton: false
	})
	map.panTo(clickLatLng)
	propertyMarker.openPopup()
	popupOpen = true

    // bind a popup with some fake info in it

    // open popup

    // clicking the popup brings up the parcel info.

});

/*
map.markerLayer.setGeoJSON({
    type: 'FeatureCollection',
    features: features
});
*/
/*************************************************************************
//
// UI
//
// ***********************************************************************/

var SECTION_TRANSITION_OUT_TIME = 175,
	SECTION_TRANSITION_IN_TIME = 350

var ZONE_URL = '/data/zones.json'
var ZONE_DATA

$.when( $.ajax({
	url: ZONE_URL,
	cache: false,
	dataType: 'json',
	success: function (i) {
		ZONE_DATA = i
	},
	error: function (x) {
	}
})).then( function () {
	var markers = L.geoJson(ZONE_DATA, {
    style: function (feature) {
        return {color: feature.properties.color};
    },
    onEachFeature: function (feature, layer) {
//        layer.bindPopup(feature.properties.description);
    }
})
//}).addTo(map);

//	console.log(ZONE_DATA)
})

$(document).ready(function () {

/*
	$('.leaflet-popup-pane').on('click', '#marker-more-info', function (e) {
		e.preventDefault()
		if ($('#section40').is(':visible') || $('#section45').is(':visible')) {
			$('#section40').fadeOut(SECTION_TRANSITION_OUT_TIME)
			$('#section45').fadeOut(SECTION_TRANSITION_OUT_TIME)
			$('#section50').fadeOut(SECTION_TRANSITION_OUT_TIME)
			$('#section50').fadeIn(SECTION_TRANSITION_IN_TIME)
		}
	})
*/
	// BUTTONS
	// External links - the rest should be in angular
	$('#main').on('click', 'button', function (e) {
		e.preventDefault()

		var url = $(this).data('externalLink')

		if (url) {
			_openExternalLink(url)
		}
	})

	$('#main').on('click', 'a.disabled', function (e) {
		// Disabled 'a' tags should behave like a disabled button
		e.preventDefault()
	})

	// SECTION 10: Business search related jQueries
	$('#main').on('submit', '#primary-business-form', function (e) {
		_doNAICSSearch()
	})
	$('#main').on('click', '.naics-result button', function (e) {
		// Select a business from the list
		$('#primary-business-results p.replace').text($(this).parent().find('span').text())
		$('#primary-business-results a.next').removeClass('disabled')
	})

	// SECTION 40: Address search related jQueries
	$('#main').on('submit', '#property-address-form', function (e) {

		// Really should be sending this event to an Angular thing
		window.location.hash = encodeURIComponent('/section/50')

	})

	// Scrollfixed elements
	var scrollTemp
	$(window).scroll(function () {

		var $fixedEl = $('.scrollfix')

		if ($fixedEl.length > 0 ) {
			if ($(window).scrollTop() > $fixedEl.offset().top - 40) {
				scrollTemp = $fixedEl.offset().top - 40
		        $fixedEl.css('position', 'fixed').css('top', '40px').css('margin-left', '10px');
			}
			else if ($(window).scrollTop() < scrollTemp) {
				$fixedEl.css('position', 'relative').css('top', '0').css('margin-left', '7px');
			}
		}

	});

	// MODAL
	// Opens modal
	$('#main').on('click', 'a.modal', function (e) {
		e.preventDefault()
		$('#modal').show()
		$('.modal-title').text($(this).data('title'))
		$('.modal-text').text($(this).data('content'))
	})

	// Various ways of closing it
	// by close link
	$('.modal-close a').on('click', function (e) {
		e.preventDefault()
		_closeModal()
	})
	// by close hit area
	$('.modal-close').on('click', _closeModal)
	// by hitting the background area around the modal
	$('.modal-background').on('click', _closeModal)
	// by pressing ESC
	$(document).keyup( function (e) {
		if ((e.keyCode === 13 || e.keyCode === 27) && $('#modal').is(':visible')) {
			_closeModal()
		}
	})

	// PILLS
	$('.clickable.pill').on('click', function (e) {
		var link = $(this).parents().filter(function() {
			return $(this).css("display") === "block";
		}).first().find('a')
 		link.click()
	})

});

/*************************************************************************
//
// FUNCTIONS
//
// ***********************************************************************/

function _openExternalLink (url) {

/*	if ($(clicked).attr('id') == 'external-pre-app') {
		url = encodeURI(url + '?ProjectAddress=' + propertyAddress + '&Parcel=002-02-119&Ward=(unknown)&ProposedUse=' + businessType +'')
		window.open(url, '_blank')
		return true
	}
*/
	window.open(url, '_blank')
	return true

}

function _changeSection (clicked) {

	if ($(clicked).val() == 'next') {
		$targetSection = $thisSection.next('section')
	}

	if ($(clicked).val() == 'back') {
		$targetSection = $thisSection.prev('section')
	}

	if ($(clicked).data('section')) {
		$targetSection = $(document).find('#' + $(clicked).data('section'))
	}

	if ($targetSection) {
		$thisSection.fadeOut(SECTION_TRANSITION_OUT_TIME, function () {

			$targetSection.fadeIn(SECTION_TRANSITION_IN_TIME)

		})
	}
}

function _closeModal() {
	if ($('#modal').is(':visible')) {
		$('#modal').hide()
	}
}

function _doNAICSSearch () {
	// Show loader and clear search results area
	$('#search-results').text('')
	$('#search-results').show()
	$('.loading-small').show()

	// Do a search
	var searchAPI   = 'http://api.naics.us/v0/s?year=2012&collapse=1&terms='
	var searchTerms = $('#primary-business-input').val()
	var searchURL   = searchAPI + encodeURIComponent(searchTerms)
	var searchResults

	var naicsXHR = $.get(searchURL, function(data) {
		searchResults = data
	}).done( function () {

		// Hide loader
		$('.loading-small').hide()

		// Message for no results
		if (searchResults.length == 0) {
			$('#search-results').text('Nothing found for those search terms.')
			return
		}

		// Format data & display
		for (var i = 0; i < searchResults.length; i++) {
			searchResults[i].id = searchResults[i].code
			$('#search-results').append('
' + searchResults[i].title + '<button>Select</button>
')
		}

		// Show selection box
		$('#primary-business-results').show()

	}).fail( function () {

		$('#search-results').text('Error performing search for NAICS business categories')

	})
}

<commit_msg>always hide loading gif on NAICS search<commit_after>// DOF
'use strict'

/*************************************************************************
//
// CONFIGURATION
// User editable options (global variables)
//
// ***********************************************************************/

var MAPBOX_ID           = 'codeforamerica.map-wzcm8dk0',
	MAPBOX_ID_RETINA    = 'codeforamerica.map-dfs3qfso'

var MAP_INIT_LATLNG     = [36.1665, -115.1479],
	MAP_INIT_ZOOM       = 16,
	MAP_FIT_PADDING     = 0.25,
	MAP_MAX_PADDING     = 6

var DEBUG_ALLOW         = true

/*************************************************************************
//
// INITIALIZE APP
//
// ***********************************************************************/

var propertyAddress = '495 S. Main Street',
	businessType = 'Beer Garden'

/*************************************************************************
//
// INITIALIZE MAP
// Sets initial location, view, attribution, marker types
//
// ***********************************************************************/
/*
var map = L.mapbox.map('map', MAPBOX_ID, {
	minZoom: MAP_INIT_ZOOM,
	maxZoom: MAP_INIT_ZOOM
})*/
var map = L.mapbox.map('map', MAPBOX_ID, {
	doubleClickZoom: false
}).setView(MAP_INIT_LATLNG, MAP_INIT_ZOOM)
	// This will be overridden later when map bounds are set based on available markers.

// Use normal map
/*
map.addLayer(L.mapbox.tileLayer(MAPBOX_ID, {
	detectRetina: true,
	retinaVersion: MAPBOX_ID_RETINA
}))
*/

// Map imagery attribution
// Note that mapbox.js provides its own separate attribution, which I don't
// know how to edit, so I've hidden it with CSS (super hacky!)
var control = L.control.attribution({
	prefix: 'Map imagery by MapBox. Data © OpenStreetMap contributors.'
}).addTo(map)

// Set up icons for markers
var markerIconSize =    [36, 62], // size of the icon
	markerIconAnchor =  [18, 50], // point of the icon which will correspond to marker's location
	markerPopupAnchor = [0, -55]  // point from which the popup should open relative to the iconAnchor

var vendorMarker = L.icon({
	iconUrl: 'img/pin-food-on.png',

	iconSize:     markerIconSize,
	iconAnchor:   markerIconAnchor,
	popupAnchor:  markerPopupAnchor
})

var vendorMarkerOff = L.icon({
	iconUrl: 'img/pin-food-off.png',

	iconSize:     markerIconSize,
	iconAnchor:   markerIconAnchor,
	popupAnchor:  markerPopupAnchor
})

// Not used - currently using Mapbox version of this icon.
var hereMarker = L.icon({
	iconUrl: 'img/pin-here.png',

	iconSize:     markerIconSize,
	iconAnchor:   markerIconAnchor,
	popupAnchor:  markerPopupAnchor
});

var propertyMarker
var popupOpen = false
map.on('click', function (e) {
    var containerPoint = e.containerPoint.toString()
    var clickLatLng = e.latlng

    // add a marker on the point someone just clicked

    var markerHTML = document.getElementById('markerHTML').innerHTML

	if (popupOpen == true) {
//		propertyMarker.closePopup()
		popupOpen = false
		return
	}
	if (propertyMarker) {
		map.removeLayer(propertyMarker)
		propertyMarker = ''
	}

	propertyMarker = L.marker(clickLatLng).addTo(map)
	propertyMarker.bindPopup(markerHTML, {
		closeButton: false
	})
	map.panTo(clickLatLng)
	propertyMarker.openPopup()
	popupOpen = true

    // bind a popup with some fake info in it

    // open popup

    // clicking the popup brings up the parcel info.

});

/*
map.markerLayer.setGeoJSON({
    type: 'FeatureCollection',
    features: features
});
*/
/*************************************************************************
//
// UI
//
// ***********************************************************************/

var SECTION_TRANSITION_OUT_TIME = 175,
	SECTION_TRANSITION_IN_TIME = 350

var ZONE_URL = '/data/zones.json'
var ZONE_DATA

$.when( $.ajax({
	url: ZONE_URL,
	cache: false,
	dataType: 'json',
	success: function (i) {
		ZONE_DATA = i
	},
	error: function (x) {
	}
})).then( function () {
	var markers = L.geoJson(ZONE_DATA, {
    style: function (feature) {
        return {color: feature.properties.color};
    },
    onEachFeature: function (feature, layer) {
//        layer.bindPopup(feature.properties.description);
    }
})
//}).addTo(map);

//	console.log(ZONE_DATA)
})

$(document).ready(function () {

/*
	$('.leaflet-popup-pane').on('click', '#marker-more-info', function (e) {
		e.preventDefault()
		if ($('#section40').is(':visible') || $('#section45').is(':visible')) {
			$('#section40').fadeOut(SECTION_TRANSITION_OUT_TIME)
			$('#section45').fadeOut(SECTION_TRANSITION_OUT_TIME)
			$('#section50').fadeOut(SECTION_TRANSITION_OUT_TIME)
			$('#section50').fadeIn(SECTION_TRANSITION_IN_TIME)
		}
	})
*/
	// BUTTONS
	// External links - the rest should be in angular
	$('#main').on('click', 'button', function (e) {
		e.preventDefault()

		var url = $(this).data('externalLink')

		if (url) {
			_openExternalLink(url)
		}
	})

	$('#main').on('click', 'a.disabled', function (e) {
		// Disabled 'a' tags should behave like a disabled button
		e.preventDefault()
	})

	// SECTION 10: Business search related jQueries
	$('#main').on('submit', '#primary-business-form', function (e) {
		_doNAICSSearch()
	})
	$('#main').on('click', '.naics-result button', function (e) {
		// Select a business from the list
		$('#primary-business-results p.replace').text($(this).parent().find('span').text())
		$('#primary-business-results a.next').removeClass('disabled')
	})

	// SECTION 40: Address search related jQueries
	$('#main').on('submit', '#property-address-form', function (e) {

		// Really should be sending this event to an Angular thing
		window.location.hash = encodeURIComponent('/section/50')

	})

	// Scrollfixed elements
	var scrollTemp
	$(window).scroll(function () {

		var $fixedEl = $('.scrollfix')

		if ($fixedEl.length > 0 ) {
			if ($(window).scrollTop() > $fixedEl.offset().top - 40) {
				scrollTemp = $fixedEl.offset().top - 40
		        $fixedEl.css('position', 'fixed').css('top', '40px').css('margin-left', '10px');
			}
			else if ($(window).scrollTop() < scrollTemp) {
				$fixedEl.css('position', 'relative').css('top', '0').css('margin-left', '7px');
			}
		}

	});

	// MODAL
	// Opens modal
	$('#main').on('click', 'a.modal', function (e) {
		e.preventDefault()
		$('#modal').show()
		$('.modal-title').text($(this).data('title'))
		$('.modal-text').text($(this).data('content'))
	})

	// Various ways of closing it
	// by close link
	$('.modal-close a').on('click', function (e) {
		e.preventDefault()
		_closeModal()
	})
	// by close hit area
	$('.modal-close').on('click', _closeModal)
	// by hitting the background area around the modal
	$('.modal-background').on('click', _closeModal)
	// by pressing ESC
	$(document).keyup( function (e) {
		if ((e.keyCode === 13 || e.keyCode === 27) && $('#modal').is(':visible')) {
			_closeModal()
		}
	})

	// PILLS
	$('.clickable.pill').on('click', function (e) {
		var link = $(this).parents().filter(function() {
			return $(this).css("display") === "block";
		}).first().find('a')
 		link.click()
	})

});

/*************************************************************************
//
// FUNCTIONS
//
// ***********************************************************************/

function _openExternalLink (url) {

/*	if ($(clicked).attr('id') == 'external-pre-app') {
		url = encodeURI(url + '?ProjectAddress=' + propertyAddress + '&Parcel=002-02-119&Ward=(unknown)&ProposedUse=' + businessType +'')
		window.open(url, '_blank')
		return true
	}
*/
	window.open(url, '_blank')
	return true

}

function _changeSection (clicked) {

	if ($(clicked).val() == 'next') {
		$targetSection = $thisSection.next('section')
	}

	if ($(clicked).val() == 'back') {
		$targetSection = $thisSection.prev('section')
	}

	if ($(clicked).data('section')) {
		$targetSection = $(document).find('#' + $(clicked).data('section'))
	}

	if ($targetSection) {
		$thisSection.fadeOut(SECTION_TRANSITION_OUT_TIME, function () {

			$targetSection.fadeIn(SECTION_TRANSITION_IN_TIME)

		})
	}
}

function _closeModal() {
	if ($('#modal').is(':visible')) {
		$('#modal').hide()
	}
}

function _doNAICSSearch () {
	// Show loader and clear search results area
	$('#search-results').text('')
	$('#search-results').show()
	$('.loading-small').show()

	// Do a search
	var searchAPI   = 'http://api.naics.us/v0/s?year=2012&collapse=1&terms='
	var searchTerms = $('#primary-business-input').val()
	var searchURL   = searchAPI + encodeURIComponent(searchTerms)
	var searchResults

	var naicsXHR = $.get(searchURL, function(data) {
		searchResults = data
	}).done( function () {

		// Message for no results
		if (searchResults.length == 0) {
			$('#search-results').text('Nothing found for those search terms.')
			return
		}

		// Format data & display
		for (var i = 0; i < searchResults.length; i++) {
			searchResults[i].id = searchResults[i].code
			$('#search-results').append('
' + searchResults[i].title + '<button>Select</button>
')
		}

		// Show selection box
		$('#primary-business-results').show()

	}).fail( function () {
		// Error message
		$('#search-results').text('Error performing search for NAICS business categories')

	}).always( function () {
		// Hide loader
		$('.loading-small').hide()
	})
}

<|endoftext|>


<commit_before>var app = app || {};

(function ($) {
    $('#hook').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget);
        var modal = $(this);

        $('.btn-danger', modal).hide();
        $('.callout-danger', modal).hide();
        $('.callout-warning', modal).hide();
        $('.has-error', modal).removeClass('has-error');
        $('.label-danger', modal).remove();

        if (button.hasClass('btn-edit')) {
            $('.btn-danger', modal).show();
        } else {
            $('#hook_id').val('');
            $('#hook_name').val('');
            $('#hook_type').val('');
            $('#hook :input[id^=hook_config]').val('');
            $('#hook .hook-config input[type=checkbox]').prop('checked', true);
            $('#hook .hook-enabled input[type=checkbox]').prop('checked', true);
            $('#hook .modal-footer').hide();
            $('.hook-config').hide();
            $('.hook-enabled').hide();
            $('#hook-type').show();
            modal.find('.modal-title span').text(trans('hooks.create'));
        }
    });

    $('#hook #hook-type a.btn-app').on('click', function(event) {
        var button = $(event.currentTarget);
        var modal = $('#hook');

        if (button.attr('disabled')) {
            $('.callout-warning', modal).show();
            return;
        }

        $('.callout-warning', modal).hide();

        var type = button.data('type');
        setTitleWithIcon(type, 'create');
    });

    function setTitleWithIcon(type, action) {
        $('#hook .modal-title span').text(trans('hooks.' + action + '_' + type));

        var element = $('#hook .modal-title i').removeClass().addClass('ion');
        var icon = 'cogs';

        if (type === 'slack') {
            icon = 'pound';
        } else if (type === 'mail') {
            icon = 'email';
        } else if (type === 'custom') {
            icon = 'compose';
        }

        element.addClass('ion-' + icon);

        $('#hook .modal-footer').show();
        $('.hook-config').hide();
        $('#hook-type').hide();
        $('#hook-name').show();
        $('#hook-triggers').show();
        $('.hook-enabled').show();
        $('#hook-config-' + type).show();
        $('#hook_type').val(type);
    }

    //$('#hook button.btn-delete').on('click', function (event) {
    $('body').delegate('.hook-trash button.btn-delete','click', function (event) {
        var target = $(event.currentTarget);
        var icon = target.find('i');
        var dialog = target.parents('.modal');

        icon.addClass('ion-refresh fixhub-spin');
        dialog.find('input').attr('disabled', 'disabled');
        $('button.close', dialog).hide();

        var hook = app.Hooks.get($('#model_id').val());

        hook.destroy({
            wait: true,
            success: function(model, response, options) {
                dialog.modal('hide');
                $('.callout-danger', dialog).hide();

                icon.removeClass('ion-refresh fixhub-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');
            },
            error: function() {
                icon.removeClass('ion-refresh fixhub-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');
            }
        });
    });

    $('#hook button.btn-save').on('click', function (event) {
        var target = $(event.currentTarget);
        var icon = target.find('i');
        var dialog = target.parents('.modal');

        icon.addClass('ion-refresh fixhub-spin');
        dialog.find('input').attr('disabled', 'disabled');
        $('button.close', dialog).hide();

        var hook_id = $('#hook_id').val();

        if (hook_id) {
            var hook = app.Hooks.get(hook_id);
        } else {
            var hook = new app.Hook();
        }

        var data = {
          config:                     null,
          name:                       $('#hook_name').val(),
          type:                       $('#hook_type').val(),
          project_id:                 parseInt($('input[name="project_id"]').val()),
          enabled:                    $('#hook_enabled').is(':checked'),
          on_deployment_success:      $('#hook_on_deployment_success').is(':checked'),
          on_deployment_failure:      $('#hook_on_deployment_failure').is(':checked')
        };

        $('#hook #hook-config-' + data.type + ' :input[id^=hook_config]').each(function(key, field) {
            var name = $(field).attr('name');

            data[name] = $(field).val();
        });

        hook.save(data, {
            wait: true,
            success: function(model, response, options) {
                dialog.modal('hide');
                $('.callout-danger', dialog).hide();

                icon.removeClass('ion-refresh fixhub-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');

                if (!hook_id) {
                    app.Hooks.add(response);
                }
            },
            error: function(model, response, options) {
                $('.callout-danger', dialog).show();

                var errors = response.responseJSON;

                $('.has-error', dialog).removeClass('has-error');
                $('.label-danger', dialog).remove();

                $('form input', dialog).each(function (index, element) {
                    element = $(element);

                    var name = element.attr('name');

                    if (typeof errors[name] !== 'undefined') {
                        var parent = element.parents('div.form-group');
                        parent.addClass('has-error');
                        parent.append($('<span>').attr('class', 'label label-danger').text(errors[name]));
                    }
                });

                icon.removeClass('ion-refresh ion-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');
            }
        });
    });

    app.Hook = Backbone.Model.extend({
        urlRoot: '/hooks'
    });

    var Hooks = Backbone.Collection.extend({
        model: app.Hook
    });

    app.Hooks = new Hooks();

    app.HooksTab = Backbone.View.extend({
        el: '#app',
        events: {

        },
        initialize: function() {
            this.$list = $('#hook_list tbody');

            $('#no_hooks').show();
            $('#hook_list').hide();

            this.listenTo(app.Hooks, 'add', this.addOne);
            this.listenTo(app.Hooks, 'reset', this.addAll);
            this.listenTo(app.Hooks, 'remove', this.addAll);
            this.listenTo(app.Hooks, 'all', this.render);

            app.listener.on('hook:Fixhub\\Bus\\Events\\ModelChangedEvent', function (data) {
                var hook = app.Hooks.get(parseInt(data.model.id));

                if (server) {
                    hook.set(data.model);
                }
            });

            app.listener.on('hook:Fixhub\\Bus\\Events\\ModelCreatedEvent', function (data) {
                if (parseInt(data.model.project_id) === parseInt(app.project_id)) {
                    app.Hooks.add(data.model);
                }
            });

            app.listener.on('hook:Fixhub\\Bus\\Events\\ModelTrashedEvent', function (data) {
                var hook = app.Hooks.get(parseInt(data.model.id));

                if (hook) {
                    app.Hooks.remove(hook);
                }
            });
        },
        render: function () {
            if (app.Hooks.length) {
                $('#no_hooks').hide();
                $('#hook_list').show();
            } else {
                $('#no_hooks').show();
                $('#hook_list').hide();
            }
        },
        addOne: function (hook) {
            var view = new app.HookView({
                model: hook
            });

            this.$list.append(view.render().el);
        },
        addAll: function () {
            this.$list.html('');
            app.Hooks.each(this.addOne, this);
        }
    });

    app.HookView = Backbone.View.extend({
        tagName:  'tr',
        events: {
            'click .btn-edit': 'editHook',
            'click .btn-delete': 'trashHook'
        },
        initialize: function () {
            this.listenTo(this.model, 'change', this.render);
            this.listenTo(this.model, 'destroy', this.remove);

            this.template = _.template($('#hook-template').html());
        },
        render: function () {
            var data = this.model.toJSON();

            data.icon = 'compose';
            data.label = trans('hooks.custom');

            if (this.model.get('type') !== 'custom') {
                data.label = trans('hooks.' + this.model.get('type'));
            }

            if (this.model.get('type') === 'slack') {
                data.icon = 'pound';
            } else if (this.model.get('type') === 'mail') {
                data.icon = 'email';
            }

            this.$el.html(this.template(data));

            return this;
        },
        editHook: function() {
            var type = this.model.get('type');

            $.each(this.model.get('config'), function(field, value) {
                $('#hook-config-' + type + ' #hook_config_' + field).val(value);
            });

            $('#hook_id').val(this.model.id);
            $('#hook_name').val(this.model.get('name'));
            $('#hook_type').val(type);
            $('#hook_enabled').prop('checked', (this.model.get('enabled') === true));
            $('#hook_on_deployment_success').prop('checked', (this.model.get('on_deployment_success') === true));
            $('#hook_on_deployment_failure').prop('checked', (this.model.get('on_deployment_failure') === true));

            setTitleWithIcon(this.model.get('type'), 'edit');
        },
        trashHook: function() {
            var target = $('#model_id');
            target.val(this.model.id);
            target.parents('.modal').removeClass().addClass('modal fade hook-trash');
        }
    });
})(jQuery);<commit_msg>Fix typo<commit_after>var app = app || {};

(function ($) {
    $('#hook').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget);
        var modal = $(this);

        $('.btn-danger', modal).hide();
        $('.callout-danger', modal).hide();
        $('.callout-warning', modal).hide();
        $('.has-error', modal).removeClass('has-error');
        $('.label-danger', modal).remove();

        if (button.hasClass('btn-edit')) {
            $('.btn-danger', modal).show();
        } else {
            $('#hook_id').val('');
            $('#hook_name').val('');
            $('#hook_type').val('');
            $('#hook :input[id^=hook_config]').val('');
            $('#hook .hook-config input[type=checkbox]').prop('checked', true);
            $('#hook .hook-enabled input[type=checkbox]').prop('checked', true);
            $('#hook .modal-footer').hide();
            $('.hook-config').hide();
            $('.hook-enabled').hide();
            $('#hook-type').show();
            modal.find('.modal-title span').text(trans('hooks.create'));
        }
    });

    $('#hook #hook-type a.btn-app').on('click', function(event) {
        var button = $(event.currentTarget);
        var modal = $('#hook');

        if (button.attr('disabled')) {
            $('.callout-warning', modal).show();
            return;
        }

        $('.callout-warning', modal).hide();

        var type = button.data('type');
        setTitleWithIcon(type, 'create');
    });

    function setTitleWithIcon(type, action) {
        $('#hook .modal-title span').text(trans('hooks.' + action + '_' + type));

        var element = $('#hook .modal-title i').removeClass().addClass('ion');
        var icon = 'cogs';

        if (type === 'slack') {
            icon = 'pound';
        } else if (type === 'mail') {
            icon = 'email';
        } else if (type === 'custom') {
            icon = 'compose';
        }

        element.addClass('ion-' + icon);

        $('#hook .modal-footer').show();
        $('.hook-config').hide();
        $('#hook-type').hide();
        $('#hook-name').show();
        $('#hook-triggers').show();
        $('.hook-enabled').show();
        $('#hook-config-' + type).show();
        $('#hook_type').val(type);
    }

    //$('#hook button.btn-delete').on('click', function (event) {
    $('body').delegate('.hook-trash button.btn-delete','click', function (event) {
        var target = $(event.currentTarget);
        var icon = target.find('i');
        var dialog = target.parents('.modal');

        icon.addClass('ion-refresh fixhub-spin');
        dialog.find('input').attr('disabled', 'disabled');
        $('button.close', dialog).hide();

        var hook = app.Hooks.get($('#model_id').val());

        hook.destroy({
            wait: true,
            success: function(model, response, options) {
                dialog.modal('hide');
                $('.callout-danger', dialog).hide();

                icon.removeClass('ion-refresh fixhub-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');
            },
            error: function() {
                icon.removeClass('ion-refresh fixhub-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');
            }
        });
    });

    $('#hook button.btn-save').on('click', function (event) {
        var target = $(event.currentTarget);
        var icon = target.find('i');
        var dialog = target.parents('.modal');

        icon.addClass('ion-refresh fixhub-spin');
        dialog.find('input').attr('disabled', 'disabled');
        $('button.close', dialog).hide();

        var hook_id = $('#hook_id').val();

        if (hook_id) {
            var hook = app.Hooks.get(hook_id);
        } else {
            var hook = new app.Hook();
        }

        var data = {
          config:                     null,
          name:                       $('#hook_name').val(),
          type:                       $('#hook_type').val(),
          project_id:                 parseInt($('input[name="project_id"]').val()),
          enabled:                    $('#hook_enabled').is(':checked'),
          on_deployment_success:      $('#hook_on_deployment_success').is(':checked'),
          on_deployment_failure:      $('#hook_on_deployment_failure').is(':checked')
        };

        $('#hook #hook-config-' + data.type + ' :input[id^=hook_config]').each(function(key, field) {
            var name = $(field).attr('name');

            data[name] = $(field).val();
        });

        hook.save(data, {
            wait: true,
            success: function(model, response, options) {
                dialog.modal('hide');
                $('.callout-danger', dialog).hide();

                icon.removeClass('ion-refresh fixhub-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');

                if (!hook_id) {
                    app.Hooks.add(response);
                }
            },
            error: function(model, response, options) {
                $('.callout-danger', dialog).show();

                var errors = response.responseJSON;

                $('.has-error', dialog).removeClass('has-error');
                $('.label-danger', dialog).remove();

                $('form input', dialog).each(function (index, element) {
                    element = $(element);

                    var name = element.attr('name');

                    if (typeof errors[name] !== 'undefined') {
                        var parent = element.parents('div.form-group');
                        parent.addClass('has-error');
                        parent.append($('<span>').attr('class', 'label label-danger').text(errors[name]));
                    }
                });

                icon.removeClass('ion-refresh ion-spin');
                $('button.close', dialog).show();
                dialog.find('input').removeAttr('disabled');
            }
        });
    });

    app.Hook = Backbone.Model.extend({
        urlRoot: '/hooks'
    });

    var Hooks = Backbone.Collection.extend({
        model: app.Hook
    });

    app.Hooks = new Hooks();

    app.HooksTab = Backbone.View.extend({
        el: '#app',
        events: {

        },
        initialize: function() {
            this.$list = $('#hook_list tbody');

            $('#no_hooks').show();
            $('#hook_list').hide();

            this.listenTo(app.Hooks, 'add', this.addOne);
            this.listenTo(app.Hooks, 'reset', this.addAll);
            this.listenTo(app.Hooks, 'remove', this.addAll);
            this.listenTo(app.Hooks, 'all', this.render);

            app.listener.on('hook:Fixhub\\Bus\\Events\\ModelChangedEvent', function (data) {
                var hook = app.Hooks.get(parseInt(data.model.id));

                if (hook) {
                    hook.set(data.model);
                }
            });

            app.listener.on('hook:Fixhub\\Bus\\Events\\ModelCreatedEvent', function (data) {
                if (parseInt(data.model.project_id) === parseInt(app.project_id)) {
                    app.Hooks.add(data.model);
                }
            });

            app.listener.on('hook:Fixhub\\Bus\\Events\\ModelTrashedEvent', function (data) {
                var hook = app.Hooks.get(parseInt(data.model.id));

                if (hook) {
                    app.Hooks.remove(hook);
                }
            });
        },
        render: function () {
            if (app.Hooks.length) {
                $('#no_hooks').hide();
                $('#hook_list').show();
            } else {
                $('#no_hooks').show();
                $('#hook_list').hide();
            }
        },
        addOne: function (hook) {
            var view = new app.HookView({
                model: hook
            });

            this.$list.append(view.render().el);
        },
        addAll: function () {
            this.$list.html('');
            app.Hooks.each(this.addOne, this);
        }
    });

    app.HookView = Backbone.View.extend({
        tagName:  'tr',
        events: {
            'click .btn-edit': 'editHook',
            'click .btn-delete': 'trashHook'
        },
        initialize: function () {
            this.listenTo(this.model, 'change', this.render);
            this.listenTo(this.model, 'destroy', this.remove);

            this.template = _.template($('#hook-template').html());
        },
        render: function () {
            var data = this.model.toJSON();

            data.icon = 'compose';
            data.label = trans('hooks.custom');

            if (this.model.get('type') !== 'custom') {
                data.label = trans('hooks.' + this.model.get('type'));
            }

            if (this.model.get('type') === 'slack') {
                data.icon = 'pound';
            } else if (this.model.get('type') === 'mail') {
                data.icon = 'email';
            }

            this.$el.html(this.template(data));

            return this;
        },
        editHook: function() {
            var type = this.model.get('type');

            $.each(this.model.get('config'), function(field, value) {
                $('#hook-config-' + type + ' #hook_config_' + field).val(value);
            });

            $('#hook_id').val(this.model.id);
            $('#hook_name').val(this.model.get('name'));
            $('#hook_type').val(type);
            $('#hook_enabled').prop('checked', (this.model.get('enabled') === true));
            $('#hook_on_deployment_success').prop('checked', (this.model.get('on_deployment_success') === true));
            $('#hook_on_deployment_failure').prop('checked', (this.model.get('on_deployment_failure') === true));

            setTitleWithIcon(this.model.get('type'), 'edit');
        },
        trashHook: function() {
            var target = $('#model_id');
            target.val(this.model.id);
            target.parents('.modal').removeClass().addClass('modal fade hook-trash');
        }
    });
})(jQuery);<|endoftext|>


<commit_before>$(main);

function main() {
    $.getJSON('./data.json', function(d) {
        var data = attachColors(groupData(d));
        var state = {
            type: '',
            category: '',
            amount: ''
        };
        var update = updateAll.bind(undefined, $('.content.row'), data, state);

        $(window).on('resize', update);

        createCdns($('.cdns'), data, update);
        createControls($('.controls.row'), state, update);
        $('.controlsContainer .control:last-child').trigger('click');
        $('.types .control:first').trigger('click');
        update();
    });

    function groupData(data) {
        var ret = {};

        Object.keys(data).forEach(function(type) {
            var name;

            data[type].forEach(function(v) {
                var d = v.data;

                name = getProviderName(v.name);

                if(!(name in ret)) ret[name] = {
                    _enabled: true
                };
                if(!(v.type in ret[name])) ret[name][v.type] = {};

                if(type == 'uptime') {
                    d = d.map(function(v) {
                        return v * 100;
                    });
                }

                d = d.map(toFixed(2));

                ret[name][v.type][type] = d.reverse(); /* from oldest to newest */
            });
        });

        return ret;
    }

    function toFixed(a) {
        return function(v) {
            return parseFloat(v.toFixed(a), 10);
        };
    }

    function attachColors(data) {
        var i = 0;

        for(var name in data) {
            data[name]._color = getColor(i);

            i++;
        }

        return data;
    }

    function createCdns($p, data, update) {
        Object.keys(data).forEach(function(name) {
            var $e = $('<a>', {'class': 'cdn', href: '#'}).text(name).appendTo($p).on('click', function(e) {
                e.preventDefault();

                $e.toggleClass('selected');

                data[name]._enabled = $e.hasClass('selected');

                update();
            });
        });

        $('.cdn').addClass('selected');
    }

    function createControls($p, state, update) {
        createTypes($p, state, update);
        createAmounts($p, state, update);
    }

    function createTypes($p, state, update) {
        $controls($p, state, update, 'types', 'type', ['ping', 'http', 'https']);
    }

    function createAmounts($p, state, update) {
        // TODO: replace with a slider?
        $controls($p, state, update, 'amounts', 'amount', [7, 14]);
    }

    function $controls($p, state, update, containerClass, itemClass, items) {
        var $e = $('<div>',
            {'class': 'small-12 large-4 columns controlsContainer ' + containerClass}).appendTo($p);
        items.forEach($control.bind(undefined, $e, state, itemClass, update));
    }

    function $control($p, state, type, update, name) {
        var $e = $('<a>', {'class': 'control ' + type, href: '#'}).text(name).on('click', function(e) {
            e.preventDefault();

            $e.siblings().removeClass('selected').removeClass('label');
            $e.addClass('selected label');

            state[type] = name;

            update();
        }).appendTo($p);
    }

    function updateAll($p, data, state) {
        updateCharts($p, data, state);
        updateLegend($p, data, state);
    }

    function updateCharts($p, data, state) {
        var $container = $('.chartContainer:first');

        if(!$container.length) {
            $container = $('<div>',
                {'class': 'chartContainer small-12 large-8 columns'}).appendTo($p);
        }

        updateChart($container, data, state, 'uptime', 100);
        updateChart($container, data, state, 'latency', 300)
    }

    function updateChart($p, data, state, category, height) {
        var $canvas = $('.' + category + 'Chart:first');
        var ctx, width;

        if(!$canvas.length) {
            $canvas = $('<canvas>', {'class': category + 'Chart'}).appendTo($p);
        }

        width = $canvas.parent().width();

        $canvas.attr({width: width, height: height});

        var ctx = $canvas[0].getContext('2d');
        new Chart(ctx).Line(getData(data, state, category), {
            datasetFill: false,
            animation: true,
            animationSteps: 45,
	        pointDot: true,
	        scaleShowGridLines: true,
            scaleGridLineColor: 'rgba(224,224,224,0.5)',
	        scaleGridLineWidth: 1,
	        pointDotRadius: 3,
	        bezierCurve: false
        });
    }

    function updateLegend($p, data, state) {
        var $table = $('table.legend:first');
        var provider, color, $e, $header;

        if(!$table.length) {
            $e = $('<div>',
                {'class': 'legendContainer small-12 large-4 columns'}).appendTo($p);

            $table = $('<table>', {'class': 'legend'}).appendTo($e);
        }

        $table.empty();

        $header = $('<tr>').appendTo($table);

        $('<th>', {'class': 'colorLegend'}).appendTo($header);
        $('<th>', {'class': 'cdn'}).text('CDN').appendTo($header);
        $('<th>', {'class': 'latency'}).text(title('latency')).appendTo($header);
        $('<th>', {'class': 'uptime'}).text(title('uptime')).appendTo($header);

        for(var name in data) {
            provider = data[name];
            color = provider._color;

            if(provider._enabled && state.type in provider) {
                var $row = $('<tr>').appendTo($table);

                $('<td>', {'class': 'color'}).css('background-color',
                    color).appendTo($row);
                $('<td>', {'class': 'name'}).text(name).appendTo($row);

                ['latency', 'uptime'].forEach(function(category) {
                    var values = provider[state.type][category];
                    var value;

                    if(values) value = average(values.slice(-state.amount)).toFixed(1);
                    if(category == 'latency') value += ' ms';
                    if(category == 'uptime') value += ' %';

                    $('<td>', {'class': 'value'}).text(value).appendTo($row);
                });
            }
        }
    }

    function title(a) {
        if(!a) return;

        return a[0].toUpperCase() + a.slice(1);
    }

    function average(arr) {
        if(!arr) return;

        return sum(arr) / arr.length;
    }

    function sum(arr) {
        if(!arr) return;

        return arr.reduce(function(a, b) {
            return a + b;
        });
    }

    function getData(data, state, category) {
        return {
            labels: getLabels(state.amount),
            datasets: getDatasets(data, state, category)
        };
    }

    function getLabels(amount) {
        var ret = [];
        var i, d;

        for(i = 0; i < amount; i++) {
            d = new XDate();

            d.addDays(-(amount - i - 1));

            ret.push(d.toString('dd MMM'));
        }

        return ret;
    }

    function getDatasets(data, state, category) {
        var ret = [];
        var provider, color;

        for(var cdn in data) {
            provider = data[cdn];
            color = provider._color;

            if(!provider._enabled) continue;
            if(!(state.type in data[cdn])) continue;
            if(!(category in data[cdn][state.type])) continue;

            ret.push({
                strokeColor: color,
                pointColor: color,
                pointStrokeColor: color,
                data: data[cdn][state.type][category].slice(-state.amount)
            });
        }

        return ret;
    }

    function getProviderName(fullname) {
        return fullname.split(' ')[0];
    }

    function getColor(index) {
        return [
            '#d84f44',
            '#aee3d6',
            '#f3d5a2',
            '#5d96d7',
            '#444',
            '#e388eb',
            '#aadd5e'
        ][index];
    }

    function unique(arr) {
        var ret = {};

        arr.forEach(function(v) {
            ret[v] = true;
        });

        return Object.keys(ret);
    }

    function prop(name) {
        return function(v) {
            return v[name];
        };
    }
}
<commit_msg>Make it possible to set type and amount via qs<commit_after>$(main);

function main() {
    $.getJSON('./data.json', function(d) {
        var data = attachColors(groupData(d));
        var state = initializeState();
        var update = updateAll.bind(undefined, $('.content.row'), data, state);

        $(window).on('resize', update);

        createCdns($('.cdns'), data, update);
        createControls($('.controls.row'), state, update);

        initializeControls(state);
    });

    function initializeState() {
        return overlay({
            type: '',
            amount: ''
        }, qsToObject());
    }

    function initializeControls(state) {
        var $e, k, v;

        for(k in state) {
            v = state[k];

            $e = v && $('.control.' + k + '.' + v) || '';
            if($e.length) $e.trigger('click');
            else $('.control.' + k + ':last').trigger('click');
        }
    }

    function overlay(a, b) {
        var ret = {};

        for(var k in a) ret[k] = k in b? b[k]: a[k];

        return ret;
    }

    function qsToObject() {
        var search = window.location.search;

        if(!search) return {};

        return zipToObject(search.slice(1).split('&').map(op('split', '=')));
    }

    function op(name, param) {
        return function(a) {
            return a[name](param);
        };
    }

    function zipToObject(z) {
        var ret = {};

        z.forEach(function(v) {
            ret[v[0]] = v[1];
        });

        return ret;
    }

    function groupData(data) {
        var ret = {};

        Object.keys(data).forEach(function(type) {
            var name;

            data[type].forEach(function(v) {
                var d = v.data;

                name = getProviderName(v.name);

                if(!(name in ret)) ret[name] = {
                    _enabled: true
                };
                if(!(v.type in ret[name])) ret[name][v.type] = {};

                if(type == 'uptime') {
                    d = d.map(function(v) {
                        return v * 100;
                    });
                }

                d = d.map(toFixed(2));

                ret[name][v.type][type] = d.reverse(); /* from oldest to newest */
            });
        });

        return ret;
    }

    function toFixed(a) {
        return function(v) {
            return parseFloat(v.toFixed(a), 10);
        };
    }

    function attachColors(data) {
        var i = 0;

        for(var name in data) {
            data[name]._color = getColor(i);

            i++;
        }

        return data;
    }

    function createCdns($p, data, update) {
        Object.keys(data).forEach(function(name) {
            var $e = $('<a>', {'class': 'cdn', href: '#'}).text(name).appendTo($p).on('click', function(e) {
                e.preventDefault();

                $e.toggleClass('selected');

                data[name]._enabled = $e.hasClass('selected');

                update();
            });
        });

        $('.cdn').addClass('selected');
    }

    function createControls($p, state, update) {
        createTypes($p, state, update);
        createAmounts($p, state, update);
    }

    function createTypes($p, state, update) {
        $controls($p, state, update, 'types', 'type', ['ping', 'http', 'https']);
    }

    function createAmounts($p, state, update) {
        // TODO: replace with a slider?
        $controls($p, state, update, 'amounts', 'amount', [7, 14]);
    }

    function $controls($p, state, update, containerClass, itemClass, items) {
        var $e = $('<div>',
            {'class': 'small-12 large-4 columns controlsContainer ' + containerClass}).appendTo($p);
        items.forEach($control.bind(undefined, $e, state, itemClass, update));
    }

    function $control($p, state, type, update, name) {
        var $e = $('<a>', {'class': 'control ' + type + ' ' + name, href: '#'}).text(name).on('click', function(e) {
            e.preventDefault();

            $e.siblings().removeClass('selected').removeClass('label');
            $e.addClass('selected label');

            state[type] = name;

            update();
        }).appendTo($p);
    }

    function updateAll($p, data, state) {
        updateCharts($p, data, state);
        updateLegend($p, data, state);
    }

    function updateCharts($p, data, state) {
        var $container = $('.chartContainer:first');

        if(!$container.length) {
            $container = $('<div>',
                {'class': 'chartContainer small-12 large-8 columns'}).appendTo($p);
        }

        updateChart($container, data, state, 'uptime', 100);
        updateChart($container, data, state, 'latency', 300)
    }

    function updateChart($p, data, state, category, height) {
        var $canvas = $('.' + category + 'Chart:first');
        var ctx, width;

        if(!$canvas.length) {
            $canvas = $('<canvas>', {'class': category + 'Chart'}).appendTo($p);
        }

        width = $canvas.parent().width();

        $canvas.attr({width: width, height: height});

        var ctx = $canvas[0].getContext('2d');
        new Chart(ctx).Line(getData(data, state, category), {
            datasetFill: false,
            animation: true,
            animationSteps: 45,
	        pointDot: true,
	        scaleShowGridLines: true,
            scaleGridLineColor: 'rgba(224,224,224,0.5)',
	        scaleGridLineWidth: 1,
	        pointDotRadius: 3,
	        bezierCurve: false
        });
    }

    function updateLegend($p, data, state) {
        var $table = $('table.legend:first');
        var provider, color, $e, $header;

        if(!$table.length) {
            $e = $('<div>',
                {'class': 'legendContainer small-12 large-4 columns'}).appendTo($p);

            $table = $('<table>', {'class': 'legend'}).appendTo($e);
        }

        $table.empty();

        $header = $('<tr>').appendTo($table);

        $('<th>', {'class': 'colorLegend'}).appendTo($header);
        $('<th>', {'class': 'cdn'}).text('CDN').appendTo($header);
        $('<th>', {'class': 'latency'}).text(title('latency')).appendTo($header);
        $('<th>', {'class': 'uptime'}).text(title('uptime')).appendTo($header);

        for(var name in data) {
            provider = data[name];
            color = provider._color;

            if(provider._enabled && state.type in provider) {
                var $row = $('<tr>').appendTo($table);

                $('<td>', {'class': 'color'}).css('background-color',
                    color).appendTo($row);
                $('<td>', {'class': 'name'}).text(name).appendTo($row);

                ['latency', 'uptime'].forEach(function(category) {
                    var values = provider[state.type][category];
                    var value;

                    if(values) value = average(values.slice(-state.amount)).toFixed(1);
                    if(category == 'latency') value += ' ms';
                    if(category == 'uptime') value += ' %';

                    $('<td>', {'class': 'value'}).text(value).appendTo($row);
                });
            }
        }
    }

    function title(a) {
        if(!a) return;

        return a[0].toUpperCase() + a.slice(1);
    }

    function average(arr) {
        if(!arr) return;

        return sum(arr) / arr.length;
    }

    function sum(arr) {
        if(!arr) return;

        return arr.reduce(function(a, b) {
            return a + b;
        });
    }

    function getData(data, state, category) {
        return {
            labels: getLabels(state.amount),
            datasets: getDatasets(data, state, category)
        };
    }

    function getLabels(amount) {
        var ret = [];
        var i, d;

        for(i = 0; i < amount; i++) {
            d = new XDate();

            d.addDays(-(amount - i - 1));

            ret.push(d.toString('dd MMM'));
        }

        return ret;
    }

    function getDatasets(data, state, category) {
        var ret = [];
        var provider, color;

        for(var cdn in data) {
            provider = data[cdn];
            color = provider._color;

            if(!provider._enabled) continue;
            if(!(state.type in data[cdn])) continue;
            if(!(category in data[cdn][state.type])) continue;

            ret.push({
                strokeColor: color,
                pointColor: color,
                pointStrokeColor: color,
                data: data[cdn][state.type][category].slice(-state.amount)
            });
        }

        return ret;
    }

    function getProviderName(fullname) {
        return fullname.split(' ')[0];
    }

    function getColor(index) {
        return [
            '#d84f44',
            '#aee3d6',
            '#f3d5a2',
            '#5d96d7',
            '#444',
            '#e388eb',
            '#aadd5e'
        ][index];
    }

    function unique(arr) {
        var ret = {};

        arr.forEach(function(v) {
            ret[v] = true;
        });

        return Object.keys(ret);
    }

    function prop(name) {
        return function(v) {
            return v[name];
        };
    }
}
<|endoftext|>