<commit_before>var nodeunit = require('nodeunit'), fs = require('fs');
var GQ = require('../index');

var data_types = new Array();
module.exports = nodeunit.testCase({
  'one-task': function(t) {

    var q = GQ(), pkgj = './task-test1.json';
    var p = {}, task_ids = [];
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      q.destroy(), t.ok(true, 'one-task: going to done.');
      t.done();
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  },
  'two-tasks': function(t) {

    var q = GQ(), pkgjs = ['./task-test1.json', './task-test2.json'];
    var p = {}, task_ids = [];

    var pkgcs = pkgjs.map(function(pkgj) {
      return JSON.parse(fs.readFileSync(pkgj).toString());
    });

    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      var pkgc = (pkgcs[0].taskList.length == 0 ? pkgcs.shift(): pkgcs[0]);
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        var pkgc = pkgcs[pkgcs[0].taskList[0] == name ? 0: 1];
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      if(task_ids.length == 0) {
        q.destroy(), t.ok(true, 'two-tasks: going to done.');
        t.done();
      }
    }));

    pkgjs.forEach(function(pkgj, i) {
      _setConcatTaskp(p, i + 1), _setUglifyTaskp(p);
      q.enqueue(pkgj, p, {
        workdir: __dirname
      }).on('end', function(_id, task) {
        t.equal(_id.length, 32), t.equal(task._id, _id);
        task_ids.push(_id);
      });
    });

  },
  'error-task': function(t) {

    var q = GQ(), pkgj = './task-teste.json';
    var p = {}, task_ids = [], e = 1;
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('error', function() {
      e--;
      q.progress(task_ids[0], function(err, data) {
        t.equal(data.state, 'error');
        t.ok(data.progress instanceof Error);
      });
      if(e === 0)
        setTimeout(function() {
          q.progress(task_ids[0], function(err, data) {
            t.equal(e, 0);
            t.equal(data.state, 'error');
            t.ok(data.progress instanceof Error);
            q.destroy(), t.ok(true, 'error-task: going to done.');
            // 2(start, finish) * 8 (complete-task-num) + 1 * 1 (error-task-num)
            console.log(data_types); // for debug.
            t.equals(data_types.length, 2 * 7 + 1), t.done();
          });
        }, 5000);
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname,
      timeout: 10 * 1000
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  }
});

function _setConcatTaskp(p, tidx) {
  p.concat = {};
  p.concat.options = {
    separator: ";"
  };
  p.concat.dist = {
    src: ["src/test" + tidx + "/*.js"],
    dest: "dist/<%= pkg.name %>.js"
  };
}

function _setUglifyTaskp(p) {
  p.uglify = {};
  p.uglify.options = {
    banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  };
  p.uglify.dist = {
    files: {
      'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
    }
  };
}

function _bindLogging(ee) {
  ee.on('ready', function() {
    //console.log('ready', arguments);
  }).on('error', function() {
    console.error(arguments);
  }).on('busy', function() {
    console.error('onbusy', arguments);
  }).on('empty', function() {
    console.error('onempty', arguments);
  }).on('data', function() {
    //console.log('ondata', arguments);
  }).on('progress', function() {
    //console.log('onprogress', arguments);
  });
}

function chkReady(q, t) {
  // q._ready has been set true.
  t.ok(q._ready);
}

function chkProgress(q, t, task_id, task_ids) {

  // task_id has been returned after enqueue
  t.ok(~task_ids.indexOf(task_id), 'Task #' + task_id + ' end.');

  t.equal(GQ.Task.countAlives(), task_ids.length);
  q.dequeue(task_id);

  // dequeue twice is not allowed
  try {
    q.dequeue(task_id)
  } catch(e) {
    t.equal(/The task is not found./.test(e.message), true);
  }

  task_ids.splice(task_ids.indexOf(task_id), 1);
  t.equal(GQ.Task.countAlives(), task_ids.length);
  t.equal(q._q.length, 1);
  t.equal(Object.keys(q._fq).length, 0);
  t.equal(q._workers.length, require('os').cpus().length);

}
<commit_msg>fix test<commit_after>var nodeunit = require('nodeunit'), fs = require('fs');
var GQ = require('../index');

var data_types = new Array();
module.exports = nodeunit.testCase({
  'one-task': function(t) {

    var q = GQ(), pkgj = './task-test1.json';
    var p = {}, task_ids = [];
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      q.destroy(), t.ok(true, 'one-task: going to done.');
      t.done();
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  },
  'two-tasks': function(t) {

    var q = GQ(), pkgjs = ['./task-test1.json', './task-test2.json'];
    var p = {}, task_ids = [];

    var pkgcs = pkgjs.map(function(pkgj) {
      return JSON.parse(fs.readFileSync(pkgj).toString());
    });

    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      var pkgc = (pkgcs[0].taskList.length == 0 ? pkgcs.shift(): pkgcs[0]);
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        var pkgc = pkgcs[pkgcs[0].taskList[0] == name ? 0: 1];
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('progress', function(task_id) {
      chkProgress(q, t, task_id, task_ids);
      if(task_ids.length == 0) {
        q.destroy(), t.ok(true, 'two-tasks: going to done.');
        t.done();
      }
    }));

    pkgjs.forEach(function(pkgj, i) {
      _setConcatTaskp(p, i + 1), _setUglifyTaskp(p);
      q.enqueue(pkgj, p, {
        workdir: __dirname
      }).on('end', function(_id, task) {
        t.equal(_id.length, 32), t.equal(task._id, _id);
        task_ids.push(_id);
      });
    });

  },
  'error-task': function(t) {

    var q = GQ(), pkgj = './task-teste.json';
    var p = {}, task_ids = [], e = 1;
    _setConcatTaskp(p, 1), _setUglifyTaskp(p);

    var pkgc = JSON.parse(fs.readFileSync(pkgj).toString());
    _bindLogging(q.on('ready', function() {
      chkReady(q, t);
    }).on('data', function(task_id, type, args) {
      data_types.push('[' + args[0] + '] ' + type);
      type == 'finish' && (function(name) {
        t.equal(pkgc.taskList.shift(), name);
      })(args[0]);
    }).on('error', function() {
      e--;
      q.progress(task_ids[0], function(err, data) {
        t.equal(data.state, 'error');
        t.ok(data.progress instanceof Error);
      });
      if(e === 0)
        setTimeout(function() {
          q.progress(task_ids[0], function(err, data) {
            t.equal(e, 0);
            t.equal(data.state, 'error');
            t.ok(data.progress instanceof Error);
            q.destroy(), t.ok(true, 'error-task: going to done.');
            // 2(start, finish) * 8 (complete-task-num) + 1 * 1 (error-task-num)
            console.log(data_types); // for debug.
            t.equals(data_types.length, 2 * 8 + 1 * 1), t.done();
          });
        }, 5000);
    }));

    q.enqueue(pkgj, p, {
      workdir: __dirname,
      timeout: 10 * 1000
    }).on('end', function(_id, task) {
      t.equal(_id.length, 32), t.equal(task._id, _id);
      task_ids.push(_id);
    });

  }
});

function _setConcatTaskp(p, tidx) {
  p.concat = {};
  p.concat.options = {
    separator: ";"
  };
  p.concat.dist = {
    src: ["src/test" + tidx + "/*.js"],
    dest: "dist/<%= pkg.name %>.js"
  };
}

function _setUglifyTaskp(p) {
  p.uglify = {};
  p.uglify.options = {
    banner: '/*! <%= pkg.name %> <%= grunt.template.today("dd-mm-yyyy") %> */\n'
  };
  p.uglify.dist = {
    files: {
      'dist/<%= pkg.name %>.min.js': ['<%= concat.dist.dest %>']
    }
  };
}

function _bindLogging(ee) {
  ee.on('ready', function() {
    //console.log('ready', arguments);
  }).on('error', function() {
    console.error(arguments);
  }).on('busy', function() {
    console.error('onbusy', arguments);
  }).on('empty', function() {
    console.error('onempty', arguments);
  }).on('data', function() {
    //console.log('ondata', arguments);
  }).on('progress', function() {
    //console.log('onprogress', arguments);
  });
}

function chkReady(q, t) {
  // q._ready has been set true.
  t.ok(q._ready);
}

function chkProgress(q, t, task_id, task_ids) {

  // task_id has been returned after enqueue
  t.ok(~task_ids.indexOf(task_id), 'Task #' + task_id + ' end.');

  t.equal(GQ.Task.countAlives(), task_ids.length);
  q.dequeue(task_id);

  // dequeue twice is not allowed
  try {
    q.dequeue(task_id)
  } catch(e) {
    t.equal(/The task is not found./.test(e.message), true);
  }

  task_ids.splice(task_ids.indexOf(task_id), 1);
  t.equal(GQ.Task.countAlives(), task_ids.length);
  t.equal(q._q.length, 1);
  t.equal(Object.keys(q._fq).length, 0);
  t.equal(q._workers.length, require('os').cpus().length);

}
<|endoftext|>


<commit_before><commit_msg>Update intlTelInput.js<commit_after><|endoftext|>


<commit_before>var calculator = {

  init: function() {
    $('#calculator .input').click(function() {

      if(this.dataset.keyType == "digit") {
        calculator.handleInput(this.dataset.digit);
      } else if (this.dataset.keyType == "operator") {
        calculator.handleOperator(this.dataset.operator);
      } else if (this.dataset.keyType == "delete") {
        calculator.handleDelete();
      } else if (this.dataset.keyType == "equals") {
        calculator.evaluateResult();
      }
    });

    $('#calculator #delete').dblclick(function() {
        calculator.clearPreview();
        calculator.clearResult();
    });

    ['0','1','2','3','4','5','6','7','8','9','/','*','+','-'].forEach(function(digit) {
      $(document).bind('keyup', digit ,function() {
        calculator.handleInput(digit);
      });
    });

    ['/','*','+','-'].forEach(function(digit) {
      $(document).bind('keyup', digit ,function() {
        calculator.handleOperator(digit);
      });
    });

    $(document).bind('keyup', '.' , function() {
      lastNumber = calculator.getLastNumber();
      if(lastNumber.indexOf('.') == -1) {
        if(lastNumber.length == 0) {
          calculator.handleInput(0);
        }
        calculator.handleInput('.');
      }
    });

    $(document).bind('keyup', 'backspace' ,function() {
        calculator.handleDelete();
      });
    $(document).bind('keyup', 'shift+=' ,function() {
        calculator.handleOperator('+');
      });
    ['=','return'].forEach(function(key) {
    $(document).bind('keyup', key ,function() {
        calculator.evaluateResult();
      });
    });
  },
  /*
  handleInput: function(input) {
    $('#preview').html($('#preview').html() + input);
  },
  */
  handleInput: function(input) {
    $('#preview').html($('#preview').html() + input);
  },

   handleOperator: function(operator) {
    if($('#preview').html().length == 0) {
      if(operator == '-') {
        calculator.handleInput('-');
      }
    } else {
      if(calculator.checkLastCharIsOperator()) {
        calculator.handleDelete();
      }
        calculator.handleInput(operator);
      }
  },

  handleDelete: function() {
      $('#preview').html($('#preview').html().slice(0, -1));
      if($('#preview').html().length == 0) {
        calculator.clearResult();
      }
  },

  evaluateResult: function() {
      if(calculator.checkLastCharIsOperator()) {
        calculator.handleDelete();
      }
      $('#result').html(eval($('#preview').html()));
  },

  clearResult: function() {
      $('#result').html('');
  },

  clearPreview: function() {
      $('#preview').html('');
  },

  clearPreview: function() {
      $('#preview').html('');
  },

  getLastNumber: function() {
    str = $('#preview').html();
    regexp = /[+\-*\/]?([0-9.])*$/
    matches = str.match(regexp);
    if(matches == null) {
      return str;
    } else {
      return  matches[0].slice(1);
    }
  },

  getLastChar: function() {
    str = $('#preview').html();
    if(str.length == 0) {
      return str;
    } else {
    return str[str.length - 1];
    }
  },

  checkLastCharIsOperator: function() {
     lastChar = calculator.getLastChar();
     return(['+','-', '*', '/'].indexOf(lastChar) != -1);
  }
}

$(document).ready(function() {
  calculator.init();
});<commit_msg>handling corner cases for Equals<commit_after>var calculator = {

  init: function() {
    $('#calculator .input').click(function() {

      if(this.dataset.keyType == "digit") {
        calculator.handleInput(this.dataset.digit);
      } else if (this.dataset.keyType == "operator") {
        calculator.handleOperator(this.dataset.operator);
      } else if (this.dataset.keyType == "delete") {
        calculator.handleDelete();
      } else if (this.dataset.keyType == "equals") {
        calculator.evaluateResult();
      }
    });

    $('#calculator #delete').dblclick(function() {
        calculator.clearPreview();
        calculator.clearResult();
    });

    ['0','1','2','3','4','5','6','7','8','9','/','*','+','-'].forEach(function(digit) {
      $(document).bind('keyup', digit ,function() {
        calculator.handleInput(digit);
      });
    });

    ['/','*','+','-'].forEach(function(digit) {
      $(document).bind('keyup', digit ,function() {
        calculator.handleOperator(digit);
      });
    });

    $(document).bind('keyup', '.' , function() {
      lastNumber = calculator.getLastNumber();
      if(lastNumber.indexOf('.') == -1) {
        if(lastNumber.length == 0) {
          calculator.handleInput(0);
        }
        calculator.handleInput('.');
      }
    });

    $(document).bind('keyup', 'backspace' ,function() {
        calculator.handleDelete();
      });
    $(document).bind('keyup', 'shift+=' ,function() {
        calculator.handleOperator('+');
      });
    ['=','return'].forEach(function(key) {
    $(document).bind('keyup', key ,function() {
        calculator.evaluateResult();
      });
    });
  },
  /*
  handleInput: function(input) {
    $('#preview').html($('#preview').html() + input);
  },
  */
  handleInput: function(input) {
    $('#preview').html($('#preview').html() + input);
  },

   handleOperator: function(operator) {
    if($('#preview').html().length == 0) {
      if(operator == '-') {
        calculator.handleInput('-');
      }
    } else {
      if(calculator.checkLastCharIsOperator()) {
        calculator.handleDelete();
      }
        calculator.handleInput(operator);
      }
  },

  handleDelete: function() {
      $('#preview').html($('#preview').html().slice(0, -1));
      if($('#preview').html().length == 0) {
        calculator.clearResult();
      }
  },

  evaluateResult: function() {
      if(calculator.checkLastCharIsOperator()) {
        calculator.handleDelete();
      }
      $('#result').html(eval($('#preview').html()));
  },

  clearResult: function() {
      $('#result').html('');
  },

  clearPreview: function() {
      $('#preview').html('');
  },

  clearPreview: function() {
      $('#preview').html('');
  },

  getLastNumber: function() {
    str = $('#preview').html();
    regexp = /[+\-*\/]?([0-9.])*$/
    matches = str.match(regexp);
    if(matches == null) {
      return str;
    } else {
      return  matches[0].slice(1);
    }
  },

  getLastChar: function() {
    str = $('#preview').html();
    if(str.length == 0) {
      return str;
    } else {
    return str[str.length - 1];
    }
  },

  checkLastCharIsOperator: function() {
     lastChar = calculator.getLastChar();
     return(['+','-', '*', '/'].indexOf(lastChar) != -1);
  }
}

$(document).ready(function() {
  calculator.init();
});<|endoftext|>


<commit_before>var test = require('tape')
var convertToBuffer = require('../')

test('convert to buffer from uint8array', function (t) {
  if (typeof Uint8Array === 'function') {
    var arr = new Uint8Array([1, 2, 3])
    arr = convertToBuffer(arr)

    t.deepEqual(arr, new Buffer([1, 2, 3]), 'contents equal')
    t.ok(Buffer.isBuffer(arr), 'is buffer')
    t.equal(arr.readUInt16BE(0), 258)
  } else {
    t.pass('browser lacks uint8array support, skip test')
  }
  t.end()
})

test('convert to buffer from another array type (uint32array)', function (t) {
  if (typeof Uint32Array === 'function') {
    var arr = new Uint32Array([1, 2, 3])
    arr = convertToBuffer(arr)

    t.deepEqual(arr, new Buffer([1, 2, 3]), 'contents equal')
    t.ok(Buffer.isBuffer(arr), 'is buffer')
    t.equal(arr.readUInt16BE(0), 258)
  } else {
    t.pass('browser lacks uint32array support, skip test')
  }
  t.end()
})
<commit_msg>fix typed array check<commit_after>var test = require('tape')
var convertToBuffer = require('../')

test('convert to buffer from uint8array', function (t) {
  if (typeof Uint8Array !== 'undefined') {
    var arr = new Uint8Array([1, 2, 3])
    arr = convertToBuffer(arr)

    t.deepEqual(arr, new Buffer([1, 2, 3]), 'contents equal')
    t.ok(Buffer.isBuffer(arr), 'is buffer')
    t.equal(arr.readUInt16BE(0), 258)
  } else {
    t.pass('browser lacks uint8array support, skip test')
  }
  t.end()
})

test('convert to buffer from another array type (uint32array)', function (t) {
  if (typeof Uint32Array !== 'undefined') {
    var arr = new Uint32Array([1, 2, 3])
    arr = convertToBuffer(arr)

    t.deepEqual(arr, new Buffer([1, 2, 3]), 'contents equal')
    t.ok(Buffer.isBuffer(arr), 'is buffer')
    t.equal(arr.readUInt16BE(0), 258)
  } else {
    t.pass('browser lacks uint32array support, skip test')
  }
  t.end()
})
<|endoftext|>


<commit_before>

////////////// db-subscriptions:

Meteor.subscribe('currentUser');
Meteor.subscribe('version');

// Always load english translation
// For dynamically constructed translation strings there is no default
// translation and meteor would show the translation key if there is no
// translation in the current locale
mfPkg.loadLangs('en');

// close any verification dialogs still open
Router.onBeforeAction(function() {
	Tooltips.hide();

	Session.set('verify', false);

	this.next();
});

// Store routeName to be able to refer to previous route
Router.onStop(function() {
	var route = Router.current().route;
	if (route) Session.set('previousRouteName', route.getName());
});

// Subscribe to list of regions and configure the regions
// This checks client storage for a region setting. When there is no previously
// selected region, we ask the server to do geolocation. If that fails too,
// we just set it to 'all regions'.

var regionSelectors =
	[ Session.get('region') // The region might have been chosen already because the user is logged-in. See Accounts.onLogin().
	, UrlTools.queryParam('region')
	, localStorage.getItem('region')
	].filter(Boolean);

// When the region is not provided we show a splash screen
Session.set('showSplash', regionSelectors.length < 1);

// Define routes where we don't go to the homepage when selecting a region
// and therefore show the region splash.
RoutesToKeep = ['home', 'find', 'venue', 'calendar'];

Meteor.subscribe('regions', function() {
	var useAsRegion = function(regionId) {
		if (!regionId) return;
		if (regionId == 'all') {
			Session.set("region", regionId);
			return true;
		}
		if (Regions.findOne({ _id: regionId })) {
			Session.set("region", regionId);
			return true;
		}

		var region = Regions.findOne({ name: regionId });
		if (region) {
			Session.set("region", region._id);
			return true;
		}
		return false;
	};

	if (regionSelectors.some(useAsRegion)) return;

	// Give up and ask the server to place us
	Meteor.call('autoSelectRegion', function(error, regionId) {
		if (useAsRegion(regionId)) return;

		// Give up
		useAsRegion('all');
	});
});

// We keep two subscription caches around. One is for the regular subscriptions like list of courses,
// the other (miniSubs) is for the name lookups we do all over the place.
subs = new SubsCache({ cacheLimit: 5, expireAfter: 1 });
miniSubs = new SubsCache({ cacheLimit: 50, expireAfter: 1 });

// Try to guess a sensible language
Meteor.startup(function() {
	var useLocale = function(lang) {
		if (!lang) return false;

		var locale = false;
		if (Languages[lang]) {
			locale = lang;
		}
		if (!locale && lang.length > 2) {
			var short = lang.substring(0, 2);
			if (Languages[short]) {
				locale = short;
			}
		}
		if (locale) {
			Session.set('locale', locale);
			return true;
		}
		return false;
	};

	// Check query parameter and cookies
	if (useLocale(UrlTools.queryParam('lg'))) return;
	if (useLocale(localStorage.getItem('locale'))) return;

	// Try to access the preferred languages. For the legacy browsers that don't
	// expose it we could ask the server for the Accept-Language headers but I'm
	// too lazy to implement this. It would become obsolete anyway.
	for (var i in navigator.languages || []) {
		if (useLocale(navigator.languages[i])) return;
	}

	// Here we ask for the browser UI language which may not be what the visitor
	// wanted. Oh well.
	if (useLocale(navigator.language)) return;

	// Give up. Here's to Cultural Homogenization.
	useLocale('en');
});

Meteor.startup(function() {
	Tracker.autorun(function() {
		var desiredLocale = Session.get('locale');

		mfPkg.setLocale(desiredLocale);

		// Logic taken from mfpkg:core to get text directionality
		var lang = desiredLocale.substr(0, 2);
		var textDirectionality = msgfmt.dirFromLang(lang);
		Session.set('textDirectionality', textDirectionality);

		// Msgfmt already sets the dir attribute, but we want a class too.
		var isRTL = textDirectionality == 'rtl';
		$('body').toggleClass('rtl', isRTL);

		// Tell moment to switch the locale
		// Also change timeLocale which will invalidate the parts that depend on it
		var setLocale = moment.locale(desiredLocale);
		Session.set('timeLocale', setLocale);
		if (desiredLocale !== setLocale) console.log("Date formatting set to "+setLocale+" because "+desiredLocale+" not available");

		// HACK replace the datepicker locale settings
		// I do not understand why setting language: moment.locale() does not
		// work for the datepicker. But we want to use the momentjs settings
		// anyway, so we might as well clobber the 'en' locale.
		var mf = moment().localeData();

		var monthsShort = function() {
			if (typeof mf.monthsShort === 'function') {
				return _.map(_.range(12), function(month) { return mf.monthsShort(moment().month(month), ''); });
			}
			return mf._monthsShort;
		};

		$.fn.datepicker.dates.en = _.extend({}, $.fn.datepicker.dates.en, {
			days: mf._weekdays,
			daysShort: mf._weekdaysShort,
			daysMin: mf._weekdaysMin,
			months: mf._months || mf._monthsNominativeEl,
			monthsShort: monthsShort(),
			weekStart: mf._week.dow
		});
	});
});

Meteor.startup(Assistant.init);

Meteor.startup(getViewportWidth);

Accounts.onLogin(function() {
	var user = Meteor.user();

	var locale = user.profile.locale;
	if (locale) Session.set('locale', locale);

	var regionId = user.profile.regionId;
	if (regionId) Session.set('region', regionId);
});

Accounts.onEmailVerificationLink(function(token, done) {
	Router.go('profile');
	Accounts.verifyEmail(token, function(error) {
		if (error) {
			showServerError('Address could not be verified', error);
		} else {
			addMessage(mf("email.verified", "Email verified."), 'success');
		}
	});
});

minuteTime = new ReactiveVar();

// Set up reactive date sources that can be used for updates based on time
function setTimes() {
	var now = new Date();

	now.setSeconds(0);
	now.setMilliseconds(0);
	var old = minuteTime.get();
	if (!old || old.getTime() !== now.getTime()) {
		minuteTime.set(now);
	}
}
setTimes();

// Update interval of five seconds is okay
Meteor.setInterval(setTimes, 1000*5);
<commit_msg>add view venues to the routes to keep when switching region<commit_after>

////////////// db-subscriptions:

Meteor.subscribe('currentUser');
Meteor.subscribe('version');

// Always load english translation
// For dynamically constructed translation strings there is no default
// translation and meteor would show the translation key if there is no
// translation in the current locale
mfPkg.loadLangs('en');

// close any verification dialogs still open
Router.onBeforeAction(function() {
	Tooltips.hide();

	Session.set('verify', false);

	this.next();
});

// Store routeName to be able to refer to previous route
Router.onStop(function() {
	var route = Router.current().route;
	if (route) Session.set('previousRouteName', route.getName());
});

// Subscribe to list of regions and configure the regions
// This checks client storage for a region setting. When there is no previously
// selected region, we ask the server to do geolocation. If that fails too,
// we just set it to 'all regions'.

var regionSelectors =
	[ Session.get('region') // The region might have been chosen already because the user is logged-in. See Accounts.onLogin().
	, UrlTools.queryParam('region')
	, localStorage.getItem('region')
	].filter(Boolean);

// When the region is not provided we show a splash screen
Session.set('showSplash', regionSelectors.length < 1);

// Define routes where we don't go to the homepage when selecting a region
// and therefore show the region splash.
RoutesToKeep = ['home', 'find', 'venue', 'calendar', 'venues'];

Meteor.subscribe('regions', function() {
	var useAsRegion = function(regionId) {
		if (!regionId) return;
		if (regionId == 'all') {
			Session.set("region", regionId);
			return true;
		}
		if (Regions.findOne({ _id: regionId })) {
			Session.set("region", regionId);
			return true;
		}

		var region = Regions.findOne({ name: regionId });
		if (region) {
			Session.set("region", region._id);
			return true;
		}
		return false;
	};

	if (regionSelectors.some(useAsRegion)) return;

	// Give up and ask the server to place us
	Meteor.call('autoSelectRegion', function(error, regionId) {
		if (useAsRegion(regionId)) return;

		// Give up
		useAsRegion('all');
	});
});

// We keep two subscription caches around. One is for the regular subscriptions like list of courses,
// the other (miniSubs) is for the name lookups we do all over the place.
subs = new SubsCache({ cacheLimit: 5, expireAfter: 1 });
miniSubs = new SubsCache({ cacheLimit: 50, expireAfter: 1 });

// Try to guess a sensible language
Meteor.startup(function() {
	var useLocale = function(lang) {
		if (!lang) return false;

		var locale = false;
		if (Languages[lang]) {
			locale = lang;
		}
		if (!locale && lang.length > 2) {
			var short = lang.substring(0, 2);
			if (Languages[short]) {
				locale = short;
			}
		}
		if (locale) {
			Session.set('locale', locale);
			return true;
		}
		return false;
	};

	// Check query parameter and cookies
	if (useLocale(UrlTools.queryParam('lg'))) return;
	if (useLocale(localStorage.getItem('locale'))) return;

	// Try to access the preferred languages. For the legacy browsers that don't
	// expose it we could ask the server for the Accept-Language headers but I'm
	// too lazy to implement this. It would become obsolete anyway.
	for (var i in navigator.languages || []) {
		if (useLocale(navigator.languages[i])) return;
	}

	// Here we ask for the browser UI language which may not be what the visitor
	// wanted. Oh well.
	if (useLocale(navigator.language)) return;

	// Give up. Here's to Cultural Homogenization.
	useLocale('en');
});

Meteor.startup(function() {
	Tracker.autorun(function() {
		var desiredLocale = Session.get('locale');

		mfPkg.setLocale(desiredLocale);

		// Logic taken from mfpkg:core to get text directionality
		var lang = desiredLocale.substr(0, 2);
		var textDirectionality = msgfmt.dirFromLang(lang);
		Session.set('textDirectionality', textDirectionality);

		// Msgfmt already sets the dir attribute, but we want a class too.
		var isRTL = textDirectionality == 'rtl';
		$('body').toggleClass('rtl', isRTL);

		// Tell moment to switch the locale
		// Also change timeLocale which will invalidate the parts that depend on it
		var setLocale = moment.locale(desiredLocale);
		Session.set('timeLocale', setLocale);
		if (desiredLocale !== setLocale) console.log("Date formatting set to "+setLocale+" because "+desiredLocale+" not available");

		// HACK replace the datepicker locale settings
		// I do not understand why setting language: moment.locale() does not
		// work for the datepicker. But we want to use the momentjs settings
		// anyway, so we might as well clobber the 'en' locale.
		var mf = moment().localeData();

		var monthsShort = function() {
			if (typeof mf.monthsShort === 'function') {
				return _.map(_.range(12), function(month) { return mf.monthsShort(moment().month(month), ''); });
			}
			return mf._monthsShort;
		};

		$.fn.datepicker.dates.en = _.extend({}, $.fn.datepicker.dates.en, {
			days: mf._weekdays,
			daysShort: mf._weekdaysShort,
			daysMin: mf._weekdaysMin,
			months: mf._months || mf._monthsNominativeEl,
			monthsShort: monthsShort(),
			weekStart: mf._week.dow
		});
	});
});

Meteor.startup(Assistant.init);

Meteor.startup(getViewportWidth);

Accounts.onLogin(function() {
	var user = Meteor.user();

	var locale = user.profile.locale;
	if (locale) Session.set('locale', locale);

	var regionId = user.profile.regionId;
	if (regionId) Session.set('region', regionId);
});

Accounts.onEmailVerificationLink(function(token, done) {
	Router.go('profile');
	Accounts.verifyEmail(token, function(error) {
		if (error) {
			showServerError('Address could not be verified', error);
		} else {
			addMessage(mf("email.verified", "Email verified."), 'success');
		}
	});
});

minuteTime = new ReactiveVar();

// Set up reactive date sources that can be used for updates based on time
function setTimes() {
	var now = new Date();

	now.setSeconds(0);
	now.setMilliseconds(0);
	var old = minuteTime.get();
	if (!old || old.getTime() !== now.getTime()) {
		minuteTime.set(now);
	}
}
setTimes();

// Update interval of five seconds is okay
Meteor.setInterval(setTimes, 1000*5);
<|endoftext|>


<commit_before>var ExpeditionController = function() {
	//var loadData = require('data-loader.js');
	//this.currentExpedition;
	//this.viewingMode; //landing, expedition

	this.expeditions = [];
	var features;
	var that = this;

	var IC = require('./interface-controller.js');
	var InterfaceController = new IC(this);
	var MC = require('./map-controller.js');
	var MapController = new MC();

	$.when($.get('dist/data/expeditions.json'), $.get('dist/data/expeditions-geometries.json'))
	.done(function(exp, geoms) {
		that.expeditions = $.parseJSON(exp[0]);
		features = $.parseJSON(geoms[0]).features;

		//read hash from URL and direct to correct expedition
		//if urlParameters !== null {
			//go to specific expedition
			//call InterfaceController()
		//} else {
		//goto landing page
			buildLandingView();
		//}

	});

	this.changeViewingMode = function() {
		//do stuff needed to transition from one mode to another
		  // change URL
		  // delete stuff from map
		  // destroy interface elements

		  //call constructors for new viewingMode
	};

	var buildLandingView = function() {
		console.log("building LandingView");
		InterfaceController.buildLandingView();
		MapController.buildLandingView(features);

		InterfaceController.registerMapEvents(MapController);
		MapController.registerInterfaceEvents(InterfaceController);

	};

	this.loadExpedition = function(expedition) {
		currentExpedition = expedition;
		//destroy current expedition if in viewing mode
		//destroy expeditions if on landing page

		//call InterfaceController
		//call MapController
		//register events in both
	};
};

module.exports = ExpeditionController;<commit_msg>add parseJSON check<commit_after>var ExpeditionController = function() {
	//var loadData = require('data-loader.js');
	//this.currentExpedition;
	//this.viewingMode; //landing, expedition

	this.expeditions = [];
	var features;
	var that = this;

	var IC = require('./interface-controller.js');
	var InterfaceController = new IC(this);
	var MC = require('./map-controller.js');
	var MapController = new MC();

	$.when($.get('dist/data/expeditions.json'), $.get('dist/data/expeditions-geometries.json'))
	.done(function(exp, geoms) {

		if (typeof exp[0] === "string") {
			that.expeditions = $.parseJSON(exp[0]);
			features = $.parseJSON(geoms[0]).features;
		} else {
			that.expeditions = exp[0];
			features = $.parseJSON(geoms[0]).features;
		}

		//read hash from URL and direct to correct expedition
		//if urlParameters !== null {
			//go to specific expedition
			//call InterfaceController()
		//} else {
		//goto landing page
			buildLandingView();
		//}

	});

	this.changeViewingMode = function() {
		//do stuff needed to transition from one mode to another
		  // change URL
		  // delete stuff from map
		  // destroy interface elements

		  //call constructors for new viewingMode
	};

	var buildLandingView = function() {
		console.log("building LandingView");
		InterfaceController.buildLandingView();
		MapController.buildLandingView(features);

		InterfaceController.registerMapEvents(MapController);
		MapController.registerInterfaceEvents(InterfaceController);

	};

	this.loadExpedition = function(expedition) {
		currentExpedition = expedition;
		//destroy current expedition if in viewing mode
		//destroy expeditions if on landing page

		//call InterfaceController
		//call MapController
		//register events in both
	};
};

module.exports = ExpeditionController;<|endoftext|>


<commit_before>module.exports = {};

const moment = require('moment');
require('moment-countdown');

// Define the Start & End Date
const eventStartDate = '2016-06-22 18:00:00 GMT-0400';
const eventEndDate = '2016-06-22 20:00:00 GMT-0400';

// Define when to switch content
const beforeEvent = moment().isBefore(eventStartDate);
const duringEvent = moment().isAfter(eventStartDate) && moment().isBefore(eventEndDate);

// Set Clock Value
const setClockNumbers = (date) => {
    if (moment(date).isValid()) {
        const countdown = moment().countdown(date);
        $('.countdown-text.days').text(`${countdown.days} Days`);
        $('.countdown-text.hours').text(`${countdown.hours} Hours`);
        $('.countdown-text.minutes').text(`${countdown.minutes} Minutes`);
        $('.countdown-text.seconds').text(`${countdown.seconds} Seconds`);
    } else {
        $('.countdown-text').each(function() {
            $(this).text(date);
        });
    }
};

const setClockHands = (date) => {
    const r = (el, deg) => {
        el.setAttribute('transform', `rotate(${deg} 50 50)`);
    };
    const countdown = moment().countdown(date);
    if (moment(date).isValid()) {
        r(document.getElementById('day'), 12 * countdown.days);
        r(document.getElementById('hour'), 30 * (countdown.hours % 12) + countdown.minutes / 2);
        r(document.getElementById('min'), 6 * countdown.minutes);
        r(document.getElementById('sec'), 6 * countdown.seconds);
    } else {

        // spin the hands
    }
};

const setCopy = (text) => {
    if (!$('.event-copy').html())
        $('.event-copy').append(text);
};

setInterval(function() {
    let clockVal;
    let eventCopy;

    if(beforeEvent) {
        clockVal = eventStartDate;
        eventCopy = `The next #crappyhour is June 22nd, 6-8pm at <a href="">One Mile House</a>.`;
    } else if(duringEvent) {
        clockVal = eventEndDate;
        eventCopy = `#crappyhour is happening right now until 8pm, at ` +
        `<a href="">One Mile House</a>! If you hurry, you might be ` +
        `able to make it. Sign up below for a reminder about next month's event.`;
    } else {
        clockVal = '88:88';
        eventCopy = `The next #crappyhour <a href="#">can't come soon enough</a>.`;
    }

    setClockNumbers(clockVal);
    setClockHands(clockVal);
    setCopy(eventCopy);
}, 1000);
<commit_msg>move countdown assignement inside validity check for setClockHands<commit_after>module.exports = {};

const moment = require('moment');
require('moment-countdown');

// Define the Start & End Date
const eventStartDate = '2016-06-22 18:00:00 GMT-0400';
const eventEndDate = '2016-06-22 20:00:00 GMT-0400';

// Define when to switch content
const beforeEvent = moment().isBefore(eventStartDate);
const duringEvent = moment().isAfter(eventStartDate) && moment().isBefore(eventEndDate);

// Set Clock Value
const setClockNumbers = (date) => {
    if (moment(date).isValid()) {
        const countdown = moment().countdown(date);
        $('.countdown-text.days').text(`${countdown.days} Days`);
        $('.countdown-text.hours').text(`${countdown.hours} Hours`);
        $('.countdown-text.minutes').text(`${countdown.minutes} Minutes`);
        $('.countdown-text.seconds').text(`${countdown.seconds} Seconds`);
    } else {
        $('.countdown-text').each(function() {
            $(this).text(date);
        });
    }
};

const setClockHands = (date) => {
    const r = (el, deg) => {
        el.setAttribute('transform', `rotate(${deg} 50 50)`);
    };
    if (moment(date).isValid()) {
        const countdown = moment().countdown(date);
        r(document.getElementById('day'), 12 * countdown.days);
        r(document.getElementById('hour'), 30 * (countdown.hours % 12) + countdown.minutes / 2);
        r(document.getElementById('min'), 6 * countdown.minutes);
        r(document.getElementById('sec'), 6 * countdown.seconds);
    } else {

        // spin the hands
    }
};

const setCopy = (text) => {
    if (!$('.event-copy').html())
        $('.event-copy').append(text);
};

setInterval(function() {
    let clockVal;
    let eventCopy;

    if(beforeEvent) {
        clockVal = eventStartDate;
        eventCopy = `The next #crappyhour is June 22nd, 6-8pm at <a href="">One Mile House</a>.`;
    } else if(duringEvent) {
        clockVal = eventEndDate;
        eventCopy = `#crappyhour is happening right now until 8pm, at ` +
        `<a href="">One Mile House</a>! If you hurry, you might be ` +
        `able to make it. Sign up below for a reminder about next month's event.`;
    } else {
        clockVal = '88:88';
        eventCopy = `The next #crappyhour <a href="#">can't come soon enough</a>.`;
    }

    setClockNumbers(clockVal);
    setClockHands(clockVal);
    setCopy(eventCopy);
}, 1000);
<|endoftext|>


<commit_before>/* global RTCPeerConnection */
// jshint unused:false

var cordova = window.cordova;

// Expose WebRTC Globals
if (cordova && cordova.plugins && cordova.plugins.iosrtc) {
  cordova.plugins.iosrtc.registerGlobals();
  //cordova.plugins.iosrtc.debug.enable('*', true);
  cordova.plugins.iosrtc.turnOnSpeaker(true);
  cordova.plugins.iosrtc.requestPermission(true, true, function (result) {
    console.log('requestPermission.result', result);
  });
}

//
// Container
//

document.body.innerHTML = "";
var appContainer = document.body;

//
// getUserMedia
//

var localStream;
var localVideoEl;
function TestGetUserMedia() {

  // Note: Support for Multiple TestRTCPeerConnection calls
  if (localStream) {

    // Close local Stream if already connected
    localStream.stop();

    // Clear local video element
    if (localVideoEl.srcObject) {
      localVideoEl.srcObject = null;
      appContainer.removeChild(localVideoEl);
    }
  }

  localVideoEl = document.createElement('video');
  localVideoEl.setAttribute('autoplay', 'autoplay');
  localVideoEl.setAttribute('playsinline', 'playsinline');

  // Note: Test CSS positioning
  localVideoEl.style.backgroundColor = 'purple'; // Cause zIndex - 1 failure
  localVideoEl.style.position = 'absolute';
  localVideoEl.style.top = 0;
  localVideoEl.style.left = 0;
  localVideoEl.style.width = "100px";
  localVideoEl.style.height = "100px";
  localVideoEl.style.transform = "scaleX(-1)";
  appContainer.appendChild(localVideoEl);

  navigator.mediaDevices.enumerateDevices().then(function (devices) {
      console.log('getMediaDevices.ok', devices);
      devices.forEach(function (device, idx) {
        console.log('getMediaDevices.devices', idx, device.label, device.kind, device.deviceId);
      });
  }, function (err) {
      console.log('getMediaDevices.err', err);
  });

  return navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
    /*
    video: {
      // Test Back Camera
      //deviceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      //sourceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      deviceId: {
        exact: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      }
    },
    audio: {
      exact: 'Built-In Microphone'
    }*/
  }).then(function (stream) {

    console.log('getUserMedia.stream', stream);
    console.log('getUserMedia.stream.getTracks', stream.getTracks());

    // Note: Expose for debug
    localStream = stream;

    // Attach local stream to video element
    localVideoEl.srcObject = localStream;

    // Test HTML over Video element
    TestPluginMediaStreamRenderer(localVideoEl);

    return localStream;

  }).catch(function (err) {
    console.log('getUserMediaError', err, err.stack);
  });
}

var useAnimateVideo = false;
function TestPluginMediaStreamRenderer(localVideoEl) {

  // Animate video position
  var currentPosition = {
    x: 0,
    y: 0
  };

  var animateTimer;
  function animateVideo() {

    currentPosition.x = currentPosition.x < (window.innerWidth - parseInt(localVideoEl.style.width, 10)) ? currentPosition.x + 1 : 0;
    currentPosition.y = currentPosition.y < (window.innerHeight - parseInt(localVideoEl.style.height, 10)) ? currentPosition.y + 1 : 0;

    localVideoEl.style.top = currentPosition.y + 'px';
    localVideoEl.style.left = currentPosition.x + 'px';

    if (cordova && cordova.plugins && cordova.plugins.iosrtc) {
      //cordova.plugins.iosrtc.refreshVideos();
    }

    return (animateTimer = requestAnimationFrame(animateVideo));
  }

  if (useAnimateVideo) {
    animateTimer = animateVideo();
  }

  //
  // Test Video behind Element
  //

  // Note: Test HTML over video requiring Z-Index -1 and transparent <html> and <body>
  document.body.style.background = "transparent";
  document.documentElement.style.background = "transparent";
  localVideoEl.style.backgroundColor = '';
  localVideoEl.style.zIndex = -1;

  var overEl = document.createElement('button');
  overEl.style.backgroundColor = 'red';
  overEl.style.position = 'absolute';
  overEl.style.left = 0;
  overEl.style.top = 0;
  overEl.style.width = "100px";
  overEl.style.height = "100px";

  overEl.addEventListener('click', function () {
    overEl.style.backgroundColor = overEl.style.backgroundColor === 'red' ? 'green' : 'red';

    if (overEl.style.backgroundColor === 'red') {
      animateTimer = animateVideo();
    } else {
      cancelAnimationFrame(animateTimer);
    }
  });

  appContainer.appendChild(overEl);

  overEl.style.left = ((window.innerWidth / 2)  - parseInt(overEl.style.width, 10)) + 'px';
  overEl.style.top  = ((window.innerHeight / 2) - parseInt(overEl.style.height, 10)) + 'px';

}

//
// Test RTCPeerConnection
//

var peerConnectionConfig = {
    iceServers: [
      {
        urls: "stun:stun.stunprotocol.org"
      }
    ]
};
var pc1 = new RTCPeerConnection(peerConnectionConfig),
    pc2 = new RTCPeerConnection(peerConnectionConfig);

var sendChannel, receiveChannel;
function TestPeerDataChannel() {
  sendChannel = pc1.createDataChannel("sendChannel");

  sendChannel.addEventListener('message',  function (event) {
    console.log('sendChannel.message', event, event.data);
  });

  sendChannel.addEventListener('open', function (event) {
      console.log('sendChannel.open', event);
      sendChannel.send("data message Date: " + new Date());
  });

  sendChannel.addEventListener('close', function (event) {
      console.log('sendChannel.close', event);
  });

  pc2.addEventListener('datachannel', function (event) {
    receiveChannel = event.channel;
    receiveChannel.addEventListener('message',  function (event) {
      console.log('receiveChannel.message', event, event.data);
    });
    receiveChannel.addEventListener('open',  function (event) {
      console.log('receiveChannel.open', event);
    });
    receiveChannel.addEventListener('close',  function (event) {
      console.log('receiveChannel.close', event);
    });
  });
}

var peerVideoEl;
var peerStream;
function TestRTCPeerConnection(localStream) {

  // Note: Support for Multiple TestRTCPeerConnection calls
  if (peerStream) {

    // Close peer Stream if already connected
    peerStream.stop();

    // Clear peer video element
    if (peerVideoEl.srcObject) {
      peerVideoEl.srcObject = null;
      appContainer.removeChild(peerVideoEl);
    }

    // Disconnect peer
    if (pc1.iceConnectionState === 'completed') {
      pc1.close();

      // Current you cannot reuse previous RTCPeerConnection
      pc1 = new RTCPeerConnection();
      pc2 = new RTCPeerConnection();
    }
  }

  // Note: Deprecated but supported
  //pc1.addStream(localStream);

  // Note: Deprecated Test removeStream
  // pc1.removeStream(pc1.getLocalStreams()[0])

  // Note: Chrome Version 77.0.3865.90 (Official Build) still
  // require to use addStream without webrtc-adapter.
  localStream.getTracks().forEach(function (track) {
    console.log('addTrack', track);
    pc1.addTrack(track);
  });

  function onAddIceCandidate(pc, can) {
    console.log('addIceCandidate', pc, can);
    return can && pc.addIceCandidate(can).catch(function (err) {
      console.log('addIceCandidateError', err);
    });
  }

  pc1.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc2, e.candidate);
  });

  pc2.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc1, e.candidate);
  });

  pc2.addEventListener('track', function (e) {
    console.log('pc2.track', e);
  });

  pc2.addEventListener('removetrack', function (e) {
    console.log('pc2.removeTrack', e);
  });

  pc2.addEventListener('addstream', function (e) {
    console.log('pc2.addStream', e);
    peerVideoEl = document.createElement('video');
    peerVideoEl.setAttribute('autoplay', 'autoplay');
    peerVideoEl.setAttribute('playsinline', 'playsinline');

    // Note: Test Object-fix
    peerVideoEl.style.objectFit = "cover";

    // Note: Test CSS positioning
    peerVideoEl.style.backgroundColor = 'blue';
    peerVideoEl.style.position = 'fixed';
    peerVideoEl.style.width = "100px";
    peerVideoEl.style.height = "100px";
    peerVideoEl.style.top = 0;
    peerVideoEl.style.left = (window.innerWidth - parseInt(peerVideoEl.style.width, 10)) + 'px';
    appContainer.appendChild(peerVideoEl);

    // Note: Expose for debug
    peerStream = e.stream;

    // Attach peer stream to video element
    peerVideoEl.srcObject = peerStream;
  });

  pc1.addEventListener('iceconnectionstatechange', function (e) {
    console.log('pc1.iceConnectionState', e, pc1.iceConnectionState);

    if (pc1.iceConnectionState === 'completed') {
      console.log('pc1.getSenders', pc1.getSenders());
      console.log('pc2.getReceivers', pc2.getReceivers());
    }
  });

  pc1.addEventListener('icegatheringstatechange', function (e) {
    console.log('pc1.iceGatheringStateChange', e);
  });

  // https://stackoverflow.com/questions/48963787/failed-to-set-local-answer-sdp-called-in-wrong-state-kstable
  // https://bugs.chromium.org/p/chromium/issues/detail?id=740501
  var isNegotiating = false;
  pc1.addEventListener('signalingstatechange', function (e) {
    console.log('pc1.signalingstatechange',  e);
    isNegotiating = (pc1.signalingState !== "stable");
  });

  pc1.addEventListener('negotiationneeded', function (e) {

    if (isNegotiating) {
      // Should not trigger on iosrtc cause of PluginRTCPeerConnection.swift fix
      console.log("pc1.negotiatioNeeded", "SKIP nested negotiations");
      return;
    }
    isNegotiating = true;

    console.log('pc1.negotiatioNeeded', e);

    return pc1.createOffer().then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc1.setLocalDescription', desc);
      return pc1.setLocalDescription(desc);
    }).then(function () {
      var desc = {
        type: pc1.localDescription.type,
        sdp: pc1.localDescription.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setRemoteDescription(desc);
    }).then(function () {
      console.log('pc2.createAnswer');
      return pc2.createAnswer();
    }).then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setLocalDescription(d);
    }).then(function () {
      var desc = {
        type: pc2.localDescription.type,
        sdp: pc2.localDescription.sdp
      };
      console.log('pc1.setRemoteDescription', desc);
      return pc1.setRemoteDescription(desc);
    }).then(function () {
      TestMediaRenderCatpure(peerVideoEl);
      TestMediaRenderCatpure(localVideoEl);
      TestPeerDataChannel();
    }).catch(function (err) {
      console.log('pc1.createOfferError', err);
    });
  });
}

var canvasEl;
function TestMediaRenderCatpure(videoEl) {

  if (!canvasEl) {
    canvasEl = document.createElement('canvas');
  }

  var ctx = canvasEl.getContext("2d");
  canvasEl.style.position = 'absolute';
  canvasEl.style.left = 0;
  canvasEl.style.bottom = 0;
  appContainer.appendChild(canvasEl);
  var image = new Image();
  image.addEventListener('load', function() {
    canvasEl.width = image.width;
    canvasEl.height = image.height;
    ctx.drawImage(image, 0, 0);
  });
  videoEl.render.save(function (data) {
    image.src = "data:image/jpg;base64," + data;
  });
}

var testMediaRenderCatpureAnimateFrame;
function TestMediaRenderCatpureAnimate() {
  TestMediaRenderCatpure(peerVideoEl);
  testMediaRenderCatpureAnimateFrame = requestAnimationFrame(TestMediaRenderCatpureAnimate);
}

// Disabled to avoid confusion with remoteStream
var cloneStream;
var cloneVideoEl;
function TestPluginMediaStreamClone(mediaStream) {
  cloneVideoEl = document.createElement('video');
  cloneVideoEl.setAttribute('autoplay', 'autoplay');
  cloneVideoEl.setAttribute('playsinline', 'playsinline');
  cloneVideoEl.style.backgroundColor = 'purple';
  cloneVideoEl.style.position = 'absolute';
  cloneVideoEl.style.bottom = 0;
  cloneVideoEl.style.left = 0;
  cloneVideoEl.style.width = "100px";
  cloneVideoEl.style.height = "100px";
  cloneVideoEl.style.transform = "scaleX(-1)";

  cloneStream = mediaStream.clone();
  cloneVideoEl.srcObject = cloneStream;

  appContainer.appendChild(cloneVideoEl);
}

var useWebRTCAdapter = false;

// Expose webrtc-adapter
if (useWebRTCAdapter && typeof window.adapter === 'undefined') {

    // load adapter.js
    var version = 'latest';
    var script = document.createElement("script");
    script.type = "text/javascript";
    //script.src = "adapter-latest.js";
    script.src = "https://webrtc.github.io/adapter/adapter-" + version + ".js";
    script.async = false;
    document.getElementsByTagName("head")[0].appendChild(script);
    script.addEventListener('load', function () {
      console.log('useWebRTCAdapter.loaded', script.src);
      TestGetUserMedia().then(function (localStream) {
        TestRTCPeerConnection(localStream);
      });
    });
} else {
  TestGetUserMedia().then(function (localStream) {
    TestRTCPeerConnection(localStream);
  });
}

<commit_msg>Update renderer-and-libwebrtc-tests.js<commit_after>/* global RTCPeerConnection */
// jshint unused:false

var cordova = window.cordova;

// Expose WebRTC Globals
if (cordova && cordova.plugins && cordova.plugins.iosrtc) {
  cordova.plugins.iosrtc.registerGlobals();
  //cordova.plugins.iosrtc.debug.enable('*', true);
  cordova.plugins.iosrtc.turnOnSpeaker(true);
  cordova.plugins.iosrtc.requestPermission(true, true, function (result) {
    console.log('requestPermission.result', result);
  });
}

//
// Container
//

document.body.innerHTML = "";
var appContainer = document.body;

//
// getUserMedia
//

var localStream;
var localVideoEl;
function TestGetUserMedia() {

  // Note: Support for Multiple TestRTCPeerConnection calls
  if (localStream) {

    // Close local Stream if already connected
    localStream.stop();

    // Clear local video element
    if (localVideoEl.srcObject) {
      localVideoEl.srcObject = null;
      appContainer.removeChild(localVideoEl);
    }
  }

  localVideoEl = document.createElement('video');
  localVideoEl.setAttribute('autoplay', 'autoplay');
  localVideoEl.setAttribute('playsinline', 'playsinline');

  // Note: Test CSS positioning
  localVideoEl.style.backgroundColor = 'purple'; // Cause zIndex - 1 failure
  localVideoEl.style.position = 'absolute';
  localVideoEl.style.top = 0;
  localVideoEl.style.left = 0;
  localVideoEl.style.width = "100px";
  localVideoEl.style.height = "100px";
  localVideoEl.style.transform = "scaleX(-1)";
  appContainer.appendChild(localVideoEl);

  navigator.mediaDevices.enumerateDevices().then(function (devices) {
      console.log('getMediaDevices.ok', devices);
      devices.forEach(function (device, idx) {
        console.log('getMediaDevices.devices', idx, device.label, device.kind, device.deviceId);
      });
  }, function (err) {
      console.log('getMediaDevices.err', err);
  });

  return navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
    /*
    video: {
      // Test Back Camera
      //deviceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      //sourceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      deviceId: {
        exact: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      }
    },
    audio: {
      exact: 'Built-In Microphone'
    }*/
  }).then(function (stream) {

    console.log('getUserMedia.stream', stream);
    console.log('getUserMedia.stream.getTracks', stream.getTracks());

    // Note: Expose for debug
    localStream = stream;

    // Attach local stream to video element
    localVideoEl.srcObject = localStream;

    // Test HTML over Video element
    TestPluginMediaStreamRenderer(localVideoEl);

    return localStream;

  }).catch(function (err) {
    console.log('getUserMediaError', err, err.stack);
  });
}

var useAnimateVideo = false;
function TestPluginMediaStreamRenderer(localVideoEl) {

  // Animate video position
  var currentPosition = {
    x: 0,
    y: 0
  };

  var animateTimer;
  function animateVideo() {

    currentPosition.x = currentPosition.x < (window.innerWidth - parseInt(localVideoEl.style.width, 10)) ? currentPosition.x + 1 : 0;
    currentPosition.y = currentPosition.y < (window.innerHeight - parseInt(localVideoEl.style.height, 10)) ? currentPosition.y + 1 : 0;

    localVideoEl.style.top = currentPosition.y + 'px';
    localVideoEl.style.left = currentPosition.x + 'px';

    if (cordova && cordova.plugins && cordova.plugins.iosrtc) {
      //cordova.plugins.iosrtc.refreshVideos();
    }

    return (animateTimer = requestAnimationFrame(animateVideo));
  }

  if (useAnimateVideo) {
    animateTimer = animateVideo();
  }

  //
  // Test Video behind Element
  //

  // Note: Test HTML over video requiring Z-Index -1 and transparent <html> and <body>
  document.body.style.background = "transparent";
  document.documentElement.style.background = "transparent";
  localVideoEl.style.backgroundColor = '';
  localVideoEl.style.zIndex = -1;

  var overEl = document.createElement('button');
  overEl.style.backgroundColor = 'red';
  overEl.style.position = 'absolute';
  overEl.style.left = 0;
  overEl.style.top = 0;
  overEl.style.width = "100px";
  overEl.style.height = "100px";

  overEl.addEventListener('click', function () {
    overEl.style.backgroundColor = overEl.style.backgroundColor === 'red' ? 'green' : 'red';

    if (overEl.style.backgroundColor === 'red') {
      animateTimer = animateVideo();
    } else {
      cancelAnimationFrame(animateTimer);
    }
  });

  appContainer.appendChild(overEl);

  overEl.style.left = ((window.innerWidth / 2)  - parseInt(overEl.style.width, 10)) + 'px';
  overEl.style.top  = ((window.innerHeight / 2) - parseInt(overEl.style.height, 10)) + 'px';

}

//
// Test RTCPeerConnection
//

var peerConnectionConfig = {
    offerToReceiveVideo: true,
    //iceTransportPolicy: 'relay',
    sdpSemantics: 'unified-plan',
    offerToReceiveAudio: true,
    //sdpSemantics: 'plan-b',
    //bundlePolicy: 'max-compat',
    //rtcpMuxPolicy: 'negotiate',
    iceServers: [
        {
            url: "stun:stun.stunprotocol.org"
        }
    ]
};
var pc1 = new RTCPeerConnection(peerConnectionConfig),
    pc2 = new RTCPeerConnection(peerConnectionConfig);

var sendChannel, receiveChannel;
function TestPeerDataChannel() {
  sendChannel = pc1.createDataChannel("sendChannel");

  sendChannel.addEventListener('message',  function (event) {
    console.log('sendChannel.message', event, event.data);
  });

  sendChannel.addEventListener('open', function (event) {
      console.log('sendChannel.open', event);
      sendChannel.send("data message Date: " + new Date());
  });

  sendChannel.addEventListener('close', function (event) {
      console.log('sendChannel.close', event);
  });

  pc2.addEventListener('datachannel', function (event) {
    receiveChannel = event.channel;
    receiveChannel.addEventListener('message',  function (event) {
      console.log('receiveChannel.message', event, event.data);
    });
    receiveChannel.addEventListener('open',  function (event) {
      console.log('receiveChannel.open', event);
    });
    receiveChannel.addEventListener('close',  function (event) {
      console.log('receiveChannel.close', event);
    });
  });
}

var peerVideoEl;
var peerStream;
function TestRTCPeerConnection(localStream) {

  // Note: Support for Multiple TestRTCPeerConnection calls
  if (peerStream) {

    // Close peer Stream if already connected
    peerStream.stop();

    // Clear peer video element
    if (peerVideoEl.srcObject) {
      peerVideoEl.srcObject = null;
      appContainer.removeChild(peerVideoEl);
    }

    // Disconnect peer
    if (pc1.iceConnectionState === 'completed') {
      pc1.close();

      // Current you cannot reuse previous RTCPeerConnection
      pc1 = new RTCPeerConnection();
      pc2 = new RTCPeerConnection();
    }
  }

  // Note: Deprecated but supported
  //pc1.addStream(localStream);

  // Note: Deprecated Test removeStream
  // pc1.removeStream(pc1.getLocalStreams()[0])

  // Note: Chrome Version 77.0.3865.90 (Official Build) still
  // require to use addStream without webrtc-adapter.
  localStream.getTracks().forEach(function (track) {
    console.log('addTrack', track);
    pc1.addTrack(track);
  });

  function onAddIceCandidate(pc, can) {
    console.log('addIceCandidate', pc, can);
    return can && pc.addIceCandidate(can).catch(function (err) {
      console.log('addIceCandidateError', err);
    });
  }

  pc1.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc2, e.candidate);
  });

  pc2.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc1, e.candidate);
  });

  pc2.addEventListener('track', function (e) {
    console.log('pc2.track', e);
  });

  pc2.addEventListener('removetrack', function (e) {
    console.log('pc2.removeTrack', e);
  });

  pc2.addEventListener('addstream', function (e) {
    console.log('pc2.addStream', e);
    peerVideoEl = document.createElement('video');
    peerVideoEl.setAttribute('autoplay', 'autoplay');
    peerVideoEl.setAttribute('playsinline', 'playsinline');

    // Note: Test Object-fix
    peerVideoEl.style.objectFit = "cover";

    // Note: Test CSS positioning
    peerVideoEl.style.backgroundColor = 'blue';
    peerVideoEl.style.position = 'fixed';
    peerVideoEl.style.width = "100px";
    peerVideoEl.style.height = "100px";
    peerVideoEl.style.top = 0;
    peerVideoEl.style.left = (window.innerWidth - parseInt(peerVideoEl.style.width, 10)) + 'px';
    appContainer.appendChild(peerVideoEl);

    // Note: Expose for debug
    peerStream = e.stream;

    // Attach peer stream to video element
    peerVideoEl.srcObject = peerStream;
  });

  pc1.addEventListener('iceconnectionstatechange', function (e) {
    console.log('pc1.iceConnectionState', e, pc1.iceConnectionState);

    if (pc1.iceConnectionState === 'completed') {
      console.log('pc1.getSenders', pc1.getSenders());
      console.log('pc2.getReceivers', pc2.getReceivers());
    }
  });

  pc1.addEventListener('icegatheringstatechange', function (e) {
    console.log('pc1.iceGatheringStateChange', e);
  });

  // https://stackoverflow.com/questions/48963787/failed-to-set-local-answer-sdp-called-in-wrong-state-kstable
  // https://bugs.chromium.org/p/chromium/issues/detail?id=740501
  var isNegotiating = false;
  pc1.addEventListener('signalingstatechange', function (e) {
    console.log('pc1.signalingstatechange',  e);
    isNegotiating = (pc1.signalingState !== "stable");
  });

  pc1.addEventListener('negotiationneeded', function (e) {

    if (isNegotiating) {
      // Should not trigger on iosrtc cause of PluginRTCPeerConnection.swift fix
      console.log("pc1.negotiatioNeeded", "SKIP nested negotiations");
      return;
    }
    isNegotiating = true;

    console.log('pc1.negotiatioNeeded', e);

    return pc1.createOffer().then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc1.setLocalDescription', desc);
      return pc1.setLocalDescription(desc);
    }).then(function () {
      var desc = {
        type: pc1.localDescription.type,
        sdp: pc1.localDescription.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setRemoteDescription(desc);
    }).then(function () {
      console.log('pc2.createAnswer');
      return pc2.createAnswer();
    }).then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setLocalDescription(d);
    }).then(function () {
      var desc = {
        type: pc2.localDescription.type,
        sdp: pc2.localDescription.sdp
      };
      console.log('pc1.setRemoteDescription', desc);
      return pc1.setRemoteDescription(desc);
    }).then(function () {
      TestMediaRenderCatpure(peerVideoEl);
      TestMediaRenderCatpure(localVideoEl);
      TestPeerDataChannel();
    }).catch(function (err) {
      console.log('pc1.createOfferError', err);
    });
  });
}

var canvasEl;
function TestMediaRenderCatpure(videoEl) {

  if (!canvasEl) {
    canvasEl = document.createElement('canvas');
  }

  var ctx = canvasEl.getContext("2d");
  canvasEl.style.position = 'absolute';
  canvasEl.style.left = 0;
  canvasEl.style.bottom = 0;
  appContainer.appendChild(canvasEl);
  var image = new Image();
  image.addEventListener('load', function() {
    canvasEl.width = image.width;
    canvasEl.height = image.height;
    ctx.drawImage(image, 0, 0);
  });
  videoEl.render.save(function (data) {
    image.src = "data:image/jpg;base64," + data;
  });
}

var testMediaRenderCatpureAnimateFrame;
function TestMediaRenderCatpureAnimate() {
  TestMediaRenderCatpure(peerVideoEl);
  testMediaRenderCatpureAnimateFrame = requestAnimationFrame(TestMediaRenderCatpureAnimate);
}

// Disabled to avoid confusion with remoteStream
var cloneStream;
var cloneVideoEl;
function TestPluginMediaStreamClone(mediaStream) {
  cloneVideoEl = document.createElement('video');
  cloneVideoEl.setAttribute('autoplay', 'autoplay');
  cloneVideoEl.setAttribute('playsinline', 'playsinline');
  cloneVideoEl.style.backgroundColor = 'purple';
  cloneVideoEl.style.position = 'absolute';
  cloneVideoEl.style.bottom = 0;
  cloneVideoEl.style.left = 0;
  cloneVideoEl.style.width = "100px";
  cloneVideoEl.style.height = "100px";
  cloneVideoEl.style.transform = "scaleX(-1)";

  cloneStream = mediaStream.clone();
  cloneVideoEl.srcObject = cloneStream;

  appContainer.appendChild(cloneVideoEl);
}

var useWebRTCAdapter = false;

// Expose webrtc-adapter
if (useWebRTCAdapter && typeof window.adapter === 'undefined') {

    // load adapter.js
    var version = 'latest';
    var script = document.createElement("script");
    script.type = "text/javascript";
    //script.src = "adapter-latest.js";
    script.src = "https://webrtc.github.io/adapter/adapter-" + version + ".js";
    script.async = false;
    document.getElementsByTagName("head")[0].appendChild(script);
    script.addEventListener('load', function () {
      console.log('useWebRTCAdapter.loaded', script.src);
      TestGetUserMedia().then(function (localStream) {
        TestRTCPeerConnection(localStream);
      });
    });
} else {
  TestGetUserMedia().then(function (localStream) {
    TestRTCPeerConnection(localStream);
  });
}

<|endoftext|>


<commit_before>(function() {

  function Heidelberg(el, options) {

    // Allow developer to omit new when instantiating
    if (!(this instanceof Heidelberg)) {
      if (el.length) {
        Array.prototype.forEach.call(el, function(n) {
          return new Heidelberg(n, options);
        });
      } else {
        return new Heidelberg(el, options);
      }
    }

    // Check for Modernizr, if not available assume modern browser
    if(!Modernizr) {
      window.Modernizr = {
        csstransforms3d: true
      };
    }

    // OPTIONS
    var defaults = {
      nextButton: $(),
      previousButton: $(),
      hasSpreads: false,
      canClose: false,
      arrowKeys: true,
      concurrentAnimations: null,
      onPageTurn: function() {},
      onSpreadSetup: function() {}
    };

    this.options = $.extend({}, defaults, options);

    !this.options.concurrentAnimations || this.options.concurrentAnimations++;

    // PRIVATE VARIABLES
    // Main element always a jQuery object
    this.el = (el instanceof jQuery) ? el : $(el);

    // RUN
    this.init();

  };

  Heidelberg.prototype.init = function() {

    var el       = this.el;
    var options  = this.options;

    var setReady = function() {
      el.addClass('is-ready');
    }

    if(options.hasSpreads) {
      this.setupSpreads(function() {
        setReady();
      });
    } else {
      setReady();
    }

    var els = {
      pages:      $('.Heidelberg-Page', el),
      pagesLeft:  options.canClose ? $('.Heidelberg-Page:nth-child(2n)', el) : $('.Heidelberg-Page:nth-child(2n+1)', el),
      pagesRight: options.canClose ? $('.Heidelberg-Page:nth-child(2n+1)', el) : $('.Heidelberg-Page:nth-child(2n)', el),
    };

    if(!options.canClose) {
      var coverEl = $('<div />').addClass('Heidelberg-HiddenCover');
      el.prepend(coverEl.clone());
      el.append(coverEl.clone());
      els.pages.eq(0).add(els.pages.eq(1)).addClass('is-active');
    }
    else {
      els.pages.eq(0).addClass('is-active');
    }

    els.previousTrigger = els.pagesLeft.add(options.previousButton);
    els.nextTrigger     = els.pagesRight.add(options.nextButton);

    els.previousTrigger.on('click', function() {
      this.turnPage('back');
    }.bind(this));

    els.nextTrigger.on('click', function() {
      this.turnPage('forwards');
    }.bind(this));

    if(typeof Hammer !== 'undefined') {
      opts = {
        drag_min_distance: 5,
        swipe_velocity: 0.3
      }
      Hammer(els.pagesLeft, opts).on("dragright", function(evt) {
        this.turnPage('back');
        evt.gesture.stopDetect();
      }.bind(this));

      Hammer(els.pagesRight, opts).on("dragleft", function(evt) {
        this.turnPage('forwards');
        evt.gesture.stopDetect();
      }.bind(this));
    }

    var forwardsKeycode = 37;
    var backKeycode = 39;

    if((!Modernizr.csstransforms3d)) {
      forwardsKeycode = 39;
      backKeycode = 37;
    }

    if(options.arrowKeys) {
      $(document).keydown(function(e){
        if (e.keyCode == forwardsKeycode) {
          this.turnPage('forwards');
          return false;
        }
        if (e.keyCode == backKeycode) {
          this.turnPage('back');
          return false;
        }
      }.bind(this));
    }
  };

  Heidelberg.prototype.turnPage = function(direction) {

    var el = this.el;
    var els = {};
    var options = this.options;

    els.pages = $('.Heidelberg-Page', el);

    if((els.pages.last().hasClass('is-active') && direction == 'forwards') ||
       (els.pages.first().hasClass('is-active') && direction == 'back') ||
        (options.concurrentAnimations && $('.Heidelberg-Page.is-animating', el).length > options.concurrentAnimations) ||
        ((!Modernizr.preserve3d) && $('.Heidelberg-Page.is-animating', el).length > 2))
    {
      return
    }

    els.isActive       = $('.Heidelberg-Page.is-active', el);
    els.isAnimatingOut = (direction == 'back') ? els.isActive.first() : els.isActive.last();

    $('.Heidelberg-Page.was-active', el).removeClass('was-active');

    if (direction == 'back') {
      els.isAnimatingIn = els.isAnimatingOut.prev();
      els.newActive     = els.isAnimatingIn.add(els.isAnimatingIn.prev());
    }

    if (direction == 'forwards') {
      els.isAnimatingIn = els.isAnimatingOut.next();
      els.newActive     = els.isAnimatingIn.add(els.isAnimatingIn.next());
    }

    els.isActive.removeClass('is-active').addClass('was-active');
    els.newActive.addClass('is-active');

    els.isAnimating = els.isAnimatingIn.add(els.isAnimatingOut);

    if((Modernizr.csstransforms3d)) {
      els.isAnimating.addClass('is-animating');
    }
    els.isAnimating.on('webkittransitionEnd otransitionend mstransitionEnd transitionend', function () {
      els.isAnimating.removeClass('is-animating');
    }.bind(document));

    options.onPageTurn(el, els);

  };

  Heidelberg.prototype.setupSpreads = function(callback) {

    var el      = this.el;
    var options = this.options;

    $('.Heidelberg-Spread', el).each(function() {
      var spreadEl = $(this);
      var pageEl   = $('<div />').addClass('Heidelberg-Page with-Spread').html(spreadEl.clone());
      spreadEl.after(pageEl);
      spreadEl.replaceWith(pageEl.clone());
    });

    options.onSpreadSetup(el);
    if(typeof callback == 'function') {
      callback();
    }
  }

  // expose Heidelberg
  window.Heidelberg = Heidelberg;

})();<commit_msg>Tidy up Modernizr check<commit_after>(function() {

  function Heidelberg(el, options) {

    // Allow developer to omit new when instantiating
    if (!(this instanceof Heidelberg)) {
      if (el.length) {
        Array.prototype.forEach.call(el, function(n) {
          return new Heidelberg(n, options);
        });
      } else {
        return new Heidelberg(el, options);
      }
    }

    // Check for Modernizr, if not available assume modern browser
    window.Modernizr = Modernizr || {csstransforms3d: true};

    // OPTIONS
    var defaults = {
      nextButton: $(),
      previousButton: $(),
      hasSpreads: false,
      canClose: false,
      arrowKeys: true,
      concurrentAnimations: null,
      onPageTurn: function() {},
      onSpreadSetup: function() {}
    };

    this.options = $.extend({}, defaults, options);

    !this.options.concurrentAnimations || this.options.concurrentAnimations++;

    // PRIVATE VARIABLES
    // Main element always a jQuery object
    this.el = (el instanceof jQuery) ? el : $(el);

    // RUN
    this.init();

  };

  Heidelberg.prototype.init = function() {

    var el       = this.el;
    var options  = this.options;

    var setReady = function() {
      el.addClass('is-ready');
    }

    if(options.hasSpreads) {
      this.setupSpreads(function() {
        setReady();
      });
    } else {
      setReady();
    }

    var els = {
      pages:      $('.Heidelberg-Page', el),
      pagesLeft:  options.canClose ? $('.Heidelberg-Page:nth-child(2n)', el) : $('.Heidelberg-Page:nth-child(2n+1)', el),
      pagesRight: options.canClose ? $('.Heidelberg-Page:nth-child(2n+1)', el) : $('.Heidelberg-Page:nth-child(2n)', el),
    };

    if(!options.canClose) {
      var coverEl = $('<div />').addClass('Heidelberg-HiddenCover');
      el.prepend(coverEl.clone());
      el.append(coverEl.clone());
      els.pages.eq(0).add(els.pages.eq(1)).addClass('is-active');
    }
    else {
      els.pages.eq(0).addClass('is-active');
    }

    els.previousTrigger = els.pagesLeft.add(options.previousButton);
    els.nextTrigger     = els.pagesRight.add(options.nextButton);

    els.previousTrigger.on('click', function() {
      this.turnPage('back');
    }.bind(this));

    els.nextTrigger.on('click', function() {
      this.turnPage('forwards');
    }.bind(this));

    if(typeof Hammer !== 'undefined') {
      opts = {
        drag_min_distance: 5,
        swipe_velocity: 0.3
      }
      Hammer(els.pagesLeft, opts).on("dragright", function(evt) {
        this.turnPage('back');
        evt.gesture.stopDetect();
      }.bind(this));

      Hammer(els.pagesRight, opts).on("dragleft", function(evt) {
        this.turnPage('forwards');
        evt.gesture.stopDetect();
      }.bind(this));
    }

    var forwardsKeycode = 37;
    var backKeycode = 39;

    if((!Modernizr.csstransforms3d)) {
      forwardsKeycode = 39;
      backKeycode = 37;
    }

    if(options.arrowKeys) {
      $(document).keydown(function(e){
        if (e.keyCode == forwardsKeycode) {
          this.turnPage('forwards');
          return false;
        }
        if (e.keyCode == backKeycode) {
          this.turnPage('back');
          return false;
        }
      }.bind(this));
    }
  };

  Heidelberg.prototype.turnPage = function(direction) {

    var el = this.el;
    var els = {};
    var options = this.options;

    els.pages = $('.Heidelberg-Page', el);

    if((els.pages.last().hasClass('is-active') && direction == 'forwards') ||
       (els.pages.first().hasClass('is-active') && direction == 'back') ||
        (options.concurrentAnimations && $('.Heidelberg-Page.is-animating', el).length > options.concurrentAnimations) ||
        ((!Modernizr.preserve3d) && $('.Heidelberg-Page.is-animating', el).length > 2))
    {
      return
    }

    els.isActive       = $('.Heidelberg-Page.is-active', el);
    els.isAnimatingOut = (direction == 'back') ? els.isActive.first() : els.isActive.last();

    $('.Heidelberg-Page.was-active', el).removeClass('was-active');

    if (direction == 'back') {
      els.isAnimatingIn = els.isAnimatingOut.prev();
      els.newActive     = els.isAnimatingIn.add(els.isAnimatingIn.prev());
    }

    if (direction == 'forwards') {
      els.isAnimatingIn = els.isAnimatingOut.next();
      els.newActive     = els.isAnimatingIn.add(els.isAnimatingIn.next());
    }

    els.isActive.removeClass('is-active').addClass('was-active');
    els.newActive.addClass('is-active');

    els.isAnimating = els.isAnimatingIn.add(els.isAnimatingOut);

    if((Modernizr.csstransforms3d)) {
      els.isAnimating.addClass('is-animating');
    }
    els.isAnimating.on('webkittransitionEnd otransitionend mstransitionEnd transitionend', function () {
      els.isAnimating.removeClass('is-animating');
    }.bind(document));

    options.onPageTurn(el, els);

  };

  Heidelberg.prototype.setupSpreads = function(callback) {

    var el      = this.el;
    var options = this.options;

    $('.Heidelberg-Spread', el).each(function() {
      var spreadEl = $(this);
      var pageEl   = $('<div />').addClass('Heidelberg-Page with-Spread').html(spreadEl.clone());
      spreadEl.after(pageEl);
      spreadEl.replaceWith(pageEl.clone());
    });

    options.onSpreadSetup(el);
    if(typeof callback == 'function') {
      callback();
    }
  }

  // expose Heidelberg
  window.Heidelberg = Heidelberg;

})();<|endoftext|>


<commit_before>var test = require('tape')

test('sublevel - batch', function (t) {

  require('rimraf').sync('/tmp/test-sublevel')
  var base = require('levelup')('/tmp/test-sublevel')

  var Sublevel = require('../')

  Sublevel(base, '~')

  var a    = base.sublevel('A')
  var b    = base.sublevel('B')

  var keys = ''
  var sum  = 0

  a.batch([
    {key: 'a', value: 1, type: 'put'},
    {key: 'b', value: 2, type: 'put'},
    {key: 'c', value: 3, type: 'put'},
    {key: 'd', value: 4, type: 'put'},
    {key: 'e', value: 5, type: 'put'},
  ], function (err) {
    a.createReadStream()
      .on('data', function (ch) {
        keys += ch.key
        sum += Number(ch.value)
      })
      .on('end', function () {
        t.equal(keys, 'abcde')
        t.equal(sum, 15)
        t.end()
      })
  })

})

test('sublevel - prefixed batches', function (t) {

  require('rimraf').sync('/tmp/test-sublevel2')
  var base = require('levelup')('/tmp/test-sublevel2')

  var Sublevel = require('../')

  Sublevel(base, '~')

  var a    = base.sublevel('A')
  var b    = base.sublevel('B')

  var obj = {}

  base.batch([
    {key: 'a', value: 1, type: 'put'},
    {key: 'b', value: 2, type: 'put', prefix: b},
    {key: 'c', value: 3, type: 'put'},
    {key: 'd', value: 4, type: 'put', prefix: a},
    {key: 'e', value: 5, type: 'put', prefix: base},
  ], function (err) {
    base.createReadStream()
      .on('data', function (ch) {
        obj[ch.key] = ch.value
      })
      .on('end', function () {
        t.deepEqual(obj, {
          'a': '1',
          'c': '3',
          'e': '5',
          '~A~d': '4',
          '~B~b': '2'
        })
        console.log(obj)
        t.end()
      })
  })

})

<commit_msg>update test for batches on subsection<commit_after>var test = require('tape')

test('sublevel - batch', function (t) {

  require('rimraf').sync('/tmp/test-sublevel')
  var base = require('levelup')('/tmp/test-sublevel')

  var Sublevel = require('../')

  Sublevel(base, '~')

  var a    = base.sublevel('A')
  var b    = base.sublevel('B')

  var keys = ''
  var sum  = 0

  a.batch([
    {key: 'a', value: 1, type: 'put'},
    {key: 'b', value: 2, type: 'put'},
    {key: 'c', value: 3, type: 'put'},
    {key: 'd', value: 4, type: 'put'},
    {key: 'e', value: 5, type: 'put'},
  ], function (err) {
    a.createReadStream()
      .on('data', function (ch) {
        keys += ch.key
        sum += Number(ch.value)
      })
      .on('end', function () {
        t.equal(keys, 'abcde')
        t.equal(sum, 15)
        t.end()
      })
  })

})

test('sublevel - prefixed batches', function (t) {

  require('rimraf').sync('/tmp/test-sublevel2')
  var base = require('levelup')('/tmp/test-sublevel2')

  var Sublevel = require('../')

  Sublevel(base, '~')

  var a    = base.sublevel('A')
  var b    = base.sublevel('B')

  var obj = {}

  base.batch([
    {key: 'a', value: 1, type: 'put'},
    {key: 'b', value: 2, type: 'put', prefix: b},
    {key: 'c', value: 3, type: 'put'},
    {key: 'd', value: 4, type: 'put', prefix: a},
    {key: 'e', value: 5, type: 'put', prefix: base},
  ], function (err) {
    base.createReadStream()
      .on('data', function (ch) {
        obj[ch.key] = ch.value
      })
      .on('end', function () {
        t.deepEqual(obj, {
          'a': '1',
          'c': '3',
          'e': '5',
          '~A~d': '4',
          '~B~b': '2'
        })
        console.log(obj)
        t.end()
      })
  })

})

test('sublevel - prefixed batches on subsection', function (t) {

  require('rimraf').sync('/tmp/test-sublevel3')
  var base = require('levelup')('/tmp/test-sublevel3')

  var Sublevel = require('../')

  Sublevel(base, '~')

  var a    = base.sublevel('A')
  var b    = base.sublevel('B')

  var obj = {}

  a.batch([
    {key: 'a', value: 1, type: 'put', prefix: base},
    {key: 'b', value: 2, type: 'put', prefix: b},
    {key: 'c', value: 3, type: 'put', prefix: base},
    {key: 'd', value: 4, type: 'put'},
    {key: 'e', value: 5, type: 'put', prefix: base},
  ], function (err) {
    base.createReadStream()
      .on('data', function (ch) {
        obj[ch.key] = ch.value
      })
      .on('end', function () {
        t.deepEqual(obj, {
          'a': '1',
          'c': '3',
          'e': '5',
          '~A~d': '4',
          '~B~b': '2'
        })
        console.log(obj)
        t.end()
      })
  })

})

<|endoftext|>


<commit_before>var Spaz; if (!Spaz) Spaz = {};

/***********
Spaz.UI
***********/
if (!Spaz.Keyboard) Spaz.Keyboard = {};

Spaz.Keyboard.setShortcuts = function() {
	Spaz.dump("Setting Shortcuts=================================================")
    Spaz.dump("os: " + air.Capabilities['os']);

	var Modkey = 'Meta';

	if (air.Capabilities['os'].search(/Windows/i) != -1) {
		Spaz.dump('THIS IS WINDOWS');
		Modkey = 'Ctrl';
	} else if (air.Capabilities['os'].search(/Linux/i) != -1) { // thx agolna
		Spaz.dump('THIS IS LINUX');
		Modkey = 'Ctrl';
	} else if (air.Capabilities['os'].search(/Mac/i) != -1) {
		Spaz.dump('THIS IS MACOS');
		Modkey = 'Meta';
	}

	Spaz.dump('Modkey is '+Modkey);

	shortcut.add(Modkey+'+T', function() {
		$('#entrybox').focus();
	})

	shortcut.add('F5', function() {
		Spaz.UI.reloadCurrentTab(true);
		Spaz.restartReloadTimer();
	})

	shortcut.add('Shift+F5', function() {
		Spaz.UI.clearCurrentTimeline();
		Spaz.UI.reloadCurrentTab(true);
		Spaz.restartReloadTimer();
	})

	shortcut.add(Modkey+'+Shift+A', function() {
		Spaz.UI.showShortLink();
	});

	shortcut.add(Modkey+'+Shift+M', function() {
		Spaz.UI.markCurrentTimelineAsRead();
	});

	shortcut.add('F1', function() {
		Spaz.UI.showHelp();
	});

	/*
		Added so we can open the preferences folder if the UI is hosed by bad CSS
	*/
	shortcut.add(Modkey+'+Shift+,', function() {
		Spaz.Sys.openAppStorageFolder();
	});

	shortcut.add(Modkey+'+Shift+@', function() {
			Spaz.dump('getting screenname from current selection');
			var screenname = $('div.ui-selected .user-screen-name').text();

			if (screenname) {
				Spaz.dump('username for reply is:'+screenname);
				// var username = '';
				Spaz.UI.prepReply(screenname);
			}
		}, {
			'disable_in_input':false
	});

	// ****************************************
	// tabs shortcuts
	// ****************************************
	shortcut.add(Modkey+'+1', function() {
		Spaz.UI.showTab(0);
	})
	shortcut.add(Modkey+'+2', function() {
		Spaz.UI.showTab(1);
	})
	shortcut.add(Modkey+'+3', function() {
		Spaz.UI.showTab(2);
	})
	shortcut.add(Modkey+'+4', function() {
		Spaz.UI.showTab(3);
	})
	shortcut.add(Modkey+'+5', function() {
		Spaz.UI.showTab(4);
	})
	shortcut.add(Modkey+'+6', function() {
		Spaz.UI.showTab(5);
	})
	shortcut.add(Modkey+'+7', function() {
		Spaz.UI.showTab(6);
	})
	shortcut.add(Modkey+'+,', function() {
		Spaz.UI.showPrefs()
	})

	// ****************************************
	// Keys to navigate timeline
	// ****************************************
	shortcut.add(Modkey+'+down', function() {
		Spaz.Keyboard.move('down', '.reply');
	});
	shortcut.add(Modkey+'+up', function() {
		Spaz.Keyboard.move('up', '.reply');
	});
	shortcut.add(Modkey+'+Shift+down', function() {
		Spaz.Keyboard.move('down', '.dm');
	});
	shortcut.add(Modkey+'+Shift+up', function() {
		Spaz.Keyboard.move('up', '.dm');
	});
	shortcut.add(Modkey+'+End', function() {
		Spaz.Keyboard.move('down', ':last');
	});
	shortcut.add(Modkey+'+Home', function() {
		Spaz.Keyboard.move('up', ':first');
	});
	shortcut.add('Down', function() {
			Spaz.Keyboard.move('down');
		}, {
			'disable_in_input':true
	});
	shortcut.add('Up', function() {
			Spaz.Keyboard.move('up');
		}, {
			'disable_in_input':true
	});
	shortcut.add(Modkey+'+J', function() {
		Spaz.Keyboard.move('down');
	});
	shortcut.add(Modkey+'+K', function() {
		Spaz.Keyboard.move('up');
	});
	shortcut.add('J', function() {
			Spaz.Keyboard.move('down');
		}, {
			'disable_in_input':true
	});
	shortcut.add('K', function() {
			Spaz.Keyboard.move('up');
		}, {
			'disable_in_input':true
	});

	shortcut.add(Modkey+'+F', function() {
			Spaz.UI.toggleTimelineFilter();
			return false;
		}, {
			type:'keypress',
			propagate:false
	});

	// ****************************************
	// editor shortcuts
	// ****************************************
	shortcut.add(Modkey+'+B', function() {
			Spaz.Editor.bold();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add(Modkey+'+I', function() {
			Spaz.Editor.italics();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add(Modkey+'+R', function() {
			Spaz.Editor.code();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add(Modkey+'+U', function() {
			Spaz.Editor.link();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add('Enter', function() {
			Spaz.UI.sendUpdate();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
}

Spaz.Keyboard.move = function(dir, selector) {

	if (!selector) {
		selector = '';
	}

	Spaz.dump("selector is '" + selector+"'")

	var timelineid = 'timeline-friends';

	if (!dir) { dir = 'down' }

	if (dir == 'down') {
		var movefunc = 'nextAll';
		var wrapselc = 'first';
	} else if (dir == 'up') {
		dir = 'up'
		var movefunc = 'prevAll';
		var wrapselc = 'last';
	} else {
		return false;
	}

	// get current selected
	var jqsel = $('#'+timelineid+' div.ui-selected');
	// alert('selected:'+selected.length);
	//alert('moving:'+movefunc+'/'+wrapselc+"\n"+'selected:'+selected.length + "\n"+'current:'+selected.html());

	// if none selected, or there is no 'next', select first
	if (selector == ":first" || selector == ":last") {
		Spaz.dump('first in timeline')
		Spaz.Keyboard.moveSelect($('#'+timelineid+' div.timeline-entry'+selector), timelineid)
	} else if (jqsel.length == 0 ) {
		Spaz.dump('nothing is selected')
		Spaz.Keyboard.moveSelect($('#'+timelineid+' div.timeline-entry'+selector+':'+wrapselc), timelineid)
		jqsel = $('#'+timelineid+' div.timeline-entry.ui-selected'+selector);
	} else if (jqsel[movefunc]('div.timeline-entry'+selector).eq(0).length == 0) {
		Spaz.dump('we are at the beginning or end')
		Spaz.Keyboard.moveSelect($('#'+timelineid+' div.timeline-entry'+selector+':'+wrapselc), timelineid)
		jqsel = $('#'+timelineid+' div.timeline-entry.ui-selected'+selector);
	} else {
		Spaz.dump('something is now selected');
		Spaz.Keyboard.moveSelect(jqsel[movefunc]('div.timeline-entry'+selector).eq(0), timelineid);
	}
	// if selected is at bottom, go to top
}

Spaz.Keyboard.moveSelect = function(jqelement, timelineid) {

	Spaz.dump('Moving to new selected item');

	Spaz.dump('jqelement.length:'+jqelement.length);

	// unselect everything
	$('#'+timelineid+' div.timeline-entry.ui-selected').removeClass('ui-selected').addClass('read');

	if ( entryId = Spaz.UI.getStatusIdFromElement(jqelement[0]) ) {
		Spaz.DB.markEntryAsRead(entryId);
	}

	// select passed
	if (jqelement.length > 0) {
		jqelement.toggleClass('ui-selected');
		$('#'+timelineid+'').scrollTo(jqelement, {
								offset:-25,
								speed:90,
								easing:'swing'
								}
		);
	} else {
		Spaz.dump("Problem - jqelement passed length = 0 - can't scroll to anything");
	}
}

/******************************
 * Keyboard
 ******************************/
Spaz.Keyboard.keyboardHandler = function(event) {
	e = event || window.event;
	el = e.srcElement || e.target;

	if (el.name) {
		return true;
	}

	if (e.which == 13 && e.srcElement.id == 'entrybox') {
		Spaz.UI.sendUpdate();
		return false;
	}

	// debugging
	if (e.srcElement.id == 'home') {
		Spaz.dump('keyboard Event =================');
		Spaz.dump("keyIdentifier:"+ e.keyIdentifier);
		Spaz.dump("KeyCode:" + e.keyCode);
		Spaz.dump("which:"+ e.which);
		Spaz.dump("type:"+ e.type);
		Spaz.dump("shift:"+ e.shiftKey);
		Spaz.dump("ctrl:"+ e.ctrlKey);
		Spaz.dump("alt:"+ e.altKey);
		Spaz.dump("meta:"+ e.metaKey);
		Spaz.dump("src:"+ e.srcElement.id);
	}

	return true;
}<commit_msg>- Enter in #search-for now starts search<commit_after>var Spaz; if (!Spaz) Spaz = {};

/***********
Spaz.UI
***********/
if (!Spaz.Keyboard) Spaz.Keyboard = {};

Spaz.Keyboard.setShortcuts = function() {
	Spaz.dump("Setting Shortcuts=================================================")
    Spaz.dump("os: " + air.Capabilities['os']);

	var Modkey = 'Meta';

	if (air.Capabilities['os'].search(/Windows/i) != -1) {
		Spaz.dump('THIS IS WINDOWS');
		Modkey = 'Ctrl';
	} else if (air.Capabilities['os'].search(/Linux/i) != -1) { // thx agolna
		Spaz.dump('THIS IS LINUX');
		Modkey = 'Ctrl';
	} else if (air.Capabilities['os'].search(/Mac/i) != -1) {
		Spaz.dump('THIS IS MACOS');
		Modkey = 'Meta';
	}

	Spaz.dump('Modkey is '+Modkey);

	shortcut.add(Modkey+'+T', function() {
		$('#entrybox').focus();
	})

	shortcut.add('F5', function() {
		Spaz.UI.reloadCurrentTab(true);
		Spaz.restartReloadTimer();
	})

	shortcut.add('Shift+F5', function() {
		Spaz.UI.clearCurrentTimeline();
		Spaz.UI.reloadCurrentTab(true);
		Spaz.restartReloadTimer();
	})

	shortcut.add(Modkey+'+Shift+A', function() {
		Spaz.UI.showShortLink();
	});

	shortcut.add(Modkey+'+Shift+M', function() {
		Spaz.UI.markCurrentTimelineAsRead();
	});

	shortcut.add('F1', function() {
		Spaz.UI.showHelp();
	});

	/*
		Added so we can open the preferences folder if the UI is hosed by bad CSS
	*/
	shortcut.add(Modkey+'+Shift+,', function() {
		Spaz.Sys.openAppStorageFolder();
	});

	shortcut.add(Modkey+'+Shift+@', function() {
			Spaz.dump('getting screenname from current selection');
			var screenname = $('div.ui-selected .user-screen-name').text();

			if (screenname) {
				Spaz.dump('username for reply is:'+screenname);
				// var username = '';
				Spaz.UI.prepReply(screenname);
			}
		}, {
			'disable_in_input':false
	});

	// ****************************************
	// tabs shortcuts
	// ****************************************
	shortcut.add(Modkey+'+1', function() {
		Spaz.UI.showTab(0);
	})
	shortcut.add(Modkey+'+2', function() {
		Spaz.UI.showTab(1);
	})
	shortcut.add(Modkey+'+3', function() {
		Spaz.UI.showTab(2);
	})
	shortcut.add(Modkey+'+4', function() {
		Spaz.UI.showTab(3);
	})
	shortcut.add(Modkey+'+5', function() {
		Spaz.UI.showTab(4);
	})
	shortcut.add(Modkey+'+6', function() {
		Spaz.UI.showTab(5);
	})
	shortcut.add(Modkey+'+7', function() {
		Spaz.UI.showTab(6);
	})
	shortcut.add(Modkey+'+,', function() {
		Spaz.UI.showPrefs()
	})

	// ****************************************
	// Keys to navigate timeline
	// ****************************************
	shortcut.add(Modkey+'+down', function() {
		Spaz.Keyboard.move('down', '.reply');
	});
	shortcut.add(Modkey+'+up', function() {
		Spaz.Keyboard.move('up', '.reply');
	});
	shortcut.add(Modkey+'+Shift+down', function() {
		Spaz.Keyboard.move('down', '.dm');
	});
	shortcut.add(Modkey+'+Shift+up', function() {
		Spaz.Keyboard.move('up', '.dm');
	});
	shortcut.add(Modkey+'+End', function() {
		Spaz.Keyboard.move('down', ':last');
	});
	shortcut.add(Modkey+'+Home', function() {
		Spaz.Keyboard.move('up', ':first');
	});
	shortcut.add('Down', function() {
			Spaz.Keyboard.move('down');
		}, {
			'disable_in_input':true
	});
	shortcut.add('Up', function() {
			Spaz.Keyboard.move('up');
		}, {
			'disable_in_input':true
	});
	shortcut.add(Modkey+'+J', function() {
		Spaz.Keyboard.move('down');
	});
	shortcut.add(Modkey+'+K', function() {
		Spaz.Keyboard.move('up');
	});
	shortcut.add('J', function() {
			Spaz.Keyboard.move('down');
		}, {
			'disable_in_input':true
	});
	shortcut.add('K', function() {
			Spaz.Keyboard.move('up');
		}, {
			'disable_in_input':true
	});

	shortcut.add(Modkey+'+F', function() {
			Spaz.UI.toggleTimelineFilter();
			return false;
		}, {
			type:'keypress',
			propagate:false
	});

	/*
		Search box submit on Enter
	*/
	shortcut.add('Enter', function() {
			Spaz.Section.search.build();
		}, {
			target:$('search-for')[0],
			type:'keypress',
			propagate:false
	});

	// ****************************************
	// editor shortcuts
	// ****************************************
	shortcut.add(Modkey+'+B', function() {
			Spaz.Editor.bold();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add(Modkey+'+I', function() {
			Spaz.Editor.italics();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add(Modkey+'+R', function() {
			Spaz.Editor.code();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add(Modkey+'+U', function() {
			Spaz.Editor.link();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
	shortcut.add('Enter', function() {
			Spaz.UI.sendUpdate();
		}, {
			target:$('entrybox')[0],
			type:'keypress',
			propagate:false
	});
}

Spaz.Keyboard.move = function(dir, selector) {

	if (!selector) {
		selector = '';
	}

	Spaz.dump("selector is '" + selector+"'")

	var timelineid = 'timeline-friends';

	if (!dir) { dir = 'down' }

	if (dir == 'down') {
		var movefunc = 'nextAll';
		var wrapselc = 'first';
	} else if (dir == 'up') {
		dir = 'up'
		var movefunc = 'prevAll';
		var wrapselc = 'last';
	} else {
		return false;
	}

	// get current selected
	var jqsel = $('#'+timelineid+' div.ui-selected');
	// alert('selected:'+selected.length);
	//alert('moving:'+movefunc+'/'+wrapselc+"\n"+'selected:'+selected.length + "\n"+'current:'+selected.html());

	// if none selected, or there is no 'next', select first
	if (selector == ":first" || selector == ":last") {
		Spaz.dump('first in timeline')
		Spaz.Keyboard.moveSelect($('#'+timelineid+' div.timeline-entry'+selector), timelineid)
	} else if (jqsel.length == 0 ) {
		Spaz.dump('nothing is selected')
		Spaz.Keyboard.moveSelect($('#'+timelineid+' div.timeline-entry'+selector+':'+wrapselc), timelineid)
		jqsel = $('#'+timelineid+' div.timeline-entry.ui-selected'+selector);
	} else if (jqsel[movefunc]('div.timeline-entry'+selector).eq(0).length == 0) {
		Spaz.dump('we are at the beginning or end')
		Spaz.Keyboard.moveSelect($('#'+timelineid+' div.timeline-entry'+selector+':'+wrapselc), timelineid)
		jqsel = $('#'+timelineid+' div.timeline-entry.ui-selected'+selector);
	} else {
		Spaz.dump('something is now selected');
		Spaz.Keyboard.moveSelect(jqsel[movefunc]('div.timeline-entry'+selector).eq(0), timelineid);
	}
	// if selected is at bottom, go to top
}

Spaz.Keyboard.moveSelect = function(jqelement, timelineid) {

	Spaz.dump('Moving to new selected item');

	Spaz.dump('jqelement.length:'+jqelement.length);

	// unselect everything
	$('#'+timelineid+' div.timeline-entry.ui-selected').removeClass('ui-selected').addClass('read');

	if ( entryId = Spaz.UI.getStatusIdFromElement(jqelement[0]) ) {
		Spaz.DB.markEntryAsRead(entryId);
	}

	// select passed
	if (jqelement.length > 0) {
		jqelement.toggleClass('ui-selected');
		$('#'+timelineid+'').scrollTo(jqelement, {
								offset:-25,
								speed:90,
								easing:'swing'
								}
		);
	} else {
		Spaz.dump("Problem - jqelement passed length = 0 - can't scroll to anything");
	}
}

/******************************
 * Keyboard
 ******************************/
Spaz.Keyboard.keyboardHandler = function(event) {
	e = event || window.event;
	el = e.srcElement || e.target;

	if (el.name) {
		return true;
	}

	if (e.which == 13 && e.srcElement.id == 'entrybox') {
		Spaz.UI.sendUpdate();
		return false;
	}

	// debugging
	if (e.srcElement.id == 'home') {
		Spaz.dump('keyboard Event =================');
		Spaz.dump("keyIdentifier:"+ e.keyIdentifier);
		Spaz.dump("KeyCode:" + e.keyCode);
		Spaz.dump("which:"+ e.which);
		Spaz.dump("type:"+ e.type);
		Spaz.dump("shift:"+ e.shiftKey);
		Spaz.dump("ctrl:"+ e.ctrlKey);
		Spaz.dump("alt:"+ e.altKey);
		Spaz.dump("meta:"+ e.metaKey);
		Spaz.dump("src:"+ e.srcElement.id);
	}

	return true;
}<|endoftext|>