<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        expect(fileContentReadme.indexOf('## License'), 'The README.md needs to have a section ## License').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## Changelog').not.equal(-1);
        expect(fileContentReadme.indexOf('## Changelog'), 'The README.md needs to have a section ## License').to.be.below(fileContentReadme.indexOf('## License'));
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should have a section ## License');
            console.log();
        }
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        done();
    });
});
<|endoftext|>


<commit_before>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        expect(fs.existsSync(__dirname + '/../LICENSE'), 'A LICENSE must exist');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should have a section ## License');
            console.log();
        }
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        done();
    });
});
<commit_msg>update basic package-file testing<commit_after>/* jshint -W097 */
/* jshint strict:false */
/* jslint node: true */
/* jshint expr: true */
var expect = require('chai').expect;
var fs        = require('fs');

describe('Test package.json and io-package.json', function() {
    it('Test package files', function (done) {
        console.log();

        var fileContentIOPackage = fs.readFileSync(__dirname + '/../io-package.json', 'utf8');
        var ioPackage = JSON.parse(fileContentIOPackage);

        var fileContentNPMPackage = fs.readFileSync(__dirname + '/../package.json', 'utf8');
        var npmPackage = JSON.parse(fileContentNPMPackage);

        expect(ioPackage).to.be.an('object');
        expect(npmPackage).to.be.an('object');

        expect(ioPackage.common.version, 'ERROR: Version number in io-package.json needs to exist').to.exist;
        expect(npmPackage.version, 'ERROR: Version number in package.json needs to exist').to.exist;

        expect(ioPackage.common.version, 'ERROR: Version numbers in package.json and io-package.json needs to match').to.be.equal(npmPackage.version);

        if (!ioPackage.common.news || !ioPackage.common.news[ioPackage.common.version]) {
            console.log('WARNING: No news entry for current version exists in io-package.json, no rollback in Admin possible!');
            console.log();
        }

        expect(npmPackage.author, 'ERROR: Author in package.json needs to exist').to.exist;
        expect(ioPackage.common.authors, 'ERROR: Authors in io-package.json needs to exist').to.exist;

        if (ioPackage.common.name.indexOf('template') !== 0) {
            if (Array.isArray(ioPackage.common.authors)) {
                expect(ioPackage.common.authors.length, 'ERROR: Author in io-package.json needs to be set').to.not.be.equal(0);
                if (ioPackage.common.authors.length === 1) {
                    expect(ioPackage.common.authors[0], 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
                }
            }
            else {
                expect(ioPackage.common.authors, 'ERROR: Author in io-package.json needs to be a real name').to.not.be.equal('my Name <my@email.com>');
            }
        }
        else {
            console.log('WARNING: Testing for set authors field in io-package skipped because template adapter');
            console.log();
        }
        expect(fs.existsSync(__dirname + '/../README.md'), 'ERROR: README.md needs to exist! Please create one with description, detail information and changelog. English is mandatory.').to.be.true;
        expect(fs.existsSync(__dirname + '/../LICENSE'), 'ERROR: LICENSE needs to exist! Please create one.').to.be.true;
        if (!ioPackage.common.titleLang || typeof ioPackage.common.titleLang !== 'object') {
            console.log('WARNING: titleLang is not existing in io-package.json. Please add');
            console.log();
        }
        if (
            ioPackage.common.title.indexOf('iobroker') !== -1 ||
            ioPackage.common.title.indexOf('ioBroker') !== -1 ||
            ioPackage.common.title.indexOf('adapter') !== -1 ||
            ioPackage.common.title.indexOf('Adapter') !== -1
        ) {
            console.log('WARNING: title contains Adapter or ioBroker. It is clear anyway, that it is adapter for ioBroker.');
            console.log();
        }

        if (ioPackage.common.name.indexOf('vis-') !== 0) {
            if (!ioPackage.common.materialize || !fs.existsSync(__dirname + '/../admin/index_m.html') || !fs.existsSync(__dirname + '/../gulpfile.js')) {
                console.log('WARNING: Admin3 support is missing! Please add it');
                console.log();
            }
            if (ioPackage.common.materialize) {
                expect(fs.existsSync(__dirname + '/../admin/index_m.html'), 'Admin3 support is enabled in io-package.json, but index_m.html is missing!').to.be.true;
            }
        }

        var licenseFileExists = fs.existsSync(__dirname + '/../LICENSE');
        var fileContentReadme = fs.readFileSync(__dirname + '/../README.md', 'utf8');
        if (fileContentReadme.indexOf('## Changelog') === -1) {
            console.log('Warning: The README.md should have a section ## Changelog');
            console.log();
        }
        expect((licenseFileExists || fileContentReadme.indexOf('## License') !== -1), 'A LICENSE must exist as LICENSE file or as part of the README.md').to.be.true;
        if (!licenseFileExists) {
            console.log('Warning: The License should also exist as LICENSE file');
            console.log();
        }
        if (fileContentReadme.indexOf('## License') === -1) {
            console.log('Warning: The README.md should also have a section ## License to be shown in Admin3');
            console.log();
        }
        done();
    });
});
<|endoftext|>


<commit_before>/**
 *
 */

function addQuestion(questionType){
	var div = document.createElement('form');
	$(div).addClass('form-horizontal')
	var label = document.createElement('label')
	$(label).text('Vul hier uw vraag in: ');

}<commit_msg>some changes<commit_after>/**
 *
 */

function addQuestion(questionType) {
	var div = document.createElement('form');
	$(div).addClass('form-horizontal')
	var label = document.createElement('label')
	$(label).text('Vul hier uw vraag in: ');

}

function createSurvey() {
	var json = {
		"questions" : []
	};

	var cntr = 1;
	var id = "vraag" + cntr + "type";
	var element = document.getElementById(id);
	while (element !== undefined) {

		cntr++;
		id = "vraag" + cntr + "type";
		element = document.getElementById(id);
	}

}<|endoftext|>


<commit_before>var word_list, exists, index, string, temp, totalVideos;
totalVideos = videoData.length;
word_list = [];

function setWordArray() {
  for (var k = 0; k < skillArray.length; k++) {
    temp = { text: skillArray[k].skill, weight: skillArray[k].number, color: "green" };
    word_list.push(temp);
  }
  //sort list by weight
  word_list.sort(function (a, b) {
    return b.weight - a.weight;
  })
  //set colour of words
  for (var k = 0; k < word_list.length; k++) {
    word_list[k].color = colorData[k];
  }
}

$(function () {
  setWordArray();
  growTree();
  $("#wordList").jQCloud(word_list);
  setTimeout(function () {
    var obj = $("#demo").data("jqcloud");
    var data = obj.word_list;
    for (var i in data) {
      $("#" + data[i]["attr"]["id"]).css("color", data[i]["color"]);
    }
  }, 100);
});

function growTree() {
  if (word_list.length >= 5) {
    document.getElementById("rootTree").src = "../images/treeTrunk.png";
    document.getElementById("rootTree").classList.add("tree");
    document.getElementById("wordList").style.bottom = "180px";
  }
  else {
    document.getElementById("rootTree").src = "../images/sprout.png";
    document.getElementById("rootTree").classList.add("sprout");
    document.getElementById("wordList").style.bottom = "85px";
  }
}<commit_msg>Update wordCloud.js<commit_after>var word_list, exists, index, string, temp, totalVideos;
totalVideos = videoData.length;
word_list = [];

function setWordArray() {
  for (var k = 0; k < skillArray.length; k++) {
    temp = { text: skillArray[k].skill, weight: skillArray[k].number, color: "green" };
    word_list.push(temp);
  }
  //sort list by weight
  word_list.sort(function (a, b) {
    return b.weight - a.weight;
  })
  //set colour of words
  for (var k = 0; k < word_list.length; k++) {
    word_list[k].color = colorData[k];
  }
}

$(function () {
  setWordArray();
  growTree();
  $("#wordList").jQCloud(word_list);
  setTimeout(function () {
    var obj = $("#demo").data("jqcloud");
    var data = obj.word_list;
    for (var i in data) {
      $("#" + data[i]["attr"]["id"]).css("color", data[i]["color"]);
    }
  }, 100);
});

function growTree() {
  if (word_list.length >= 5) {
    document.getElementById("rootTree").src = "images/treeTrunk.png";
    document.getElementById("rootTree").classList.add("tree");
    document.getElementById("wordList").style.bottom = "180px";
  }
  else {
    document.getElementById("rootTree").src = "images/sprout.png";
    document.getElementById("rootTree").classList.add("sprout");
    document.getElementById("wordList").style.bottom = "85px";
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import {findDOMNode} from 'react-dom';

/**
 * A testing module to verify that arbitrary React-supported attributes are passed
 * through the destination element node. The conformance checker uses the following
 * valid JSX attributes as examples:
 *
 * - className
 * - id
 * - style
 * - data-foo
 * - aria-label
 *
 * Each must be able to be mixed and matched without overwriting each other,
 * with the exception of `id`, where `props.id`
 *
 * @param {function}  render        a pre-build render function to take in vdom and render to a designated place
 * @param {function}  Constructor   a valid ReactClass
 * @param {object}    baseProps     any fundamental props that are needed for the component to be rendered successfully
 * @param {string}   [key] an instance key to check for compliance instead of the base element; this is
 *                                  used for React components that render to <body> or a node other than its logical parent
 */
export default function verifyConformance(render, Constructor, baseProps, key) {
    let node;

    const renderWithPropsAndGetNode = (props) => {
        const element = render(
            React.createElement(
                Constructor, {
                    ...baseProps,
                    ...props
                }
            )
        );

        if (key) {
            return   element[key] instanceof HTMLElement
                   ? element[key]
                   : findDOMNode(element[key]);
        }

        return findDOMNode(element);
    };

    /* verify props.className */
    node = renderWithPropsAndGetNode({className: 'foo'});

    expect(node.classList.contains('foo')).toBe(true,
        `${Constructor.name} does not support adding of classes via props.className`
    );

    /* verify props.id */
    node = renderWithPropsAndGetNode({id: 'foo'});

    expect(node.id === 'foo').toBe(true,
        `${Constructor.name} does not support adding of an HTML id via props.id`
    );

    /* verify props.style */
    node = renderWithPropsAndGetNode({style: {color: 'red'}});

    expect(node.style.color === 'red').toBe(true,
        `${Constructor.name} does not support adding inline styles via props.style`
    );

    /* verify props['data-foo'] */
    node = renderWithPropsAndGetNode({'data-foo': 'bar'});

    expect(node.getAttribute('data-foo') === 'bar').toBe(true,
        `${Constructor.name} does not support adding data attributes via props`
    );

    /* verify props['aria-label'] */
    node = renderWithPropsAndGetNode({'aria-label': 'foo'});

    expect(node.getAttribute('aria-label') === 'foo').toBe(true,
        `${Constructor.name} does not support adding aria attributes via props`
    );
};
<commit_msg>Make UIUtils/conform use lodash.get() under the hood<commit_after>import React from 'react';
import {findDOMNode} from 'react-dom';
import {get} from 'lodash';

/**
 * A testing module to verify that arbitrary React-supported attributes are passed
 * through the destination element node. The conformance checker uses the following
 * valid JSX attributes as examples:
 *
 * - className
 * - id
 * - style
 * - data-foo
 * - aria-label
 *
 * Each must be able to be mixed and matched without overwriting each other,
 * with the exception of `id`, where `props.id`
 *
 * @param {function}  render        a pre-build render function to take in vdom and render to a designated place
 * @param {function}  Constructor   a valid ReactClass
 * @param {object}    baseProps     any fundamental props that are needed for the component to be rendered successfully
 * @param {string}   [key] an instance key to check for compliance instead of the base element; this is
 *                                  used for React components that render to <body> or a node other than its logical parent
 */
export default function verifyConformance(render, Constructor, baseProps, key) {
    let node;

    const renderWithPropsAndGetNode = (props) => {
        const element = render(
            React.createElement(
                Constructor, {
                    ...baseProps,
                    ...props
                }
            )
        );

        if (key) {
            return   get(element, key) instanceof HTMLElement
                   ? get(element, key)
                   : findDOMNode(get(element, key));
        }

        return findDOMNode(element);
    };

    /* verify props.className */
    node = renderWithPropsAndGetNode({className: 'foo'});

    expect(node.classList.contains('foo')).toBe(true,
        `${Constructor.name} does not support adding of classes via props.className`
    );

    /* verify props.id */
    node = renderWithPropsAndGetNode({id: 'foo'});

    expect(node.id === 'foo').toBe(true,
        `${Constructor.name} does not support adding of an HTML id via props.id`
    );

    /* verify props.style */
    node = renderWithPropsAndGetNode({style: {color: 'red'}});

    expect(node.style.color === 'red').toBe(true,
        `${Constructor.name} does not support adding inline styles via props.style`
    );

    /* verify props['data-foo'] */
    node = renderWithPropsAndGetNode({'data-foo': 'bar'});

    expect(node.getAttribute('data-foo') === 'bar').toBe(true,
        `${Constructor.name} does not support adding data attributes via props`
    );

    /* verify props['aria-label'] */
    node = renderWithPropsAndGetNode({'aria-label': 'foo'});

    expect(node.getAttribute('aria-label') === 'foo').toBe(true,
        `${Constructor.name} does not support adding aria attributes via props`
    );
};
<|endoftext|>


<commit_before>"use strict";

function compare_buildings_by_priority(a, b)
{
  const energyPriority = [
    STRUCTURE_SPAWN,
    STRUCTURE_TOWER,
    STRUCTURE_EXTENSION,
    STRUCTURE_STORAGE
  ];
  if (a.structureType == b.structureType)
    return 0;
  const a_priority = energyPriority.indexOf(a.structureType);
  const b_priority = energyPriority.indexOf(b.structureType);
  if (a_priority < b_priority)
		return -1;
	if (a_priority > b_priority)
		return 1;
}

function doDelivery(creep)
{
  creep.say('delivering');
  var storages = creep.room.find(FIND_MY_STRUCTURES, {
    filter: i => (i.structureType == STRUCTURE_EXTENSION && i.energy < i.energyCapacity) ||
      (i.structureType == STRUCTURE_STORAGE && _.sum(i.store) < i.storeCapacity) ||
      (i.energy < (i.energyCapacity - creep.carryCapacity))
  });
  storages.sort(compare_buildings_by_priority);
  var target = storages[0];
  if (creep.transfer(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
    creep.moveTo(target);
  }
}

function doRefuel(creep)
{
  creep.say('refueling');
  const target =  creep.pos.findClosestByRange(FIND_DROPPED_ENERGY);
  if (target) {
    if (creep.pickup(target) == ERR_NOT_IN_RANGE) {
      creep.moveTo(target);
      return;
    }
  } else {
    const storages = creep.room.find(FIND_STRUCTURES, {
      filter: i => i.structureType == STRUCTURE_CONTAINER
    });
    storages.sort((a,b) => b.store[RESOURCE_ENERGY] - a.store[RESOURCE_ENERGY]);
    if (storages.length > 0) {
      if (creep.withdraw(storages[0], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
        creep.moveTo(storages[0]);
      }
    }
  }
}

module.exports = {
  run: function(creep) {
    if ((creep.room.lookForAt(LOOK_STRUCTURES, creep).length == 0) && (creep.room.lookForAt(LOOK_CONSTRUCTION_SITES, creep).length == 0)) {
      creep.room.createConstructionSite(creep, STRUCTURE_ROAD);
    }
    if (creep.memory.mode = 'refuel') {
      if (_.sum(creep.carry) == creep.carryCapacity) {
        creep.memory.mode = 'deliver';
        doDelivery(creep);
      } else {
        doRefuel(creep);
      }
    } else {
       if (creep.carry[RESOURCE_ENERGY] == 0) {
         creep.memory.mode = 'refuel';
         doRefuel(creep);
       } else {
         doDelivery(Creep);
       }
    }
  },
  bodyparts: [MOVE, MOVE, CARRY, CARRY]
};
<commit_msg>fixed a bug in mode switching, thanks kire7393<commit_after>"use strict";

function compare_buildings_by_priority(a, b)
{
  const energyPriority = [
    STRUCTURE_SPAWN,
    STRUCTURE_TOWER,
    STRUCTURE_EXTENSION,
    STRUCTURE_STORAGE
  ];
  if (a.structureType == b.structureType)
    return 0;
  const a_priority = energyPriority.indexOf(a.structureType);
  const b_priority = energyPriority.indexOf(b.structureType);
  if (a_priority < b_priority)
		return -1;
	if (a_priority > b_priority)
		return 1;
}

function doDelivery(creep)
{
  creep.say('delivering');
  var storages = creep.room.find(FIND_MY_STRUCTURES, {
    filter: i => (i.structureType == STRUCTURE_EXTENSION && i.energy < i.energyCapacity) ||
      (i.structureType == STRUCTURE_STORAGE && _.sum(i.store) < i.storeCapacity) ||
      (i.energy < (i.energyCapacity - creep.carryCapacity))
  });
  storages.sort(compare_buildings_by_priority);
  var target = storages[0];
  if (creep.transfer(target, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
    creep.moveTo(target);
  }
}

function doRefuel(creep)
{
  creep.say('refueling');
  const target =  creep.pos.findClosestByRange(FIND_DROPPED_ENERGY);
  if (target) {
    if (creep.pickup(target) == ERR_NOT_IN_RANGE) {
      creep.moveTo(target);
      return;
    }
  } else {
    const storages = creep.room.find(FIND_STRUCTURES, {
      filter: i => i.structureType == STRUCTURE_CONTAINER
    });
    storages.sort((a,b) => b.store[RESOURCE_ENERGY] - a.store[RESOURCE_ENERGY]);
    if (storages.length > 0) {
      if (creep.withdraw(storages[0], RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
        creep.moveTo(storages[0]);
      }
    }
  }
}

module.exports = {
  run: function(creep) {
    if ((creep.room.lookForAt(LOOK_STRUCTURES, creep).length == 0) && (creep.room.lookForAt(LOOK_CONSTRUCTION_SITES, creep).length == 0)) {
      creep.room.createConstructionSite(creep, STRUCTURE_ROAD);
    }
    if (creep.memory.mode == 'refuel') {
      if (_.sum(creep.carry) == creep.carryCapacity) {
        creep.memory.mode = 'deliver';
        doDelivery(creep);
      } else {
        doRefuel(creep);
      }
    } else {
       if (creep.carry[RESOURCE_ENERGY] == 0) {
         creep.memory.mode = 'refuel';
         doRefuel(creep);
       } else {
         doDelivery(Creep);
       }
    }
  },
  bodyparts: [MOVE, MOVE, CARRY, CARRY]
};
<|endoftext|>


<commit_before>/**
 * Created by truthlighting on 9/14/2016.
 */
var roleHauler = {

    /** @param {Creep} creep **/

    run: function(creep) {

        var notEmptyContainers = creep.room.find(FIND_STRUCTURES, {
                    filter: (structure) => {
                    return (structure.structureType == STRUCTURE_CONTAINER) &&
                           _.sum(structure.store) > 0;
                    }
        })

        var notFullStoragePlaces = creep.room.find(FIND_STRUCTURES, {
                    filter: (structure) => {
                    return (structure.structureType == STRUCTURE_STORAGE) &&
                        (_.sum(structure.store) < structure.storeCapacity)
                    }
        })

        if(creep.memory.transporting && creep.carry.energy == 0) {
            creep.memory.transporting = false;
            creep.say("C-Travelling");
        } else if (!creep.memory.transporting && creep.carry.energy == creep.carryCapacity || ((!creep.pos.findClosestByPath(FIND_SOURCES_ACTIVE)) && creep.carry.energy > 0)) {
            creep.memory.transporting = true;
            creep.say("C-Xporting");
        } else {
            creep.memory.transporting = false;
            creep.memory.idling = true;
            creep.say("C-Idling")
        }

        if (creep.memory.transporting) {
            if (notFullStoragePlaces.length > 0) {
                var notFullStorage = creep.pos.findClosestByPath(notFullStoragePlaces);
                if (creep.transfer(notFullStorage, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(notFullStorage);
                }
            }
        } else if (!creep.memory.idling) {
            if(notEmptyContainers.length > 0) {
                var notEmptyContainer = creep.pos.findClosestByPath(notEmptyContainers);
                if (creep.withdraw(notEmptyContainer, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(notEmptyContainer);
                }
            }
        } else {
            //idle
            var targetFlag = creep.pos.findClosestByPath([Game.flags.Flag1,Game.flags.Flag2]);
            creep.moveTo(targetFlag);
        }
    }
};

module.exports = roleHauler;<commit_msg>fixing logic in hauler<commit_after>/**
 * Created by truthlighting on 9/14/2016.
 */
var roleHauler = {

    /** @param {Creep} creep **/

    run: function(creep) {

        var notEmptyContainers = creep.room.find(FIND_STRUCTURES, {
                    filter: (structure) => {
                    return (structure.structureType == STRUCTURE_CONTAINER) &&
                           structure.store[RESOURCE_ENERGY] > 0;
                    }
        })

        var notFullStoragePlaces = creep.room.find(FIND_STRUCTURES, {
                    filter: (structure) => {
                    return (structure.structureType == STRUCTURE_STORAGE) &&
                        (_.sum(structure.store) < structure.storeCapacity)
                    }
        })

        if(creep.memory.transporting && creep.carry.energy == 0) {
            creep.memory.transporting = false;
            creep.say("C-Travelling");
        } else if (!creep.memory.transporting && creep.carry.energy == creep.carryCapacity || ((!creep.pos.findClosestByPath(notFullStoragePlaces)) && creep.carry.energy > 0)) {
            creep.memory.transporting = true;
            creep.say("C-Xporting");
        } else {
            creep.memory.transporting = false;
            creep.memory.idling = true;
            creep.say("C-Idling")
        }

        if (creep.memory.transporting) {
            if (notFullStoragePlaces.length > 0) {
                var notFullStorage = creep.pos.findClosestByPath(notFullStoragePlaces);
                if (creep.transfer(notFullStorage, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(notFullStorage);
                }
            }
        } else if (!creep.memory.idling) {
            if(notEmptyContainers.length > 0) {
                var notEmptyContainer = creep.pos.findClosestByPath(notEmptyContainers);
                if (creep.withdraw(notEmptyContainer, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) {
                    creep.moveTo(notEmptyContainer);
                }
            }
        } else {
            //idle
            var targetFlag = creep.pos.findClosestByPath([Game.flags.Flag1,Game.flags.Flag2]);
            creep.moveTo(targetFlag);
        }
    }
};

module.exports = roleHauler;<|endoftext|>


<commit_before>/**
 * Created by Freddy on 14/12/14.
 */
(function() {
    var NS              = null;

    var _l              = null;
    var request         = null;

    var __isNode = (typeof module !== 'undefined' && typeof module.exports !== 'undefined');
    if (__isNode) {
        var jsface      = require("jsface");
        var Class       = jsface.Class;

        _l              = require('../../logger.js').logger;
        request         = require('superagent');

        NS = exports;
    } else {
        //Add to Visionscapers namespace
        NS              = window.__VI__ || window;

        request         = NS.request || window.request;
    }

    NS.SuperAgentMixin = Class({

        /***************************************************************
         *
         * PROTECTED METHODS
         *
         ***************************************************************/
        /**
         *
         * Method that creates a request so it can be send
         * Used by {{#crossLink "HTTPAPIClient:request"}}{{/crossLink}}
         *
         * This method needs to be overridden by any subclass
         *
         * @method _createRequest
         * @protected
         *
         * @param {String} method       ... HTTP Method name
         * @param {String} url          ... Path to resource
         * @param {Object|null} data    ... data to send
         *
         * @return {Object}             ... request object
         */
        _createRequest : function(method, url, data) {
            var me = this.getName() + "::SuperAgentMixin::_createRequest";

            if (_.hasMethod(request, method)) {
                return request[method](url);
            } else {
                _l.error(me, "Method {0} is not supported, unable to create request".fmt(method));
                return null;
            }
        },

        /**
         *
         * Method that sends requests
         * Used by {{#crossLink "HTTPAPIClient:request"}}{{/crossLink}}
         *
         * This method needs to be overridden by any subclass
         *
         * @method _sendRequest
         * @protected
         *
         * @param {Object} req                          ... Request object.
         *                                                  See {{#crossLink "HTTPAPIClient:_createRequest"}}{{/crossLink}}
         * @param {HTTPAPIClient~ResponseCB} responseCb ... Callback function(data, err) on response
         *
         * @return {Boolean}                            ... True when sending of the request was successful, else false
         *
         */
        _sendRequest : function(req, responseCb) {
            var me      = this.getName() + "::SuperAgentMixin::_sendRequest";
            var success = false;

            if (!_.hasMethod(req, 'end')) {
                _l.error(me, "Request method does not have the expected end method, unable to send request");
                return success;
            }

            req.end(function(err, data) {
                responseCb(data, err);
            });

            success = true;
            return success;
        }
    });
})();
<commit_msg>Updated super agent API mixin to deal with changes in HTTPAPIClient + fixed error response handling<commit_after>/**
 * Created by Freddy on 14/12/14.
 */
(function() {
    var NS              = null;

    var _l              = null;
    var _               = null;
    var Class           = null;
    var request         = null;

    var __isNode = (typeof module !== 'undefined' && typeof module.exports !== 'undefined');
    if (__isNode) {
        var jsface      = require("jsface");

        _               = require('../../util.js').utils;
        _l              = require('../../logger.js').logger;

        request         = require('superagent');
        Class           = jsface.Class;

        NS              = exports;
    } else {
        //Add to Visionscapers namespace
        NS              = window.__VI__ || window;

        _               = NS.utils;
        _l              = NS.logger;

        request         = NS.request || window.request;
        Class           = window.jsface.Class;
    }

    NS.SuperAgentMixin = Class({

        /***************************************************************
         *
         * PROTECTED METHODS
         *
         ***************************************************************/
        /**
         *
         * Method that creates a request so it can be send
         * Used by {{#crossLink "HTTPAPIClient:request"}}{{/crossLink}}
         *
         * This method needs to be overridden by any subclass
         *
         * @method _createRequest
         * @protected
         *
         * @param {String} method       ... HTTP Method name
         * @param {String} url          ... Path to resource
         * @param {Object|null} data    ... data to send
         *
         * @return {Object}             ... request object
         */
        _createRequest : function(method, url, data) {
            var me  = this.getName() + "::SuperAgentMixin::_createRequest";
            var req = null;

            if (_.hasMethod(superagent, method)) {
                req = superagent[method](url);
                req.set('Content-Type', 'application/json')
                   .set('Accept', 'application/json');

                return req;
            } else {
                _l.error(me, "Method {0} is not supported, unable to create request".fmt(method));
                return null;
            }
        },

        /**
         *
         * Method that sends requests
         * Used by {{#crossLink "HTTPAPIClient:request"}}{{/crossLink}}
         *
         * This method needs to be overridden by any subclass
         *
         * @method _sendRequest
         * @protected
         *
         * @param {Object} req                          ... Request object.
         *                                                  See {{#crossLink "HTTPAPIClient:_createRequest"}}{{/crossLink}}
         * @param {Function} internalResponseCb         ... Callback function(data, err, status, headers) on response
         *
         * @return {Boolean}                            ... True when sending of the request was successful, else false
         *
         * @protected
         */
        _sendRequest : function(req, internalResponseCb) {
            var me      = this.getName() + "::SuperAgentMixin::_sendRequest";
            var success = false;

            internalResponseCb = _.ensureFunc(internalResponseCb);

            if (!_.hasMethod(req, 'end')) {
                _l.error(me, "Request method does not have the expected end method, unable to send request");
                return success;
            }

            req.end(function(_err, _data) {
                var data = null;
                var err  = null;

                if (_.def(_err)) {
                    err = _err;
                    internalResponseCb(data, err, -1);
                    return;
                }

                _data = _data || {};

                var SAError = _data.error;
                if (_.obj(SAError)) {
                    err = {
                        message : SAError.message || "UNKNOWN ERROR",
                        status  : _data.status
                    };

                    internalResponseCb(data, err, _data.status, _data.headers);
                    return;
                }

                data = _data.body;
                internalResponseCb(data, err, _data.status, _data.headers);
            });

            success = true;
            return success;
        }
    });
})();
<|endoftext|>


<commit_before>function find(data, args) {
	/*
	Context: Given a JS object and a string, return as if string was an eval
	Example: find({"names": {"john":5, "stacy":34}}, ["names", "john"]) => 5}

	This is actually a cool little piece of code IMO. The recursion loops through each argument and applys them one by one to the data
	*/
	if (args.length === 0){
		return data;
	}

	return find(data[args.shift()], args);
}

request = {

	error: function (msg) {
		return {'status': 'error', "data": msg}
	},

	// Get request
	get: function(table, query) {
		// If it's just a table, they want a table.
		if (query === undefined) {
			return table;
		}

		// Else, they have an actual request
		else {
			return find(table, query);
		}
	},

	// Put request
	put: function(table, query) {
		if (query === undefined || query.length != 2) {
			return error("bad query");
		}

		else {

			return table;
		}
	},

	// Save request
	save: function(table) {
		return "failed";
	}
}

module.exports = request;<commit_msg>Added a note to myself for later<commit_after>function find(data, args) {
	/*
	Context: Given a JS object and a string, return as if string was an eval
	Example: find({"names": {"john":5, "stacy":34}}, ["names", "john"]) => 5}

	This is actually a cool little piece of code IMO. The recursion loops through each argument and applys them one by one to the data
	*/
	if (args.length === 0){
		return data;
	}

	return find(data[args.shift()], args);
}

request = {

	error: function (msg) {
		return {'status': 'error', "data": msg}
	},

	// Get request
	get: function(table, query) {
		// If it's just a table, they want a table.
		if (query === undefined) {
			return table;
		}

		// Else, they have an actual request
		else {
			return find(table, query);
		}
	},

	// Put request
	put: function(table, query) {
		if (query === undefined || query.length != 2) {
			return error("bad query");
		}

		else {
			//REUSE FIND CODE WITH SET. every level "equals" the next, until we hit path, then equals to args
		}
	},

	// Save request
	save: function(table) {
		return "failed";
	}
}

module.exports = request;<|endoftext|>


<commit_before>import { DefaultDOMElement } from '../dom'
import { platform } from '../util'
import { Document, HTMLImporter, JSONConverter } from '../model'

const INLINENODES = ['a','b','big','i','small','tt','abbr','acronym','cite','code','dfn','em','kbd','strong','samp','time','var','bdo','br','img','map','object','q','script','span','sub','sup','button','input','label','select','textarea'].reduce((m,n)=>{m[n]=true;return m}, {})

/**
  Import HTML from clipboard. Used for inter-application copy'n'paste.

  @internal
*/
export default
class ClipboardImporter extends HTMLImporter {

  constructor(config) {
    super(_withCatchAllConverter(config))
    // disabling warnings about default importers
    this.IGNORE_DEFAULT_WARNINGS = true

    Object.assign(config, {
      trimWhitespaces: true,
      REMOVE_INNER_WS: true
    })

    // ATTENTION: this is only here so we can enfore windows conversion
    // mode from within tests
    this._isWindows = platform.isWindows
    this.editorOptions = config.editorOptions
  }

  /**
    Parses HTML and applies some sanitization/normalization.
  */
  importDocument(html) {
    if (this._isWindows) {
      // Under windows we can exploit  and
      // to have an easier life
      let match = /(.*)/.exec(html)
      if (match) {
        html = match[1]
      }
    }

    // when copying from a substance editor we store JSON in a script tag in the head
    // If the import fails e.g. because the schema is incompatible
    // we fall back to plain HTML import
    if (html.search(/script id=.substance-clipboard./)>=0) {
      let htmlDoc = DefaultDOMElement.parseHTML(html)
      let substanceData = htmlDoc.find('#substance-clipboard')
      if (substanceData) {
        let jsonStr = substanceData.textContent
        try {
          return this.importFromJSON(jsonStr)
        } finally {
          // nothing
        }
      }
    }

    if (this.editorOptions && this.editorOptions['forcePlainTextPaste']) {
      return null;
    }

    let htmlDoc = DefaultDOMElement.parseHTML(html)
    let body = htmlDoc.find('body')
    body = this._sanitizeBody(body)
    if (!body) {
      console.warn('Invalid HTML.')
      return null
    }
    this._wrapIntoParagraph(body)
    this.reset()
    this.convertBody(body)
    const doc = this.state.doc
    return doc
  }

  _sanitizeBody(body) {
    body = this._fixupGoogleDocsBody(body)
    // Remove <meta> element
    body.findAll('meta').forEach(el => el.remove())
    return body
  }

  _fixupGoogleDocsBody(body) {
    if (!body) return
    // Google Docs has a strange convention to use a bold tag as
    // container for the copied elements
    // HACK: we exploit the fact that this element has an id with a
    // specific format, e.g., id="docs-internal-guid-5bea85da-43dc-fb06-e327-00c1c6576cf7"
    let bold = body.find('b')
    if (bold && /^docs-internal/.exec(bold.id)) {
      body = bold
    }

    body.findAll('span').forEach(span => {
      // Google Docs uses spans with inline styles
      // insted of inline nodes
      // We are scanning each span for certain inline styles:
      // font-weight: 700 ->
      // font-style: italic ->
      // vertical-align: super ->
      // vertical-align: sub ->

      let nodeTypes = []
      if(span.getStyle('font-weight') === '700') nodeTypes.push('b')
      if(span.getStyle('font-style') === 'italic') nodeTypes.push('i')
      if(span.getStyle('vertical-align') === 'super') nodeTypes.push('sup')
      if(span.getStyle('vertical-align') === 'sub') nodeTypes.push('sub')

      function createInlineNodes(parentEl, isRoot) {
        if(nodeTypes.length > 0) {
          let el = parentEl.createElement(nodeTypes[0])
          if(nodeTypes.length === 1) el.append(span.textContent)

          if(isRoot) {
            parentEl.replaceChild(span, el)
          } else {
            parentEl.appendChild(el)
          }

          nodeTypes.shift()
          createInlineNodes(el)
        }
      }

      createInlineNodes(span.getParent(), true)
    })

    let tags = ['b', 'i', 'sup', 'sub']

    tags.forEach(tag => {
      body.findAll(tag).forEach(el => {
        // Union siblings with the same tags, e.g. we are turning
        // strong to strong
        let previousSiblingEl = el.getPreviousSibling()
        if(previousSiblingEl && el.tagName === previousSiblingEl.tagName) {
          let parentEl = el.getParent()
          let newEl = parentEl.createElement(tag)
          newEl.setInnerHTML(previousSiblingEl.getInnerHTML() + el.getInnerHTML())
          parentEl.replaceChild(el, newEl)
          parentEl.removeChild(previousSiblingEl)
        }

        // Union siblings and child with the same tags, e.g. we are turning
        // emphasis to emphasis
        // Note that at this state children always have the same text content
        // e.g. there can't be cases like emph asis so we don't treat them
        if(previousSiblingEl && previousSiblingEl.tagName && el.getChildCount() > 0 && el.getChildAt(0).tagName === previousSiblingEl.tagName) {
          let parentEl = el.getParent()
          let childEl = el.getChildAt(0)
          let newEl = parentEl.createElement(previousSiblingEl.tagName)
          let newChildEl = newEl.createElement(tag)
          newChildEl.setTextContent(childEl.textContent)
          newEl.appendChild(newChildEl)
          parentEl.replaceChild(el, newEl)
        }
      })
    })

    return body
  }

  _wrapIntoParagraph(body) {
    let childNodes = body.getChildNodes()
    let shouldWrap = false
    for (let i = 0; i < childNodes.length; i++) {
      const c = childNodes[i]
      if (c.isTextNode()) {
        if (!(/^\s+$/.exec(c.textContent))) {
          shouldWrap = true
          break
        }
      } else if (INLINENODES[c.tagName]) {
        shouldWrap = true
        break
      }
    }
    if (shouldWrap) {
      let p = body.createElement('p')
      p.append(childNodes)
      body.append(p)
    }
  }

  importFromJSON(jsonStr) {
    this.reset()
    let doc = this.getDocument()
    let jsonData = JSON.parse(jsonStr)
    let converter = new JSONConverter()
    converter.importDocument(doc, jsonData)
    return doc
  }

  /**
    Converts all children of a given body element.

    @param {String} body body element of given HTML document
  */
  convertBody(body) {
    this.convertContainer(body.childNodes, Document.SNIPPET_ID)
  }

  /**
    Creates substance document to paste.

    @return {Document} the document instance
  */
  _createDocument() {
    let emptyDoc = super._createDocument()
    return emptyDoc.createSnippet()
  }
}

function _withCatchAllConverter(config) {
  config = Object.assign({}, config)
  let defaultTextType = config.schema.getDefaultTextType()
  config.converters = config.converters.concat([{
    type: defaultTextType,
    matchElement: function(el) { return el.is('div') },
    import: function(el, node, converter) {
      node.content = converter.annotatedText(el, [node.id, 'content'])
    }
  }])
  return config
}
<commit_msg>Replace new line with spaces for LibreOffice generator.<commit_after>import { DefaultDOMElement } from '../dom'
import { platform } from '../util'
import { Document, HTMLImporter, JSONConverter } from '../model'

const INLINENODES = ['a','b','big','i','small','tt','abbr','acronym','cite','code','dfn','em','kbd','strong','samp','time','var','bdo','br','img','map','object','q','script','span','sub','sup','button','input','label','select','textarea'].reduce((m,n)=>{m[n]=true;return m}, {})

/**
  Import HTML from clipboard. Used for inter-application copy'n'paste.

  @internal
*/
export default
class ClipboardImporter extends HTMLImporter {

  constructor(config) {
    super(_withCatchAllConverter(config))
    // disabling warnings about default importers
    this.IGNORE_DEFAULT_WARNINGS = true

    Object.assign(config, {
      trimWhitespaces: true,
      REMOVE_INNER_WS: true
    })

    // ATTENTION: this is only here so we can enfore windows conversion
    // mode from within tests
    this._isWindows = platform.isWindows
    this.editorOptions = config.editorOptions
  }

  /**
    Parses HTML and applies some sanitization/normalization.
  */
  importDocument(html) {
    if (this._isWindows) {
      // Under windows we can exploit  and
      // to have an easier life
      let match = /(.*)/.exec(html)
      if (match) {
        html = match[1]
      }
    }

    // when copying from a substance editor we store JSON in a script tag in the head
    // If the import fails e.g. because the schema is incompatible
    // we fall back to plain HTML import
    if (html.search(/script id=.substance-clipboard./)>=0) {
      let htmlDoc = DefaultDOMElement.parseHTML(html)
      let substanceData = htmlDoc.find('#substance-clipboard')
      if (substanceData) {
        let jsonStr = substanceData.textContent
        try {
          return this.importFromJSON(jsonStr)
        } finally {
          // nothing
        }
      }
    }

    if (this.editorOptions && this.editorOptions['forcePlainTextPaste']) {
      return null;
    }

    let htmlDoc = DefaultDOMElement.parseHTML(html)
    let generatorMeta = htmlDoc.find('meta[name="generator"]')
    if(generatorMeta) {
      let generator = generatorMeta.getAttribute('content')
      if(generator.indexOf('LibreOffice') > -1) this._isLibreOffice = true
    }

    let body = htmlDoc.find('body')
    body = this._sanitizeBody(body)
    if (!body) {
      console.warn('Invalid HTML.')
      return null
    }
    this._wrapIntoParagraph(body)
    this.reset()
    this.convertBody(body)
    const doc = this.state.doc
    return doc
  }

  _sanitizeBody(body) {
    body = this._fixupGoogleDocsBody(body)
    // Remove <meta> element
    body.findAll('meta').forEach(el => el.remove())

    // Some word processors are exporting new lines instead of spaces
    // for these editors we will replace all new lines with space
    if(this._isLibreOffice) {
      let bodyHtml = body.getInnerHTML()
      body.setInnerHTML(bodyHtml.replace(/\n/g, ' '))
    }

    return body
  }

  _fixupGoogleDocsBody(body) {
    if (!body) return
    // Google Docs has a strange convention to use a bold tag as
    // container for the copied elements
    // HACK: we exploit the fact that this element has an id with a
    // specific format, e.g., id="docs-internal-guid-5bea85da-43dc-fb06-e327-00c1c6576cf7"
    let bold = body.find('b')
    if (bold && /^docs-internal/.exec(bold.id)) {
      body = bold
    }

    body.findAll('span').forEach(span => {
      // Google Docs uses spans with inline styles
      // insted of inline nodes
      // We are scanning each span for certain inline styles:
      // font-weight: 700 ->
      // font-style: italic ->
      // vertical-align: super ->
      // vertical-align: sub ->

      let nodeTypes = []
      if(span.getStyle('font-weight') === '700') nodeTypes.push('b')
      if(span.getStyle('font-style') === 'italic') nodeTypes.push('i')
      if(span.getStyle('vertical-align') === 'super') nodeTypes.push('sup')
      if(span.getStyle('vertical-align') === 'sub') nodeTypes.push('sub')

      function createInlineNodes(parentEl, isRoot) {
        if(nodeTypes.length > 0) {
          let el = parentEl.createElement(nodeTypes[0])
          if(nodeTypes.length === 1) el.append(span.textContent)

          if(isRoot) {
            parentEl.replaceChild(span, el)
          } else {
            parentEl.appendChild(el)
          }

          nodeTypes.shift()
          createInlineNodes(el)
        }
      }

      createInlineNodes(span.getParent(), true)
    })

    let tags = ['b', 'i', 'sup', 'sub']

    tags.forEach(tag => {
      body.findAll(tag).forEach(el => {
        // Union siblings with the same tags, e.g. we are turning
        // strong to strong
        let previousSiblingEl = el.getPreviousSibling()
        if(previousSiblingEl && el.tagName === previousSiblingEl.tagName) {
          let parentEl = el.getParent()
          let newEl = parentEl.createElement(tag)
          newEl.setInnerHTML(previousSiblingEl.getInnerHTML() + el.getInnerHTML())
          parentEl.replaceChild(el, newEl)
          parentEl.removeChild(previousSiblingEl)
        }

        // Union siblings and child with the same tags, e.g. we are turning
        // emphasis to emphasis
        // Note that at this state children always have the same text content
        // e.g. there can't be cases like emph asis so we don't treat them
        if(previousSiblingEl && previousSiblingEl.tagName && el.getChildCount() > 0 && el.getChildAt(0).tagName === previousSiblingEl.tagName) {
          let parentEl = el.getParent()
          let childEl = el.getChildAt(0)
          let newEl = parentEl.createElement(previousSiblingEl.tagName)
          let newChildEl = newEl.createElement(tag)
          newChildEl.setTextContent(childEl.textContent)
          newEl.appendChild(newChildEl)
          parentEl.replaceChild(el, newEl)
        }
      })
    })

    return body
  }

  _wrapIntoParagraph(body) {
    let childNodes = body.getChildNodes()
    let shouldWrap = false
    for (let i = 0; i < childNodes.length; i++) {
      const c = childNodes[i]
      if (c.isTextNode()) {
        if (!(/^\s+$/.exec(c.textContent))) {
          shouldWrap = true
          break
        }
      } else if (INLINENODES[c.tagName]) {
        shouldWrap = true
        break
      }
    }
    if (shouldWrap) {
      let p = body.createElement('p')
      p.append(childNodes)
      body.append(p)
    }
  }

  importFromJSON(jsonStr) {
    this.reset()
    let doc = this.getDocument()
    let jsonData = JSON.parse(jsonStr)
    let converter = new JSONConverter()
    converter.importDocument(doc, jsonData)
    return doc
  }

  /**
    Converts all children of a given body element.

    @param {String} body body element of given HTML document
  */
  convertBody(body) {
    this.convertContainer(body.childNodes, Document.SNIPPET_ID)
  }

  /**
    Creates substance document to paste.

    @return {Document} the document instance
  */
  _createDocument() {
    let emptyDoc = super._createDocument()
    return emptyDoc.createSnippet()
  }
}

function _withCatchAllConverter(config) {
  config = Object.assign({}, config)
  let defaultTextType = config.schema.getDefaultTextType()
  config.converters = config.converters.concat([{
    type: defaultTextType,
    matchElement: function(el) { return el.is('div') },
    import: function(el, node, converter) {
      node.content = converter.annotatedText(el, [node.id, 'content'])
    }
  }])
  return config
}
<|endoftext|>


<commit_before>var current_page = 0;
var num_result = 0;

function handlePaginationClick(new_page_index, pagination_container) {
	if(new_page_index != current_page){
		var items_per_page = parseInt($("#num_hits").val());

		var cqp 	= $("#cqp_string").val();
		var corpus 	= $("#corpus_id").val();

		var start 	= new_page_index*items_per_page;
		var end 		= (start + items_per_page);

		makeRequest(cqp, corpus, start, end);
		current_page = new_page_index;
	}

   return false;
}

function makeRequest(cqp, corpus, start, end){
	$('#results').html(language.loading);

	var selected_corpus = settings.corpora[getCorpus()];
	var attributes = ['msd','lemma'];

	var data = {
					command:'query',
					corpus:corpus,
					cqp:cqp,
					start:start,
					end:end,
					context:'1 sentence',
					show:[],
				};

	$.each(selected_corpus.attributes, function(key,val){
		data.show.push(key);
	})

	$.ajax({ url: settings.cgi_script+'?callback=?',
				dataType: "jsonp",
				data:data,
				traditional:true,
				success: corpus_results});

	setJsonLink(data);
}

function setJsonLink(data){
	$.ajaxSetup({ traditional: true }); //fix the problem with show[]=...
	url = url.replace(/\[\]/g,"");
	$('#json-link').attr('href', url);
	$('#json-link').css('display', 'inline');
}

function submitFormToServer(){
	num_result = 0;
	$('#results').html(language.loading);

	var cqp 	= $("#cqp_string").val();
	var corpus 	= $("#corpus_id").val();

	var start 	= 0;
	var end 	= $("#num_hits").val()-1;

	makeRequest(cqp, corpus, start, end);

	$('#results-wraper').css('display', 'block');
}

function buildPager(number_of_hits){
	var items_per_page = $("#num_hits").val();

	if(number_of_hits > items_per_page){
		$("#Pagination").pagination(number_of_hits, {
			items_per_page:items_per_page,
			callback:handlePaginationClick,
			next_text: language.next,
			prev_text: language.prev,
			link_to:"#",
			num_edge_entries:2,
			ellipse_text: '..'
		});
	}else{
		$("#Pagination").html('');
	}
}

function corpus_results(data){

	var corpus = settings.corpora[getCorpus()];

	//if this is the first result-set
	if(num_result == 0){
		buildPager(data.hits);
	}
	$('#num-result').html(data.hits);
	num_result = data.hits;

	var output = '

';

	$.each(data.kwic, function(i,item){
		output += '
';
		if(corpus.attributes.sentence != null)
			output += '	';

		/*Left */
		output += '';

		var from = 0;
		if(item.match.start > 12)
			from = item.match.start-12;
		for (var i = from; i < item.match.start; i++) {
			output +='';
			output +=''+item.tokens[i].word+' ';

			$.each(corpus.attributes, function(key,val){
				if(item.tokens[i][key] != null){
					output +=''+item.tokens[i][key]+' ';
				}
			})
			output +='';
		}
		output += '	';

		/*Match */
		output += '';
		for (var i = item.match.start; i < item.match.end; i++) {
			output +='';
			output +=''+item.tokens[i].word+' ';

			$.each(corpus.attributes, function(key,val){
				if(item.tokens[i][key] != null){
					output +=''+item.tokens[i][key]+' ';
				}
			})
			output +='';
		}
		output += '	';

		/*Right */
		var len=item.tokens.length;

		var to = len;
		if((len-item.match.end) > 12)
			to = item.match.end+12;

		output += '';
		for (var i = item.match.end; i < to; i++) {
			output +='';
			output +=''+item.tokens[i].word+' ';

			$.each(corpus.attributes, function(key,val){
				if(item.tokens[i][key] != null){
					output +=''+item.tokens[i][key]+' ';
				}
			})
			output +='';
		}
		output += '
';
	});

	output += '

';
	$('#results').html(output);

	//show selected attributes
	$.each(corpus.attributes, function(key,val){
		if($('input[value='+key+']').is(':checked')){
			$('.'+key).css('display', 'inline');
		}
	})

	$('.result_table tr:even').addClass('alt');

	$('.token').hover(
			function(){
				console.log('in '+$(this).html());
				$(this).addClass('token_hover');
			},
			function(){
				console.log('out '+$(this).html());
				$(this).removeClass('token_hover');
			}
	);
}

function tooltipIn(object){
	//
	console.log('in'+$(object).html());
}

function tooltipOut(object){
	console.log('out');
}

function renderToken(token){
	var output = ''+token.word+''+token.word+''+tokens.lemma+' ';
	return output;
}

/*******************
 * Read args
 */
$(document).ready(function(){
	//var vars = $.getUrlVars();
	//alert(vars['word']);
	//$('.arg_value').value(vars['word']);

});

// Read a page's GET URL variables and return them as an associative array.
$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

$.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/;
  while(x<c.length){var m=r.exec(c.substr(x));
    if(m!=null && m.length>1 && m[1]!=''){o+=m[1];x+=m[1].length;
    }else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16);
    o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;},
URLDecode:function(s){var o=s;var binVal,t;var r=/(%[^%]{2})/;
  while((m=r.exec(o))!=null && m.length>1 && m[1]!=''){b=parseInt(m[1].substr(1),16);
  t=String.fromCharCode(b);o=o.replace(m[1],t);}return o;}
});

<commit_msg><commit_after>var current_page = 0;
var num_result = 0;

function handlePaginationClick(new_page_index, pagination_container) {
	if(new_page_index != current_page){
		var items_per_page = parseInt($("#num_hits").val());

		var cqp 	= $("#cqp_string").val();
		var corpus 	= $("#corpus_id").val();

		var start 	= new_page_index*items_per_page;
		var end 		= (start + items_per_page);

		makeRequest(cqp, corpus, start, end);
		current_page = new_page_index;
	}

   return false;
}

function makeRequest(cqp, corpus, start, end){
	$('#results').html(language.loading);

	var selected_corpus = settings.corpora[getCorpus()];
	var attributes = ['msd','lemma'];

	var data = {
					command:'query',
					corpus:corpus,
					cqp:cqp,
					start:start,
					end:end,
					context:'1 sentence',
					show:[],
				};

	$.each(selected_corpus.attributes, function(key,val){
		data.show.push(key);
	})

	$.ajax({ url: settings.cgi_script+'?callback=?',
				dataType: "jsonp",
				data:data,
				traditional:true,
				success: corpus_results});

	setJsonLink(data);
}

function setJsonLink(data){
	$.ajaxSetup({ traditional: true }); //fix the problem with show[]=...
	$('#json-link').attr('href', url);
	$('#json-link').css('display', 'inline');
}

function submitFormToServer(){
	num_result = 0;
	$('#results').html(language.loading);

	var cqp 	= $("#cqp_string").val();
	var corpus 	= $("#corpus_id").val();

	var start 	= 0;
	var end 	= $("#num_hits").val()-1;

	makeRequest(cqp, corpus, start, end);

	$('#results-wraper').css('display', 'block');
}

function buildPager(number_of_hits){
	var items_per_page = $("#num_hits").val();

	if(number_of_hits > items_per_page){
		$("#Pagination").pagination(number_of_hits, {
			items_per_page:items_per_page,
			callback:handlePaginationClick,
			next_text: language.next,
			prev_text: language.prev,
			link_to:"#",
			num_edge_entries:2,
			ellipse_text: '..'
		});
	}else{
		$("#Pagination").html('');
	}
}

function corpus_results(data){

	var corpus = settings.corpora[getCorpus()];

	//if this is the first result-set
	if(num_result == 0){
		buildPager(data.hits);
	}
	$('#num-result').html(data.hits);
	num_result = data.hits;

	var output = '

';

	$.each(data.kwic, function(i,item){
		output += '
';
		if(corpus.attributes.sentence != null)
			output += '	';

		/*Left */
		output += '';

		var from = 0;
		if(item.match.start > 12)
			from = item.match.start-12;
		for (var i = from; i < item.match.start; i++) {
			output +='';
			output +=''+item.tokens[i].word+' ';

			$.each(corpus.attributes, function(key,val){
				if(item.tokens[i][key] != null){
					output +=''+item.tokens[i][key]+' ';
				}
			})
			output +='';
		}
		output += '	';

		/*Match */
		output += '';
		for (var i = item.match.start; i < item.match.end; i++) {
			output +='';
			output +=''+item.tokens[i].word+' ';

			$.each(corpus.attributes, function(key,val){
				if(item.tokens[i][key] != null){
					output +=''+item.tokens[i][key]+' ';
				}
			})
			output +='';
		}
		output += '	';

		/*Right */
		var len=item.tokens.length;

		var to = len;
		if((len-item.match.end) > 12)
			to = item.match.end+12;

		output += '';
		for (var i = item.match.end; i < to; i++) {
			output +='';
			output +=''+item.tokens[i].word+' ';

			$.each(corpus.attributes, function(key,val){
				if(item.tokens[i][key] != null){
					output +=''+item.tokens[i][key]+' ';
				}
			})
			output +='';
		}
		output += '
';
	});

	output += '

';
	$('#results').html(output);

	//show selected attributes
	$.each(corpus.attributes, function(key,val){
		if($('input[value='+key+']').is(':checked')){
			$('.'+key).css('display', 'inline');
		}
	})

	$('.result_table tr:even').addClass('alt');

	$('.token').hover(
			function(){
				console.log('in '+$(this).html());
				$(this).addClass('token_hover');
			},
			function(){
				console.log('out '+$(this).html());
				$(this).removeClass('token_hover');
			}
	);
}

function tooltipIn(object){
	//
	console.log('in'+$(object).html());
}

function tooltipOut(object){
	console.log('out');
}

function renderToken(token){
	var output = ''+token.word+''+token.word+''+tokens.lemma+' ';
	return output;
}

/*******************
 * Read args
 */
$(document).ready(function(){
	//var vars = $.getUrlVars();
	//alert(vars['word']);
	//$('.arg_value').value(vars['word']);

});

// Read a page's GET URL variables and return them as an associative array.
$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

$.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/;
  while(x<c.length){var m=r.exec(c.substr(x));
    if(m!=null && m.length>1 && m[1]!=''){o+=m[1];x+=m[1].length;
    }else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16);
    o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;},
URLDecode:function(s){var o=s;var binVal,t;var r=/(%[^%]{2})/;
  while((m=r.exec(o))!=null && m.length>1 && m[1]!=''){b=parseInt(m[1].substr(1),16);
  t=String.fromCharCode(b);o=o.replace(m[1],t);}return o;}
});

<|endoftext|>


<commit_before>CT.stream.Video = CT.Class({
	CLASSNAME: "CT.stream.Video",
	_buffers: [],
	_lastTime: 0,
	_nextChunk: 0,
	_sourceOpen: function() {
		this.log("sourceopen");
		this.setSourceBuffer();
	},
	_sourceUpdate: function() {
		this.log("_sourceUpdate", this._buffers.length,
			(this.sourceBuffer && this.sourceBuffer.updating));//, this.mediaSource.readyState);
		if (this.video.error) {
			this.log("ERROR - RESET video");
			this.reset();
		} else if (this.sourceBuffer && !this.sourceBuffer.updating) {
			if (this._buffers.length)
				this.sourceBuffer.appendBuffer(this._buffers.shift());
			else if (this.mediaSource.readyState == "open")
				this.mediaSource.endOfStream();
		}
	},
	_error: function(e) {
		this.log("ERROR RESET", e.message, e.target.error);
		this.reset();
	},
	setSourceBuffer: function() {
		var mt = this.opts.mimeType;
		this.log("setSourceBuffer - exists:", !!this.sourceBuffer, "mimeType", mt);
		if (!this.sourceBuffer) {
			this.sourceBuffer = this.mediaSource.addSourceBuffer(mt);
			this.sourceBuffer.mode = 'sequence';
			this.sourceBuffer.addEventListener("updateend", this._sourceUpdate);
			this.sourceBuffer.addEventListener("error", this._error);
		}
	},
	bufferer: function(buffer) {
		var v = this.video;
		this._buffers.push(buffer);
		this._sourceUpdate();

		if (v.duration != Infinity && !isNaN(v.duration)) {
			if (this._duration == v.duration)
				this.reset();
			this._duration = v.duration;
			var target = v.duration - (CT.stream.opts.chunk / 1000);
			if (v.currentTime < this._lastTime) {
				this.log("SKIPPED RESET (backtracking)");
//				that.reset();
			}
			this._lastTime = v.currentTime;
			if (!v.paused && v.currentTime < target)
				v.currentTime = target;
		}
	},
	process: function(blob) {
		this.recorder && this.recorder.remember(blob);
		CT.stream.util.blob_to_buffer(blob, this.bufferer);
	},
	start: function() {
		this.log("start (attempting) - paused:", this.video.paused);
		var that = this, prom = this.video.play();
		prom && prom.then(function() {
			that.log("started!!! streaming!");
		})["catch"](function(error) {
			that.log("play failed! awaiting user input (android)", error.message);
			if (CT.stream.opts.requiresInput && !CT.stream.opts.requestedInput) {
				that.audio.node && CT.stream.opts.waiting.push(that.audio.node);
				CT.stream.opts.requestedInput = true;
				(new CT.modal.Prompt({
					cb: CT.stream.opts.startWaiting,
					transition: "fade",
					style: "single-choice",
					data: [ "Play Stream" ],
					prompt: "Ready to stream?"
				})).show();
			}
			CT.stream.opts.waiting.push(that.video);
		});
	},
	_miniRecorder: function() {
		var rec = {
			blobs: [],
			remember: function(blob) {
				if (rec.recording)
					rec.blobs.push(blob);
			},
			start: function() {
				rec.recording = true;
			},
			stop: function() {
				rec.recording = false;
			},
			_save: function(blob_or_blobs) {
				var fname = (new Date()).toString().split("-")[0].replace(/\W/g, "") + ".webm",
					ctf = CT.file.make(blob_or_blobs);
				(new CT.modal.Modal({
					content: [
						CT.dom.div("Your file is ready for download!", "bigger pb10"),
						ctf.download(fname, "click me!", "bold centered block")
					]
				})).show();
			},
			save: function() {
				if (CT.stream.opts.transcoder)
					CT.stream.opts.transcoder(rec._save)(new Blob(rec.blobs));
				else
					rec._save(rec.blobs);
				rec.blobs = [];
			}
		};
		return rec;
	},
	save: function() {
		if (this.recorder) { // stop recording
			this._saveButton.firstChild.classList.remove("buttonActive");
			this.recorder.stop();
			this.recorder.save();
			clearTimeout(this._saveTimer);
			delete this._saveTimer;
			delete this.recorder;
		} else {             // start recording
			this._saveButton.firstChild.classList.add("buttonActive");
			this.recorder = this._miniRecorder();
			this.recorder.start();
			this._saveTimer = setTimeout(this.save, CT.stream.opts.cutoff);
		}
	},
	remove: function() {
		this.video.src = "";
		CT.dom.remove(this.node);
		this.audio.remove();
	},
	_wakeup: function() {
		if (this.video._lastct == this.video.currentTime)
			this.video.currentTime += 1; // help video along....
		this.video._lastct = this.video.currentTime;
	},
	setVideo: function() {
		this.video = this.opts.video || CT.dom.video(this.opts.stream,
			this.opts.videoClass, this.opts.videoId, this.opts.attrs);
		this.video.on("canplay", this.start);
		this.video.on("pause", this.start);
		this.video.on("error", this._error);
	},
	setMediaSource: function() {
		this.mediaSource = new MediaSource();
		this.video.src = URL.createObjectURL(this.mediaSource);
		this.mediaSource.addEventListener("sourceopen", this._sourceOpen);
		this.mediaSource.addEventListener("error", this._error);
	},
	fullscreen: function() {
		var v = this.video;
		if (v.requestFullscreen)
			v.requestFullscreen();
		else if (v.webkitRequestFullscreen)
			v.webkitRequestFullscreen();
	},
	switchEncoding: function() {
		var codecs = CT.stream.opts.codecs, oz = this.opts;
		oz.mimeType = (oz.mimeType == codecs.av) ? codecs.video : codecs.av;
		this.log("switching encoding to", oz.mimeType);
	},
	setEncoding: function(mode) {
		var oz = this.opts, prev = oz.mimeType;
		oz.mimeType = CT.stream.opts.modes[mode];
		this.log(mode, "mode:", oz.mimeType);
		if (this.sourceBuffer && oz.mimeType != prev) {
			this.log("mode swap reset!");
			this.reset();
		}
	},
	reset: function() {
		if (!this.video.parentNode) return; //  node is removed -- we're done
		var n = Date.now(), chunk = CT.stream.opts.chunk;
		if (this._lastReset) {
			var diff = n - this._lastReset;
			this.log("RESET", diff);
			if (diff < chunk / 2)
				return; // wait
			if (diff < chunk * 8)
				this.opts.onreset && this.opts.onreset();
		}
		this._lastReset = n;
		this.video.removeEventListener("canplay", this.start);
		this.video.removeEventListener("pause", this.start);
		this.video.removeEventListener("error", this._error);
		this.setVideo();
		this.video.muted = !this.audio.active;
		this.node.insertBefore(this.video, this.node.video);
		CT.dom.remove(this.node.video);
		this.node.video = this.video;
		this.sourceBuffer.removeEventListener("updateend", this._sourceUpdate);
		this.sourceBuffer.removeEventListener("error", this._error);
		delete this.sourceBuffer;
		this.mediaSource.removeEventListener("sourceopen", this._sourceOpen);
		this.mediaSource.removeEventListener("error", this._error);
		this.setMediaSource();
		if (this._buffers.length > 10)
			this._buffers.length = 0;
		else
			this._buffers.shift();
		this.requiredInitChunk = this.receivedInitChunk;
		this.opts.onrefresh && this.opts.onrefresh();
	},
	init: function(opts) {
		this.opts = opts = CT.merge(opts, {
			video: null,
			stream: null,
			className: null,
			id: null,
			frame: true,
			videoClass: null,
			videoId: null,
			watermark: null,
			mimeType: CT.stream.opts.codecs.av,
			activeAudio: false,
			onreset: null,
			buttons: [], // only checked when frame is false
			record: { // recorder always shows when frame is true
				streamer: false,
				lurker: false,
				auto: false
			},
			fullscreen: {
				streamer: false,
				lurker: true
			},
			attrs: {
				autoplay: true
			}
		});
		if (opts.stream)
			opts.attrs.srcObject = opts.stream;
		this.setVideo();
		this.audio = new CT.stream.Audio(opts.activeAudio, this);
		this._fullscreenButton = CT.dom.img("/img/fullscreen.png",
			"defpointer hoverglow w80p", this.fullscreen);
		this._saveButton = CT.dom.img("/img/save.png",
			"defpointer hoverglow w80p", this.save);
		this.node = opts.frame ? CT.dom.div([
			this.video,
			CT.dom.div([
				this.audio.button,
				CT.dom.pad(2),
				this._fullscreenButton,
				CT.dom.pad(2),
				this._saveButton
			], "centered")
		], opts.className, opts.id) : CT.dom.div(this.video, opts.className || "fulldef", opts.id);
		this.node.video = this.video;
		var hasRecorder = opts.record[opts.stream ? "streamer" : "lurker"],
			hasFullscreen = opts.fullscreen[opts.stream ? "streamer" : "lurker"];
		if (!opts.frame) {
			var cbl = CT.dom.div(null, "abs cbl");
			if (hasRecorder)
				cbl.appendChild(this._saveButton);
			if (hasFullscreen) {
				if (cbl.childNodes.length)
					cbl.appendChild(CT.dom.pad());
				cbl.appendChild(this._fullscreenButton);
			}
			opts.buttons.forEach(function(b) {
				if (cbl.childNodes.length)
					cbl.appendChild(CT.dom.pad());
				cbl.appendChild(b);
			});
			if (cbl.childNodes.length)
				this.node.appendChild(cbl);
		}
		hasRecorder && opts.record.auto && this.save();
		if (opts.watermark)
			this.node.appendChild(CT.dom.img(opts.watermark, "abs ctr w1-4 mosthigh nofilt"));
		if (opts.stream)
			this.audio.disable();
		else {
			this.setMediaSource();
			this.audio.build();
			setInterval(this._wakeup, 1000);
		}
	}
});<commit_msg>stream.Video stability improvements: bufferer() shifts playbackRate instead of jumping around; reset() timeout increased from half-chunk to chunk<commit_after>CT.stream.Video = CT.Class({
	CLASSNAME: "CT.stream.Video",
	_buffers: [],
	_lastTime: 0,
	_nextChunk: 0,
	_sourceOpen: function() {
		this.log("sourceopen");
		this.setSourceBuffer();
	},
	_sourceUpdate: function() {
		this.log("_sourceUpdate", this._buffers.length,
			(this.sourceBuffer && this.sourceBuffer.updating));//, this.mediaSource.readyState);
		if (this.video.error) {
			this.log("ERROR - RESET video");
			this.reset();
		} else if (this.sourceBuffer && !this.sourceBuffer.updating) {
			if (this._buffers.length)
				this.sourceBuffer.appendBuffer(this._buffers.shift());
			else if (this.mediaSource.readyState == "open")
				this.mediaSource.endOfStream();
		}
	},
	_error: function(e) {
		this.log("ERROR RESET", e.message, e.target.error);
		this.reset();
	},
	setSourceBuffer: function() {
		var mt = this.opts.mimeType;
		this.log("setSourceBuffer - exists:", !!this.sourceBuffer, "mimeType", mt);
		if (!this.sourceBuffer) {
			this.sourceBuffer = this.mediaSource.addSourceBuffer(mt);
			this.sourceBuffer.mode = 'sequence';
			this.sourceBuffer.addEventListener("updateend", this._sourceUpdate);
			this.sourceBuffer.addEventListener("error", this._error);
		}
	},
	bufferer: function(buffer) {
		var v = this.video;
		this._buffers.push(buffer);
		this._sourceUpdate();

		if (v.duration != Infinity && !isNaN(v.duration)) {
			if (this._duration == v.duration) {
				this.log("DURATION MATCH RESET!!!");
				this.reset();
			}
			this._duration = v.duration;
			var target = v.duration - (CT.stream.opts.chunk / 1000);
			if (v.currentTime < this._lastTime) {
				this.log("SKIPPED RESET (backtracking)");
//				that.reset();
			}
			this._lastTime = v.currentTime;
			if (!v.paused) {
				if (v.currentTime > target)
					v.playbackRate = 0.5;
				else if (v.currentTime < target - 1)
					v.playbackRate = 2; // v.currentTime = target;
				else
					v.playbackRate = 1;
			}
		}
	},
	process: function(blob) {
		this.recorder && this.recorder.remember(blob);
		CT.stream.util.blob_to_buffer(blob, this.bufferer);
	},
	start: function() {
		this.log("start (attempting) - paused:", this.video.paused);
		var that = this, prom = this.video.play();
		prom && prom.then(function() {
			that.log("started!!! streaming!");
		})["catch"](function(error) {
			that.log("play failed! awaiting user input (android)", error.message);
			if (CT.stream.opts.requiresInput && !CT.stream.opts.requestedInput) {
				that.audio.node && CT.stream.opts.waiting.push(that.audio.node);
				CT.stream.opts.requestedInput = true;
				(new CT.modal.Prompt({
					cb: CT.stream.opts.startWaiting,
					transition: "fade",
					style: "single-choice",
					data: [ "Play Stream" ],
					prompt: "Ready to stream?"
				})).show();
			}
			CT.stream.opts.waiting.push(that.video);
		});
	},
	_miniRecorder: function() {
		var rec = {
			blobs: [],
			remember: function(blob) {
				if (rec.recording)
					rec.blobs.push(blob);
			},
			start: function() {
				rec.recording = true;
			},
			stop: function() {
				rec.recording = false;
			},
			_save: function(blob_or_blobs) {
				var fname = (new Date()).toString().split("-")[0].replace(/\W/g, "") + ".webm",
					ctf = CT.file.make(blob_or_blobs);
				(new CT.modal.Modal({
					content: [
						CT.dom.div("Your file is ready for download!", "bigger pb10"),
						ctf.download(fname, "click me!", "bold centered block")
					]
				})).show();
			},
			save: function() {
				if (CT.stream.opts.transcoder)
					CT.stream.opts.transcoder(rec._save)(new Blob(rec.blobs));
				else
					rec._save(rec.blobs);
				rec.blobs = [];
			}
		};
		return rec;
	},
	save: function() {
		if (this.recorder) { // stop recording
			this._saveButton.firstChild.classList.remove("buttonActive");
			this.recorder.stop();
			this.recorder.save();
			clearTimeout(this._saveTimer);
			delete this._saveTimer;
			delete this.recorder;
		} else {             // start recording
			this._saveButton.firstChild.classList.add("buttonActive");
			this.recorder = this._miniRecorder();
			this.recorder.start();
			this._saveTimer = setTimeout(this.save, CT.stream.opts.cutoff);
		}
	},
	remove: function() {
		this.video.src = "";
		CT.dom.remove(this.node);
		this.audio.remove();
	},
	_wakeup: function() {
		if (this.video._lastct == this.video.currentTime)
			this.video.currentTime += 1; // help video along....
		this.video._lastct = this.video.currentTime;
	},
	setVideo: function() {
		this.video = this.opts.video || CT.dom.video(this.opts.stream,
			this.opts.videoClass, this.opts.videoId, this.opts.attrs);
		this.video.on("canplay", this.start);
		this.video.on("pause", this.start);
		this.video.on("error", this._error);
	},
	setMediaSource: function() {
		this.mediaSource = new MediaSource();
		this.video.src = URL.createObjectURL(this.mediaSource);
		this.mediaSource.addEventListener("sourceopen", this._sourceOpen);
		this.mediaSource.addEventListener("error", this._error);
	},
	fullscreen: function() {
		var v = this.video;
		if (v.requestFullscreen)
			v.requestFullscreen();
		else if (v.webkitRequestFullscreen)
			v.webkitRequestFullscreen();
	},
	switchEncoding: function() {
		var codecs = CT.stream.opts.codecs, oz = this.opts;
		oz.mimeType = (oz.mimeType == codecs.av) ? codecs.video : codecs.av;
		this.log("switching encoding to", oz.mimeType);
	},
	setEncoding: function(mode) {
		var oz = this.opts, prev = oz.mimeType;
		oz.mimeType = CT.stream.opts.modes[mode];
		this.log(mode, "mode:", oz.mimeType);
		if (this.sourceBuffer && oz.mimeType != prev) {
			this.log("mode swap reset!");
			this.reset();
		}
	},
	reset: function() {
		if (!this.video.parentNode) return; //  node is removed -- we're done
		var n = Date.now(), chunk = CT.stream.opts.chunk;
		if (this._lastReset) {
			var diff = n - this._lastReset;
			this.log("RESET", diff);
			if (diff < chunk)
				return; // wait
			if (diff < chunk * 8)
				this.opts.onreset && this.opts.onreset();
		}
		this._lastReset = n;
		this.video.removeEventListener("canplay", this.start);
		this.video.removeEventListener("pause", this.start);
		this.video.removeEventListener("error", this._error);
		this.setVideo();
		this.video.muted = !this.audio.active;
		this.node.insertBefore(this.video, this.node.video);
		CT.dom.remove(this.node.video);
		this.node.video = this.video;
		this.sourceBuffer.removeEventListener("updateend", this._sourceUpdate);
		this.sourceBuffer.removeEventListener("error", this._error);
		delete this.sourceBuffer;
		this.mediaSource.removeEventListener("sourceopen", this._sourceOpen);
		this.mediaSource.removeEventListener("error", this._error);
		this.setMediaSource();
		if (this._buffers.length > 10)
			this._buffers.length = 0;
		else
			this._buffers.shift();
		this.requiredInitChunk = this.receivedInitChunk;
		this.opts.onrefresh && this.opts.onrefresh();
	},
	init: function(opts) {
		this.opts = opts = CT.merge(opts, {
			video: null,
			stream: null,
			className: null,
			id: null,
			frame: true,
			videoClass: null,
			videoId: null,
			watermark: null,
			mimeType: CT.stream.opts.codecs.av,
			activeAudio: false,
			onreset: null,
			buttons: [], // only checked when frame is false
			record: { // recorder always shows when frame is true
				streamer: false,
				lurker: false,
				auto: false
			},
			fullscreen: {
				streamer: false,
				lurker: true
			},
			attrs: {
				autoplay: true
			}
		});
		if (opts.stream)
			opts.attrs.srcObject = opts.stream;
		this.setVideo();
		this.audio = new CT.stream.Audio(opts.activeAudio, this);
		this._fullscreenButton = CT.dom.img("/img/fullscreen.png",
			"defpointer hoverglow w80p", this.fullscreen);
		this._saveButton = CT.dom.img("/img/save.png",
			"defpointer hoverglow w80p", this.save);
		this.node = opts.frame ? CT.dom.div([
			this.video,
			CT.dom.div([
				this.audio.button,
				CT.dom.pad(2),
				this._fullscreenButton,
				CT.dom.pad(2),
				this._saveButton
			], "centered")
		], opts.className, opts.id) : CT.dom.div(this.video, opts.className || "fulldef", opts.id);
		this.node.video = this.video;
		var hasRecorder = opts.record[opts.stream ? "streamer" : "lurker"],
			hasFullscreen = opts.fullscreen[opts.stream ? "streamer" : "lurker"];
		if (!opts.frame) {
			var cbl = CT.dom.div(null, "abs cbl");
			if (hasRecorder)
				cbl.appendChild(this._saveButton);
			if (hasFullscreen) {
				if (cbl.childNodes.length)
					cbl.appendChild(CT.dom.pad());
				cbl.appendChild(this._fullscreenButton);
			}
			opts.buttons.forEach(function(b) {
				if (cbl.childNodes.length)
					cbl.appendChild(CT.dom.pad());
				cbl.appendChild(b);
			});
			if (cbl.childNodes.length)
				this.node.appendChild(cbl);
		}
		hasRecorder && opts.record.auto && this.save();
		if (opts.watermark)
			this.node.appendChild(CT.dom.img(opts.watermark, "abs ctr w1-4 mosthigh nofilt"));
		if (opts.stream)
			this.audio.disable();
		else {
			this.setMediaSource();
			this.audio.build();
			setInterval(this._wakeup, 1000);
		}
	}
});<|endoftext|>