<commit_before>var coreFilename = require.resolve('bh/lib/bh.js'),
    EOL = require('os').EOL;

/**
 * @class BHCommonJSTech
 * @augments {BaseTech}
 * @classdesc
 *
 * Compile CommonJS module of BH with requires of core and source templates (bh.js files).

 *
 * Use to apply in server side only (Node.js). You can use `require` in templates.

 *
 * Important: for correct apply the source files and files are specified in `requires` should be in file system.
 *
 * @param {Object}      [options]                           Options
 * @param {String}      [options.target='?.bh.js']          Path to target with compiled file.
 * @param {String}      [options.filesTarget='?.files']     Path to target with FileList.
 * @param {String[]}    [options.sourceSuffixes='bh.js']    Files with specified suffixes involved in the assembly.
 * @param {String[]}    [options.mimic]                     Names to export.
 * @param {Boolean}     [options.devMode=true]              Drop cache for `require` of source templates.
 * @param {String}      [options.jsAttrName='data-bem']     Set `jsAttrName` option for BH core.
 * @param {String}      [options.jsAttrScheme='json']       Set `jsAttrScheme` option for BH core.
 * @param {String}      [options.jsCls='i-bem']             Set `jsCls` option for BH core.
 * @param {Boolean}     [options.jsElem=true]               Set `jsElem` option for BH core.
 * @param {Boolean}     [options.escapeContent=false]       Set `escapeContent` option for BH core.
 *
 * @example
 * var BHCommonJSTech = require('enb-bh/techs/bh-commonjs'),
 *     FileProvideTech = require('enb/techs/file-provider'),
 *     bem = require('enb-bem-techs');
 *
 * module.exports = function(config) {
 *     config.node('bundle', function(node) {
 *         // get FileList
 *         node.addTechs([
 *             [FileProvideTech, { target: '?.bemdecl.js' }],
 *             [bem.levels, levels: ['blocks']],
 *             bem.deps,
 *             bem.files
 *         ]);
 *
 *         // build BH file
 *         node.addTech(BHCommonJSTech);
 *         node.addTarget('?.bh.js');
 *     });
 * };
 */
module.exports = require('enb/lib/build-flow').create()
    .name('bh-commonjs')
    .target('target', '?.bh.js')
    .defineOption('mimic', [])
    .defineOption('devMode', true)
    .defineOption('jsAttrName', 'data-bem')
    .defineOption('jsAttrScheme', 'json')
    .defineOption('jsCls', 'i-bem')
    .defineOption('jsElem', true)
    .defineOption('escapeContent', false)
    .useFileList(['bh.js'])
    .builder(function (bhFiles) {
        var node = this.node,
            devMode = this._devMode,
            mimic = [].concat(this._mimic);

        /**
         * Compile code for `require` module.
         *
         * In dev mode will be added code for drop cache of require.
         *
         * @param {String} filename - absolute path to module
         * @param {String} varname - variable name to get module
         */
        function compileRequire(varname, filename) {
            if (arguments.length === 1) {
                filename = varname;
                varname = undefined;
            }

            var relPath = node.relativePath(filename);

            // Replace slashes with backslashes for windows paths for correct require work.
            /* istanbul ignore if */
            if (relPath.indexOf('\\') !== -1) {
                relPath = relPath.replace(/\\/g, '/');
            }

            return [
                devMode ? 'dropRequireCache(require, require.resolve("' + relPath + '"));' : '',
                (varname ? 'var ' + varname + '= ' : '') + 'require("' + relPath + '")' + (varname ? '' : '(bh)') + ';'
            ].join(EOL);
        }

        var dropRequireCacheFunc = [
            'function dropRequireCache(requireFunc, filename) {',
            '    var module = requireFunc.cache[filename];',
            '    if (module) {',
            '        if (module.parent) {',
            '            if (module.parent.children) {',
            '                var moduleIndex = module.parent.children.indexOf(module);',
            '                if (moduleIndex !== -1) {',
            '                    module.parent.children.splice(moduleIndex, 1);',
            '                }',
            '            }',
            '            delete module.parent;',
            '        }',
            '        delete module.children;',
            '        delete requireFunc.cache[filename];',
            '    }',
            '};'
        ].join(EOL);

        return [
            devMode ? dropRequireCacheFunc : '',
            compileRequire('BH', coreFilename),
            'var bh = new BH();',
            'bh.setOptions({',
            '   jsAttrName: \'' + this._jsAttrName + '\',',
            '   jsAttrScheme: \'' + this._jsAttrScheme + '\',',
            '   jsCls: ' + (this._jsCls ? ('\'' + this._jsCls + '\'') : false) + ',',
            '   jsElem: ' + this._jsElem + ',',
            '   escapeContent: ' + this._escapeContent,
            '});',
            '',
            bhFiles.map(function (file) {
                return compileRequire(file.fullname);
            }).join(EOL),
            '',
            'module.exports = bh;',
            mimic.length ? mimic.map(function (name) {
                return 'bh[\'' + name + '\'] = bh;';
            }).join(EOL) : ''
        ].join(EOL);
    })
    .createTech();
<commit_msg>#93 Make code refactoring of bh-commonjs tech module. It needs for ability to override buider function in enb-bem-18n technology and prevent dublication of code<commit_after>var coreFilename = require.resolve('bh/lib/bh.js'),
    EOL = require('os').EOL;

/**
 * @class BHCommonJSTech
 * @augments {BaseTech}
 * @classdesc
 *
 * Compile CommonJS module of BH with requires of core and source templates (bh.js files).

 *
 * Use to apply in server side only (Node.js). You can use `require` in templates.

 *
 * Important: for correct apply the source files and files are specified in `requires` should be in file system.
 *
 * @param {Object}      [options]                           Options
 * @param {String}      [options.target='?.bh.js']          Path to target with compiled file.
 * @param {String}      [options.filesTarget='?.files']     Path to target with FileList.
 * @param {String[]}    [options.sourceSuffixes='bh.js']    Files with specified suffixes involved in the assembly.
 * @param {String[]}    [options.mimic]                     Names to export.
 * @param {Boolean}     [options.devMode=true]              Drop cache for `require` of source templates.
 * @param {String}      [options.jsAttrName='data-bem']     Set `jsAttrName` option for BH core.
 * @param {String}      [options.jsAttrScheme='json']       Set `jsAttrScheme` option for BH core.
 * @param {String}      [options.jsCls='i-bem']             Set `jsCls` option for BH core.
 * @param {Boolean}     [options.jsElem=true]               Set `jsElem` option for BH core.
 * @param {Boolean}     [options.escapeContent=false]       Set `escapeContent` option for BH core.
 *
 * @example
 * var BHCommonJSTech = require('enb-bh/techs/bh-commonjs'),
 *     FileProvideTech = require('enb/techs/file-provider'),
 *     bem = require('enb-bem-techs');
 *
 * module.exports = function(config) {
 *     config.node('bundle', function(node) {
 *         // get FileList
 *         node.addTechs([
 *             [FileProvideTech, { target: '?.bemdecl.js' }],
 *             [bem.levels, levels: ['blocks']],
 *             bem.deps,
 *             bem.files
 *         ]);
 *
 *         // build BH file
 *         node.addTech(BHCommonJSTech);
 *         node.addTarget('?.bh.js');
 *     });
 * };
 */
module.exports = require('enb/lib/build-flow').create()
    .name('bh-commonjs')
    .target('target', '?.bh.js')
    .defineOption('mimic', [])
    .defineOption('devMode', true)
    .defineOption('jsAttrName', 'data-bem')
    .defineOption('jsAttrScheme', 'json')
    .defineOption('jsCls', 'i-bem')
    .defineOption('jsElem', true)
    .defineOption('escapeContent', false)
    .useFileList(['bh.js'])
    .builder(function (bhFiles) {
        return this._compile(bhFiles);
    })
    .methods(/** @lends BHBundleTech.prototype */{

        /**
         * Creates code of dropRequireCache function.
         *
         * @protected
         * @returns {String} generated code of dropRequireCache function
         */
        _generateDropRequireCacheFunc: function () {
            return [
                'function dropRequireCache(requireFunc, filename) {',
                '    var module = requireFunc.cache[filename];',
                '    if (module) {',
                '        if (module.parent) {',
                '            if (module.parent.children) {',
                '                var moduleIndex = module.parent.children.indexOf(module);',
                '                if (moduleIndex !== -1) {',
                '                    module.parent.children.splice(moduleIndex, 1);',
                '                }',
                '            }',
                '            delete module.parent;',
                '        }',
                '        delete module.children;',
                '        delete requireFunc.cache[filename];',
                '    }',
                '};'
            ].join(EOL);
        },

        /**
         * Compile code for `require` module.
         * In dev mode will be added code for drop cache of require.
         *
         * @param {String} varname - variable name to get module
         * @param {String} filename - absolute path to module
         * @param {Boolean} devMode - development mode flag
         */
        _compileRequire: function (varname, filename, devMode) {
            var relPath = this.node.relativePath(filename);

            // Replace slashes with backslashes for windows paths for correct require work.
            /* istanbul ignore if */
            if (relPath.indexOf('\\') !== -1) {
                relPath = relPath.replace(/\\/g, '/');
            }

            return [
                devMode ? 'dropRequireCache(require, require.resolve("' + relPath + '"));' : '',
                (varname ? 'var ' + varname + '= ' : '') + 'require("' + relPath + '")' + (varname ? '' : '(bh)') + ';'
            ].join(EOL);
        },

        /**
         * Compile code of bh module with core and source templates.
         *
         * @protected
         * @param {Array.<{path: String, contents: String}>} sources - Files with source templates.
         * @returns {String} compiled code of bh module
         */
        _compile: function (bhFiles) {
            var devMode = this._devMode,
                mimic = [].concat(this._mimic);

            return [
                devMode ? this._generateDropRequireCacheFunc() : '',
                this._compileRequire('BH', coreFilename, devMode),
                'var bh = new BH();',
                'bh.setOptions({',
                '   jsAttrName: \'' + this._jsAttrName + '\',',
                '   jsAttrScheme: \'' + this._jsAttrScheme + '\',',
                '   jsCls: ' + (this._jsCls ? ('\'' + this._jsCls + '\'') : false) + ',',
                '   jsElem: ' + this._jsElem + ',',
                '   escapeContent: ' + this._escapeContent,
                '});',
                '',
                bhFiles.map(function (file) {
                    return this._compileRequire(null, file.fullname, devMode);
                }, this).join(EOL),
                '',
                'module.exports = bh;',
                mimic.length ? mimic.map(function (name) {
                    return 'bh[\'' + name + '\'] = bh;';
                }).join(EOL) : ''
            ].join(EOL);
        }
    })
    .createTech();
<|endoftext|>


<commit_before>const expect = require('chai').expect;
const G6 = require('../../src/');

const div = document.createElement('div');
div.id = 'issue-659';
document.body.appendChild(div);

const Util = G6.Util;
const data = {
  nodes: [{
    id: 'node1',
    x: 100,
    y: 100,
    shape: 'circle-animate',
    size: 20,
    label: '图形动画',
    labelCfg: {
      position: 'bottom'
    }
  }, {
    id: 'node2',
    x: 300,
    y: 200,
    shape: 'background-animate',
    color: '#b5b5b5',
    size: 20,
    label: '背景动画',
    labelCfg: {
      position: 'bottom'
    }
  }, {
    id: 'node3',
    x: 400,
    y: 100,
    size: [ 40, 40 ],
    shape: 'inner-animate',
    img: 'data:image/webp;base64,UklGRq4FAABXRUJQVlA4IKIFAABwHwCdASo8ADwAPiEMhEGhhv6rQAYAgS2NHsdCq/4D8AOoA64OEUAj/XPxVwyvRGvyO/gGxN/t3oK/1X6zesX3L/p/RP/2HCgKAB9AGeAbCB+AGwAbQBtA/8c/m/4PYHTonm+SzRH6B9sv2i/rOZC+G/ln9l/ML/GdoD7APcA/TD+09QDzAfrX+vHYM9AD+Uf0zrAPQA/bH0vv2t+CH9qf2R+A39e6X098/I7IAcLcs8Gjmc/9T7gPbX9H+wJ+rPVV9En9ZmBI5oUiYhkYHIVjRr9hzCTPcV5Rs/wjjIHkxPgtr/3ALZSuUm146HHwqQVA23hnnqH/4aJ/k4v4hU6RBZ0AAAD+//8ARPyL9yWIlAbWBAD0oKSqlYWreuRa3Oj02u+TvSQS8iwMYewUYTWLDNp9wOlFJaWnqE+za35UwUXuDAT6T0I4fwY+u+qrRVhl+S1ir4X7BQiNswug5AX+MjQcXEeUwfSIEUT+DFPCr+BUiwTbFxLni7fv61vRbmXoauLz4tiqOFTzEGP8tNXP5+H7mZVGfNjIxapT3FGUtqBdp/SD5cTOYOkn2fawkpqpCSqf2+CfiGWtIF673fEzlk/hIbWDhQ81C/ddxLn609d/5efckbdZ8HZbhhVmM82/Uat7CFmw1SH5xCxRxEEhjpf1EP1Xn5q9VZfm1+OFTab/MN67Xha8K//5oVBlMgZALE653X0fas/+2xMqiyCu5Wa7PHsCwbBwqROfNmzi4LPOTjkFPHVKDD1Nfj4/sul6cANdF68rf2jszlyZsUUoLTP7H3swSroc3ssNXSRVAcYd7+iBZpfoAYWvKgnr+Hv62fHZX5ZbjYbYzVjq6fsXkubto858NuUx4+ILb5y7dP6W3/IYVeUSF0yZseKIZhOMs9BBf5uB2Y3Ott//+1OG7hYINzcqigrzWAOJbSmVw3G0ULywkobx+rvfk8VmZFzQGgP/+4T74mp/vsZyM1NLguiTO2gNO05tcpXwveq5mrcweXrJ/bRZDmU2KBrnXhkXq+735c+UHTFq4h4jMOPm5shKioB6XaqhUf3DJlMg8937g/SKjrgD0H5sNm0/k4FfilBbcrsjc3dd6cwEYJo3CNhe3SpNJ2geNXyV4/hq/BZXZ1kiVknjmf5cUx7Tv/9Sb+fQ/DgAsRNSz1wiVodiLjP7aVrkxbWx5gJ8U/j0o1Ipm/nyDZRPrQXmbPAcy1eDDejxTDBKe42ElHpC2QlFdhOedsp4i9QVjt8EqWGy1YzPaGqZhCVg/LWt8/+4BmiCzNGtpR21MGJf4kI/n/1sbe36e1QBCBAx4EVfTM82ZM2lh0P189e7eY0A3NzXWVrUek8SEn+DYYCQeEaC5hDHGreFHT1baY6KyrFx3G9oMm3fLrCqmNjFRnZa3LB/5m8FgCpq9B/1OCLRE5GzVTZnVzj/4V38PgCIpX16Kznijf01+MkDeS9oCF2hEXQ9tr+mPLrjGy4Cg5fyLgyCj1fUq33nMf79Svli2h83m3gqkoxJcXvBetFQP8V/gRjBNGmFXK5TfwLhbolWEjDqUGK3n+hxzQLif9zreYO88EIRTUNbzE1/Sn7rBEtjB0uawNje5OubWsB62SOlMZoZpxrDbMb4UvQrODPhSafmhcYe9zm/dHxssMfUthhDKjyMhoRhngPjbzfGXmIV2Omgrn/zbefK/PawUGSH6x4Qk4HCN4/X8S+XCf51JJtOQeHST/yfwg69uMkE07SONnhGUrL6j5oQn6JI+zkaH/H/P/Ti/pfOTfAWxQNiMvWX08mqbuUweFSQ/G5YUP/uCvZAXutf1+Nhl2jj/n4/fPOihPjwvfFnnjOaQvs9PSpF33d+396LASZ3IID/4UP4pf9eOMXw82ccoUUUHX6MfBWyBDvARCrdPmerUwKwW+lBIAe1dsAAAA==',
    label: 'rect',
    labelCfg: {
      position: 'bottom'
    }
  }, {
    id: 'node4',
    x: 300,
    y: 400,
    shape: 'rect',
    label: 'rect',
    labelCfg: {
      position: 'bottom'
    }
  }],
  edges: [
    {
      source: 'node1',
      target: 'node2'
    },
    {
      source: 'node3',
      target: 'node2'
    },
    {
      source: 'node2',
      target: 'node4'
    }
  ] };

// 放大、变小动画
G6.registerNode('circle-animate', {
  afterDraw(cfg, group) {
    const shape = group.get('children')[0];
    shape.animate({
      repeat: true,
      onFrame(ratio) {
        const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
        return {
          r: cfg.size / 2 + diff
        };
      }
    }, 3000, 'easeCubic');
  }
}, 'circle');

G6.registerNode('background-animate', {
  afterDraw(cfg, group) {
    const r = cfg.size / 2;
    const back1 = group.addShape('circle', {
      zIndex: -3,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    const back2 = group.addShape('circle', {
      zIndex: -2,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color, // 为了显示清晰，随意设置了颜色
        opacity: 0.6
      }
    });

    const back3 = group.addShape('circle', {
      zIndex: -1,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    group.sort(); // 排序，根据zIndex 排序
    back1.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 0); // 无延迟

    back2.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 1000); // 1 秒延迟

    back3.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 2000); // 2 秒延迟
  }
}, 'circle');

G6.registerNode('inner-animate', {
  afterDraw(cfg, group) {
    const size = cfg.size;
    const width = size[0] - 12;
    const height = size[1] - 12;
    const image = group.addShape('image', {
      attrs: {
        x: -width / 2,
        y: -height / 2,
        width,
        height,
        img: cfg.img
      }
    });
    image.animate({
      onFrame(ratio) {
        const matrix = Util.mat3.create();
        const toMatrix = Util.transform(matrix, [
          [ 'r', ratio * Math.PI * 2 ]
        ]);
        return {
          matrix: toMatrix
        };
      },
      repeat: true
    }, 3000, 'easeCubic');
  }
}, 'rect');
G6.Global.nodeStateStyle.hover = {
  stroke: '#d9d9d9',
  fill: '#5394ef'
};
const graph = new G6.Graph({
  container: 'issue-659',
  width: 1000,
  height: 600,
  modes: {
    default: [ 'drag-canvas', 'drag-node', 'zoom-canvas', 'click-select' ]
  }
});
graph.data(data);
graph.render();

graph.on('node:mouseenter', ev => {
  const { item } = ev;
  graph.setItemState(item, 'hover', true);
});
graph.on('node:mouseleave', ev => {
  const { item } = ev;
  graph.setItemState(item, 'hover', false);
});

describe('#659', () => {
  const node = graph.findById('node1');
  const keyShape = node.getKeyShape();
  graph.emit('node:mouseenter', { item: node });
  expect(keyShape.attr('fill')).to.equal('#5394ef');
  expect(keyShape.attr('stroke')).to.equal('#d9d9d9');
  graph.emit('node:dragstart', { item: node, x: 200, y: 200 });
  graph.emit('node:dragend', { item: node, x: 500, y: 500 });
  expect(node.get('model').x).to.equal(400);
  expect(node.get('model').y).to.equal(400);
  expect(keyShape.attr('fill')).to.equal('#5394ef');
  expect(keyShape.attr('stroke')).to.equal('#d9d9d9');
  graph.emit('node:mouseleave', { item: node });
  expect(keyShape.attr('fill')).to.equal('#36cfc9');
  expect(keyShape.attr('stroke')).to.equal('#87e8de');
});
<commit_msg>update test unit<commit_after>const expect = require('chai').expect;
const G6 = require('../../src/');

const div = document.createElement('div');
div.id = 'issue-659';
document.body.appendChild(div);

const Util = G6.Util;
const data = {
  nodes: [{
    id: 'node1',
    x: 100,
    y: 100,
    shape: 'circle-animate',
    size: 20,
    label: '图形动画',
    labelCfg: {
      position: 'bottom'
    }
  }, {
    id: 'node2',
    x: 300,
    y: 200,
    shape: 'background-animate',
    color: '#b5b5b5',
    size: 20,
    label: '背景动画',
    labelCfg: {
      position: 'bottom'
    }
  }, {
    id: 'node3',
    x: 400,
    y: 100,
    size: [ 40, 40 ],
    shape: 'inner-animate',
    img: 'data:image/webp;base64,UklGRq4FAABXRUJQVlA4IKIFAABwHwCdASo8ADwAPiEMhEGhhv6rQAYAgS2NHsdCq/4D8AOoA64OEUAj/XPxVwyvRGvyO/gGxN/t3oK/1X6zesX3L/p/RP/2HCgKAB9AGeAbCB+AGwAbQBtA/8c/m/4PYHTonm+SzRH6B9sv2i/rOZC+G/ln9l/ML/GdoD7APcA/TD+09QDzAfrX+vHYM9AD+Uf0zrAPQA/bH0vv2t+CH9qf2R+A39e6X098/I7IAcLcs8Gjmc/9T7gPbX9H+wJ+rPVV9En9ZmBI5oUiYhkYHIVjRr9hzCTPcV5Rs/wjjIHkxPgtr/3ALZSuUm146HHwqQVA23hnnqH/4aJ/k4v4hU6RBZ0AAAD+//8ARPyL9yWIlAbWBAD0oKSqlYWreuRa3Oj02u+TvSQS8iwMYewUYTWLDNp9wOlFJaWnqE+za35UwUXuDAT6T0I4fwY+u+qrRVhl+S1ir4X7BQiNswug5AX+MjQcXEeUwfSIEUT+DFPCr+BUiwTbFxLni7fv61vRbmXoauLz4tiqOFTzEGP8tNXP5+H7mZVGfNjIxapT3FGUtqBdp/SD5cTOYOkn2fawkpqpCSqf2+CfiGWtIF673fEzlk/hIbWDhQ81C/ddxLn609d/5efckbdZ8HZbhhVmM82/Uat7CFmw1SH5xCxRxEEhjpf1EP1Xn5q9VZfm1+OFTab/MN67Xha8K//5oVBlMgZALE653X0fas/+2xMqiyCu5Wa7PHsCwbBwqROfNmzi4LPOTjkFPHVKDD1Nfj4/sul6cANdF68rf2jszlyZsUUoLTP7H3swSroc3ssNXSRVAcYd7+iBZpfoAYWvKgnr+Hv62fHZX5ZbjYbYzVjq6fsXkubto858NuUx4+ILb5y7dP6W3/IYVeUSF0yZseKIZhOMs9BBf5uB2Y3Ott//+1OG7hYINzcqigrzWAOJbSmVw3G0ULywkobx+rvfk8VmZFzQGgP/+4T74mp/vsZyM1NLguiTO2gNO05tcpXwveq5mrcweXrJ/bRZDmU2KBrnXhkXq+735c+UHTFq4h4jMOPm5shKioB6XaqhUf3DJlMg8937g/SKjrgD0H5sNm0/k4FfilBbcrsjc3dd6cwEYJo3CNhe3SpNJ2geNXyV4/hq/BZXZ1kiVknjmf5cUx7Tv/9Sb+fQ/DgAsRNSz1wiVodiLjP7aVrkxbWx5gJ8U/j0o1Ipm/nyDZRPrQXmbPAcy1eDDejxTDBKe42ElHpC2QlFdhOedsp4i9QVjt8EqWGy1YzPaGqZhCVg/LWt8/+4BmiCzNGtpR21MGJf4kI/n/1sbe36e1QBCBAx4EVfTM82ZM2lh0P189e7eY0A3NzXWVrUek8SEn+DYYCQeEaC5hDHGreFHT1baY6KyrFx3G9oMm3fLrCqmNjFRnZa3LB/5m8FgCpq9B/1OCLRE5GzVTZnVzj/4V38PgCIpX16Kznijf01+MkDeS9oCF2hEXQ9tr+mPLrjGy4Cg5fyLgyCj1fUq33nMf79Svli2h83m3gqkoxJcXvBetFQP8V/gRjBNGmFXK5TfwLhbolWEjDqUGK3n+hxzQLif9zreYO88EIRTUNbzE1/Sn7rBEtjB0uawNje5OubWsB62SOlMZoZpxrDbMb4UvQrODPhSafmhcYe9zm/dHxssMfUthhDKjyMhoRhngPjbzfGXmIV2Omgrn/zbefK/PawUGSH6x4Qk4HCN4/X8S+XCf51JJtOQeHST/yfwg69uMkE07SONnhGUrL6j5oQn6JI+zkaH/H/P/Ti/pfOTfAWxQNiMvWX08mqbuUweFSQ/G5YUP/uCvZAXutf1+Nhl2jj/n4/fPOihPjwvfFnnjOaQvs9PSpF33d+396LASZ3IID/4UP4pf9eOMXw82ccoUUUHX6MfBWyBDvARCrdPmerUwKwW+lBIAe1dsAAAA==',
    label: 'rect',
    labelCfg: {
      position: 'bottom'
    }
  }, {
    id: 'node4',
    x: 300,
    y: 400,
    shape: 'rect',
    label: 'rect',
    labelCfg: {
      position: 'bottom'
    }
  }],
  edges: [
    {
      source: 'node1',
      target: 'node2'
    },
    {
      source: 'node3',
      target: 'node2'
    },
    {
      source: 'node2',
      target: 'node4'
    }
  ] };

// 放大、变小动画
G6.registerNode('circle-animate', {
  afterDraw(cfg, group) {
    const shape = group.get('children')[0];
    shape.animate({
      repeat: true,
      onFrame(ratio) {
        const diff = ratio <= 0.5 ? ratio * 10 : (1 - ratio) * 10;
        return {
          r: cfg.size / 2 + diff
        };
      }
    }, 3000, 'easeCubic');
  }
}, 'circle');

G6.registerNode('background-animate', {
  afterDraw(cfg, group) {
    const r = cfg.size / 2;
    const back1 = group.addShape('circle', {
      zIndex: -3,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    const back2 = group.addShape('circle', {
      zIndex: -2,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color, // 为了显示清晰，随意设置了颜色
        opacity: 0.6
      }
    });

    const back3 = group.addShape('circle', {
      zIndex: -1,
      attrs: {
        x: 0,
        y: 0,
        r,
        fill: cfg.color,
        opacity: 0.6
      }
    });
    group.sort(); // 排序，根据zIndex 排序
    back1.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 0); // 无延迟

    back2.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 1000); // 1 秒延迟

    back3.animate({ // 逐渐放大，并消失
      r: r + 10,
      opacity: 0.1,
      repeat: true // 循环
    }, 3000, 'easeCubic', null, 2000); // 2 秒延迟
  }
}, 'circle');

G6.registerNode('inner-animate', {
  afterDraw(cfg, group) {
    const size = cfg.size;
    const width = size[0] - 12;
    const height = size[1] - 12;
    const image = group.addShape('image', {
      attrs: {
        x: -width / 2,
        y: -height / 2,
        width,
        height,
        img: cfg.img
      }
    });
    image.animate({
      onFrame(ratio) {
        const matrix = Util.mat3.create();
        const toMatrix = Util.transform(matrix, [
          [ 'r', ratio * Math.PI * 2 ]
        ]);
        return {
          matrix: toMatrix
        };
      },
      repeat: true
    }, 3000, 'easeCubic');
  }
}, 'rect');
G6.Global.nodeStateStyle.hover = {
  stroke: '#d9d9d9',
  fill: '#5394ef'
};
const graph = new G6.Graph({
  container: 'issue-659',
  width: 1000,
  height: 600,
  modes: {
    default: [ 'drag-canvas', 'drag-node', 'zoom-canvas', 'click-select' ]
  }
});
graph.data(data);
graph.render();

graph.on('node:mouseenter', ev => {
  const { item } = ev;
  graph.setItemState(item, 'hover', true);
});
graph.on('node:mouseleave', ev => {
  const { item } = ev;
  graph.setItemState(item, 'hover', false);
});

describe('#659', () => {
  const node = graph.findById('node1');
  const keyShape = node.getKeyShape();
  graph.emit('node:mouseenter', { item: node });
  expect(keyShape.attr('fill')).to.equal('#5394ef');
  expect(keyShape.attr('stroke')).to.equal('#d9d9d9');
  graph.emit('node:dragstart', { item: node, x: 200, y: 200 });
  graph.emit('node:dragend', { item: node, x: 500, y: 500 });
  expect(node.get('model').x).to.equal(400);
  expect(node.get('model').y).to.equal(400);
  expect(keyShape.attr('fill')).to.equal('#5394ef');
  expect(keyShape.attr('stroke')).to.equal('#d9d9d9');
  graph.emit('node:mouseleave', { item: node });
  expect(keyShape.attr('fill')).to.equal('#91d5ff');
  expect(keyShape.attr('stroke')).to.equal('#91d5ff');
});
<|endoftext|>


<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

(function() {
  var startup = function() {
    console.log("Startup.");
    __axiomRequire__('shell/launch');
  }

  if (document.readyState === 'complete') {
    startup();
  } else {
    var onReadyStateChange = function() {
      if (document.readyState === 'complete') {
        document.removeEventListener('readystatechange', onReadyStateChange);
        startup();
      }
    };
    document.addEventListener('readystatechange', onReadyStateChange);
  }
})();
<commit_msg>Export axiom_lib into global window object.<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

(function() {
  var startup = function() {
    console.log("Startup.");
    __axiomExport__(window);
  }

  if (document.readyState === 'complete') {
    startup();
  } else {
    var onReadyStateChange = function() {
      if (document.readyState === 'complete') {
        document.removeEventListener('readystatechange', onReadyStateChange);
        startup();
      }
    };
    document.addEventListener('readystatechange', onReadyStateChange);
  }
})();
<|endoftext|>


<commit_before>/*

  table.js is released under the GNU Affero General Public License.
  See COPYRIGHT.txt and LICENSE.txt.

  Part of the OpenEnergyMonitor project:
  http://openenergymonitor.org

*/

var customtablefields = {

    'icon':
    {
        'draw': function(row,field)
        {
            if (table.data[row][field] == true) return "";
            if (table.data[row][field] == false) return "";
        },

        'event': function()
        {
            // Event code for clickable switch state icon's
            $(table.element).on('click', 'i[type=input]', function() {
                var row = $(this).parent().attr('row');
                var field = $(this).parent().attr('field');
                table.data[row][field] = !table.data[row][field];

                var fields = {};
                fields[field] = table.data[row][field];

                $(table.element).trigger("onSave",[table.data[row]['id'],fields]);

                if (table.data[row][field]) $(this).attr('class', table.fields[field].trueicon); else $(this).attr('class', table.fields[field].falseicon);
            });
        }
    },

    'updated':
    {
        'draw': function (row,field) { return list_format_updated(table.data[row][field]) }
    },

    'value':
    {
        'draw': function (row,field) { return list_format_value(table.data[row][field]) }
    },

    'processlist':
    {
        'draw': function (row,field) {

          var processlist = table.data[row][field];
          if (!processlist) return "";

          var processPairs = processlist.split(",");

          var out = "";

          for (z in processPairs)
          {
            var keyvalue = processPairs[z].split(":");

            var key = parseInt(keyvalue[0]);
            var type = "";
            var color = "";

            switch(key)
            {
              case 1:
                key = 'log'; type = 2; break;
              case 2:
                key = 'x'; type = 0; break;
              case 3:
                key = '+'; type = 0; break;
              case 4:
                key = 'kwh'; type = 2; break;
              case 5:
                key = 'kwhd'; type = 2; break;
              case 6:
                key = 'x inp'; type = 1; break;
              case 7:
                key = 'ontime'; type = 2; break;
              case 8:
                key = 'kwhinckwhd'; type = 2; break;
              case 9:
                key = 'kwhkwhd'; type = 2; break;
              case 10:
                key = 'update'; type = 2; break;
              case 11:
                key = '+ inp'; type = 1; break;
              case 12:
                key = '/ inp'; type = 1; break;
              case 13:
                key = 'phaseshift'; type =2; break;
              case 14:
                key = 'accumulate'; type = 2; break;
              case 15:
                key = 'rate'; type = 2; break;
              case 16:
                key = 'hist'; type = 2; break;
              case 17:
                key = 'average'; type = 2; break;
              case 18:
                key = 'flux'; type = 2; break;
              case 19:
                key = 'pwrgain'; type = 2; break;
              case 20:
                key = 'pulsdiff'; type = 2; break;
              case 21:
                key = 'kwhpwr'; type = 2; break;
              case 22:
                key = '- inp'; type = 1; break;
              case 23:
                key = 'kwhkwhd'; type = 2; break;
              case 24:
                key = '> 0'; type = 3; break;
              case 25:
                key = '< 0'; type = 3; break;
              case 26:
                key = 'unsign'; type = 3; break;
            }

            value = keyvalue[1];

            switch(type)
            {
              case 0:
                type = 'value: '; color = 'important';
                break;
              case 1:
                type = 'input: '; color = 'warning';
                break;
              case 2:
                type = 'feed: '; color = 'info';
                break;
              case 3:
                type = ''; color = 'important';
                value = '' // Argument type is NONE, we don't mind the value
                break;
            }

            if (type == 'feed: ') {
              out += "<a href='"+path+"vis/auto?feedid="+value+"'"+key+" ";
            } else {
              out += ""+key+" ";
            }
          }

          return out;
        }
    },

    'iconlink':
    {
        'draw': function (row,field) {
          var icon = 'icon-eye-open'; if (table.fields[field].icon) icon = table.fields[field].icon;
          return ""
        }
    },

    'iconbasic':
    {
        'draw': function(row,field)
        {
            return "";
        }
    }
}

// Calculate and color updated time
function list_format_updated(time)
{
  var now = (new Date()).getTime();
  var update = (new Date(time)).getTime();
  var lastupdate = (now-update)/1000;

  var secs = (now-update)/1000;
  var mins = secs/60;
  var hour = secs/3600

  var updated = secs.toFixed(0)+"s ago";
  if (secs>180) updated = mins.toFixed(0)+" mins ago";
  if (secs>(3600*2)) updated = hour.toFixed(0)+" hours ago";
  if (hour>24) updated = "inactive";

  var color = "rgb(255,125,20)";
  if (secs<25) color = "rgb(50,200,50)"
  else if (secs<60) color = "rgb(240,180,20)";

  return ""+updated+"";
}

// Format value dynamically
function list_format_value(value)
{
  if (value>10) value = (1*value).toFixed(1);
  if (value>100) value = (1*value).toFixed(0);
  if (value<10) value = (1*value).toFixed(2);
  return value;
}
<commit_msg>Missing semicolon<commit_after>/*

  table.js is released under the GNU Affero General Public License.
  See COPYRIGHT.txt and LICENSE.txt.

  Part of the OpenEnergyMonitor project:
  http://openenergymonitor.org

*/

var customtablefields = {

    'icon':
    {
        'draw': function(row,field)
        {
            if (table.data[row][field] == true) return "";
            if (table.data[row][field] == false) return "";
        },

        'event': function()
        {
            // Event code for clickable switch state icon's
            $(table.element).on('click', 'i[type=input]', function() {
                var row = $(this).parent().attr('row');
                var field = $(this).parent().attr('field');
                table.data[row][field] = !table.data[row][field];

                var fields = {};
                fields[field] = table.data[row][field];

                $(table.element).trigger("onSave",[table.data[row]['id'],fields]);

                if (table.data[row][field]) $(this).attr('class', table.fields[field].trueicon); else $(this).attr('class', table.fields[field].falseicon);
            });
        }
    },

    'updated':
    {
        'draw': function (row,field) { return list_format_updated(table.data[row][field]) }
    },

    'value':
    {
        'draw': function (row,field) { return list_format_value(table.data[row][field]) }
    },

    'processlist':
    {
        'draw': function (row,field) {

          var processlist = table.data[row][field];
          if (!processlist) return "";

          var processPairs = processlist.split(",");

          var out = "";

          for (z in processPairs)
          {
            var keyvalue = processPairs[z].split(":");

            var key = parseInt(keyvalue[0]);
            var type = "";
            var color = "";

            switch(key)
            {
              case 1:
                key = 'log'; type = 2; break;
              case 2:
                key = 'x'; type = 0; break;
              case 3:
                key = '+'; type = 0; break;
              case 4:
                key = 'kwh'; type = 2; break;
              case 5:
                key = 'kwhd'; type = 2; break;
              case 6:
                key = 'x inp'; type = 1; break;
              case 7:
                key = 'ontime'; type = 2; break;
              case 8:
                key = 'kwhinckwhd'; type = 2; break;
              case 9:
                key = 'kwhkwhd'; type = 2; break;
              case 10:
                key = 'update'; type = 2; break;
              case 11:
                key = '+ inp'; type = 1; break;
              case 12:
                key = '/ inp'; type = 1; break;
              case 13:
                key = 'phaseshift'; type =2; break;
              case 14:
                key = 'accumulate'; type = 2; break;
              case 15:
                key = 'rate'; type = 2; break;
              case 16:
                key = 'hist'; type = 2; break;
              case 17:
                key = 'average'; type = 2; break;
              case 18:
                key = 'flux'; type = 2; break;
              case 19:
                key = 'pwrgain'; type = 2; break;
              case 20:
                key = 'pulsdiff'; type = 2; break;
              case 21:
                key = 'kwhpwr'; type = 2; break;
              case 22:
                key = '- inp'; type = 1; break;
              case 23:
                key = 'kwhkwhd'; type = 2; break;
              case 24:
                key = '> 0'; type = 3; break;
              case 25:
                key = '< 0'; type = 3; break;
              case 26:
                key = 'unsign'; type = 3; break;
            }

            value = keyvalue[1];

            switch(type)
            {
              case 0:
                type = 'value: '; color = 'important';
                break;
              case 1:
                type = 'input: '; color = 'warning';
                break;
              case 2:
                type = 'feed: '; color = 'info';
                break;
              case 3:
                type = ''; color = 'important';
                value = ''; // Argument type is NONE, we don't mind the value
                break;
            }

            if (type == 'feed: ') {
              out += "<a href='"+path+"vis/auto?feedid="+value+"'"+key+" ";
            } else {
              out += ""+key+" ";
            }
          }

          return out;
        }
    },

    'iconlink':
    {
        'draw': function (row,field) {
          var icon = 'icon-eye-open'; if (table.fields[field].icon) icon = table.fields[field].icon;
          return ""
        }
    },

    'iconbasic':
    {
        'draw': function(row,field)
        {
            return "";
        }
    }
}

// Calculate and color updated time
function list_format_updated(time)
{
  var now = (new Date()).getTime();
  var update = (new Date(time)).getTime();
  var lastupdate = (now-update)/1000;

  var secs = (now-update)/1000;
  var mins = secs/60;
  var hour = secs/3600

  var updated = secs.toFixed(0)+"s ago";
  if (secs>180) updated = mins.toFixed(0)+" mins ago";
  if (secs>(3600*2)) updated = hour.toFixed(0)+" hours ago";
  if (hour>24) updated = "inactive";

  var color = "rgb(255,125,20)";
  if (secs<25) color = "rgb(50,200,50)"
  else if (secs<60) color = "rgb(240,180,20)";

  return ""+updated+"";
}

// Format value dynamically
function list_format_value(value)
{
  if (value>10) value = (1*value).toFixed(1);
  if (value>100) value = (1*value).toFixed(0);
  if (value<10) value = (1*value).toFixed(2);
  return value;
}
<|endoftext|>


<commit_before>// ==UserScript==
// @name        FUT Refresh Transfer List
// @version     0.1.4
// @description Refresh Transfer List
// @license     MIT
// @author      Tim Klingeleers
// @match       https://www.easports.com/fifa/ultimate-team/web-app/*
// @namespace   https://github.com/Mardaneus86
// @updateURL   https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/refresh-transfer-list.user.js
// @downloadURL https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/refresh-transfer-list.user.js
// @supportURL  https://github.com/Mardaneus86/futwebapp-tampermonkey/issues
// ==/UserScript==
// ==OpenUserJS==
// @author Mardaneus86
// ==/OpenUserJS==
(function () {
  'use strict';

  $(document).bind('DOMNodeInserted', function (event) {
    switch (gNavManager.getCurrentScreen()._screenId) {
      case "TradePile":
      case "SearchResults":
      case "MyClubSearch":
        if ($('#header .subTitle').find('.refreshList').length === 0) {
          $('#header').find('.subTitle').append('Refresh list');
          $('.refreshList').click(function () {
            gNavManager.getCurrentScreenController()._controller._listController._requestItems();
          });
        }
        break;
    }
  });
})();
<commit_msg>fix: prevent error when no screen is shown<commit_after>// ==UserScript==
// @name        FUT Refresh Transfer List
// @version     0.1.5
// @description Refresh Transfer List
// @license     MIT
// @author      Tim Klingeleers
// @match       https://www.easports.com/fifa/ultimate-team/web-app/*
// @namespace   https://github.com/Mardaneus86
// @updateURL   https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/refresh-transfer-list.user.js
// @downloadURL https://raw.githubusercontent.com/Mardaneus86/futwebapp-tampermonkey/master/refresh-transfer-list.user.js
// @supportURL  https://github.com/Mardaneus86/futwebapp-tampermonkey/issues
// ==/UserScript==
// ==OpenUserJS==
// @author Mardaneus86
// ==/OpenUserJS==
(function () {
  'use strict';

  $(document).bind('DOMNodeInserted', function (event) {
    var currentScreen = gNavManager.getCurrentScreen();
    if (!currentScreen) {
      return;
    }

    switch (currentScreen._screenId) {
      case "TradePile":
      case "SearchResults":
      case "MyClubSearch":
        if ($('#header .subTitle').find('.refreshList').length === 0) {
          $('#header').find('.subTitle').append('Refresh list');
          $('.refreshList').click(function () {
            gNavManager.getCurrentScreenController()._controller._listController._requestItems();
          });
        }
        break;
    }
  });
})();
<|endoftext|>


<commit_before>import {
  CREATE,
  DELETE,
  GET_LIST,
  GET_MANY,
  GET_MANY_REFERENCE,
  GET_ONE,
  UPDATE,
} from 'admin-on-rest';
import isPlainObject from 'lodash.isplainobject';
import qs from 'qs';
import fetchHydra from './fetchHydra';

class AORDocument {
  constructor(obj) {
    Object.assign(this, obj, {
      originId: obj.id,
      id: obj['@id'],
    });
  }

  /**
   * @return {string}
   */
  toString() {
    return `[object ${this.id}]`;
  }
}

const aorDocumentsCache = new Map();

/**
 * Transforms a JSON-LD document to an admin-on-rest compatible document
 *
 * @param {Object} document
 * @param {bool} clone
 *
 * @return {AORDocument}
 */
export const transformJsonLdDocumentToAORDocument = (
  document,
  clone = true,
) => {
  if (clone) {
    // deep clone documents
    document = JSON.parse(JSON.stringify(document));
  }

  // The main document is a JSON-LD document, convert it and store it in the cache
  if (document['@id']) {
    document = new AORDocument(document);
    aorDocumentsCache[document['@id']] = document;
  }

  // Replace embedded objects by their IRIs, and store the object itself in the cache to reuse without issuing new HTTP requests.
  Object.keys(document).forEach(key => {
    // to-one
    if (isPlainObject(document[key]) && document[key]['@id']) {
      aorDocumentsCache[
        document[key]['@id']
      ] = transformJsonLdDocumentToAORDocument(document[key], false);
      document[key] = document[key]['@id'];

      return;
    }

    // to-many
    if (
      Array.isArray(document[key]) &&
      document[key].length &&
      isPlainObject(document[key][0]) &&
      document[key][0]['@id']
    ) {
      document[key] = document[key].map(obj => {
        aorDocumentsCache[obj['@id']] = transformJsonLdDocumentToAORDocument(
          obj,
          false,
        );

        return obj['@id'];
      });
    }
  });

  return document;
};

/**
 * Maps admin-on-rest queries to a Hydra powered REST API
 *
 * @see http://www.hydra-cg.com/
 *
 * @example
 * CREATE   => POST http://my.api.url/posts/123
 * DELETE   => DELETE http://my.api.url/posts/123
 * GET_LIST => GET http://my.api.url/posts
 * GET_MANY => GET http://my.api.url/posts/123, GET http://my.api.url/posts/456, GET http://my.api.url/posts/789
 * GET_ONE  => GET http://my.api.url/posts/123
 * UPDATE   => PUT http://my.api.url/posts/123
 */
export default ({entrypoint, resources = []}, httpClient = fetchHydra) => {
  /**
   * @param {string} resource
   * @param {Object} data
   *
   * @returns {Promise}
   */
  const convertAORDataToHydraData = (resource, data = {}) => {
    resource = resources.find(({name}) => resource === name);
    if (undefined === resource) {
      return Promise.resolve(data);
    }

    const fieldData = [];
    resource.fields.forEach(({name, normalizeData}) => {
      if (!(name in data) || undefined === normalizeData) {
        return;
      }

      fieldData[name] = normalizeData(data[name]);
    });

    const fieldDataKeys = Object.keys(fieldData);
    const fieldDataValues = Object.values(fieldData);

    return Promise.all(fieldDataValues).then(fieldData => {
      const object = {};
      for (let i = 0; i < fieldDataKeys.length; i++) {
        object[fieldDataKeys[i]] = fieldData[i];
      }

      return {...data, ...object};
    });
  };

  /**
   * @param {string} type
   * @param {string} resource
   * @param {Object} params
   *
   * @returns {Object}
   */
  const convertAORRequestToHydraRequest = (type, resource, params) => {
    switch (type) {
      case CREATE:
        return convertAORDataToHydraData(resource, params.data).then(data => ({
          options: {
            body: JSON.stringify(data),
            method: 'POST',
          },
          url: `${entrypoint}/${resource}`,
        }));

      case DELETE:
        return Promise.resolve({
          options: {
            method: 'DELETE',
          },
          url: entrypoint + params.id,
        });

      case GET_LIST: {
        const {
          pagination: {page},
          sort: {field, order},
        } = params;

        return Promise.resolve({
          options: {},
          url: `${entrypoint}/${resource}?${qs.stringify({
            ...params.filter,
            order: {
              [field]: order,
            },
            page,
          })}`,
        });
      }

      case GET_MANY_REFERENCE:
        return Promise.resolve({
          options: {},
          url: `${entrypoint}/${resource}?${qs.stringify({
            [params.target]: params.id,
          })}`,
        });

      case GET_ONE:
        return Promise.resolve({
          options: {},
          url: entrypoint + params.id,
        });

      case UPDATE:
        return convertAORDataToHydraData(resource, params.data).then(data => ({
          options: {
            body: JSON.stringify(data),
            method: 'PUT',
          },
          url: entrypoint + params.id,
        }));

      default:
        throw new Error(`Unsupported fetch action type ${type}`);
    }
  };

  /**
   * @param {string} resource
   * @param {Object} data
   *
   * @returns {Promise}
   */
  const convertHydraDataToAORData = (resource, data = {}) => {
    resource = resources.find(({name}) => resource === name);
    if (undefined === resource) {
      return Promise.resolve(data);
    }

    const fieldData = {};
    resource.fields.forEach(({name, denormalizeData}) => {
      if (!(name in data) || undefined === denormalizeData) {
        return;
      }

      fieldData[name] = denormalizeData(data[name]);
    });

    const fieldDataKeys = Object.keys(fieldData);
    const fieldDataValues = Object.values(fieldData);

    return Promise.all(fieldDataValues).then(fieldData => {
      const object = {};
      for (let i = 0; i < fieldDataKeys.length; i++) {
        object[fieldDataKeys[i]] = fieldData[i];
      }

      return {...data, ...object};
    });
  };

  /**
   * @param {Object} response
   * @param {string} resource
   * @param {string} type
   *
   * @returns {Promise}
   */
  const convertHydraResponseToAORResponse = (type, resource, response) => {
    switch (type) {
      case GET_LIST:
      case GET_MANY_REFERENCE:
        // TODO: support other prefixes than "hydra:"
        return Promise.resolve(
          response.json['hydra:member'].map(
            transformJsonLdDocumentToAORDocument,
          ),
        )
          .then(data =>
            Promise.all(
              data.map(data => convertHydraDataToAORData(resource, data)),
            ),
          )
          .then(data => ({data, total: response.json['hydra:totalItems']}));

      default:
        return Promise.resolve(
          transformJsonLdDocumentToAORDocument(response.json),
        )
          .then(data => convertHydraDataToAORData(resource, data))
          .then(data => ({data}));
    }
  };

  /**
   * @param {string} type
   * @param {string} resource
   * @param {Object} params
   *
   * @returns {Promise}
   */
  const fetchApi = (type, resource, params) => {
    // Hydra doesn't handle WHERE IN requests, so we fallback to calling GET_ONE n times instead
    if (GET_MANY === type) {
      return Promise.all(
        params.ids.map(
          id =>
            aorDocumentsCache[id]
              ? Promise.resolve({data: aorDocumentsCache[id]})
              : fetchApi(GET_ONE, resource, {id}),
        ),
      ).then(responses => ({data: responses.map(({data}) => data)}));
    }

    return convertAORRequestToHydraRequest(type, resource, params)
      .then(({url, options}) => httpClient(url, options))
      .then(response =>
        convertHydraResponseToAORResponse(type, resource, response),
      );
  };

  return fetchApi;
};
<commit_msg>Avoid caching useless documents.<commit_after>import {
  CREATE,
  DELETE,
  GET_LIST,
  GET_MANY,
  GET_MANY_REFERENCE,
  GET_ONE,
  UPDATE,
} from 'admin-on-rest';
import isPlainObject from 'lodash.isplainobject';
import qs from 'qs';
import fetchHydra from './fetchHydra';

class AORDocument {
  constructor(obj) {
    Object.assign(this, obj, {
      originId: obj.id,
      id: obj['@id'],
    });
  }

  /**
   * @return {string}
   */
  toString() {
    return `[object ${this.id}]`;
  }
}

/**
 * Local cache containing embedded documents.
 * It will be used to prevent useless extra HTTP query if the relation is displayed.
 *
 * @type {Map}
 */
const aorDocumentsCache = new Map();

/**
 * Transforms a JSON-LD document to an admin-on-rest compatible document.
 *
 * @param {Object} document
 * @param {bool} clone
 *
 * @return {AORDocument}
 */
export const transformJsonLdDocumentToAORDocument = (
  document,
  clone = true,
  addToCache = true,
) => {
  if (clone) {
    // deep clone documents
    document = JSON.parse(JSON.stringify(document));
  }

  // The main document is a JSON-LD document, convert it and store it in the cache
  if (document['@id']) {
    document = new AORDocument(document);
  }

  // Replace embedded objects by their IRIs, and store the object itself in the cache to reuse without issuing new HTTP requests.
  Object.keys(document).forEach(key => {
    // to-one
    if (isPlainObject(document[key]) && document[key]['@id']) {
      if (addToCache) {
        aorDocumentsCache[
          document[key]['@id']
        ] = transformJsonLdDocumentToAORDocument(document[key], false, false);
      }
      document[key] = document[key]['@id'];

      return;
    }

    // to-many
    if (
      Array.isArray(document[key]) &&
      document[key].length &&
      isPlainObject(document[key][0]) &&
      document[key][0]['@id']
    ) {
      document[key] = document[key].map(obj => {
        if (addToCache) {
          aorDocumentsCache[obj['@id']] = transformJsonLdDocumentToAORDocument(
            obj,
            false,
            false,
          );
        }

        return obj['@id'];
      });
    }
  });

  return document;
};

/**
 * Maps admin-on-rest queries to a Hydra powered REST API
 *
 * @see http://www.hydra-cg.com/
 *
 * @example
 * CREATE   => POST http://my.api.url/posts/123
 * DELETE   => DELETE http://my.api.url/posts/123
 * GET_LIST => GET http://my.api.url/posts
 * GET_MANY => GET http://my.api.url/posts/123, GET http://my.api.url/posts/456, GET http://my.api.url/posts/789
 * GET_ONE  => GET http://my.api.url/posts/123
 * UPDATE   => PUT http://my.api.url/posts/123
 */
export default ({entrypoint, resources = []}, httpClient = fetchHydra) => {
  /**
   * @param {string} resource
   * @param {Object} data
   *
   * @returns {Promise}
   */
  const convertAORDataToHydraData = (resource, data = {}) => {
    resource = resources.find(({name}) => resource === name);
    if (undefined === resource) {
      return Promise.resolve(data);
    }

    const fieldData = [];
    resource.fields.forEach(({name, normalizeData}) => {
      if (!(name in data) || undefined === normalizeData) {
        return;
      }

      fieldData[name] = normalizeData(data[name]);
    });

    const fieldDataKeys = Object.keys(fieldData);
    const fieldDataValues = Object.values(fieldData);

    return Promise.all(fieldDataValues).then(fieldData => {
      const object = {};
      for (let i = 0; i < fieldDataKeys.length; i++) {
        object[fieldDataKeys[i]] = fieldData[i];
      }

      return {...data, ...object};
    });
  };

  /**
   * @param {string} type
   * @param {string} resource
   * @param {Object} params
   *
   * @returns {Object}
   */
  const convertAORRequestToHydraRequest = (type, resource, params) => {
    switch (type) {
      case CREATE:
        return convertAORDataToHydraData(resource, params.data).then(data => ({
          options: {
            body: JSON.stringify(data),
            method: 'POST',
          },
          url: `${entrypoint}/${resource}`,
        }));

      case DELETE:
        return Promise.resolve({
          options: {
            method: 'DELETE',
          },
          url: entrypoint + params.id,
        });

      case GET_LIST: {
        const {
          pagination: {page},
          sort: {field, order},
        } = params;

        return Promise.resolve({
          options: {},
          url: `${entrypoint}/${resource}?${qs.stringify({
            ...params.filter,
            order: {
              [field]: order,
            },
            page,
          })}`,
        });
      }

      case GET_MANY_REFERENCE:
        return Promise.resolve({
          options: {},
          url: `${entrypoint}/${resource}?${qs.stringify({
            [params.target]: params.id,
          })}`,
        });

      case GET_ONE:
        return Promise.resolve({
          options: {},
          url: entrypoint + params.id,
        });

      case UPDATE:
        return convertAORDataToHydraData(resource, params.data).then(data => ({
          options: {
            body: JSON.stringify(data),
            method: 'PUT',
          },
          url: entrypoint + params.id,
        }));

      default:
        throw new Error(`Unsupported fetch action type ${type}`);
    }
  };

  /**
   * @param {string} resource
   * @param {Object} data
   *
   * @returns {Promise}
   */
  const convertHydraDataToAORData = (resource, data = {}) => {
    resource = resources.find(({name}) => resource === name);
    if (undefined === resource) {
      return Promise.resolve(data);
    }

    const fieldData = {};
    resource.fields.forEach(({name, denormalizeData}) => {
      if (!(name in data) || undefined === denormalizeData) {
        return;
      }

      fieldData[name] = denormalizeData(data[name]);
    });

    const fieldDataKeys = Object.keys(fieldData);
    const fieldDataValues = Object.values(fieldData);

    return Promise.all(fieldDataValues).then(fieldData => {
      const object = {};
      for (let i = 0; i < fieldDataKeys.length; i++) {
        object[fieldDataKeys[i]] = fieldData[i];
      }

      return {...data, ...object};
    });
  };

  /**
   * @param {Object} response
   * @param {string} resource
   * @param {string} type
   *
   * @returns {Promise}
   */
  const convertHydraResponseToAORResponse = (type, resource, response) => {
    switch (type) {
      case GET_LIST:
      case GET_MANY_REFERENCE:
        // TODO: support other prefixes than "hydra:"
        return Promise.resolve(
          response.json['hydra:member'].map(
            transformJsonLdDocumentToAORDocument,
          ),
        )
          .then(data =>
            Promise.all(
              data.map(data => convertHydraDataToAORData(resource, data)),
            ),
          )
          .then(data => ({data, total: response.json['hydra:totalItems']}));

      default:
        return Promise.resolve(
          transformJsonLdDocumentToAORDocument(response.json),
        )
          .then(data => convertHydraDataToAORData(resource, data))
          .then(data => ({data}));
    }
  };

  /**
   * @param {string} type
   * @param {string} resource
   * @param {Object} params
   *
   * @returns {Promise}
   */
  const fetchApi = (type, resource, params) => {
    // Hydra doesn't handle WHERE IN requests, so we fallback to calling GET_ONE n times instead
    if (GET_MANY === type) {
      return Promise.all(
        params.ids.map(
          id =>
            aorDocumentsCache[id]
              ? Promise.resolve({data: aorDocumentsCache[id]})
              : fetchApi(GET_ONE, resource, {id}),
        ),
      ).then(responses => ({data: responses.map(({data}) => data)}));
    }

    return convertAORRequestToHydraRequest(type, resource, params)
      .then(({url, options}) => httpClient(url, options))
      .then(response =>
        convertHydraResponseToAORResponse(type, resource, response),
      );
  };

  return fetchApi;
};
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var passport = require('passport');
var process = require('process');
var http = require('http');

var configPath = './config/app.js';
process.argv.forEach((val, index) => {
  if (index > 1) {
    if (val.toLowerCase().startsWith('--config=')) {
      configPath = val.split('=')[1];
    }
    else {
      var error = "Cannot parse '" + val + "'.  The only accepted parameter is --config=<path-to-config-file> ";
      throw error;
    }
  }
});

var config = require('./config');
config.loadConfig(configPath);

var modelsUtil = require('./models/util/util');
var log = require('./logging');
var models = require('./models');

log.info('Starting Full Noise.');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(passport.initialize());
log.addExpressApp(app);

// Adding API documentation
app.use(express.static(__dirname + '/apidoc'));

// Adding headers to allow cross-origin HTTP request.
// This is so the web interface running on a different port/domain can access the API.
// This could cause security issues with Cookies but JWTs are used instead of Cookies.
app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS, PATCH');
  res.header('Access-Control-Allow-Headers', 'where, offset, limit, Authorization');
  next();
});

require('./api/V1')(app);
app.use(require('./api/customErrors').errorHandler);

// Add file processing API.
var fileProcessingApp = express();
fileProcessingApp.use(bodyParser.urlencoded({ extended: false }));
require('./api/fileProcessing')(fileProcessingApp);
http.createServer(fileProcessingApp).listen(config.fileProcessing.port);
log.info('Starting file processing on', config.fileProcessing.port);

log.info("Connecting to database.....");
models.sequelize
  .authenticate()
  .then(() => log.info("Connected to database."))
  .then(() => checkS3Connection())
  .then(() => openHttpServer(app))
  .catch(function(error) {
    log.error(error);
    process.exit(2);
  });

function openHttpServer(app) {
  return new Promise(function(resolve, reject) {
    if (!config.server.http.active)
    {return resolve();}
    try {
      log.info('Starting http server on ', config.server.http.port);
      http.createServer(app).listen(config.server.http.port);
      return resolve();
    } catch (err) {
      return reject(err);
    }
  });
}

// Returns a Promise that will reolve if it could connect to the S3 file storage
// and reject if connection failed.
function checkS3Connection() {
  return new Promise(function(resolve, reject) {
    var s3 = modelsUtil.openS3();
    var params = { Bucket: config.s3.bucket };
    log.info("Connecting to S3.....");
    s3.headBucket(params, function(err) {
      if (err) {
        log.error("Error with connecting to S3.");
        return reject(err);
      }
      log.info("Connected to S3.");
      return resolve();
    });
  });
}
<commit_msg>Added error handler to the file processing API<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var passport = require('passport');
var process = require('process');
var http = require('http');

var configPath = './config/app.js';
process.argv.forEach((val, index) => {
  if (index > 1) {
    if (val.toLowerCase().startsWith('--config=')) {
      configPath = val.split('=')[1];
    }
    else {
      var error = "Cannot parse '" + val + "'.  The only accepted parameter is --config=<path-to-config-file> ";
      throw error;
    }
  }
});

var config = require('./config');
config.loadConfig(configPath);

var modelsUtil = require('./models/util/util');
var log = require('./logging');
var models = require('./models');

log.info('Starting Full Noise.');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(passport.initialize());
log.addExpressApp(app);

// Adding API documentation
app.use(express.static(__dirname + '/apidoc'));

// Adding headers to allow cross-origin HTTP request.
// This is so the web interface running on a different port/domain can access the API.
// This could cause security issues with Cookies but JWTs are used instead of Cookies.
app.all('*', function(req, res, next) {
  res.header('Access-Control-Allow-Origin', req.headers.origin);
  res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS, PATCH');
  res.header('Access-Control-Allow-Headers', 'where, offset, limit, Authorization');
  next();
});

require('./api/V1')(app);
app.use(require('./api/customErrors').errorHandler);

// Add file processing API.
var fileProcessingApp = express();
fileProcessingApp.use(bodyParser.urlencoded({ extended: false }));
require('./api/fileProcessing')(fileProcessingApp);
http.createServer(fileProcessingApp).listen(config.fileProcessing.port);
log.info('Starting file processing on', config.fileProcessing.port);
fileProcessingApp.use(require('./api/customErrors').errorHandler);

log.info("Connecting to database.....");
models.sequelize
  .authenticate()
  .then(() => log.info("Connected to database."))
  .then(() => checkS3Connection())
  .then(() => openHttpServer(app))
  .catch(function(error) {
    log.error(error);
    process.exit(2);
  });

function openHttpServer(app) {
  return new Promise(function(resolve, reject) {
    if (!config.server.http.active)
    {return resolve();}
    try {
      log.info('Starting http server on ', config.server.http.port);
      http.createServer(app).listen(config.server.http.port);
      return resolve();
    } catch (err) {
      return reject(err);
    }
  });
}

// Returns a Promise that will reolve if it could connect to the S3 file storage
// and reject if connection failed.
function checkS3Connection() {
  return new Promise(function(resolve, reject) {
    var s3 = modelsUtil.openS3();
    var params = { Bucket: config.s3.bucket };
    log.info("Connecting to S3.....");
    s3.headBucket(params, function(err) {
      if (err) {
        log.error("Error with connecting to S3.");
        return reject(err);
      }
      log.info("Connected to S3.");
      return resolve();
    });
  });
}
<|endoftext|>


<commit_before>// import dbmodels from 'bt-mongodb';
//
// ueber dbmodels.profile muesstest du Zugriff auf die Funktionen kriegen

module.exports = (req, res, next) => {
  if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
    const authToken = req.headers.authorization.split(' ')[1];

    // Suche nach Profile in unserer Datenbank
    // TODO: Nur zum testen
    if (authToken !== 'das_ist_ein_geheimnis') {
      return next(new Error('Das Token stimmt nicht überein'));
    }
    return next();
  }

  return next(new Error('Authorization header is empty or does not have the format: "Bearer <token>"'));
};
<commit_msg>Verifizierung bei API Calls weitergeschrieben<commit_after>import dbmodels from 'bt-mongodb';

module.exports = (req, res, next) => {
  if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
    const authToken = req.headers.authorization.split(' ')[1];

    if (authToken === undefined) {
      next(new Error('The token is undefined'));
    }

    dbmodels.profile.findByOauthtoken(authToken, (err, profile) => {
      if (err) {
        next(new Error('Error in findIdByOauthtoken'));
      }

      if (!profile) {
        next(new Error('No matching profile found'));
      }

      next();
    });
  } else {
    next(new Error('Authorization header is empty or does not have the format: "Bearer <token>"'));
  }
};
<|endoftext|>


<commit_before>CKEDITOR.plugins.add('imagebrowser', {
	"init": function (editor) {
		if (typeof(editor.config.imageBrowser_listUrl) === 'undefined' || editor.config.imageBrowser_listUrl === null) {
			return;
		}

		editor.config.filebrowserImageBrowseUrl = editor.plugins.imagebrowser.path + "browser/browser.html?listUrl=" + encodeURIComponent(editor.config.imageBrowser_listUrl);
	}
});
<commit_msg>Relative image URL's are not resolved correctly!<commit_after>CKEDITOR.plugins.add('imagebrowser', {
	"init": function (editor) {
		if (typeof(editor.config.imageBrowser_listUrl) === 'undefined' || editor.config.imageBrowser_listUrl === null) {
			return;
		}

		editor.config.filebrowserImageBrowseUrl = editor.plugins.imagebrowser.path + "browser/browser.html?listUrl=" + encodeURIComponent(editor.config.imageBrowser_listUrl) + "&baseHref=" + encodeURIComponent(editor.config.baseHref);
	}
});
<|endoftext|>


<commit_before>/**
 * GLOW.Vector3 Based upon THREE.Vector3 by
 * @author mr.doob / http://mrdoob.com/
 * @author kile / http://kile.stravaganza.org/
 * @author philogb / http://blog.thejit.org/
 * @author mikael emtinger / http://gomo.se/
 */

GLOW.Vector3 = (function( x, y, z ) {

	"use strict"; "use restrict";

    // constructor
    function vector3( x, y, z ) {
    	this.value = new Float32Array( 3 );
    	this.value[ 0 ] = x !== undefined ? x : 0;
    	this.value[ 1 ] = y !== undefined ? y : 0;
    	this.value[ 2 ] = z !== undefined ? z : 0;
    }

    // methods
    vector3.prototype.set = function( x, y, z ) {
    	this.value[ 0 ] = x;
    	this.value[ 1 ] = y;
    	this.value[ 2 ] = z;
    	return this;
    }

    vector3.prototype.copy = function ( v ) {
    	this.set( this.value[ 0 ], this.value[ 1 ], this.value[ 2 ] );
    	return this;
    }

    vector3.prototype.add = function ( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 0 ] + b[ 0 ];
    	this.value[ 1 ] = a[ 1 ] + b[ 1 ];
    	this.value[ 2 ] = a[ 2 ] + b[ 2 ];
    	return this;
    }

    vector3.prototype.addSelf = function ( a ) {
    	a = a.value;
    	this.value[ 0 ] = this.value[ 0 ] + a[ 0 ];
    	this.value[ 1 ] = this.value[ 1 ] + a[ 1 ];
    	this.value[ 2 ] = this.value[ 2 ] + a[ 2 ];
    	return this;
    }

    vector3.prototype.addScalar = function ( s ) {
    	this.value[ 0 ] += s;
    	this.value[ 1 ] += s;
    	this.value[ 2 ] += s;
    	return this;
    }

    vector3.prototype.sub = function ( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 0 ] - b[ 0 ];
    	this.value[ 1 ] = a[ 1 ] - b[ 1 ];
    	this.value[ 2 ] = a[ 2 ] - b[ 2 ];
    	return this;
    }

    vector3.prototype.subSelf = function ( a ) {
    	a = a.value;
    	this.value[ 0 ] -= a[ 0 ];
    	this.value[ 1 ] -= a[ 1 ];
    	this.value[ 2 ] -= a[ 2 ];
    	return this;
    }

    vector3.prototype.cross = function ( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
    	this.value[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
    	this.value[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
    	return this;
    }

    vector3.prototype.crossSelf = function ( a ) {
    	a = a.value;
    	var ax = a[ 0 ], ay = a[ 1 ], az = a[ 2 ];
    	var vx = this.value[ 0 ], vy = this.value[ 1 ], vz = this.value[ 2 ];
    	this.value[ 0 ] = ay * vz - az * vy;
    	this.value[ 1 ] = az * vx - ax * vz;
    	this.value[ 2 ] = ax * vy - ay * vx;
    	return this;
    }

    vector3.prototype.multiply = function( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 0 ] * b[ 0 ];
    	this.value[ 1 ] = a[ 1 ] * b[ 1 ];
    	this.value[ 2 ] = a[ 2 ] * b[ 2 ];
    	return this;
    }

    vector3.prototype.multiplySelf = function( a ) {
    	a = a.value;
    	this.value[ 0 ] *= a[ 0 ];
    	this.value[ 1 ] *= a[ 1 ];
    	this.value[ 2 ] *= a[ 2 ];
    	return this;
    }

    vector3.prototype.multiplyScalar = function( s ) {
    	this.value[ 0 ] *= s;
    	this.value[ 1 ] *= s;
    	this.value[ 2 ] *= s;
    	return this;
    }

    vector3.prototype.divideSelf = function( a ) {
    	a = a.value;
    	this.value[ 0 ] /= a[ 0 ];
    	this.value[ 1 ] /= a[ 1 ];
    	this.value[ 2 ] /= a[ 2 ];
    	return this;
    }

    vector3.prototype.divideScalar = function( s ) {
    	this.value[ 0 ] /= s;
    	this.value[ 1 ] /= s;
    	this.value[ 2 ] /= s;
    	return this;
    }

    vector3.prototype.negate = function() {
    	this.value[ 0 ] = -this.value[ 0 ];
    	this.value[ 1 ] = -this.value[ 1 ];
    	this.value[ 2 ] = -this.value[ 2 ];
    	return this;
    }

    vector3.prototype.dot = function( a ) {
    	a = a.value;
    	return this.value[ 0 ] * a[ 0 ] + this.value[ 1 ] * a[ 1 ] + this.value[ 2 ] * a[ 2 ];
    }

    vector3.prototype.distanceTo = function ( a ) {
    	return Math.sqrt( this.distanceToSquared( a ) );
    }

    vector3.prototype.distanceToSquared = function( a ) {
    	a = a.value;
    	var dx = this.value[ 0 ] - a[ 0 ], dy = this.value[ 1 ] - a[ 1 ], dz = this.value[ 2 ] - a[ 2 ];
    	return dx * dx + dy * dy + dz * dz;
    }

    vector3.prototype.length = function() {
    	return Math.sqrt( this.lengthSq() );
    }

    vector3.prototype.lengthSq = function() {
    	return this.value[ 0 ] * this.value[ 0 ] + this.value[ 1 ] * this.value[ 1 ] + this.value[ 2 ] * this.value[ 2 ];
    }

    vector3.prototype.lengthManhattan = function() {
    	return this.value[ 0 ] + this.value[ 1 ] + this.value[ 2 ];
    }

    vector3.prototype.normalize = function() {
    	var l = Math.sqrt( this.value[ 0 ] * this.value[ 0 ] + this.value[ 1 ] * this.value[ 1 ] + this.value[ 2 ] * this.value[ 2 ] );
    	l > 0 ? this.multiplyScalar( 1 / l ) : this.set( 0, 0, 0 );
    	return this;
    }

    vector3.prototype.setPositionFromMatrix = function( m ) {
    	m = m.value;
    	this.value[ 0 ] = m[ 12 ];
    	this.value[ 1 ] = m[ 13 ];
    	this.value[ 2 ] = m[ 14 ];
    }

    vector3.prototype.setLength = function( l ) {
    	return this.normalize().multiplyScalar( l );
    }

    vector3.prototype.isZero = function() {
    	var almostZero = 0.0001;
    	return ( Math.abs( this.value[ 0 ] ) < almostZero ) && ( Math.abs( this.value[ 1 ] ) < almostZero ) && ( Math.abs( this.value[ 2 ] ) < almostZero );
    }

    vector3.prototype.clone = function() {
    	return GLOW.Vector3( this.value[ 0 ], this.value[ 1 ], this.value[ 2 ] );
    }

    return vector3;
})();
<commit_msg>Small bugfix<commit_after>/**
 * GLOW.Vector3 Based upon THREE.Vector3 by
 * @author mr.doob / http://mrdoob.com/
 * @author kile / http://kile.stravaganza.org/
 * @author philogb / http://blog.thejit.org/
 * @author mikael emtinger / http://gomo.se/
 */

GLOW.Vector3 = (function() {

	"use strict"; "use restrict";

    // constructor
    function vector3( x, y, z ) {
    	this.value = new Float32Array( 3 );
    	this.value[ 0 ] = x !== undefined ? x : 0;
    	this.value[ 1 ] = y !== undefined ? y : 0;
    	this.value[ 2 ] = z !== undefined ? z : 0;
    }

    // methods
    vector3.prototype.set = function( x, y, z ) {
    	this.value[ 0 ] = x;
    	this.value[ 1 ] = y;
    	this.value[ 2 ] = z;
    	return this;
    }

    vector3.prototype.copy = function ( v ) {
    	this.set( v.value[ 0 ], v.value[ 1 ], v.value[ 2 ] );
    	return this;
    }

    vector3.prototype.add = function ( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 0 ] + b[ 0 ];
    	this.value[ 1 ] = a[ 1 ] + b[ 1 ];
    	this.value[ 2 ] = a[ 2 ] + b[ 2 ];
    	return this;
    }

    vector3.prototype.addSelf = function ( a ) {
    	a = a.value;
    	this.value[ 0 ] = this.value[ 0 ] + a[ 0 ];
    	this.value[ 1 ] = this.value[ 1 ] + a[ 1 ];
    	this.value[ 2 ] = this.value[ 2 ] + a[ 2 ];
    	return this;
    }

    vector3.prototype.addScalar = function ( s ) {
    	this.value[ 0 ] += s;
    	this.value[ 1 ] += s;
    	this.value[ 2 ] += s;
    	return this;
    }

    vector3.prototype.sub = function ( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 0 ] - b[ 0 ];
    	this.value[ 1 ] = a[ 1 ] - b[ 1 ];
    	this.value[ 2 ] = a[ 2 ] - b[ 2 ];
    	return this;
    }

    vector3.prototype.subSelf = function ( a ) {
    	a = a.value;
    	this.value[ 0 ] -= a[ 0 ];
    	this.value[ 1 ] -= a[ 1 ];
    	this.value[ 2 ] -= a[ 2 ];
    	return this;
    }

    vector3.prototype.cross = function ( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
    	this.value[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
    	this.value[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
    	return this;
    }

    vector3.prototype.crossSelf = function ( a ) {
    	a = a.value;
    	var ax = a[ 0 ], ay = a[ 1 ], az = a[ 2 ];
    	var vx = this.value[ 0 ], vy = this.value[ 1 ], vz = this.value[ 2 ];
    	this.value[ 0 ] = ay * vz - az * vy;
    	this.value[ 1 ] = az * vx - ax * vz;
    	this.value[ 2 ] = ax * vy - ay * vx;
    	return this;
    }

    vector3.prototype.multiply = function( a, b ) {
    	a = a.value;
    	b = b.value;
    	this.value[ 0 ] = a[ 0 ] * b[ 0 ];
    	this.value[ 1 ] = a[ 1 ] * b[ 1 ];
    	this.value[ 2 ] = a[ 2 ] * b[ 2 ];
    	return this;
    }

    vector3.prototype.multiplySelf = function( a ) {
    	a = a.value;
    	this.value[ 0 ] *= a[ 0 ];
    	this.value[ 1 ] *= a[ 1 ];
    	this.value[ 2 ] *= a[ 2 ];
    	return this;
    }

    vector3.prototype.multiplyScalar = function( s ) {
    	this.value[ 0 ] *= s;
    	this.value[ 1 ] *= s;
    	this.value[ 2 ] *= s;
    	return this;
    }

    vector3.prototype.divideSelf = function( a ) {
    	a = a.value;
    	this.value[ 0 ] /= a[ 0 ];
    	this.value[ 1 ] /= a[ 1 ];
    	this.value[ 2 ] /= a[ 2 ];
    	return this;
    }

    vector3.prototype.divideScalar = function( s ) {
    	this.value[ 0 ] /= s;
    	this.value[ 1 ] /= s;
    	this.value[ 2 ] /= s;
    	return this;
    }

    vector3.prototype.negate = function() {
    	this.value[ 0 ] = -this.value[ 0 ];
    	this.value[ 1 ] = -this.value[ 1 ];
    	this.value[ 2 ] = -this.value[ 2 ];
    	return this;
    }

    vector3.prototype.dot = function( a ) {
    	a = a.value;
    	return this.value[ 0 ] * a[ 0 ] + this.value[ 1 ] * a[ 1 ] + this.value[ 2 ] * a[ 2 ];
    }

    vector3.prototype.distanceTo = function ( a ) {
    	return Math.sqrt( this.distanceToSquared( a ) );
    }

    vector3.prototype.distanceToSquared = function( a ) {
    	a = a.value;
    	var dx = this.value[ 0 ] - a[ 0 ], dy = this.value[ 1 ] - a[ 1 ], dz = this.value[ 2 ] - a[ 2 ];
    	return dx * dx + dy * dy + dz * dz;
    }

    vector3.prototype.length = function() {
    	return Math.sqrt( this.lengthSq() );
    }

    vector3.prototype.lengthSq = function() {
    	return this.value[ 0 ] * this.value[ 0 ] + this.value[ 1 ] * this.value[ 1 ] + this.value[ 2 ] * this.value[ 2 ];
    }

    vector3.prototype.lengthManhattan = function() {
    	return this.value[ 0 ] + this.value[ 1 ] + this.value[ 2 ];
    }

    vector3.prototype.normalize = function() {
    	var l = Math.sqrt( this.value[ 0 ] * this.value[ 0 ] + this.value[ 1 ] * this.value[ 1 ] + this.value[ 2 ] * this.value[ 2 ] );
    	l > 0 ? this.multiplyScalar( 1 / l ) : this.set( 0, 0, 0 );
    	return this;
    }

    vector3.prototype.setPositionFromMatrix = function( m ) {
    	m = m.value;
    	this.value[ 0 ] = m[ 12 ];
    	this.value[ 1 ] = m[ 13 ];
    	this.value[ 2 ] = m[ 14 ];
    }

    vector3.prototype.setLength = function( l ) {
    	return this.normalize().multiplyScalar( l );
    }

    vector3.prototype.isZero = function() {
    	var almostZero = 0.0001;
    	return ( Math.abs( this.value[ 0 ] ) < almostZero ) && ( Math.abs( this.value[ 1 ] ) < almostZero ) && ( Math.abs( this.value[ 2 ] ) < almostZero );
    }

    vector3.prototype.clone = function() {
    	return GLOW.Vector3( this.value[ 0 ], this.value[ 1 ], this.value[ 2 ] );
    }

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


<commit_before>/* eslint no-var: 0 */
var exec = require('child_process').exec;
var fs = require('fs-extra');

function copyFile(filePath,destinationPath,callback){
    if(!destinationPath){
        throw new Error('Destination directory missing');
    }
    if(!filePath){
        throw new Error('Source file missing');
    }

    fs.copy(filePath,destinationPath,function(error){
        if(error){
            return console.error(error)
        }else{
            console.log('COPY: ' + filePath + ' copied to ' + destinationPath)
            if(callback){
                callback()
            }
        }
    });
}

function copyDir(source,dest,callback){
    if(!source){
        throw new Error('Source directory missing');
    }
    if(!dest){
        throw new Error('Destination directory missing');
    }

    fs.copy(source,dest,function(error){
        if(error){
            return console.error(error)
        }else{
            console.log( 'COPY: ' + source + ' copied to ' + dest)
            if(callback){
                callback();
            }
        }
    });
}

function createDir(dirPath,callback){
    if(!dirPath){
        throw new Error('directory path missing');
    }

    fs.ensureDir(dirPath,function(error){
        if(error){
            return console.error(error)
        }else{
            console.log( 'Directory created at : ' + dirPath)
            if(callback){
                callback();
            }
        }
    });
}

function remove(source,callback){
    fs.remove(source, function(error) {
        if (error) {
            return console.error(error)
        }
        console.log('REMOVE: ' + source + ' deleted')
        if(callback){
            callback();
        }
    })
}

function writeJson(source,json){
    fs.writeJson(source,json, function(error) {
        if (error) {
            return console.error(error)
        }
        console.log('WRITE: ' + source + ' created')
    })
}

function updateJson(source,newJson,callback){
    fs.readJson(source,function(error,sourceJson){
        var json = Object.assign({},sourceJson,newJson);
        fs.outputJson(source,json, function(error) {
            if (error) {
                return console.error(error)
            }
            console.log('WRITE: ' + source + ' created')
            if(callback){
                callback();
            }
        })
    })

}

function changeCurrentWorkingDirTemporarily(dirPath, command){
    //For this Node process 'bower install' working directory is changed to build/client
//upon completion Node cwd will shift back to root where we started this process.
    execute(command, false,{
        cwd:dirPath
    });
}

function execute(commands,setNodeEnv,options,callback){
    if(Array.isArray(commands)){
        commands.map(function(cmdLine){
            _execute(cmdLine,setNodeEnv,options);
        })
    }else {
        _execute(commands,setNodeEnv,options);
    }
    if(callback){
        callback()
    }
}

function _execute(cmdLine,setNodeEnv,options){

    if(typeof cmdLine !== 'string'){
        throw new Error("String format expected for commands")
    }
    if(setNodeEnv){
        var environ = (!process.argv[2].indexOf('development')) ? 'development' : 'production';
        if (process.platform === 'win32') {
            cmdLine = 'set NODE_ENV=' + environ + '&& ' + cmdLine;
        } else {
            cmdLine = 'NODE_ENV=' + environ + ' ' + cmdLine;
        }
    }

    var command;
    if(options) {
        command = exec(cmdLine,options);
    }else {
        command = exec(cmdLine);
    }

    /* eslint-disable */
    command.stdout.on('data', function(data) {
        process.stdout.write(data);
    });
    command.stderr.on('data', function(data) {
        process.stderr.write(data);
    });
    command.on('error', function(err) {
        process.stderr.write(err);
    });
    /* eslint-enable */
}

module.exports = {
    copyFile,
    copyDir,
    createDir,
    remove,
    writeJson,
    updateJson,
    execute,
    changeCurrentWorkingDirTemporarily
};

<commit_msg>callback added to command<commit_after>/* eslint no-var: 0 */
var exec = require('child_process').exec;
var fs = require('fs-extra');

function copyFile(filePath,destinationPath,callback){
    if(!destinationPath){
        throw new Error('Destination directory missing');
    }
    if(!filePath){
        throw new Error('Source file missing');
    }

    fs.copy(filePath,destinationPath,function(error){
        if(error){
            return console.error(error)
        }else{
            console.log('COPY: ' + filePath + ' copied to ' + destinationPath)
            if(callback){
                callback()
            }
        }
    });
}

function copyDir(source,dest,callback){
    if(!source){
        throw new Error('Source directory missing');
    }
    if(!dest){
        throw new Error('Destination directory missing');
    }

    fs.copy(source,dest,function(error){
        if(error){
            return console.error(error)
        }else{
            console.log( 'COPY: ' + source + ' copied to ' + dest)
            if(callback){
                callback();
            }
        }
    });
}

function createDir(dirPath,callback){
    if(!dirPath){
        throw new Error('directory path missing');
    }

    fs.ensureDir(dirPath,function(error){
        if(error){
            return console.error(error)
        }else{
            console.log( 'Directory created at : ' + dirPath)
            if(callback){
                callback();
            }
        }
    });
}

function remove(source,callback){
    fs.remove(source, function(error) {
        if (error) {
            return console.error(error)
        }
        console.log('REMOVE: ' + source + ' deleted')
        if(callback){
            callback();
        }
    })
}

function writeJson(source,json){
    fs.writeJson(source,json, function(error) {
        if (error) {
            return console.error(error)
        }
        console.log('WRITE: ' + source + ' created')
    })
}

function updateJson(source,newJson,callback){
    fs.readJson(source,function(error,sourceJson){
        var json = Object.assign({},sourceJson,newJson);
        fs.outputJson(source,json, function(error) {
            if (error) {
                return console.error(error)
            }
            console.log('WRITE: ' + source + ' created')
            if(callback){
                callback();
            }
        })
    })

}

function changeCurrentWorkingDirTemporarily(dirPath, command){
    //For this Node process 'bower install' working directory is changed to build/client
//upon completion Node cwd will shift back to root where we started this process.
    execute(command, false,{
        cwd:dirPath
    });
}

function execute(commands,setNodeEnv,options,callback){
    if(Array.isArray(commands)){
        commands.map(function(cmdLine){
            _execute(cmdLine,setNodeEnv,options,callback);
        })
    }else {
        _execute(commands,setNodeEnv,options,callback);
    }
}

function _execute(cmdLine,setNodeEnv,options,callback){

    if(typeof cmdLine !== 'string'){
        throw new Error("String format expected for commands")
    }
    if(setNodeEnv){
        var environ = (!process.argv[2].indexOf('development')) ? 'development' : 'production';
        if (process.platform === 'win32') {
            cmdLine = 'set NODE_ENV=' + environ + '&& ' + cmdLine;
        } else {
            cmdLine = 'NODE_ENV=' + environ + ' ' + cmdLine;
        }
    }

    var command;
    if(options) {
        command = exec(cmdLine,options,(error, stdout, stderr) => {
            if (error) {
                console.error(`exec error: ${error}`);
                return;
            }
            console.log(`stdout: ${stdout}`);
            console.log(`stderr: ${stderr}`);
            if(callback){
                callback();
            }
        });
    }else {
        command = exec(cmdLine,(error, stdout, stderr) => {
            if (error) {
                console.error(`exec error: ${error}`);
                return;
            }
            console.log(`stdout: ${stdout}`);
            console.log(`stderr: ${stderr}`);
            if(callback){
                callback();
            }
        });
    }

}

module.exports = {
    copyFile,
    copyDir,
    createDir,
    remove,
    writeJson,
    updateJson,
    execute,
    changeCurrentWorkingDirTemporarily
};

<|endoftext|>