<commit_before>'use strict'
var conn=require('./conn'),Editor=require('./editor').Editor,IDE=require('./ide').IDE,prefs=require('./prefs')
require('./prefs-colours');require('./demo');require('./cm-foldgutter');require('./wse')
$(function(){
  // don't use Alt- keystrokes on the Mac (see email from 2015-09-01)
  var h=CodeMirror.keyMap.emacsy;for(var k in h)if(/^alt-[a-z]$/i.test(k))delete h[k]
  if(D.nwjs){
    var zM=11 // zoom level can be between -zM and zM inclusive
    var ZMI=function(){prefs.zoom(Math.min( zM,prefs.zoom()+1));updPW()}
    var ZMO=function(){prefs.zoom(Math.max(-zM,prefs.zoom()-1));updPW()}
    var ZMR=function(){prefs.zoom(0);updPW()}
    var updPW=function(){D.ide&&D.ide.wins&&D.ide.wins[0]&&D.ide.wins[0].updPW()}
    $.extend(CodeMirror.commands,{ZMI:ZMI,ZMO:ZMO,ZMR:ZMR})
    $(document).bind('mousewheel',function(e){
      var d=e.originalEvent.wheelDelta;d&&e.ctrlKey&&!e.shiftKey&&!e.altKey&&(d>0?ZMI:ZMO)()
    })
    $('body').addClass('zoom'+prefs.zoom())
    prefs.zoom(function(z){
      if(!D.ide)return
      var wins=D.ide.wins
      for (var x in wins){
        var $b=$('body',wins[x].getDocument())
        $b.prop('class','zoom'+z+' '+$b.prop('class').split(/\s+/).filter(function(s){return!/^zoom-?\d+$/.test(s)}).join(' '))
        wins[x].refresh()
      }
      wins[0].scrollCursorIntoView()
    })
  }
  D.open=D.open||function(url,o){
    var x=o.x,y=o.y,width=o.width,height=o.height,spec='resizable=1'
    if(width!=null&&height!=null)spec+=',width='+width+',height='+height
    if(x!=null&&y!=null)spec+=',left='+x+',top='+y+',screenX='+x+',screenY='+y
    return!!open(url,'_blank',spec)
  }
  D.openExternal||(D.openExternal=function(x){open(x,'_blank')})
  D.setTitle||(D.setTitle=function(s){document.title=s})
  var urlParams={},ref=(location+'').replace(/^[^\?]*($|\?)/,'').split('&')
  for(var i=0;i<ref.length;i++){var m=/^([^=]*)=?(.*)$/.exec(ref[i]);urlParams[unescape(m[1]||'')]=unescape(m[2]||'')}
  var win=urlParams.win
  if(D.floating&&win){
    $('body').addClass('floating-window')
    $(window).resize(function(){ed&&ed.updSize()})
    var pe=opener.D.pendingEditors[win], editorOpts=pe.editorOpts, ee=pe.ee, ide=pe.ide
    D.ide=opener.D.ide
    var ed=D.ide.wins[win]=new Editor(ide,$(document.body),editorOpts)
    ed.open(ee);ed.updSize();D.setTitle(ed.name)
    window.onbeforeunload=function(){return ed.onbeforeunload()}
    setTimeout(function(){ed.refresh()},500) // work around a rendering issue on Ubuntu
    D.ide.unblock()
  }else{
    D.socket=(D.createSocket||function(){
      var skt=new WebSocket((location.protocol==='https:'?'wss://':'ws://')+location.host)
      var l={},q=[],io={} // l:listeners, q:send queue, io:socket.io-like API
      var flush=function(){while(skt.readyState===1&&q.length)skt.send(q.shift())}
      var io={
        emit:function(x,y){q.push(JSON.stringify([x,y]));flush();return this},
        on:function(e,f){(l[e]=l[e]||[]).push(f);return this},
        onevent:function(x){var a=l[x.data[0]]||[];for(var i=0;i<a.length;i++)a[i].apply(null,x.data.slice(1))}
      }
      skt.onopen=flush
      skt.onerror=function(e){console.info('ws error:',e)}
      skt.onmessage=function(m){io.onevent({data:JSON.parse(m.data)})}
      return io
    })()
    if(!D.quit)D.quit=close
    var e=D.process?D.process.env:{}
    if(e.RIDE_LISTEN)conn().listen(e.RIDE_LISTEN)
    else if(e.RIDE_CONNECT)conn().connect(e.RIDE_CONNECT)
    else if(+e.RIDE_SPAWN){ // the value of this env var should be '0' or '1'
      new IDE;D.socket.emit('*launch',{}) // '*error' is handled in ide.coffee
      window.onbeforeunload=function(){D.socket.emit('Exit',{code:0})}
    }
    else conn()
  }

  if(!prefs.theme()){
    prefs.theme(D.mac||/^(darwin|mac|ipad|iphone|ipod)/i.test(navigator?navigator.platform:'')?'cupertino':
                D.win||/^win/.test(navigator?navigator.platform:'')?'redmond':'classic')
  }
  var updThm=function(){$('#thm').html('@import url(themes/'+prefs.theme()+'.css);')}
  prefs.theme(function(){updThm();D.ide&&D.ide.layout.resizeAll()});updThm()

  D.nwjs&&$('body').addClass(D.mac?'platform-mac':D.win?'platform-windows':'')

  $(window).on('focus blur',function(e){$('body').toggleClass('window-focused',window.focused=e.type==='focus')})
  window.focused=true

  // Some library is doing "localStorage.debug=undefined" instead of "delete localStorage.debug".
  // It doesn't work that way.  It may work for other objects, but the values in localStorage
  // are always strings and that leaves us with 'undefined' as a string.  So, let's clean up...
  delete localStorage.debug

  // migrations
  var db=D.db||localStorage
  db.version=db.version||'[3,0]' // localStorage.version defaults to current version
  var v=JSON.parse(db.version)
  if(v[0]<3&&db.favs){
    try{db.favs=JSON.strigify(JSON.parse(db.favs).map(function(x){x.type='connect';x.port===4502&&delete x.port}))}
    catch(_){delete db.favs}
    db.version='[3,0]'
  }

  // Implement access keys (Alt-X) using .
  // The built-in accesskey=X doesn't handle duplicates well -- it doesn't always focus the visible one.
  $(document).keydown(function(e){
    if(e.altKey&&!e.ctrlKey&&!e.metaKey&&64<e.which&&e.which<91){ // Alt-A...Alt-Z or Alt-Shift-A...Alt-Shift-Z
      var c=String.fromCharCode(e.which).toLowerCase(),C=c.toUpperCase()
      var $ctx=$('.ui-widget-overlay').length?$('.ui-dialog:visible').last():$('body') // modal dialogs take priority
      var $a=$('u:visible',$ctx).map(function(){
        var h=this.innerHTML;if(h!==c&&h!==C)return
        var $i=$(this).closest(':input,label,a').eq(0)
        if($i.is('label'))$i=$('#'+$i.attr('for')).add($i.find(':input')).eq(0)
        return $i[0]
      })
      if($a.length>1){$a.eq(($a.index(':focus')+1)%$a.length).focus()}
      else if($a.is(':checkbox')){$a.focus().prop('checked',!$a.prop('checked')).change()}
      else if($a.is(':text,select')){$a.focus()}
      else{$a.click()}
      return!1
    }
  })

  // drag and drop
  CodeMirror.defaults.dragDrop=0;window.ondragover=window.ondrop=function(e){e.preventDefault();return!1}
  window.ondrop=function(e){
    var a=e.dataTransfer.files,f=a[0].path
    if(!D.lastSpawnedExe){$.alert('Drag and drop of workspaces works only for locally started interpreters.','Error')}
    else if(!/\.dws$/i.test(f)){$.alert('RIDE supports drag and drop only for .dws files.','Error')}
    else if(a.length!==1){$.alert('RIDE does not support dropping of multiple files.','Error')}
    else{$.confirm('Are you sure you want to )load '+f.replace(/^.*[\\\/]/,'')+'?','Load workspace',
              function(x){x&&D.ide.exec(['      )load '+f+'\n'],0)})}
    e.preventDefault();return!1
  }
})
<commit_msg>don't crash on bad drag and drop<commit_after>'use strict'
var conn=require('./conn'),Editor=require('./editor').Editor,IDE=require('./ide').IDE,prefs=require('./prefs')
require('./prefs-colours');require('./demo');require('./cm-foldgutter');require('./wse')
$(function(){
  // don't use Alt- keystrokes on the Mac (see email from 2015-09-01)
  var h=CodeMirror.keyMap.emacsy;for(var k in h)if(/^alt-[a-z]$/i.test(k))delete h[k]
  if(D.nwjs){
    var zM=11 // zoom level can be between -zM and zM inclusive
    var ZMI=function(){prefs.zoom(Math.min( zM,prefs.zoom()+1));updPW()}
    var ZMO=function(){prefs.zoom(Math.max(-zM,prefs.zoom()-1));updPW()}
    var ZMR=function(){prefs.zoom(0);updPW()}
    var updPW=function(){D.ide&&D.ide.wins&&D.ide.wins[0]&&D.ide.wins[0].updPW()}
    $.extend(CodeMirror.commands,{ZMI:ZMI,ZMO:ZMO,ZMR:ZMR})
    $(document).bind('mousewheel',function(e){
      var d=e.originalEvent.wheelDelta;d&&e.ctrlKey&&!e.shiftKey&&!e.altKey&&(d>0?ZMI:ZMO)()
    })
    $('body').addClass('zoom'+prefs.zoom())
    prefs.zoom(function(z){
      if(!D.ide)return
      var wins=D.ide.wins
      for (var x in wins){
        var $b=$('body',wins[x].getDocument())
        $b.prop('class','zoom'+z+' '+$b.prop('class').split(/\s+/).filter(function(s){return!/^zoom-?\d+$/.test(s)}).join(' '))
        wins[x].refresh()
      }
      wins[0].scrollCursorIntoView()
    })
  }
  D.open=D.open||function(url,o){
    var x=o.x,y=o.y,width=o.width,height=o.height,spec='resizable=1'
    if(width!=null&&height!=null)spec+=',width='+width+',height='+height
    if(x!=null&&y!=null)spec+=',left='+x+',top='+y+',screenX='+x+',screenY='+y
    return!!open(url,'_blank',spec)
  }
  D.openExternal||(D.openExternal=function(x){open(x,'_blank')})
  D.setTitle||(D.setTitle=function(s){document.title=s})
  var urlParams={},ref=(location+'').replace(/^[^\?]*($|\?)/,'').split('&')
  for(var i=0;i<ref.length;i++){var m=/^([^=]*)=?(.*)$/.exec(ref[i]);urlParams[unescape(m[1]||'')]=unescape(m[2]||'')}
  var win=urlParams.win
  if(D.floating&&win){
    $('body').addClass('floating-window')
    $(window).resize(function(){ed&&ed.updSize()})
    var pe=opener.D.pendingEditors[win], editorOpts=pe.editorOpts, ee=pe.ee, ide=pe.ide
    D.ide=opener.D.ide
    var ed=D.ide.wins[win]=new Editor(ide,$(document.body),editorOpts)
    ed.open(ee);ed.updSize();D.setTitle(ed.name)
    window.onbeforeunload=function(){return ed.onbeforeunload()}
    setTimeout(function(){ed.refresh()},500) // work around a rendering issue on Ubuntu
    D.ide.unblock()
  }else{
    D.socket=(D.createSocket||function(){
      var skt=new WebSocket((location.protocol==='https:'?'wss://':'ws://')+location.host)
      var l={},q=[],io={} // l:listeners, q:send queue, io:socket.io-like API
      var flush=function(){while(skt.readyState===1&&q.length)skt.send(q.shift())}
      var io={
        emit:function(x,y){q.push(JSON.stringify([x,y]));flush();return this},
        on:function(e,f){(l[e]=l[e]||[]).push(f);return this},
        onevent:function(x){var a=l[x.data[0]]||[];for(var i=0;i<a.length;i++)a[i].apply(null,x.data.slice(1))}
      }
      skt.onopen=flush
      skt.onerror=function(e){console.info('ws error:',e)}
      skt.onmessage=function(m){io.onevent({data:JSON.parse(m.data)})}
      return io
    })()
    if(!D.quit)D.quit=close
    var e=D.process?D.process.env:{}
    if(e.RIDE_LISTEN)conn().listen(e.RIDE_LISTEN)
    else if(e.RIDE_CONNECT)conn().connect(e.RIDE_CONNECT)
    else if(+e.RIDE_SPAWN){ // the value of this env var should be '0' or '1'
      new IDE;D.socket.emit('*launch',{}) // '*error' is handled in ide.coffee
      window.onbeforeunload=function(){D.socket.emit('Exit',{code:0})}
    }
    else conn()
  }

  if(!prefs.theme()){
    prefs.theme(D.mac||/^(darwin|mac|ipad|iphone|ipod)/i.test(navigator?navigator.platform:'')?'cupertino':
                D.win||/^win/.test(navigator?navigator.platform:'')?'redmond':'classic')
  }
  var updThm=function(){$('#thm').html('@import url(themes/'+prefs.theme()+'.css);')}
  prefs.theme(function(){updThm();D.ide&&D.ide.layout.resizeAll()});updThm()

  D.nwjs&&$('body').addClass(D.mac?'platform-mac':D.win?'platform-windows':'')

  $(window).on('focus blur',function(e){$('body').toggleClass('window-focused',window.focused=e.type==='focus')})
  window.focused=true

  // Some library is doing "localStorage.debug=undefined" instead of "delete localStorage.debug".
  // It doesn't work that way.  It may work for other objects, but the values in localStorage
  // are always strings and that leaves us with 'undefined' as a string.  So, let's clean up...
  delete localStorage.debug

  // migrations
  var db=D.db||localStorage
  db.version=db.version||'[3,0]' // localStorage.version defaults to current version
  var v=JSON.parse(db.version)
  if(v[0]<3&&db.favs){
    try{db.favs=JSON.strigify(JSON.parse(db.favs).map(function(x){x.type='connect';x.port===4502&&delete x.port}))}
    catch(_){delete db.favs}
    db.version='[3,0]'
  }

  // Implement access keys (Alt-X) using .
  // The built-in accesskey=X doesn't handle duplicates well -- it doesn't always focus the visible one.
  $(document).keydown(function(e){
    if(e.altKey&&!e.ctrlKey&&!e.metaKey&&64<e.which&&e.which<91){ // Alt-A...Alt-Z or Alt-Shift-A...Alt-Shift-Z
      var c=String.fromCharCode(e.which).toLowerCase(),C=c.toUpperCase()
      var $ctx=$('.ui-widget-overlay').length?$('.ui-dialog:visible').last():$('body') // modal dialogs take priority
      var $a=$('u:visible',$ctx).map(function(){
        var h=this.innerHTML;if(h!==c&&h!==C)return
        var $i=$(this).closest(':input,label,a').eq(0)
        if($i.is('label'))$i=$('#'+$i.attr('for')).add($i.find(':input')).eq(0)
        return $i[0]
      })
      if($a.length>1){$a.eq(($a.index(':focus')+1)%$a.length).focus()}
      else if($a.is(':checkbox')){$a.focus().prop('checked',!$a.prop('checked')).change()}
      else if($a.is(':text,select')){$a.focus()}
      else{$a.click()}
      return!1
    }
  })

  // drag and drop
  CodeMirror.defaults.dragDrop=0;window.ondragover=window.ondrop=function(e){e.preventDefault();return!1}
  window.ondrop=function(e){
    var a=e.dataTransfer.files,f=(a[0]||{}).path
    if(!D.lastSpawnedExe){$.alert('Drag and drop of workspaces works only for locally started interpreters.','Error')}
    else if(!/\.dws$/i.test(f)){$.alert('RIDE supports drag and drop only for .dws files.','Error')}
    else if(a.length!==1){$.alert('RIDE does not support dropping of multiple files.','Error')}
    else{$.confirm('Are you sure you want to )load '+f.replace(/^.*[\\\/]/,'')+'?','Load workspace',
              function(x){x&&D.ide.exec(['      )load '+f+'\n'],0)})}
    e.preventDefault();return!1
  }
})
<|endoftext|>


<commit_before>;(function() {
	if(!window.io) {
		console.warn('You shall turn Ristretto on.');
	} else {
		var url = location.protocol+'//'+location.hostname+":<%= port %>/";
		var socket = io.connect(url);
		socket.on("error", function(e){
			console.warn('error ', arguments);
		})
		socket.on("connect", function() {
			console.log('Ristretto on.');
			socket.on("reload stylesheets", function() {
				var links = document.getElementsByTagName("link");
				for(var i = 0; i < links.length; i++) {
					var link = links[i];
					if(link.rel === "stylesheet") {
						link.href += "?";
					}
				}
			});
			socket.on("reload", function() {
				window.location.reload();
			});
		});
	}
})();<commit_msg>Autoreconnecting client-side script<commit_after>;(function() {
	if(!window.io) {
		console.warn('You shall turn Ristretto on.');
	} else {
		var connect_ristretto = function() {
			var url = location.protocol+'//'+location.hostname+":<%= port %>/";
			var socket = io.connect(url);
			socket.on("error", function(){
				console.warn('error', arguments);
			});
			socket.on("connect", function() {
				console.log('Ristretto on.');
				socket.on("reload stylesheets", function() {
					var links = document.getElementsByTagName("link");
					for(var i = 0; i < links.length; i++) {
						var link = links[i];
						if(link.rel === "stylesheet") {
							link.href += "?";
						}
					}
				});
				socket.on("reload", function() {
					window.location.reload();
				});
			});
		};
		connect_ristretto();
	}
})();<|endoftext|>


<commit_before>'use strict';

/**
 * nodecached client.
 * (C) 2013 Alex Fernández.
 */

// requires
require('prototypes');
var token = require('./token.js');
var server = require('./server.js');
var Log = require('log');
var net = require('net');
var testing = require('testing');

// constants
var DEFAULT_PORT = 11211;
var TIMEOUT = 5000;

// globals
var log = new Log('info');

/**
 * A client object.
 */
exports.Client = function(options, callback)
{
	// self-reference
	var self = this;

	// attributes
	var connection;
	var pending = callback;

	// init
	init();

	/**
	 * Init the connection.
	 */
	function init()
	{
		options.port = options.port || DEFAULT_PORT;
		connection = net.connect(options);
		connection.setTimeout(TIMEOUT);
		connection.on('connect', function()
		{
			log.debug('Client connected to server');
			if (pending)
			{
				pending(null);
			}
		});
		connection.on('end', function()
		{
			log.debug('Client disconnected from server');
			if (pending)
			{
				pending(null);
			}
		});
		connection.on('error', function(error)
		{
			log.error('Connection error: %s', error);
			if (pending)
			{
				pending(error);
			}
			connection.destroy();
		});
		connection.on('data', function(data)
		{
			if (!pending)
			{
				log.error('Unexpected data %s', data);
				return;
			}
			pending(null, data);
		});
		connection.on('timeout', function()
		{
			if (pending)
			{
				pending('timeout');
			}
		});
	}

	/**
	 * Get a value.
	 */
	self.get = function(key, callback)
	{
		pending = getGetter(callback);
		connection.write('get ' + key + '\r\n');
	};

	/**
	 * Get a function to receive the output of a get.
	 */
	function getGetter(callback)
	{
		return getPending(callback, function(data)
		{
			var parsed = parseGet(data);
			if (!parsed)
			{
				return callback(null, parsed);
			}
			if (parsed.startsWith('{') && parsed.endsWith('}'))
			{
				try
				{
					return callback(null, JSON.parse(parsed));
				}
				catch(exception)
				{
					log.error('Fake json in %s: %s', parsed, exception);
				}
			}
			callback(null, parsed);
		});
	}

	/**
	 * Parse the result of a get.
	 */
	function parseGet(data)
	{
		var lines = String(data).split('\r\n');
		var line = lines.shift();
		if (line == 'END')
		{
			return null;
		}
		var words = line.split(' ');
		var word = words.shift();
		if (word != 'VALUE')
		{
			log.error('Unknown token %s', word);
			return null;
		}
		word = words.shift();
		word = words.shift();
		word = words.shift();
		if (!word)
		{
			log.error('Invalid length %s', word);
			return null;
		}
		var length = parseInt(word, 10);
		line = lines.shift();
		if (line.length != length)
		{
			log.error('Unexpected line length not %s in %s', length, line);
			return null;
		}
		return line;
	}

	/**
	 * Set a value.
	 */
	self.set = function(key, exptime, value, callback)
	{
		pending = getSetter(callback);
		var message = value;
		if (typeof value != 'string')
		{
			message = JSON.stringify(value);
		}
		connection.write('set ' + key + ' 0 ' + exptime + ' ' + message.length + '\r\n');
		connection.write(message + '\r\n');
	};

	/**
	 * Get a function to receive the output of a set.
	 */
	function getSetter(callback)
	{
		return getPending(callback, function(data)
		{
			var result = String(data).trim();
			if (result == 'STORED')
			{
				return callback(null, true);
			}
			log.error('Set result: %s', result);
			callback(null, false);
		});
	}

	/**
	 * Delete a value.
	 */
	self.delete = function(key, callback)
	{
		pending = getDeleter(callback);
		connection.write('delete ' + key + '\r\n');
	};

	/**
	 * Get a function to receive the output of a delete.
	 */
	function getDeleter(callback)
	{
		return getPending(callback, function(data)
		{
			var result = String(data).trim();
			if (result == 'DELETED')
			{
				return callback(null, true);
			}
			if (result == 'NOT_FOUND')
			{
				return callback(null, false);
			}
			log.error('Delete result: %s', result);
			callback(null, false);
		});
	}

	/**
	 * Get a pending function with a callback and a handler for data.
	 */
	function getPending(callback, handler)
	{
		return function(error, result)
		{
			if (error)
			{
				return callback(error);
			}
			return handler(result);
		};
	}

	/**
	 * Stop the client.
	 */
	self.stop = function(callback)
	{
		log.debug('Stopping the client');
		pending = callback;
		connection.end();
	};
};

/**
 * Test get, set and delete.
 */
function testGetSetDelete(callback)
{
	var options = {
		port: 11235,
	};
	var key = 'test' + token.create();
	var value = {
		a: 'b',
	};
	server.start(options, function(error, nodecached)
	{
		testing.check(error, 'Could not start server', callback);
		var client = new exports.Client(options, function(error)
		{
			testing.check(error, 'Could not create client', callback);
			client.set(key, 10, value, function(error, result)
			{
				testing.check(error, 'Could not set value', callback);
				testing.assertEquals(result, true, 'Invalid set result', callback);
				client.get(key, function(error, result)
				{
					testing.check(error, 'Could not get value', callback);
					testing.assertEquals(result, value, 'Invalid get result', callback);
					client.delete(key, function(error, result)
					{
						testing.check(error, 'Could not delete value', callback);
						testing.assertEquals(result, true, 'Invalid delete result', callback);
						client.get(key, function(error, result)
						{
							testing.check(error, 'Could not get after delete', callback);
							testing.assertEquals(result, null, 'Invalid get deleted result', callback);
							client.stop(function(error)
							{
								testing.check(error, 'Could not stop client', callback);
								server.stop(nodecached, callback);
							});
						});
					});
				});
			});
		});
	});
}

/**
 * Test what happens with values not found.
 */
function testNotFound(callback)
{
	var options = {
		port: 11236,
	};
	var key = 'test' + token.create();
	server.start(options, function(error, nodecached)
	{
		testing.check(error, 'Could not start server', callback);
		var client = new exports.Client(options, function(error)
		{
			testing.check(error, 'Could not create client', callback);
			client.get(key, function(error, result)
			{
				testing.check(error, 'Could not get value', callback);
				testing.assertEquals(result, null, 'Invalid empty get result', callback);
				client.delete(key, function(error, result)
				{
					testing.check(error, 'Could not delete value', callback);
					testing.assertEquals(result, false, 'Invalid empty delete result', callback);
					client.stop(function(error)
					{
						testing.check(error, 'Could not stop client', callback);
						server.stop(nodecached, callback);
					});
				});
			});
		});
	});
}

/**
 * Run all tests.
 */
exports.test = function(callback)
{
	log.debug('Running tests');
	testing.run({
		getSetDelete: testGetSetDelete,
		notFound: testNotFound,
	}, callback);
};

// run tests if invoked directly
if (__filename == process.argv[1])
{
	exports.test(testing.show);
}

<commit_msg>Allow empty callback for client.set().<commit_after>'use strict';

/**
 * nodecached client.
 * (C) 2013 Alex Fernández.
 */

// requires
require('prototypes');
var token = require('./token.js');
var server = require('./server.js');
var Log = require('log');
var net = require('net');
var testing = require('testing');

// constants
var DEFAULT_PORT = 11211;
var TIMEOUT = 5000;

// globals
var log = new Log('info');

/**
 * A client object.
 */
exports.Client = function(options, callback)
{
	// self-reference
	var self = this;

	// attributes
	var connection;
	var pending = callback;

	// init
	init();

	/**
	 * Init the connection.
	 */
	function init()
	{
		options.port = options.port || DEFAULT_PORT;
		connection = net.connect(options);
		connection.setTimeout(TIMEOUT);
		connection.on('connect', function()
		{
			log.debug('Client connected to server');
			if (pending)
			{
				pending(null);
			}
		});
		connection.on('end', function()
		{
			log.debug('Client disconnected from server');
			if (pending)
			{
				pending(null);
			}
		});
		connection.on('error', function(error)
		{
			log.error('Connection error: %s', error);
			if (pending)
			{
				pending(error);
			}
			connection.destroy();
		});
		connection.on('data', function(data)
		{
			if (!pending)
			{
				log.error('Unexpected data %s', data);
				return;
			}
			pending(null, data);
		});
		connection.on('timeout', function()
		{
			if (pending)
			{
				pending('timeout');
			}
		});
	}

	/**
	 * Get a value.
	 */
	self.get = function(key, callback)
	{
		pending = getGetter(callback);
		connection.write('get ' + key + '\r\n');
	};

	/**
	 * Get a function to receive the output of a get.
	 */
	function getGetter(callback)
	{
		return getPending(callback, function(data)
		{
			var parsed = parseGet(data);
			if (!parsed)
			{
				return callback(null, parsed);
			}
			if (parsed.startsWith('{') && parsed.endsWith('}'))
			{
				try
				{
					return callback(null, JSON.parse(parsed));
				}
				catch(exception)
				{
					log.error('Fake json in %s: %s', parsed, exception);
				}
			}
			callback(null, parsed);
		});
	}

	/**
	 * Parse the result of a get.
	 */
	function parseGet(data)
	{
		var lines = String(data).split('\r\n');
		var line = lines.shift();
		if (line == 'END')
		{
			return null;
		}
		var words = line.split(' ');
		var word = words.shift();
		if (word != 'VALUE')
		{
			log.error('Unknown token %s', word);
			return null;
		}
		word = words.shift();
		word = words.shift();
		word = words.shift();
		if (!word)
		{
			log.error('Invalid length %s', word);
			return null;
		}
		var length = parseInt(word, 10);
		line = lines.shift();
		if (line.length != length)
		{
			log.error('Unexpected line length not %s in %s', length, line);
			return null;
		}
		return line;
	}

	/**
	 * Set a value.
	 */
	self.set = function(key, exptime, value, callback)
	{
		pending = getSetter(callback);
		var message = value;
		if (typeof value != 'string')
		{
			message = JSON.stringify(value);
		}
		connection.write('set ' + key + ' 0 ' + exptime + ' ' + message.length + '\r\n');
		connection.write(message + '\r\n');
	};

	/**
	 * Get a function to receive the output of a set.
	 */
	function getSetter(callback)
	{
		callback = callback || function () {};
		return getPending(callback, function(data)
		{
			var result = String(data).trim();
			if (result == 'STORED')
			{
				return callback(null, true);
			}
			log.error('Set result: %s', result);
			callback(null, false);
		});
	}

	/**
	 * Delete a value.
	 */
	self.delete = function(key, callback)
	{
		pending = getDeleter(callback);
		connection.write('delete ' + key + '\r\n');
	};

	/**
	 * Get a function to receive the output of a delete.
	 */
	function getDeleter(callback)
	{
		return getPending(callback, function(data)
		{
			var result = String(data).trim();
			if (result == 'DELETED')
			{
				return callback(null, true);
			}
			if (result == 'NOT_FOUND')
			{
				return callback(null, false);
			}
			log.error('Delete result: %s', result);
			callback(null, false);
		});
	}

	/**
	 * Get a pending function with a callback and a handler for data.
	 */
	function getPending(callback, handler)
	{
		return function(error, result)
		{
			if (error)
			{
				return callback(error);
			}
			return handler(result);
		};
	}

	/**
	 * Stop the client.
	 */
	self.stop = function(callback)
	{
		log.debug('Stopping the client');
		pending = callback;
		connection.end();
	};
};

/**
 * Test get, set and delete.
 */
function testGetSetDelete(callback)
{
	var options = {
		port: 11235,
	};
	var key = 'test' + token.create();
	var value = {
		a: 'b',
	};
	server.start(options, function(error, nodecached)
	{
		testing.check(error, 'Could not start server', callback);
		var client = new exports.Client(options, function(error)
		{
			testing.check(error, 'Could not create client', callback);
			client.set(key, 10, value, function(error, result)
			{
				testing.check(error, 'Could not set value', callback);
				testing.assertEquals(result, true, 'Invalid set result', callback);
				client.get(key, function(error, result)
				{
					testing.check(error, 'Could not get value', callback);
					testing.assertEquals(result, value, 'Invalid get result', callback);
					client.delete(key, function(error, result)
					{
						testing.check(error, 'Could not delete value', callback);
						testing.assertEquals(result, true, 'Invalid delete result', callback);
						client.get(key, function(error, result)
						{
							testing.check(error, 'Could not get after delete', callback);
							testing.assertEquals(result, null, 'Invalid get deleted result', callback);
							client.stop(function(error)
							{
								testing.check(error, 'Could not stop client', callback);
								server.stop(nodecached, callback);
							});
						});
					});
				});
			});
		});
	});
}

/**
 * Test what happens with values not found.
 */
function testNotFound(callback)
{
	var options = {
		port: 11236,
	};
	var key = 'test' + token.create();
	server.start(options, function(error, nodecached)
	{
		testing.check(error, 'Could not start server', callback);
		var client = new exports.Client(options, function(error)
		{
			testing.check(error, 'Could not create client', callback);
			client.get(key, function(error, result)
			{
				testing.check(error, 'Could not get value', callback);
				testing.assertEquals(result, null, 'Invalid empty get result', callback);
				client.delete(key, function(error, result)
				{
					testing.check(error, 'Could not delete value', callback);
					testing.assertEquals(result, false, 'Invalid empty delete result', callback);
					client.stop(function(error)
					{
						testing.check(error, 'Could not stop client', callback);
						server.stop(nodecached, callback);
					});
				});
			});
		});
	});
}

/**
 * Run all tests.
 */
exports.test = function(callback)
{
	log.debug('Running tests');
	testing.run({
		getSetDelete: testGetSetDelete,
		notFound: testNotFound,
	}, callback);
};

// run tests if invoked directly
if (__filename == process.argv[1])
{
	exports.test(testing.show);
}

<|endoftext|>


<commit_before>/* Copyright 2015 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

'use strict';

const EventEmitter = require('events');
const fs = require('fs');

const debugFactory = require('debug');
const random = require('random-js')();
const _ = require('underscore');

const debug = require('debug')('wall:library');
const fakeRequire = require('lib/fake_require');
const googleapis = require('server/util/googleapis');
const module_interface = require('lib/module_interface');
const network = require('server/network/network');
const safeEval = require('lib/eval');
const util = require('util');
const wallGeometry = require('server/util/wall_geometry');

// Node modules made available to server-side modules.
// Entries with "undefined" are only available on the client;
// we mention them here so that the server module can call require()
// without throwing.
var exposedNodeModules = {
  leaflet: undefined,
};

// Creates an execution context for server-side modules.
// Cf. the client-side version in client/modules/module_manager.js.
function serverSandbox(name, opt_dependencies) {
  return _.extend({
    debug : debugFactory('wall:module:' + name),
    globalWallGeometry: wallGeometry.getGeo(),
    require: fakeRequire.createEnvironment(exposedNodeModules),
  }, opt_dependencies || {});
}

// Verifies that the script (as a string) is valid, according to our spec.
// Returns a ModuleDefinition or null, in the case of an error.
let loadAndVerifyScript = function(name, script) {
  try {
    var serverSideModuleDef, clientSideModuleDef;
    var sandbox = _.extend({
      register: function(serverSide, clientSide) {
        serverSideModuleDef = serverSide;
        clientSideModuleDef = clientSide;
      },
      network: network,
      // In verify mode, the local wall geometry is the same as the global.
      wallGeometry: wallGeometry.getGeo(),
    }, serverSandbox(name));
    safeEval(script, sandbox);
    debug('Parsed correctly');
    if (!serverSideModuleDef) {
      debug('Module did not register a server-side module!');
      return null;
    }
    if (!(serverSideModuleDef.prototype instanceof module_interface.Server)) {
      debug(
          'Module\'s server-side module did not implement module_interface.Server!');
      return null;
    }
    if (clientSideModuleDef &&
        !(clientSideModuleDef.prototype instanceof module_interface.Client)) {
      debug(
          'Module\'s client-side module did not implement module_interface.Client!');
      return null;
    }
    // Send the WHOLE script to the client, or it will only see the constructor!
    return script;
  } catch (e) {
    debug('Failed to load script!', e);
    debug(e.stack);
    return null;
  }
};

// Schedules a module to be loaded at 'path', verifies that it's valid, and
// returns promise that will be resolved if valid or rejected if not.
let loadModuleAtPath = function(path) {
  return new Promise(function(resolve, reject) {
    fs.readFile(path, 'utf-8', function(err, content) {
      if (err) {
        reject(err);
        return;
      }
      // Prepend a directive to make sure the module runs in strict mode.
      // Append a directive that tells Chrome and Node that the client script
      // is, in fact, a file. This makes debugging these far simpler.
      content = `"use strict";${content}\n//# sourceURL=${path}\n`;
      try {
        var moduleDef = loadAndVerifyScript(path, content);
        if (!moduleDef) {
          // Not verifiable! Abort!
          throw new Error('Script at "' + path + '" is not verifiable!');
        }
        resolve(moduleDef);
      } catch (e) {
        reject(e);
      }
    });
  });
};

/**
 * The ModuleDef class contains all the information necessary to load &
 * instantiate a module, including code location and config parameters.
 */
class ModuleDef extends EventEmitter {
  constructor(name, pathOrBaseModule, title, author, config) {
    super();
    this.name = name;
    this.config = config || {};
    this.title = title;
    this.author = author;

    // The string source of the module.
    this.def_ = '';
    if (pathOrBaseModule instanceof ModuleDef) {
      // The promise that when set, indicates the module is loaded.
      this.loadPromise = pathOrBaseModule.loadPromise.then(() => {
        this.def_ = pathOrBaseModule.def_;
      });
    } else {
      this.load_(pathOrBaseModule);
    }
  }

  // Returns a custom object for serializing in debug logs.
  inspect(depth, opts) {
    return {
      name: this.name,
      config: util.inspect(this.config),
      title: this.title,
      author: this.author
    };
  }
  // Returns a new module def that extends this def with new configuration.
  extend(name, title, author, config) {
    return new ModuleDef(name, this,
      title || this.title, author || this.author, config);
  }
  // Loads a module from disk asynchronously, assigning def when complete.
  load_(path) {
    let loadModule = () => {
      let rewatch = () => {
        // Watch for future changes.
        debug('Watching', path);
        let watch = fs.watch(path, {persistent: true}, (event) => {
          debug('Module changed! Reloading', path);
          watch.close();
          loadModule();
          // When the load is finished, tell listeners that we reloaded.
          this.loadPromise.then(() => this.emit('reloaded'));
        });
      };

      this.loadPromise = loadModuleAtPath(path).then((def) => {
        debug('Loaded', path);
        this.def_ = def;

        // Start rewatcher.
        rewatch();
      }, (e) => {
        debug('Error loading ' + path);
        debug(e);

        // Start rewatcher, despite error.
        rewatch();

        // Allow users to note that this module failed to load correctly.
        return Promise.reject(e);
      });
    };

    loadModule();
  }

  // Instantiates this server-side version of this module, with any additional
  // globals being passed along.
  // TODO(applmak): Once automatic globals are removed, cache the constructor
  // after the eval (do it on load), then change the require to construct the
  // per-module globals (like network, which required 'deadline') to occur
  // dynamically. Basically, make this module's 'require' somehow delegate to
  // this particular instantiation.
  instantiate(additionalGlobals, deadline) {

    var serverSideModuleDef;
    var sandbox = _.extend({
      register: function(serverSide, unused) {
        serverSideModuleDef = serverSide;
      },
    }, serverSandbox(this.name, additionalGlobals));
    // Use safeEval to actually run the script so that Node doesn't leak
    // anything: https://github.com/nodejs/node/issues/3113
    safeEval(this.def_, sandbox);

    return new serverSideModuleDef(this.config, deadline);
  }

  // Returns a JSON-serializable form of this for transmission to the client.
  serializeForClient() {
    return {
      name: this.name,
      config: this.config,
      title: this.title,
      author: this.author,
      def: this.def_
    };
  }
}

// Export the module def class.
module.exports = ModuleDef;

<commit_msg>Remove server-side use of fake require.<commit_after>/* Copyright 2015 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

'use strict';

const EventEmitter = require('events');
const fs = require('fs');

const debugFactory = require('debug');
const random = require('random-js')();
const _ = require('underscore');

const debug = require('debug')('wall:library');
const fakeRequire = require('lib/fake_require');
const googleapis = require('server/util/googleapis');
const module_interface = require('lib/module_interface');
const network = require('server/network/network');
const safeEval = require('lib/eval');
const util = require('util');
const wallGeometry = require('server/util/wall_geometry');

// Creates an execution context for server-side modules.
// Cf. the client-side version in client/modules/module_manager.js.
function serverSandbox(name, opt_dependencies) {
  return _.extend({
    debug : debugFactory('wall:module:' + name),
    globalWallGeometry: wallGeometry.getGeo(),
    require: require,
  }, opt_dependencies || {});
}

// Verifies that the script (as a string) is valid, according to our spec.
// Returns a ModuleDefinition or null, in the case of an error.
let loadAndVerifyScript = function(name, script) {
  try {
    var serverSideModuleDef, clientSideModuleDef;
    var sandbox = _.extend({
      register: function(serverSide, clientSide) {
        serverSideModuleDef = serverSide;
        clientSideModuleDef = clientSide;
      },
      network: network,
      // In verify mode, the local wall geometry is the same as the global.
      wallGeometry: wallGeometry.getGeo(),
    }, serverSandbox(name));
    safeEval(script, sandbox);
    debug('Parsed correctly');
    if (!serverSideModuleDef) {
      debug('Module did not register a server-side module!');
      return null;
    }
    if (!(serverSideModuleDef.prototype instanceof module_interface.Server)) {
      debug(
          'Module\'s server-side module did not implement module_interface.Server!');
      return null;
    }
    if (clientSideModuleDef &&
        !(clientSideModuleDef.prototype instanceof module_interface.Client)) {
      debug(
          'Module\'s client-side module did not implement module_interface.Client!');
      return null;
    }
    // Send the WHOLE script to the client, or it will only see the constructor!
    return script;
  } catch (e) {
    debug('Failed to load script!', e);
    debug(e.stack);
    return null;
  }
};

// Schedules a module to be loaded at 'path', verifies that it's valid, and
// returns promise that will be resolved if valid or rejected if not.
let loadModuleAtPath = function(path) {
  return new Promise(function(resolve, reject) {
    fs.readFile(path, 'utf-8', function(err, content) {
      if (err) {
        reject(err);
        return;
      }
      // Prepend a directive to make sure the module runs in strict mode.
      // Append a directive that tells Chrome and Node that the client script
      // is, in fact, a file. This makes debugging these far simpler.
      content = `"use strict";${content}\n//# sourceURL=${path}\n`;
      try {
        var moduleDef = loadAndVerifyScript(path, content);
        if (!moduleDef) {
          // Not verifiable! Abort!
          throw new Error('Script at "' + path + '" is not verifiable!');
        }
        resolve(moduleDef);
      } catch (e) {
        reject(e);
      }
    });
  });
};

/**
 * The ModuleDef class contains all the information necessary to load &
 * instantiate a module, including code location and config parameters.
 */
class ModuleDef extends EventEmitter {
  constructor(name, pathOrBaseModule, title, author, config) {
    super();
    this.name = name;
    this.config = config || {};
    this.title = title;
    this.author = author;

    // The string source of the module.
    this.def_ = '';
    if (pathOrBaseModule instanceof ModuleDef) {
      // The promise that when set, indicates the module is loaded.
      this.loadPromise = pathOrBaseModule.loadPromise.then(() => {
        this.def_ = pathOrBaseModule.def_;
      });
    } else {
      this.load_(pathOrBaseModule);
    }
  }

  // Returns a custom object for serializing in debug logs.
  inspect(depth, opts) {
    return {
      name: this.name,
      config: util.inspect(this.config),
      title: this.title,
      author: this.author
    };
  }
  // Returns a new module def that extends this def with new configuration.
  extend(name, title, author, config) {
    return new ModuleDef(name, this,
      title || this.title, author || this.author, config);
  }
  // Loads a module from disk asynchronously, assigning def when complete.
  load_(path) {
    let loadModule = () => {
      let rewatch = () => {
        // Watch for future changes.
        debug('Watching', path);
        let watch = fs.watch(path, {persistent: true}, (event) => {
          debug('Module changed! Reloading', path);
          watch.close();
          loadModule();
          // When the load is finished, tell listeners that we reloaded.
          this.loadPromise.then(() => this.emit('reloaded'));
        });
      };

      this.loadPromise = loadModuleAtPath(path).then((def) => {
        debug('Loaded', path);
        this.def_ = def;

        // Start rewatcher.
        rewatch();
      }, (e) => {
        debug('Error loading ' + path);
        debug(e);

        // Start rewatcher, despite error.
        rewatch();

        // Allow users to note that this module failed to load correctly.
        return Promise.reject(e);
      });
    };

    loadModule();
  }

  // Instantiates this server-side version of this module, with any additional
  // globals being passed along.
  // TODO(applmak): Once automatic globals are removed, cache the constructor
  // after the eval (do it on load), then change the require to construct the
  // per-module globals (like network, which required 'deadline') to occur
  // dynamically. Basically, make this module's 'require' somehow delegate to
  // this particular instantiation.
  instantiate(additionalGlobals, deadline) {

    var serverSideModuleDef;
    var sandbox = _.extend({
      register: function(serverSide, unused) {
        serverSideModuleDef = serverSide;
      },
    }, serverSandbox(this.name, additionalGlobals));
    // Use safeEval to actually run the script so that Node doesn't leak
    // anything: https://github.com/nodejs/node/issues/3113
    safeEval(this.def_, sandbox);

    return new serverSideModuleDef(this.config, deadline);
  }

  // Returns a JSON-serializable form of this for transmission to the client.
  serializeForClient() {
    return {
      name: this.name,
      config: this.config,
      title: this.title,
      author: this.author,
      def: this.def_
    };
  }
}

// Export the module def class.
module.exports = ModuleDef;

<|endoftext|>


<commit_before>(function(){var e={json:null,show_group_label:false,show_placeholder:false,show_input_label:false};this.Leafbird=function(e){if(!(this instanceof Leafbird)){return new Leafbird(e)}this.configure(e)};Leafbird.prototype.configure=function(t){for(var n in t){if(e.hasOwnProperty(n)&&t[n]!=undefined)e[n]=t[n]}};Leafbird.prototype.find=function(t,n,r,i){var s=[];var o=i==undefined?e.json:i;for(var u in o){if(u==t&&(n==undefined||r&&o[t].indexOf(n)>-1||!r&&o[t]==n)){s.push(o)}if(o[u]instanceof Object){var a=this.find(t,n,r,o[u]);if(a.length>0)s=s.concat(a)}}return s};Leafbird.prototype.print=function(n,r,i){var s={};for(var o in e)s[o]=e[o];if(!(n instanceof HTMLElement)){throw new SyntaxError("Invalid HTMLElement.",n)}this.configure(i);var u=this.getElements(r);for(var a in u){t(u[a],n)}this.configure(s)};Leafbird.prototype.getElements=function(t){if(!e.json)throw new Error("JSON is not valid.",e.json);var n=[];var r=t&&t.indexOf("*")==0?1:0;if(t==undefined){n.push(e.json)}else if(t.indexOf("#")==r){n=this.find("id",t.substring(r+1),r)}else if(t.indexOf(".")==r){n=this.find("class",t.substring(r+1),r)}else if(t.indexOf(":")==r){n=this.find("name",t.substring(r+1),r)}else{throw new SyntaxError("JSONAttribute '"+t+"' is not valid.",t)}return n};var t=function(e,i){if(e.hasOwnProperty("type")){r(e,i)}else{var s=n(e);for(var o in e){if(e[o]instanceof Array){for(var u in e[o]){t(e[o][u],s)}}}i.appendChild(s)}};var n=function(t){var n=document.createElement("div");if(t.id!=undefined)n.setAttribute("id",t.id);if(t.class!=undefined)n.setAttribute("class",t.class);if(e.show_group_label&&t.label!=undefined){var r=document.createElement("span");r.appendChild(document.createTextNode(t.label.value));n.appendChild(r)}return n};var r=function(t,n){if(e.show_input_label&&t.label!=undefined){var r=document.createElement("label");if(t.id!=undefined)r.setAttribute("for",t.id);if(t.label.class!=undefined)r.setAttribute("class",t.label.class);r.appendChild(document.createTextNode(t.label.value));n.appendChild(r)}if(t.name==undefined)throw new SyntaxError("InputName is required.",t.name);switch(t.type){case"text":case"number":case"date":case"currency":i(t,n);break;case"radio":case"checkbox":o(t,n);break;case"textarea":s(t,n);break;case"select":u(t,n);break;case"file":a(t,n);break;default:throw new SyntaxError("Invalid InputType.",t.type)}};var i=function(t,n){var r=document.createElement("input");r.setAttribute("type","text");r.setAttribute("name",t.name);if(t.id!=undefined)r.setAttribute("id",t.id);if(t.class!=undefined)r.setAttribute("class",t.class);if(t.default!=undefined)r.setAttribute("value",t.default);if(e.show_placeholder&&(t.placeholder!=undefined||t.label!=undefined)){r.setAttribute("placeholder",t.placeholder==undefined?t.label.value:t.placeholder)}n.appendChild(r)};var s=function(t,n){var r=document.createElement("textarea");r.setAttribute("name",t.name);if(t.id!=undefined)r.setAttribute("id",t.id);if(t.class!=undefined)r.setAttribute("class",t.class);if(t.default!=undefined)r.appendChild(document.createTextNode(t.default));if(e.show_placeholder&&(t.placeholder!=undefined||t.label!=undefined)){input.setAttribute("placeholder",t.placeholder==undefined?t.label.value:t.placeholder)}n.appendChild(r)};var o=function(e,t){for(var n in e.values){var r=document.createElement("input");r.setAttribute("type",e.type);r.setAttribute("name",e.name);r.setAttribute("value",e.values[n].value);if(e.id!=undefined)r.setAttribute("id",e.id+"_"+n);if(e.class!=undefined)r.setAttribute("class",e.class);if(e.default==e.values[n].value)r.setAttribute("checked","checked");if(e.values[n].label!=undefined){var i=document.createElement("label");if(e.id!=undefined)i.setAttribute("for",e.id+"_"+n);if(e.values[n].label.class!=undefined)i.setAttribute("class",e.values[n].label.class);i.appendChild(r);i.appendChild(document.createTextNode(e.values[n].label.value));t.appendChild(i)}else t.appendChild(r)}};var u=function(e,t){var n=document.createElement("select");n.setAttribute("name",e.name);if(e.id!=undefined)n.setAttribute("id",e.id);if(e.class!=undefined)n.setAttribute("class",e.class);for(var r in e.values){var i=document.createElement("option");i.appendChild(document.createTextNode(e.values[r].label.value));i.setAttribute("value",e.values[r].value);if(e.values[r].label.class!=undefined)i.setAttribute("class",e.values[r].label.class);if(e.default==e.values[r].value)i.setAttribute("selected","selected");n.appendChild(i)}t.appendChild(n)};var a=function(e,t){var n=document.createElement("input");n.setAttribute("type","file");n.setAttribute("name",e.name);if(e.id!=undefined)n.setAttribute("id",e.id);if(e.class!=undefined)n.setAttribute("class",e.class);if(e.acept!=undefined)n.setAttribute("acept",e.acept);t.appendChild(n)};window.Leafbird=Leafbird,window.lb=Leafbird})()
<commit_msg>Add suppot to title for label and inputs<commit_after>(function(){var e={json:null,show_group_label:false,show_placeholder:false,show_input_label:false,multiselect_input:false,multifile_input:false};this.Leafbird=function(e){if(!(this instanceof Leafbird)){return new Leafbird(e)}this.configure(e)};Leafbird.prototype.configure=function(t){for(var n in t){if(e.hasOwnProperty(n)&&t[n]!=undefined)e[n]=t[n]}};Leafbird.prototype.find=function(t,n,r,i){var s=[];var o=i==undefined?e.json:i;for(var u in o){if(u==t&&(n==undefined||r&&o[t].indexOf(n)>-1||!r&&o[t]==n)){s.push(o)}if(o[u]instanceof Object){var a=this.find(t,n,r,o[u]);if(a.length>0)s=s.concat(a)}}return s};Leafbird.prototype.print=function(n,r,i){var s={};for(var o in e)s[o]=e[o];if(!(n instanceof HTMLElement)){throw new SyntaxError("Invalid HTMLElement.",n)}this.configure(i);var u=this.getElements(r);for(var a in u){t(u[a],n)}this.configure(s)};Leafbird.prototype.getElements=function(t){if(!e.json)throw new Error("JSON is not valid.",e.json);var n=[];var r=t&&t.indexOf("*")==0?1:0;if(t==undefined){n.push(e.json)}else if(t.indexOf("#")==r){n=this.find("id",t.substring(r+1),r)}else if(t.indexOf(".")==r){n=this.find("class",t.substring(r+1),r)}else if(t.indexOf(":")==r){n=this.find("name",t.substring(r+1),r)}else{throw new SyntaxError("JSONAttribute '"+t+"' is not valid.",t)}return n};var t=function(e,i){if(e.hasOwnProperty("type")){r(e,i)}else{var s=n(e);for(var o in e){if(e[o]instanceof Array){for(var u in e[o]){t(e[o][u],s)}}}i.appendChild(s)}};var n=function(t){var n=document.createElement("div");if(t.id!=undefined)n.setAttribute("id",t.id);if(t.class!=undefined)n.setAttribute("class",t.class);if(e.show_group_label&&t.label!=undefined){var r=document.createElement("span");if(t.label.title!=undefined)r.setAttribute("title",t.label.title);r.appendChild(document.createTextNode(t.label.value));n.appendChild(r)}return n};var r=function(t,n){if(e.show_input_label&&t.label!=undefined){var r=document.createElement("label");if(t.id!=undefined)r.setAttribute("for",t.id);if(t.label.class!=undefined)r.setAttribute("class",t.label.class);if(t.label.title!=undefined)r.setAttribute("title",t.label.title);r.appendChild(document.createTextNode(t.label.value));n.appendChild(r)}if(t.name==undefined)throw new SyntaxError("InputName is required.",t.name);switch(t.type){case"text":case"number":case"date":case"currency":i(t,n);break;case"radio":case"checkbox":o(t,n);break;case"textarea":s(t,n);break;case"select":u(t,n);break;case"file":a(t,n);break;default:throw new SyntaxError("Invalid InputType.",t.type)}};var i=function(t,n){var r=document.createElement("input");r.setAttribute("type","text");r.setAttribute("name",t.name);if(t.id!=undefined)r.setAttribute("id",t.id);if(t.class!=undefined)r.setAttribute("class",t.class);if(t.default!=undefined)r.setAttribute("value",t.default);if(t.title!=undefined)r.setAttribute("title",t.title);if(e.show_placeholder&&(t.placeholder!=undefined||t.label!=undefined)){r.setAttribute("placeholder",t.placeholder==undefined?t.label.value:t.placeholder)}n.appendChild(r)};var s=function(t,n){var r=document.createElement("textarea");r.setAttribute("name",t.name);if(t.id!=undefined)r.setAttribute("id",t.id);if(t.class!=undefined)r.setAttribute("class",t.class);if(t.title!=undefined)r.setAttribute("title",t.title);if(t.default!=undefined)r.appendChild(document.createTextNode(t.default));if(e.show_placeholder&&(t.placeholder!=undefined||t.label!=undefined)){input.setAttribute("placeholder",t.placeholder==undefined?t.label.value:t.placeholder)}n.appendChild(r)};var o=function(e,t){for(var n in e.values){var r=document.createElement("input");r.setAttribute("type",e.type);r.setAttribute("name",e.name);r.setAttribute("value",e.values[n].value);if(e.id!=undefined)r.setAttribute("id",e.id+"_"+n);if(e.class!=undefined)r.setAttribute("class",e.class);if(e.default==e.values[n].value)r.setAttribute("checked","checked");if(e.values[n].label!=undefined){var i=document.createElement("label");if(e.id!=undefined)i.setAttribute("for",e.id+"_"+n);if(e.values[n].label.class!=undefined)i.setAttribute("class",e.values[n].label.class);if(e.values[n].label.title!=undefined)i.setAttribute("title",e.values[n].label.title);i.appendChild(r);i.appendChild(document.createTextNode(e.values[n].label.value));t.appendChild(i)}else t.appendChild(r)}};var u=function(t,n){var r=document.createElement("select");r.setAttribute("name",t.name);if(t.id!=undefined)r.setAttribute("id",t.id);if(t.class!=undefined)r.setAttribute("class",t.class);if(t.title!=undefined)r.setAttribute("title",t.title);if(e.multiselect_input)r.setAttribute("multiple","multiple");for(var i in t.values){var s=document.createElement("option");s.appendChild(document.createTextNode(t.values[i].label.value));s.setAttribute("value",t.values[i].value);if(t.values[i].label.class!=undefined)s.setAttribute("class",t.values[i].label.class);if(t.default==t.values[i].value)s.setAttribute("selected","selected");r.appendChild(s)}n.appendChild(r)};var a=function(t,n){var r=document.createElement("input");r.setAttribute("type","file");r.setAttribute("name",t.name);if(t.id!=undefined)r.setAttribute("id",t.id);if(t.class!=undefined)r.setAttribute("class",t.class);if(t.accept!=undefined)r.setAttribute("accept",t.accept);if(t.title!=undefined)r.setAttribute("title",t.title);if(e.multifile_input)r.setAttribute("multiple","multiple");n.appendChild(r)};window.Leafbird=Leafbird,window.lb=Leafbird})()
<|endoftext|>


<commit_before>//function canvas() {
//  var canvas    = document.getElementById('game');
//  var gameBoard = canvas.getContext("2d");
//  var width     = $(canvas).width();
//  var height    = $(canvas).height();
//
//  gameBoard.fillStyle = "black";
//  gameBoard.fillRect(0, 0, width, height);
//  return gameBoard;
//}

//Change 'trail' attribute to take in coordinate objects rather than an array

function Player(color, startingX, startingY, startingDirection) {
  this.color     = color;
  this.trail     = [[startingX, startingY]]; //Could change to {x: startingX, y: startingY}
  this.direction = startingDirection;
}

Player.prototype.colorize = function(gameBoard) {
  for(var i = 0; i < this.trail.length; i++) {
    var el = this.trail[i];

    gameBoard.fillStyle = this.color;
    gameBoard.fillRect(el[0]*10, el[1]*10, 10, 10);
  }
};

function Game() {
}

Game.prototype.createBoard = function() {
  var canvas    = document.getElementById('game');
  var gameBoard = canvas.getContext("2d");
  var width     = $(canvas).width();
  var height    = $(canvas).height();

  gameBoard.fillStyle = "black";
  gameBoard.fillRect(0, 0, width, height);

  this.board = gameBoard;
};

$(document).ready(function() {
  var game = new Game();
  game.createBoard();

  Player.prototype.move = function() {
    var xPosition = this.trail[this.trail.length - 1][0];
    var yPosition = this.trail[this.trail.length - 1][1];

    //Could probably break this out into its own prototype method

    switch(this.direction) {
      case "right":
        xPosition++;
        break;
      case "left":
        xPosition--;
        break;
      case "up":
        yPosition--;
        break;
      case "down":
        yPosition++;
        break;
    }

    this.trail.push([xPosition, yPosition]);
    this.colorize(game.board);
    detectCollision(xPosition, yPosition);
    window.playerTrails.push([xPosition, yPosition]);
  };

  function detectCollision(xPosition, yPosition) {

    //Detects border collisions

    if (xPosition == -1 || xPosition == 1200/10 || yPosition == -1 || yPosition == 600/10) {
      clearInterval(window.gameLoop);
      endGame();
    }

    //Detects collisions with player trails

    for (var i = 0; i < window.playerTrails.length; i++) {
      if (xPosition == window.playerTrails[i][0] && yPosition == window.playerTrails[i][1]) {
        clearInterval(window.gameLoop);
        endGame();
      }
    }
  }

  function endGame() {
    gameBoard.fillStyle = "green";
    gameBoard.fillRect(200, 200, 775, 175);
    gameBoard.font = "40px Georgia";
    gameBoard.fillStyle = "white";
    gameBoard.fillText("Game Over! Press 'enter' to play again", 250, 300);

    $(document).keydown(function(k){
      var key = k.which;
      if(key == "13") location.reload();
    });
  }

  function movePlayers() {
    playerOne.move();
    playerTwo.move();
  }

  function playerKeys(key, keyBindings, player) {
    if(key == keyBindings.left && player.direction != "right")
      player.direction = "left";
    else if(key == keyBindings.up && player.direction != "down")
      player.direction = "up";
    else if(key == keyBindings.right && player.direction != "left")
      player.direction = "right";
    else if(key == keyBindings.down && player.direction != "up")
      player.direction = "down";
  }

  function startGame()
  {
    window.playerOne = new Player("red", 10, 30, "right");
    window.playerTwo = new Player("blue", 110, 30, "left");
    window.playerTrails = [];

    movePlayers();
    window.gameLoop = setInterval(movePlayers, 30);

    $(document).keydown(function(k){
      var key = k.which;

      var oneKeys = {
        left: "65",
        up: "87",
        right: "68",
        down: "83"
      };

      var twoKeys = {
        left: "37",
        up: "38",
        right: "39",
        down: "40"
      };

      playerKeys(key, oneKeys, playerOne);
      playerKeys(key, twoKeys, playerTwo);
    });
  }

  startGame();
});
<commit_msg>Add end and start method to Game prototype<commit_after>//function canvas() {
//  var canvas    = document.getElementById('game');
//  var gameBoard = canvas.getContext("2d");
//  var width     = $(canvas).width();
//  var height    = $(canvas).height();
//
//  gameBoard.fillStyle = "black";
//  gameBoard.fillRect(0, 0, width, height);
//  return gameBoard;
//}

//Change 'trail' attribute to take in coordinate objects rather than an array

function Player(color, startingX, startingY, startingDirection) {
  this.color     = color;
  this.trail     = [[startingX, startingY]]; //Could change to {x: startingX, y: startingY}
  this.direction = startingDirection;
}

Player.prototype.colorize = function(gameBoard) {
  for(var i = 0; i < this.trail.length; i++) {
    var el = this.trail[i];

    gameBoard.fillStyle = this.color;
    gameBoard.fillRect(el[0]*10, el[1]*10, 10, 10);
  }
};

function Game() {
}

Game.prototype.createBoard = function() {
  var canvas    = document.getElementById('game');
  var gameBoard = canvas.getContext("2d");
  var width     = $(canvas).width();
  var height    = $(canvas).height();

  gameBoard.fillStyle = "black";
  gameBoard.fillRect(0, 0, width, height);

  this.board = gameBoard;
};

$(document).ready(function() {
  var game = new Game();
  game.createBoard();

  Player.prototype.move = function() {
    var xPosition = this.trail[this.trail.length - 1][0];
    var yPosition = this.trail[this.trail.length - 1][1];

    //Could probably break this out into its own prototype method

    switch(this.direction) {
      case "right":
        xPosition++;
        break;
      case "left":
        xPosition--;
        break;
      case "up":
        yPosition--;
        break;
      case "down":
        yPosition++;
        break;
    }

    this.trail.push([xPosition, yPosition]);
    this.colorize(game.board);
    detectCollision(xPosition, yPosition);
    window.playerTrails.push([xPosition, yPosition]);
  };

  function detectCollision(xPosition, yPosition) {

    //Detects border collisions

    if (xPosition == -1 || xPosition == 1200/10 || yPosition == -1 || yPosition == 600/10) {
      clearInterval(window.gameLoop);
      game.end();
    }

    //Detects collisions with player trails

    for (var i = 0; i < window.playerTrails.length; i++) {
      if (xPosition == window.playerTrails[i][0] && yPosition == window.playerTrails[i][1]) {
        clearInterval(window.gameLoop);
        game.end();
      }
    }
  }

  Game.prototype.end = function() {
    this.board.fillStyle = "green";
    this.board.fillRect(200, 200, 775, 175);
    this.board.font = "40px Georgia";
    this.board.fillStyle = "white";
    this.board.fillText("Game Over! Press 'enter' to play again", 250, 300);

    $(document).keydown(function(k){
      var key = k.which;
      if(key == "13") location.reload();
    });
  };

  function movePlayers() {
    playerOne.move();
    playerTwo.move();
  }

  function playerKeys(key, keyBindings, player) {
    if(key == keyBindings.left && player.direction != "right")
      player.direction = "left";
    else if(key == keyBindings.up && player.direction != "down")
      player.direction = "up";
    else if(key == keyBindings.right && player.direction != "left")
      player.direction = "right";
    else if(key == keyBindings.down && player.direction != "up")
      player.direction = "down";
  }

  Game.prototype.start = function () {

    window.playerOne = new Player("red", 10, 30, "right");
    window.playerTwo = new Player("blue", 110, 30, "left");
    window.playerTrails = [];

    movePlayers();
    window.gameLoop = setInterval(movePlayers, 30);

    $(document).keydown(function(k){
      var key = k.which;

      var oneKeys = {
        left: "65",
        up: "87",
        right: "68",
        down: "83"
      };

      var twoKeys = {
        left: "37",
        up: "38",
        right: "39",
        down: "40"
      };

      playerKeys(key, oneKeys, playerOne);
      playerKeys(key, twoKeys, playerTwo);
    });
  };

  game.start();
});
<|endoftext|>


<commit_before>(function(){

  // Set AudioContext to vendor version
  this.AudioContext = this.AudioContext || this.webkitAudioContext
                                        || this.mozAudioContext
                                        || this.oAudioContext
                                        || this.msAudioContext;

  if (!this.AudioContext) throw "Theremin Error: The Web Audio API is not available in this environment";

  // Create Theremin object and private variables
  this.Theremin = {};
  var context, version = "0.0.1";

  // Theremin object methods
  Theremin.getVersion = function() {
    return version;
  };

  Theremin.setContext = function(audio_context){
    return context = audio_context;
  };

  Theremin.getContext = function(){
    return context;
  };

  // Theremin Player Constructor
  Theremin.Player = (function() {
    var Player = function(loop){
      this.loop = loop;
    };

    var buffer, source, play_start, accumulated_duration = 0;

    var getAjaxBufferPromise = function(url) {

      return new Promise(function(resolve, reject) {

        var request = new XMLHttpRequest();

        request.open('GET', url, true);
        request.responseType = 'arraybuffer';

        request.onload = function() {
          request.status === 200 ? resolve(request.response) : reject(Error(request.statusText));
        };

        request.onerror = function(){
          reject(Error("Theremin Error: AJAX request Network Error "));
        };

        request.send();
      });
    };

    var createSourceAndPlay = function() {
      play_start = context.currentTime;
      source = context.createBufferSource();
      source.buffer = buffer;
      source.loop = this.loop;
      source.connect(context.destination);
      source.start(0, accumulated_duration);
    };

    var resetPlayer = function() {
      if (source) {
        source.stop();
        source = null;
      }
      accumulated_duration = 0;
    };

    Player.prototype.getBuffer = function(){
      return buffer;
    };

    Player.prototype.loadBuffer = function(url){

      if(typeof Promise === "undefined") throw "Theremin unable to load buffer because your environment does not support Promises";

      getAjaxBufferPromise(url).then(function(response) {
        context.decodeAudioData(response, function(loaded_buffer){
          buffer = loaded_buffer;
        });
      }, function(error) {
        console.error("Theremin Error: Error loading buffer, " + error);
      });
    };

    Player.prototype.play = function(){

      if (!buffer) throw "No buffer loaded for this player";

      if (this.loop) {
        accumulated_duration = accumulated_duration % buffer.duration;
      } else {
        var duration = source ? context.currentTime - play_start : 0;
        if (accumulated_duration + duration > buffer.duration) resetPlayer();
      }

      if (!source) createSourceAndPlay();
    };

    Player.prototype.pause = function(){
      if (source) {
        var duration = context.currentTime - play_start;
        accumulated_duration += duration;
        source.stop();
        source = null;
      }
    };

    Player.prototype.jumpTo = function(seconds, play) {
      if (source) {
        source.stop();
        source = null;
      }
      accumulated_duration = seconds;
      if (play) this.play();
    };

    return Player;
  })();
}());
<commit_msg>make state variables instance variables<commit_after>(function(){

  // Set AudioContext to vendor version
  this.AudioContext = this.AudioContext || this.webkitAudioContext
                                        || this.mozAudioContext
                                        || this.oAudioContext
                                        || this.msAudioContext;

  if (!this.AudioContext) throw "Theremin Error: The Web Audio API is not available in this environment";

  // Create Theremin object and private variables
  this.Theremin = {};
  var context, version = "0.0.1";

  // Theremin object methods
  Theremin.getVersion = function() {
    return version;
  };

  Theremin.setContext = function(audio_context){
    return context = audio_context;
  };

  Theremin.getContext = function(){
    return context;
  };

  // Theremin Player Constructor
  Theremin.Player = (function() {

    var Player = function(loop){
      this.loop = loop;
      this.buffer = null;
      this.source = null;
      this.play_start = null;
      this.accumulated_duration = 0;
    };

    var getAjaxBufferPromise = function(url) {

      return new Promise(function(resolve, reject) {

        var request = new XMLHttpRequest();

        request.open('GET', url, true);
        request.responseType = 'arraybuffer';

        request.onload = function() {
          request.status === 200 ? resolve(request.response) : reject(Error(request.statusText));
        };

        request.onerror = function(){
          reject(Error("Theremin Error: AJAX request Network Error "));
        };

        request.send();
      });
    };

    Player.prototype.createSourceAndPlay = function() {
      this.play_start = context.currentTime;
      this.source = context.createBufferSource();
      this.source.buffer = this.buffer;
      this.source.loop = this.loop;
      this.source.connect(context.destination);
      this.source.start(0, this.accumulated_duration);
    };

    Player.prototype.resetPlayer = function() {
      if (this.source) {
        this.source.stop();
        this.source = null;
      }
      this.accumulated_duration = 0;
    };

    Player.prototype.loadBuffer = function(url){

      if(typeof Promise === "undefined") throw "Theremin unable to load buffer because your environment does not support Promises";
      var that = this;
      getAjaxBufferPromise(url).then(function(response) {
        context.decodeAudioData(response, function(loaded_buffer){
          that.buffer = loaded_buffer;
        });
      }, function(error) {
        console.error("Theremin Error: Error loading buffer, " + error);
      });
    };

    Player.prototype.play = function(){

      if (!this.buffer) throw "No buffer loaded for this player";

      if (this.loop) {
        this.accumulated_duration = this.accumulated_duration % this.buffer.duration;
      } else {
        var duration = this.source ? context.currentTime - this.play_start : 0;
        if (this.accumulated_duration + duration > this.buffer.duration) resetPlayer();
      }

      if (!this.source) this.createSourceAndPlay();
    };

    Player.prototype.pause = function(){
      if (this.source) {
        var duration = context.currentTime - this.play_start;
        this.accumulated_duration += duration;
        this.source.stop();
        this.source = null;
      }
    };

    Player.prototype.jumpTo = function(seconds, play) {
      if (this.source) {
        this.source.stop();
        this.source = null;
      }
      this.accumulated_duration = seconds;
      if (play) this.play();
    };

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


<commit_before>;(function() {

	var url = location.protocol+'\/\/'+location.hostname+":{$port}/rstrt";

	// clone link tag, and destroys origin when clone is loaded.
	var simple_swap_links = function(link, first_time) {
		var char = (link.href.indexOf('?')>-1) ? '&' : '?';
		link.href += (first_time === true) ? (char+(new Date()).getTime()) : char;
	};

	var swap_links = function(link, first_time) {
		var char = (link.href.indexOf('?')>-1) ? '&' : '?';
		var new_link = link.cloneNode();
		new_link.href += (first_time === true) ? (char+(new Date()).getTime()) : char;
		var parent = link.parentNode;
		new_link.onload = function(){
			parent.removeChild(link);
		};
		parent.appendChild(new_link);
	};

	var is_touch_device = function() {
		return 'ontouchstart' in window || 'onmsgesturechange' in window;
	};

	// finds all link elements, and reloads them.
	var reload_stylesheets = function(first_time) {
		var links = document.getElementsByTagName("link");
		var link;
		var replacing = [];
		for(var i = 0; i < links.length; i++) {
			link = links[i];
			char = '?';
			if(link.rel === "stylesheet") {
				replacing.push(link);
			}
		}
		var fn = is_touch_device() ? simple_swap_links : swap_links;
		for(i=0; i < replacing.length; i++) {
			fn(replacing[i], first_time);
		}
	};

	var tryout_delay = function(tryouts, fn) {
		var to = setTimeout(function() {
			clearTimeout(to);
			fn();
		}, 20 + tryouts*5);
		return to;
	};

	var tryouts = 0;
	var startup = function(){
		tryouts++;
		if(!SockJS) {
			if(typeof console !== 'undefined') {
				console.warn('You shall turn Ristretto on.');
				tryout_delay(tryouts, startup);
			}
		} else {
			var sockjs = rstrt_sockjs = new SockJS(url, { debug: true });
			sockjs.onclose = function() {
				tryout_delay(tryouts, startup);
			};
			sockjs.onmessage = function(e) {
				switch(e.data) {
					case 'reload-stylesheets':
						reload_stylesheets();
						break;
					case 'reload-page':
						window.location.reload();
						break;
				}
			};
		}
	};

	// Run, Ristretto, run!
	startup();
})();
<commit_msg>Add caching workaround<commit_after>;(function() {

	var url = location.protocol+'\/\/'+location.hostname+":{$port}/rstrt";

	// clone link tag, and destroys origin when clone is loaded.
	var simple_swap_links = function(link, first_time) {
		var char = (link.href.indexOf('?')>-1) ? '&' : '?';
		link.href += (first_time === true) ? (char+(new Date()).getTime()) : char;
	};

	var swap_links = function(link, first_time) {
		var char = (link.href.indexOf('?')>-1) ? ('&' + Math.random().toString(36).substring(0,2)) : '?';
		var new_link = link.cloneNode();
		new_link.href += (first_time === true) ? (char+(new Date()).getTime()) : char;
		var parent = link.parentNode;
		new_link.onload = function(){
			parent.removeChild(link);
		};
		parent.appendChild(new_link);
	};

	var is_touch_device = function() {
		return 'ontouchstart' in window || 'onmsgesturechange' in window;
	};

	// finds all link elements, and reloads them.
	var reload_stylesheets = function(first_time) {
		var links = document.getElementsByTagName("link");
		var link;
		var replacing = [];
		for(var i = 0; i < links.length; i++) {
			link = links[i];
			char = '?';
			if(link.rel === "stylesheet") {
				replacing.push(link);
			}
		}
		var fn = is_touch_device() ? simple_swap_links : swap_links;
		for(i=0; i < replacing.length; i++) {
			fn(replacing[i], first_time);
		}
	};

	var tryout_delay = function(tryouts, fn) {
		var to = setTimeout(function() {
			clearTimeout(to);
			fn();
		}, 20 + tryouts*5);
		return to;
	};

	var tryouts = 0;
	var startup = function(){
		tryouts++;
		if(!SockJS) {
			if(typeof console !== 'undefined') {
				console.warn('You shall turn Ristretto on.');
				tryout_delay(tryouts, startup);
			}
		} else {
			var sockjs = rstrt_sockjs = new SockJS(url, { debug: true });
			sockjs.onclose = function() {
				tryout_delay(tryouts, startup);
			};
			sockjs.onmessage = function(e) {
				switch(e.data) {
					case 'reload-stylesheets':
						reload_stylesheets();
						break;
					case 'reload-page':
						window.location.reload();
						break;
				}
			};
		}
	};

	// Run, Ristretto, run!
	startup();
})();
<|endoftext|>


<commit_before>/**
 * @author zz85 https://github.com/zz85
 *
 * Centripetal CatmullRom Curve - which is useful for avoiding
 * cusps and self-intersections in non-uniform catmull rom curves.
 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
 *
 * curve.type accepts centripetal(default), chordal and catmullrom
 * curve.tension is used for catmullrom which defaults to 0.5
 */

THREE.CatmullRomCurve3 = ( function() {

	var
		tmp = new THREE.Vector3(),
		px = new CubicPoly(),
		py = new CubicPoly(),
		pz = new CubicPoly();

	/*
	Based on an optimized c++ solution in
	 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
	 - http://ideone.com/NoEbVM

	This CubicPoly class could be used for reusing some variables and calculations,
	but for three.js curve use, it could be possible inlined and flatten into a single function call
	which can be placed in CurveUtils.
	*/

	function CubicPoly() {

	}

	/*
	 * Compute coefficients for a cubic polynomial
	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
	 * such that
	 *   p(0) = x0, p(1) = x1
	 *  and
	 *   p'(0) = t0, p'(1) = t1.
	 */
	CubicPoly.prototype.init = function( x0, x1, t0, t1 ) {

		this.c0 = x0;
		this.c1 = t0;
		this.c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
		this.c3 = 2 * x0 - 2 * x1 + t0 + t1;

	};

	CubicPoly.prototype.initNonuniformCatmullRom = function( x0, x1, x2, x3, dt0, dt1, dt2 ) {

		// compute tangents when parameterized in [t1,t2]
		var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
		var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;

		// rescale tangents for parametrization in [0,1]
		t1 *= dt1;
		t2 *= dt1;

		// initCubicPoly
		this.init( x1, x2, t1, t2 );

	};

	// standard Catmull-Rom spline: interpolate between x1 and x2 with previous/following points x1/x4
	CubicPoly.prototype.initCatmullRom = function( x0, x1, x2, x3, tension ) {

		this.init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );

	};

	CubicPoly.prototype.calc = function( t ) {

		var t2 = t * t;
		var t3 = t2 * t;
		return this.c0 + this.c1 * t + this.c2 * t2 + this.c3 * t3;

	};

	// Subclass Three.js curve
	return THREE.Curve.create(

		function ( p /* array of Vector3 */ ) {

			this.points = p || [];

		},

		function ( t ) {

			var points = this.points,
				point, intPoint, weight, l;

			l = points.length;

			if ( l < 2 ) console.log( 'duh, you need at least 2 points' );

			point = ( l - 1 ) * t;
			intPoint = Math.floor( point );
			weight = point - intPoint;

			if ( weight === 0 && intPoint === l - 1 ) {

				intPoint = l - 2;
				weight = 1;

			}

			var p0, p1, p2, p3;

			if ( intPoint === 0 ) {

				// extrapolate first point
				tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
				p0 = tmp;

			} else {

				p0 = points[ intPoint - 1 ];

			}

			p1 = points[ intPoint ];
			p2 = points[ intPoint + 1 ];

			if ( intPoint + 2 < l ) {

				p3 = points[ intPoint + 2 ]

			} else {

				// extrapolate last point
				tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 2 ] );
				p3 = tmp;

			}

			if ( this.type === undefined || this.type === 'centripetal' || this.type === 'chordal' ) {

				// init Centripetal / Chordal Catmull-Rom
				var pow = this.type === 'chordal' ? 0.5 : 0.25;
				var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
				var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
				var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );

				// safety check for repeated points
				if ( dt1 < 1e-4 ) dt1 = 1.0;
				if ( dt0 < 1e-4 ) dt0 = dt1;
				if ( dt2 < 1e-4 ) dt2 = dt1;

				px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
				py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
				pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );

			} else if ( this.type === 'catmullrom' ) {

				var tension = this.tension !== undefined ? this.tension : 0.5;
				px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, tension );
				py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, tension );
				pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, tension );

			}

			var v = new THREE.Vector3(
				px.calc( weight ),
				py.calc( weight ),
				pz.calc( weight )
			);

			return v;

		}

	);

} )();
<commit_msg>fix CatmullRomCurve3 end-point extrapolation<commit_after>/**
 * @author zz85 https://github.com/zz85
 *
 * Centripetal CatmullRom Curve - which is useful for avoiding
 * cusps and self-intersections in non-uniform catmull rom curves.
 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf
 *
 * curve.type accepts centripetal(default), chordal and catmullrom
 * curve.tension is used for catmullrom which defaults to 0.5
 */

THREE.CatmullRomCurve3 = ( function() {

	var
		tmp = new THREE.Vector3(),
		px = new CubicPoly(),
		py = new CubicPoly(),
		pz = new CubicPoly();

	/*
	Based on an optimized c++ solution in
	 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/
	 - http://ideone.com/NoEbVM

	This CubicPoly class could be used for reusing some variables and calculations,
	but for three.js curve use, it could be possible inlined and flatten into a single function call
	which can be placed in CurveUtils.
	*/

	function CubicPoly() {

	}

	/*
	 * Compute coefficients for a cubic polynomial
	 *   p(s) = c0 + c1*s + c2*s^2 + c3*s^3
	 * such that
	 *   p(0) = x0, p(1) = x1
	 *  and
	 *   p'(0) = t0, p'(1) = t1.
	 */
	CubicPoly.prototype.init = function( x0, x1, t0, t1 ) {

		this.c0 = x0;
		this.c1 = t0;
		this.c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
		this.c3 = 2 * x0 - 2 * x1 + t0 + t1;

	};

	CubicPoly.prototype.initNonuniformCatmullRom = function( x0, x1, x2, x3, dt0, dt1, dt2 ) {

		// compute tangents when parameterized in [t1,t2]
		var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
		var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;

		// rescale tangents for parametrization in [0,1]
		t1 *= dt1;
		t2 *= dt1;

		// initCubicPoly
		this.init( x1, x2, t1, t2 );

	};

	// standard Catmull-Rom spline: interpolate between x1 and x2 with previous/following points x1/x4
	CubicPoly.prototype.initCatmullRom = function( x0, x1, x2, x3, tension ) {

		this.init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );

	};

	CubicPoly.prototype.calc = function( t ) {

		var t2 = t * t;
		var t3 = t2 * t;
		return this.c0 + this.c1 * t + this.c2 * t2 + this.c3 * t3;

	};

	// Subclass Three.js curve
	return THREE.Curve.create(

		function ( p /* array of Vector3 */ ) {

			this.points = p || [];

		},

		function ( t ) {

			var points = this.points,
				point, intPoint, weight, l;

			l = points.length;

			if ( l < 2 ) console.log( 'duh, you need at least 2 points' );

			point = ( l - 1 ) * t;
			intPoint = Math.floor( point );
			weight = point - intPoint;

			if ( weight === 0 && intPoint === l - 1 ) {

				intPoint = l - 2;
				weight = 1;

			}

			var p0, p1, p2, p3;

			if ( intPoint === 0 ) {

				// extrapolate first point
				tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
				p0 = tmp;

			} else {

				p0 = points[ intPoint - 1 ];

			}

			p1 = points[ intPoint ];
			p2 = points[ intPoint + 1 ];

			if ( intPoint + 2 < l ) {

				p3 = points[ intPoint + 2 ]

			} else {

				// extrapolate last point
				tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] );
				p3 = tmp;

			}

			if ( this.type === undefined || this.type === 'centripetal' || this.type === 'chordal' ) {

				// init Centripetal / Chordal Catmull-Rom
				var pow = this.type === 'chordal' ? 0.5 : 0.25;
				var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow );
				var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow );
				var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow );

				// safety check for repeated points
				if ( dt1 < 1e-4 ) dt1 = 1.0;
				if ( dt0 < 1e-4 ) dt0 = dt1;
				if ( dt2 < 1e-4 ) dt2 = dt1;

				px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
				py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
				pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );

			} else if ( this.type === 'catmullrom' ) {

				var tension = this.tension !== undefined ? this.tension : 0.5;
				px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, tension );
				py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, tension );
				pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, tension );

			}

			var v = new THREE.Vector3(
				px.calc( weight ),
				py.calc( weight ),
				pz.calc( weight )
			);

			return v;

		}

	);

} )();
<|endoftext|>


<commit_before>"use strict";

import from from "../src/eslinq";

const owners = [
	{ name: "Kathy", pets: ["dog", "cat"] },
	{ name: "Johnny", pets: ["monkey", "spider"] },
	{ name: "Annie", pets: ["monkey", "cat"] }
];

const identity = n => n,
	double = n => n * 2,
	even = n => n % 2 === 0;

describe("from", () => {

	it("is defined", () => {
		expect(from).toBeDefined();
	});

	it("returns something when given an empty array", () => {
		expect(from([])).toBeDefined();
	});

	describe("can also work with non-array iterables, like", () => {

		const verifyForIterable = (iterable) => {
			const expected = [2, 4, 6],
				actual = from(iterable).select(double).toArray();
			expect(actual).toEqual(expected);
		};

		it("a set", () => {
		 	verifyForIterable(new Set([1, 2, 3]));
		});

	});

	describe("select", () => {

		it("returns an empty iterable when given an empty iterable", () => {
			const original = [],
				expected = [],
				actual = from(original).select(identity).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns the element itself when given the identity function", () => {
			const original = [1, 2],
			    expected = [1, 2],
				actual = from(original).select(identity).toArray();
			expect(actual).toEqual(expected);
		});

		it("can transform a one-element array", () => {
			const original = [1],
				expected = [2],
				actual = from(original).select(double).toArray();
			expect(actual).toEqual(expected);
		});

		it("can transform a two-element array", () => {
			const original = [1, 2],
			    expected = [2, 4],
				actual = from(original).select(double).toArray();
			expect(actual).toEqual(expected);
		});

		const verifyWithConstant = (constant) => {
			const original = [1, 2],
				expected = [constant, constant],
				actual = from(original).select(_ => constant).toArray();
			expect(actual).toEqual(expected);
		}

		it("works as expected if the transform function returns undefined", () => {
			verifyWithConstant(undefined);
		});

		it("works as expected if the transform function returns null", () => {
			verifyWithConstant(null);
		});

		it("works as expected if the transform function returns false", () => {
			verifyWithConstant(false);
		});

	});

	describe("selectMany", () => {

		const getPets = o => o.pets;

		it("returns an empty iterable when given an empty iterable", () => {
			const original = [],
				expected = [],
				actual = from(original).selectMany(getPets).toArray();
			expect(actual).toEqual(expected);
		});

		it("throws an error if the transform function does not return an iterable", () => {
			const original = [1, 2],
				wrapper = () => from(original).selectMany(identity).toArray(),
				expectedError = "Transform function should return an iterable";
			expect(wrapper).toThrowError(expectedError);
		});

		it("returns the concatenation of the arrays returned by transform", () => {
			const expected = ["dog", "cat", "monkey", "spider", "monkey", "cat"],
				actual = from(owners).selectMany(getPets).toArray();
			expect(actual).toEqual(expected);
		});

		it("behaves correctly if the transform function returns an empty iterable", () => {
			const original = [[1], [], [2], []],
				expected = [1, 2],
				actual = from(original).selectMany(identity).toArray();
			expect(actual).toEqual(expected);
		});

	});

	describe("where", () => {

		const verifyAllElementsReturned = (original) => {
			const expected = original,
				actual = from(original).where(_ => true).toArray();
			expect(actual).toEqual(expected);
		};

		it("returns an empty iterable when given an empty iterable", () => {
			const original = [],
				expected = [],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns an empty iterable when no elements match", () => {
			const original = [1, 3, 5],
				expected = [],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns only matching elements", () => {
			const original = [1, 2, 3, 4, 5],
				expected = [2, 4],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns all elements when all of them match", () => {
			const original = [2, 4, 6],
				actual = from(original).where(_ => true).toArray();
			expect(actual).toEqual(original);
		});

		it("returns an empty iterable if the only element in a collection does not match", () => {
			const original = [1],
				expected = [],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns the element if the only element in a collection matches", () => {
			const original = [2],
				expected = [2],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("works as expected if there are undefined elements in the collection", () => {
			verifyAllElementsReturned([1, undefined]);
		});

		it("works as expected if there are null elements in the collection", () => {
			verifyAllElementsReturned([1, null]);
		});

		it("works as expected if there are false elements in the collection", () => {
			verifyAllElementsReturned([1, false]);
		});

	});
});<commit_msg>Test cases for 'all'<commit_after>"use strict";

import from from "../src/eslinq";

const owners = [
	{ name: "Kathy", pets: ["dog", "cat"] },
	{ name: "Johnny", pets: ["monkey", "spider"] },
	{ name: "Annie", pets: ["monkey", "cat"] }
];

const identity = n => n,
	double = n => n * 2,
	even = n => n % 2 === 0;

describe("from", () => {

	it("is defined", () => {
		expect(from).toBeDefined();
	});

	it("returns something when given an empty array", () => {
		expect(from([])).toBeDefined();
	});

	describe("can also work with non-array iterables, like", () => {

		const verifyForIterable = (iterable) => {
			const expected = [2, 4, 6],
				actual = from(iterable).select(double).toArray();
			expect(actual).toEqual(expected);
		};

		it("a set", () => {
		 	verifyForIterable(new Set([1, 2, 3]));
		});

	});

	describe("select", () => {

		it("returns an empty iterable when given an empty iterable", () => {
			const original = [],
				expected = [],
				actual = from(original).select(identity).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns the element itself when given the identity function", () => {
			const original = [1, 2],
			    expected = [1, 2],
				actual = from(original).select(identity).toArray();
			expect(actual).toEqual(expected);
		});

		it("can transform a one-element array", () => {
			const original = [1],
				expected = [2],
				actual = from(original).select(double).toArray();
			expect(actual).toEqual(expected);
		});

		it("can transform a two-element array", () => {
			const original = [1, 2],
			    expected = [2, 4],
				actual = from(original).select(double).toArray();
			expect(actual).toEqual(expected);
		});

		const verifyWithConstant = (constant) => {
			const original = [1, 2],
				expected = [constant, constant],
				actual = from(original).select(_ => constant).toArray();
			expect(actual).toEqual(expected);
		}

		it("works as expected if the transform function returns undefined", () => {
			verifyWithConstant(undefined);
		});

		it("works as expected if the transform function returns null", () => {
			verifyWithConstant(null);
		});

		it("works as expected if the transform function returns false", () => {
			verifyWithConstant(false);
		});

	});

	describe("selectMany", () => {

		const getPets = o => o.pets;

		it("returns an empty iterable when given an empty iterable", () => {
			const original = [],
				expected = [],
				actual = from(original).selectMany(getPets).toArray();
			expect(actual).toEqual(expected);
		});

		it("throws an error if the transform function does not return an iterable", () => {
			const original = [1, 2],
				wrapper = () => from(original).selectMany(identity).toArray(),
				expectedError = "Transform function should return an iterable";
			expect(wrapper).toThrowError(expectedError);
		});

		it("returns the concatenation of the arrays returned by transform", () => {
			const expected = ["dog", "cat", "monkey", "spider", "monkey", "cat"],
				actual = from(owners).selectMany(getPets).toArray();
			expect(actual).toEqual(expected);
		});

		it("behaves correctly if the transform function returns an empty iterable", () => {
			const original = [[1], [], [2], []],
				expected = [1, 2],
				actual = from(original).selectMany(identity).toArray();
			expect(actual).toEqual(expected);
		});

	});

	describe("where", () => {

		const verifyAllElementsReturned = (original) => {
			const expected = original,
				actual = from(original).where(_ => true).toArray();
			expect(actual).toEqual(expected);
		};

		it("returns an empty iterable when given an empty iterable", () => {
			const original = [],
				expected = [],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns an empty iterable when no elements match", () => {
			const original = [1, 3, 5],
				expected = [],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns only matching elements", () => {
			const original = [1, 2, 3, 4, 5],
				expected = [2, 4],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns all elements when all of them match", () => {
			const original = [2, 4, 6],
				actual = from(original).where(_ => true).toArray();
			expect(actual).toEqual(original);
		});

		it("returns an empty iterable if the only element in a collection does not match", () => {
			const original = [1],
				expected = [],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("returns the element if the only element in a collection matches", () => {
			const original = [2],
				expected = [2],
				actual = from(original).where(even).toArray();
			expect(actual).toEqual(expected);
		});

		it("works as expected if there are undefined elements in the collection", () => {
			verifyAllElementsReturned([1, undefined]);
		});

		it("works as expected if there are null elements in the collection", () => {
			verifyAllElementsReturned([1, null]);
		});

		it("works as expected if there are false elements in the collection", () => {
			verifyAllElementsReturned([1, false]);
		});

	});

	describe("all", () => {

		it("returns true when given an empty iterable and a constant true condition", () => {
			const original = [],
				expected = true,
				actual = from(original).all(_ => true);
			expect(actual).toEqual(expected);
		});

		it("returns true when given an empty iterable and a constant false condition", () => {
			const original = [],
				expected = true,
				actual = from(original).all(_ => false);
			expect(actual).toEqual(expected);
		});

		it("returns true when given a one-element iterable and a constant true condition", () => {
			const original = [1],
				expected = true,
				actual = from(original).all(_ => true);
			expect(actual).toEqual(expected);
		});

		it("returns false when given a one-element iterable and a constant false condition", () => {
			const original = [1],
				expected = false,
				actual = from(original).all(_ => false);
			expect(actual).toEqual(expected);
		});

		it("returns true if all elements match", () => {
			const original = [1, 2, 3],
				expected = true,
				matches = n => n < 4,
				actual = from(original).all(matches);
			expect(actual).toEqual(expected);
		});

		it("returns false if no elements match", () => {
			const original = [1, 2, 3],
				expected = false,
				matches = n => n >= 4,
				actual = from(original).all(matches);
			expect(actual).toEqual(expected);
		});

		it("returns false if one element doesn't match", () => {
			const original = [1, 2, 3],
				expected = false,
				matches = n => n < 3,
				actual = from(original).all(matches);
			expect(actual).toEqual(expected);
		});

		it("works if the condition returns non-boolean truthy values", () => {
			const original = [1, '1'];
			expect(from(original).all(identity)).toBe(true);
		});

		it("works if the condition returns non-boolean falsy values", () => {
			const cases = [0, undefined, NaN, ""];
			for (let c of cases)
				expect(from([c]).all(identity)).toBe(false);
		});

	});
});<|endoftext|>


<commit_before>exports.config = {
    params: {
    baseUrl: {
      osio: 'https://openshift.io/',
      username: 'testuser@redhat.com'
    }
    },
    useAllAngular2AppRoots: true,
    getPageTimeout: 30000,
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['src/tests/**/*.spec.js'],
    exclude: ['src/tests/**/EE/*.spec.js'],
    jasmineNodeOpts: {
        defaultTimeoutInterval: 30000
    },

    capabilities: {
         'browserName': 'phantomjs',
         'phantomjs.binary.path': require('phantomjs-prebuilt').path,
         'phantomjs.cli.args': ['--webdriver-loglevel=ERROR', '--local-storage-path=/tmp/phantom_' + Math.random()]

    }
};

<commit_msg>Use chromedriver instead of phantomjs<commit_after>exports.config = {
    params: {
    baseUrl: {
      osio: 'https://openshift.io/',
      username: 'testuser@redhat.com'
    }
    },
    useAllAngular2AppRoots: true,
    getPageTimeout: 30000,
    seleniumAddress: 'http://localhost:4444/wd/hub',
    specs: ['src/tests/**/*.spec.js'],
    exclude: ['src/tests/**/EE/*.spec.js'],

    jasmineNodeOpts: {
        isVerbose: true,
        showColors: true,
        includeStackTrace: true,
        defaultTimeoutInterval: 60000
    },

    troubleshoot: true,

    capabilities: {
      'browserName': 'chrome',
      'maxInstances': 2,
      'shardTestFiles': true,
      'loggingPrefs': {
      'driver': 'WARNING',
      'server': 'WARNING',
      'browser': 'INFO'
      },
      'chromeOptions': {
      'args': [ '--no-sandbox', '--window-workspace=1']
      }
    }
};

<|endoftext|>