<commit_before>/**
 * Created by Ady on 12/27/2014.
 */
var http = require('http');
var Q = require('q');
var Class = require('./Class.js').Class;
const events = require('events');
const util = require('util');
const request = require('request');
const formidable = require('formidable');
const _ = require('underscore');
var Bot = require('./bot.js');
var AdminBot = require('./adminBot.js');
var fs = require('fs');
var mongoData = require('./data/mongoData.js')(process.env['MONGOLAB_URI']);
var roomPrefs = require('./data/roomPrefs.js');

var BotsManager = Class.extend(function () {

    return {
        init: function (options) {
            this.options = options;
console.log(options)
            this.allBots=[];
            var e = new events.EventEmitter();
            _.extend(this, e);
            console.log('bot manager', this.options);
            this.startListening();
            /*.then(this.killAllBots.bind(this))*/
            this.getAllBots().then(this.registerMissingBots.bind(this));
            this.timerInterval=setInterval(function(){this.onTimeTick()}.bind(this),1*60*1000);
        },
        onTimeTick: function(){
            roomPrefs.getAllRoomPrefs().then(function(rooms){

               try{ _.each(rooms,function(room){
                    if (room.warData.inWar){
                      //  console.log('onTick',room.roomId,this.allBots);
                        var botObj = _.findWhere(this.allBots, {group_id: room.roomId+''});
                        if (botObj && botObj.manager && botObj.manager.onTimeTick){
                            botObj.manager.onTimeTick(room);
                        }
                    }
                }.bind(this));}
                catch(e){console.warn('error',e);}

            }.bind(this));

        },
        getAllBots: function () {
            var deferred = Q.defer();

            var url = 'https://api.groupme.com/v3/bots?token=' + this.options.token;
            request({url: url, method: 'GET'}, function (err, response, body) {
                body = JSON.parse(body);
                var bots = [];
                _.each(body.response, function (bot) {
                    bots.push(bot);
                });
                this.allBots = bots;

                deferred.resolve(bots);
            }.bind(this));

            return deferred.promise;
        },
        killAllBots: function () {
            var deferred = Q.defer();
            var that = this;
            var unregArray=[];
            try {
                _.each(this.allBots, function (bot) {
                    unregArray.push(that.unregisterBot(bot.bot_id));
                });
            }
            catch (e) {
                console.log('------->',e);
            }
            Q.all(unregArray).then(function(){
                this.allBots = [];
                deferred.resolve( this.allBots);
            }.bind(this))

            return deferred.promise;
        },
        registerMissingBots: function () {
            var self=this;
            var deferred = Q.defer();
            console.log('register bots');
            mongoData.getSettings().then(function(settings){
                var guilds = settings.guilds;
               console.log('got settings',settings,guilds);
                var adminGroup=self.options.adminGroup;
                try {
                    if (_.find(guilds, function (guild) {
                            guild.roomId + '' == adminGroup + '';
                        })==null) {
                        guilds.push({
                            roomId:adminGroup,
                            guildName:'Admin',
                            guildId:''
                        });
                    }
                }catch(e){console.log(e);}
                //console.log('register',groupIds);
                var registerArr=[];
                _.each(guilds, function (guild) {
                   try {
                       var botObj=_.findWhere(this.allBots, {group_id: Number(guild.roomId)});
                       if (botObj == undefined) {
                           registerArr.push(this.registerBotAndCreateManager(guild.roomId));
                       }else{
                           registerArr.push(this.createManager(guild.roomId,botObj));
                       }
                   }catch(e){}
                }.bind(this));
                Q.all(registerArr).then(function(){
                    deferred.resolve();
                })
            }.bind(this))

            return deferred.promise;
        },
        unregisterBot: function (botId) {
            console.log('unregister', botId);
            var deferred = Q.defer();
            var url = 'https://api.groupme.com/v3/bots/destroy?token=' + this.options.token;
            request({url: url, method: 'POST', body: JSON.stringify({bot_id: botId})},
                function (error, response, body) {
                    deferred.resolve();
                }.bind(this));
            return deferred.promise;
        },
        createManager : function(groupIdx,botObj){
            var manager = this.options.adminGroup==groupIdx? new AdminBot(botObj, groupIdx) : new Bot(botObj, groupIdx);
            manager.on('botRegister',function(ctx,guild){
                var botObj = _.findWhere(this.allBots, {group_id: guild.roomId});
                if (botObj==undefined) {
                    this.registerBotAndCreateManager(guild.roomId).then(function (newBot) {
                        ctx.botRegistered(guild.roomId);
                        newBot.postMessage('RavenBot is successfully registered in this room.\nRaven Manual:\nhttps://docs.google.com/document/d/15naOzWKf9z9CT-D4hHZTryTE55l4HyNiR8sahye0TzU/edit');
                        this.addGroupToSettings(guild);
                    }.bind(this));
                }else{
                    ctx.postMessage('Bot already registered');
                }

            }.bind(this));
            manager.on('botUnregister',function(ctx,groupId){
                var botObj = _.findWhere(this.allBots, {group_id: groupId});
                if (botObj!=undefined) {
                    botObj.manager.postMessage('Bye.');
                    this.allBots = _.filter(this.allBots, function (bot) {
                        return bot.group_id != groupId;
                    });
                    this.removeGroupFromSettings(groupId);
                    this.unregisterBot(botObj.bot_id).then(function () {
                        ctx.botUnregistered(groupId);

                    }.bind(this));
                }else{
                    ctx.postMessage('Bot is not registered');

                }

            }.bind(this));
            manager.on('broadcast',function(ctx,broadcastObj){
                this.broadCast(ctx,broadcastObj.guild,broadcastObj.msg);

            }.bind(this));
            var botResponse = response.response.bot;
            botResponse.manager = manager;
            this.allBots.push(botResponse);
            return manager;
        },
        registerBotAndCreateManager: function(groupId){
            var deferred = Q.defer();
            this.registerBot(groupId).then(function (data) {
                var response=data.response;
                var groupIdx=data.groupId;
                if (response.meta.code > 200 && response.meta.code < 300) {
                    try {
                        var botObj=response.response.bot;
                        var manager=createManager(groupIdx,botObj);
                        deferred.resolve(manager);
                    } catch (e) {
                        console.log('------->', e);
                        deferred.reject(e);
                    }
                }

            }.bind(this)).fail(function(e){
                console.log('--------------->>>>',e);

            });
            return deferred.promise;
        },
        broadCast: function(ctx,group,msg){
            if (group=='all'){
                _.each(this.allBots,function(bot){
                    if (bot.group_id!=this.options.adminGroup) {
                        bot.manager.postMessage(msg);
                    }
                }.bind(this));
                ctx.postMessage('Msg sent.');
            }
            else{
                var botObj = _.findWhere(this.allBots, {group_id: group});
                if (botObj==undefined) {
                 ctx.postMessage('Group not found.');
                }
                else{
                    botObj.manager.postMessage(msg);
                    ctx.postMessage('Msg sent.');
                }
            }

        },
        registerBot: function (groupId) {
            var deferred = Q.defer();
            var bot = {};
            bot.name = this.options.name;
            bot.group_id = groupId;
            bot.callback_url = this.options.url + '/incoming';
            if (this.options.avatar_url) {
                bot.avatar_url = this.options.avatar_url;
            }
            ;
            var url = 'https://api.groupme.com/v3/bots?token=' + this.options.token;

            request({url: url, method: 'POST', body: JSON.stringify({bot: bot})},
                function (error, response, body) {
                    if (!error) {
                      try {
                          var parsedBody = JSON.parse(body);
                          deferred.resolve({response: parsedBody, groupId: groupId});
                      }
                    catch(e){
                        deferred.reject(e);

                      }

                    } else {
                        deferred.reject(error);
                    }
                }.bind(this)
            );
            return deferred.promise;
        },
        handleMessage: function (self, msg) {
            /*{
             "id": "1234567890",
             "source_guid": "GUID",
             "created_at": 1302623328,
             "user_id": "1234567890",
             "group_id": "1234567890",
             "name": "John",
             "avatar_url": "http://i.groupme.com/123456789",
             "text": "Hello world ☃☃",
             "system": true,
             "favorited_by": [
             "101",
             "66",
             "1234567890"
             ],
             "attachments": []
             }*/
            var groupId = msg.group_id;
            if (msg.name != self.options.name) {
                var botObj = _.findWhere(this.allBots, {group_id: groupId});
                if (botObj==undefined){
                    console.log('couldnt find a bot to handle:',msg)
                    return;

                }else {
                  try {
                      botObj.manager.handleMessage(msg);
                  }catch(e){
                      console.warn('FATAL ERROR : ',e);

                  }
                }
            }
        },
        startListening: function () {
            var self = this;

            this.on('botMessage', this.handleMessage.bind(this));

                var self = this;
                //console.log(JSON.stringify({'name': self.options.name, 'groups': settings.groups}));
                var server = http.createServer(function (request, response) {
                    if (request.url == '/' && request.method == 'GET') {
                        response.writeHead(200, {"Content-Type": "application/json"});
                        response.end(JSON.stringify({'name': self.options.name}));
                    } else if (request.url == '/images/raven.jpeg') {
                        var img = fs.readFileSync('./images/raven.jpeg');
                        response.writeHead(200, {'Content-Type': 'image/jpeg'});
                        response.end(img, 'binary');
                    } else if (request.url == '/incoming' && request.method == 'POST') {
                        var form = new formidable.IncomingForm();
                        var messageFields = {};
                        form.parse(request, function (err, fields, files) {
                            if (err) console.error("bad incoming data " + err);
                        });

                        form.on('field', function (name, value) {
                            messageFields[name] = value;
                        });

                        form.on('end', function () {
                            response.writeHead(200, {"Content-Type": "text/plain"});
                            response.end("THANKS");
                            self.emit('botMessage', self, messageFields);
                        });

                    } else {
                        response.writeHead(404, {"Content-Type": "text/plain"});
                        response.end("NOT FOUND");
                    }

                }.bind(this));

                server.listen(self.options.port);
                console.log('server up');

        },
        addGroupToSettings: function(guild){
            mongoData.getSettings().then(function(settings){
                var guilds = settings.guilds;
                if (!_.findWhere(guilds,{roomId:Number(guild.roomId)})){
                    guilds.push({
                        roomId:guild.roomId,
                        guildName:guild.guildName,
                        guildId:guild.guildId

                    });
                    settings.guilds=guilds;
                    settings.save();
                }
            })

        },
        removeGroupFromSettings: function(groupId){
            mongoData.getSettings().then(function(settings){
                var guilds = settings.guilds;
                if (_.findWhere(guilds,{roomId:Number(groupId)})){
                    guilds = _.filter(guilds,function(guild){
                        return guild.roomId!=groupId;
                    })
                    settings.guilds=guilds;
                    settings.save();
                }
            })

        }
    }
}());

module.exports = function (options) {
    var md = new BotsManager(options);

    return md;
};<commit_msg>fix bot rooms init<commit_after>/**
 * Created by Ady on 12/27/2014.
 */
var http = require('http');
var Q = require('q');
var Class = require('./Class.js').Class;
const events = require('events');
const util = require('util');
const request = require('request');
const formidable = require('formidable');
const _ = require('underscore');
var Bot = require('./bot.js');
var AdminBot = require('./adminBot.js');
var fs = require('fs');
var mongoData = require('./data/mongoData.js')(process.env['MONGOLAB_URI']);
var roomPrefs = require('./data/roomPrefs.js');

var BotsManager = Class.extend(function () {

    return {
        init: function (options) {
            this.options = options;
console.log(options)
            this.allBots=[];
            var e = new events.EventEmitter();
            _.extend(this, e);
            console.log('bot manager', this.options);
            this.startListening();
            /*.then(this.killAllBots.bind(this))*/
            this.getAllBots().then(this.registerMissingBots.bind(this));
            this.timerInterval=setInterval(function(){this.onTimeTick()}.bind(this),1*60*1000);
        },
        onTimeTick: function(){
            roomPrefs.getAllRoomPrefs().then(function(rooms){

               try{ _.each(rooms,function(room){
                    if (room.warData.inWar){
                      //  console.log('onTick',room.roomId,this.allBots);
                        var botObj = _.findWhere(this.allBots, {group_id: room.roomId+''});
                        if (botObj && botObj.manager && botObj.manager.onTimeTick){
                            botObj.manager.onTimeTick(room);
                        }
                    }
                }.bind(this));}
                catch(e){console.warn('error',e);}

            }.bind(this));

        },
        getAllBots: function () {
            var deferred = Q.defer();

            var url = 'https://api.groupme.com/v3/bots?token=' + this.options.token;
            request({url: url, method: 'GET'}, function (err, response, body) {
                body = JSON.parse(body);
                var bots = [];
                _.each(body.response, function (bot) {
                    bots.push(bot);
                });
                this.allBots = bots;

                deferred.resolve(bots);
            }.bind(this));

            return deferred.promise;
        },
        killAllBots: function () {
            var deferred = Q.defer();
            var that = this;
            var unregArray=[];
            try {
                _.each(this.allBots, function (bot) {
                    unregArray.push(that.unregisterBot(bot.bot_id));
                });
            }
            catch (e) {
                console.log('------->',e);
            }
            Q.all(unregArray).then(function(){
                this.allBots = [];
                deferred.resolve( this.allBots);
            }.bind(this))

            return deferred.promise;
        },
        registerMissingBots: function () {
            var self=this;
            var deferred = Q.defer();
            console.log('register bots');
            mongoData.getSettings().then(function(settings){
                var guilds = settings.guilds;
               console.log('got settings',settings,guilds);
                var adminGroup=self.options.adminGroup;
                try {
                    if (_.find(guilds, function (guild) {
                            guild.roomId + '' == adminGroup + '';
                        })==null) {
                        guilds.push({
                            roomId:adminGroup,
                            guildName:'Admin',
                            guildId:''
                        });
                    }
                }catch(e){console.log(e);}
                //console.log('register',groupIds);
                var registerArr=[];
                _.each(guilds, function (guild) {
                   try {
                       var botObj=_.findWhere(this.allBots, {group_id: Number(guild.roomId)});
                       if (botObj == undefined) {
                           registerArr.push(this.registerBotAndCreateManager(guild.roomId));
                       }else{
                           registerArr.push(this.createManager(guild.roomId,botObj));
                       }
                   }catch(e){}
                }.bind(this));
                Q.all(registerArr).then(function(){
                    deferred.resolve();
                })
            }.bind(this))

            return deferred.promise;
        },
        unregisterBot: function (botId) {
            console.log('unregister', botId);
            var deferred = Q.defer();
            var url = 'https://api.groupme.com/v3/bots/destroy?token=' + this.options.token;
            request({url: url, method: 'POST', body: JSON.stringify({bot_id: botId})},
                function (error, response, body) {
                    deferred.resolve();
                }.bind(this));
            return deferred.promise;
        },
        createManager : function(groupIdx,botObj){
            var manager = this.options.adminGroup==groupIdx? new AdminBot(botObj, groupIdx) : new Bot(botObj, groupIdx);
            manager.on('botRegister',function(ctx,guild){
                var botObj = _.findWhere(this.allBots, {group_id: guild.roomId});
                if (botObj==undefined) {
                    this.registerBotAndCreateManager(guild.roomId).then(function (newBot) {
                        ctx.botRegistered(guild.roomId);
                        newBot.postMessage('RavenBot is successfully registered in this room.\nRaven Manual:\nhttps://docs.google.com/document/d/15naOzWKf9z9CT-D4hHZTryTE55l4HyNiR8sahye0TzU/edit');
                        this.addGroupToSettings(guild);
                    }.bind(this));
                }else{
                    ctx.postMessage('Bot already registered');
                }

            }.bind(this));
            manager.on('botUnregister',function(ctx,groupId){
                var botObj = _.findWhere(this.allBots, {group_id: groupId});
                if (botObj!=undefined) {
                    botObj.manager.postMessage('Bye.');
                    this.allBots = _.filter(this.allBots, function (bot) {
                        return bot.group_id != groupId;
                    });
                    this.removeGroupFromSettings(groupId);
                    this.unregisterBot(botObj.bot_id).then(function () {
                        ctx.botUnregistered(groupId);

                    }.bind(this));
                }else{
                    ctx.postMessage('Bot is not registered');

                }

            }.bind(this));
            manager.on('broadcast',function(ctx,broadcastObj){
                this.broadCast(ctx,broadcastObj.guild,broadcastObj.msg);

            }.bind(this));
            var botResponse = response.response.bot;
            botResponse.manager = manager;
            this.allBots.push(botResponse);
            return manager;
        },
        registerBotAndCreateManager: function(groupId){
            var deferred = Q.defer();
            this.registerBot(groupId).then(function (data) {
                var response=data.response;
                var groupIdx=data.groupId;
                if (response.meta.code > 200 && response.meta.code < 300) {
                    try {
                        var botObj=response.response.bot;
                        var manager=this.createManager(groupIdx,botObj);
                        deferred.resolve(manager);
                    } catch (e) {
                        console.log('------->', e);
                        deferred.reject(e);
                    }
                }

            }.bind(this)).fail(function(e){
                console.log('--------------->>>>',e);

            });
            return deferred.promise;
        },
        broadCast: function(ctx,group,msg){
            if (group=='all'){
                _.each(this.allBots,function(bot){
                    if (bot.group_id!=this.options.adminGroup) {
                        bot.manager.postMessage(msg);
                    }
                }.bind(this));
                ctx.postMessage('Msg sent.');
            }
            else{
                var botObj = _.findWhere(this.allBots, {group_id: group});
                if (botObj==undefined) {
                 ctx.postMessage('Group not found.');
                }
                else{
                    botObj.manager.postMessage(msg);
                    ctx.postMessage('Msg sent.');
                }
            }

        },
        registerBot: function (groupId) {
            var deferred = Q.defer();
            var bot = {};
            bot.name = this.options.name;
            bot.group_id = groupId;
            bot.callback_url = this.options.url + '/incoming';
            if (this.options.avatar_url) {
                bot.avatar_url = this.options.avatar_url;
            }
            ;
            var url = 'https://api.groupme.com/v3/bots?token=' + this.options.token;

            request({url: url, method: 'POST', body: JSON.stringify({bot: bot})},
                function (error, response, body) {
                    if (!error) {
                      try {
                          var parsedBody = JSON.parse(body);
                          deferred.resolve({response: parsedBody, groupId: groupId});
                      }
                    catch(e){
                        deferred.reject(e);

                      }

                    } else {
                        deferred.reject(error);
                    }
                }.bind(this)
            );
            return deferred.promise;
        },
        handleMessage: function (self, msg) {
            /*{
             "id": "1234567890",
             "source_guid": "GUID",
             "created_at": 1302623328,
             "user_id": "1234567890",
             "group_id": "1234567890",
             "name": "John",
             "avatar_url": "http://i.groupme.com/123456789",
             "text": "Hello world ☃☃",
             "system": true,
             "favorited_by": [
             "101",
             "66",
             "1234567890"
             ],
             "attachments": []
             }*/
            var groupId = msg.group_id;
            if (msg.name != self.options.name) {
                var botObj = _.findWhere(this.allBots, {group_id: groupId});
                if (botObj==undefined){
                    console.log('couldnt find a bot to handle:',msg)
                    return;

                }else {
                  try {
                      botObj.manager.handleMessage(msg);
                  }catch(e){
                      console.warn('FATAL ERROR : ',e);

                  }
                }
            }
        },
        startListening: function () {
            var self = this;

            this.on('botMessage', this.handleMessage.bind(this));

                var self = this;
                //console.log(JSON.stringify({'name': self.options.name, 'groups': settings.groups}));
                var server = http.createServer(function (request, response) {
                    if (request.url == '/' && request.method == 'GET') {
                        response.writeHead(200, {"Content-Type": "application/json"});
                        response.end(JSON.stringify({'name': self.options.name}));
                    } else if (request.url == '/images/raven.jpeg') {
                        var img = fs.readFileSync('./images/raven.jpeg');
                        response.writeHead(200, {'Content-Type': 'image/jpeg'});
                        response.end(img, 'binary');
                    } else if (request.url == '/incoming' && request.method == 'POST') {
                        var form = new formidable.IncomingForm();
                        var messageFields = {};
                        form.parse(request, function (err, fields, files) {
                            if (err) console.error("bad incoming data " + err);
                        });

                        form.on('field', function (name, value) {
                            messageFields[name] = value;
                        });

                        form.on('end', function () {
                            response.writeHead(200, {"Content-Type": "text/plain"});
                            response.end("THANKS");
                            self.emit('botMessage', self, messageFields);
                        });

                    } else {
                        response.writeHead(404, {"Content-Type": "text/plain"});
                        response.end("NOT FOUND");
                    }

                }.bind(this));

                server.listen(self.options.port);
                console.log('server up');

        },
        addGroupToSettings: function(guild){
            mongoData.getSettings().then(function(settings){
                var guilds = settings.guilds;
                if (!_.findWhere(guilds,{roomId:Number(guild.roomId)})){
                    guilds.push({
                        roomId:guild.roomId,
                        guildName:guild.guildName,
                        guildId:guild.guildId

                    });
                    settings.guilds=guilds;
                    settings.save();
                }
            })

        },
        removeGroupFromSettings: function(groupId){
            mongoData.getSettings().then(function(settings){
                var guilds = settings.guilds;
                if (_.findWhere(guilds,{roomId:Number(groupId)})){
                    guilds = _.filter(guilds,function(guild){
                        return guild.roomId!=groupId;
                    })
                    settings.guilds=guilds;
                    settings.save();
                }
            })

        }
    }
}());

module.exports = function (options) {
    var md = new BotsManager(options);

    return md;
};<|endoftext|>


<commit_before>/****************************************************************************************************************************/

/*
Admittedly, this code is incredibly sloppy. There are far too many global variables that could be easily localized. For
example, setSession() and setBreak() should probably take onSession as a parameter, since setSession() shouldonly be used
when onSession == true and setBreak() when onSession == false.

Also, using an alert() when the timer goes off isn't the best form, since pop-ups are typically annoying and can be disabled.

This project was rushed in order to complete the FCC Front-End course as fast as possible.
*/

// Initialize global variables

var sessionLength = 25;
var breakLength = 5;
var mins = 25;
var secs = 0;
var onSession = true; // determines whether the session timer or break timer is enabled
var timerRunning = false;
var countdown; // for use with setInterval()

// Initialize colors (should match colors in SCSS)

var bodyColor = "#ECECEC";
var accentColor = "#337AB7";

// Helper functions

function resetTimer() {
  mins = onSession ? sessionLength : breakLength;
  if (timerRunning) mins--;
  secs = 0;
  clearInterval(countdown);
  document.getElementById("timerMin").innerHTML = mins < 10 ? "0" + mins : mins.toString();
  document.getElementById("timerSec").innerHTML = "00";
}

function setSession() { // change from break to session
  // enable session button
  document.getElementById("sessionButton").style.backgroundColor = accentColor;
  document.getElementById("sessionButton").style.color = bodyColor;
  // disable break button
  document.getElementById("breakButton").style.backgroundColor = bodyColor;
  document.getElementById("breakButton").style.color = accentColor;
  // reset timer
  resetTimer();
}

function setBreak() { // change from session to break
  // enable break button
  document.getElementById("breakButton").style.backgroundColor = accentColor;
  document.getElementById("breakButton").style.color = bodyColor;
  // disable session button
  document.getElementById("sessionButton").style.backgroundColor = bodyColor;
  document.getElementById("sessionButton").style.color = accentColor;
  // reset timer
  resetTimer();
}

function playOrPause() {
  if (timerRunning) {
    document.getElementById("playPause").innerHTML = "";
    countdown = setInterval(function() {
      secs--;
      if (secs < 0) {
        mins--;
        if (mins < 0) { // timer goes off
          onSession = !onSession; // change timer from session to break, or vice versa
          if (onSession) {
            alert("Time to work for " + sessionLength + " minutes!");
            setSession(); // runs resetTimer()
          }
          else {
            alert("Break time! Relax for " + breakLength + " minutes.");
            setBreak(); // runs resetTimer()
          }
          playOrPause(); // rerun this function with new timer
        }
        document.getElementById("timerMin").innerHTML = mins < 10 ? "0" + mins : mins.toString();
        secs = 59;
      }
      document.getElementById("timerSec").innerHTML = secs < 10 ? "0" + secs : secs.toString();
    }, 1000);
  } else {
    document.getElementById("playPause").innerHTML = "";
    clearInterval(countdown);
  }
}

// Choose session or break timer

document.getElementById("sessionButton").onclick = function() {
  if (timerRunning) return;
  onSession = true;
  setSession();
}

document.getElementById("breakButton").onclick = function() {
  if (timerRunning) return;
  onSession = false;
  setBreak();
}

// Change sessions & break lengths

document.getElementById("sessionDec").onclick = function() {
  if (sessionLength == 1 || timerRunning) return;
  sessionLength--;
  document.getElementById("sessionTime").innerHTML = sessionLength < 10 ? "0" + sessionLength : sessionLength.toString();
  resetTimer();
}

document.getElementById("sessionInc").onclick = function() {
  if (sessionLength == 99 || timerRunning) return;
  sessionLength++;
  document.getElementById("sessionTime").innerHTML = sessionLength < 10 ? "0" + sessionLength : sessionLength.toString();
  resetTimer();
}

document.getElementById("breakDec").onclick = function() {
  if (breakLength == 1 || timerRunning) return;
  breakLength--;
  document.getElementById("breakTime").innerHTML = breakLength < 10 ? "0" + breakLength : breakLength.toString();
  resetTimer();
}

document.getElementById("breakInc").onclick = function() {
  if (breakLength == 99 || timerRunning) return;
  breakLength++;
  document.getElementById("breakTime").innerHTML = breakLength < 10 ? "0" + breakLength : breakLength.toString();
  resetTimer();
}

// Manipulate timer

document.getElementById("playPause").onclick = function() {
  timerRunning = !timerRunning; // toggle timerRunning as true or false
  playOrPause();
}

document.getElementById("reset").onclick = function() {
  document.getElementById("playPause").innerHTML = "";
  timerRunning = false;
  resetTimer();
}<commit_msg>Delete index.js<commit_after><|endoftext|>


<commit_before>var deprecate = require('depd')('axe-webdriverjs');
var AxeInjector = require('./axe-injector');
var normalizeContext = require('./normalize-context');

/**
 * Constructor for chainable WebDriver API
 * @param {WebDriver} driver WebDriver instance to analyze
 */
function AxeBuilder(driver, source) {
  if (!(this instanceof AxeBuilder)) {
    return new AxeBuilder(driver, source);
  }

  this._driver = driver;
  this._source = source || null;
  this._includes = [];
  this._excludes = [];
  this._options = null;
  this._config = null;
}

/**
 * Selector to include in analysis
 * @param  {String} selector CSS selector of the element to include
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.include = function(selector) {
  this._includes.push(Array.isArray(selector) ? selector : [selector]);
  return this;
};

/**
 * Selector to exclude in analysis
 * @param  {String} selector CSS selector of the element to exclude
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.exclude = function(selector) {
  this._excludes.push(Array.isArray(selector) ? selector : [selector]);
  return this;
};

/**
 * Options to directly pass to `axe.run`.  See API documentation for axe-core for use.  Will override any other configured options, including calls to `withRules` and `withTags`.
 * @param  {Object} options Options object
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.options = function(options) {
  this._options = options;
  return this;
};

/**
 * Limit analysis to only the specified rules.  Cannot be used with `withTags`.
 * @param {Array|String} rules Array of rule IDs, or a single rule ID as a string
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.withRules = function(rules) {
  rules = Array.isArray(rules) ? rules : [rules];
  this._options = this._options || {};
  this._options.runOnly = {
    type: 'rule',
    values: rules
  };

  return this;
};

/**
 * Limit analysis to only the specified tags.  Cannot be used with `withRules`.
 * @param {Array|String} rules Array of tags, or a single tag as a string
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.withTags = function(tags) {
  tags = Array.isArray(tags) ? tags : [tags];
  this._options = this._options || {};
  this._options.runOnly = {
    type: 'tag',
    values: tags
  };

  return this;
};

/**
 * Set the list of rules to skip when running an analysis
 * @param {Array|String} rules Array of rule IDs, or a single rule ID as a string
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.disableRules = function(rules) {
  rules = Array.isArray(rules) ? rules : [rules];
  this._options = this._options || {};
  this._options.rules = {};

  rules.forEach(
    function(rulesConfiguration, ruleToDisable) {
      rulesConfiguration[ruleToDisable] = {
        enabled: false
      };
    }.bind(null, this._options.rules)
  );

  return this;
};

/**
 * Configure aXe before running analyze. *Does not chain.*
 * @param  {Object} config Configuration object to use in analysis
 */
AxeBuilder.prototype.configure = function(config) {
  if (typeof config !== 'object') {
    throw new Error(
      'AxeBuilder needs an object to configure. See axe-core configure API.'
    );
  }

  this._config = config;
  return this;
};

/**
 * Perform analysis and retrieve results. *Does not chain.*
 *
 * If a `callback` is provided, it is strongly recommended that it accepts two arguments: `error, results`. If only a single argument is accepted, a deprecation warning will be printed to `stderr` and any errors encoutered during analysis will crash the Node process.
 *
 * @param  {Function} [callback] Function to execute when analysis completes
 * @return {Promise}
 */
AxeBuilder.prototype.analyze = function(callback) {
  var context = normalizeContext(this._includes, this._excludes),
    driver = this._driver,
    options = this._options,
    config = this._config,
    source = this._source;

  // Check if the provided `callback` uses the old argument signature (an arity of 1). If it does, provide a helpful deprecation warning.
  var isOldAPI = callback && callback.length === 1;
  if (isOldAPI) {
    deprecate('Error must be handled as the first argument of axe.analyze. See: #83');
  }

  return new Promise((resolve, reject) => {
    var injector = new AxeInjector({ driver, axeSource: source, config });
    injector.inject(() => {
      driver
        .executeAsyncScript(
          function(context, options, config) {
            /* eslint-env browser */
            if (config !== null) {
              window.axe.configure(config);
            }
            window.axe
              .run(context || document, options || {})
              .then(arguments[arguments.length - 1]);
          },
          context,
          options,
          config
        )
        .then(function(results) {
          if (callback) {
            // If using the old API, provide the `results` as the first and only argument. Otherwise, provide `null` indicating no errors were encountered.
            if (isOldAPI) {
              callback(results);
            } else {
              callback(null, results);
            }
          }
          resolve(results);
        })
        .catch(err => {
          // When using a callback, do *not* reject the wrapping Promise. This prevents having to handle the same error twice.
          if (callback) {
            // If using the old API, throw this error (and unfortunately crash the process), since there is no way to handle it. Otherwise, provide the error as the first argument ("error-back" style).
            if (isOldAPI) {
              throw err;
            } else {
              callback(err, null);
            }
          } else {
            reject(err);
          }
        });
    });
  });
};

exports = module.exports = AxeBuilder;
<commit_msg>feat: add ES6 modules/TypeScript compatible export (#94)<commit_after>var deprecate = require('depd')('axe-webdriverjs');
var AxeInjector = require('./axe-injector');
var normalizeContext = require('./normalize-context');

/**
 * Constructor for chainable WebDriver API
 * @param {WebDriver} driver WebDriver instance to analyze
 */
function AxeBuilder(driver, source) {
  if (!(this instanceof AxeBuilder)) {
    return new AxeBuilder(driver, source);
  }

  this._driver = driver;
  this._source = source || null;
  this._includes = [];
  this._excludes = [];
  this._options = null;
  this._config = null;
}

/**
 * Selector to include in analysis
 * @param  {String} selector CSS selector of the element to include
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.include = function(selector) {
  this._includes.push(Array.isArray(selector) ? selector : [selector]);
  return this;
};

/**
 * Selector to exclude in analysis
 * @param  {String} selector CSS selector of the element to exclude
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.exclude = function(selector) {
  this._excludes.push(Array.isArray(selector) ? selector : [selector]);
  return this;
};

/**
 * Options to directly pass to `axe.run`.  See API documentation for axe-core for use.  Will override any other configured options, including calls to `withRules` and `withTags`.
 * @param  {Object} options Options object
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.options = function(options) {
  this._options = options;
  return this;
};

/**
 * Limit analysis to only the specified rules.  Cannot be used with `withTags`.
 * @param {Array|String} rules Array of rule IDs, or a single rule ID as a string
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.withRules = function(rules) {
  rules = Array.isArray(rules) ? rules : [rules];
  this._options = this._options || {};
  this._options.runOnly = {
    type: 'rule',
    values: rules
  };

  return this;
};

/**
 * Limit analysis to only the specified tags.  Cannot be used with `withRules`.
 * @param {Array|String} rules Array of tags, or a single tag as a string
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.withTags = function(tags) {
  tags = Array.isArray(tags) ? tags : [tags];
  this._options = this._options || {};
  this._options.runOnly = {
    type: 'tag',
    values: tags
  };

  return this;
};

/**
 * Set the list of rules to skip when running an analysis
 * @param {Array|String} rules Array of rule IDs, or a single rule ID as a string
 * @return {AxeBuilder}
 */
AxeBuilder.prototype.disableRules = function(rules) {
  rules = Array.isArray(rules) ? rules : [rules];
  this._options = this._options || {};
  this._options.rules = {};

  rules.forEach(
    function(rulesConfiguration, ruleToDisable) {
      rulesConfiguration[ruleToDisable] = {
        enabled: false
      };
    }.bind(null, this._options.rules)
  );

  return this;
};

/**
 * Configure aXe before running analyze. *Does not chain.*
 * @param  {Object} config Configuration object to use in analysis
 */
AxeBuilder.prototype.configure = function(config) {
  if (typeof config !== 'object') {
    throw new Error(
      'AxeBuilder needs an object to configure. See axe-core configure API.'
    );
  }

  this._config = config;
  return this;
};

/**
 * Perform analysis and retrieve results. *Does not chain.*
 *
 * If a `callback` is provided, it is strongly recommended that it accepts two arguments: `error, results`. If only a single argument is accepted, a deprecation warning will be printed to `stderr` and any errors encoutered during analysis will crash the Node process.
 *
 * @param  {Function} [callback] Function to execute when analysis completes
 * @return {Promise}
 */
AxeBuilder.prototype.analyze = function(callback) {
  var context = normalizeContext(this._includes, this._excludes),
    driver = this._driver,
    options = this._options,
    config = this._config,
    source = this._source;

  // Check if the provided `callback` uses the old argument signature (an arity of 1). If it does, provide a helpful deprecation warning.
  var isOldAPI = callback && callback.length === 1;
  if (isOldAPI) {
    deprecate(
      'Error must be handled as the first argument of axe.analyze. See: #83'
    );
  }

  return new Promise((resolve, reject) => {
    var injector = new AxeInjector({ driver, axeSource: source, config });
    injector.inject(() => {
      driver
        .executeAsyncScript(
          function(context, options, config) {
            /* eslint-env browser */
            if (config !== null) {
              window.axe.configure(config);
            }
            window.axe
              .run(context || document, options || {})
              .then(arguments[arguments.length - 1]);
          },
          context,
          options,
          config
        )
        .then(function(results) {
          if (callback) {
            // If using the old API, provide the `results` as the first and only argument. Otherwise, provide `null` indicating no errors were encountered.
            if (isOldAPI) {
              callback(results);
            } else {
              callback(null, results);
            }
          }
          resolve(results);
        })
        .catch(err => {
          // When using a callback, do *not* reject the wrapping Promise. This prevents having to handle the same error twice.
          if (callback) {
            // If using the old API, throw this error (and unfortunately crash the process), since there is no way to handle it. Otherwise, provide the error as the first argument ("error-back" style).
            if (isOldAPI) {
              throw err;
            } else {
              callback(err, null);
            }
          } else {
            reject(err);
          }
        });
    });
  });
};

exports = module.exports = AxeBuilder;

// TypeScript/ES6 module support (see #74).
exports.default = AxeBuilder;
<|endoftext|>


<commit_before>var should = require('should');
var request = require('superagent');
var crawl = require('crawl');
var w3cjs = require('w3cjs');

var app = require('../../build/server');

var ignores = [];

/**
 * HTML validation checks
 */
describe('The pattern library', function() {
  var validationQueue = [];

  this.timeout(5000);

  it('should be valid HTML', function(done) {
    crawl.crawl('http://localhost:' + (process.env.PORT || 3000), function(err, crawlResults) {
      if (err) {
        throw('An error occured while crawling before html validation', err);
        return;
      }

      crawlResults.forEach(function(page) {

        if(page.contentType.indexOf('text/html') !== '-1') {

          validationQueue.push(new Promise(function(resolve, reject) {

            request
              .get(page.url)
              .end(function(err, res){

                if(res.type !== 'text/html') {
                  resolve();
                  return;
                }

                w3cjs.validate({
                  input: res.text,
                  callback: function (res) {

                    var output = page.url;

                    res.messages.forEach(function(message) {

                      // Don't need to fail the test for info messages
                      if(message.type === 'info') {
                        return;
                      }

                      // Exclude any warnings that we are ignoring
                      if(ignores.indexOf(message.message) !== -1) {
                        return;
                      }

                      output += '\nLine: ' + message.lastLine + ' Col: ' + message.firstColumn + ' => ' + message.message;
                    });

                    output.should.be.equal(page.url);

                    resolve();
                  }
                });

              });
          }));
        }
      });

      Promise
        .all(validationQueue)
        .then(function() {
          done();
        });
    });
  })
});
<commit_msg>Add line to debug travis<commit_after>var should = require('should');
var request = require('superagent');
var crawl = require('crawl');
var w3cjs = require('w3cjs');

var app = require('../../build/server');

var ignores = [];

/**
 * HTML validation checks
 */
describe('The pattern library', function() {
  var validationQueue = [];

  this.timeout(5000);

  it('should be valid HTML', function(done) {
    crawl.crawl('http://localhost:' + (process.env.PORT || 3000), function(err, crawlResults) {
      if (err) {
        throw('An error occured while crawling before html validation', err);
        return;
      }

      crawlResults.forEach(function(page) {

        if(page.contentType.indexOf('text/html') !== '-1') {

          validationQueue.push(new Promise(function(resolve, reject) {

            request
              .get(page.url)
              .end(function(err, res){

                console.log(page.url, res.type);

                if(res.type !== 'text/html') {
                  resolve();
                  return;
                }

                w3cjs.validate({
                  input: res.text,
                  callback: function (res) {

                    var output = page.url;

                    res.messages.forEach(function(message) {

                      // Don't need to fail the test for info messages
                      if(message.type === 'info') {
                        return;
                      }

                      // Exclude any warnings that we are ignoring
                      if(ignores.indexOf(message.message) !== -1) {
                        return;
                      }

                      output += '\nLine: ' + message.lastLine + ' Col: ' + message.firstColumn + ' => ' + message.message;
                    });

                    output.should.be.equal(page.url);

                    resolve();
                  }
                });

              });
          }));
        }
      });

      Promise
        .all(validationQueue)
        .then(function() {
          done();
        });
    });
  })
});
<|endoftext|>


<commit_before>L.TileLayer.WMS = L.TileLayer.extend({

	defaultWmsParams: {
		service: 'WMS',
		request: 'GetMap',
		version: '1.1.1',
		layers: '',
		styles: '',
		format: 'image/jpeg',
		transparent: false
	},

	initialize: function (url, options) { // (String, Object)

		this._url = url;

		var wmsParams = L.Util.extend({}, this.defaultWmsParams);

		if (options.detectRetina && L.Browser.retina) {
			wmsParams.width = wmsParams.height = this.options.tileSize * 2;
		} else {
			wmsParams.width = wmsParams.height = this.options.tileSize;
		}

		for (var i in options) {
			// all keys that are not TileLayer options go to WMS params
			if (!this.options.hasOwnProperty(i)) {
				wmsParams[i] = options[i];
			}
		}

		this.wmsParams = wmsParams;

		L.Util.setOptions(this, options);
	},

	onAdd: function (map) {

		var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs';
		this.wmsParams[projectionKey] = map.options.crs.code;

		L.TileLayer.prototype.onAdd.call(this, map);
	},

	getTileUrl: function (tilePoint, zoom) { // (Point, Number) -> String

		var map = this._map,
			crs = map.options.crs,
			tileSize = this.options.tileSize,

			nwPoint = tilePoint.multiplyBy(tileSize),
			sePoint = nwPoint.add(new L.Point(tileSize, tileSize)),

			nw = crs.project(map.unproject(nwPoint, zoom)),
			se = crs.project(map.unproject(sePoint, zoom)),

			bbox = [nw.x, se.y, se.x, nw.y].join(','),

			url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)});

		return url + L.Util.getParamString(this.wmsParams) + "&bbox=" + bbox;
	},

	setParams: function (params, noRedraw) {

		L.Util.extend(this.wmsParams, params);

		if (!noRedraw) {
			this.redraw();
		}

		return this;
	}
});

L.tileLayer.wms = function (url, options) {
	return new L.TileLayer(url, options);
};
<commit_msg>Fix L.tileLayer.wms class factory<commit_after>L.TileLayer.WMS = L.TileLayer.extend({

	defaultWmsParams: {
		service: 'WMS',
		request: 'GetMap',
		version: '1.1.1',
		layers: '',
		styles: '',
		format: 'image/jpeg',
		transparent: false
	},

	initialize: function (url, options) { // (String, Object)

		this._url = url;

		var wmsParams = L.Util.extend({}, this.defaultWmsParams);

		if (options.detectRetina && L.Browser.retina) {
			wmsParams.width = wmsParams.height = this.options.tileSize * 2;
		} else {
			wmsParams.width = wmsParams.height = this.options.tileSize;
		}

		for (var i in options) {
			// all keys that are not TileLayer options go to WMS params
			if (!this.options.hasOwnProperty(i)) {
				wmsParams[i] = options[i];
			}
		}

		this.wmsParams = wmsParams;

		L.Util.setOptions(this, options);
	},

	onAdd: function (map) {

		var projectionKey = parseFloat(this.wmsParams.version) >= 1.3 ? 'crs' : 'srs';
		this.wmsParams[projectionKey] = map.options.crs.code;

		L.TileLayer.prototype.onAdd.call(this, map);
	},

	getTileUrl: function (tilePoint, zoom) { // (Point, Number) -> String

		var map = this._map,
			crs = map.options.crs,
			tileSize = this.options.tileSize,

			nwPoint = tilePoint.multiplyBy(tileSize),
			sePoint = nwPoint.add(new L.Point(tileSize, tileSize)),

			nw = crs.project(map.unproject(nwPoint, zoom)),
			se = crs.project(map.unproject(sePoint, zoom)),

			bbox = [nw.x, se.y, se.x, nw.y].join(','),

			url = L.Util.template(this._url, {s: this._getSubdomain(tilePoint)});

		return url + L.Util.getParamString(this.wmsParams) + "&bbox=" + bbox;
	},

	setParams: function (params, noRedraw) {

		L.Util.extend(this.wmsParams, params);

		if (!noRedraw) {
			this.redraw();
		}

		return this;
	}
});

L.tileLayer.wms = function (url, options) {
	return new L.TileLayer.WMS(url, options);
};
<|endoftext|>


<commit_before>import { Asset } from '../../asset/asset.js';
import { Entity } from '../../framework/entity.js';
import { MeshInstance } from '../../scene/mesh-instance.js';
import { MorphInstance } from '../../scene/morph-instance.js';
import { SkinInstance } from '../../scene/skin-instance.js';
import { SkinInstanceCache } from '../../scene/skin-instance-cache.js';
import { Model } from '../../scene/model.js';
import { Debug } from '../../core/debug.js';

// Container resource returned by the GlbParser. Implements the ContainerResource interface.
class GlbContainerResource {
    constructor(data, asset, assets, defaultMaterial) {
        const createAsset = function (type, resource, index) {
            const subAsset = GlbContainerResource.createAsset(asset.name, type, resource, index);
            assets.add(subAsset);
            return subAsset;
        };

        // render assets
        const renders = [];
        for (let i = 0; i < data.renders.length; ++i) {
            renders.push(createAsset('render', data.renders[i], i));
        }

        // create material assets
        const materials = [];
        for (let i = 0; i < data.materials.length; ++i) {
            materials.push(createAsset('material', data.materials[i], i));
        }

        // create animation assets
        const animations = [];
        for (let i = 0; i < data.animations.length; ++i) {
            animations.push(createAsset('animation', data.animations[i], i));
        }

        this.data = data;
        this._model = null;
        this._assetName = asset.name;
        this._assets = assets;
        this._defaultMaterial = defaultMaterial;
        this.renders = renders;
        this.materials = materials;
        this.textures = data.textures; // texture assets are created directly
        this.animations = animations;
    }

    get model() {
        if (!this._model) {
            // create model only when needed
            const model = GlbContainerResource.createModel(this.data, this._defaultMaterial);
            const modelAsset = GlbContainerResource.createAsset(this._assetName, 'model', model, 0);
            this._assets.add(modelAsset);
            this._model = modelAsset;
        }
        return this._model;
    }

    static createAsset(assetName, type, resource, index) {
        const subAsset = new Asset(assetName + '/' + type + '/' + index, type, {
            url: ''
        });
        subAsset.resource = resource;
        subAsset.loaded = true;
        return subAsset;
    }

    instantiateModelEntity(options) {
        const entity = new Entity();
        entity.addComponent('model', Object.assign({ type: 'asset', asset: this.model }, options));
        return entity;
    }

    instantiateRenderEntity(options) {

        const defaultMaterial = this._defaultMaterial;
        const skinnedMeshInstances = [];

        const createMeshInstance = function (root, entity, mesh, materials, meshDefaultMaterials, skins, gltfNode) {

            // clone mesh instance
            const materialIndex = meshDefaultMaterials[mesh.id];
            const material = (materialIndex === undefined) ? defaultMaterial : materials[materialIndex];
            const meshInstance = new MeshInstance(mesh, material);

            // create morph instance
            if (mesh.morph) {
                meshInstance.morphInstance = new MorphInstance(mesh.morph);
            }

            // store data to create skin instance after the hierarchy is created
            if (gltfNode.hasOwnProperty('skin')) {
                skinnedMeshInstances.push({
                    meshInstance: meshInstance,
                    rootBone: root,
                    entity: entity
                });
            }

            return meshInstance;
        };

        // helper function to recursively clone a hierarchy of GraphNodes to Entities
        const cloneHierarchy = (root, node, glb) => {

            const entity = new Entity();
            node._cloneInternal(entity);

            // first entity becomes the root
            if (!root) root = entity;

            // find all components needed for this node
            let attachedMi = null;
            let renderAsset = null;
            for (let i = 0; i < glb.nodes.length; i++) {
                const glbNode = glb.nodes[i];
                if (glbNode === node) {
                    const gltfNode = glb.gltf.nodes[i];

                    // mesh
                    if (gltfNode.hasOwnProperty('mesh')) {
                        const meshGroup = glb.renders[gltfNode.mesh].meshes;
                        renderAsset = this.renders[gltfNode.mesh];
                        for (var mi = 0; mi < meshGroup.length; mi++) {
                            const mesh = meshGroup[mi];
                            if (mesh) {
                                const cloneMi = createMeshInstance(root, entity, mesh, glb.materials, glb.meshDefaultMaterials, glb.skins, gltfNode);

                                // add it to list
                                if (!attachedMi) {
                                    attachedMi = [];
                                }
                                attachedMi.push(cloneMi);
                            }
                        }
                    }

                    // light - clone (additional child) entity with the light component
                    // cannot clone the component as additional entity has a rotation to handle different light direction
                    if (glb.lights) {
                        const lightEntity = glb.lights.get(gltfNode);
                        if (lightEntity) {
                            entity.addChild(lightEntity.clone());
                        }
                    }

                    // camera
                    if (glb.cameras) {
                        const cameraEntity = glb.cameras.get(gltfNode);
                        if (cameraEntity) {
                            // clone camera component into the entity
                            cameraEntity.camera.system.cloneComponent(cameraEntity, entity);
                        }
                    }
                }
            }

            // create render components for mesh instances
            if (attachedMi) {
                entity.addComponent('render', Object.assign({
                    type: 'asset',
                    meshInstances: attachedMi,
                    rootBone: root
                }, options));

                // assign asset id without recreating mesh instances which are already set up with materials
                entity.render.assignAsset(renderAsset);
            }

            // recursively clone children
            const children = node.children;
            for (let i = 0; i < children.length; i++) {
                const childClone = cloneHierarchy(root, children[i], glb);
                entity.addChild(childClone);
            }

            return entity;
        };

        // clone scenes hierarchies
        const sceneClones = [];
        for (const scene of this.data.scenes) {
            sceneClones.push(cloneHierarchy(null, scene, this.data));
        }

        // now that the hierarchy is created, create skin instances and resolve bones using the hierarchy
        skinnedMeshInstances.forEach((data) => {
            data.meshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(data.meshInstance.mesh.skin, data.rootBone, data.entity);
        });

        // return the scene hierarchy created from scene clones
        return GlbContainerResource.createSceneHierarchy(sceneClones, 'Entity');
    }

    // get material variants
    getMaterialVariants() {
        return this.data.variants ? Object.keys(this.data.variants) : [];
    }

    // apply material variant to entity
    applyMaterialVariant(entity, name) {
        const variant = name ? this.data.variants[name] : null;
        if (variant === undefined) {
            Debug.warn(`No variant named ${name} exists in resource`);
            return;
        }
        const renders = entity.findComponents("render");
        for (let i = 0; i < renders.length; i++) {
            const renderComponent = renders[i];
            this._applyMaterialVariant(variant, renderComponent.meshInstances);
        }
    }

    // apply material variant to mesh instances
    applyMaterialVariantInstances(instances, name) {
        const variant = name ? this.data.variants[name] : null;
        if (variant === undefined) {
            Debug.warn(`No variant named ${name} exists in resource`);
            return;
        }
        this._applyMaterialVariant(variant, instances);
    }

    // internally apply variant to instances
    _applyMaterialVariant(variant, instances) {
        instances.forEach((instance) => {
            if (variant === null) {
                instance.material = this._defaultMaterial;
            } else {
                const meshVariants = this.data.meshVariants[instance.mesh.id];
                if (meshVariants) {
                    instance.material = this.data.materials[meshVariants[variant]];
                }
            }
            Debug.assert(instance.material);
        });
    }

    // helper function to create a single hierarchy from an array of nodes
    static createSceneHierarchy(sceneNodes, nodeType) {

        // create a single root of the hierarchy - either the single scene, or a new Entity parent if multiple scenes
        let root = null;
        if (sceneNodes.length === 1) {
            // use scene if only one
            root = sceneNodes[0];
        } else {
            // create group node for all scenes
            root = new nodeType('SceneGroup');
            for (const scene of sceneNodes) {
                root.addChild(scene);
            }
        }

        return root;
    }

    // create a pc.Model from the parsed GLB data structures
    static createModel(glb, defaultMaterial) {

        const createMeshInstance = function (model, mesh, skins, skinInstances, materials, node, gltfNode) {
            const material = (mesh.materialIndex === undefined) ? defaultMaterial : materials[mesh.materialIndex];
            const meshInstance = new MeshInstance(mesh, material, node);

            if (mesh.morph) {
                const morphInstance = new MorphInstance(mesh.morph);
                meshInstance.morphInstance = morphInstance;
                model.morphInstances.push(morphInstance);
            }

            if (gltfNode.hasOwnProperty('skin')) {
                const skinIndex = gltfNode.skin;
                const skin = skins[skinIndex];
                mesh.skin = skin;

                const skinInstance = skinInstances[skinIndex];
                meshInstance.skinInstance = skinInstance;
                model.skinInstances.push(skinInstance);
            }

            model.meshInstances.push(meshInstance);
        };

        const model = new Model();

        // create skinInstance for each skin
        const skinInstances = [];
        for (const skin of glb.skins) {
            const skinInstance = new SkinInstance(skin);
            skinInstance.bones = skin.bones;
            skinInstances.push(skinInstance);
        }

        // node hierarchy for the model
        model.graph = GlbContainerResource.createSceneHierarchy(glb.scenes, 'GraphNode');

        // create mesh instance for meshes on nodes that are part of hierarchy
        for (let i = 0; i < glb.nodes.length; i++) {
            const node = glb.nodes[i];
            if (node.root === model.graph) {
                const gltfNode = glb.gltf.nodes[i];
                if (gltfNode.hasOwnProperty('mesh')) {
                    const meshGroup = glb.renders[gltfNode.mesh].meshes;
                    for (var mi = 0; mi < meshGroup.length; mi++) {
                        const mesh = meshGroup[mi];
                        if (mesh) {
                            createMeshInstance(model, mesh, glb.skins, skinInstances, glb.materials, node, gltfNode);
                        }
                    }
                }
            }
        }

        return model;
    }

    destroy() {
        const registry = this._assets;

        const destroyAsset = function (asset) {
            registry.remove(asset);
            asset.unload();
        };

        const destroyAssets = function (assets) {
            assets.forEach(function (asset) {
                destroyAsset(asset);
            });
        };

        // unload and destroy assets
        if (this.animations) {
            destroyAssets(this.animations);
            this.animations = null;
        }

        if (this.textures) {
            destroyAssets(this.textures);
            this.textures = null;
        }

        if (this.materials) {
            destroyAssets(this.materials);
            this.materials = null;
        }

        if (this.renders) {
            destroyAssets(this.renders);
            this.renders = null;
        }

        if (this._model) {
            destroyAsset(this._model);
            this._model = null;
        }

        this.data = null;
        this.assets = null;
    }
}

export { GlbContainerResource };
<commit_msg>Handle default material for createModel (#4566)<commit_after>import { Asset } from '../../asset/asset.js';
import { Entity } from '../../framework/entity.js';
import { MeshInstance } from '../../scene/mesh-instance.js';
import { MorphInstance } from '../../scene/morph-instance.js';
import { SkinInstance } from '../../scene/skin-instance.js';
import { SkinInstanceCache } from '../../scene/skin-instance-cache.js';
import { Model } from '../../scene/model.js';
import { Debug } from '../../core/debug.js';

// Container resource returned by the GlbParser. Implements the ContainerResource interface.
class GlbContainerResource {
    constructor(data, asset, assets, defaultMaterial) {
        const createAsset = function (type, resource, index) {
            const subAsset = GlbContainerResource.createAsset(asset.name, type, resource, index);
            assets.add(subAsset);
            return subAsset;
        };

        // render assets
        const renders = [];
        for (let i = 0; i < data.renders.length; ++i) {
            renders.push(createAsset('render', data.renders[i], i));
        }

        // create material assets
        const materials = [];
        for (let i = 0; i < data.materials.length; ++i) {
            materials.push(createAsset('material', data.materials[i], i));
        }

        // create animation assets
        const animations = [];
        for (let i = 0; i < data.animations.length; ++i) {
            animations.push(createAsset('animation', data.animations[i], i));
        }

        this.data = data;
        this._model = null;
        this._assetName = asset.name;
        this._assets = assets;
        this._defaultMaterial = defaultMaterial;
        this.renders = renders;
        this.materials = materials;
        this.textures = data.textures; // texture assets are created directly
        this.animations = animations;
    }

    get model() {
        if (!this._model) {
            // create model only when needed
            const model = GlbContainerResource.createModel(this.data, this._defaultMaterial);
            const modelAsset = GlbContainerResource.createAsset(this._assetName, 'model', model, 0);
            this._assets.add(modelAsset);
            this._model = modelAsset;
        }
        return this._model;
    }

    static createAsset(assetName, type, resource, index) {
        const subAsset = new Asset(assetName + '/' + type + '/' + index, type, {
            url: ''
        });
        subAsset.resource = resource;
        subAsset.loaded = true;
        return subAsset;
    }

    instantiateModelEntity(options) {
        const entity = new Entity();
        entity.addComponent('model', Object.assign({ type: 'asset', asset: this.model }, options));
        return entity;
    }

    instantiateRenderEntity(options) {

        const defaultMaterial = this._defaultMaterial;
        const skinnedMeshInstances = [];

        const createMeshInstance = function (root, entity, mesh, materials, meshDefaultMaterials, skins, gltfNode) {

            // clone mesh instance
            const materialIndex = meshDefaultMaterials[mesh.id];
            const material = (materialIndex === undefined) ? defaultMaterial : materials[materialIndex];
            const meshInstance = new MeshInstance(mesh, material);

            // create morph instance
            if (mesh.morph) {
                meshInstance.morphInstance = new MorphInstance(mesh.morph);
            }

            // store data to create skin instance after the hierarchy is created
            if (gltfNode.hasOwnProperty('skin')) {
                skinnedMeshInstances.push({
                    meshInstance: meshInstance,
                    rootBone: root,
                    entity: entity
                });
            }

            return meshInstance;
        };

        // helper function to recursively clone a hierarchy of GraphNodes to Entities
        const cloneHierarchy = (root, node, glb) => {

            const entity = new Entity();
            node._cloneInternal(entity);

            // first entity becomes the root
            if (!root) root = entity;

            // find all components needed for this node
            let attachedMi = null;
            let renderAsset = null;
            for (let i = 0; i < glb.nodes.length; i++) {
                const glbNode = glb.nodes[i];
                if (glbNode === node) {
                    const gltfNode = glb.gltf.nodes[i];

                    // mesh
                    if (gltfNode.hasOwnProperty('mesh')) {
                        const meshGroup = glb.renders[gltfNode.mesh].meshes;
                        renderAsset = this.renders[gltfNode.mesh];
                        for (var mi = 0; mi < meshGroup.length; mi++) {
                            const mesh = meshGroup[mi];
                            if (mesh) {
                                const cloneMi = createMeshInstance(root, entity, mesh, glb.materials, glb.meshDefaultMaterials, glb.skins, gltfNode);

                                // add it to list
                                if (!attachedMi) {
                                    attachedMi = [];
                                }
                                attachedMi.push(cloneMi);
                            }
                        }
                    }

                    // light - clone (additional child) entity with the light component
                    // cannot clone the component as additional entity has a rotation to handle different light direction
                    if (glb.lights) {
                        const lightEntity = glb.lights.get(gltfNode);
                        if (lightEntity) {
                            entity.addChild(lightEntity.clone());
                        }
                    }

                    // camera
                    if (glb.cameras) {
                        const cameraEntity = glb.cameras.get(gltfNode);
                        if (cameraEntity) {
                            // clone camera component into the entity
                            cameraEntity.camera.system.cloneComponent(cameraEntity, entity);
                        }
                    }
                }
            }

            // create render components for mesh instances
            if (attachedMi) {
                entity.addComponent('render', Object.assign({
                    type: 'asset',
                    meshInstances: attachedMi,
                    rootBone: root
                }, options));

                // assign asset id without recreating mesh instances which are already set up with materials
                entity.render.assignAsset(renderAsset);
            }

            // recursively clone children
            const children = node.children;
            for (let i = 0; i < children.length; i++) {
                const childClone = cloneHierarchy(root, children[i], glb);
                entity.addChild(childClone);
            }

            return entity;
        };

        // clone scenes hierarchies
        const sceneClones = [];
        for (const scene of this.data.scenes) {
            sceneClones.push(cloneHierarchy(null, scene, this.data));
        }

        // now that the hierarchy is created, create skin instances and resolve bones using the hierarchy
        skinnedMeshInstances.forEach((data) => {
            data.meshInstance.skinInstance = SkinInstanceCache.createCachedSkinInstance(data.meshInstance.mesh.skin, data.rootBone, data.entity);
        });

        // return the scene hierarchy created from scene clones
        return GlbContainerResource.createSceneHierarchy(sceneClones, 'Entity');
    }

    // get material variants
    getMaterialVariants() {
        return this.data.variants ? Object.keys(this.data.variants) : [];
    }

    // apply material variant to entity
    applyMaterialVariant(entity, name) {
        const variant = name ? this.data.variants[name] : null;
        if (variant === undefined) {
            Debug.warn(`No variant named ${name} exists in resource`);
            return;
        }
        const renders = entity.findComponents("render");
        for (let i = 0; i < renders.length; i++) {
            const renderComponent = renders[i];
            this._applyMaterialVariant(variant, renderComponent.meshInstances);
        }
    }

    // apply material variant to mesh instances
    applyMaterialVariantInstances(instances, name) {
        const variant = name ? this.data.variants[name] : null;
        if (variant === undefined) {
            Debug.warn(`No variant named ${name} exists in resource`);
            return;
        }
        this._applyMaterialVariant(variant, instances);
    }

    // internally apply variant to instances
    _applyMaterialVariant(variant, instances) {
        instances.forEach((instance) => {
            if (variant === null) {
                instance.material = this._defaultMaterial;
            } else {
                const meshVariants = this.data.meshVariants[instance.mesh.id];
                if (meshVariants) {
                    instance.material = this.data.materials[meshVariants[variant]];
                }
            }
            Debug.assert(instance.material);
        });
    }

    // helper function to create a single hierarchy from an array of nodes
    static createSceneHierarchy(sceneNodes, nodeType) {

        // create a single root of the hierarchy - either the single scene, or a new Entity parent if multiple scenes
        let root = null;
        if (sceneNodes.length === 1) {
            // use scene if only one
            root = sceneNodes[0];
        } else {
            // create group node for all scenes
            root = new nodeType('SceneGroup');
            for (const scene of sceneNodes) {
                root.addChild(scene);
            }
        }

        return root;
    }

    // create a pc.Model from the parsed GLB data structures
    static createModel(glb, defaultMaterial) {

        const createMeshInstance = function (model, mesh, skins, skinInstances, materials, node, gltfNode) {
            const materialIndex = glb.meshDefaultMaterials[mesh.id];
            const material = (materialIndex === undefined) ? defaultMaterial : materials[materialIndex];
            const meshInstance = new MeshInstance(mesh, material, node);

            if (mesh.morph) {
                const morphInstance = new MorphInstance(mesh.morph);
                meshInstance.morphInstance = morphInstance;
                model.morphInstances.push(morphInstance);
            }

            if (gltfNode.hasOwnProperty('skin')) {
                const skinIndex = gltfNode.skin;
                const skin = skins[skinIndex];
                mesh.skin = skin;

                const skinInstance = skinInstances[skinIndex];
                meshInstance.skinInstance = skinInstance;
                model.skinInstances.push(skinInstance);
            }

            model.meshInstances.push(meshInstance);
        };

        const model = new Model();

        // create skinInstance for each skin
        const skinInstances = [];
        for (const skin of glb.skins) {
            const skinInstance = new SkinInstance(skin);
            skinInstance.bones = skin.bones;
            skinInstances.push(skinInstance);
        }

        // node hierarchy for the model
        model.graph = GlbContainerResource.createSceneHierarchy(glb.scenes, 'GraphNode');

        // create mesh instance for meshes on nodes that are part of hierarchy
        for (let i = 0; i < glb.nodes.length; i++) {
            const node = glb.nodes[i];
            if (node.root === model.graph) {
                const gltfNode = glb.gltf.nodes[i];
                if (gltfNode.hasOwnProperty('mesh')) {
                    const meshGroup = glb.renders[gltfNode.mesh].meshes;
                    for (var mi = 0; mi < meshGroup.length; mi++) {
                        const mesh = meshGroup[mi];
                        if (mesh) {
                            createMeshInstance(model, mesh, glb.skins, skinInstances, glb.materials, node, gltfNode);
                        }
                    }
                }
            }
        }

        return model;
    }

    destroy() {
        const registry = this._assets;

        const destroyAsset = function (asset) {
            registry.remove(asset);
            asset.unload();
        };

        const destroyAssets = function (assets) {
            assets.forEach(function (asset) {
                destroyAsset(asset);
            });
        };

        // unload and destroy assets
        if (this.animations) {
            destroyAssets(this.animations);
            this.animations = null;
        }

        if (this.textures) {
            destroyAssets(this.textures);
            this.textures = null;
        }

        if (this.materials) {
            destroyAssets(this.materials);
            this.materials = null;
        }

        if (this.renders) {
            destroyAssets(this.renders);
            this.renders = null;
        }

        if (this._model) {
            destroyAsset(this._model);
            this._model = null;
        }

        this.data = null;
        this.assets = null;
    }
}

export { GlbContainerResource };
<|endoftext|>


<commit_before>/****************************************************************************
	leaflet-control-position.js,

	(c) 2016, FCOO

	https://github.com/FCOO/leaflet-control-position
	https://github.com/FCOO

****************************************************************************/
;(function (L, window, document, undefined) {
	"use strict";

	if (typeof console == "undefined") {
    this.console = { log: function (/*msg*/) { /* do nothing since it would otherwise break IE */} };
	}

	L.Control.Position = L.Control.extend({
    options: {
			VERSION: "{VERSION}",
      collapsed: true,
      position: 'topleft',
      text: 'Zoom to (lat, lon) position',
      bounds: null, // L.LatLngBounds
      className: 'leaflet-control-position',
      icon: 'leaflet-control-position-icon'
    },

    initialize: function (options) {
      L.Util.setOptions(this, options);
      this._container = L.DomUtil.create('div', this.options.className);
      //this._container = L.DomUtil.create('div', 'leaflet-bar ' + className);
    },

    onAdd: function (map) {
      this._map = map;

      var className = this.options.className;
      var container = this._container;

      L.DomEvent.disableClickPropagation(container);

      var form = this._form = L.DomUtil.create('form', className + '-form');

      var input_lon = this._input_lon = document.createElement('input');
      input_lon.className = className + '-form-input-lon';
      input_lon.name = "lon";
      input_lon.type = "text";
      input_lon.placeholder = "Lon (ddd mm ss.sss W/E)";
      var input_lat = this._input_lat = document.createElement('input');
      input_lat.className = className + '-form-input-lat';
      input_lat.type = "text";
      input_lat.name = "lat";
      input_lat.placeholder = "Lat (dd mm ss.sss N/S)";

      var submit = document.createElement('input');
      submit.type = "submit";
      submit.value = this.options.text;

      form.appendChild(input_lat);
      form.appendChild(input_lon);
      form.appendChild(submit);

      L.DomEvent.addListener(form, 'submit', this._position, this);

      if (this.options.collapsed) {
        L.DomEvent.addListener(container, 'mouseover', this._expand, this);
        L.DomEvent.addListener(container, 'mouseout', this._collapse, this);

				var button = this._layersButton = L.DomUtil.create('a', className + ' ' + this.options.icon, container);
        button.title = 'Input latitude and longitude';

        L.DomEvent.addListener(button, L.Browser.touch ? 'click' : 'focus', this._expand, this);

        this._map.on('movestart', this._collapse, this);
      } else {
				this._expand();
      }

      container.appendChild(form);

      return container;
    },

    _position : function (event) {
			var n, lon, lat;
      L.DomEvent.preventDefault(event);
      try {
        lon = window.magellan(this._input_lon.value).longitude();
        if (lon === null) {
          throw new Error('Invalid longitude.');
        }
        lon = parseFloat(lon.toDD());
      } catch(err) {
	      console.log(err);
        n = window.noty({text: err.message, type: "error", timeout: 3500});
        throw err;
      }

			try {
        lat = window.magellan(this._input_lat.value).latitude();
        if (lat === null) {
	        throw new Error('Invalid latitude.');
        }
        lat = parseFloat(lat.toDD());
      } catch(err) {
		    console.log(err);
        n = window.noty({text: err.message, type: "error", timeout: 3500});
        throw err;
      }
      this._map.panTo([lat, lon]);

			if (this._marker !== undefined) {
	      this._map.removeLayer(this._marker);
      }
      this._marker = L.circleMarker([lat, lon], {
	      color: '#136AEC',
        fillColor: '#2A93EE',
        fillOpacity: 0.7,
        weight: 2,
        opacity: 0.9,
        radius: 5
      });

			var _remove_marker = function(arg) {
				this._map.removeLayer(arg.target);
      };
			this._marker.on('click', _remove_marker);
      this._marker.addTo(this._map);
		},

    _expand: function () {
		  L.DomUtil.addClass(this._container, 'leaflet-control-position-expanded');
      //this._layersLink.className = this._layersLink.className.replace(' ' + this.options.icon, '');
    },

		_collapse: function () {
			this._container.className = this._container.className.replace(' leaflet-control-position-expanded', '');
    }
	});

}(L, this, document));

<commit_msg>fixed indentation<commit_after>/****************************************************************************
leaflet-control-position.js,

(c) 2016, FCOO

https://github.com/FCOO/leaflet-control-position
https://github.com/FCOO

****************************************************************************/
;(function (L, window, document, undefined) {
    "use strict";

    if (typeof console == "undefined") {
        this.console = { log: function (/*msg*/) { /* do nothing since it would otherwise break IE */} };
    }

    L.Control.Position = L.Control.extend({
        options: {
            collapsed: true,
            position: 'topleft',
            text: 'Zoom to (lat, lon) position',
            bounds: null, // L.LatLngBounds
            className: 'leaflet-control-position',
            icon: 'leaflet-control-position-icon'
        },

        initialize: function (options) {
            L.Util.setOptions(this, options);
            this._container = L.DomUtil.create('div', this.options.className);
            //this._container = L.DomUtil.create('div', 'leaflet-bar ' + className);
        },

        onAdd: function (map) {
            this._map = map;

            var className = this.options.className;
            var container = this._container;

            L.DomEvent.disableClickPropagation(container);

            var form = this._form = L.DomUtil.create('form', className + '-form');

            var input_lon = this._input_lon = document.createElement('input');
            input_lon.className = className + '-form-input-lon';
            input_lon.name = "lon";
            input_lon.type = "text";
            input_lon.placeholder = "Lon (ddd mm ss.sss W/E)";
            var input_lat = this._input_lat = document.createElement('input');
            input_lat.className = className + '-form-input-lat';
            input_lat.type = "text";
            input_lat.name = "lat";
            input_lat.placeholder = "Lat (dd mm ss.sss N/S)";

            var submit = document.createElement('input');
            submit.type = "submit";
            submit.value = this.options.text;

            form.appendChild(input_lat);
            form.appendChild(input_lon);
            form.appendChild(submit);

            L.DomEvent.addListener(form, 'submit', this._position, this);

            if (this.options.collapsed) {
                L.DomEvent.addListener(container, 'mouseover', this._expand, this);
                L.DomEvent.addListener(container, 'mouseout', this._collapse, this);

                var button = this._layersButton = L.DomUtil.create('a', className + ' ' + this.options.icon, container);
                button.title = 'Input latitude and longitude';

                L.DomEvent.addListener(button, L.Browser.touch ? 'click' : 'focus', this._expand, this);

                this._map.on('movestart', this._collapse, this);
            } else {
                this._expand();
            }

            container.appendChild(form);

            return container;
        },

        _position : function (event) {
            var n, lon, lat;
            L.DomEvent.preventDefault(event);
            try {
                lon = window.magellan(this._input_lon.value).longitude();
                if (lon === null) {
                    throw new Error('Invalid longitude.');
                }
                lon = parseFloat(lon.toDD());
            } catch(err) {
                console.log(err);
                n = window.noty({text: err.message, type: "error", timeout: 3500});
                throw err;
            }

            try {
                lat = window.magellan(this._input_lat.value).latitude();
                if (lat === null) {
                    throw new Error('Invalid latitude.');
                }
                lat = parseFloat(lat.toDD());
            } catch(err) {
                console.log(err);
                n = window.noty({text: err.message, type: "error", timeout: 3500});
                throw err;
            }
            this._map.panTo([lat, lon]);

            if (this._marker !== undefined) {
                this._map.removeLayer(this._marker);
            }
            this._marker = L.circleMarker([lat, lon], {
                color: '#136AEC',
                fillColor: '#2A93EE',
                fillOpacity: 0.7,
                weight: 2,
                opacity: 0.9,
                radius: 5
            });

            var _remove_marker = function(arg) {
                this._map.removeLayer(arg.target);
            };
            this._marker.on('click', _remove_marker);
            this._marker.addTo(this._map);
        },

        _expand: function () {
            L.DomUtil.addClass(this._container, 'leaflet-control-position-expanded');
            //this._layersLink.className = this._layersLink.className.replace(' ' + this.options.icon, '');
        },

        _collapse: function () {
            this._container.className = this._container.className.replace(' leaflet-control-position-expanded', '');
        }
    });

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


<commit_before>var gulp = require('gulp');
var concat = require('gulp-concat');
var pump = require('pump');
var mainBowerFiles = require('gulp-main-bower-files');
var minify = require('gulp-clean-css');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');

gulp.task('css', function(cb) {
    pump([
        gulp.src('./bower.json'),
        mainBowerFiles('**/*.css'),
        concat('ng-croppie.css'),
        gulp.dest('./'),
        //minified
        rename({suffix: '.min'}),
        minify({compatibility: 'ie11', keepBreaks: true}),
        gulp.dest('./')
    ], cb);
});

gulp.task('js', function(cb) {
    pump([
        gulp.src('ng-croppie.js'),
        rename({suffix: '.min'}),
        uglify(),
        gulp.dest('./')
    ], cb);
});

gulp.task('default', ['css', 'js']);
<commit_msg>add minify task<commit_after>var gulp = require('gulp');
var concat = require('gulp-concat');
var pump = require('pump');
var mainBowerFiles = require('gulp-main-bower-files');
var minify = require('gulp-clean-css');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');

gulp.task('css', function(cb) {
    pump([
        gulp.src('./bower.json'),
        mainBowerFiles('**/*.css'),
        concat('ng-croppie.css'),
        gulp.dest('./')
    ], cb);
});

gulp.task('css-minify', function(cb) {
    pump([
        gulp.src('./bower.json'),
        mainBowerFiles('**/*.css'),
        concat('ng-croppie.css'),
        rename({suffix: '.min'}),
        minify({compatibility: 'ie11', keepBreaks: true}),
        gulp.dest('./')
    ], cb);
});

gulp.task('js', function(cb) {
    pump([
        gulp.src('ng-croppie.js'),
        rename({suffix: '.min'}),
        uglify(),
        gulp.dest('./')
    ], cb);
});

gulp.task('default', ['css', 'css-minify', 'js']);<|endoftext|>


<commit_before>// Copyright 2014-2015 runtime.js project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';
var packagejson = require('./package.json');
require('module-singleton')(packagejson);
require('./version');

console.log(`v${packagejson.version} core library`);
console.log('loading...');

var isDebug = packagejson.runtimejs.debug;
global.debug = isDebug ? isolate.log : function() {};

// Load runtime.js core
require('./core');

// Start services
require('./service/dhcp-client');

runtime.shell = require('./service/shell');
runtime.dns = require('./service/dns-resolver');
runtime.debug = isDebug;

// Example shell command
runtime.shell.setCommand('1', function(args, cb) {
  runtime.tty.print('OK.\n');
  runtime.dns.resolve('www.google.com', {}, function(err, data) {
    if (err) return cb();
    console.log(JSON.stringify(data));
    cb();
  });
});

// Builtin functions
require('./builtins/clear')(runtime);
require('./builtins/echo')(runtime);
require('./builtins/power')(runtime);

// Start device drivers
require('./driver/ps2');
require('./driver/virtio');

module.exports = runtime;
<commit_msg>Update requires<commit_after>// Copyright 2014-2015 runtime.js project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';
var packagejson = require('./package.json');
require('module-singleton')(packagejson);
require('./version');

console.log(`v${packagejson.version} core library`);
console.log('loading...');

var isDebug = packagejson.runtimejs.debug;
global.debug = isDebug ? isolate.log : function() {};

// Load runtime.js core
require('./core');

// Start services
require('./service/dhcp-client');

runtime.shell = require('./service/shell');
runtime.dns = require('./service/dns-resolver');
runtime.debug = isDebug;

// Example shell command
runtime.shell.setCommand('1', function(args, cb) {
  runtime.tty.print('OK.\n');
  runtime.dns.resolve('www.google.com', {}, function(err, data) {
    if (err) return cb();
    console.log(JSON.stringify(data));
    cb();
  });
});

// Builtin functions
require('./shell/clear')(runtime);
require('./shell/echo')(runtime);
require('./shell/power')(runtime);

// Start device drivers
require('./driver/ps2');
require('./driver/virtio');

module.exports = runtime;
<|endoftext|>