<commit_before>var version = "0.3.9-beta";

var debug = require('debug')('pagermon:server');
var io = require('@pm2/io').init({
    http          : true, // HTTP routes logging (default: true)
    ignore_routes : [/socket\.io/, /notFound/], // Ignore http routes with this pattern (Default: [])
    errors        : true, // Exceptions logging (default: true)
    custom_probes : true, // Auto expose JS Loop Latency and HTTP req/s as custom metrics
    network       : true, // Network monitoring at the application level
    ports         : true,  // Shows which ports your app is listening on (default: false)
    transactions  : true
});
var http = require('http');
var compression = require('compression');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('./log');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var fs = require('fs');
var session = require('express-session');
var request = require('request');
var SQLiteStore = require('connect-sqlite3')(session);
var flash    = require('connect-flash');
var passport = require('./auth/local');

process.on('SIGINT', function() {
    console.log( "\nGracefully shutting down from SIGINT (Ctrl-C)" );
    process.exit(1);
});

// create config file if it does not exist, and set defaults
var conf_defaults = require('./config/default.json');
var conf_file = './config/config.json';
if( ! fs.existsSync(conf_file) ) {
    fs.writeFileSync( conf_file, JSON.stringify(conf_defaults,null, 2) );
}
// load the config file
var nconf = require('nconf');
    nconf.file({file: conf_file});
    nconf.load();

//Load current theme
var theme = nconf.get('global:theme')
// set the theme if none found, for backwards compatibility
if (!theme) {
  nconf.set('global:theme', "default");
  nconf.save();
  var theme = nconf.get('global:theme')
}

//Enable Azure Monitoring if enabled
var azureEnable = nconf.get('monitoring:azureEnable')
var azureKey = nconf.get('monitoring:azureKey')
if (azureEnable) {
  logger.main.debug('Starting Azure Application Insights')
  const appInsights = require('applicationinsights');
  appInsights.setup(azureKey)
             .setAutoDependencyCorrelation(true)
             .setAutoCollectRequests(true)
             .setAutoCollectPerformance(true)
             .setAutoCollectExceptions(true)
             .setAutoCollectDependencies(true)
             .setAutoCollectConsole(true)
             .setUseDiskRetryCaching(true)
             .start();
}

var dbinit = require('./db');
    dbinit.init();
var db = require('./knex/knex.js');

// routes
var index = require('./routes/index');
var admin = require('./routes/admin');
var api = require('./routes/api');
var auth = require('./routes/auth');

var port = normalizePort(process.env.PORT || '3000');
var app = express();
    app.set('port', port);
    // view engine setup
    app.set('views', path.join(__dirname,'themes',theme, 'views'));
    app.set('view engine', 'ejs');
    app.set('trust proxy', 'loopback, linklocal, uniquelocal');

var server = http.createServer(app);
var io = require('socket.io').listen(server);
    server.listen(port);
    server.on('error', onError);
    server.on('listening', onListening);
    //Set connection timeout to prevent long running queries failing on large databases - mostly capacode refresh on MySQL
    server.on('connection', function(connection) {
      connection.setTimeout(600 * 1000);
    });
    //Lets set setMaxListeners to a decent number - not to high to allow the memory leak warking to still trigger
    io.sockets.setMaxListeners(20);
io.sockets.on('connection', function (socket) {
    socket.removeAllListeners();
    debug('client connect to normal socket');
//    socket.on('echo', function (data) {
//        io.sockets.emit('message', data);
//        console.log('message', data);
//    });
});
//Admin Socket
var adminio = io.of('/adminio');
adminio.on('connection', function (socket) {
    socket.removeAllListeners();
    debug('client connect to admin socket');
//    adminio.on('echo', function (data) {
//        adminio.emit('message', data);
//        console.log('message', data);
//    });
});

app.use(favicon(path.join(__dirname,'themes',theme, 'public', 'favicon.ico')));

// set socket.io to be shared across all modules
app.use(function(req,res,next){
    req.io = io;
    next();
});

// session secret is controlled by config
var secret = nconf.get('global:sessionSecret');
// compress all responses
app.use(compression());
app.use(require("morgan")("combined", { "stream": logger.http.stream }));
app.use(bodyParser.json({
  limit: '1mb',
}));       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({
  extended: true,
  limit: '1mb',
})); // to support URL-encoded bodies
app.use(cookieParser());

var sessSet = {
    cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 }, // 1 week
    store: new SQLiteStore,
    saveUninitialized: true,
    resave: 'true',
    secret: secret
}

if (process.env.HOSTNAME && process.env.USE_COOKIE_HOST)
    sessSet.cookie.domain = '.'+process.env.HOSTNAME;

app.use(session(sessSet));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash());
app.use(express.static(path.join(__dirname,'themes',theme, 'public')));
app.use('/node_modules', express.static(path.join(__dirname, 'node_modules')));
app.use(function(req, res, next) {
  res.locals.version = version;
  res.locals.loglevel = nconf.get('global:loglevel') || 'info';
  next();
});

app.use('/', index);
app.use('/admin', admin);
app.use('/post', api);
app.use('/api', api);
app.use('/auth', auth);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  var title = nconf.get('global:monitorName') || 'PagerMon';
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  //these 3 have to be here to stop the error handler shitting up the logs with undefined references when it receives a 500 error ... nfi why
  res.locals.login = req.isAuthenticated();
  res.locals.gaEnable = nconf.get('monitoring:gaEnable');
  res.locals.monitorName = nconf.get("global:monitorName");
  res.locals.register = nconf.get('auth:registration')

  // render the error page
  res.status(err.status || 500);
  res.render(path.join(__dirname,'themes',theme, 'views', 'global', 'error'), { title: title });
});

// Add cronjob to automatically refresh aliases
var dbtype = nconf.get('database:type')
if (dbtype == 'mysql') {
  var aliasRefreshJob = require('cron').CronJob;
  new aliasRefreshJob('0 5,35 * * * *', function() {
    var refreshRequired = nconf.get('database:aliasRefreshRequired')
    logger.main.debug('CRON: Running Cronjob AliasRefresh')
    if (refreshRequired == 1) {
      console.time('updateMap');
      logger.main.info('CRON: Alias Refresh required, running.')
      db('messages').update('alias_id', function() {
        this.select('id')
            .from('capcodes')
            .where(db.ref('messages.address'), 'like', db.ref('capcodes.address') )
            .orderByRaw("REPLACE(address, '_', '%') DESC LIMIT 1")
      })
      .then((result) => {
          console.timeEnd('updateMap');
          nconf.set('database:aliasRefreshRequired', 0);
          nconf.save();
          logger.main.info('CRON: Alias Refresh Successful')
      })
      .catch((err) => {
        logger.main.error('CRON: Error refreshing aliases' + err);
        console.timeEnd('updateMap');
      })
    } else {
      logger.main.debug('CRON: Alias Refresh not Required, Skipping.')
    }
  }, null, true);
}

module.exports = app;

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
    logger.main.info('Listening on ' + bind);
}
<commit_msg>Fix initial startup error<commit_after>var version = "0.3.9-beta";

var debug = require('debug')('pagermon:server');
var io = require('@pm2/io').init({
    http          : true, // HTTP routes logging (default: true)
    ignore_routes : [/socket\.io/, /notFound/], // Ignore http routes with this pattern (Default: [])
    errors        : true, // Exceptions logging (default: true)
    custom_probes : true, // Auto expose JS Loop Latency and HTTP req/s as custom metrics
    network       : true, // Network monitoring at the application level
    ports         : true,  // Shows which ports your app is listening on (default: false)
    transactions  : true
});
var http = require('http');
var compression = require('compression');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('./log');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var fs = require('fs');
var session = require('express-session');
var request = require('request');
var SQLiteStore = require('connect-sqlite3')(session);
var flash    = require('connect-flash');

process.on('SIGINT', function() {
    console.log( "\nGracefully shutting down from SIGINT (Ctrl-C)" );
    process.exit(1);
});

// create config file if it does not exist, and set defaults
var conf_defaults = require('./config/default.json');
var conf_file = './config/config.json';
if( ! fs.existsSync(conf_file) ) {
    fs.writeFileSync( conf_file, JSON.stringify(conf_defaults,null, 2) );
}
// load the config file
var nconf = require('nconf');
    nconf.file({file: conf_file});
    nconf.load();

//Load current theme
var theme = nconf.get('global:theme')
// set the theme if none found, for backwards compatibility
if (!theme) {
  nconf.set('global:theme', "default");
  nconf.save();
  var theme = nconf.get('global:theme')
}

//Enable Azure Monitoring if enabled
var azureEnable = nconf.get('monitoring:azureEnable')
var azureKey = nconf.get('monitoring:azureKey')
if (azureEnable) {
  logger.main.debug('Starting Azure Application Insights')
  const appInsights = require('applicationinsights');
  appInsights.setup(azureKey)
             .setAutoDependencyCorrelation(true)
             .setAutoCollectRequests(true)
             .setAutoCollectPerformance(true)
             .setAutoCollectExceptions(true)
             .setAutoCollectDependencies(true)
             .setAutoCollectConsole(true)
             .setUseDiskRetryCaching(true)
             .start();
}

var dbinit = require('./db');
    dbinit.init();
var db = require('./knex/knex.js');

var passport = require('./auth/local');

// routes
var index = require('./routes/index');
var admin = require('./routes/admin');
var api = require('./routes/api');
var auth = require('./routes/auth');

var port = normalizePort(process.env.PORT || '3000');
var app = express();
    app.set('port', port);
    // view engine setup
    app.set('views', path.join(__dirname,'themes',theme, 'views'));
    app.set('view engine', 'ejs');
    app.set('trust proxy', 'loopback, linklocal, uniquelocal');

var server = http.createServer(app);
var io = require('socket.io').listen(server);
    server.listen(port);
    server.on('error', onError);
    server.on('listening', onListening);
    //Set connection timeout to prevent long running queries failing on large databases - mostly capacode refresh on MySQL
    server.on('connection', function(connection) {
      connection.setTimeout(600 * 1000);
    });
    //Lets set setMaxListeners to a decent number - not to high to allow the memory leak warking to still trigger
    io.sockets.setMaxListeners(20);
io.sockets.on('connection', function (socket) {
    socket.removeAllListeners();
    debug('client connect to normal socket');
//    socket.on('echo', function (data) {
//        io.sockets.emit('message', data);
//        console.log('message', data);
//    });
});
//Admin Socket
var adminio = io.of('/adminio');
adminio.on('connection', function (socket) {
    socket.removeAllListeners();
    debug('client connect to admin socket');
//    adminio.on('echo', function (data) {
//        adminio.emit('message', data);
//        console.log('message', data);
//    });
});

app.use(favicon(path.join(__dirname,'themes',theme, 'public', 'favicon.ico')));

// set socket.io to be shared across all modules
app.use(function(req,res,next){
    req.io = io;
    next();
});

// session secret is controlled by config
var secret = nconf.get('global:sessionSecret');
// compress all responses
app.use(compression());
app.use(require("morgan")("combined", { "stream": logger.http.stream }));
app.use(bodyParser.json({
  limit: '1mb',
}));       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({
  extended: true,
  limit: '1mb',
})); // to support URL-encoded bodies
app.use(cookieParser());

var sessSet = {
    cookie: { maxAge: 7 * 24 * 60 * 60 * 1000 }, // 1 week
    store: new SQLiteStore,
    saveUninitialized: true,
    resave: 'true',
    secret: secret
}

if (process.env.HOSTNAME && process.env.USE_COOKIE_HOST)
    sessSet.cookie.domain = '.'+process.env.HOSTNAME;

app.use(session(sessSet));
app.use(passport.initialize());
app.use(passport.session()); // persistent login sessions
app.use(flash());
app.use(express.static(path.join(__dirname,'themes',theme, 'public')));
app.use('/node_modules', express.static(path.join(__dirname, 'node_modules')));
app.use(function(req, res, next) {
  res.locals.version = version;
  res.locals.loglevel = nconf.get('global:loglevel') || 'info';
  next();
});

app.use('/', index);
app.use('/admin', admin);
app.use('/post', api);
app.use('/api', api);
app.use('/auth', auth);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  var title = nconf.get('global:monitorName') || 'PagerMon';
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  //these 3 have to be here to stop the error handler shitting up the logs with undefined references when it receives a 500 error ... nfi why
  res.locals.login = req.isAuthenticated();
  res.locals.gaEnable = nconf.get('monitoring:gaEnable');
  res.locals.monitorName = nconf.get("global:monitorName");
  res.locals.register = nconf.get('auth:registration')

  // render the error page
  res.status(err.status || 500);
  res.render(path.join(__dirname,'themes',theme, 'views', 'global', 'error'), { title: title });
});

// Add cronjob to automatically refresh aliases
var dbtype = nconf.get('database:type')
if (dbtype == 'mysql') {
  var aliasRefreshJob = require('cron').CronJob;
  new aliasRefreshJob('0 5,35 * * * *', function() {
    var refreshRequired = nconf.get('database:aliasRefreshRequired')
    logger.main.debug('CRON: Running Cronjob AliasRefresh')
    if (refreshRequired == 1) {
      console.time('updateMap');
      logger.main.info('CRON: Alias Refresh required, running.')
      db('messages').update('alias_id', function() {
        this.select('id')
            .from('capcodes')
            .where(db.ref('messages.address'), 'like', db.ref('capcodes.address') )
            .orderByRaw("REPLACE(address, '_', '%') DESC LIMIT 1")
      })
      .then((result) => {
          console.timeEnd('updateMap');
          nconf.set('database:aliasRefreshRequired', 0);
          nconf.save();
          logger.main.info('CRON: Alias Refresh Successful')
      })
      .catch((err) => {
        logger.main.error('CRON: Error refreshing aliases' + err);
        console.timeEnd('updateMap');
      })
    } else {
      logger.main.debug('CRON: Alias Refresh not Required, Skipping.')
    }
  }, null, true);
}

module.exports = app;

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
    logger.main.info('Listening on ' + bind);
}
<|endoftext|>


<commit_before>/*jslint node: true */
/*global require */

module.exports = function (util, events, http, querystring, url, elastic) {
    "use strict";

    var exports = {};

    var searchRequest = function (request, response) {
        request.setEncoding("utf8");

        var body = "";

        request.on("data", function (chunk) {
            body += chunk;
        });
        request.on("end", function () {
            var requestUrl = url.parse(request.url, true);

            var search = new elastic.search();

            search.query(requestUrl.query);

            search.on("success", function (searchResponse) {
                var result;
                var resultJson;

                response.writeHead(200, {"Content-Type": "application/json"});

                if (requestUrl.query.suggestion !== undefined) {
                    if (searchResponse.facets !== undefined &&
                        searchResponse.facets.title_suggestions !== undefined &&
                        searchResponse.facets.title_suggestions.terms !== undefined
                        ) {
                        var terms = searchResponse.facets.title_suggestions.terms;

                        var suggestions = [];

                        for (var suggestionPos in terms) {
                            if (terms.hasOwnProperty(suggestionPos) && terms[suggestionPos].term !== undefined) {
                                suggestions.push(terms[suggestionPos].term);
                            }
                        }

                        result = suggestions;
                    } else {
                        response.writeHead(404, {"Content-Type": "text/plain"});
                        response.end("Missing data for the suggestions response.");
                    }
                } else {
                    result = searchResponse;
                }

                resultJson = JSON.stringify(result);

                response.end(resultJson);
            });

            search.on("failure", function (error) {
                response.writeHead(404, {"Content-Type": "text/plain"});
                response.end("Search failure.");
            });
        });
    };

    var notFoundRequest = function (request, response) {
        response.writeHead(404, {"Content-Type": "text/plain"});
        response.end("Not found.");
    };

    exports.load = function (request, response) {
        var requestUrl = url.parse(request.url);

        if (requestUrl.pathname === "/") {
            return searchRequest(request, response);
        } else {
            return notFoundRequest(request, response);
        }
    };

    return exports;
};
<commit_msg>add protection against large query strings<commit_after>/*jslint node: true */
/*global require */

module.exports = function (util, events, http, querystring, url, elastic) {
    "use strict";

    var exports = {};

    var searchRequest = function (request, response) {
        request.setEncoding("utf8");

        var body = "";

        request.on("data", function (chunk) {
            body += chunk;
        });
        request.on("end", function () {
            if (request.url.length > 400) {
                response.writeHead(403, {"Content-Type": "text/plain"});
                response.end("Search string is too long.");
                return;
            }

            var requestUrl = url.parse(request.url, true);

            var search = new elastic.search();

            search.query(requestUrl.query);

            search.on("success", function (searchResponse) {
                var result;
                var resultJson;

                response.writeHead(200, {"Content-Type": "application/json"});

                if (requestUrl.query.suggestion !== undefined) {
                    if (searchResponse.facets !== undefined &&
                        searchResponse.facets.title_suggestions !== undefined &&
                        searchResponse.facets.title_suggestions.terms !== undefined
                        ) {
                        var terms = searchResponse.facets.title_suggestions.terms;

                        var suggestions = [];

                        for (var suggestionPos in terms) {
                            if (terms.hasOwnProperty(suggestionPos) && terms[suggestionPos].term !== undefined) {
                                suggestions.push(terms[suggestionPos].term);
                            }
                        }

                        result = suggestions;
                    } else {
                        response.writeHead(404, {"Content-Type": "text/plain"});
                        response.end("Missing data for the suggestions response.");
                    }
                } else {
                    result = searchResponse;
                }

                resultJson = JSON.stringify(result);

                response.end(resultJson);
            });

            search.on("failure", function (error) {
                response.writeHead(404, {"Content-Type": "text/plain"});
                response.end("Search failure.");
            });
        });
    };

    var notFoundRequest = function (request, response) {
        response.writeHead(404, {"Content-Type": "text/plain"});
        response.end("Not found.");
    };

    exports.load = function (request, response) {
        var requestUrl = url.parse(request.url);

        if (requestUrl.pathname === "/") {
            return searchRequest(request, response);
        } else {
            return notFoundRequest(request, response);
        }
    };

    return exports;
};
<|endoftext|>


<commit_before>import Vue from 'vue'
import Router from 'vue-router'
import Resource from'vue-resource'
import { sync } from 'vuex-router-sync'
import VueValidator from 'vue-validator'

Vue.use(Router)
Vue.use(Resource)
Vue.use(VueValidator)

// components
import App from './components/App.vue'
import Login from './components/Login/Login.vue'
import Dashboard from './components/Dashboard/Dashboard.vue'
import Counter from './components/Counter/Counter.vue'
// model
import store from './vuex/store.js'

// routing
var router = new Router()

router.map({
  '/login': {
    component: Login
  },
  '/dashboard': {
    component: Dashboard
  },
  '/counter': {
    component: Counter
  }
})

router.beforeEach(function() {
  window.scrollTo(0, 0)
})

router.redirect({
  '*': '/login'
})

sync(store, router)
router.start(App, 'body')

Vue.config.debug = true

Vue.http.interceptors.push({
  request: function(request) {
  	Vue.http.headers.common['Authorization'] = 'JWT' + sessionStorage.getItem('token')
    return request
  },
  response: function(response) {
    if (response.status === 401) {
      router.go('/login')
    }
    return response
  }
});<commit_msg>test deploy<commit_after>import Vue from 'vue'
import Router from 'vue-router'
import Resource from'vue-resource'
import { sync } from 'vuex-router-sync'
import VueValidator from 'vue-validator'

Vue.use(Router)
Vue.use(Resource)
Vue.use(VueValidator)

// components
import App from './components/App.vue'
import Login from './components/Login/Login.vue'
import Dashboard from './components/Dashboard/Dashboard.vue'
import Counter from './components/Counter/Counter.vue'
// model
import store from './vuex/store.js'

// routing
var router = new Router()

router.map({
  '/login': {
    component: Login
  },
  '/dashboard': {
    component: Dashboard
  },
  '/counter': {
    component: Counter
  }
})

router.beforeEach(function() {
  window.scrollTo(0, 0)
})

router.redirect({
  '*': '/login'
})

sync(store, router)
router.start(App, 'body')

Vue.config.debug = true

Vue.http.interceptors.push({
  request: function(request) {
  	Vue.http.headers.common['Authorization'] = 'JWT' + sessionStorage.getItem('token')
    return request
  },
  response: function(response) {
    if (response.status === 401) {
      router.go('/login')
    }
    return response
  }
});
// test deploy<|endoftext|>


<commit_before>
AUI().add(
	'textboxlist',
	function(A) {
		var Lang = A.Lang,

			getClassName = A.ClassNameManager.getClassName,

			ENTRY_NAME = 'textboxlistentry',
			NAME = 'textboxlist',

			BOUNDING_BOX = 'boundingBox',
			CONTENT_BOX = 'contentBox',

			CONFIG_ANIM = {
				from: {
					opacity: 1
				},
				to: {
					opacity: 0.3
				},
				duration: 0.1,
				on: {
					end: function(event) {
						var instance = this;

						var reverse = instance.get('reverse');

						if (!reverse) {
							instance.run();
						}

						instance.set('reverse', !reverse);
					}
				}
			},

			CSS_CLEARFIX = getClassName('helper', 'clearfix'),

			CSS_ICON = getClassName('icon'),
			CSS_ICON_CLOSE = getClassName('icon', 'close'),
			CSS_ICON_CLOSE_HOVER = getClassName(ENTRY_NAME, 'close', 'hover'),
			CSS_ENTRY_CLOSE = getClassName(ENTRY_NAME, 'close'),
			CSS_ENTRY_HOLDER = getClassName(ENTRY_NAME, 'holder'),
			CSS_ENTRY_TEXT = getClassName(ENTRY_NAME, 'text'),
			CSS_ENTRY_ITEM = getClassName(ENTRY_NAME, 'item'),

			CSS_INPUT_CONTAINER = getClassName(NAME, 'input','container'),

			KEY_BACKSPACE = 8,
			KEY_ENTER = 13,
			KEY_LEFT = 37,
			KEY_RIGHT = 39,

			TPL_ENTRY_CLOSE = '',
			TPL_ENTRY_TEXT = '',
			TPL_ENTRY_HOLDER = '

',

			TPL_INPUT_CONTAINER = '

';

		var TextboxList = function() {
			TextboxList.superclass.constructor.apply(this, arguments);
		};

		TextboxList.NAME = NAME;

		TextboxList.ATTRS = {
			allowAnyEntry: {
				value: false
			},
			delimChar: {
				value: ''
			}
		};

		A.extend(
			TextboxList,
			A.AutoComplete,
			{
				initializer: function(config) {
					var instance = this;

					var matchKey = instance.get('matchKey');

					instance.entries = new A.DataSet(
						{
							getKey: function(obj) {
								var instance = this;

								return obj[matchKey];
							}
						}
					);

					instance._lastSelectedEntry = -1;
				},

				renderUI: function() {
					var instance = this;

					instance._renderEntryHolder();

					TextboxList.superclass.renderUI.apply(instance, arguments);
				},

				bindUI: function() {
					var instance = this;

					TextboxList.superclass.bindUI.apply(instance, arguments);

					instance.after('itemSelect', instance._afterItemSelect);
					instance.after('focusedChange', instance._afterTBLFocusedChange);
					instance.after('textboxlistentry:focusedChange', instance._afterTBLFocusedChange);

					var entries = instance.entries;
					var entryHolder = instance.entryHolder;
					var closeSelector = '.' + CSS_ICON_CLOSE;

					entries.on('add', instance._updateEntryHolder, instance);
					entries.on('replace', instance._updateEntryHolder, instance);
					entries.on('remove', instance._updateEntryHolder, instance);

					entryHolder.delegate('click', A.bind(instance._removeItem, instance), closeSelector);
					entryHolder.delegate('mouseenter', A.bind(instance._onCloseIconMouseOver, instance), closeSelector);
					entryHolder.delegate('mouseleave', A.bind(instance._onCloseIconMouseOut, instance), closeSelector);

					A.on(
						'key',
						instance._onTBLKeypress,
						instance.get(BOUNDING_BOX),
						'down:39,40,37,38,8,13',
						instance
					);

					instance.inputNode.on('focus', instance._onInputNodeFocus, instance);
				},

				add: function(label) {
					var instance = this;

					var entry = instance._prepareEntry(label);

					instance.entries.add(entry);
				},

				insert: function(index, label) {
					var instance = this;

					var entry = instance._prepareEntry(label);

					return instance.entries.insert(index, entry);
				},

				remove: function(label) {
					var instance = this;

					return instance.entries.removeKey(label);
				},

				_afterItemSelect: function(elListItem) {
					var instance = this;

					instance.entries.add(elListItem._resultData);

				},

				_afterTBLFocusedChange: function(event) {
					var instance = this;

					if (event.type.indexOf('textboxlistentry') > -1) {
						if (event.newVal) {
							var entryBoundingBox = event.target.get(BOUNDING_BOX);

							instance._lastSelectedEntry = instance.entryHolder.all('li').indexOf(entryBoundingBox);
						}
					}
					else if (event.newVal && instance._lastSelectedEntry == -1) {
						instance.inputNode.focus();
					}
				},

				_onCloseIconMouseOut: function(event) {
					var instance = this;

					event.currentTarget.removeClass(CSS_ICON_CLOSE_HOVER);
				},

				_onCloseIconMouseOver: function(event) {
					var instance = this;

					event.currentTarget.addClass(CSS_ICON_CLOSE_HOVER);
				},

				_onInputNodeFocus: function(event) {
					var instance = this;

					instance._lastSelectedEntry = -1;
				},

				_onTBLKeypress: function(event) {
					var instance = this;

					var keyCode = event.keyCode;
					var inputNode = instance.inputNode;

					if (!inputNode.val()) {
						var lastSelectedEntry = instance._lastSelectedEntry;
						var currentSelectedEntry = -1;

						var unselected = (lastSelectedEntry == -1);

						var deleteEntry = (keyCode == KEY_BACKSPACE);
						var deleteBack = (deleteEntry && unselected);
						var moveBack = keyCode == KEY_LEFT || deleteBack;
						var moveForward = (keyCode == KEY_RIGHT);

						var entries = instance.entries;

						var entriesSize = entries.size();
						var lastEntryIndex = entriesSize - 1;

						if (moveBack) {
							if (unselected) {
								currentSelectedEntry = lastEntryIndex;
							}
							else if (lastSelectedEntry == 0) {
								currentSelectedEntry = lastSelectedEntry;
							}
							else {
								currentSelectedEntry = lastSelectedEntry - 1;
							}
						}
						else if (moveForward) {
							if (unselected || (lastSelectedEntry == lastEntryIndex)) {
								currentSelectedEntry = -1;
							}
							else {
								currentSelectedEntry = lastSelectedEntry + 1;
							}
						}
						else if (deleteEntry) {
							entries.removeAt(lastSelectedEntry);

							entriesSize = entries.size();

							if (lastSelectedEntry == entriesSize) {
								currentSelectedEntry = -1;
							}
							else {
								currentSelectedEntry = lastSelectedEntry;
							}
						}

						if (deleteBack || deleteEntry) {
							event.halt();
						}

						if (currentSelectedEntry != -1) {
							entries.item(currentSelectedEntry).entry.focus();
						}
						else {
							inputNode.focus();
						}

						instance._lastSelectedEntry = currentSelectedEntry;
					}
					else {
						if (keyCode == KEY_ENTER && instance.get('allowAnyEntry')) {
							instance.entries.add(inputNode.val(), {});
						}
					}
				},

				_onTextboxKeyPress: function(event) {
					var instance = this;

					TextboxList.superclass._onTextboxKeyPress.apply(instance, arguments);

					if (event.keyCode == KEY_ENTER) {
						event.halt();
					}
				},

				_prepareEntry: function(label) {
					var instance = this;

					var entry = {};
					var matchKey = instance.get('matchKey');

					entry[matchKey] = label;

					return entry;
				},

				_removeItem: function(event) {
					var instance = this;

					var entry = A.Widget.getByNode(event.currentTarget);

					entry = entry.get(BOUNDING_BOX);

					var currentIndex = instance.entryHolder.all('li').indexOf(entry);

					instance.entries.removeAt(currentIndex);
				},

				_renderEntryHolder: function() {
					var instance = this;

					var contentBox = instance.get(CONTENT_BOX);
					var entryHolder = A.Node.create(TPL_ENTRY_HOLDER);

					contentBox.prepend(entryHolder);

					instance.entryHolder = entryHolder;
				},

				_renderInput: function() {
					var instance = this;

					var contentBox = instance.get(CONTENT_BOX);
					var input = instance.get('input');

					var fieldConfig = {
						labelText: false
					};

					var inputParent = null;

					if (input) {
						input = A.get(input);

						fieldConfig.node = input;

						inputParent = input.get('parentNode');
					}

					var inputContainer = A.Node.create(TPL_INPUT_CONTAINER);

					instance.entryHolder.append(inputContainer);

					var inputField = new A.Textfield(fieldConfig).render(inputContainer);
					var inputBoundingBox = inputField.get(BOUNDING_BOX);

					if (inputBoundingBox.get('parentNode') != inputContainer) {
						inputContainer.appendChild(inputBoundingBox);
					}

					instance.inputContainer = inputContainer;
					instance.inputField = inputField;
					instance.inputNode = inputField.get('node');
					instance.button = new A.ToolItem();

					instance.set('uniqueName', A.stamp(instance.inputNode));
				},

				_updateEntryHolder: function(event) {
					var instance = this;

					var eventType = event.type;
					var inputNode = instance.inputNode;
					var entryHolder = instance.entryHolder;
					var item = event.item;
					var index = event.index;
					var key = event.attrName;

					if (key) {
						if (eventType == 'dataset:add') {
							var entry = new TextboxListEntry(
								{
									labelText: key
								}
							);

							entry.addTarget(instance);

							var entryNode = entry.get(BOUNDING_BOX);

							entry.render(entryHolder);

							entryHolder.all('li').item(index).placeBefore(entryNode);

							entryNode.plug(A.Plugin.NodeFX, CONFIG_ANIM);

							item.entry = entry;

							inputNode.val('');
						}
						else if (eventType == 'dataset:replace') {
							inputNode.val('');

							var entry = event.prevVal.entry;

							item.entry = entry;

							entry.get(BOUNDING_BOX).fx.run();
						}
						else if (eventType == 'dataset:remove') {
							var entryNodes = entryHolder.all('li');

							if (entryNodes) {
								entryNodes.item(index).remove();
							}
						}
					}
					else {
						instance.entries.removeAt(index);
					}
				}
			}
		);

		var TextboxListEntry = function() {
			TextboxListEntry.superclass.constructor.apply(this, arguments);
		};

		TextboxListEntry.NAME = ENTRY_NAME;

		TextboxListEntry.ATTRS = {
			labelText: {
				value: ''
			}
		};

		A.extend(
			TextboxListEntry,
			A.Widget,
			{
				BOUNDING_TEMPLATE: '

',
				CONTENT_TEMPLATE: '',
				renderUI: function() {
					var instance = this;

					var contentBox = instance.get(CONTENT_BOX);

					var text = A.Node.create(TPL_ENTRY_TEXT);
					var close = A.Node.create(TPL_ENTRY_CLOSE);

					var labelText = instance.get('labelText');

					text.set('innerHTML', labelText);

					contentBox.appendChild(text);
					contentBox.appendChild(close);
				}
			}
		);

		A.TextboxList = TextboxList;
		A.TextboxListEntry = TextboxListEntry;
	},
	'@VERSION',
	{
		requires: ['aui-base', 'autocomplete', 'anim-node-plugin', 'node-focusmanager'],
		use: []
	}
);<commit_msg>Change for reading set key<commit_after>
AUI().add(
	'textboxlist',
	function(A) {
		var Lang = A.Lang,

			getClassName = A.ClassNameManager.getClassName,

			ENTRY_NAME = 'textboxlistentry',
			NAME = 'textboxlist',

			BOUNDING_BOX = 'boundingBox',
			CONTENT_BOX = 'contentBox',

			CONFIG_ANIM = {
				from: {
					opacity: 1
				},
				to: {
					opacity: 0.3
				},
				duration: 0.1,
				on: {
					end: function(event) {
						var instance = this;

						var reverse = instance.get('reverse');

						if (!reverse) {
							instance.run();
						}

						instance.set('reverse', !reverse);
					}
				}
			},

			CSS_CLEARFIX = getClassName('helper', 'clearfix'),

			CSS_ICON = getClassName('icon'),
			CSS_ICON_CLOSE = getClassName('icon', 'close'),
			CSS_ICON_CLOSE_HOVER = getClassName(ENTRY_NAME, 'close', 'hover'),
			CSS_ENTRY_CLOSE = getClassName(ENTRY_NAME, 'close'),
			CSS_ENTRY_HOLDER = getClassName(ENTRY_NAME, 'holder'),
			CSS_ENTRY_TEXT = getClassName(ENTRY_NAME, 'text'),
			CSS_ENTRY_ITEM = getClassName(ENTRY_NAME, 'item'),

			CSS_INPUT_CONTAINER = getClassName(NAME, 'input','container'),

			KEY_BACKSPACE = 8,
			KEY_ENTER = 13,
			KEY_LEFT = 37,
			KEY_RIGHT = 39,

			TPL_ENTRY_CLOSE = '',
			TPL_ENTRY_TEXT = '',
			TPL_ENTRY_HOLDER = '

',

			TPL_INPUT_CONTAINER = '

';

		var TextboxList = function() {
			TextboxList.superclass.constructor.apply(this, arguments);
		};

		TextboxList.NAME = NAME;

		TextboxList.ATTRS = {
			allowAnyEntry: {
				value: false
			},
			delimChar: {
				value: ''
			}
		};

		A.extend(
			TextboxList,
			A.AutoComplete,
			{
				initializer: function(config) {
					var instance = this;

					var matchKey = instance.get('matchKey');

					instance.entries = new A.DataSet(
						{
							getKey: function(obj) {
								var instance = this;

								return obj[matchKey];
							}
						}
					);

					instance._lastSelectedEntry = -1;
				},

				renderUI: function() {
					var instance = this;

					instance._renderEntryHolder();

					TextboxList.superclass.renderUI.apply(instance, arguments);
				},

				bindUI: function() {
					var instance = this;

					TextboxList.superclass.bindUI.apply(instance, arguments);

					instance.after('itemSelect', instance._afterItemSelect);
					instance.after('focusedChange', instance._afterTBLFocusedChange);
					instance.after('textboxlistentry:focusedChange', instance._afterTBLFocusedChange);

					var entries = instance.entries;
					var entryHolder = instance.entryHolder;
					var closeSelector = '.' + CSS_ICON_CLOSE;

					entries.on('add', instance._updateEntryHolder, instance);
					entries.on('replace', instance._updateEntryHolder, instance);
					entries.on('remove', instance._updateEntryHolder, instance);

					entryHolder.delegate('click', A.bind(instance._removeItem, instance), closeSelector);
					entryHolder.delegate('mouseenter', A.bind(instance._onCloseIconMouseOver, instance), closeSelector);
					entryHolder.delegate('mouseleave', A.bind(instance._onCloseIconMouseOut, instance), closeSelector);

					A.on(
						'key',
						instance._onTBLKeypress,
						instance.get(BOUNDING_BOX),
						'down:39,40,37,38,8,13',
						instance
					);

					instance.inputNode.on('focus', instance._onInputNodeFocus, instance);
				},

				add: function(label) {
					var instance = this;

					var entry = instance._prepareEntry(label);

					instance.entries.add(entry);
				},

				insert: function(index, label) {
					var instance = this;

					var entry = instance._prepareEntry(label);

					return instance.entries.insert(index, entry);
				},

				remove: function(label) {
					var instance = this;

					return instance.entries.removeKey(label);
				},

				_afterItemSelect: function(elListItem) {
					var instance = this;

					instance.entries.add(elListItem._resultData);

				},

				_afterTBLFocusedChange: function(event) {
					var instance = this;

					if (event.type.indexOf('textboxlistentry') > -1) {
						if (event.newVal) {
							var entryBoundingBox = event.target.get(BOUNDING_BOX);

							instance._lastSelectedEntry = instance.entryHolder.all('li').indexOf(entryBoundingBox);
						}
					}
					else if (event.newVal && instance._lastSelectedEntry == -1) {
						instance.inputNode.focus();
					}
				},

				_onCloseIconMouseOut: function(event) {
					var instance = this;

					event.currentTarget.removeClass(CSS_ICON_CLOSE_HOVER);
				},

				_onCloseIconMouseOver: function(event) {
					var instance = this;

					event.currentTarget.addClass(CSS_ICON_CLOSE_HOVER);
				},

				_onInputNodeFocus: function(event) {
					var instance = this;

					instance._lastSelectedEntry = -1;
				},

				_onTBLKeypress: function(event) {
					var instance = this;

					var keyCode = event.keyCode;
					var inputNode = instance.inputNode;

					if (!inputNode.val()) {
						var lastSelectedEntry = instance._lastSelectedEntry;
						var currentSelectedEntry = -1;

						var unselected = (lastSelectedEntry == -1);

						var deleteEntry = (keyCode == KEY_BACKSPACE);
						var deleteBack = (deleteEntry && unselected);
						var moveBack = keyCode == KEY_LEFT || deleteBack;
						var moveForward = (keyCode == KEY_RIGHT);

						var entries = instance.entries;

						var entriesSize = entries.size();
						var lastEntryIndex = entriesSize - 1;

						if (moveBack) {
							if (unselected) {
								currentSelectedEntry = lastEntryIndex;
							}
							else if (lastSelectedEntry == 0) {
								currentSelectedEntry = lastSelectedEntry;
							}
							else {
								currentSelectedEntry = lastSelectedEntry - 1;
							}
						}
						else if (moveForward) {
							if (unselected || (lastSelectedEntry == lastEntryIndex)) {
								currentSelectedEntry = -1;
							}
							else {
								currentSelectedEntry = lastSelectedEntry + 1;
							}
						}
						else if (deleteEntry) {
							entries.removeAt(lastSelectedEntry);

							entriesSize = entries.size();

							if (lastSelectedEntry == entriesSize) {
								currentSelectedEntry = -1;
							}
							else {
								currentSelectedEntry = lastSelectedEntry;
							}
						}

						if (deleteBack || deleteEntry) {
							event.halt();
						}

						if (currentSelectedEntry != -1) {
							entries.item(currentSelectedEntry).entry.focus();
						}
						else {
							inputNode.focus();
						}

						instance._lastSelectedEntry = currentSelectedEntry;
					}
					else {
						if (keyCode == KEY_ENTER && instance.get('allowAnyEntry')) {
							instance.entries.add(inputNode.val(), {});
						}
					}
				},

				_onTextboxKeyPress: function(event) {
					var instance = this;

					TextboxList.superclass._onTextboxKeyPress.apply(instance, arguments);

					if (event.keyCode == KEY_ENTER) {
						event.halt();
					}
				},

				_prepareEntry: function(label) {
					var instance = this;

					var entry = {};
					var matchKey = instance.get('matchKey');

					entry[matchKey] = label;

					return entry;
				},

				_removeItem: function(event) {
					var instance = this;

					var entry = A.Widget.getByNode(event.currentTarget);

					entry = entry.get(BOUNDING_BOX);

					var currentIndex = instance.entryHolder.all('li').indexOf(entry);

					instance.entries.removeAt(currentIndex);
				},

				_renderEntryHolder: function() {
					var instance = this;

					var contentBox = instance.get(CONTENT_BOX);
					var entryHolder = A.Node.create(TPL_ENTRY_HOLDER);

					contentBox.prepend(entryHolder);

					instance.entryHolder = entryHolder;
				},

				_renderInput: function() {
					var instance = this;

					var contentBox = instance.get(CONTENT_BOX);
					var input = instance.get('input');

					var fieldConfig = {
						labelText: false
					};

					var inputParent = null;

					if (input) {
						input = A.get(input);

						fieldConfig.node = input;

						inputParent = input.get('parentNode');
					}

					var inputContainer = A.Node.create(TPL_INPUT_CONTAINER);

					instance.entryHolder.append(inputContainer);

					var inputField = new A.Textfield(fieldConfig).render(inputContainer);
					var inputBoundingBox = inputField.get(BOUNDING_BOX);

					if (inputBoundingBox.get('parentNode') != inputContainer) {
						inputContainer.appendChild(inputBoundingBox);
					}

					instance.inputContainer = inputContainer;
					instance.inputField = inputField;
					instance.inputNode = inputField.get('node');
					instance.button = new A.ToolItem();

					instance.set('uniqueName', A.stamp(instance.inputNode));
				},

				_updateEntryHolder: function(event) {
					var instance = this;

					var eventType = event.type;
					var inputNode = instance.inputNode;
					var entryHolder = instance.entryHolder;
					var item = event.item;
					var index = event.index;

					var matchKey = instance.get('matchKey');

					var key = item[matchKey] || event.attrName;

					if (key) {
						if (eventType == 'dataset:add') {
							var entry = new TextboxListEntry(
								{
									labelText: key
								}
							);

							entry.addTarget(instance);

							var entryNode = entry.get(BOUNDING_BOX);

							entry.render(entryHolder);

							entryHolder.all('li').item(index).placeBefore(entryNode);

							entryNode.plug(A.Plugin.NodeFX, CONFIG_ANIM);

							item.entry = entry;

							inputNode.val('');
						}
						else if (eventType == 'dataset:replace') {
							inputNode.val('');

							var entry = event.prevVal.entry;

							item.entry = entry;

							entry.get(BOUNDING_BOX).fx.run();
						}
						else if (eventType == 'dataset:remove') {
							var entryNodes = entryHolder.all('li');

							if (entryNodes) {
								entryNodes.item(index).remove();
							}
						}
					}
					else {
						instance.entries.removeAt(index);
					}
				}
			}
		);

		var TextboxListEntry = function() {
			TextboxListEntry.superclass.constructor.apply(this, arguments);
		};

		TextboxListEntry.NAME = ENTRY_NAME;

		TextboxListEntry.ATTRS = {
			labelText: {
				value: ''
			}
		};

		A.extend(
			TextboxListEntry,
			A.Widget,
			{
				BOUNDING_TEMPLATE: '

',
				CONTENT_TEMPLATE: '',
				renderUI: function() {
					var instance = this;

					var contentBox = instance.get(CONTENT_BOX);

					var text = A.Node.create(TPL_ENTRY_TEXT);
					var close = A.Node.create(TPL_ENTRY_CLOSE);

					var labelText = instance.get('labelText');

					text.set('innerHTML', labelText);

					contentBox.appendChild(text);
					contentBox.appendChild(close);
				}
			}
		);

		A.TextboxList = TextboxList;
		A.TextboxListEntry = TextboxListEntry;
	},
	'@VERSION',
	{
		requires: ['aui-base', 'autocomplete', 'anim-node-plugin', 'node-focusmanager'],
		use: []
	}
);<|endoftext|>


<commit_before>/**
 * Shopware 5
 * Copyright (c) shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 */

//{namespace name=backend/custom_search/translation}

//{block name="backend/config/view/custom_search/sorting/includes/direction_combo"}

Ext.define('Shopware.apps.Config.view.custom_search.sorting.includes.DirectionCombo', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.custom-search-direction-combo',
    displayField: 'label',
    valueField: 'key',
    queryMode: 'local',
    fieldLabel: '{s name="direction_combo"}{/s}',
    allowBlank: false,

    name: 'direction',
    value: 'ASC',

    initComponent: function() {
        var me = this;

        me.store = Ext.create('Ext.data.Store', {
            fields: ['key', 'label'],
            data: [
                { key: 'ASC', label: me.getAscendingLabel() },
                { key: 'DESC', label: me.getDescendingLabel() }
            ]
        });

        me.callParent(arguments);
    },

    getAscendingLabel: function() {
        return '{s name="ascending"}{/s}';
    },

    getDescendingLabel: function() {
        return '{s name="descending"}{/s}';
    }
});

//{/block}
<commit_msg>SW-17455 - Display descending sorting first<commit_after>/**
 * Shopware 5
 * Copyright (c) shopware AG
 *
 * According to our dual licensing model, this program can be used either
 * under the terms of the GNU Affero General Public License, version 3,
 * or under a proprietary license.
 *
 * The texts of the GNU Affero General Public License with an additional
 * permission and of our proprietary license can be found at and
 * in the LICENSE file you have received along with this program.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * "Shopware" is a registered trademark of shopware AG.
 * The licensing of the program under the AGPLv3 does not imply a
 * trademark license. Therefore any rights, title and interest in
 * our trademarks remain entirely with us.
 */

//{namespace name=backend/custom_search/translation}

//{block name="backend/config/view/custom_search/sorting/includes/direction_combo"}

Ext.define('Shopware.apps.Config.view.custom_search.sorting.includes.DirectionCombo', {
    extend: 'Ext.form.field.ComboBox',
    alias: 'widget.custom-search-direction-combo',
    displayField: 'label',
    valueField: 'key',
    queryMode: 'local',
    fieldLabel: '{s name="direction_combo"}{/s}',
    allowBlank: false,

    name: 'direction',
    value: 'DESC',

    initComponent: function() {
        var me = this;

        me.store = Ext.create('Ext.data.Store', {
            fields: ['key', 'label'],
            data: [
                { key: 'DESC', label: me.getDescendingLabel() },
                { key: 'ASC', label: me.getAscendingLabel() }
            ]
        });

        me.callParent(arguments);
    },

    getAscendingLabel: function() {
        return '{s name="ascending"}{/s}';
    },

    getDescendingLabel: function() {
        return '{s name="descending"}{/s}';
    }
});

//{/block}
<|endoftext|>


<commit_before>// @flow

import PropTypes from 'prop-types';
import * as d3 from 'd3';
import _ from 'lodash';
import ReactFauxDOM from 'react-faux-dom';
import { compose } from 'recompose';

import { withTooltip } from '@ncigdc/uikit/Tooltip';
import { withTheme } from '@ncigdc/theme';

const getNestedValue = (item, path) => {
  if (path.length === 1) {
    return item[path[0]];
  }

  const nextItem = item[path[0]];
  path.shift();

  return getNestedValue(nextItem, path);
};

const PieChart = compose(
  withTooltip,
  withTheme
)(
  ({
    data,
    path = 'file_count',
    height = 160,
    width = 160,
    setTooltip,
    marginTop = 0,
  }) => {
    const color = d3.scaleOrdinal(d3.schemeCategory20);
    const outerRadius = height / 2 + 10;

    const node = ReactFauxDOM.createElement('div');
    node.style.setProperty('margin-top', `${marginTop}px`);
    node.style.setProperty('display', 'flex');
    node.style.setProperty('justify-content', 'center');
    node.setAttribute('class', 'test-pie-chart');

    const pie = d3.pie().value(d => getNestedValue(d, path.split('.')));

    const arc = d3
      .arc()
      .padRadius(outerRadius)
      .innerRadius(0);

    const svg = d3
      .select(node)
      .append('svg')
      .attr('width', width)
      .attr('height', height)
      .append('g')
      .attr('transform', `translate(${width / 2}, ${height / 2})`);

    const g = svg
      .selectAll('.arc')
      .data(pie(data))
      .enter()
      .append('g')
      .each(d => {
        d.outerRadius = outerRadius - 20;
      })
      .attr('class', 'arc')
      .attr('stroke', '#fff')
      .attr('stroke-width', '0.5');

    const gHover = svg
      .selectAll('.arc-hover')
      .data(pie(data))
      .enter()
      .append('g')
      .each(d => {
        d.outerRadius = outerRadius - 15;
      })
      .attr('class', 'arc-hover');

    const gPath = g.append('path');
    const gHoverPath = gHover.append('path');

    gPath.attr('d', arc).style('fill', (d, i) => color(i));

    const fillHover = gHoverPath
      .attr('d', arc)
      .style('fill', (d, i) => color(i))
      .style('opacity', 0);

    fillHover
      .attr('class', d => `pointer arc-hover-${_.snakeCase(d.data.id)}`)
      .on('mouseenter', d => {
        document.querySelector(
          `.arc-hover-${_.snakeCase(d.data.id)}`
        ).style.opacity = 0.5;
        setTooltip(d.data.tooltip);
      })
      .on('mouseleave', d => {
        document.querySelector(
          `.arc-hover-${_.snakeCase(d.data.id)}`
        ).style.opacity = 0;
        setTooltip();
      })
      .on('mousedown', d => {
        if (d.data.clickHandler) {
          d.data.clickHandler(d);
          setTooltip();
        }
      });

    return node.toReact();
  }
);

PieChart.propTypes = {
  data: PropTypes.array,
};

/*----------------------------------------------------------------------------*/

export default PieChart;
<commit_msg>remove border from pie charts<commit_after>// @flow

import PropTypes from 'prop-types';
import * as d3 from 'd3';
import _ from 'lodash';
import ReactFauxDOM from 'react-faux-dom';
import { compose } from 'recompose';

import { withTooltip } from '@ncigdc/uikit/Tooltip';
import { withTheme } from '@ncigdc/theme';

const getNestedValue = (item, path) => {
  if (path.length === 1) {
    return item[path[0]];
  }

  const nextItem = item[path[0]];
  path.shift();

  return getNestedValue(nextItem, path);
};

const PieChart = compose(
  withTooltip,
  withTheme
)(
  ({
    data,
    path = 'file_count',
    height = 160,
    width = 160,
    setTooltip,
    marginTop = 0,
  }) => {
    const color = d3.scaleOrdinal(d3.schemeCategory20);
    const outerRadius = height / 2 + 10;

    const node = ReactFauxDOM.createElement('div');
    node.style.setProperty('margin-top', `${marginTop}px`);
    node.style.setProperty('display', 'flex');
    node.style.setProperty('justify-content', 'center');
    node.setAttribute('class', 'test-pie-chart');

    const pie = d3.pie().value(d => getNestedValue(d, path.split('.')));

    const arc = d3
      .arc()
      .padRadius(outerRadius)
      .innerRadius(0);

    const svg = d3
      .select(node)
      .append('svg')
      .attr('width', width)
      .attr('height', height)
      .append('g')
      .attr('transform', `translate(${width / 2}, ${height / 2})`);

    const g = svg
      .selectAll('.arc')
      .data(pie(data))
      .enter()
      .append('g')
      .each(d => {
        d.outerRadius = outerRadius - 20;
      })
      .attr('class', 'arc');

    const gHover = svg
      .selectAll('.arc-hover')
      .data(pie(data))
      .enter()
      .append('g')
      .each(d => {
        d.outerRadius = outerRadius - 15;
      })
      .attr('class', 'arc-hover');

    const gPath = g.append('path');
    const gHoverPath = gHover.append('path');

    gPath.attr('d', arc).style('fill', (d, i) => color(i));

    const fillHover = gHoverPath
      .attr('d', arc)
      .style('fill', (d, i) => color(i))
      .style('opacity', 0);

    fillHover
      .attr('class', d => `pointer arc-hover-${_.snakeCase(d.data.id)}`)
      .on('mouseenter', d => {
        document.querySelector(
          `.arc-hover-${_.snakeCase(d.data.id)}`
        ).style.opacity = 0.5;
        setTooltip(d.data.tooltip);
      })
      .on('mouseleave', d => {
        document.querySelector(
          `.arc-hover-${_.snakeCase(d.data.id)}`
        ).style.opacity = 0;
        setTooltip();
      })
      .on('mousedown', d => {
        if (d.data.clickHandler) {
          d.data.clickHandler(d);
          setTooltip();
        }
      });

    return node.toReact();
  }
);

PieChart.propTypes = {
  data: PropTypes.array,
};

/*----------------------------------------------------------------------------*/

export default PieChart;
<|endoftext|>


<commit_before>function OverviewController($scope, $http, $location) {
    $http.get('gui/accounts/2/')
        .success(function(d) {
            $scope.accounts = d;
        });

    $scope.account = "";
    $scope.exists = function(account) {
        return false;
    };

    $scope.create = function(account) {
        $http.put('gui/accounts/' + encodeURIComponent(account), {})
            .success(function() {
                $location.path('/account/' + account);
            });
    }
}
<commit_msg>encode url<commit_after>function OverviewController($scope, $http, $location) {
    $http.get('gui/accounts/2/')
        .success(function(d) {
            $scope.accounts = d;
        });

    $scope.account = "";
    $scope.exists = function(account) {
        return false;
    };

    $scope.create = function(account) {
        $http.put('gui/accounts/' + encodeURIComponent(account), {})
            .success(function() {
                $location.path('/account/' + encodeURIComponent(account));
            });
    }
}
<|endoftext|>


<commit_before>var canIWatch = function(age){
    if(age < 6){
        return "You are not allowed to watch Deadpool after 6.00pm.";
    }else if(age >= 6 && age < 17){
        return "You must be accompanied by a guardian who is 21 or older.";
    }else if(age >= 17 && age < 25){
        return "You are allowed to watch Deadpool, right after you show some ID.";
    }else if(age > 25){
        return "Yay! You can watch Deadpool with no strings attached!";
    }else{
        return "Invalid age.";
    }
};

module.exports = canIWatch
<commit_msg>add movie labe<commit_after>var canIWatch = function(age){
    if(age > 0 && age < 6){
        return "You are not allowed to watch Deadpool after 6.00pm.";
    }else if(age >= 6 && age < 17){
        return "You must be accompanied by a guardian who is 21 or older.";
    }else if(age >= 17 && age < 25){
        return "You are allowed to watch Deadpool, right after you show some ID.";
    }else if(age >= 25){
        return "Yay! You can watch Deadpool with no strings attached!";
    }else{
        return "Invalid age.";
    }
};

module.exports = canIWatch
<|endoftext|>


<commit_before>/*eslint-env node */
module.exports = function(Schaetzer) {

	Schaetzer.notSyncedTo = function(opKey, cb) {
	  console.log(JSON.stringify(Schaetzer.app.models));
      var SyncModel = Schaetzer.app.models.SchaetzerSyncToOperator;

	  SyncModel.find(
	  {
	  	 where: {and: [  {operatorKey: opKey}
	  	               , {sentToOperatorDate: null}]}
	    ,include : {relation: "schaetzer"}
	  },
	  function(err, syncArray) {
	    console.log(JSON.stringify(syncArray));
            var result = [];
	    if (syncArray) {
              result = syncArray.map(function(currentValue) {
		         //console.log("inArray: " + JSON.stringify(currentValue));
                 //console.log("");
                 //console.log(currentValue.schaetzer());
                 var schaetzer = currentValue.schaetzer();
                 if (schaetzer.operatorKey !== opKey) {
                    return schaetzer;
                 }
              }).filter(function(item) { return item != null;});
	    }
	    cb(err, result);
	  });
	};

    Schaetzer.isSynced = function(id, opKey, cb) {
      //var SyncModel = Schaetzer.app.models.SchaetzerSyncToOperator;

      var result = "";

	  var schaetzer = Schaetzer.findById(id, {

	    include : {
	    	relation: "sync",

	        scope: {
	          where: {operatorKey: opKey}
	        }
	      }
	  }, function(err, schaetzer) {

	      if (schaetzer != null) {
	      	console.log(JSON.stringify(schaetzer));
	      	schaetzer.sync({where: {operatorKey: opKey}}, function(err, syncArray) {

			    console.log(JSON.stringify(syncArray));

			    if (syncArray) {
					syncArray[0].sentToOperatorDate = new Date();
					syncArray[0].save();
					result = syncArray[0].sentToOperatorDate.toISOString();
			    }
			    cb(err, result);
			  });
		  }
		  else {
		  	cb(err, null);
		  }
	  });
	};

    Schaetzer.remoteMethod(
    	'notSyncedTo',
    	{
    	accepts: {arg: 'opKey', type: 'string', required: true},
        http: {path: '/notSyncedTo/:opKey', verb: 'get'},
        returns: { type: 'array', root:true}
    	});

    Schaetzer.remoteMethod(
    	'isSynced',
    	{
    	accepts: [
    	  {arg: 'id', type: 'string', required: true},
    	  {arg: 'opKey', type: 'string', required: true}
    	],
        http: {path: '/:id/isSynced/:opKey', verb: 'post'},
        returns: { arg: 'sentToOperatorDate', type: 'string'}
    	});
};
<commit_msg>Fix: NotSyncedTo returns schaetzer that where created by the requesting operator<commit_after>/*eslint-env node */
module.exports = function(Schaetzer) {

	Schaetzer.notSyncedTo = function(opKey, cb) {
	  console.log(JSON.stringify(Schaetzer.app.models));
      var SyncModel = Schaetzer.app.models.SchaetzerSyncToOperator;

	  SyncModel.find(
	  {
	  	 where: {and: [  {operatorKey: opKey}
	  	               , {sentToOperatorDate: null}]}
	    ,include : {relation: "schaetzer"}
	  },
	  function(err, syncArray) {
	    console.log(JSON.stringify(syncArray));
            var result = [];
	    if (syncArray) {
              result = syncArray.map(function(currentValue) {
		         //console.log("inArray: " + JSON.stringify(currentValue));
                 //console.log("");
                 //console.log(currentValue.schaetzer());
                 var schaetzer = currentValue.schaetzer();
                 //if (schaetzer.operatorKey !== opKey) {
                    return schaetzer;
                 //}
              }).filter(function(item) { return item != null;});
	    }
	    cb(err, result);
	  });
	};

    Schaetzer.isSynced = function(id, opKey, cb) {
      //var SyncModel = Schaetzer.app.models.SchaetzerSyncToOperator;

      var result = "";

	  var schaetzer = Schaetzer.findById(id, {

	    include : {
	    	relation: "sync",

	        scope: {
	          where: {operatorKey: opKey}
	        }
	      }
	  }, function(err, schaetzer) {

	      if (schaetzer != null) {
	      	console.log(JSON.stringify(schaetzer));
	      	schaetzer.sync({where: {operatorKey: opKey}}, function(err, syncArray) {

			    console.log(JSON.stringify(syncArray));

			    if (syncArray) {
					syncArray[0].sentToOperatorDate = new Date();
					syncArray[0].save();
					result = syncArray[0].sentToOperatorDate.toISOString();
			    }
			    cb(err, result);
			  });
		  }
		  else {
		  	cb(err, null);
		  }
	  });
	};

    Schaetzer.remoteMethod(
    	'notSyncedTo',
    	{
    	accepts: {arg: 'opKey', type: 'string', required: true},
        http: {path: '/notSyncedTo/:opKey', verb: 'get'},
        returns: { type: 'array', root:true}
    	});

    Schaetzer.remoteMethod(
    	'isSynced',
    	{
    	accepts: [
    	  {arg: 'id', type: 'string', required: true},
    	  {arg: 'opKey', type: 'string', required: true}
    	],
        http: {path: '/:id/isSynced/:opKey', verb: 'post'},
        returns: { arg: 'sentToOperatorDate', type: 'string'}
    	});
};
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

// see ./animatron-project-@VERSION.orderly for a readable scheme of accepted project

var AnimatronImporter = (function() {

function AnimatronImporter() { }

var C = anm.C,
    Scene = anm.Scene,
    Element = anm.Element,
    Path = anm.Path,
    Text = anm.Text,
    Bands = anm.Bands,
    test = anm._valcheck;

// ** META / PARAMS **

AnimatronImporter.prototype.configureMeta = function(prj) {
    // ( id, name, author, copyright, version, description, modificationTime, numberOfScenes )
    var _m = prj.meta;
    return {
        'title': _m.name,
        'author': _m.author,
        'copyright': _m.copyright,
        'version': _m.version,
        'description': _m.description,
        'duration': _m.duration
    };
};
AnimatronImporter.prototype.configureAnim = function(prj) {
    // ( framerate, dimension, background, duration,
    //   elements, scenes )
    var _a = prj.anim;
    return {
        'fps': _a.framerate,
        'width': _a.dimension ? Math.floor(_a.dimension[0]) : undefined,
        'height': _a.dimension ? Math.floor(_a.dimension[1]): undefined,
        'bgcolor': _a.background ? Convert.fill(_a.background) : null,
    }
}

// ** PROJECT **

AnimatronImporter.prototype.load = function(prj) {
    // ( framerate, dimension, background, duration,
    //   elements, scenes )
    // FIXME: allow importing several scenes
    var scene =  this.importScene(prj.anim.scenes[0],
                                  prj.anim.elements);
    if (prj.meta.duration != undefined) scene.setDuration(prj.meta.duration);
    if (prj.anim.background) scene.bgfill = Convert.fill(prj.anim.background);
    return scene;
};

// ** ELEMENTS **

AnimatronImporter.prototype.importScene = function(scene_id, source) {
    var scene = new Scene();
    var node = this.findNode(scene_id, source);
    if (!node) throw new Error("Scene was not found by ID");
    if (extract_type(node.id) != TYPE_SCENE) throw new Error("Given Scene ID points to something else");
    scene.add(this.convertNode(node, source));
    return scene;
}

var TYPE_UNKNOWN = "00",
    TYPE_CLIP    = "01",
    TYPE_SCENE   = "02",
    TYPE_PATH    = "03",
    TYPE_TEXT    = "04",
    TYPE_RECT    = "05",
    TYPE_OVAL    = "06",
    TYPE_PENCIL  = "07",
    TYPE_IMAGE   = "08",
    TYPE_GROUP   = "09",
    TYPE_BRUSH   = "0a",
    TYPE_STAR    = "0b",
    TYPE_POLYGON = "0c",
    TYPE_CURVE   = "0d",
    TYPE_AUDIO   = "0e",
    TYPE_LINE    = "0f";

AnimatronImporter.prototype.convertNode = function(src, all) {
//AnimatronImporter.prototype.importElement = function(trg, src, in_band) {
    var trg;
    var type = extract_type(src.id);
    // TODO: move to Converters object?
    // if a node is a group type
    if ((type == TYPE_CLIP) || (type == TYPE_GROUP) || (type == TYPE_SCENE)) {
        trg = new Element();
        trg.name = src.name;
        // iterate through the layers
        var _layers = src.layers,
            _layers_targets = [];
        // in Animatron. layers are in reverse order
        for (var li = _layers.length; li--;) {
            var lsrc = _layers[li],
                ltype = extract_type(lsrc.eid);
            // recursively check if layer element is a group or not and return the element
            var ltrg = this.convertNode(this.findNode(lsrc.eid, all), all);
            if (!ltrg.name) { ltrg.name = lsrc.name; }
            // transfer layer data from the layer source into the
            // target — contains bands, tweens and pivot
            this._transferLayerData(lsrc, ltrg, trg.xdata.gband, ltype);
            if (!lsrc.masked) {
                // layer is a normal one
                trg.add(ltrg);
                _layers_targets.push(ltrg);
            } else {
                // layer is a mask, apply it to the required number
                // of previously collected layers
                var mask = ltrg,
                    maskedToGo = lsrc.masked, // layers below to apply mask
                    ltl = _layers_targets.length;
                if (maskedToGo > ltl) {
                    throw new Error('No layers collected to apply mask')
                };
                while (maskedToGo) {
                    var masked = _layers_targets[ltl-maskedToGo];
                    //console.log(mask.name + '->' + masked.name);
                    masked.setMask(mask);
                    maskedToGo--;
                }
            }
        }
        // transfer repetition data from the source layer
        // into the target (incl. end or on-end action)
        this._transferRepetitionData(src, trg);
    } else if
      ((type != TYPE_UNKNOWN)
      /*(type == TYPE_PATH)  || (type == TYPE_TEXT)   || (type == TYPE_RECT)    ||
        (type == TYPE_OVAL)  || (type == TYPE_PENCIL) || (type == TYPE_IMAGE)   ||
        (type == TYPE_BRUSH) || (type == TYPE_STAR)   || (type == TYPE_POLYGON) ||
        (type == TYPE_CURVE) || (type == AUDIO)       || (type == LINE)*/) {
        trg = new Element();
        trg.name = src.name;
        // transfer shape data from the source into the
        // target — contains either path, text or image
        this._transferShapeData(src, trg, type);
        // FIXME: fire an event instead (event should inform about type of the importer)
        if (trg.importCustomData) trg.importCustomData(src);
    }
    /*if (trg &&
        (trg.xdata.mode != C.R_ONCE) &&
        (trg.children.length > 0) &&
        (!test.finite(trg.xdata.gband[1]))) {
        trg.makeBandFit();
    }*/
    return trg;
}
AnimatronImporter.prototype.findNode = function(id, source) {
    for (var i = 0; i < source.length; i++) {
        if (source[i].id === id) return source[i];
    }
    throw new Error("Node with id " + id + " was not found in passed source");
}
AnimatronImporter.prototype._transferShapeData = function(src, trg, type) {
    if (src.url && (type == TYPE_IMAGE)) trg.xdata.sheet = Convert.sheet(src.url, src.size);
    if (src.path) trg.xdata.path = Convert.path(src.path, src.fill, src.stroke, src.shadow);
    if (src.text) trg.xdata.path = Convert.text(src.text, src.font,
                                                src.fill, src.stroke, src.shadow);
}
// collect required data from source layer
AnimatronImporter.prototype._transferLayerData = function(src, trg, in_band, type) {
    if (src.visible === false) trg.disabled = true; // to.visible = false;
    var x = trg.xdata;
    if (type == TYPE_GROUP) {
        x.gband = [ 0, src.band[1] ];
        x.lband = [ 0, src.band[1] ];
        // x.gband = Convert.band(src.band);
        // x.lband = [ x.gband[0] - in_band[0],
        //             x.gband[1] - in_band[0] ];
    } else {
        x.lband = Convert.band(src.band);
        x.gband = in_band ? Bands.wrap(in_band, x.lband)
                          : x.lband;
    }
    x.pvt = [ 0, 0 ];
    x.reg = src.reg || [ 0, 0 ];
    if (src.tweens) {
        var translate;
        for (var tweens = src.tweens, ti = 0, tl = tweens.length;
             ti < tl; ti++) {
            if (tweens[ti].type == 'Translate') translate = tweens[ti];
            trg.addTween(Convert.tween(tweens[ti]));
        }
        if (translate && src['rotate-to-path']) {
            trg.addTween({
                type: C.T_ROT_TO_PATH,
                band: translate.band
            });
        }
    }
};
AnimatronImporter.prototype._transferRepetitionData = function(src, trg) {
    // 'on-end' is the old-style end, 'end' is the current-style
    var x = trg.xdata;
    x.mode = src['end'] ? Convert.mode(src['end'].type)
                        : Convert.oldschool_mode(src['on-end']);
    x.nrep = (src['end'] && (src['end'].counter !== undefined))
                        ? src['end'].counter : Infinity;

    if (x.mode == C.R_LOOP) {
        trg.travelChildren(function(child) {
            child.xdata.mode = C.R_STAY;
        });
    }
};

// ** CONVERTION **

var TYPE_UNKNOWN = "00",
    TYPE_CLIP    = "01",
    TYPE_SCENE   = "02",
    TYPE_PATH    = "03",
    TYPE_TEXT    = "04",
    TYPE_RECT    = "05",
    TYPE_OVAL    = "06",
    TYPE_PENCIL  = "07",
    TYPE_IMAGE   = "08",
    TYPE_GROUP   = "09",
    TYPE_BRUSH   = "0a",
    TYPE_STAR    = "0b",
    TYPE_POLYGON = "0c",
    TYPE_CURVE   = "0d",
    TYPE_AUDIO   = "0e",
    TYPE_LINE    = "0f";
function extract_type(id) {
    if (id.length !== 24) throw new Error('Invalid element id ' + id);
    return id.substring(id.length - 2);
}

var Convert = {}
Convert.tween = function(tween) {
    // (type, band, path?, easing?)
    var _t = tween,
        _type = Convert.tweenType(_t.type);

    return {
        'band': _t.band,
        'type': _type,
        'data': Convert.tweenData(_type, _t),
        'easing': Convert.easing(_t.easing)
    };
};
Convert.tweenType = function(from) {
    if (!from) return null;
    if (from === 'Rotate') return C.T_ROTATE;
    if (from === 'Translate') return C.T_TRANSLATE;
    if (from === 'Alpha') return C.T_ALPHA;
    if (from === 'Scale') return C.T_SCALE;
    if (from === 'rotate-to-path') return C.T_ROT_TO_PATH;
    if (from === 'Shear') return C.T_SHEAR;
}
Convert.tweenData = function(type, tween) {
    if (!tween.data) {
        if (tween.path) return new Path(tween.path);
        return null;
    }
    if (type === C.T_SCALE) {
        var data = tween.data;
        return [ [ data[0], data[1] ],
                 [ data[2], data[3] ] ];
    }
    return tween.data;
}
Convert.path = function(pathStr, fill, stroke, shadow) {
    // ()
    return new Path(pathStr,
                    Convert.fill(fill),
                    Convert.stroke(stroke),
                    Convert.shadow(shadow));
}
Convert.text = function(lines, font,
                        fill, stroke, shadow) {
    // (lines, font, stroke, fill)
    return new Text(lines, font,
                    Convert.fill(fill),
                    Convert.stroke(stroke),
                    Convert.shadow(shadow));
}
Convert.sheet = function(url, size) {
    var sheet = new anm.Sheet(url);
    sheet._dimen = size;
    return sheet;
}
Convert.shadow = function(src) {
  if (!src || src.offsetX == undefined) return null;
  var shadow = {};
  shadow.color = src.paint.rgba || src.paint.color;
  shadow.offsetX = src.offsetX;
  shadow.offsetY = src.offsetY;
  shadow.blurRadius = src.blur;
  return shadow;
};
Convert.easing = function(from) {
    // (name, path?)
    if (!from) return null;
    return {
          type: Convert.easingType(from.name),
          data: from.path ? (new Path('M0 0 ' + from.path + ' Z')) : null
        };
}
Convert.easingType = function(from) {
    if (!from) return null;
    if (from === 'Unknown') return C.E_PATH;
    if (from === 'Default') return C.E_DEF;
    if (from === 'Ease In') return C.E_IN;
    if (from === 'Ease Out') return C.E_OUT;
    if (from === 'Ease In Out') return C.E_INOUT;
}
Convert.stroke = function(stroke) {
    // (width, paint (color | colors | rgba | rgbas | r0, r1),
    // cap, join, limit)
    if (!stroke) return stroke;
    var brush = {};
    brush.width = stroke.width;
    brush.cap = stroke.cap;
    brush.join = stroke.join;
    if (stroke.paint) {
        var paint = stroke.paint;
        if (paint.rgba || paint.color) {
            brush.color = paint.rgba || paint.color;
        } else if ((typeof paint.r0 !== 'undefined')
                && (typeof paint.r1 !== 'undefined')) {
            brush.rgrad = Convert.gradient(paint);
        } else if (stroke.paint.colors) {
            brush.lgrad = Convert.gradient(paint);
        }
    }
    return brush;
}
Convert.fill = function(fill) {
    // (color | colors | rgba | rgbas | r0, r1)
    if (!fill) return null;
    var brush = {};
    if (!fill) {
        brush.color = "rgba(0,0,0,0)";
    } else if (fill.rgba || fill.color) {
        brush.color = fill.rgba || fill.color;
    } else if ((typeof fill.r0 !== 'undefined')
            && (typeof fill.r1 !== 'undefined')) {
        brush.rgrad = Convert.gradient(fill);
    } else if (fill.rgbas || fill.colors) {
        brush.lgrad = Convert.gradient(fill);
    }
    return brush;
}
Convert.gradient = function(src) {
    // (bounds, offsets, colors, x1, y1, r0?, r1?, alpha)
    var stops = [],
        offsets = src.offsets;
    for (var i = 0; i < offsets.length; i++) {
        stops.push([
            offsets[i],
            src.rgbas ? src.rgbas[i]
                     : src.colors[i]
        ]);
    }
    return {
        r: (typeof src.r0 !== 'undefined') ? [ src.r0, src.r1 ] : null,
        dir: [ [ src.x0, src.y0 ], [ src.x1, src.y1 ] ],
        stops: stops,
        bounds: src.bounds
    };
}
Convert.band = function(from) {
    if (!from) return [ 0, Infinity ];
    if (from.length == 2) return from;
    if (from.length == 1) return [ from[0], Infinity ];
    return [ 0, Infinity ];
}
Convert.mode = function(from) {
    if (!from) return C.R_ONCE;
    if (from === "once") return C.R_ONCE;
    if (from === "stay") return C.R_STAY;
    if (from === "loop") return C.R_LOOP;
    if (from === "bounce") return C.R_BOUNCE; // FIXME: last is not for sure
}
Convert.oldschool_mode = function(from) {
    if (!from) return C.R_ONCE;
    if (from === "STOP") return C.R_ONCE;
    if (from === "LOOP") return C.R_LOOP;
    if (from === "BOUNCE") return C.R_BOUNCE; // FIXME: last is not for sure
}

return AnimatronImporter;

})();<commit_msg>loop, not stay<commit_after>/*
 * Copyright (c) 2011-2013 by Animatron.
 * All rights are reserved.
 *
 * Animatron Player is licensed under the MIT License, see LICENSE.
 *
 * @VERSION
 */

// see ./animatron-project-@VERSION.orderly for a readable scheme of accepted project

var AnimatronImporter = (function() {

function AnimatronImporter() { }

var C = anm.C,
    Scene = anm.Scene,
    Element = anm.Element,
    Path = anm.Path,
    Text = anm.Text,
    Bands = anm.Bands,
    test = anm._valcheck;

// ** META / PARAMS **

AnimatronImporter.prototype.configureMeta = function(prj) {
    // ( id, name, author, copyright, version, description, modificationTime, numberOfScenes )
    var _m = prj.meta;
    return {
        'title': _m.name,
        'author': _m.author,
        'copyright': _m.copyright,
        'version': _m.version,
        'description': _m.description,
        'duration': _m.duration
    };
};
AnimatronImporter.prototype.configureAnim = function(prj) {
    // ( framerate, dimension, background, duration,
    //   elements, scenes )
    var _a = prj.anim;
    return {
        'fps': _a.framerate,
        'width': _a.dimension ? Math.floor(_a.dimension[0]) : undefined,
        'height': _a.dimension ? Math.floor(_a.dimension[1]): undefined,
        'bgcolor': _a.background ? Convert.fill(_a.background) : null,
    }
}

// ** PROJECT **

AnimatronImporter.prototype.load = function(prj) {
    // ( framerate, dimension, background, duration,
    //   elements, scenes )
    // FIXME: allow importing several scenes
    var scene =  this.importScene(prj.anim.scenes[0],
                                  prj.anim.elements);
    if (prj.meta.duration != undefined) scene.setDuration(prj.meta.duration);
    if (prj.anim.background) scene.bgfill = Convert.fill(prj.anim.background);
    return scene;
};

// ** ELEMENTS **

AnimatronImporter.prototype.importScene = function(scene_id, source) {
    var scene = new Scene();
    var node = this.findNode(scene_id, source);
    if (!node) throw new Error("Scene was not found by ID");
    if (extract_type(node.id) != TYPE_SCENE) throw new Error("Given Scene ID points to something else");
    scene.add(this.convertNode(node, source));
    return scene;
}

var TYPE_UNKNOWN = "00",
    TYPE_CLIP    = "01",
    TYPE_SCENE   = "02",
    TYPE_PATH    = "03",
    TYPE_TEXT    = "04",
    TYPE_RECT    = "05",
    TYPE_OVAL    = "06",
    TYPE_PENCIL  = "07",
    TYPE_IMAGE   = "08",
    TYPE_GROUP   = "09",
    TYPE_BRUSH   = "0a",
    TYPE_STAR    = "0b",
    TYPE_POLYGON = "0c",
    TYPE_CURVE   = "0d",
    TYPE_AUDIO   = "0e",
    TYPE_LINE    = "0f";

AnimatronImporter.prototype.convertNode = function(src, all) {
//AnimatronImporter.prototype.importElement = function(trg, src, in_band) {
    var trg;
    var type = extract_type(src.id);
    // TODO: move to Converters object?
    // if a node is a group type
    if ((type == TYPE_CLIP) || (type == TYPE_GROUP) || (type == TYPE_SCENE)) {
        trg = new Element();
        trg.name = src.name;
        // iterate through the layers
        var _layers = src.layers,
            _layers_targets = [];
        // in Animatron. layers are in reverse order
        for (var li = _layers.length; li--;) {
            var lsrc = _layers[li],
                ltype = extract_type(lsrc.eid);
            // recursively check if layer element is a group or not and return the element
            var ltrg = this.convertNode(this.findNode(lsrc.eid, all), all);
            if (!ltrg.name) { ltrg.name = lsrc.name; }
            // transfer layer data from the layer source into the
            // target — contains bands, tweens and pivot
            this._transferLayerData(lsrc, ltrg, trg.xdata.gband, ltype);
            if (!lsrc.masked) {
                // layer is a normal one
                trg.add(ltrg);
                _layers_targets.push(ltrg);
            } else {
                // layer is a mask, apply it to the required number
                // of previously collected layers
                var mask = ltrg,
                    maskedToGo = lsrc.masked, // layers below to apply mask
                    ltl = _layers_targets.length;
                if (maskedToGo > ltl) {
                    throw new Error('No layers collected to apply mask')
                };
                while (maskedToGo) {
                    var masked = _layers_targets[ltl-maskedToGo];
                    //console.log(mask.name + '->' + masked.name);
                    masked.setMask(mask);
                    maskedToGo--;
                }
            }
        }
        // transfer repetition data from the source layer
        // into the target (incl. end or on-end action)
        this._transferRepetitionData(src, trg);
    } else if
      ((type != TYPE_UNKNOWN)
      /*(type == TYPE_PATH)  || (type == TYPE_TEXT)   || (type == TYPE_RECT)    ||
        (type == TYPE_OVAL)  || (type == TYPE_PENCIL) || (type == TYPE_IMAGE)   ||
        (type == TYPE_BRUSH) || (type == TYPE_STAR)   || (type == TYPE_POLYGON) ||
        (type == TYPE_CURVE) || (type == AUDIO)       || (type == LINE)*/) {
        trg = new Element();
        trg.name = src.name;
        // transfer shape data from the source into the
        // target — contains either path, text or image
        this._transferShapeData(src, trg, type);
        // FIXME: fire an event instead (event should inform about type of the importer)
        if (trg.importCustomData) trg.importCustomData(src);
    }
    /*if (trg &&
        (trg.xdata.mode != C.R_ONCE) &&
        (trg.children.length > 0) &&
        (!test.finite(trg.xdata.gband[1]))) {
        trg.makeBandFit();
    }*/
    return trg;
}
AnimatronImporter.prototype.findNode = function(id, source) {
    for (var i = 0; i < source.length; i++) {
        if (source[i].id === id) return source[i];
    }
    throw new Error("Node with id " + id + " was not found in passed source");
}
AnimatronImporter.prototype._transferShapeData = function(src, trg, type) {
    if (src.url && (type == TYPE_IMAGE)) trg.xdata.sheet = Convert.sheet(src.url, src.size);
    if (src.path) trg.xdata.path = Convert.path(src.path, src.fill, src.stroke, src.shadow);
    if (src.text) trg.xdata.path = Convert.text(src.text, src.font,
                                                src.fill, src.stroke, src.shadow);
}
// collect required data from source layer
AnimatronImporter.prototype._transferLayerData = function(src, trg, in_band, type) {
    if (src.visible === false) trg.disabled = true; // to.visible = false;
    var x = trg.xdata;
    if (type == TYPE_GROUP) {
        x.gband = [ 0, src.band[1] ];
        x.lband = [ 0, src.band[1] ];
        // x.gband = Convert.band(src.band);
        // x.lband = [ x.gband[0] - in_band[0],
        //             x.gband[1] - in_band[0] ];
    } else {
        x.lband = Convert.band(src.band);
        x.gband = in_band ? Bands.wrap(in_band, x.lband)
                          : x.lband;
    }
    x.pvt = [ 0, 0 ];
    x.reg = src.reg || [ 0, 0 ];
    if (src.tweens) {
        var translate;
        for (var tweens = src.tweens, ti = 0, tl = tweens.length;
             ti < tl; ti++) {
            if (tweens[ti].type == 'Translate') translate = tweens[ti];
            trg.addTween(Convert.tween(tweens[ti]));
        }
        if (translate && src['rotate-to-path']) {
            trg.addTween({
                type: C.T_ROT_TO_PATH,
                band: translate.band
            });
        }
    }
};
AnimatronImporter.prototype._transferRepetitionData = function(src, trg) {
    // 'on-end' is the old-style end, 'end' is the current-style
    var x = trg.xdata;
    x.mode = src['end'] ? Convert.mode(src['end'].type)
                        : Convert.oldschool_mode(src['on-end']);
    x.nrep = (src['end'] && (src['end'].counter !== undefined))
                        ? src['end'].counter : Infinity;

    if (x.mode == C.R_LOOP) {
        trg.travelChildren(function(child) {
            child.xdata.mode = C.R_LOOP;
        });
    }
};

// ** CONVERTION **

var TYPE_UNKNOWN = "00",
    TYPE_CLIP    = "01",
    TYPE_SCENE   = "02",
    TYPE_PATH    = "03",
    TYPE_TEXT    = "04",
    TYPE_RECT    = "05",
    TYPE_OVAL    = "06",
    TYPE_PENCIL  = "07",
    TYPE_IMAGE   = "08",
    TYPE_GROUP   = "09",
    TYPE_BRUSH   = "0a",
    TYPE_STAR    = "0b",
    TYPE_POLYGON = "0c",
    TYPE_CURVE   = "0d",
    TYPE_AUDIO   = "0e",
    TYPE_LINE    = "0f";
function extract_type(id) {
    if (id.length !== 24) throw new Error('Invalid element id ' + id);
    return id.substring(id.length - 2);
}

var Convert = {}
Convert.tween = function(tween) {
    // (type, band, path?, easing?)
    var _t = tween,
        _type = Convert.tweenType(_t.type);

    return {
        'band': _t.band,
        'type': _type,
        'data': Convert.tweenData(_type, _t),
        'easing': Convert.easing(_t.easing)
    };
};
Convert.tweenType = function(from) {
    if (!from) return null;
    if (from === 'Rotate') return C.T_ROTATE;
    if (from === 'Translate') return C.T_TRANSLATE;
    if (from === 'Alpha') return C.T_ALPHA;
    if (from === 'Scale') return C.T_SCALE;
    if (from === 'rotate-to-path') return C.T_ROT_TO_PATH;
    if (from === 'Shear') return C.T_SHEAR;
}
Convert.tweenData = function(type, tween) {
    if (!tween.data) {
        if (tween.path) return new Path(tween.path);
        return null;
    }
    if (type === C.T_SCALE) {
        var data = tween.data;
        return [ [ data[0], data[1] ],
                 [ data[2], data[3] ] ];
    }
    return tween.data;
}
Convert.path = function(pathStr, fill, stroke, shadow) {
    // ()
    return new Path(pathStr,
                    Convert.fill(fill),
                    Convert.stroke(stroke),
                    Convert.shadow(shadow));
}
Convert.text = function(lines, font,
                        fill, stroke, shadow) {
    // (lines, font, stroke, fill)
    return new Text(lines, font,
                    Convert.fill(fill),
                    Convert.stroke(stroke),
                    Convert.shadow(shadow));
}
Convert.sheet = function(url, size) {
    var sheet = new anm.Sheet(url);
    sheet._dimen = size;
    return sheet;
}
Convert.shadow = function(src) {
  if (!src || src.offsetX == undefined) return null;
  var shadow = {};
  shadow.color = src.paint.rgba || src.paint.color;
  shadow.offsetX = src.offsetX;
  shadow.offsetY = src.offsetY;
  shadow.blurRadius = src.blur;
  return shadow;
};
Convert.easing = function(from) {
    // (name, path?)
    if (!from) return null;
    return {
          type: Convert.easingType(from.name),
          data: from.path ? (new Path('M0 0 ' + from.path + ' Z')) : null
        };
}
Convert.easingType = function(from) {
    if (!from) return null;
    if (from === 'Unknown') return C.E_PATH;
    if (from === 'Default') return C.E_DEF;
    if (from === 'Ease In') return C.E_IN;
    if (from === 'Ease Out') return C.E_OUT;
    if (from === 'Ease In Out') return C.E_INOUT;
}
Convert.stroke = function(stroke) {
    // (width, paint (color | colors | rgba | rgbas | r0, r1),
    // cap, join, limit)
    if (!stroke) return stroke;
    var brush = {};
    brush.width = stroke.width;
    brush.cap = stroke.cap;
    brush.join = stroke.join;
    if (stroke.paint) {
        var paint = stroke.paint;
        if (paint.rgba || paint.color) {
            brush.color = paint.rgba || paint.color;
        } else if ((typeof paint.r0 !== 'undefined')
                && (typeof paint.r1 !== 'undefined')) {
            brush.rgrad = Convert.gradient(paint);
        } else if (stroke.paint.colors) {
            brush.lgrad = Convert.gradient(paint);
        }
    }
    return brush;
}
Convert.fill = function(fill) {
    // (color | colors | rgba | rgbas | r0, r1)
    if (!fill) return null;
    var brush = {};
    if (!fill) {
        brush.color = "rgba(0,0,0,0)";
    } else if (fill.rgba || fill.color) {
        brush.color = fill.rgba || fill.color;
    } else if ((typeof fill.r0 !== 'undefined')
            && (typeof fill.r1 !== 'undefined')) {
        brush.rgrad = Convert.gradient(fill);
    } else if (fill.rgbas || fill.colors) {
        brush.lgrad = Convert.gradient(fill);
    }
    return brush;
}
Convert.gradient = function(src) {
    // (bounds, offsets, colors, x1, y1, r0?, r1?, alpha)
    var stops = [],
        offsets = src.offsets;
    for (var i = 0; i < offsets.length; i++) {
        stops.push([
            offsets[i],
            src.rgbas ? src.rgbas[i]
                     : src.colors[i]
        ]);
    }
    return {
        r: (typeof src.r0 !== 'undefined') ? [ src.r0, src.r1 ] : null,
        dir: [ [ src.x0, src.y0 ], [ src.x1, src.y1 ] ],
        stops: stops,
        bounds: src.bounds
    };
}
Convert.band = function(from) {
    if (!from) return [ 0, Infinity ];
    if (from.length == 2) return from;
    if (from.length == 1) return [ from[0], Infinity ];
    return [ 0, Infinity ];
}
Convert.mode = function(from) {
    if (!from) return C.R_ONCE;
    if (from === "once") return C.R_ONCE;
    if (from === "stay") return C.R_STAY;
    if (from === "loop") return C.R_LOOP;
    if (from === "bounce") return C.R_BOUNCE; // FIXME: last is not for sure
}
Convert.oldschool_mode = function(from) {
    if (!from) return C.R_ONCE;
    if (from === "STOP") return C.R_ONCE;
    if (from === "LOOP") return C.R_LOOP;
    if (from === "BOUNCE") return C.R_BOUNCE; // FIXME: last is not for sure
}

return AnimatronImporter;

})();<|endoftext|>