<commit_before>"use strict";

/*global nodeca, _*/

// stdlib
var path = require('path');

// nodeca
var NLib = require('nlib');

// 3rd-party
var connect   = require('connect');
var socket_io = require('socket.io');

// HELPERS /////////////////////////////////////////////////////////////////////

function attach_connect_app(server) {
  var app = connect(), static_helpers = {}, download_root;

  app.use("/assets/", connect.compress());
  app.use("/assets/", nodeca.runtime.assets_server);

  // init downloads static middleware
  (function (options) {
    var FINGERPRINT_RE = /-([0-9a-f]{32,40})\.[^.]+$/;
    app.use("/download/", function (req, res, next) {
      var match = FINGERPRINT_RE.exec(req.url), filename;

      options.path    = req.url;
      options.getOnly = true;

      if (match) {
        // beautify zipball name
        filename = 'filename=fontello-' + match[1].substr(0, 8) + '.zip';
        res.setHeader('Content-Disposition', 'attachment; ' + filename);
      }

      connect.static.send(req, res, next, options);
    });
  }({root: path.resolve(__dirname, '../../public/download')}));

  // init dummy static server
  (function (options) {
    var static_urls = ['/favicon.ico', '/robots.txt', '/snippet.png'];

    app.use("/", function (req, res, next) {
      if (-1 === static_urls.indexOf(req.url)) {
        next();
        return;
      }

      options.path    = req.url;
      options.getOnly = true;

      connect.static.send(req, res, next, options);
    });
  }({root: path.resolve(__dirname, '../../public/root')}));

  // middlewares
  app.use(connect.query());

  static_helpers.asset_path = function (path) {
    var asset = nodeca.runtime.assets_manifest.assets[path];
    return !asset ? "#" :("/assets/" + asset);
  };

  static_helpers.count_online_users = function () {
    try {
      return nodeca.runtime.sio.sockets.clients().length + 1;
    } catch (err) {
      nodeca.logger.error("Failed get list of socket.io clients: " +
                          (err.message || err.toString()));
      return 0;
    }
  };

  // main worker
  app.use(function (req, res) {
    var host = req.headers.host, env, match, params;

    if (-1 === nodeca.runtime.router.__vhosts__.known.indexOf(host)) {
      host = nodeca.runtime.router.__vhosts__.default_host;
    }

    if (host) {
      host = '//' + host;
    }

    match = nodeca.runtime.router.match(host + req.url.split('?').shift());

    if (!match) {
      // TODO: Fix not found handling
      res.statusCode = 404;
      res.end('Not found');
      return;
    }

    // prefill environment
    env = {
      request: {
        origin: 'HTTP',
        method: match.meta.name,
        namespace: match.meta.name.split('.').shift()
      },
      response: {
        data: {},
        headers: {},
        layout: 'default',
        view: match.meta.name
      }
    };

    // mix GET QUERY params (part after ? in URL) and params from router
    // params from router tke precedence
    params = _.extend(req.query || {}, match.params || {});
    nodeca.filters.run(match.meta.name, params, match.meta.func, function (err) {
      var data, view;

      // set required headers
      _.each(env.response.headers || {}, function (value, name) {
        res.setHeader(name, value);
      });

      if (err && err.redirect) {
        res.statusCode = err.redirect[0];
        res.setHeader('Location', err.redirect[1]);
        res.end();
        return;
      } else if (err && err.denied) {
        res.statusCode = 403;
        res.end(err.message || 'Forbidden');
        return;
      } else if (err) {
        nodeca.logger.error(err.stack || err.toString());

        res.statusCode = 500;
        res.end(('development' !== nodeca.runtime.env) ? 'Application error'
                : (err.stack || err.toString()));
        return;
      }

      view = NLib.Support.HashTree.get(nodeca.runtime.views, env.response.view);
      data = _.extend({}, static_helpers, env.response.data);

      if (!view) {
        res.statusCode = 500;
        res.end('View ' + env.response.view + ' not found');
        return;
      }

      // success render view
      res.end(view.en(data));
    }, env); // nodeca.filters.run
  });

  // connect application is a simple HTTP(S) request event handler
  server.on('request', app);
}

function attach_socket_io(server) {
  var noop = function () {}, sio;

  sio = nodeca.runtime.sio = socket_io.listen(server);

  var curr_users_count;
  setInterval(function () {
    var updated_count = sio.sockets.clients().length;
    if (updated_count !== curr_users_count) {
      curr_users_count = updated_count;
      sio.sockets.emit('users_online', curr_users_count);
    }
  }, 10000);

  sio.sockets.on('connection', function (socket) {
    socket.on('server', function (msg, cb) {
      var env, fn = NLib.Support.HashTree.get(nodeca.server, msg.method);

      if (msg.version !== nodeca.runtime.version) {
        (cb || noop)({
          version:  nodeca.runtime.version,
          error:    'Nodeca client mismatch'
        });
        return;
      }

      if (!fn) {
        (cb || noop)({
          version:  nodeca.runtime.version,
          error:    'Unknown server method: ' + msg.method
        });
        return;
      }

      // prefill environment
      env = {
        __raw__: {
          socket: socket
        },
        request: {
          origin: 'RT',
          method: msg.method,
          namespace: msg.method.split('.').shift()
        },
        session: {
          // FIXME: use req.session instead
          theme: 'desktop',
          lang: nodeca.config.locales.default
        },
        response: {
          data: {},
          layout: 'default',
          view: msg.method
        }
      };

      nodeca.filters.run(msg.method, msg.params, fn, function (err) {
        if (err) {
          nodeca.logger.error(err.stack || err.toString());
        }

        (cb || noop)({
          version:  nodeca.runtime.version,
          error:    (err ? err.toString() : null),
          result:   env.response
        });
      }, env);
    });
  });
}

function start_server(next) {
  var server, host, port, err_handler;

  // create server
  host    = nodeca.config.listen.host || 'localhost';
  port    = nodeca.config.listen.port || 3000;
  server  = require('http').createServer();

  err_handler = function (err) {
    var err_prefix = "Can't bind to <" + host + "> with port <" + port + ">: ";

    if ('EADDRINUSE' === err.code) {
      next(err_prefix + 'Address in use...');
      return;
    }

    if ('EADDRNOTAVAIL' === err.code) {
      // system has no such ip address
      next(err_prefix + 'Address is not available...');
      return;
    }

    if ('ENOENT' === err.code) {
      // failed resolve hostname to ip address
      next(err_prefix + "Failed to resolve IP address...");
      return;
    }

    // unexpected / unknown error
    next(err_prefix + err);
  };

  server.on('error', err_handler);

  // start server
  server.listen(port, host, function () {
    server.removeListener('error', err_handler);
    next(null, server);
  });
}

// MODULE EXPORTS //////////////////////////////////////////////////////////////

module.exports = function (next) {
  start_server(function (err, server) {
    if (err) {
      next(err);
      return;
    }

    // Socket.IO removes and then wraps event listeners from the server,
    // so it should be attached after connect applcation.

    attach_connect_app(server);
    attach_socket_io(server);

    next();
  });
};
<commit_msg>Improve Socket.IO production environment.<commit_after>"use strict";

/*global nodeca, _*/

// stdlib
var path = require('path');

// nodeca
var NLib = require('nlib');

// 3rd-party
var connect   = require('connect');
var socket_io = require('socket.io');

// HELPERS /////////////////////////////////////////////////////////////////////

function attach_connect_app(server) {
  var app = connect(), static_helpers = {}, download_root;

  app.use("/assets/", connect.compress());
  app.use("/assets/", nodeca.runtime.assets_server);

  // init downloads static middleware
  (function (options) {
    var FINGERPRINT_RE = /-([0-9a-f]{32,40})\.[^.]+$/;
    app.use("/download/", function (req, res, next) {
      var match = FINGERPRINT_RE.exec(req.url), filename;

      options.path    = req.url;
      options.getOnly = true;

      if (match) {
        // beautify zipball name
        filename = 'filename=fontello-' + match[1].substr(0, 8) + '.zip';
        res.setHeader('Content-Disposition', 'attachment; ' + filename);
      }

      connect.static.send(req, res, next, options);
    });
  }({root: path.resolve(__dirname, '../../public/download')}));

  // init dummy static server
  (function (options) {
    var static_urls = ['/favicon.ico', '/robots.txt', '/snippet.png'];

    app.use("/", function (req, res, next) {
      if (-1 === static_urls.indexOf(req.url)) {
        next();
        return;
      }

      options.path    = req.url;
      options.getOnly = true;

      connect.static.send(req, res, next, options);
    });
  }({root: path.resolve(__dirname, '../../public/root')}));

  // middlewares
  app.use(connect.query());

  static_helpers.asset_path = function (path) {
    var asset = nodeca.runtime.assets_manifest.assets[path];
    return !asset ? "#" :("/assets/" + asset);
  };

  static_helpers.count_online_users = function () {
    try {
      return nodeca.runtime.sio.sockets.clients().length + 1;
    } catch (err) {
      nodeca.logger.error("Failed get list of socket.io clients: " +
                          (err.message || err.toString()));
      return 0;
    }
  };

  // main worker
  app.use(function (req, res) {
    var host = req.headers.host, env, match, params;

    if (-1 === nodeca.runtime.router.__vhosts__.known.indexOf(host)) {
      host = nodeca.runtime.router.__vhosts__.default_host;
    }

    if (host) {
      host = '//' + host;
    }

    match = nodeca.runtime.router.match(host + req.url.split('?').shift());

    if (!match) {
      // TODO: Fix not found handling
      res.statusCode = 404;
      res.end('Not found');
      return;
    }

    // prefill environment
    env = {
      request: {
        origin: 'HTTP',
        method: match.meta.name,
        namespace: match.meta.name.split('.').shift()
      },
      response: {
        data: {},
        headers: {},
        layout: 'default',
        view: match.meta.name
      }
    };

    // mix GET QUERY params (part after ? in URL) and params from router
    // params from router tke precedence
    params = _.extend(req.query || {}, match.params || {});
    nodeca.filters.run(match.meta.name, params, match.meta.func, function (err) {
      var data, view;

      // set required headers
      _.each(env.response.headers || {}, function (value, name) {
        res.setHeader(name, value);
      });

      if (err && err.redirect) {
        res.statusCode = err.redirect[0];
        res.setHeader('Location', err.redirect[1]);
        res.end();
        return;
      } else if (err && err.denied) {
        res.statusCode = 403;
        res.end(err.message || 'Forbidden');
        return;
      } else if (err) {
        nodeca.logger.error(err.stack || err.toString());

        res.statusCode = 500;
        res.end(('development' !== nodeca.runtime.env) ? 'Application error'
                : (err.stack || err.toString()));
        return;
      }

      view = NLib.Support.HashTree.get(nodeca.runtime.views, env.response.view);
      data = _.extend({}, static_helpers, env.response.data);

      if (!view) {
        res.statusCode = 500;
        res.end('View ' + env.response.view + ' not found');
        return;
      }

      // success render view
      res.end(view.en(data));
    }, env); // nodeca.filters.run
  });

  // connect application is a simple HTTP(S) request event handler
  server.on('request', app);
}

function attach_socket_io(server) {
  var noop = function () {}, sio;

  sio = nodeca.runtime.sio = socket_io.listen(server);

  var curr_users_count;
  setInterval(function () {
    var updated_count = sio.sockets.clients().length;
    if (updated_count !== curr_users_count) {
      curr_users_count = updated_count;
      sio.sockets.emit('users_online', curr_users_count);
    }
  }, 10000);

  if ('development' !== nodeca.runtime.env) {
    sio.enable('browser client minification');  // send minified client
    sio.enable('browser client etag');          // apply etag caching logic based on version number
    sio.enable('browser client gzip');          // gzip the file
    sio.set('log level', 1);                    // reduce logging
  }

  sio.sockets.on('connection', function (socket) {
    socket.on('server', function (msg, cb) {
      var env, fn = NLib.Support.HashTree.get(nodeca.server, msg.method);

      if (msg.version !== nodeca.runtime.version) {
        (cb || noop)({
          version:  nodeca.runtime.version,
          error:    'Nodeca client mismatch'
        });
        return;
      }

      if (!fn) {
        (cb || noop)({
          version:  nodeca.runtime.version,
          error:    'Unknown server method: ' + msg.method
        });
        return;
      }

      // prefill environment
      env = {
        __raw__: {
          socket: socket
        },
        request: {
          origin: 'RT',
          method: msg.method,
          namespace: msg.method.split('.').shift()
        },
        session: {
          // FIXME: use req.session instead
          theme: 'desktop',
          lang: nodeca.config.locales.default
        },
        response: {
          data: {},
          layout: 'default',
          view: msg.method
        }
      };

      nodeca.filters.run(msg.method, msg.params, fn, function (err) {
        if (err) {
          nodeca.logger.error(err.stack || err.toString());
        }

        (cb || noop)({
          version:  nodeca.runtime.version,
          error:    (err ? err.toString() : null),
          result:   env.response
        });
      }, env);
    });
  });
}

function start_server(next) {
  var server, host, port, err_handler;

  // create server
  host    = nodeca.config.listen.host || 'localhost';
  port    = nodeca.config.listen.port || 3000;
  server  = require('http').createServer();

  err_handler = function (err) {
    var err_prefix = "Can't bind to <" + host + "> with port <" + port + ">: ";

    if ('EADDRINUSE' === err.code) {
      next(err_prefix + 'Address in use...');
      return;
    }

    if ('EADDRNOTAVAIL' === err.code) {
      // system has no such ip address
      next(err_prefix + 'Address is not available...');
      return;
    }

    if ('ENOENT' === err.code) {
      // failed resolve hostname to ip address
      next(err_prefix + "Failed to resolve IP address...");
      return;
    }

    // unexpected / unknown error
    next(err_prefix + err);
  };

  server.on('error', err_handler);

  // start server
  server.listen(port, host, function () {
    server.removeListener('error', err_handler);
    next(null, server);
  });
}

// MODULE EXPORTS //////////////////////////////////////////////////////////////

module.exports = function (next) {
  start_server(function (err, server) {
    if (err) {
      next(err);
      return;
    }

    // Socket.IO removes and then wraps event listeners from the server,
    // so it should be attached after connect applcation.

    attach_connect_app(server);
    attach_socket_io(server);

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


<commit_before>import { merge } from '@ember/polyfills';
import getElement from './-get-element';
import fireEvent from './fire-event';
import settled from '../settled';
import { KEYBOARD_EVENT_TYPES } from './fire-event';
import { nextTickPromise } from '../-utils';

const DEFAULT_MODIFIERS = Object.freeze({
  ctrlKey: false,
  altKey: false,
  shiftKey: false,
  metaKey: false,
});

/**
  @public
  @param {String|Element} target
  @param {'keydown' | 'keyup' | 'keypress'} eventType
  @param {String} keyCode
  @param {Object} [modifiers]
  @param {Boolean} [modifiers.ctrlKey=false]
  @param {Boolean} [modifiers.altKey=false]
  @param {Boolean} [modifiers.shiftKey=false]
  @param {Boolean} [modifiers.metaKey=false]
  @return {Promise<void>}
*/
export default function triggerKeyEvent(target, eventType, keyCode, modifiers = DEFAULT_MODIFIERS) {
  return nextTickPromise().then(() => {
    if (!target) {
      throw new Error('Must pass an element or selector to `triggerKeyEvent`.');
    }

    let element = getElement(target);
    if (!element) {
      throw new Error(`Element not found when calling \`triggerKeyEvent('${target}', ...)\`.`);
    }

    if (!eventType) {
      throw new Error(`Must provide an \`eventType\` to \`triggerKeyEvent\``);
    }

    if (KEYBOARD_EVENT_TYPES.indexOf(eventType) === -1) {
      let validEventTypes = KEYBOARD_EVENT_TYPES.join(', ');
      throw new Error(
        `Must provide an \`eventType\` of ${validEventTypes} to \`triggerKeyEvent\` but you passed \`${eventType}\`.`
      );
    }

    if (!keyCode) {
      throw new Error(`Must provide a \`keyCode\` to \`triggerKeyEvent\``);
    }

    let options = merge({ keyCode, which: keyCode, key: keyCode }, modifiers);

    fireEvent(element, eventType, options);

    return settled();
  });
}
<commit_msg>Docs: flesh out the triggerKeyEvent documentation<commit_after>import { merge } from '@ember/polyfills';
import getElement from './-get-element';
import fireEvent from './fire-event';
import settled from '../settled';
import { KEYBOARD_EVENT_TYPES } from './fire-event';
import { nextTickPromise } from '../-utils';

const DEFAULT_MODIFIERS = Object.freeze({
  ctrlKey: false,
  altKey: false,
  shiftKey: false,
  metaKey: false,
});

/**
  Triggers a keyboad event on the specified selector.

  @public
  @param {String|Element} target the element or selector to trigger the event on
  @param {'keydown' | 'keyup' | 'keypress'} eventType the type of event to trigger
  @param {String} keyCode the keyCode of the event being triggered
  @param {Object} [modifiers] the state of various modifier keys
  @param {boolean} [modifiers.ctrlKey=false] if true the generated event will indicate the control key was pressed during the key event
  @param {boolean} [modifiers.altKey=false] if true the generated event will indicate the alt key was pressed during the key event
  @param {boolean} [modifiers.shiftKey=false] if true the generated event will indicate the shift key was pressed during the key event
  @param {boolean} [modifiers.metaKey=false] if true the generated event will indicate the meta key was pressed during the key event
  @return {Promise<void>} resolves when the application is settled
*/
export default function triggerKeyEvent(target, eventType, keyCode, modifiers = DEFAULT_MODIFIERS) {
  return nextTickPromise().then(() => {
    if (!target) {
      throw new Error('Must pass an element or selector to `triggerKeyEvent`.');
    }

    let element = getElement(target);
    if (!element) {
      throw new Error(`Element not found when calling \`triggerKeyEvent('${target}', ...)\`.`);
    }

    if (!eventType) {
      throw new Error(`Must provide an \`eventType\` to \`triggerKeyEvent\``);
    }

    if (KEYBOARD_EVENT_TYPES.indexOf(eventType) === -1) {
      let validEventTypes = KEYBOARD_EVENT_TYPES.join(', ');
      throw new Error(
        `Must provide an \`eventType\` of ${validEventTypes} to \`triggerKeyEvent\` but you passed \`${eventType}\`.`
      );
    }

    if (!keyCode) {
      throw new Error(`Must provide a \`keyCode\` to \`triggerKeyEvent\``);
    }

    let options = merge({ keyCode, which: keyCode, key: keyCode }, modifiers);

    fireEvent(element, eventType, options);

    return settled();
  });
}
<|endoftext|>


<commit_before>jQuery.sap.declare("de.esconderse.Component");
jQuery.sap.require("de.esconderse.Router");

sap.ui.core.UIComponent.extend("de.esconderse.Component", {
	useMockData: false,
	metadata : 'json',
    init : function() {
        sap.ui.core.UIComponent.prototype.init.apply(this, arguments);
        var mConfig = this.getMetadata().getConfig();
        // always use absolute paths relative to our own component
        // (relative paths will fail if running in the Fiori Launchpad)
        var rootPath = jQuery.sap.getModulePath("de.esconderse");
        // Create and set domain model to the component
//        this.setModel(new sap.ui.model.odata.ODataModel(mConfig.serviceConfig.serviceUrl, true));

        // set i18n model
        this.setModel(
        	new sap.ui.model.resource.ResourceModel({
            	bundleUrl : [rootPath, mConfig.resourceBundle].join("/")
        	}), "i18n")
        .setModel(
        	new sap.ui.model.json.JSONModel({
            	isTouch : sap.ui.Device.support.touch,
            	isNoTouch : !sap.ui.Device.support.touch,
            	isPhone : sap.ui.Device.system.phone,
            	isNoPhone : !sap.ui.Device.system.phone,
        		listMode : sap.ui.Device.system.phone ? "None" : "SingleSelectMaster",
        		listItemType : sap.ui.Device.system.phone ? "Active" : "Inactive"
        	})//.setDefaultBindingMode("OneWay")
        	, "device")
        .setModel(
			new sap.ui.model.json.JSONModel(
				this.useMockData
				?"model/account.json"
				:"https://esconderse.de/account"
			)//.setDefaultBindingMode("OneWay")
			, "account")
		.setModel(
			new sap.ui.model.json.JSONModel(
				this.useMockData
				?"model/mailListNew.json"
				:"https://esconderse.de/ajax.php?list"
			)//.setDefaultBindingMode("OneWay")
		)
		.getRouter()
		.initialize();
    }
});<commit_msg>refactor model loading<commit_after>jQuery.sap.declare("de.esconderse.Component");
jQuery.sap.require("de.esconderse.Router");

sap.ui.core.UIComponent.extend("de.esconderse.Component", {
	useMockData: false,
	metadata : 'json',
	register: function(bus){
		bus.subscribe("master", "loadList", function(that){
			return function(){ that.doLoadList(); };
		}(this));
		bus.subscribe("master", "loadAccount", function(that){
			return function(){ that.doLoadAccount(); };
		}(this));
	},
    init : function() {
        sap.ui.core.UIComponent.prototype.init.apply(this, arguments);
        var mConfig = this.getMetadata().getConfig(), mailModel, resourceModel, deviceModel, accountModel;
        // always use absolute paths relative to our own component
        // (relative paths will fail if running in the Fiori Launchpad)
        var rootPath = jQuery.sap.getModulePath("de.esconderse");

		resourceModel = new sap.ui.model.resource.ResourceModel({
			bundleUrl : [rootPath, mConfig.resourceBundle].join("/")
        });
        deviceModel = new sap.ui.model.json.JSONModel({
        	isTouch : sap.ui.Device.support.touch,
        	isNoTouch : !sap.ui.Device.support.touch,
        	isPhone : sap.ui.Device.system.phone,
        	isNoPhone : !sap.ui.Device.system.phone,
        	listMode : sap.ui.Device.system.phone ? "None" : "SingleSelectMaster",
        	listItemType : sap.ui.Device.system.phone ? "Active" : "Inactive"
        });
        deviceModel.setDefaultBindingMode("OneWay");
        mailModel = new sap.ui.model.json.JSONModel();
		mailModel.setDefaultBindingMode("OneWay");
    	mailModel.attachRequestCompleted({}, function(){
		    var msg = 'Liste aktualisiert';
			sap.m.MessageToast.show(msg);
			sap.ui.getCore().getEventBus().publish("master", "enableRefresh");
    	});
        accountModel = new sap.ui.model.json.JSONModel()
        // set i18n model
        this.setModel(mailModel)
        	.setModel(deviceModel, "device")
        	.setModel(accountModel, "account")
        	.setModel(resourceModel, "i18n")
        	.doLoadList()
        	.doLoadAccount()
        	.register(sap.ui.getCore().getEventBus())
			.getRouter()
			.initialize();
    },
    onRefreshFinish: function(){
    	this.getView();
    },
    doLoadList: function(){
    	var model = this.getModel();
    	model.loadData(
			this.useMockData?"model/mailListNew.json":"https://esconderse.de/gateway.php?list"
    	);
    	return this;
    },
    doLoadAccount: function(){
    	var model = this.getModel("account");
    	model.loadData(
			this.useMockData?"model/mailListNew.json":"https://esconderse.de/gateway.php?list"
    	);
    	return this;
    }
});
<|endoftext|>


<commit_before>/*jslint node: true */
/*jshint laxbreak: true */
"use strict";

var _ = require('underscore');

var Constants = function() {
  return {
    getDataSources: function() {
      var sources = [{
        url: 'https://wwwdev.ebi.ac.uk/uniprot/services/restful/features/',
        type: 'basic'
      }, {
        url: 'https://wwwdev.ebi.ac.uk/uniprot/services/restful/proteomics/',
        type: 'basic'
      }, {
        url: 'https://wwwdev.ebi.ac.uk/uniprot/services/restful/variation/',
        type: 'variant'
      }];
      return sources;
    }, getCategoryNamesInOrder: function() {
      return [{
        DOMAINS_AND_SITES: 'Domains & sites'
      }, {
        MOLECULE_PROCESSING: 'Molecule processing'
      }, {
        PTM: 'Post translational modifications'
      }, {
        SEQUENCE_INFORMATON: 'Sequence information'
      }, {
        STRUCTURAL: 'Structural features'
      }, {
        TOPOLOGY: 'Topology'
      }, {
        MUTAGENESIS: 'Mutagenesis'
      }, {
        PROTEOMICS: 'Proteomics'
      }, {
        VARIATION: 'Variants'
      }];
    }, getCategoryName: function(name) {
      var names = this.getCategoryNamesInOrder();
      var match = _.find( names, function(item){
        return name === _.keys(item)[0];
      });
      if(match) {
        return match[name];
      } else {
        return name;
      }
    }, getTrackNames: function() {
      return {
          //molecular processing
          chain: {label: 'Chain',
              tooltip: '(aka mature region). This describes the extent of a polypeptide chain in the mature protein' +
              ' following processing'
          }, transit: {label: 'Transit peptide', tooltip: 'This describes the extent of a transit peptide'
          }, init_met: {label: 'Initiator methionine', tooltip: 'This indicates that the initiator methionine is cleaved from the mature' +
              ' protein'
          }, propep: {label: 'Propeptide', tooltip: 'Part of a protein that is cleaved during maturation or activation'
          }, peptide: {label: 'Peptide', tooltip: 'The position and length of an active peptide in the mature protein'
          }, signal: {label: 'Signal', tooltip: 'N-terminal signal peptide'},
          //structural
          helix: {label: 'Helix', tooltip: 'The positions of experimentally determined helical regions'
          }, strand: {label: 'Beta strand', tooltip: 'The positions of experimentally determined beta strands'
          }, turn: {label: 'Turn', tooltip: 'The positions of experimentally determined hydrogen-bonded turns'
          }, disulfid: {label: 'Disulfide bond', tooltip: 'The positions of cysteine residues participating in' +
              ' disulphide bonds'
          }, crosslnk: {label: 'Cross-link', tooltip: 'Covalent linkages of various types formed between two proteins' +
              ' or between two parts of the same protein'},
          //domains & sites
          region: {label: 'Region', tooltip: 'Regions in multifunctional enzymes or fusion proteins, or' +
              ' characteristics of a region, e.g., protein-protein interactions mediation'
          }, coiled:  {label: 'Coiled coil', tooltip: 'Coiled coils are built by two or more alpha-helices that wind' +
              ' around each other to form a supercoil'
          }, motif: {label: 'Motif', tooltip: 'Short conserved sequence motif of biological significance'
          }, repeat: {label: 'Repeat', tooltip: 'Repeated sequence motifs or repeated domains within the protein'
          }, ca_bind: {label: 'Calcium binding', tooltip: 'Calcium-binding regions, such as the EF-hand motif'
          }, dna_bind: {label: 'DNA binding', tooltip: 'DNA-binding domains such as AP2/ERF domain, the ETS domain,' +
              ' the Fork-Head domain, the HMG box and the Myb domain'
          }, domain: {label: 'Domain', tooltip: 'Specific combination of secondary structures organized into a ' +
              'characteristic three-dimensional structure or fold'
          }, zn_fing: {label: 'Zing finger', tooltip: 'Small, functional, independently folded domain that coordinates' +
              ' one or more zinc ions'
          }, np_bind: {label: 'Nucleotide binding', tooltip: '(aka flavin-binding). Region in the protein which binds' +
              ' nucleotide phosphates'
          }, metal: {label: 'Metal binding', tooltip: 'Binding site for a metal ion'
          }, site: {label: 'Site', tooltip: 'Any interesting single amino acid site on the sequence'
          }, binding: {label: 'Binding site', tooltip: 'Binding site for any chemical group (co-enzyme, prosthetic' +
          ' group, etc.)'
          }, act_site: {label: 'Active site', tooltip: 'Amino acid(s) directly involved in the activity of an enzyme'},
          //ptms
          mod_res: {label: 'Modified residue', tooltip: 'Modified residues such as phosphorylation, acetylation,' +
              ' acylation, methylation'
          }, lipid: {label: 'Lipidation', tooltip: 'Covalently attached lipid group(s)'
          }, carbohyd: {label: 'Glycosylation', tooltip: 'Covalently attached glycan group(s)'},
          //seqInfo
          compbias: {label: 'Compositional bias', tooltip: 'Position of regions of compositional bias within the' +
              ' protein and the particular amino acids that are over-represented within those regions'
          }, conflict: {label: 'Sequence conflict', tooltip: 'Sequence discrepancies of unknown origin'
          }, non_cons: {label: 'Non-adjacent residues', tooltip: 'Indicates that two residues in a sequence are not ' +
              'consecutive and that there is an undetermined number of unsequenced residues between them'
          }, non_ter: {label: 'Non-terminal residue', tooltip: 'The sequence is incomplete. The residue is not the ' +
              'terminal residue of the complete protein'
          }, unsure: {label: 'Sequence uncertainty', tooltip: 'Regions of a sequence for which the authors are unsure ' +
              'about the sequence assignment'
          }, non_std: {label: 'Non-standard residue', tooltip: 'Non-standard amino acids (selenocysteine and ' +
              'pyrrolysine)'},
          //mutagenesis
          mutagen: {label: 'Mutagenesis', tooltip: 'Site which has been experimentally altered by mutagenesis'},
          //topology
          topo_dom: {label: 'Topological domain', tooltip: 'Location of non-membrane regions of membrane-spanning ' +
              'proteins'
          }, transmem: {label: 'Transmembrane', tooltip: 'Extent of a membrane-spanning region'
          }, intramem: {label: 'Intramembrane', tooltip: 'Extent of a region located in a membrane without crossing it'},
          //variants
          variant: {label: 'Natural variant', tooltip: 'Natural variant of the protein, including polymorphisms, ' +
              'variations between strains, isolates or cultivars, disease-associated mutations and RNA editing events'
          },
          unique:{label:'Unique peptides',tooltip:''},
          non_unique:{label:'Non-unique peptides',tooltip:''}
      };
    }, getTrackInfo: function(name) {
      return this.getTrackNames()[name];
    }
  };
}();

module.exports = Constants;
<commit_msg>Use zinc rather than zing.<commit_after>/*jslint node: true */
/*jshint laxbreak: true */
"use strict";

var _ = require('underscore');

var Constants = function() {
  return {
    getDataSources: function() {
      var sources = [{
        url: 'https://wwwdev.ebi.ac.uk/uniprot/services/restful/features/',
        type: 'basic'
      }, {
        url: 'https://wwwdev.ebi.ac.uk/uniprot/services/restful/proteomics/',
        type: 'basic'
      }, {
        url: 'https://wwwdev.ebi.ac.uk/uniprot/services/restful/variation/',
        type: 'variant'
      }];
      return sources;
    }, getCategoryNamesInOrder: function() {
      return [{
        DOMAINS_AND_SITES: 'Domains & sites'
      }, {
        MOLECULE_PROCESSING: 'Molecule processing'
      }, {
        PTM: 'Post translational modifications'
      }, {
        SEQUENCE_INFORMATON: 'Sequence information'
      }, {
        STRUCTURAL: 'Structural features'
      }, {
        TOPOLOGY: 'Topology'
      }, {
        MUTAGENESIS: 'Mutagenesis'
      }, {
        PROTEOMICS: 'Proteomics'
      }, {
        VARIATION: 'Variants'
      }];
    }, getCategoryName: function(name) {
      var names = this.getCategoryNamesInOrder();
      var match = _.find( names, function(item){
        return name === _.keys(item)[0];
      });
      if(match) {
        return match[name];
      } else {
        return name;
      }
    }, getTrackNames: function() {
      return {
          //molecular processing
          chain: {label: 'Chain',
              tooltip: '(aka mature region). This describes the extent of a polypeptide chain in the mature protein' +
              ' following processing'
          }, transit: {label: 'Transit peptide', tooltip: 'This describes the extent of a transit peptide'
          }, init_met: {label: 'Initiator methionine', tooltip: 'This indicates that the initiator methionine is cleaved from the mature' +
              ' protein'
          }, propep: {label: 'Propeptide', tooltip: 'Part of a protein that is cleaved during maturation or activation'
          }, peptide: {label: 'Peptide', tooltip: 'The position and length of an active peptide in the mature protein'
          }, signal: {label: 'Signal', tooltip: 'N-terminal signal peptide'},
          //structural
          helix: {label: 'Helix', tooltip: 'The positions of experimentally determined helical regions'
          }, strand: {label: 'Beta strand', tooltip: 'The positions of experimentally determined beta strands'
          }, turn: {label: 'Turn', tooltip: 'The positions of experimentally determined hydrogen-bonded turns'
          }, disulfid: {label: 'Disulfide bond', tooltip: 'The positions of cysteine residues participating in' +
              ' disulphide bonds'
          }, crosslnk: {label: 'Cross-link', tooltip: 'Covalent linkages of various types formed between two proteins' +
              ' or between two parts of the same protein'},
          //domains & sites
          region: {label: 'Region', tooltip: 'Regions in multifunctional enzymes or fusion proteins, or' +
              ' characteristics of a region, e.g., protein-protein interactions mediation'
          }, coiled:  {label: 'Coiled coil', tooltip: 'Coiled coils are built by two or more alpha-helices that wind' +
              ' around each other to form a supercoil'
          }, motif: {label: 'Motif', tooltip: 'Short conserved sequence motif of biological significance'
          }, repeat: {label: 'Repeat', tooltip: 'Repeated sequence motifs or repeated domains within the protein'
          }, ca_bind: {label: 'Calcium binding', tooltip: 'Calcium-binding regions, such as the EF-hand motif'
          }, dna_bind: {label: 'DNA binding', tooltip: 'DNA-binding domains such as AP2/ERF domain, the ETS domain,' +
              ' the Fork-Head domain, the HMG box and the Myb domain'
          }, domain: {label: 'Domain', tooltip: 'Specific combination of secondary structures organized into a ' +
              'characteristic three-dimensional structure or fold'
          }, zn_fing: {label: 'Zinc finger', tooltip: 'Small, functional, independently folded domain that' +
          ' coordinates' +
              ' one or more zinc ions'
          }, np_bind: {label: 'Nucleotide binding', tooltip: '(aka flavin-binding). Region in the protein which binds' +
              ' nucleotide phosphates'
          }, metal: {label: 'Metal binding', tooltip: 'Binding site for a metal ion'
          }, site: {label: 'Site', tooltip: 'Any interesting single amino acid site on the sequence'
          }, binding: {label: 'Binding site', tooltip: 'Binding site for any chemical group (co-enzyme, prosthetic' +
          ' group, etc.)'
          }, act_site: {label: 'Active site', tooltip: 'Amino acid(s) directly involved in the activity of an enzyme'},
          //ptms
          mod_res: {label: 'Modified residue', tooltip: 'Modified residues such as phosphorylation, acetylation,' +
              ' acylation, methylation'
          }, lipid: {label: 'Lipidation', tooltip: 'Covalently attached lipid group(s)'
          }, carbohyd: {label: 'Glycosylation', tooltip: 'Covalently attached glycan group(s)'},
          //seqInfo
          compbias: {label: 'Compositional bias', tooltip: 'Position of regions of compositional bias within the' +
              ' protein and the particular amino acids that are over-represented within those regions'
          }, conflict: {label: 'Sequence conflict', tooltip: 'Sequence discrepancies of unknown origin'
          }, non_cons: {label: 'Non-adjacent residues', tooltip: 'Indicates that two residues in a sequence are not ' +
              'consecutive and that there is an undetermined number of unsequenced residues between them'
          }, non_ter: {label: 'Non-terminal residue', tooltip: 'The sequence is incomplete. The residue is not the ' +
              'terminal residue of the complete protein'
          }, unsure: {label: 'Sequence uncertainty', tooltip: 'Regions of a sequence for which the authors are unsure ' +
              'about the sequence assignment'
          }, non_std: {label: 'Non-standard residue', tooltip: 'Non-standard amino acids (selenocysteine and ' +
              'pyrrolysine)'},
          //mutagenesis
          mutagen: {label: 'Mutagenesis', tooltip: 'Site which has been experimentally altered by mutagenesis'},
          //topology
          topo_dom: {label: 'Topological domain', tooltip: 'Location of non-membrane regions of membrane-spanning ' +
              'proteins'
          }, transmem: {label: 'Transmembrane', tooltip: 'Extent of a membrane-spanning region'
          }, intramem: {label: 'Intramembrane', tooltip: 'Extent of a region located in a membrane without crossing it'},
          //variants
          variant: {label: 'Natural variant', tooltip: 'Natural variant of the protein, including polymorphisms, ' +
              'variations between strains, isolates or cultivars, disease-associated mutations and RNA editing events'
          },
          unique:{label:'Unique peptides',tooltip:''},
          non_unique:{label:'Non-unique peptides',tooltip:''}
      };
    }, getTrackInfo: function(name) {
      return this.getTrackNames()[name];
    }
  };
}();

module.exports = Constants;
<|endoftext|>


<commit_before>/**
 * @module queue-action-creator
 */

var dispatcher = require('../dispatcher');
var queueAPI = require('../utils/queue-api');

// Interface.
module.exports = {

	/**
	 * Action initiator to fetch queue data from a server.
	 *
	 * Dispatches action and delegates to the queue web API utility to actually
	 * fetch the queue data.
	 */
	fetchQueueData: function () {
		dispatcher.dispatch({
			type: 'FETCHING_QUEUE_DATA'
		});

		queueAPI.fetch();
	}
};
<commit_msg>Added (un)favorite actions.<commit_after>/**
 * @module queue-action-creator
 */

var dispatcher = require('../dispatcher');
var queueAPI = require('../utils/queue-api');

// Interface.
module.exports = {

	/**
	 * Action initiator to fetch queue data from a server.
	 *
	 * Dispatches action and delegates to the queue web API utility to actually
	 * fetch the queue data.
	 */
	fetchQueueData: function () {
		dispatcher.dispatch({
			type: 'FETCHING_QUEUE_DATA'
		});

		queueAPI.fetch();
	},

	/**
	 * Favorites a queue item.
	 *
	 * @param  {string} itemId - queue item identifier
	 */
	favoriteItem: function (itemId) {
		dispatcher.dispatch({
			type: 'FAVORITE_QUEUE_ITEM',
			payload: itemId
		});
	},

	/**
	 * Un favorites a queue item.
	 *
	 * @param  {string} itemId - queue item identifier
	 */
	unFavoriteItem: function (itemId) {
		dispatcher.dispatch({
			type: 'UN_FAVORITE_QUEUE_ITEM',
			payload: itemId
		});
	}
};
<|endoftext|>


<commit_before>angular.module('webtools').controller('subController', ['$scope', 'subModel', 'subService', 'gettext', function ($scope, subModel, subService, gettext) {
    $scope.subModel = subModel;

    $scope.translate = function () {
        var lang = {
            searchPlaceholder: gettext("Search..."),
            searchKeyword: gettext("Search keyword"),
            clearSearch: gettext("Clear search"),
            previous: gettext("Previous"),
            next: gettext("Next"),
            jumpToTop: gettext("Jump to top"),
            hideShowMenu: gettext("Hide/Show search menu"),

            search: gettext("Search..."),
            expandShowToSearch: gettext("Expand a library to search"),

            /* subDetails.html */
            selectAll: gettext("Select All"),
            deselectAll: gettext("Deselect All"),
            uploadSubtitle: gettext("Upload Subtitle"),
            deleteSelected: gettext("Delete Selected"),
            viewSubtitle: gettext("View Subtitle"),
            downloadSubtitle: gettext("Download Subtitle"),
            confirmDeleteQuestion: gettext("Are you sure you want to delete the selected subtitles?"),
            confirmDelete: gettext("Delete")
        };
        $scope.lang = lang;
        $scope.searchPlaceholder = $scope.lang.search;
    }

    $scope.init = function () {
        $scope.translate();
        subService.getShows();
    }

    $scope.isAnyShowExpanded = function () {
        var isExpanded = false;
        for (var i = 0; i < subModel.shows.length; i++) {
            var show = subModel.shows[i];
            if (show.expanded) isExpanded = true;
        }

        if (isExpanded) $scope.searchPlaceholder = $scope.lang.search;
        else $scope.searchPlaceholder = $scope.lang.expandShowToSearch;
        return isExpanded;
    }

    $scope.searchSub = function () {
        for (var i = 0; i < subModel.shows.length; i++) {
            var show = subModel.shows[i];
            $scope.reloadShow(show);
        }
    }

    $scope.reloadShow = function (show) {
        if (show.details && show.type === "movie") {
            show.skip = 0;
            show.full = false;
            show.details = [];
            subService.getMovieDetails(show);
        } else if (show.tvshows && show.type === "show") {
            show.tvshows = [];
            subService.getTvShowDetails(show);
        }
    }

    $scope.expandShow = function (show) {
        show.expanded = !show.expanded;

        if (!show.letterOptions) { //letterOptions & letter
            subService.getSectionLetterList(show);
        }

        if (!show.details && show.type === "movie") {
            show.details = [];
            subService.getMovieDetails(show);
        } else if (!show.details && show.type === "show") {
            subService.getTvShowDetails(show);
        }
    };

    $scope.expandTvShow = function (show, tvshow) {
        show.selectedTvShow = tvshow;
        if (!tvshow.seasons) {
            subService.getTvShowSeasons(tvshow);
        }
    };
    $scope.expandTvShowSeason = function (show, season) {
        show.selectedSeason = season;
        if (!season.details) {
            subService.getTvShowSeasonDetails(season);
        }
    };

    $scope.loadmore = function (show) {
        if (show.details && show.type === "movie") {
            subService.getMovieDetails(show);
        }
    }

    $scope.getAllSubtitlesChecked = function (detail) {
        for (var i = 0; i < detail.subtitles.length; i++) {
            if (detail.subtitles[i].location !== "Embedded" && !detail.subtitles[i].checked) return false;
        }
        return true;
    };

    $scope.toggleAllSubtitles = function (detail) {
        var allChecked = $scope.getAllSubtitlesChecked(detail);
        for (var i = 0; i < detail.subtitles.length; i++) {
            if (detail.subtitles[i].location === "Embedded") continue;
            detail.subtitles[i].checked = !allChecked;
        }
        detail.subAllChecked = !allChecked;
    };

    $scope.isCodexView = function (subtitle) {
        return subtitle.codec === "srt"
            || subtitle.codec === "subrip"
            || subtitle.codec === "smi"
            || subtitle.codec === "ssa"
            || subtitle.codec === "ass";
    }

    $scope.getParts = function(detail) {
        subService.getParts(detail);
    }

    $scope.upload = function (detail) {
        subService.uploadSub(detail, "file");
    };

    $scope.download = function (subtitle, $event) {
        $event.stopPropagation();
        subService.downloadSubtitle(subtitle.key);
    }

    $scope.view = function (subtitle, $event) {
        $event.stopPropagation();
        subService.viewSubtitle(subtitle.key);
    }

    $scope.delete = function (detail, subtitle) {
        subService.deleteSubtitle(detail, subtitle);
    };
    $scope.deleteSelected = function (detail) {
        for (var i = 0; i < detail.subtitles.length; i++) {
            if (detail.subtitles[i].checked) $scope.delete(detail, detail.subtitles[i]);
        }
    };

    $scope.searchKeyword = function () {
        if ($scope.subModel.searchKeywordValue && $scope.subModel.searchKeywordValue === $scope.subModel.searchKeywordValueLast) {
            if ($scope.subModel.searchFoundLines.length > 0) $scope.$broadcast("sub_search_nextLine");
        }
        else {
            $scope.$broadcast("sub_search_findKeywords");
        }
    }
    $scope.searchClear = function () {
        $scope.subModel.searchKeywordValue = "";
        $scope.$broadcast("sub_search_findKeywords");
    }
    $scope.searchPrevious = function () {
        if ($scope.subModel.searchFoundLines.length > 0) $scope.$broadcast("sub_search_previousLine");
    }
    $scope.searchJumpToTop = function () {
        $scope.$broadcast("sub_search_jumpToTop");
    }

    $scope.$on("$destroy", function () {
        subModel.selectedSub = null;
    });

    $scope.init();
}]);<commit_msg>#397   Ups...Forgot vtt files<commit_after>angular.module('webtools').controller('subController', ['$scope', 'subModel', 'subService', 'gettext', function ($scope, subModel, subService, gettext) {
    $scope.subModel = subModel;

    $scope.translate = function () {
        var lang = {
            searchPlaceholder: gettext("Search..."),
            searchKeyword: gettext("Search keyword"),
            clearSearch: gettext("Clear search"),
            previous: gettext("Previous"),
            next: gettext("Next"),
            jumpToTop: gettext("Jump to top"),
            hideShowMenu: gettext("Hide/Show search menu"),

            search: gettext("Search..."),
            expandShowToSearch: gettext("Expand a library to search"),

            /* subDetails.html */
            selectAll: gettext("Select All"),
            deselectAll: gettext("Deselect All"),
            uploadSubtitle: gettext("Upload Subtitle"),
            deleteSelected: gettext("Delete Selected"),
            viewSubtitle: gettext("View Subtitle"),
            downloadSubtitle: gettext("Download Subtitle"),
            confirmDeleteQuestion: gettext("Are you sure you want to delete the selected subtitles?"),
            confirmDelete: gettext("Delete")
        };
        $scope.lang = lang;
        $scope.searchPlaceholder = $scope.lang.search;
    }

    $scope.init = function () {
        $scope.translate();
        subService.getShows();
    }

    $scope.isAnyShowExpanded = function () {
        var isExpanded = false;
        for (var i = 0; i < subModel.shows.length; i++) {
            var show = subModel.shows[i];
            if (show.expanded) isExpanded = true;
        }

        if (isExpanded) $scope.searchPlaceholder = $scope.lang.search;
        else $scope.searchPlaceholder = $scope.lang.expandShowToSearch;
        return isExpanded;
    }

    $scope.searchSub = function () {
        for (var i = 0; i < subModel.shows.length; i++) {
            var show = subModel.shows[i];
            $scope.reloadShow(show);
        }
    }

    $scope.reloadShow = function (show) {
        if (show.details && show.type === "movie") {
            show.skip = 0;
            show.full = false;
            show.details = [];
            subService.getMovieDetails(show);
        } else if (show.tvshows && show.type === "show") {
            show.tvshows = [];
            subService.getTvShowDetails(show);
        }
    }

    $scope.expandShow = function (show) {
        show.expanded = !show.expanded;

        if (!show.letterOptions) { //letterOptions & letter
            subService.getSectionLetterList(show);
        }

        if (!show.details && show.type === "movie") {
            show.details = [];
            subService.getMovieDetails(show);
        } else if (!show.details && show.type === "show") {
            subService.getTvShowDetails(show);
        }
    };

    $scope.expandTvShow = function (show, tvshow) {
        show.selectedTvShow = tvshow;
        if (!tvshow.seasons) {
            subService.getTvShowSeasons(tvshow);
        }
    };
    $scope.expandTvShowSeason = function (show, season) {
        show.selectedSeason = season;
        if (!season.details) {
            subService.getTvShowSeasonDetails(season);
        }
    };

    $scope.loadmore = function (show) {
        if (show.details && show.type === "movie") {
            subService.getMovieDetails(show);
        }
    }

    $scope.getAllSubtitlesChecked = function (detail) {
        for (var i = 0; i < detail.subtitles.length; i++) {
            if (detail.subtitles[i].location !== "Embedded" && !detail.subtitles[i].checked) return false;
        }
        return true;
    };

    $scope.toggleAllSubtitles = function (detail) {
        var allChecked = $scope.getAllSubtitlesChecked(detail);
        for (var i = 0; i < detail.subtitles.length; i++) {
            if (detail.subtitles[i].location === "Embedded") continue;
            detail.subtitles[i].checked = !allChecked;
        }
        detail.subAllChecked = !allChecked;
    };

    $scope.isCodexView = function (subtitle) {
        return subtitle.codec === "srt"
            || subtitle.codec === "subrip"
            || subtitle.codec === "smi"
            || subtitle.codec === "ssa"
            || subtitle.codec === "vtt"
            || subtitle.codec === "ass";
    }

    $scope.getParts = function(detail) {
        subService.getParts(detail);
    }

    $scope.upload = function (detail) {
        subService.uploadSub(detail, "file");
    };

    $scope.download = function (subtitle, $event) {
        $event.stopPropagation();
        subService.downloadSubtitle(subtitle.key);
    }

    $scope.view = function (subtitle, $event) {
        $event.stopPropagation();
        subService.viewSubtitle(subtitle.key);
    }

    $scope.delete = function (detail, subtitle) {
        subService.deleteSubtitle(detail, subtitle);
    };
    $scope.deleteSelected = function (detail) {
        for (var i = 0; i < detail.subtitles.length; i++) {
            if (detail.subtitles[i].checked) $scope.delete(detail, detail.subtitles[i]);
        }
    };

    $scope.searchKeyword = function () {
        if ($scope.subModel.searchKeywordValue && $scope.subModel.searchKeywordValue === $scope.subModel.searchKeywordValueLast) {
            if ($scope.subModel.searchFoundLines.length > 0) $scope.$broadcast("sub_search_nextLine");
        }
        else {
            $scope.$broadcast("sub_search_findKeywords");
        }
    }
    $scope.searchClear = function () {
        $scope.subModel.searchKeywordValue = "";
        $scope.$broadcast("sub_search_findKeywords");
    }
    $scope.searchPrevious = function () {
        if ($scope.subModel.searchFoundLines.length > 0) $scope.$broadcast("sub_search_previousLine");
    }
    $scope.searchJumpToTop = function () {
        $scope.$broadcast("sub_search_jumpToTop");
    }

    $scope.$on("$destroy", function () {
        subModel.selectedSub = null;
    });

    $scope.init();
}]);<|endoftext|>


<commit_before>let smileys = [];
let t = 0;

function setup(){
    createCanvas( windowWidth, windowHeight );

    // create a bunch of random, sine movement smileys
    for (var i = 0; i < 20; i++) {

        // add new smiley objs to the array
        smileys.push(
            {
                period: { x: random(60, 240), y: random(60, 240) },
                maxSize: random(4),
                maxDist: {
                    x: random(width/2),
                    y: random(height/2)
                },
                pos: {
                    x: random(width),
                    y: random(height)
                }
            } // <- end smiley obj
        ); // end array push
    } // end for loop
}

function draw() {
    // set the background to 'white'
    background(0, 0, 0, 10 );

    // determine the number of smileys to draw in the array
    // based on mouse position
    // i.e. left=0 - right=all
    let numToDraw = map( mouseX, 0, width, 0, smileys.length );
    for ( let i = 0; i < numToDraw; i++ ) {
        // draw the smileys
        drawSmiley( smileys[i], t );
    }

    // increment time for the sine wave functions
    t++;

}

/* Draw the Smiley */
function drawSmiley( smiley, time ) {
    // determine the value of individual sine wave functions
    let x = sinePos( smiley.period.x, time );
    let y = sinePos( smiley.period.y, time );

    let pos_x = x * smiley.maxDist.x + smiley.pos.x;
    let pos_y = y * smiley.maxDist.y + smiley.pos.y;

    // draw a smiley based on object data
    smileyFace(
        pos_x,
        pos_y,
        x * smiley.maxSize,
        y * smiley.maxSize
    );
}

/* SMILEY FACE FUNCTION */
function smileyFace( pos_x, pos_y, scale_x, scale_y ) {
    push(); // <- Begin sandbox

    // 1. scale and position smiley face
    translate( pos_x, pos_y );
    scale( scale_x, scale_y );

    // 2. draw smiley face
    stroke( 0 );
    fill('rgba(234, 255, 61, 1.0)');
    ellipse( 0, 0, 100 );
    noStroke();
    fill( 40, 255 );
    arc( 0, 15, 75, 50, 0, PI );
    ellipse( -20, -15, 20 );
    ellipse( 20, -15, 20 );

    pop(); // <- End sandbox
}

/* sine function */
function sinePos( timeScale, time ) {
    let val = sin( TWO_PI * time/timeScale );
    return val;
}
<commit_msg>small update<commit_after>let smileys = [];
let t = 0;

function setup(){
    createCanvas( windowWidth, 800 );

    // create a bunch of random, sine movement smileys
    for (var i = 0; i < 20; i++) {

        // add new smiley objs to the array
        smileys.push(
            {
                period: { x: random(60, 240), y: random(60, 240) },
                maxSize: random(4),
                maxDist: {
                    x: random(width/2),
                    y: random(height/2)
                },
                pos: {
                    x: random(width),
                    y: random(height)
                }
            } // <- end smiley obj
        ); // end array push
    } // end for loop
}

function draw() {
    // set the background to 'white'
    background(0, 0, 0, 10 );

    // determine the number of smileys to draw in the array
    // based on mouse position
    // i.e. left=0 - right=all
    let numToDraw = map( mouseX, 0, width, 0, smileys.length );
    for ( let i = 0; i < numToDraw; i++ ) {
        // draw the smileys
        drawSmiley( smileys[i], t );
    }

    // increment time for the sine wave functions
    t++;

}

/* Draw the Smiley */
function drawSmiley( smiley, time ) {
    // determine the value of individual sine wave functions
    let x = sinePos( smiley.period.x, time );
    let y = sinePos( smiley.period.y, time );

    let pos_x = x * smiley.maxDist.x + smiley.pos.x;
    let pos_y = y * smiley.maxDist.y + smiley.pos.y;

    // draw a smiley based on object data
    smileyFace(
        pos_x,
        pos_y,
        x * smiley.maxSize,
        y * smiley.maxSize
    );
}

/* SMILEY FACE FUNCTION */
function smileyFace( pos_x, pos_y, scale_x, scale_y ) {
    push(); // <- Begin sandbox

    // 1. scale and position smiley face
    translate( pos_x, pos_y );
    scale( scale_x, scale_y );

    // 2. draw smiley face
    stroke( 0 );
    fill('rgba(234, 255, 61, 1.0)');
    ellipse( 0, 0, 100 );
    noStroke();
    fill( 40, 255 );
    arc( 0, 15, 75, 50, 0, PI );
    ellipse( -20, -15, 20 );
    ellipse( 20, -15, 20 );

    pop(); // <- End sandbox
}

/* sine function */
function sinePos( timeScale, time ) {
    let val = sin( TWO_PI * time/timeScale );
    return val;
}
<|endoftext|>


<commit_before>import bs from './bootstrap.cssmodule';
import fecha from 'fecha';
import includes from 'lodash.includes';
import path from './path.js';
import range from 'lodash.range';
import { h, Component } from 'preact';

import './DateMonth.css';

const Label = ({ selected, label, onClick }) => (

    {label}

);

const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const MMM_YYYY_PATTERN = '^\\s*([Jj][Aa][Nn]|[Ff][Ee][Bb]|[Mm][Aa][Rr]|[Aa][Pp][Rr]|[Mm][Aa][Yy]|[Jj][Uu][Nn]|[Jj][Uu][Ll]|[Aa][Uu][Gg]|[Ss][Ee][Pp]|[Oo][Cc][Tt]|[Nn][Oo][Vv]|[Dd][Ee][Cc])\\s+\\d\\d\\d\\d\\s*$';

export default class DateMonth extends Component {
  constructor(props) {
    super(props);

    const date = props.value;
    let month = undefined;
    let year = (new Date()).getFullYear();

    if (!date) {
      const initialDate = new Date();
      month = fecha.format(initialDate, 'MMM');
      year = initialDate.getFullYear();
    } else {
      const initialDate = fecha.parse(date, 'MMM YYYY');
      if (initialDate) {
        month = fecha.format(initialDate, 'MMM');
        year = initialDate.getFullYear();
      }
    }

    this.state = {
      open: false,
      month,
      year
    };
  }

  setMonth(month) {
    this.setState({ month });
  }

  setYear(year) {
    this.setState({ year });
  }

  componentDidMount() {
    this.listener = event => {
      const container = this.base;
      if (container && !includes(path(event), container)) {
        this.setState({ open: false });
      }
      return true;
    };
    this.escListener = event => {
      if (event.keyCode === 27) { // ESC
        this.setState({ open: false });
      }
      return true;
    };
    document.addEventListener('click', this.listener, { passive: true });
    document.addEventListener('keydown', this.escListener, { passive: true });
  }

  componentWillUnmount() {
    document.removeEventListener('click', this.listener);
    document.removeEventListener('keydown', this.escListener);
  }

  render(props, state) {
    const now = new Date();
    const end = state.year + (now.getFullYear() - state.year) % 10 + 1;
    const start = end - 10;
    const YEARS = range(start, end);
    const can_advance_year = now.getFullYear() - state.year > 9;

    const open = () => this.setState({
      open: true,
      undo: { month: state.month, year: state.year }
    });
    const cancel = () => this.setState({
      open: false,
      month: state.undo.month,
      year: state.undo.year
    });
    const close = () => this.setState({ open: false });
    const toggle = () => this.setState({
      open: !state.open,
      undo: { month: state.month, year: state.year }
    });
    const prev = () => this.setState({ year: state.year - 10 });
    const next = () => {
      if (can_advance_year) {
        const current_year = (new Date()).getFullYear();
        const year = Math.min(state.year + 10, current_year);
        this.setState({ year });
      }
    };
    const change = event => {
      if (this._input.checkValidity()) {
        const text = event.target.value.trim();
        const date = fecha.parse(text, 'MMM YYYY');
        if (date) {
          this.setState({
            month: MONTHS[date.getMonth()],
            year: date.getFullYear()
          });
        }
      }
    };
    const tabListener = event => {
      if (event.keyCode === 9) { // TAB
        this.setState({ open: false });
      }
      return true;
    };

    const value = state.month && state.year ? `${state.month} ${state.year}` : props.value;

    return (

            <input name={props.name}
                   ref={component => this._input = component}
                   required={props.required}
                   value={value}
                   type="text"
                   className={bs.formControl}
                   onclick={open}
                   onfocus={open}
                   oninput={change}
                   onkeydown={tabListener}
                   pattern={MMM_YYYY_PATTERN} />
            <span className={`${bs.inputGroupAddon} toggle`} onClick={toggle}>

        {state.open ?

              <div className={`month ${bs.colXs6}`}>

                  {MONTHS.map(month =>  this.setMonth(month)} />)}

              <div className={`year ${bs.colXs6}`}>
                <header className={`${bs.btnGroup} ${bs.btnGroupXs} ${bs.btnGroupJustified}`}>
                  <a id="prev" onclick={prev} className={`${bs.btn} ${bs.btnDefault}`}>

                  <a id="next" onclick={next} disabled={!can_advance_year} className={`${bs.btn} ${bs.btnDefault}`}>

                  {YEARS.map(year =>  this.setYear(year)} />)}

              <a id="save" className={`${bs.btn} ${bs.btnSm} ${bs.btnDefault}`} onclick={close}>OK
              <a id="cancel" className={`${bs.btn} ${bs.btnSm} ${bs.btnDefault}`} onclick={cancel}>Cancel

 : null}

);
  }
}
<commit_msg>gt - Correct onclick to onClick case<commit_after>import bs from './bootstrap.cssmodule';
import fecha from 'fecha';
import includes from 'lodash.includes';
import path from './path.js';
import range from 'lodash.range';
import { h, Component } from 'preact';

import './DateMonth.css';

const Label = ({ selected, label, onClick }) => (

    {label}

);

const MONTHS = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const MMM_YYYY_PATTERN = '^\\s*([Jj][Aa][Nn]|[Ff][Ee][Bb]|[Mm][Aa][Rr]|[Aa][Pp][Rr]|[Mm][Aa][Yy]|[Jj][Uu][Nn]|[Jj][Uu][Ll]|[Aa][Uu][Gg]|[Ss][Ee][Pp]|[Oo][Cc][Tt]|[Nn][Oo][Vv]|[Dd][Ee][Cc])\\s+\\d\\d\\d\\d\\s*$';

export default class DateMonth extends Component {
  constructor(props) {
    super(props);

    const date = props.value;
    let month = undefined;
    let year = (new Date()).getFullYear();

    if (!date) {
      const initialDate = new Date();
      month = fecha.format(initialDate, 'MMM');
      year = initialDate.getFullYear();
    } else {
      const initialDate = fecha.parse(date, 'MMM YYYY');
      if (initialDate) {
        month = fecha.format(initialDate, 'MMM');
        year = initialDate.getFullYear();
      }
    }

    this.state = {
      open: false,
      month,
      year
    };
  }

  setMonth(month) {
    this.setState({ month });
  }

  setYear(year) {
    this.setState({ year });
  }

  componentDidMount() {
    this.listener = event => {
      const container = this.base;
      if (container && !includes(path(event), container)) {
        this.setState({ open: false });
      }
      return true;
    };
    this.escListener = event => {
      if (event.keyCode === 27) { // ESC
        this.setState({ open: false });
      }
      return true;
    };
    document.addEventListener('click', this.listener, { passive: true });
    document.addEventListener('keydown', this.escListener, { passive: true });
  }

  componentWillUnmount() {
    document.removeEventListener('click', this.listener);
    document.removeEventListener('keydown', this.escListener);
  }

  render(props, state) {
    const now = new Date();
    const end = state.year + (now.getFullYear() - state.year) % 10 + 1;
    const start = end - 10;
    const YEARS = range(start, end);
    const can_advance_year = now.getFullYear() - state.year > 9;

    const open = () => this.setState({
      open: true,
      undo: { month: state.month, year: state.year }
    });
    const cancel = () => this.setState({
      open: false,
      month: state.undo.month,
      year: state.undo.year
    });
    const close = () => this.setState({ open: false });
    const toggle = () => this.setState({
      open: !state.open,
      undo: { month: state.month, year: state.year }
    });
    const prev = () => this.setState({ year: state.year - 10 });
    const next = () => {
      if (can_advance_year) {
        const current_year = (new Date()).getFullYear();
        const year = Math.min(state.year + 10, current_year);
        this.setState({ year });
      }
    };
    const change = event => {
      if (this._input.checkValidity()) {
        const text = event.target.value.trim();
        const date = fecha.parse(text, 'MMM YYYY');
        if (date) {
          this.setState({
            month: MONTHS[date.getMonth()],
            year: date.getFullYear()
          });
        }
      }
    };
    const tabListener = event => {
      if (event.keyCode === 9) { // TAB
        this.setState({ open: false });
      }
      return true;
    };

    const value = state.month && state.year ? `${state.month} ${state.year}` : props.value;

    return (

            <input
              className={bs.formControl}
              name={props.name}
              onClick={open}
              onFocus={open}
              onInput={change}
              onKeyDown={tabListener}
              pattern={MMM_YYYY_PATTERN}
              ref={component => this._input = component}
              required={props.required}
              type="text"
              value={value}
            />
            <span className={`${bs.inputGroupAddon} toggle`} onClick={toggle}>

        {state.open ?

              <div className={`month ${bs.colXs6}`}>

                  {MONTHS.map(month =>  this.setMonth(month)} />)}

              <div className={`year ${bs.colXs6}`}>
                <header className={`${bs.btnGroup} ${bs.btnGroupXs} ${bs.btnGroupJustified}`}>
                  <a id="prev" onClick={prev} className={`${bs.btn} ${bs.btnDefault}`}>

                  <a id="next" onClick={next} disabled={!can_advance_year} className={`${bs.btn} ${bs.btnDefault}`}>

                  {YEARS.map(year =>  this.setYear(year)} />)}

              <a id="save" className={`${bs.btn} ${bs.btnSm} ${bs.btnDefault}`} onClick={close}>OK
              <a id="cancel" className={`${bs.btn} ${bs.btnSm} ${bs.btnDefault}`} onClick={cancel}>Cancel

 : null}

);
  }
}
<|endoftext|>


<commit_before>var DateRange = (function() {
  return function(clock, dateFns) {
    var dateRange = {
        startDate: void 0,
        endDate: void 0
      },
      month = Month(dateFns),
      week = Week(dateFns),
      year = Year(dateFns),
      period = week,
      currentDate = clock.currentDate();

    period.updateRange(currentDate);

    return {
      startDate: function() {
        return dateRange.startDate;
      },
      endDate: function() {
        return dateRange.endDate;
      },
      useMonth: function() {
        updateRangeUsingNewPeriod(month);
      },
      useYear: function() {
        updateRangeUsingNewPeriod(year);
      },
      useWeek: function() {
        updateRangeUsingNewPeriod(week);
      },
      next: next,
      previous: previous,
      current: current
    };

    function current() {
      currentDate = clock.currentDate();
      period.updateRange(currentDate);
    }

    function previous() {
      currentDate = period.previousDate(currentDate);
      period.updateRange(currentDate);
    }

    function next() {
      currentDate = period.nextDate(currentDate);
      period.updateRange(currentDate);
    }

    function updateRangeUsingNewPeriod(newPeriod) {
      period = newPeriod;
      period.updateRange(currentDate);
    }

    function Month(dateFns) {
      return {
        updateRange: function(currentDate) {
          dateRange = dateFns.monthPeriodContaining(currentDate);
        },

        nextDate: function(currentDate) {
          return dateFns.oneMonthAheadOf(currentDate);
        },

        previousDate: function(currentDate) {
          return dateFns.oneMonthBackFrom(currentDate);
        }
      };
    }

    function Week(dateFns) {
      return {
        updateRange: function(currentDate) {
          dateRange = dateFns.weekPeriodContaining(currentDate);
        },

        nextDate: function(currentDate) {
          return dateFns.oneWeekAheadOf(currentDate);
        },

        previousDate: function(currentDate) {
          return dateFns.oneWeekBackFrom(currentDate);
        }
      };
    }

    function Year(dateFns) {
      return {
        updateRange: function(currentDate) {
          dateRange = dateFns.yearPeriodContaining(currentDate);
        },

        nextDate: function(currentDate) {
          return dateFns.oneYearAheadOf(currentDate);
        },

        previousDate: function(currentDate) {
          return dateFns.oneYearBackFrom(currentDate);
        }
      };
    }
  };
})();<commit_msg>Renamed method<commit_after>var DateRange = (function() {
  return function(clock, dateFns) {
    var dateRange = {
        startDate: void 0,
        endDate: void 0
      },
      month = Month(dateFns),
      week = Week(dateFns),
      year = Year(dateFns),
      period = week,
      currentDate = clock.currentDate();

    period.rangeFor(currentDate);

    return {
      startDate: function() {
        return dateRange.startDate;
      },
      endDate: function() {
        return dateRange.endDate;
      },
      useMonth: function() {
        updateRangeUsingNewPeriod(month);
      },
      useYear: function() {
        updateRangeUsingNewPeriod(year);
      },
      useWeek: function() {
        updateRangeUsingNewPeriod(week);
      },
      next: next,
      previous: previous,
      current: current
    };

    function current() {
      currentDate = clock.currentDate();
      period.rangeFor(currentDate);
    }

    function previous() {
      currentDate = period.previousDate(currentDate);
      period.rangeFor(currentDate);
    }

    function next() {
      currentDate = period.nextDate(currentDate);
      period.rangeFor(currentDate);
    }

    function updateRangeUsingNewPeriod(newPeriod) {
      period = newPeriod;
      period.rangeFor(currentDate);
    }

    function Month(dateFns) {
      return {
        rangeFor: function(currentDate) {
          dateRange = dateFns.monthPeriodContaining(currentDate);
        },

        nextDate: function(currentDate) {
          return dateFns.oneMonthAheadOf(currentDate);
        },

        previousDate: function(currentDate) {
          return dateFns.oneMonthBackFrom(currentDate);
        }
      };
    }

    function Week(dateFns) {
      return {
        rangeFor: function(currentDate) {
          dateRange = dateFns.weekPeriodContaining(currentDate);
        },

        nextDate: function(currentDate) {
          return dateFns.oneWeekAheadOf(currentDate);
        },

        previousDate: function(currentDate) {
          return dateFns.oneWeekBackFrom(currentDate);
        }
      };
    }

    function Year(dateFns) {
      return {
        rangeFor: function(currentDate) {
          dateRange = dateFns.yearPeriodContaining(currentDate);
        },

        nextDate: function(currentDate) {
          return dateFns.oneYearAheadOf(currentDate);
        },

        previousDate: function(currentDate) {
          return dateFns.oneYearBackFrom(currentDate);
        }
      };
    }
  };
})();<|endoftext|>


<commit_before>import React from 'react';
import moment from 'moment';
import { weeks } from './utils';

const tableStyle = {display: 'table'};
const captionStyle = {display: 'table-caption', textAlign: 'center'};
const rowStyle = {display: 'table-row'};
const cellStyle = {display: 'table-cell', textAlign: 'center'};

const DayPicker = React.createClass({

  propTypes: {

    initialMonth: React.PropTypes.object, // default is current month
    modifiers: React.PropTypes.object,

    onDayTouchTap: React.PropTypes.func, // requires react-tap-event-plugin enabled
    onDayMouseEnter: React.PropTypes.func,
    onDayMouseLeave: React.PropTypes.func
  },

  getDefaultProps() {
    return { initialMonth: moment() };
  },

  componentWillReceiveProps(nextProps) {
    this.setState({month: nextProps.initialMonth});
  },

  componentDidUpdate(prevProps, prevState) {
    if(this.state.focus)
      this.refs['d'+this.state.focus].getDOMNode().focus();
  },

  getInitialState() {
    return { month: this.props.initialMonth.clone(), focus: null };
  },

  handleDayTouchTap(day, modifiers, e) {
    this.props.onDayTouchTap && this.props.onDayTouchTap(day, modifiers, e);
  },

  handleDayKeyUp(day, modifiers, e) {
    if (e.keyCode === 13 || e.keyCode === 32)
      this.props.onDayTouchTap && this.props.onDayTouchTap(day, modifiers, e);
  },

  handleDayMouseEnter(day, modifiers, e) {
    this.props.onDayMouseEnter && this.props.onDayMouseEnter(day, modifiers, e);
  },

  handleDayMouseLeave(day, modifiers, e) {
    this.props.onDayMouseLeave && this.props.onDayMouseLeave(day, modifiers, e);
  },

  handleDayFocus(day, modifiers, e){
    this.setState({focus: day.dayOfYear()}, () => {
      this.props.onDayFocus && this.props.onDayFocus(e);
    });
  },

  handleDayBlur(day, modifiers, e){
    this.setState({focus: null});
  },

  handleNextTouchTap(e) {
    const nextMonth = this.state.month.add(1, 'month');
    this.setState({month: nextMonth});
  },

  handlePrevTouchTap(e) {
    const prevMonth = this.state.month.subtract(1, 'month');
    this.setState({month: prevMonth});
  },

  getDayModifiers(day) {
    if (!this.props.modifiers) return '';
    const modifiers = this.props.modifiers;
    var dayModifiers = [];
    for (let modifier in modifiers) {
      var func = modifiers[modifier];
      if (func(day)) dayModifiers.push(modifier);
    }
    return dayModifiers;
  },

  render() {
    return (

        { this.renderToolbar() }
        { this.renderWeekHeader() }
        { this.renderWeeks() }

    );
  },

  renderToolbar() {
    return (

        { this.renderToolbarButton('left') }
        { this.state.month.format('MMMM YYYY') }
        { this.renderToolbarButton('right') }

    );
  },

  renderToolbarButton(position) {
    const className = `daypicker__toolbar-button daypicker__toolbar-button--${position}`;
    const handler = position === 'left' ?  this.handlePrevTouchTap :  this.handleNextTouchTap;

    return <button ref={"btn-"+position} className={className} style={{float: position}} onTouchTap={handler} />;
  },

  renderWeeks() {
    return weeks(this.state.month).map((week, i) => {
      return (

          { this.renderDays(week) }

      );
    });
  },

  renderWeekHeader() {
    var header = [];
    for (let i = 0; i < 7; i++) {
      header.push(

          { moment().weekday(i).format('dd') }

      )
    }
    return
{ header }
;
  },

  renderDays(week) {
    const firstDay = week[0];
    const lastDay = week[week.length-1];

    var days = week.map(day => this.renderDay(day));

    // days belonging to the previous month
    for (let i = 0; i < firstDay.weekday(); i++) {
      var prevDay = firstDay.clone().subtract(i+1, 'day');
      days.unshift(this.renderDay(prevDay, true));
    }

    // days belonging to the next month
    for (let j = lastDay.weekday() + 1, count = 1; j < 7; j++, count++) {
      var nextDay = lastDay.clone().add(count, 'day');
      days.push(this.renderDay(nextDay, true));
    }

    return days;
  },

  renderDay(day, otherMonth) {
    const modifiers = this.getDayModifiers(day);

    var className = 'daypicker__day';
    if (otherMonth) className += ' daypicker__day--other-month';
    className += modifiers.map((mod) => { return ' daypicker__day--' + mod }).join('');

    return (
      <div tabIndex="0"
        ref={"d" + day.dayOfYear()}
        key={"d" + day.dayOfYear()}
        className={className}
        style={cellStyle}
        onMouseEnter={this.handleDayMouseEnter.bind(this, day, modifiers)}
        onMouseLeave={this.handleDayMouseLeave.bind(this, day, modifiers)}
        onKeyUp={this.handleDayKeyUp.bind(this, day, modifiers)}
        onTouchTap={this.handleDayTouchTap.bind(this, day, modifiers)}
        onBlur={this.handleDayBlur.bind(this, day, modifiers)}
        onFocus={this.handleDayFocus.bind(this, day, modifiers)}>
        { day.format('D') }

    );
  }

});

export default DayPicker;<commit_msg>Fix an issue when modifiers are not defined<commit_after>import React from 'react';
import moment from 'moment';
import { weeks } from './utils';

const tableStyle = {display: 'table'};
const captionStyle = {display: 'table-caption', textAlign: 'center'};
const rowStyle = {display: 'table-row'};
const cellStyle = {display: 'table-cell', textAlign: 'center'};

const DayPicker = React.createClass({

  propTypes: {

    initialMonth: React.PropTypes.object, // default is current month
    modifiers: React.PropTypes.object,

    onDayTouchTap: React.PropTypes.func, // requires react-tap-event-plugin enabled
    onDayMouseEnter: React.PropTypes.func,
    onDayMouseLeave: React.PropTypes.func
  },

  getDefaultProps() {
    return { initialMonth: moment() };
  },

  componentWillReceiveProps(nextProps) {
    this.setState({month: nextProps.initialMonth});
  },

  componentDidUpdate(prevProps, prevState) {
    if(this.state.focus)
      this.refs['d'+this.state.focus].getDOMNode().focus();
  },

  getInitialState() {
    return { month: this.props.initialMonth.clone(), focus: null };
  },

  handleDayTouchTap(day, modifiers, e) {
    this.props.onDayTouchTap && this.props.onDayTouchTap(day, modifiers, e);
  },

  handleDayKeyUp(day, modifiers, e) {
    if (e.keyCode === 13 || e.keyCode === 32)
      this.props.onDayTouchTap && this.props.onDayTouchTap(day, modifiers, e);
  },

  handleDayMouseEnter(day, modifiers, e) {
    this.props.onDayMouseEnter && this.props.onDayMouseEnter(day, modifiers, e);
  },

  handleDayMouseLeave(day, modifiers, e) {
    this.props.onDayMouseLeave && this.props.onDayMouseLeave(day, modifiers, e);
  },

  handleDayFocus(day, modifiers, e){
    this.setState({focus: day.dayOfYear()}, () => {
      this.props.onDayFocus && this.props.onDayFocus(e);
    });
  },

  handleDayBlur(day, modifiers, e){
    this.setState({focus: null});
  },

  handleNextTouchTap(e) {
    const nextMonth = this.state.month.add(1, 'month');
    this.setState({month: nextMonth});
  },

  handlePrevTouchTap(e) {
    const prevMonth = this.state.month.subtract(1, 'month');
    this.setState({month: prevMonth});
  },

  getDayModifiers(day) {
    var dayModifiers = [];
    if (!this.props.modifiers) return dayModifiers;
    const modifiers = this.props.modifiers;
    for (let modifier in modifiers) {
      var func = modifiers[modifier];
      if (func(day)) dayModifiers.push(modifier);
    }
    return dayModifiers;
  },

  render() {
    return (

        { this.renderToolbar() }
        { this.renderWeekHeader() }
        { this.renderWeeks() }

    );
  },

  renderToolbar() {
    return (

        { this.renderToolbarButton('left') }
        { this.state.month.format('MMMM YYYY') }
        { this.renderToolbarButton('right') }

    );
  },

  renderToolbarButton(position) {
    const className = `daypicker__toolbar-button daypicker__toolbar-button--${position}`;
    const handler = position === 'left' ?  this.handlePrevTouchTap :  this.handleNextTouchTap;

    return <button ref={"btn-"+position} className={className} style={{float: position}} onTouchTap={handler} />;
  },

  renderWeeks() {
    return weeks(this.state.month).map((week, i) => {
      return (

          { this.renderDays(week) }

      );
    });
  },

  renderWeekHeader() {
    var header = [];
    for (let i = 0; i < 7; i++) {
      header.push(

          { moment().weekday(i).format('dd') }

      )
    }
    return
{ header }
;
  },

  renderDays(week) {
    const firstDay = week[0];
    const lastDay = week[week.length-1];

    var days = week.map(day => this.renderDay(day));

    // days belonging to the previous month
    for (let i = 0; i < firstDay.weekday(); i++) {
      var prevDay = firstDay.clone().subtract(i+1, 'day');
      days.unshift(this.renderDay(prevDay, true));
    }

    // days belonging to the next month
    for (let j = lastDay.weekday() + 1, count = 1; j < 7; j++, count++) {
      var nextDay = lastDay.clone().add(count, 'day');
      days.push(this.renderDay(nextDay, true));
    }

    return days;
  },

  renderDay(day, otherMonth) {
    const modifiers = this.getDayModifiers(day);

    var className = 'daypicker__day';
    if (otherMonth) className += ' daypicker__day--other-month';
    className += modifiers.map((mod) => { return ' daypicker__day--' + mod }).join('');

    return (
      <div tabIndex="0"
        ref={"d" + day.dayOfYear()}
        key={"d" + day.dayOfYear()}
        className={className}
        style={cellStyle}
        onMouseEnter={this.handleDayMouseEnter.bind(this, day, modifiers)}
        onMouseLeave={this.handleDayMouseLeave.bind(this, day, modifiers)}
        onKeyUp={this.handleDayKeyUp.bind(this, day, modifiers)}
        onTouchTap={this.handleDayTouchTap.bind(this, day, modifiers)}
        onBlur={this.handleDayBlur.bind(this, day, modifiers)}
        onFocus={this.handleDayFocus.bind(this, day, modifiers)}>
        { day.format('D') }

    );
  }

});

export default DayPicker;<|endoftext|>


<commit_before>/*
 * getMediaInfo functions
 *
 * Allow to retrieve meta data of servers supporting icecast
 * Also find out what type of media is being streamed (audio, video, etc)
 */

var EventEmitter  = require('events').EventEmitter;
var util          = require('util');
var icy           = require('icy');
var devnull       = require('dev-null');
//if (process.env.NODE_ENV !== 'production'){
//    require('longjohn');
//}

var DISCOVER_ICY_METADATA = true;

var Connection = function (url2play, org_url2play, streamType, callback) {
    EventEmitter.call(this);
    this._url2play = url2play;
    this._callback = callback;
    this._media = {
        // Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
        contentId: url2play,
        streamType: streamType, // LIVE or BUFFERED

        // Title and cover displayed while buffering
        metadata: {
            type: 0,
            metadataType: 0,
            title: org_url2play
        }
    };

    //See if we have to run in dummy mode
    if (!DISCOVER_ICY_METADATA) {
        callback(this._media);
        return;
    }

    this._pipeOn = false;

    try {
        this._requestObject = icy.get(url2play, this._connected.bind(this));
        this._requestObject.on('error', function (e) {
            console.log("MediaInformation - ICY connection error for " + this._url2play + ": " + e);
        });
    } catch (e) {
        console.log("MediaInformation - Cannot connect to " + this._url2play + ": " + e);
    }
};

util.inherits(Connection, EventEmitter);

Connection.prototype.getMedia = function () {
    return this._media;
};

Connection.prototype.close = function () {
    if (this._requestObject) {
        this._requestObject.abort();
    }
};

Connection.prototype._connected = function (res) {
    console.log("MediaInformation - Connected to " + this._url2play);
    /*
     * Example from http://edge.live.mp3.mdn.newmedia.nacamar.net/ps-dieneue_rock/livestream_hi.mp3
     *
     * {'accept-ranges': 'none',
     *  'content-type': 'audio/mpeg',
     *  'icy-br': '128',
     *  'ice-audio-info': 'ice-samplerate=44100;ice-bitrate=128;ice-channels=2',
     *  'icy-description': 'BESTER ROCK UND POP',
     *  'icy-genre': 'Rock',
     *  'icy-name': 'DIE NEUE 107.7',
     *  'icy-pub': '1',
     *  'icy-url': 'http://www.dieneue1077.de',
     *  server: 'Icecast 2.3.3-kh11',
     *  'cache-control': 'no-cache, no-store',
     *  pragma: 'no-cache',
     *  'access-control-allow-origin': '*',
     *  'access-control-allow-headers': 'Origin, Accept, X-Requested-With, Content-Type',
     *  'access-control-allow-methods': 'GET, OPTIONS, HEAD',
     *  connection: 'close',
     *  expires: 'Mon, 26 Jul 1997 05:00:00 GMT',
     *  'icy-metaint': '16000' }
     */
    // log the HTTP response headers
    console.log(res.headers);

    if (res.headers &&
        res.headers["content-type"] &&
        ((res.headers["content-type"].indexOf("audio") >= 0) ||
         (res.headers["content-type"].indexOf("video") >= 0)))
        this._media.contentType = res.headers["content-type"];
    //console.log(this._media);

    if ("icy-name" in res.headers) {
        //As backup call the callback if we do not get
        //first metadata in less than 1 second
        this._timeoutHandler = setTimeout(function () {
            this._callback(this._media);
        }, 1000);

        // log any "metadata" events that happen
        res.on('metadata', this._gotMetadata.bind(this, res));
    } else {
        //Not ICY -> call callback already
        this._callback(this._media);
    }

};

Connection.prototype._gotMetadata = function (res, metadata) {
    /*
     * { StreamTitle: 'BILLY IDOL - WHITE WEDDING',
     StreamUrl: '&artist=BILLY%20IDOL&title=WHITE%20WEDDING&album=&duration=&songtype=S&overlay=&buycd=&website=&picture' }
     */
    var parsed = icy.parse(metadata);
    console.log(parsed);

    //Get title
    this._media.metadata.title = parsed.StreamTitle;

    //If we got media info then call callback already
    if (this._timeoutHandler) {
        clearTimeout(this._timeoutHandler);
        this._timeoutHandler = undefined;
        this._callback(this._media);
    }

    //Notify that media has been updated
    this.emit("media", this._media);

    if (!this._pipeOn) {
        //We need to keep reading in order to receive additional metadata
        //We do it here to avoid reading data for sources that do not send
        //any metadata
        res.pipe(devnull());
        this._pipeOn = true;
    }
};

var activeConnections = {};

function getMediaInfoListerner(callerId, url2play, org_url2play, streamType, callback) {

    if (url2play in activeConnections &&
        callerId in activeConnections[url2play].callerIDs) {

        //Call callback
        callback(activeConnections[url2play].connection.getMedia());

        //This callerID is already listing the URL
        return activeConnections[url2play].connection;
    }

    //Close in case this caller was already listing -> only one connection/callerID
    closeMediaInfoListerner(callerId);

    //If this is the first listener for this URL then create object
    if (!(url2play in activeConnections)) {
        var connection = new Connection(url2play, org_url2play, streamType, callback);
        activeConnections[url2play] = {
                callerIDs: {},
                connection: connection
        };
    }

    //Remember callerId
    activeConnections[url2play].callerIDs[callerId] = true;

    //Return connection
    return activeConnections[url2play].connection;
}

function closeMediaInfoListerner(callerId) {
    for (var url2play in activeConnections) {

        //Set this callerId as inactive
        activeConnections[url2play].callerIDs[callerId] = false;

        //Any active listeners for this URL?
        var anyListenerActive = false;
        for (var i in activeConnections[url2play].callerIDs) {
            anyListenerActive |= activeConnections[url2play].callerIDs[i];
        }

        if (!anyListenerActive) {
            //None is listening to this URL -> destroy connection
            activeConnections[url2play].connection.close();
            activeConnections[url2play].callerIDs = undefined;
            console.log("Disconnect " + url2play);
            console.log("Last listener was " + callerId);
            delete activeConnections[url2play];
        }
    }
}

module.exports.getListener   = getMediaInfoListerner;
module.exports.closeListener = closeMediaInfoListerner;
<commit_msg>Replace this with "that" to avoid errors in callbacks.<commit_after>/*
 * getMediaInfo functions
 *
 * Allow to retrieve meta data of servers supporting icecast
 * Also find out what type of media is being streamed (audio, video, etc)
 */

var EventEmitter  = require('events').EventEmitter;
var util          = require('util');
var icy           = require('icy');
var devnull       = require('dev-null');
//if (process.env.NODE_ENV !== 'production'){
//    require('longjohn');
//}

var DISCOVER_ICY_METADATA = true;

var Connection = function (url2play, org_url2play, streamType, callback) {
    that = this;
    EventEmitter.call(that);
    that._url2play = url2play;
    that._callback = callback;
    that._media = {
        // Here you can plug an URL to any mp4, webm, mp3 or jpg file with the proper contentType.
        contentId: url2play,
        streamType: streamType, // LIVE or BUFFERED

        // Title and cover displayed while buffering
        metadata: {
            type: 0,
            metadataType: 0,
            title: org_url2play
        }
    };

    //See if we have to run in dummy mode
    if (!DISCOVER_ICY_METADATA) {
        callback(that._media);
        return;
    }

    that._pipeOn = false;

    try {
        that._requestObject = icy.get(url2play, that._connected.bind(that));
        that._requestObject.on('error', function (e) {
            console.log("MediaInformation - ICY connection error for " + that._url2play + ": " + e);
        });
    } catch (e) {
        console.log("MediaInformation - Cannot connect to " + that._url2play + ": " + e);
    }
};

util.inherits(Connection, EventEmitter);

Connection.prototype.getMedia = function () {
    return that._media;
};

Connection.prototype.close = function () {
    if (that._requestObject) {
        that._requestObject.abort();
    }
};

Connection.prototype._connected = function (res) {
    console.log("MediaInformation - Connected to " + that._url2play);
    /*
     * Example from http://edge.live.mp3.mdn.newmedia.nacamar.net/ps-dieneue_rock/livestream_hi.mp3
     *
     * {'accept-ranges': 'none',
     *  'content-type': 'audio/mpeg',
     *  'icy-br': '128',
     *  'ice-audio-info': 'ice-samplerate=44100;ice-bitrate=128;ice-channels=2',
     *  'icy-description': 'BESTER ROCK UND POP',
     *  'icy-genre': 'Rock',
     *  'icy-name': 'DIE NEUE 107.7',
     *  'icy-pub': '1',
     *  'icy-url': 'http://www.dieneue1077.de',
     *  server: 'Icecast 2.3.3-kh11',
     *  'cache-control': 'no-cache, no-store',
     *  pragma: 'no-cache',
     *  'access-control-allow-origin': '*',
     *  'access-control-allow-headers': 'Origin, Accept, X-Requested-With, Content-Type',
     *  'access-control-allow-methods': 'GET, OPTIONS, HEAD',
     *  connection: 'close',
     *  expires: 'Mon, 26 Jul 1997 05:00:00 GMT',
     *  'icy-metaint': '16000' }
     */
    // log the HTTP response headers
    console.log(res.headers);

    if (res.headers &&
        res.headers["content-type"] &&
        ((res.headers["content-type"].indexOf("audio") >= 0) ||
         (res.headers["content-type"].indexOf("video") >= 0)))
        that._media.contentType = res.headers["content-type"];
    //console.log(that._media);
    that._media.debugHeaderDump = res.headers;

    if ("icy-name" in res.headers) {
        //As backup call the callback if we do not get
        //first metadata in less than 1 second
        that._timeoutHandler = setTimeout(function () {
            that._callback(that._media);
        }, 1000);

        // log any "metadata" events that happen
        res.on('metadata', that._gotMetadata.bind(that, res));
    } else {
        //Not ICY -> call callback already
        that._callback(that._media);
    }

};

Connection.prototype._gotMetadata = function (res, metadata) {
    /*
     * { StreamTitle: 'BILLY IDOL - WHITE WEDDING',
     StreamUrl: '&artist=BILLY%20IDOL&title=WHITE%20WEDDING&album=&duration=&songtype=S&overlay=&buycd=&website=&picture' }
     */
    var parsed = icy.parse(metadata);
    console.log(parsed);

    //Get title
    that._media.metadata.title = parsed.StreamTitle;

    //If we got media info then call callback already
    if (that._timeoutHandler) {
        clearTimeout(that._timeoutHandler);
        that._timeoutHandler = undefined;
        that._callback(that._media);
    }

    //Notify that media has been updated
    that.emit("media", that._media);

    if (!that._pipeOn) {
        //We need to keep reading in order to receive additional metadata
        //We do it here to avoid reading data for sources that do not send
        //any metadata
        res.pipe(devnull());
        that._pipeOn = true;
    }
};

var activeConnections = {};

function getMediaInfoListerner(callerId, url2play, org_url2play, streamType, callback) {

    if (url2play in activeConnections &&
        callerId in activeConnections[url2play].callerIDs) {

        //Call callback
        callback(activeConnections[url2play].connection.getMedia());

        //This callerID is already listing the URL
        return activeConnections[url2play].connection;
    }

    //Close in case this caller was already listing -> only one connection/callerID
    closeMediaInfoListerner(callerId);

    //If this is the first listener for this URL then create object
    if (!(url2play in activeConnections)) {
        var connection = new Connection(url2play, org_url2play, streamType, callback);
        activeConnections[url2play] = {
                callerIDs: {},
                connection: connection
        };
    }

    //Remember callerId
    activeConnections[url2play].callerIDs[callerId] = true;

    //Return connection
    return activeConnections[url2play].connection;
}

function closeMediaInfoListerner(callerId) {
    for (var url2play in activeConnections) {

        //Set this callerId as inactive
        activeConnections[url2play].callerIDs[callerId] = false;

        //Any active listeners for this URL?
        var anyListenerActive = false;
        for (var i in activeConnections[url2play].callerIDs) {
            anyListenerActive |= activeConnections[url2play].callerIDs[i];
        }

        if (!anyListenerActive) {
            //None is listening to this URL -> destroy connection
            activeConnections[url2play].connection.close();
            activeConnections[url2play].callerIDs = undefined;
            console.log("Disconnect " + url2play);
            console.log("Last listener was " + callerId);
            delete activeConnections[url2play];
        }
    }
}

module.exports.getListener   = getMediaInfoListerner;
module.exports.closeListener = closeMediaInfoListerner;
<|endoftext|>