<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Because 'in' checks whether or not the key exists within the object and returns a boolean, we can see that using dot notation keys and values can be added to objects easily. keys and values can also be deleted using the 'delete' keyword (thus removing that key-value pair from being returned by 'in').<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>var mongoose = require('mongoose'),
    User = mongoose.model('User'),
    Account = mongoose.model('Account'),
    Assignment = mongoose.model('Assignment')

    exports.view = function(req, res) {

        var getUsername = function(users, usernames, cb) {
            if (users.length == 0) return cb(usernames)
            var user = users.pop()
            User
                .findOne({
                    "email": user
                })
                .exec(function(err, user) {
                    if (err) return null;
                    if (user) usernames.push(user.username)
                    getUsername(users, usernames, cb)
                })
        }

        if (!req.params.assignmentNumber)
            return next("no assignment number provided")

        Assignment
            .find({
                assignmentID: req.params.assignmentNumber,
                shared: true
            })
            .exec(function(err, assignmentResult) {
                if (err) return next(err)

                if (!assignmentResult) return next("could not find " +
                    "assignemnt " + req.params.assignmentNumber)

                var users = []
                for (i = 0; i < assignmentResult.length; i++)
                    users.push(assignmentResult[i].email)

                getUsername(users, [], function(usernames) {

                    return res.render('assignments/gallery', {
                        "user":req.user,
                        "title": "Assignment gallery",
                        "usernames": usernames
                    })
                })
            })
    }
<commit_msg>cleaned up some formatting<commit_after>var mongoose = require('mongoose'),
    User = mongoose.model('User'),
    Account = mongoose.model('Account'),
    Assignment = mongoose.model('Assignment')

exports.view = function(req, res) {

    var getUsername = function(users, usernames, cb) {
        if (users.length == 0) return cb(usernames)
        var user = users.pop()
        User
            .findOne({
                "email": user
            })
            .exec(function(err, user) {
                if (err) return null;
                if (user) usernames.push(user.username)
                getUsername(users, usernames, cb)
            })
    }

    if (!req.params.assignmentNumber)
        return next("no assignment number provided")

    Assignment
        .find({
            assignmentID: req.params.assignmentNumber,
            shared: true
        })
        .exec(function(err, assignmentResult) {
            if (err) return next(err)

            if (!assignmentResult) return next("could not find " +
                "assignemnt " + req.params.assignmentNumber)

            var users = []
            for (i = 0; i < assignmentResult.length; i++)
                users.push(assignmentResult[i].email)

            getUsername(users, [], function(usernames) {

                return res.render('assignments/gallery', {
                    "title": "Assignment gallery",
                    "user":req.user,
                    "usernames": usernames
                })
            })
        })
}
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>AboutObjects passes tests<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2014);
    expect(meglomaniac.calculateAge()).toBe(44);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe("red");

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe("This circle has a radius of: 10");
    expect(colouredCircle.describe()).toBe("This circle has a radius of: 5");
  });
});
<|endoftext|>


<commit_before>var parametros = arguments[0] || {},
    API = require('http_client'),
    buscar = Ti.UI.Android.createSearchView({hintText : 'Buscar'});

function procesarRespuesta(jsonArray) {
    var lugares = [];

    _.each(jsonArray, function(lugar) {
        lugares.push({
            data: lugar,
            nombre: {text: lugar.name},
            descripcion: {text: lugar.description},
            properties: {
                width: Ti.UI.FILL,
                height: Ti.UI.SIZE,
                backgroundColor: 'transparent',
                searchableText: lugar.name +' '+ lugar.description,
            }
        });
    });

    $.seccion.setItems(lugares);
    Alloy.Globals.Loader.hide();
}

function procesarError() {
    Alloy.Globals.crouton.alert('Algo salió mal, intenta nuevamente');
    Alloy.Globals.Loader.hide();
}

function cargarLugares() {
    Alloy.Globals.Loader.show('Cargando...');

    var xhr = API.GET({
        endpoint: '/places',
        onSuccess: procesarRespuesta,
        onError: procesarError
    });

    xhr.send();
}

function procesarLogout() {
    Ti.App.Properties.setBool('logueado', false);
    Ti.App.Properties.setString('access_token', null);
    Alloy.createController('login', {salir: true});

    Alloy.Globals.Loader.hide();
    $.lugares.close();
}

function eventoCerrarSesion() {
    Alloy.Globals.Loader.show('Cerrando sesión...');

    var xhr = API.POST({
        endpoint: '/logout',
        onSuccess: procesarLogout,
        onError: procesarError
    });

    xhr.send();
}

function eventoAbrirPerfil() {
    Alloy.createController('perfil');
}

function eventoActualizarLugares() {
    cargarLugares();
}

function crearMenu(e) {
    e.menu.add({
        title: 'Buscar lugar',
        icon: Ti.Android.R.drawable.ic_menu_search,
        actionView: buscar,
        showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM
    });

    e.menu.add({title: 'Actualizar'}).addEventListener('click', eventoActualizarLugares);
    e.menu.add({title: 'Mi Perfil'}).addEventListener('click', eventoAbrirPerfil);
    e.menu.add({title: 'Salir'}).addEventListener('click', eventoCerrarSesion);
}

function eventoOpen() {
    var abx = require('com.alcoapps.actionbarextras');

    abx.titleFont = 'SourceSansPro-Black.ttf';
    abx.titleColor = '#FFCEAF';

    $.lugares.activity.invalidateOptionsMenu();

    if (parametros.entrar && parametros.entrar === true) {
        Alloy.Globals.crouton.confirm('Bievenido/a');
    }
}

function eventoClick(e) {
    var item = e.section.getItemAt(e.itemIndex);
    Alloy.Globals.lugar = item.data;
    Alloy.createController('lugar', item.data);
}

function eventoBuscar() {
    $.lista.setSearchText(buscar.value);
}

$.lugares.activity.onCreateOptionsMenu = crearMenu;

buscar.addEventListener('change', eventoBuscar);
$.lugares.addEventListener('open', eventoOpen);
$.lista.addEventListener('itemclick', eventoClick);

$.lugares.open();

cargarLugares();
<commit_msg>Limpiando código<commit_after>var parametros = arguments[0] || {},
    API = require('http_client'),
    buscar = Ti.UI.Android.createSearchView({hintText : 'Buscar'});

function procesarRespuesta(jsonArray) {
    var lugares = [];

    _.each(jsonArray, function(lugar) {
        var item = {
            data: lugar,
            nombre: {text: lugar.name},
            descripcion: {text: lugar.description},
            properties: {
                width: Ti.UI.FILL,
                height: Ti.UI.SIZE,
                backgroundColor: 'transparent',
                searchableText: lugar.name +' '+ lugar.description,
            }
        };

        lugares.push(item);
    });

    $.seccion.setItems(lugares);
    Alloy.Globals.Loader.hide();
}

function procesarError() {
    Alloy.Globals.crouton.alert('Algo salió mal, intenta nuevamente');
    Alloy.Globals.Loader.hide();
}

function cargarLugares() {
    Alloy.Globals.Loader.show('Cargando...');

    var xhr = API.GET({
        endpoint: '/places',
        onSuccess: procesarRespuesta,
        onError: procesarError
    });

    xhr.send();
}

function procesarLogout() {
    Ti.App.Properties.setBool('logueado', false);
    Ti.App.Properties.setString('access_token', null);
    Alloy.createController('login', {salir: true});

    Alloy.Globals.Loader.hide();
    $.lugares.close();
}

function eventoCerrarSesion() {
    Alloy.Globals.Loader.show('Cerrando sesión...');

    var xhr = API.POST({
        endpoint: '/logout',
        onSuccess: procesarLogout,
        onError: procesarError
    });

    xhr.send();
}

function eventoAbrirPerfil() {
    Alloy.createController('perfil');
}

function eventoActualizarLugares() {
    cargarLugares();
}

function crearMenu(e) {
    e.menu.add({
        title: 'Buscar lugar',
        icon: Ti.Android.R.drawable.ic_menu_search,
        actionView: buscar,
        showAsAction: Ti.Android.SHOW_AS_ACTION_IF_ROOM
    });

    e.menu.add({title: 'Actualizar'}).addEventListener('click', eventoActualizarLugares);
    e.menu.add({title: 'Mi Perfil'}).addEventListener('click', eventoAbrirPerfil);
    e.menu.add({title: 'Salir'}).addEventListener('click', eventoCerrarSesion);
}

function eventoOpen() {
    var abx = require('com.alcoapps.actionbarextras');

    abx.titleFont = 'SourceSansPro-Black.ttf';
    abx.titleColor = '#FFCEAF';

    $.lugares.activity.invalidateOptionsMenu();

    if (parametros.entrar && parametros.entrar === true) {
        Alloy.Globals.crouton.confirm('Bievenido/a');
    }
}

function eventoClick(e) {
    var item = e.section.getItemAt(e.itemIndex);
    Alloy.Globals.lugar = item.data;
    Alloy.createController('lugar', item.data);
}

function eventoBuscar() {
    $.lista.setSearchText(buscar.value);
}

$.lugares.activity.onCreateOptionsMenu = crearMenu;

buscar.addEventListener('change', eventoBuscar);
$.lugares.addEventListener('open', eventoOpen);
$.lista.addEventListener('itemclick', eventoClick);

$.lugares.open();

cargarLugares();
<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Made test for properties as methods pass.<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>
/*!
 * Module dependencies.
 */

var _ = require('lodash');
var mongoose = require('mongoose');
var Session = mongoose.model('Notebook');
var multiparty = require('multiparty');
var knox = require('knox');
var randomstring = require('randomstring');
var path = require('path');
var easyimage = require('easyimage');
var async = require('async');

var s3Client = knox.createClient({
    secure: false,
    key: process.env.S3_KEY,
    secret: process.env.S3_SECRET,
    bucket: process.env.S3_BUCKET,
});

exports.index = function (req, res) {

    Session.find({}, null, {sort: {createdAt: -1}}, function(err, sessions) {

        res.render('session/index', {
            sessions: sessions
        });
    });
};

exports.feed = function (req, res, next) {

    var sessionId = req.params.sid;

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        res.render('session/feed', {
            session: session
        });
    });
};

exports.read = function (req, res, next) {

    var sessionId = req.params.sid;
    var vizId = req.params.vid;

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        var viz = _.find(session.visualizations, function (v) {
            return v.id === vizId;
        });

        res.render('session/visualization', {
            session: session,
            viz: viz
        });
    });
};

exports.create = function(req, res, next) {

    console.log('creating session');
    var session = new Session();
    session.save(function(err) {
        if(err) {
            return next(err);
        }
        return res.redirect('/sessions/' + session.id + '/feed/');
    });
};

exports.getNew = function(req, res, next) {

    console.log('creating session');
    var session = new Session();
    session.save(function(err) {
        if(err) {
            return next(err);
        }
        return res.redirect('/sessions/' + session.id + '/feed/');
    });
};

exports.addData = function (req, res, next) {
    var sessionId = req.params.sid;

    // var form = new multiparty.Form({
    //     autoFiles
    // });

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        if(req.is('json')) {

            console.log('finding session');
            if(err) {
                return next(err);
            }

            session.visualizations.push({data: req.body.data, type: req.body.type});
            var viz = session.visualizations[session.visualizations.length - 1];

            req.io.of('/sessions/' + sessionId)
                .emit('viz', viz);

            session.save(function(err) {
                if(err) {
                    return next(err);
                }

                return res.json(200);
            });

        } else {
            // console.log()
            var form = new multiparty.Form();
            form.parse(req, function(err, fields, files) {

                _.each(files, function(f) {
                    thumbnailAndUpload(f, sessionId, function(err, data) {

                        var imgData = data.imgData;
                        var s3Response = data.response;

                        console.log(imgData);
                        session.visualizations.push({images: [imgData], type: 'image'});
                        viz = session.visualizations[session.visualizations.length - 1];

                        req.io.of('/sessions/' + sessionId)
                            .emit('viz', viz);

                        session.save(function(err) {
                            if(err) {
                                return next(err);
                            }
                            res.statusCode = s3Response.statusCode;
                            s3Response.pipe(res);
                        });
                    });
                });

            });

        }
    });

};

exports.addImage = function (req, res, next) {

    var sessionId = req.params.sid;
    var vizId = req.params.vid;

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        var viz = _.find(session.visualizations, function (v) {
            return v.id === vizId;
        });

        if(!viz) {
            next(404);
        }

        var form = new multiparty.Form();

        form.parse(req, function(err, fields, files) {
            _.each(files, function(f) {
                thumbnailAndUpload(f, sessionId, function(err, data) {

                    var imgData = data.imgData;
                    var s3Response = data.response;

                    viz.images.push(imgData);

                    req.io.of('/sessions/' + sessionId)
                        .emit('update', {
                            vizId: viz._id,
                            data: imgData
                        });

                    session.save(function(err) {
                        if(err) {
                            return next(err);
                        }
                        res.statusCode = s3Response.statusCode;
                        s3Response.pipe(res);
                    });
                });
            });
        });
    });
};

var thumbnailAndUpload = function(f, sessionId, callback) {

    var maxWidth = 500;
    var maxHeight = 500;

    // Image file info
    var imgPath = f[0].path;
    var extension = path.extname(imgPath).toLowerCase();
    var filenameWithoutExtension = path.basename(imgPath, extension);
    var thumbnailPath = path.dirname(imgPath) + filenameWithoutExtension + '_thumbnail' + extension;

    // Upload paths for s3
    var uploadName = randomstring.generate();
    var destPath = '/sessions/' + sessionId + '/';
    var originalS3Path = destPath + uploadName;
    var thumbnailS3Path = destPath + uploadName + '_small';

    // s3 headers
    var headers = {
      'x-amz-acl': 'public-read',
    };
    if( extension === '.jpg' || extension === '.jpeg' ) {
        headers['Content-Type'] = 'image/jpeg';
    } else if (extension === '.png') {
        headers['Content-Type'] = 'image/png';
    }

    easyimage
        .info(imgPath)
        .then(function(file) {
            var thumbWidth;
            var thumbHeight;

            console.log('outputing to: ' + thumbnailPath);

            if(file.width > file.height) {
                thumbWidth = Math.min(maxWidth, file.width);
                thumbHeight = file.height * (thumbWidth / file.width);
            } else {
                thumbHeight = Math.min(maxHeight, file.height);
                thumbWidth = file.width * (thumbHeight / file.height);
            }

            return easyimage.resize({
                src: imgPath,
                dst: thumbnailPath,
                width: thumbWidth,
                height: thumbHeight
            });
        }).then(function() {
            async.parallel([
                function(callback) {
                    console.log(imgPath + ':' + originalS3Path);
                    s3Client.putFile(imgPath, originalS3Path, headers, callback);
                },
                function(callback) {
                    console.log(thumbnailPath + ':' + thumbnailS3Path);
                    s3Client.putFile(thumbnailPath, thumbnailS3Path, headers, callback);
                }
            ], function(err, results) {
                var s3Response = results[0];

                var imgURL = 'https://s3.amazonaws.com/' + process.env.S3_BUCKET + originalS3Path;
                var thumbURL = 'https://s3.amazonaws.com/' + process.env.S3_BUCKET + thumbnailS3Path;

                var imgData = {
                    original: imgURL,
                    thumbnail: thumbURL
                };

                callback(null, {
                    response: s3Response,
                    imgData: imgData
                });

            });
        }, function(err) {
            callback(err);
        });
};<commit_msg>more error output<commit_after>
/*!
 * Module dependencies.
 */

var _ = require('lodash');
var mongoose = require('mongoose');
var Session = mongoose.model('Notebook');
var multiparty = require('multiparty');
var knox = require('knox');
var randomstring = require('randomstring');
var path = require('path');
var easyimage = require('easyimage');
var async = require('async');

var s3Client = knox.createClient({
    secure: false,
    key: process.env.S3_KEY,
    secret: process.env.S3_SECRET,
    bucket: process.env.S3_BUCKET,
});

exports.index = function (req, res) {

    Session.find({}, null, {sort: {createdAt: -1}}, function(err, sessions) {

        res.render('session/index', {
            sessions: sessions
        });
    });
};

exports.feed = function (req, res, next) {

    var sessionId = req.params.sid;

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        res.render('session/feed', {
            session: session
        });
    });
};

exports.read = function (req, res, next) {

    var sessionId = req.params.sid;
    var vizId = req.params.vid;

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        var viz = _.find(session.visualizations, function (v) {
            return v.id === vizId;
        });

        res.render('session/visualization', {
            session: session,
            viz: viz
        });
    });
};

exports.create = function(req, res, next) {

    console.log('creating session');
    var session = new Session();
    session.save(function(err) {
        if(err) {
            return next(err);
        }
        return res.redirect('/sessions/' + session.id + '/feed/');
    });
};

exports.getNew = function(req, res, next) {

    console.log('creating session');
    var session = new Session();
    session.save(function(err) {
        if(err) {
            return next(err);
        }
        return res.redirect('/sessions/' + session.id + '/feed/');
    });
};

exports.addData = function (req, res, next) {
    var sessionId = req.params.sid;

    // var form = new multiparty.Form({
    //     autoFiles
    // });

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        if(req.is('json')) {

            console.log('finding session');
            if(err) {
                return next(err);
            }

            session.visualizations.push({data: req.body.data, type: req.body.type});
            var viz = session.visualizations[session.visualizations.length - 1];

            req.io.of('/sessions/' + sessionId)
                .emit('viz', viz);

            session.save(function(err) {
                if(err) {
                    return next(err);
                }

                return res.json(200);
            });

        } else {
            // console.log()
            var form = new multiparty.Form();
            form.parse(req, function(err, fields, files) {

                _.each(files, function(f) {
                    thumbnailAndUpload(f, sessionId, function(err, data) {

                        var imgData = data.imgData;
                        var s3Response = data.response;

                        console.log(imgData);
                        session.visualizations.push({images: [imgData], type: 'image'});
                        viz = session.visualizations[session.visualizations.length - 1];

                        req.io.of('/sessions/' + sessionId)
                            .emit('viz', viz);

                        session.save(function(err) {
                            if(err) {
                                return next(err);
                            }
                            res.statusCode = s3Response.statusCode;
                            s3Response.pipe(res);
                        });
                    });
                });

            });

        }
    });

};

exports.addImage = function (req, res, next) {

    var sessionId = req.params.sid;
    var vizId = req.params.vid;

    Session.findById(sessionId, function(err, session) {
        if(err) {
            return next(err);
        }

        var viz = _.find(session.visualizations, function (v) {
            return v.id === vizId;
        });

        if(!viz) {
            next(404);
        }

        var form = new multiparty.Form();

        form.parse(req, function(err, fields, files) {
            _.each(files, function(f) {
                thumbnailAndUpload(f, sessionId, function(err, data) {

                    var imgData = data.imgData;
                    var s3Response = data.response;

                    viz.images.push(imgData);

                    req.io.of('/sessions/' + sessionId)
                        .emit('update', {
                            vizId: viz._id,
                            data: imgData
                        });

                    session.save(function(err) {
                        if(err) {
                            return next(err);
                        }
                        res.statusCode = s3Response.statusCode;
                        s3Response.pipe(res);
                    });
                });
            });
        });
    });
};

var thumbnailAndUpload = function(f, sessionId, callback) {

    var maxWidth = 500;
    var maxHeight = 500;

    // Image file info
    var imgPath = f[0].path;
    var extension = path.extname(imgPath).toLowerCase();
    var filenameWithoutExtension = path.basename(imgPath, extension);
    var thumbnailPath = path.dirname(imgPath) + filenameWithoutExtension + '_thumbnail' + extension;

    // Upload paths for s3
    var uploadName = randomstring.generate();
    var destPath = '/sessions/' + sessionId + '/';
    var originalS3Path = destPath + uploadName;
    var thumbnailS3Path = destPath + uploadName + '_small';

    // s3 headers
    var headers = {
      'x-amz-acl': 'public-read',
    };
    if( extension === '.jpg' || extension === '.jpeg' ) {
        headers['Content-Type'] = 'image/jpeg';
    } else if (extension === '.png') {
        headers['Content-Type'] = 'image/png';
    }

    easyimage
        .info(imgPath)
        .then(function(file) {
            var thumbWidth;
            var thumbHeight;

            console.log('outputing to: ' + thumbnailPath);

            if(file.width > file.height) {
                thumbWidth = Math.min(maxWidth, file.width);
                thumbHeight = file.height * (thumbWidth / file.width);
            } else {
                thumbHeight = Math.min(maxHeight, file.height);
                thumbWidth = file.width * (thumbHeight / file.height);
            }

            return easyimage.resize({
                src: imgPath,
                dst: thumbnailPath,
                width: thumbWidth,
                height: thumbHeight
            });
        }).then(function() {
            async.parallel([
                function(callback) {
                    console.log(imgPath + ':' + originalS3Path);
                    s3Client.putFile(imgPath, originalS3Path, headers, callback);
                },
                function(callback) {
                    console.log(thumbnailPath + ':' + thumbnailS3Path);
                    s3Client.putFile(thumbnailPath, thumbnailS3Path, headers, callback);
                }
            ], function(err, results) {
                var s3Response = results[0];

                var imgURL = 'https://s3.amazonaws.com/' + process.env.S3_BUCKET + originalS3Path;
                var thumbURL = 'https://s3.amazonaws.com/' + process.env.S3_BUCKET + thumbnailS3Path;

                var imgData = {
                    original: imgURL,
                    thumbnail: thumbURL
                };

                callback(null, {
                    response: s3Response,
                    imgData: imgData
                });

            });
        }, function(err) {
            console.log(err);
            callback(err);
        });
};<|endoftext|>


<commit_before>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Update AboutObjects.js<commit_after>describe("About Objects", function () {

  describe("Properties", function () {
    var meglomaniac;

    beforeEach(function () {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function () {
      expect(meglomaniac.mastermind).toBe("Joker");
    });

    it("should confirm that properties are case sensitive", function () {
      expect(meglomaniac.henchwoman).toBe("Harley");
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function () {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function (noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect("They are Pinky and the Brain Brain Brain Brain Brain").toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date()
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function () {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function () {
    var meglomaniac;
    beforeEach(function () {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function () {

      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function () {

      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function () {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function () {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function () {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<|endoftext|>


<commit_before>describe("About Objects", function() {

  describe("Properties", function() {
    var meglomaniac;

    beforeEach(function() {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function() {
      expect(meglomaniac.mastermind).toBe(FILL_ME_IN);
    });

    it("should confirm that properties are case sensitive", function() {
      expect(meglomaniac.henchwoman).toBe(FILL_ME_IN);
      expect(meglomaniac.henchWoman).toBe(FILL_ME_IN);
    });
  });

  it("should know properties that are functions act like methods", function() {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function(noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect(FILL_ME_IN).toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function() {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(FILL_ME_IN);
    expect(meglomaniac.calculateAge()).toBe(FILL_ME_IN);
  });

  describe("'in' keyword", function() {
    var meglomaniac;
    beforeEach(function() {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function() {
      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(FILL_ME_IN);
    });

    it("should not have the detonator however", function() {
      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(FILL_ME_IN);
    });
  });

  it("should know that properties can be added and deleted", function() {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(FILL_ME_IN);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(FILL_ME_IN);
  });

  it("should use prototype to add to all objects", function() {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(FILL_ME_IN);
    expect(colouredCircle.colour).toBe(FILL_ME_IN);

    Circle.prototype.describe = function() {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe(FILL_ME_IN);
    expect(colouredCircle.describe()).toBe(FILL_ME_IN);
  });
});
<commit_msg>Fixed all unit tests.<commit_after>describe("About Objects", function() {

  describe("Properties", function() {
    var meglomaniac;

    beforeEach(function() {
       meglomaniac = {  mastermind: "Joker", henchwoman: "Harley" };
    });

    it("should confirm objects are collections of properties", function() {
      expect(meglomaniac.mastermind).toBe('Joker');
    });

    it("should confirm that properties are case sensitive", function() {
      expect(meglomaniac.henchwoman).toBe('Harley');
      expect(meglomaniac.henchWoman).toBe(undefined);
    });
  });

  it("should know properties that are functions act like methods", function() {
    var meglomaniac = {
      mastermind : "Brain",
      henchman: "Pinky",
      battleCry: function(noOfBrains) {
        return "They are " + this.henchman + " and the" +
          Array(noOfBrains + 1).join(" " + this.mastermind);
      }
    };

    var battleCry = meglomaniac.battleCry(4);
    expect('They are Pinky and the Brain Brain Brain Brain Brain').toMatch(battleCry);
  });

  it("should confirm that when a function is attached to an object, 'this' refers to the object", function () {
    var currentDate = new Date();
    var currentYear = (currentDate.getFullYear());
    var meglomaniac = {
      mastermind: "James Wood",
      henchman: "Adam West",
      birthYear: 1970,
      calculateAge: function() {
        return currentYear - this.birthYear;
      }
    };

    expect(currentYear).toBe(2015);
    expect(meglomaniac.calculateAge()).toBe(45);
  });

  describe("'in' keyword", function() {
    var meglomaniac;
    beforeEach(function() {
      meglomaniac = {
        mastermind: "The Monarch",
        henchwoman: "Dr Girlfriend",
        theBomb: true
      };
    });

    it("should have the bomb", function() {
      var hasBomb = "theBomb" in meglomaniac;

      expect(hasBomb).toBe(true);
    });

    it("should not have the detonator however", function() {
      var hasDetonator = "theDetonator" in meglomaniac;

      expect(hasDetonator).toBe(false);
    });
  });

  it("should know that properties can be added and deleted", function() {
    var meglomaniac = { mastermind : "Agent Smith", henchman: "Agent Smith" };

    expect("secretary" in meglomaniac).toBe(false);

    meglomaniac.secretary = "Agent Smith";
    expect("secretary" in meglomaniac).toBe(true);

    delete meglomaniac.henchman;
    expect("henchman" in meglomaniac).toBe(false);
  });

  it("should use prototype to add to all objects", function() {
    function Circle(radius)
    {
      this.radius = radius;
    }

    var simpleCircle = new Circle(10);
    var colouredCircle = new Circle(5);
    colouredCircle.colour = "red";

    expect(simpleCircle.colour).toBe(undefined);
    expect(colouredCircle.colour).toBe('red');

    Circle.prototype.describe = function() {
      return "This circle has a radius of: " + this.radius;
    };

    expect(simpleCircle.describe()).toBe('This circle has a radius of: 10');
    expect(colouredCircle.describe()).toBe('This circle has a radius of: 5');
  });
});
<|endoftext|>


<commit_before>var express = require('express'),
    router = express.Router(),
    config = require('../../config/config'),
    db = require('../models'),
    fb = require('../helpers/facebookGraphAPI'),
    bodyParser = require('body-parser'),
    request = require('request');

module.exports = function (app) {
  app.use('/', router);
};

// Facebook verification
router.get('/webhook/', function (req, res) {
  if (req.query['hub.verify_token'] === config.verify_token) {
    res.send(req.query['hub.challenge']);
  }
  res.send('Error, wrong token');
});

router.post('/webhook/', function (req, res) {
  messaging_events = req.body.entry[0].messaging;

  for (i = 0; i < messaging_events.length; i++) {
    event = req.body.entry[0].messaging[i];
    sender = event.sender.id;

    // Handle opt-in via the Send-to-Messenger Plugin, store user data and greet the user by name
    if (event.optin) {
      userNamePromise = fb.getUserName(sender);

      userNamePromise.then(function(userName) {
        fb.sendTextMessage(sender, "Hi there, " + userName.first_name + "! I'm Thomas. Type 'Start' to begin a conversation or 'Help' for tips on how I can talk to you.");
      });
    }

    // Handle receipt of a message
    if (event.message && event.message.text) {
      text = event.message.text;

      // Handle special keywords
      if (text === 'Start') {
        fb.sendQuickReply(sender);
        continue;

      } else if (text === 'Help') {
        fb.sendTextMessage(sender, "List of commands:\n1. Start - Begin help questions\n");
        continue;

      // } else if (text === 'Generic') {
      //   fb.sendGenericMessage(sender);
      //   continue;

        } else if (text === 'IT') {
        fb.sendITReply(sender);
        continue;

      } else {
        // Failsafe + reminder for anything else
        fb.sendTextMessage(sender, "I'm sorry, I don't understand that input.\nRemember to type 'Help' for a list of commands.");
        continue;
      }
    }

    // Handle receipt of a postback
    if (event.postback) {
      text = JSON.stringify(event.postback);
      fb.sendTextMessage(sender, "Postback received: "+text.substring(0, 200));
      continue;
    }

  }
  res.sendStatus(200);

});
<commit_msg>clean up webhook.js to switch statements<commit_after>var express = require('express'),
    router = express.Router(),
    config = require('../../config/config'),
    db = require('../models'),
    fb = require('../helpers/facebookGraphAPI'),
    bodyParser = require('body-parser'),
    request = require('request');

module.exports = function (app) {
  app.use('/', router);
};

// Facebook verification
router.get('/webhook/', function (req, res) {
  if (req.query['hub.verify_token'] === config.verify_token) {
    res.send(req.query['hub.challenge']);
  }
  res.send('Error, wrong token');
});

router.post('/webhook/', function (req, res) {
  messaging_events = req.body.entry[0].messaging;

  for (i = 0; i < messaging_events.length; i++) {
    event = req.body.entry[0].messaging[i];
    sender = event.sender.id;

    // Handle opt-in via the Send-to-Messenger Plugin, store user data and greet the user by name
    if (event.optin) {
      userNamePromise = fb.getUserName(sender);

      userNamePromise.then(function(userName) {
        fb.sendTextMessage(sender, "Hi there, " + userName.first_name + "! I'm Thomas. Type 'Start' to begin a conversation or 'Help' for tips on how I can talk to you.");
      });
    }

    // Handle receipt of a message
    if (event.message && event.message.text) {
      text = event.message.text;

      switch(text) {

        case 'Start':
          fb.sendQuickReply(sender);
          continue;

        case 'Help':
          fb.sendTextMessage(sender, "List of commands:\n1. Start - Begin help questions\n");
          continue;

        default:
          fb.sendTextMessage(sender, "I'm sorry, I don't understand that input.\nRemember to type 'Help' for a list of commands.");
          continue;
        }

      // // Handle special keywords
      // if (text === 'Start') {
      //   fb.sendQuickReply(sender);
      //   continue;

      // } else if (text === 'Help') {
      //   fb.sendTextMessage(sender, "List of commands:\n1. Start - Begin help questions\n");
      //   continue;

      // // } else if (text === 'Generic') {
      // //   fb.sendGenericMessage(sender);
      // //   continue;

      // } else if (text === 'IT') {
      //   fb.sendITReply(sender);
      //   continue;

      // } else {
      //   // Failsafe + reminder for anything else
      //   fb.sendTextMessage(sender, "I'm sorry, I don't understand that input.\nRemember to type 'Help' for a list of commands.");
      //   continue;
      // }
    }

    // Handle receipt of a postback
    if (event.postback) {
      text = JSON.stringify(event.postback);
      fb.sendTextMessage(sender, "Postback received: "+text.substring(0, 200));
      continue;
    }

  }
  res.sendStatus(200);

});
<|endoftext|>


<commit_before>var axios = require('axios');

var url = require('url');
var yaml = require('yamljs');
var pg = require('pg');
var fs = require('fs');

//get modules
var USGS_CONSTANT = require("./lib/usgs_api/usgs_constants.js");
var USGS_FUNCTION = require("./lib/usgs_api/usgs_functions.js");
var USGS_HELPER = require("./lib/usgs_api/usgs_helpers.js");
var PG_HANDLER = require('./lib/postgres/postgres_handlers.js')

var apphelpers = require('./lib/helpers/app_helpers.js')
var APP_HELPERS = apphelpers();

var emailer = require('./lib/email/send_error_email.js');
var error_email = emailer()

var download_counter = require('./download_counter.js');
var DownloadCounter = download_counter();

var download_scenes = require('./lib/helpers/DownloadScenes.js');
var DownloadScenes = download_scenes();

//call delete old files
APP_HELPERS.delete_old_files('download_landsat_data', 'logs/', '.log');
APP_HELPERS.delete_old_files('order_failed', '', '.txt');
APP_HELPERS.delete_old_files('download_failed', '', '.txt');
APP_HELPERS.delete_old_files('downloaded', '', '.txt');
APP_HELPERS.delete_old_files('ordered', '', '.txt');

APP_HELPERS.set_logfile('download_landsat_data')

const LOG_LEVEL_ERR = 'error';
const LOG_LEVEL_INFO = 'info';

//config data
const CONFIG_YAML = yaml.load("./lib/usgs_api/config.yaml");

var scene_downloads = [];
var orders = [];

APP_HELPERS.set_logger_level('debug');

APP_HELPERS.write_message(LOG_LEVEL_INFO, 'download data start', '');

//set base URL for axios
axios.defaults.baseURL = USGS_CONSTANT.USGS_URL;

//get config data
const PG_CONNECT = yaml.load("./lib/postgres/config.yaml");

const pg_client = PG_HANDLER.pg_connect(PG_CONNECT)

const scene_arg = process.argv[2]

const last_day_scenes_fields = ' scene_id, sensor, acquisition_date, browse_url, path, row, cc_full, cc_quad_ul, cc_quad_ur, cc_quad_ll, cc_quad_lr, data_type_l1 ';

const list_yesterdays_failed = APP_HELPERS.get_yesterdays_failures();

var yesterdays_failed_scenes = ''

if (list_yesterdays_failed.length > 0){
  yesterdays_failed_scenes =  'SELECT' +
                              last_day_scenes_fields +
                            ' FROM landsat_metadata ' +
                            ' WHERE scene_id in ' + list_yesterdays_failed;
} else {
  yesterdays_failed_scenes = ''
}

const last_day_scenes = " SELECT " +
                          last_day_scenes_fields +
                        " FROM landsat_metadata  WHERE scene_id in ('LE70220342003237EDC01')"

//"SELECT " + last_day_scenes_fields + " FROM vw_last_days_scenes"

                        // ,'LT50300402003237PAC02','LT50300392003237PAC02')
// ,'LE70330382016238EDC00','LE70170382016238EDC00'

//acquisition_date =  '2003-08-25'::date AND

// "SELECT " + last_day_scenes_fields + " FROM vw_last_days_scenes";

var scenes_for_dowloading_SQL = yesterdays_failed_scenes +
                      " UNION " +
                      last_day_scenes;

//check if there is an argument of a scene if so use that.
if( scene_arg ){
  scenes_for_dowloading_SQL = "SELECT " + last_day_scenes_fields + " FROM landsat_metadata  WHERE scene_id = '" + scene_arg + "'";
}

// //captures lastpromise first one is resolved
var lastPromise = Promise.resolve();

const query = pg_client.query(scenes_for_dowloading_SQL);

//login and get promise for api key
var api_key_main = USGS_HELPER.get_api_key();

// query to check for duplicate scenes
query.on('row', function(row, result) {

    // process rows here
      api_key_main
      .then( (apiKey) => {

        //get constant for node "EE"
        const node = USGS_CONSTANT.NODE_EE;
        const entityIds = [];
        const products =  ["STANDARD"];
        const scene_id = row.scene_id;
        const acquisition_date = row.acquisition_date;

        //derieve dataset name from the scene_id and acquisition_date
        const datasetName = USGS_HELPER.get_datasetName(scene_id, acquisition_date);

        //add scene_id to entityIds array only one here,  api requires the scene_id(s) as an array
        entityIds.push(scene_id);

        //see if scene needs to be downloaded or ordered by finding out about availablelty
        const request_body = USGS_FUNCTION.usgsapi_downloadoptions(apiKey, node, datasetName, entityIds);

        const USGS_REQUEST_CODE = USGS_HELPER.get_usgs_response_code('downloadoptions');

        //make call to USGS api.  Make sure last promise is resolved first
        //  becuase USGS api is throttled for one request at a time
        //  wrap this in a resolve promoise so the there all requests are in promise and each one has
        //  to be resolved befire the next promise is started.  This is due to only limitations of the USGS API- only allows one
        //  api call at at time,
        return lastPromise = lastPromise.then( () => {
          //yes USGS throttles downloads so lets wait a few seconds before next request;

            //actual request after the last promise has been resolved
            return USGS_HELPER.get_usgsapi_response(USGS_REQUEST_CODE, request_body)
              .then( downloads => {

                // nothing to return so write out failed????
                if(!downloads[0]){
                  DownloadScenes.add_failed('not able to download scene', scene_id);
                }

                //get the orders option for the standard
                const standard_option_order = downloads[0].downloadOptions.filter( options => {
                  return options.downloadCode === "STANDARD" && !options.available
                })

                //get the download option for the standard
                const standard_option_dowload = downloads[0].downloadOptions.filter( options => {
                  return options.downloadCode === "STANDARD" && options.available
                })

                const entityId = downloads[0].entityId;
                const entityIds = [entityId]

                //create array to hold the request json for all orders
                if(standard_option_order.length > 0){
                  const orders_obj = {apiKey,node,datasetName,entityIds};
                  orders.push(orders_obj);
                  DownloadScenes.add_order(orders_obj)
                }

                //create array to hold the request json for all downloads
                if(standard_option_dowload.length > 0){
                  const download_obj = {apiKey,node,datasetName,products,entityIds};
                  scene_downloads.push(download_obj);
                  DownloadScenes.add_download(download_obj)
                }

                var msg_header = 'Total';
                var msg = DownloadScenes.get_total_count();
                APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

                msg_header = 'Current';
                msg = DownloadScenes.get_current_count();
                APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

                msg_header = 'Complete';
                msg = DownloadScenes.iscomplete();
                APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

                //once we have completed adding all the scenes to either ordering or downloading
                //  start the process to actually order and download products
                //  again we have to start after completion because we are limited to one API call at time.
                if( DownloadScenes.iscomplete() ) {
                  DownloadScenes.start_order()
                }

            }).catch( (error) => {

              // failed_downloads.push({scene_id});
              // console.log('dowload options api: ' + error.message);
              msg_header = 'download failed for scene';
              msg = DownloadScenes.iscomplete();

              DownloadScenes.add_failed(msg_header, scene_id);
              APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

            });

        }).catch( (error) => {
          msg_header = 'last promise error';
          msg = error.message;
          APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

        });

      }).catch( (error) => {
        msg_header = 'api';
        msg = error.message;
        APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

        });

    // wait for order to complete every n seconds via usgs api?  this may take tooo long no I have one in process for a few days.
    //it seems that currently all scenes are in progesss.

  });

query.on('error', function(err) {
    msg_header = 'query error';
    msg = err.message;
    APP_HELPERS.write_message(LOG_LEVEL_ERR, msg_header, msg);
  });

query.on('end', function(result) {
    DownloadScenes.set_total(result.rowCount);
  });
<commit_msg>worked so added back download all<commit_after>var axios = require('axios');

var url = require('url');
var yaml = require('yamljs');
var pg = require('pg');
var fs = require('fs');

//get modules
var USGS_CONSTANT = require("./lib/usgs_api/usgs_constants.js");
var USGS_FUNCTION = require("./lib/usgs_api/usgs_functions.js");
var USGS_HELPER = require("./lib/usgs_api/usgs_helpers.js");
var PG_HANDLER = require('./lib/postgres/postgres_handlers.js')

var apphelpers = require('./lib/helpers/app_helpers.js')
var APP_HELPERS = apphelpers();

var emailer = require('./lib/email/send_error_email.js');
var error_email = emailer()

var download_counter = require('./download_counter.js');
var DownloadCounter = download_counter();

var download_scenes = require('./lib/helpers/DownloadScenes.js');
var DownloadScenes = download_scenes();

//call delete old files
APP_HELPERS.delete_old_files('download_landsat_data', 'logs/', '.log');
APP_HELPERS.delete_old_files('order_failed', '', '.txt');
APP_HELPERS.delete_old_files('download_failed', '', '.txt');
APP_HELPERS.delete_old_files('downloaded', '', '.txt');
APP_HELPERS.delete_old_files('ordered', '', '.txt');

APP_HELPERS.set_logfile('download_landsat_data')

const LOG_LEVEL_ERR = 'error';
const LOG_LEVEL_INFO = 'info';

//config data
const CONFIG_YAML = yaml.load("./lib/usgs_api/config.yaml");

var scene_downloads = [];
var orders = [];

APP_HELPERS.set_logger_level('debug');

APP_HELPERS.write_message(LOG_LEVEL_INFO, 'download data start', '');

//set base URL for axios
axios.defaults.baseURL = USGS_CONSTANT.USGS_URL;

//get config data
const PG_CONNECT = yaml.load("./lib/postgres/config.yaml");

const pg_client = PG_HANDLER.pg_connect(PG_CONNECT)

const scene_arg = process.argv[2]

const last_day_scenes_fields = ' scene_id, sensor, acquisition_date, browse_url, path, row, cc_full, cc_quad_ul, cc_quad_ur, cc_quad_ll, cc_quad_lr, data_type_l1 ';

const list_yesterdays_failed = APP_HELPERS.get_yesterdays_failures();

var yesterdays_failed_scenes = ''

if (list_yesterdays_failed.length > 0){
  yesterdays_failed_scenes =  'SELECT' +
                              last_day_scenes_fields +
                            ' FROM landsat_metadata ' +
                            ' WHERE scene_id in ' + list_yesterdays_failed;
} else {
  yesterdays_failed_scenes = ''
}

const last_day_scenes = "SELECT " + last_day_scenes_fields + " FROM vw_last_days_scenes"

// " SELECT " +
//                           last_day_scenes_fields +
//                         " FROM landsat_metadata  WHERE scene_id in ('LE70220342003237EDC01')"

//"SELECT " + last_day_scenes_fields + " FROM vw_last_days_scenes"

                        // ,'LT50300402003237PAC02','LT50300392003237PAC02')
// ,'LE70330382016238EDC00','LE70170382016238EDC00'

//acquisition_date =  '2003-08-25'::date AND

// "SELECT " + last_day_scenes_fields + " FROM vw_last_days_scenes";

var scenes_for_dowloading_SQL = yesterdays_failed_scenes +
                      " UNION " +
                      last_day_scenes;

//check if there is an argument of a scene if so use that.
if( scene_arg ){
  scenes_for_dowloading_SQL = "SELECT " + last_day_scenes_fields + " FROM landsat_metadata  WHERE scene_id = '" + scene_arg + "'";
}

// //captures lastpromise first one is resolved
var lastPromise = Promise.resolve();

const query = pg_client.query(scenes_for_dowloading_SQL);

//login and get promise for api key
var api_key_main = USGS_HELPER.get_api_key();

// query to check for duplicate scenes
query.on('row', function(row, result) {

    // process rows here
      api_key_main
      .then( (apiKey) => {

        //get constant for node "EE"
        const node = USGS_CONSTANT.NODE_EE;
        const entityIds = [];
        const products =  ["STANDARD"];
        const scene_id = row.scene_id;
        const acquisition_date = row.acquisition_date;

        //derieve dataset name from the scene_id and acquisition_date
        const datasetName = USGS_HELPER.get_datasetName(scene_id, acquisition_date);

        //add scene_id to entityIds array only one here,  api requires the scene_id(s) as an array
        entityIds.push(scene_id);

        //see if scene needs to be downloaded or ordered by finding out about availablelty
        const request_body = USGS_FUNCTION.usgsapi_downloadoptions(apiKey, node, datasetName, entityIds);

        const USGS_REQUEST_CODE = USGS_HELPER.get_usgs_response_code('downloadoptions');

        //make call to USGS api.  Make sure last promise is resolved first
        //  becuase USGS api is throttled for one request at a time
        //  wrap this in a resolve promoise so the there all requests are in promise and each one has
        //  to be resolved befire the next promise is started.  This is due to only limitations of the USGS API- only allows one
        //  api call at at time,
        return lastPromise = lastPromise.then( () => {
          //yes USGS throttles downloads so lets wait a few seconds before next request;

            //actual request after the last promise has been resolved
            return USGS_HELPER.get_usgsapi_response(USGS_REQUEST_CODE, request_body)
              .then( downloads => {

                // nothing to return so write out failed????
                if(!downloads[0]){
                  DownloadScenes.add_failed('not able to download scene', scene_id);
                }

                //get the orders option for the standard
                const standard_option_order = downloads[0].downloadOptions.filter( options => {
                  return options.downloadCode === "STANDARD" && !options.available
                })

                //get the download option for the standard
                const standard_option_dowload = downloads[0].downloadOptions.filter( options => {
                  return options.downloadCode === "STANDARD" && options.available
                })

                const entityId = downloads[0].entityId;
                const entityIds = [entityId]

                //create array to hold the request json for all orders
                if(standard_option_order.length > 0){
                  const orders_obj = {apiKey,node,datasetName,entityIds};
                  orders.push(orders_obj);
                  DownloadScenes.add_order(orders_obj)
                }

                //create array to hold the request json for all downloads
                if(standard_option_dowload.length > 0){
                  const download_obj = {apiKey,node,datasetName,products,entityIds};
                  scene_downloads.push(download_obj);
                  DownloadScenes.add_download(download_obj)
                }

                var msg_header = 'Total';
                var msg = DownloadScenes.get_total_count();
                APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

                msg_header = 'Current';
                msg = DownloadScenes.get_current_count();
                APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

                msg_header = 'Complete';
                msg = DownloadScenes.iscomplete();
                APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

                //once we have completed adding all the scenes to either ordering or downloading
                //  start the process to actually order and download products
                //  again we have to start after completion because we are limited to one API call at time.
                if( DownloadScenes.iscomplete() ) {
                  DownloadScenes.start_order()
                }

            }).catch( (error) => {

              // failed_downloads.push({scene_id});
              // console.log('dowload options api: ' + error.message);
              msg_header = 'download failed for scene';
              msg = DownloadScenes.iscomplete();

              DownloadScenes.add_failed(msg_header, scene_id);
              APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

            });

        }).catch( (error) => {
          msg_header = 'last promise error';
          msg = error.message;
          APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

        });

      }).catch( (error) => {
        msg_header = 'api';
        msg = error.message;
        APP_HELPERS.write_message(LOG_LEVEL_INFO, msg_header, msg);

        });

    // wait for order to complete every n seconds via usgs api?  this may take tooo long no I have one in process for a few days.
    //it seems that currently all scenes are in progesss.

  });

query.on('error', function(err) {
    msg_header = 'query error';
    msg = err.message;
    APP_HELPERS.write_message(LOG_LEVEL_ERR, msg_header, msg);
  });

query.on('end', function(result) {
    DownloadScenes.set_total(result.rowCount);
  });
<|endoftext|>


<commit_before>Event.addBehavior({
  "#sort_uploads:click": function(e){
    Comment.update();
  },
  "#sort_all:click": function(e){
    Comment.update();
  },
  "#sort_hours:click": function(e){
    Comment.update();
  },
  "form .showPreview button:click": function(e){
    $(this).up('form').showPreview();
    return false;
  },
  "form .showPreview a:click": function(e){
    $(this).up('form').closePreview();
    return false;
  }
});

Comment = {
  update_uploads_current: function(e) {
    if (e.select('div.upload_thumbnail').length == 0)
      e.hide();
    else
      e.show();
  },
  update: function() {
    var params = {};
    if ($('sort_uploads').checked) {
      params = { show: 'uploads' };
    } else if ($('sort_hours').checked) {
      params = { show: 'hours' };
    }
    new Ajax.Request(comments_update_url, { method: 'get', parameters: $H(params).merge(comments_parameters) });
  },
  watch_status: function(){
    $$('.statuses .status').each(function(e){
      if(e.hasClassName('open'))
        e.down('select').observe('change', Comment.change_assigned)
      else
        e.observe('click', Comment.change_status)
    });
  },
  change_assigned: function(e){
    Comment.unselect_all_statuses()
    Comment.mark_status_for_assigned(e.element())
  },
  change_status: function(e){
    Comment.unselect_all_statuses()
    Comment.assign_to_nobody()
    Comment.mark_status(e.element())
  },
  unselect_all_statuses: function(){
    $$('.statuses .active').each(function(ee){ ee.removeClassName('active') })
    $$('.statuses input').each(function(ee){ ee.checked = false })
  },
  mark_status: function(e){
    e.down('input').checked = true
    e.addClassName('active')
  },
  mark_status_for_assigned: function(e){
    $$('#new_comment option').each(function(ee){
      if(ee.value == ''){
        if(ee.selected == true)
          Comment.mark_status($('new_comment').down('.hold'))
        else
          Comment.mark_status(e.up('.status'))
      }
    })
  },
  assign_to_nobody: function(){
    $$('#new_comment option').each(function(e){
      if(e.value == '')
        e.selected = true
      else
        e.selected = false
    })
  },
  make_autocomplete: function(element_id, items){
    new Autocompleter.Local(element_id, element_id + '_list', items, {tokens:[' ']});
  },

  check_edit: function(){
    var list = Comment.edit_watch_list;
    var len = list.length;
    var now = new Date();
    Comment.edit_watch_list = list.reject(function(c){
      if (now > c.date) {
        var el = $(c.id);
        if (el)
          el.down('.actions').hide();
        return true;
      }
      return false;
    });

    if (Comment.edit_watch_list.length > 0)
      Comment.edit_watch_timer = setTimeout(Comment.check_edit, 1000);
  },
  cancel_watch_edit: function(){
    if (Comment.edit_watch_timer)
      clearTimeout(Comment.edit_watch_timer);
    Comment.edit_watch_timer = null;
  },
  watch_edit: function(){
    this.cancel_watch_edit();
    var date = new Date();

    Comment.edit_watch_list = $$('div.comment').map(function(c){
        var time = new Date();
        time.setTime(c.readAttribute('immutable_at'));
        return {id: c.readAttribute('id'), date:time};
    }).reject(function(c){
        if (date >= c.date) {
          $(c.id + '_actions').hide();
          return true;
        }
        return false;
    });
    Comment.check_edit();
  }
};
<commit_msg>Fix problem with comment actions being permanently hidden<commit_after>Event.addBehavior({
  "#sort_uploads:click": function(e){
    Comment.update();
  },
  "#sort_all:click": function(e){
    Comment.update();
  },
  "#sort_hours:click": function(e){
    Comment.update();
  },
  "form .showPreview button:click": function(e){
    $(this).up('form').showPreview();
    return false;
  },
  "form .showPreview a:click": function(e){
    $(this).up('form').closePreview();
    return false;
  }
});

Comment = {
  update_uploads_current: function(e) {
    if (e.select('div.upload_thumbnail').length == 0)
      e.hide();
    else
      e.show();
  },
  update: function() {
    var params = {};
    if ($('sort_uploads').checked) {
      params = { show: 'uploads' };
    } else if ($('sort_hours').checked) {
      params = { show: 'hours' };
    }
    new Ajax.Request(comments_update_url, { method: 'get', parameters: $H(params).merge(comments_parameters) });
  },
  watch_status: function(){
    $$('.statuses .status').each(function(e){
      if(e.hasClassName('open'))
        e.down('select').observe('change', Comment.change_assigned)
      else
        e.observe('click', Comment.change_status)
    });
  },
  change_assigned: function(e){
    Comment.unselect_all_statuses()
    Comment.mark_status_for_assigned(e.element())
  },
  change_status: function(e){
    Comment.unselect_all_statuses()
    Comment.assign_to_nobody()
    Comment.mark_status(e.element())
  },
  unselect_all_statuses: function(){
    $$('.statuses .active').each(function(ee){ ee.removeClassName('active') })
    $$('.statuses input').each(function(ee){ ee.checked = false })
  },
  mark_status: function(e){
    e.down('input').checked = true
    e.addClassName('active')
  },
  mark_status_for_assigned: function(e){
    $$('#new_comment option').each(function(ee){
      if(ee.value == ''){
        if(ee.selected == true)
          Comment.mark_status($('new_comment').down('.hold'))
        else
          Comment.mark_status(e.up('.status'))
      }
    })
  },
  assign_to_nobody: function(){
    $$('#new_comment option').each(function(e){
      if(e.value == '')
        e.selected = true
      else
        e.selected = false
    })
  },
  make_autocomplete: function(element_id, items){
    new Autocompleter.Local(element_id, element_id + '_list', items, {tokens:[' ']});
  },

  check_edit: function(){
    var list = Comment.edit_watch_list;
    var len = list.length;
    var now = new Date();
    Comment.edit_watch_list = list.reject(function(c){
      if (now > c.date) {
        var el = $(c.id);
        if (el)
          el.down('.actions').hide();
        return true;
      }
      return false;
    });

    if (Comment.edit_watch_list.length > 0)
      Comment.edit_watch_timer = setTimeout(Comment.check_edit, 1000);
  },
  cancel_watch_edit: function(){
    if (Comment.edit_watch_timer)
      clearTimeout(Comment.edit_watch_timer);
    Comment.edit_watch_timer = null;
  },
  watch_edit: function(){
    this.cancel_watch_edit();
    var date = new Date();

    Comment.edit_watch_list = $$('div.comment').map(function(c){
        var time = new Date();
        time.setTime(c.readAttribute('immutable_at'));
        return {id: c.readAttribute('id'), date:time};
    }).reject(function(c){
        if (date >= c.date) {
          $(c.id + '_actions').hide();
          return true;
        } else {
          $(c.id + '_actions').show();
        }
        return false;
    });
    Comment.check_edit();
  }
};
<|endoftext|>


<commit_before>'use strict';

angular.module('lx.sort', [])
/**
 * @ngdoc directive
 * @name lx.sort.directive:lxSort
 * @restrict E
 * @param {string} fieldName The name of the property which should sort.
 * @param {object} sortOpts The options for configuration.
 * @param {function(sortingOptions) } onSorting The callback which is called on sorting.
 *
 * @description
 * Directive for custom sorting or server side sorting.
 *
 * For more details see our {@link /sort Guide}.
 *
 */
    .directive('lxSort', function () {
        return {
            restrict: 'E',
            transclude: true,
            replace: true,
            template: '
' +
            '' +
            '
',
            scope: {
                options: '=sortOpts',
                onSorting: '&'
            },
            link: function (scope, element, attrs) {
                scope.field = attrs.fieldName;

                scope.sort = function () {
                    if (scope.options) {
                        //scope.direction = scope.options[scope.field] || 1;
                        scope.direction = scope.options.direction || 1;
                        scope.direction *= -1;
                        scope.onSorting({sortingOptions: {field: scope.field, direction: scope.direction}});
                    }
                };
            }
        };
    });
<commit_msg>chore:<commit_after>'use strict';

angular.module('lx.sort', [])
/**
 * @ngdoc directive
 * @name lx.sort.directive:lxSort
 * @restrict E
 * @param {string} fieldName The name of the property which should sort.
 * @param {object} sortOpts The options for configuration.
 * @param {function(sortingOptions) } onSorting The callback which is called on sorting.
 *
 * @description
 * Directive for custom sorting or server side sorting.
 *
 * For more details see our {@link /sort Guide}.
 *
 */
    .directive('lxSort', function () {
        return {
            restrict: 'E',
            transclude: true,
            replace: true,
            template: '
' +
            '' +
            '
',
            scope: {
                options: '=sortOpts',
                onSorting: '&'
            },
            link: function (scope, element, attrs) {
                scope.field = attrs.fieldName;

                scope.sort = function () {
                    if (scope.options) {
                        //scope.direction = scope.options[scope.field] || 1;
                        scope.direction = scope.options.direction || 1;
                        scope.direction *= -1;
                        scope.onSorting({sortingOptions: {field: scope.field, direction: scope.direction}});
                    }
                };
            }
        };
    });
<|endoftext|>


<commit_before>import assert from "assert";
import connect from "@pipes/core/connect";
import Pipe from "@pipes/core/pipe";

import debounce from "../src/debounce";
import repeat from "../src/repeat";
import take from "../src/take";

import {
  createTestWritable,
  broker
} from "./utils";

suite("debounce");

let
  [ min, max ] = [ 50, 100 ],
  factor = Math.floor( (max + min ) / 2 ),
  genRand = ( min, max ) => Math.random() * ( max - min ) + min,
  randDelay = (min, max) => chunk => new Promise( resolve => {
    global.setTimeout( () => resolve( Date.now() ), genRand( min, max ) );
  });

test("check flow", done => {
  let
    readable = repeat( true ),
    writable, res=[];

  // Create test streams
  writable = createTestWritable( c => res.push( c ));

  // End case
  broker.on(writable.signals.close, () => {
    // Make sure result array
    assert( res.map( (t, i) => {
        if (i+1 < res.length) {
          return res[i+1] - t;
        }

        return factor;
      })
        .map( a => a >= factor )
        .reduce( (a, b) => a && b, true )
    );

      done();
    });

  // Connect the streams
  assert.doesNotThrow( () => {
    connect(
      readable,
      new Pipe.async( randDelay( min, max ) ),
      debounce( factor, false ),
      take( 3 ),
      writable
    );
  });
});
<commit_msg>Fixed debounce test<commit_after>import "babel-polyfill";

import assert from "assert";
import connect from "@pipes/core/connect";
import Pipe from "@pipes/core/pipe";

import debounce from "../src/debounce";
import repeat from "../src/repeat";
import take from "../src/take";

import {
  createTestWritable,
  broker
} from "./utils";

suite("debounce");

let
  [ min, max ] = [ 50, 100 ],
  factor = Math.floor( (max + min ) / 2 ),
  genRand = ( min, max ) => Math.random() * ( max - min ) + min,
  randDelay = (min, max) => chunk => new Promise( resolve => {
    global.setTimeout( () => resolve( Date.now() ), genRand( min, max ) );
  });

test("check flow", done => {
  let
    readable = repeat( true ),
    writable, res=[];

  // Create test streams
  writable = createTestWritable( c => res.push( c ));

  // End case
  broker.on(writable.signals.close, () => {
    // Make sure result array
    assert( res.map( (t, i) => {
        if (i+1 < res.length) {
          return res[i+1] - t;
        }

        return factor;
      })
        .map( a => a >= factor )
        .reduce( (a, b) => a && b, true )
    );

      done();
    });

  // Connect the streams
  assert.doesNotThrow( () => {
    connect(
      readable,
      new Pipe.async( randDelay( min, max ) ),
      debounce( factor, false ),
      take( 3 ),
      writable
    );
  });
});
<|endoftext|>


<commit_before>/*
== Multi-State Button jQuery Plugin ==
== msb.jquery.js ==
Version: 0.2.1
Plugin URI: https://github.com/fchaussin/jquery-multi-state-button
Author: fchaussin
Author URI: https://francoischaussin.com
License: MIT License (MIT)
*/
(function($, window, document, undefined) {
	var defaultStates = {};
	var get_defaultStates = function() {
		return this.defaultStates;
	};
	var set_defaultStates = function(states) {
		this.defaultStates = $.extend(true, this.defaultStates, states);
	};
	var methods = {
		init: function(options, callback) {
			var states = $.extend(true, {}, $.fn.msb.defaults, options);
			set_defaultStates(states);
			if (typeof callback == "function") {
				callback.call(this);
			}
			return this.each(function() {
				$(this).addClass("msb");
				if (!$(this).attr("data-state")) {
					$(this).attr("data-state", "default");
				}
				// get state
				var state = $(this).data("state");
				methods._build($(this), state);
			});
		},
		update: function(state, callback) {
			var states = get_defaultStates();
			if (typeof callback == "function") {
				callback.call(this);
			}
			return this.each(function() {
				if (states[state] != undefined) {
					var prevState = states[$(this).data("state")];
					$(this)
						.removeClass(prevState.cssClass)
						.data("state", state);
					methods._build($(this), state);
				} else {
					console.log("State: '" + state + "' hasn't been defined.");
				}
			});
		},
		_build: function(el, state) {
			var states = get_defaultStates();
			// change icon name, and keep it for rebuid
			var icon = el.find("i.material-icons").html(states[state].icon.name);
			// remove any icon anim css class (msb-anim-*)
			el.find("i.material-icons").removeClass(function(index, className) {
				return (className.match(/(^|\s)msb-anim-\S+/g) || []).join(" ");
			});
			// now, if state icon anim, adding it
			if (states[state].icon.anim != false) {
				el.find("i.material-icons").addClass("msb-anim-" + states[state].icon.anim);
			}
			// rebuild button
			el.addClass(states[state].cssClass)
			  .html(icon)
			  .append(states[state].label)
			  .prop("disabled", states[state].disabled);
		}
	};

	$.fn.msb = function(methodOrOptions) {
		if (methods[methodOrOptions]) {
			return methods[methodOrOptions].apply(
				this,
				Array.prototype.slice.call(arguments, 1)
			);
		} else if (typeof methodOrOptions === "object" || !methodOrOptions) {
			// Default to "init"
			return methods.init.apply(this, arguments);
		} else {
			$.error("Method " + methodOrOptions + " does not exist on jQuery.msb");
		}
	};
	$.fn.msb.defaults = {
		default: {
			cssClass: "blue",
			label: "submit",
			icon: {
				name: "send",
				anim: false
			},
			disabled: false,
			stateBar: ""
		},
		success: {
			cssClass: "green",
			label: "sent",
			icon: {
				name: "check",
				anim: false
			},
			disabled: true,
			stateBar: ""
		},
		warning: {
			cssClass: "orange",
			label: "try again",
			icon: {
				name: "warning",
				anim: false
			},
			disabled: false,
			stateBar: ""
		},
		error: {
			cssClass: "red",
			label: "try again",
			icon: {
				name: "cancel",
				anim: false
			},
			disabled: false,
			stateBar: ""
		},
		process: {
			cssClass: "yellow black-text",
			label: "processing",
			icon: {
				name: "refresh",
				anim: "rotate"
			},
			disabled: true,
			stateBar: ""
		}
	};
})(jQuery, window, document);
<commit_msg>Font-Awesome compatibility<commit_after>/*
== Multi-State Button jQuery Plugin ==
== msb.jquery.js ==
Version: 0.2.1
Plugin URI: https://github.com/fchaussin/jquery-multi-state-button
Author: fchaussin
Author URI: https://francoischaussin.com
License: MIT License (MIT)
*/
(function($, window, document, undefined) {
	var defaultStates = {},
	get_defaultStates = function() {
		return this.defaultStates;
	},
	set_defaultStates = function(states) {
		this.defaultStates = $.extend(true, this.defaultStates, states);
	},
	methods = {
		init: function(options, callback) {
			var states = $.extend(true, {}, $.fn.msb.defaults, options);
			set_defaultStates(states);
			if (typeof callback == "function") {
				callback.call(this);
			}
			return this.each(function() {
				$(this).addClass("msb");
				if (!$(this).attr("data-state")) {
					$(this).attr("data-state", "default");
				}
				// get state
				var state = $(this).data("state");
				methods._build($(this), state);
			});
		},
		update: function(state, callback) {
			var states = get_defaultStates();
			if (typeof callback == "function") {
				callback.call(this);
			}
			return this.each(function() {
				if (states[state] != undefined) {
					var prevState = states[$(this).data("state")];
					$(this)
						.removeClass(prevState.cssClass)
						.data("state", state);
					methods._build($(this), state);
				} else {
					console.log("State: '" + state + "' hasn't been defined.");
				}
			});
		},
		_build: function(el, state) {
			var states = get_defaultStates();
			var icon = "";
			var md = el.find("i.material-icons");
			var fa = el.find("i.fa");
			if (md.length > 0) {
				icon = md.html(states[state].icon.name);
				// remove any icon anim css class (msb-anim-*)
				md.removeClass(function(index, className) {
					return (className.match(/(^|\s)msb-anim-\S+/g) || []).join(" ");
				});
				// now, if state icon anim, adding it
				if (states[state].icon.anim != false) {
					md.addClass("msb-anim-" + states[state].icon.anim);
				}
			} else if (fa.length > 0) {
				fa.removeClass(function(index, className) {
					return (className.match(/(^|\s)fa-\S+/g) || []).join(" ");
				});
				fa.removeClass(function(index, className) {
					return (className.match(/(^|\s)msb-anim-\S+/g) || []).join(" ");
				});
				icon = fa.addClass('fa-' + states[state].icon.name);
				// now, if state icon anim, adding it
				if (states[state].icon.anim != false) {
					fa.addClass("msb-anim-" + states[state].icon.anim);
				}
			}
			// rebuild button
			el
				.addClass(states[state].cssClass)
				.html(icon)
				.append(states[state].label)
				.prop("disabled", states[state].disabled);
		}
	};

	$.fn.msb = function(methodOrOptions) {
		if (methods[methodOrOptions]) {
			return methods[methodOrOptions].apply(
				this,
				Array.prototype.slice.call(arguments, 1)
			);
		} else if (typeof methodOrOptions === "object" || !methodOrOptions) {
			// Default to "init"
			return methods.init.apply(this, arguments);
		} else {
			$.error("Method " + methodOrOptions + " does not exist on jQuery.msb");
		}
	};
	$.fn.msb.defaults = {
		default: {
			cssClass: "blue",
			label: "submit",
			icon: {
				name: "send",
				anim: false
			},
			disabled: false,
			stateBar: ""
		},
		success: {
			cssClass: "green",
			label: "sent",
			icon: {
				name: "check",
				anim: false
			},
			disabled: true,
			stateBar: ""
		},
		warning: {
			cssClass: "orange",
			label: "try again",
			icon: {
				name: "warning",
				anim: false
			},
			disabled: false,
			stateBar: ""
		},
		error: {
			cssClass: "red",
			label: "try again",
			icon: {
				name: "cancel",
				anim: false
			},
			disabled: false,
			stateBar: ""
		},
		process: {
			cssClass: "yellow black-text",
			label: "processing",
			icon: {
				name: "refresh",
				anim: "rotate"
			},
			disabled: true,
			stateBar: ""
		}
	};
})(jQuery, window, document);
<|endoftext|>