<commit_before>'use strict';

var $ = require('../util/jquery');
var oo = require('../util/oo');
var Component = require('./Component');
var $$ = Component.$$;

function Panel() {
  Component.apply(this, arguments);
}

Panel.Prototype = function() {

  // This method must be overriden with your panel implementation
  this.render = function() {
    return $$("div")
      .addClass("panel")
      .append(
        $$('div')
          .addClass('panel-content')
          .append('YOUR_PANEL_CONTENT')
      );
  };

  this.getController = function() {
    return this.context.controller;
  };

  this.getDocument = function() {
    return this.props.doc;
  };

  this.getPanelContentElement = function() {
    return this.refs.panelContent.$el[0];
  };

  this.getScrollableContainer = function() {
    return this.refs.panelContent.$el[0];
  };

  // Returns the cumulated height of a panel's content
  this.getContentHeight = function() {
    // initialized lazily as this element is not accessible earlier (e.g. during construction)
    // get the new dimensions
    // TODO: better use outerheight for contentheight determination?
    var contentHeight = 0;
    var panelContentEl = this.getPanelContentElement();

    $(panelContentEl).children().each(function() {
     contentHeight += $(this).outerHeight();
    });
    return contentHeight;
  };

  // Returns the height of panel (inner content overflows)
  this.getPanelHeight = function() {
    var panelContentEl = this.getPanelContentElement();
    return $(panelContentEl).height();
  };

  this.getScrollPosition = function() {
    var panelContentEl = this.getPanelContentElement();
    return $(panelContentEl).scrollTop();
  };

  this.getPanelOffsetForElement = function(el) {
    // initial offset
    var offset = $(el).position().top;

    // Now look at the parents
    function addParentOffset(el) {
      var parentEl = el.parentNode;

      // Reached the panel or the document body. We are done.
      if ($(el).hasClass('panel-content-inner') || !parentEl) return;

      // Found positioned element (calculate offset!)
      if ($(el).css('position') === 'absolute' || $(el).css('position') === 'relative') {
        offset += $(el).position().top;
      }
      addParentOffset(parentEl);
    }

    addParentOffset(el.parentNode);
    return offset;
  };

  this.scrollToNode = function(nodeId) {
    // var n = this.findNodeView(nodeId);
    // TODO make this generic
    var panelContentEl = this.getScrollableContainer();

    // Node we want to scroll to
    var targetNode = $(panelContentEl).find('*[data-id="'+nodeId+'"]')[0];

    if (targetNode) {
      $(panelContentEl).scrollTop(this.getPanelOffsetForElement(targetNode));
    } else {
      console.warn(nodeId, 'not found in scrollable container');
    }
  };
};

oo.inherit(Panel, Component);

module.exports = Panel;
<commit_msg>Fix panel offset calculation.<commit_after>'use strict';

var $ = require('../util/jquery');
var oo = require('../util/oo');
var Component = require('./Component');
var $$ = Component.$$;

function Panel() {
  Component.apply(this, arguments);
}

Panel.Prototype = function() {

  // This method must be overriden with your panel implementation
  this.render = function() {
    return $$("div")
      .addClass("panel")
      .append(
        $$('div')
          .addClass('panel-content')
          .append('YOUR_PANEL_CONTENT')
      );
  };

  this.getController = function() {
    return this.context.controller;
  };

  this.getDocument = function() {
    return this.props.doc;
  };

  this.getPanelContentElement = function() {
    return this.refs.panelContent.$el[0];
  };

  this.getScrollableContainer = function() {
    return this.refs.panelContent.$el[0];
  };

  // Returns the cumulated height of a panel's content
  this.getContentHeight = function() {
    // initialized lazily as this element is not accessible earlier (e.g. during construction)
    // get the new dimensions
    // TODO: better use outerheight for contentheight determination?
    var contentHeight = 0;
    var panelContentEl = this.getPanelContentElement();

    $(panelContentEl).children().each(function() {
     contentHeight += $(this).outerHeight();
    });
    return contentHeight;
  };

  // Returns the height of panel (inner content overflows)
  this.getPanelHeight = function() {
    var panelContentEl = this.getPanelContentElement();
    return $(panelContentEl).height();
  };

  this.getScrollPosition = function() {
    var panelContentEl = this.getPanelContentElement();
    return $(panelContentEl).scrollTop();
  };

  this.getPanelOffsetForElement = function(el) {
    // initial offset
    var offset = $(el).position().top;

    // Now look at the parents
    function addParentOffset(el) {
      var parentEl = el.parentNode;

      // Reached the panel or the document body. We are done.
      if ($(el).hasClass('panel-content-inner') || $(el).hasClass('panel-content') || !parentEl) return;

      // Found positioned element (calculate offset!)
      if ($(el).css('position') === 'absolute' || $(el).css('position') === 'relative') {
        offset += $(el).position().top;
      }
      addParentOffset(parentEl);
    }

    addParentOffset(el.parentNode);
    return offset;
  };

  this.scrollToNode = function(nodeId) {
    // var n = this.findNodeView(nodeId);
    // TODO make this generic
    var panelContentEl = this.getScrollableContainer();

    // Node we want to scroll to
    var targetNode = $(panelContentEl).find('*[data-id="'+nodeId+'"]')[0];

    if (targetNode) {
      $(panelContentEl).scrollTop(this.getPanelOffsetForElement(targetNode));
    } else {
      console.warn(nodeId, 'not found in scrollable container');
    }
  };
};

oo.inherit(Panel, Component);

module.exports = Panel;
<|endoftext|>


<commit_before>// ES2017 w/ Node 5
require('core-js/fn/object/entries');
require('core-js/fn/object/values');
require('core-js/fn/object/get-own-property-descriptors');
require('core-js/fn/string/pad-start');
require('core-js/fn/string/pad-end');
<commit_msg>Added comments to polyfill explaining why they are needed<commit_after>// ES2017: Object.values/Object.entries
// https://github.com/tc39/proposal-object-values-entries
require('core-js/fn/object/entries');
require('core-js/fn/object/values');

// ES2017: Object.getOwnPropertyDescriptors
// https://github.com/ljharb/proposal-object-getownpropertydescriptors
require('core-js/fn/object/get-own-property-descriptors');

// ES2017: String padding
// https://github.com/tc39/proposal-string-pad-start-end
require('core-js/fn/string/pad-start');
require('core-js/fn/string/pad-end');
<|endoftext|>


<commit_before>var maxSpeedX = 4;
var maxSpeedY = 2;
var iterationsBeforeNewSpeed = 30;
var chanceGoLeft = 0.1;
var abroadArea = 0.3;

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var unicorns = [];
var unicornRight = document.createElement('img');
var unicornLeft = document.createElement('img');

unicornRight.src = 'unicorns/img/unicorn_right.png';
unicornLeft.src = 'unicorns/img/unicorn_left.png';

window.onresize = function () {
    canvas.width = document.body.clientWidth;
    canvas.height = document.body.clientHeight;
};

function render() {
    requestAnimationFrame(render);

    context.clearRect(0, 0, canvas.width, canvas.height);

    unicorns.forEach(function (unicorn) {
        var img = (unicorn.directionX > 0) ? unicornRight : unicornLeft;
        var leftBorderOut = unicorn.x + (img.width * (1 - abroadArea)) < 0 && unicorn.directionX < 0;
        var rightBorderOut = unicorn.x + (img.width * abroadArea) > canvas.width && unicorn.directionX > 0;
        var bottomBorderOut = unicorn.y + (img.height * abroadArea) > canvas.height;

        if (leftBorderOut) {
            unicorn.x = canvas.width - (img.width * abroadArea);
        } else if (rightBorderOut) {
            unicorn.x = 0 - (img.width * (1 - abroadArea));
        }
        if (bottomBorderOut) {
            unicorn.y = 0 - (img.height * (1 - abroadArea));
        }

        if (unicorn.speedIterations > iterationsBeforeNewSpeed) {
            unicorn.speedX = Math.random() * maxSpeedX;
            unicorn.speedY = Math.random() * maxSpeedY;
            unicorn.speedIterations = 0;
            unicorn.directionX = (Math.random() < chanceGoLeft) ? -1 : 1;
        } else {
            unicorn.speedIterations++;
        }

        unicorn.x += unicorn.directionX * unicorn.speedX;
        unicorn.y += unicorn.speedY;

        context.drawImage(img, Math.round(unicorn.x), Math.round(unicorn.y));
    });
}

document.getElementById('summon').addEventListener('click', function () {
    unicorns.push({
        x: 0,
        y: 0,
        speedX: Math.random() * maxSpeedX,
        speedY: Math.random() * maxSpeedY,
        speedIterations: 0,
        directionX: 1
    });
});

window.onresize();
render();
<commit_msg>unicorn's flip, yea<commit_after>var maxSpeedX = 4;
var maxSpeedY = 2;
var maxRotationSpeed = 15;
var iterationsBeforeNewSpeed = 30;
var chanceStartRotation = 0.0005;
var chanceGoLeft = 0.05;
var abroadArea = 0.3;

var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var unicorns = [];
var unicornRight = document.createElement('img');
var unicornLeft = document.createElement('img');

unicornRight.src = 'unicorns/img/unicorn_right.png';
unicornLeft.src = 'unicorns/img/unicorn_left.png';

window.onresize = function () {
    canvas.width = document.body.clientWidth;
    canvas.height = document.body.clientHeight;
};

function render() {
    requestAnimationFrame(render);

    context.clearRect(0, 0, canvas.width, canvas.height);

    unicorns.forEach(function (unicorn) {
        var img = (unicorn.directionX > 0) ? unicornRight : unicornLeft;
        var leftBorderOut = unicorn.position.x + (img.width * (1 - abroadArea)) < 0 && unicorn.directionX < 0;
        var rightBorderOut = unicorn.position.x + (img.width * abroadArea) > canvas.width && unicorn.directionX > 0;
        var bottomBorderOut = unicorn.position.y + (img.height * abroadArea) > canvas.height;
        var changeDirection = !unicorn.rotation.enabled && Math.random() < chanceGoLeft;

        if (leftBorderOut) {
            unicorn.position.x = canvas.width - (img.width * abroadArea);
        } else if (rightBorderOut) {
            unicorn.position.x = 0 - (img.width * (1 - abroadArea));
        }
        if (bottomBorderOut) {
            unicorn.position.y = 0 - (img.height * (1 - abroadArea));
        }

        if (unicorn.speed.iterations > iterationsBeforeNewSpeed) {
            unicorn.speed.x = Math.random() * maxSpeedX;
            unicorn.speed.y = Math.random() * maxSpeedY;
            unicorn.speed.iterations = 0;
            unicorn.directionX = changeDirection ? -1 : 1;
        } else {
            unicorn.speed.iterations++;
        }

        if (!unicorn.rotation.enabled && Math.random() < chanceStartRotation) {
            unicorn.rotation.enabled = true;
            unicorn.rotation.speed = (Math.random() * maxRotationSpeed + 3) | 0;
        }

        if (unicorn.rotation.enabled) {
            drawRotatedImage(img, Math.round(unicorn.position.x), Math.round(unicorn.position.y), unicorn.rotation.angle);

            unicorn.rotation.angle += unicorn.rotation.speed;

            if (unicorn.rotation.angle >= 360) {
                unicorn.rotation.angle = 0;
                unicorn.rotation.enabled = false;
            }
        } else {
            unicorn.position.x += unicorn.directionX * unicorn.speed.x;
            unicorn.position.y += unicorn.speed.y;

            context.drawImage(img, Math.round(unicorn.position.x), Math.round(unicorn.position.y));
        }
    });
}

function drawRotatedImage(image, x, y, angle) {
    var halfImageWidth = image.width / 2;
    var halfImageHeight = image.height / 2;

    context.save();
    context.translate(x + halfImageWidth, y + halfImageHeight);
    context.rotate(angle * Math.PI / 180);
    context.drawImage(image, -halfImageWidth, -halfImageHeight);
    context.restore();
}

document.getElementById('summon').addEventListener('click', function () {
    unicorns.push({
        position: {
            x: 0,
            y: 0
        },
        speed: {
            x: Math.random() * maxSpeedX,
            y: Math.random() * maxSpeedY,
            iterations: 0
        },
        rotation: {
            enabled: false,
            angle: 0,
            speed: 0
        },
        directionX: 1
    });
});

window.onresize();
render();
<|endoftext|>


<commit_before>#!/usr/bin/env node
"use strict";
var sjcl = require('./sjcl.js');
var https = require('https');
var crypto = require('crypto');
var FormData = require('form-data');
var mmm = require('mmmagic');
var mime = require('mime');
var fs = require('fs');
var cli = require('snack-cli');
var path = require('path');
var S = require('string');
S.extendPrototype();
const { URL } = require('url');

var argv = cli
	.name('up')
	.version('0.1')
	.usage('[options] [files]')
	.description('Upload files and text to an Up1 based pastebin. If no argument is specified, stdin is assumed.')
	.option('-b, --binary', 'force application/octet-stream', false)
	.option('-t, --text', 'force text/plain', false)
	.option('-f, --file <name>', 'force file name for stdin based inputs', false)
	.option('-m, --mime <mime>', 'force given mime type', 'detect')
	.parse();

const uphost = new URL(process.env.UP1_HOST || "https://up1.ca");
const apikey = process.env.UP1_APIKEY || "c61540b5ceecd05092799f936e27755f";

function parametersfrombits(seed) {
    var out = sjcl.hash.sha512.hash(seed)
    return {
        'seed': seed,
        'key': sjcl.bitArray.bitSlice(out, 0, 256),
        'iv': sjcl.bitArray.bitSlice(out, 256, 384),
        'ident': sjcl.bitArray.bitSlice(out, 384, 512)
    }
}

function parameters(seed) {
    if (typeof seed == 'string') {
        seed = sjcl.codec.base64url.toBits(seed)
    } else {
        seed = sjcl.codec.bytes.toBits(seed)
    }
    return parametersfrombits(seed)
}

function encrypt(file, seed, id) {
    var params = parameters(seed)
    var uarr = new Uint8Array(file)
    var before = sjcl.codec.bytes.toBits(uarr)
    var prp = new sjcl.cipher.aes(params.key)
    var after = sjcl.arrayBuffer.ccm.compat_encrypt(prp, before, params.iv)
    var afterarray = new Buffer(sjcl.codec.bytes.fromBits(after))
    return {
        'id': id,
        'seed': sjcl.codec.base64url.fromBits(params.seed),
        'ident': sjcl.codec.base64url.fromBits(params.ident),
        'encrypted': afterarray
    };
}

function decrypt(file, seed, id) {
    var params = parameters(seed)
    var uarr = new Uint8Array(file)
    var before = sjcl.codec.bytes.toBits(uarr);
    var prp = new sjcl.cipher.aes(params.key);
    var after = sjcl.arrayBuffer.ccm.compat_decrypt(prp, before, params.iv);
    var afterarray = new Uint8Array(sjcl.codec.bytes.fromBits(after));

    var header = ''

    var headerview = new DataView(afterarray.buffer)

    var i = 0;
    for (; ; i++) {
        var num = headerview.getUint16(i * 2, false)
        if (num == 0) {
            break;
        }
        header += String.fromCharCode(num);
    }

    console.log(header)

    var header = JSON.parse(header)

    var data = new Blob([afterarray])

    postMessage({
        'id': id,
        'header': header,
        'decrypted': data.slice((i * 2) + 2, data.size, header.mime)
    })
}

function ident(seed, id) {
    var params = parameters(seed)
    postMessage({
        'id': id,
        'ident': sjcl.codec.base64url.fromBits(params.ident)
    })
}

function str2ab(str) {
	var buf = new Buffer(str.length*2);
	for (var i = 0, strLen = str.length; i < strLen; i++) {
		buf.writeUInt16BE(str.charCodeAt(i), i*2);
	}
	return buf;
}

function doUpload(data, name, type) {
	var seed = new Uint8Array(16);
	seed.set(crypto.randomBytes(seed.length));

	var header = JSON.stringify({
	    'mime': type,
	    'name': name
	})

	var zero = new Buffer([0,0]);
	var blob = Buffer.concat([str2ab(header), zero, Buffer(data)])

	var result = encrypt(blob, seed, 0);

	var formdata = new FormData()
	formdata.append('api_key', apikey)
	formdata.append('ident', result.ident)
	formdata.append('file', result.encrypted, {filename: 'file', contentType: 'text/plain'})

	var req = https.request({
	    host: uphost.hostname,
	    port: uphost.port,
	    path: '/up',
	    method: 'POST',
	    headers: formdata.getHeaders()
	});

	formdata.pipe(req);

	req.on('error', function(err) {
	});

	req.on('response', function(res) {
	    res.setEncoding('utf8');
	    var data_out = '';
	    res.on('data', function(chunk) {
		data_out += chunk;
	    });
	    res.on('end', function() {
		var res_url = uphost.origin+"/#"+result.seed;
		console.log(res_url);
	    });
	});

	req.end();
}

function validateMimeType(type, buf, cb) {
	var guess = null;
	if (argv.binary)
		guess = "application/octet-stream";
  else if (argv.text)
    guess = "text/plain";
  else if (argv.mime != "detect")
		guess = argv.mime;
  else if (type.startsWith("audio") || type.startsWith("video") || type.startsWith("text") || type.startsWith("image"))
		guess = type;

	if (guess != null) {
		cb(guess);
		return;
	}
	var magic = new mmm.Magic(mmm.MAGIC_MIME_ENCODING);
	magic.detect(buf, function(err, result) {
		cb(result == "binary" ? "application/octet-stream" : "text/plain");
	});
}

var rndbuf = crypto.prng(1024);
for (var i = 0; i < 256; i++) {
    sjcl.random.addEntropy(rndbuf.readInt32LE(i*4), 32, "prng");
}

if (argv.args.length > 0) {
	argv.args.forEach(function (val, idx, arr) {
		var buffer = fs.readFileSync(val);
		validateMimeType(mime.lookup(val), buffer, function(mimeType) {
			doUpload(buffer, path.basename(val), mimeType);
		});
	});
} else {
	var buffer = fs.readFileSync('/dev/stdin');
	var magic = new mmm.Magic(mmm.MAGIC_MIME_TYPE);

	magic.detect(buffer, function (err, result) {
		validateMimeType(result, buffer, function(mimeType) {
			var ext = mime.extension(result);
			doUpload(buffer, argv.file ? argv.file : "Pasted." + ext, mimeType);
		});

	});
}
<commit_msg>quick and dirty http support<commit_after>#!/usr/bin/env node
"use strict";
var sjcl = require('./sjcl.js');
var https = require('https');
var http = require('http');
var crypto = require('crypto');
var FormData = require('form-data');
var mmm = require('mmmagic');
var mime = require('mime');
var fs = require('fs');
var cli = require('snack-cli');
var path = require('path');
var S = require('string');
S.extendPrototype();
const { URL } = require('url');

var argv = cli
	.name('up')
	.version('0.1')
	.usage('[options] [files]')
	.description('Upload files and text to an Up1 based pastebin. If no argument is specified, stdin is assumed.')
	.option('-b, --binary', 'force application/octet-stream', false)
	.option('-t, --text', 'force text/plain', false)
	.option('-f, --file <name>', 'force file name for stdin based inputs', false)
	.option('-m, --mime <mime>', 'force given mime type', 'detect')
	.parse();

const uphost = new URL(process.env.UP1_HOST || "https://up1.ca");
const apikey = process.env.UP1_APIKEY || "c61540b5ceecd05092799f936e27755f";

function parametersfrombits(seed) {
    var out = sjcl.hash.sha512.hash(seed)
    return {
        'seed': seed,
        'key': sjcl.bitArray.bitSlice(out, 0, 256),
        'iv': sjcl.bitArray.bitSlice(out, 256, 384),
        'ident': sjcl.bitArray.bitSlice(out, 384, 512)
    }
}

function parameters(seed) {
    if (typeof seed == 'string') {
        seed = sjcl.codec.base64url.toBits(seed)
    } else {
        seed = sjcl.codec.bytes.toBits(seed)
    }
    return parametersfrombits(seed)
}

function encrypt(file, seed, id) {
    var params = parameters(seed)
    var uarr = new Uint8Array(file)
    var before = sjcl.codec.bytes.toBits(uarr)
    var prp = new sjcl.cipher.aes(params.key)
    var after = sjcl.arrayBuffer.ccm.compat_encrypt(prp, before, params.iv)
    var afterarray = new Buffer(sjcl.codec.bytes.fromBits(after))
    return {
        'id': id,
        'seed': sjcl.codec.base64url.fromBits(params.seed),
        'ident': sjcl.codec.base64url.fromBits(params.ident),
        'encrypted': afterarray
    };
}

function decrypt(file, seed, id) {
    var params = parameters(seed)
    var uarr = new Uint8Array(file)
    var before = sjcl.codec.bytes.toBits(uarr);
    var prp = new sjcl.cipher.aes(params.key);
    var after = sjcl.arrayBuffer.ccm.compat_decrypt(prp, before, params.iv);
    var afterarray = new Uint8Array(sjcl.codec.bytes.fromBits(after));

    var header = ''

    var headerview = new DataView(afterarray.buffer)

    var i = 0;
    for (; ; i++) {
        var num = headerview.getUint16(i * 2, false)
        if (num == 0) {
            break;
        }
        header += String.fromCharCode(num);
    }

    console.log(header)

    var header = JSON.parse(header)

    var data = new Blob([afterarray])

    postMessage({
        'id': id,
        'header': header,
        'decrypted': data.slice((i * 2) + 2, data.size, header.mime)
    })
}

function ident(seed, id) {
    var params = parameters(seed)
    postMessage({
        'id': id,
        'ident': sjcl.codec.base64url.fromBits(params.ident)
    })
}

function str2ab(str) {
	var buf = new Buffer(str.length*2);
	for (var i = 0, strLen = str.length; i < strLen; i++) {
		buf.writeUInt16BE(str.charCodeAt(i), i*2);
	}
	return buf;
}

function doUpload(data, name, type) {
	var seed = new Uint8Array(16);
	seed.set(crypto.randomBytes(seed.length));

	var header = JSON.stringify({
	    'mime': type,
	    'name': name
	})

	var zero = new Buffer([0,0]);
	var blob = Buffer.concat([str2ab(header), zero, Buffer(data)])

	var result = encrypt(blob, seed, 0);

	var formdata = new FormData()
	formdata.append('api_key', apikey)
	formdata.append('ident', result.ident)
	formdata.append('file', result.encrypted, {filename: 'file', contentType: 'text/plain'})

    // There *must* be a more elegant way to write this if-else.
    // I just wanted to quickly get it to work.
    if ( uphost.protocol === "https:" ) {
        var req = https.request({
            host: uphost.hostname,
            port: uphost.port,
            path: '/up',
            method: 'POST',
            headers: formdata.getHeaders()
        });
    } else if ( uphost.protocol === "http:" ) {
        var req = http.request({
            host: uphost.hostname,
            port: uphost.port,
            path: '/up',
            method: 'POST',
            headers: formdata.getHeaders()
        });
    }

	formdata.pipe(req);

	req.on('error', function(err) {
	});

	req.on('response', function(res) {
	    res.setEncoding('utf8');
	    var data_out = '';
	    res.on('data', function(chunk) {
		data_out += chunk;
	    });
	    res.on('end', function() {
		var res_url = uphost.origin+"/#"+result.seed;
		console.log(res_url);
	    });
	});

	req.end();
}

function validateMimeType(type, buf, cb) {
	var guess = null;
	if (argv.binary)
		guess = "application/octet-stream";
  else if (argv.text)
    guess = "text/plain";
  else if (argv.mime != "detect")
		guess = argv.mime;
  else if (type.startsWith("audio") || type.startsWith("video") || type.startsWith("text") || type.startsWith("image"))
		guess = type;

	if (guess != null) {
		cb(guess);
		return;
	}
	var magic = new mmm.Magic(mmm.MAGIC_MIME_ENCODING);
	magic.detect(buf, function(err, result) {
		cb(result == "binary" ? "application/octet-stream" : "text/plain");
	});
}

var rndbuf = crypto.prng(1024);
for (var i = 0; i < 256; i++) {
    sjcl.random.addEntropy(rndbuf.readInt32LE(i*4), 32, "prng");
}

if (argv.args.length > 0) {
	argv.args.forEach(function (val, idx, arr) {
		var buffer = fs.readFileSync(val);
		validateMimeType(mime.lookup(val), buffer, function(mimeType) {
			doUpload(buffer, path.basename(val), mimeType);
		});
	});
} else {
	var buffer = fs.readFileSync('/dev/stdin');
	var magic = new mmm.Magic(mmm.MAGIC_MIME_TYPE);

	magic.detect(buffer, function (err, result) {
		validateMimeType(result, buffer, function(mimeType) {
			var ext = mime.extension(result);
			doUpload(buffer, argv.file ? argv.file : "Pasted." + ext, mimeType);
		});

	});
}
<|endoftext|>


<commit_before>import _ from 'lodash';

let createdInstance = null;

export default class ThemeManager {
    constructor(state) {
        this.state = state;
    }

    availableThemes() {
        return this.state.themes;
    }

    currentTheme() {
        let state = this.state;
        let currentThemeName = state.user_settings.theme || state.settings.theme;

        // If no theme was set, use the first one in our theme list
        if (!currentThemeName) {
            currentThemeName = state.themes[0].name;
        }

        currentThemeName = currentThemeName.toLowerCase();

        return _.find(state.settings.themes, t => {
            let isMatch = t.name.toLowerCase() === currentThemeName;
            return isMatch;
        });
    }

    setTheme(themeName) {
        // Make sure this theme exists
        let themeExists = !!_.find(this.state.themes, t => {
            let isMatch = t.name.toLowerCase() === themeName.toLowerCase();
            return isMatch;
        });

        if (!themeExists) {
            return;
        }

        this.state.user_settings.theme = themeName;
    }

    reload() {
        let theme = this.currentTheme();
        if (!theme) {
            return;
        }

        let url = theme.url;
        if (url.indexOf('cb=') > -1) {
            url = url.replace(/cb=[0-9]+/, () => 'cb=' + Date.now());
        } else if (url.indexOf('?') > -1) {
            url += '&cb=' + Date.now();
        } else {
            url += '?cb=' + Date.now();
        }
    }
}

ThemeManager.instance = function instance(state) {
    if (!createdInstance) {
        createdInstance = new ThemeManager(state);
    }

    return createdInstance;
};
<commit_msg>Reload the theme on CTCP ‘kiwi theme change’. Makes theme auto reload possible without hosting your own kiwi server<commit_after>import _ from 'lodash';

let createdInstance = null;

export default class ThemeManager {
    constructor(state) {
        this.state = state;
        this.listenForIrcEvents();
    }

    availableThemes() {
        return this.state.themes;
    }

    currentTheme() {
        let state = this.state;
        let currentThemeName = state.user_settings.theme || state.settings.theme;

        // If no theme was set, use the first one in our theme list
        if (!currentThemeName) {
            currentThemeName = state.themes[0].name;
        }

        currentThemeName = currentThemeName.toLowerCase();

        return _.find(state.settings.themes, t => {
            let isMatch = t.name.toLowerCase() === currentThemeName;
            return isMatch;
        });
    }

    setTheme(themeName) {
        // Make sure this theme exists
        let themeExists = !!_.find(this.state.themes, t => {
            let isMatch = t.name.toLowerCase() === themeName.toLowerCase();
            return isMatch;
        });

        if (!themeExists) {
            return;
        }

        this.state.user_settings.theme = themeName;
    }

    reload() {
        let theme = this.currentTheme();
        if (!theme) {
            return;
        }

        let url = theme.url;
        if (url.indexOf('cb=') > -1) {
            url = url.replace(/cb=[0-9]+/, () => 'cb=' + Date.now());
        } else if (url.indexOf('?') > -1) {
            url += '&cb=' + Date.now();
        } else {
            url += '?cb=' + Date.now();
        }

        theme.url = url;
    }

    // When we get a CTCP 'kiwi theme reload' then reload our theme. Handy for theme devs
    listenForIrcEvents() {
        this.state.$on('irc:ctcp request', (event, network) => {
            let ctcpType = (event.type || '').toLowerCase();
            if (ctcpType === 'kiwi' && event.message.indexOf('theme reload') > -1) {
                this.reload();
            }
        });
    }
}

ThemeManager.instance = function instance(state) {
    if (!createdInstance) {
        createdInstance = new ThemeManager(state);
    }

    return createdInstance;
};
<|endoftext|>


<commit_before>var Bind = require("github/jillix/bind");
var Events = require("github/jillix/events");

module.exports = function(config) {

    // get self (the module)
    var self = this;

    // config
    self.config = config;

    // process config
    processConfig(config);

    // call events
    Events.call(self, config);

    // get the iframe from the module
    var $iframe = $("iframe", self.dom);

    // get file inputs
    var $fileInputs = $("input[type='file']", self.dom);

    // create the accept attr value
    var acceptAttrValue = "";

    // for every file type
    for (var i = 0; i < self.config.options.acceptTypes.length; ++i) {

        // get current type
        var cType = self.config.options.acceptTypes[i];

        // append it to the attr value string
        acceptAttrValue += "." + cType + ",";
    }

    // remove last comma
    acceptAttrValue = acceptAttrValue.substring(0, acceptAttrValue.length - 1);

    // set accept attr
    $fileInputs.attr("accept", acceptAttrValue);

    // file input change event
    $fileInputs.on("change", function () {
        // is the file accepted?
        if (!checkFileType.call(self, this)) {
            // empty the value of file input
            // TODO is this supported on IE?
            $(this).val("");
        }
    });

    // forms on submit
    $("form", self.dom).on("submit", function () {

        // get submiited form
        var $form = $(this);

        // unset the load handler
        $iframe.off("load");

        // set it again
        $iframe.on("load", function () {

            // get text from the page
            var result = $(this.contentWindow.document).text();

            // if no result, return
            if (!result) { return; }

            // get file input jQuery object
            var $inputFile = $form.find("input[type='file']");

            // verify its value
            if (!$inputFile.val()) {
                return;
            }

            // try to parse result
            try {
                result = JSON.parse(result);
            } catch (e) {
                // nothing to do
            }

            // emit fileUploaded event and the result
            self.emit("fileUploaded", result);

            // set src of iframe
            $iframe.attr("src", "");

            // replace the file input
            $inputFile.replaceWith($inputFile.clone(true));
        });
    });

    // emit ready event
    self.emit("ready", config);

    // listen to events
    self.on("setData", setData);
};

/*
 *  This function checks if the selected file has a correct
 *  extension (self.config.options.acceptTypes)
 * */
function checkFileType (fileInput) {
    // get self
    var self = this;

    // get file extension
    var extension = fileInput.value.split(".").reverse()[0];

    // the extension is not supported
    if (self.config.options.acceptTypes.indexOf(extension) === -1) {
        return false;
    }

    // the extension is supported
    return true;
}

/*
 *  This function appends to the upload form hidden inputs with values
 *  from the selected table item
 * */
function setData (data, path) {

    var self = this;

    if (!path) {
        path = "";
    }

    // build the inputs from the object
    for (var key in data) {
        if (key[0] !== '_' && data.hasOwnProperty(key)) {

            // build the object path
            var objPath = path.length ? (path + '.' + key) : key;

            if (typeof data[key] === "object") {

                setData(data[key], objPath);
            } else {

                // get the form
                var $form = $("form", self.dom);

                //create the input
                var el = '<input type="hidden" class="hide" name="' + objPath + '" value="' + data[key] + '">';
                $form.append(el);
            }
        }
    }
}

/*
 *  Process config
 *
 * */
function processConfig (config) {
    config.options = config.options || {};
    config.options.acceptTypes = config.options.acceptTypes || [];
}
<commit_msg>new initActions function created so the module can be loaded by form (this is a work in progress)<commit_after>var Bind = require("github/jillix/bind");
var Events = require("github/jillix/events");

module.exports = function(config) {

    // get self (the module)
    var self = this;

    // config
    self.config = config;

    // process config
    processConfig(config);

    // call events
    Events.call(self, config);

    // call actions
    initActions.call(self);

    // emit ready event
    self.emit("ready", config);

    // listen to events
    self.on("setData", setData);
    self.on("initActions", initActions);
};

function initActions () {
    var self = this;

    // reinitialize the dom (if exists)
    var dom_id = self.dom.id;
    if (document.getElementById(dom_id)) {
        self.dom = document.getElementById(dom_id);
    } else {
        return;
    }

    // get the iframe from the module
    var $iframe = $("iframe", self.dom);

    // get file inputs
    var $fileInputs = $("input[type='file']", self.dom);

    // create the accept attr value
    var acceptAttrValue = "";

    // for every file type
    for (var i = 0; i < self.config.options.acceptTypes.length; ++i) {

        // get current type
        var cType = self.config.options.acceptTypes[i];

        // append it to the attr value string
        acceptAttrValue += "." + cType + ",";
    }

    // remove last comma
    acceptAttrValue = acceptAttrValue.substring(0, acceptAttrValue.length - 1);

    // set accept attr
    $fileInputs.attr("accept", acceptAttrValue);

    // file input change event
    $fileInputs.on("change", function () {
        // is the file accepted?
        if (!checkFileType.call(self, this)) {
            // empty the value of file input
            // TODO is this supported on IE?
            $(this).val("");
        }
    });

    // forms on submit
    $("form", self.dom).on("submit", function () {
        // get submiited form
        var $form = $(this);

        // unset the load handler
        $iframe.off("load");

        // set it again
        $iframe.on("load", function () {

            // get text from the page
            var result = $(this.contentWindow.document).text();

            // if no result, return
            if (!result) { return; }

            // get file input jQuery object
            var $inputFile = $form.find("input[type='file']");

            // verify its value
            if (!$inputFile.val()) {
                return;
            }

            // try to parse result
            try {
                result = JSON.parse(result);
            } catch (e) {
                // nothing to do
            }

            // emit fileUploaded event and the result
            self.emit("fileUploaded", result);

            // set src of iframe
            $iframe.attr("src", "");

            // replace the file input
            $inputFile.replaceWith($inputFile.clone(true));
        });
    });
}

/*
 *  This function checks if the selected file has a correct
 *  extension (self.config.options.acceptTypes)
 * */
function checkFileType (fileInput) {
    // get self
    var self = this;

    // get file extension
    var extension = fileInput.value.split(".").reverse()[0];

    // the extension is not supported
    if (self.config.options.acceptTypes.indexOf(extension) === -1) {
        return false;
    }

    // the extension is supported
    return true;
}

/*
 *  This function appends to the upload form hidden inputs with values
 *  from the selected table item
 * */
function setData (data, path) {

    var self = this;

    if (!path) {
        path = "";
    }

    // build the inputs from the object
    for (var key in data) {
        if (key[0] !== '_' && data.hasOwnProperty(key)) {

            // build the object path
            var objPath = path.length ? (path + '.' + key) : key;

            if (typeof data[key] === "object") {

                setData(data[key], objPath);
            } else {

                // get the form
                var $form = $("form", self.dom);

                //create the input
                var el = '<input type="hidden" class="hide" name="' + objPath + '" value="' + data[key] + '">';
                $form.append(el);
            }
        }
    }
}

/*
 *  Process config
 *
 * */
function processConfig (config) {
    config.options = config.options || {};
    config.options.acceptTypes = config.options.acceptTypes || [];
}
<|endoftext|>


<commit_before>export default {
  el: {
    colorpicker: {
      confirm: 'OK',
      clear: 'Töm'
    },
    datepicker: {
      now: 'Nu',
      today: 'Idag',
      cancel: 'Avbryt',
      clear: 'Töm',
      confirm: 'OK',
      selectDate: 'Välj datum',
      selectTime: 'Välj tid',
      startDate: 'Startdatum',
      startTime: 'Starttid',
      endDate: 'Slutdatum',
      endTime: 'Sluttid',
      prevYear: 'Previous Year', // to be translated
      nextYear: 'Next Year', // to be translated
      prevMonth: 'Previous Month', // to be translated
      nextMonth: 'Next Month', // to be translated
      year: 'År',
      month1: 'Januari',
      month2: 'Februari',
      month3: 'Mars',
      month4: 'April',
      month5: 'Maj',
      month6: 'Juni',
      month7: 'Juli',
      month8: 'Augusti',
      month9: 'September',
      month10: 'Oktober',
      month11: 'November',
      month12: 'December',
      // week: 'week',
      weeks: {
        sun: 'Sön',
        mon: 'Mån',
        tue: 'Tis',
        wed: 'Ons',
        thu: 'Tor',
        fri: 'Fre',
        sat: 'Lör'
      },
      months: {
        jan: 'Jan',
        feb: 'Feb',
        mar: 'Mar',
        apr: 'Apr',
        may: 'Maj',
        jun: 'Jun',
        jul: 'Jul',
        aug: 'Aug',
        sep: 'Sep',
        oct: 'Okt',
        nov: 'Nov',
        dec: 'Dec'
      }
    },
    select: {
      loading: 'Laddar',
      noMatch: 'Hittade inget',
      noData: 'Ingen data',
      placeholder: 'Välj'
    },
    cascader: {
      noMatch: 'Hittade inget',
      loading: 'Laddar',
      placeholder: 'Välj',
      noData: 'Ingen data'
    },
    pagination: {
      goto: 'Gå till',
      pagesize: '/sida',
      total: 'Total {total}',
      pageClassifier: ''
    },
    messagebox: {
      title: 'Meddelande',
      confirm: 'OK',
      cancel: 'Avbryt',
      error: 'Felaktig inmatning'
    },
    upload: {
      deleteTip: 'press delete to remove', // to be translated
      delete: 'Radera',
      preview: 'Förhandsvisa',
      continue: 'Fortsätt'
    },
    table: {
      emptyText: 'Inga Data',
      confirmFilter: 'Bekräfta',
      resetFilter: 'Återställ',
      clearFilter: 'Alla',
      sumText: 'Sum' // to be translated
    },
    tree: {
      emptyText: 'Inga Data'
    },
    transfer: {
      noMatch: 'Hittade inget',
      noData: 'Ingen data',
      titles: ['List 1', 'List 2'], // to be translated
      filterPlaceholder: 'Enter keyword', // to be translated
      noCheckedFormat: '{total} items', // to be translated
      hasCheckedFormat: '{checked}/{total} checked' // to be translated
    },
    image: {
      error: 'FAILED' // to be translated
    },
    pageHeader: {
      title: 'Back' // to be translated
    },
    popconfirm: {
      confirmButtonText: 'Yes', // to be translated
      cancelButtonText: 'No' // to be translated
    }
  }
};
<commit_msg>I18n: Update sv-SE.js (#17926)<commit_after>export default {
  el: {
    colorpicker: {
      confirm: 'OK',
      clear: 'Töm'
    },
    datepicker: {
      now: 'Nu',
      today: 'Idag',
      cancel: 'Avbryt',
      clear: 'Töm',
      confirm: 'OK',
      selectDate: 'Välj datum',
      selectTime: 'Välj tid',
      startDate: 'Startdatum',
      startTime: 'Starttid',
      endDate: 'Slutdatum',
      endTime: 'Sluttid',
      prevYear: 'Föregående år',
      nextYear: 'Nästa år',
      prevMonth: 'Föregående månad',
      nextMonth: 'Nästa månad',
      year: '',
      month1: 'Januari',
      month2: 'Februari',
      month3: 'Mars',
      month4: 'April',
      month5: 'Maj',
      month6: 'Juni',
      month7: 'Juli',
      month8: 'Augusti',
      month9: 'September',
      month10: 'Oktober',
      month11: 'November',
      month12: 'December',
      // week: 'week',
      weeks: {
        sun: 'Sön',
        mon: 'Mån',
        tue: 'Tis',
        wed: 'Ons',
        thu: 'Tor',
        fri: 'Fre',
        sat: 'Lör'
      },
      months: {
        jan: 'Jan',
        feb: 'Feb',
        mar: 'Mar',
        apr: 'Apr',
        may: 'Maj',
        jun: 'Jun',
        jul: 'Jul',
        aug: 'Aug',
        sep: 'Sep',
        oct: 'Okt',
        nov: 'Nov',
        dec: 'Dec'
      }
    },
    select: {
      loading: 'Laddar',
      noMatch: 'Hittade inget',
      noData: 'Ingen data',
      placeholder: 'Välj'
    },
    cascader: {
      noMatch: 'Hittade inget',
      loading: 'Laddar',
      placeholder: 'Välj',
      noData: 'Ingen data'
    },
    pagination: {
      goto: 'Gå till',
      pagesize: '/sida',
      total: 'Totalt {total}',
      pageClassifier: ''
    },
    messagebox: {
      title: 'Meddelande',
      confirm: 'OK',
      cancel: 'Avbryt',
      error: 'Felaktig inmatning'
    },
    upload: {
      deleteTip: 'press delete to remove', // to be translated
      delete: 'Radera',
      preview: 'Förhandsvisa',
      continue: 'Fortsätt'
    },
    table: {
      emptyText: 'Inga Data',
      confirmFilter: 'Bekräfta',
      resetFilter: 'Återställ',
      clearFilter: 'Alla',
      sumText: 'Summa'
    },
    tree: {
      emptyText: 'Ingen data'
    },
    transfer: {
      noMatch: 'Hittade inget',
      noData: 'Ingen data',
      titles: ['List 1', 'List 2'], // to be translated
      filterPlaceholder: 'Enter keyword', // to be translated
      noCheckedFormat: '{total} items', // to be translated
      hasCheckedFormat: '{checked}/{total} checked' // to be translated
    },
    image: {
      error: 'FAILED' // to be translated
    },
    pageHeader: {
      title: 'Bakåt' // to be translated
    },
    popconfirm: {
      confirmButtonText: 'Ja',
      cancelButtonText: 'Nej'
    }
  }
};
<|endoftext|>


<commit_before>var fs = require("fs");
var FIELD_NAME = "solution";
var WRITE_STREAM = "ws";
var FILE_NAME = "originalFilename";
var PATH = "path";
var SIZE = "size";
var SIZE_LIMIT = 6291456;
var INDEX_FIELD = "index";
var destPath = __dirname + "\\solutions\\"
var task =  function(request, callback){
	var field = request.files[FIELD_NAME];
	var size = field[SIZE];
	var fileName = field[FILE_NAME];
	if(size <= 0 || fileName === ""){
		callback("no file to save");
		return;
	}
	if(size > SIZE_LIMIT) {
		callback(" unacceptable filesize > " + SIZE_LIMIT);
		return;
	}
	var uploadPath = field[WRITE_STREAM][PATH];
	var fileName = field[FILE_NAME];
	var index = request.body[INDEX_FIELD] ? request.body[INDEX_FIELD] + "_" : "_";
	var destinationFileName = destPath + index + fileName;
	var overwritten = fs.existsSync(destinationFileName);

	fs.readFile(uploadPath, function (err, data) {

	  	fs.writeFile(destinationFileName, data, function (err) {
	    	if(err) {
				callback(err);
				return;
			}
			console.log("saved")
			callback(null, fileName + " saved succesfully." + (overwritten ?  " Previous version was overwritten" : ""));
	  	});
	});

	//callback(null,"save path: "+ uploadPath + "dest: " + destPath + fileName);

}

exports.action = task<commit_msg>fixing<commit_after>var fs = require("fs");
var FIELD_NAME = "solution";
var WRITE_STREAM = "ws";
var FILE_NAME = "originalFilename";
var PATH = "path";
var SIZE = "size";
var SIZE_LIMIT = 6291456;
var INDEX_FIELD = "index";
var destPath = __dirname + "\\uploads\\"
var task =  function(request, callback){
	var field = request.files[FIELD_NAME];
	var size = field[SIZE];
	var fileName = field[FILE_NAME];
	if(size <= 0 || fileName === ""){
		callback("no file to save");
		return;
	}
	if(size > SIZE_LIMIT) {
		callback(" unacceptable filesize > " + SIZE_LIMIT);
		return;
	}
	var uploadPath = field[WRITE_STREAM][PATH];
	var fileName = field[FILE_NAME];
	var index = request.body[INDEX_FIELD] ? request.body[INDEX_FIELD] + "_" : "_";
	var destinationFileName = destPath + index + fileName;
	var overwritten = fs.existsSync(destinationFileName);

	fs.readFile(uploadPath, function (err, data) {

	  	fs.writeFile(destinationFileName, data, function (err) {
	    	if(err) {
				callback(err);
				return;
			}
			callback(null, fileName + " saved succesfully." + (overwritten ?  " Previous version was overwritten" : ""));
	  	});
	});

	//callback(null,"save path: "+ uploadPath + "dest: " + destPath + fileName);

}

exports.action = task<|endoftext|>


<commit_before>"use strict";
/* jshint esversion: 6, strict: global */
/* globals chrome */
/* globals XMLHttpRequest */
/* globals setTimeout */
// licensed under the MPL 2.0 by (github.com/serv-inc)

/**
* @fileoverview looks through all received text to find words, adds up
* score, shows blocking page
*/

/** @return settings to options page */
function getSettings() { return settings; }
let settings = {};

chrome.runtime.onMessage.addListener(function(pageText, sender, sendResponse) {
    if ( ! settings.whitelist.test(sender.url) ) {
        scan(pageText, sender);
    }
});

// td: this is non-testable due to i, score, ... above, maybe refactor
function scan(pageText, sender, score=0, matches=[],
              i=(settings.blockvals.length-1)) {
    score += _do_score(pageText, settings.blockvals[i], matches);

    if ( score > settings.limit ) {
	chrome.tabs.update(sender.tab.id,
			   {'url': chrome.extension.getURL('popup.html')});
    }

    if ( i > 0 ) {
        setTimeout(function() {
	    scan(pageText, sender, score, matches, i-1);
	}, 0);
    }
}

/** @return score of this blockObject on text */
function _do_score(pageText, blockObject, all_matches) {
    let tmp = pageText.match(RegExp(blockObject.value, "gi"));
    let matches = new Set();
    if ( tmp !== null ) {
        tmp.forEach((el) => {matches.add(el.toLowerCase());});
    }
    matches.forEach((el) => all_matches.push(el));
    return matches.size * blockObject.name;
}

/* OPTIONS CODE */
chrome.storage.local.get(null, function(result) {
    console.log('storage');
    console.log(settings);
    settings.blockvals = result.blockvals;
    settings.limit = result.limit;
    settings.whitelist = result.whitelist && RegExp(result.whitelist);
    console.log(settings);
    if ( ! settings.blockvals || ! settings.limit || ! settings.whitelist ) {
        loadFileSettings();
    }
});

function loadFileSettings() {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'preset.json', true);
    xobj.onreadystatechange = function() {
        if (xobj.readyState == 4 && xobj.status == "200") {
            loadFromJSON(xobj.responseText);
        }
    };
    xobj.send(null);
}

function loadFromJSON(jsonObj) {
    console.log('JSON');
    console.log(settings);
    let parsed = JSON.parse(jsonObj);
    settings.blockvals = settings.blockvals || parsed.blockvals;
    settings.limit = settings.limit || parsed.limit;
    settings.whitelist = settings.whitelist || parsed.whitelist;
    console.log(settings);
}

chrome.storage.onChanged.addListener(updateOptions);
function updateOptions(changes, area) {
    if ( changes ? 'whitelist' in changes : false ) {
        settings.whitelist = RegExp(changes.whitelist.newValue);
    }
    if ( changes ? 'limit' in changes : false ) {
        settings.limit = changes.limit.newValue;
    }
    if ( changes ? 'blockvals' in changes : false ) {
        settings.blockvals = changes.blockvals.newValue;
    }
}
<commit_msg>had forgotten to regexp whitelist<commit_after>"use strict";
/* jshint esversion: 6, strict: global */
/* globals chrome */
/* globals XMLHttpRequest */
/* globals setTimeout */
// licensed under the MPL 2.0 by (github.com/serv-inc)

/**
* @fileoverview looks through all received text to find words, adds up
* score, shows blocking page
*/

/** @return settings to options page */
function getSettings() { return settings; }
let settings = {};

chrome.runtime.onMessage.addListener(function(pageText, sender, sendResponse) {
    if ( ! settings.whitelist.test(sender.url) ) {
        scan(pageText, sender);
    }
});

// td: this is non-testable due to i, score, ... above, maybe refactor
function scan(pageText, sender, score=0, matches=[],
              i=(settings.blockvals.length-1)) {
    score += _do_score(pageText, settings.blockvals[i], matches);

    if ( score > settings.limit ) {
	chrome.tabs.update(sender.tab.id,
			   {'url': chrome.extension.getURL('popup.html')});
    }

    if ( i > 0 ) {
        setTimeout(function() {
	    scan(pageText, sender, score, matches, i-1);
	}, 0);
    }
}

/** @return score of this blockObject on text */
function _do_score(pageText, blockObject, all_matches) {
    let tmp = pageText.match(RegExp(blockObject.value, "gi"));
    let matches = new Set();
    if ( tmp !== null ) {
        tmp.forEach((el) => {matches.add(el.toLowerCase());});
    }
    matches.forEach((el) => all_matches.push(el));
    return matches.size * blockObject.name;
}

/* OPTIONS CODE */
chrome.storage.local.get(null, function(result) {
    settings.blockvals = result.blockvals;
    settings.limit = result.limit;
    settings.whitelist = result.whitelist && RegExp(result.whitelist);
    if ( ! settings.blockvals || ! settings.limit || ! settings.whitelist ) {
        loadFileSettings();
    }
});

function loadFileSettings() {
    var xobj = new XMLHttpRequest();
    xobj.overrideMimeType("application/json");
    xobj.open('GET', 'preset.json', true);
    xobj.onreadystatechange = function() {
        if (xobj.readyState == 4 && xobj.status == "200") {
            loadFromJSON(xobj.responseText);
        }
    };
    xobj.send(null);
}

function loadFromJSON(jsonObj) {
    let parsed = JSON.parse(jsonObj);
    settings.blockvals = settings.blockvals || parsed.blockvals;
    settings.limit = settings.limit || parsed.limit;
    settings.whitelist = settings.whitelist || RegExp(parsed.whitelist);
}

chrome.storage.onChanged.addListener(updateOptions);
function updateOptions(changes, area) {
    if ( changes ? 'whitelist' in changes : false ) {
        settings.whitelist = RegExp(changes.whitelist.newValue);
    }
    if ( changes ? 'limit' in changes : false ) {
        settings.limit = changes.limit.newValue;
    }
    if ( changes ? 'blockvals' in changes : false ) {
        settings.blockvals = changes.blockvals.newValue;
    }
}
<|endoftext|>


<commit_before>JSM.AddVertexToBody = function (body, x, y, z)
{
	body.AddVertex (new JSM.BodyVertex (new JSM.Coord (x, y, z)));
};

JSM.AddPolygonToBody = function (body, vertices)
{
	body.AddPolygon (new JSM.BodyPolygon (vertices));
};

JSM.CalculateBodyVertexToPolygon = function (body)
{
	var result = [];

	var i, j;
	for (i = 0; i < body.VertexCount (); i++) {
		result[i] = [];
	}

	var polygon;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = body.GetPolygon (i);
		for (j = 0; j < polygon.VertexIndexCount (); j++) {
			result[polygon.GetVertexIndex (j)].push (i);
		}
	}

	return result;
};

JSM.CalculateBodyPolygonNormal = function (body, index)
{
	var polygon = body.GetPolygon (index);
	var count = polygon.VertexIndexCount ();

	var normal = new JSM.Vector (0.0, 0.0, 0.0);
	if (count >= 3) {
		var i, currentIndex, nextIndex, current, next;
		for (i = 0; i < count; i++) {
			currentIndex = i;
			nextIndex = (i + 1) % count;

			current = body.GetVertexPosition (polygon.GetVertexIndex (currentIndex));
			next = body.GetVertexPosition (polygon.GetVertexIndex (nextIndex));

			normal.x += (current.y - next.y) * (current.z + next.z);
			normal.y += (current.z - next.z) * (current.x + next.x);
			normal.z += (current.x - next.x) * (current.y + next.y);
		}
	}

	var normalized = JSM.VectorNormalize (normal);
	return normalized;
};

JSM.CalculateBodyPolygonNormals = function (body)
{
	var result = [];

	var i;
	for (i = 0; i < body.PolygonCount (); i++) {
		result.push (JSM.CalculateBodyPolygonNormal (body, i));
	}

	return result;
};

JSM.CalculateBodyVertexNormals = function (body)
{
	var result = [];
	var polygonNormals = JSM.CalculateBodyPolygonNormals (body);
	var vertexToPolygon = JSM.CalculateBodyVertexToPolygon (body);

	var i, j, k, polygon, normal;
	var average, count, neighbourPolygons, neighbourPolygon;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = body.GetPolygon (i);
		result[i] = [];

		if (polygon.HasCurveGroup ()) {
			for (j = 0; j < polygon.VertexIndexCount (); j++) {
				average = new JSM.Vector (0.0, 0.0, 0.0);
				count = 0;

				neighbourPolygons = vertexToPolygon[polygon.GetVertexIndex (j)];
				for (k = 0; k < neighbourPolygons.length; k++) {
					neighbourPolygon = body.GetPolygon (neighbourPolygons[k]);
					if (neighbourPolygon.GetCurveGroup () === polygon.GetCurveGroup ()) {
						average = JSM.CoordAdd (average, polygonNormals[neighbourPolygons[k]]);
						count++;
					}
				}

				average = JSM.VectorMultiply (average, 1.0 / count);
				average = JSM.VectorNormalize (average);
				result[i].push (average);
			}
		} else {
			normal = polygonNormals[i];
			for (j = 0; j < polygon.VertexIndexCount (); j++) {
				result[i].push (new JSM.Vector (normal.x, normal.y, normal.z));
			}
		}
	}

	return result;
};

JSM.MakeBodyInsideOut = function (body)
{
	var i, j, polygon, count, vertices;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = body.GetPolygon (i);
		vertices = polygon.vertices.slice (0);
		count = vertices.length;
		polygon.vertices = [];
		for (j = 0; j < count; j++) {
			polygon.vertices.push (vertices[count - j - 1]);
		}
	}
};

JSM.GetGaussianParameterToReachEpsilonAtValue = function (x, a, b, epsilon)
{
	return Math.sqrt (-(Math.pow (x - b, 2.0) / (2.0 * Math.log (epsilon / Math.abs (a)))));
};

JSM.GetGaussianValue = function (x, a, b, c)
{
	return a * Math.exp (-(Math.pow (x - b, 2.0) / (2.0 * Math.pow (c, 2.0))));
};

JSM.SoftMoveBodyVertex = function (body, index, radius, direction, distance)
{
	var referenceCoord = body.GetVertex (index).position;

	var eps = 0.00001;
	var a = distance;
	var b = 0.0;
	var c = JSM.GetGaussianParameterToReachEpsilonAtValue (radius, a, b, eps);

	var i, x, currentDistance, newDistance, currentCoord;
	for (i = 0; i < body.VertexCount (); i++) {
		currentDistance = JSM.CoordDistance (referenceCoord, body.GetVertex (i).position);
		if (JSM.IsGreater (currentDistance, radius)) {
			continue;
		}

		x = currentDistance;
		newDistance = JSM.GetGaussianValue (x, distance, b, c);

		currentCoord = body.GetVertex (i).position;
		body.GetVertex (i).position = JSM.CoordOffset (currentCoord, direction, newDistance);
	}
};

JSM.CalculatePolygonCentroid = function (body, index)
{
	var polygon = body.GetPolygon (index);
	var count = polygon.VertexIndexCount ();

	var result = new JSM.Coord ();
	var i;
	for (i = 0; i < count; i++) {
		result = JSM.CoordAdd (result, body.GetVertexPosition (polygon.GetVertexIndex (i)));
	}

	result = JSM.VectorMultiply (result, 1.0 / count);
	return result;
};

JSM.TriangulateWithCentroids = function (body)
{
	var result = new JSM.Body ();

	var i, j, vertCoord;
	for (i = 0; i < body.VertexCount (); i++) {
		vertCoord = body.GetVertex (i).position;
		result.AddVertex (new JSM.BodyVertex (new JSM.Coord (vertCoord.x, vertCoord.y, vertCoord.z)));
	}

	var polygon, oldPolygon, vertexCount, curr, next, centroid;
	for (i = 0; i < body.PolygonCount (); i++) {
		vertCoord = JSM.CalculatePolygonCentroid (body, i);
		centroid = result.VertexCount ();
		result.AddVertex (new JSM.BodyVertex (new JSM.Coord (vertCoord.x, vertCoord.y, vertCoord.z)));

		oldPolygon = body.GetPolygon (i);
		vertexCount = oldPolygon.VertexIndexCount ();
		for (j = 0; j < vertexCount; j++) {
			curr = oldPolygon.GetVertexIndex (j);
			next = oldPolygon.GetVertexIndex (j < vertexCount - 1 ? j + 1 : 0);
			polygon = new JSM.BodyPolygon ([curr, next, centroid]);
			polygon.material = oldPolygon.material;
			polygon.curved = oldPolygon.curved;
			result.AddPolygon (polygon);
		}
	}

	return result;
};

JSM.TriangulatePolygons = function (body)
{
	var result = new JSM.Body ();

	var i, j, coord;
	for (i = 0; i < body.VertexCount (); i++) {
		coord = body.GetVertexPosition (i);
		result.AddVertex (new JSM.BodyVertex (new JSM.Coord (coord.x, coord.y, coord.z)));
	}

	var polygon, bodyPolygon, triangleIndices, triangle, bodyTriangle;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = new JSM.Polygon ();
		bodyPolygon = body.GetPolygon (i);
		for (j = 0; j < bodyPolygon.VertexIndexCount (); j++) {
			coord = body.GetVertexPosition (bodyPolygon.GetVertexIndex (j));
			polygon.AddVertex (coord.x, coord.y, coord.z);
		}
		triangleIndices = JSM.PolygonTriangulate (polygon);
		for (j = 0; j < triangleIndices.length; j++) {
			triangle = triangleIndices[j];
			bodyTriangle = new JSM.BodyPolygon ([
				bodyPolygon.GetVertexIndex (triangle[0]),
				bodyPolygon.GetVertexIndex (triangle[1]),
				bodyPolygon.GetVertexIndex (triangle[2])
			]);
			bodyTriangle.InheritAttributes (bodyPolygon);
			result.AddPolygon (bodyTriangle);
		}
	}

	return result;
};

JSM.GenerateRandomMaterials = function (body, materials, seeded)
{
	var minColor = 0;
	var maxColor = 16777215;
	var i, color, material;
	for (i = 0; i < body.PolygonCount (); i++) {
		if (seeded !== undefined && seeded) {
			color = JSM.SeededRandomInt (minColor, maxColor, i + 1);
		} else {
			color = JSM.RandomInt (minColor, maxColor);
		}
		materials.AddMaterial (new JSM.Material (color, color));
		material = materials.Count () - 1;
		body.GetPolygon (i).SetMaterialIndex (material);
	}
};
<commit_msg>Lazy calculate vertexToPolygon array in CalculateBodyVertexNormals.<commit_after>JSM.AddVertexToBody = function (body, x, y, z)
{
	body.AddVertex (new JSM.BodyVertex (new JSM.Coord (x, y, z)));
};

JSM.AddPolygonToBody = function (body, vertices)
{
	body.AddPolygon (new JSM.BodyPolygon (vertices));
};

JSM.CalculateBodyVertexToPolygon = function (body)
{
	var result = [];

	var i, j;
	for (i = 0; i < body.VertexCount (); i++) {
		result.push ([]);
	}

	var polygon;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = body.GetPolygon (i);
		for (j = 0; j < polygon.VertexIndexCount (); j++) {
			result[polygon.GetVertexIndex (j)].push (i);
		}
	}

	return result;
};

JSM.CalculateBodyPolygonNormal = function (body, index)
{
	var polygon = body.GetPolygon (index);
	var count = polygon.VertexIndexCount ();

	var normal = new JSM.Vector (0.0, 0.0, 0.0);
	if (count >= 3) {
		var i, currentIndex, nextIndex, current, next;
		for (i = 0; i < count; i++) {
			currentIndex = i;
			nextIndex = (i + 1) % count;

			current = body.GetVertexPosition (polygon.GetVertexIndex (currentIndex));
			next = body.GetVertexPosition (polygon.GetVertexIndex (nextIndex));

			normal.x += (current.y - next.y) * (current.z + next.z);
			normal.y += (current.z - next.z) * (current.x + next.x);
			normal.z += (current.x - next.x) * (current.y + next.y);
		}
	}

	var normalized = JSM.VectorNormalize (normal);
	return normalized;
};

JSM.CalculateBodyPolygonNormals = function (body)
{
	var result = [];

	var i;
	for (i = 0; i < body.PolygonCount (); i++) {
		result.push (JSM.CalculateBodyPolygonNormal (body, i));
	}

	return result;
};

JSM.CalculateBodyVertexNormals = function (body)
{
	var result = [];
	var polygonNormals = JSM.CalculateBodyPolygonNormals (body);
	var vertexToPolygon = null;

	var i, j, k, polygon, normal;
	var average, count, neighbourPolygons, neighbourPolygon;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = body.GetPolygon (i);
		result[i] = [];

		if (polygon.HasCurveGroup ()) {
			if (vertexToPolygon === null) {
				vertexToPolygon = JSM.CalculateBodyVertexToPolygon (body);
			}
			for (j = 0; j < polygon.VertexIndexCount (); j++) {
				average = new JSM.Vector (0.0, 0.0, 0.0);
				count = 0;

				neighbourPolygons = vertexToPolygon[polygon.GetVertexIndex (j)];
				for (k = 0; k < neighbourPolygons.length; k++) {
					neighbourPolygon = body.GetPolygon (neighbourPolygons[k]);
					if (neighbourPolygon.GetCurveGroup () === polygon.GetCurveGroup ()) {
						average = JSM.CoordAdd (average, polygonNormals[neighbourPolygons[k]]);
						count++;
					}
				}

				average = JSM.VectorMultiply (average, 1.0 / count);
				average = JSM.VectorNormalize (average);
				result[i].push (average);
			}
		} else {
			normal = polygonNormals[i];
			for (j = 0; j < polygon.VertexIndexCount (); j++) {
				result[i].push (new JSM.Vector (normal.x, normal.y, normal.z));
			}
		}
	}

	return result;
};

JSM.MakeBodyInsideOut = function (body)
{
	var i, j, polygon, count, vertices;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = body.GetPolygon (i);
		vertices = polygon.vertices.slice (0);
		count = vertices.length;
		polygon.vertices = [];
		for (j = 0; j < count; j++) {
			polygon.vertices.push (vertices[count - j - 1]);
		}
	}
};

JSM.GetGaussianParameterToReachEpsilonAtValue = function (x, a, b, epsilon)
{
	return Math.sqrt (-(Math.pow (x - b, 2.0) / (2.0 * Math.log (epsilon / Math.abs (a)))));
};

JSM.GetGaussianValue = function (x, a, b, c)
{
	return a * Math.exp (-(Math.pow (x - b, 2.0) / (2.0 * Math.pow (c, 2.0))));
};

JSM.SoftMoveBodyVertex = function (body, index, radius, direction, distance)
{
	var referenceCoord = body.GetVertex (index).position;

	var eps = 0.00001;
	var a = distance;
	var b = 0.0;
	var c = JSM.GetGaussianParameterToReachEpsilonAtValue (radius, a, b, eps);

	var i, x, currentDistance, newDistance, currentCoord;
	for (i = 0; i < body.VertexCount (); i++) {
		currentDistance = JSM.CoordDistance (referenceCoord, body.GetVertex (i).position);
		if (JSM.IsGreater (currentDistance, radius)) {
			continue;
		}

		x = currentDistance;
		newDistance = JSM.GetGaussianValue (x, distance, b, c);

		currentCoord = body.GetVertex (i).position;
		body.GetVertex (i).position = JSM.CoordOffset (currentCoord, direction, newDistance);
	}
};

JSM.CalculatePolygonCentroid = function (body, index)
{
	var polygon = body.GetPolygon (index);
	var count = polygon.VertexIndexCount ();

	var result = new JSM.Coord ();
	var i;
	for (i = 0; i < count; i++) {
		result = JSM.CoordAdd (result, body.GetVertexPosition (polygon.GetVertexIndex (i)));
	}

	result = JSM.VectorMultiply (result, 1.0 / count);
	return result;
};

JSM.TriangulateWithCentroids = function (body)
{
	var result = new JSM.Body ();

	var i, j, vertCoord;
	for (i = 0; i < body.VertexCount (); i++) {
		vertCoord = body.GetVertex (i).position;
		result.AddVertex (new JSM.BodyVertex (new JSM.Coord (vertCoord.x, vertCoord.y, vertCoord.z)));
	}

	var polygon, oldPolygon, vertexCount, curr, next, centroid;
	for (i = 0; i < body.PolygonCount (); i++) {
		vertCoord = JSM.CalculatePolygonCentroid (body, i);
		centroid = result.VertexCount ();
		result.AddVertex (new JSM.BodyVertex (new JSM.Coord (vertCoord.x, vertCoord.y, vertCoord.z)));

		oldPolygon = body.GetPolygon (i);
		vertexCount = oldPolygon.VertexIndexCount ();
		for (j = 0; j < vertexCount; j++) {
			curr = oldPolygon.GetVertexIndex (j);
			next = oldPolygon.GetVertexIndex (j < vertexCount - 1 ? j + 1 : 0);
			polygon = new JSM.BodyPolygon ([curr, next, centroid]);
			polygon.material = oldPolygon.material;
			polygon.curved = oldPolygon.curved;
			result.AddPolygon (polygon);
		}
	}

	return result;
};

JSM.TriangulatePolygons = function (body)
{
	var result = new JSM.Body ();

	var i, j, coord;
	for (i = 0; i < body.VertexCount (); i++) {
		coord = body.GetVertexPosition (i);
		result.AddVertex (new JSM.BodyVertex (new JSM.Coord (coord.x, coord.y, coord.z)));
	}

	var polygon, bodyPolygon, triangleIndices, triangle, bodyTriangle;
	for (i = 0; i < body.PolygonCount (); i++) {
		polygon = new JSM.Polygon ();
		bodyPolygon = body.GetPolygon (i);
		for (j = 0; j < bodyPolygon.VertexIndexCount (); j++) {
			coord = body.GetVertexPosition (bodyPolygon.GetVertexIndex (j));
			polygon.AddVertex (coord.x, coord.y, coord.z);
		}
		triangleIndices = JSM.PolygonTriangulate (polygon);
		for (j = 0; j < triangleIndices.length; j++) {
			triangle = triangleIndices[j];
			bodyTriangle = new JSM.BodyPolygon ([
				bodyPolygon.GetVertexIndex (triangle[0]),
				bodyPolygon.GetVertexIndex (triangle[1]),
				bodyPolygon.GetVertexIndex (triangle[2])
			]);
			bodyTriangle.InheritAttributes (bodyPolygon);
			result.AddPolygon (bodyTriangle);
		}
	}

	return result;
};

JSM.GenerateRandomMaterials = function (body, materials, seeded)
{
	var minColor = 0;
	var maxColor = 16777215;
	var i, color, material;
	for (i = 0; i < body.PolygonCount (); i++) {
		if (seeded !== undefined && seeded) {
			color = JSM.SeededRandomInt (minColor, maxColor, i + 1);
		} else {
			color = JSM.RandomInt (minColor, maxColor);
		}
		materials.AddMaterial (new JSM.Material (color, color));
		material = materials.Count () - 1;
		body.GetPolygon (i).SetMaterialIndex (material);
	}
};
<|endoftext|>


<commit_before>define([
	'lodash',
	'jquery',
	'app/components/component',
	'app/components/app',
	'app/components/input/shortcuts',
	'app/components/midi/controller',
	'app/components/ui/piano',
	'app/components/ui/tab_controls',
	'app/components/ui/theme',
	'app/components/ui/music',
	'app/models/chord_bank',
	'app/models/key_signature',
	'app/models/midi_device'
], function(
	_,
	$,
	Component,
	AppComponent,
	KeyboardShortcutsComponent,
	MidiControllerComponent,
	PianoComponent,
	TabControlsComponent,
	ThemeComponent,
	TranscriptComponent,
	ChordBank,
	KeySignature,
	MidiDevice
) {

	/**
	 * AppExerciseComponent class.
	 *
	 * Creates the sandbox environment for playing and experimenting
	 * with chords and chord sequences. This is the basic mode of the
	 * application for students to just play around and try things.
	 *
	 * @constructor
	 */
	var AppExerciseComponent = function(settings) {
		AppComponent.call(this, settings);
	};

	AppExerciseComponent.prototype = new AppComponent();

	/**
	 * Returns the models used by the app.
	 */
	AppExerciseComponent.prototype.getModels = function() {
		var models = {};
		models.playChords = new ChordBank();
		models.exerciseChords = new ChordBank();
		models.keySignature = new KeySignature();
		models.midiDevice = new MidiDevice();
		return models;
	};

	/**
	 * Returns an array of functions that will create and initialize
	 * each sub-component of the application.
	 *
	 * @return {array} of functions
	 */
	AppExerciseComponent.prototype.getComponentMethods = function() {
		var methods = [
			function() {
				var c = new PianoComponent();
				c.init(this);
				c.renderTo("#piano");
				this.addComponent(c);
			},
			function() {
				var c = new MidiControllerComponent({
					chords: this.models.playChords,
					midiDevice: this.models.midiDevice
				});
				c.init(this);
				this.addComponent(c);
			},
			function() {
				var c = new KeyboardShortcutsComponent({
					keySignature: this.models.keySignature
				});
				c.init(this);
				this.addComponent(c);
			},
			function() {
				var c = new TabControlsComponent({
					keySignature: this.models.keySignature,
					midiDevice: this.models.midiDevice
				});
				c.init(this);
				this.addComponent(c);
			},
			function() {
				var c = new TranscriptComponent({
					chords: this.models.exerciseChords,
					keySignature: this.models.keySignature
				});
				c.init(this);
				c.renderTo("#staff-area");
				this.addComponent(c);
			},
			function() {
				var c = new ThemeComponent({
					targetEl: "#container"
				});
				c.init(this);
				c.renderTo("#theme-select");
				this.addComponent(c);
			}
		];
		return methods;
	};

	/**
	 * Initializes the application.
	 * Intended to be called $(document).ready().
	 *
	 * @return undefined
	 */
	AppExerciseComponent.ready = function() {
		app = new AppExerciseComponent();
		app.init();
		app.log("App ready");
	};

	return AppExerciseComponent;
});
<commit_msg>update parameter name<commit_after>define([
	'lodash',
	'jquery',
	'app/components/component',
	'app/components/app',
	'app/components/input/shortcuts',
	'app/components/midi/controller',
	'app/components/ui/piano',
	'app/components/ui/tab_controls',
	'app/components/ui/theme',
	'app/components/ui/music',
	'app/models/chord_bank',
	'app/models/key_signature',
	'app/models/midi_device'
], function(
	_,
	$,
	Component,
	AppComponent,
	KeyboardShortcutsComponent,
	MidiControllerComponent,
	PianoComponent,
	TabControlsComponent,
	ThemeComponent,
	MusicComponent,
	ChordBank,
	KeySignature,
	MidiDevice
) {

	/**
	 * AppExerciseComponent class.
	 *
	 * Creates the sandbox environment for playing and experimenting
	 * with chords and chord sequences. This is the basic mode of the
	 * application for students to just play around and try things.
	 *
	 * @constructor
	 */
	var AppExerciseComponent = function(settings) {
		AppComponent.call(this, settings);
	};

	AppExerciseComponent.prototype = new AppComponent();

	/**
	 * Returns the models used by the app.
	 */
	AppExerciseComponent.prototype.getModels = function() {
		var models = {};
		models.playChords = new ChordBank();
		models.exerciseChords = new ChordBank();
		models.keySignature = new KeySignature();
		models.midiDevice = new MidiDevice();
		return models;
	};

	/**
	 * Returns an array of functions that will create and initialize
	 * each sub-component of the application.
	 *
	 * @return {array} of functions
	 */
	AppExerciseComponent.prototype.getComponentMethods = function() {
		var methods = [
			function() {
				var c = new PianoComponent();
				c.init(this);
				c.renderTo("#piano");
				this.addComponent(c);
			},
			function() {
				var c = new MidiControllerComponent({
					chords: this.models.playChords,
					midiDevice: this.models.midiDevice
				});
				c.init(this);
				this.addComponent(c);
			},
			function() {
				var c = new KeyboardShortcutsComponent({
					keySignature: this.models.keySignature
				});
				c.init(this);
				this.addComponent(c);
			},
			function() {
				var c = new TabControlsComponent({
					keySignature: this.models.keySignature,
					midiDevice: this.models.midiDevice
				});
				c.init(this);
				this.addComponent(c);
			},
			function() {
				var c = new MusicComponent({
					chords: this.models.exerciseChords,
					keySignature: this.models.keySignature
				});
				c.init(this);
				c.renderTo("#staff-area");
				this.addComponent(c);
			},
			function() {
				var c = new ThemeComponent({
					targetEl: "#container"
				});
				c.init(this);
				c.renderTo("#theme-select");
				this.addComponent(c);
			}
		];
		return methods;
	};

	/**
	 * Initializes the application.
	 * Intended to be called $(document).ready().
	 *
	 * @return undefined
	 */
	AppExerciseComponent.ready = function() {
		app = new AppExerciseComponent();
		app.init();
		app.log("App ready");
	};

	return AppExerciseComponent;
});
<|endoftext|>