<commit_before>angular.module('index', ['ui.bootstrap','chart.js'])
    .controller('IndexController', function ($scope) {
        var basetitle = 'electionDay';
        $scope.title = basetitle;
        $scope.$watch('numseggio', function () {
            if ($scope.numseggio > 0)
                $scope.title = basetitle + " - Seggio " + $scope.numseggio;
            else
                $scope.title = basetitle
        });

        oraInizio = 7;
        oraFine = 23;
        labels = [];
        for(var j=oraInizio;j<=oraFine;j++)
        {
            labels.push('ore ' + j);
        }
        $scope.data = {};
        $scope.resetData = function(all){
            if(all===true) {
                if(confirm("Vuoi cancellare tutti i dati salvati?")) {
                    $scope.data = {};
                    $scope.data.settings = {maxdonne: 0, maxuomini: 0, maxtotale: 0};
                }
            }
            $scope.data.dati = [];
        };

        $scope.addOra = function(){
            if($scope.data.dati.length === 0){
                this_ora = oraInizio;
            }
            else{
                this_ora = $scope.data.dati.slice(-1)[0].ora + 1;
            }
            if(this_ora <= oraFine)
                $scope.data.dati.push({'ora': this_ora, 'donne': 0, 'uomini': 0});
        };

        $scope.removeLastOra =  function(){
            if($scope.data.dati.length > 1){
                $scope.data.dati.pop();
            }
        };

        $scope.drawPieDistribuzione = function() {
            pie_uomini = $scope.data.dati.slice(-1)[0].uomini;
            pie_donne = $scope.data.dati.slice(-1)[0].donne;
            pie_tot = pie_donne + pie_uomini;

            $scope.labels_distribuzione = ["Femmine", "Maschi"];
            $scope.data_distribuzione = null;
            $scope.data_distribuzione = [pie_donne, pie_uomini];
            $scope.colors_distribuzione = ['#ff6384', '#2117c0'];
            $scope.options_distribuzione = {
                legend: {display: true}, tooltips: {
                    callbacks: {
                        label: function (tooltipItem, data) {
                            var value = data.datasets[0].data[tooltipItem.index];
                            var label = data.labels[tooltipItem.index];
                            var perc = Math.round(value / pie_tot * 100);
                            return label + ': ' + perc + '%';
                        }
                    }
                }
            };
            $scope.type_distribuzione = 'pie';
        };

        $scope.drawPieAffluenza = function(){
            pie_tot_votanti =  $scope.data.settings.maxtotale;

            pie_votanti = $scope.data.dati.slice(-1)[0].totale;
            pie_non_votanti = pie_tot_votanti - $scope.data.dati.slice(-1)[0].totale;

            $scope.labels_affluenza = ["Votanti", "Non Votanti"];
            $scope.data_affluenza = null;
            $scope.data_affluenza = [pie_votanti, pie_non_votanti];
            $scope.colors_affluenza = ['#00ee00','#cccccc'];
            $scope.options_affluenza ={ legend: { display: true }, tooltips: {
                callbacks: {
                    label: function(tooltipItem, data) {
                        var value = data.datasets[0].data[tooltipItem.index];
                        var label = data.labels[tooltipItem.index];
                        var perc = Math.round(value / pie_tot_votanti * 100);
                        return label + ': ' + perc + '%';
                    }
                }
            }};
            $scope.type_affluenza = 'pie';
        };

        $scope.drawGraph = function () {
            $scope.glabels = [];
            for (var i = oraInizio; i <= oraFine; i++) {
                $scope.glabels.push('ore ' + i);
            }
            $scope.gseries = ['Maschi', 'Femmine', 'Totale'];
            $scope.gdata = [[],[],[]];
            $scope.data.dati.forEach(function(x){
                $scope.gdata[0].push(x.uomini);
                $scope.gdata[1].push(x.donne);
                $scope.gdata[2].push(x.totale);
            });
            $scope.gcolors = ['#2117c0','#ff6384','#4bc0c0'];
            $scope.goptions = {
                scales: {
                    yAxes: [
                        {
                            id: 'y-axis-1',
                            type: 'linear',
                            display: true,
                            position: 'left'
                        }
                    ]
                }
            };
        };

        $scope.reloadGraphs = function(){
            $scope.drawGraph();
            $scope.drawPieDistribuzione();
            $scope.drawPieAffluenza();
        };
        $scope.toggle = function () {
            $scope.type_distribuzione = $scope.type_distribuzione === 'doughnut' ? 'pie' : 'doughnut';
            $scope.type_affluenza = $scope.type_affluenza === 'doughnut' ? 'pie' : 'doughnut';
            $scope.type_line = $scope.type_line === 'bar' ? 'line' : 'bar';
        };

        //getting data from localstorage, or initializing data if not set.
        var data_ls = localStorage.getItem('data');
        if (data_ls === null) {
            console.log('data is null! initializing data');
            $scope.resetData();
            $scope.addOra();
        }
        else {
            $scope.data = JSON.parse(data_ls);
            $scope.reloadGraphs();
        }

        $scope.$watch('data', function(){
            console.log('data changed, saving again');
            if ($scope.data) {
                localStorage.setItem('data', JSON.stringify($scope.data));
                console.log($scope.data);
            }
        }, true);

});<commit_msg>aggiunto spanGaps per plot di orari senza dati<commit_after>angular.module('index', ['ui.bootstrap','chart.js'])
    .controller('IndexController', function ($scope) {
        var basetitle = 'electionDay';
        $scope.title = basetitle;
        $scope.$watch('numseggio', function () {
            if ($scope.numseggio > 0)
                $scope.title = basetitle + " - Seggio " + $scope.numseggio;
            else
                $scope.title = basetitle
        });

        oraInizio = 7;
        oraFine = 23;
        labels = [];
        for(var j=oraInizio;j<=oraFine;j++)
        {
            labels.push('ore ' + j);
        }
        $scope.data = {};
        $scope.resetData = function(all){
            if(all===true) {
                if(confirm("Vuoi cancellare tutti i dati salvati?")) {
                    $scope.data = {};
                    $scope.data.settings = {maxdonne: 0, maxuomini: 0, maxtotale: 0};
                }
            }
            $scope.data.dati = [];
        };

        $scope.addOra = function(){
            if($scope.data.dati.length === 0){
                this_ora = oraInizio;
            }
            else{
                this_ora = $scope.data.dati.slice(-1)[0].ora + 1;
            }
            if(this_ora <= oraFine)
                $scope.data.dati.push({'ora': this_ora, 'donne': 0, 'uomini': 0});
        };

        $scope.removeLastOra =  function(){
            if($scope.data.dati.length > 1){
                $scope.data.dati.pop();
            }
        };

        $scope.drawPieDistribuzione = function() {
            pie_uomini = $scope.data.dati.slice(-1)[0].uomini;
            pie_donne = $scope.data.dati.slice(-1)[0].donne;
            pie_tot = pie_donne + pie_uomini;

            $scope.labels_distribuzione = ["Femmine", "Maschi"];
            $scope.data_distribuzione = null;
            $scope.data_distribuzione = [pie_donne, pie_uomini];
            $scope.colors_distribuzione = ['#ff6384', '#2117c0'];
            $scope.options_distribuzione = {
                legend: {display: true}, tooltips: {
                    callbacks: {
                        label: function (tooltipItem, data) {
                            var value = data.datasets[0].data[tooltipItem.index];
                            var label = data.labels[tooltipItem.index];
                            var perc = Math.round(value / pie_tot * 100);
                            return label + ': ' + perc + '%';
                        }
                    }
                }
            };
            $scope.type_distribuzione = 'pie';
        };

        $scope.drawPieAffluenza = function(){
            pie_tot_votanti =  $scope.data.settings.maxtotale;

            pie_votanti = $scope.data.dati.slice(-1)[0].totale;
            pie_non_votanti = pie_tot_votanti - $scope.data.dati.slice(-1)[0].totale;

            $scope.labels_affluenza = ["Votanti", "Non Votanti"];
            $scope.data_affluenza = null;
            $scope.data_affluenza = [pie_votanti, pie_non_votanti];
            $scope.colors_affluenza = ['#00ee00','#cccccc'];
            $scope.options_affluenza ={ legend: { display: true }, tooltips: {
                callbacks: {
                    label: function(tooltipItem, data) {
                        var value = data.datasets[0].data[tooltipItem.index];
                        var label = data.labels[tooltipItem.index];
                        var perc = Math.round(value / pie_tot_votanti * 100);
                        return label + ': ' + perc + '%';
                    }
                }
            }};
            $scope.type_affluenza = 'pie';
        };

        $scope.drawGraph = function () {
            $scope.glabels = [];
            for (var i = oraInizio; i <= oraFine; i++) {
                $scope.glabels.push('ore ' + i);
            }
            $scope.gseries = ['Maschi', 'Femmine', 'Totale'];
            $scope.gdata = [[],[],[]];
            $scope.data.dati.forEach(function(x){
                $scope.gdata[0].push((x.uomini === 0 && x.ora!==oraInizio) ? null : x.uomini);
                $scope.gdata[1].push((x.donne === 0 && x.ora!==oraInizio) ? null : x.donne);
                $scope.gdata[2].push((x.totale === 0 && x.ora!==oraInizio) ? null : x.totale);
            });
            $scope.gcolors = ['#2117c0','#ff6384','#4bc0c0'];
            $scope.goptions = {
                spanGaps: true,
                scales: {
                    yAxes: [
                        {
                            id: 'y-axis-1',
                            type: 'linear',
                            display: true,
                            position: 'left'
                        }
                    ]
                }
            };
        };

        $scope.reloadGraphs = function(){
            $scope.drawGraph();
            $scope.drawPieDistribuzione();
            $scope.drawPieAffluenza();
        };
        $scope.toggle = function () {
            $scope.type_distribuzione = $scope.type_distribuzione === 'doughnut' ? 'pie' : 'doughnut';
            $scope.type_affluenza = $scope.type_affluenza === 'doughnut' ? 'pie' : 'doughnut';
            $scope.type_line = $scope.type_line === 'bar' ? 'line' : 'bar';
        };

        //getting data from localstorage, or initializing data if not set.
        var data_ls = localStorage.getItem('data');
        if (data_ls === null) {
            console.log('data is null! initializing data');
            $scope.resetData();
            $scope.addOra();
        }
        else {
            $scope.data = JSON.parse(data_ls);
            $scope.reloadGraphs();
        }

        $scope.$watch('data', function(){
            console.log('data changed, saving again');
            if ($scope.data) {
                localStorage.setItem('data', JSON.stringify($scope.data));
                console.log($scope.data);
            }
        }, true);

});<|endoftext|>


<commit_before>'use strict';
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var debug = require('debug')('meshblu-chromecast')
var Client = require('castv2').Client;
var mdns = require('mdns');
var io = require('socket.io-client')
var getYouTubeId = require('get-youtube-id');
var chromecastFound;
var _ = require('lodash');

var MESSAGE_SCHEMA = {
  type: 'object',
  properties: {
    CastingApplication: {
      type: 'string',
      "enum" : ['youtube', 'DisplayText', 'Url' , 'Media', 'CustomApp' ] ,
      required: true
    },
    youtubeUrl: {
      type: 'string',
      required: true
    },
    Message: {
      type: 'string',
      required: true
    },
    Url: {
      type: 'string',
      required: true
    },
    MediaURL: {
      type: 'string',
      required: true
    },
    AppID: {
      type: 'string',
      required: true
    },
    urn: {
      type: 'string',
      required: true
    },
    payload: {
      type: 'string',
      required: true
    }
  }
};

var OPTIONS_SCHEMA = {
  type: 'object',
  properties: {
    AutoDiscovery: {
      type: 'boolean',
      required: true
    },
    ChromecastName: {
      type: 'string',
      required: true
    }
  }
};

var doesMatchPluginSerivce = function(pluginName, serviceName){
  if(!pluginName || !serviceName) return;
  return pluginName.toLowerCase() === serviceName.toLowerCase;
};

function Plugin(){
  var self = this;
  self.options = {};
  self.messageSchema = MESSAGE_SCHEMA;
  self.optionsSchema = OPTIONS_SCHEMA;
  self.requestId = 1443;
  return self;
}

util.inherits(Plugin, EventEmitter);

Plugin.prototype.onMessage = function (message) {
  debug('onMessage', message);

  if (!message.payload) return;

  this.detectChromecast(message.payload);
};

Plugin.prototype.onConfig = function(device){
  debug('onConfig');

  this.setOptions(device.options || {});
  this.setupChromecast();
};

Plugin.prototype.setOptions = function (options){
  this.options = options || {};
};

Plugin.prototype.setupChromecast = function() {
  debug('Setting up chromecast....');
};

Plugin.prototype.detectChromecast = function (message) {
  var self = this,
    pluginName = self.options.ChromecastName,
    autodiscovery = self.options.AutoDiscovery;

  if(!autodiscovery && !pluginName) return;

  var browser = mdns.createBrowser(mdns.tcp('googlecast')).on('serviceUp', function (chromecast) {
    self.chromecast = chromecast;
    if (autodiscovery || doesMatchPluginSerivce(pluginName, self.chromecast.name)) {
      return self.sendMessageToDevice(message, self.chromecast);
    }
  });

  browser.start();
};

 Plugin.prototype.sendMessageToDevice = function (message, service) {
  debug('sendMessageToDevice', 'Casting...');

  var hostIP = service.addresses[0];

  // this.emit('message', { devices: ['*'], topic: 'echo', payload: service });
  this.onDeviceUp(hostIP, message);
}

Plugin.prototype.onDeviceUp = function (host, message) {
  debug('onDeviceUp', message);
  var self = this;
  self.client = new Client();

  self.client.connect(host, function () {
    self.sendMessageToClient(message);
  });
}

Plugin.prototype.sendMessageToClient = function(message){
  var self = this;
  var APPID = this.getChromecastApplicationID(message);
  // Google Chromecast various namespace handlers for initializing connection.
  var connection = self.client.createChannel('sender-0', 'receiver-0', 'urn:x-cast:com.google.cast.tp.connection', 'JSON');
  var heartbeat = self.client.createChannel('sender-0', 'receiver-0', 'urn:x-cast:com.google.cast.tp.heartbeat', 'JSON');
  var receiver = self.client.createChannel('sender-0', 'receiver-0', 'urn:x-cast:com.google.cast.receiver', 'JSON');

  var launchRequestId;

  // establish virtual connection to the receiver
  connection.send({ type: 'CONNECT' });

  // Check first if the app is avaliable.
  receiver.send({ type: 'GET_APP_AVAILABILITY', appId: [APPID], requestId: self.requestId });

  // start heartbeating
  setInterval(function () {
    heartbeat.send({ type: 'PING' });
  }, 5000);

  receiver.on('message', function (data, broadcast) {
    debug('chromecast on message', data);
    if (data.requestId === self.requestId) {
      if ('APP_AVAILABLE' === data.availability[APPID]) {
        debug('app is available');
        // console.log(data);
        launchRequestId = self.requestId;
        debug('request id', self.requestId);
        receiver.send({ type: 'LAUNCH', appId: APPID, requestId: self.requestId++ });
      }
    }else if (data.requestId == launchRequestId) {
      debug('handling launch response...');
      var app = _.find(data.status.applications, {appId: APPID})
      if(_.isEmpty(app)) return;
      var mySenderConnection = self.client.createChannel('client-13243', app.transportId, 'urn:x-cast:com.google.cast.tp.connection', 'JSON');
      mySenderConnection.send({ type: 'CONNECT' });
      self.sendChromecastAppSpecficMessage(message, app, self.client);
    }
  });
};

Plugin.prototype.getChromecastApplicationID = function (message) {
  debug('getChromecastApplicationID');

  if (_.has(message, 'CastingApplication')) {
    switch (message.CastingApplication) {
      case 'youtube':
      return '233637DE';
      case 'DisplayText':
      return '794B7BBF';
      case 'Url':
      return '7897BA3B';
      case 'Media':
      return 'CC1AD845';
      case 'CustomApp':
      return message.AppID;
    }
  }
}

Plugin.prototype.getChromecastAppNamespace = function (message) {
  if (_.has(message, 'CastingApplication')) {
    switch (message.CastingApplication) {
      case 'youtube':
      return 'urn:x-cast:com.google.youtube.mdx';
      case 'DisplayText':
      return 'urn:x-cast:com.google.cast.sample.helloworld';
      case 'Url':
      return 'urn:x-cast:uk.co.splintered.urlcaster';
      case 'Media':
      return 'urn:x-cast:com.google.cast.media';
      case 'CustomApp':
      return message.urn;
    }
  }

}

Plugin.prototype.sendChromecastAppSpecficMessage = function (message, app, client) {
  debug('sending chromecast a specific message');
  var self = this;
  var namespace = self.getChromecastAppNamespace(message);

  if (!_.has(message, 'CastingApplication')) {
    return;
  }
  switch (message.CastingApplication) {
    case 'youtube':
      if(!_.has(message, 'youtubeUrl')){ return; }
      // var link = 'https://www.youtube.com/watch?v=0vxOhd4qlnA';
      var youtubeId = getYouTubeId(message.youtubeUrl);
      debug('Sending Youtube', message.youtubeUrl, youtubeId);
      var url = client.createChannel('client-13243', app.transportId, namespace, 'JSON');
      url.send({
        type: 'flingVideo',
        data: {
          currentTime: 0,
          videoId: youtubeId
        }
      });
      break;
    case 'DisplayText':
      if(!_.has(message, 'Message')){ return; }
      var url = client.createChannel('client-13243', app.transportId, namespace);
      url.send(message.Message);
      break;
    case 'Url':
      if(!_.has(message, 'MeetingID')){ return; }
      var url = client.createChannel('client-13243', app.transportId, namespace);
      url.send(message.Url);
      break;
    case 'Media':
      if(!_.has(message, 'MediaURL')){ return; }
      var url = client.createChannel('client-13243', app.transportId, namespace, 'JSON');
      url.send({
        type: 'LOAD',
        requestId: 77063063,
        sessionId: app.sessionId,
        media: {
          contentId: message.MediaURL,
          streamType: 'LIVE',
          contentType: 'video/mp4'
        },
        autoplay: true,
        currentTime: 0,
        customData: {
          payload: {
            title: 'Triggered from Octoblu'
          }
        }
      });
      break;
  }
}
module.exports = {
  messageSchema: MESSAGE_SCHEMA,
  optionsSchema: OPTIONS_SCHEMA,
  Plugin: Plugin
};
<commit_msg>Debounced detectChromecast<commit_after>'use strict';
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var debug = require('debug')('meshblu-chromecast')
var Client = require('castv2').Client;
var mdns = require('mdns');
var io = require('socket.io-client')
var getYouTubeId = require('get-youtube-id');
var chromecastFound;
var _ = require('lodash');

var MESSAGE_SCHEMA = {
  type: 'object',
  properties: {
    CastingApplication: {
      type: 'string',
      "enum" : ['youtube', 'DisplayText', 'Url' , 'Media', 'CustomApp' ] ,
      required: true
    },
    youtubeUrl: {
      type: 'string',
      required: true
    },
    Message: {
      type: 'string',
      required: true
    },
    Url: {
      type: 'string',
      required: true
    },
    MediaURL: {
      type: 'string',
      required: true
    },
    AppID: {
      type: 'string',
      required: true
    },
    urn: {
      type: 'string',
      required: true
    },
    payload: {
      type: 'string',
      required: true
    }
  }
};

var OPTIONS_SCHEMA = {
  type: 'object',
  properties: {
    AutoDiscovery: {
      type: 'boolean',
      required: true
    },
    ChromecastName: {
      type: 'string',
      required: true
    }
  }
};

var doesMatchPluginSerivce = function(pluginName, serviceName){
  if(!pluginName || !serviceName) return;
  return pluginName.toLowerCase() === serviceName.toLowerCase;
};

function Plugin(){
  var self = this;
  self.options = {};
  self.messageSchema = MESSAGE_SCHEMA;
  self.optionsSchema = OPTIONS_SCHEMA;
  self.requestId = 1443;
  return self;
}

util.inherits(Plugin, EventEmitter);

Plugin.prototype.onMessage = function (message) {
  debug('onMessage', message);

  if (!message.payload) return;

  this.detectChromecast(message.payload);
};

Plugin.prototype.onConfig = function(device){
  debug('onConfig');

  this.setOptions(device.options || {});
  this.setupChromecast();
};

Plugin.prototype.setOptions = function (options){
  this.options = options || {};
};

Plugin.prototype.setupChromecast = function() {
  debug('Setting up chromecast....');
};

Plugin.prototype.detectChromecastImmediately = function (message) {
  var self = this,
    pluginName = self.options.ChromecastName,
    autodiscovery = self.options.AutoDiscovery;

  if(!autodiscovery && !pluginName) return;

  var browser = mdns.createBrowser(mdns.tcp('googlecast')).on('serviceUp', function (chromecast) {
    self.chromecast = chromecast;
    if (autodiscovery || doesMatchPluginSerivce(pluginName, self.chromecast.name)) {
      return self.sendMessageToDevice(message, self.chromecast);
    }
  });

  browser.start();
};

Plugin.prototype.detectChromecast = _.debounce(Plugin.prototype.detectChromecastImmediately, 1000);

Plugin.prototype.sendMessageToDevice = function (message, service) {
  debug('sendMessageToDevice', 'Casting...');

  var hostIP = service.addresses[0];

  // this.emit('message', { devices: ['*'], topic: 'echo', payload: service });
  this.onDeviceUp(hostIP, message);
}

Plugin.prototype.onDeviceUp = function (host, message) {
  debug('onDeviceUp', message);
  var self = this;
  self.client = new Client();

  self.client.connect(host, function () {
    self.sendMessageToClient(message);
  });
}

Plugin.prototype.sendMessageToClient = function(message){
  var self = this;
  var APPID = this.getChromecastApplicationID(message);
  // Google Chromecast various namespace handlers for initializing connection.
  var connection = self.client.createChannel('sender-0', 'receiver-0', 'urn:x-cast:com.google.cast.tp.connection', 'JSON');
  var heartbeat = self.client.createChannel('sender-0', 'receiver-0', 'urn:x-cast:com.google.cast.tp.heartbeat', 'JSON');
  var receiver = self.client.createChannel('sender-0', 'receiver-0', 'urn:x-cast:com.google.cast.receiver', 'JSON');

  var launchRequestId;

  // establish virtual connection to the receiver
  connection.send({ type: 'CONNECT' });

  // Check first if the app is avaliable.
  receiver.send({ type: 'GET_APP_AVAILABILITY', appId: [APPID], requestId: self.requestId });

  // start heartbeating
  setInterval(function () {
    heartbeat.send({ type: 'PING' });
  }, 5000);

  receiver.on('message', function (data, broadcast) {
    debug('chromecast ReceiverMessage', JSON.stringify(data));
    if (data.requestId === self.requestId) {
      debug('data requestId');
      debug('self requestId');
      if ('APP_AVAILABLE' === data.availability[APPID]) {
        debug('app is available', data.availability[APPID]);
        launchRequestId = self.requestId;
        debug('request id', self.requestId);
        receiver.send({ type: 'LAUNCH', appId: APPID, requestId: self.requestId++ });
      }
    }else if (data.requestId == launchRequestId) {
      // data requestId and self requestId are diff
      debug('handling launch response...');
      debug('launchRequestId', launchRequestId);
      var app = _.find(data.status.applications, {appId: APPID})
      if(_.isEmpty(app)) return;
      var mySenderConnection = self.client.createChannel('client-13243', app.transportId, 'urn:x-cast:com.google.cast.tp.connection', 'JSON');
      mySenderConnection.send({ type: 'CONNECT' });
      self.sendChromecastAppSpecficMessage(message, app, self.client);
    }
  });
};

Plugin.prototype.getChromecastApplicationID = function (message) {
  debug('getChromecastApplicationID');

  if (_.has(message, 'CastingApplication')) {
    switch (message.CastingApplication) {
      case 'youtube':
      return '233637DE';
      case 'DisplayText':
      return '794B7BBF';
      case 'Url':
      return '7897BA3B';
      case 'Media':
      return 'CC1AD845';
      case 'CustomApp':
      return message.AppID;
    }
  }
}

Plugin.prototype.getChromecastAppNamespace = function (message) {
  if (_.has(message, 'CastingApplication')) {
    switch (message.CastingApplication) {
      case 'youtube':
      return 'urn:x-cast:com.google.youtube.mdx';
      case 'DisplayText':
      return 'urn:x-cast:com.google.cast.sample.helloworld';
      case 'Url':
      return 'urn:x-cast:uk.co.splintered.urlcaster';
      case 'Media':
      return 'urn:x-cast:com.google.cast.media';
      case 'CustomApp':
      return message.urn;
    }
  }

}

Plugin.prototype.sendChromecastAppSpecficMessage = function (message, app, client) {
  debug('sending chromecast a specific message');
  var self = this;
  var namespace = self.getChromecastAppNamespace(message);

  if (!_.has(message, 'CastingApplication')) {
    return;
  }
  switch (message.CastingApplication) {
    case 'youtube':
      if(!_.has(message, 'youtubeUrl')){ return; }
      // var link = 'https://www.youtube.com/watch?v=0vxOhd4qlnA';
      var youtubeId = getYouTubeId(message.youtubeUrl);
      debug('Sending Youtube', message.youtubeUrl, youtubeId);
      var url = client.createChannel('client-13243', app.transportId, namespace, 'JSON');
      url.send({
        type: 'flingVideo',
        data: {
          currentTime: 0,
          videoId: youtubeId
        }
      });
      break;
    case 'DisplayText':
      if(!_.has(message, 'Message')){ return; }
      var url = client.createChannel('client-13243', app.transportId, namespace);
      url.send(message.Message);
      break;
    case 'Url':
      if(!_.has(message, 'MeetingID')){ return; }
      var url = client.createChannel('client-13243', app.transportId, namespace);
      url.send(message.Url);
      break;
    case 'Media':
      if(!_.has(message, 'MediaURL')){ return; }
      var url = client.createChannel('client-13243', app.transportId, namespace, 'JSON');
      url.send({
        type: 'LOAD',
        requestId: 77063063,
        sessionId: app.sessionId,
        media: {
          contentId: message.MediaURL,
          streamType: 'LIVE',
          contentType: 'video/mp4'
        },
        autoplay: true,
        currentTime: 0,
        customData: {
          payload: {
            title: 'Triggered from Octoblu'
          }
        }
      });
      break;
  }
}
module.exports = {
  messageSchema: MESSAGE_SCHEMA,
  optionsSchema: OPTIONS_SCHEMA,
  Plugin: Plugin
};
<|endoftext|>


<commit_before>'use strict';

var Promise = require('native-or-bluebird');
var es = require('elasticsearch');
var merge = require('node-helper-utilities').merge;

var Driver = function OsmosElasticDriver(options, index) {
  this.client = es.Client(options);
  this.index = index;
};

Driver.prototype.createIndices = function createIndex(model, data, callback) {
  if('object' !== typeof data) {
    throw new Error('`data` needs to be a valid object!');
  }

  if(!data.hasOwnProperty('type')) {
    data.type = model.bucket;
  }

  if(!data.hasOwnProperty('body')) {
    data.body = {};
  }

  var indices = merge(data, {
    index: this.index
  });

  return this.client.indices.create(indices, function(err) {
    callback(err);
  });
};

Driver.prototype.create = function create(model, callback) {
  return Promise.resolve({}).nodeify(callback);
};

Driver.prototype.get = function get(model, key, callback) {
  var spec = {
    index: this.index,
    type: model.bucket,
    id: key
  };
  return this.client.get(spec).then(function(result) {
    result._source[model.schema.primaryKey] = result._id;

    return Promise.resolve(result._source);
  }).nodeify(callback);
};

Driver.prototype.post = function post(document, data, callback) {
  var payload = {
    index: this.index,
    type: document.model.bucket,
    body: data,
    published: true,
    refresh: true,
    consistency: 'quorum'
  };

  if (document.primaryKey) {
    payload.id = document.primaryKey;
  }

  return this.client.index(payload).then(function(result) {
    document.primaryKey = result._id;

    return Promise.resolve();
  }).nodeify(callback);
};

Driver.prototype.put = function put(document, set, unset, callback) {
  if(!(document.model.schema.primaryKey && document.primaryKey)) {
    return Promise.reject(new Error('You cannot put a document without a primary key')).nodeify(callback);
  }

  if(!document.__originalData__[document.model.schema.primaryKey]) {
    return this.post(document, data).nodeify(callback);
  }

  var diff = {};
  Object.keys(set).forEach(function(k) {

    diff[k] = set[k];
  });

  Object.keys(unset).forEach(function(k) {
    diff[k] = null;
  });

  var primaryKey;

  if (diff[document.schema.primaryKey]) {
    primaryKey = document.__originalData__[document.schema.primaryKey];
  } else {
    primaryKey = document.primaryKey;
  }

  var payload = {
    index: this.index,
    type: document.model.bucket,
    consistency: 'quorum',
    refresh: true,
    body: {
      doc: diff
    },
    id: primaryKey
  };

  return this.client.update(payload);
};

Driver.prototype.del = function deleteRecord(model, key, callback) {
  if (key.constructor.name === 'Object') {
    key = key[Object.keys(key)[0]];
  }
  var spec ={
    index: this.index,
    type: model.bucket,
    id: key,
    refresh: true
  };

  return this.client.delete(spec);
};

Driver.prototype.findOne = function findOne(model, spec, callback) {
  var body = merge({ size: 1 }, spec);

  var query = {
    index: this.index,
    type: model.bucket,
    body: body
  };

  return this.client.search(query).then(function(result) {
    var records = result.hits.hits;

    records = records.map(function(record) {
      record._source[model.schema.primaryKey] = record._id;

      return record._source;
    });

    if (records.length) {
      return Promise.resolve(records[0]);
    } else {
      return Promise.resolve();
    }
  }).nodeify(callback);
};

Driver.prototype.count = function count(model, spec, callback) {
  return this.find(model, spec).then(function(records) {
    return Promise.resolve(records.length);
  }).nodeify(callback);
};

Driver.prototype.find = function find(model, spec, callback) {
  var body = merge({
    size: 9999999
  }, spec);

  var query = {
    index: this.index,
    type: model.bucket,
    body: body
  };

  return this.client.search(query).then(function(result) {
    var records = result.hits.hits;

    records = records.map(function(record) {
      record._source[model.schema.primaryKey] = record._id;

      return record._source;
    });

    return Promise.resolve(records);
  });
};

Driver.prototype.findLimit = function findLimit(model, spec, start, limit, callback) {
  var body = merge({
    from: start,
    size: limit
  }, spec);

  var query = {
    index: this.index,
    type: model.bucket,
    body: body
  };

  return this.client.search(query).then(function(err, result) {
    var records = result.hits.hits;

    records = records.map(function(record) {
      record._source[model.schema.primaryKey] = record._id;

      return record._source;
    });

    return Promise.resolve({
      docs: records,
      count: result.hits.total,
      start: start,
      limit: limit
    });
  });
};

module.exports = Driver;
<commit_msg>code: use promise for creating indices<commit_after>'use strict';

var Promise = require('native-or-bluebird');
var es = require('elasticsearch');
var merge = require('node-helper-utilities').merge;

var Driver = function OsmosElasticDriver(options, index) {
  this.client = es.Client(options);
  this.index = index;
};

Driver.prototype.createIndices = function createIndex(model, data, callback) {
  if('object' !== typeof data) {
    throw new Error('`data` needs to be a valid object!');
  }

  if(!data.hasOwnProperty('type')) {
    data.type = model.bucket;
  }

  if(!data.hasOwnProperty('body')) {
    data.body = {};
  }

  var indices = merge(data, {
    index: this.index
  });

  return this.client.indices.create(indices).nodeify(callback);
};

Driver.prototype.create = function create(model, callback) {
  return Promise.resolve({}).nodeify(callback);
};

Driver.prototype.get = function get(model, key, callback) {
  var spec = {
    index: this.index,
    type: model.bucket,
    id: key
  };
  return this.client.get(spec).then(function(result) {
    result._source[model.schema.primaryKey] = result._id;

    return Promise.resolve(result._source);
  }).nodeify(callback);
};

Driver.prototype.post = function post(document, data, callback) {
  var payload = {
    index: this.index,
    type: document.model.bucket,
    body: data,
    published: true,
    refresh: true,
    consistency: 'quorum'
  };

  if (document.primaryKey) {
    payload.id = document.primaryKey;
  }

  return this.client.index(payload).then(function(result) {
    document.primaryKey = result._id;

    return Promise.resolve();
  }).nodeify(callback);
};

Driver.prototype.put = function put(document, set, unset, callback) {
  if(!(document.model.schema.primaryKey && document.primaryKey)) {
    return Promise.reject(new Error('You cannot put a document without a primary key')).nodeify(callback);
  }

  if(!document.__originalData__[document.model.schema.primaryKey]) {
    return this.post(document, data).nodeify(callback);
  }

  var diff = {};
  Object.keys(set).forEach(function(k) {

    diff[k] = set[k];
  });

  Object.keys(unset).forEach(function(k) {
    diff[k] = null;
  });

  var primaryKey;

  if (diff[document.schema.primaryKey]) {
    primaryKey = document.__originalData__[document.schema.primaryKey];
  } else {
    primaryKey = document.primaryKey;
  }

  var payload = {
    index: this.index,
    type: document.model.bucket,
    consistency: 'quorum',
    refresh: true,
    body: {
      doc: diff
    },
    id: primaryKey
  };

  return this.client.update(payload);
};

Driver.prototype.del = function deleteRecord(model, key, callback) {
  if (key.constructor.name === 'Object') {
    key = key[Object.keys(key)[0]];
  }
  var spec ={
    index: this.index,
    type: model.bucket,
    id: key,
    refresh: true
  };

  return this.client.delete(spec);
};

Driver.prototype.findOne = function findOne(model, spec, callback) {
  var body = merge({ size: 1 }, spec);

  var query = {
    index: this.index,
    type: model.bucket,
    body: body
  };

  return this.client.search(query).then(function(result) {
    var records = result.hits.hits;

    records = records.map(function(record) {
      record._source[model.schema.primaryKey] = record._id;

      return record._source;
    });

    if (records.length) {
      return Promise.resolve(records[0]);
    } else {
      return Promise.resolve();
    }
  }).nodeify(callback);
};

Driver.prototype.count = function count(model, spec, callback) {
  return this.find(model, spec).then(function(records) {
    return Promise.resolve(records.length);
  }).nodeify(callback);
};

Driver.prototype.find = function find(model, spec, callback) {
  var body = merge({
    size: 9999999
  }, spec);

  var query = {
    index: this.index,
    type: model.bucket,
    body: body
  };

  return this.client.search(query).then(function(result) {
    var records = result.hits.hits;

    records = records.map(function(record) {
      record._source[model.schema.primaryKey] = record._id;

      return record._source;
    });

    return Promise.resolve(records);
  });
};

Driver.prototype.findLimit = function findLimit(model, spec, start, limit, callback) {
  var body = merge({
    from: start,
    size: limit
  }, spec);

  var query = {
    index: this.index,
    type: model.bucket,
    body: body
  };

  return this.client.search(query).then(function(err, result) {
    var records = result.hits.hits;

    records = records.map(function(record) {
      record._source[model.schema.primaryKey] = record._id;

      return record._source;
    });

    return Promise.resolve({
      docs: records,
      count: result.hits.total,
      start: start,
      limit: limit
    });
  });
};

module.exports = Driver;
<|endoftext|>


<commit_before>'use strict';
var path = require('path');
var gutil = require('gulp-util');
var through = require('through2');
var Converter=require("csvtojson").Converter;

var getVariableName = function(file,options){
    if (typeof(options.globalvariable) !== "undefined" && options.globalvariable !== null)
        return options.globalvariable;

    return path.basename(file.path, path.extname(file.path))
};

var onComplete = function(stream,file,options,done){
    if (options.genjs){
        file.path = gutil.replaceExtension(file.path,'.js');
    }
    else
        file.path = gutil.replaceExtension(file.path,'.json');

    stream.push(file);
    return done();
};

var generateJsStream = function(variablename){
    var firstLine = true;
    return through(function(chunk,enc,cb){
        if(firstLine){
            this.push("var "+variablename+" = ");
            firstLine=false;
        }

        this.push(chunk);
        cb();
    },function (cb) {
        this.push(';');
        cb();
    });
};

module.exports = function (options) {
    if (typeof(options) === "undefined") {
        options = { genjs: false };
    }

    return through.obj(function (file, enc, cb) {
        var self = this;

        if (file.isNull()) {
            cb(null, file);
            return;
        }

        try {
            if (file.isStream()) {
                options.constructResult=false;
                options.toArrayString=true;
                var csvConverter = new Converter(options);

                file.contents = file.contents.pipe(csvConverter);
                if (options.genjs) {
                    var variablename = getVariableName(file,options)
                    file.contents = file.contents.pipe(generateJsStream(variablename));
                }
                return onComplete(self,file,options,cb);
            }

            if(file.isBuffer()){
                var csvConverter = new Converter(options);

                csvConverter.fromString(file.contents.toString(), function(err, jsonObj) {
                    if(err){
                        this.emit('error', new gutil.PluginError('gulp-csvtojson', err));
                        cb(new gutil.PluginError('gulp-csvtojson', err));
                    }

                    var output = JSON.stringify(jsonObj);
                    if (options.genjs) {
                        var variablename = getVariableName(file,options)
                        output = "var "+variablename + " = " + output + ";";
                    }
                    file.contents = new Buffer(output);
                    onComplete(self,file,options,cb);
                });
            }
        } catch (err) {
            this.emit('error', new gutil.PluginError('gulp-csvtojson', err));
            cb(new gutil.PluginError('gulp-csvtojson', err));
        }
    });
};<commit_msg>Refactor to separate out buffer vs stream handling<commit_after>'use strict';
var path = require('path');
var gutil = require('gulp-util');
var through = require('through2');
var Converter=require("csvtojson").Converter;

var getVariableName = function(file,options){
    if (typeof(options.globalvariable) !== "undefined" && options.globalvariable !== null){
        return options.globalvariable;
    }

    return path.basename(file.path, path.extname(file.path));
};

var onComplete = function(stream,file,options,done){
    if (options.genjs){
        file.path = gutil.replaceExtension(file.path,'.js');
    }
    else{
        file.path = gutil.replaceExtension(file.path,'.json');
    }

    stream.push(file);
    return done();
};

var generateJsStream = function(variablename){
    var firstLine = true;
    return through(function(chunk,enc,cb){
        if(firstLine){
            this.push("var "+variablename+" = ");
            firstLine=false;
        }

        this.push(chunk);
        cb();
    },function (cb) {
        this.push(';');
        cb();
    });
};

var processStream = function(file,options,cb){
    options.toArrayString=true;
    options.constructResult=false;
    var csvConverter = new Converter(options);

    file.contents = file.contents.pipe(csvConverter);
    if (options.genjs) {
        var variablename = getVariableName(file,options);
        file.contents = file.contents.pipe(generateJsStream(variablename));
    }
    cb();
};

var processBuffer = function(file,options,cb){
    var csvConverter = new Converter(options);

    csvConverter.fromString(file.contents.toString(), function(err, jsonObj) {
        if(err){
            return cb(err);
        }

        var output = JSON.stringify(jsonObj);
        if (options.genjs) {
            var variablename = getVariableName(file,options);
            output = "var "+variablename + " = " + output + ";";
        }
        file.contents = new Buffer(output);
        cb();
    });
};

module.exports = function (options) {
    if (typeof(options) === "undefined") {
        options = { genjs: false };
    }

    return through.obj(function (file, enc, cb) {
        var self = this;

        if (file.isNull()) {
            return cb(null, file);
        }

        try {
            var done = function(err){
                if(err){ throw err; }
                onComplete(self,file,options,cb);
            };

            if (file.isStream()) {
                return processStream(file,options,done);
            }

            if(file.isBuffer()){
                return processBuffer(file,options,done);
            }

        } catch (err) {
            this.emit('error', new gutil.PluginError('gulp-csvtojson', err));
            cb(new gutil.PluginError('gulp-csvtojson', err));
        }
    });
};<|endoftext|>


<commit_before>/*!
 * micromatch <https://github.com/jonschlinkert/micromatch>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var diff = require('arr-diff');
var typeOf = require('kind-of');
var omit = require('object.omit');
var unique = require('array-unique');
var cache = require('regex-cache');
var isGlob = require('is-glob');
var expand = require('./lib/expand');
var utils = require('./lib/utils');

/**
 * The main function. Pass an array of filepaths,
 * and a string or array of glob patterns
 *
 * @param  {Array|String} `files`
 * @param  {Array|String} `patterns`
 * @param  {Object} `opts`
 * @return {Array} Array of matches
 */

function micromatch(files, patterns, opts) {
  if (!files || !patterns) return [];
  opts = opts || {};

  if (typeof opts.cache === 'undefined') {
    opts.cache = true;
  }

  if (!Array.isArray(patterns)) {
    return match(files, patterns, opts);
  }

  var len = patterns.length, i = 0;
  var omit = [], keep = [];

  while (len--) {
    var glob = patterns[i++];
    if (glob.charCodeAt(0) === 33 /* ! */) {
      omit.push.apply(omit, match(files, glob.slice(1), opts));
    } else {
      keep.push.apply(keep, match(files, glob, opts));
    }
  }
  return diff(keep, omit);
}

/**
 * Pass an array of files and a glob pattern as a string.
 *
 * This function is called by the main `micromatch` function
 * If you only need to pass a single pattern you might get
 * very minor speed improvements using this function.
 *
 * @param  {Array} `files`
 * @param  {Array} `pattern`
 * @param  {Object} `options`
 * @return {Array}
 */

function match(files, pattern, opts) {
  if (typeOf(files) !== 'string' && !Array.isArray(files)) {
    throw new Error(msg('match', 'files', 'a string or array'));
  }

  files = utils.arrayify(files);
  opts = opts || {};

  var negate = opts.negate || false;
  var orig = pattern;

  if (typeof pattern === 'string' && opts.nonegate !== true) {
    negate = pattern.charAt(0) === '!';
    if (negate) {
      pattern = pattern.slice(1);
    }
  }

  var _isMatch = matcher(pattern, opts);
  var len = files.length, i = 0;
  var res = [];

  while (i < len) {
    var file = files[i++];
    var fp = utils.unixify(file, opts);

    if (!_isMatch(fp)) { continue; }
    res.push(fp);
  }

  if (res.length === 0) {
    if (opts.failglob === true) {
      throw new Error('micromatch.match() found no matches for: "' + orig + '".');
    }

    if (opts.nonull || opts.nullglob) {
      res.push(utils.unescapeGlob(orig));
    }
  }

  // if `negate` was defined, diff negated files
  if (negate) { res = diff(files, res); }

  // if `ignore` was defined, diff ignored filed
  if (opts.ignore && opts.ignore.length) {
    pattern = opts.ignore;
    opts = omit(opts, ['ignore']);
    res = diff(res, micromatch(res, pattern, opts));
  }

  if (opts.nodupes) {
    return unique(res);
  }
  return res;
}

/**
 * Returns a function that takes a glob pattern or array of glob patterns
 * to be used with `Array#filter()`. (Internally this function generates
 * the matching function using the [matcher] method).
 *
 * ```js
 * var fn = mm.filter('[a-c]');
 * ['a', 'b', 'c', 'd', 'e'].filter(fn);
 * //=> ['a', 'b', 'c']
 * ```
 *
 * @param  {String|Array} `patterns` Can be a glob or array of globs.
 * @param  {Options} `opts` Options to pass to the [matcher] method.
 * @return {Function} Filter function to be passed to `Array#filter()`.
 */

function filter(patterns, opts) {
  if (!Array.isArray(patterns) && typeof patterns !== 'string') {
    throw new TypeError(msg('filter', 'patterns', 'a string or array'));
  }

  patterns = utils.arrayify(patterns);
  var len = patterns.length, i = 0;
  while (i < len) {
    patterns[i] = matcher(patterns[i++], opts);
  }

  return function (fp) {
    if (fp == null) return [];
    var len = patterns.length, i = 0;
    var res = true;

    fp = utils.unixify(fp, opts);
    while (i < len) {
      var fn = patterns[i++];
      if (!fn(fp)) {
        res = false;
        break;
      }
    }
    return res;
  };
}

/**
 * Returns true if the filepath contains the given
 * pattern. Can also return a function for matching.
 *
 * ```js
 * isMatch('foo.md', '*.md', {});
 * //=> true
 *
 * isMatch('*.md', {})('foo.md')
 * //=> true
 * ```
 *
 * @param  {String} `fp`
 * @param  {String} `pattern`
 * @param  {Object} `opts`
 * @return {Boolean}
 */

function isMatch(fp, pattern, opts) {
  if (typeof fp !== 'string') {
    throw new TypeError(msg('isMatch', 'filepath', 'a string'));
  }

  fp = utils.unixify(fp, opts);
  if (typeOf(pattern) === 'object') {
    return matcher(fp, pattern);
  }
  return matcher(pattern, opts)(fp);
}

/**
 * Returns true if the filepath matches the
 * given pattern.
 */

function contains(fp, pattern, opts) {
  if (typeof fp !== 'string') {
    throw new TypeError(msg('contains', 'pattern', 'a string'));
  }

  opts = opts || {};
  opts.contains = (pattern !== '');
  fp = utils.unixify(fp, opts);

  if (opts.contains && !isGlob(pattern)) {
    return fp.indexOf(pattern) !== -1;
  }
  return matcher(pattern, opts)(fp);
}

/**
 * Returns true if a file path matches any of the
 * given patterns.
 *
 * @param  {String} `fp` The filepath to test.
 * @param  {String|Array} `patterns` Glob patterns to use.
 * @param  {Object} `opts` Options to pass to the `matcher()` function.
 * @return {String}
 */

function any(fp, patterns, opts) {
  if (!Array.isArray(patterns) && typeof patterns !== 'string') {
    throw new TypeError(msg('any', 'patterns', 'a string or array'));
  }

  patterns = utils.arrayify(patterns);
  var len = patterns.length;

  fp = utils.unixify(fp, opts);
  while (len--) {
    var isMatch = matcher(patterns[len], opts);
    if (isMatch(fp)) {
      return true;
    }
  }
  return false;
}

/**
 * Filter the keys of an object with the given `glob` pattern
 * and `options`
 *
 * @param  {Object} `object`
 * @param  {Pattern} `object`
 * @return {Array}
 */

function matchKeys(obj, glob, options) {
  if (typeOf(obj) !== 'object') {
    throw new TypeError(msg('matchKeys', 'first argument', 'an object'));
  }

  var fn = matcher(glob, options);
  var res = {};

  for (var key in obj) {
    if (obj.hasOwnProperty(key) && fn(key)) {
      res[key] = obj[key];
    }
  }
  return res;
}

/**
 * Return a function for matching based on the
 * given `pattern` and `options`.
 *
 * @param  {String} `pattern`
 * @param  {Object} `options`
 * @return {Function}
 */

function matcher(pattern, opts) {
  // pattern is a function
  if (typeof pattern === 'function') {
    return pattern;
  }
  // pattern is a regex
  if (pattern instanceof RegExp) {
    return function(fp) {
      return pattern.test(fp);
    };
  }

  // strings, all the way down...
  pattern = utils.unixify(pattern, opts);

  // pattern is a non-glob string
  if (!isGlob(pattern)) {
    return utils.matchPath(pattern, opts);
  }
  // pattern is a glob string
  var re = makeRe(pattern, opts);

  // `matchBase` is defined
  if (opts && opts.matchBase) {
    return utils.hasFilename(re, opts);
  }
  // `matchBase` is not defined
  return function(fp) {
    fp = utils.unixify(fp, opts);
    return re.test(fp);
  };
}

/**
 * Create and cache a regular expression for matching
 * file paths.
 *
 * If the leading character in the `glob` is `!`, a negation
 * regex is returned.
 *
 * @param  {String} `glob`
 * @param  {Object} `options`
 * @return {RegExp}
 */

function toRegex(glob, options) {
  if (typeOf(glob) !== 'string') {
    throw new Error(msg('toRegex', 'glob', 'a string'));
  }

  // clone options to prevent  mutating the original object
  var opts = Object.create(options || {});
  var flags = opts.flags || '';
  if (opts.nocase && flags.indexOf('i') === -1) {
    flags += 'i';
  }

  var parsed = expand(glob, opts);

  // pass in tokens to avoid parsing more than once
  opts.negated = opts.negated || parsed.negated;
  opts.negate = opts.negated;
  glob = wrapGlob(parsed.pattern, opts);
  var re;

  try {
    re = new RegExp(glob, flags);
    return re;
  } catch (err) {
    var msg = 'micromatch invalid regex: (' + re + ')';
    if (opts.strict) throw new SyntaxError(msg + err);
  }
  return /$^/;
}

/**
 * Create the regex to do the matching. If the leading
 * character in the `glob` is `!` a negation regex is returned.
 *
 * @param {String} `glob`
 * @param {Boolean} `negate`
 */

function wrapGlob(glob, opts) {
  var prefix = (opts && !opts.contains) ? '^' : '';
  var after = (opts && !opts.contains) ? '$' : '';
  glob = ('(?:' + glob + ')' + after);
  if (opts && opts.negate) {
    return prefix + ('(?!^' + glob + ').*$');
  }
  return prefix + glob;
}

/**
 * Wrap `toRegex` to memoize the generated regex
 * the string and options don't change
 */

function makeRe(glob, opts) {
  return cache(toRegex, glob, opts);
}

/**
 * Make error messages consistent. Follows this format:
 *
 * ```js
 * msg(methodName, argNumber, nativeType);
 * // example:
 * msg('matchKeys', 'first', 'an object');
 * ```
 *
 * @param  {String} `method`
 * @param  {String} `num`
 * @param  {String} `type`
 * @return {String}
 */

function msg(method, what, type) {
  return 'micromatch.' + method + '(): ' + what + ' should be ' + type + '.';
}

/**
 * Public methods
 */

micromatch.any       = any;
micromatch.braces    = micromatch.braceExpand = require('braces');
micromatch.contains  = contains;
micromatch.expand    = expand;
micromatch.filter    = filter;
micromatch.isMatch   = isMatch;
micromatch.makeRe    = makeRe;
micromatch.match     = match;
micromatch.matcher   = matcher;
micromatch.matchKeys = matchKeys;

/**
 * Expose `micromatch`
 */

module.exports = micromatch;
<commit_msg>Fix overwritten user input<commit_after>/*!
 * micromatch <https://github.com/jonschlinkert/micromatch>
 *
 * Copyright (c) 2014-2015, Jon Schlinkert.
 * Licensed under the MIT License.
 */

'use strict';

var diff = require('arr-diff');
var typeOf = require('kind-of');
var omit = require('object.omit');
var unique = require('array-unique');
var cache = require('regex-cache');
var isGlob = require('is-glob');
var expand = require('./lib/expand');
var utils = require('./lib/utils');

/**
 * The main function. Pass an array of filepaths,
 * and a string or array of glob patterns
 *
 * @param  {Array|String} `files`
 * @param  {Array|String} `patterns`
 * @param  {Object} `opts`
 * @return {Array} Array of matches
 */

function micromatch(files, patterns, opts) {
  if (!files || !patterns) return [];
  opts = opts || {};

  if (typeof opts.cache === 'undefined') {
    opts.cache = true;
  }

  if (!Array.isArray(patterns)) {
    return match(files, patterns, opts);
  }

  var len = patterns.length, i = 0;
  var omit = [], keep = [];

  while (len--) {
    var glob = patterns[i++];
    if (glob.charCodeAt(0) === 33 /* ! */) {
      omit.push.apply(omit, match(files, glob.slice(1), opts));
    } else {
      keep.push.apply(keep, match(files, glob, opts));
    }
  }
  return diff(keep, omit);
}

/**
 * Pass an array of files and a glob pattern as a string.
 *
 * This function is called by the main `micromatch` function
 * If you only need to pass a single pattern you might get
 * very minor speed improvements using this function.
 *
 * @param  {Array} `files`
 * @param  {Array} `pattern`
 * @param  {Object} `options`
 * @return {Array}
 */

function match(files, pattern, opts) {
  if (typeOf(files) !== 'string' && !Array.isArray(files)) {
    throw new Error(msg('match', 'files', 'a string or array'));
  }

  files = utils.arrayify(files);
  opts = opts || {};

  var negate = opts.negate || false;
  var orig = pattern;

  if (typeof pattern === 'string' && opts.nonegate !== true) {
    negate = pattern.charAt(0) === '!';
    if (negate) {
      pattern = pattern.slice(1);
    }
  }

  var _isMatch = matcher(pattern, opts);
  var len = files.length, i = 0;
  var res = [];

  while (i < len) {
    var file = files[i++];
    var fp = utils.unixify(file, opts);

    if (!_isMatch(fp)) { continue; }
    res.push(fp);
  }

  if (res.length === 0) {
    if (opts.failglob === true) {
      throw new Error('micromatch.match() found no matches for: "' + orig + '".');
    }

    if (opts.nonull || opts.nullglob) {
      res.push(utils.unescapeGlob(orig));
    }
  }

  // if `negate` was defined, diff negated files
  if (negate) { res = diff(files, res); }

  // if `ignore` was defined, diff ignored filed
  if (opts.ignore && opts.ignore.length) {
    pattern = opts.ignore;
    opts = omit(opts, ['ignore']);
    res = diff(res, micromatch(res, pattern, opts));
  }

  if (opts.nodupes) {
    return unique(res);
  }
  return res;
}

/**
 * Returns a function that takes a glob pattern or array of glob patterns
 * to be used with `Array#filter()`. (Internally this function generates
 * the matching function using the [matcher] method).
 *
 * ```js
 * var fn = mm.filter('[a-c]');
 * ['a', 'b', 'c', 'd', 'e'].filter(fn);
 * //=> ['a', 'b', 'c']
 * ```
 *
 * @param  {String|Array} `patterns` Can be a glob or array of globs.
 * @param  {Options} `opts` Options to pass to the [matcher] method.
 * @return {Function} Filter function to be passed to `Array#filter()`.
 */

function filter(patterns, opts) {
  if (!Array.isArray(patterns) && typeof patterns !== 'string') {
    throw new TypeError(msg('filter', 'patterns', 'a string or array'));
  }

  patterns = utils.arrayify(patterns);
  var len = patterns.length, i = 0;
  var patternMatchers = Array(len);
  while (i < len) {
    patternMatchers[i] = matcher(patterns[i++], opts);
  }

  return function (fp) {
    if (fp == null) return [];
    var len = patternMatchers.length, i = 0;
    var res = true;

    fp = utils.unixify(fp, opts);
    while (i < len) {
      var fn = patternMatchers[i++];
      if (!fn(fp)) {
        res = false;
        break;
      }
    }
    return res;
  };
}

/**
 * Returns true if the filepath contains the given
 * pattern. Can also return a function for matching.
 *
 * ```js
 * isMatch('foo.md', '*.md', {});
 * //=> true
 *
 * isMatch('*.md', {})('foo.md')
 * //=> true
 * ```
 *
 * @param  {String} `fp`
 * @param  {String} `pattern`
 * @param  {Object} `opts`
 * @return {Boolean}
 */

function isMatch(fp, pattern, opts) {
  if (typeof fp !== 'string') {
    throw new TypeError(msg('isMatch', 'filepath', 'a string'));
  }

  fp = utils.unixify(fp, opts);
  if (typeOf(pattern) === 'object') {
    return matcher(fp, pattern);
  }
  return matcher(pattern, opts)(fp);
}

/**
 * Returns true if the filepath matches the
 * given pattern.
 */

function contains(fp, pattern, opts) {
  if (typeof fp !== 'string') {
    throw new TypeError(msg('contains', 'pattern', 'a string'));
  }

  opts = opts || {};
  opts.contains = (pattern !== '');
  fp = utils.unixify(fp, opts);

  if (opts.contains && !isGlob(pattern)) {
    return fp.indexOf(pattern) !== -1;
  }
  return matcher(pattern, opts)(fp);
}

/**
 * Returns true if a file path matches any of the
 * given patterns.
 *
 * @param  {String} `fp` The filepath to test.
 * @param  {String|Array} `patterns` Glob patterns to use.
 * @param  {Object} `opts` Options to pass to the `matcher()` function.
 * @return {String}
 */

function any(fp, patterns, opts) {
  if (!Array.isArray(patterns) && typeof patterns !== 'string') {
    throw new TypeError(msg('any', 'patterns', 'a string or array'));
  }

  patterns = utils.arrayify(patterns);
  var len = patterns.length;

  fp = utils.unixify(fp, opts);
  while (len--) {
    var isMatch = matcher(patterns[len], opts);
    if (isMatch(fp)) {
      return true;
    }
  }
  return false;
}

/**
 * Filter the keys of an object with the given `glob` pattern
 * and `options`
 *
 * @param  {Object} `object`
 * @param  {Pattern} `object`
 * @return {Array}
 */

function matchKeys(obj, glob, options) {
  if (typeOf(obj) !== 'object') {
    throw new TypeError(msg('matchKeys', 'first argument', 'an object'));
  }

  var fn = matcher(glob, options);
  var res = {};

  for (var key in obj) {
    if (obj.hasOwnProperty(key) && fn(key)) {
      res[key] = obj[key];
    }
  }
  return res;
}

/**
 * Return a function for matching based on the
 * given `pattern` and `options`.
 *
 * @param  {String} `pattern`
 * @param  {Object} `options`
 * @return {Function}
 */

function matcher(pattern, opts) {
  // pattern is a function
  if (typeof pattern === 'function') {
    return pattern;
  }
  // pattern is a regex
  if (pattern instanceof RegExp) {
    return function(fp) {
      return pattern.test(fp);
    };
  }

  // strings, all the way down...
  pattern = utils.unixify(pattern, opts);

  // pattern is a non-glob string
  if (!isGlob(pattern)) {
    return utils.matchPath(pattern, opts);
  }
  // pattern is a glob string
  var re = makeRe(pattern, opts);

  // `matchBase` is defined
  if (opts && opts.matchBase) {
    return utils.hasFilename(re, opts);
  }
  // `matchBase` is not defined
  return function(fp) {
    fp = utils.unixify(fp, opts);
    return re.test(fp);
  };
}

/**
 * Create and cache a regular expression for matching
 * file paths.
 *
 * If the leading character in the `glob` is `!`, a negation
 * regex is returned.
 *
 * @param  {String} `glob`
 * @param  {Object} `options`
 * @return {RegExp}
 */

function toRegex(glob, options) {
  if (typeOf(glob) !== 'string') {
    throw new Error(msg('toRegex', 'glob', 'a string'));
  }

  // clone options to prevent  mutating the original object
  var opts = Object.create(options || {});
  var flags = opts.flags || '';
  if (opts.nocase && flags.indexOf('i') === -1) {
    flags += 'i';
  }

  var parsed = expand(glob, opts);

  // pass in tokens to avoid parsing more than once
  opts.negated = opts.negated || parsed.negated;
  opts.negate = opts.negated;
  glob = wrapGlob(parsed.pattern, opts);
  var re;

  try {
    re = new RegExp(glob, flags);
    return re;
  } catch (err) {
    var msg = 'micromatch invalid regex: (' + re + ')';
    if (opts.strict) throw new SyntaxError(msg + err);
  }
  return /$^/;
}

/**
 * Create the regex to do the matching. If the leading
 * character in the `glob` is `!` a negation regex is returned.
 *
 * @param {String} `glob`
 * @param {Boolean} `negate`
 */

function wrapGlob(glob, opts) {
  var prefix = (opts && !opts.contains) ? '^' : '';
  var after = (opts && !opts.contains) ? '$' : '';
  glob = ('(?:' + glob + ')' + after);
  if (opts && opts.negate) {
    return prefix + ('(?!^' + glob + ').*$');
  }
  return prefix + glob;
}

/**
 * Wrap `toRegex` to memoize the generated regex
 * the string and options don't change
 */

function makeRe(glob, opts) {
  return cache(toRegex, glob, opts);
}

/**
 * Make error messages consistent. Follows this format:
 *
 * ```js
 * msg(methodName, argNumber, nativeType);
 * // example:
 * msg('matchKeys', 'first', 'an object');
 * ```
 *
 * @param  {String} `method`
 * @param  {String} `num`
 * @param  {String} `type`
 * @return {String}
 */

function msg(method, what, type) {
  return 'micromatch.' + method + '(): ' + what + ' should be ' + type + '.';
}

/**
 * Public methods
 */

micromatch.any       = any;
micromatch.braces    = micromatch.braceExpand = require('braces');
micromatch.contains  = contains;
micromatch.expand    = expand;
micromatch.filter    = filter;
micromatch.isMatch   = isMatch;
micromatch.makeRe    = makeRe;
micromatch.match     = match;
micromatch.matcher   = matcher;
micromatch.matchKeys = matchKeys;

/**
 * Expose `micromatch`
 */

module.exports = micromatch;
<|endoftext|>


<commit_before>var request = require('request'),
config = require('./config');

var perform_request = function(url, resolve, reject){

  var options = {
    url: url,
    headers: {
      'Accept': 'application/json',
      'X-Mashape-Key': config.apikey
    }
  };

  return request(options, function(error, response, body) {

    if(!error){
      error = (response.statusCode != 200 ? response.statusCode + " - " + options.url : null);
    }

    if (error) {
      if(reject){
        return reject(error);
      }else{
        throw error;
      }
    }

    if (response.statusCode == 200 && resolve) {
      return resolve({
        url: options.url,
        body: JSON.parse(body),
        head: response.headers,
        scroll_url: response.headers['X-Next-Page'],
        scroll_count: response.headers['X-Count']
      });
    }
  });
}

var get = function(url, fields, opts, resolve, reject) {
  url = config.endpoint + url + "/";
  if (opts) {
    var optUrl = [], filter, param;
    for (param in opts) {
      var paramValue = opts[param];
      if (param == "filters") {
        for (filter in paramValue) {
          filter_split = filter.split('-')
          optUrl.push("filter[" + filter_split.join("][") + "]=" + paramValue[filter]);
        }
      } else if(param == "ids") {
        url += paramValue.join(',')
      } else {
        optUrl.push(param + "=" + paramValue);
      }
    }

    if(fields){
      optUrl.push("fields=" + fields.join(','));
    }

    url += "?" + optUrl.join('&');
  }

  return perform_request(url, resolve, reject);
};

var endpoint = function(e){
  return function(opts, fields) {
    return new Promise(function(resolve, reject){
      get(e, fields, opts, resolve, reject);
    });
  }
}

var endpoints = ["games", "companies", "people", "genres", "keywords", "platforms", "player_perspectives", "pulses", "themes", "franchises", "collections"],
endpoints_obj = {
  image: function(image_object, size, filetype){
    if(image_object){
      return "https://res.cloudinary.com/igdb/image/upload/t_" + (size || "thumb") + "/" + image_object.cloudinary_id + "." + (filetype || "jpg");
    }
  },
  scroll: function(url){
    return new Promise(function(resolve, reject){
      return perform_request(url, resolve, reject);
    });
  }
};

for(i = 0; i < endpoints.length; i++){
  endpoints_obj[endpoints[i]] = endpoint(endpoints[i]);
}

module.exports = endpoints_obj<commit_msg>update image domain<commit_after>var request = require('request'),
config = require('./config');

var perform_request = function(url, resolve, reject){

  var options = {
    url: url,
    headers: {
      'Accept': 'application/json',
      'X-Mashape-Key': config.apikey
    }
  };

  return request(options, function(error, response, body) {

    if(!error){
      error = (response.statusCode != 200 ? response.statusCode + " - " + options.url : null);
    }

    if (error) {
      if(reject){
        return reject(error);
      }else{
        throw error;
      }
    }

    if (response.statusCode == 200 && resolve) {
      return resolve({
        url: options.url,
        body: JSON.parse(body),
        head: response.headers,
        scroll_url: response.headers['X-Next-Page'],
        scroll_count: response.headers['X-Count']
      });
    }
  });
}

var get = function(url, fields, opts, resolve, reject) {
  url = config.endpoint + url + "/";
  if (opts) {
    var optUrl = [], filter, param;
    for (param in opts) {
      var paramValue = opts[param];
      if (param == "filters") {
        for (filter in paramValue) {
          filter_split = filter.split('-')
          optUrl.push("filter[" + filter_split.join("][") + "]=" + paramValue[filter]);
        }
      } else if(param == "ids") {
        url += paramValue.join(',')
      } else {
        optUrl.push(param + "=" + paramValue);
      }
    }

    if(fields){
      optUrl.push("fields=" + fields.join(','));
    }

    url += "?" + optUrl.join('&');
  }

  return perform_request(url, resolve, reject);
};

var endpoint = function(e){
  return function(opts, fields) {
    return new Promise(function(resolve, reject){
      get(e, fields, opts, resolve, reject);
    });
  }
}

var endpoints = ["games", "companies", "people", "genres", "keywords", "platforms", "player_perspectives", "pulses", "themes", "franchises", "collections"],
endpoints_obj = {
  image: function(image_object, size, filetype){
    if(image_object){
      return "https://images.igdb.com/igdb/image/upload/t_" + (size || "thumb") + "/" + image_object.cloudinary_id + "." + (filetype || "jpg");
    }
  },
  scroll: function(url){
    return new Promise(function(resolve, reject){
      return perform_request(url, resolve, reject);
    });
  }
};

for(i = 0; i < endpoints.length; i++){
  endpoints_obj[endpoints[i]] = endpoint(endpoints[i]);
}

module.exports = endpoints_obj
<|endoftext|>


<commit_before>// Used for Atom editor
/* jshint esversion: 6, node: true */

'use strict';

const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const app = express();

app.set('port', (process.env.PORT || 5000));

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

// Set default index reponse
app.get('/', function (req, res) {
    res.send('LOBLAWS-MESSENGER');
});

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

// Start the express server
app.listen(app.get('port'), function() {
    console.log('Running on port', app.get('port'));
});

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

    console.log('Received POST to webhook from: ', req.connection);

    for (var i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {
            sendMessage(event.sender.id, {text: "Echo: " + event.message.text});
        }
    }

    res.sendStatus(200);
});

function sendMessage(recipientId, message) {
    console.log('Sending message: ', message);

    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
}
<commit_msg>Fix logging<commit_after>// Used for Atom editor
/* jshint esversion: 6, node: true */

'use strict';

const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const app = express();

app.set('port', (process.env.PORT || 5000));

app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

// Set default index reponse
app.get('/', function (req, res) {
    res.send('LOBLAWS-MESSENGER');
});

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

// Start the express server
app.listen(app.get('port'), function() {
    console.log('Running on port', app.get('port'));
});

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

    console.log('Received POST to webhook from: ', req.connection.remoteAddress);

    for (var i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {
            sendMessage(event.sender.id, {text: "Echo: " + event.message.text});
        }
    }

    res.sendStatus(200);
});

function sendMessage(recipientId, message) {
    console.log('Sending message: \'', message.text, '\' to ', recipientId);

    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
}
<|endoftext|>


<commit_before>exports = module.exports = {
    db: require('./db')
}<commit_msg>export the new JSON redis<commit_after>exports = module.exports = {
    db: require('./db'),
    JSONredis: require('./json-redis')
}
<|endoftext|>


<commit_before>'use strict';
/* global window */
require('classlist-polyfill');
var debounce = require('lodash/debounce');
var assign = require('lodash/assign');

function LaserCarousel(el, opts) {
    var self = this;

    self.el = el.children[0];

    self.opts = {
        itemWidth: '100px',
        namespace: '',
        initialSlide: 0,
        itemNavigation: true,
        currentItemSpacing: 1,
        touch: true,
        speed: 300,
        dots: true,
        arrows: true,
        asForDots: false,
    };

    assign(self.opts, opts);

    self.currentItemIdx = self.opts.initialSlide;

    self.items = [];
    self.storeItems();
    self.itemCount = self.items.length;

    self.currentX = 0;
    self.trackWidth = 0;
    self.dragging = false;

    self.settings = {};
    self.initialised = false;

    self.initialize();
}

LaserCarousel.prototype = {
    swipe: require('./swipe'),

    storeItems: function() {
        var self = this,
            items = self.el.getElementsByClassName(self.opts.namespace + 'carousel__item'),
            i = items.length - 1;

        for (i; i >= 0; i--) {
            self.items[i] = {};
            self.items[i].el = items[i].cloneNode(true);
            self.el.removeChild(items[i]);
        }
    },

    applyTrackTransition: function() {
        var self = this;
        self.track.style.transitionProperty = 'transform';
        self.track.style.transitionDuration = self.opts.speed + 'ms';
    },

    panToCurrent: function() {
        var self = this,
            idx = self.currentItemIdx,
            itemWidth = self.items[0] && self.items[0].el.offsetWidth || 0;

        self.currentX = -idx * itemWidth;
        self.track.style.transform = 'translate3d(' + self.currentX + 'px, 0 ,0)';
    },

    addTrack: function() {
        var self = this,
            i,
            items = self.items;

        self.track = document.createElement('div');
        self.track.classList.add(self.opts.namespace + 'carousel__track');
        self.el.insertBefore(self.track, self.el.firstChild);

        for (i = 0; i < self.items.length; i++) {
            self.track.appendChild(self.items[i].el);
        }
    },

    setTrackWidth: function() {
        var self = this;
        var itemWidth = self.el.offsetWidth;
        itemWidth = parseInt(itemWidth);

        self.trackWidth = itemWidth * self.items.length;
        self.track.style.width = self.trackWidth + 'px';
    },

    addDots: function() {
        var self = this,
            html = '';

        // Don't output single dot.
        if (self.items.length === 1) {
            return;
        }

        self.carouselNavigation = document.createElement('ul');
        self.carouselNavigation.classList.add(self.opts.namespace + 'carousel__navigation');
        self.el.appendChild(self.carouselNavigation);

        for (var i = 0; i < self.items.length; i++) {
            html += '
<button class="' + self.opts.namespace + 'carousel__navigation-button">' + (i + 1) + '</button>
\n';
        }

        self.carouselNavigation.innerHTML = html;
    },

    addArrows: function() {
        var self = this,
            html = '';

        self.arrowLeft = document.createElement('button');
        self.arrowRight = document.createElement('button');

        self.arrowLeft.classList.add(self.opts.namespace + 'carousel__arrow');
        self.arrowLeft.classList.add(self.opts.namespace + 'carousel__arrow--left');

        self.arrowRight.classList.add(self.opts.namespace + 'carousel__arrow');
        self.arrowRight.classList.add(self.opts.namespace + 'carousel__arrow--right');

        self.el.appendChild(self.arrowLeft);
        self.el.appendChild(self.arrowRight);

        self.arrowLeft.addEventListener('click', self.previous.bind(this));
        self.arrowRight.addEventListener('click', self.next.bind(this));
    },

    setCurrent: function(idx) {
        var self = this,
            items,
            current;

        if (self.currentItem) {
            self.currentItem.classList.remove(self.opts.namespace + 'carousel__item--current');
        }

        self.currentItem = self.items[idx] && self.items[idx].el;

        if (!self.items[idx]) {
            return;
        }

        if (self.currentItem) {
            self.currentItemIdx = idx;
            self.currentItem.classList.add(self.opts.namespace + 'carousel__item--current');
        }

        if (self.carouselNavigation) {
            current = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item--current')[0];

            if (current) {
                current.classList.remove(self.opts.namespace + 'carousel__navigation-item--current');
            }

            items = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

            if (items[idx]) {
                items[idx].classList.add(self.opts.namespace + 'carousel__navigation-item--current');
            }
        }

        if (idx !== 0 || idx !== self.items.length - 1) {
            self.el.parentNode.classList.remove('carousel--at-end');
            self.el.parentNode.classList.remove('carousel--at-start');
        }

        if (idx === 0) {
            self.el.parentNode.classList.remove('carousel--at-end');
            self.el.parentNode.classList.add('carousel--at-start');
        }

        if (idx === self.items.length - 1) {
            self.el.parentNode.classList.remove('carousel--at-start');
            self.el.parentNode.classList.add('carousel--at-end');
        }
    },

    positionItems: function() {
        var self = this;
        var idx = 0;
        var current;
        var isCurrent = false;

        for (var i = 0; i < self.items.length; i++) {
            current = self.items[i].el;
            isCurrent = false;

            if (self.currentItem && current === self.currentItem) {
                isCurrent = true;
                idx = idx + self.opts.currentItemSpacing;
            }

            current.style.width = self.el.offsetWidth + 'px';
            current.style.transform = 'translate3d(' + (i * 100) + '%, 0%, 0)';
            current.style.display = 'block';
        }
    },

    goto: function(idx) {
        var self = this;
        self.setCurrent(idx);
        self.positionItems();
        self.panToCurrent();
    },

    next: function() {
        var self = this;

        if (self.currentItemIdx + 1 <= self.itemCount - 1 ) {
            self.goto(self.currentItemIdx + 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    previous: function() {
        var self = this;

        if (self.currentItemIdx - 1 >= 0) {
            self.goto(self.currentItemIdx - 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    attachNavigationHandler: function() {
        var self = this;
        var items = (self.opts.asForDots) ? self.opts.asForDots : self.el.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

        var attachClickHandler = function(el, idx) {
            el.addEventListener('click', function(e) {
                if (!self.dragging) {
                    self.goto(idx);
                }

                e.preventDefault();
            });
        };

        for (var i = 0; i < items.length; i++) {
            attachClickHandler(items[i], i);

            if (self.opts.itemNavigation) {
                attachClickHandler(self.items[i].el, i);
            }
        }
    },

    settingsFromBreakpoint: function(breakpoint) {
        var self = this;

        self.settings.itemWidth = breakpoint.itemWidth || self.opts.itemWidth;
        self.settings.initialSlide = breakpoint.initialSlide || self.opts.initialSlide;
        self.settings.currentItemSpacing = breakpoint.currentItemSpacing || self.opts.currentItemSpacing;
        self.settings.speed = breakpoint.speed || self.opts.speed;
    },

    settingsByScreenSize: function() {
        var self = this,
            wWidth = window.offsetWidth,
            breakpointToUse = false;

        // Reset to defaults.
        self.settings.itemWidth = self.opts.itemWidth;
        self.settings.initialSlide = self.opts.initialSlide;
        self.settings.currentItemSpacing = self.opts.currentItemSpacing;
        self.settings.speed = self.opts.speed;

        if (self.opts.responsive) {
            for (var key in self.opts.responsive) {
                if (wWidth > key) {
                    breakpointToUse = key;
                }
            }
        }

        if (breakpointToUse) {
            self.settingsFromBreakpoint(self.opts.responsive[breakpointToUse]);
        }
    },

    start: function() {
        var self = this;

        self.setTrackWidth();
        self.setCurrent(self.currentItemIdx);
        self.positionItems();

        self.panToCurrent();
        self.applyTrackTransition();
    },

    initialize: function() {
        var self = this;

        self.addTrack();

        window.addEventListener('resize', debounce(self.start.bind(self), 300));

        if (self.opts.dots && !self.opts.asForDots) {
            self.addDots();
        }

        if (self.opts.arrows) {
            self.addArrows();
        }

        if (self.opts.touch) {
            self.swipe();
        }

        self.start();

        self.attachNavigationHandler();
    }
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = LaserCarousel;
} else {
    window.LaserCarousel = LaserCarousel;
}
<commit_msg>added ability to use fade transition in carousel. if option transition = fade we don't do the track transitions and panning etc.<commit_after>'use strict';
/* global window */
require('classlist-polyfill');
var debounce = require('lodash/debounce');
var assign = require('lodash/assign');

function LaserCarousel(el, opts) {
    var self = this;

    self.el = el.children[0];

    self.opts = {
        itemWidth: '100px',
        namespace: '',
        initialSlide: 0,
        itemNavigation: true,
        currentItemSpacing: 1,
        touch: true,
        speed: 300,
        dots: true,
        arrows: true,
        asForDots: false,
    };

    assign(self.opts, opts);

    self.currentItemIdx = self.opts.initialSlide;

    self.items = [];
    self.storeItems();
    self.itemCount = self.items.length;

    self.currentX = 0;
    self.trackWidth = 0;
    self.dragging = false;

    self.settings = {};
    self.initialised = false;

    self.initialize();
}

LaserCarousel.prototype = {
    swipe: require('./swipe'),

    storeItems: function() {
        var self = this,
            items = self.el.getElementsByClassName(self.opts.namespace + 'carousel__item'),
            i = items.length - 1;

        for (i; i >= 0; i--) {
            self.items[i] = {};
            self.items[i].el = items[i].cloneNode(true);
            self.el.removeChild(items[i]);
        }
    },

    applyTrackTransition: function() {
        var self = this;
        self.track.style.transitionProperty = 'transform';
        self.track.style.transitionDuration = self.opts.speed + 'ms';
    },

    panToCurrent: function() {
        var self = this,
            idx = self.currentItemIdx,
            itemWidth = self.items[0] && self.items[0].el.offsetWidth || 0;

        self.currentX = -idx * itemWidth;
        self.track.style.transform = 'translate3d(' + self.currentX + 'px, 0 ,0)';
    },

    addTrack: function() {
        var self = this,
            i,
            items = self.items;

        self.track = document.createElement('div');
        self.track.classList.add(self.opts.namespace + 'carousel__track');
        self.el.insertBefore(self.track, self.el.firstChild);

        for (i = 0; i < self.items.length; i++) {
            self.track.appendChild(self.items[i].el);
        }
    },

    setTrackWidth: function() {
        var self = this;
        var itemWidth = self.el.offsetWidth;
        itemWidth = parseInt(itemWidth);

        self.trackWidth = itemWidth * self.items.length;
        self.track.style.width = self.trackWidth + 'px';
    },

    addDots: function() {
        var self = this,
            html = '';

        // Don't output single dot.
        if (self.items.length === 1) {
            return;
        }

        self.carouselNavigation = document.createElement('ul');
        self.carouselNavigation.classList.add(self.opts.namespace + 'carousel__navigation');
        self.el.appendChild(self.carouselNavigation);

        for (var i = 0; i < self.items.length; i++) {
            html += '
<button class="' + self.opts.namespace + 'carousel__navigation-button">' + (i + 1) + '</button>
\n';
        }

        self.carouselNavigation.innerHTML = html;
    },

    addArrows: function() {
        var self = this,
            html = '';

        self.arrowLeft = document.createElement('button');
        self.arrowRight = document.createElement('button');

        self.arrowLeft.classList.add(self.opts.namespace + 'carousel__arrow');
        self.arrowLeft.classList.add(self.opts.namespace + 'carousel__arrow--left');

        self.arrowRight.classList.add(self.opts.namespace + 'carousel__arrow');
        self.arrowRight.classList.add(self.opts.namespace + 'carousel__arrow--right');

        self.el.appendChild(self.arrowLeft);
        self.el.appendChild(self.arrowRight);

        self.arrowLeft.addEventListener('click', self.previous.bind(this));
        self.arrowRight.addEventListener('click', self.next.bind(this));
    },

    setCurrent: function(idx) {
        var self = this,
            items,
            current;

        if (self.currentItem) {
            self.currentItem.classList.remove(self.opts.namespace + 'carousel__item--current');
        }

        self.currentItem = self.items[idx] && self.items[idx].el;

        if (!self.items[idx]) {
            return;
        }

        if (self.currentItem) {
            self.currentItemIdx = idx;
            self.currentItem.classList.add(self.opts.namespace + 'carousel__item--current');
        }

        if (self.carouselNavigation) {
            current = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item--current')[0];

            if (current) {
                current.classList.remove(self.opts.namespace + 'carousel__navigation-item--current');
            }

            items = self.carouselNavigation.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

            if (items[idx]) {
                items[idx].classList.add(self.opts.namespace + 'carousel__navigation-item--current');
            }
        }

        if (idx !== 0 || idx !== self.items.length - 1) {
            self.el.parentNode.classList.remove('carousel--at-end');
            self.el.parentNode.classList.remove('carousel--at-start');
        }

        if (idx === 0) {
            self.el.parentNode.classList.remove('carousel--at-end');
            self.el.parentNode.classList.add('carousel--at-start');
        }

        if (idx === self.items.length - 1) {
            self.el.parentNode.classList.remove('carousel--at-start');
            self.el.parentNode.classList.add('carousel--at-end');
        }
    },

    positionItems: function() {
        var self = this;
        var idx = 0;
        var current;
        var isCurrent = false;

        for (var i = 0; i < self.items.length; i++) {
            current = self.items[i].el;
            isCurrent = false;

            if (self.currentItem && current === self.currentItem) {
                isCurrent = true;
                idx = idx + self.opts.currentItemSpacing;
            }

            current.style.width = self.el.offsetWidth + 'px';
            current.style.transform = 'translate3d(' + (i * 100) + '%, 0%, 0)';
            current.style.display = 'block';
        }
    },

    goto: function(idx) {
        var self = this;
        self.setCurrent(idx);

        if (!self.opts.transition || self.opts.transition === 'slide') {
            self.positionItems();
            self.panToCurrent();
        }
    },

    next: function() {
        var self = this;

        if (self.currentItemIdx + 1 <= self.itemCount - 1 ) {
            self.goto(self.currentItemIdx + 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    previous: function() {
        var self = this;

        if (self.currentItemIdx - 1 >= 0) {
            self.goto(self.currentItemIdx - 1);
        } else {
            self.goto(self.currentItemIdx);
        }
    },

    attachNavigationHandler: function() {
        var self = this;
        var items = (self.opts.asForDots) ? self.opts.asForDots : self.el.getElementsByClassName(self.opts.namespace + 'carousel__navigation-item');

        var attachClickHandler = function(el, idx) {
            el.addEventListener('click', function(e) {
                if (!self.dragging) {
                    self.goto(idx);
                }

                e.preventDefault();
            });
        };

        for (var i = 0; i < items.length; i++) {
            attachClickHandler(items[i], i);

            if (self.opts.itemNavigation) {
                attachClickHandler(self.items[i].el, i);
            }
        }
    },

    settingsFromBreakpoint: function(breakpoint) {
        var self = this;

        self.settings.itemWidth = breakpoint.itemWidth || self.opts.itemWidth;
        self.settings.initialSlide = breakpoint.initialSlide || self.opts.initialSlide;
        self.settings.currentItemSpacing = breakpoint.currentItemSpacing || self.opts.currentItemSpacing;
        self.settings.speed = breakpoint.speed || self.opts.speed;
    },

    settingsByScreenSize: function() {
        var self = this,
            wWidth = window.offsetWidth,
            breakpointToUse = false;

        // Reset to defaults.
        self.settings.itemWidth = self.opts.itemWidth;
        self.settings.initialSlide = self.opts.initialSlide;
        self.settings.currentItemSpacing = self.opts.currentItemSpacing;
        self.settings.speed = self.opts.speed;

        if (self.opts.responsive) {
            for (var key in self.opts.responsive) {
                if (wWidth > key) {
                    breakpointToUse = key;
                }
            }
        }

        if (breakpointToUse) {
            self.settingsFromBreakpoint(self.opts.responsive[breakpointToUse]);
        }
    },

    start: function() {
        var self = this;

        self.setCurrent(self.currentItemIdx);

        if (!self.opts.transition || self.opts.transition === 'slide') {
            self.setTrackWidth();
            self.positionItems();
        }

        if (!self.opts.transition || self.opts.transition === 'slide') {
            self.panToCurrent();
            self.applyTrackTransition();
        }
    },

    initialize: function() {
        var self = this;

        self.addTrack();

        window.addEventListener('resize', debounce(self.start.bind(self), 300));

        if (self.opts.dots && !self.opts.asForDots) {
            self.addDots();
        }

        if (self.opts.arrows) {
            self.addArrows();
        }

        if (self.opts.touch) {
            self.swipe();
        }

        self.start();

        self.attachNavigationHandler();
    }
};

if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
    module.exports = LaserCarousel;
} else {
    window.LaserCarousel = LaserCarousel;
}
<|endoftext|>