<commit_before>var express = require('express')
, fs = require('fs')
, http  = require('http')
, log_stream = openLog('app.log')
, path    = require('path')
, request = require('request')
, xml     = require('xml2js').parseString

var app     = express()
var stops   = require('../data/stops')

var extract_data = function (data, cb) {
  xml(data, function (err, res) {
    if (err) {
      cb(err, null)
    }

    var result    = {}
    , data_body   = res['soap:Envelope']['soap:Body'][0]

    if (data_body === undefined || data_body.getUserRealTimeForecastExByStopResponse === undefined) {
      cb({message:'no data', name:'', lat:'', lon:'', next:[]})
      return
    }

    var data_response = data_body.getUserRealTimeForecastExByStopResponse[0]
    , data_result     = data_response.getUserRealTimeForecastExByStopResult[0]

    if (data_result == 'WsAuthenticationError') {
      cb({error: 'WsAuthenticationError'})
      return
    }

    var data          = JSON.parse(data_result)
    , info            = data.InfoNodo[0]

    result.name       = info.descrNodo
    result.lat        = info.coordLon
    result.lon        = info.coordLat

    result.next       = []

    data.Orari.forEach(function (departure) {
      result.next.push({
        l:   departure.codAzLinea,
        t:   departure.orario,
        ts:  departure.orarioSched,
        rt:  departure.statoPrevisione == 'Prev' ? 1 : 0,
        d:   departure.capDest
      })
    })

    cb(null, result)
  })
}

/* Routes
----------------------------------------------------------------------------- */

module.exports = function (options) {
  log('Starting...')

  app.get('/oracle/:query', function (req, res) {
    request('http://m.atb.no/xmlhttprequest.php?service=routeplannerOracle.getOracleAnswer&question=' + req.params.query, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        body = body.replace(/\n/g, '')
        body = body.replace(/([a-zA-Z])\.([a-zA-Z])/g, '$1.
$2')
        res.send(body)
      }
    })
  })

  app.get('/rt/:stopid', function (req, res){
    if (options.user === '' || options.pass === '') {
      res.json({error:'Webservice username and password missing in config file'})
      return
    }

    if (/\D/.test(req.params.stopid)) {
      res.json({error:'Not a valid stopid'})
      return
    }

    var env = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/soap/envelope/"><soap12:Body><getUserRealTimeForecastExByStop xmlns="http://miz.it/infotransit"><auth><user>'+ options.user +'</user><password>'+ options.pass +'</password></auth><busStopId>' + req.params.stopid + '</busStopId><nForecast>20</nForecast></getUserRealTimeForecastExByStop></soap12:Body></soap12:Envelope>'

    var post_request = {
      host: 'st.atb.no',
      path: '/InfoTransit/userservices.asmx',
      port: 80,
      method: 'POST',
      headers: {
        'Cookie': 'cookie',
        'Content-Type': 'text/xml;charset="utf-8"',
        'SOAPAction': 'http://miz.it/infotransit/getUserRealTimeForecastExByStop',
        'Content-Length': Buffer.byteLength(env)
      }
    }

    var request = http.request( post_request, function (r) {
      var buffer = ''

      r.on( "data", function( data ) {
        buffer = buffer + data
      })

      r.on( "end", function( data ) {
        extract_data(buffer, function (err, data) {
          if (err) {
            res.json({error: 'Something went wrong'})
          }

          res.json(data)
        })
      })
    })

    request.write( env )
    request.end()
  })

  app.get('/stops', function (req, res) {
    res.json(stops.stops)
  })

  return app;
}

function openLog (logfile) {
  return fs.createWriteStream(logfile, {
    flags: 'a', encoding: 'utf8', mode: 0644
  })
}

function log (msg) {
  log_stream.write(msg + '\n')
}

process.on('uncaughtException', function (err) {
  log(err.stack)
})

process.once('SIGTERM', function () {
  log('Stopping...')

  app.on('close', function () {
    log('Stopped.')

    log_stream.on('close', function () {
      process.exit(0)
    }).end()
  })
})
<commit_msg>Update error checks<commit_after>var express = require('express')
, fs = require('fs')
, http  = require('http')
, log_stream = openLog('app.log')
, path    = require('path')
, request = require('request')
, xml     = require('xml2js').parseString

var app     = express()
var stops   = require('../data/stops')

var extract_data = function (data, cb) {
  xml(data, function (err, res) {
    if (err) {
      return cb(err, null)
    }

    var result    = {}
    , data_body   = res['soap:Envelope']['soap:Body'][0]

    if (data_body === undefined || data_body.getUserRealTimeForecastExByStopResponse === undefined) {
      cb({message:'no data', name:'', lat:'', lon:'', next:[]})
      return
    }

    var data_response = data_body.getUserRealTimeForecastExByStopResponse[0]
    , data_result     = data_response.getUserRealTimeForecastExByStopResult[0]

    if (data_result == 'WsAuthenticationError') {
      cb({error: 'WsAuthenticationError'})
      return
    }

    var data          = JSON.parse(data_result)
    , info            = data.InfoNodo[0]

    result.name       = info.descrNodo
    result.lat        = info.coordLon
    result.lon        = info.coordLat

    result.next       = []

    data.Orari.forEach(function (departure) {
      result.next.push({
        l:   departure.codAzLinea,
        t:   departure.orario,
        ts:  departure.orarioSched,
        rt:  departure.statoPrevisione == 'Prev' ? 1 : 0,
        d:   departure.capDest
      })
    })

    cb(null, result)
  })
}

/* Routes
----------------------------------------------------------------------------- */

module.exports = function (options) {
  log('Starting...')

  app.get('/oracle/:query', function (req, res) {
    request('http://m.atb.no/xmlhttprequest.php?service=routeplannerOracle.getOracleAnswer&question=' + req.params.query, function (err, response, body) {
      if (err) {
        return res.json({error:'Ops, somthing went wrong'})
      }

      if (response.statusCode == 200) {
        body = body.replace(/\n/g, '')
        body = body.replace(/([a-zA-Z])\.([a-zA-Z])/g, '$1.
$2')
        res.send(body)
      }
    })
  })

  app.get('/rt/:stopid', function (req, res){
    if (options.user === '' || options.pass === '') {
      return res.json({error:'Webservice username and password missing'})
    }

    if (/\D/.test(req.params.stopid)) {
      return res.json({error:'Not a valid stopid'})
    }

    var env = '<?xml version="1.0" encoding="utf-8"?><soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/soap/envelope/"><soap12:Body><getUserRealTimeForecastExByStop xmlns="http://miz.it/infotransit"><auth><user>'+ options.user +'</user><password>'+ options.pass +'</password></auth><busStopId>' + req.params.stopid + '</busStopId><nForecast>20</nForecast></getUserRealTimeForecastExByStop></soap12:Body></soap12:Envelope>'

    var post_request = {
      host: 'st.atb.no',
      path: '/InfoTransit/userservices.asmx',
      port: 80,
      method: 'POST',
      headers: {
        'Cookie': 'cookie',
        'Content-Type': 'text/xml;charset="utf-8"',
        'SOAPAction': 'http://miz.it/infotransit/getUserRealTimeForecastExByStop',
        'Content-Length': Buffer.byteLength(env)
      }
    }

    var request = http.request( post_request, function (r) {
      var buffer = ''

      r.on( "data", function( data ) {
        buffer = buffer + data
      })

      r.on( "end", function( data ) {
        extract_data(buffer, function (err, data) {
          if (err) {
            res.json({error: 'Something went wrong'})
          }

          res.json(data)
        })
      })
    })

    request.write( env )
    request.end()
  })

  app.get('/stops', function (req, res) {
    res.json(stops.stops)
  })

  return app;
}

function openLog (logfile) {
  return fs.createWriteStream(logfile, {
    flags: 'a', encoding: 'utf8', mode: 0644
  })
}

function log (msg) {
  log_stream.write(msg + '\n')
}

process.on('uncaughtException', function (err) {
  log(err.stack)
})

process.once('SIGTERM', function () {
  log('Stopping...')

  app.on('close', function () {
    log('Stopped.')

    log_stream.on('close', function () {
      process.exit(0)
    }).end()
  })
})
<|endoftext|>


<commit_before>var util               = require('util');
var vm                 = require('vm');
var fs                 = require('fs');
var FileSystemReadOnly = require('./fs-read-only');

//-----------------------------------------------------------------------------
// Sandbox
//-----------------------------------------------------------------------------

var code    = '';
var stdin   = process.openStdin();
var result;

var sandbox_filesystem_path = process.argv[2];
var manifest_hash = process.argv[3];

var manifest;
try {
  manifest = fs.readFileSync(sandbox_filesystem_path + manifest_hash, { encoding: 'utf8' });
  manifest = JSON.parse(manifest);
} catch(error) {
  throw new Error('Error reading code manifest. ' + error);
}

var fsreadonly = new FileSystemReadOnly(sandbox_filesystem_path, manifest);

// Get code
stdin.on('data', function(data) {
  code += data;
});
stdin.on('end', run);

function getSafeRunner() {
  var global = this;
  // Keep it outside of strict mode
  function UserScript(str) {
    // We want a global scoped function that has implicit returns.
    return Function('return eval('+JSON.stringify(str+'')+')');
  }
  // place with a closure that is not exposed thanks to strict mode
  return function run(comm, src) {
    // stop argument / caller attacks
    "use strict";
    var send = function send(event) {
      "use strict";
      //
      // All comm must be serialized properly to avoid attacks, JSON or XJSON
      //
      comm.send(event, JSON.stringify([].slice.call(arguments,1)));
    };
    var __readFileSync = function(path) {
      "use strict";
      return comm.__readFileSync(JSON.stringify([ path ]));
    }
    var exit = function exit(){
      "use strict";
      onmessage = null;
      comm.exit();
    };
    global.console = { log: send.bind(global, 'stdout') };

    // Modify timers to set the __outstanding_timers variable
    global.__outstanding_timers = 0;
    function wrapTimer(fn) {
      "use strict";
      return function(){
        global.__outstanding_timers += 1;
        var callback = arguments[0];
        arguments[0] = function() {
          callback();
          global.__outstanding_timers -= 1;
          global.__check_finished();
        };
        fn.apply(global, arguments);
      };
    }
    global.setImmediate = wrapTimer(comm.timers.setImmediate).bind(global);
    global.clearImmediate = wrapTimer(comm.timers.clearImmediate).bind(global);
    global.setTimeout = wrapTimer(comm.timers.setTimeout).bind(global);
    global.clearTimeout = wrapTimer(comm.timers.clearTimeout).bind(global);

    global.print = send.bind(global, 'stdout');
    global.console = { log: send.bind(global, 'stdout') };
    global.process = {
      stdout: { write: send.bind(global, 'stdout') },
      exit: exit,
      nextTick: global.setImmediate.bind(global),
      version: comm.vars.node_version
    };
    global.__check_finished = function() {
      if (typeof onmessage !== 'function' && global.__outstanding_timers === 0) {
        process.exit();
      }
    };
    global.postMessage = send.bind(global, 'message');
    global.__readFileSync = __readFileSync.bind(global);
    global.global = global._global = global;

    // This is where the user's source code is actually evaluated
    var result = UserScript(src)();
    send('end', result);
  }
};

// Run code
function run() {

  var context = vm.createContext();
  var safeRunner = vm.runInContext('('+getSafeRunner.toString()+')()', context);

  try {
    safeRunner({
      send: function (event, value) {
        "use strict";

        switch (event) {
          case 'stdout':
            process.stdout.write(JSON.parse(value)[0] + '\n');
            break;
          case 'end':
            result = JSON.parse(value)[0];
            break;
          case 'message':
            process.send({ type: 'message', data: JSON.parse(value)[0] });
            break;
          default:
            throw new Error('Unknown event type');
        }
      },
      exit: function(){
        processExit();
      },
      __readFileSync: function(path) {
        path = JSON.parse(path)[0];
        return fsreadonly.readFileSync(String(path));
      },
      timers: {
        setTimeout: wrapTimer(context, setTimeout),
        clearTimeout: wrapTimer(context, clearTimeout),
        setImmediate: wrapTimer(context, setImmediate),
        clearImmediate: wrapTimer(context, clearImmediate)
      },
      vars: {
        node_version: String(process.version)
      }
    }, code);
  }
  catch (e) {
    console.log(e.stack);
    return;
  }

  process.on('message', processMessageListener.bind(null, context));

  process.send({ type: 'ready' });

  // This will exit the process if onmessage was not defined
  checkIfProcessFinished(context);
};

// If the sandboxed code has defined an `onmessage` function, pass the message
// we received to it. Note that we are still worried about what external users
// might pass in to the sandboxed code
function processMessageListener(context, message){
  vm.runInContext('if (typeof onmessage === "function") { onmessage('+ JSON.stringify(String(message)) + '); }', context);
  checkIfProcessFinished(context);
};

// The process should only be considered finished if `onmessage` is not set
// or if the sandboxed code calls `process.exit()` explicitly
function checkIfProcessFinished(context) {
  if(vm.runInContext('typeof onmessage', context) !== 'function' && vm.runInContext('__outstanding_timers', context) <= 0) {
    processExit();
  }
};

// Send the result to the parent process and exit this process
function processExit() {
  console.log('processExit')

  process.removeListener('message', processMessageListener);

  process.send({ type: 'result', data: result });

  process.exit(0);
};

function wrapTimer(context, fn) {
  return function(){
    var timer_context = this;
    var callback = arguments[0];
    arguments[0] = function() {
      callback();
      // checkIfProcessFinished(context);
    };
    fn.apply(timer_context, arguments);
    return;
  };
}
<commit_msg>[TASK] Remove console.log statement<commit_after>var util               = require('util');
var vm                 = require('vm');
var fs                 = require('fs');
var FileSystemReadOnly = require('./fs-read-only');

//-----------------------------------------------------------------------------
// Sandbox
//-----------------------------------------------------------------------------

var code    = '';
var stdin   = process.openStdin();
var result;

var sandbox_filesystem_path = process.argv[2];
var manifest_hash = process.argv[3];

var manifest;
try {
  manifest = fs.readFileSync(sandbox_filesystem_path + manifest_hash, { encoding: 'utf8' });
  manifest = JSON.parse(manifest);
} catch(error) {
  throw new Error('Error reading code manifest. ' + error);
}

var fsreadonly = new FileSystemReadOnly(sandbox_filesystem_path, manifest);

// Get code
stdin.on('data', function(data) {
  code += data;
});
stdin.on('end', run);

function getSafeRunner() {
  var global = this;
  // Keep it outside of strict mode
  function UserScript(str) {
    // We want a global scoped function that has implicit returns.
    return Function('return eval('+JSON.stringify(str+'')+')');
  }
  // place with a closure that is not exposed thanks to strict mode
  return function run(comm, src) {
    // stop argument / caller attacks
    "use strict";
    var send = function send(event) {
      "use strict";
      //
      // All comm must be serialized properly to avoid attacks, JSON or XJSON
      //
      comm.send(event, JSON.stringify([].slice.call(arguments,1)));
    };
    var __readFileSync = function(path) {
      "use strict";
      return comm.__readFileSync(JSON.stringify([ path ]));
    }
    var exit = function exit(){
      "use strict";
      onmessage = null;
      comm.exit();
    };
    global.console = { log: send.bind(global, 'stdout') };

    // Modify timers to set the __outstanding_timers variable
    global.__outstanding_timers = 0;
    function wrapTimer(fn) {
      "use strict";
      return function(){
        global.__outstanding_timers += 1;
        var callback = arguments[0];
        arguments[0] = function() {
          callback();
          global.__outstanding_timers -= 1;
          global.__check_finished();
        };
        fn.apply(global, arguments);
      };
    }
    global.setImmediate = wrapTimer(comm.timers.setImmediate).bind(global);
    global.clearImmediate = wrapTimer(comm.timers.clearImmediate).bind(global);
    global.setTimeout = wrapTimer(comm.timers.setTimeout).bind(global);
    global.clearTimeout = wrapTimer(comm.timers.clearTimeout).bind(global);

    global.print = send.bind(global, 'stdout');
    global.console = { log: send.bind(global, 'stdout') };
    global.process = {
      stdout: { write: send.bind(global, 'stdout') },
      exit: exit,
      nextTick: global.setImmediate.bind(global),
      version: comm.vars.node_version
    };
    global.__check_finished = function() {
      if (typeof onmessage !== 'function' && global.__outstanding_timers === 0) {
        process.exit();
      }
    };
    global.postMessage = send.bind(global, 'message');
    global.__readFileSync = __readFileSync.bind(global);
    global.global = global._global = global;

    // This is where the user's source code is actually evaluated
    var result = UserScript(src)();
    send('end', result);
  }
};

// Run code
function run() {

  var context = vm.createContext();
  var safeRunner = vm.runInContext('('+getSafeRunner.toString()+')()', context);

  try {
    safeRunner({
      send: function (event, value) {
        "use strict";

        switch (event) {
          case 'stdout':
            process.stdout.write(JSON.parse(value)[0] + '\n');
            break;
          case 'end':
            result = JSON.parse(value)[0];
            break;
          case 'message':
            process.send({ type: 'message', data: JSON.parse(value)[0] });
            break;
          default:
            throw new Error('Unknown event type');
        }
      },
      exit: function(){
        processExit();
      },
      __readFileSync: function(path) {
        path = JSON.parse(path)[0];
        return fsreadonly.readFileSync(String(path));
      },
      timers: {
        setTimeout: wrapTimer(context, setTimeout),
        clearTimeout: wrapTimer(context, clearTimeout),
        setImmediate: wrapTimer(context, setImmediate),
        clearImmediate: wrapTimer(context, clearImmediate)
      },
      vars: {
        node_version: String(process.version)
      }
    }, code);
  }
  catch (e) {
    console.log(e.stack);
    return;
  }

  process.on('message', processMessageListener.bind(null, context));

  process.send({ type: 'ready' });

  // This will exit the process if onmessage was not defined
  checkIfProcessFinished(context);
};

// If the sandboxed code has defined an `onmessage` function, pass the message
// we received to it. Note that we are still worried about what external users
// might pass in to the sandboxed code
function processMessageListener(context, message){
  vm.runInContext('if (typeof onmessage === "function") { onmessage('+ JSON.stringify(String(message)) + '); }', context);
  checkIfProcessFinished(context);
};

// The process should only be considered finished if `onmessage` is not set
// or if the sandboxed code calls `process.exit()` explicitly
function checkIfProcessFinished(context) {
  if(vm.runInContext('typeof onmessage', context) !== 'function' && vm.runInContext('__outstanding_timers', context) <= 0) {
    processExit();
  }
};

// Send the result to the parent process and exit this process
function processExit() {
  process.removeListener('message', processMessageListener);

  process.send({ type: 'result', data: result });

  process.exit(0);
};

function wrapTimer(context, fn) {
  return function(){
    var timer_context = this;
    var callback = arguments[0];
    arguments[0] = function() {
      callback();
      // checkIfProcessFinished(context);
    };
    fn.apply(timer_context, arguments);
    return;
  };
}
<|endoftext|>


<commit_before>/**
  Copyright 2010-2011 Mateusz Paprocki <mattpap@gmail.com>
  Copyright 2011 Christian Iversen <ci@sikkerhed.org>

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

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

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

var $PY = {};

var py_builtins = {};

py_builtins.PY$__python3__ = false;

function defined(obj) {
    return typeof(obj) != 'undefined';
}

function iterate(obj, func) {
    var seq = iter(obj);
    while (true) {
        try {
            func(seq.PY$next());
        } catch (exc) {
            if (py_builtins.isinstance(exc, py_builtins.StopIteration) == true) {
                break;
            } else {
                throw exc;
            }
        }
    }
}

var js = function(obj) {
    /*
       Converts (recursively) a Python object to a javascript builtin object.

       In particular:

       tuple -> Array
       list -> Array
       dict -> Object

       It uses the obj._js_() if it is defined, otherwise it just returns the
       same object. It is the responsibility of _js_() to convert recursively
       the object itself.
    */
    if ((obj != null) && typeof(obj._js_) != 'undefined')
        return obj._js_();
    else
        return obj;
};
<commit_msg> + Added __kwargs_make() and __kwargs_get() helpers<commit_after>/**
  Copyright 2010-2011 Mateusz Paprocki <mattpap@gmail.com>
  Copyright 2011 Christian Iversen <ci@sikkerhed.org>

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

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

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

var $PY = {};

var py_builtins = {};

py_builtins.PY$__python3__ = false;

function defined(obj) {
    return typeof(obj) != 'undefined';
}

function iterate(obj, func) {
    var seq = iter(obj);
    while (true) {
        try {
            func(seq.PY$next());
        } catch (exc) {
            if (py_builtins.isinstance(exc, py_builtins.StopIteration) == true) {
                break;
            } else {
                throw exc;
            }
        }
    }
}

var __kwargs_make = function(kw) {
    kw.__kwargs = true;
    return kw;
};

var __kwargs_get = function(args) {
    if (args.length && args[args.length-1].__kwargs === true) {
        delete args[args.length-1].__kwargs;
        var res = dict(args[args.length-1]);
        delete args[args.length-1];
        return res;
    } else {
        return dict();
    }
};

var js = function(obj) {
    /*
       Converts (recursively) a Python object to a javascript builtin object.

       In particular:

       tuple -> Array
       list -> Array
       dict -> Object

       It uses the obj._js_() if it is defined, otherwise it just returns the
       same object. It is the responsibility of _js_() to convert recursively
       the object itself.
    */
    if ((obj != null) && typeof(obj._js_) != 'undefined')
        return obj._js_();
    else
        return obj;
};
<|endoftext|>


<commit_before>/**
 * @package     hubzero-cms
 * @file        components/com_groups/assets/js/groups.jquery.js
 * @copyright   Copyright 2005-2011 Purdue University. All rights reserved.
 * @license     http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
 */

//-----------------------------------------------------------
//  Ensure we have our namespace
//-----------------------------------------------------------
if (!HUB) {
	var HUB = {};
}

//----------------------------------------------------------
//  Members scripts
//----------------------------------------------------------
if (!jq) {
	var jq = $;
}

HUB.Groups = {
	jQuery: jq,

	initialize: function()
	{
		//
		HUB.Groups.membershipNotifications();

		//verify wanting to cancel from group
		HUB.Groups.confirmCancelMembership();

		//confirm messages
		HUB.Groups.confirmLeaveArea();

		//logo picker to show logo picked in preview
		HUB.Groups.customizePickLogo();

		//show or hide custom content box
		HUB.Groups.customizeOverviewContent();

		//group page preview in lightbox
		HUB.Groups.customizePreviewPage();

		//hide all empty paragraphs generated from wiki
		//HUB.Groups.fixEmptyParagraphs();

		//toggle between public and private group desc
		HUB.Groups.togglePublicPrivateDescription();

		//special groups
		HUB.Groups.specialGroups();

		//
		HUB.Groups.scrollingAssetBrowser();
	},

	//----

	membershipNotifications: function()
	{
		var $ = this.jQuery;

		var content = "",
			invites = $(".invites"),
			requests = $(".requests");

		if(invites.length)
		{
			invites.addClass("hide");
			content += invites.html();
		}

		if(requests.length)
		{
			requests.addClass("hide");
			content += "
" + requests.html();
		}

		if(content != "")
		{
			var timeout = setTimeout(function() {
				$.fancybox({
					autoSize:false,
					width: 600,
					height: 'auto',
					content: content,
					beforeload: function() {
						invites.toggleClass("hide");
						requests.toggleClass("hide");
					}
				});
			}, 2000);
		}
	},

	//-----

	fixEmptyParagraphs: function()
	{
		var $ = this.jQuery;

		$('p').each(function(i, el) {
			var text = el.innerHTML;
			if(escape(text) == '%3Cbr%3E%0A' || text == "") {
				el.addClass('hide');
			}
		});
	},

	//-----

	togglePublicPrivateDescription: function()
	{
		var $ = this.jQuery;

		var publicDesc = $("#public"),
			privateDesc = $("#private"),
			toggleSwitch = $("#toggle_description");

		if(toggleSwitch.length)
		{
			toggleSwitch.removeClass('hide');

			toggleSwitch.bind("click", function(e) {
				e.preventDefault();

				if(publicDesc.hasClass("hide"))
				{
					toggleSwitch.html('Show Private Description (-)');
				}
				else
				{
					toggleSwitch.html('Show Public Description (+)');
				}

				publicDesc.toggleClass("hide");
				privateDesc.toggleClass("hide");
			});
		}
	},

	//-----

	confirmCancelMembership: function()
	{
		var $ = this.jQuery;

		$(".cancel_group_membership").live('click', function(e) {
			e.preventDefault();

			var answer = confirm('Are you sure you would like to cancel your group membership?');
			if(answer)
			{
				window.location = this.href;
			}
		});
	},

	//-----

	confirmLeaveArea: function()
	{
		var $ = this.jQuery;

		$('.leave_area').bind('click', function(e) {
			e.preventDefault();

			var question = $(this).attr('rel'),
				answer = confirm(question);

			if(answer) {
				window.location = this.href;
			}
		});
	},

	//-----

	customizePickLogo: function()
	{
		var $ = this.jQuery;

		var logo = "",
			logoSelecter = $("#group_logo");

		if(logoSelecter.length)
		{
			logoSelecter.bind("change", function(e) {

				if(this.value == "")
				{
					logo = '';
				}
				else
				{
					logo = '';
				}

				$("#logo_picked").html(logo)
			});
		}
	},

	//-----

	customizeOverviewContent: function()
	{
		var $ = this.jQuery;

		var overview = $('#overview_content'),
			customOverview = $('#group_overview_type_custom').attr("checked");

		if(overview.length)
		{
			if(!customOverview)
			{
				overview.addClass("hide-left");
			}

			$("input[type=radio]").bind("click", function(e){
				$('p.side-by-side').removeClass('checked');
				$(this).parents(".side-by-side").addClass("checked");
				if(this.value == 1)
				{
					overview.removeClass('hide-left');
				}
				else
				{
					overview.addClass('hide-left');
				}
			});
		}
	},

	//-----

	customizePreviewPage: function()
	{
		var $ = this.jQuery;

		$('.quick-view').fancybox({
			type: 'inline',
			width: 600,
			height: 'auto',
			autoSize: false,
			fitToView: false,
			titleShow: false
		});
	},

	//-----

	scrollingAssetBrowser: function()
	{
		var $ = this.jQuery;

		var topBox = $("#top_box"),
			bottomBox = $("#bottom_box"),
			assetBox = $("#asset_browser");

		if(assetBox.length)
		{
			var element = $(document);
			min = (topBox.length != 0) ? (topBox.offset().top) : 0;
			max = (bottomBox.length != 0) ? bottomBox.offset().top+bottomBox.outerHeight(true)-assetBox.outerHeight(true)-min : 0;
			margin = 0;

			//margin-top of asset-browser, not sure why .outerheight(true) is calculating right
			max -= 7;

			if(element.scrollTop() > max)
			{
				margin = (max-element.scrollTop());
			}

			$(".explaination").css({
				'position':'fixed',
				'right':'80px',
				'z-index':'999',
				'width':'24%',
				'margin-top': margin
			});
		}
	},

	//-----

	specialGroups: function()
	{

	}
}

//-----------------------------------------------------------

jQuery(document).ready(function($){
	HUB.Groups.initialize();
});

//-----------------------------------------------------------

jQuery(window).scroll(function($){
	HUB.Groups.scrollingAssetBrowser();
});<commit_msg>Changed asset browser to scroll iteself, not its parent container and determine its width rather than hard-coded value<commit_after>/**
 * @package     hubzero-cms
 * @file        components/com_groups/assets/js/groups.jquery.js
 * @copyright   Copyright 2005-2011 Purdue University. All rights reserved.
 * @license     http://www.gnu.org/licenses/lgpl-3.0.html LGPLv3
 */

//-----------------------------------------------------------
//  Ensure we have our namespace
//-----------------------------------------------------------
if (!HUB) {
	var HUB = {};
}

//----------------------------------------------------------
//  Members scripts
//----------------------------------------------------------
if (!jq) {
	var jq = $;
}

HUB.Groups = {
	jQuery: jq,

	initialize: function()
	{
		//
		HUB.Groups.membershipNotifications();

		//verify wanting to cancel from group
		HUB.Groups.confirmCancelMembership();

		//confirm messages
		HUB.Groups.confirmLeaveArea();

		//logo picker to show logo picked in preview
		HUB.Groups.customizePickLogo();

		//show or hide custom content box
		HUB.Groups.customizeOverviewContent();

		//group page preview in lightbox
		HUB.Groups.customizePreviewPage();

		//hide all empty paragraphs generated from wiki
		//HUB.Groups.fixEmptyParagraphs();

		//toggle between public and private group desc
		HUB.Groups.togglePublicPrivateDescription();

		//special groups
		HUB.Groups.specialGroups();

		//
		HUB.Groups.scrollingAssetBrowser();
	},

	//----

	membershipNotifications: function()
	{
		var $ = this.jQuery;

		var content = "",
			invites = $(".invites"),
			requests = $(".requests");

		if(invites.length)
		{
			invites.addClass("hide");
			content += invites.html();
		}

		if(requests.length)
		{
			requests.addClass("hide");
			content += "
" + requests.html();
		}

		if(content != "")
		{
			var timeout = setTimeout(function() {
				$.fancybox({
					autoSize:false,
					width: 600,
					height: 'auto',
					content: content,
					beforeload: function() {
						invites.toggleClass("hide");
						requests.toggleClass("hide");
					}
				});
			}, 2000);
		}
	},

	//-----

	fixEmptyParagraphs: function()
	{
		var $ = this.jQuery;

		$('p').each(function(i, el) {
			var text = el.innerHTML;
			if(escape(text) == '%3Cbr%3E%0A' || text == "") {
				el.addClass('hide');
			}
		});
	},

	//-----

	togglePublicPrivateDescription: function()
	{
		var $ = this.jQuery;

		var publicDesc = $("#public"),
			privateDesc = $("#private"),
			toggleSwitch = $("#toggle_description");

		if(toggleSwitch.length)
		{
			toggleSwitch.removeClass('hide');

			toggleSwitch.bind("click", function(e) {
				e.preventDefault();

				if(publicDesc.hasClass("hide"))
				{
					toggleSwitch.html('Show Private Description (-)');
				}
				else
				{
					toggleSwitch.html('Show Public Description (+)');
				}

				publicDesc.toggleClass("hide");
				privateDesc.toggleClass("hide");
			});
		}
	},

	//-----

	confirmCancelMembership: function()
	{
		var $ = this.jQuery;

		$(".cancel_group_membership").live('click', function(e) {
			e.preventDefault();

			var answer = confirm('Are you sure you would like to cancel your group membership?');
			if(answer)
			{
				window.location = this.href;
			}
		});
	},

	//-----

	confirmLeaveArea: function()
	{
		var $ = this.jQuery;

		$('.leave_area').bind('click', function(e) {
			e.preventDefault();

			var question = $(this).attr('rel'),
				answer = confirm(question);

			if(answer) {
				window.location = this.href;
			}
		});
	},

	//-----

	customizePickLogo: function()
	{
		var $ = this.jQuery;

		var logo = "",
			logoSelecter = $("#group_logo");

		if(logoSelecter.length)
		{
			logoSelecter.bind("change", function(e) {

				if(this.value == "")
				{
					logo = '';
				}
				else
				{
					logo = '';
				}

				$("#logo_picked").html(logo)
			});
		}
	},

	//-----

	customizeOverviewContent: function()
	{
		var $ = this.jQuery;

		var overview = $('#overview_content'),
			customOverview = $('#group_overview_type_custom').attr("checked");

		if(overview.length)
		{
			if(!customOverview)
			{
				overview.addClass("hide-left");
			}

			$("input[type=radio]").bind("click", function(e){
				$('p.side-by-side').removeClass('checked');
				$(this).parents(".side-by-side").addClass("checked");
				if(this.value == 1)
				{
					overview.removeClass('hide-left');
				}
				else
				{
					overview.addClass('hide-left');
				}
			});
		}
	},

	//-----

	customizePreviewPage: function()
	{
		var $ = this.jQuery;

		$('.quick-view').fancybox({
			type: 'inline',
			width: 600,
			height: 'auto',
			autoSize: false,
			fitToView: false,
			titleShow: false
		});
	},

	//-----

	scrollingAssetBrowser: function()
	{
		var $ = this.jQuery;

		var topBox = $("#top_box"),
			bottomBox = $("#bottom_box"),
			assetBox = $("#asset_browser");

		if(assetBox.length)
		{
			var element = $(document);
			min = (topBox.length != 0) ? (topBox.offset().top) : 0;
			max = (bottomBox.length != 0) ? bottomBox.offset().top+bottomBox.outerHeight(true)-assetBox.outerHeight(true)-min : 0;
			margin = 0;

			//margin-top of asset-browser, not sure why .outerheight(true) is calculating right
			max -= 7;

			if(element.scrollTop() > max)
			{
				margin = (max-element.scrollTop());
			}

			assetBox.css({
				'position':'fixed',
				'z-index':'999',
				'width': assetBox.width() + 'px',
				'padding': '0px',
				'margin-top': margin
			});
		}
	},

	//-----

	specialGroups: function()
	{

	}
}

//-----------------------------------------------------------

jQuery(document).ready(function($){
	HUB.Groups.initialize();
});

//-----------------------------------------------------------

jQuery(window).scroll(function($){
	HUB.Groups.scrollingAssetBrowser();
});<|endoftext|>


<commit_before>import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { connect } from 'react-redux'

import Hostname from 'components/Hostname'
import Summary from 'components/Summary'

import Waypoint from 'react-waypoint'
import ProgressiveImage from 'react-progressive-image'

import * as ArticleActions from 'actions/Articles'

@connect()
class Article extends Component {

    trackEngagement = e => this.props.dispatch(
        ArticleActions.engage(this.props.object.id, (this.props.index + 7))
    )

    trackImpression = () => this.props.dispatch(
        ArticleActions.impression(this.props.object.id)
    )

    handleImgLoad = (src, id) => {
        if (src == null || src.indexOf('track') != -1) {
            document.getElementById(id).src = '../img/app/placeholder.png'
        }
    }

    render() {

        return (

                    <Waypoint onEnter={() => {
                        this.trackImpression(this.props.object.id)
                    }} />

                        <ProgressiveImage src={this.props.object.imageSrc} placeholder='../img/app/placeholder.png'>
                            {(src) =>
                                 this.handleImgLoad(src, this.props.object.id)}
                                    id={this.props.object.id} />
                            }
                        </ProgressiveImage>

                            {this.props.object.title}

                        {this.props.object.summary}

                        {this.props.site.name || this.props.site.siteUrl}

        )
    }

}

@connect(state => ({ articles: state.Articles, }))
class Articles extends Component {

    state = {
        appending: false,
        page: 1,
        version: null,
    }

    handleScroll = e => {

        if (this.$i || this.state.appending) {
            clearTimeout(this.$i)
        }

        this.$i = setTimeout(() => {

            if (this.state.appending) return

            if (((this.$scrollY || 0) - window.scrollY) >= 0) {
                return
            }

            this.$scrollY = window.scrollY

            const offset = document.body.scrollTop + window.innerHeight,
                  height = document.body.offsetHeight

            if (offset > (height - 100)) {
                this.setState({ appending: true, page: this.state.page + 1, })
                this.props.dispatch(ArticleActions.load(this.state.page))
                    .then(() => this.setState({ appending: false, }))
            }
        }, 200)
    }

    componentDidMount() {
        window.addEventListener('scroll', this.handleScroll)
    }

    componentWillUnmount() {
        window.removeEventListener('scroll', this.handleScroll)
    }

    render() {
        return (

                {this.props.articles.slice(7).map((article, index) =>
                    <Article {...article} index={index} key={`article-${article.object.id}`} />
                )}
                {this.state.appending ?

                    <svg width="35px" height="35px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" className="uil-ring">
                        <rect x="0" y="0" width="100" height="100" fill="none" className="bk"></rect>
                        <defs>
                            <filter id="uil-ring-shadow" x="-100%" y="-100%" width="300%" height="300%">
                                <feOffset result="offOut" in="SourceGraphic" dx="0" dy="0"></feOffset>
                                <feGaussianBlur result="blurOut" in="offOut" stdDeviation="0"></feGaussianBlur>
                                <feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend>
                            </filter>
                        </defs>
                        <path d="M10,50c0,0,0,0.5,0.1,1.4c0,0.5,0.1,1,0.2,1.7c0,0.3,0.1,0.7,0.1,1.1c0.1,0.4,0.1,0.8,0.2,1.2c0.2,0.8,0.3,1.8,0.5,2.8 c0.3,1,0.6,2.1,0.9,3.2c0.3,1.1,0.9,2.3,1.4,3.5c0.5,1.2,1.2,2.4,1.8,3.7c0.3,0.6,0.8,1.2,1.2,1.9c0.4,0.6,0.8,1.3,1.3,1.9 c1,1.2,1.9,2.6,3.1,3.7c2.2,2.5,5,4.7,7.9,6.7c3,2,6.5,3.4,10.1,4.6c3.6,1.1,7.5,1.5,11.2,1.6c4-0.1,7.7-0.6,11.3-1.6 c3.6-1.2,7-2.6,10-4.6c3-2,5.8-4.2,7.9-6.7c1.2-1.2,2.1-2.5,3.1-3.7c0.5-0.6,0.9-1.3,1.3-1.9c0.4-0.6,0.8-1.3,1.2-1.9 c0.6-1.3,1.3-2.5,1.8-3.7c0.5-1.2,1-2.4,1.4-3.5c0.3-1.1,0.6-2.2,0.9-3.2c0.2-1,0.4-1.9,0.5-2.8c0.1-0.4,0.1-0.8,0.2-1.2 c0-0.4,0.1-0.7,0.1-1.1c0.1-0.7,0.1-1.2,0.2-1.7C90,50.5,90,50,90,50s0,0.5,0,1.4c0,0.5,0,1,0,1.7c0,0.3,0,0.7,0,1.1 c0,0.4-0.1,0.8-0.1,1.2c-0.1,0.9-0.2,1.8-0.4,2.8c-0.2,1-0.5,2.1-0.7,3.3c-0.3,1.2-0.8,2.4-1.2,3.7c-0.2,0.7-0.5,1.3-0.8,1.9 c-0.3,0.7-0.6,1.3-0.9,2c-0.3,0.7-0.7,1.3-1.1,2c-0.4,0.7-0.7,1.4-1.2,2c-1,1.3-1.9,2.7-3.1,4c-2.2,2.7-5,5-8.1,7.1 c-0.8,0.5-1.6,1-2.4,1.5c-0.8,0.5-1.7,0.9-2.6,1.3L66,87.7l-1.4,0.5c-0.9,0.3-1.8,0.7-2.8,1c-3.8,1.1-7.9,1.7-11.8,1.8L47,90.8 c-1,0-2-0.2-3-0.3l-1.5-0.2l-0.7-0.1L41.1,90c-1-0.3-1.9-0.5-2.9-0.7c-0.9-0.3-1.9-0.7-2.8-1L34,87.7l-1.3-0.6 c-0.9-0.4-1.8-0.8-2.6-1.3c-0.8-0.5-1.6-1-2.4-1.5c-3.1-2.1-5.9-4.5-8.1-7.1c-1.2-1.2-2.1-2.7-3.1-4c-0.5-0.6-0.8-1.4-1.2-2 c-0.4-0.7-0.8-1.3-1.1-2c-0.3-0.7-0.6-1.3-0.9-2c-0.3-0.7-0.6-1.3-0.8-1.9c-0.4-1.3-0.9-2.5-1.2-3.7c-0.3-1.2-0.5-2.3-0.7-3.3 c-0.2-1-0.3-2-0.4-2.8c-0.1-0.4-0.1-0.8-0.1-1.2c0-0.4,0-0.7,0-1.1c0-0.7,0-1.2,0-1.7C10,50.5,10,50,10,50z" fill="#16c98d" filter="url(#uil-ring-shadow)">
                            <animateTransform attributeName="transform" type="rotate" from="0 50 50" to="360 50 50" repeatCount="indefinite" dur="1s"></animateTransform>
                        </path>
                    </svg>

 : null}

        )
    }

}

export default Articles
<commit_msg>Default placeholder image<commit_after>import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { connect } from 'react-redux'

import Hostname from 'components/Hostname'
import Summary from 'components/Summary'

import Waypoint from 'react-waypoint'
import ProgressiveImage from 'react-progressive-image'

import * as ArticleActions from 'actions/Articles'

@connect()
class Article extends Component {

    trackEngagement = e => this.props.dispatch(
        ArticleActions.engage(this.props.object.id, (this.props.index + 7))
    )

    trackImpression = () => this.props.dispatch(
        ArticleActions.impression(this.props.object.id)
    )

    handleImgLoad = (src, id, err) => {
        if (src == null || src.indexOf('track') != -1) {
            document.getElementById(id).src = 'img/app/placeholder.png'
        }
        if (err) {
            document.getElementById(id).src = 'img/app/placeholder.png'
        }
    }

    render() {

        return (

                    <Waypoint onEnter={() => {
                        this.trackImpression(this.props.object.id)
                    }} />

                        <ProgressiveImage src={this.props.object.imageSrc} placeholder='../img/app/placeholder.png'>
                            {(src) =>
                                 this.handleImgLoad(src, this.props.object.id)}
                                    onError={() => this.handleImgLoad(src, this.props.object.id, true)}
                                    id={this.props.object.id} />
                            }
                        </ProgressiveImage>

                            {this.props.object.title}

                        {this.props.object.summary}

                        {this.props.site.name || this.props.site.siteUrl}

        )
    }

}

@connect(state => ({ articles: state.Articles, }))
class Articles extends Component {

    state = {
        appending: false,
        page: 1,
        version: null,
    }

    handleScroll = e => {

        if (this.$i || this.state.appending) {
            clearTimeout(this.$i)
        }

        this.$i = setTimeout(() => {

            if (this.state.appending) return

            if (((this.$scrollY || 0) - window.scrollY) >= 0) {
                return
            }

            this.$scrollY = window.scrollY

            const offset = document.body.scrollTop + window.innerHeight,
                  height = document.body.offsetHeight

            if (offset > (height - 100)) {
                this.setState({ appending: true, page: this.state.page + 1, })
                this.props.dispatch(ArticleActions.load(this.state.page))
                    .then(() => this.setState({ appending: false, }))
            }
        }, 200)
    }

    componentDidMount() {
        window.addEventListener('scroll', this.handleScroll)
    }

    componentWillUnmount() {
        window.removeEventListener('scroll', this.handleScroll)
    }

    render() {
        return (

                {this.props.articles.slice(7).map((article, index) =>
                    <Article {...article} index={index} key={`article-${article.object.id}`} />
                )}
                {this.state.appending ?

                    <svg width="35px" height="35px" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" className="uil-ring">
                        <rect x="0" y="0" width="100" height="100" fill="none" className="bk"></rect>
                        <defs>
                            <filter id="uil-ring-shadow" x="-100%" y="-100%" width="300%" height="300%">
                                <feOffset result="offOut" in="SourceGraphic" dx="0" dy="0"></feOffset>
                                <feGaussianBlur result="blurOut" in="offOut" stdDeviation="0"></feGaussianBlur>
                                <feBlend in="SourceGraphic" in2="blurOut" mode="normal"></feBlend>
                            </filter>
                        </defs>
                        <path d="M10,50c0,0,0,0.5,0.1,1.4c0,0.5,0.1,1,0.2,1.7c0,0.3,0.1,0.7,0.1,1.1c0.1,0.4,0.1,0.8,0.2,1.2c0.2,0.8,0.3,1.8,0.5,2.8 c0.3,1,0.6,2.1,0.9,3.2c0.3,1.1,0.9,2.3,1.4,3.5c0.5,1.2,1.2,2.4,1.8,3.7c0.3,0.6,0.8,1.2,1.2,1.9c0.4,0.6,0.8,1.3,1.3,1.9 c1,1.2,1.9,2.6,3.1,3.7c2.2,2.5,5,4.7,7.9,6.7c3,2,6.5,3.4,10.1,4.6c3.6,1.1,7.5,1.5,11.2,1.6c4-0.1,7.7-0.6,11.3-1.6 c3.6-1.2,7-2.6,10-4.6c3-2,5.8-4.2,7.9-6.7c1.2-1.2,2.1-2.5,3.1-3.7c0.5-0.6,0.9-1.3,1.3-1.9c0.4-0.6,0.8-1.3,1.2-1.9 c0.6-1.3,1.3-2.5,1.8-3.7c0.5-1.2,1-2.4,1.4-3.5c0.3-1.1,0.6-2.2,0.9-3.2c0.2-1,0.4-1.9,0.5-2.8c0.1-0.4,0.1-0.8,0.2-1.2 c0-0.4,0.1-0.7,0.1-1.1c0.1-0.7,0.1-1.2,0.2-1.7C90,50.5,90,50,90,50s0,0.5,0,1.4c0,0.5,0,1,0,1.7c0,0.3,0,0.7,0,1.1 c0,0.4-0.1,0.8-0.1,1.2c-0.1,0.9-0.2,1.8-0.4,2.8c-0.2,1-0.5,2.1-0.7,3.3c-0.3,1.2-0.8,2.4-1.2,3.7c-0.2,0.7-0.5,1.3-0.8,1.9 c-0.3,0.7-0.6,1.3-0.9,2c-0.3,0.7-0.7,1.3-1.1,2c-0.4,0.7-0.7,1.4-1.2,2c-1,1.3-1.9,2.7-3.1,4c-2.2,2.7-5,5-8.1,7.1 c-0.8,0.5-1.6,1-2.4,1.5c-0.8,0.5-1.7,0.9-2.6,1.3L66,87.7l-1.4,0.5c-0.9,0.3-1.8,0.7-2.8,1c-3.8,1.1-7.9,1.7-11.8,1.8L47,90.8 c-1,0-2-0.2-3-0.3l-1.5-0.2l-0.7-0.1L41.1,90c-1-0.3-1.9-0.5-2.9-0.7c-0.9-0.3-1.9-0.7-2.8-1L34,87.7l-1.3-0.6 c-0.9-0.4-1.8-0.8-2.6-1.3c-0.8-0.5-1.6-1-2.4-1.5c-3.1-2.1-5.9-4.5-8.1-7.1c-1.2-1.2-2.1-2.7-3.1-4c-0.5-0.6-0.8-1.4-1.2-2 c-0.4-0.7-0.8-1.3-1.1-2c-0.3-0.7-0.6-1.3-0.9-2c-0.3-0.7-0.6-1.3-0.8-1.9c-0.4-1.3-0.9-2.5-1.2-3.7c-0.3-1.2-0.5-2.3-0.7-3.3 c-0.2-1-0.3-2-0.4-2.8c-0.1-0.4-0.1-0.8-0.1-1.2c0-0.4,0-0.7,0-1.1c0-0.7,0-1.2,0-1.7C10,50.5,10,50,10,50z" fill="#16c98d" filter="url(#uil-ring-shadow)">
                            <animateTransform attributeName="transform" type="rotate" from="0 50 50" to="360 50 50" repeatCount="indefinite" dur="1s"></animateTransform>
                        </path>
                    </svg>

 : null}

        )
    }

}

export default Articles
<|endoftext|>


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

// requires Extensions.js

(function ($) {
  $.fn.numericInput = function (options) {
    var negative = !options || options.negative;
    var decimal = !options || options.decimal;

    this.filter("input[type='text']").each(function () {
      var $this = $(this).on("keydown", function (e) {
        var numeric = $this.data("numeric");
        var current = numeric.previousValue = $this.val();

        // if starting a paste, capture selection start and length

        if (numeric.ctrl && e.which == 86) {
          numeric.selectionStart = $this.prop("selectionStart");
          numeric.selectionEnd = $this.prop("selectionEnd");
        }

        // allow ctrl sequences, backspace, tab, arrow keys, home, end, delete, digits, minus as the first character and one decimal point

        if (numeric.ctrl || e.which == 8 || e.which == 9 || (e.which >= 35 && e.which <= 40) || e.which == 46 || (!numeric.shift && e.which >= 48 && e.which <= 57) ||
            (negative && e.which == 189 && $this.prop("selectionStart") == 0) || (decimal && e.which == 190 && numeric.previousValue.indexOf(".") < 0)) {

          // prevent key hold-down repetition

          if (e.which != numeric.key) {
            numeric.key = e.which;

            // capture previous value and text selection

            numeric.previousValue = $this.val();
            numeric.selectionStart = $this.prop("selectionStart");
            numeric.selectionEnd = $this.prop("selectionEnd");
            return;
          }
        }

        // store state of shift and allow it through

        if (e.which == 16) {
          numeric.shift = true;
          return;
        }

        // store state of ctrl and allow it through

        if (e.which == 17) {
          numeric.ctrl = true;
          return;
        }

        // otherwise prevent key from working

        e.preventDefault();
      }).on("keyup", function (e) {
        var numeric = $this.data("numeric");

        if (e.which == numeric.key) {
          numeric.key = -1;
        }

        // reset shift state

        if (e.which == 16) {
          numeric.shift = false;
        }

        // reset ctrl state

        if (e.which == 17) {
          numeric.ctrl = false;
        }

        // if not numeric after typing or paste, revert

        if (!numeric.ctrl || e.which == 86) {
          var newValue = $this.val();

          if (newValue.length && newValue != "-" && newValue != "." && newValue != "-." && !newValue.isNumeric()) {
            $this.val(numeric.previousValue);
            $this.prop("selectionStart", numeric.selectionStart);
            $this.prop("selectionEnd", numeric.selectionEnd);
          }
        }
      }).on("change", function () {
        if (!$this.val().isNumeric()) {
          $this.val("");
        }
      }).on("blur", function () {
        var numeric = $this.data("numeric");
        numeric.shift = false;
        numeric.ctrl = false;
      }).data("numeric", {
        key: -1,
        ctrl: false,
        shift: false,
        selectionStart: -1,
        selectionEnd: -1,
        previousValue: ""
      });
    });

    return this;
  };
})(jQuery);<commit_msg>fixed #40, #59 numeric keypad not working<commit_after>//  Copyright 2012 Applied Geographics, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.

// requires Extensions.js

(function ($) {
  $.fn.numericInput = function (options) {
    var negative = !options || options.negative;
    var decimal = !options || options.decimal;

    this.filter("input[type='text']").each(function () {
      var $this = $(this).on("keydown", function (e) {
        var numeric = $this.data("numeric");
        var current = numeric.previousValue = $this.val();

        // if starting a paste, capture selection start and length

        if (numeric.ctrl && e.which == 86) {
          numeric.selectionStart = $this.prop("selectionStart");
          numeric.selectionEnd = $this.prop("selectionEnd");
        }

        // allow any of the following

        if (numeric.ctrl ||                                      // ctrl sequences
          e.which == 8 ||                                        // backspace
          e.which == 9 ||                                        // tab
          (e.which >= 35 && e.which <= 40) ||                    // arrow keys, home, end
          e.which == 46 ||                                       // delete
          (!numeric.shift && e.which >= 48 && e.which <= 57) ||  // digits from keyboard
          (e.which >= 96 && e.which <= 105) ||                   // digits from keypad
          (negative && (e.which == 189 || e.which == 109) && $this.prop("selectionStart") == 0) ||       // minus as the first character
          (decimal && (e.which == 190 || e.which == 110)  && numeric.previousValue.indexOf(".") < 0)) {  // one decimal point

          // prevent key hold-down repetition

          if (e.which != numeric.key) {
            numeric.key = e.which;

            // capture previous value and text selection

            numeric.previousValue = $this.val();
            numeric.selectionStart = $this.prop("selectionStart");
            numeric.selectionEnd = $this.prop("selectionEnd");
            return;
          }
        }

        // store state of shift and allow it through

        if (e.which == 16) {
          numeric.shift = true;
          return;
        }

        // store state of ctrl and allow it through

        if (e.which == 17) {
          numeric.ctrl = true;
          return;
        }

        // otherwise prevent key from working

        e.preventDefault();
      }).on("keyup", function (e) {
        var numeric = $this.data("numeric");

        if (e.which == numeric.key) {
          numeric.key = -1;
        }

        // reset shift state

        if (e.which == 16) {
          numeric.shift = false;
        }

        // reset ctrl state

        if (e.which == 17) {
          numeric.ctrl = false;
        }

        // if not numeric after typing or paste, revert

        if (!numeric.ctrl || e.which == 86) {
          var newValue = $this.val();

          if (newValue.length && newValue != "-" && newValue != "." && newValue != "-." && !newValue.isNumeric()) {
            $this.val(numeric.previousValue);
            $this.prop("selectionStart", numeric.selectionStart);
            $this.prop("selectionEnd", numeric.selectionEnd);
          }
        }
      }).on("change", function () {
        if (!$this.val().isNumeric()) {
          $this.val("");
        }
      }).on("blur", function () {
        var numeric = $this.data("numeric");
        numeric.shift = false;
        numeric.ctrl = false;
      }).data("numeric", {
        key: -1,
        ctrl: false,
        shift: false,
        selectionStart: -1,
        selectionEnd: -1,
        previousValue: ""
      });
    });

    return this;
  };
})(jQuery);<|endoftext|>


<commit_before>angular.module('qmsk.e2.server', [
        'qmsk.e2',
        'qmsk.e2.console',
        'qmsk.e2.web',
        'ngResource',
        'ngRoute',
        'jsonFormatter',
        'ui.bootstrap',
])

.config(function($routeProvider) {
    $routeProvider
        .when('/main', {
            templateUrl: '/static/qmsk.e2/server/main.html',
            controller: 'MainCtrl',
            reloadOnSearch: false,
        })
        .when('/sources', {
            templateUrl: '/static/qmsk.e2/server/sources.html',
            controller: 'SourcesCtrl',
        })
        .when('/screens', {
            templateUrl: '/static/qmsk.e2/server/screens.html',
            controller: 'ScreensCtrl',
        })
        .when('/auxes', {
            templateUrl: '/static/qmsk.e2/server/auxes.html',
            controller: 'AuxesCtrl',
        })
        .when('/presets', {
            templateUrl: '/static/qmsk.e2/server/presets.html',
            controller: 'PresetsCtrl',
            reloadOnSearch: false,
        })
        .when('/system', {
            templateUrl: '/static/qmsk.e2/server/system.html',
            controller: 'SystemCtrl',
        })
        .otherwise({
            redirectTo: '/main',
        });
})

.factory('Preset', function($resource) {
    return $resource('/api/presets/:id', { }, {
        get: {
            method: 'GET',
            url: '/api/presets',
        },
        all: {
            method: 'GET',
            isArray: true,
        },
        query: {
            method: 'GET',
            isArray: false,
        },
        activate: {
            method: 'POST',
            url: '/api/presets',
        },
    }, {stripTrailingSlashes: false});
})

.filter('dimensions', function() {
    return function(dimensions) {
        if (dimensions && dimensions.width && dimensions.height) {
            return dimensions.width + "x" + dimensions.height;
        } else {
            return null;
        }
    };
})

.directive('e2Source', function() {
    return {
        restrict: 'AE',
        scope: {
            source: '=source',
            input: '=input',
            detail: '=detail',
        },
        templateUrl: '/static/qmsk.e2/server/source.html',
    };
})

.controller('MainCtrl', function($scope, $location) {
    $scope.sources = [];

    $scope.$watch('state.System', function(system) {
        // compute a merged state mapping sources to their active destinations
        // TODO: aux destinations
        $scope.sources = $.map(system.SrcMgr.SourceCol, function(source, sourceID){
            var item = {
                id: sourceID,
                type: source.SrcType,
                name: source.Name,
                source: source,
                active: false,
                preview: [],
                program: [],
            };

            if (source.SrcType == "input") {
                item.input = system.SrcMgr.InputCfgCol[source.InputCfgIndex];
            }

            $.each(system.DestMgr.ScreenDestCol, function(screenID, screen) {
                var output = {
                    type: "screen",
                    id: screenID,
                    name: screen.Name,
                    active: screen.IsActive > 0,
                };

                $.each(screen.LayerCollection, function(layerID, layer) {
                    if (layer.PgmMode > 0 && layer.LastSrcIdx == sourceID) {
                        output.program = true;
                    }

                    if (layer.PvwMode > 0 && layer.LastSrcIdx == sourceID) {
                        output.preview = true;
                    }
                });

                if (output.program) {
                    item.program.push(output);
                }
                if (output.preview) {
                    item.preview.push(output);
                }
                if (output.active && output.preview) {
                    item.active = true;
                }
            });

            return item;
        });
    });

    $scope.selectOrder = function(order) {
        $scope.order = order;
        $scope.orderBy = function(){
            switch (order) {
            case 'source':
                return ['-type', 'name'];
            case 'preview':
                return ['preview_screens', 'program_screens'];
            case 'program':
                return ['program_screens', 'preview_screens'];
            default:
                return [];
            }
        }();

        $location.search('order', order || null);
    };
    $scope.selectOrder($location.search().order || 'source');
})

.controller('SourcesCtrl', function($scope) {

})

.controller('ScreensCtrl', function($scope) {

})

.controller('AuxesCtrl', function($scope) {

})

.controller('PresetsCtrl', function($scope, Preset, $location, Console) {
    // size
    $scope.displaySize = $location.search().size || 'normal';

    $scope.$watch('displaySize', function(displaySize) {
        $location.search('size', displaySize);
    });

    // collapsing
    $scope.showGroup = $location.search().group || null;
    $scope.collapseGroups = {};

    $scope.selectGroup = function(groupID) {
        $scope.collapseGroups = {};

        if (groupID != $scope.showGroup) {
            $scope.showGroup = groupID;

            $location.search('group', groupID);
        }
    }
    $scope.clearGroup = function() {
        $scope.collapseGroups = {};
        $scope.showGroup = null;
        $location.search('group', null);
    };
    $scope.toggleGroup = function(groupID) {
        $scope.collapseGroups[groupID] = !$scope.collapseGroups[groupID];
    };

    // grouping
    $scope.groupBy = $location.search().groupBy || 'sno';

    $scope.$watch('groupBy', function(groupBy) {
        $location.search('groupBy', groupBy);
    });

    function groupBySno(presets) {
        var groups = { };

        $.each(presets, function(id, preset) {
            var groupID = preset.presetSno.Group;
            var groupIndex = preset.presetSno.Index;

            preset = $.extend({groupIndex: groupIndex}, preset);

            // group it
            var group = groups[groupID];

            if (!group) {
                group = groups[groupID] = {
                    id: groupID,
                    name: groupID,
                    presets: []
                };
            }

            group.presets.push(preset);
        });

        return $.map(groups, function(group, id){
            return group;
        });
    };
    function groupByConsole(presets) {
        var groups = { };

        $.each($scope.state.System.ConsoleLayoutMgr.ConsoleLayout.PresetBusColl, function(buttonID, button) {
            var groupID = Math.floor(button.id / 12); // rows of 12 keys
            var group = groups[groupID];
            var preset = presets[button.ConsoleButtonTypeIndex];

            if (button.ConsoleButtonType != 'preset' || !preset) {
                return;
            }

            // copy with groupIndex, since the same preset can be included multiple times
            preset = $.extend({ groupIndex: button.id }, preset);

            if (!group) {
                group = groups[groupID] = {
                    id: groupID+1,
                    name: "Preset PG" + (groupID+1),
                    presets: []
                };
            }

            group.presets.push(preset);

        });

        return $.map(groups, function(group) {
            return group;
        });
    }

    $scope.groups = [];

    $scope.$watchGroup(['groupBy', 'state.System'], function() {
        var presets = $scope.state.System.PresetMgr.Preset;
        var groups;

        if ($scope.groupBy == 'sno') {
            groups = groupBySno(presets);
        } else if ($scope.groupBy == 'console') {
            groups = groupByConsole(presets);
        } else {

            groups = [{
                id: 0,
                name: "",
                presets: $.map(presets, function(preset){
                    return $.extend({groupIndex: preset.id}, preset);
                }),
            }];
        }

        Console.log("Refresh presets: presets=" + Object.keys(presets).length + ", groupBy=" + $scope.groupBy + ", groups=" + groups.length);

        $scope.groups = groups;
    });

    // active preset on server; reset while changing...
    $scope.activePresetID = null;
    $scope.$watch('state.System', function(system) {
        $scope.activePresetID = system.PresetMgr.LastRecall
    });

    // select preset for preview
    $scope.previewPreset = null
    $scope.select = function(preset) {
        $scope.activePresetID = null;

        Console.log("Recall preset " + preset.id + ": " + preset.name);

        Preset.activate({id: preset.id},
            function success(r) {
                $scope.previewPreset = preset;
            },
            function error(e) {

            }
        );
    };

    // take preset for program
    $scope.autoTake = $location.search().autotake || false;

    $scope.$watch('autoTake', function(autoTake) {
        $location.search('autotake', autoTake ? true : null);
    });

    $scope.programPreset = null;
    $scope.take = function(preset) {
        if (preset) {

        } else if ($scope.previewPreset) {
            preset = $scope.previewPreset;
        } else {
            return;
        }

        Console.log("Take preset " + preset.id + ": " + preset.name);

        $scope.activePresetID = null;
        Preset.activate({id: preset.id, live: true},
            function success(r) {
                $scope.programPreset = preset;
            },
            function error(e) {

            }
        );
    };

    // preview -> program
    $scope.cut = function() {
        Console.log("Cut")

        Preset.activate({cut: true});
    };
    $scope.autotrans = function() {
        Console.log("AutoTrans")

        Preset.activate({autotrans: 0});
    };
})

.controller('SystemCtrl', function($scope) {

})

;
<commit_msg>server web: show auxes in main view<commit_after>angular.module('qmsk.e2.server', [
        'qmsk.e2',
        'qmsk.e2.console',
        'qmsk.e2.web',
        'ngResource',
        'ngRoute',
        'jsonFormatter',
        'ui.bootstrap',
])

.config(function($routeProvider) {
    $routeProvider
        .when('/main', {
            templateUrl: '/static/qmsk.e2/server/main.html',
            controller: 'MainCtrl',
            reloadOnSearch: false,
        })
        .when('/sources', {
            templateUrl: '/static/qmsk.e2/server/sources.html',
            controller: 'SourcesCtrl',
        })
        .when('/screens', {
            templateUrl: '/static/qmsk.e2/server/screens.html',
            controller: 'ScreensCtrl',
        })
        .when('/auxes', {
            templateUrl: '/static/qmsk.e2/server/auxes.html',
            controller: 'AuxesCtrl',
        })
        .when('/presets', {
            templateUrl: '/static/qmsk.e2/server/presets.html',
            controller: 'PresetsCtrl',
            reloadOnSearch: false,
        })
        .when('/system', {
            templateUrl: '/static/qmsk.e2/server/system.html',
            controller: 'SystemCtrl',
        })
        .otherwise({
            redirectTo: '/main',
        });
})

.factory('Preset', function($resource) {
    return $resource('/api/presets/:id', { }, {
        get: {
            method: 'GET',
            url: '/api/presets',
        },
        all: {
            method: 'GET',
            isArray: true,
        },
        query: {
            method: 'GET',
            isArray: false,
        },
        activate: {
            method: 'POST',
            url: '/api/presets',
        },
    }, {stripTrailingSlashes: false});
})

.filter('dimensions', function() {
    return function(dimensions) {
        if (dimensions && dimensions.width && dimensions.height) {
            return dimensions.width + "x" + dimensions.height;
        } else {
            return null;
        }
    };
})

.directive('e2Source', function() {
    return {
        restrict: 'AE',
        scope: {
            source: '=source',
            input: '=input',
            detail: '=detail',
        },
        templateUrl: '/static/qmsk.e2/server/source.html',
    };
})

.controller('MainCtrl', function($scope, $location) {
    $scope.sources = [];

    $scope.$watch('state.System', function(system) {
        // compute a merged state mapping sources to their active destinations
        // TODO: aux destinations
        $scope.sources = $.map(system.SrcMgr.SourceCol, function(source, sourceID){
            var item = {
                id: sourceID,
                type: source.SrcType,
                name: source.Name,
                source: source,
                active: false,
                preview: [],
                program: [],
            };

            if (source.SrcType == "input") {
                item.input = system.SrcMgr.InputCfgCol[source.InputCfgIndex];
            }

            $.each(system.DestMgr.ScreenDestCol, function(screenID, screen) {
                var output = {
                    type: "screen",
                    id: screenID,
                    name: screen.Name,
                    active: screen.IsActive > 0,
                };

                $.each(screen.LayerCollection, function(layerID, layer) {
                    if (layer.PgmMode > 0 && layer.LastSrcIdx == sourceID) {
                        output.program = true;
                    }

                    if (layer.PvwMode > 0 && layer.LastSrcIdx == sourceID) {
                        output.preview = true;
                    }
                });

                if (output.program) {
                    item.program.push(output);
                }
                if (output.preview) {
                    item.preview.push(output);
                }
                if (output.active && output.preview) {
                    item.active = true;
                }
            });

            $.each(system.DestMgr.AuxDestCol, function(auxID, aux) {
              var output = {
                  type: "aux",
                  id: auxID,
                  name: aux.Name,
                  active: aux.IsActive > 0,
              };

              if (aux.PgmLastSrcIndex == sourceID) {
                output.program = true;
                item.program.push(output);
              }
              if (aux.PvwLastSrcIndex == sourceID) {
                output.preview = true;
                item.preview.push(output);
              }

              if (output.active && output.preview) {
                  item.active = true;
              }
            });

            return item;
        });
    });

    $scope.selectOrder = function(order) {
        $scope.order = order;
        $scope.orderBy = function(){
            switch (order) {
            case 'source':
                return ['-type', 'name'];
            case 'preview':
                return ['preview_screens', 'program_screens'];
            case 'program':
                return ['program_screens', 'preview_screens'];
            default:
                return [];
            }
        }();

        $location.search('order', order || null);
    };
    $scope.selectOrder($location.search().order || 'source');
})

.controller('SourcesCtrl', function($scope) {

})

.controller('ScreensCtrl', function($scope) {

})

.controller('AuxesCtrl', function($scope) {

})

.controller('PresetsCtrl', function($scope, Preset, $location, Console) {
    // size
    $scope.displaySize = $location.search().size || 'normal';

    $scope.$watch('displaySize', function(displaySize) {
        $location.search('size', displaySize);
    });

    // collapsing
    $scope.showGroup = $location.search().group || null;
    $scope.collapseGroups = {};

    $scope.selectGroup = function(groupID) {
        $scope.collapseGroups = {};

        if (groupID != $scope.showGroup) {
            $scope.showGroup = groupID;

            $location.search('group', groupID);
        }
    }
    $scope.clearGroup = function() {
        $scope.collapseGroups = {};
        $scope.showGroup = null;
        $location.search('group', null);
    };
    $scope.toggleGroup = function(groupID) {
        $scope.collapseGroups[groupID] = !$scope.collapseGroups[groupID];
    };

    // grouping
    $scope.groupBy = $location.search().groupBy || 'sno';

    $scope.$watch('groupBy', function(groupBy) {
        $location.search('groupBy', groupBy);
    });

    function groupBySno(presets) {
        var groups = { };

        $.each(presets, function(id, preset) {
            var groupID = preset.presetSno.Group;
            var groupIndex = preset.presetSno.Index;

            preset = $.extend({groupIndex: groupIndex}, preset);

            // group it
            var group = groups[groupID];

            if (!group) {
                group = groups[groupID] = {
                    id: groupID,
                    name: groupID,
                    presets: []
                };
            }

            group.presets.push(preset);
        });

        return $.map(groups, function(group, id){
            return group;
        });
    };
    function groupByConsole(presets) {
        var groups = { };

        $.each($scope.state.System.ConsoleLayoutMgr.ConsoleLayout.PresetBusColl, function(buttonID, button) {
            var groupID = Math.floor(button.id / 12); // rows of 12 keys
            var group = groups[groupID];
            var preset = presets[button.ConsoleButtonTypeIndex];

            if (button.ConsoleButtonType != 'preset' || !preset) {
                return;
            }

            // copy with groupIndex, since the same preset can be included multiple times
            preset = $.extend({ groupIndex: button.id }, preset);

            if (!group) {
                group = groups[groupID] = {
                    id: groupID+1,
                    name: "Preset PG" + (groupID+1),
                    presets: []
                };
            }

            group.presets.push(preset);

        });

        return $.map(groups, function(group) {
            return group;
        });
    }

    $scope.groups = [];

    $scope.$watchGroup(['groupBy', 'state.System'], function() {
        var presets = $scope.state.System.PresetMgr.Preset;
        var groups;

        if ($scope.groupBy == 'sno') {
            groups = groupBySno(presets);
        } else if ($scope.groupBy == 'console') {
            groups = groupByConsole(presets);
        } else {

            groups = [{
                id: 0,
                name: "",
                presets: $.map(presets, function(preset){
                    return $.extend({groupIndex: preset.id}, preset);
                }),
            }];
        }

        Console.log("Refresh presets: presets=" + Object.keys(presets).length + ", groupBy=" + $scope.groupBy + ", groups=" + groups.length);

        $scope.groups = groups;
    });

    // active preset on server; reset while changing...
    $scope.activePresetID = null;
    $scope.$watch('state.System', function(system) {
        $scope.activePresetID = system.PresetMgr.LastRecall
    });

    // select preset for preview
    $scope.previewPreset = null
    $scope.select = function(preset) {
        $scope.activePresetID = null;

        Console.log("Recall preset " + preset.id + ": " + preset.name);

        Preset.activate({id: preset.id},
            function success(r) {
                $scope.previewPreset = preset;
            },
            function error(e) {

            }
        );
    };

    // take preset for program
    $scope.autoTake = $location.search().autotake || false;

    $scope.$watch('autoTake', function(autoTake) {
        $location.search('autotake', autoTake ? true : null);
    });

    $scope.programPreset = null;
    $scope.take = function(preset) {
        if (preset) {

        } else if ($scope.previewPreset) {
            preset = $scope.previewPreset;
        } else {
            return;
        }

        Console.log("Take preset " + preset.id + ": " + preset.name);

        $scope.activePresetID = null;
        Preset.activate({id: preset.id, live: true},
            function success(r) {
                $scope.programPreset = preset;
            },
            function error(e) {

            }
        );
    };

    // preview -> program
    $scope.cut = function() {
        Console.log("Cut")

        Preset.activate({cut: true});
    };
    $scope.autotrans = function() {
        Console.log("AutoTrans")

        Preset.activate({autotrans: 0});
    };
})

.controller('SystemCtrl', function($scope) {

})

;
<|endoftext|>


<commit_before>function initMap() {
    "use strict";
    var scale = $mc.width() / 3600,
        pings = [],
        ctx = $("#pings")[0].getContext("2d");

    glow.map = {};

    ctx.fillStyle = "#fff";

    /* Shuffle the array in place. (Fisher-Yates) */
    var shuffle = function(xs) {
        var i = xs.length, j, tmp;
        if (i == 0) { return; }
        while (--i) {
            j = Math.floor(Math.random() * (i + 1));
            tmp = xs[j];
            xs[j] = xs[i];
            xs[i] = tmp;
        }
    };

    function addPing(latitude, longitude) {
        longitude = ~~((-parseFloat(longitude)+90)*10*scale);
        latitude = ~~((parseFloat(latitude)+180)*10*scale);
        for (var n = 0; n<pings.length; n++) {
            if (pings[n][0] < 0) {
                pings[n][0] = 0;
                pings[n][1] = longitude;
                pings[n][2] = latitude;
                return;
            }
        }
        pings.push([0, longitude, latitude]);
    }
    /* Each ping looks like [latitude, longitude, count]. It represents the
     * numbers of downloads in the timeframe from this location. */
    glow.map.playNext = function() {
        var response = glow.data.map.next,
            /* [date, total, [pings]] */
            data = response.data,
            pings = data[2],
            currentData = [];

        /* Add `count` [lat, long] pairs to currentData, then shuffle the whole
         * thing. */
        for (var j = 0, jj = pings.length; j < jj; j++) {
            // My kingdom for destructuring bind.
            var ping = pings[j], loc = [ping[0], ping[1]], count = ping[2];
            for (var k = 0; k < count; k++) {
                currentData.push(loc);
            }
        }
        shuffle(currentData);

        /* How many pings we've been through so far. */
        var index = 0, total = currentData.length;
        function drawPings(i) {
            for (var goal = i * total; index < goal; index++) {
                addPing.apply(null, currentData[index]);
            }
        }

        vast.animate.over(response.interval * 1000, drawPings, this,
                          {after: glow.map.playNext});
        glow.fetchMap(response.interval);
    };

    var i,p,l,el;
    function iteratePings(t) {
        for (i=0; i<pings.length; i++) {
            p = pings[i];
            if (p[0] < 0) continue;
            ctx.clearRect(p[2]-5,p[1]-5,10,10);
        }
        for (i=0; i<pings.length; i++) {
            p = pings[i];
            if (p[0] < 0) continue;
            if (p[0]==0) {
                p[0] = t;
            }
            l = (t-p[0])/1000;
            if (l > 1) {
                p[0] = -1;
            } else {
                ctx.beginPath();
                ctx.fillStyle = "rgba(255,255,255," + (1-l) + ")";
                ctx.arc(p[2],p[1],5*l,0,Math.PI*2,true);
                ctx.fill();
            }
        }
    }
    vast.GlobalClock.register(iteratePings, this);

    $(window).resize(vast.debounce(function() {
        $("#pings").css({
            width: $mc.width() + "px",
            height: $mc.height() + "px"
        });
        $("#pings")[0].width=$mc.width();
        $("#pings")[0].height=$mc.height();
    }, 500, this));

}
<commit_msg>readability<commit_after>function initMap() {
    "use strict";
    var scale = $mc.width() / 3600,
        pings = [],
        ctx = $("#pings")[0].getContext("2d");

    glow.map = {};

    ctx.fillStyle = "#fff";

    /* Shuffle the array in place. (Fisher-Yates) */
    var shuffle = function(xs) {
        var i = xs.length, j, tmp;
        if (i == 0) { return; }
        while (--i) {
            j = Math.floor(Math.random() * (i + 1));
            tmp = xs[j];
            xs[j] = xs[i];
            xs[i] = tmp;
        }
    };

    function addPing(latitude, longitude) {
        longitude = ~~((-parseFloat(longitude)+90)*10*scale);
        latitude = ~~((parseFloat(latitude)+180)*10*scale);
        for (var n = 0; n<pings.length; n++) {
            if (pings[n][0] < 0) {
                pings[n][0] = 0;
                pings[n][1] = longitude;
                pings[n][2] = latitude;
                return;
            }
        }
        pings.push([0, longitude, latitude]);
    }
    /* Each ping looks like [latitude, longitude, count]. It represents the
     * numbers of downloads in the timeframe from this location. */
    glow.map.playNext = function() {
        var response = glow.data.map.next,
            /* [date, total, [pings]] */
            data = response.data,
            pings = data[2],
            currentData = [];

        /* Add `count` [lat, long] pairs to currentData, then shuffle the whole
         * thing. */
        for (var j = 0, jj = pings.length; j < jj; j++) {
            // My kingdom for destructuring bind.
            var ping = pings[j], loc = [ping[0], ping[1]], count = ping[2];
            for (var k = 0; k < count; k++) {
                currentData.push(loc);
            }
        }
        shuffle(currentData);

        /* How many pings we've been through so far. */
        var index = 0, total = currentData.length;
        function drawPings(i) {
            for (var goal = i * total; index < goal; index++) {
                addPing.apply(null, currentData[index]);
            }
        }

        vast.animate.over(response.interval * 1000, drawPings, this,
                          {after: glow.map.playNext});
        glow.fetchMap(response.interval);
    };

    function iteratePings(t) {
        for (i=0; i<pings.length; i++) {
            p = pings[i];
            if (p[0] < 0) continue;
            ctx.clearRect(p[2]-5,p[1]-5,10,10);
        }
        for (var i = 0, ii = pings.length; i < ii; i++) {
            p = pings[i];
            if (p[0] < 0) {
                continue;
            }
            if (p[0] == 0) {
                p[0] = t;
            }
            var age = (t - p[0]) / 1000;
            if (age > 1) {
                p[0] = -1;
            } else {
                ctx.beginPath();
                ctx.fillStyle = "rgba(255, 255, 255, " + (1 - age) + ")";
                ctx.arc(p[2], p[1], 5 * age, 0, Math.PI * 2, true);
                ctx.fill();
            }
        }
    }
    vast.GlobalClock.register(iteratePings, this);

    $(window).resize(vast.debounce(function() {
        $("#pings").css({
            width: $mc.width() + "px",
            height: $mc.height() + "px"
        });
        $("#pings")[0].width=$mc.width();
        $("#pings")[0].height=$mc.height();
    }, 500, this));
}
<|endoftext|>


<commit_before>// Current version turns on office light when there's motion
// this code has an adaptive algorithm that extends the time the
// light is on the more often it is turned on.

const hue = require("node-hue-api")
const moment = require("moment")
const constants = require('./constants')
const api = new hue.HueApi(constants.ip, constants.username)
const particle = require('./lib/Particle')
const _ = require('underscore')
const lightState = hue.lightState
const huelib = require('./lib/Hue')
const lightName = require('./lib/LightName')

const debug = function(m) { console.log(`${moment().format('MMM DD hh:mm:ss')}   ${m}`) }

const lightIntervals = [10, 60, 5*60, 5*60, 10*60] // seconds
let lightIntervalIndex = 0

let senseTimerHandle = null
let lightTimerHandle = null
let motionSticky = false

// called whenever motion is seen
const onMotion = function() {
	debug(`saw motion`)
	debug(`setting light timer to ${getLightInterval()} seconds`)
	motionSticky = true
	turnLightsOn()
	clearTimeout(lightTimerHandle)
	lightTimerHandle = setTimeout(turnLightsOff, getLightInterval() * 1000)

	// set a timer that determines next time to see if there's been motion
	// set twice as long as light is on, so that user can wave to turn light on
	// when it goes off, and process is still sensing
	if (!senseTimerHandle) {
		debug(`setting sense timer to ${getLightInterval() *2} seconds`)
		senseTimerHandle = setTimeout(senseTimerExpired, getLightInterval() * 2 * 1000)
	}
}

const onHighMotion = function() {
	debug(`saw lots of motion, setting interval to max`)
	lightIntervalIndex = lightIntervals.length - 1
}

const senseTimerExpired = function() {
	debug(`sense timer expired`)
	senseTimerHandle = null
	if (motionSticky) {
		debug(`there was motion during sense period`)
		motionSticky = false
		increaseLightInterval()
		// set timer again and wait another sense interval
		debug(`setting sense timer for ${getLightInterval() * 2} seconds`)
		senseTimerHandle = setTimeout(senseTimerExpired, getLightInterval() * 2 * 1000)
	} else {
		// no motion in last sense interval
		// set sense interval back to default and turn lights off
		resetLightInterval()
		debug(`no motion in sense interval, light interval is now ${getLightInterval()} seconds`)
	}
}

const getLightInterval = function() {
	return lightIntervals[lightIntervalIndex]
}

const increaseLightInterval = function() {
	// don't increase past length of array
	lightIntervalIndex = Math.min(lightIntervalIndex + 1, lightIntervals.length - 1)
}

const resetLightInterval = function() {
	lightIntervalIndex = 0
}

// turn light to low on then fade to on. Turn light to low off, then fade to off
var lights = null // set by main from argv
const lowOn = lightState.create().on(true).hsb(100, 30, 0)
const on = lightState.create().on(true).white(325, 100	).transition(3000)
const lowOff = lightState.create().on(true).hsb(250, 100, 0).transition(10000)
const off = lightState.create().on(false)

// used to transition between low on to on and low off to off states.
let lightTimer = null
let _lightState = 'off' // off, lowOff, on, lowOn

const turnLightsOn = function() {
	if (isDaytime()) { return }
	if (_lightState === 'off') {
		// set to lowOn, wait, On
		clearTimeout(lightTimer)
		setLights(lights, lowOn)
		_lightState = 'lowOn'
		lightTimer = setTimeout(function() {
			setLights(lights, on)
			_lightState = 'on'
		}, 1000)
	} else if (_lightState === 'lowOff') {
		// straight to on
		clearTimeout(lightTimer)
		setLights(lights, on)
		_lightState = 'on'
	}
	// if _lightState is lowOn or on, do nothing
}

const turnLightsOff = function() {
	if (_lightState === 'on' || _lightState === 'lowOn') {
		debug(`turning lights off`)
		clearTimeout(lightTimer)
		setLights(lights, lowOff)
		_lightState = 'lowOff'
		lightTimer = setTimeout(function() {
			setLights(lights, off)
			_lightState = 'off'
		}, 10000)
	}
}

const setLights = function(lights, lightState) {
	lights.forEach(function(light) {
		api.setLightState(light.id, lightState)
	})
}

const isDaytime = function() {
	let h = moment().hour()
	return (h > 7 && h < 17)
}

const loop = function() {
	particle.getMotion()
	.then(function(reply) {
		if (reply.return_value === 1) {
			onMotion()
		} else if (reply.return_value === 2) {
			onHighMotion()
			onMotion()
		}
		setTimeout(loop, 1000)
	}).catch(function(err) {
		debug(`Caught error: ${err}`)
		setTimeout(loop, 10000)
	})
}

const main = function() {
	if (process.argv.length < 3) {
		usage()
		process.exit(0)
	}

	debug(`starting`)
	lights = lightName.lightsFromNamesOrExit(process.argv.slice(2))
	setLights(lights, off)
	loop()
}

const usage = function() {
	debug("usage: node " + __filename + " LIGHTNAME LIGHTNAME ...")
	debug("Each LIGHTNAME is the name of a light defined in constants.js:")
	var lightNames = _.pluck(constants.lights, 'name').join(", ")
	debug('"' + lightNames + '"')
}

main()

<commit_msg>changed timing<commit_after>// Current version turns on office light when there's motion
// this code has an adaptive algorithm that extends the time the
// light is on the more often it is turned on.

const hue = require("node-hue-api")
const moment = require("moment")
const constants = require('./constants')
const api = new hue.HueApi(constants.ip, constants.username)
const particle = require('./lib/Particle')
const _ = require('underscore')
const lightState = hue.lightState
const huelib = require('./lib/Hue')
const lightName = require('./lib/LightName')

const debug = function(m) { console.log(`${moment().format('MMM DD hh:mm:ss')}   ${m}`) }

const lightIntervals = [10, 60, 5*60, 5*60, 10*60] // seconds
let lightIntervalIndex = 0

let senseTimerHandle = null
let lightTimerHandle = null
let motionSticky = false

// called whenever motion is seen
const onMotion = function() {
	debug(`saw motion`)
	debug(`setting light timer to ${getLightInterval()} seconds`)
	motionSticky = true
	turnLightsOn()
	clearTimeout(lightTimerHandle)
	lightTimerHandle = setTimeout(turnLightsOff, getLightInterval() * 1000)

	// set a timer that determines next time to see if there's been motion
	// set twice as long as light is on, so that user can wave to turn light on
	// when it goes off, and process is still sensing
	if (!senseTimerHandle) {
		debug(`setting sense timer to ${getLightInterval()} seconds`)
		senseTimerHandle = setTimeout(senseTimerExpired, getLightInterval() * 1000)
	}
}

const onHighMotion = function() {
	debug(`saw lots of motion, setting interval to max`)
	lightIntervalIndex = lightIntervals.length - 1
}

const senseTimerExpired = function() {
	debug(`sense timer expired`)
	senseTimerHandle = null
	if (motionSticky) {
		debug(`there was motion during sense period`)
		motionSticky = false
		increaseLightInterval()
		// set timer again and wait another sense interval
		debug(`setting sense timer for ${getLightInterval()} seconds`)
		senseTimerHandle = setTimeout(senseTimerExpired, getLightInterval() * 1000)
	} else {
		// no motion in last sense interval
		// set sense interval back to default and turn lights off
		resetLightInterval()
		debug(`no motion in sense interval, light interval is now ${getLightInterval()} seconds`)
	}
}

const getLightInterval = function() {
	return lightIntervals[lightIntervalIndex]
}

const increaseLightInterval = function() {
	// don't increase past length of array
	lightIntervalIndex = Math.min(lightIntervalIndex + 1, lightIntervals.length - 1)
}

const resetLightInterval = function() {
	lightIntervalIndex = 0
}

// turn light to low on then fade to on. Turn light to low off, then fade to off
var lights = null // set by main from argv
const lowOn = lightState.create().on(true).hsb(100, 30, 0)
const on = lightState.create().on(true).white(325, 100	).transition(3000)
const lowOff = lightState.create().on(true).hsb(250, 100, 0).transition(10000)
const off = lightState.create().on(false)

// used to transition between low on to on and low off to off states.
let lightTimer = null
let _lightState = 'off' // off, lowOff, on, lowOn

const turnLightsOn = function() {
	if (isDaytime()) { return }
	if (_lightState === 'off') {
		// set to lowOn, wait, On
		clearTimeout(lightTimer)
		setLights(lights, lowOn)
		_lightState = 'lowOn'
		lightTimer = setTimeout(function() {
			setLights(lights, on)
			_lightState = 'on'
		}, 1000)
	} else if (_lightState === 'lowOff') {
		// straight to on
		clearTimeout(lightTimer)
		setLights(lights, on)
		_lightState = 'on'
	}
	// if _lightState is lowOn or on, do nothing
}

const turnLightsOff = function() {
	if (_lightState === 'on' || _lightState === 'lowOn') {
		debug(`turning lights off`)
		clearTimeout(lightTimer)
		setLights(lights, lowOff)
		_lightState = 'lowOff'
		lightTimer = setTimeout(function() {
			setLights(lights, off)
			_lightState = 'off'
		}, 10000)
	}
}

const setLights = function(lights, lightState) {
	lights.forEach(function(light) {
		api.setLightState(light.id, lightState)
	})
}

const isDaytime = function() {
	let h = moment().hour()
	return (h > 7 && h < 17)
}

const loop = function() {
	particle.getMotion()
	.then(function(reply) {
		if (reply.return_value === 1) {
			onMotion()
		} else if (reply.return_value === 2) {
			onHighMotion()
			onMotion()
		}
		setTimeout(loop, 1000)
	}).catch(function(err) {
		debug(`Caught error: ${err}`)
		setTimeout(loop, 10000)
	})
}

const main = function() {
	if (process.argv.length < 3) {
		usage()
		process.exit(0)
	}

	debug(`starting`)
	lights = lightName.lightsFromNamesOrExit(process.argv.slice(2))
	setLights(lights, off)
	loop()
}

const usage = function() {
	debug("usage: node " + __filename + " LIGHTNAME LIGHTNAME ...")
	debug("Each LIGHTNAME is the name of a light defined in constants.js:")
	var lightNames = _.pluck(constants.lights, 'name').join(", ")
	debug('"' + lightNames + '"')
}

main()

<|endoftext|>