1
0
Fork 0
Nibriboard/Nibriboard/ClientFiles/NibriClient.js

932 lines
26 KiB
JavaScript

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
'use strict';
class RippleLink
{
constructor(inSocketUrl, inBoardWindow)
{
this.socketUrl = inSocketUrl;
this.boardWindow = inBoardWindow;
this.settings = this.boardWindow.settings;
this.websocket = new WebSocket( this.socketUrl, [ this.settings.WebsocketProtocol ] );
}
}
function get(u){return new Promise(function(r,t,a){a=new XMLHttpRequest();a.onload=function(b,c){b=a.status;c=a.response;if(b>199&&b<300){r(c);}else{t(c);}};a.open("GET",u,true);a.send(null);})}
// npm modules
window.EventEmitter = require("event-emitter-es6");
window.FaviconNotification = require("favicon-notification");
// Our files
class BoardWindow extends EventEmitter
{
constructor(canvas)
{
super(); // Run the parent constructor
this.maxFps = 60;
this.renderTimeIndicator = document.createElement("span");
this.renderTimeIndicator.innerHTML = "0ms";
document.querySelector(".fps").appendChild(this.renderTimeIndicator);
this.canvas = canvas;
this.context = canvas.getContext("2d");
FaviconNotification.init({
color: '#ff6333'
});
FaviconNotification.add();
get("/Settings.json").then(JSON.parse).then((function(settings) {
console.info("[setup]", "Obtained settings from server:", settings);
this.settings = settings;
this.setup();
}).bind(this), function(errorMessage) {
console.error(`Error: Failed to fetch settings from server! Response: ${errorMessage}`);
});
this.trackWindowSize();
}
setup() {
this.rippleLink = new RippleLink(this.settings.WebsocketUri, this);
}
nextFrame()
{
// The time at which the current frame started rendering.
let frameStart = +new Date();
if(frameStart - this.lastFrameStart >= (1 / this.maxFps) * 1000)
{
this.update();
this.render(this.canvas, this.context);
}
// Update the time the last frame started rendering
this.lastFrameStart = frameStart;
// Update the time we took rendering the last frame
this.lastFrameTime = +new Date() - frameStart;
this.renderTimeIndicator.innerHTML = `${this.lastFrameTime}ms`;
// Limit the maximum fps
requestAnimationFrame(this.nextFrame.bind(this));
}
update()
{
}
render(canvas, context)
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = "red";
context.fillRect(10, 10, 100, 100);
}
/**
* Updates the canvas size to match the current viewport size.
*/
matchWindowSize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.render(this.canvas, this.context);
}
/**
* Makes the canvas size track the window size.
*/
trackWindowSize() {
this.matchWindowSize();
window.addEventListener("resize", this.matchWindowSize.bind(this));
}
}
window.FpsIndicator = require("fps-indicator");
window.addEventListener("load", function (event) {
let fpsIndicator = FpsIndicator({
updatePeriod: 1000,
maxFps: 60
});
fpsIndicator.element.style.color = "rgb(114, 194, 179)";
let canvas = document.getElementById("canvas-main"),
boardWindow = new BoardWindow(canvas);
boardWindow.nextFrame();
window.boardWindow = boardWindow;
});
},{"event-emitter-es6":2,"favicon-notification":3,"fps-indicator":4}],2:[function(require,module,exports){
'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var DEFAULT_VALUES = {
emitDelay: 10,
strictMode: false
};
/**
* @typedef {object} EventEmitterListenerFunc
* @property {boolean} once
* @property {function} fn
*/
/**
* @class EventEmitter
*
* @private
* @property {Object.<string, EventEmitterListenerFunc[]>} _listeners
* @property {string[]} events
*/
var EventEmitter = function () {
/**
* @constructor
* @param {{}} [opts]
* @param {number} [opts.emitDelay = 10] - Number in ms. Specifies whether emit will be sync or async. By default - 10ms. If 0 - fires sync
* @param {boolean} [opts.strictMode = false] - is true, Emitter throws error on emit error with no listeners
*/
function EventEmitter() {
var opts = arguments.length <= 0 || arguments[0] === undefined ? DEFAULT_VALUES : arguments[0];
_classCallCheck(this, EventEmitter);
var emitDelay = void 0,
strictMode = void 0;
if (opts.hasOwnProperty('emitDelay')) {
emitDelay = opts.emitDelay;
} else {
emitDelay = DEFAULT_VALUES.emitDelay;
}
this._emitDelay = emitDelay;
if (opts.hasOwnProperty('strictMode')) {
strictMode = opts.strictMode;
} else {
strictMode = DEFAULT_VALUES.strictMode;
}
this._strictMode = strictMode;
this._listeners = {};
this.events = [];
}
/**
* @protected
* @param {string} type
* @param {function} listener
* @param {boolean} [once = false]
*/
_createClass(EventEmitter, [{
key: '_addListenner',
value: function _addListenner(type, listener, once) {
if (typeof listener !== 'function') {
throw TypeError('listener must be a function');
}
if (this.events.indexOf(type) === -1) {
this._listeners[type] = [{
once: once,
fn: listener
}];
this.events.push(type);
} else {
this._listeners[type].push({
once: once,
fn: listener
});
}
}
/**
* Subscribes on event type specified function
* @param {string} type
* @param {function} listener
*/
}, {
key: 'on',
value: function on(type, listener) {
this._addListenner(type, listener, false);
}
/**
* Subscribes on event type specified function to fire only once
* @param {string} type
* @param {function} listener
*/
}, {
key: 'once',
value: function once(type, listener) {
this._addListenner(type, listener, true);
}
/**
* Removes event with specified type. If specified listenerFunc - deletes only one listener of specified type
* @param {string} eventType
* @param {function} [listenerFunc]
*/
}, {
key: 'off',
value: function off(eventType, listenerFunc) {
var _this = this;
var typeIndex = this.events.indexOf(eventType);
var hasType = eventType && typeIndex !== -1;
if (hasType) {
if (!listenerFunc) {
delete this._listeners[eventType];
this.events.splice(typeIndex, 1);
} else {
(function () {
var removedEvents = [];
var typeListeners = _this._listeners[eventType];
typeListeners.forEach(
/**
* @param {EventEmitterListenerFunc} fn
* @param {number} idx
*/
function (fn, idx) {
if (fn.fn === listenerFunc) {
removedEvents.unshift(idx);
}
});
removedEvents.forEach(function (idx) {
typeListeners.splice(idx, 1);
});
if (!typeListeners.length) {
_this.events.splice(typeIndex, 1);
delete _this._listeners[eventType];
}
})();
}
}
}
/**
* Applies arguments to specified event type
* @param {string} eventType
* @param {*[]} eventArguments
* @protected
*/
}, {
key: '_applyEvents',
value: function _applyEvents(eventType, eventArguments) {
var typeListeners = this._listeners[eventType];
if (!typeListeners || !typeListeners.length) {
if (this._strictMode) {
throw 'No listeners specified for event: ' + eventType;
} else {
return;
}
}
var removableListeners = [];
typeListeners.forEach(function (eeListener, idx) {
eeListener.fn.apply(null, eventArguments);
if (eeListener.once) {
removableListeners.unshift(idx);
}
});
removableListeners.forEach(function (idx) {
typeListeners.splice(idx, 1);
});
}
/**
* Emits event with specified type and params.
* @param {string} type
* @param eventArgs
*/
}, {
key: 'emit',
value: function emit(type) {
var _this2 = this;
for (var _len = arguments.length, eventArgs = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
eventArgs[_key - 1] = arguments[_key];
}
if (this._emitDelay) {
setTimeout(function () {
_this2._applyEvents.call(_this2, type, eventArgs);
}, this._emitDelay);
} else {
this._applyEvents(type, eventArgs);
}
}
/**
* Emits event with specified type and params synchronously.
* @param {string} type
* @param eventArgs
*/
}, {
key: 'emitSync',
value: function emitSync(type) {
for (var _len2 = arguments.length, eventArgs = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
eventArgs[_key2 - 1] = arguments[_key2];
}
this._applyEvents(type, eventArgs);
}
/**
* Destroys EventEmitter
*/
}, {
key: 'destroy',
value: function destroy() {
this._listeners = {};
this.events = [];
}
}]);
return EventEmitter;
}();
module.exports = EventEmitter;
},{}],3:[function(require,module,exports){
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], factory);
} else if (typeof exports === 'object') {
// Node. Does not work with strict CommonJS, but
// only CommonJS-like environments that support module.exports,
// like Node.
module.exports = factory();
} else {
// Browser globals (root is window)
root.FaviconNotification = factory();
}
}(this, function() {
// Just return a value to define the module export.
// This example returns an object, but the module
// can return a function as the exported value.
// Only run in browser
if (typeof document === 'undefined') {
console.log('This script only run in browsers.');
return;
}
// Private properties
var _options = {};
var _defaults = {
url: '/favicon.ico',
color: '#eb361e',
lineColor: '#ffffff'
};
var _generatedFavicon;
var _iconElement;
// Provate methods
var _addFavicon = function(src) {
var head = document.getElementsByTagName('head')[0];
_iconElement = document.createElement('link');
_iconElement.type = 'image/x-icon';
_iconElement.rel = 'icon';
_iconElement.href = src;
// remove existing favicons
var links = document.getElementsByTagName('link');
for(var i=0, len=links.length; i < len; i++) {
var exists = (typeof(links[i]) !== 'undefined');
if (exists && (links[i].getAttribute('rel') || '').match(/\bicon\b/)) {
head.removeChild(links[i]);
}
}
head.appendChild(_iconElement);
};
var _generateIcon = function(cb) {
var img = document.createElement('img');
img.src = _options.url;
img.onload = function() {
var lineWidth = 2;
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var context = canvas.getContext('2d');
context.clearRect(0, 0, img.width, img.height);
context.drawImage(img, 0, 0);
var centerX = img.width - (img.width / 4.5) - lineWidth;
var centerY = img.height - (img.height / 4.5) - lineWidth;
var radius = img.width / 4.5;
context.fillStyle = _options.color;
context.strokeStyle = _options.lineColor;
context.lineWidth = lineWidth;
context.beginPath();
context.arc(centerX, centerY, radius, 0, Math.PI * 2, false);
context.closePath();
context.fill();
context.stroke();
cb(null, context.canvas.toDataURL());
};
};
var _setOptions = function(options) {
if (!options) {
_options = _defaults;
return;
}
_options = {};
for(var key in _defaults){
_options[key] = options.hasOwnProperty(key) ? options[key] : _defaults[key];
}
};
var FaviconNotification = {
init: function(options) {
_setOptions(options);
_generateIcon(function(err, url){
_generatedFavicon = url;
});
_addFavicon(_options.url);
},
add: function() {
if (!_generatedFavicon && !_iconElement) {
_setOptions();
_generateIcon(function(err, url) {
_generatedFavicon = url;
_addFavicon(url);
});
} else {
_iconElement.href = _generatedFavicon;
}
},
remove: function() {
_iconElement.href = _options.url;
}
};
return FaviconNotification;
}));
},{}],4:[function(require,module,exports){
/**
* @module fps-indicator
*/
const raf = require('raf');
const now = require('right-now');
module.exports = fps;
function fps (opts) {
if (!(this instanceof fps)) return new fps(opts);
opts = opts || {};
if (opts.container) {
if (typeof opts.container === 'string') {
this.container = document.querySelector(opts.container);
}
else {
this.container = opts.container;
}
}
else {
this.container = document.body || document.documentElement;
}
//init fps
this.element = document.createElement('div');
this.element.classList.add('fps');
this.element.innerHTML = `
<div class="fps-bg"></div>
<canvas class="fps-canvas"></canvas>
<span class="fps-text">fps <span class="fps-value">60.0</span></span>
`;
this.container.appendChild(this.element);
this.canvas = this.element.querySelector('.fps-canvas');
this.textEl = this.element.querySelector('.fps-text');
this.valueEl = this.element.querySelector('.fps-value');
this.bgEl = this.element.querySelector('.fps-bg');
this.element.style.cssText = `
line-height: 1;
position: absolute;
z-index: 1;
top: 0;
right: 0;
`;
this.canvas.style.cssText = `
position: relative;
width: 2em;
height: 1em;
display: block;
float: left;
margin-right: .333em;
`;
this.bgEl.style.cssText = `
position: absolute;
height: 1em;
width: 2em;
background: currentcolor;
opacity: .1;
`;
this.canvas.width = parseInt(getComputedStyle(this.canvas).width) || 1;
this.canvas.height = parseInt(getComputedStyle(this.canvas).height) || 1;
this.context = this.canvas.getContext('2d');
let ctx = this.context;
let w = this.canvas.width;
let h = this.canvas.height;
let count = 0;
let lastTime = 0;
let values = opts.values || Array(this.canvas.width);
let updatePeriod = opts.updatePeriod || 1000;
let maxFps = opts.maxFps || 100;
//enable update routine
let that = this;
raf(function measure () {
count++;
let t = now();
if (t - lastTime > updatePeriod) {
let color = that.color;
lastTime = t;
values.push(count / (maxFps * updatePeriod * 0.001));
values = values.slice(-w);
count = 0;
ctx.clearRect(0, 0, w, h);
ctx.fillStyle = getComputedStyle(that.canvas).color;
for (let i = w; i--;) {
let value = values[i];
if (value == null) break;
ctx.fillRect(i, h - h * value, 1, h * value);
}
that.valueEl.innerHTML = (values[values.length - 1]*maxFps).toFixed(1);
}
raf(measure);
});
}
},{"raf":6,"right-now":7}],5:[function(require,module,exports){
(function (process){
// Generated by CoffeeScript 1.7.1
(function() {
var getNanoSeconds, hrtime, loadTime;
if ((typeof performance !== "undefined" && performance !== null) && performance.now) {
module.exports = function() {
return performance.now();
};
} else if ((typeof process !== "undefined" && process !== null) && process.hrtime) {
module.exports = function() {
return (getNanoSeconds() - loadTime) / 1e6;
};
hrtime = process.hrtime;
getNanoSeconds = function() {
var hr;
hr = hrtime();
return hr[0] * 1e9 + hr[1];
};
loadTime = getNanoSeconds();
} else if (Date.now) {
module.exports = function() {
return Date.now() - loadTime;
};
loadTime = Date.now();
} else {
module.exports = function() {
return new Date().getTime() - loadTime;
};
loadTime = new Date().getTime();
}
}).call(this);
}).call(this,require('_process'))
},{"_process":8}],6:[function(require,module,exports){
(function (global){
var now = require('performance-now')
, root = typeof window === 'undefined' ? global : window
, vendors = ['moz', 'webkit']
, suffix = 'AnimationFrame'
, raf = root['request' + suffix]
, caf = root['cancel' + suffix] || root['cancelRequest' + suffix]
for(var i = 0; !raf && i < vendors.length; i++) {
raf = root[vendors[i] + 'Request' + suffix]
caf = root[vendors[i] + 'Cancel' + suffix]
|| root[vendors[i] + 'CancelRequest' + suffix]
}
// Some versions of FF have rAF but not cAF
if(!raf || !caf) {
var last = 0
, id = 0
, queue = []
, frameDuration = 1000 / 60
raf = function(callback) {
if(queue.length === 0) {
var _now = now()
, next = Math.max(0, frameDuration - (_now - last))
last = next + _now
setTimeout(function() {
var cp = queue.slice(0)
// Clear queue here to prevent
// callbacks from appending listeners
// to the current frame's queue
queue.length = 0
for(var i = 0; i < cp.length; i++) {
if(!cp[i].cancelled) {
try{
cp[i].callback(last)
} catch(e) {
setTimeout(function() { throw e }, 0)
}
}
}
}, Math.round(next))
}
queue.push({
handle: ++id,
callback: callback,
cancelled: false
})
return id
}
caf = function(handle) {
for(var i = 0; i < queue.length; i++) {
if(queue[i].handle === handle) {
queue[i].cancelled = true
}
}
}
}
module.exports = function(fn) {
// Wrap in a new function to prevent
// `cancel` potentially being assigned
// to the native rAF function
return raf.call(root, fn)
}
module.exports.cancel = function() {
caf.apply(root, arguments)
}
module.exports.polyfill = function() {
root.requestAnimationFrame = raf
root.cancelAnimationFrame = caf
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"performance-now":5}],7:[function(require,module,exports){
(function (global){
module.exports =
global.performance &&
global.performance.now ? function now() {
return performance.now()
} : Date.now || function now() {
return +new Date
}
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],8:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
// cached from whatever global is present so that test runners that stub it
// don't break things. But we need to wrap it in a try catch in case it is
// wrapped in strict mode code which doesn't define any globals. It's inside a
// function because try/catches deoptimize in certain engines.
var cachedSetTimeout;
var cachedClearTimeout;
function defaultSetTimout() {
throw new Error('setTimeout has not been defined');
}
function defaultClearTimeout () {
throw new Error('clearTimeout has not been defined');
}
(function () {
try {
if (typeof setTimeout === 'function') {
cachedSetTimeout = setTimeout;
} else {
cachedSetTimeout = defaultSetTimout;
}
} catch (e) {
cachedSetTimeout = defaultSetTimout;
}
try {
if (typeof clearTimeout === 'function') {
cachedClearTimeout = clearTimeout;
} else {
cachedClearTimeout = defaultClearTimeout;
}
} catch (e) {
cachedClearTimeout = defaultClearTimeout;
}
} ())
function runTimeout(fun) {
if (cachedSetTimeout === setTimeout) {
//normal enviroments in sane situations
return setTimeout(fun, 0);
}
// if setTimeout wasn't available but was latter defined
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
cachedSetTimeout = setTimeout;
return setTimeout(fun, 0);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedSetTimeout(fun, 0);
} catch(e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedSetTimeout.call(null, fun, 0);
} catch(e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
return cachedSetTimeout.call(this, fun, 0);
}
}
}
function runClearTimeout(marker) {
if (cachedClearTimeout === clearTimeout) {
//normal enviroments in sane situations
return clearTimeout(marker);
}
// if clearTimeout wasn't available but was latter defined
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
cachedClearTimeout = clearTimeout;
return clearTimeout(marker);
}
try {
// when when somebody has screwed with setTimeout but no I.E. maddness
return cachedClearTimeout(marker);
} catch (e){
try {
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
return cachedClearTimeout.call(null, marker);
} catch (e){
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
return cachedClearTimeout.call(this, marker);
}
}
}
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
if (!draining || !currentQueue) {
return;
}
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = runTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
if (currentQueue) {
currentQueue[queueIndex].run();
}
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
runClearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
runTimeout(drainQueue);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = noop;
process.emit = noop;
process.binding = function (name) {
throw new Error('process.binding is not supported');
};
process.cwd = function () { return '/' };
process.chdir = function (dir) {
throw new Error('process.chdir is not supported');
};
process.umask = function() { return 0; };
},{}]},{},[1]);