<commit_before>$(document).ready(function(){
    $("#myTab a").click(function(e){
        e.preventDefault();
        $(this).tab("show");
    })
    var polling = function(){
        load_table("/githubworld", "#world-table");
        load_table("/githubchina", "#china-table");
    }
    interval = setInterval(polling, 1000);

    var updater = function(url, select) {
        this.select = select;
        this.url = "ws://" + location.host + url;
        this.start = function(){
            if ("WebSocket" in window) {
                this.socket = new WebSocket(this.url);
            }
            else if ("MozWebSocket" in window){
                this.socket = new MozWebSocket(this.url);
            }
            if (this.socket != nu"l){
                var socket = this.socket;
                var select = this.select;
                socket.onmessage = function(event) {
                    var data = JSON.parse(event.data);
                    fill_table(data, select)
                    socket.send(JSON.stringify(data));
                };
                socket.onclose = function(event) {
                    socket.close();
                };
            }
            else {
                alert("websocket are not supported in your browser, chose chrome browser or firfox!");
            }
        }
    }
    //var chinasocket = new updater("/socketchina", "#china-table");
    //var worldsocket = new updater("/socketworld", "#world-table");
    //chinasocket.start();
    //worldsocket.start();

    function fill_table(data, select){
        var github_table  = "

";
        github_table +=  "Rank	";
        github_table +=  "Name	";
        github_table +=  "Score	";
        github_table +=  "Language	";
        github_table +=  "Location	";
        github_table +=  "Profile	";
        github_table += "

";
        for (var i in data){
            var count = parseInt(i) + 1;
            github_table += "#" + count + "	";
            github_table += "" + "" + data[i]["login"] + "" + "&nbsp(" + data[i]["name"] + ")" + "	";
            github_table += "" + parseInt(data[i]["score"]) + "	";
            github_table += "" + data[i]["language"] + "	";
            github_table += "" + data[i]["location"] + "	";
            github_table += "" + "" + "	";
            github_table +="

";
        }
        github_table += "

";
        if (data.length == 0){
            $(select).html("

");
        }else{
            $(select).html(github_table);
        }
    }

    function load_table(url, select){
        $.ajax({
            type: 'POST',
            url: url,
            data: {"site": "Tornado-data"},
            dataType: "json",
            success: function(data){
                var select = null;
                if (url.substring(7) == "world"){
                    select = "#world-table";
                }else{
                    select = "#china-table";
                }
                fill_table(data, select);
            }
        });
    }
});
<commit_msg>fixed bugs<commit_after>$(document).ready(function(){
    $("#myTab a").click(function(e){
        e.preventDefault();
        $(this).tab("show");
    })
    var polling = function(){
        load_table("/githubworld", "#world-table");
        load_table("/githubchina", "#china-table");
    }
    interval = setInterval(polling, 1000);

    var updater = function(url, select) {
        this.select = select;
        this.url = "ws://" + location.host + url;
        this.start = function(){
            if ("WebSocket" in window) {
                this.socket = new WebSocket(this.url);
            }
            else if ("MozWebSocket" in window){
                this.socket = new MozWebSocket(this.url);
            }
            if (this.socket != null){
                var socket = this.socket;
                var select = this.select;
                socket.onmessage = function(event) {
                    var data = JSON.parse(event.data);
                    fill_table(data, select)
                    socket.send(JSON.stringify(data));
                };
                socket.onclose = function(event) {
                    socket.close();
                };
            }
            else {
                alert("websocket are not supported in your browser, chose chrome browser or firfox!");
            }
        }
    }
    //var chinasocket = new updater("/socketchina", "#china-table");
    //var worldsocket = new updater("/socketworld", "#world-table");
    //chinasocket.start();
    //worldsocket.start();

    function fill_table(data, select){
        var github_table  = "

";
        github_table +=  "Rank	";
        github_table +=  "Name	";
        github_table +=  "Score	";
        github_table +=  "Language	";
        github_table +=  "Location	";
        github_table +=  "Profile	";
        github_table += "

";
        for (var i in data){
            var count = parseInt(i) + 1;
            github_table += "#" + count + "	";
            github_table += "" + "" + data[i]["login"] + "" + "&nbsp(" + data[i]["name"] + ")" + "	";
            github_table += "" + parseInt(data[i]["score"]) + "	";
            github_table += "" + data[i]["language"] + "	";
            github_table += "" + data[i]["location"] + "	";
            github_table += "" + "" + "	";
            github_table +="

";
        }
        github_table += "

";
        if (data.length == 0){
            $(select).html("

");
        }else{
            $(select).html(github_table);
        }
    }

    function load_table(url, select){
        $.ajax({
            type: 'POST',
            url: url,
            data: {"site": "Tornado-data"},
            dataType: "json",
            success: function(data){
                var select = null;
                if (url.substring(7) == "world"){
                    select = "#world-table";
                }else{
                    select = "#china-table";
                }
                fill_table(data, select);
            }
        });
    }
});
<|endoftext|>


<commit_before>describe('satellizer.config', function() {

  beforeEach(function() {
    var self = this;
    module('satellizer', function($authProvider) {
      self.$authProvider = $authProvider;
    });
  });

  beforeEach(inject(['satellizer.config', function(config) {
    this.config = config;
  }]));

  it('should set logoutRedirect', function() {
    this.$authProvider.logoutRedirect = '/signout';
    expect(this.config.logoutRedirect).toEqual('/signout');
    expect(this.$authProvider.logoutRedirect).toEqual('/signout');
  });

  it('should set loginRedirect', function() {
    this.$authProvider.loginRedirect = '/signin';
    expect(this.config.loginRedirect).toEqual('/signin');
    expect(this.$authProvider.loginRedirect).toEqual('/signin');
  });

  it('should set signupRedirect', function() {
    this.$authProvider.signupRedirect = '/newurl';
    expect(this.config.signupRedirect).toEqual('/newurl');
    expect(this.$authProvider.signupRedirect).toEqual('/newurl');
  });

  it('should set authHeader', function() {
    var configDefault = this.$authProvider.authHeader;

    this.$authProvider.authHeader = 'x-new-header';
    expect(this.config.authHeader).toEqual('x-new-header');
    expect(this.$authProvider.authHeader).toEqual('x-new-header');

    this.$authProvider.authHeader = configDefault;
  });

  it('should get loginOnSignup', function() {
    this.$authProvider.loginOnSignup = true;
    expect(this.config.loginOnSignup).toEqual(true);
    expect(this.$authProvider.loginOnSignup).toEqual(true);
  });

  it('should set loginUrl', function() {
    this.$authProvider.loginUrl = '/api/signin';
    expect(this.config.loginUrl).toEqual('/api/signin');
    expect(this.$authProvider.loginUrl).toEqual('/api/signin');
  });

  it('should set signupUrl', function() {
    this.$authProvider.signupUrl = '/api/signup';
    expect(this.config.signupUrl).toEqual('/api/signup');
    expect(this.$authProvider.signupUrl).toEqual('/api/signup');
  });

  it('should set loginRoute', function() {
    this.$authProvider.loginRoute = '/signin';
    expect(this.config.loginRoute).toEqual('/signin');
    expect(this.$authProvider.loginRoute).toEqual('/signin');
  });

  it('should set signupRoute', function() {
    this.$authProvider.signupRoute = '/register';
    expect(this.config.signupRoute).toEqual('/register');
    expect(this.$authProvider.signupRoute).toEqual('/register');
  });

  it('should set tokenName', function() {
    this.$authProvider.tokenName = 'access_token';
    expect(this.config.tokenName).toEqual('access_token');
    expect(this.$authProvider.tokenName).toEqual('access_token');
  });

  it('should set tokenPrefix', function() {
    this.$authProvider.tokenPrefix = 'myApp';
    expect(this.config.tokenPrefix).toEqual('myApp');
    expect(this.$authProvider.tokenPrefix).toEqual('myApp');
  });

  it('should set unlinkUrl', function() {
    this.$authProvider.unlinkUrl = '/disconnect/';
    expect(this.config.unlinkUrl).toEqual('/disconnect/');
    expect(this.$authProvider.unlinkUrl).toEqual('/disconnect/');
  });

  it('should update facebook with new params', function() {
    this.$authProvider.facebook({ clientId: '1234' });
    expect(this.config.providers.facebook.clientId).toBe('1234');
  });

  it('should update google with new params', function() {
    this.$authProvider.google({ state: 'secret' });
    expect(this.config.providers.google.state).toBe('secret');
  });

  it('should update github with new params', function() {
    this.$authProvider.github({ clientId: '1234' });
    expect(this.config.providers.github.clientId).toBe('1234');
  });

  it('should update linkedin with new params', function() {
    this.$authProvider.linkedin({ state: 'secret' });
    expect(this.config.providers.linkedin.state).toBe('secret');
  });

  it('should update twitter with new params', function() {
    this.$authProvider.twitter({ url: '/api/twitter' });
    expect(this.config.providers.twitter.url).toBe('/api/twitter');
  });

  it('should create new oauth2 provider', function() {
    this.$authProvider.oauth2({ name: 'instagram', url: '/auth/instagram' });
    expect(this.config.providers['instagram'].name).toBe('instagram');
    expect(this.config.providers['instagram'].url).toBe('/auth/instagram');
  });

  it('should add a new oauth1 provider', function() {
    this.$authProvider.oauth1({ name: 'goodreads', url: '/auth/goodreads' });
    expect(this.config.providers['goodreads'].url).toBe('/auth/goodreads');
  });

});

<commit_msg>added test for the platform config option<commit_after>describe('satellizer.config', function() {

  beforeEach(function() {
    var self = this;
    module('satellizer', function($authProvider) {
      self.$authProvider = $authProvider;
    });
  });

  beforeEach(inject(['satellizer.config', function(config) {
    this.config = config;
  }]));

  it('should set logoutRedirect', function() {
    this.$authProvider.logoutRedirect = '/signout';
    expect(this.config.logoutRedirect).toEqual('/signout');
    expect(this.$authProvider.logoutRedirect).toEqual('/signout');
  });

  it('should set loginRedirect', function() {
    this.$authProvider.loginRedirect = '/signin';
    expect(this.config.loginRedirect).toEqual('/signin');
    expect(this.$authProvider.loginRedirect).toEqual('/signin');
  });

  it('should set signupRedirect', function() {
    this.$authProvider.signupRedirect = '/newurl';
    expect(this.config.signupRedirect).toEqual('/newurl');
    expect(this.$authProvider.signupRedirect).toEqual('/newurl');
  });

  it('should set authHeader', function() {
    var configDefault = this.$authProvider.authHeader;

    this.$authProvider.authHeader = 'x-new-header';
    expect(this.config.authHeader).toEqual('x-new-header');
    expect(this.$authProvider.authHeader).toEqual('x-new-header');

    this.$authProvider.authHeader = configDefault;
  });

  it('should get loginOnSignup', function() {
    this.$authProvider.loginOnSignup = true;
    expect(this.config.loginOnSignup).toEqual(true);
    expect(this.$authProvider.loginOnSignup).toEqual(true);
  });

  it('should set loginUrl', function() {
    this.$authProvider.loginUrl = '/api/signin';
    expect(this.config.loginUrl).toEqual('/api/signin');
    expect(this.$authProvider.loginUrl).toEqual('/api/signin');
  });

  it('should set signupUrl', function() {
    this.$authProvider.signupUrl = '/api/signup';
    expect(this.config.signupUrl).toEqual('/api/signup');
    expect(this.$authProvider.signupUrl).toEqual('/api/signup');
  });

  it('should set loginRoute', function() {
    this.$authProvider.loginRoute = '/signin';
    expect(this.config.loginRoute).toEqual('/signin');
    expect(this.$authProvider.loginRoute).toEqual('/signin');
  });

  it('should set signupRoute', function() {
    this.$authProvider.signupRoute = '/register';
    expect(this.config.signupRoute).toEqual('/register');
    expect(this.$authProvider.signupRoute).toEqual('/register');
  });

  it('should set tokenName', function() {
    this.$authProvider.tokenName = 'access_token';
    expect(this.config.tokenName).toEqual('access_token');
    expect(this.$authProvider.tokenName).toEqual('access_token');
  });

  it('should set tokenPrefix', function() {
    this.$authProvider.tokenPrefix = 'myApp';
    expect(this.config.tokenPrefix).toEqual('myApp');
    expect(this.$authProvider.tokenPrefix).toEqual('myApp');
  });

  it('should set unlinkUrl', function() {
    this.$authProvider.unlinkUrl = '/disconnect/';
    expect(this.config.unlinkUrl).toEqual('/disconnect/');
    expect(this.$authProvider.unlinkUrl).toEqual('/disconnect/');
  });

  it('should update facebook with new params', function() {
    this.$authProvider.facebook({ clientId: '1234' });
    expect(this.config.providers.facebook.clientId).toBe('1234');
  });

  it('should update google with new params', function() {
    this.$authProvider.google({ state: 'secret' });
    expect(this.config.providers.google.state).toBe('secret');
  });

  it('should update github with new params', function() {
    this.$authProvider.github({ clientId: '1234' });
    expect(this.config.providers.github.clientId).toBe('1234');
  });

  it('should update linkedin with new params', function() {
    this.$authProvider.linkedin({ state: 'secret' });
    expect(this.config.providers.linkedin.state).toBe('secret');
  });

  it('should update twitter with new params', function() {
    this.$authProvider.twitter({ url: '/api/twitter' });
    expect(this.config.providers.twitter.url).toBe('/api/twitter');
  });

  it('should create new oauth2 provider', function() {
    this.$authProvider.oauth2({ name: 'instagram', url: '/auth/instagram' });
    expect(this.config.providers['instagram'].name).toBe('instagram');
    expect(this.config.providers['instagram'].url).toBe('/auth/instagram');
  });

  it('should add a new oauth1 provider', function() {
    this.$authProvider.oauth1({ name: 'goodreads', url: '/auth/goodreads' });
    expect(this.config.providers['goodreads'].url).toBe('/auth/goodreads');
  });

  it('should set platform', function() {
    this.$authProvider.platform = 'browser';
    expect(this.config.platform).toEqual('browser');
    expect(this.$authProvider.platform).toEqual('browser');
  });

});

<|endoftext|>


<commit_before>// Browser Detection Module
// ------------------------
// A derivative work by mediafreakch based on http://browser-update.org/
// Project Github page: https://github.com/mediafreakch/browserdetection

var browserDetection = (function () {
    var browser, os;

    // get the browser details
    var getBrowser = function () {
        var n, v, t, ua = navigator.userAgent;
        var names = {
            i: 'Internet Explorer',
            f: 'Firefox',
            o: 'Opera',
            s: 'Apple Safari',
            n: 'Netscape Navigator',
            c: 'Chrome',
            x: 'Other'
        };

        if (/bot|googlebot|slurp|mediapartners|adsbot|silk|android|phone|bingbot|google web preview|like firefox|chromeframe|seamonkey|opera mini|min|meego|netfront|moblin|maemo|arora|camino|flot|k-meleon|fennec|kazehakase|galeon|android|mobile|iphone|ipod|ipad|epiphany|rekonq|symbian|webos/i.test(ua)) n = "x";
        else if (/Trident.(\d+\.\d+)/i.test(ua)) n = 'io';
        else if (/MSIE.(\d+\.\d+)/i.test(ua)) n = 'i';
        else if (/Chrome.(\d+\.\d+)/i.test(ua)) n = 'c';
        else if (/Firefox.(\d+\.\d+)/i.test(ua)) n = 'f';
        else if (/Version.(\d+.\d+).{0,10}Safari/i.test(ua)) n = 's';
        else if (/Safari.(\d+)/i.test(ua)) n = 'so';
        else if (/Opera.*Version.(\d+\.?\d+)/i.test(ua)) n = 'o';
        else if (/Opera.(\d+\.?\d+)/i.test(ua)) n = 'o';
        else if (/Netscape.(\d+)/i.test(ua)) n = 'n';
        else return {
            n: 'x',
            v: 0,
            t: names[n]
        };

        if (n == 'x') return {
            n: 'x',
            v: 0,
            t: names[n]
        };

        v = Number(RegExp.$1);

        if (n == 'so') {
            v = ((v < 100) && 1.0) || ((v < 130) && 1.2) || ((v < 320) && 1.3) || ((v < 520) && 2.0) || ((v < 524) && 3.0) || ((v < 526) && 3.2) || 4.0;
            n = 's';
        }

        if (n == 'i' && v == 7 && window.XDomainRequest) {
            v = 8;
        }

        if (n == 'io') {
            n = 'i';
            if (v > 5) v = 10;
            else if (v > 4) v = 9;
            else if (v > 3.1) v = 8;
            else if (v > 3) v = 7;
            else v = 9;
        }

        return {
            n: n,
            v: v,
            t: names[n] + ' ' + v,
            name: names[n]
        }
    }

    browser = getBrowser();

    // get the OS
    var getOS = function () {
        var av = navigator.appVersion,
            os;

        if (av.indexOf("Win") != -1) os = 'Windows';
        else if (av.indexOf("Mac") != -1) os = 'Mac';
        else if (av.indexOf("X11") != -1) os = 'Unix';
        else if (av.indexOf("Linux") != -1) os = 'Linux';
        else os = "Unknown OS";
        return os;
    }

    os = getOS();

    // define a submodule that contains the logic to handle legacy browsers
    var Utils = (function (browser, os) {
        var LEGACYVERSIONS = {
            i: 9,
            f: 4,
            o: 11,
            s: 4,
            n: 10
        };

        var isLegacyBrowser = function (config) {
            var config = config || LEGACYVERSIONS;

            return (browser.n == 'x' || browser.n == 'c' || browser.v > config[browser.n]) ? false : true;
        }

        var runDetection = function (config, fn) {
            var legacyBrowsers = (config.legacyBrowsers ? config.legacyBrowsers : LEGACYVERSIONS),
                cookie = 'browserDetected=1';

            if ((!isLegacyBrowser(legacyBrowsers) || document.cookie.indexOf(cookie) > -1) && !config.debug)
                return;

            if (config.rememberUser) {
                var intv = config.rememberInterval,
                    exp;

                if (intv && intv > 0)
                    exp = ';expires=' + new Date(new Date().getTime() + 1000 * 3600 * 24 * intv).toUTCString();
                else
                    exp = '';

                document.cookie = cookie + ';path=/' + exp;
            }

            // execute callback if provided
            if (typeof (fn) === 'function')
                fn(os, browser.name, browser.v)
            else
            // or launch default notification
                console.log('%cYou are using ' + browser.name + ' ' + browser.v + ' on ' + os, 'font-weight:bold;color:blue', '\nThe owner of this website says that this is an old browser that shouldn\'t be used anymore');
        }

        // the facade for the submodule
        return {
            LEGACYVERSIONS: LEGACYVERSIONS,
            isLegacy: isLegacyBrowser,
            notify: runDetection
        };
    }(browser, os))

    // the facade for the core module
    return {
        Utils: Utils,
        getBrowser: function () {
            return browser.t;
        },
        getBrowserName: function () {
            return browser.name;
        },
        getBrowserVersion: function () {
            return browser.v;
        },
        getOS: function () {
            return os;
        }
    }
}())
<commit_msg>get rid of unnecessary other browsers test<commit_after>// Browser Detection Module
// ------------------------
// A derivative work by mediafreakch based on http://browser-update.org/
// Project Github page: https://github.com/mediafreakch/browserdetection

var browserDetection = (function () {
    var browser, os;

    // get the browser details
    var getBrowser = function () {
        var n, v, t, ua = navigator.userAgent;
        var names = {
            i: 'Internet Explorer',
            f: 'Firefox',
            o: 'Opera',
            s: 'Apple Safari',
            n: 'Netscape Navigator',
            c: 'Chrome',
            x: 'Other'
        };

        if (/Trident.(\d+\.\d+)/i.test(ua)) n = 'io';
        else if (/MSIE.(\d+\.\d+)/i.test(ua)) n = 'i';
        else if (/Chrome.(\d+\.\d+)/i.test(ua)) n = 'c';
        else if (/Firefox.(\d+\.\d+)/i.test(ua)) n = 'f';
        else if (/Version.(\d+.\d+).{0,10}Safari/i.test(ua)) n = 's';
        else if (/Safari.(\d+)/i.test(ua)) n = 'so';
        else if (/Opera.*Version.(\d+\.?\d+)/i.test(ua)) n = 'o';
        else if (/Opera.(\d+\.?\d+)/i.test(ua)) n = 'o';
        else if (/Netscape.(\d+)/i.test(ua)) n = 'n';
        else return {
            n: 'x',
            v: 0,
            t: names[n]
        };

        if (n == 'x') return {
            n: 'x',
            v: 0,
            t: names[n]
        };

        v = Number(RegExp.$1);

        if (n == 'so') {
            v = ((v < 100) && 1.0) || ((v < 130) && 1.2) || ((v < 320) && 1.3) || ((v < 520) && 2.0) || ((v < 524) && 3.0) || ((v < 526) && 3.2) || 4.0;
            n = 's';
        }

        if (n == 'i' && v == 7 && window.XDomainRequest) {
            v = 8;
        }

        if (n == 'io') {
            n = 'i';
            if (v > 5) v = 10;
            else if (v > 4) v = 9;
            else if (v > 3.1) v = 8;
            else if (v > 3) v = 7;
            else v = 9;
        }

        return {
            n: n,
            v: v,
            t: names[n] + ' ' + v,
            name: names[n]
        }
    }

    browser = getBrowser();

    // get the OS
    var getOS = function () {
        var av = navigator.appVersion,
            os;

        if (av.indexOf("Win") != -1) os = 'Windows';
        else if (av.indexOf("Mac") != -1) os = 'Mac';
        else if (av.indexOf("X11") != -1) os = 'Unix';
        else if (av.indexOf("Linux") != -1) os = 'Linux';
        else os = "Unknown OS";
        return os;
    }

    os = getOS();

    // define a submodule that contains the logic to handle legacy browsers
    var Utils = (function (browser, os) {
        var LEGACYVERSIONS = {
            i: 9,
            f: 4,
            o: 11,
            s: 4,
            n: 10
        };

        var isLegacyBrowser = function (config) {
            var config = config || LEGACYVERSIONS;

            return (browser.n == 'x' || browser.n == 'c' || browser.v > config[browser.n]) ? false : true;
        }

        var runDetection = function (config, fn) {
            var legacyBrowsers = (config.legacyBrowsers ? config.legacyBrowsers : LEGACYVERSIONS),
                cookie = 'browserDetected=1';

            if ((!isLegacyBrowser(legacyBrowsers) || document.cookie.indexOf(cookie) > -1) && !config.debug)
                return;

            if (config.rememberUser) {
                var intv = config.rememberInterval,
                    exp;

                if (intv && intv > 0)
                    exp = ';expires=' + new Date(new Date().getTime() + 1000 * 3600 * 24 * intv).toUTCString();
                else
                    exp = '';

                document.cookie = cookie + ';path=/' + exp;
            }

            // execute callback if provided
            if (typeof (fn) === 'function')
                fn(os, browser.name, browser.v)
            else
            // or launch default notification
                console.log('%cYou are using ' + browser.name + ' ' + browser.v + ' on ' + os, 'font-weight:bold;color:blue', '\nThe owner of this website says that this is an old browser that shouldn\'t be used anymore');
        }

        // the facade for the submodule
        return {
            LEGACYVERSIONS: LEGACYVERSIONS,
            isLegacy: isLegacyBrowser,
            notify: runDetection
        };
    }(browser, os))

    // the facade for the core module
    return {
        Utils: Utils,
        getBrowser: function () {
            return browser.t;
        },
        getBrowserName: function () {
            return browser.name;
        },
        getBrowserVersion: function () {
            return browser.v;
        },
        getOS: function () {
            return os;
        }
    }
}())
<|endoftext|>


<commit_before>// Array.from polyfill {{{
/* eslint-disable */
// Production steps of ECMA-262, Edition 6, 22.1.2.1
if (!Array.from) {
  Array.from = (function () {
    var toStr = Object.prototype.toString;
    var isCallable = function (fn) {
      return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
    };
    var toInteger = function (value) {
      var number = Number(value);
      if (isNaN(number)) { return 0; }
      if (number === 0 || !isFinite(number)) { return number; }
      return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
    };
    var maxSafeInteger = Math.pow(2, 53) - 1;
    var toLength = function (value) {
      var len = toInteger(value);
      return Math.min(Math.max(len, 0), maxSafeInteger);
    };

    // The length property of the from method is 1.
    return function from(arrayLike/*, mapFn, thisArg */) {
      // 1. Let C be the this value.
      var C = this;

      // 2. Let items be ToObject(arrayLike).
      var items = Object(arrayLike);

      // 3. ReturnIfAbrupt(items).
      if (arrayLike == null) {
        throw new TypeError('Array.from requires an array-like object - not null or undefined');
      }

      // 4. If mapfn is undefined, then let mapping be false.
      var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
      var T;
      if (typeof mapFn !== 'undefined') {
        // 5. else
        // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
        if (!isCallable(mapFn)) {
          throw new TypeError('Array.from: when provided, the second argument must be a function');
        }

        // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
        if (arguments.length > 2) {
          T = arguments[2];
        }
      }

      // 10. Let lenValue be Get(items, "length").
      // 11. Let len be ToLength(lenValue).
      var len = toLength(items.length);

      // 13. If IsConstructor(C) is true, then
      // 13. a. Let A be the result of calling the [[Construct]] internal method
      // of C with an argument list containing the single item len.
      // 14. a. Else, Let A be ArrayCreate(len).
      var A = isCallable(C) ? Object(new C(len)) : new Array(len);

      // 16. Let k be 0.
      var k = 0;
      // 17. Repeat, while k < len… (also steps a - h)
      var kValue;
      while (k < len) {
        kValue = items[k];
        if (mapFn) {
          A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
        } else {
          A[k] = kValue;
        }
        k += 1;
      }
      // 18. Let putStatus be Put(A, "length", len, true).
      A.length = len;
      // 20. Return A.
      return A;
    };
  }());
}
/* eslint-enable */
// }}}

(function game() {
    'use strict';

    var achievements = JSON.parse(window.localStorage.getItem('achievements'));
    var pageKey = window.location.pathname.replace('/article/', '').replace('/','');
    var totalAchievements = document.querySelectorAll('[data-achievement]').length;
    var achievementsHeadline = document.getElementById('achievements-headline');
    var interaction = 'click';
    if (typeof PointerEvent === 'function') {
        interaction = 'pointerup';
    }

    function addAchievementToDOM(text) {
        var achievementItem = document.createElement('li');
        achievementItem.textContent = text;
        document.getElementById('achievements-list').appendChild(achievementItem);
    }

    if (achievements && achievements[pageKey] && achievements[pageKey].length > 0) {
        achievements[pageKey].forEach(addAchievementToDOM);
        achievementsHeadline.textContent += ' ' + achievements[pageKey].length + '/' + totalAchievements;
    }
    else {
        achievementsHeadline.textContent += ' 0/' + totalAchievements;
    }
    console.log(achievementsHeadline);

    document.documentElement.addEventListener(interaction, function choiceClicks(event) {
        var achievement = event.target.dataset.achievement;
        if (!event.target.closest('.game-button')) {
            return false;
        }

        // Achievement.
        if (achievement) {
            if (!achievements || !achievements[pageKey]) {
                achievements = {};
                achievements[pageKey] = [];
            }
            if (achievements[pageKey].indexOf(achievement) !== -1) {
                return false;
            }
            document.getElementById('achievement-message').textContent = achievement;
            document.getElementById('achievement').classList.add('achievement--active');
            window.setTimeout(function hideAchievementMessage() {
                document.getElementById('achievement').classList.remove('achievement--active');
            }, 5000);
            addAchievementToDOM(achievement);
            achievements[pageKey].push(achievement);
            window.localStorage.setItem('achievements', JSON.stringify(achievements));
        }

        if (event.target.dataset.targetId === 'restart') {
            // Hide all exposed paths.
            Array.from(document.querySelectorAll('.game-scene'))
                .forEach(function hideGamePath(element) {
                    element.hidden = true;
                });
            // Re-enable all choices.
            Array.from(document.querySelectorAll('.game-button'))
                .forEach(function showChoices(element) {
                    element.removeAttribute('disabled');
                    element.classList.remove('game-button--selected');
                });
            // Show the starting segment.
            document.querySelector('.game-scene').hidden = false;
            // Scroll to top, aka the beginning of the story.
            window.scrollTo({
                top: 0,
                left: 0,
                behavior: 'smooth'
            });
            return;
        }

        // Show the path selected.
        document.getElementById(event.target.dataset.targetId).hidden = false;
        // Disable the buttons to choose the current path, and indicate your correct choice.
        Array.from(
            event.target.parentNode.querySelectorAll('.game-button')
        ).forEach(function disableButtons(button) {
            button.setAttribute('disabled', 'disabled');
            if (button.dataset.targetId === event.target.dataset.targetId) {
                button.classList.add('game-button--selected');
            }
        });
    }, false);
})();

// vim: foldmethod=marker
<commit_msg>Remove Array.from polyfill<commit_after>if (window.NodeList && !NodeList.prototype.forEach) {
    NodeList.prototype.forEach = Array.prototype.forEach;
}

(function game() {
    'use strict';

    var achievements = JSON.parse(window.localStorage.getItem('achievements'));
    var pageKey = window.location.pathname.replace('/article/', '').replace('/','');
    var totalAchievements = document.querySelectorAll('[data-achievement]').length;
    var achievementsHeadline = document.getElementById('achievements-headline');
    var interaction = 'click';
    if (typeof PointerEvent === 'function') {
        interaction = 'pointerup';
    }

    function addAchievementToDOM(text) {
        var achievementItem = document.createElement('li');
        achievementItem.textContent = text;
        document.getElementById('achievements-list').appendChild(achievementItem);
    }

    if (achievements && achievements[pageKey] && achievements[pageKey].length > 0) {
        achievements[pageKey].forEach(addAchievementToDOM);
        achievementsHeadline.textContent += ' ' + achievements[pageKey].length + '/' + totalAchievements;
    }
    else {
        achievementsHeadline.textContent += ' 0/' + totalAchievements;
    }
    console.log(achievementsHeadline);

    document.documentElement.addEventListener(interaction, function choiceClicks(event) {
        var achievement = event.target.dataset.achievement;
        if (!event.target.closest('.game-button')) {
            return false;
        }

        // Achievement.
        if (achievement) {
            if (!achievements || !achievements[pageKey]) {
                achievements = {};
                achievements[pageKey] = [];
            }
            if (achievements[pageKey].indexOf(achievement) !== -1) {
                return false;
            }
            document.getElementById('achievement-message').textContent = achievement;
            document.getElementById('achievement').classList.add('achievement--active');
            window.setTimeout(function hideAchievementMessage() {
                document.getElementById('achievement').classList.remove('achievement--active');
            }, 5000);
            addAchievementToDOM(achievement);
            achievements[pageKey].push(achievement);
            window.localStorage.setItem('achievements', JSON.stringify(achievements));
        }

        if (event.target.dataset.targetId === 'restart') {
            // Hide all exposed paths.
            document.querySelectorAll('.game-scene')
                .forEach(function hideGamePath(element) {
                    element.hidden = true;
                });
            // Re-enable all choices.
            document.querySelectorAll('.game-button')
                .forEach(function showChoices(element) {
                    element.removeAttribute('disabled');
                    element.classList.remove('game-button--selected');
                });
            // Show the starting segment.
            document.querySelector('.game-scene').hidden = false;
            // Scroll to top, aka the beginning of the story.
            window.scrollTo({
                top: 0,
                left: 0,
                behavior: 'smooth'
            });
            return;
        }

        // Show the path selected.
        document.getElementById(event.target.dataset.targetId).hidden = false;
        // Disable the buttons to choose the current path, and indicate your correct choice.
        event.target.parentNode.querySelectorAll('.game-button')
            .forEach(function disableButtons(button) {
                button.setAttribute('disabled', 'disabled');
                if (button.dataset.targetId === event.target.dataset.targetId) {
                    button.classList.add('game-button--selected');
                }
        });
    }, false);
})();

// vim: foldmethod=marker
<|endoftext|>


<commit_before>import moment from 'moment';
class NavbarController {
  constructor() {
    this.name = 'navbar';
  }
  $onInit(){
    this.moment = moment().format('dddd HH:mm');

    this.user =
      {
        name: 'Jesus Garcia',
        mail: 'ctw@ctwhome.com',
        picture: '//icons.iconarchive.com/icons/graphicloads/flat-finance/256/person-icon.png',
        lists: [
          {
            name: 'Study',
            timers: [
              {
                name: 'Timer 1',
                time: '1500'
              },
              {
                name: 'Timer 2',
                time: '1500'
              },
              {
                name: 'Timer 3',
                time: '1500'
              }
            ]
          },
          {
            name: 'Piano',
            timers: [
              {
                name: 'Timer 4',
                time: '1500'
              },
              {
                name: 'Timer 5',
                time: '1500'
              }
            ]
          }
        ]
      };

  }
}

export default NavbarController;
<commit_msg>Update local Date automatically<commit_after>import moment from 'moment';
class NavbarController {
  constructor() {
    this.name = 'navbar';
  }

  $onInit(){
    this.moment = moment().format('dddd HH:mm');

    this.updateDate();

    this.user =
      {
        name: 'Jesus Garcia',
        mail: 'ctw@ctwhome.com',
        picture: '//icons.iconarchive.com/icons/graphicloads/flat-finance/256/person-icon.png',
        lists: [
          {
            name: 'Study',
            timers: [
              {
                name: 'Timer 1',
                time: '1500'
              },
              {
                name: 'Timer 2',
                time: '1500'
              },
              {
                name: 'Timer 3',
                time: '1500'
              }
            ]
          },
          {
            name: 'Piano',
            timers: [
              {
                name: 'Timer 4',
                time: '1500'
              },
              {
                name: 'Timer 5',
                time: '1500'
              }
            ]
          }
        ]
      };
  }

  updateDate () {
    setTimeout(() => {
      this.moment = moment().format('dddd HH:mm');
      this.updateDate();
    }, 1000);
  }

}

export default NavbarController;
<|endoftext|>


<commit_before>var gulp = require("gulp");
var CFG = require("./utils/config.js");
var $ = require("gulp-load-plugins")();
var path = require("path");
var pkg = require(path.join("..", CFG.FILE.config.pkg));

/**
 * script:minify
 * @see www.npmjs.org/package/gulp-uglify
 * @see github.com/mishoo/UglifyJS
 */
gulp.task("script:minify", ["script:optimize", "script:minify:json", "source"], function() {
  // TODO Use gulp-header to add version info.

  return gulp.src([
      path.join(CFG.DIR.dist, "/**/*." + CFG.FILE.extension.script.js)
    ])
    .pipe($.uglify({
      outSourceMap: false, // Disable sourcemaps until github.com/gulpjs/gulp/issues/356
      preserveComments: "some",
      compress: {
        drop_console: true,
        dead_code: true,
        drop_debugger: true,
        join_vars: true,
        warnings: false,
        pure_funcs: [/* "console.log" */]
      }
    }))
    .pipe(gulp.dest(CFG.DIR.dist));
});
<commit_msg>Ensure that Uglify does not mangle the global require and define variables.<commit_after>var gulp = require("gulp");
var CFG = require("./utils/config.js");
var $ = require("gulp-load-plugins")();
var path = require("path");
var pkg = require(path.join("..", CFG.FILE.config.pkg));

/**
 * script:minify
 * @see www.npmjs.org/package/gulp-uglify
 * @see github.com/mishoo/UglifyJS
 */
gulp.task("script:minify", ["script:optimize", "script:minify:json", "source"], function() {
  // TODO Use gulp-header to add version info.

  return gulp.src([
      path.join(CFG.DIR.dist, "/**/*." + CFG.FILE.extension.script.js)
    ])
    .pipe($.uglify({
      outSourceMap: false, // Disable sourcemaps until github.com/gulpjs/gulp/issues/356
      // See github.com/terinjokes/gulp-uglify/issues/67
      mangle: {
        except: [
          "require",
          "define"
        ]
      },
      preserveComments: "some",
      compress: {
        drop_console: true,
        dead_code: true,
        drop_debugger: true,
        join_vars: true,
        warnings: false,
        pure_funcs: [/* "console.log" */]
      }
    }))
    .pipe(gulp.dest(CFG.DIR.dist));
});
<|endoftext|>


<commit_before>var _ = require('lodash')

exports['config'] = {
  'override booleans': function(test) {
    var redefine = require('../lib')
      , config = redefine.config({showWarnings:false})

    test.ok(!config.showWarnings)
    test.done()
  },

  'globalize': function(test) {
    var redefine = require('../lib')
      , globalize = _.partialRight(redefine.config().helpers.toGlobal, 'factory()')

    test.equal( escape(globalize('window.test-test'.split('.')))
              , escape('window["test-test"] = factory()'))

    test.equal( escape(globalize('a.b.c.d'.split('.')))
              , escape( 'a["b"] = parent["b"] || {};\n'
                      + 'a["b"]["c"] = parent["b"]["c"] || {};\n'
                      + 'a["b"]["c"]["d"] = factory();\n'))

    test.done()
  }

}

function escape(val) {
  return val.replace(/\n|\r/g,'')
            .replace(/\'|\"/g, '"')
            .replace(/\ |\;/g, '')
}

<commit_msg>added some tests around config.toString method<commit_after>var _ = require('lodash')

exports['config'] = {
  'override booleans': function(test) {
    var redefine = require('../lib')
      , config = redefine.config({showWarnings:false})

    test.ok(!config.showWarnings)
    test.done()
  },

  'to array': function(test) {
    var redefine = require('../lib')
      , config = redefine.config({})
      , _toString = config.helpers.toString

    test.equal(_toString([1,2,3,4,5]), '[\'1\',\'2\',\'3\',\'4\',\'5\']')
    test.equal(_toString([1,1,1]), "['1']")
    test.equal(_toString(['a','a']), "['a']")
    test.done()
  },

  'globalize': function(test) {
    var redefine = require('../lib')
      , globalize = _.partialRight(redefine.config().helpers.toGlobal, 'factory()')

    test.equal( escape(globalize('window.test-test'.split('.')))
              , escape('window["test-test"] = factory()'))

    test.equal( escape(globalize('a.b.c.d'.split('.')))
              , escape( 'a["b"] = parent["b"] || {};\n'
                      + 'a["b"]["c"] = parent["b"]["c"] || {};\n'
                      + 'a["b"]["c"]["d"] = factory();\n'))

    test.done()
  }

}

function escape(val) {
  return val.replace(/\n|\r/g,'')
            .replace(/\'|\"/g, '"')
            .replace(/\ |\;/g, '')
}

<|endoftext|>


<commit_before>import SideNavModule from './sideNav'
import SideNavController from './sideNav.controller';
import SideNavComponent from './sideNav.component';
import SideNavTemplate from './sideNav.html';

describe('SideNav', () => {
  let $rootScope, makeController;

  beforeEach(window.module(SideNavModule.name));
  beforeEach(inject((_$rootScope_) => {
    $rootScope = _$rootScope_;
    makeController = () => {
      return new SideNavController();
    };
  }));

  describe('Module', () => {
    // top-level specs: i.e., routes, injection, naming
  });

  describe('Controller', () => {
    // controller specs
    it('has a name property [REMOVE]', () => { // erase if removing this.name from the controller
      let controller = makeController();
      expect(controller).to.have.property('name');
    });
  });

  describe('Template', () => {
    // template specs
    // tip: use regex to ensure correct bindings are used e.g., {{  }}
    it('has name in template [REMOVE]', () => {
      expect(SideNavTemplate).to.match(/{{\s?vm\.name\s?}}/g);
    });
  });

  describe('Component', () => {
      // component/directive specs
      let component = SideNavComponent();

      it('includes the intended template',() => {
        expect(component.template).to.equal(SideNavTemplate);
      });

      it('uses `controllerAs` syntax', () => {
        expect(component).to.have.property('controllerAs');
      });

      it('invokes the right controller', () => {
        expect(component.controller).to.equal(SideNavController);
      });
  });
});
<commit_msg>oops sideNav spec failure fixed.<commit_after>import SideNavModule from './sideNav'
import SideNavController from './sideNav.controller';
import SideNavComponent from './sideNav.component';
import SideNavTemplate from './sideNav.html';

describe('SideNav', () => {
  let $rootScope, makeController;

  beforeEach(window.module(SideNavModule.name));
  beforeEach(inject((_$rootScope_) => {
    $rootScope = _$rootScope_;
    makeController = () => {
      return new SideNavController();
    };
  }));

  describe('Module', () => {
    // top-level specs: i.e., routes, injection, naming
  });

  describe('Controller', () => {
    // controller specs
    it('has a name property [REMOVE]', () => { // erase if removing this.name from the controller
      let controller = makeController();
      expect(controller).to.have.property('name');
    });
  });

  describe('Component', () => {
      // component/directive specs
      let component = SideNavComponent();

      it('includes the intended template',() => {
        expect(component.template).to.equal(SideNavTemplate);
      });

      it('uses `controllerAs` syntax', () => {
        expect(component).to.have.property('controllerAs');
      });

      it('invokes the right controller', () => {
        expect(component.controller).to.equal(SideNavController);
      });
  });
});
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */
var should = require('should'),
	mongoose = require('mongoose'),
	Child = mongoose.model('Child');

/**
 * Globals
 */
var  child;

/**
 * Unit tests
 */
describe('Child Model Unit Tests:', function() {
	beforeEach(function(done) {

			child = new Child({
				firstName: 'Tom',
				lastName: 'Jones'
			});
			done();
	});

	describe('Testing child model, FName is required on Method Save', function() {
		it('should be able to save without problems', function(done) {
			this.timeout(0);
			return child.save(function(err) {
				should.not.exist(err);
				done();
			});
		});

		it('should be able to show an error when try to save without fname', function(done) {
			child.firstName = '';

			return child.save(function(err) {
				should.exist(err);
				done();
			});
		});
	});

	afterEach(function(done) {
		Child.remove().exec();

		done();
	});
});<commit_msg>adding more fields to child server model test<commit_after>'use strict';

/**
 * Module dependencies.
 */
var should = require('should'),
	mongoose = require('mongoose'),
	Child = mongoose.model('Child');

/**
 * Globals
 */
var  child;

/**
 * Unit tests
 */
describe('Child Model Unit Tests:', function() {
	beforeEach(function(done) {

			child = new Child({
				firstName: 'Tom',
				lastName: 'Jones',
                enrolled: false,
                contact: {
                    email:'tom.jones@gmail.com',
                    home:'1234561234',
                    work:'7894561234',
                    address:'202 working lane, gvill, Fl 32612'
                },
                dob: {
                    month: 10,
                    day: 10,
                    year: 1994

                },
                schoolName: 'the cool school',
                size: 'medium',
                schedule: {
                    mon: false,
                    tue: false,
                    wed: false,
                    thu: false,
                    fri: false,
                    sat: false,
                    sun: false
                }
			});
			done();
	});

	describe('Testing child model, FName is required on Method Save', function() {
		it('should be able to save without problems', function(done) {
			this.timeout(0);
			return child.save(function(err) {
				should.not.exist(err);
				done();
			});
		});

		it('should be able to show an error when try to save without fname', function(done) {
			child.firstName = '';

			return child.save(function(err) {
				should.exist(err);
				done();
			});
		});
	});

	afterEach(function(done) {
		Child.remove().exec();

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


<commit_before>/*globals exports*/
(function () {
// Todo: Note to self: Integrate research from other jml notes
// Todo: Add tests
// Todo: Allow building of generic XML (pass configuration object)

/*
1) String element name (or array of 1-4)
2) Optional object with attributes
3) Optional array of text nodes and child elements
4) Optionally repeat for siblings
*/

/**
 * Creates an XHTML or HTML element (XHTML is preferred, but only in browsers that support);
 * Any element after element can be omitted, and any subsequent type or types added afterwards
 * @param {String} el The element to create (by lower-case name)
 * @param {Object} [atts] Attributes to add with the key as the attribute name and value as the
 *                                               attribute value; important for IE where the input element's type cannot
 *                                               be added later after already added to the page
 * @param {DOMElement[]} [children] The optional children of this element (but raw DOM elements
 *                                                                      required to be specified within arrays since
 *                                                                      could not otherwise be distinguished from siblings being added)
 * @param {DOMElement} [parent] The optional parent to which to attach the element (always the last
 *                                                                  unless followed by null, in which case it is the second-to-last)
 * @param {null} [returning] Can use null to indicate an array of elements should be returned
 * @returns {DOMElement} The newly created (and possibly already appended) element or array of elements
 */
/*
RULES
    1) Last element always the parent (put null if don't want but want to return) unless only atts and children (no other elements)
    2) Individual elements (DOM elements or sequences of string[/object/array]) get added to parent first-in, first-added
    3) Arrays or arrays of arrays always indicate children
    4) Strings always indicate elements
    5) Non-DOM-element objects always indicate attribute-value pairs
    6) null always indicates a place-holder (only needed in place of parent for last argument if want array returned)
    7) First item must be an element
    8) Always returns first created element, unless null as last argument, in which case, it returns an array of all added elements
*/
/*
// EXAMPLES
// 1)
var input = jml('input');
// 2)
var input = jml('input', {type:'password'});
// 3)
var div = jml('div', {'class': 'myClass'}, [
    ['p', ['Some inner text']],
    ['p', ['another child paragraph']]
]);
// 4)
var div = jml('div', [
    ['p', ['no attributes on the div']]
]);
// 5)
var simpleAttachToParent = jml('hr', document.body);
// 6)
var firstTr = jml('tr', [
        ['td', ['row 1 cell 1']],
        ['td', ['row 1 cell 2']]
    ],
    'tr', {className: 'anotherRowSibling'}, [
        ['td', ['row 2 cell 1']],
        ['td', ['row 2 cell 2']]
    ],
    table
);
// 7)
var trsArray = jml('tr', [
        ['td', ['row 1 cell 1']],
        ['td', ['row 1 cell 2']]
    ],
    'tr', {className: 'anotherRowSibling'}, [
        ['td', ['row 2 cell 1']],
        ['td', ['row 2 cell 2']]
    ],
    table,
    null
);
// 8)

var div = jml(
    'div', [
        $('DOMChildrenMustBeInArray')
    ],
    $('anotherElementToAddToParent'),
    $('yetAnotherSiblingToAddToParent'),
    parent
);
*/

    'use strict';

    /**
     * Need this function for IE since options weren't otherwise getting added
     * @private
     * @param {DOMElement} parent The parent to which to append the element
     * @param {DOMNode} el The element or other node to append to the parent
     */
    function _appendNode (parent, el) {
        if (parent.nodeName.toLowerCase() === 'select' && el.nodeName.toLowerCase() === 'option') {
            try {
                parent.add(el, null);
            }
            catch (err) {
                parent.add(el); // IE
            }
        }
        else {
            parent.appendChild(el);
        }
    }

    /**
     * Attach event in a cross-browser fashion
     * @param {DOMElement} el DOM element to which to attach the event
     * @param {String} type The DOM event (without 'on') to attach to the element
     * @param {Function} handler The event handler to attach to the element
     * @param {Boolean} [capturing] Whether or not the event should be
     *                                                              capturing (W3C-browsers only); default is false; NOT IN USE
     */
    function _addEvent (el, type, handler, capturing) {
        if (el.addEventListener) { // W3C
            el.addEventListener(type, handler, !!capturing);
        }
        else if (el.attachEvent) { // IE
            el.attachEvent('on' + type, handler);
        }
        else { // OLDER BROWSERS (DOM0)
            el['on' + type] = handler;
        }
    }

    function _createSafeReference (type, prefix, arg) {
        // For security reasons related to innerHTML, we ensure this string only contains potential entity characters
        if (!arg.match(/^\w+$/)) {
            throw 'Bad ' + type;
        }
        var elContainer = document.createElement('div');
        elContainer.innerHTML = '&' + prefix + arg + ';';
        return document.createTextNode(elContainer.innerHTML);
    }

    function jml () {
        var i, arg, procValue, p, val, elContainer, textnode, k, elsl, j, cl, elem, nodes = [], elStr, atts, child = [], argc = arguments.length, argv = arguments, NS_HTML = 'http://www.w3.org/1999/xhtml',
            _getType = function (item) {
                if (typeof item === 'string') {
                    return 'string';
                }
                if (typeof item === 'object') {
                    if (item === null) {
                        return 'null';
                    }
                    if (Array.isArray(item)) {
                        return 'array';
                    }
                    if (item.nodeType === 1) {
                        return 'element';
                    }
                    return 'object';
                }
            };
        for (i = 0; i < argc; i++) {
            arg = argv[i];
            switch (_getType(arg)) {
                case 'null': // null always indicates a place-holder (only needed for last argument if want array returned)
                    if (i === argc - 1) {
                        return nodes.length <= 1 ? nodes[0] : nodes;
                    }
                    break;
                case 'string': // Strings always indicate elements
                    switch (arg) {
                        case '!':
                            nodes[nodes.length] = document.createComment(argv[++i]);
                            break;
                        case '?':
                            arg = argv[++i];
                            val = argv[++i];
                            if (typeof val === 'object') {
                                procValue = [];
                                for (p in val) {
                                    if (val.hasOwnProperty(p)) {
                                        procValue.push(p + '=' + '"' + val[p].replace(/"/g, '\\"') + '"');
                                    }
                                }
                                procValue = procValue.join(' ');
                            }
                            // Firefox allows instructions with ">" in this method, but not if placed directly!
                            nodes[nodes.length] = document.createProcessingInstruction(arg, procValue);
                            break;
                        // Browsers don't support document.createEntityReference, so we just use this as a convenience
                        case '&':
                            nodes[nodes.length] = _createSafeReference('entity', '', argv[++i]);
                            break;
                        case '#': // // Decimal character reference - '#', ['01234'] // Ӓ // probably easier to use JavaScript Unicode escapes
                            nodes[nodes.length] = _createSafeReference('decimal', arg, argv[++i]);
                            break;
                        case '#x': // Hex character reference - '#x', ['123a'] // ሺ // probably easier to use JavaScript Unicode escapes
                            nodes[nodes.length] = _createSafeReference('hex', arg, argv[++i]);
                            break;
                        case '![':
                            // '![', ['escaped <&> text'] // <![CDATA[escaped <&> text]]>
                            // CDATA valid in XML only, so we'll just treat as text for mutual compatibility
                            // Todo: config (or detection via some kind of document.documentType property?) of whether in XML
                            // nodes[nodes.length] = document.createCDATASection(argv[++i]);
                            nodes[nodes.length] = document.createTextNode(argv[++i]);
                            break;
                        default: // An element
                            elStr = arg;
                            if (document.createElementNS) {
                                elem = document.createElementNS(NS_HTML, elStr);
                            }
                            else {
                                elem = document.createElement(elStr);
                            }
                            nodes[nodes.length] = elem; // Add to parent
                            break;
                    }
                    break;
                case 'object': // Non-DOM-element objects always indicate attribute-value pairs
                    atts = arg;
                    for (p in atts) {
                        if (atts.hasOwnProperty(p)) {
                            switch(p) {
                                // Todo: add '$a' for array of ordered (prefix-)attribute-value arrays
                                // Todo: Allow "xmlns" to accept prefix-value array or array of prefix-value arrays
                                // Todo: {$: ['xhtml', 'div']} for prefixed elements
                                // Todo: {'#': ['text1', ['span', ['inner text']], 'text2']} for transclusion-friendly fragments
                                // Todo: Accept array for any attribute with first item as prefix and second as value
                                case '$event': /* Could alternatively allow specific event names like 'change' or 'onchange'; could also alternatively allow object inside instead of array*/
                                    _addEvent(elem, atts[p][0], atts[p][1], atts[p][2]); // element, event name, handler, capturing
                                    break;
                                case 'className': case 'class':
                                    elem.className = atts[p];
                                    break;
                                // Todo: Disable this by default unless configuration explicitly allows (for security)
                                case 'innerHTML':
                                    elem.innerHTML = atts[p];
                                    break;
                                case 'selected' : case 'checked': case 'value' : case 'text':
                                    elem[p] = atts[p];
                                    break;
                                // float not needed as for style.cssFloat (or style.styleFloat in IE)
                                case 'htmlFor': case 'for':
                                    if (elStr === 'label') {
                                        elem.htmlFor = atts[p];
                                        break;
                                    }
                                    elem.setAttribute(p, atts[p]);
                                    break;
                                default:
                                    // Todo: Allow key as plain "on" with map (like $event?)
                                    if (p.match(/^on/)) {
                                        _addEvent(elem, p.slice(2), atts[p], false);
                                        break;
                                    }
                                    elem.setAttribute(p, atts[p]);
                                    break;
                            }
                        }
                    }
                    break;
                case 'element':
                    /*
                    1) Last element always the parent (put null if don't want parent and want to return array) unless only atts and children (no other elements)
                    2) Individual elements (DOM elements or sequences of string[/object/array]) get added to parent first-in, first-added
                    */
                    if (i === argc - 1 || (i === argc - 2 && argv[i+1] === null)) { // parent
                        for (k = 0, elsl = nodes.length; k < elsl; k++) {
                            _appendNode(arg, nodes[k]);
                        }
                    }
                    else {
                        nodes[nodes.length] = arg;
                    }
                    break;
                case 'array': // Arrays or arrays of arrays indicate child nodes
                    child = arg;
                    for (j = 0, cl = child.length; j < cl; j++) { // Go through children array container to handle elements
                        if (typeof child[j] === 'string') {
                            elem.appendChild(document.createTextNode(child[j]));
                        }
                        else if (Array.isArray(child[j])) { // Arrays representing child elements
                            _appendNode(elem, jml.apply(null, child[j]));
                        }
                        else { // Single DOM element children
                            _appendNode(elem, child[j]);
                        }
                    }
                    break;
            }
        }
        return nodes[0];
    }

    // EXPORTS
    (typeof exports === 'undefined' ? window : exports).jml = jml;

}());
<commit_msg>Fix proc-inst.<commit_after>/*globals exports*/
(function () {
// Todo: Note to self: Integrate research from other jml notes
// Todo: Add tests
// Todo: Allow building of generic XML (pass configuration object)

/*
1) String element name (or array of 1-4)
2) Optional object with attributes
3) Optional array of text nodes and child elements
4) Optionally repeat for siblings
*/

/**
 * Creates an XHTML or HTML element (XHTML is preferred, but only in browsers that support);
 * Any element after element can be omitted, and any subsequent type or types added afterwards
 * @param {String} el The element to create (by lower-case name)
 * @param {Object} [atts] Attributes to add with the key as the attribute name and value as the
 *                                               attribute value; important for IE where the input element's type cannot
 *                                               be added later after already added to the page
 * @param {DOMElement[]} [children] The optional children of this element (but raw DOM elements
 *                                                                      required to be specified within arrays since
 *                                                                      could not otherwise be distinguished from siblings being added)
 * @param {DOMElement} [parent] The optional parent to which to attach the element (always the last
 *                                                                  unless followed by null, in which case it is the second-to-last)
 * @param {null} [returning] Can use null to indicate an array of elements should be returned
 * @returns {DOMElement} The newly created (and possibly already appended) element or array of elements
 */
/*
RULES
    1) Last element always the parent (put null if don't want but want to return) unless only atts and children (no other elements)
    2) Individual elements (DOM elements or sequences of string[/object/array]) get added to parent first-in, first-added
    3) Arrays or arrays of arrays always indicate children
    4) Strings always indicate elements
    5) Non-DOM-element objects always indicate attribute-value pairs
    6) null always indicates a place-holder (only needed in place of parent for last argument if want array returned)
    7) First item must be an element
    8) Always returns first created element, unless null as last argument, in which case, it returns an array of all added elements
*/
/*
// EXAMPLES
// 1)
var input = jml('input');
// 2)
var input = jml('input', {type:'password'});
// 3)
var div = jml('div', {'class': 'myClass'}, [
    ['p', ['Some inner text']],
    ['p', ['another child paragraph']]
]);
// 4)
var div = jml('div', [
    ['p', ['no attributes on the div']]
]);
// 5)
var simpleAttachToParent = jml('hr', document.body);
// 6)
var firstTr = jml('tr', [
        ['td', ['row 1 cell 1']],
        ['td', ['row 1 cell 2']]
    ],
    'tr', {className: 'anotherRowSibling'}, [
        ['td', ['row 2 cell 1']],
        ['td', ['row 2 cell 2']]
    ],
    table
);
// 7)
var trsArray = jml('tr', [
        ['td', ['row 1 cell 1']],
        ['td', ['row 1 cell 2']]
    ],
    'tr', {className: 'anotherRowSibling'}, [
        ['td', ['row 2 cell 1']],
        ['td', ['row 2 cell 2']]
    ],
    table,
    null
);
// 8)

var div = jml(
    'div', [
        $('DOMChildrenMustBeInArray')
    ],
    $('anotherElementToAddToParent'),
    $('yetAnotherSiblingToAddToParent'),
    parent
);
*/

    'use strict';

    /**
     * Need this function for IE since options weren't otherwise getting added
     * @private
     * @param {DOMElement} parent The parent to which to append the element
     * @param {DOMNode} el The element or other node to append to the parent
     */
    function _appendNode (parent, el) {
        if (parent.nodeName.toLowerCase() === 'select' && el.nodeName.toLowerCase() === 'option') {
            try {
                parent.add(el, null);
            }
            catch (err) {
                parent.add(el); // IE
            }
        }
        else {
            parent.appendChild(el);
        }
    }

    /**
     * Attach event in a cross-browser fashion
     * @param {DOMElement} el DOM element to which to attach the event
     * @param {String} type The DOM event (without 'on') to attach to the element
     * @param {Function} handler The event handler to attach to the element
     * @param {Boolean} [capturing] Whether or not the event should be
     *                                                              capturing (W3C-browsers only); default is false; NOT IN USE
     */
    function _addEvent (el, type, handler, capturing) {
        if (el.addEventListener) { // W3C
            el.addEventListener(type, handler, !!capturing);
        }
        else if (el.attachEvent) { // IE
            el.attachEvent('on' + type, handler);
        }
        else { // OLDER BROWSERS (DOM0)
            el['on' + type] = handler;
        }
    }

    function _createSafeReference (type, prefix, arg) {
        // For security reasons related to innerHTML, we ensure this string only contains potential entity characters
        if (!arg.match(/^\w+$/)) {
            throw 'Bad ' + type;
        }
        var elContainer = document.createElement('div');
        elContainer.innerHTML = '&' + prefix + arg + ';';
        return document.createTextNode(elContainer.innerHTML);
    }

    function jml () {
        var i, arg, procValue, p, val, elContainer, textnode, k, elsl, j, cl, elem, nodes = [], elStr, atts, child = [], argc = arguments.length, argv = arguments, NS_HTML = 'http://www.w3.org/1999/xhtml',
            _getType = function (item) {
                if (typeof item === 'string') {
                    return 'string';
                }
                if (typeof item === 'object') {
                    if (item === null) {
                        return 'null';
                    }
                    if (Array.isArray(item)) {
                        return 'array';
                    }
                    if (item.nodeType === 1) {
                        return 'element';
                    }
                    return 'object';
                }
            };
        for (i = 0; i < argc; i++) {
            arg = argv[i];
            switch (_getType(arg)) {
                case 'null': // null always indicates a place-holder (only needed for last argument if want array returned)
                    if (i === argc - 1) {
                        return nodes.length <= 1 ? nodes[0] : nodes;
                    }
                    break;
                case 'string': // Strings always indicate elements
                    switch (arg) {
                        case '!':
                            nodes[nodes.length] = document.createComment(argv[++i]);
                            break;
                        case '?':
                            arg = argv[++i];
                            procValue = val = argv[++i];
                            if (typeof val === 'object') {
                                procValue = [];
                                for (p in val) {
                                    if (val.hasOwnProperty(p)) {
                                        procValue.push(p + '=' + '"' + val[p].replace(/"/g, '\\"') + '"');
                                    }
                                }
                                procValue = procValue.join(' ');
                            }
                            // Firefox allows instructions with ">" in this method, but not if placed directly!
                            nodes[nodes.length] = document.createProcessingInstruction(arg, procValue);
                            break;
                        // Browsers don't support document.createEntityReference, so we just use this as a convenience
                        case '&':
                            nodes[nodes.length] = _createSafeReference('entity', '', argv[++i]);
                            break;
                        case '#': // // Decimal character reference - '#', ['01234'] // Ӓ // probably easier to use JavaScript Unicode escapes
                            nodes[nodes.length] = _createSafeReference('decimal', arg, argv[++i]);
                            break;
                        case '#x': // Hex character reference - '#x', ['123a'] // ሺ // probably easier to use JavaScript Unicode escapes
                            nodes[nodes.length] = _createSafeReference('hex', arg, argv[++i]);
                            break;
                        case '![':
                            // '![', ['escaped <&> text'] // <![CDATA[escaped <&> text]]>
                            // CDATA valid in XML only, so we'll just treat as text for mutual compatibility
                            // Todo: config (or detection via some kind of document.documentType property?) of whether in XML
                            // nodes[nodes.length] = document.createCDATASection(argv[++i]);
                            nodes[nodes.length] = document.createTextNode(argv[++i]);
                            break;
                        default: // An element
                            elStr = arg;
                            if (document.createElementNS) {
                                elem = document.createElementNS(NS_HTML, elStr);
                            }
                            else {
                                elem = document.createElement(elStr);
                            }
                            nodes[nodes.length] = elem; // Add to parent
                            break;
                    }
                    break;
                case 'object': // Non-DOM-element objects always indicate attribute-value pairs
                    atts = arg;
                    for (p in atts) {
                        if (atts.hasOwnProperty(p)) {
                            switch(p) {
                                // Todo: add '$a' for array of ordered (prefix-)attribute-value arrays
                                // Todo: Allow "xmlns" to accept prefix-value array or array of prefix-value arrays
                                // Todo: {$: ['xhtml', 'div']} for prefixed elements
                                // Todo: {'#': ['text1', ['span', ['inner text']], 'text2']} for transclusion-friendly fragments
                                // Todo: Accept array for any attribute with first item as prefix and second as value
                                case '$event': /* Could alternatively allow specific event names like 'change' or 'onchange'; could also alternatively allow object inside instead of array*/
                                    _addEvent(elem, atts[p][0], atts[p][1], atts[p][2]); // element, event name, handler, capturing
                                    break;
                                case 'className': case 'class':
                                    elem.className = atts[p];
                                    break;
                                // Todo: Disable this by default unless configuration explicitly allows (for security)
                                case 'innerHTML':
                                    elem.innerHTML = atts[p];
                                    break;
                                case 'selected' : case 'checked': case 'value' : case 'text':
                                    elem[p] = atts[p];
                                    break;
                                // float not needed as for style.cssFloat (or style.styleFloat in IE)
                                case 'htmlFor': case 'for':
                                    if (elStr === 'label') {
                                        elem.htmlFor = atts[p];
                                        break;
                                    }
                                    elem.setAttribute(p, atts[p]);
                                    break;
                                default:
                                    // Todo: Allow key as plain "on" with map (like $event?)
                                    if (p.match(/^on/)) {
                                        _addEvent(elem, p.slice(2), atts[p], false);
                                        break;
                                    }
                                    elem.setAttribute(p, atts[p]);
                                    break;
                            }
                        }
                    }
                    break;
                case 'element':
                    /*
                    1) Last element always the parent (put null if don't want parent and want to return array) unless only atts and children (no other elements)
                    2) Individual elements (DOM elements or sequences of string[/object/array]) get added to parent first-in, first-added
                    */
                    if (i === argc - 1 || (i === argc - 2 && argv[i+1] === null)) { // parent
                        for (k = 0, elsl = nodes.length; k < elsl; k++) {
                            _appendNode(arg, nodes[k]);
                        }
                    }
                    else {
                        nodes[nodes.length] = arg;
                    }
                    break;
                case 'array': // Arrays or arrays of arrays indicate child nodes
                    child = arg;
                    for (j = 0, cl = child.length; j < cl; j++) { // Go through children array container to handle elements
                        if (typeof child[j] === 'string') {
                            elem.appendChild(document.createTextNode(child[j]));
                        }
                        else if (Array.isArray(child[j])) { // Arrays representing child elements
                            _appendNode(elem, jml.apply(null, child[j]));
                        }
                        else { // Single DOM element children
                            _appendNode(elem, child[j]);
                        }
                    }
                    break;
            }
        }
        return nodes[0];
    }

    // EXPORTS
    (typeof exports === 'undefined' ? window : exports).jml = jml;

}());
<|endoftext|>


<commit_before>(function() {
  'use strict';

  angular.module('app.states')
    .run(appRun);

  /** @ngInject */
  function appRun(routerHelper) {
    routerHelper.configureStates(getStates());
  }

  function getStates() {
    return {
      'services.list': {
        url: '', // No url, this state is the index of projects
        templateUrl: 'app/states/services/list/list.html',
        controller: StateController,
        controllerAs: 'vm',
        title: N_('Service List'),
        resolve: {
          services: resolveServices,
        },
      },
    };
  }

  /** @ngInject */
  function resolveServices(CollectionsApi) {
    var options = {
      expand: 'resources',
      attributes: ['picture', 'picture.image_href', 'evm_owner.name', 'v_total_vms', 'chargeback_report'],
      filter: ['service_id=nil'],
    };

    return CollectionsApi.query('services', options);
  }

  /** @ngInject */
  function StateController($state, services, ServicesState, $filter, $rootScope, Language, ListView, Chargeback) {
    var vm = this;

    vm.services = [];

    if (angular.isDefined($rootScope.notifications) && $rootScope.notifications.data.length > 0) {
      $rootScope.notifications.data.splice(0, $rootScope.notifications.data.length);
    }

    angular.forEach(services.resources, function(item) {
      item.powerState = angular.isDefined(item.options.power_state) ? item.options.power_state : "";
    });

    angular.forEach(services.resources, function(item) {
      if (angular.isUndefined(item.service_id)) {
        vm.services.push(item);
      }
    });

    vm.services.forEach(Chargeback.processReports);
    Chargeback.adjustRelativeCost(vm.services);

    vm.servicesList = angular.copy(vm.services);

    vm.listConfig = {
      selectItems: false,
      showSelectBox: false,
      selectionMatchProp: 'service_status',
      onClick: handleClick,
    };

    var serviceFilterConfig = {
      fields: getServiceFilterFields(),
      resultsCount: vm.servicesList.length,
      appliedFilters: ServicesState.filterApplied ? ServicesState.getFilters() : [],
      onFilterChange: filterChange,
    };

    var serviceSortConfig = {
      fields: getServiceSortFields(),
      onSortChange: sortChange,
      isAscending: ServicesState.getSort().isAscending,
      currentField: ServicesState.getSort().currentField,
    };

    vm.toolbarConfig = {
      filterConfig: serviceFilterConfig,
      sortConfig: serviceSortConfig,
    };

    vm.actionButtons = [
      {
        name: __('Start'),
        title: __('Start this service'),
        actionFn: startService,
        isDisabled: false,
      },
    ];

    vm.menuActions = [
      {
        name: __('Stop'),
        title: __('Stop this service'),
        actionFn: stopService,
        isDisabled: false,
      },
      {
        name: __('Suspend'),
        title: __('Suspend this service'),
        actionFn: suspendService,
        isDisabled: false,
      },
    ];

    function getServiceFilterFields() {
      var retires = [__('Current'), __('Soon'), __('Retired')];
      var dollars = ['$', '$$', '$$$', '$$$$'];

      return [
        ListView.createFilterField('name', __('Name'), __('Filter by Name'), 'text'),
        ListView.createFilterField('retirement', __('Retirement Date'), __('Filter by Retirement Date'), 'select', retires),
        ListView.createFilterField('vms', __('Number of VMs'), __('Filter by VMs'), 'text'),
        ListView.createFilterField('owner', __('Owner'), __('Filter by Owner'), 'text'),
        ListView.createFilterField('owner', __('Created'), __('Filter by Created On'), 'text'),
        ListView.createFilterField('chargeback_relative_cost', __('Relative Cost'), __('Filter by Relative Cost'), 'select', dollars),
      ];
    }

    function getServiceSortFields() {
      return [
        ListView.createSortField('name', __('Name'), 'alpha'),
        ListView.createSortField('retires', __('Retirement Date'), 'numeric'),
        ListView.createSortField('vms', __('Number of VMs'), 'numeric'),
        ListView.createSortField('owner', __('Owner'), 'alpha'),
        ListView.createSortField('created', __('Created'), 'numeric'),
        ListView.createSortField('chargeback_relative_cost', __('Relative Cost'), 'alpha'),
      ];
    }

    if (ServicesState.filterApplied) {
      /* Apply the filtering to the data list */
      filterChange(ServicesState.getFilters());
      ServicesState.filterApplied = false;
    } else {
      vm.servicesList = ListView.applyFilters(ServicesState.getFilters(), vm.servicesList, vm.services, ServicesState, matchesFilter);

      /* Make sure sorting direction is maintained */
      sortChange(ServicesState.getSort().currentField, ServicesState.getSort().isAscending);
    }

    function startService(action, item) {
      console.log("startService");
    }

    function stopService(action, item) {
      console.log("stopService");
    }

    function suspendService(action, item) {
      console.log("suspendService");
    }

    function handleClick(item, e) {
      $state.go('services.details', {serviceId: item.id});
    }

    function sortChange(sortId, isAscending) {
      vm.servicesList.sort(compareFn);

      /* Keep track of the current sorting state */
      ServicesState.setSort(sortId, vm.toolbarConfig.sortConfig.isAscending);
    }

    function compareFn(item1, item2) {
      var compValue = 0;
      if (vm.toolbarConfig.sortConfig.currentField.id === 'name') {
        compValue = item1.name.localeCompare(item2.name);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'vms') {
        compValue = item1.v_total_vms - item2.v_total_vms;
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'owner') {
        if (angular.isUndefined(item1.evm_owner)
          && angular.isDefined(item2.evm_owner)) {
          compValue = 1;
        } else if (angular.isDefined(item1.evm_owner)
          && angular.isUndefined(item2.evm_owner)) {
          compValue = -1;
        } else if (angular.isUndefined(item1.evm_owner)
          && angular.isUndefined(item2.evm_owner)) {
          compValue = 0;
        } else {
          compValue = item1.evm_owner.name.localeCompare(item2.evm_owner.name);
        }
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'created') {
        compValue = new Date(item1.created_at) - new Date(item2.created_at);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'retires') {
        compValue = getRetirementDate(item1.retires_on) - getRetirementDate(item2.retires_on);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'chargeback_relative_cost') {
        compValue = item1.chargeback_relative_cost.length - item2.chargeback_relative_cost.length;
      }

      if (!vm.toolbarConfig.sortConfig.isAscending) {
        compValue = compValue * -1;
      }

      return compValue;
    }

    /* Date 10 years into the future */
    var neverRetires = new Date();
    neverRetires.setDate(neverRetires.getYear() + 10);

    function getRetirementDate(value) {
      if (angular.isDefined(value)) {
        return new Date(value);
      } else {
        return neverRetires;
      }
    }

    function filterChange(filters) {
      vm.servicesList = ListView.applyFilters(filters, vm.servicesList, vm.services, ServicesState, matchesFilter);

      /* Make sure sorting direction is maintained */
      sortChange(ServicesState.getSort().currentField, ServicesState.getSort().isAscending);

      vm.toolbarConfig.filterConfig.resultsCount = vm.servicesList.length;
    }

    function matchesFilter(item, filter) {
      if (filter.id === 'name') {
        return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'vms') {
        return String(item.v_total_vms).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'owner' && angular.isDefined(item.evm_owner)) {
        return item.evm_owner.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'retirement') {
        return checkRetirementDate(item, filter.value.toLowerCase());
      } else if (filter.id === 'created') {
        return $filter('date')(item.created_at).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'chargeback_relative_cost') {
        return item.chargeback_relative_cost === filter.value;
      }

      return false;
    }

    function checkRetirementDate(item, filterValue) {
      var currentDate = new Date();

      if (filterValue === 'retired' && angular.isDefined(item.retires_on)) {
        return angular.isDefined(item.retired) && item.retired === true;
      } else if (filterValue === 'current') {
        return angular.isUndefined(item.retired) || item.retired === false;
      } else if (filterValue === 'soon' && angular.isDefined(item.retires_on)) {
        return new Date(item.retires_on) >= currentDate
          && new Date(item.retires_on) <= currentDate.setDate(currentDate.getDate() + 30);
      }

      return false;
    }

    Language.fixState(ServicesState, vm.toolbarConfig);
  }
})();
<commit_msg>Add methods for start, stop and suspend<commit_after>(function() {
  'use strict';

  angular.module('app.states')
    .run(appRun);

  /** @ngInject */
  function appRun(routerHelper) {
    routerHelper.configureStates(getStates());
  }

  function getStates() {
    return {
      'services.list': {
        url: '', // No url, this state is the index of projects
        templateUrl: 'app/states/services/list/list.html',
        controller: StateController,
        controllerAs: 'vm',
        title: N_('Service List'),
        resolve: {
          services: resolveServices,
        },
      },
    };
  }

  /** @ngInject */
  function resolveServices(CollectionsApi) {
    var options = {
      expand: 'resources',
      attributes: ['picture', 'picture.image_href', 'evm_owner.name', 'v_total_vms', 'chargeback_report'],
      filter: ['service_id=nil'],
    };

    return CollectionsApi.query('services', options);
  }

  /** @ngInject */
<<<<<<< ff484ab23f7cdf6f72829c04136daf04d03e32be
  function StateController($state, services, ServicesState, $filter, $rootScope, Language, ListView, Chargeback) {
=======
  function StateController($state, services, ServicesState, $filter, $rootScope, Language, ListView, CollectionsApi, EventNotifications) {
>>>>>>> Add methods for start, stop and suspend
    var vm = this;

    vm.services = [];

    if (angular.isDefined($rootScope.notifications) && $rootScope.notifications.data.length > 0) {
      $rootScope.notifications.data.splice(0, $rootScope.notifications.data.length);
    }

    angular.forEach(services.resources, function(item) {
      item.powerState = angular.isDefined(item.options.power_state) ? item.options.power_state : "";
    });

    angular.forEach(services.resources, function(item) {
      if (angular.isUndefined(item.service_id)) {
        vm.services.push(item);
      }
    });

    vm.services.forEach(Chargeback.processReports);
    Chargeback.adjustRelativeCost(vm.services);

    vm.servicesList = angular.copy(vm.services);

    vm.listConfig = {
      selectItems: false,
      showSelectBox: false,
      selectionMatchProp: 'service_status',
      onClick: handleClick,
    };

    var serviceFilterConfig = {
      fields: getServiceFilterFields(),
      resultsCount: vm.servicesList.length,
      appliedFilters: ServicesState.filterApplied ? ServicesState.getFilters() : [],
      onFilterChange: filterChange,
    };

    var serviceSortConfig = {
      fields: getServiceSortFields(),
      onSortChange: sortChange,
      isAscending: ServicesState.getSort().isAscending,
      currentField: ServicesState.getSort().currentField,
    };

    vm.toolbarConfig = {
      filterConfig: serviceFilterConfig,
      sortConfig: serviceSortConfig,
    };

    vm.actionButtons = [
      {
        name: __('Start'),
        title: __('Start this service'),
        actionFn: startService,
        isDisabled: false,
      },
    ];

    vm.menuActions = [
      {
        name: __('Stop'),
        title: __('Stop this service'),
        actionFn: stopService,
        isDisabled: false,
      },
      {
        name: __('Suspend'),
        title: __('Suspend this service'),
        actionFn: suspendService,
        isDisabled: false,
      },
    ];

    function getServiceFilterFields() {
      var retires = [__('Current'), __('Soon'), __('Retired')];
      var dollars = ['$', '$$', '$$$', '$$$$'];

      return [
        ListView.createFilterField('name', __('Name'), __('Filter by Name'), 'text'),
        ListView.createFilterField('retirement', __('Retirement Date'), __('Filter by Retirement Date'), 'select', retires),
        ListView.createFilterField('vms', __('Number of VMs'), __('Filter by VMs'), 'text'),
        ListView.createFilterField('owner', __('Owner'), __('Filter by Owner'), 'text'),
        ListView.createFilterField('owner', __('Created'), __('Filter by Created On'), 'text'),
        ListView.createFilterField('chargeback_relative_cost', __('Relative Cost'), __('Filter by Relative Cost'), 'select', dollars),
      ];
    }

    function getServiceSortFields() {
      return [
        ListView.createSortField('name', __('Name'), 'alpha'),
        ListView.createSortField('retires', __('Retirement Date'), 'numeric'),
        ListView.createSortField('vms', __('Number of VMs'), 'numeric'),
        ListView.createSortField('owner', __('Owner'), 'alpha'),
        ListView.createSortField('created', __('Created'), 'numeric'),
        ListView.createSortField('chargeback_relative_cost', __('Relative Cost'), 'alpha'),
      ];
    }

    if (ServicesState.filterApplied) {
      /* Apply the filtering to the data list */
      filterChange(ServicesState.getFilters());
      ServicesState.filterApplied = false;
    } else {
      vm.servicesList = ListView.applyFilters(ServicesState.getFilters(), vm.servicesList, vm.services, ServicesState, matchesFilter);

      /* Make sure sorting direction is maintained */
      sortChange(ServicesState.getSort().currentField, ServicesState.getSort().isAscending);
    }

    function startService(action, item) {
      item.powerState = 'starting';
      CollectionsApi.post('services', item.id, {}, {action: 'start'}).then(startSuccess, startFailure);

      function startSuccess() {
        EventNotifications.success(item.name + __(' was started.'));
      }

      function startFailure() {
        EventNotifications.error(__('There was an error stopping this service.'));
      }
    }

    function stopService(action, item) {
      item.powerState = 'stopping';
      CollectionsApi.post('services', item.id, {}, {action: 'stop'}).then(stopSuccess, stopFailure);

      function stopSuccess() {
        EventNotifications.success(item.name + __(' was stopped.'));
      }

      function stopFailure() {
        EventNotifications.error(__('There was an error stopping this service.'));
      }
    }

    function suspendService(action, item) {
      item.powerState = 'suspending';
      CollectionsApi.post('services', item.id, {}, {action: 'suspend'}).then(suspendSuccess, suspendFailure);

      function suspendSuccess() {
        EventNotifications.success(item.name + __(' was suspended.'));
      }

      function suspendFailure() {
        EventNotifications.error(__('There was an error suspending this service.'));
      }
    }

    function handleClick(item, e) {
      $state.go('services.details', {serviceId: item.id});
    }

    function sortChange(sortId, isAscending) {
      vm.servicesList.sort(compareFn);

      /* Keep track of the current sorting state */
      ServicesState.setSort(sortId, vm.toolbarConfig.sortConfig.isAscending);
    }

    function compareFn(item1, item2) {
      var compValue = 0;
      if (vm.toolbarConfig.sortConfig.currentField.id === 'name') {
        compValue = item1.name.localeCompare(item2.name);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'vms') {
        compValue = item1.v_total_vms - item2.v_total_vms;
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'owner') {
        if (angular.isUndefined(item1.evm_owner)
          && angular.isDefined(item2.evm_owner)) {
          compValue = 1;
        } else if (angular.isDefined(item1.evm_owner)
          && angular.isUndefined(item2.evm_owner)) {
          compValue = -1;
        } else if (angular.isUndefined(item1.evm_owner)
          && angular.isUndefined(item2.evm_owner)) {
          compValue = 0;
        } else {
          compValue = item1.evm_owner.name.localeCompare(item2.evm_owner.name);
        }
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'created') {
        compValue = new Date(item1.created_at) - new Date(item2.created_at);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'retires') {
        compValue = getRetirementDate(item1.retires_on) - getRetirementDate(item2.retires_on);
      } else if (vm.toolbarConfig.sortConfig.currentField.id === 'chargeback_relative_cost') {
        compValue = item1.chargeback_relative_cost.length - item2.chargeback_relative_cost.length;
      }

      if (!vm.toolbarConfig.sortConfig.isAscending) {
        compValue = compValue * -1;
      }

      return compValue;
    }

    /* Date 10 years into the future */
    var neverRetires = new Date();
    neverRetires.setDate(neverRetires.getYear() + 10);

    function getRetirementDate(value) {
      if (angular.isDefined(value)) {
        return new Date(value);
      } else {
        return neverRetires;
      }
    }

    function filterChange(filters) {
      vm.servicesList = ListView.applyFilters(filters, vm.servicesList, vm.services, ServicesState, matchesFilter);

      /* Make sure sorting direction is maintained */
      sortChange(ServicesState.getSort().currentField, ServicesState.getSort().isAscending);

      vm.toolbarConfig.filterConfig.resultsCount = vm.servicesList.length;
    }

    function matchesFilter(item, filter) {
      if (filter.id === 'name') {
        return item.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'vms') {
        return String(item.v_total_vms).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'owner' && angular.isDefined(item.evm_owner)) {
        return item.evm_owner.name.toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'retirement') {
        return checkRetirementDate(item, filter.value.toLowerCase());
      } else if (filter.id === 'created') {
        return $filter('date')(item.created_at).toLowerCase().indexOf(filter.value.toLowerCase()) !== -1;
      } else if (filter.id === 'chargeback_relative_cost') {
        return item.chargeback_relative_cost === filter.value;
      }

      return false;
    }

    function checkRetirementDate(item, filterValue) {
      var currentDate = new Date();

      if (filterValue === 'retired' && angular.isDefined(item.retires_on)) {
        return angular.isDefined(item.retired) && item.retired === true;
      } else if (filterValue === 'current') {
        return angular.isUndefined(item.retired) || item.retired === false;
      } else if (filterValue === 'soon' && angular.isDefined(item.retires_on)) {
        return new Date(item.retires_on) >= currentDate
          && new Date(item.retires_on) <= currentDate.setDate(currentDate.getDate() + 30);
      }

      return false;
    }

    Language.fixState(ServicesState, vm.toolbarConfig);
  }
})();
<|endoftext|>