<commit_before>/**
 * Assemble
 * Assemble <http://assemble.io>
 * Created and maintained by Jon Schlinkert and Brian Woodward
 *
 * Copyright (c) 2013 Upstage.
 * Licensed under the MIT License (MIT).
 */

// node_modules
var yfm = require('assemble-yaml');
var _   = require('lodash');

var Assemble = function() {

  // Assemble utils.
  var engineUtils = require('./engine');
  var collection  = require('./collection');
  var plugins  = require('./plugins');

  var steps = [];

  var init = function(task, grunt){

    this.grunt = grunt;
    this.task = task;
    this.options = task.options({
      layoutdir: '',
      layout: '',
      layoutext: '',
      partials: [],
      data: [],
      assets: '',
      ext: '.html'
    });

    this.options.data = mergeOptionsArrays.apply(this, [task.target, 'data']);
    this.options.partials = mergeOptionsArrays.apply(this, [task.target, 'partials']);
    this.options.collections = mergeOptionsArrays.apply(this, [task.target, 'collections']);

    // add default collections
    this.options.collections = _.union(this.options.collections, ['tags', 'categories', { name: 'pages' }]);

    this.options.collections = collection.normalize(this.options.collections);

    // if there is a pages property and it's an array, turn it into an object
    if(this.options.pages && grunt.util.kindOf(this.options.pages) === 'array') {
      var pages = {};
      _.forEach(this.options.pages, function(page) {
        if(page.filename && page.filename.length > 0) {
          pages[page.filename] = page;
        }
      });
      this.options.pages = _.cloneDeep(pages);
    }

    this.files = task.files;
    steps = [];

    return this;
  };

  var step = function(fn) {
    steps.push(fn);
    return this;
  };

  var build = function(callback) {
    this.grunt.verbose.writeln('Assembling');
    var self = this;
    this.grunt.verbose.writeln('Steps: ' + steps.length);
    if(steps.length === 0) {
      if(callback) {
        callback(null, true);
      }
      return true;
    }

    var step = 0, totalSteps = steps.length;
    steps[step++](self, function next(assemble) {
      assemble.grunt.verbose.writeln('\nStep ' + step + ' assembled.');
      if(step < totalSteps) {
        assemble.grunt.verbose.writeln('Calling step ' + (step + 1));
        steps[step++](self, next);
      } else {
        assemble.grunt.verbose.writeln('Build completed. Returning');
        if(callback) {
          callback(null, true);
        }
        return true;
      }
    });
  };

  var mergeOptionsArrays = function(target, name) {
    var globalArray = this.grunt.config(['assemble', 'options', name]) || [];
    var targetArray = this.grunt.config(['assemble', target, 'options', name]) || [];
    return _.union([], globalArray, targetArray);
  };

  return {
    init: init,
    step: step,
    build: build,
    plugins: plugins,

    data: yfm,
    engine: engineUtils,
    util: collection
  };

};

module.exports = exports = new Assemble();
<commit_msg>adds `originalAssets` property to root context, to store the pre-calculated assets path<commit_after>/**
 * Assemble
 * Assemble <http://assemble.io>
 * Created and maintained by Jon Schlinkert and Brian Woodward
 *
 * Copyright (c) 2013 Upstage.
 * Licensed under the MIT License (MIT).
 */

// node_modules
var yfm = require('assemble-yaml');
var _   = require('lodash');

var Assemble = function() {

  // Assemble utils.
  var engineUtils = require('./engine');
  var collection  = require('./collection');
  var plugins  = require('./plugins');

  var steps = [];

  var init = function(task, grunt){

    this.grunt = grunt;
    this.task = task;
    this.options = task.options({
      layoutdir: '',
      layout: '',
      layoutext: '',
      partials: [],
      data: [],
      assets: '',
      ext: '.html'
    });

    this.options.originalAssets = this.options.assets;

    this.options.data = mergeOptionsArrays.apply(this, [task.target, 'data']);
    this.options.partials = mergeOptionsArrays.apply(this, [task.target, 'partials']);
    this.options.collections = mergeOptionsArrays.apply(this, [task.target, 'collections']);

    // add default collections
    this.options.collections = _.union(this.options.collections, ['tags', 'categories', { name: 'pages' }]);

    this.options.collections = collection.normalize(this.options.collections);

    // if there is a pages property and it's an array, turn it into an object
    if(this.options.pages && grunt.util.kindOf(this.options.pages) === 'array') {
      var pages = {};
      _.forEach(this.options.pages, function(page) {
        if(page.filename && page.filename.length > 0) {
          pages[page.filename] = page;
        }
      });
      this.options.pages = _.cloneDeep(pages);
    }

    this.files = task.files;
    steps = [];

    return this;
  };

  var step = function(fn) {
    steps.push(fn);
    return this;
  };

  var build = function(callback) {
    this.grunt.verbose.writeln('Assembling');
    var self = this;
    this.grunt.verbose.writeln('Steps: ' + steps.length);
    if(steps.length === 0) {
      if(callback) {
        callback(null, true);
      }
      return true;
    }

    var step = 0, totalSteps = steps.length;
    steps[step++](self, function next(assemble) {
      assemble.grunt.verbose.writeln('\nStep ' + step + ' assembled.');
      if(step < totalSteps) {
        assemble.grunt.verbose.writeln('Calling step ' + (step + 1));
        steps[step++](self, next);
      } else {
        assemble.grunt.verbose.writeln('Build completed. Returning');
        if(callback) {
          callback(null, true);
        }
        return true;
      }
    });
  };

  var mergeOptionsArrays = function(target, name) {
    var globalArray = this.grunt.config(['assemble', 'options', name]) || [];
    var targetArray = this.grunt.config(['assemble', target, 'options', name]) || [];
    return _.union([], globalArray, targetArray);
  };

  return {
    init: init,
    step: step,
    build: build,
    plugins: plugins,

    data: yfm,
    engine: engineUtils,
    util: collection
  };

};

module.exports = exports = new Assemble();
<|endoftext|>


<commit_before>/**
 * Created by alexeiv on 01/03/2017.
 */
function populateDropDownList() {

    const DEFAULT_OPTIONS_NUMBER = 10;

    let artifactoryServers = document.getElementsByName("artifactoryServer");
    let t = document.getElementsByName("artifactoryServer")[artifactoryServers.length - 1];
    let button = t.nextElementSibling.nextElementSibling;

    button.onclick = function () {
        let retryValue = document.getElementsByName('connectionRetry');
        for (let i = 0; i < retryValue.length; i++) {
            if (retryValue[i].length === 0) {
                // populate the selection fields and set 3 as default.
                for (let j = 0; j < DEFAULT_OPTIONS_NUMBER; j++) {
                    let el = document.createElement("option");
                    el.textContent = j;
                    el.value = j;
                    retryValue[i].appendChild(el);
                    if (j === 3) {
                        retryValue[i].selectedIndex = j;
                    }
                }
            }
        }

        // Populates the timeout field
        let timeout = document.getElementsByName("_.artifactory.timeout");
        let value = 300;
        for (let i = 0; i < timeout.length; i++) {
            if (!timeout[i].value) {
                timeout[i].value = value;
            }
        }

        // Populates the deploymentThreads field
        let deploymentThreadsValue = document.getElementsByName("deploymentThreads");
        for (let i = 0; i < deploymentThreadsValue.length; i++) {
            if (deploymentThreadsValue[i].length === 0) {
                // populate the selection fields and set 3 as default.
                for (let j = 1; j < DEFAULT_OPTIONS_NUMBER; j++) {
                    let el = document.createElement("option");
                    el.textContent = j;
                    el.value = j;
                    deploymentThreadsValue[i].appendChild(el);
                    if (j === 3) {
                        deploymentThreadsValue[i].selectedIndex = j;
                    }
                }
            }
        }
    }
}
<commit_msg>HAP-1197 - The default value of "Number of threads for Generic uploads" is 1 - should be 3<commit_after>/**
 * Created by alexeiv on 01/03/2017.
 */
function populateDropDownList() {

    const DEFAULT_OPTIONS_NUMBER = 10;

    let artifactoryServers = document.getElementsByName("artifactoryServer");
    let t = document.getElementsByName("artifactoryServer")[artifactoryServers.length - 1];
    let button = t.nextElementSibling.nextElementSibling;

    button.onclick = function () {
        let retryValue = document.getElementsByName('connectionRetry');
        for (let i = 0; i < retryValue.length; i++) {
            if (retryValue[i].length === 0) {
                // populate the selection fields and set 3 as default.
                for (let j = 0; j < DEFAULT_OPTIONS_NUMBER; j++) {
                    let el = document.createElement("option");
                    el.textContent = j;
                    el.value = j;
                    retryValue[i].appendChild(el);
                    if (j === 3) {
                        retryValue[i].selectedIndex = j;
                    }
                }
            }
        }

        // Populates the timeout field
        let timeout = document.getElementsByName("_.artifactory.timeout");
        let value = 300;
        for (let i = 0; i < timeout.length; i++) {
            if (!timeout[i].value) {
                timeout[i].value = value;
            }
        }

        // Populates the deploymentThreads field
        let deploymentThreadsValue = document.getElementsByName("deploymentThreads");
        for (let i = 0; i < deploymentThreadsValue.length; i++) {
            if (deploymentThreadsValue[i].length === 0) {
                // populate the selection fields and set 3 as default.
                let index = 0;
                for (let j = 1; j < DEFAULT_OPTIONS_NUMBER; j++) {
                    let el = document.createElement("option");
                    el.textContent = j;
                    el.value = j;
                    deploymentThreadsValue[i].appendChild(el);
                    if (j === 3) {
                        deploymentThreadsValue[i].selectedIndex = index;
                    }
                    index++;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/* The first state of the game. */
function EntryState () {}

/* Entry state assets are loaded in the boot section */

/* Phaser state function */
EntryState.prototype.create = function () {
	this.add.image(0, 0, 'entryBg');

	var title = this.add.text(this.world.centerX, this.world.centerY/2, LANG.TEXT.title, {
		font: '50pt ' +  GLOBAL.FONT,
		fill: '#ffff00',
		stroke: '#000000',
		strokeThickness: 5
	});
	title.anchor.set(0.5);

	var text = this.add.text(this.world.centerX, this.world.centerY, LANG.TEXT.start, {
		font: '50pt ' +  GLOBAL.FONT,
		fill: '#dd00dd'
	});
	text.anchor.set(0.5);
	text.inputEnabled = true;
	text.events.onInputDown.add(function () {
		user.login('debug', 'debug');
		//this.add.audio('yeah').play();
		this.state.start(GLOBAL.STATE.garden);
	}, this);

	var credits = this.add.text(this.world.centerX, this.world.centerY/0.75, LANG.TEXT.credits, {
		font: '50pt ' +  GLOBAL.FONT,
		fill: '#000000'
	});
	credits.anchor.set(0.5);
	credits.inputEnabled = true;
	credits.events.onInputDown.add(function () {
		credits.visible = false;
		text.visible = false;
		allCredits.visible = true;
	}, this);

	var allCredits = this.add.text(this.world.centerX, this.world.centerY/2+50,
		'This game was made at Lund University\n\n' +
		'Game development:\nErik Anderberg, Agneta Gulz, Magnus Haake, Layla Husain\n' +
		'Programming:\nErik Anderberg, Marcus Malmberg\n' +
		'Graphics:\n Sebastian Gulz Haake\n' +
		'Special Thanks:\nAnton Axelsson, Sanne Bengtsson, Maja Håkansson, Lisa Lindberg, Björn Norrliden', {
		font: '15pt ' +  GLOBAL.FONT,
		fill: '#000000',
		align: 'center'
	});
	allCredits.anchor.set(0.5, 0);
	allCredits.visible = false;
	allCredits.inputEnabled = true;
	allCredits.events.onInputDown.add(function () {
		allCredits.visible = false;
		credits.visible = true;
		text.visible = true;
	}, this);
};

/* Phaser state function */
Subgame.prototype.shutdown = onShutDown;<commit_msg>Change to credits<commit_after>/* The first state of the game. */
function EntryState () {}

/* Entry state assets are loaded in the boot section */

/* Phaser state function */
EntryState.prototype.create = function () {
	this.add.image(0, 0, 'entryBg');

	var title = this.add.text(this.world.centerX, this.world.centerY/2, LANG.TEXT.title, {
		font: '50pt ' +  GLOBAL.FONT,
		fill: '#ffff00',
		stroke: '#000000',
		strokeThickness: 5
	});
	title.anchor.set(0.5);

	var text = this.add.text(this.world.centerX, this.world.centerY, LANG.TEXT.start, {
		font: '50pt ' +  GLOBAL.FONT,
		fill: '#dd00dd'
	});
	text.anchor.set(0.5);
	text.inputEnabled = true;
	text.events.onInputDown.add(function () {
		user.login('debug', 'debug');
		//this.add.audio('yeah').play();
		this.state.start(GLOBAL.STATE.garden);
	}, this);

	var credits = this.add.text(this.world.centerX, this.world.centerY/0.75, LANG.TEXT.credits, {
		font: '50pt ' +  GLOBAL.FONT,
		fill: '#000000'
	});
	credits.anchor.set(0.5);
	credits.inputEnabled = true;
	credits.events.onInputDown.add(function () {
		fade(credits, false, 0.3);
		fade(text, false, 0.3);
		fade(allCredits, true);
		rolling.restart();
		cover.visible = true;
		TweenMax.to(cover, 0.5, { alpha: 0.7 });
	}, this);

	var cover = new Cover('#000000', 0);
	cover.visible = false;
	cover.inputEnabled = true;
	cover.events.onInputDown.add(function () {
		fade(credits, true);
		fade(text, true);
		fade(allCredits, false, 0.3);
		rolling.pause();
		TweenMax.to(cover, 0.3, { alpha: 0, onComplete: function () { cover.visible = false; } });
	}, this);
	this.world.add(cover);

	var allCredits = this.add.text(this.world.centerX, this.world.height,
		'This game was made at Lund University\n\n' +
		'Game development:\nErik Anderberg, Agneta Gulz, Magnus Haake, Layla Husain\n' +
		'Programming:\nErik Anderberg, Marcus Malmberg, Henrik Söllvander\n' +
		'Graphics:\nSebastian Gulz Haake\n\n' +
		'Special Thanks:\nAnton Axelsson, Sanne Bengtsson, Maja Håkansson, Lisa Lindberg, Björn Norrliden', {
		font: '15pt ' +  GLOBAL.FONT,
		fill: '#ffffff',
		align: 'center'
	});
	allCredits.anchor.set(0.5, 0);
	allCredits.visible = false;
	var rolling = TweenMax.fromTo(allCredits, 15,
		{ y: this.world.height },
		{ y: -allCredits.height, ease: Power0.easeInOut, repeat: -1, paused: true });
};

/* Phaser state function */
Subgame.prototype.shutdown = onShutDown;<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var util = require("adapter/util"),
        descriptor = require("adapter/ps/descriptor"),
        OS = require("adapter/os"),
        system = require("js/util/system"),
        UI = require("adapter/ps/ui"),
        toolLib = require("adapter/lib/tool"),
        Tool = require("js/models/tool"),
        EventPolicy = require("js/models/eventpolicy"),
        KeyboardEventPolicy = EventPolicy.KeyboardEventPolicy,
        PointerEventPolicy = EventPolicy.PointerEventPolicy;

    var VectorTool = require("./superselect/vector"),
        TypeTool = require("./superselect/type");

    var _ = require("lodash");

    var SuperselectOverlay = require("jsx!js/jsx/tools/SuperselectOverlay");

    /**
     * Failsafe check for pointer policy list
     * So we don't mistakenly remove default policies
     */
    var _initialPointerPolicyListLength;

    /**
     * Flag to keep track of space key, so we can start panning on empty pixels
     */
    var _spaceKeyDown;

    /**
     * @implements {Tool}
     * @constructor
     */
    var SuperSelectTool = function () {
        this.id = "newSelect";
        this.icon = "newSelect";
        this.name = "Super Select";
        this.nativeToolName = "moveTool";
        this.dragging = false;
        this.dragEvent = null;
        this.activationKey = "v";

        var selectHandler = function (tool) {
            var toolOptions = {
                "$AtSl": false, // Auto select on drag
                "$ASGr": false, // Auto select Groups,
                "$Abbx": false // Don't show transform controls
            };

            var centerOffsets = this.flux.store("ui").getState().centerOffsets,
                panelWidth = centerOffsets ? centerOffsets.right : 0,
                scrimArea = {
                    x: 0,
                    y: 0,
                    width: document.body.clientWidth - panelWidth,
                    height: document.body.clientHeight
                };

            var scrimScrollPolicy = new PointerEventPolicy(UI.policyAction.ALWAYS_PROPAGATE,
                    OS.eventKind.MOUSE_WHEEL, null, scrimArea);

            tool.pointerPolicyList.push(scrimScrollPolicy);

            return descriptor.playObject(toolLib.setToolOptions("moveTool", toolOptions))
                .then(function () {
                    UI.setPointerPropagationMode({
                        defaultMode: UI.pointerPropagationMode.NEVER_PROPAGATE
                    });
                });
        };

        var deselectHandler = function (tool) {
            // If for some reason we've come here and we only have the default policies installed,
            // we shouldn't alter the pointer policy list
            if (tool.pointerPolicyList.length > _initialPointerPolicyListLength) {
                tool.pointerPolicyList.pop();
            }

            return UI.setPointerPropagationMode({
                defaultMode: UI.pointerPropagationMode.ALPHA_PROPAGATE
            });
        };

        this.selectHandler = selectHandler;
        this.deselectHandler = deselectHandler;

        var escapeKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ESCAPE),
            tabKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.TAB),
            enterKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ENTER),
            arrowUpKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_UP),
            arrowDownKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_DOWN),
            arrowLeftKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_LEFT),
            arrowRightKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_RIGHT);

        this.keyboardPolicyList = [
            escapeKeyPolicy,
            tabKeyPolicy,
            enterKeyPolicy,
            arrowUpKeyPolicy,
            arrowDownKeyPolicy,
            arrowLeftKeyPolicy,
            arrowRightKeyPolicy
        ];

        var pointerPolicy = new PointerEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.LEFT_MOUSE_DOWN);
        this.pointerPolicyList = [pointerPolicy];

        _initialPointerPolicyListLength = this.pointerPolicyList.length;
        _spaceKeyDown = false;

        this.subToolList = [
            new VectorTool(),
            new TypeTool()
        ];
    };
    util.inherits(SuperSelectTool, Tool);

    /**
     * Handler for mouse down events, installed when the tool is active.
     *
     * @param {SyntheticEvent} event
     */
    SuperSelectTool.prototype.onMouseDown = function (event) {
        // We don't want to handle right or middle clicks!
        if (event.button !== 0) {
            return;
        }

        this.dragging = true;
        this.dragEvent = _.clone(event);
    };

    /**
     * Handler for mouse up, turns off dragging
     *
     * @param {SyntheticEvent} event
     */
    SuperSelectTool.prototype.onMouseUp = function (event) {
        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument(),
            mouseDownFlag = !!this.dragEvent,
            diveIn = false;

        if (mouseDownFlag) {
            diveIn = system.isMac ? this.dragEvent.metaKey : this.dragEvent.ctrlKey;
        }

        // Clean up even if we're canceling out
        this.dragging = false;
        this.dragEvent = null;

        // if dragEvent is null, mouse down was not hit, so we shouldn't try to click
        if (!currentDocument || !mouseDownFlag) {
            return;
        }
        flux.actions.superselect.click(currentDocument, event.pageX, event.pageY, diveIn, event.shiftKey);
    };

    /**
     * Handler for mouse move, sends a click to Photoshop at mouse down location
     */
    SuperSelectTool.prototype.onMouseMove = function () {
        if (!this.dragging) {
            return;
        }
        this.dragging = false;

        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument();

        if (!currentDocument) {
            return;
        }

        var dragEvent = this.dragEvent,
            modifiers = {
                option: dragEvent.altKey,
                command: dragEvent.metaKey,
                shift: dragEvent.shiftKey,
                control: dragEvent.ctrlKey
            };

        // Since we don't get the mouse up after we start dragging in PS, we need to reset the event here
        this.dragEvent = null;
        flux.actions.superselect.drag(currentDocument, dragEvent.pageX, dragEvent.pageY, modifiers, _spaceKeyDown);

        // If we start panning, PS is going to eat up the key up event during, so set it to false here
        _spaceKeyDown = false;
    };

    SuperSelectTool.prototype.onClick = function (event) {
        // Prevents clicks from reaching the window and dismissing onWindowClick dialogs
        event.stopPropagation();
    };

    /**
     * Handler for mouse click events, installed when the tool is active.
     *
     * @param {SyntheticEvent} event
     */
    SuperSelectTool.prototype.onDoubleClick = function (event) {
        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument();

        if (!currentDocument) {
            return;
        }

        flux.actions.superselect.doubleClick(currentDocument, event.pageX, event.pageY);
    };

    /**
     * Handler for keydown events, installed when the tool is active.
     *
     * @todo  Fix this after keyboard policies are more in place
     * @param {CustomEvent} event
     */
    SuperSelectTool.prototype.onKeyDown = function (event) {
        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument();

        if (!currentDocument) {
            return;
        }

        var detail = event.detail,
            direction = "";

        switch (detail.keyCode) {
        case OS.eventKeyCode.ESCAPE: // Escape
            var dontDeselectAll = system.isMac ? detail.modifiers.alt : detail.modifiers.shift;
            flux.actions.superselect.backOut(currentDocument, dontDeselectAll);
            break;
        case OS.eventKeyCode.TAB: // Tab
            var cycleBack = detail.modifiers.shift;
            flux.actions.superselect.nextSibling(currentDocument, cycleBack);
            break;
        case OS.eventKeyCode.ENTER: // Enter
            flux.actions.superselect.diveIn(currentDocument);
            break;
        case OS.eventKeyCode.ARROW_UP:
            direction = "up";
            break;
        case OS.eventKeyCode.ARROW_DOWN:
            direction = "down";
            break;
        case OS.eventKeyCode.ARROW_LEFT:
            direction = "left";
            break;
        case OS.eventKeyCode.ARROW_RIGHT:
            direction = "right";
            break;
        }

        if (direction !== "") {
            var bigStep = detail.modifiers.shift,
                selected = currentDocument.layers.selected;
            flux.actions.transform.nudgeLayersDebounced(currentDocument, selected, direction, bigStep);
        }

        if (detail.keyChar === " ") {
            _spaceKeyDown = true;
        }
    };

    /**
     * Handler for key up events, we look for space bar key up event to
     * reset the flag we send to superselect.drag
     *
     * @param {CustomEvent} event
     */
    SuperSelectTool.prototype.onKeyUp = function (event) {
        var detail = event.detail;

        if (detail.keyChar === " ") {
            _spaceKeyDown = false;
        }
    };

    SuperSelectTool.prototype.toolOverlay = SuperselectOverlay;

    module.exports = SuperSelectTool;
});
<commit_msg>Remove unused mouse wheel policy from select tool<commit_after>/*
 * Copyright (c) 2014 Adobe Systems Incorporated. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 */

define(function (require, exports, module) {
    "use strict";

    var util = require("adapter/util"),
        descriptor = require("adapter/ps/descriptor"),
        OS = require("adapter/os"),
        system = require("js/util/system"),
        UI = require("adapter/ps/ui"),
        toolLib = require("adapter/lib/tool"),
        Tool = require("js/models/tool"),
        EventPolicy = require("js/models/eventpolicy"),
        KeyboardEventPolicy = EventPolicy.KeyboardEventPolicy,
        PointerEventPolicy = EventPolicy.PointerEventPolicy;

    var VectorTool = require("./superselect/vector"),
        TypeTool = require("./superselect/type");

    var _ = require("lodash");

    var SuperselectOverlay = require("jsx!js/jsx/tools/SuperselectOverlay");

    /**
     * Flag to keep track of space key, so we can start panning on empty pixels
     */
    var _spaceKeyDown;

    /**
     * @implements {Tool}
     * @constructor
     */
    var SuperSelectTool = function () {
        this.id = "newSelect";
        this.icon = "newSelect";
        this.name = "Super Select";
        this.nativeToolName = "moveTool";
        this.dragging = false;
        this.dragEvent = null;
        this.activationKey = "v";

        var selectHandler = function () {
            var toolOptions = {
                "$AtSl": false, // Auto select on drag
                "$ASGr": false, // Auto select Groups,
                "$Abbx": false // Don't show transform controls
            };

            return descriptor.playObject(toolLib.setToolOptions("moveTool", toolOptions))
                .then(function () {
                    UI.setPointerPropagationMode({
                        defaultMode: UI.pointerPropagationMode.NEVER_PROPAGATE
                    });
                });
        };

        var deselectHandler = function () {
            return UI.setPointerPropagationMode({
                defaultMode: UI.pointerPropagationMode.ALPHA_PROPAGATE
            });
        };

        this.selectHandler = selectHandler;
        this.deselectHandler = deselectHandler;

        var escapeKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ESCAPE),
            tabKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.TAB),
            enterKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ENTER),
            arrowUpKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_UP),
            arrowDownKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_DOWN),
            arrowLeftKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_LEFT),
            arrowRightKeyPolicy = new KeyboardEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.KEY_DOWN, null, OS.eventKeyCode.ARROW_RIGHT);

        this.keyboardPolicyList = [
            escapeKeyPolicy,
            tabKeyPolicy,
            enterKeyPolicy,
            arrowUpKeyPolicy,
            arrowDownKeyPolicy,
            arrowLeftKeyPolicy,
            arrowRightKeyPolicy
        ];

        var pointerPolicy = new PointerEventPolicy(UI.policyAction.NEVER_PROPAGATE,
                OS.eventKind.LEFT_MOUSE_DOWN);
        this.pointerPolicyList = [
            pointerPolicy
        ];

        _spaceKeyDown = false;

        this.subToolList = [
            new VectorTool(),
            new TypeTool()
        ];
    };
    util.inherits(SuperSelectTool, Tool);

    /**
     * Handler for mouse down events, installed when the tool is active.
     *
     * @param {SyntheticEvent} event
     */
    SuperSelectTool.prototype.onMouseDown = function (event) {
        // We don't want to handle right or middle clicks!
        if (event.button !== 0) {
            return;
        }

        this.dragging = true;
        this.dragEvent = _.clone(event);
    };

    /**
     * Handler for mouse up, turns off dragging
     *
     * @param {SyntheticEvent} event
     */
    SuperSelectTool.prototype.onMouseUp = function (event) {
        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument(),
            mouseDownFlag = !!this.dragEvent,
            diveIn = false;

        if (mouseDownFlag) {
            diveIn = system.isMac ? this.dragEvent.metaKey : this.dragEvent.ctrlKey;
        }

        // Clean up even if we're canceling out
        this.dragging = false;
        this.dragEvent = null;

        // if dragEvent is null, mouse down was not hit, so we shouldn't try to click
        if (!currentDocument || !mouseDownFlag) {
            return;
        }
        flux.actions.superselect.click(currentDocument, event.pageX, event.pageY, diveIn, event.shiftKey);
    };

    /**
     * Handler for mouse move, sends a click to Photoshop at mouse down location
     */
    SuperSelectTool.prototype.onMouseMove = function () {
        if (!this.dragging) {
            return;
        }
        this.dragging = false;

        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument();

        if (!currentDocument) {
            return;
        }

        var dragEvent = this.dragEvent,
            modifiers = {
                option: dragEvent.altKey,
                command: dragEvent.metaKey,
                shift: dragEvent.shiftKey,
                control: dragEvent.ctrlKey
            };

        // Since we don't get the mouse up after we start dragging in PS, we need to reset the event here
        this.dragEvent = null;
        flux.actions.superselect.drag(currentDocument, dragEvent.pageX, dragEvent.pageY, modifiers, _spaceKeyDown);

        // If we start panning, PS is going to eat up the key up event during, so set it to false here
        _spaceKeyDown = false;
    };

    SuperSelectTool.prototype.onClick = function (event) {
        // Prevents clicks from reaching the window and dismissing onWindowClick dialogs
        event.stopPropagation();
    };

    /**
     * Handler for mouse click events, installed when the tool is active.
     *
     * @param {SyntheticEvent} event
     */
    SuperSelectTool.prototype.onDoubleClick = function (event) {
        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument();

        if (!currentDocument) {
            return;
        }

        flux.actions.superselect.doubleClick(currentDocument, event.pageX, event.pageY);
    };

    /**
     * Handler for keydown events, installed when the tool is active.
     *
     * @todo  Fix this after keyboard policies are more in place
     * @param {CustomEvent} event
     */
    SuperSelectTool.prototype.onKeyDown = function (event) {
        var flux = this.getFlux(),
            applicationStore = flux.store("application"),
            currentDocument = applicationStore.getCurrentDocument();

        if (!currentDocument) {
            return;
        }

        var detail = event.detail,
            direction = "";

        switch (detail.keyCode) {
        case OS.eventKeyCode.ESCAPE: // Escape
            var dontDeselectAll = system.isMac ? detail.modifiers.alt : detail.modifiers.shift;
            flux.actions.superselect.backOut(currentDocument, dontDeselectAll);
            break;
        case OS.eventKeyCode.TAB: // Tab
            var cycleBack = detail.modifiers.shift;
            flux.actions.superselect.nextSibling(currentDocument, cycleBack);
            break;
        case OS.eventKeyCode.ENTER: // Enter
            flux.actions.superselect.diveIn(currentDocument);
            break;
        case OS.eventKeyCode.ARROW_UP:
            direction = "up";
            break;
        case OS.eventKeyCode.ARROW_DOWN:
            direction = "down";
            break;
        case OS.eventKeyCode.ARROW_LEFT:
            direction = "left";
            break;
        case OS.eventKeyCode.ARROW_RIGHT:
            direction = "right";
            break;
        }

        if (direction !== "") {
            var bigStep = detail.modifiers.shift,
                selected = currentDocument.layers.selected;
            flux.actions.transform.nudgeLayersDebounced(currentDocument, selected, direction, bigStep);
        }

        if (detail.keyChar === " ") {
            _spaceKeyDown = true;
        }
    };

    /**
     * Handler for key up events, we look for space bar key up event to
     * reset the flag we send to superselect.drag
     *
     * @param {CustomEvent} event
     */
    SuperSelectTool.prototype.onKeyUp = function (event) {
        var detail = event.detail;

        if (detail.keyChar === " ") {
            _spaceKeyDown = false;
        }
    };

    SuperSelectTool.prototype.toolOverlay = SuperselectOverlay;

    module.exports = SuperSelectTool;
});
<|endoftext|>


<commit_before>/**
 * Simple static class for processing server-side JSON.
 */
var JsonRewriter = module.exports = {
  /**
   * Filter affected nodes by type.
   *
   * If affectedNodes is not a valid set of nodes, returns an empty array.
   */
  filterAnodes: function (affectedNodes, type) {
    if (!affectedNodes) return [];

    return affectedNodes.filter(function (an) {
      an = an.CreatedNode ? an.CreatedNode :
           an.ModifiedNode ? an.ModifiedNode :
           {};

      return an.LedgerEntryType === type;
    });
  },

  /**
   * Returns resulting (new or modified) fields from an affected node.
   */
  getAnodeResult: function (an) {
    an = an.CreatedNode ? an.CreatedNode :
         an.ModifiedNode ? an.ModifiedNode :
         {};

    var fields = $.extend({}, an.NewFields, an.FinalFields);

    return fields;
  },

  /**
   * Takes a metadata affected node and returns a simpler JSON object.
   *
   * The resulting object looks like this:
   *
   *   {
   *     // Type of diff, e.g. CreatedNode, ModifiedNode
   *     diffType: 'CreatedNode'
   *
   *     // Type of node affected, e.g. RippleState, AccountRoot
   *     entryType: 'RippleState',
   *
   *     // Index of the ledger this change occurred in
   *     ledgerIndex: '01AB01AB...',
   *
   *     // Contains all fields with later versions taking precedence
   *     //
   *     // This is a shorthand for doing things like checking which account
   *     // this affected without having to check the diffType.
   *     fields: {...},
   *
   *     // Old fields (before the change)
   *     fieldsPrev: {...},
   *
   *     // New fields (that have been added)
   *     fieldsNew: {...},
   *
   *     // Changed fields
   *     fieldsFinal: {...}
   *   }
   */
  processAnode: function (an) {
    var result = {};

    ["CreatedNode", "ModifiedNode", "DeletedNode"].forEach(function (x) {
      if (an[x]) result.diffType = x;
    });

    if (!result.diffType) return null;

    an = an[result.diffType];

    result.entryType = an.LedgerEntryType;
    result.ledgerIndex = an.LedgerIndex;

    result.fields = $.extend({}, an.PreviousFields, an.NewFields, an.FinalFields);
    result.fieldsPrev = an.PreviousFields || {};
    result.fieldsNew = an.NewFields || {};
    result.fieldsFinal = an.FinalFields || {};

    return result;
  },

  /**
   * Convert transactions into a more useful (for our purposes) format.
   *
   * The main operation this function performs is to change the view on the
   * transaction from a neutral view to a subjective view specific to our
   * account.
   *
   * For example, rather than having a sender and receiver, the transaction has
   * a counterparty and a flag whether it is incoming or outgoing.
   *
   * processTxn returns main purpose of transaction and side effects.
   *
   * Main purpose
   *  - Payment (sent/received)
   *  - TrustSet (trusting/trusted)
   *  - OfferCreate (offernew)
   *
   * Side effects
   *  - balance_change
   *  - Trust (trust_create_local, trust_create_remote, trust_change_local, trust_change_remote, trust_change_balance)
   *  - Offer (offer_created, offer_funded, offer_partially_funded, offer_cancelled, offer_bought)
   */
  processTxn: function (tx, meta, account) {
    var obj = {};

    // Currency balances that have been affected by the transaction
    var affected_currencies = [];

    // Main transaction
    if (tx.Account === account
        || (tx.Destination && tx.Destination === account)
        || (tx.LimitAmount && tx.LimitAmount.issuer === account)) {
      var transaction = {};

      switch (tx.TransactionType) {
        case 'Payment':
          var amount = ripple.Amount.from_json(tx.Amount);

          transaction.type = tx.Account === account ? 'sent' : 'received';
          transaction.counterparty = tx.Account === account ? tx.Destination : tx.Account;
          transaction.amount = amount;
          transaction.currency = amount.currency().to_json();
          break;

        case 'TrustSet':
          transaction.type = tx.Account === account ? 'trusting' : 'trusted';
          transaction.counterparty = tx.Account === account ? tx.LimitAmount.issuer : tx.Account;
          transaction.amount = ripple.Amount.from_json(tx.LimitAmount);
          transaction.currency = tx.LimitAmount.currency;
          break;

        case 'OfferCreate':
          transaction.type = 'offernew';
          transaction.pays = ripple.Amount.from_json(tx.TakerPays);
          transaction.gets = ripple.Amount.from_json(tx.TakerGets);
          break;

        case 'OfferCancel':
          transaction.type = 'offercancel';
          break;

        case 'AccountSet':
          // Ignored for now
          break;

        default:
          console.log('Unknown transaction type: "'+tx.TransactionType+'"', tx);
      }

      if (!$.isEmptyObject(transaction)) {
        if (tx.Flags)
          transaction.flags = tx.Flags;

        obj.transaction = transaction;
      }
    }

    // Side effects
    meta.AffectedNodes.forEach(function (n) {
      var node = JsonRewriter.processAnode(n);
      var feeEff;
      var effect = {};

      // AccountRoot - Current account node
      if (node.entryType === "AccountRoot" && node.fields.Account === account) {
        obj.accountRoot = node.fields;

        if (node.fieldsPrev.Balance) {
          var balance = ripple.Amount.from_json(node.fields.Balance);

          // Fee
          if(tx.Account === account && tx.Fee) {
            feeEff = {
              type: "fee",
              amount: ripple.Amount.from_json(tx.Fee).negate(),
              balance: balance
            };
          }

          // Updated XRP Balance
          if (tx.Fee != node.fieldsPrev.Balance - node.fields.Balance) {
            if (feeEff)
              balance = balance.subtract(feeEff.amount);

            effect.type = "balance_change";
            effect.amount = balance.subtract(node.fieldsPrev.Balance);
            effect.balance = balance;

            // balance_changer is set to true if the transaction / effect has changed one of the account balances
            obj.balance_changer = effect.balance_changer = true;
            affected_currencies.push('XRP');
          }
        }
      }

      // RippleState - Ripple Lines
      if (node.entryType === "RippleState"
          && (node.fields.HighLimit.issuer === account || node.fields.LowLimit.issuer === account)) {

        var high = node.fields.HighLimit;
        var low = node.fields.LowLimit;

        // New trust line
        if (node.diffType === "CreatedNode") {
          effect.limit = ripple.Amount.from_json(high.value > 0 ? high : low);
          effect.limit_peer = ripple.Amount.from_json(high.value > 0 ? low : high);

          if ((high.value > 0 && high.issuer === account)
              || (low.value > 0 && low.issuer === account)) {
            effect.type = "trust_create_local";
          } else {
            effect.type = "trust_create_remote";
          }
        }

        // Modified trust line
        else if (node.diffType === "ModifiedNode" || node.diffType === "DeletedNode") {
          var highPrev = node.fieldsPrev.HighLimit;
          var lowPrev = node.fieldsPrev.LowLimit;

          // Trust Balance change
          if (node.fieldsPrev.Balance) {
            effect.type = "trust_change_balance";

            effect.amount = high.issuer === account
              ? effect.amount = ripple.Amount.from_json(node.fieldsPrev.Balance).subtract(node.fields.Balance)
              : effect.amount = ripple.Amount.from_json(node.fields.Balance).subtract(node.fieldsPrev.Balance);

            obj.balance_changer = effect.balance_changer = true;
            affected_currencies.push(high.currency.toUpperCase());
          }

          // Trust Limit change
          else if (highPrev || lowPrev) {
            if (high.issuer === account) {
              effect.limit = ripple.Amount.from_json(high);
              effect.limit_peer = ripple.Amount.from_json(low);
            } else {
              effect.limit = ripple.Amount.from_json(low);
              effect.limit_peer = ripple.Amount.from_json(high);
            }

            if (highPrev) {
              effect.prevLimit = ripple.Amount.from_json(highPrev);
              effect.type = high.issuer === account ? "trust_change_local" : "trust_change_remote";
            }
            else if (lowPrev) {
              effect.prevLimit = ripple.Amount.from_json(lowPrev);
              effect.type = high.issuer === account ? "trust_change_remote" : "trust_change_local";
            }
          }
        }

        if (!$.isEmptyObject(effect)) {
          effect.counterparty = high.issuer === account ? low.issuer : high.issuer;
          effect.currency = high.currency;
          effect.balance = high.issuer === account
            ? ripple.Amount.from_json(node.fields.Balance).negate(true)
            : ripple.Amount.from_json(node.fields.Balance);

          if (obj.transaction && obj.transaction.type == "trust_change_balance") {
            obj.transaction.balance = effect.balance;
          }
        }
      }

      // Offer
      else if (node.entryType === "Offer") {

        // For new and cancelled offers we use "fields"
        var fieldSet = node.fields;

        // Current account offer
        if (node.fields.Account === account) {

          // Partially funded offer [and deleted.. no more funds]
          /* Offer has been partially funded and deleted (because of the luck of funds)
             if the node is deleted and the TakerGets/TakerPays field has been changed */
          if (node.diffType === "ModifiedNode" ||
            (node.diffType === "DeletedNode"
              && node.fieldsPrev.TakerGets
              && !ripple.Amount.from_json(node.fieldsFinal.TakerGets).is_zero())) {
            effect.type = 'offer_partially_funded';

            if (node.diffType !== "DeletedNode")
              effect.remaining = ripple.Amount.from_json(node.fields.TakerGets);
          }
          else {
            // New / Funded / Cancelled offer
            effect.type = node.diffType === "CreatedNode"
              ? 'offer_created'
              : node.fieldsPrev.TakerPays
                ? 'offer_funded'
                : 'offer_cancelled';

            // For funded offers we use "fieldsPrev".
            if (effect.type === 'offer_funded')
              fieldSet = node.fieldsPrev;

            // We don't count cancelling an offer as a side effect if it's
            // already the primary effect of the transaction.
            if (effect.type === 'offer_cancelled' &&
                obj.transaction &&
                obj.transaction.type === "offercancel") {

              // Fill in remaining information about offer
              obj.transaction.gets = fieldSet.TakerGets;
              obj.transaction.pays = fieldSet.TakerPays;
            }
          }

          effect.seq = +node.fields.Sequence;
        }

        // Another account offer. We care about it only if our transaction changed the offer amount (we bought currency)
        else if(tx.Account === account && !$.isEmptyObject(node.fieldsPrev) /* Offer is unfunded if node.fieldsPrev is empty */) {
          effect.type = 'offer_bought';
        }

        if (effect.type) {
          effect.gets = ripple.Amount.from_json(fieldSet.TakerGets);
          effect.pays = ripple.Amount.from_json(fieldSet.TakerPays);

          if ('offer_partially_funded' === effect.type || 'offer_bought' === effect.type) {
            effect.got = ripple.Amount.from_json(node.fieldsPrev.TakerGets).subtract(node.fields.TakerGets);
            effect.paid = ripple.Amount.from_json(node.fieldsPrev.TakerPays).subtract(node.fields.TakerPays);
          }
        }
      }

      if (!$.isEmptyObject(effect)) {
        if (node.diffType === "DeletedNode") {
          effect.deleted = true;
        }

        if (!obj.effects) obj.effects = [];
        obj.effects.push(effect);
      }

      // Fee effect
      if (feeEff) {
        if (!obj.effects) obj.effects = [];
        obj.effects.push(feeEff);
      }
    });

    // Balance after the transaction
    if (obj.accountRoot && obj.transaction && "undefined" === typeof obj.transaction.balance) {
      obj.transaction.balance = ripple.Amount.from_json(obj.accountRoot.Balance);
    }

    if ($.isEmptyObject(obj))
      return;

    // If the transaction didn't wind up cancelling an offer
    if (tx.TransactionType === 'OfferCancel' && (!obj.transaction.gets || !obj.transaction.pays)) {
      return;
    }

    obj.tx_type = tx.TransactionType;
    obj.tx_result = meta.TransactionResult;
    obj.fee = tx.Fee;
    obj.date = (tx.date + 0x386D4380) * 1000;
    obj.hash = tx.hash;
    obj.affected_currencies = affected_currencies ? affected_currencies : [];

    return obj;
  }
};
<commit_msg>JsonRewriter: effect.amount includes currency issuer<commit_after>/**
 * Simple static class for processing server-side JSON.
 */
var JsonRewriter = module.exports = {
  /**
   * Filter affected nodes by type.
   *
   * If affectedNodes is not a valid set of nodes, returns an empty array.
   */
  filterAnodes: function (affectedNodes, type) {
    if (!affectedNodes) return [];

    return affectedNodes.filter(function (an) {
      an = an.CreatedNode ? an.CreatedNode :
           an.ModifiedNode ? an.ModifiedNode :
           {};

      return an.LedgerEntryType === type;
    });
  },

  /**
   * Returns resulting (new or modified) fields from an affected node.
   */
  getAnodeResult: function (an) {
    an = an.CreatedNode ? an.CreatedNode :
         an.ModifiedNode ? an.ModifiedNode :
         {};

    var fields = $.extend({}, an.NewFields, an.FinalFields);

    return fields;
  },

  /**
   * Takes a metadata affected node and returns a simpler JSON object.
   *
   * The resulting object looks like this:
   *
   *   {
   *     // Type of diff, e.g. CreatedNode, ModifiedNode
   *     diffType: 'CreatedNode'
   *
   *     // Type of node affected, e.g. RippleState, AccountRoot
   *     entryType: 'RippleState',
   *
   *     // Index of the ledger this change occurred in
   *     ledgerIndex: '01AB01AB...',
   *
   *     // Contains all fields with later versions taking precedence
   *     //
   *     // This is a shorthand for doing things like checking which account
   *     // this affected without having to check the diffType.
   *     fields: {...},
   *
   *     // Old fields (before the change)
   *     fieldsPrev: {...},
   *
   *     // New fields (that have been added)
   *     fieldsNew: {...},
   *
   *     // Changed fields
   *     fieldsFinal: {...}
   *   }
   */
  processAnode: function (an) {
    var result = {};

    ["CreatedNode", "ModifiedNode", "DeletedNode"].forEach(function (x) {
      if (an[x]) result.diffType = x;
    });

    if (!result.diffType) return null;

    an = an[result.diffType];

    result.entryType = an.LedgerEntryType;
    result.ledgerIndex = an.LedgerIndex;

    result.fields = $.extend({}, an.PreviousFields, an.NewFields, an.FinalFields);
    result.fieldsPrev = an.PreviousFields || {};
    result.fieldsNew = an.NewFields || {};
    result.fieldsFinal = an.FinalFields || {};

    return result;
  },

  /**
   * Convert transactions into a more useful (for our purposes) format.
   *
   * The main operation this function performs is to change the view on the
   * transaction from a neutral view to a subjective view specific to our
   * account.
   *
   * For example, rather than having a sender and receiver, the transaction has
   * a counterparty and a flag whether it is incoming or outgoing.
   *
   * processTxn returns main purpose of transaction and side effects.
   *
   * Main purpose
   *  - Payment (sent/received)
   *  - TrustSet (trusting/trusted)
   *  - OfferCreate (offernew)
   *
   * Side effects
   *  - balance_change
   *  - Trust (trust_create_local, trust_create_remote, trust_change_local, trust_change_remote, trust_change_balance)
   *  - Offer (offer_created, offer_funded, offer_partially_funded, offer_cancelled, offer_bought)
   */
  processTxn: function (tx, meta, account) {
    var obj = {};

    // Currency balances that have been affected by the transaction
    var affected_currencies = [];

    // Main transaction
    if (tx.Account === account
        || (tx.Destination && tx.Destination === account)
        || (tx.LimitAmount && tx.LimitAmount.issuer === account)) {
      var transaction = {};

      switch (tx.TransactionType) {
        case 'Payment':
          var amount = ripple.Amount.from_json(tx.Amount);

          transaction.type = tx.Account === account ? 'sent' : 'received';
          transaction.counterparty = tx.Account === account ? tx.Destination : tx.Account;
          transaction.amount = amount;
          transaction.currency = amount.currency().to_json();
          break;

        case 'TrustSet':
          transaction.type = tx.Account === account ? 'trusting' : 'trusted';
          transaction.counterparty = tx.Account === account ? tx.LimitAmount.issuer : tx.Account;
          transaction.amount = ripple.Amount.from_json(tx.LimitAmount);
          transaction.currency = tx.LimitAmount.currency;
          break;

        case 'OfferCreate':
          transaction.type = 'offernew';
          transaction.pays = ripple.Amount.from_json(tx.TakerPays);
          transaction.gets = ripple.Amount.from_json(tx.TakerGets);
          break;

        case 'OfferCancel':
          transaction.type = 'offercancel';
          break;

        case 'AccountSet':
          // Ignored for now
          break;

        default:
          console.log('Unknown transaction type: "'+tx.TransactionType+'"', tx);
      }

      if (!$.isEmptyObject(transaction)) {
        if (tx.Flags)
          transaction.flags = tx.Flags;

        obj.transaction = transaction;
      }
    }

    // Side effects
    meta.AffectedNodes.forEach(function (n) {
      var node = JsonRewriter.processAnode(n);
      var feeEff;
      var effect = {};

      // AccountRoot - Current account node
      if (node.entryType === "AccountRoot" && node.fields.Account === account) {
        obj.accountRoot = node.fields;

        if (node.fieldsPrev.Balance) {
          var balance = ripple.Amount.from_json(node.fields.Balance);

          // Fee
          if(tx.Account === account && tx.Fee) {
            feeEff = {
              type: "fee",
              amount: ripple.Amount.from_json(tx.Fee).negate(),
              balance: balance
            };
          }

          // Updated XRP Balance
          if (tx.Fee != node.fieldsPrev.Balance - node.fields.Balance) {
            if (feeEff)
              balance = balance.subtract(feeEff.amount);

            effect.type = "balance_change";
            effect.amount = balance.subtract(node.fieldsPrev.Balance);
            effect.balance = balance;

            // balance_changer is set to true if the transaction / effect has changed one of the account balances
            obj.balance_changer = effect.balance_changer = true;
            affected_currencies.push('XRP');
          }
        }
      }

      // RippleState - Ripple Lines
      if (node.entryType === "RippleState"
          && (node.fields.HighLimit.issuer === account || node.fields.LowLimit.issuer === account)) {

        var high = node.fields.HighLimit;
        var low = node.fields.LowLimit;

        // New trust line
        if (node.diffType === "CreatedNode") {
          effect.limit = ripple.Amount.from_json(high.value > 0 ? high : low);
          effect.limit_peer = ripple.Amount.from_json(high.value > 0 ? low : high);

          if ((high.value > 0 && high.issuer === account)
              || (low.value > 0 && low.issuer === account)) {
            effect.type = "trust_create_local";
          } else {
            effect.type = "trust_create_remote";
          }
        }

        // Modified trust line
        else if (node.diffType === "ModifiedNode" || node.diffType === "DeletedNode") {
          var highPrev = node.fieldsPrev.HighLimit;
          var lowPrev = node.fieldsPrev.LowLimit;

          // Trust Balance change
          if (node.fieldsPrev.Balance) {
            effect.type = "trust_change_balance";

            var issuer =  node.fields.Balance.value > 0 || node.fieldsPrev.Balance.value > 0
              ? high.issuer : low.issuer;

            effect.amount = high.issuer === account
              ? effect.amount = ripple.Amount.from_json(
                  node.fieldsPrev.Balance.value
                      + "/" + node.fieldsPrev.Balance.currency
                      + "/" + issuer).subtract(node.fields.Balance)
              : effect.amount = ripple.Amount.from_json(
                  node.fields.Balance.value
                      + "/" + node.fields.Balance.currency
                      + "/" + issuer).subtract(node.fieldsPrev.Balance);

            obj.balance_changer = effect.balance_changer = true;
            affected_currencies.push(high.currency.toUpperCase());
          }

          // Trust Limit change
          else if (highPrev || lowPrev) {
            if (high.issuer === account) {
              effect.limit = ripple.Amount.from_json(high);
              effect.limit_peer = ripple.Amount.from_json(low);
            } else {
              effect.limit = ripple.Amount.from_json(low);
              effect.limit_peer = ripple.Amount.from_json(high);
            }

            if (highPrev) {
              effect.prevLimit = ripple.Amount.from_json(highPrev);
              effect.type = high.issuer === account ? "trust_change_local" : "trust_change_remote";
            }
            else if (lowPrev) {
              effect.prevLimit = ripple.Amount.from_json(lowPrev);
              effect.type = high.issuer === account ? "trust_change_remote" : "trust_change_local";
            }
          }
        }

        if (!$.isEmptyObject(effect)) {
          effect.counterparty = high.issuer === account ? low.issuer : high.issuer;
          effect.currency = high.currency;
          effect.balance = high.issuer === account
            ? ripple.Amount.from_json(node.fields.Balance).negate(true)
            : ripple.Amount.from_json(node.fields.Balance);

          if (obj.transaction && obj.transaction.type == "trust_change_balance") {
            obj.transaction.balance = effect.balance;
          }
        }
      }

      // Offer
      else if (node.entryType === "Offer") {

        // For new and cancelled offers we use "fields"
        var fieldSet = node.fields;

        // Current account offer
        if (node.fields.Account === account) {

          // Partially funded offer [and deleted.. no more funds]
          /* Offer has been partially funded and deleted (because of the luck of funds)
             if the node is deleted and the TakerGets/TakerPays field has been changed */
          if (node.diffType === "ModifiedNode" ||
            (node.diffType === "DeletedNode"
              && node.fieldsPrev.TakerGets
              && !ripple.Amount.from_json(node.fieldsFinal.TakerGets).is_zero())) {
            effect.type = 'offer_partially_funded';

            if (node.diffType !== "DeletedNode")
              effect.remaining = ripple.Amount.from_json(node.fields.TakerGets);
          }
          else {
            // New / Funded / Cancelled offer
            effect.type = node.diffType === "CreatedNode"
              ? 'offer_created'
              : node.fieldsPrev.TakerPays
                ? 'offer_funded'
                : 'offer_cancelled';

            // For funded offers we use "fieldsPrev".
            if (effect.type === 'offer_funded')
              fieldSet = node.fieldsPrev;

            // We don't count cancelling an offer as a side effect if it's
            // already the primary effect of the transaction.
            if (effect.type === 'offer_cancelled' &&
                obj.transaction &&
                obj.transaction.type === "offercancel") {

              // Fill in remaining information about offer
              obj.transaction.gets = fieldSet.TakerGets;
              obj.transaction.pays = fieldSet.TakerPays;
            }
          }

          effect.seq = +node.fields.Sequence;
        }

        // Another account offer. We care about it only if our transaction changed the offer amount (we bought currency)
        else if(tx.Account === account && !$.isEmptyObject(node.fieldsPrev) /* Offer is unfunded if node.fieldsPrev is empty */) {
          effect.type = 'offer_bought';
        }

        if (effect.type) {
          effect.gets = ripple.Amount.from_json(fieldSet.TakerGets);
          effect.pays = ripple.Amount.from_json(fieldSet.TakerPays);

          if ('offer_partially_funded' === effect.type || 'offer_bought' === effect.type) {
            effect.got = ripple.Amount.from_json(node.fieldsPrev.TakerGets).subtract(node.fields.TakerGets);
            effect.paid = ripple.Amount.from_json(node.fieldsPrev.TakerPays).subtract(node.fields.TakerPays);
          }
        }
      }

      if (!$.isEmptyObject(effect)) {
        if (node.diffType === "DeletedNode") {
          effect.deleted = true;
        }

        if (!obj.effects) obj.effects = [];
        obj.effects.push(effect);
      }

      // Fee effect
      if (feeEff) {
        if (!obj.effects) obj.effects = [];
        obj.effects.push(feeEff);
      }
    });

    // Balance after the transaction
    if (obj.accountRoot && obj.transaction && "undefined" === typeof obj.transaction.balance) {
      obj.transaction.balance = ripple.Amount.from_json(obj.accountRoot.Balance);
    }

    if ($.isEmptyObject(obj))
      return;

    // If the transaction didn't wind up cancelling an offer
    if (tx.TransactionType === 'OfferCancel' && (!obj.transaction.gets || !obj.transaction.pays)) {
      return;
    }

    obj.tx_type = tx.TransactionType;
    obj.tx_result = meta.TransactionResult;
    obj.fee = tx.Fee;
    obj.date = (tx.date + 0x386D4380) * 1000;
    obj.hash = tx.hash;
    obj.affected_currencies = affected_currencies ? affected_currencies : [];

    return obj;
  }
};
<|endoftext|>


<commit_before>'use strict'

module.exports = function autolink(option, callback) {
  var src = option.src;
  callback();
}
<commit_msg>try design interface<commit_after>'use strict'

/*
The goal of module is looking for link and call user function to do smth with it
params:
option - is object with string to parse and may be some option
searchCallback - user function to be call when link was found
replaceCallback - user function to be call to replace link after search
geturlCallback - user function to be call get url of link
usage:
var text = "to ream more click http://google.com";

function httpSearch(startLinkIndex, linkLength) {
  //do smth may be save startLinkIndex and linkLength
}
function httpReplace() {
  // replace link on startLinkIndex to what we need
  // use httpGeturl to get url
}
function httpGeturl(url) {
  // this function is useful in httpReplace()
}
var httpLink = autolink( { src: text }, httpSearch, httpReplace, httpGeturl);
httpLink.search();
httpLink.replace();

*/
module.exports = function autolink(option, searchCallback, replaceCallback, geturlCallback) {
  var src = option.src;
  var startLink = 0;
  var endLink = 0;
  var lengthLink = 0;
  var url = undefined;
  return {
    function search() {
      url = undefined;
      startLink = src.indexOf("http");
      lengthLink = "http".length;
      endLink = startLink+lengthLink;
      if ( typeof searchCallback === 'function' )
        searchCallback(startLink, lengthLink);
      return startLink;
    }
    function replace() {
      if ( typeof replaceCallback === 'function' )
        replaceCallback();
    }
    function getUrl() {
      if (url !== undefined) url = src.substring(startLink, lengthLink);
      if ( typeof geturlCallback === 'function' )
        geturlCallback(url);
    }
  };
}
<|endoftext|>


<commit_before>var EditBlock = (function (document) {

	function EditBlock (options) {
		this.options = {};

		for ( var i in options ) {
			this.options[i] = options[i];
		}

		this.el = typeof this.options.el == 'string' ? document.querySelector(this.options.el) : this.options.el;
		this.stage = this.options.stage || {dropped:function(){}};
		this.words = this.el.querySelectorAll('a');

		this.el.className += ' edit';
		this.el._tap = new Tap({el: this.el});
		this.el.addEventListener('tap', this, false);

		document.addEventListener('touchend', this, false);
		document.addEventListener('mouseup', this, false);
	}

	EditBlock.prototype.handleEvent = function (e) {
		switch (e.type) {
			case 'touchend':
			case 'mouseup':
				this.cancel(e);
				break;
			case 'tap':
				this.edit(e);
				break;
		}
	};

	EditBlock.prototype.cancel = function (e) {
		var target = e.target;

		if ( target == this.el || target.parentNode == this.el || target.parentNode.parentNode == this.el ) {
			return;
		}

		this.destroy();
	};

	EditBlock.prototype.edit = function (e) {
		e.stopPropagation();

		var theCut = e.target;
		var cutPointReached;
		var wordCount = this.words.length;

		if ( theCut.tagName != 'A' || theCut == this.words[wordCount-1] ) {
			return;
		}

		// Create a new block
		var newBlock = document.createElement('section');
		var newParagraph, prevContainer;

		newBlock.className = 'item';

		for ( var i = 0; i < wordCount; i++ ) {
			if ( this.words[i].parentNode != prevContainer ) {
				if ( newParagraph && cutPointReached && newParagraph.querySelector('a') ) {
					newBlock.appendChild(newParagraph);
				}

				newParagraph = document.createElement('p');
				prevContainer = this.words[i].parentNode;
			}

			if ( cutPointReached ) {
				newParagraph.appendChild(this.words[i]);

				if ( !prevContainer.querySelector('a') ) {
					prevContainer.parentNode.removeChild(prevContainer);
				}
			}

			if ( !cutPointReached && this.words[i] == theCut ) {
				cutPointReached = true;
			}
		}

		newBlock.appendChild(newParagraph);

		var action = document.createElement('div');
		action.className = 'actions';
		newBlock.appendChild(action);

		this.el.parentNode.insertBefore(newBlock, this.el.nextSibling);
		this.el.handleHTML = this.el.innerHTML;

		this.stage.dropped(newBlock);

		this.destroy();
	};

	EditBlock.prototype.destroy = function () {
		// Remove edit status
		this.el.className = this.el.className.replace(/(^|\s)edit(\s|$)/g, ' ');

		document.removeEventListener('touchend', this, false);
		document.removeEventListener('mouseup', this, false);

		this.el.removeEventListener('tap', this, false);
		this.el._editBlock = null;

		this.el._tap.destroy();
		this.el._tap = null;
	};

	return EditBlock;
})(document);<commit_msg>editblock now clones original block<commit_after>var EditBlock = (function (document) {

	function EditBlock (options) {
		this.options = {};

		for ( var i in options ) {
			this.options[i] = options[i];
		}

		this.el = typeof this.options.el == 'string' ? document.querySelector(this.options.el) : this.options.el;
		this.stage = this.options.stage || {dropped:function(){}};
		this.words = this.el.querySelectorAll('a');

		this.el.className += ' edit';
		this.el._tap = new Tap({el: this.el});
		this.el.addEventListener('tap', this, false);

		document.addEventListener('touchend', this, false);
		document.addEventListener('mouseup', this, false);
	}

	EditBlock.prototype.handleEvent = function (e) {
		switch (e.type) {
			case 'touchend':
			case 'mouseup':
				this.cancel(e);
				break;
			case 'tap':
				this.edit(e);
				break;
		}
	};

	EditBlock.prototype.cancel = function (e) {
		var target = e.target;

		if ( target == this.el || target.parentNode == this.el || target.parentNode.parentNode == this.el ) {
			return;
		}

		this.destroy();
	};

	EditBlock.prototype.edit = function (e) {
		e.stopPropagation();

		var theCut = e.target;
		var cutPointReached;
		var wordCount = this.words.length;

		if ( theCut.tagName != 'A' || theCut == this.words[wordCount-1] ) {
			return;
		}

		// Create a new block
		//var newBlock = document.createElement('section');
		var newBlock = this.el.cloneNode(false);
		var newParagraph, prevContainer;

		newBlock.className = newBlock.className.replace(/(^|\s)edit(\s|$)/g, ' ');

		//newBlock.className = 'item';

		for ( var i = 0; i < wordCount; i++ ) {
			if ( this.words[i].parentNode != prevContainer ) {
				if ( newParagraph && cutPointReached && newParagraph.querySelector('a') ) {
					newBlock.appendChild(newParagraph);
				}

				newParagraph = document.createElement('p');
				prevContainer = this.words[i].parentNode;
			}

			if ( cutPointReached ) {
				newParagraph.appendChild(this.words[i]);

				if ( !prevContainer.querySelector('a') ) {
					prevContainer.parentNode.removeChild(prevContainer);
				}
			}

			if ( !cutPointReached && this.words[i] == theCut ) {
				cutPointReached = true;
			}
		}

		newBlock.appendChild(newParagraph);

		var action = document.createElement('div');
		action.className = 'actions';
		newBlock.appendChild(action);

		this.el.parentNode.insertBefore(newBlock, this.el.nextSibling);
		this.el.handleHTML = this.el.innerHTML;

		this.stage.dropped(newBlock);

		this.destroy();
	};

	EditBlock.prototype.destroy = function () {
		// Remove edit status
		this.el.className = this.el.className.replace(/(^|\s)edit(\s|$)/g, ' ');

		document.removeEventListener('touchend', this, false);
		document.removeEventListener('mouseup', this, false);

		this.el.removeEventListener('tap', this, false);
		this.el._editBlock = null;

		this.el._tap.destroy();
		this.el._tap = null;
	};

	return EditBlock;
})(document);<|endoftext|>


<commit_before>// atc872.js - Part of the ATC872 project which delivers a low-maintenance online
//             chat forum service.
//
// Copyright (c) 2013, Chris Bristow
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those
// of the authors and should not be interpreted as representing official policies,
// either expressed or implied, of the FreeBSD Project.

// Globals.

var user = "";
var channel = "";
var latest_row = -1;
var poll_timer = null;
var short_poll_interval = 2000;
var long_poll_interval = 10000;
var poll_interval = long_poll_interval;
var poll_acc = 0;
var poll_acc_ticks = 15;
var max_extent = 200;
var highlight = false

// This runs when the page has fully loaded.  The channel is collected from
// the URL and control passed to the initialisation function.

window.addEvent('domready', function()
{
  channel = decodeURIComponent((location.search).replace("?channel=", ""));
  initialise();
});

// If there is a "user" cookie set, jump straight into the channel, otherwise prompt
// for a username.  Also, displays an error if the page is loaded without a channel
// specified.

function initialise()
{
  clearTimeout(poll_timer);

  if(channel.length == 0)
  {
    $("area51").innerHTML = "Error: No channel specified !!";
  }
  else
  {
    user = Cookie.read("user");

    if(user == null || user.length == 0)
    {
      $("area51").innerHTML  = "
Enter your name here:
";
      $("area51").innerHTML += "
<input class=\"usertextinputcss\" type=\"text\" id=\"auser\" onkeyup=\"enter_userid(event);\">
";
    }
    else
    {
      init_channel();
    }
  }
}

// Verify that the user name entered conforms, then jump to the channel view.

function enter_userid(event)
{
  if(event.keyCode == 13 && $("auser").value.length > 1 && $("auser").value.length < 100 && /\S+/.test($("auser").value))
  {
    user = $("auser").value;
    Cookie.write('user', user, { duration: 365 });
    init_channel();
  }
}

// Verify that an entered search term is valid, then post a search request to the server.

function enter_search(event)
{
  if(event.keyCode == 13 && $("asearch").value.length > 1 && /\S+/.test($("asearch").value))
  {
    $("textlist").innerHTML = "";
    highlight = false;

    var ajax=new Request({ url: "searchrows", onSuccess: function(responseText, responseXML) { fetched_rows(responseText) } });
    ajax.post("channel="+channel+"&back="+max_extent+"&pattern="+$("asearch").value);
  }
}

// Verify that a text line is valid, post it to the server and re-start polling (at the fast rate).

function enter_usertext(event)
{
  if(event.keyCode == 13 && $("usertextinput").value.length > 0 && /\S+/.test($("usertextinput").value))
  {
    var ajax=new Request({ url: "addrow", onSuccess: function(responseText, responseXML) { fetched_rows(responseText) } });
    ajax.post("channel="+channel+"&user="+user+"&text="+encodeURIComponent($("usertextinput").value)+"&from="+latest_row+"&back="+max_extent);

    $("usertextinput").value = "";
    poll_interval = short_poll_interval;
    poll_acc = poll_acc_ticks;
    clearTimeout(poll_timer);
    poll_timer = setTimeout("do_poll()", poll_interval);
  }
}

// Post check-for-update request to the server.  Switch to the slow polling rate if there has been
// no user input recently.

function do_poll()
{
  document.title = channel;
  clearTimeout(poll_timer);

  var ajax=new Request({ url: "fetchrows", onSuccess: function(responseText, responseXML) { fetched_rows(responseText) } });
  ajax.post("channel="+channel+"&user="+user+"&from="+latest_row+"&back="+max_extent);

  if(poll_acc > 0)
  {
    poll_interval = short_poll_interval;
    poll_acc --;
  }
  else
  {
    poll_interval = long_poll_interval;
  }

  poll_timer = setTimeout("do_poll()", poll_interval);
}

// Render the channel view page structure and initiate polling.

function init_channel()
{
  latest_row = -1;
  document.title = channel;
  highlight = true;

  $("area51").innerHTML  = "
"+user+" - switch user - search
";
  $("area51").innerHTML += "
"+channel+"
";
  $("area51").innerHTML += "
<input class=\"usertextinputcss\" type=\"text\" id=\"usertextinput\" onkeyup=\"enter_usertext(event);\">
";
  $("area51").innerHTML += "

";

  do_poll();
}

// Render the search page and prompt for a search term.

function go_to_search()
{
  clearTimeout(poll_timer);

  $("area51").innerHTML  = "
Search in \""+channel+"\" for:
";
  $("area51").innerHTML += "
<input class=\"usertextinputcss\" type=\"text\" id=\"asearch\" onkeyup=\"enter_search(event);\">
";
  $("area51").innerHTML += "
return to channel
";
  $("area51").innerHTML += "

";
}

// Update the "user" cookie and re-initialise with a new user name after switching user.

function change_user()
{
  user = "";
  latest_row = -1;
  Cookie.write('user', user, { duration: 365 });
  initialise();
}

// Render the channel text event list, or search result list.

function fetched_rows(responseText)
{
  var obj = JSON.decode(responseText);

  if(obj.status == "ok")
  {
    if(highlight && latest_row != obj.latest && latest_row > -1)
    {
      document.title = "********";
    }

    latest_row = obj.latest;

    for(var i = 0; i < obj.rows.length; i ++)
    {
      var tm = obj.rows[i].time;
      var us = obj.rows[i].user;
      var tx = obj.rows[i].text;

      $("textlist").innerHTML = "
"+tm+" "+us+" :

"+tx+"
" + $("textlist").innerHTML;
    }
  }
}
<commit_msg>JS now works with IE<commit_after>// atc872.js - Part of the ATC872 project which delivers a low-maintenance online
//             chat forum service.
//
// Copyright (c) 2013, Chris Bristow
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The views and conclusions contained in the software and documentation are those
// of the authors and should not be interpreted as representing official policies,
// either expressed or implied, of the FreeBSD Project.

// Globals.

var user = "";
var channel = "";
var latest_row = -1;
var poll_timer = null;
var short_poll_interval = 2000;
var long_poll_interval = 10000;
var poll_interval = long_poll_interval;
var poll_acc = 0;
var poll_acc_ticks = 15;
var max_extent = 200;
var highlight = false

// This runs when the page has fully loaded.  The channel is collected from
// the URL and control passed to the initialisation function.

window.addEvent('domready', function()
{
  channel = decodeURIComponent((location.search).replace("?channel=", ""));
  initialise();
});

// If there is a "user" cookie set, jump straight into the channel, otherwise prompt
// for a username.  Also, displays an error if the page is loaded without a channel
// specified.

function initialise()
{
  clearTimeout(poll_timer);

  if(channel.length == 0)
  {
    $("area51").innerHTML = "Error: No channel specified !!";
  }
  else
  {
    user = Cookie.read("user");

    if(user == null || user.length == 0)
    {
      $("area51").innerHTML  = "
Enter your name here:
";
      $("area51").innerHTML += "
<input class=\"usertextinputcss\" type=\"text\" id=\"auser\" onkeyup=\"enter_userid(event);\">
";
    }
    else
    {
      init_channel();
    }
  }
}

// Verify that the user name entered conforms, then jump to the channel view.

function enter_userid(event)
{
  if(event.keyCode == 13 && $("auser").value.length > 1 && $("auser").value.length < 100 && /\S+/.test($("auser").value))
  {
    user = $("auser").value;
    Cookie.write('user', user, { duration: 365 });
    init_channel();
  }
}

// Verify that an entered search term is valid, then post a search request to the server.

function enter_search(event)
{
  if(event.keyCode == 13 && $("asearch").value.length > 1 && /\S+/.test($("asearch").value))
  {
    $("textlist").innerHTML = "";
    highlight = false;

    var ajax=new Request({ url: "searchrows", onSuccess: function(responseText, responseXML) { fetched_rows(responseText) } });
    ajax.post("channel="+channel+"&back="+max_extent+"&pattern="+$("asearch").value);
  }
}

// Verify that a text line is valid, post it to the server and re-start polling (at the fast rate).

function enter_usertext(event)
{
  if(event.keyCode == 13 && $("usertextinput").value.length > 0 && /\S+/.test($("usertextinput").value))
  {
    var ajax=new Request({ url: "addrow", onSuccess: function(responseText, responseXML) { fetched_rows(responseText) } });
    ajax.post("channel="+channel+"&user="+user+"&text="+encodeURIComponent($("usertextinput").value)+"&from="+latest_row+"&back="+max_extent);

    $("usertextinput").value = "";
    poll_interval = short_poll_interval;
    poll_acc = poll_acc_ticks;
    clearTimeout(poll_timer);
    poll_timer = setTimeout("do_poll()", poll_interval);
  }
}

// Post check-for-update request to the server.  Switch to the slow polling rate if there has been
// no user input recently.

function do_poll()
{
  document.title = channel;
  clearTimeout(poll_timer);

  var ajax=new Request({ url: "fetchrows", onSuccess: function(responseText, responseXML) { fetched_rows(responseText) } });
  ajax.post("channel="+channel+"&user="+user+"&from="+latest_row+"&back="+max_extent);

  if(poll_acc > 0)
  {
    poll_interval = short_poll_interval;
    poll_acc --;
  }
  else
  {
    poll_interval = long_poll_interval;
  }

  poll_timer = setTimeout("do_poll()", poll_interval);
}

// Render the channel view page structure and initiate polling.

function init_channel()
{
  latest_row = -1;
  document.title = channel;
  highlight = true;

  $("area51").innerHTML  = "
"+user+" - switch user - search
";
  $("area51").innerHTML += "
"+channel+"
";
  $("area51").innerHTML += "
<input class=\"usertextinputcss\" type=\"text\" id=\"usertextinput\" onkeyup=\"enter_usertext(event);\">
";
  $("area51").innerHTML += "

";

  do_poll();
}

// Render the search page and prompt for a search term.

function go_to_search()
{
  clearTimeout(poll_timer);

  $("area51").innerHTML  = "
Search in \""+channel+"\" for:
";
  $("area51").innerHTML += "
<input class=\"usertextinputcss\" type=\"text\" id=\"asearch\" onkeyup=\"enter_search(event);\">
";
  $("area51").innerHTML += "
return to channel
";
  $("area51").innerHTML += "

";
}

// Update the "user" cookie and re-initialise with a new user name after switching user.

function change_user()
{
  user = "";
  latest_row = -1;
  Cookie.write('user', user, { duration: 365 });
  initialise();
}

// Render the channel text event list, or search result list.

function fetched_rows(responseText)
{
  var obj = JSON.decode(responseText);

  if(obj.status == "ok")
  {
    if(highlight && latest_row != obj.latest && latest_row > -1)
    {
      document.title = "********";
    }

    latest_row = obj.latest;

    for(var i = 0; i < obj.rows.length; i ++)
    {
      var tm = obj.rows[i].time;
      var us = obj.rows[i].user;
      var tx = obj.rows[i].text;

      $("textlist").innerHTML = "

"+tm+" "+us+" :

"+tx+"
" + $("textlist").innerHTML;
    }
  }
}
<|endoftext|>


<commit_before>'use strict';

var domify = require('domify');
var _template = require('lodash.template');
var matcher = require('template-matcher');
var _uniq = require('lodash.uniq');

module.exports = function bindling(template, model) {

	var dom = (typeof template === 'object') ? template : domify(template);

	var watchers = {};

	if (!model)
	{
		return dom;
	}

	var elements = dom.querySelectorAll('*');

	Array.prototype.forEach.call(elements, function(element) {

		Array.prototype.forEach.call(element.childNodes, function(node) {
			if (node.nodeType === 3)
			{
				parse(watchers, element, null, node, node.nodeValue, model);
			}
		});

		Array.prototype.forEach.call(element.attributes, function(attr) {
			parse(watchers, element, attr.name, null, attr.value, model);
		});
	});

	Object.observe(model, function(changes) {
		onChanges(watchers, changes);
	}, ['update']);

	return dom;
};

/* PRIVATE */

function parse(watchers, element, attrName, textNode, value, model)
{
	if (attrName && attrName.substr(0,3) === 'on-')
	{
		return addListener(element, attrName, value, model);
	}

	if (value.indexOf('{') === -1 )
	{
		return;
	}

	var paramCount = params(value).length;

	var watch = {
		element: element,
		attrName: attrName,
		textNode: textNode,
		renderer: paramCount === 1 ? bindFactory(params(value)) : _template(value)
	};

	render(watch, model);

	params(value).forEach(function(param) {
		var watcher = watchers[param];

		if (!watcher)
		{
			watcher = watchers[param] = [];
		}

		watcher.push(watch);
	});
}

function onChanges(watchers, changes)
{
	changes.forEach(function(change) {
		var watcher = watchers[change.name];

		if (!watcher)
		{
			return;
		}

		watcher.forEach(function(watch) {
			render(watch, change.object);
		});
	});
}

function render(watch, model)
{
	var content = watch.renderer(model);

	if (watch.attrName && watch.element.getAttribute(watch.attrName) !== content)
	{
		watch.element[watch.attrName] = content;
	}
	else if (watch.textNode && watch.textNode.nodeValue !== content)
	{
		watch.textNode.nodeValue = content;
	}
}

function params(value)
{
	return _uniq(matcher(value));
}

function addListener(element, attrName, value, model)
{
	var event = attrName.substring(3).toLowerCase();

	var open = value.indexOf('(');
	var functionName = value.substring(0, open);

	var argStr = value.substring(open+1, value.indexOf(')'));
	var args = argStr.split(',');

	element.removeAttribute(attrName);

	element.addEventListener(event, function onEvent(event) {

		var argValues = [];

		args.forEach(function(arg){
			if (arg)
			{
				if (arg.substr(0, 5) === 'this.')
				{
					argValues.push( element[arg.substring(5)] );
				}
				else
				{
					argValues.push( eval(arg) );
				}
			}
		});
		argValues.push(event);

		model[functionName].apply(model, argValues);
	});
}

function bindFactory(value)
{
	return function (model) {
		if (model[value] !== undefined)
		{
			return model[value];
		}
		else
		{
			return null;
		}
	};
}<commit_msg>Null checks for IE<commit_after>'use strict';

var domify = require('domify');
var _template = require('lodash.template');
var matcher = require('template-matcher');
var _uniq = require('lodash.uniq');

module.exports = function bindling(template, model) {

	var dom = (typeof template === 'object') ? template : domify(template);

	var watchers = {};

	if (!model)
	{
		return dom;
	}

	var elements = dom.querySelectorAll('*');

	Array.prototype.forEach.call(elements, function(element) {

		Array.prototype.forEach.call(element.childNodes, function(node) {
			if (node && node.nodeType === 3)
			{
				parse(watchers, element, null, node, node.nodeValue, model);
			}
		});

		Array.prototype.forEach.call(element.attributes, function(attr) {
			if (attr)
			{
				parse(watchers, element, attr.name, null, attr.value, model);
			}
		});
	});

	Object.observe(model, function(changes) {
		onChanges(watchers, changes);
	}, ['update']);

	return dom;
};

/* PRIVATE */

function parse(watchers, element, attrName, textNode, value, model)
{
	if (attrName && attrName.substr(0,3) === 'on-')
	{
		return addListener(element, attrName, value, model);
	}

	if (value.indexOf('{') === -1 )
	{
		return;
	}

	var paramCount = params(value).length;

	var watch = {
		element: element,
		attrName: attrName,
		textNode: textNode,
		renderer: paramCount === 1 ? bindFactory(params(value)) : _template(value)
	};

	render(watch, model);

	params(value).forEach(function(param) {
		var watcher = watchers[param];

		if (!watcher)
		{
			watcher = watchers[param] = [];
		}

		watcher.push(watch);
	});
}

function onChanges(watchers, changes)
{
	changes.forEach(function(change) {
		var watcher = watchers[change.name];

		if (!watcher)
		{
			return;
		}

		watcher.forEach(function(watch) {
			render(watch, change.object);
		});
	});
}

function render(watch, model)
{
	var content = watch.renderer(model);

	if (watch.attrName && watch.element.getAttribute(watch.attrName) !== content)
	{
		watch.element[watch.attrName] = content;
	}
	else if (watch.textNode && watch.textNode.nodeValue !== content)
	{
		watch.textNode.nodeValue = content;
	}
}

function params(value)
{
	return _uniq(matcher(value));
}

function addListener(element, attrName, value, model)
{
	var event = attrName.substring(3).toLowerCase();

	var open = value.indexOf('(');
	var functionName = value.substring(0, open);

	var argStr = value.substring(open+1, value.indexOf(')'));
	var args = argStr.split(',');

	element.removeAttribute(attrName);

	element.addEventListener(event, function onEvent(event) {

		var argValues = [];

		args.forEach(function(arg){
			if (arg)
			{
				if (arg.substr(0, 5) === 'this.')
				{
					argValues.push( element[arg.substring(5)] );
				}
				else
				{
					argValues.push( eval(arg) );
				}
			}
		});
		argValues.push(event);

		model[functionName].apply(model, argValues);
	});
}

function bindFactory(value)
{
	return function (model) {
		if (model[value] !== undefined)
		{
			return model[value];
		}
		else
		{
			return null;
		}
	};
}<|endoftext|>


<commit_before>const fs = require("fs");

//input file is of the format:

const TEST_INPUT = [{
  title: "Page 1 Text",
  subtitle: "The First Page",
  text: "asfdsadfasdfasdfadsfasf",
  sort: ["aug", "1"]
}, {
  title: "Page 2",
  subtitle: "Second",
  text: "asdf",
  sort: ["aug", "0"]
}, {
  title: "3",
  subtitle: "3",
  text: "3",
  sort: ["aff", "2"]
}];

//config: sort order
const SORTORDER = ["int", "aug", "aff", "0", "1", "2", "3"];

//sorting stuff

function strcmp(str1, str2) {
  return ((str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1));
}

//loading

function loadBook(path) {
  let book = JSON.parse(fs.readFileSync(path).toString("utf-8"));
  //assert book.isArray();
  //this is where I would put my assert statement. IF I HAD ONE
  return book;
}

//object

function Book(loadPath, sorter) {
  this.book = loadBook(loadPath);
  this.sorter = sorter;
  this.sortEntryOrders();
  this.book.sort(this.comparePage);
}

//.compareTo functions for symbols and pages in Book

//compares two symbols using the list of symbols in this.sorter
//if s1 comes before s2, return -1
//if s1 == s2, return 0
//if s2 comes before s1, return 1
Book.prototype.compareSymbol = function(s1, s2) {
  if (s1 === s2) return 0;
  for (let i = 0; i < SORTORDER.length; i++) {
    let curr = SORTORDER[i];
    if (s1 === curr) return -1;
    if (s2 === curr) return 1;
  }
  return null; //ya fucked up
};

function compareSymbol(s1, s2) {
  if (s1 === s2) return 0;
  for (let i = 0; i < SORTORDER.length; i++) {
    let curr = SORTORDER[i];
    if (s1 === curr) return -1;
    if (s2 === curr) return 1;
  }
  return null; //ya fucked up
};

//Assumes the symbols in p1.sort and p2.sort are in order specified by this.sorter
Book.prototype.comparePage = function(p1, p2) {
  for (let i = 0; i < p1.sort.length && i < p2.sort.length; i++) {
    let compval = compareSymbol(p1.sort[i], p2.sort[i]);
    if (compval !== 0) return compval;
  }
  if (p1.sort.length == p2.sort.length) {//they are the same
    return strcmp(p1.title, p2.title);
  }
  else return (p1.sort.length < p2.sort.length ? -1 : 1);
};

//Go through every page in the book and make sure its .sort is in the correct order.
Book.prototype.sortEntryOrders = function() {
  for (let i = 0; i < this.book.length; i++) {
    this.book[i].sort.sort(this.compareSymbol);
  }
};

Book.prototype.getPageByNum = function(num) {
  return this.book[num + 1];
};

Book.prototype.getPageByName = function(name) {
  for (let i = 0; i < this.book.length; i++) {
    if (this.book[i].title.toLowerCase() === name.toLowerCase()) {
      return this.book[i];
    }
  }
  return null;
};

//display

Book.prototype.pageToPretty = function(page) {
  let ret = "\n";
  ret += "**" + page.title + "**\n";
  if (page.subtitle !== "") ret += "*" + page.subtitle + "*\n";
  ret += page.text;
  ret += "";
  return ret;
};

function pad(toPad, bigNum) {
  let length = Math.floor(Math.log10(bigNum) + 1);
  let plen = Math.floor(Math.log10(toPad) + 1);
  return " ".repeat(length - plen) + toPad;
}

Book.prototype.tableofcontents = function() {
  let ret = "**Table of Contents**\n```"
  for (let i = 0; i < this.book.length; i++) {
    ret += "" + pad(i + 1, this.book.length) + " " + this.book[i].title + "\n";
  }
  ret += "```";
  return ret;
};

module.exports = {
  Book
};<commit_msg>fixed off by 2 error<commit_after>const fs = require("fs");

//input file is of the format:

const TEST_INPUT = [{
  title: "Page 1 Text",
  subtitle: "The First Page",
  text: "asfdsadfasdfasdfadsfasf",
  sort: ["aug", "1"]
}, {
  title: "Page 2",
  subtitle: "Second",
  text: "asdf",
  sort: ["aug", "0"]
}, {
  title: "3",
  subtitle: "3",
  text: "3",
  sort: ["aff", "2"]
}];

//config: sort order
const SORTORDER = ["int", "aug", "aff", "0", "1", "2", "3"];

//sorting stuff

function strcmp(str1, str2) {
  return ((str1 == str2) ? 0 : ((str1 > str2) ? 1 : -1));
}

//loading

function loadBook(path) {
  let book = JSON.parse(fs.readFileSync(path).toString("utf-8"));
  //assert book.isArray();
  //this is where I would put my assert statement. IF I HAD ONE
  return book;
}

//object

function Book(loadPath, sorter) {
  this.book = loadBook(loadPath);
  this.sorter = sorter;
  this.sortEntryOrders();
  this.book.sort(this.comparePage);
}

//.compareTo functions for symbols and pages in Book

//compares two symbols using the list of symbols in this.sorter
//if s1 comes before s2, return -1
//if s1 == s2, return 0
//if s2 comes before s1, return 1
Book.prototype.compareSymbol = function(s1, s2) {
  if (s1 === s2) return 0;
  for (let i = 0; i < SORTORDER.length; i++) {
    let curr = SORTORDER[i];
    if (s1 === curr) return -1;
    if (s2 === curr) return 1;
  }
  return null; //ya fucked up
};

function compareSymbol(s1, s2) {
  if (s1 === s2) return 0;
  for (let i = 0; i < SORTORDER.length; i++) {
    let curr = SORTORDER[i];
    if (s1 === curr) return -1;
    if (s2 === curr) return 1;
  }
  return null; //ya fucked up
};

//Assumes the symbols in p1.sort and p2.sort are in order specified by this.sorter
Book.prototype.comparePage = function(p1, p2) {
  for (let i = 0; i < p1.sort.length && i < p2.sort.length; i++) {
    let compval = compareSymbol(p1.sort[i], p2.sort[i]);
    if (compval !== 0) return compval;
  }
  if (p1.sort.length == p2.sort.length) {//they are the same
    return strcmp(p1.title, p2.title);
  }
  else return (p1.sort.length < p2.sort.length ? -1 : 1);
};

//Go through every page in the book and make sure its .sort is in the correct order.
Book.prototype.sortEntryOrders = function() {
  for (let i = 0; i < this.book.length; i++) {
    this.book[i].sort.sort(this.compareSymbol);
  }
};

Book.prototype.getPageByNum = function(num) {
  return this.book[num - 1];
};

Book.prototype.getPageByName = function(name) {
  for (let i = 0; i < this.book.length; i++) {
    if (this.book[i].title.toLowerCase() === name.toLowerCase()) {
      return this.book[i];
    }
  }
  return null;
};

//display

Book.prototype.pageToPretty = function(page) {
  let ret = "\n";
  ret += "**" + page.title + "**\n";
  if (page.subtitle !== "") ret += "*" + page.subtitle + "*\n";
  ret += page.text;
  ret += "";
  return ret;
};

function pad(toPad, bigNum) {
  let length = Math.floor(Math.log10(bigNum) + 1);
  let plen = Math.floor(Math.log10(toPad) + 1);
  return " ".repeat(length - plen) + toPad;
}

Book.prototype.tableofcontents = function() {
  let ret = "**Table of Contents**\n```"
  for (let i = 0; i < this.book.length; i++) {
    ret += "" + pad(i + 1, this.book.length) + " " + this.book[i].title + "\n";
  }
  ret += "```";
  return ret;
};

module.exports = {
  Book
};<|endoftext|>