<commit_before>'use strict';

/**
 * Start a main loop on the provided game with the provided options.
 * @param {Array.<Object>} updateables Objects with two functions: update() and render().
 *   update(deltaTime) should update the game state. The deltaTime parameter
 *   is time passed since the last update in seconds.
 *   render() should draw the current game state and optionally return a
 *   CanvasRenderingContext2D that the following updateables in the array will use.
 *   Updateables that are processed after the first one receive this rendering context
 *   as a parameter.
 * @param {Object} options Takes the following keys:
 *
 * updateFPS: number
 *  The rate at which the game state receives update() calls.
 *  Having a fixed update rate can help you to make the game deterministic
 *  and to keep physics calculations stable.
 *  Every update is not necessarily displayed on the screen.
 *
 * debugMode: boolean
 *  When debugMode is on, a timeline of frames is drawn on the canvas returned
 *  from updateables[i].render().
 *  - Green in the log is an update which was rendered to the screen.
 *  - Orange in the log is an update which was not rendered to the screen.
 *  - White in the log is a frame on which the game state was not updated.
 */
var startMainLoop = function(updateables, options) {
    var defaults = {
        updateFPS: 60,
        debugMode: false
    };

    if (options === undefined) {
        options = {};
    }
    for(var key in defaults) {
        if(!options.hasOwnProperty(key)) {
            options[key] = defaults[key];
        }
    }
    if (!(updateables instanceof Array)) {
        updateables = [updateables];
    }

    var timePerUpdate = 1000 / options.updateFPS;

    var nextFrameTime = new Date().getTime() - timePerUpdate * 0.5;

    var frameLog = [];

    var logTimeToX = function(time, lastTime, canvasWidth) {
        var fpsMult = Math.max(60, options.updateFPS) / 60;
        return (canvasWidth - 1) - (Math.ceil(lastTime / 2000) * 2000 - time) * 0.2 * fpsMult;
    }

    var drawFrameLog = function(ctx, callbackTime) {
        var w = ctx.canvas.width;
        ctx.save();
        ctx.globalAlpha = 0.5;
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, w, 10);

        ctx.globalAlpha = 1.0;
        ctx.fillStyle = '#0f0';
        var lastTime = callbackTime;
        var i = frameLog.length;
        var x = ctx.canvas.width;
        while (i > 0 && x > 0) {
            --i;
            var frameStats = frameLog[i];
            if (frameStats.updates >= 1) {
                ctx.fillRect(logTimeToX(frameStats.time, lastTime, w), 0, 2, 10);
                    if (frameStats.updates > 1) {
                    ctx.fillStyle = '#f84';
                    for (var j = 1; j < frameStats.updates; ++j) {
                        var updateX = logTimeToX(frameStats.time - (j - 0.5) * timePerUpdate, lastTime, w);
                        ctx.fillRect(Math.round(updateX), 0, 2, 10);
                    }
                    ctx.fillStyle = '#0f0';
                }
            } else {
                ctx.fillStyle = '#fff';
                ctx.fillRect(logTimeToX(frameStats.time, lastTime, w), 0, 2, 10);
                ctx.fillStyle = '#0f0';
            }
        }
        ctx.restore();
    };

    var frame = function() {
        // Process a single requestAnimationFrame callback
        var time = new Date().getTime();
        var callbackTime = time;
        var updated = false;
        var updates = 0;
        // If there's been a long time since the last callback, it can be a sign that the game
        // is running very badly but it is possible that the game has gone out of focus entirely.
        // In either case, it is reasonable to do a maximum of half a second's worth of updates
        // at once.
        if (time - nextFrameTime > 500) {
            nextFrameTime = time - 500;
        }
        while (time > nextFrameTime) {
            nextFrameTime += timePerUpdate;
            for (var i = 0; i < updateables.length; ++i) {
                updateables[i].update(timePerUpdate * 0.001);
            }
            updates++;
        }
        if (options.debugMode) {
            frameLog.push({time: callbackTime, updates: updates});
        }
        if (updates > 0) {
            var ctx = updateables[0].render();
            for (var i = 1; i < updateables.length; ++i) {
                var candidateCtx = updateables[i].render(ctx);
                if (candidateCtx !== undefined) {
                    ctx = candidateCtx;
                }
            }
            if (options.debugMode && (ctx instanceof CanvasRenderingContext2D)) {
                drawFrameLog(ctx, callbackTime);
                if (frameLog.length >= 1024) {
                    frameLog.splice(0, 512);
                }
            }
        }
        requestAnimationFrame(frame);
    };
    frame();
};
<commit_msg>Use performance.now if it is available<commit_after>'use strict';

/**
 * Start a main loop on the provided game with the provided options.
 * @param {Array.<Object>} updateables Objects with two functions: update() and render().
 *   update(deltaTime) should update the game state. The deltaTime parameter
 *   is time passed since the last update in seconds.
 *   render() should draw the current game state and optionally return a
 *   CanvasRenderingContext2D that the following updateables in the array will use.
 *   Updateables that are processed after the first one receive this rendering context
 *   as a parameter.
 * @param {Object} options Takes the following keys:
 *
 * updateFPS: number
 *  The rate at which the game state receives update() calls.
 *  Having a fixed update rate can help you to make the game deterministic
 *  and to keep physics calculations stable.
 *  Every update is not necessarily displayed on the screen.
 *
 * debugMode: boolean
 *  When debugMode is on, a timeline of frames is drawn on the canvas returned
 *  from updateables[i].render().
 *  - Green in the log is an update which was rendered to the screen.
 *  - Orange in the log is an update which was not rendered to the screen.
 *  - White in the log is a frame on which the game state was not updated.
 */
var startMainLoop = function(updateables, options) {
    var defaults = {
        updateFPS: 60,
        debugMode: false
    };

    if (options === undefined) {
        options = {};
    }
    for(var key in defaults) {
        if(!options.hasOwnProperty(key)) {
            options[key] = defaults[key];
        }
    }
    if (!(updateables instanceof Array)) {
        updateables = [updateables];
    }

    var now = function() {
        if ('performance' in window && 'now' in performance) {
            return performance.now();
        } else {
            return Date.now();
        }
    };

    var timePerUpdate = 1000 / options.updateFPS;

    var nextFrameTime = now() - timePerUpdate * 0.5;

    var frameLog = [];

    var logTimeToX = function(time, lastTime, canvasWidth) {
        var fpsMult = Math.max(60, options.updateFPS) / 60;
        return (canvasWidth - 1) - (Math.ceil(lastTime / 2000) * 2000 - time) * 0.2 * fpsMult;
    }

    var drawFrameLog = function(ctx, callbackTime) {
        var w = ctx.canvas.width;
        ctx.save();
        ctx.globalAlpha = 0.5;
        ctx.fillStyle = '#000';
        ctx.fillRect(0, 0, w, 10);

        ctx.globalAlpha = 1.0;
        ctx.fillStyle = '#0f0';
        var lastTime = callbackTime;
        var i = frameLog.length;
        var x = ctx.canvas.width;
        while (i > 0 && x > 0) {
            --i;
            var frameStats = frameLog[i];
            if (frameStats.updates >= 1) {
                ctx.fillRect(logTimeToX(frameStats.time, lastTime, w), 0, 2, 10);
                    if (frameStats.updates > 1) {
                    ctx.fillStyle = '#f84';
                    for (var j = 1; j < frameStats.updates; ++j) {
                        var updateX = logTimeToX(frameStats.time - (j - 0.5) * timePerUpdate, lastTime, w);
                        ctx.fillRect(Math.round(updateX), 0, 2, 10);
                    }
                    ctx.fillStyle = '#0f0';
                }
            } else {
                ctx.fillStyle = '#fff';
                ctx.fillRect(logTimeToX(frameStats.time, lastTime, w), 0, 2, 10);
                ctx.fillStyle = '#0f0';
            }
        }
        ctx.restore();
    };

    var frame = function() {
        // Process a single requestAnimationFrame callback
        var time = now();
        var callbackTime = time;
        var updated = false;
        var updates = 0;
        // If there's been a long time since the last callback, it can be a sign that the game
        // is running very badly but it is possible that the game has gone out of focus entirely.
        // In either case, it is reasonable to do a maximum of half a second's worth of updates
        // at once.
        if (time - nextFrameTime > 500) {
            nextFrameTime = time - 500;
        }
        while (time > nextFrameTime) {
            nextFrameTime += timePerUpdate;
            for (var i = 0; i < updateables.length; ++i) {
                updateables[i].update(timePerUpdate * 0.001);
            }
            updates++;
        }
        if (options.debugMode) {
            frameLog.push({time: callbackTime, updates: updates});
        }
        if (updates > 0) {
            var ctx = updateables[0].render();
            for (var i = 1; i < updateables.length; ++i) {
                var candidateCtx = updateables[i].render(ctx);
                if (candidateCtx !== undefined) {
                    ctx = candidateCtx;
                }
            }
            if (options.debugMode && (ctx instanceof CanvasRenderingContext2D)) {
                drawFrameLog(ctx, callbackTime);
                if (frameLog.length >= 1024) {
                    frameLog.splice(0, 512);
                }
            }
        }
        requestAnimationFrame(frame);
    };
    frame();
};
<|endoftext|>


<commit_before>var minifyJS = require('../buildTypes/minifyJS'),
	minifyCSS = require('../buildTypes/minifyCSS'),
	transformActiveSource = require("../node/transform_active_source");
function minify(node, options){
	transformActiveSource(node,"minify-true", function(node, source){
		var minifier = node.load.metadata.buildType === "css" ?
				minifyCSS : minifyJS;
		var result = ''
		try {
			result = minifier(source, options);
		} catch(e) {
			console.warn('Error occured while minification of', node.load.address);
			throw(e)
		}

		return result;
	});
}

module.exports = function(graph, options){
	options = options || {};

	if(Array.isArray(graph, options)) {
		graph.forEach(function(node){
			minify(node, options);
		});
	} else {
		for(var name in graph) {
			var node = graph[name];
			minify(node, options);
		}
	}
	return graph;
};
<commit_msg>Add semicolons<commit_after>var minifyJS = require('../buildTypes/minifyJS'),
	minifyCSS = require('../buildTypes/minifyCSS'),
	transformActiveSource = require("../node/transform_active_source");
function minify(node, options){
	transformActiveSource(node,"minify-true", function(node, source){
		var minifier = node.load.metadata.buildType === "css" ?
				minifyCSS : minifyJS;
		var result = '';
		try {
			result = minifier(source, options);
		} catch(e) {
			console.warn('Error occured while minification of', node.load.address);
			throw(e);
		}

		return result;
	});
}

module.exports = function(graph, options){
	options = options || {};

	if(Array.isArray(graph, options)) {
		graph.forEach(function(node){
			minify(node, options);
		});
	} else {
		for(var name in graph) {
			var node = graph[name];
			minify(node, options);
		}
	}
	return graph;
};
<|endoftext|>


<commit_before>var Q = require('q'),
    _ = require('underscore'),
    TEMPLATE_REPO = 'git+http://github.com/heinzelmannchen/heinzelmannchen-tpl-default-config',
    TEMPLATE_FILE = 'heinzelrc.tpl',
    DATA_FILE = 'heinzelrc.json',
    heinzel = require('heinzelmannchen');

module.exports = {
    command: 'init [template] [ask] [repo]',
    alias: 'ii [template] [ask] [repo]',
    description: 'initialize the .heinzelrc',
    action: init
};

function init(template, ask, repo) {
    if (template && !ask) {
        ask = template.replace('tpl', 'json');
    }
    return heinzel.init(repo || TEMPLATE_REPO, template || TEMPLATE_FILE, ask || DATA_FILE);
}
<commit_msg>init function where it belongs<commit_after>var Q = require('q'),
    _ = require('underscore'),
    TEMPLATE_REPO = 'git+http://github.com/heinzelmannchen/heinzelmannchen-tpl-default-config',
    TEMPLATE_FILE = 'heinzelrc.tpl',
    DATA_FILE = 'heinzelrc.json',
    heinzel = require('heinzelmannchen'),
    askGen = require('heinzelmannchen-gen-ask');

module.exports = {
    command: 'init [template] [ask] [repo]',
    alias: 'ii [template] [ask] [repo]',
    description: 'initialize the .heinzelrc',
    action: init
};

function init(template, ask, repo) {
    if (template && !ask) {
        ask = template.replace('tpl', 'json');
    }
    repo = repo || TEMPLATE_REPO;
    template = template || TEMPLATE_FILE;
    ask = ask || DATA_FILE;
    return heinzel.installTemplates(repo)
        .then(function(module) {
            module = heinzel.resolvePackageNameFromUrl(module);
            askGen = new askGen();
            askGen.setConfig(require(module[0] + '/' + ask));
            return askGen.createData().then(function(answers) {
                var data = {};
                answers = answers[0];
                _.each(answers, function(element, key) {
                    var values = _.map(element.split(','), function(value) {
                        return value.trim();
                    });
                    data[key] = values;
                });
                return heinzel.templateFromNpm(module[0] + '/' + template, data);
            });
        })
        .then(function(content) {
            return heinzel.write('.heinzelrc', content);
        });
}
<|endoftext|>


<commit_before>require('colors');

var sketchplatePath = require('../config').sketchplatePath,
    spawn = require('win-spawn'),
    path = require('path'),
    fs = require('graceful-fs'),
    _ = require('underscore');

/**
 * Launch your project in your editor
 * @param {String} location the path to your project
 * @param {Object} options
 * @param {Array} options.editorArgs the arguments used to launch your editor
 * @param {Function} callback(err, code)
 * @return {ChildProcess}
 */
module.exports = function( location, options, callback ){
    var editorArgs,
        isDirectory = fs.statSync(location).isDirectory();
    //find editorArgs
    if( typeof options === 'object' && options.cmd ){
        editorArgs = options;
    } else if ( !options || !options.editorArgs || !options.editorArgs.cmd ){
        throw new Error('Invalid `options.editorArgs` parameter');
    } else {
        editorArgs = options.editorArgs;
    }

    editorArgs.args = editorArgs.args || [];
    callback = callback || function(){};

    var variables = {
        workspace: location,
        workspaceDir: isDirectory ? location : path.dirname(location),
        sketchplatePath: sketchplatePath,
        process: process
    };

    if( editorArgs.cwd ){
        editorArgs.cwd = _.template( editorArgs.cwd, variables );
    }
    editorArgs.cmd = _.template( editorArgs.cmd, variables );
    editorArgs.args = editorArgs.args.map(function(arg){
        return _.template( arg, variables );
    });

    var editorProcess = spawn( editorArgs.cmd, editorArgs.args, {
        cwd: editorArgs.cwd ? editorArgs.cwd : undefined,
        stdio: 'inherit'
    });

    editorProcess.on('exit', function ( code ){
        var error = null;
        if( code !== 0){
            error = new Error('Editor exited with code '.red+ code);
        }
        callback( error, code );
    });

    return editorProcess;
};
<commit_msg>editor params are absolute paths<commit_after>require('colors');

var sketchplatePath = require('../config').sketchplatePath,
    spawn = require('win-spawn'),
    path = require('path'),
    fs = require('graceful-fs'),
    _ = require('underscore');

/**
 * Launch your project in your editor
 * @param {String} location the path to your project
 * @param {Object} options
 * @param {Array} options.editorArgs the arguments used to launch your editor
 * @param {Function} callback(err, code)
 * @return {ChildProcess}
 */
module.exports = function( location, options, callback ){
    var editorArgs,
        isDirectory = fs.statSync(location).isDirectory();
    //find editorArgs
    if( typeof options === 'object' && options.cmd ){
        editorArgs = options;
    } else if ( !options || !options.editorArgs || !options.editorArgs.cmd ){
        throw new Error('Invalid `options.editorArgs` parameter');
    } else {
        editorArgs = options.editorArgs;
    }

    editorArgs.args = editorArgs.args || [];
    callback = callback || function(){};

    location = path.resolve(location);

    var variables = {
        workspace: location,
        workspaceDir: isDirectory ? location : path.dirname(location),
        sketchplatePath: sketchplatePath,
        process: process
    };

    if( editorArgs.cwd ){
        editorArgs.cwd = _.template( editorArgs.cwd, variables );
    }
    editorArgs.cmd = _.template( editorArgs.cmd, variables );
    editorArgs.args = editorArgs.args.map(function(arg){
        return _.template( arg, variables );
    });

    var editorProcess = spawn( editorArgs.cmd, editorArgs.args, {
        cwd: editorArgs.cwd ? editorArgs.cwd : undefined,
        stdio: 'inherit'
    });

    editorProcess.on('exit', function ( code ){
        var error = null;
        if( code !== 0){
            error = new Error('Editor exited with code '.red+ code);
        }
        callback( error, code );
    });

    return editorProcess;
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name         eBox
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.emag.ro/*
// @grant        none
// @require http://code.jquery.com/jquery-3.2.1.js
// ==/UserScript==

(function() {
    'use strict';

    console.log('Greasemonkey loaded!');

    var matches = window.location.href.match(/pd\/([^\/]+)/);
    if (!matches) return;
    var productCode = matches[1];
    console.log('Product code: ' + productCode);

    function checkDeliveryEstimatePanel() {
        console.log('Looking for panel...');
        var deliveryEstimatePanel = $('.delivery-estimate-panel');
        if (!deliveryEstimatePanel.find('.delivery-estimate-box').length) {
            setTimeout(checkDeliveryEstimatePanel, 300);
            return;
        }

        console.log('Ready!');

        deliveryEstimatePanel.append('

eBox instant
livrare automata instantanee

');
    }

    setTimeout(checkDeliveryEstimatePanel, 2000);
})();<commit_msg>Checking boxability on a whitelist in the user script<commit_after>// ==UserScript==
// @name         eBox
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.emag.ro/*
// @grant        none
// @require http://code.jquery.com/jquery-3.2.1.js
// ==/UserScript==

(function() {
    'use strict';

    console.log('Greasemonkey loaded!');

    var matches = window.location.href.match(/pd\/([^\/]+)/);
    if (!matches) return;
    var productCode = matches[1];
    console.log('Product code: ' + productCode);

    function checkDeliveryEstimatePanel() {
        console.log('Looking for panel...');
        var deliveryEstimatePanel = $('.delivery-estimate-panel');
        if (!deliveryEstimatePanel.find('.delivery-estimate-box').length) {
            setTimeout(checkDeliveryEstimatePanel, 300);
            return;
        }

        console.log('Ready!');
        console.log('Checking boxability...');

        var boxable = false;
        var boxableProductCodes = ['DY3MHDBBM','D3SBN2BBM','DLXM4KBBM','D1XVG7BBM','DSQD33BBM','DFXR03BBM','DRXVG7BBM','DPTK07BBM','DKJB4KBBM','DPDVF2BBM','DNDVF2BBM','DMSQKMBBM','DPL63MBBM','DX90QBBBM','DKQH5YBBM','DN0G1BBBM','D0HQXBBBM','DX5L07BBM','DP0TCBBBM','DPTL42BBM','DJFNS7BBM','D2WS8YBBM','DSY023BBM','DNJGZ3BBM','DY2JV2BBM','DTY0RBBBM','DNL6X2BBM','DLZGDDBBM','DJQT0MBBM','D0R5SBBBM'];
        for (var i in boxableProductCodes) {
            if (boxableProductCodes[i] == productCode) {
                boxable = true;
                break;
            }
        }
        if (boxable) {
            console.log('Boxable it is!');
            deliveryEstimatePanel.append(
                '
'+
                    '
'+
                        ''+
                        '
'+
                            '
eBox instant
livrare automata instantanee'+
                        '
'+
                    '
'+
                '
'
            );
        } else {
            console.log('Not boxable at this time!');
        }
    }

    setTimeout(checkDeliveryEstimatePanel, 2000);
})();<|endoftext|>


<commit_before>'use strict';
/* eslint-env es6 */
/* eslint-disable no-unused-vars */

// jscs:disable disallowMultipleVarDecl
var Q = require('q');
var Hoxy = require('hoxy');
var Mongoose = require('mongoose');
Mongoose.Promise = require('q').Promise;
var mongoDB;
var Prettyjson = require('prettyjson');
var _ = require('lodash');
var __ = require('./lodash-like.js');

exports.serve = function(configParams) {
  // jshint validthis:true
  var servicesShemaModel =
    {
      url: String,
      method: String,
      headers: Object,
      body: Object,
      responseData: Object,
      responseStatusCode: Number,
      timeStamp: Date
    },
    ServicesSchema, proxy;

  function formatHeaders(headers) {
    return _.omit(headers, ['host', 'user-agent', 'accept', 'accept-language', 'accept-encoding', 'dnt',
      'x-requested-with', 'content-type', 'referer', 'content-length', 'cookie', 'origin',
      'connection', 'pragma', 'cache-control']);
  }

  function respondEntry(response, entry) {
    var responseData = entry.responseData || entry.successData; // <- legacy support.
    response.statusCode = entry.responseStatusCode || 200;
    response.string = JSON.stringify(responseData);
  }

  function updateRequestEntry(request, response, entry) {
    entry.responseData = response.json;
    return entry;
  }

  function createRequestEntry(request, response) {
    (new ServicesSchema({
      url: request.url,
      method: request.method,
      headers: __.sortObjectDeep(formatHeaders(request.headers), true),
      body: __.sortObjectDeep(request.json, true),
      responseData: response.json,
      responseStatusCode: response.statusCode,
      timeStamp: Date.now()
    })).save(function(error) {
      if (error) return console.error(error);
    });
  }

  function responseInterceptor(request, response) {
    createRequestEntry(request, response);
    if (!configParams.quiet) {
      requestPrintLog(request);
    }
  }

  function printSearchNeedle(searchNeedle) {
    console.info('===================== Serach Needle =======================');
    console.info(Prettyjson.render({searchedTimeStamp: String(Date.now())}));
    console.info();
    console.info(Prettyjson.render(__.sortObjectDeep(searchNeedle.source, true)));
  }

  function requestPrintLog(request) {
    console.info('============ Request from greenTomato -> server ===============');
    console.info(Prettyjson.render({requestTimeStamp: String(Date.now())}));
    console.info();
    console.info(Prettyjson.render(request));
  }

  function getSearchNeedle(request) {
    var searchNeedle =
      {
        url: _.clone(request.url),
        method: _.clone(request.method)
      },
      parsedHeaders = __.sortObjectDeep(formatHeaders(request.headers));

    if (!_.isEmpty(parsedHeaders)) {
      searchNeedle.headers = parsedHeaders;
    }

    if (request.json) {
      searchNeedle.body = __.sortObjectDeep(request.json);
    }

    if (configParams.searchIgnore) {
      __.unassign(searchNeedle, configParams.searchIgnore);
    }

    return {
      query: __.toPath(searchNeedle),
      source: searchNeedle
    };
  }

  function respondError(response) {
    response.statusCode = 418;
    response.string = 'I\'m a teapot';
  }

  function requestInterceptor(request, response) {
    var searchNeedle;

    if (configParams.regexp && configParams.substitution) {
      request.url = request.url.replace(configParams.regex.search, configParams.regex.replace);
    }

    searchNeedle = getSearchNeedle(request);
    if (!configParams.quiet) {
      printSearchNeedle(searchNeedle);
    }

    return ServicesSchema.find(searchNeedle.query)
      .sort({timeStamp: -1})
      .findOne()
      .exec()
      .then(respondEntry.bind(this, response))
      .catch(respondError.bind(this, response))
    ;
  }

  function attachInterceptors() {
    var method = /post|get|put|delete/i;

    if (configParams.forceCache) {
      proxy.intercept({
        phase: 'request',
        method: method
      }, requestInterceptor);
    } else {
      if (configParams.regexp) {
        proxy.intercept({
          phase: 'request',
          method: method
        }, function(request) {
          request.url = request.url.replace(configParams.regexp.search, configParams.regexp.replace);
        });
      }

      proxy.intercept({
        phase: 'response',
        as: 'json',
        method: method
      }, responseInterceptor);
    }
  }

  function initDB() {
    Mongoose.connect('mongodb://localhost/greenTomato', {
      server: {
        auto_reconnect: true,
        socketOptions : {
          keepAlive: 1
        }
      }
    });

    mongoDB = Mongoose.connection;
    mongoDB.once('open', function () {
      ServicesSchema = Mongoose.model(configParams.mongoSchema, Mongoose.Schema(servicesShemaModel));
    });
    mongoDB.on('error', console.error.bind(console, 'Error:'));
  }

  function initialize() {
    initDB();
    proxy = Hoxy.createServer({
      reverse: configParams.proxyHost
    }).listen(configParams.port);

    attachInterceptors();
  }

  initialize();
};
<commit_msg>feat(core): Included the filter functionallity previously described.<commit_after>'use strict';
/* eslint-env es6 */
/* eslint-disable no-unused-vars */

const Q = require('q');
const Hoxy = require('hoxy');
const Mongoose = require('mongoose');
Mongoose.Promise = require('q').Promise;
const Prettyjson = require('prettyjson');
const _ = require('lodash');
const __ = require('./lodash-like.js');
const Child_process = require('child_process');
var mongoDB;

exports.serve = function(configParams) {
  var servicesShemaModel =
    {
      url: String,
      method: String,
      headers: Object,
      body: Object,
      responseData: Object,
      responseStatusCode: Number,
      timeStamp: Date
    },
    ServicesSchema, proxy;

  function formatHeaders(headers) {
    return _.omit(headers, ['host', 'user-agent', 'accept', 'accept-language', 'accept-encoding', 'dnt',
      'x-requested-with', 'content-type', 'referer', 'content-length', 'cookie', 'origin',
      'connection', 'pragma', 'cache-control']);
  }

  function respondEntry(response, entry) {
    var responseData = entry.responseData || entry.successData; // <- legacy support.
    response.statusCode = entry.responseStatusCode || 200;
    response.string = JSON.stringify(responseData);
  }

  function updateRequestEntry(request, response, entry) {
    entry.responseData = response.json;
    return entry;
  }

  function createRequestEntry(request, response) {
    (new ServicesSchema({
      url: request.url,
      method: request.method,
      headers: __.sortObjectDeep(formatHeaders(request.headers), true),
      body: __.sortObjectDeep(request.json, true),
      responseData: response.json,
      responseStatusCode: response.statusCode,
      timeStamp: Date.now()
    })).save(function(error) {
      if (error) return console.error(error);
    });
  }

  function responseInterceptor(request, response) {
    if (configParams.filter &&
    Child_process.spawnSync(configParams.filter, [JSON.stringify(response.json)]).status === 0) {
      createRequestEntry(request, response);
    }

    if (!configParams.quiet) {
      requestPrintLog(request);
    }
  }

  function printSearchNeedle(searchNeedle) {
    console.info('===================== Serach Needle =======================');
    console.info(Prettyjson.render({searchedTimeStamp: String(Date.now())}));
    console.info();
    console.info(Prettyjson.render(__.sortObjectDeep(searchNeedle.source, true)));
  }

  function requestPrintLog(request) {
    console.info('============ Request from greenTomato -> server ===============');
    console.info(Prettyjson.render({requestTimeStamp: String(Date.now())}));
    console.info();
    console.info(Prettyjson.render(request));
  }

  function getSearchNeedle(request) {
    var searchNeedle =
      {
        url: _.clone(request.url),
        method: _.clone(request.method)
      },
      parsedHeaders = __.sortObjectDeep(formatHeaders(request.headers));

    if (!_.isEmpty(parsedHeaders)) {
      searchNeedle.headers = parsedHeaders;
    }

    if (request.json) {
      searchNeedle.body = __.sortObjectDeep(request.json);
    }

    if (configParams.searchIgnore) {
      __.unassign(searchNeedle, configParams.searchIgnore);
    }

    return {
      query: __.toPath(searchNeedle),
      source: searchNeedle
    };
  }

  function respondError(response) {
    response.statusCode = 418;
    response.string = 'I\'m a teapot';
  }

  function requestInterceptor(request, response) {
    var searchNeedle;

    if (configParams.regexp && configParams.substitution) {
      request.url = request.url.replace(configParams.regex.search, configParams.regex.replace);
    }

    searchNeedle = getSearchNeedle(request);
    if (!configParams.quiet) {
      printSearchNeedle(searchNeedle);
    }

    return ServicesSchema.find(searchNeedle.query)
      .sort({timeStamp: -1})
      .findOne()
      .exec()
      .then(respondEntry.bind(this, response))
      .catch(respondError.bind(this, response))
    ;
  }

  function attachInterceptors() {
    var method = /post|get|put|delete/i;

    if (configParams.forceCache) {
      proxy.intercept({
        phase: 'request',
        method: method
      }, requestInterceptor);
    } else {
      if (configParams.regexp) {
        proxy.intercept({
          phase: 'request',
          method: method
        }, function(request) {
          request.url = request.url.replace(configParams.regexp.search, configParams.regexp.replace);
        });
      }

      proxy.intercept({
        phase: 'response',
        as: 'json',
        method: method
      }, responseInterceptor);
    }
  }

  function initDB() {
    Mongoose.connect('mongodb://localhost/greenTomato', {
      server: {
        auto_reconnect: true,
        socketOptions : {
          keepAlive: 1
        }
      }
    });

    mongoDB = Mongoose.connection;
    mongoDB.once('open', function () {
      ServicesSchema = Mongoose.model(configParams.mongoSchema, Mongoose.Schema(servicesShemaModel));
    });
    mongoDB.on('error', console.error.bind(console, 'Error:'));
  }

  function initialize() {
    initDB();
    proxy = Hoxy.createServer({
      reverse: configParams.proxyHost
    }).listen(configParams.port);

    attachInterceptors();
  }

  initialize();
};
<|endoftext|>


<commit_before>/*
Step: [0-1]
StepSink: Step ->
StepSource: StepSink ->
  step(n): stepSource // produce n linear steps between 0 and 1 inclusive
VertexSink: Vertex, Step, Step* ->
VertexGenerator: VertexSink -> StepSink
  vertices(vertices) // take the given vertices to create a VertexGenerator
  vertices(f): (Step -> Vertex) -> VertexGenerator // convert a vertex producer into a vertex generator
VertexMap: VertexSink -> VertexSink
  zTranslate(start,end): translate vertices along z axis
  zRotate(start*,end*): rotate vertices around z axis
  tag(edges): mark vertices with tags
Facer: FaceSink -> VertexSink
  face(options): Produce a facer with the given options for tesselating and joining
Renderer: * -> FaceSink
  ThreeJSRenderer
  CSGRenerer
  STLRenderer
  NativeRenderer
*/

// cube
var renderer = ThreeJSRenderer();

// cube
step(2)(
  vertices([[1,1],[-1,1],[-1,-1],[1,-1]])(
  transform(zTranslate(1), label) (
  face( edgeLoop, tesselate('bottom'), tesselate('top',true) )( renderer ))))

var geometry = renderer.geometry;

// OR
extrudeClosed = face( edgeLoop, tesselate('bottom'), tesselate('top',true) )

// sphere
var R = 40, Q = 20, 2PI = 2*Math.Pi, hPI = Math.PI/2;
function simiCircle(s) {return [R*Math.cos(tween(s,-hPI,hPI)),0,R*Math.sin(tween(s,-hPI,hPI))]}

step(Q)(
  step(Q)(
    vertices(semiCircle))(
      zRotate()(
        face(connect:'tb', singular:'lr')( renderer ))))

/// TESSELATE

function vadd(a,v) { return [a[0]+v[0], a[1]+v[1], a[2]+v[2]]; }
function vsub(a,v) { return [a[0]-v[0], a[1]-v[1], a[2]-v[2]]; }
function vscale(a,c) { return [a[0]*c, a[1]*c, a[2]*c]; }
function vdot(a,v) { return a[0]*v[0] + a[1]*v[1] + a[2]*v[2]; }
function vcross(v) { return [a[1]*v[2] - a[2]*v[1], a[2]*v[0] - a[0]*v[2], a[0]*v[1] - a[1]*v[0]]; }
function vec(a) {
  var o={
    add : function add(v) { a=vadd(a,v); return o}
    sub : function sub(v) { a=vsub(a,v); return o}
    scale : function scale(c) { a=vscale(a,c) ; return o}
    dot : function dot(v) { return vdot(a,v); }
    cross : function cross(v) { a = vcross(a,v); return o}
    toA : function() {return a}
  return o
}

function vectorAverage(vs) { return vs.lenght ? vscale( vs.reduce(vadd,[0,0,0]), 1/vs.length ) : [0,0,0]; }

function loopMeanNormal(vs) {
  function v(i) { return vs[i%vs.length] }
  return vectorAverage(vs.map(function(v0,i){return vcross(vsub(v0,v(i+1)), vsub(v(i+2), v(i+1)))}))
}

function intersect(v1, v2, v3, v4) {
  var det = (v1.x-v2.x)*(v3.y-v4.y) - (v1.y-v2.y)*(v3.x-v4.x);
  return !det ? null : {
    x: ((v1.x*v2.y-v2.x*v1.y)*(v3.x-v4.x) - (v3.x*v4.y-v4.x*v3.y)*(v1.x-v2.x))/det,
    y: ((v1.x*v2.y-v2.x*v1.y)*(v3.y-v4.y) - (v3.x*v4.y-v4.x*v3.y)*(v1.y-v2.y))/det
  };
}

function doesIntersect(v1, v2, v3, v4) {
  var p = intersect(v1,v2,v3,v4);
  if (!p) return false;
  return p.x >= Math.min(v1.x,v2.x) && p.x >= Math.min(v3.x,v4.x)
    && p.x <= Math.max(v1.x,v2.x) && p.x <= Math.max(v3.x,v4.x)
    && p.y >= Math.min(v1.y,v2.y) && p.y >= Math.min(v3.y,v4.y)
    && p.y <= Math.max(v1.y,v2.y) && p.y <= Math.max(v3.y,v4.y);
}

function isSelfIntersecting( p1, p2, vertices ) {
  for (var i=0,v1,v2; v1=vertices[i], v2=vertices[i+1]; i++)
    if ( doesIntersect(p1,p2,v1,v2) ) return true;
  return false;
}

function tesselate3d() {
  // first find the mean plane by finding the mean point of all the vertices, then finding the mean normal
  // by averaging the cross-product of every 3 consecutive vertices. Then project each vertex onto this plane.
  // These should be passed to tesslateVertices, and the faceSink should be wrapped to return the original 3d
  // vertex.
}

function tesselateVertices(vertices, faceSink) {
  if ( vertices.length < 3 ) return;
  if ( vertices.length < 4 ) return tesselateConvex(vertices);

  // traveling in either direction, find the first negative vertex followed by a positive one.
  // If there are no negative vertices, the shape is convex. Tesselate and return.
  // Starting with the vertex after that, find the first negative vertex or the last vertext s.t.
  //   the angle formed from it and the first two vertices is < π.
  // Create two new sets of vertices, one containing all the vertices found above, and the
  //   other containing the rest plus the first and last from above.
  // The first set is convex, so pass it on to be tesselated.
  // The second list is "less concave", because the points at the ends now have less negative angles.
  // Recurse with the second list.
  function index(i) { return (i+vertices.length)%vertices.length;  }
  function center(i) { return vertices[ i%vertices.length ] }
  function left(i) { return vertices[ (i+vertices.length-1)%vertices.length ] }
  function right(i) { return vertices[ (i+1)%vertices.length ] }
  function angle(l,p,r) { return Math.atan2(
    (r.x-p.x)*(l.y-p.y) - (r.y-p.y)*(l.x-p.x),
    (r.x-p.x)*(l.x-p.x) + (r.y-p.y)*(l.y-p.y)
  ) }

  var angles = vertices.map( function(p,i) { return angle(left(i),p,right(i)); })

  var startPoint;
  for (var i=vertices.length-1; i>=0; i--) {
    if ( angles[i] <= 0 && angles[index(i+1)] > 0 ) {
      startPoint = i;

      for (var j=2, endPoint; j<vertices.length-1; j++) {
      endPoint = j + startPoint;
        if ( angle(left(endPoint),center(endPoint),right(endPoint)) <= 0 )
          break;

        if ( angle(center(endPoint),center(startPoint), right(startPoint)) <= 0 ) {
          endPoint = (endPoint+vertices.length-1) % vertices.length;
          break;
        }
      }

      endPoint = index(endPoint);

      var newShape, rest;
      if (endPoint < startPoint) {
        newShape = vertices.slice(startPoint).concat(vertices.slice(0,endPoint+1));
        rest = vertices.slice(endPoint, startPoint+1);
      } else {
        newShape = vertices.slice(startPoint, endPoint+1);
        rest = vertices.slice(endPoint).concat(vertices.slice(0,startPoint+1));
      }

      if ( ! isSelfIntersecting( vertices[startPoint], vertices[endPoint], rest.slice(1,rest.length-1) ) ) {
        if ( Math.abs(endPoint- startPoint) <= 1 || Math.abs(endPoint- startPoint) >= vertices.length -1 ) {
          console.log("wrap around", startPoint, endPoint, vertices.length);
          return;
        }
        if (endPoint < startPoint) {
          tesselate( vertices.slice(startPoint).concat(vertices.slice(0,endPoint+1)) );
          tesselate( vertices.slice(endPoint, startPoint+1 ) );
        } else {
          tesselate( vertices.slice(startPoint, endPoint+1 ) );
          tesselate( vertices.slice(endPoint).concat(vertices.slice(0,startPoint+1)) );
        }

        ctx.strokeStyle = '#fff';
        ctx.lineWidth = 2;
        var p = center(startPoint);
        ctx.beginPath()
        ctx.moveTo( p.x, p.y );
        p = center(endPoint);
        ctx.lineTo( p.x, p.y );
        ctx.stroke();
        return;
      }
    }
  }

  return tesselateConvex(vertices);

}

function tesselateConvex(vertices) {
  var ai = 0, bi=(vertices.length/3)|0, ci=(2*vertices.length/3)|0;
  var a = vertices[ai], b=vertices[bi], c=vertices[ci];

  ctx.fillStyle = randomColor();
  ctx.strokeStyle = '#000';
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(a.x,a.y);
  ctx.lineTo(b.x,b.y);
  ctx.lineTo(c.x,c.y);
  ctx.closePath();
  ctx.fill();
  ctx.stroke();

  if (bi-ai > 1) tesselateConvex(vertices.slice(ai,bi+1));
  if (ci-bi > 1) tesselateConvex(vertices.slice(bi,ci+1));
  if (vertices.length-ci > 1)
    tesselateConvex(vertices.slice(ci,vertices.length).concat([a]));
}
<commit_msg>projecting points onto a plane<commit_after>/*
Step: [0-1]
StepSink: Step ->
StepSource: StepSink ->
  step(n): stepSource // produce n linear steps between 0 and 1 inclusive
VertexSink: Vertex, Step, Step* ->
VertexGenerator: VertexSink -> StepSink
  vertices(vertices) // take the given vertices to create a VertexGenerator
  vertices(f): (Step -> Vertex) -> VertexGenerator // convert a vertex producer into a vertex generator
VertexMap: VertexSink -> VertexSink
  zTranslate(start,end): translate vertices along z axis
  zRotate(start*,end*): rotate vertices around z axis
  tag(edges): mark vertices with tags
Facer: FaceSink -> VertexSink
  face(options): Produce a facer with the given options for tesselating and joining
Renderer: * -> FaceSink
  ThreeJSRenderer
  CSGRenerer
  STLRenderer
  NativeRenderer
*/

// cube
var renderer = ThreeJSRenderer();

// cube
step(2)(
  vertices([[1,1],[-1,1],[-1,-1],[1,-1]])(
  transform(zTranslate(1), label) (
  face( edgeLoop, tesselate('bottom'), tesselate('top',true) )( renderer ))))

var geometry = renderer.geometry;

// OR
extrudeClosed = face( edgeLoop, tesselate('bottom'), tesselate('top',true) )

// sphere
var R = 40, Q = 20, 2PI = 2*Math.Pi, hPI = Math.PI/2;
function simiCircle(s) {return [R*Math.cos(tween(s,-hPI,hPI)),0,R*Math.sin(tween(s,-hPI,hPI))]}

step(Q)(
  step(Q)(
    vertices(semiCircle))(
      zRotate()(
        face(connect:'tb', singular:'lr')( renderer ))))

/// TESSELATE

function vadd(a,v) { return [a[0]+v[0], a[1]+v[1], a[2]+v[2]]; }
function vsub(a,v) { return [a[0]-v[0], a[1]-v[1], a[2]-v[2]]; }
function vscale(a,c) { return [a[0]*c, a[1]*c, a[2]*c]; }
function vdot(a,v) { return a[0]*v[0] + a[1]*v[1] + a[2]*v[2]; }
function vcross(v) { return [a[1]*v[2] - a[2]*v[1], a[2]*v[0] - a[0]*v[2], a[0]*v[1] - a[1]*v[0]]; }
function vlength(v) { return Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]); }
function vnorm(v) { var l=vlength(v); return v > 0 ? [v[0]/l, v[1]/l, v[2]/l] : v; }

function vectorAverage(vs) { return vs.lenght ? vscale( vs.reduce(vadd,[0,0,0]), 1/vs.length ) : [0,0,0]; }

function loopMeanNormal(vs) {
  function v(i) { return vs[i%vs.length] }
  return vectorAverage(vs.map(function(v0,i){return vcross(vsub(v0,v(i+1)), vsub(v(i+2), v(i+1)))}))
}

function intersect(v1, v2, v3, v4) {
  var det = (v1.x-v2.x)*(v3.y-v4.y) - (v1.y-v2.y)*(v3.x-v4.x);
  return !det ? null : {
    x: ((v1.x*v2.y-v2.x*v1.y)*(v3.x-v4.x) - (v3.x*v4.y-v4.x*v3.y)*(v1.x-v2.x))/det,
    y: ((v1.x*v2.y-v2.x*v1.y)*(v3.y-v4.y) - (v3.x*v4.y-v4.x*v3.y)*(v1.y-v2.y))/det
  };
}

function doesIntersect(v1, v2, v3, v4) {
  var p = intersect(v1,v2,v3,v4);
  if (!p) return false;
  return p.x >= Math.min(v1.x,v2.x) && p.x >= Math.min(v3.x,v4.x)
    && p.x <= Math.max(v1.x,v2.x) && p.x <= Math.max(v3.x,v4.x)
    && p.y >= Math.min(v1.y,v2.y) && p.y >= Math.min(v3.y,v4.y)
    && p.y <= Math.max(v1.y,v2.y) && p.y <= Math.max(v3.y,v4.y);
}

function isSelfIntersecting( p1, p2, vertices ) {
  for (var i=0,v1,v2; v1=vertices[i], v2=vertices[i+1]; i++)
    if ( doesIntersect(p1,p2,v1,v2) ) return true;
  return false;
}

function projectIntoPlane( p, planePoint, planeNormal ) {
  // p - pp - (((p-pp) . pn) * pn)
  var pTranslated = vsub( p, planePoint );
  return vsub( pTranslated, vscale( planeNormal, vdot( pTranslated, planeNormal )))
}

function tesselate3d( points3d, faceSink ) {
  var planeNormal = vnorm(loopMeanNormal(points3d));
  var planePoint = vectorAverage(points3d);

  var offNormal = vadd( planePoint, Math.abs(planeNormal[0] < .5) ? [1,0,0] : [0,1,0] );
  var axis1 = vnorm(projectIntoPlane(offNormal ,planePoint, planeNormal));
  var axis2 = vcross( axis1, planeNormal );
  // first find the mean plane by finding the mean point of all the vertices, then finding the mean normal
  // by averaging the cross-product of every 3 consecutive vertices. Then project each vertex onto this plane.
  // These should be passed to tesslateVertices, and the faceSink should be wrapped to return the original 3d
  // vertex.

  // PROJECT:
  // ap = the average point
  // an = the average normal
  // projected = p + ((p-ap) . an) for p in points
  // u1 = norm(projected[0]-ap) // or the first point != ap
  // u2 = norm(u1 X an)
  // flattend = [p . u1, p . u2] for p in projected
}

function tesselateVertices(vertices, faceSink) {
  if ( vertices.length < 3 ) return;
  if ( vertices.length < 4 ) return tesselateConvex(vertices);

  // traveling in either direction, find the first negative vertex followed by a positive one.
  // If there are no negative vertices, the shape is convex. Tesselate and return.
  // Starting with the vertex after that, find the first negative vertex or the last vertext s.t.
  //   the angle formed from it and the first two vertices is < π.
  // Create two new sets of vertices, one containing all the vertices found above, and the
  //   other containing the rest plus the first and last from above.
  // The first set is convex, so pass it on to be tesselated.
  // The second list is "less concave", because the points at the ends now have less negative angles.
  // Recurse with the second list.
  function index(i) { return (i+vertices.length)%vertices.length;  }
  function center(i) { return vertices[ i%vertices.length ] }
  function left(i) { return vertices[ (i+vertices.length-1)%vertices.length ] }
  function right(i) { return vertices[ (i+1)%vertices.length ] }
  function angle(l,p,r) { return Math.atan2(
    (r.x-p.x)*(l.y-p.y) - (r.y-p.y)*(l.x-p.x),
    (r.x-p.x)*(l.x-p.x) + (r.y-p.y)*(l.y-p.y)
  ) }

  var angles = vertices.map( function(p,i) { return angle(left(i),p,right(i)); })

  var startPoint;
  for (var i=vertices.length-1; i>=0; i--) {
    if ( angles[i] <= 0 && angles[index(i+1)] > 0 ) {
      startPoint = i;

      for (var j=2, endPoint; j<vertices.length-1; j++) {
      endPoint = j + startPoint;
        if ( angle(left(endPoint),center(endPoint),right(endPoint)) <= 0 )
          break;

        if ( angle(center(endPoint),center(startPoint), right(startPoint)) <= 0 ) {
          endPoint = (endPoint+vertices.length-1) % vertices.length;
          break;
        }
      }

      endPoint = index(endPoint);

      var newShape, rest;
      if (endPoint < startPoint) {
        newShape = vertices.slice(startPoint).concat(vertices.slice(0,endPoint+1));
        rest = vertices.slice(endPoint, startPoint+1);
      } else {
        newShape = vertices.slice(startPoint, endPoint+1);
        rest = vertices.slice(endPoint).concat(vertices.slice(0,startPoint+1));
      }

      if ( ! isSelfIntersecting( vertices[startPoint], vertices[endPoint], rest.slice(1,rest.length-1) ) ) {
        if ( Math.abs(endPoint- startPoint) <= 1 || Math.abs(endPoint- startPoint) >= vertices.length -1 ) {
          console.log("wrap around", startPoint, endPoint, vertices.length);
          return;
        }
        if (endPoint < startPoint) {
          tesselate( vertices.slice(startPoint).concat(vertices.slice(0,endPoint+1)) );
          tesselate( vertices.slice(endPoint, startPoint+1 ) );
        } else {
          tesselate( vertices.slice(startPoint, endPoint+1 ) );
          tesselate( vertices.slice(endPoint).concat(vertices.slice(0,startPoint+1)) );
        }

        ctx.strokeStyle = '#fff';
        ctx.lineWidth = 2;
        var p = center(startPoint);
        ctx.beginPath()
        ctx.moveTo( p.x, p.y );
        p = center(endPoint);
        ctx.lineTo( p.x, p.y );
        ctx.stroke();
        return;
      }
    }
  }

  return tesselateConvex(vertices);

}

function tesselateConvex(vertices) {
  var ai = 0, bi=(vertices.length/3)|0, ci=(2*vertices.length/3)|0;
  var a = vertices[ai], b=vertices[bi], c=vertices[ci];

  ctx.fillStyle = randomColor();
  ctx.strokeStyle = '#000';
  ctx.lineWidth = 1;
  ctx.beginPath();
  ctx.moveTo(a.x,a.y);
  ctx.lineTo(b.x,b.y);
  ctx.lineTo(c.x,c.y);
  ctx.closePath();
  ctx.fill();
  ctx.stroke();

  if (bi-ai > 1) tesselateConvex(vertices.slice(ai,bi+1));
  if (ci-bi > 1) tesselateConvex(vertices.slice(bi,ci+1));
  if (vertices.length-ci > 1)
    tesselateConvex(vertices.slice(ci,vertices.length).concat([a]));
}
<|endoftext|>


<commit_before>dojo.provide("dojox.grid._Layout");
dojo.require("dojox.grid.cells");
dojo.require("dojox.grid._RowSelector");

dojo.declare("dojox.grid._Layout", null, {
	// summary:
	//	Controls grid cell layout. Owned by grid and used internally.
	constructor: function(inGrid){
		this.grid = inGrid;
	},
	// flat array of grid cells
	cells: [],
	// structured array of grid cells
	structure: null,
	// default cell width
	defaultWidth: '6em',

	// methods
	moveColumn: function(sourceViewIndex, destViewIndex, cellIndex, targetIndex, before){
		var source_cells = this.structure[sourceViewIndex].cells[0];
		var dest_cells = this.structure[destViewIndex].cells[0];

		var cell = null;
		var cell_ri = 0;
		var target_ri = 0;

		for(var i=0, c; c=source_cells[i]; i++){
			if(c.index == cellIndex){
				cell_ri = i;
				break;
			}
		}
		cell = source_cells.splice(cell_ri, 1)[0];
		cell.view = grid.views.views[destViewIndex];

		for(i=0, c=null; c=dest_cells[i]; i++){
			if(c.index == targetIndex){
				target_ri = i;
				break;
			}
		}
		if(!before){
			target_ri += 1;
		}
		dest_cells.splice(target_ri, 0, cell);

		this.cells = [];
		var cellIndex = 0;
		for(var i=0, v; v=this.structure[i]; i++){
			for(var j=0, cs; cs=v.cells[j]; j++){
				for(var k=0, c; c=cs[k]; k++){
					c.index = cellIndex;
					this.cells.push(c);
					cellIndex++;
				}
			}
		}
		//this.grid.renderOnIdle();
	},

	setStructure: function(inStructure){
		var self = this;

		var getCellWidth = function(inDef){
			var w = 0;
			if(inDef.colSpan > 1){
				w = 0;
			}else if(!isNaN(inDef.width)){
				w = inDef.width + "em";
			}else{
				w = inDef.width || self.defaultWidth;
			}
			return w;
		};

		var addCellDef = function(inRowIndex, inCellIndex, inDef){
			var props = {
				grid: self.grid,
				subrow: inRowIndex,
				layoutIndex: inCellIndex,
				index: self.cells.length
			};

			if(inDef && inDef instanceof dojox.grid.cells._Base){
				props.unitWidth = getCellWidth(inDef._props);
				inDef = dojo.mixin(inDef, self._defaultCellProps, inDef._props, props);
				return inDef;
			}

			var cell_type = inDef.type || self._defaultCellProps.type || dojox.grid.cells.Cell;

			props.unitWidth = getCellWidth(inDef);
			return new cell_type(dojo.mixin({}, self._defaultCellProps, inDef, props));
		};

		var addRowDef = function(inRowIndex, inDef){
			var result = [];
			for(var i=0, def, cell; (def=inDef[i]); i++){
				cell = addCellDef(inRowIndex, i, def);
				result.push(cell);
				self.cells.push(cell);
			}
			return result;
		};

		var addRowsDef = function(inDef){
			var result = [];
			if(dojo.isArray(inDef)){
				if(dojo.isArray(inDef[0])){
					for(var i=0, row; inDef && (row=inDef[i]); i++){
						result.push(addRowDef(i, row));
					}
				}else{
					result.push(addRowDef(0, inDef));
				}
			}
			return result;
		};

		var addViewDef = function(inDef){
			self._defaultCellProps = inDef.defaultCell || {};
			return dojo.mixin({}, inDef, {cells: addRowsDef(inDef.rows || inDef.cells)});
		};

		this.fieldIndex = 0;
		this.cells = [];
		var s = this.structure = [];

		if(this.grid.rowSelector){
			var sel = { type: dojox._scopeName + ".grid._RowSelector" };

			if(dojo.isString(this.grid.rowSelector)){
				var width = this.grid.rowSelector;

				if(width == "false"){
					sel = null;
				}else if(width != "true"){
					sel['width'] = width;
				}
			}else{
				if(!this.grid.rowSelector){
					sel = null;
				}
			}

			if(sel){
				s.push(addViewDef(sel));
			}
		}

		var isCell = function(def){
			return ("name" in def || "field" in def || "get" in def);
		};

		var isRowDef = function(def){
			if(dojo.isArray(def)){
				if(dojo.isArray(def[0]) || isCell(def[0])){
					return true;
				}
			}
			return false;
		};

		var isView = function(def){
			return (def != null && dojo.isObject(def) &&
					("cells" in def || "rows" in def || "type" in def));
		};

		if(dojo.isArray(inStructure)){
			var hasViews = false;
			for(var i=0, st; (st=inStructure[i]); i++){
				if(isView(st)){
					hasViews = true;
					break;
				}
			}
			if(!hasViews){
				s.push(addViewDef({ cells: inStructure }));
			}else{
				for(var i=0, st; (st=inStructure[i]); i++){
					if(isRowDef(st)){
						s.push(addViewDef({ cells: st }));
					}else if(isView(st)){
						s.push(addViewDef(st));
					}
				}
			}
		}else if(isView(inStructure)){
			// it's a view object
			s.push(addViewDef(inStructure));
		}

		this.cellCount = this.cells.length;
	}
});
<commit_msg>Refs #7010 - missing this reference !strict<commit_after>dojo.provide("dojox.grid._Layout");
dojo.require("dojox.grid.cells");
dojo.require("dojox.grid._RowSelector");

dojo.declare("dojox.grid._Layout", null, {
	// summary:
	//	Controls grid cell layout. Owned by grid and used internally.
	constructor: function(inGrid){
		this.grid = inGrid;
	},
	// flat array of grid cells
	cells: [],
	// structured array of grid cells
	structure: null,
	// default cell width
	defaultWidth: '6em',

	// methods
	moveColumn: function(sourceViewIndex, destViewIndex, cellIndex, targetIndex, before){
		var source_cells = this.structure[sourceViewIndex].cells[0];
		var dest_cells = this.structure[destViewIndex].cells[0];

		var cell = null;
		var cell_ri = 0;
		var target_ri = 0;

		for(var i=0, c; c=source_cells[i]; i++){
			if(c.index == cellIndex){
				cell_ri = i;
				break;
			}
		}
		cell = source_cells.splice(cell_ri, 1)[0];
		cell.view = this.grid.views.views[destViewIndex];

		for(i=0, c=null; c=dest_cells[i]; i++){
			if(c.index == targetIndex){
				target_ri = i;
				break;
			}
		}
		if(!before){
			target_ri += 1;
		}
		dest_cells.splice(target_ri, 0, cell);

		this.cells = [];
		var cellIndex = 0;
		for(var i=0, v; v=this.structure[i]; i++){
			for(var j=0, cs; cs=v.cells[j]; j++){
				for(var k=0, c; c=cs[k]; k++){
					c.index = cellIndex;
					this.cells.push(c);
					cellIndex++;
				}
			}
		}
		//this.grid.renderOnIdle();
	},

	setStructure: function(inStructure){
		var self = this;

		var getCellWidth = function(inDef){
			var w = 0;
			if(inDef.colSpan > 1){
				w = 0;
			}else if(!isNaN(inDef.width)){
				w = inDef.width + "em";
			}else{
				w = inDef.width || self.defaultWidth;
			}
			return w;
		};

		var addCellDef = function(inRowIndex, inCellIndex, inDef){
			var props = {
				grid: self.grid,
				subrow: inRowIndex,
				layoutIndex: inCellIndex,
				index: self.cells.length
			};

			if(inDef && inDef instanceof dojox.grid.cells._Base){
				props.unitWidth = getCellWidth(inDef._props);
				inDef = dojo.mixin(inDef, self._defaultCellProps, inDef._props, props);
				return inDef;
			}

			var cell_type = inDef.type || self._defaultCellProps.type || dojox.grid.cells.Cell;

			props.unitWidth = getCellWidth(inDef);
			return new cell_type(dojo.mixin({}, self._defaultCellProps, inDef, props));
		};

		var addRowDef = function(inRowIndex, inDef){
			var result = [];
			for(var i=0, def, cell; (def=inDef[i]); i++){
				cell = addCellDef(inRowIndex, i, def);
				result.push(cell);
				self.cells.push(cell);
			}
			return result;
		};

		var addRowsDef = function(inDef){
			var result = [];
			if(dojo.isArray(inDef)){
				if(dojo.isArray(inDef[0])){
					for(var i=0, row; inDef && (row=inDef[i]); i++){
						result.push(addRowDef(i, row));
					}
				}else{
					result.push(addRowDef(0, inDef));
				}
			}
			return result;
		};

		var addViewDef = function(inDef){
			self._defaultCellProps = inDef.defaultCell || {};
			return dojo.mixin({}, inDef, {cells: addRowsDef(inDef.rows || inDef.cells)});
		};

		this.fieldIndex = 0;
		this.cells = [];
		var s = this.structure = [];

		if(this.grid.rowSelector){
			var sel = { type: dojox._scopeName + ".grid._RowSelector" };

			if(dojo.isString(this.grid.rowSelector)){
				var width = this.grid.rowSelector;

				if(width == "false"){
					sel = null;
				}else if(width != "true"){
					sel['width'] = width;
				}
			}else{
				if(!this.grid.rowSelector){
					sel = null;
				}
			}

			if(sel){
				s.push(addViewDef(sel));
			}
		}

		var isCell = function(def){
			return ("name" in def || "field" in def || "get" in def);
		};

		var isRowDef = function(def){
			if(dojo.isArray(def)){
				if(dojo.isArray(def[0]) || isCell(def[0])){
					return true;
				}
			}
			return false;
		};

		var isView = function(def){
			return (def != null && dojo.isObject(def) &&
					("cells" in def || "rows" in def || "type" in def));
		};

		if(dojo.isArray(inStructure)){
			var hasViews = false;
			for(var i=0, st; (st=inStructure[i]); i++){
				if(isView(st)){
					hasViews = true;
					break;
				}
			}
			if(!hasViews){
				s.push(addViewDef({ cells: inStructure }));
			}else{
				for(var i=0, st; (st=inStructure[i]); i++){
					if(isRowDef(st)){
						s.push(addViewDef({ cells: st }));
					}else if(isView(st)){
						s.push(addViewDef(st));
					}
				}
			}
		}else if(isView(inStructure)){
			// it's a view object
			s.push(addViewDef(inStructure));
		}

		this.cellCount = this.cells.length;
	}
});
<|endoftext|>


<commit_before>/*!
 * Module dependencies.
 */

var PhoneGap = require('../../lib/phonegap'),
    project = require('../../lib/phonegap/util/project'),
    events = require('events'),
    soundwave = require('phonegap-soundwave'),
    phonegap,
    options;

/*!
 * Specification: phonegap.serve(options, [callback])
 */

describe('phonegap.serve(options, [callback])', function() {
    beforeEach(function() {
        phonegap = new PhoneGap();
        options = {};
        spyOn(project, 'cd').andReturn(true);
        spyOn(soundwave,'serve');
        spyOn(soundwave,'on').andCallThrough();
    });

    it('should require options', function() {
        expect(function() {
            options = undefined;
            phonegap.serve(options, function(e) {});
        }).toThrow();
    });

    it('should not require options.port', function() {
        expect(function() {
            options.port = undefined;
            phonegap.serve(options, function(e) {});
        }).not.toThrow();
    });

    it('should not require callback', function() {
        expect(function() {
            phonegap.serve(options);
        }).not.toThrow();
    });

    it('should return itself', function() {
        expect(phonegap.serve(options)).toEqual(phonegap);
    });

    it('should change to project directory', function() {
        phonegap.serve(options);
        expect(project.cd).toHaveBeenCalledWith({
            emitter: phonegap,
            callback: jasmine.any(Function)
        });
    });

    it('should try to serve the project', function() {
        phonegap.serve(options);
        expect(soundwave.serve).toHaveBeenCalled();
    });

    describe('when successfully started server', function() {
        it('should emit a "log" event', function() {
            phonegap.serve(options);
            expect(soundwave.on).toHaveBeenCalledWith('log',jasmine.any(Function))
        });
    });

});
<commit_msg>[#214] Refactor serve spec to test log event.<commit_after>/*!
 * Module dependencies.
 */

var PhoneGap = require('../../lib/phonegap'),
    project = require('../../lib/phonegap/util/project'),
    events = require('events'),
    soundwave = require('phonegap-soundwave'),
    phonegap,
    options;

/*!
 * Specification: phonegap.serve(options, [callback])
 */

describe('phonegap.serve(options, [callback])', function() {
    beforeEach(function() {
        phonegap = new PhoneGap();
        options = {};
        spyOn(project, 'cd').andReturn(true);
        spyOn(soundwave,'serve');
        spyOn(soundwave,'on').andCallThrough();
    });

    it('should require options', function() {
        expect(function() {
            options = undefined;
            phonegap.serve(options, function(e) {});
        }).toThrow();
    });

    it('should not require options.port', function() {
        expect(function() {
            options.port = undefined;
            phonegap.serve(options, function(e) {});
        }).not.toThrow();
    });

    it('should not require callback', function() {
        expect(function() {
            phonegap.serve(options);
        }).not.toThrow();
    });

    it('should return itself', function() {
        expect(phonegap.serve(options)).toEqual(phonegap);
    });

    it('should change to project directory', function() {
        phonegap.serve(options);
        expect(project.cd).toHaveBeenCalledWith({
            emitter: phonegap,
            callback: jasmine.any(Function)
        });
    });

    it('should try to serve the project', function() {
        phonegap.serve(options);
        expect(soundwave.serve).toHaveBeenCalled();
    });

    describe('when successfully started server', function() {
        beforeEach(function() {
            soundwave.serve.andCallFake(function(options, callback) {
                soundwave.emit('log', 'serve has started');
                callback();
            });
        });

        it('should emit a "log" event', function(done) {
            phonegap.on('log', function(message) {
                expect(message).toEqual(jasmine.any(String));
                done();
            });
            phonegap.serve(options);
        });
    });

});
<|endoftext|>


<commit_before>/*
    cycle.js
    2015-02-25

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint eval, for */

/*property
    $ref, apply, call, decycle, hasOwnProperty, length, prototype, push,
    retrocycle, stringify, test, toString
*/

if (typeof JSON.decycle !== 'function') {
    JSON.decycle = function decycle(object) {
        'use strict';

// Make a deep copy of an object or array, assuring that there is at most
// one instance of each object or array in the resulting structure. The
// duplicate references (which might be forming cycles) are replaced with
// an object of the form
//      {$ref: PATH}
// where the PATH is a JSONPath string that locates the first occurance.
// So,
//      var a = [];
//      a[0] = a;
//      return JSON.stringify(JSON.decycle(a));
// produces the string '[{"$ref":"$"}]'.

// JSONPath is used to locate the unique object. $ indicates the top level of
// the object or array. [NUMBER] or [STRING] indicates a child member or
// property.

        var objects = [],   // Keep a reference to each unique object or array
            paths = [];     // Keep the path to each unique object or array

        return (function derez(value, path) {

// The derez recurses through the object, producing the deep copy.

            var i,          // The loop counter
                name,       // Property name
                nu;         // The new object or array

// typeof null === 'object', so go on if this value is really an object but not
// one of the weird builtin objects.

            if (typeof value === 'object' && value !== null &&
                    !(value instanceof Boolean) &&
                    !(value instanceof Date) &&
                    !(value instanceof Number) &&
                    !(value instanceof RegExp) &&
                    !(value instanceof String)) {

// If the value is an object or array, look to see if we have already
// encountered it. If so, return a $ref/path object. This is a hard way,
// linear search that will get slower as the number of unique objects grows.

                for (i = 0; i < objects.length; i += 1) {
                    if (objects[i] === value) {
                        return {$ref: paths[i]};
                    }
                }

// Otherwise, accumulate the unique value and its path.

                objects.push(value);
                paths.push(path);

// If it is an array, replicate the array.

                if (Object.prototype.toString.apply(value) === '[object Array]') {
                    nu = [];
                    for (i = 0; i < value.length; i += 1) {
                        nu[i] = derez(value[i], path + '[' + i + ']');
                    }
                } else {

// If it is an object, replicate the object.

                    nu = {};
                    for (name in value) {
                        if (Object.prototype.hasOwnProperty.call(value, name)) {
                            nu[name] = derez(value[name],
                                    path + '[' + JSON.stringify(name) + ']');
                        }
                    }
                }
                return nu;
            }
            return value;
        }(object, '$'));
    };
}

if (typeof JSON.retrocycle !== 'function') {
    JSON.retrocycle = function retrocycle($) {
        'use strict';

// Restore an object that was reduced by decycle. Members whose values are
// objects of the form
//      {$ref: PATH}
// are replaced with references to the value found by the PATH. This will
// restore cycles. The object will be mutated.

// The eval function is used to locate the values described by a PATH. The
// root object is kept in a $ variable. A regular expression is used to
// assure that the PATH is extremely well formed. The regexp contains nested
// * quantifiers. That has been known to have extremely bad performance
// problems on some browsers for very long strings. A PATH is expected to be
// reasonably short. A PATH is allowed to belong to a very restricted subset of
// Goessner's JSONPath.

// So,
//      var s = '[{"$ref":"$"}]';
//      return JSON.retrocycle(JSON.parse(s));
// produces an array containing a single element which is the array itself.

        var px = /^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;

        (function rez(value) {

// The rez function walks recursively through the object looking for $ref
// properties. When it finds one that has a value that is a path, then it
// replaces the $ref object with a reference to the value that is found by
// the path.

            var i, item, name, path;

            if (value && typeof value === 'object') {
                if (Object.prototype.toString.apply(value) === '[object Array]') {
                    for (i = 0; i < value.length; i += 1) {
                        item = value[i];
                        if (item && typeof item === 'object') {
                            path = item.$ref;
                            if (typeof path === 'string' && px.test(path)) {
                                value[i] = eval(path);
                            } else {
                                rez(item);
                            }
                        }
                    }
                } else {
                    for (name in value) {
                        if (typeof value[name] === 'object') {
                            item = value[name];
                            if (item) {
                                path = item.$ref;
                                if (typeof path === 'string' && px.test(path)) {
                                    value[name] = eval(path);
                                } else {
                                    rez(item);
                                }
                            }
                        }
                    }
                }
            }
        }($));
        return $;
    };
}
<commit_msg>replacer<commit_after>/*
    cycle.js
    2016-05-01

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.
*/

/*jslint eval, for */

/*property
    $ref, decycle, forEach, isArray, keys, length, push, retrocycle, stringify,
    test
*/

if (typeof JSON.decycle !== "function") {
    JSON.decycle = function decycle(object, replacer) {
        "use strict";

// Make a deep copy of an object or array, assuring that there is at most
// one instance of each object or array in the resulting structure. The
// duplicate references (which might be forming cycles) are replaced with
// an object of the form

//      {"$ref": PATH}

// where the PATH is a JSONPath string that locates the first occurance.

// So,

//      var a = [];
//      a[0] = a;
//      return JSON.stringify(JSON.decycle(a));

// produces the string '[{"$ref":"$"}]'.

// If a replacer function is provided, then it will be called for each value.
// A replacer function receives a value and returns a replacement value.

// JSONPath is used to locate the unique object. $ indicates the top level of
// the object or array. [NUMBER] or [STRING] indicates a child element or
// property.

        var objects = [];   // Keep a reference to each unique object or array
        var paths = [];     // Keep the path to each unique object or array

        return (function derez(value, path) {

// The derez function recurses through the object, producing the deep copy.

            var i;          // The loop counter
            var nu;         // The new object or array

// If a replacer function was provided, then call it to get a replacement value.

            if (replacer !== undefined) {
                value = replacer(value);
            }

// typeof null === "object", so go on if this value is really an object but not
// one of the weird builtin objects.

            if (
                typeof value === "object" && value !== null &&
                !(value instanceof Boolean) &&
                !(value instanceof Date) &&
                !(value instanceof Number) &&
                !(value instanceof RegExp) &&
                !(value instanceof String)
            ) {

// If the value is an object or array, look to see if we have already
// encountered it. If so, return a {"$ref":PATH} object. This is a hard
// linear search that will get slower as the number of unique objects grows.
// Someday, this should be replaced with an ES6 WeakMap.

                i = objects.indexOf(value);
                if (i >= 0) {
                    return {$ref: paths[i]};
                }

// Otherwise, accumulate the unique value and its path.

                objects.push(value);
                paths.push(path);

// If it is an array, replicate the array.

                if (Array.isArray(value)) {
                    nu = [];
                    value.forEach(function (element, i) {
                        nu[i] = derez(element, path + "[" + i + "]");
                    });
                } else {

// If it is an object, replicate the object.

                    nu = {};
                    Object.keys(value).forEach(function (name) {
                        nu[name] = derez(
                            value[name],
                            path + "[" + JSON.stringify(name) + "]"
                        );
                    });
                }
                return nu;
            }
            return value;
        }(object, "$"));
    };
}

if (typeof JSON.retrocycle !== "function") {
    JSON.retrocycle = function retrocycle($) {
        "use strict";

// Restore an object that was reduced by decycle. Members whose values are
// objects of the form
//      {$ref: PATH}
// are replaced with references to the value found by the PATH. This will
// restore cycles. The object will be mutated.

// The eval function is used to locate the values described by a PATH. The
// root object is kept in a $ variable. A regular expression is used to
// assure that the PATH is extremely well formed. The regexp contains nested
// * quantifiers. That has been known to have extremely bad performance
// problems on some browsers for very long strings. A PATH is expected to be
// reasonably short. A PATH is allowed to belong to a very restricted subset of
// Goessner's JSONPath.

// So,
//      var s = '[{"$ref":"$"}]';
//      return JSON.retrocycle(JSON.parse(s));
// produces an array containing a single element which is the array itself.

        var px = /^\$(?:\[(?:\d+|\"(?:[^\\\"\u0000-\u001f]|\\([\\\"\/bfnrt]|u[0-9a-zA-Z]{4}))*\")\])*$/;

        (function rez(value) {

// The rez function walks recursively through the object looking for $ref
// properties. When it finds one that has a value that is a path, then it
// replaces the $ref object with a reference to the value that is found by
// the path.

            if (value && typeof value === "object") {
                if (Array.isArray(value)) {
                    value.forEach(function (element, i) {
                        if (typeof element === "object" && element !== null) {
                            var path = element.$ref;
                            if (typeof path === "string" && px.test(path)) {
                                value[i] = eval(path);
                            } else {
                                rez(element);
                            }
                        }
                    });
                } else {
                    Object.keys(value).forEach(function (name) {
                        var item = value[name];
                        if (typeof item === "object" && item !== null) {
                            var path = item.$ref;
                            if (typeof path === "string" && px.test(path)) {
                                value[name] = eval(path);
                            } else {
                                rez(item);
                            }
                        }
                    });
                }
            }
        }($));
        return $;
    };
}
<|endoftext|>


<commit_before>/*jslint node: true */
/*jshint laxbreak: true */
"use strict";

var d3 = require("d3");
var _ = require("underscore");
var TooltipFactory = require("./TooltipFactory");

var ViewerFactory = function() {
    var mousedownXY = {x: -1, y: -1}, mouseupXY = {x: -2, y: -2};
    return {
        createSVG: function(container, width, height, fv, clazz) {
            var svg = container
                .append('svg')
                .attr('width', width)
                .attr('height', height)
                .on('mousedown', function() {
                    mousedownXY = {x: d3.event.pageX, y: d3.event.pageY};
                    mouseupXY = {x: -2, y: -2};
                })
                .on('mouseup', function() {
                    mouseupXY = {x: d3.event.pageX, y: d3.event.pageY};
                    if ((mousedownXY.x === mouseupXY.x) && (mousedownXY.y === mouseupXY.y)
                        && !fv.overFeature && fv.selectedFeature ) {
                        ViewerFactory.selectFeature(fv.selectedFeature, fv.selectedFeatureElement, fv);
                    }
                    mousedownXY = {x: -1, y: -1};
                })
                .call(fv.zoom);

            if (clazz) {
                svg.attr('class', clazz);
            }
            svg.append('g').append('rect')
                .classed('up_pftv_shadow', true)
                .attr('x', 0)
                .attr('y', 0)
                .attr('height', height)
                .attr('width', 0);

            return svg;
        }
    };
}();

ViewerFactory.updateShadow = function(feature, fv) {
    var aaWidth = fv.xScale(2) - fv.xScale(1);
    var width = aaWidth * (feature.end ? feature.end - feature.begin + 1 : 1);
    var gapRegion = aaWidth/2;
    var xTranslate = fv.xScale(feature.begin);
    d3.selectAll('.up_pftv_shadow')
        .attr('x', -(gapRegion))
        .attr('width', width)
        .attr('transform', 'translate(' + xTranslate + ',0)');
};

ViewerFactory.selectFeature = function(feature, elem, fv) {
    var selectedElem = d3.select(elem);
    var previousSelection = {feature: fv.selectedFeature, elem: fv.selectedFeatureElement};
    if (feature === fv.selectedFeature) {
        fv.selectedFeature = undefined;
        fv.selectedFeatureElement = undefined;
        d3.selectAll('.up_pftv_shadow')
            .attr('x', 0)
            .attr('width', 0)
            .attr('transform', 'translate(0,0)');
    } else {
        fv.selectedFeature = feature;
        fv.selectedFeatureElement = elem;
        this.updateShadow(feature, fv);
    }
    var selectedPath = selectedElem.classed('up_pftv_activeFeature');
    d3.selectAll('svg path.up_pftv_activeFeature').classed('up_pftv_activeFeature', false);
    //it is not active anymore
    selectedElem.classed('up_pftv_activeFeature', !selectedPath);
    fv.updateFeatureSelector();
    if (previousSelection.feature) {
        fv.dispatcher.featureDeselected(
            {feature: previousSelection.feature, color: d3.select(previousSelection.elem).style("fill")}
        );
    }
    if (feature !== previousSelection.feature) {
        fv.dispatcher.featureSelected({feature: fv.selectedFeature, color: selectedElem.style("fill")});
    }
};

ViewerFactory.addEventsClassAndTitle = function(elements, fv, container) {
    elements
        .classed('up_pftv_activeFeature', function(d) {
            return d === fv.selectedFeature;
        })
        .on('click', function(d){
            TooltipFactory.createTooltip(fv, d, container);
            ViewerFactory.selectFeature(d, this, fv);
        })
        .on('mouseover', function() {
            fv.overFeature = true;
        })
        .on('mouseout', function() {
            fv.overFeature = false;
        });
    elements.selectAll('title')
        .data(function(d) {
            return [d]
        }).enter()
        .append('title')
            .text(function(d){
                var text = d.type.label.toUpperCase();
                text += ', Position: ' + d.begin + (d.end ? ' - ' + d.end : '');
                return (text);
            })
    ;
};

module.exports = ViewerFactory;<commit_msg>Remove title tooltip for features.<commit_after>/*jslint node: true */
/*jshint laxbreak: true */
"use strict";

var d3 = require("d3");
var _ = require("underscore");
var TooltipFactory = require("./TooltipFactory");

var ViewerFactory = function() {
    var mousedownXY = {x: -1, y: -1}, mouseupXY = {x: -2, y: -2};
    return {
        createSVG: function(container, width, height, fv, clazz) {
            var svg = container
                .append('svg')
                .attr('width', width)
                .attr('height', height)
                .on('mousedown', function() {
                    mousedownXY = {x: d3.event.pageX, y: d3.event.pageY};
                    mouseupXY = {x: -2, y: -2};
                })
                .on('mouseup', function() {
                    mouseupXY = {x: d3.event.pageX, y: d3.event.pageY};
                    if ((mousedownXY.x === mouseupXY.x) && (mousedownXY.y === mouseupXY.y)
                        && !fv.overFeature && fv.selectedFeature ) {
                        ViewerFactory.selectFeature(fv.selectedFeature, fv.selectedFeatureElement, fv);
                    }
                    mousedownXY = {x: -1, y: -1};
                })
                .call(fv.zoom);

            if (clazz) {
                svg.attr('class', clazz);
            }
            svg.append('g').append('rect')
                .classed('up_pftv_shadow', true)
                .attr('x', 0)
                .attr('y', 0)
                .attr('height', height)
                .attr('width', 0);

            return svg;
        }
    };
}();

ViewerFactory.updateShadow = function(feature, fv) {
    var aaWidth = fv.xScale(2) - fv.xScale(1);
    var width = aaWidth * (feature.end ? feature.end - feature.begin + 1 : 1);
    var gapRegion = aaWidth/2;
    var xTranslate = fv.xScale(feature.begin);
    d3.selectAll('.up_pftv_shadow')
        .attr('x', -(gapRegion))
        .attr('width', width)
        .attr('transform', 'translate(' + xTranslate + ',0)');
};

ViewerFactory.selectFeature = function(feature, elem, fv) {
    var selectedElem = d3.select(elem);
    var previousSelection = {feature: fv.selectedFeature, elem: fv.selectedFeatureElement};
    if (feature === fv.selectedFeature) {
        fv.selectedFeature = undefined;
        fv.selectedFeatureElement = undefined;
        d3.selectAll('.up_pftv_shadow')
            .attr('x', 0)
            .attr('width', 0)
            .attr('transform', 'translate(0,0)');
    } else {
        fv.selectedFeature = feature;
        fv.selectedFeatureElement = elem;
        this.updateShadow(feature, fv);
    }
    var selectedPath = selectedElem.classed('up_pftv_activeFeature');
    d3.selectAll('svg path.up_pftv_activeFeature').classed('up_pftv_activeFeature', false);
    //it is not active anymore
    selectedElem.classed('up_pftv_activeFeature', !selectedPath);
    fv.updateFeatureSelector();
    if (previousSelection.feature) {
        fv.dispatcher.featureDeselected(
            {feature: previousSelection.feature, color: d3.select(previousSelection.elem).style("fill")}
        );
    }
    if (feature !== previousSelection.feature) {
        fv.dispatcher.featureSelected({feature: fv.selectedFeature, color: selectedElem.style("fill")});
    }
};

ViewerFactory.addEventsClassAndTitle = function(elements, fv, container) {
    elements
        .classed('up_pftv_activeFeature', function(d) {
            return d === fv.selectedFeature;
        })
        .on('click', function(d){
            TooltipFactory.createTooltip(fv, d, container);
            ViewerFactory.selectFeature(d, this, fv);
        })
        .on('mouseover', function() {
            fv.overFeature = true;
        })
        .on('mouseout', function() {
            fv.overFeature = false;
        });
};

module.exports = ViewerFactory;<|endoftext|>


<commit_before>import TagManager from '../src/tagmanager-wrap';

describe('Tagmanager', () => {
  window.tagManagerDataLayer = [];
  const tagManager = new TagManager(window.tagManagerDataLayer, {
    gtmId: '222222',
    startPush: {
      page_type: 'pages:demo',
      path_category: 'reformas-e-reparos/demo',
      experiments: window.experiments || [],
    },
  });

  describe('constructor', () => {
    it('defines default properties', () => {
      expect(tagManager.options).toBeDefined();
      expect(tagManager.dataLayer).toBeDefined();
    });
  });

  describe('.defineProperties', () => {
    it('sets default properties', () => {
      expect(tagManager.options.gtmId).toEqual('222222');
      expect(tagManager.options.startPush.page_type).toEqual('pages:demo');
      expect(tagManager.options.startPush.path_category).toEqual('reformas-e-reparos/demo');
      expect(tagManager.options.virtualPageViewEvent).toEqual('virtual_pageview');
    });
  });

  describe('.dataLayer init', () => {
    it('sets initial data', () => {
      expect(tagManager.dataLayer.length).not.toEqual(0);
    });
  });

  describe('.init', () => {
    beforeEach(() => {
      document.body.innerHTML = __html__['spec/fixtures/index.html'];
      tagManager.init();
    });

    it('appends async script', () => {
      const scriptTag = document.querySelector('[data-id="google-tagmanager"]');

      expect(scriptTag).not.toBeNull();
    });

    it('appends noscript fallback', () => {
      const noScript = document.querySelector('[data-id="noscript-google-tagmanager"]');

      expect(noScript).not.toBeNull();
    });
  });

  describe('.prependExperiment', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.prependExperiment({
        event: 'yourCustomEvent',
        schema: 'your:br.com.custom/schema/jsonschema/1-0-0',
        data: {
          experimentDescription: 'Description Experiment',
          experimentGoal: 'request conversion rate',
          experimentId: 'popup-user-leaves-request',
          experimentPageCategory: ['all'],
          experimentPageType: ['categories'],
          experimentTool: 'Abba',
          experimentType: 'page',
          experimentVersion: 'demo',
        },
      });
    });

    it('preppends experiment', () => {
      expect(tagManager.dataLayer[0].experiments.length).toEqual(1);
    });

    it('has description equal to Description Experiment', () => {
      expect(tagManager.dataLayer[0].experiments[0].experimentDescription).toEqual('Description Experiment');
    });
  });

  describe('.virtualPageView', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.virtualPageView('/profile/created');
    });

    it('preppends virtualPageView', () => {
      const result = tagManager.dataLayer.filter(item => item.vpname !== undefined);

      expect(result.length).toEqual(1);
    });

    it('has vpname', () => {
      const result = tagManager.dataLayer.filter(item => item.vpname !== undefined);
      expect(result[0].vpname).toEqual('/profile/created');
    });
  });

  describe('.eventCategory', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.eventCategory('pre-fill', {
        eventAction: 'success',
      });
    });

    it('preppends eventCategory', () => {
      const result = tagManager.dataLayer.filter(item => item.eventCategory !== undefined);

      expect(result.length).toEqual(1);
    });

    it('has event', () => {
      const result = tagManager.dataLayer.filter(item => item.eventCategory !== undefined);

      expect(result[0].event).toEqual('GAEvent');
    });

    it('has eventCategory', () => {
      const result = tagManager.dataLayer.filter(item => item.eventCategory !== undefined);

      expect(result[0].eventCategory).toEqual('pre-fill');
    });

    it('has eventAction', () => {
      const result = tagManager.dataLayer.filter(item => item.eventAction !== undefined);

      expect(result[0].eventAction).toEqual('success');
    });
  });

  describe('.customObj', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.custom({
        user_id: 123,
        event: 'user_info',
      });
    });

    it('preppends customObj', () => {
      const result = tagManager.dataLayer.filter(item => item.user_id !== undefined);

      expect(result.length).toEqual(1);
    });

    it('has user_id', () => {
      const result = tagManager.dataLayer.filter(item => item.user_id !== undefined);

      expect(result[0].user_id).toEqual(123);
    });

    it('has event', () => {
      const result = tagManager.dataLayer.filter(item => item.user_id !== undefined);

      expect(result[0].event).toEqual('user_info');
    });
  });

  describe('.bindEvents', () => {
    it('appends gtm-bind attribute', () => {
      document.body.innerHTML = __html__['spec/fixtures/index.html'];
      const btn = document.getElementsByClassName('btn')[0];

      tagManager.init();
      tagManager.bindEvents();

      const attribute = btn.getAttribute('data-gtm-bind');

      expect(Boolean(attribute)).toEqual(true);
    });
  });

  describe('.clickGAEvent', () => {
    beforeEach(() => {
      tagManager.dataLayer = [];
    });

    it('dispatches .eventCategory', () => {
      document.body.innerHTML = __html__['spec/fixtures/index.html'];
      spyOn(tagManager, 'eventCategory');

      tagManager.init();
      tagManager.bindEvents();

      const btn = document.getElementsByClassName('btn')[0];
      const evt = {
        currentTarget: btn,
      };

      btn.click(evt);

      expect(tagManager.eventCategory).toHaveBeenCalled();
    });
  });
});
<commit_msg>Add fileSystem to replace __html__ on jest tests<commit_after>import TagManager from '../src/tagmanager-wrap';
import fs from 'fs'

describe('Tagmanager', () => {
  window.tagManagerDataLayer = [];
  const tagManager = new TagManager(window.tagManagerDataLayer, {
    gtmId: '222222',
    startPush: {
      page_type: 'pages:demo',
      path_category: 'reformas-e-reparos/demo',
      experiments: window.experiments || [],
    },
  });

  describe('constructor', () => {
    it('defines default properties', () => {
      expect(tagManager.options).toBeDefined();
      expect(tagManager.dataLayer).toBeDefined();
    });
  });

  describe('.defineProperties', () => {
    it('sets default properties', () => {
      expect(tagManager.options.gtmId).toEqual('222222');
      expect(tagManager.options.startPush.page_type).toEqual('pages:demo');
      expect(tagManager.options.startPush.path_category).toEqual('reformas-e-reparos/demo');
      expect(tagManager.options.virtualPageViewEvent).toEqual('virtual_pageview');
    });
  });

  describe('.dataLayer init', () => {
    it('sets initial data', () => {
      expect(tagManager.dataLayer.length).not.toEqual(0);
    });
  });

  describe('.init', () => {
    beforeEach(() => {
      document.body.innerHTML = fs.readFileSync(`${__dirname}/fixtures/index.html`)
      tagManager.init();
    });

    it('appends async script', () => {
      const scriptTag = document.querySelector('[data-id="google-tagmanager"]');

      expect(scriptTag).not.toBeNull();
    });

    it('appends noscript fallback', () => {
      const noScript = document.querySelector('[data-id="noscript-google-tagmanager"]');

      expect(noScript).not.toBeNull();
    });
  });

  describe('.prependExperiment', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.prependExperiment({
        event: 'yourCustomEvent',
        schema: 'your:br.com.custom/schema/jsonschema/1-0-0',
        data: {
          experimentDescription: 'Description Experiment',
          experimentGoal: 'request conversion rate',
          experimentId: 'popup-user-leaves-request',
          experimentPageCategory: ['all'],
          experimentPageType: ['categories'],
          experimentTool: 'Abba',
          experimentType: 'page',
          experimentVersion: 'demo',
        },
      });
    });

    it('preppends experiment', () => {
      expect(tagManager.dataLayer[0].experiments.length).toEqual(1);
    });

    it('has description equal to Description Experiment', () => {
      expect(tagManager.dataLayer[0].experiments[0].experimentDescription).toEqual('Description Experiment');
    });
  });

  describe('.virtualPageView', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.virtualPageView('/profile/created');
    });

    it('preppends virtualPageView', () => {
      const result = tagManager.dataLayer.filter(item => item.vpname !== undefined);

      expect(result.length).toEqual(1);
    });

    it('has vpname', () => {
      const result = tagManager.dataLayer.filter(item => item.vpname !== undefined);
      expect(result[0].vpname).toEqual('/profile/created');
    });
  });

  describe('.eventCategory', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.eventCategory('pre-fill', {
        eventAction: 'success',
      });
    });

    it('preppends eventCategory', () => {
      const result = tagManager.dataLayer.filter(item => item.eventCategory !== undefined);

      expect(result.length).toEqual(1);
    });

    it('has event', () => {
      const result = tagManager.dataLayer.filter(item => item.eventCategory !== undefined);

      expect(result[0].event).toEqual('GAEvent');
    });

    it('has eventCategory', () => {
      const result = tagManager.dataLayer.filter(item => item.eventCategory !== undefined);

      expect(result[0].eventCategory).toEqual('pre-fill');
    });

    it('has eventAction', () => {
      const result = tagManager.dataLayer.filter(item => item.eventAction !== undefined);

      expect(result[0].eventAction).toEqual('success');
    });
  });

  describe('.customObj', () => {
    beforeEach(() => {
      tagManager.init();

      tagManager.custom({
        user_id: 123,
        event: 'user_info',
      });
    });

    it('preppends customObj', () => {
      const result = tagManager.dataLayer.filter(item => item.user_id !== undefined);

      expect(result.length).toEqual(1);
    });

    it('has user_id', () => {
      const result = tagManager.dataLayer.filter(item => item.user_id !== undefined);

      expect(result[0].user_id).toEqual(123);
    });

    it('has event', () => {
      const result = tagManager.dataLayer.filter(item => item.user_id !== undefined);

      expect(result[0].event).toEqual('user_info');
    });
  });

  describe('.bindEvents', () => {
    it('appends gtm-bind attribute', () => {
      document.body.innerHTML = fs.readFileSync(`${__dirname}/fixtures/index.html`)
      const btn = document.getElementsByClassName('btn')[0];

      tagManager.init();
      tagManager.bindEvents();

      const attribute = btn.getAttribute('data-gtm-bind');

      expect(Boolean(attribute)).toEqual(true);
    });
  });

  describe('.clickGAEvent', () => {
    beforeEach(() => {
      tagManager.dataLayer = [];
    });

    it('dispatches .eventCategory', () => {
      document.body.innerHTML = fs.readFileSync(`${__dirname}/fixtures/index.html`)
      spyOn(tagManager, 'eventCategory');

      tagManager.init();
      tagManager.bindEvents();

      const btn = document.getElementsByClassName('btn')[0];
      const evt = {
        currentTarget: btn,
      };

      btn.click(evt);

      expect(tagManager.eventCategory).toHaveBeenCalled();
    });
  });
});
<|endoftext|>