<commit_before>'use strict'

const RBAC = require('easy-rbac')
const MongoClient = require('mongodb').MongoClient
const errors = require('lambda-errors-formatter')
const options = require('./options')

function rbacCatch(err, callback) {
  if (err && typeof err.message === 'string') {
    return callback(errors.forbidden(err.message))
  }
  return callback(errors.internalServerError())
}

class Crud {

  constructor(stringConnection, collectionName, user, roles) {
    this.stringConnection = stringConnection
    this.collectionName = collectionName
    this.user = user
    this.rbac = new RBAC(roles)
  }

  list(query, permission, roleOptions, callback) {

    const pagination = options.getPagination(query);
    const sort = options.getSort(query);
    const search = options.getSearch(query);
    const projections = options.getProjections(query);

    query = options.clearQuery(query)
    query = Object.assign(query, search);

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.find(query).sort(sort).project(projections).limit(pagination.limit).skip(pagination.from).toArray((err, docs) => {

            if (err) {
              db.close()
              return callback(err)
            }

            if (!pagination.isPaginated) {
              db.close()
              return callback(null, docs)
            }

            collection.count(query, (err, total) => {
              db.close()

              if (err) {
                return callback(err)
              }

              return callback(null, options.getPaginatedResponse(docs, pagination, total))
            });
          })
        })
      })

      .catch(err => rbacCatch(err, callback))
  }

  listAggregate(query, stages, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          const pagination = options.getPagination(query);
          const sort = options.getSort(query);
          const search = options.getSearch(query);
          const projections = options.getProjections(query);

          query = options.clearQuery(query)
          query = Object.assign(query, search);

          let collection = db.collection(this.collectionName)
          collection.count(query, (err, total) => {

            if (err) {
              db.close()
              return callback(err)
            }

            stages.unshift({ $match: query })

            if (sort && Object.keys(sort).length > 0) {
              stages.push({ $sort: sort })
            }

            if (projections && Object.keys(projections).length > 0) {
              stages.push({ $project: projections })
            }

            stages = stages.concat(options.getPaginationStages(pagination));

            collection.aggregate(stages, (err, results) => {

                db.close()

                if (err) {
                  return callback(err)
                }

                if (!pagination.isPaginated) {
                  return callback(null, results);
                }

                return callback(null, options.getPaginatedResponse(results, pagination, total))
              }
            );
          });
        })
      })

      .catch(err => rbacCatch(err, callback))
  }

  get(query, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.findOne(query, (err, doc) => {
            db.close()

            if (err) {
              return callback(err)
            }

            if (!doc) {
              return callback(errors.notFound())
            }

            return callback(null, doc)
          })
        })
      })

      .catch(err => rbacCatch(err, callback))
  }

  create(data, permission, roleOptions, callback) {

    data.createdAt = new Date();

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.insertOne(data, (err, doc) => {

            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, doc.ops[0])
          })
        })

      })

      .catch(err => rbacCatch(err, callback))
  }

  delete(query, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {
          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.findOneAndDelete(query, (err, doc) => {

            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, doc.value)
          })
        })
      })

      .catch((err) => rbacCatch(err, callback))
  }

  update(query, data, permission, roleOptions, callback) {

    delete data.createdAt
    data.updateAt = new Date()

    const options = {
      upsert: false,
      returnOriginal: false
    }

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {
          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.findOneAndUpdate(query, { $set: data }, options, (err, doc) => {

            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, doc.value)
          })
        })
      })

      .catch((err) => rbacCatch(err, callback))
  }

  upsertMany(data, keyForQuery, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {
          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          const bulk = collection.initializeUnorderedBulkOp();

          for (let obj of data) {
            let query = {}
            query[keyForQuery] = obj[keyForQuery]
            bulk.find(query).upsert().updateOne({ $set: obj });
          }

          bulk.execute((err, result) => {
            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, result)
          });
        })
      })

      .catch((err) => rbacCatch(err, callback))
  }
}

module.exports = Crud
<commit_msg>fix (crud.js): lint<commit_after>'use strict'

const RBAC = require('easy-rbac')
const MongoClient = require('mongodb').MongoClient
const errors = require('lambda-errors-formatter')
const options = require('./options')

function rbacCatch(err, callback) {
  if (err && typeof err.message === 'string') {
    return callback(errors.forbidden(err.message))
  }
  return callback(errors.internalServerError())
}

class Crud {

  constructor(stringConnection, collectionName, user, roles) {
    this.stringConnection = stringConnection
    this.collectionName = collectionName
    this.user = user
    this.rbac = new RBAC(roles)
  }

  list(query, permission, roleOptions, callback) {

    const pagination = options.getPagination(query);
    const sort = options.getSort(query);
    const search = options.getSearch(query);
    const projections = options.getProjections(query);

    query = options.clearQuery(query)
    query = Object.assign(query, search);

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.find(query).sort(sort).project(projections).limit(pagination.limit).skip(pagination.from).toArray((err, docs) => {

            if (err) {
              db.close()
              return callback(err)
            }

            if (!pagination.isPaginated) {
              db.close()
              return callback(null, docs)
            }

            collection.count(query, (err, total) => {
              db.close()

              if (err) {
                return callback(err)
              }

              return callback(null, options.getPaginatedResponse(docs, pagination, total))
            });
          })
        })
      })

      .catch(err => rbacCatch(err, callback))
  }

  listAggregate(query, stages, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          const pagination = options.getPagination(query);
          const sort = options.getSort(query);
          const search = options.getSearch(query);
          const projections = options.getProjections(query);

          query = options.clearQuery(query)
          query = Object.assign(query, search);

          let collection = db.collection(this.collectionName)
          collection.count(query, (err, total) => {

            if (err) {
              db.close()
              return callback(err)
            }

            stages.unshift({ $match: query })

            if (sort && Object.keys(sort).length > 0) {
              stages.push({ $sort: sort })
            }

            if (projections && Object.keys(projections).length > 0) {
              stages.push({ $project: projections })
            }

            stages = stages.concat(options.getPaginationStages(pagination));

            collection.aggregate(stages, (err, results) => {

              db.close()

              if (err) {
                return callback(err)
              }

              if (!pagination.isPaginated) {
                return callback(null, results);
              }

              return callback(null, options.getPaginatedResponse(results, pagination, total))
            }
            );
          });
        })
      })

      .catch(err => rbacCatch(err, callback))
  }

  get(query, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.findOne(query, (err, doc) => {
            db.close()

            if (err) {
              return callback(err)
            }

            if (!doc) {
              return callback(errors.notFound())
            }

            return callback(null, doc)
          })
        })
      })

      .catch(err => rbacCatch(err, callback))
  }

  create(data, permission, roleOptions, callback) {

    data.createdAt = new Date();

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {

          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.insertOne(data, (err, doc) => {

            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, doc.ops[0])
          })
        })

      })

      .catch(err => rbacCatch(err, callback))
  }

  delete(query, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {
          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.findOneAndDelete(query, (err, doc) => {

            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, doc.value)
          })
        })
      })

      .catch((err) => rbacCatch(err, callback))
  }

  update(query, data, permission, roleOptions, callback) {

    delete data.createdAt
    data.updateAt = new Date()

    const options = {
      upsert: false,
      returnOriginal: false
    }

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {
          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          collection.findOneAndUpdate(query, { $set: data }, options, (err, doc) => {

            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, doc.value)
          })
        })
      })

      .catch((err) => rbacCatch(err, callback))
  }

  upsertMany(data, keyForQuery, permission, roleOptions, callback) {

    this.rbac.can(this.user.role, permission, roleOptions)

      .then(() => {

        MongoClient.connect(this.stringConnection, (err, db) => {
          if (err) {
            return callback(err)
          }

          let collection = db.collection(this.collectionName)

          const bulk = collection.initializeUnorderedBulkOp();

          for (let obj of data) {
            let query = {}
            query[keyForQuery] = obj[keyForQuery]
            bulk.find(query).upsert().updateOne({ $set: obj });
          }

          bulk.execute((err, result) => {
            db.close()

            if (err) {
              return callback(err)
            }

            return callback(null, result)
          });
        })
      })

      .catch((err) => rbacCatch(err, callback))
  }
}

module.exports = Crud
<|endoftext|>


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

var elo = require('./elo');

var WIN = 0;
var LOSS = 1;

var Game = function(map, teamA, teamB, winner, round) {
    this.map = map;
    this.teamA = teamA;
    this.teamB = teamB;
    this.winner = winner;
    this.round = round;
};

Game.prototype = {
    printGame: function() {
        console.log(' ', this.map, '[' + this.teamA +'/'+ this.teamB + ']', this.winner, this.round);
    }
};

var Series = function(map_list, teamA, teamB) {
    this.maps = map_list.split(',');
    this.games = [];
    this.teamA = teamA;
    this.teamB = teamB;
    this.teamAWins = 0;
    this.teamBWins = 0;
    this.mapIndex = 0;
};

Series.prototype = {
    addGame: function(winner, round) {
        this.games.push(new Game(this.maps[this.mapIndex], this.teamA, this.teamB, winner, round));
        this.mapIndex += 1;
    },
    endSeries: function() {
        for (var i = 0; i < this.games.length; i++) {
            if (this.games[i].winner === this.teamA) {
                this.teamAWins += 1;
            } else {
                this.teamBWins += 1;
            }
        }
        if (this.teamAWins > this.teamBWins) {
            this.winner = this.teamA;
        } else {
            this.winner = this.teamB;
        }
        this._printSeries();
    },
    _printSeries: function() {
        console.log('Series:', this.teamA, this.teamB, this.maps.join(','));
        var numGames = this.games.length;
        for (var i = 0; i < numGames; i++) {
            this.games[i].printGame();
        }
        if (this.winner === this.teamA) {
            console.log(this.teamA, 'wins the series', this.teamAWins, this.teamBWins)
        } else {
            console.log(this.teamB, 'wins the series', this.teamBWins, this.teamAWins)
        }
        console.log(' ')
    }
};

var DataCollector = function() {

};

DataCollector.prototype = {
    _entries: [],
    addGame: function(map, teamA, teamB, winner, round) {
        this._entries.push(new Game(map, teamA, teamB, winner, round));
    },
    startSeries: function(map_list, teamA, teamB) {
        var series = new Series(map_list, teamA, teamB);
        this._entries.push(series);
        return series;

    },
    printPlayersSummary: function(teams) {
        var i;
        var winLoss = {};
        for (i=0; i < teams.length; i++) {
            winLoss[teams[i]] = [0,0]
        }
        for (i=0; i < this._entries.length; i++) {
            var entry = this._entries[i];
            if (entry.winner === entry.teamA) {
                winLoss[entry.teamA][WIN] += 1;
                winLoss[entry.teamB][LOSS] += 1;
            } else {
                winLoss[entry.teamA][LOSS] += 1;
                winLoss[entry.teamB][WIN] += 1;
            }
        }
        console.log('');
        console.log('Summary:');
        for (var team in winLoss) {
            var per = Math.floor(winLoss[team][WIN] / (winLoss[team][LOSS] + winLoss[team][WIN])*100);
            console.log(team, '\t', winLoss[team][WIN], winLoss[team][LOSS], per);
        }
    },
    _getGames: function(series) {
        var games = [];

        if (series) {
            for (i = 0; i < this._entries.length; i++) {
                games = games.concat(this._entries[i].games);
            }
        } else {
            games = this._entries;
        }
        return games;
    },
    printPlayerMapSummary: function(team, maps, series) {
        _printPlayerMapSummary(team, maps, this._getGames(series));
    },
    reset: function() {
        this._entries = [];
    },
    saveAsCSV: function(series) {
        var game;
        var games = this._getGames(series);
        var csv = '';
        for (var i = 0; i < games.length; i++) {
            game = games[i];
            csv += [game.map, game.teamA, game.teamB, game.winner, game.round].join(',') + '\n';
        }
        fs.writeFileSync('games.csv', csv);
        console.log('');
        console.log('Games saved to ./games.csv');
    },
    computeELOs: function(teams, series) {
        var team, game, i, aELO, bELO;
        var games = this._getGames(series);
        var teamELO = {};
        for (i = 0; i < teams.length; i++) {
            teamELO[teams[i]] = 1400;
        }

        for (i = 0; i < games.length; i++) {
            game = games[i];
            if (teams.indexOf(game.teamA) !== -1 && teams.indexOf(game.teamB) !== -1) {
                aELO = teamELO[game.teamA];
                bELO = teamELO[game.teamB];

                teamELO[game.teamA] = elo.calculate_new_elo(aELO, bELO, game.winner === game.teamA);
                teamELO[game.teamB] = elo.calculate_new_elo(bELO, aELO, game.winner === game.teamB);
            }
        }

        console.log(' ');
        console.log('Relative ELOs');
        for (i = 0; i < teams.length; i++) {
            team = teams[i];
            console.log(team, '\t', teamELO[team]);
        }
    }

};

function _printPlayerMapSummary(team, maps, games) {
    var i, j;
    var mapWinLoss = {};
    for (i=0; i < maps.length; i++) {
        mapWinLoss[maps[i]] = [0,0];
    }

    console.log('Wins on maps for team ' + team);
    for (i = 0; i < games.length; i++) {
        var game = games[i];
        if (game.teamA === team || game.teamB === team) {
            if (game.winner === team) {
                mapWinLoss[game.map][WIN] += 1;
            } else {
                mapWinLoss[game.map][LOSS] += 1;
            }
        }
    }
    console.log('');
    console.log('Summary:');
    for (var map in mapWinLoss) {
        var per = Math.floor(mapWinLoss[map][WIN] / (mapWinLoss[map][WIN] + mapWinLoss[map][LOSS])*100);
        console.log(map, '\t', mapWinLoss[map][WIN], mapWinLoss[map][LOSS], per);
    }

}

module.exports.DataCollector = DataCollector;<commit_msg>Fixed summary to be more detailed<commit_after>var fs = require('fs');

var elo = require('./elo');

var WIN = 0;
var LOSS = 1;

var Game = function(map, teamA, teamB, winner, round) {
    this.map = map;
    this.teamA = teamA;
    this.teamB = teamB;
    this.winner = winner;
    this.round = round;
};

Game.prototype = {
    printGame: function() {
        console.log(' ', this.map, '[' + this.teamA +'/'+ this.teamB + ']', this.winner, this.round);
    }
};

var Series = function(map_list, teamA, teamB) {
    this.maps = map_list.split(',');
    this.games = [];
    this.teamA = teamA;
    this.teamB = teamB;
    this.teamAWins = 0;
    this.teamBWins = 0;
    this.mapIndex = 0;
};

Series.prototype = {
    addGame: function(winner, round) {
        this.games.push(new Game(this.maps[this.mapIndex], this.teamA, this.teamB, winner, round));
        this.mapIndex += 1;
    },
    endSeries: function() {
        for (var i = 0; i < this.games.length; i++) {
            if (this.games[i].winner === this.teamA) {
                this.teamAWins += 1;
            } else {
                this.teamBWins += 1;
            }
        }
        if (this.teamAWins > this.teamBWins) {
            this.winner = this.teamA;
        } else {
            this.winner = this.teamB;
        }
        this._printSeries();
    },
    _printSeries: function() {
        console.log('Series:', this.teamA, this.teamB, this.maps.join(','));
        var numGames = this.games.length;
        for (var i = 0; i < numGames; i++) {
            this.games[i].printGame();
        }
        if (this.winner === this.teamA) {
            console.log(this.teamA, 'wins the series', this.teamAWins, this.teamBWins)
        } else {
            console.log(this.teamB, 'wins the series', this.teamBWins, this.teamAWins)
        }
        console.log(' ')
    }
};

var DataCollector = function() {

};

DataCollector.prototype = {
    _entries: [],
    addGame: function(map, teamA, teamB, winner, round) {
        this._entries.push(new Game(map, teamA, teamB, winner, round));
    },
    startSeries: function(map_list, teamA, teamB) {
        var series = new Series(map_list, teamA, teamB);
        this._entries.push(series);
        return series;

    },
    printPlayersSummary: function(teams) {
        var i;
        var winLoss = {};
        for (i=0; i < teams.length; i++) {
            winLoss[teams[i]] = [0,0]
        }
        for (i=0; i < this._entries.length; i++) {
            var entry = this._entries[i];
            if (entry.winner === entry.teamA) {
                winLoss[entry.teamA][WIN] += 1;
                winLoss[entry.teamB][LOSS] += 1;
            } else {
                winLoss[entry.teamA][LOSS] += 1;
                winLoss[entry.teamB][WIN] += 1;
            }
        }
        console.log('');
        console.log('Summary:');
        console.log('team', '\t', 'wins', '\t', 'losses', '\t', '%')
        for (var team in winLoss) {
            var per = Math.floor(winLoss[team][WIN] / (winLoss[team][LOSS] + winLoss[team][WIN])*100);
            console.log(team, '\t', winLoss[team][WIN], '\t', winLoss[team][LOSS], '\t', per);
        }
    },
    _getGames: function(series) {
        var games = [];

        if (series) {
            for (i = 0; i < this._entries.length; i++) {
                games = games.concat(this._entries[i].games);
            }
        } else {
            games = this._entries;
        }
        return games;
    },
    printPlayerMapSummary: function(team, maps, series) {
        _printPlayerMapSummary(team, maps, this._getGames(series));
    },
    reset: function() {
        this._entries = [];
    },
    saveAsCSV: function(series) {
        var game;
        var games = this._getGames(series);
        var csv = '';
        for (var i = 0; i < games.length; i++) {
            game = games[i];
            csv += [game.map, game.teamA, game.teamB, game.winner, game.round].join(',') + '\n';
        }
        fs.writeFileSync('games.csv', csv);
        console.log('');
        console.log('Games saved to ./games.csv');
    },
    computeELOs: function(teams, series) {
        var team, game, i, aELO, bELO;
        var games = this._getGames(series);
        var teamELO = {};
        for (i = 0; i < teams.length; i++) {
            teamELO[teams[i]] = 1400;
        }

        for (i = 0; i < games.length; i++) {
            game = games[i];
            if (teams.indexOf(game.teamA) !== -1 && teams.indexOf(game.teamB) !== -1) {
                aELO = teamELO[game.teamA];
                bELO = teamELO[game.teamB];

                teamELO[game.teamA] = elo.calculate_new_elo(aELO, bELO, game.winner === game.teamA);
                teamELO[game.teamB] = elo.calculate_new_elo(bELO, aELO, game.winner === game.teamB);
            }
        }

        console.log(' ');
        console.log('Relative ELOs');
        for (i = 0; i < teams.length; i++) {
            team = teams[i];
            console.log(team, '\t', teamELO[team]);
        }
    }

};

function _printPlayerMapSummary(team, maps, games) {
    var i, j;
    var mapWinLoss = {};
    for (i=0; i < maps.length; i++) {
        mapWinLoss[maps[i]] = [0,0];
    }

    console.log('Wins on maps for team ' + team);
    for (i = 0; i < games.length; i++) {
        var game = games[i];
        if (game.teamA === team || game.teamB === team) {
            if (game.winner === team) {
                mapWinLoss[game.map][WIN] += 1;
            } else {
                mapWinLoss[game.map][LOSS] += 1;
            }
        }
    }
    console.log('');
    console.log('Summary:');
    console.log('team', '\t', 'wins', '\t', 'losses', '\t', '%')
    for (var map in mapWinLoss) {
        var per = Math.floor(mapWinLoss[map][WIN] / (mapWinLoss[map][WIN] + mapWinLoss[map][LOSS])*100);
        console.log(map, '\t', mapWinLoss[map][WIN], '\t', mapWinLoss[map][LOSS], '\t', per);
    }

}

module.exports.DataCollector = DataCollector;<|endoftext|>


<commit_before>(function() {

  var development = true,
      bounceEnable = false,
      logTip = null,
      qtips = {},
      currentTip,
      username,
      tweetlen = 140,
      bitlylen = 1 + 20,          // space + url
      menuVisible = false;

  var sendMessage = function() {
    var textarea = $('#ui-tooltip-everywhere-log textarea');
    var message = jQuery.trim(textarea.val());
    message = html_sanitize(message);
    if (message === "" || message.length > (tweetlen - bitlylen)) {
      return;
    }
    var url = esc(document.location.href);
    chrome.extension.sendRequest({ msgType: "update",
                                   url: url,
                                   message: message
                                 });
    textarea.val("");
    $('.everywhere-string-counter').text(tweetlen-bitlylen);
  };

  var esc = function(str){
    return str.replace(/</g, '<').replace(/>/g, '>');
  };

  var createTip = function(message) {
    var divprofile = $('
');
    divprofile.append('

');
    divprofile.append('
'+message.username+'
');
    // divprofile.append('
'+(message.realname||"")+'
');
    // divprofile.append('
'+(message.location||"")+'
');
    divprofile
      .append(
        $('
')
          .attr('class', 'everywhere-qtip-date')
          .text(howLongAgo(message.date)))
      .append(
        $('
')
          .attr('class', 'everywhere-qtip-message')
          .text(message.message))
      .append('
Reply
');

    return qtips[message.username] = $('a#'+message.username).qtip({
      id: 'everywhere-user-'+message.username,
      prerender: true,
      content: { text: divprofile.html() },
      position: { my: 'bottom right',
                  at: 'top left',
                  adjust: { screen: true, x: 20, y: 0 }
                },
      style: { classes: 'ui-tooltip-youtube',
               width: 200,
               tip: { corner: 'bottom right' }
             },
      show: { event: 'mouseenter', delay: 0 },
      hide: { event: 'unfocus', delay: 0 }
    }).qtip();
  };

  // dock

  var joinToDock = function(message) {
    var _username = esc(message.username);
    if ($('a#'+_username).length) {
      if (development) console.log('already joined: ' + _username);
      return;
    }
    if (development) console.log('join: ' + _username);

    // create dock item
    var item = $('');
    item.appendTo('.everywhere-dock-container');
    item.bind('mouseenter', function() {
      currentTip = $(this).attr('id');
      for (var i in qtips) qtips[i].hide();
      qtips[currentTip].show();
    });

    updateDock();

    // bounce the new item
    if (bounceEnable) {
      item.animate({ bottom: '60px' }, 400, 'easeInBack');
      item.animate({ bottom: '0px' }, 400, 'easeOutBack');
    }

    createTip(message);
  };

  var updateDock = function(message) {
    $('.everywhere-dock-item').each(function(index){
      $(this).css('right', 30*(index-1));
    });

    // show dock
    $('#everywhere-dock').animate({ bottom: '0px' }, 500);
    setTimeout(function() {
      $('#everywhere-dock').animate({ bottom: '-60px' }, 500);
    }, 2000);

    $('#everywhere-menu-button #everywhere-menu-counter').text($('.everywhere-dock-item').length);
  };

  // TODO
  var howLongAgo = function(prevDateString) {
    // var date = "";
    // var sec = Math.round((new Date() - new Date(prevDateString)) / 1000);
    // if (sec >= 60) {
    //   var min = Math.round(sec/60);
    //   if (min >= 60) {
    //     var hour = Math.round(min/60);
    //     if (hour >= 24) {
    //       date = prevDateString.substr(0, 24);
    //     } else {
    //       date = hour + ' hour ago';
    //     }
    //   } else {
    //     date = min + ' min ago';
    //   }
    // } else {
    //   date = sec + ' sec ago';
    // }
    // return date;
    if (typeof prevDateString === 'string') {
      return prevDateString.substr(0, 24);
    } else {
      return "";
    }
  };

  var createLogTip = function(log) {
    var text = "";
    if (log) {
      var divlog = $('

');
      for (var i = 0, len = log.length; i < len; i++) {
        divlog.append(makeMessage(log[i]));
        text = '
' + divlog.html() + '
';
      }
    } else {
      text = '

Post the first message on this page!

';
    }

    // add textarea
    text += '<textarea></textarea>'
      + '
'+(tweetlen-bitlylen)+'
'
      + '
<button class="everywhere-button" id="everywhere-log-send-button" type="button">Send</button>
';

    logTip = $('#everywhere-menu-button').qtip({
      id: 'everywhere-log',
      prerender: true,
      content: { text: text, title: { text: 'Everywhere!' } },
      position: { my: 'bottom right',
                  at: 'top left',
                  // type: 'fixed',
                  target: $('#everywhere-menu-button'),
                  adjust: { screen: true, x: 20, y: -5  }
                },
      style: { classes: 'ui-tooltip-youtube',
               width: 200,
               height: 300,
               tip: { corner: 'bottom right' }
             },
      show: false,
      hide: false
    }).qtip();
  };

  var makeMessage = function(message) {
    var date = howLongAgo(message.date);
    var divmessage = $('

');
    divmessage.append('

');
    divmessage.append('
'+message.username+'
');

    divmessage.append('
'+date+'
');
    if (message.message) {
      var ret = message.message.match(/http:\/\/bit\.ly.*/g);
      if (ret) {
        var text = jQuery.trim(RegExp.leftContext);
        text = esc(text);
        divmessage.append('
'+text+'
');
      } else {
        var text = esc(message.message);
        divmessage.append('
'+text+'
');
      }
    } else {
      divmessage.append('

');
    }
    return divmessage;
  };

  var reply = function() {
    if (logTip) {
      var textarea = logTip.elements.content.find('textarea');
      var replyTo = currentTip || $('#qtipManager').text();
      textarea.text('@'+replyTo+' ');
      logTip.show();
      textarea.focus();

      $('.everywhere-string-counter').text(tweetlen-bitlylen-(replyTo.length+2));

      var keydown = jQuery.Event("keydown");
      keydown.which = 40;
      textarea.trigger(keydown);
    }
  };

  var exitFromDock = function(obj) {
    $('a#' + obj.message.username).remove();
    $('#ui-tooltip-everywhere-user-' + obj.message.username).remove();
    delete(qtips[obj.message.username]);
    updateDock();
  };

  // initialize

  $('body')
    .append(
      $('
')
        .attr('id', 'everywhere-menu-button')
        .append(
          $('
')
            .attr('id', 'everywhere-menu-counter')))
    .append(
      $('
')
        .attr('id', 'everywhere-dock')
        .append(
          $('
')
            .attr('class', 'everywhere-dock-container')));

  $('#everywhere-dock').css({bottom: '-60px'});
  $('#everywhere-menu-button').click(function() {
    if (menuVisible) {
      $('#everywhere-dock').animate({ bottom: '-60px' }, 300);
      if (logTip) logTip.hide();
    } else {
      $('#everywhere-dock').animate({ bottom: '0px' }, 300);
      if (logTip) logTip.show();
      var qtiplog = $('.everywhere-qtip-log');
      qtiplog.scrollTop(qtiplog.height());
    }
    menuVisible = !menuVisible;
  });
  $('

').appendTo('body');
  $('#qtipManager').bind('reply', reply);

  chrome.extension.sendRequest({getUsername: true}, function(response) {
    username = response;
  });

  // add event handler
  var timer = setInterval(function() {
    if ($('#everywhere-log-send-button') && $('#everywhere-log-send-button').length === 1) {
      $('#everywhere-log-send-button').click(sendMessage);
      clearInterval(timer);

      $('#ui-tooltip-everywhere-log textarea').keyup(function() {
        var count = tweetlen-bitlylen-$(this).val().length;
        $('.everywhere-string-counter').text(count);
        if (count < 0) {
          $('.everywhere-string-counter').css('color', '#ff0000');
        } else {
          $('.everywhere-string-counter').css('color', '#e3e3e3');
        }
      });
    }
  }, 100);

  chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
    if (development) console.log(request);

    if (request.disconnected) {
      $('#everywhere-menu-button').css('background', 'rgba(255,0,0,0.8)');
      $('#everywhere-menu-button #everywhere-menu-counter').text('x');
    } else {
      $('#everywhere-menu-button').css('background', 'rgba(34,37,42,0.8)');
      $('#everywhere-menu-button #everywhere-menu-counter').text($('.everywhere-dock-item').length);
    }

    var msgType = request.msgType;
    switch(msgType) {

     case 'log':
      createLogTip(request.message.log);
      for (var i = 0, len = request.message.users.length; i < len; i++) {
        joinToDock(request.message.users[i]);
      }
      break;

     case 'join':
      if ($('#' + request.message.username).size() === 0) {
        joinToDock(request.message);
      }
      break;

     case 'update':
      var qtiplog = $('.everywhere-qtip-log');
      var msg = request.message;
      qtiplog.append(makeMessage(msg));
      //logTip.show();
      var height = 0;
      $('.everywhere-qtip-log-message').each(function(index) {
        height += $(this).height();
      });
      qtiplog.scrollTop(height);

      // update message of profile tip
      var tip = $('#ui-tooltip-everywhere-user-'+msg.username);
      tip.find('.everywhere-qtip-date').text(howLongAgo((msg.date)));
      tip.find('.everywhere-qtip-message').text(msg.message);

      // show the message sender's avator
      if (msg.username !== username) {
        if (!menuVisible) {
          $('a#'+msg.username).animate({ bottom: '60px' }, 300);
          setTimeout(function() {
            $('a#'+msg.username).animate({ bottom: '0px' }, 300);
          }, 2000);

          // show tip
          setTimeout(function() {
            tip.qtip().show();
            setTimeout(function() {
              tip.qtip().hide();
            }, 2000);
          }, 300);
        }
      }
      break;

     case 'exit':
      exitFromDock(request);
      break;

    default:
      break;

    }
  });

})();<commit_msg>add doc<commit_after>/**
 * Copyright (c) 2010 Masahiro Hayashi
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * Everywhere! <http://everywhere.no.de>
 */

(function() {

  var development = true,
      bounceEnable = false,
      logTip = null,
      qtips = {},
      currentTip,
      username,
      tweetlen = 140,
      bitlylen = 1 + 20,          // space + url
      menuVisible = false;

  var sendMessage = function() {
    var textarea = $('#ui-tooltip-everywhere-log textarea');
    var message = jQuery.trim(textarea.val());
    message = html_sanitize(message);
    if (message === "" || message.length > (tweetlen - bitlylen)) {
      return;
    }
    var url = esc(document.location.href);
    chrome.extension.sendRequest({ msgType: "update",
                                   url: url,
                                   message: message
                                 });
    textarea.val("");
    $('.everywhere-string-counter').text(tweetlen-bitlylen);
  };

  var esc = function(str){
    return str.replace(/</g, '<').replace(/>/g, '>');
  };

  var createTip = function(message) {
    var divprofile = $('
');
    divprofile.append('

');
    divprofile.append('
'+message.username+'
');
    // divprofile.append('
'+(message.realname||"")+'
');
    // divprofile.append('
'+(message.location||"")+'
');
    divprofile
      .append(
        $('
')
          .attr('class', 'everywhere-qtip-date')
          .text(howLongAgo(message.date)))
      .append(
        $('
')
          .attr('class', 'everywhere-qtip-message')
          .text(message.message))
      .append('
Reply
');

    return qtips[message.username] = $('a#'+message.username).qtip({
      id: 'everywhere-user-'+message.username,
      prerender: true,
      content: { text: divprofile.html() },
      position: { my: 'bottom right',
                  at: 'top left',
                  adjust: { screen: true, x: 20, y: 0 }
                },
      style: { classes: 'ui-tooltip-youtube',
               width: 200,
               tip: { corner: 'bottom right' }
             },
      show: { event: 'mouseenter', delay: 0 },
      hide: { event: 'unfocus', delay: 0 }
    }).qtip();
  };

  // dock

  var joinToDock = function(message) {
    var _username = esc(message.username);
    if ($('a#'+_username).length) {
      if (development) console.log('already joined: ' + _username);
      return;
    }
    if (development) console.log('join: ' + _username);

    // create dock item
    var item = $('');
    item.appendTo('.everywhere-dock-container');
    item.bind('mouseenter', function() {
      currentTip = $(this).attr('id');
      for (var i in qtips) qtips[i].hide();
      qtips[currentTip].show();
    });

    updateDock();

    // bounce the new item
    if (bounceEnable) {
      item.animate({ bottom: '60px' }, 400, 'easeInBack');
      item.animate({ bottom: '0px' }, 400, 'easeOutBack');
    }

    createTip(message);
  };

  var updateDock = function(message) {
    $('.everywhere-dock-item').each(function(index){
      $(this).css('right', 30*(index-1));
    });

    // show dock
    $('#everywhere-dock').animate({ bottom: '0px' }, 500);
    setTimeout(function() {
      $('#everywhere-dock').animate({ bottom: '-60px' }, 500);
    }, 2000);

    $('#everywhere-menu-button #everywhere-menu-counter').text($('.everywhere-dock-item').length);
  };

  // TODO
  var howLongAgo = function(prevDateString) {
    // var date = "";
    // var sec = Math.round((new Date() - new Date(prevDateString)) / 1000);
    // if (sec >= 60) {
    //   var min = Math.round(sec/60);
    //   if (min >= 60) {
    //     var hour = Math.round(min/60);
    //     if (hour >= 24) {
    //       date = prevDateString.substr(0, 24);
    //     } else {
    //       date = hour + ' hour ago';
    //     }
    //   } else {
    //     date = min + ' min ago';
    //   }
    // } else {
    //   date = sec + ' sec ago';
    // }
    // return date;
    if (typeof prevDateString === 'string') {
      return prevDateString.substr(0, 24);
    } else {
      return "";
    }
  };

  var createLogTip = function(log) {
    var text = "";
    if (log) {
      var divlog = $('

');
      for (var i = 0, len = log.length; i < len; i++) {
        divlog.append(makeMessage(log[i]));
        text = '
' + divlog.html() + '
';
      }
    } else {
      text = '

Post the first message on this page!

';
    }

    // add textarea
    text += '<textarea></textarea>'
      + '
'+(tweetlen-bitlylen)+'
'
      + '
<button class="everywhere-button" id="everywhere-log-send-button" type="button">Send</button>
';

    logTip = $('#everywhere-menu-button').qtip({
      id: 'everywhere-log',
      prerender: true,
      content: { text: text, title: { text: 'Everywhere!' } },
      position: { my: 'bottom right',
                  at: 'top left',
                  // type: 'fixed',
                  target: $('#everywhere-menu-button'),
                  adjust: { screen: true, x: 20, y: -5  }
                },
      style: { classes: 'ui-tooltip-youtube',
               width: 200,
               height: 300,
               tip: { corner: 'bottom right' }
             },
      show: false,
      hide: false
    }).qtip();
  };

  var makeMessage = function(message) {
    var date = howLongAgo(message.date);
    var divmessage = $('

');
    divmessage.append('

');
    divmessage.append('
'+message.username+'
');

    divmessage.append('
'+date+'
');
    if (message.message) {
      var ret = message.message.match(/http:\/\/bit\.ly.*/g);
      if (ret) {
        var text = jQuery.trim(RegExp.leftContext);
        text = esc(text);
        divmessage.append('
'+text+'
');
      } else {
        var text = esc(message.message);
        divmessage.append('
'+text+'
');
      }
    } else {
      divmessage.append('

');
    }
    return divmessage;
  };

  var reply = function() {
    if (logTip) {
      var textarea = logTip.elements.content.find('textarea');
      var replyTo = currentTip || $('#qtipManager').text();
      textarea.text('@'+replyTo+' ');
      logTip.show();
      textarea.focus();

      $('.everywhere-string-counter').text(tweetlen-bitlylen-(replyTo.length+2));

      var keydown = jQuery.Event("keydown");
      keydown.which = 40;
      textarea.trigger(keydown);
    }
  };

  var exitFromDock = function(obj) {
    $('a#' + obj.message.username).remove();
    $('#ui-tooltip-everywhere-user-' + obj.message.username).remove();
    delete(qtips[obj.message.username]);
    updateDock();
  };

  // initialize

  $('body')
    .append(
      $('
')
        .attr('id', 'everywhere-menu-button')
        .append(
          $('
')
            .attr('id', 'everywhere-menu-counter')))
    .append(
      $('
')
        .attr('id', 'everywhere-dock')
        .append(
          $('
')
            .attr('class', 'everywhere-dock-container')));

  $('#everywhere-dock').css({bottom: '-60px'});
  $('#everywhere-menu-button').click(function() {
    if (menuVisible) {
      $('#everywhere-dock').animate({ bottom: '-60px' }, 300);
      if (logTip) logTip.hide();
    } else {
      $('#everywhere-dock').animate({ bottom: '0px' }, 300);
      if (logTip) logTip.show();
      var qtiplog = $('.everywhere-qtip-log');
      qtiplog.scrollTop(qtiplog.height());
    }
    menuVisible = !menuVisible;
  });
  $('

').appendTo('body');
  $('#qtipManager').bind('reply', reply);

  chrome.extension.sendRequest({getUsername: true}, function(response) {
    username = response;
  });

  // add event handler
  var timer = setInterval(function() {
    if ($('#everywhere-log-send-button') && $('#everywhere-log-send-button').length === 1) {
      $('#everywhere-log-send-button').click(sendMessage);
      clearInterval(timer);

      $('#ui-tooltip-everywhere-log textarea').keyup(function() {
        var count = tweetlen-bitlylen-$(this).val().length;
        $('.everywhere-string-counter').text(count);
        if (count < 0) {
          $('.everywhere-string-counter').css('color', '#ff0000');
        } else {
          $('.everywhere-string-counter').css('color', '#e3e3e3');
        }
      });
    }
  }, 100);

  chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
    if (development) console.log(request);

    if (request.disconnected) {
      $('#everywhere-menu-button').css('background', 'rgba(255,0,0,0.8)');
      $('#everywhere-menu-button #everywhere-menu-counter').text('x');
    } else {
      $('#everywhere-menu-button').css('background', 'rgba(34,37,42,0.8)');
      $('#everywhere-menu-button #everywhere-menu-counter').text($('.everywhere-dock-item').length);
    }

    var msgType = request.msgType;
    switch(msgType) {

     case 'log':
      createLogTip(request.message.log);
      for (var i = 0, len = request.message.users.length; i < len; i++) {
        joinToDock(request.message.users[i]);
      }
      break;

     case 'join':
      if ($('#' + request.message.username).size() === 0) {
        joinToDock(request.message);
      }
      break;

     case 'update':
      var qtiplog = $('.everywhere-qtip-log');
      var msg = request.message;
      qtiplog.append(makeMessage(msg));
      //logTip.show();
      var height = 0;
      $('.everywhere-qtip-log-message').each(function(index) {
        height += $(this).height();
      });
      qtiplog.scrollTop(height);

      // update message of profile tip
      var tip = $('#ui-tooltip-everywhere-user-'+msg.username);
      tip.find('.everywhere-qtip-date').text(howLongAgo((msg.date)));
      tip.find('.everywhere-qtip-message').text(msg.message);

      // show the message sender's avator
      if (msg.username !== username) {
        if (!menuVisible) {
          $('a#'+msg.username).animate({ bottom: '60px' }, 300);
          setTimeout(function() {
            $('a#'+msg.username).animate({ bottom: '0px' }, 300);
          }, 2000);

          // show tip
          setTimeout(function() {
            tip.qtip().show();
            setTimeout(function() {
              tip.qtip().hide();
            }, 2000);
          }, 300);
        }
      }
      break;

     case 'exit':
      exitFromDock(request);
      break;

    default:
      break;

    }
  });

})();<|endoftext|>


<commit_before>(function(window) {

  var Lazy = window.Lazy;

  function NodeSequence(node) {
    this.node = node;
  }

  NodeSequence.prototype = new Lazy.Sequence();

  /**
   * Iterates over a DOM node's children and executes a function for each child.
   *
   * @param {function(Node):*} fn The function to call on each child.
   */
  NodeSequence.prototype.each = function(fn) {
    var children = this.node.childNodes,
        length   = children.length,
        i        = -1;

    while (++i < length) {
      if (fn(children[i], i) === false) {
        break;
      }
    }
  };

  NodeSequence.prototype.flatten = function() {
    return new FlattenedNodeSequence(this.node);
  };

  function FlattenedNodeSequence(node) {
    this.node = node;
  }

  FlattenedNodeSequence.prototype = new Lazy.Sequence();

  /**
   * Iterates over all of a DOM node's descendents (its children, and their
   * children, etc.) and executes a function for each descendent.
   *
   * @param {function(Node):*} fn The function to call on each descendent.
   */
  FlattenedNodeSequence.prototype.each = function(fn) {
    var done = false;

    Lazy(this.node).each(function(child) {
      if (fn(child) === false) {
        return false;
      }

      Lazy(child).flatten().each(function(descendent) {
        if (fn(descendent) === false) {
          done = true;
          return false;
        }
      });

      if (done) {
        return false;
      }
    });
  };

  function EventSequence(element, eventName) {
    this.element = element;
    this.eventName = eventName;
  }

  EventSequence.prototype = new Lazy.Sequence();

  /**
   * Handles every event in this sequence.
   *
   * @param {function(Event):*} fn The function to call on each event in the
   *     sequence. Return false from the function to stop handling the events.
   */
  EventSequence.prototype.each = function(fn) {
    var element = this.element,
        eventName = this.eventName;

    var listener = function(e) {
      if (fn(e) === false) {
        element.removeEventListener(eventName, listener);
      }
    };

    this.element.addEventListener(this.eventName, listener);
  };

  /**
   * Creates a {@link Sequence} from the specified DOM events triggered on the
   * given element. This sequence works asynchronously, so synchronous methods
   * such as {@code indexOf}, {@code any}, and {@code toArray} won't work.
   *
   * @param {Element} element The DOM element to capture events from.
   * @param {string} eventName The name of the event type (e.g., 'keypress')
   *     that will make up this sequence.
   * @return {Sequence} The sequence of events.
   */
  Lazy.events = function(element, eventName) {
    return new EventSequence(element, eventName);
  };

  var OriginalLazy = Lazy;

  /*
   * Assuming someone does:
   * <script src="lazy.js"></script>
   * <script src="lazy.dom.js"></script>
   *
   * Then they should be able to write:
   * Lazy(source)
   *
   * Where `source` can be a:
   * - Array
   * - Object
   * - String
   * - Node
   *
   * This function provides the last one, and then falls back to the original
   * 'Lazy' which provides the first three.
   */
  Lazy = function(source) {
    if (source instanceof Node) {
      return new NodeSequence(source);
    } else {
      return OriginalLazy(source);
    }
  };

  /*
   * Attach all of the same properties that Lazy already had.
   *
   * TODO: Think of a better approach here. This is really hacky.
   */
  for (var prop in OriginalLazy) {
    if (OriginalLazy.hasOwnProperty(prop)) {
      Lazy[prop] = OriginalLazy[prop];
    }
  }

  window.Lazy = Lazy;

}(window));
<commit_msg>fixed up NodeSequence (I think)<commit_after>(function(window) {

  var Lazy = window.Lazy;

  function NodeSequence(source) {
    this.source = source;
  }

  NodeSequence.prototype = new Lazy.ArrayLikeSequence();

  NodeSequence.prototype.get = function(i) {
    return this.source[i];
  };

  NodeSequence.prototype.length = function() {
    return this.source.length;
  };

  NodeSequence.prototype.flatten = function() {
    return new FlattenedNodeSequence(this.source);
  };

  function FlattenedNodeSequence(source) {
    this.source = source;
  }

  FlattenedNodeSequence.prototype = new Lazy.Sequence();

  /**
   * Iterates over all of a DOM node's descendents (its children, and their
   * children, etc.) and executes a function for each descendent.
   *
   * @param {function(Node):*} fn The function to call on each descendent.
   */
  FlattenedNodeSequence.prototype.each = function(fn) {
    var i    = 0,
        done = false;

    Lazy(this.source).each(function(child) {
      if (fn(child, i++) === false) {
        return false;
      }

      Lazy(child.children).flatten().each(function(descendent) {
        if (fn(descendent, i++) === false) {
          done = true;
          return false;
        }
      });

      if (done) {
        return false;
      }
    });
  };

  function EventSequence(element, eventName) {
    this.element = element;
    this.eventName = eventName;
  }

  EventSequence.prototype = new Lazy.Sequence();

  /**
   * Handles every event in this sequence.
   *
   * @param {function(Event):*} fn The function to call on each event in the
   *     sequence. Return false from the function to stop handling the events.
   */
  EventSequence.prototype.each = function(fn) {
    var element = this.element,
        eventName = this.eventName;

    var listener = function(e) {
      if (fn(e) === false) {
        element.removeEventListener(eventName, listener);
      }
    };

    this.element.addEventListener(this.eventName, listener);
  };

  /**
   * Creates a {@link Sequence} from the specified DOM events triggered on the
   * given element. This sequence works asynchronously, so synchronous methods
   * such as {@code indexOf}, {@code any}, and {@code toArray} won't work.
   *
   * @param {Element} element The DOM element to capture events from.
   * @param {string} eventName The name of the event type (e.g., 'keypress')
   *     that will make up this sequence.
   * @return {Sequence} The sequence of events.
   */
  Lazy.events = function(element, eventName) {
    return new EventSequence(element, eventName);
  };

  var OriginalLazy = Lazy;

  /*
   * Assuming someone does:
   * <script src="lazy.js"></script>
   * <script src="lazy.dom.js"></script>
   *
   * Then they should be able to write:
   * Lazy(source)
   *
   * Where `source` can be a:
   * - Array
   * - Object
   * - String
   * - NodeList or HTMLCollection
   *
   * This function provides the last one, and then falls back to the original
   * 'Lazy' which provides the first three.
   */
  Lazy = function(source) {
    if (source instanceof NodeList || source instanceof HTMLCollection) {
      return new NodeSequence(source);
    } else {
      return OriginalLazy(source);
    }
  };

  /*
   * Attach all of the same properties that Lazy already had.
   *
   * TODO: Think of a better approach here. This is really hacky.
   */
  for (var prop in OriginalLazy) {
    if (OriginalLazy.hasOwnProperty(prop)) {
      Lazy[prop] = OriginalLazy[prop];
    }
  }

  window.Lazy = Lazy;

}(window));
<|endoftext|>


<commit_before>/*
  lazyload.js: Image lazy loading

  Copyright (c) 2012 Vincent Voyer, http://fasterize.com

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

// Prevent double lazyload script on same page
// We NEED to use string as closure compiler would otherwise compile this statement badly
if (!window['lzld']) {
  (function(window, document){

    var pageHasLoaded = false, winH = viewport();

    // retro compatibility old lazyload
    window['lzld'] = (function() {
      var instance;
      return function() {
        if (!instance) instance = new Lazyload();
        else instance.apply(null, arguments);
      }
    }());

    window['Lazyload'] = Lazyload;

    addEvent(window, 'load', function loaded() {
      pageHasLoaded = true;
      winH = viewport();
    });

    addEvent(window, 'resize', throttle(function saveViewport() {
      winH = viewport();
    }, 50));

    /**
     * A new lazyloader, watching the whole window right now
     * @constructor
     * @param {Object=} opts Provide offset or lazyAttr or none
     */
    function Lazyload(opts) {
      this.opts = merge({
        offset: 200,
        lazyAttr: 'data-src'
      }, opts || {});

      this.imgs = [];
      this.listening = false;
      this.showImagesT = throttle(bind(this.showImages, this), 20)

      // init
      domready(bind(this.findImages, this));
      domready(bind(this.showImages, this));
      setTimeout(this.showImagesT, 25);

      addEvent(window, 'load', this.showImagesT);
      addEvent(window, 'load', partial(setTimeout, this.showImagesT, 25));

      // Bind events
      this.subscribe();

      // Override image element .getAttribute globally so that we give the real src
      // does not works for ie < 8: http://perfectionkills.com/whats-wrong-with-extending-the-dom/
      // Internet Explorer 7 (and below) [...] does not expose global Node, Element, HTMLElement, HTMLParagraphElement
      if ('HTMLImageElement' in window) {
        this.replaceGetAttribute();
      }

      return bind(this.onDataSrcImgLoad, this);
    }

    Lazyload.prototype.replaceGetAttribute = function replaceGetAttribute() {
      var original = HTMLImageElement.prototype.getAttribute;
      var lazyload = this;
      HTMLImageElement.prototype.getAttribute = function(name) {
        if(name === 'src') {
          var realSrc = original.call(this, lazyload.opts.lazyAttr);
          return realSrc || original.call(this, name);
        } else {
          // our own lazyloader will go through theses lines
          // because we use getAttribute(opts.lazyAttr)
          return original.call(this, name);
        }
      }
    }

    // called by img onload= or onerror= for IE6/7
    Lazyload.prototype.onDataSrcImgLoad = function onDataSrcImgLoad(img) {
      // if image is not already in the imgs array
      // it can already be in it if domready was fast and img onload slow
      if (inArray(img, this.imgs) === -1) {
        // this case happens when the page had loaded but we inserted more lazyload images with
        // javascript (ajax). We need to re-watch scroll/resize
        if (!this.listening) {
          this.subscribe();
        }
        this.showIfVisible(img, this.imgs.push(img) - 1);
      }
    }

    // find and merge images on domready with possibly already present onload= onerror= imgs
    Lazyload.prototype.findImages = function findImages() {
      var
        domreadyImgs = document.getElementsByTagName('img'),
        currentImg;

      // merge them with already self onload registered imgs
      for (var imgIndex = 0, max = domreadyImgs.length; imgIndex < max; imgIndex += 1) {
        currentImg = domreadyImgs[imgIndex];
        if (currentImg.getAttribute(this.opts.lazyAttr) && inArray(currentImg, this.imgs) === -1) {
          this.imgs.push(currentImg);
        }
      }
    }

    // img = dom element
    // index = imgs array index
    Lazyload.prototype.showIfVisible = function showIfVisible(img, index) {
      // We have to check that the current node is in the DOM
      // It could be a detached() dom node
      // http://bugs.jquery.com/ticket/4996
      if (contains(document.documentElement, img)
        && img.getBoundingClientRect().top < winH + this.opts.offset) {
        // To avoid onload loop calls
        // removeAttribute on IE is not enough to prevent the event to fire
        img.onload = null;
        img.removeAttribute('onload');
        // on IE < 8 we get an onerror event instead of an onload event
        img.onerror = null;
        img.removeAttribute('onerror');

        img.src = img.getAttribute(this.opts.lazyAttr);
        img.removeAttribute(this.opts.lazyAttr);
        this.imgs[index] = null;

        return true; // img shown
      } else {
        return false; // img to be shown
      }
    }

    // Loop through an images array to find to-be-shown images
    Lazyload.prototype.showImages = function showImages() {
      var
        last = this.imgs.length,
        current,
        allImagesDone = true;

      for (current = 0; current < last; current++) {
        var img = this.imgs[current];
        // if showIfVisible is false, it means we have some waiting images to be
        // shown
        if(img !== null && !this.showIfVisible(img, current)) {
          allImagesDone = false;
        }
      }

      if (allImagesDone && pageHasLoaded) {
        this.unsubscribe();
      }
    }

    Lazyload.prototype.unsubscribe = function unsubscribe() {
      removeEvent(window, 'scroll', this.showImagesT);
      this.listening = false;
    }

    Lazyload.prototype.subscribe = function subscribe() {
      addEvent(window, 'scroll', this.showImagesT);
      this.listening = true;
    }

    function bind (method, context){
      return function(){
        method.apply(context, arguments);
      }
    }

    function merge(defaults, opts) {
      for (var name in defaults) {
        if (opts[name] === undefined) {
          opts[name] = defaults[name];
        }
      }

      return opts;
    }

    function throttle(fn, minDelay) {
      var lastCall = 0;
      return function() {
        var now = +new Date();
        if (now - lastCall < minDelay) {
          return;
        }
        lastCall = now;
        // we do not return anything as
        // https://github.com/documentcloud/underscore/issues/387
        fn.apply(this, arguments);
      }
    }

    // X-browser
    function addEvent( el, type, fn ) {
      if (el.attachEvent) {
        el.attachEvent && el.attachEvent( 'on' + type, fn );
      } else {
        el.addEventListener( type, fn, false );
      }
    }

    // X-browser
    function removeEvent( el, type, fn ) {
      if (el.detachEvent) {
        el.detachEvent && el.detachEvent( 'on' + type, fn );
      } else {
        el.removeEventListener( type, fn, false );
      }
    }

    // custom domready function
    // ripped from https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js
    // http://javascript.nwbox.com/ContentLoaded/
    // http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
    // kept the inner logic, merged with our helpers/variables
    function domready(callback) {
      var
        done = false,
        top = true;

      function init(e) {
        if (e.type === 'readystatechange' && document.readyState !== 'complete') return;
        removeEvent((e.type === 'load' ? window : document), e.type, init);
        if (!done) {
          done = true;
          callback();
        }
      }

      function poll() {
        try { document.documentElement.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
        init('poll');
      }

      if (document.readyState === 'complete') callback();
      else {
        if (document.createEventObject && document.documentElement.doScroll) {
          try { top = !window.frameElement; } catch(e) { }
          if (top) poll();
        }
        addEvent(document, 'DOMContentLoaded', init);
        addEvent(document, 'readystatechange', init);
        addEvent(window, 'load', init);
      }

    }

    // cross browser viewport calculation
    function viewport() {
      // All new browsers
      if (document.documentElement.clientHeight >= 0) {
        return document.documentElement.clientHeight;
      // IE6/7/8 quirksmode
      } else if (document.body && document.body.clientHeight >= 0) {
        return document.body.clientHeight
      } else if (window.innerHeight >= 0) {
        return window.innerHeight;
      } else {
        return 0;
      }
    }

    // https://github.com/jquery/sizzle/blob/3136f48b90e3edc84cbaaa6f6f7734ef03775a07/sizzle.js#L708
    var contains = document.documentElement.compareDocumentPosition ?
      function( a, b ) {
        return !!(a.compareDocumentPosition( b ) & 16);
      } :
      document.documentElement.contains ?
      function( a, b ) {
        return a !== b && ( a.contains ? a.contains( b ) : false );
      } :
      function( a, b ) {
        while ( (b = b.parentNode) ) {
          if ( b === a ) {
            return true;
          }
        }
        return false;
      };

    // https://github.com/jquery/jquery/blob/f3515b735e4ee00bb686922b2e1565934da845f8/src/core.js#L610
    // We cannot use Array.prototype.indexOf because it's not always available
    function inArray(elem, array, i) {
      var len;

      if ( array ) {
        if ( Array.prototype.indexOf ) {
          return Array.prototype.indexOf.call( array, elem, i );
        }

        len = array.length;
        i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

        for ( ; i < len; i++ ) {
          // Skip accessing in sparse arrays
          if ( i in array && array[ i ] === elem ) {
            return i;
          }
        }
      }

      return -1;
    }

    function partial(fn /*, args...*/) {
      // A reference to the Array#slice method.
      var slice = Array.prototype.slice;
      // Convert arguments object to an array, removing the first argument.
      var args = slice.call(arguments, 1);

      return function() {
        // Invoke the originally-specified function, passing in all originally-
        // specified arguments, followed by any just-specified arguments.
        return fn.apply(this, args.concat(slice.call(arguments, 0)));
      };
    }

  }(this, document))
}
<commit_msg>Correct lzld => Lazyload<commit_after>/*
  lazyload.js: Image lazy loading

  Copyright (c) 2012 Vincent Voyer, http://fasterize.com

  Permission is hereby granted, free of charge, to any person obtaining
  a copy of this software and associated documentation files (the
  "Software"), to deal in the Software without restriction, including
  without limitation the rights to use, copy, modify, merge, publish,
  distribute, sublicense, and/or sell copies of the Software, and to
  permit persons to whom the Software is furnished to do so, subject to
  the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

*/

// Prevent double lazyload script on same page
// We NEED to use string as closure compiler would otherwise compile this statement badly
if (!window['Lazyload']) {
  (function(window, document){

    var pageHasLoaded = false, winH = viewport();

    // retro compatibility old lazyload
    // will automatically create an instance at first lzld call
    window['lzld'] = (function() {
      var instance;
      return function() {
        if (!instance) instance = new Lazyload();
        else instance.apply(null, arguments);
      }
    }());

    window['Lazyload'] = Lazyload;

    addEvent(window, 'load', function loaded() {
      pageHasLoaded = true;
      winH = viewport();
    });

    addEvent(window, 'resize', throttle(function saveViewport() {
      winH = viewport();
    }, 50));

    /**
     * A new lazyloader, watching the whole window right now
     * @constructor
     * @param {Object=} opts Provide offset or lazyAttr or none
     */
    function Lazyload(opts) {
      this.opts = merge({
        offset: 200,
        lazyAttr: 'data-src'
      }, opts || {});

      this.imgs = [];
      this.listening = false;
      this.showImagesT = throttle(bind(this.showImages, this), 20)

      // init
      domready(bind(this.findImages, this));
      domready(bind(this.showImages, this));
      setTimeout(this.showImagesT, 25);

      addEvent(window, 'load', this.showImagesT);
      addEvent(window, 'load', partial(setTimeout, this.showImagesT, 25));

      // Bind events
      this.subscribe();

      // Override image element .getAttribute globally so that we give the real src
      // does not works for ie < 8: http://perfectionkills.com/whats-wrong-with-extending-the-dom/
      // Internet Explorer 7 (and below) [...] does not expose global Node, Element, HTMLElement, HTMLParagraphElement
      if ('HTMLImageElement' in window) {
        this.replaceGetAttribute();
      }

      return bind(this.onDataSrcImgLoad, this);
    }

    Lazyload.prototype.replaceGetAttribute = function replaceGetAttribute() {
      var original = HTMLImageElement.prototype.getAttribute;
      var lazyload = this;
      HTMLImageElement.prototype.getAttribute = function(name) {
        if(name === 'src') {
          var realSrc = original.call(this, lazyload.opts.lazyAttr);
          return realSrc || original.call(this, name);
        } else {
          // our own lazyloader will go through theses lines
          // because we use getAttribute(opts.lazyAttr)
          return original.call(this, name);
        }
      }
    }

    // called by img onload= or onerror= for IE6/7
    Lazyload.prototype.onDataSrcImgLoad = function onDataSrcImgLoad(img) {
      // if image is not already in the imgs array
      // it can already be in it if domready was fast and img onload slow
      if (inArray(img, this.imgs) === -1) {
        // this case happens when the page had loaded but we inserted more lazyload images with
        // javascript (ajax). We need to re-watch scroll/resize
        if (!this.listening) {
          this.subscribe();
        }
        this.showIfVisible(img, this.imgs.push(img) - 1);
      }
    }

    // find and merge images on domready with possibly already present onload= onerror= imgs
    Lazyload.prototype.findImages = function findImages() {
      var
        domreadyImgs = document.getElementsByTagName('img'),
        currentImg;

      // merge them with already self onload registered imgs
      for (var imgIndex = 0, max = domreadyImgs.length; imgIndex < max; imgIndex += 1) {
        currentImg = domreadyImgs[imgIndex];
        if (currentImg.getAttribute(this.opts.lazyAttr) && inArray(currentImg, this.imgs) === -1) {
          this.imgs.push(currentImg);
        }
      }
    }

    // img = dom element
    // index = imgs array index
    Lazyload.prototype.showIfVisible = function showIfVisible(img, index) {
      // We have to check that the current node is in the DOM
      // It could be a detached() dom node
      // http://bugs.jquery.com/ticket/4996
      if (contains(document.documentElement, img)
        && img.getBoundingClientRect().top < winH + this.opts.offset) {
        // To avoid onload loop calls
        // removeAttribute on IE is not enough to prevent the event to fire
        img.onload = null;
        img.removeAttribute('onload');
        // on IE < 8 we get an onerror event instead of an onload event
        img.onerror = null;
        img.removeAttribute('onerror');

        img.src = img.getAttribute(this.opts.lazyAttr);
        img.removeAttribute(this.opts.lazyAttr);
        this.imgs[index] = null;

        return true; // img shown
      } else {
        return false; // img to be shown
      }
    }

    // Loop through an images array to find to-be-shown images
    Lazyload.prototype.showImages = function showImages() {
      var
        last = this.imgs.length,
        current,
        allImagesDone = true;

      for (current = 0; current < last; current++) {
        var img = this.imgs[current];
        // if showIfVisible is false, it means we have some waiting images to be
        // shown
        if(img !== null && !this.showIfVisible(img, current)) {
          allImagesDone = false;
        }
      }

      if (allImagesDone && pageHasLoaded) {
        this.unsubscribe();
      }
    }

    Lazyload.prototype.unsubscribe = function unsubscribe() {
      removeEvent(window, 'scroll', this.showImagesT);
      this.listening = false;
    }

    Lazyload.prototype.subscribe = function subscribe() {
      addEvent(window, 'scroll', this.showImagesT);
      this.listening = true;
    }

    function bind (method, context){
      return function(){
        method.apply(context, arguments);
      }
    }

    function merge(defaults, opts) {
      for (var name in defaults) {
        if (opts[name] === undefined) {
          opts[name] = defaults[name];
        }
      }

      return opts;
    }

    function throttle(fn, minDelay) {
      var lastCall = 0;
      return function() {
        var now = +new Date();
        if (now - lastCall < minDelay) {
          return;
        }
        lastCall = now;
        // we do not return anything as
        // https://github.com/documentcloud/underscore/issues/387
        fn.apply(this, arguments);
      }
    }

    // X-browser
    function addEvent( el, type, fn ) {
      if (el.attachEvent) {
        el.attachEvent && el.attachEvent( 'on' + type, fn );
      } else {
        el.addEventListener( type, fn, false );
      }
    }

    // X-browser
    function removeEvent( el, type, fn ) {
      if (el.detachEvent) {
        el.detachEvent && el.detachEvent( 'on' + type, fn );
      } else {
        el.removeEventListener( type, fn, false );
      }
    }

    // custom domready function
    // ripped from https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js
    // http://javascript.nwbox.com/ContentLoaded/
    // http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
    // kept the inner logic, merged with our helpers/variables
    function domready(callback) {
      var
        done = false,
        top = true;

      function init(e) {
        if (e.type === 'readystatechange' && document.readyState !== 'complete') return;
        removeEvent((e.type === 'load' ? window : document), e.type, init);
        if (!done) {
          done = true;
          callback();
        }
      }

      function poll() {
        try { document.documentElement.doScroll('left'); } catch(e) { setTimeout(poll, 50); return; }
        init('poll');
      }

      if (document.readyState === 'complete') callback();
      else {
        if (document.createEventObject && document.documentElement.doScroll) {
          try { top = !window.frameElement; } catch(e) { }
          if (top) poll();
        }
        addEvent(document, 'DOMContentLoaded', init);
        addEvent(document, 'readystatechange', init);
        addEvent(window, 'load', init);
      }

    }

    // cross browser viewport calculation
    function viewport() {
      // All new browsers
      if (document.documentElement.clientHeight >= 0) {
        return document.documentElement.clientHeight;
      // IE6/7/8 quirksmode
      } else if (document.body && document.body.clientHeight >= 0) {
        return document.body.clientHeight
      } else if (window.innerHeight >= 0) {
        return window.innerHeight;
      } else {
        return 0;
      }
    }

    // https://github.com/jquery/sizzle/blob/3136f48b90e3edc84cbaaa6f6f7734ef03775a07/sizzle.js#L708
    var contains = document.documentElement.compareDocumentPosition ?
      function( a, b ) {
        return !!(a.compareDocumentPosition( b ) & 16);
      } :
      document.documentElement.contains ?
      function( a, b ) {
        return a !== b && ( a.contains ? a.contains( b ) : false );
      } :
      function( a, b ) {
        while ( (b = b.parentNode) ) {
          if ( b === a ) {
            return true;
          }
        }
        return false;
      };

    // https://github.com/jquery/jquery/blob/f3515b735e4ee00bb686922b2e1565934da845f8/src/core.js#L610
    // We cannot use Array.prototype.indexOf because it's not always available
    function inArray(elem, array, i) {
      var len;

      if ( array ) {
        if ( Array.prototype.indexOf ) {
          return Array.prototype.indexOf.call( array, elem, i );
        }

        len = array.length;
        i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

        for ( ; i < len; i++ ) {
          // Skip accessing in sparse arrays
          if ( i in array && array[ i ] === elem ) {
            return i;
          }
        }
      }

      return -1;
    }

    function partial(fn /*, args...*/) {
      // A reference to the Array#slice method.
      var slice = Array.prototype.slice;
      // Convert arguments object to an array, removing the first argument.
      var args = slice.call(arguments, 1);

      return function() {
        // Invoke the originally-specified function, passing in all originally-
        // specified arguments, followed by any just-specified arguments.
        return fn.apply(this, args.concat(slice.call(arguments, 0)));
      };
    }

  }(this, document))
}
<|endoftext|>


<commit_before>angular
  .module('lnPatterns')
  .controller('lnMAdminBarController', lnMAdminBarController);

lnMAdminBarController.$inject = ['$log', '$rootScope', '$scope', '$cookies', '$timeout', '$element', 'lnMAdminBarService'];

var STATUS = {
  INIT: 0,
  LOADING: 1,
  LOADED: 2
};

function lnMAdminBarController($log, $rootScope, $scope, $cookies, $timeout, $element, lnMAdminBarService) {
  var vm = this;
  var status = STATUS.INIT;
  var loginCookie = '';

  if (vm.lnLoadFromApi) {
    _disableAdminBar();
    _loginCheck();
  } else {
    _enableAdminBar();
  }

  /////////

  function _loginCheck() {
    loginCookie = $cookies.get('wp_admin_bar_user') || '';
    _reviewStatus();
    $timeout(_loginCheck, 5000);
  }

  function _reviewStatus(){
    if (status === STATUS.INIT && loginCookie !== '') {
      _loadData();
    }

    if ((status === STATUS.LOADING || status === STATUS.LOADED) && loginCookie === '') {
      status = STATUS.INIT;
      _disableAdminBar();
    }
  }

  function _loadData() {
    if (lnMAdminBarService.getApiUrl() !== '') {
      status = STATUS.LOADING;

      lnMAdminBarService
        .getAdminBarData()
        .then(_configureAdminBar, _logError);
    }
  }

  function _configureAdminBar(response) {
    if (response.data && status === STATUS.LOADING) {
      status = STATUS.LOADED;

      vm.lnSiteName = response.data.site_name;
      vm.lnUserName = response.data.user_name || loginCookie;
      vm.lnDashboardUrl = response.data.dashboard_url;
      vm.lnLogoutUrl = response.data.logout_url;
      vm.lnEditPageUrl = response.data.edit_page_url;
      vm.lnNewItemTypes = response.data.post_types;
      vm.lnUserNicename = angular.isDefined( response.data.nicename ) ? response.data.nicename : '';
      vm.lnUserDisplayName = angular.isDefined( response.data.display_name ) ? response.data.display_name : '';
      vm.lnUserFirstName = angular.isDefined( response.data.first_name ) ? response.data.first_name : '';
      vm.lnUserLastName = angular.isDefined( response.data.last_name ) ? response.data.last_name : '';
      vm.lnUserEmail = angular.isDefined( response.data.email ) ? response.data.email : '';

      _enableAdminBar();
    }
  }

  function _logError(error) {
    $log.error('lnMAdminBarService.getAdminBarData() -> error: ', error);
  }

  function _enableAdminBar() {
    vm.adminBarEnabled = true;
    $element.removeClass('ng-hide');
    $rootScope.$broadcast('lnMAdminBarEnabled');
  }

  function _disableAdminBar() {
    vm.adminBarEnabled = false;
    $element.addClass('ng-hide');
    $rootScope.$broadcast('lnMAdminBarDisabled');
  }
}
<commit_msg>Send the value of the API response with the events<commit_after>angular
  .module('lnPatterns')
  .controller('lnMAdminBarController', lnMAdminBarController);

lnMAdminBarController.$inject = ['$log', '$rootScope', '$scope', '$cookies', '$timeout', '$element', 'lnMAdminBarService'];

var STATUS = {
  INIT: 0,
  LOADING: 1,
  LOADED: 2
};

function lnMAdminBarController($log, $rootScope, $scope, $cookies, $timeout, $element, lnMAdminBarService) {
  var vm = this;
  var status = STATUS.INIT;
  var loginCookie = '';

  if (vm.lnLoadFromApi) {
    _disableAdminBar();
    _loginCheck();
  } else {
    _enableAdminBar();
  }

  /////////

  function _loginCheck() {
    loginCookie = $cookies.get('wp_admin_bar_user') || '';
    _reviewStatus();
    $timeout(_loginCheck, 5000);
  }

  function _reviewStatus(){
    if (status === STATUS.INIT && loginCookie !== '') {
      _loadData();
    }

    if ((status === STATUS.LOADING || status === STATUS.LOADED) && loginCookie === '') {
      status = STATUS.INIT;
      _disableAdminBar();
    }
  }

  function _loadData() {
    if (lnMAdminBarService.getApiUrl() !== '') {
      status = STATUS.LOADING;

      lnMAdminBarService
        .getAdminBarData()
        .then(_configureAdminBar, _logError);
    }
  }

  function _configureAdminBar(response) {
    if (response.data && status === STATUS.LOADING) {
      status = STATUS.LOADED;

      vm.lnSiteName = response.data.site_name;
      vm.lnUserName = response.data.user_name || loginCookie;
      vm.lnDashboardUrl = response.data.dashboard_url;
      vm.lnLogoutUrl = response.data.logout_url;
      vm.lnEditPageUrl = response.data.edit_page_url;
      vm.lnNewItemTypes = response.data.post_types;
      vm.lnUserNicename = angular.isDefined( response.data.nicename ) ? response.data.nicename : '';
      vm.lnUserDisplayName = angular.isDefined( response.data.display_name ) ? response.data.display_name : '';
      vm.lnUserFirstName = angular.isDefined( response.data.first_name ) ? response.data.first_name : '';
      vm.lnUserLastName = angular.isDefined( response.data.last_name ) ? response.data.last_name : '';
      vm.lnUserEmail = angular.isDefined( response.data.email ) ? response.data.email : '';

      _enableAdminBar();
    }
  }

  function _logError(error) {
    $log.error('lnMAdminBarService.getAdminBarData() -> error: ', error);
  }

  function _enableAdminBar() {
    vm.adminBarEnabled = true;
    $element.removeClass('ng-hide');
    $rootScope.$broadcast('lnMAdminBarEnabled', vm);
  }

  function _disableAdminBar() {
    vm.adminBarEnabled = false;
    $element.addClass('ng-hide');
    $rootScope.$broadcast('lnMAdminBarDisabled', {});
  }
}
<|endoftext|>


<commit_before>/* @flow strict-local */

import React, { PureComponent } from 'react';
import { AppState, NetInfo, View, StyleSheet, Platform, NativeModules } from 'react-native';
import SafeArea from 'react-native-safe-area';
import Orientation from 'react-native-orientation';

import type { Node as React$Node } from 'react';
import type { Dispatch, Orientation as OrientationT } from '../types';
import { connect } from '../react-redux';
import { getUnreadByHuddlesMentionsAndPMs } from '../selectors';
import { handleInitialNotification, NotificationListener } from '../notification';
import {
  appOnline,
  appOrientation,
  appState,
  initSafeAreaInsets,
  reportPresence,
} from '../actions';

const styles = StyleSheet.create({
  wrapper: {
    flex: 1,
    flexDirection: 'column',
    alignItems: 'stretch',
  },
});

type Props = {|
  dispatch: Dispatch,
  children: React$Node,
  unreadCount: number,
|};

class AppEventHandlers extends PureComponent<Props> {
  handleOrientationChange = (orientation: OrientationT) => {
    const { dispatch } = this.props;
    dispatch(appOrientation(orientation));
  };

  handleConnectivityChange = connectionInfo => {
    const { dispatch } = this.props;
    const isConnected = connectionInfo.type !== 'none' && connectionInfo.type !== 'unknown';
    dispatch(appOnline(isConnected));
  };

  handleAppStateChange = state => {
    const { dispatch, unreadCount } = this.props;
    dispatch(reportPresence(state === 'active'));
    dispatch(appState(state === 'active'));
    if (state === 'background' && Platform.OS === 'android') {
      NativeModules.BadgeCountUpdaterModule.setBadgeCount(unreadCount);
    }
  };

  notificationListener = new NotificationListener(this.props.dispatch);

  handleMemoryWarning = () => {
    // Release memory here
  };

  componentDidMount() {
    const { dispatch } = this.props;
    handleInitialNotification(dispatch);

    NetInfo.addEventListener('connectionChange', this.handleConnectivityChange);
    AppState.addEventListener('change', this.handleAppStateChange);
    AppState.addEventListener('memoryWarning', this.handleMemoryWarning);
    SafeArea.getSafeAreaInsetsForRootView().then(params =>
      dispatch(initSafeAreaInsets(params.safeAreaInsets)),
    );
    // $FlowFixMe: libdef wrongly says callback's parameter is optional
    Orientation.addOrientationListener(this.handleOrientationChange);
    this.notificationListener.start();
  }

  componentWillUnmount() {
    NetInfo.removeEventListener('connectionChange', this.handleConnectivityChange);
    AppState.removeEventListener('change', this.handleAppStateChange);
    AppState.removeEventListener('memoryWarning', this.handleMemoryWarning);
    // $FlowFixMe: libdef wrongly says callback's parameter is optional
    Orientation.removeOrientationListener(this.handleOrientationChange);
    this.notificationListener.stop();
  }

  render() {
    return <View style={styles.wrapper}>{this.props.children}</View>;
  }
}

export default connect(state => ({
  unreadCount: getUnreadByHuddlesMentionsAndPMs(state),
}))(AppEventHandlers);
<commit_msg>flow: Add types to handleAppStateChange<commit_after>/* @flow strict-local */

import React, { PureComponent } from 'react';
import { AppState, NetInfo, View, StyleSheet, Platform, NativeModules } from 'react-native';
import SafeArea from 'react-native-safe-area';
import Orientation from 'react-native-orientation';

import type { Node as React$Node } from 'react';
import type { Dispatch, Orientation as OrientationT } from '../types';
import { connect } from '../react-redux';
import { getUnreadByHuddlesMentionsAndPMs } from '../selectors';
import { handleInitialNotification, NotificationListener } from '../notification';
import {
  appOnline,
  appOrientation,
  appState,
  initSafeAreaInsets,
  reportPresence,
} from '../actions';

const styles = StyleSheet.create({
  wrapper: {
    flex: 1,
    flexDirection: 'column',
    alignItems: 'stretch',
  },
});

type Props = {|
  dispatch: Dispatch,
  children: React$Node,
  unreadCount: number,
|};

class AppEventHandlers extends PureComponent<Props> {
  handleOrientationChange = (orientation: OrientationT) => {
    const { dispatch } = this.props;
    dispatch(appOrientation(orientation));
  };

  handleConnectivityChange = connectionInfo => {
    const { dispatch } = this.props;
    const isConnected = connectionInfo.type !== 'none' && connectionInfo.type !== 'unknown';
    dispatch(appOnline(isConnected));
  };

  /** https://facebook.github.io/react-native/docs/appstate */
  handleAppStateChange = (state: 'active' | 'background' | 'inactive') => {
    const { dispatch, unreadCount } = this.props;
    dispatch(reportPresence(state === 'active'));
    dispatch(appState(state === 'active'));
    if (state === 'background' && Platform.OS === 'android') {
      NativeModules.BadgeCountUpdaterModule.setBadgeCount(unreadCount);
    }
  };

  notificationListener = new NotificationListener(this.props.dispatch);

  handleMemoryWarning = () => {
    // Release memory here
  };

  componentDidMount() {
    const { dispatch } = this.props;
    handleInitialNotification(dispatch);

    NetInfo.addEventListener('connectionChange', this.handleConnectivityChange);
    AppState.addEventListener('change', this.handleAppStateChange);
    AppState.addEventListener('memoryWarning', this.handleMemoryWarning);
    SafeArea.getSafeAreaInsetsForRootView().then(params =>
      dispatch(initSafeAreaInsets(params.safeAreaInsets)),
    );
    // $FlowFixMe: libdef wrongly says callback's parameter is optional
    Orientation.addOrientationListener(this.handleOrientationChange);
    this.notificationListener.start();
  }

  componentWillUnmount() {
    NetInfo.removeEventListener('connectionChange', this.handleConnectivityChange);
    AppState.removeEventListener('change', this.handleAppStateChange);
    AppState.removeEventListener('memoryWarning', this.handleMemoryWarning);
    // $FlowFixMe: libdef wrongly says callback's parameter is optional
    Orientation.removeOrientationListener(this.handleOrientationChange);
    this.notificationListener.stop();
  }

  render() {
    return <View style={styles.wrapper}>{this.props.children}</View>;
  }
}

export default connect(state => ({
  unreadCount: getUnreadByHuddlesMentionsAndPMs(state),
}))(AppEventHandlers);
<|endoftext|>


<commit_before>var assert = require('assert');
var path = require('path');
var Logger = require('../../src/helpers/logger');
require('colors');

global.args = {};
global.log = new Logger();

describe('#auto generate ssl certificate', function () {
  var proxyServer = null;
  before(function () {
    var Proxy = require('../../src/index');
    proxyServer = new Proxy(8859, 10022);
    proxyServer.addRewriteFile(path.join(__dirname, 'rewrite'));
    proxyServer.start();
  });

  it('should auto generate certificate', function (done) {
    var https = require('https');
    var options = {
      host: '127.0.0.1',
      port: 10022,
      path: 'https://example.io/',
      method: 'GET',
      headers: {
        'Host': 'example.io'
      },
      rejectUnauthorized: false
    };

    var req = https.request(options, function (res) {
      var certInfo = res.connection.getPeerCertificate(true);
      var subject = certInfo.subject;
      var issuer = certInfo.issuer;

      // subject
      // {
      //   CN: 'example.io',
      //   C: 'CN',
      //   ST: 'Bei Jing',
      //   L: 'Hai Dian',
      //   O: 'Hiproxy',
      //   OU: 'Development'
      // }
      // issuer
      // {
      //   CN: 'Hiproxy Custom CA',
      //   C: 'CN',
      //   ST: 'Bei Jing',
      //   L: 'Hai Dian',
      //   O: 'Hiproxy',
      //   OU: 'Development'
      // }
      assert(subject.CN, 'example.io');
      assert(issuer.CN, 'Hiproxy Custom CA');
      done();
    });

    req.on('error', function (err) {
      done(err);
    });

    req.end();
  });

  after(function () {
    proxyServer.stop();
  });
});
<commit_msg>update port<commit_after>var assert = require('assert');
var path = require('path');
var Logger = require('../../src/helpers/logger');
require('colors');

global.args = {};
global.log = new Logger();

describe('#auto generate ssl certificate', function () {
  var proxyServer = null;
  before(function () {
    var Proxy = require('../../src/index');
    proxyServer = new Proxy(8859, 10086);
    proxyServer.addRewriteFile(path.join(__dirname, 'rewrite'));
    proxyServer.start();
  });

  it('should auto generate certificate', function (done) {
    var https = require('https');
    var options = {
      host: '127.0.0.1',
      port: 10086,
      path: 'https://example.io/',
      method: 'GET',
      headers: {
        'Host': 'example.io'
      },
      rejectUnauthorized: false
    };

    var req = https.request(options, function (res) {
      var certInfo = res.connection.getPeerCertificate(true);
      var subject = certInfo.subject;
      var issuer = certInfo.issuer;

      // subject
      // {
      //   CN: 'example.io',
      //   C: 'CN',
      //   ST: 'Bei Jing',
      //   L: 'Hai Dian',
      //   O: 'Hiproxy',
      //   OU: 'Development'
      // }
      // issuer
      // {
      //   CN: 'Hiproxy Custom CA',
      //   C: 'CN',
      //   ST: 'Bei Jing',
      //   L: 'Hai Dian',
      //   O: 'Hiproxy',
      //   OU: 'Development'
      // }
      assert(subject.CN, 'example.io');
      assert(issuer.CN, 'Hiproxy Custom CA');
      done();
    });

    req.on('error', function (err) {
      done(err);
    });

    req.end();
  });

  after(function () {
    proxyServer.stop();
  });
});
<|endoftext|>