<commit_before>
// SmoothScroll v0.8.6
// Licensed under the terms of the MIT license.

// People involved
// - Balazs Galambosi: maintainer (CHANGELOG.txt)
// - Patrick Brunner (patrickb1991@gmail.com)
// - Michael Herf: Pulse Algorithm
// - Frank Yan: Direction Switching Fixes
// - Ismael Barros: Keyboard Fixes

(function(window){

// Frame Variables
var frame = false;
var noscrollframe = false;
var lastYOffset = 0;

// Scroll Variables (tweakables)
var framerate = 50;  // [Hz]
var animtime  = 400; // [px]
var scrollsz  = 120; // [px]

// Pulse (less tweakables)
// ratio of 'tail' to 'acceleration'
var pulseAlgorithm = true;
var pulseScale     = 8;
var pulseNormalize = 1;

// Keyboard Settings
var keyboardsupport = true;
var arrscroll = 50;  // [px]
var pgscroll  = 800; // [px] unused
var exclude   = "";

// Arrays of timeouts
var up   = [];
var down = [];

// Other Variables
var scrolls;
var lastScrollTop = 1337; // 1337??
var delta    = 0;
var initdone = false;
var disableKeyboard = false;

/***********************************************
 * SETTINGS
 ***********************************************/

var port = chrome.extension.connect({
    name: "smoothscroll"
});
port.onMessage.addListener(function (settings) {

    // NOTE: + converts to {Number}
    framerate = +settings.framerate;
    animtime  = +settings.animtime;
    scrollsz  = +settings.scrollsz;

    pulseAlgorithm = (settings.pulseAlgorithm == "true");
    pulseScale     = +settings.pulseScale;
    pulseNormalize = +settings.pulseNormalize;

    keyboardsupport = (settings.keyboardsupport == "true");
    arrscroll = +settings.arrscroll;
    //pgscroll  = +settings.pgscroll;
    exclude   = settings.exclude;

    scrolls = setupScrolls();
    computePulseScale();

    // it seems that sometimes settings come late
    // and we need to test again for excluded pages
    initTest();

    if (keyboardsupport && !disableKeyboard) {
        document.onkeydown = keydown;
    }

    // If extension settings were deleted somehow
    if (!framerate) {
        alert("SmoothScroll: Please restart Chrome");
    }
});

/***********************************************
 * INITIALIZE
 ***********************************************/

/**
 * Tests if smooth scrolling is allowed. Shuts down everything if not.
 */
function initTest() {
    var embed = document.getElementsByTagName('embed')[0];
    if (embed && embed.type === "application/pdf") {
        window.onmousewheel = null;
        disableKeyboard = true;
    } else if (document.URL.indexOf("google.com/reader/view") > -1) {
        disableKeyboard = true;
    } else if (exclude) {
        var domains = exclude.split(/[,\n] ?/);
        for (var i = domains.length; i--;) {
            if (document.URL.indexOf(domains[i]) > -1) {
                window.onmousewheel = null;
                disableKeyboard = true;
                break;
            }
        }
    }

    if (disableKeyboard) {
        document.onkeydown = null;
    }
}

/**
 * Fills up the scrolls array with easing values.
 * Uses pulse to make it smooth.
 */
function setupScrolls() {

    scrolls = [];

    var last = 0;
    var frames = Math.floor(framerate * animtime / 1000);

    for (var i = 0; i < frames; i++) {
        // scroll is [0, 1]
        var scroll = (i + 1) / frames;
        // transform [0, 1] -> [0, 1]:
        if (pulseAlgorithm) {
           scroll = pulse(scroll);
        }

        // scale and quantize to int so our pixel difference works:
        var iscroll = Math.floor(scrollsz * scroll + 0.99);
        scrolls.push(iscroll - last);
        last = iscroll;
    }

    return scrolls;
}

/**
 * Sets up scrolls array, determines if frames are involved.
 */
function init() {

    var body = document.body;

    initTest();

    if (!scrolls) {
      scrolls = setupScrolls();
    }

    // Checks if this script is running in a frame
    if (top != self) {
        frame = true;
        // document.documentElement ?
        if (body.scrollHeight <= body.clientHeight + 10) {
            noscrollframe = true;
        }
    }

    /**
     * This fixes a bug where the areas left and right
     * to the content does not trigger the onmousewheel
     * event on some pages. Acid3 test is excluded.
     */
    if (document.URL !== "http://acid3.acidtests.org/") {
        var underlay = document.createElement('div');
        underlay.setAttribute( "style",
            "z-index: -1; position:absolute; top:0; left: 0; " +
            "width: 100%; height: " + body.scrollHeight + "px;" );
        body.appendChild(underlay);
    }
    initdone = true;
}

/***********************************************
 * EVENTS
 ***********************************************/

/**
 * Mouse wheel handler.
 * NOTE: function logic should be decomposed.
 * @param {Object} event
 */
function wheel(event) {

    if (!initdone) {
        init();
    }

    var scroll = true;
    var prevent = false;
    var scrollup = true;
    var scrolldown = true;
    var lastdelta = delta;
    var i, overflow, delay, elem, dir;

    delta = event.wheelDelta || 0;

    // normalize delta
    if (delta) {
        ///simple: delta /= Math.abs(delta);
        delta /= 120;
        // synaptics seems to send 1 sometimes,
        // and 120 other times (fix)
        if (Math.abs(delta) < 0.01) {
            delta *= 120;
        }
    }

    dir = (delta > 0) ? up : down;
    elem = overflowingAncestor(event.target);

    if (!elem) {
        return true;
    }

    if (elem === document.body) {
        scroll = true;
    } else { // other overflowing element
        prevent = true;
        if (elem.scrollTop === lastScrollTop) {
            if (elem.scrollTop === 0) {
                scrollup   = true;
                scrolldown = false;
            } else {
                scrolldown = true;
                scrollup   = false;
            }
        } else {
            scroll = false;
        }
        lastScrollTop = elem.scrollTop;
        scrollElement(elem, delta, 1); // Fixes a bug
        clearTimeouts(dir === up ? down : up);
        for (i = 0; i < 10; i++) {
            delay = i * 1000 / framerate + 1;
            dir.push(setTimeout(function() {
                scrollElement(elem, delta, 10);
            }, delay));
        }
    }

    if (frame) {
        if (noscrollframe) {
            scroll = false;
        } else {
            // the last scroll did nothing
            if (lastYOffset === window.pageYOffset) {
                // scrolling downwards did nothing
                if (lastdelta < 0) {
                    scrollup   = true;
                    scrolldown = false;
                }
                // scrolling upwards did nothing
                else if (lastdelta > 0) {
                    scrollup   = false;
                    scrolldown = true;
                }
            }
            lastYOffset = window.pageYOffset;
        }
    }
    if (scroll) {
        if ((scrolldown && delta < 0) || (scrollup && delta > 0)) {
            scrollArray(dir, -delta);
            event.preventDefault();
        }
    }
    // Prevention for scrollable html elements
    if (prevent) {
        event.preventDefault();
    }

    //Debug
    //console.log("scrollup "+scrollup);
    //console.log("scrolldown "+scrolldown);
    //console.log("scroll "+scroll);
    //console.log("frame "+frame);
    //console.log("prevent "+prevent);
    //console.log("noscrframe "+noscrollframe);
    //console.log(document.documentElement.scrollHeight);
    //console.log(document.documentElement.clientHeight+10);
}

/**
 * Keydown event handler.
 * @param {Object} event
 */
function keydown(event) {

    var keyCode  = event.keyCode;
    var target   = event.target;
    var modifier = event.ctrlKey || event.altKey || event.metaKey;

    // do nothing if user is editing text
    // or using a modifier key (except shift)
    if ( isNodeName(target, "input")    ||
         isNodeName(target, "textarea") ||
         target.isContentEditable       ||
         modifier ) {
      return true;
    }

    var shift = (event.shiftKey ? 1 : -1);
    var keys = {
        38 : [ arrowScroll,        1   ], // up arrow
        40 : [ arrowScroll,       -1   ], // down arrow
        32 : [ pageScroll,       shift ], // spacebar (+ shift)
        33 : [ pageScroll,         1   ], // page up
        34 : [ pageScroll,        -1   ], // page down
        35 : [ scrollToBottom,  target ], // end
        36 : [ scrollToTop,     target ]  // home
    };
    if (keys[keyCode]) {
        keys[keyCode][0]( keys[keyCode][1] );
        event.preventDefault();
    }
}

/***********************************************
 * HELPERS
 ***********************************************/

function isNodeName(el, tag) {
    return el.nodeName.toLowerCase() === tag.toLowerCase();
}

function clearTimeouts(array) {
    while (array.length) {
        clearTimeout(array.pop());
    }
}

function overflowingAncestor(el) {
    var bodyScrollHeight = document.body.scrollHeight;
    do {
        if (bodyScrollHeight === el.scrollHeight) {
            return document.body;
        }
        else if (el.clientHeight + 10 < el.scrollHeight) {
            overflow = getComputedStyle(el, "").getPropertyValue("overflow");
            if (overflow === "scroll" || overflow === "auto") {
                return el;
            }
        }
    } while (el = el.parentNode);
}

/***********************************************
 * PULSE
 ***********************************************/

/**
 * Viscous fluid with a pulse for part and decay for the rest.
 * - Applies a fixed force over an interval (a damped acceleration), and
 * - Lets the exponential bleed away the velocity over a longer interval
 * - Michael Herf, http://stereopsis.com/stopping/
 */
function pulse_(x) {
    var val, start, expx;
    // test
    x = x * pulseScale;
    if (x < 1) {
        val = x - (1 - Math.exp(-x));
    } else {
        // the previous animation ended here:
        start = Math.exp(-1);
        // simple viscous drag
        x -= 1;
        expx = 1 - Math.exp(-x);
        val = start + (expx * (1 - start));
    }
    return val * pulseNormalize;
}

function computePulseScale() {
    pulseNormalize = 1 / pulse_(1);
}

/**
 * Viscous fluid with a pulse for part and decay for the rest
 */
function pulse(x) {
    if (x >= 1) return 1;
    if (x <= 0) return 0;

    if (pulseNormalize == 1) {
        computePulseScale();
    }
    return pulse_(x);
}

/************************************************
 * SCROLLING
 ************************************************/

/**
 * Scrolls an element by a given amount.
 */
function scrollElement(el, delta, amount) {
    if (delta > 0) {
        el.scrollTop -= amount;
    } else {
        el.scrollTop += amount;
    }
}

/**
 * Pushes scroll actions to a given direction Array.
 */
function scrollArray(dir, multiply, delay) {
    delay || (delay = 1000);
    clearTimeouts(dir === up ? down : up);
    function step() {
        window.scrollBy( 0 , multiply * scrolls[i++] );
    }
    for (var i = scrolls.length; i--;) {
        dir.push(setTimeout(step, i * delay / framerate + 1));
    }
    i = 0; // reset so that step() can increment again
}

/**
 * Scrolls the window according to a given delta.
 */
function arrowScroll(delta) {
    var scale = arrscroll / scrollsz;
    var dir = (delta > 0) ? up : down;
    scrollArray(dir, -delta*scale, 500);
}

/**
 * Scrolls the element for one Page Up/Down
 */
function pageScroll(delta) {
    var winScale = window.innerHeight / scrollsz;
    var dir = (delta > 0) ? up : down;
    scrollArray(dir, -delta*winScale);
}

/**
 * Scrolls an element to the absolute top.
 */
function scrollToTop(src) {
    var upamt = src.scrollTop;
    var winScale = upamt / scrollsz;
    if (!upamt) {
      return;
    }
    scrollArray(up, -winScale);
}

/**
 * Scrolls an element to the absolute bottom.
 */
function scrollToBottom(src) {
    var damt = src.scrollHeight - src.scrollTop - window.innerHeight;
    var winScale = damt / scrollsz;
    if (damt <= 0) {
      return;
    }
    scrollArray(down, winScale);
}

window.addEventListener("mousewheel", wheel, false);
window.addEventListener("DOMContentLoaded", init, false);

})(window);
<commit_msg>changed key handling again. it's conditionally structured without function calls. it's easier to manage now.<commit_after>
// SmoothScroll v0.8.6
// Licensed under the terms of the MIT license.

// People involved
// - Balazs Galambosi: maintainer (CHANGELOG.txt)
// - Patrick Brunner (patrickb1991@gmail.com)
// - Michael Herf: Pulse Algorithm
// - Frank Yan: Direction Switching Fixes
// - Ismael Barros: Keyboard Fixes

(function(window){

// Frame Variables
var frame = false;
var noscrollframe = false;
var lastYOffset = 0;

// Scroll Variables (tweakables)
var framerate = 50;  // [Hz]
var animtime  = 400; // [px]
var scrollsz  = 120; // [px]

// Pulse (less tweakables)
// ratio of 'tail' to 'acceleration'
var pulseAlgorithm = true;
var pulseScale     = 8;
var pulseNormalize = 1;

// Keyboard Settings
var keyboardsupport = true;
var arrscroll = 50;  // [px]
var pgscroll  = 800; // [px] unused
var exclude   = "";

// Arrays of timeouts
var up   = [];
var down = [];

// Other Variables
var scrolls;
var lastScrollTop = 1337; // 1337??
var delta    = 0;
var initdone = false;
var disableKeyboard = false;

/***********************************************
 * SETTINGS
 ***********************************************/

var port = chrome.extension.connect({
    name: "smoothscroll"
});
port.onMessage.addListener(function (settings) {

    // NOTE: + converts to {Number}
    framerate = +settings.framerate;
    animtime  = +settings.animtime;
    scrollsz  = +settings.scrollsz;

    pulseAlgorithm = (settings.pulseAlgorithm == "true");
    pulseScale     = +settings.pulseScale;
    pulseNormalize = +settings.pulseNormalize;

    keyboardsupport = (settings.keyboardsupport == "true");
    arrscroll = +settings.arrscroll;
    //pgscroll  = +settings.pgscroll;
    exclude   = settings.exclude;

    scrolls = setupScrolls();
    computePulseScale();

    // it seems that sometimes settings come late
    // and we need to test again for excluded pages
    initTest();

    if (keyboardsupport && !disableKeyboard) {
        document.onkeydown = keydown;
    }

    // If extension settings were deleted somehow
    if (!framerate) {
        alert("SmoothScroll: Please restart Chrome");
    }
});

/***********************************************
 * INITIALIZE
 ***********************************************/

/**
 * Tests if smooth scrolling is allowed. Shuts down everything if not.
 */
function initTest() {
    var embed = document.getElementsByTagName('embed')[0];
    if (embed && embed.type === "application/pdf") {
        window.onmousewheel = null;
        disableKeyboard = true;
    } else if (document.URL.indexOf("google.com/reader/view") > -1) {
        disableKeyboard = true;
    } else if (exclude) {
        var domains = exclude.split(/[,\n] ?/);
        for (var i = domains.length; i--;) {
            if (document.URL.indexOf(domains[i]) > -1) {
                window.onmousewheel = null;
                disableKeyboard = true;
                break;
            }
        }
    }

    if (disableKeyboard) {
        document.onkeydown = null;
    }
}

/**
 * Fills up the scrolls array with easing values.
 * Uses pulse to make it smooth.
 */
function setupScrolls() {

    scrolls = [];

    var last = 0;
    var frames = Math.floor(framerate * animtime / 1000);

    for (var i = 0; i < frames; i++) {
        // scroll is [0, 1]
        var scroll = (i + 1) / frames;
        // transform [0, 1] -> [0, 1]:
        if (pulseAlgorithm) {
           scroll = pulse(scroll);
        }

        // scale and quantize to int so our pixel difference works:
        var iscroll = Math.floor(scrollsz * scroll + 0.99);
        scrolls.push(iscroll - last);
        last = iscroll;
    }

    return scrolls;
}

/**
 * Sets up scrolls array, determines if frames are involved.
 */
function init() {

    var body = document.body;

    initTest();

    if (!scrolls) {
      scrolls = setupScrolls();
    }

    // Checks if this script is running in a frame
    if (top != self) {
        frame = true;
        // document.documentElement ?
        if (body.scrollHeight <= body.clientHeight + 10) {
            noscrollframe = true;
        }
    }

    /**
     * This fixes a bug where the areas left and right
     * to the content does not trigger the onmousewheel
     * event on some pages. Acid3 test is excluded.
     */
    if (document.URL !== "http://acid3.acidtests.org/") {
        var underlay = document.createElement('div');
        underlay.setAttribute( "style",
            "z-index: -1; position:absolute; top:0; left: 0; " +
            "width: 100%; height: " + body.scrollHeight + "px;" );
        body.appendChild(underlay);
    }
    initdone = true;
}

/***********************************************
 * EVENTS
 ***********************************************/

/**
 * Mouse wheel handler.
 * NOTE: function logic should be decomposed.
 * @param {Object} event
 */
function wheel(event) {

    if (!initdone) {
        init();
    }

    var scroll = true;
    var prevent = false;
    var scrollup = true;
    var scrolldown = true;
    var lastdelta = delta;
    var i, overflow, delay, elem, dir;

    delta = event.wheelDelta || 0;

    // normalize delta
    if (delta) {
        ///simple: delta /= Math.abs(delta);
        delta /= 120;
        // synaptics seems to send 1 sometimes,
        // and 120 other times (fix)
        if (Math.abs(delta) < 0.01) {
            delta *= 120;
        }
    }

    dir = (delta > 0) ? up : down;
    elem = overflowingAncestor(event.target);

    if (!elem) {
        return true;
    }

    if (elem === document.body) {
        scroll = true;
    } else { // other overflowing element
        prevent = true;
        if (elem.scrollTop === lastScrollTop) {
            if (elem.scrollTop === 0) {
                scrollup   = true;
                scrolldown = false;
            } else {
                scrolldown = true;
                scrollup   = false;
            }
        } else {
            scroll = false;
        }
        lastScrollTop = elem.scrollTop;
        scrollElement(elem, delta, 1); // Fixes a bug
        clearTimeouts(dir === up ? down : up);
        for (i = 0; i < 10; i++) {
            delay = i * 1000 / framerate + 1;
            dir.push(setTimeout(function() {
                scrollElement(elem, delta, 10);
            }, delay));
        }
    }

    if (frame) {
        if (noscrollframe) {
            scroll = false;
        } else {
            // the last scroll did nothing
            if (lastYOffset === window.pageYOffset) {
                // scrolling downwards did nothing
                if (lastdelta < 0) {
                    scrollup   = true;
                    scrolldown = false;
                }
                // scrolling upwards did nothing
                else if (lastdelta > 0) {
                    scrollup   = false;
                    scrolldown = true;
                }
            }
            lastYOffset = window.pageYOffset;
        }
    }
    if (scroll) {
        if ((scrolldown && delta < 0) || (scrollup && delta > 0)) {
            scrollArray(dir, -delta);
            event.preventDefault();
        }
    }
    // Prevention for scrollable html elements
    if (prevent) {
        event.preventDefault();
    }

    //Debug
    //console.log("scrollup "+scrollup);
    //console.log("scrolldown "+scrolldown);
    //console.log("scroll "+scroll);
    //console.log("frame "+frame);
    //console.log("prevent "+prevent);
    //console.log("noscrframe "+noscrollframe);
    //console.log(document.documentElement.scrollHeight);
    //console.log(document.documentElement.clientHeight+10);
}

/**
 * Keydown event handler.
 * @param {Object} event
 */
function keydown(event) {

    var keyCode  = event.keyCode;
    var target   = event.target;
    var modifier = event.ctrlKey || event.altKey || event.metaKey;

    // do nothing if user is editing text
    // or using a modifier key (except shift)
    if ( isNodeName(target, "input")    ||
         isNodeName(target, "textarea") ||
         target.isContentEditable       ||
         modifier ) {
      return true;
    }

    var scale, dir, shift;

    if (keyCode === 38) {         // up arrow
        scale = -arrscroll;
        dir = up;
    } else if (keyCode === 40) {  // down arrow
        scale = arrscroll;
        dir = down;
    } else if (keyCode === 32) {  // spacebar (+ shift)
        shift = event.shiftKey ? 1 : -1;
        scale = -shift * window.innerHeight;
        dir = (shift > 0) ? up : down;
    } else if (keyCode === 33) {  // page up
        scale = -window.innerHeight;
        dir = up;
    } else if (keyCode === 34) {  // page down
        scale = window.innerHeight;
        dir = down;
    } else if (keyCode === 36) {  // home
        scale = -target.scrollTop;
        dir = up;
    } else if (keyCode === 35) {  // end
        var damt = target.scrollHeight - target.scrollTop - window.innerHeight;
        scale = (damt > 0) ? damt : 0;
        dir = down;
    } else {
        return true; // a key we don't care about
    }

    scrollArray(dir, scale / scrollsz, 1000);
    event.preventDefault();
}

/***********************************************
 * HELPERS
 ***********************************************/

function isNodeName(el, tag) {
    return el.nodeName.toLowerCase() === tag.toLowerCase();
}

function clearTimeouts(array) {
    while (array.length) {
        clearTimeout(array.pop());
    }
}

function overflowingAncestor(el) {
    var bodyScrollHeight = document.body.scrollHeight;
    do {
        if (bodyScrollHeight === el.scrollHeight) {
            return document.body;
        }
        else if (el.clientHeight + 10 < el.scrollHeight) {
            overflow = getComputedStyle(el, "").getPropertyValue("overflow");
            if (overflow === "scroll" || overflow === "auto") {
                return el;
            }
        }
    } while (el = el.parentNode);
}

/***********************************************
 * PULSE
 ***********************************************/

/**
 * Viscous fluid with a pulse for part and decay for the rest.
 * - Applies a fixed force over an interval (a damped acceleration), and
 * - Lets the exponential bleed away the velocity over a longer interval
 * - Michael Herf, http://stereopsis.com/stopping/
 */
function pulse_(x) {
    var val, start, expx;
    // test
    x = x * pulseScale;
    if (x < 1) {
        val = x - (1 - Math.exp(-x));
    } else {
        // the previous animation ended here:
        start = Math.exp(-1);
        // simple viscous drag
        x -= 1;
        expx = 1 - Math.exp(-x);
        val = start + (expx * (1 - start));
    }
    return val * pulseNormalize;
}

function computePulseScale() {
    pulseNormalize = 1 / pulse_(1);
}

/**
 * Viscous fluid with a pulse for part and decay for the rest
 */
function pulse(x) {
    if (x >= 1) return 1;
    if (x <= 0) return 0;

    if (pulseNormalize == 1) {
        computePulseScale();
    }
    return pulse_(x);
}

/************************************************
 * SCROLLING
 ************************************************/

/**
 * Scrolls an element by a given amount.
 */
function scrollElement(el, delta, amount) {
    if (delta > 0) {
        el.scrollTop -= amount;
    } else {
        el.scrollTop += amount;
    }
}

/**
 * Pushes scroll actions to a given direction Array.
 */
function scrollArray(dir, multiply, delay) {
    delay || (delay = 1000);
    clearTimeouts(dir === up ? down : up);
    function step() {
        window.scrollBy( 0 , multiply * scrolls[i++] );
    }
    for (var i = scrolls.length; i--;) {
        dir.push(setTimeout(step, i * delay / framerate + 1));
    }
    i = 0; // reset so that step() can increment again
}

window.addEventListener("mousewheel", wheel, false);
window.addEventListener("DOMContentLoaded", init, false);

})(window);
<|endoftext|>


<commit_before>/**
 * Alloy
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * See LICENSE for more information on licensing.
 */

exports.cliVersion = '>=3.X';

exports.init = function (logger, config, cli, appc) {

	var path = require('path'),
		afs = appc.fs,
		i18n = appc.i18n(__dirname),
		__ = i18n.__,
		__n = i18n.__n,
		pkginfo = appc.pkginfo.package(module),
		exec = require('child_process').exec,
		spawn = require('child_process').spawn,
		parallel = appc.async.parallel;

	cli.addHook('build.pre.compile', function (build, finished) {
		var appDir = path.join(cli.argv['project-dir'], 'app');
		if (!afs.exists(appDir)) {
			logger.info(__('Project not an Alloy app, continuing'));
			finished();
			return;
		}

		logger.info(__('Found Alloy app in %s', appDir.cyan));

		var compilerCommand = afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js'),
			config = {
				platform: cli.argv.platform,
				version: '0',
				simtype: 'none',
				devicefamily: /iphone|ios/.test(cli.argv.platform) ? build.deviceFamily : 'none',
				deploytype: build.deployType || cli.argv['deploy-type'] || 'development'
			};

		config = Object.keys(config).map(function (c) {
			return c + '=' + config[c];
		}).join(',');

		if (afs.exists(compilerCommand)) {
			// we're being invoked from the actual alloy directory!
			// no need to subprocess, just require() and run
			var origLimit = Error.stackTraceLimit;
			Error.stackTraceLimit = Infinity;
			try {
				require(compilerCommand)({}, {
					config: config,
					outputPath: cli.argv['project-dir'],
					_version: pkginfo.version,
				});
			} catch (e) {
				logger.error(__('Alloy compiler failed'));
				e.toString().split('\n').forEach(function (line) {
					line && logger.error(line);
				});
				process.exit(1);
			}
			Error.stackTraceLimit = origLimit;
			finished();
		} else {
			// we have no clue where alloy is installed, so we're going to subprocess
			// alloy and hope it's in the system path or a well known place
			var paths = {};
			parallel(this, ['alloy', 'node'].map(function (bin) {
				return function (done) {
					var envName = 'ALLOY_' + (bin == 'node' ? 'NODE_' : '') + 'PATH';
					if (paths[bin] = process.env[envName]) {
						done();
					} else if (process.platform == 'win32') {
						paths['alloy'] = 'alloy.cmd';
						done();
					} else {
						exec('which ' + bin, function (err, stdout, strerr) {
							if (!err) {
								paths[bin] = stdout.trim();
								done();
							} else {
								parallel(this, [
									'/usr/local/bin/' + bin,
									'/opt/local/bin/' + bin,
									path.join(process.env['HOME'], 'local/bin', bin),
									'/opt/bin/' + bin,
									'/usr/bin/' + bin
								].map(function (p) {
									return function (cb) {
										afs.exists(p) && (paths[bin] = p);
										cb();
									};
								}), done);
							}
						});
					}
				};
			}), function () {
				var cmd = [paths.node, paths.alloy, 'compile', appDir, '--config', config];
				cli.argv['no-colors'] && cmd.push('--no-colors');
				process.platform == 'win32' && cmd.shift();
				logger.info(__('Executing Alloy compile: %s', cmd.join(' ').cyan));

				var child = spawn(cmd.shift(), cmd);
					// this regex is used to strip [INFO] and friends from alloy's output and re-log it using our logger
					re = new RegExp('(\u001b\\[\\d+m)?\\[?(' + logger.getLevels().join('|') + ')\\]?\s*(\u001b\\[\\d+m)?(.*)', 'i');

				child.stdout.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						if (line) {
							var m = line.match(re);
							if (m) {
								logger[m[2].toLowerCase()](m[4].trim());
							} else {
								logger.debug(line);
							}
						}
					});
				});
				child.stderr.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						line && logger.error(line);
					});
				});
				child.on('exit', function (code) {
					if (code) {
						logger.error(__('Alloy compiler failed'));
						process.exit(1);
					} else {
						logger.info(__('Alloy compiler completed successfully'));
					}
					finished();
				});
			});
		}
	});

};
<commit_msg>fixed regexes for ios platform in hook<commit_after>/**
 * Alloy
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * See LICENSE for more information on licensing.
 */

exports.cliVersion = '>=3.X';

exports.init = function (logger, config, cli, appc) {

	var path = require('path'),
		afs = appc.fs,
		i18n = appc.i18n(__dirname),
		__ = i18n.__,
		__n = i18n.__n,
		pkginfo = appc.pkginfo.package(module),
		exec = require('child_process').exec,
		spawn = require('child_process').spawn,
		parallel = appc.async.parallel;

	cli.addHook('build.pre.compile', function (build, finished) {
		var appDir = path.join(cli.argv['project-dir'], 'app');
		if (!afs.exists(appDir)) {
			logger.info(__('Project not an Alloy app, continuing'));
			finished();
			return;
		}

		logger.info(__('Found Alloy app in %s', appDir.cyan));

		var compilerCommand = afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js'),
			config = {
				platform: /(?:iphone|ipad)/.test(cli.argv.platform) ? 'ios' : cli.argv.platform,
				version: '0',
				simtype: 'none',
				devicefamily: /(?:iphone|ios)/.test(cli.argv.platform) ? build.deviceFamily : 'none',
				deploytype: build.deployType || cli.argv['deploy-type'] || 'development'
			};

		config = Object.keys(config).map(function (c) {
			return c + '=' + config[c];
		}).join(',');

		if (afs.exists(compilerCommand)) {
			// we're being invoked from the actual alloy directory!
			// no need to subprocess, just require() and run
			var origLimit = Error.stackTraceLimit;
			Error.stackTraceLimit = Infinity;
			try {
				require(compilerCommand)({}, {
					config: config,
					outputPath: cli.argv['project-dir'],
					_version: pkginfo.version,
				});
			} catch (e) {
				logger.error(__('Alloy compiler failed'));
				e.toString().split('\n').forEach(function (line) {
					line && logger.error(line);
				});
				process.exit(1);
			}
			Error.stackTraceLimit = origLimit;
			finished();
		} else {
			// we have no clue where alloy is installed, so we're going to subprocess
			// alloy and hope it's in the system path or a well known place
			var paths = {};
			parallel(this, ['alloy', 'node'].map(function (bin) {
				return function (done) {
					var envName = 'ALLOY_' + (bin == 'node' ? 'NODE_' : '') + 'PATH';
					if (paths[bin] = process.env[envName]) {
						done();
					} else if (process.platform == 'win32') {
						paths['alloy'] = 'alloy.cmd';
						done();
					} else {
						exec('which ' + bin, function (err, stdout, strerr) {
							if (!err) {
								paths[bin] = stdout.trim();
								done();
							} else {
								parallel(this, [
									'/usr/local/bin/' + bin,
									'/opt/local/bin/' + bin,
									path.join(process.env['HOME'], 'local/bin', bin),
									'/opt/bin/' + bin,
									'/usr/bin/' + bin
								].map(function (p) {
									return function (cb) {
										afs.exists(p) && (paths[bin] = p);
										cb();
									};
								}), done);
							}
						});
					}
				};
			}), function () {
				var cmd = [paths.node, paths.alloy, 'compile', appDir, '--config', config];
				cli.argv['no-colors'] && cmd.push('--no-colors');
				process.platform == 'win32' && cmd.shift();
				logger.info(__('Executing Alloy compile: %s', cmd.join(' ').cyan));

				var child = spawn(cmd.shift(), cmd);
					// this regex is used to strip [INFO] and friends from alloy's output and re-log it using our logger
					re = new RegExp('(\u001b\\[\\d+m)?\\[?(' + logger.getLevels().join('|') + ')\\]?\s*(\u001b\\[\\d+m)?(.*)', 'i');

				child.stdout.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						if (line) {
							var m = line.match(re);
							if (m) {
								logger[m[2].toLowerCase()](m[4].trim());
							} else {
								logger.debug(line);
							}
						}
					});
				});
				child.stderr.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						line && logger.error(line);
					});
				});
				child.on('exit', function (code) {
					if (code) {
						logger.error(__('Alloy compiler failed'));
						process.exit(1);
					} else {
						logger.info(__('Alloy compiler completed successfully'));
					}
					finished();
				});
			});
		}
	});

};
<|endoftext|>


<commit_before> //Scripts for utilities page

 function convertToHours(totalTime,unit)
 {
    //This is a javascript port of the php function
    //convert_to_hours in convert_times.php

    var hours = Math.floor(totalTime / 3600);
    var minutes = totalTime - (hours * 3600);
    var minutes2 = minutes/ 60;
    var minFormat = (Math.round(minutes2/unit) * unit) / 100;
    var minFormatFixed = minFormat.toFixed(2);
    var minVal = (minFormatFixed + "").split(".");
    return hours + '.' + minVal[1];
 }

var oTable;

$(document).ready(function() {

    //set header widget
    $('#utilities_nav').addClass('ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr');

    //Add navigation buttons
    $('.utilities_nav_choices').buttonset();

    //Add navigation actions
    target = $('div#utilities_panel');

    //User clicks reports button
    $('#reports_button').click(function() {

        //Show the report chooser
        $('#report_chooser').appendTo('#utilities_panel').show();

        //Add chosen
        $('select[name="type"]').chosen();

        //Add datepickers
        $('input[name="date_start_display"]').datepicker({
            dateFormat : "DD, MM d, yy",
            altField:$('input[name = "date_start"]'),
            altFormat: "yy-mm-dd"
            });

        $('input[name="date_start_display"]').datepicker('setDate', '-7');

        $('input[name="date_end_display"]').datepicker({
            dateFormat : "DD, MM d, yy",
            altField:$('input[name = "date_end"]'),
            altFormat: "yy-mm-dd"
            });

        $('input[name="date_end_display"]').datepicker('setDate', new Date());

        //Create a table
        $('#report_chooser').after( '

' );

        //Dynamically create dataTable, load data
        $('button.report_submit').click(function(event){
            event.preventDefault();

            var tableHeight = $('#utilities_panel').height() - $('#report_chooser').height() - 150;

            if ($('#table_reports tfoot th').length)
            {
                //$('#table_reports tfoot th').remove();
                $('#table_reports').dataTable().fnDestroy();

                $('#table_reports tfoot tr').empty();
            }

            if ($('thead th').length)
            {
                $('thead th').remove();
            }

            var q_type =$('select[name="type"]').val();

            var start = $('input[name="date_start"]').val();

            var end = $('input[name="date_end"]').val();

            var detail = $('input[name="detail"]').val();

            var query = [];

            if (q_type.indexOf("_grp_") != -1) //user groups
            {
                query.push('grp',q_type);
            }
            else if (q_type.indexOf("_spv_") != -1) //supervisor groups
            {
                query.push('supvsr_grp',q_type);
            }
            else if(q_type.indexOf("_cse_") != -1) //case
            {
                query.push('case',q_type);
            }
            else
            {
                query.push('user',q_type);//single user
            }

            //Load data from server
            $.ajax({
                url:'lib/php/data/utilities_reports_load.php?type=' + query[0] +
                            '&columns_only=true',
                dataType: 'json',
                type: 'get',
                error: function() {
                    return true;
                },
                success: function(data) {

                    if( data )
                    {
                        //Add footer to html
                        for (var i = 0; i < data.aoColumns.length; i++) {
                            $('#table_reports tfoot tr').append('	');
                        }

                        oTable = $('#table_reports').dataTable({
                            "sAjaxSource": 'lib/php/data/utilities_reports_load.php?type=' + query[0] +
                            '&val=' + query[1] + '&date_start=' + start + '&date_end=' + end,
                            "aoColumns": data.aoColumns,
                            "bAutoWidth":false,
                            "bProcessing": true,
                            "bScrollInfinite": true,
                            "sScrollY":tableHeight,
                            "iDisplayLength": 150,
                            "bSortCellsTop": true,
                            "bDestroy": true,
                            "oLanguage": {
                                "sEmptyTable": "No data found."
                            },
                            "oTableTools":
                            {
                                "sSwfPath": "lib/DataTables-1.8.2/extras/TableTools/media/swf/copy_cvs_xls_pdf.swf",
                                "aButtons": [
                                    {
                                        "sExtends": "collection",
                                        "sButtonText": "Print/Export",
                                        "aButtons": [
                                            {"sExtends": "copy",
                                                "mColumns": "visible"
                                            },

                                            {"sExtends": "csv",
                                                "mColumns": "visible"
                                            },

                                            {"sExtends": "xls",
                                                "mColumns": "visible"
                                            },

                                            {"sExtends": "pdf",
                                                "mColumns": "visible",
                                                "sTitle": "Report",
                                                "bFooter":"visible"

                                            },

                                            {"sExtends": "print",
                                                "mColumns": "visible"
                                            }
                                        ]
                                    }
                                ]
                            },
                            "sDom": 'frTt',
                            "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {

                                    if (aaData.length > 0) //no need for footer if no data.
                                    {
                                        var totalTime = 0;

                                        colIndex = oTable.fnGetColumnIndex('Seconds');

                                        for ( var a=0 ; a<aaData.length ; a++ )
                                        {
                                            totalTime += parseFloat(aaData[a][colIndex]);

                                        }

                                        var nCells = nRow.getElementsByTagName('th');

                                        //problem has to do with adding a hidden column

                                        var previousCell = colIndex - 2;

                                        nCells[previousCell].innerHTML = 'Total Hours';

                                        var unit = $('#utilities_panel').attr('data-unit');

                                        nCells[colIndex - 1].innerHTML = convertToHours(totalTime,unit);
                                    }

                               // }

                            }

                        });
                    }}
                });

        });

        //Create toolbar
        $('div.toolbar').html('toolbar here');
    });

    //User clicks configuration button
    $('#config_button').click(function() {
        target.load('lib/php/data/utilities_configuration_load.php');

    });

    //Set default load
    $('#reports_button').trigger('click');
});

//
//Listeners
//

//Toggle
$('a.config_item_link').live('click', function(event) {
    event.preventDefault();

    // Toggle open/closed state
    if ($(this).hasClass('closed'))
    {
        $(this).removeClass('closed').addClass('opened');
    }
    else
    {
        $(this).removeClass('opened').addClass('closed');
    }

    $('div.config_item > a').not($(this)).removeClass('opened').addClass('closed');

    // Show/hide the form
    $(this).next().toggle();
    $('form.config_form').not($(this).next()).hide();

});

//Submit changes
$('a.change_config').live('click', function(event) {

    event.preventDefault();

    var formTarget = $(this).closest('form');

    var formParent = $(this).closest('div.config_item');

    var target = $(this).closest('div').attr('id');

    //If clicking delete button, remove the form element
    if (!$(this).hasClass('add'))
    {
        $(this).parent().remove();
    }

    var formVals = formTarget.serializeArray();

    formVals.push({'name': 'type','value': formTarget.attr('data-type')});

    $.post('lib/php/data/utilities_configuration_process.php', formVals, function(data) {
        var serverResponse = $.parseJSON(data);
        if (serverResponse.error === true)
        {
            notify(serverResponse.message, true);
        }
        else
        {
            notify(serverResponse.message);
            formParent.load('lib/php/data/utilities_configuration_load.php #' + target, function() {
                $(this).find('form').show();
            });
        }

    });
});
<commit_msg>Clean up Utilities fix<commit_after> //Scripts for utilities page

 function convertToHours(totalTime,unit)
 {
    //This is a javascript port of the php function
    //convert_to_hours in convert_times.php
    var hours = Math.floor(totalTime / 3600);
    var minutes = totalTime - (hours * 3600);
    var minutes2 = minutes/ 60;
    var minFormat = (Math.round(minutes2/unit) * unit) / 100;
    var minFormatFixed = minFormat.toFixed(2);
    var minVal = (minFormatFixed + "").split(".");
    return hours + '.' + minVal[1];
 }

var oTable;

$(document).ready(function() {

    //set header widget
    $('#utilities_nav').addClass('ui-toolbar ui-widget-header ui-corner-tl ui-corner-tr');

    //Add navigation buttons
    $('.utilities_nav_choices').buttonset();

    //Add navigation actions
    target = $('div#utilities_panel');

    //User clicks reports button
    $('#reports_button').click(function() {

        //Show the report chooser
        $('#report_chooser').appendTo('#utilities_panel').show();

        //Add chosen
        $('select[name="type"]').chosen();

        //Add datepickers
        $('input[name="date_start_display"]').datepicker({
            dateFormat : "DD, MM d, yy",
            altField:$('input[name = "date_start"]'),
            altFormat: "yy-mm-dd"
            });

        $('input[name="date_start_display"]').datepicker('setDate', '-7');

        $('input[name="date_end_display"]').datepicker({
            dateFormat : "DD, MM d, yy",
            altField:$('input[name = "date_end"]'),
            altFormat: "yy-mm-dd"
            });

        $('input[name="date_end_display"]').datepicker('setDate', new Date());

        //Create a table
        $('#report_chooser').after( '

' );

        //Dynamically create dataTable, load data
        $('button.report_submit').click(function(event){
            event.preventDefault();

            var tableHeight = $('#utilities_panel').height() - $('#report_chooser').height() - 150;

            if ($('#table_reports tfoot th').length)
            {
                $('#table_reports').dataTable().fnDestroy();

                $('#table_reports tfoot tr').empty();
            }

            if ($('thead th').length)
            {
                $('thead th').remove();
            }

            var q_type =$('select[name="type"]').val();

            var start = $('input[name="date_start"]').val();

            var end = $('input[name="date_end"]').val();

            var detail = $('input[name="detail"]').val();

            var query = [];

            if (q_type.indexOf("_grp_") != -1) //user groups
            {
                query.push('grp',q_type);
            }
            else if (q_type.indexOf("_spv_") != -1) //supervisor groups
            {
                query.push('supvsr_grp',q_type);
            }
            else if(q_type.indexOf("_cse_") != -1) //case
            {
                query.push('case',q_type);
            }
            else
            {
                query.push('user',q_type);//single user
            }

            //Load data from server
            $.ajax({
                url:'lib/php/data/utilities_reports_load.php?type=' + query[0] +
                            '&columns_only=true',
                dataType: 'json',
                type: 'get',
                error: function() {
                    return true;
                },
                success: function(data) {

                    if( data )
                    {
                        //Add footer to html
                        for (var i = 0; i < data.aoColumns.length; i++) {
                            $('#table_reports tfoot tr').append('	');
                        }

                        oTable = $('#table_reports').dataTable({
                            "sAjaxSource": 'lib/php/data/utilities_reports_load.php?type=' + query[0] +
                            '&val=' + query[1] + '&date_start=' + start + '&date_end=' + end,
                            "aoColumns": data.aoColumns,
                            "bAutoWidth":false,
                            "bProcessing": true,
                            "bScrollInfinite": true,
                            "sScrollY":tableHeight,
                            "iDisplayLength": 150,
                            "bSortCellsTop": true,
                            "oLanguage": {
                                "sEmptyTable": "No data found."
                            },
                            "oTableTools":
                            {
                                "sSwfPath": "lib/DataTables-1.8.2/extras/TableTools/media/swf/copy_cvs_xls_pdf.swf",
                                "aButtons": [
                                    {
                                        "sExtends": "collection",
                                        "sButtonText": "Print/Export",
                                        "aButtons": [
                                            {"sExtends": "copy",
                                                "mColumns": "visible"
                                            },

                                            {"sExtends": "csv",
                                                "mColumns": "visible"
                                            },

                                            {"sExtends": "xls",
                                                "mColumns": "visible"
                                            },

                                            {"sExtends": "pdf",
                                                "mColumns": "visible",
                                                "sTitle": "Report",
                                                "bFooter":"visible"

                                            },

                                            {"sExtends": "print",
                                                "mColumns": "visible"
                                            }
                                        ]
                                    }
                                ]
                            },
                            "sDom": 'frTt',
                            "fnFooterCallback": function ( nRow, aaData, iStart, iEnd, aiDisplay ) {

                                    if (aaData.length > 0) //no need for footer if no data.
                                    {
                                        var totalTime = 0;

                                        colIndex = oTable.fnGetColumnIndex('Seconds');

                                        for ( var a=0 ; a<aaData.length ; a++ )
                                        {
                                            totalTime += parseFloat(aaData[a][colIndex]);

                                        }

                                        var nCells = nRow.getElementsByTagName('th');

                                        //problem has to do with adding a hidden column

                                        var previousCell = colIndex - 2;

                                        nCells[previousCell].innerHTML = 'Total Hours';

                                        var unit = $('#utilities_panel').attr('data-unit');

                                        nCells[colIndex - 1].innerHTML = convertToHours(totalTime,unit);
                                    }

                               // }

                            }

                        });
                    }}
                });

        });

        //Create toolbar
        $('div.toolbar').html('toolbar here');
    });

    //User clicks configuration button
    $('#config_button').click(function() {
        target.load('lib/php/data/utilities_configuration_load.php');

    });

    //Set default load
    $('#reports_button').trigger('click');
});

//
//Listeners
//

//Toggle
$('a.config_item_link').live('click', function(event) {
    event.preventDefault();

    // Toggle open/closed state
    if ($(this).hasClass('closed'))
    {
        $(this).removeClass('closed').addClass('opened');
    }
    else
    {
        $(this).removeClass('opened').addClass('closed');
    }

    $('div.config_item > a').not($(this)).removeClass('opened').addClass('closed');

    // Show/hide the form
    $(this).next().toggle();
    $('form.config_form').not($(this).next()).hide();

});

//Submit changes
$('a.change_config').live('click', function(event) {

    event.preventDefault();

    var formTarget = $(this).closest('form');

    var formParent = $(this).closest('div.config_item');

    var target = $(this).closest('div').attr('id');

    //If clicking delete button, remove the form element
    if (!$(this).hasClass('add'))
    {
        $(this).parent().remove();
    }

    var formVals = formTarget.serializeArray();

    formVals.push({'name': 'type','value': formTarget.attr('data-type')});

    $.post('lib/php/data/utilities_configuration_process.php', formVals, function(data) {
        var serverResponse = $.parseJSON(data);
        if (serverResponse.error === true)
        {
            notify(serverResponse.message, true);
        }
        else
        {
            notify(serverResponse.message);
            formParent.load('lib/php/data/utilities_configuration_load.php #' + target, function() {
                $(this).find('form').show();
            });
        }

    });
});
<|endoftext|>


<commit_before>
// SmoothScroll v0.9.5
// Licensed under the terms of the MIT license.

// People involved
// - Balazs Galambosi: maintainer (CHANGELOG.txt)
// - Patrick Brunner (patrickb1991@gmail.com)
// - Michael Herf: Pulse Algorithm

// Frame Variables
var frame         = false;
var noscrollframe = false;

// Scroll Variables (tweakable)
var framerate = 150; // [Hz]
var animtime  = 400; // [px]
var stepsize  = 120; // [px]

// Pulse (less tweakable)
// ratio of "tail" to "acceleration"
var pulseAlgorithm = true;
var pulseScale     = 8;
var pulseNormalize = 1;

// Keyboard Settings
var keyboardsupport = true;
var disableKeyboard = false;
var arrowscroll     = 50; // [px]

// Excluded pages
var exclude = "";

// Other Variables
var scrolls;
var deltaX = 0;
var deltaY = 0;
var direction = "down";
var initdone  = false;
var activeElement;

var key = { up: 38, down: 40, spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36 };

/***********************************************
 * SETTINGS
 ***********************************************/

chrome.extension.connect({ name: "smoothscroll" }).
onMessage.addListener(function (settings) {

    // NOTE: + converts to {Number}
    framerate = +settings.framerate;
    animtime  = +settings.animtime;
    stepsize  = +settings.scrollsz;
    exclude   = settings.exclude;
    pulseAlgorithm  = (settings.pulseAlgorithm == "true");
    pulseScale      = +settings.pulseScale;
    keyboardsupport = (settings.keyboardsupport == "true");
    arrowscroll     = +settings.arrscroll;

    computePulseScale();

    // it seems that sometimes settings come late
    // and we need to test again for excluded pages
    initTest();

    if (keyboardsupport && !disableKeyboard) {
        addEvent("keydown", keydown);
    }

    // If extension settings were deleted somehow
    if (!framerate) {
        alert("SmoothScroll: Please restart Chrome");
    }
});

/***********************************************
 * INITIALIZE
 ***********************************************/

/**
 * Tests if smooth scrolling is allowed. Shuts down everything if not.
 */
function initTest() {

    // disable keys for google reader (spacebar conflict)
    if (document.URL.indexOf("google.com/reader/view") > -1) {
        disableKeyboard = true;
    }

    // disable everything if the page is blacklisted
    if (exclude) {
        var domains = exclude.split(/[,\n] ?/);
        for (var i = domains.length; i--;) {
            if (document.URL.indexOf(domains[i]) > -1) {
                removeEvent("mousewheel", wheel);
                disableKeyboard = true;
                break;
            }
        }
    }

    // disable keyboard support if anything above requested it
    if (disableKeyboard) {
        removeEvent("keydown", keydown);
    }
}

/**
 * Sets up scrolls array, determines if frames are involved.
 */
function init() {

    var body  = document.body;
    var docel = document.documentElement;
    var htmlHeight   = docel.offsetHeight;
    var windowHeight = window.innerHeight;

    activeElement = body;
    initTest();

    if (document.domain === "acid3.acidtests.org") return;

    // Checks if this script is running in a frame
    if (top != self) {
        frame = true;
        if (docel.scrollHeight <= docel.clientHeight + 10) {
            noscrollframe = true;
        }
    }

    /**
     * This fixes a bug where the areas left and right to
     * the content does not trigger the onmousewheel event
     * on some pages. e.g.: html, body { height: 100% }
     */
    else if (body.scrollHeight > windowHeight &&
            (body.offsetHeight <= windowHeight || htmlHeight <= windowHeight)) {

        var underlay = document.createElement("div");
        underlay.setAttribute( "style",
            "z-index: -1; position: absolute; top: 0; left: 0; " +
            "width: 100%; height: " + body.scrollHeight + "px;" );
        body.appendChild(underlay);

        var scrollHeight = body.scrollHeight;
        var pending = false;

        // DOMChange delayed
        var refresh = function() {
            if (!pending && scrollHeight != body.scrollHeight) {
                pending = true; // add a new pending action
                setTimeout(function(){
                    underlay.style.height = body.scrollHeight + "px";
                    scrollHeight = body.scrollHeight;
                    pending = false;
                }, 1000); // act rarely to stay fast
            }
        }

        addEvent("DOMNodeInserted", refresh);
        addEvent("DOMNodeRemoved",  refresh);
    }
    initdone = true;
}

/************************************************
 * SCROLLING
 ************************************************/

var que = [];
var pending = false;

/**
 * Pushes scroll actions to a given direction Array.
 */
function scrollArray(elem, dir, multiplyX, multiplyY, delay) {

    delay || (delay = 1000);
    directionCheck(dir);

    // contains the scroll commands [ x, y, start, last ]
    que.push([multiplyX, multiplyY, +new Date, 0]);

    // don't act if there's a pending queue
    if (pending) {
        return;
    }

    var step = function() {

        var now = +new Date;
        var addX = 0;
        var addY = 0;
        var finished;
        var x = 0, y = 1, start = 2, last = 3; // {enum}

        for (var i = 0; i < que.length; i++) {

            var item = que[i];
            var elapsed = now - item[start];

            finished = (elapsed >= animtime);

            // scroll position: [0, 1]
            var scroll = (finished) ? 1 : elapsed / animtime;
            // easing [optional]
            if (pulseAlgorithm) {
                scroll = pulse(scroll);
            }

            // only need the difference
            scroll -= item[last];
            item[last] += scroll;

            // add this to the actual scrolling
            addX += item[x] * scroll;
            addY += item[y] * scroll;

            // delete and step back
            if (finished) {
                que.splice(i, 1); i--;
            }
        }

        // scroll left
        if (multiplyX) {
            var lastLeft = elem.scrollLeft;
            elem.scrollLeft += addX;

            // scroll left failed (edge)
            if (addX >> 0 && elem.scrollLeft === lastLeft) {
                multiplyX = 0;
            }
        }

        // scroll top
        if (multiplyY) {
            var lastTop = elem.scrollTop;
            elem.scrollTop += addY;

            // scroll top failed (edge)
            if (addY >> 0 && elem.scrollTop === lastTop) {
                multiplyY = 0;
            }
        }

        // clean up if there's nothing left to do
        if (!multiplyX && !multiplyY) {
            que = [];
        }

        if (que.length) {
            setTimeout(step, delay / framerate + 1);
        } else {
            pending = false;
        }
    }

    // start a new queue of actions
    setTimeout(step, 0);
    pending = true;
}

/***********************************************
 * EVENTS
 ***********************************************/

/**
 * Mouse wheel handler.
 * NOTE: function logic should be decomposed.
 * @param {Object} event
 */
function wheel(event) {

    if (!initdone) {
        init();
    }

    var target = event.target;

    // use default if there's no overflowing
    // element or default action is prevented
    var elem = overflowingAncestor(target);
    if (!elem || noscrollframe || event.defaultPrevented ||
        isNodeName(activeElement, "embed") ||
       (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
        return true;
    }

    deltaX = event.wheelDeltaX || 0;
    deltaY = event.wheelDeltaY || 0;

    // synaptics seems to send 1 sometimes,
    // and 120 other times (fix)
    if (Math.abs(deltaX) < 1.2) {
        deltaX *= 120;
    }
    if (Math.abs(deltaY) < 1.2) {
        deltaY *= 120;
    }

    var dir = (deltaY > 0) ? "up" : "down";
    scrollArray(elem, dir, -deltaX, -deltaY);
    event.preventDefault();
}

/**
 * Keydown event handler.
 * @param {Object} event
 */
function keydown(event) {

    var target   = event.target;
    var modifier = event.ctrlKey || event.altKey || event.metaKey;

    // do nothing if user is editing text
    // or using a modifier key (except shift)
    if ( /input|textarea|embed/i.test(target.nodeName) ||
         target.isContentEditable ||
         event.defaultPrevented   ||
         modifier ) {
      return true;
    }
    // spacebar should trigger button press
    if (isNodeName(target, "button") &&
        event.keyCode === key.spacebar) {
      return true;
    }

    var scale, dir, shift;
    var elem = overflowingAncestor(activeElement);
    var clientHeight = elem.clientHeight;

    if (elem == document.body) {
        clientHeight = window.innerHeight;
    }

    switch (event.keyCode) {
        case key.up:
            scale = -arrowscroll;
            dir = "up";
            break;
        case key.down:
            scale = arrowscroll;
            dir = "down";
            break;
        case key.spacebar: // (+ shift)
            shift = event.shiftKey ? 1 : -1;
            scale = -shift * clientHeight * 0.9;
            dir = (shift > 0) ? "up" : "down";
            break;
        case key.pageup:
            scale = -clientHeight * 0.9;
            dir = "up";
            break;
        case key.pagedown:
            scale = clientHeight * 0.9;
            dir = "down";
            break;
        case key.home:
            scale = -elem.scrollTop;
            dir = "up";
            break;
        case key.end:
            var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
            scale = (damt > 0) ? damt+10 : 0;
            dir = "down";
            break;
        default:
            return true; // a key we don"t care about
    }

    scrollArray(elem, dir, 0, scale);
    event.preventDefault();
}

/**
 * Mousedown event only for updating activeElement
 */
function mousedown(event) {
    activeElement = event.target;
}

/***********************************************
 * HELPERS
 ***********************************************/

function addEvent(type, fn, bubble) {
    window.addEventListener(type, fn, (bubble||false));
}

function removeEvent(type, fn, bubble) {
    window.removeEventListener(type, fn, (bubble||false));
}

function isNodeName(el, tag) {
    return el.nodeName.toLowerCase() === tag.toLowerCase();
}

function directionCheck(dir) {
    if (direction !== dir) {
        que = [];
        direction = dir;
    }
}

function overflowingAncestor(el) {
    var bodyScrollHeight = document.body.scrollHeight;
    do {
        if (bodyScrollHeight === el.scrollHeight) {
            return document.body;
        }
        else if (el.clientHeight + 10 < el.scrollHeight) {
            overflow = getComputedStyle(el, "").getPropertyValue("overflow");
            if (overflow === "scroll" || overflow === "auto") {
                return el;
            }
        }
    } while (el = el.parentNode);
}

/***********************************************
 * PULSE
 ***********************************************/

/**
 * Viscous fluid with a pulse for part and decay for the rest.
 * - Applies a fixed force over an interval (a damped acceleration), and
 * - Lets the exponential bleed away the velocity over a longer interval
 * - Michael Herf, http://stereopsis.com/stopping/
 */
function pulse_(x) {
    var val, start, expx;
    // test
    x = x * pulseScale;
    if (x < 1) { // acceleartion
        val = x - (1 - Math.exp(-x));
    } else {     // tail
        // the previous animation ended here:
        start = Math.exp(-1);
        // simple viscous drag
        x -= 1;
        expx = 1 - Math.exp(-x);
        val = start + (expx * (1 - start));
    }
    return val * pulseNormalize;
}

function computePulseScale() {
    pulseNormalize = 1 / pulse_(1);
}

/**
 * Viscous fluid with a pulse for part and decay for the rest
 */
function pulse(x) {
    if (x >= 1) return 1;
    if (x <= 0) return 0;

    if (pulseNormalize == 1) {
        computePulseScale();
    }
    return pulse_(x);
}

addEvent("mousedown", mousedown);
addEvent("mousewheel", wheel);
addEvent("load", init);
<commit_msg>diferent goal tracking. hash for scroll commands. comments updated<commit_after>
// SmoothScroll v0.9.5
// Licensed under the terms of the MIT license.

// People involved
// - Balazs Galambosi: maintainer (CHANGELOG.txt)
// - Patrick Brunner (patrickb1991@gmail.com)
// - Michael Herf: Pulse Algorithm

// Frame Variables
var frame         = false;
var noscrollframe = false;

// Scroll Variables (tweakable)
var framerate = 150; // [Hz]
var animtime  = 400; // [px]
var stepsize  = 120; // [px]

// Pulse (less tweakable)
// ratio of "tail" to "acceleration"
var pulseAlgorithm = true;
var pulseScale     = 8;
var pulseNormalize = 1;

// Keyboard Settings
var keyboardsupport = true;
var disableKeyboard = false;
var arrowscroll     = 50; // [px]

// Excluded pages
var exclude = "";

// Other Variables
var scrolls;
var deltaX = 0;
var deltaY = 0;
var direction = "down";
var initdone  = false;
var activeElement;

var key = { up: 38, down: 40, spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36 };

/***********************************************
 * SETTINGS
 ***********************************************/

chrome.extension.connect({ name: "smoothscroll" }).
onMessage.addListener(function (settings) {

    // NOTE: + converts to {Number}
    framerate = +settings.framerate;
    animtime  = +settings.animtime;
    stepsize  = +settings.scrollsz;
    exclude   = settings.exclude;
    pulseAlgorithm  = (settings.pulseAlgorithm == "true");
    pulseScale      = +settings.pulseScale;
    keyboardsupport = (settings.keyboardsupport == "true");
    arrowscroll     = +settings.arrscroll;

    computePulseScale();

    // it seems that sometimes settings come late
    // and we need to test again for excluded pages
    initTest();

    if (keyboardsupport && !disableKeyboard) {
        addEvent("keydown", keydown);
    }

    // If extension settings were deleted somehow
    if (!framerate) {
        alert("SmoothScroll: Please restart Chrome");
    }
});

/***********************************************
 * INITIALIZE
 ***********************************************/

/**
 * Tests if smooth scrolling is allowed. Shuts down everything if not.
 */
function initTest() {

    // disable keys for google reader (spacebar conflict)
    if (document.URL.indexOf("google.com/reader/view") > -1) {
        disableKeyboard = true;
    }

    // disable everything if the page is blacklisted
    if (exclude) {
        var domains = exclude.split(/[,\n] ?/);
        for (var i = domains.length; i--;) {
            if (document.URL.indexOf(domains[i]) > -1) {
                removeEvent("mousewheel", wheel);
                disableKeyboard = true;
                break;
            }
        }
    }

    // disable keyboard support if anything above requested it
    if (disableKeyboard) {
        removeEvent("keydown", keydown);
    }
}

/**
 * Sets up scrolls array, determines if frames are involved.
 */
function init() {

    var body  = document.body;
    var docel = document.documentElement;
    var htmlHeight   = docel.offsetHeight;
    var windowHeight = window.innerHeight;

    activeElement = body;
    initTest();

    if (document.domain === "acid3.acidtests.org") return;

    // Checks if this script is running in a frame
    if (top != self) {
        frame = true;
        if (docel.scrollHeight <= docel.clientHeight + 10) {
            noscrollframe = true;
        }
    }

    /**
     * This fixes a bug where the areas left and right to
     * the content does not trigger the onmousewheel event
     * on some pages. e.g.: html, body { height: 100% }
     */
    else if (body.scrollHeight > windowHeight &&
            (body.offsetHeight <= windowHeight || htmlHeight <= windowHeight)) {

        var underlay = document.createElement("div");
        underlay.setAttribute( "style",
            "z-index: -1; position: absolute; top: 0; left: 0; " +
            "width: 100%; height: " + body.scrollHeight + "px;" );
        body.appendChild(underlay);

        var scrollHeight = body.scrollHeight;
        var pending = false;

        // DOMChange delayed
        var refresh = function() {
            if (!pending && scrollHeight != body.scrollHeight) {
                pending = true; // add a new pending action
                setTimeout(function(){
                    underlay.style.height = body.scrollHeight + "px";
                    scrollHeight = body.scrollHeight;
                    pending = false;
                }, 1000); // act rarely to stay fast
            }
        }

        addEvent("DOMNodeInserted", refresh);
        addEvent("DOMNodeRemoved",  refresh);
    }
    initdone = true;
}

/************************************************
 * SCROLLING
 ************************************************/

var que = [];
var pending = false;

/**
 * Pushes scroll actions to a given direction Array.
 */
function scrollArray(elem, dir, multiplyX, multiplyY, delay) {

    delay || (delay = 1000);
    directionCheck(dir);

    // push a scroll command
    que.push({
        x: multiplyX,
        y: multiplyY,
        lastX: 0,
        lastY: 0,
        start: +new Date
    });

    // don't act if there's a pending queue
    if (pending) {
        return;
    }

    var step = function() {

        var now = +new Date;
        var totalX = 0;
        var totalY = 0;
        var finished;

        for (var i = 0; i < que.length; i++) {

            var item = que[i];
            var elapsed = now - item.start;

            finished = (elapsed >= animtime);

            // scroll position: [0, 1]
            var scroll = (finished) ? 1 : elapsed / animtime;

            // easing [optional]
            if (pulseAlgorithm) {
                scroll = pulse(scroll);
            }

            // only need the difference
            var scrollX = (item.x * scroll - item.lastX) >> 0;
            var scrollY = (item.y * scroll - item.lastY) >> 0;

            // add this to the total scrolling
            totalX += scrollX;
            totalY += scrollY;

            // update last values
            item.lastX += scrollX;
            item.lastY += scrollY;

            // delete and step back if it's over
            if (finished) {
                que.splice(i, 1); i--;
            }
        }

        // scroll left
        if (multiplyX) {
            var lastLeft = elem.scrollLeft;
            elem.scrollLeft += totalX;

            // scroll left failed (edge)
            if (totalX >> 0 && elem.scrollLeft === lastLeft) {
                multiplyX = 0;
            }
        }

        // scroll top
        if (multiplyY) {
            var lastTop = elem.scrollTop;
            elem.scrollTop += totalY;

            // scroll top failed (edge)
            if (totalY >> 0 && elem.scrollTop === lastTop) {
                multiplyY = 0;
            }
        }

        // clean up if there's nothing left to do
        if (!multiplyX && !multiplyY) {
            que = [];
        }

        if (que.length) {
            setTimeout(step, delay / framerate + 1);
        } else {
            pending = false;
        }
    }

    // start a new queue of actions
    setTimeout(step, 0);
    pending = true;
}

/***********************************************
 * EVENTS
 ***********************************************/

/**
 * Mouse wheel handler.
 * NOTE: function logic should be decomposed.
 * @param {Object} event
 */
function wheel(event) {

    if (!initdone) {
        init();
    }

    var target = event.target;

    // use default if there's no overflowing
    // element or default action is prevented
    var elem = overflowingAncestor(target);
    if (!elem || noscrollframe || event.defaultPrevented ||
        isNodeName(activeElement, "embed") ||
       (isNodeName(target, "embed") && /\.pdf/i.test(target.src))) {
        return true;
    }

    deltaX = event.wheelDeltaX || 0;
    deltaY = event.wheelDeltaY || 0;

    // synaptics seems to send 1 sometimes,
    // and 120 other times (fix)
    if (Math.abs(deltaX) < 1.2) {
        deltaX *= 120;
    }
    if (Math.abs(deltaY) < 1.2) {
        deltaY *= 120;
    }

    var dir = (deltaY > 0) ? "up" : "down";
    scrollArray(elem, dir, -deltaX, -deltaY);
    event.preventDefault();
}

/**
 * Keydown event handler.
 * @param {Object} event
 */
function keydown(event) {

    var target   = event.target;
    var modifier = event.ctrlKey || event.altKey || event.metaKey;

    // do nothing if user is editing text
    // or using a modifier key (except shift)
    if ( /input|textarea|embed/i.test(target.nodeName) ||
         target.isContentEditable ||
         event.defaultPrevented   ||
         modifier ) {
      return true;
    }
    // spacebar should trigger button press
    if (isNodeName(target, "button") &&
        event.keyCode === key.spacebar) {
      return true;
    }

    var scale, dir, shift;
    var elem = overflowingAncestor(activeElement);
    var clientHeight = elem.clientHeight;

    if (elem == document.body) {
        clientHeight = window.innerHeight;
    }

    switch (event.keyCode) {
        case key.up:
            scale = -arrowscroll;
            dir = "up";
            break;
        case key.down:
            scale = arrowscroll;
            dir = "down";
            break;
        case key.spacebar: // (+ shift)
            shift = event.shiftKey ? 1 : -1;
            scale = -shift * clientHeight * 0.9;
            dir = (shift > 0) ? "up" : "down";
            break;
        case key.pageup:
            scale = -clientHeight * 0.9;
            dir = "up";
            break;
        case key.pagedown:
            scale = clientHeight * 0.9;
            dir = "down";
            break;
        case key.home:
            scale = -elem.scrollTop;
            dir = "up";
            break;
        case key.end:
            var damt = elem.scrollHeight - elem.scrollTop - clientHeight;
            scale = (damt > 0) ? damt+10 : 0;
            dir = "down";
            break;
        default:
            return true; // a key we don"t care about
    }

    scrollArray(elem, dir, 0, scale);
    event.preventDefault();
}

/**
 * Mousedown event only for updating activeElement
 */
function mousedown(event) {
    activeElement = event.target;
}

/***********************************************
 * HELPERS
 ***********************************************/

function addEvent(type, fn, bubble) {
    window.addEventListener(type, fn, (bubble||false));
}

function removeEvent(type, fn, bubble) {
    window.removeEventListener(type, fn, (bubble||false));
}

function isNodeName(el, tag) {
    return el.nodeName.toLowerCase() === tag.toLowerCase();
}

function directionCheck(dir) {
    if (direction !== dir) {
        que = [];
        direction = dir;
    }
}

function overflowingAncestor(el) {
    var bodyScrollHeight = document.body.scrollHeight;
    do {
        if (bodyScrollHeight === el.scrollHeight) {
            return document.body;
        }
        else if (el.clientHeight + 10 < el.scrollHeight) {
            overflow = getComputedStyle(el, "").getPropertyValue("overflow");
            if (overflow === "scroll" || overflow === "auto") {
                return el;
            }
        }
    } while (el = el.parentNode);
}

/***********************************************
 * PULSE
 ***********************************************/

/**
 * Viscous fluid with a pulse for part and decay for the rest.
 * - Applies a fixed force over an interval (a damped acceleration), and
 * - Lets the exponential bleed away the velocity over a longer interval
 * - Michael Herf, http://stereopsis.com/stopping/
 */
function pulse_(x) {
    var val, start, expx;
    // test
    x = x * pulseScale;
    if (x < 1) { // acceleartion
        val = x - (1 - Math.exp(-x));
    } else {     // tail
        // the previous animation ended here:
        start = Math.exp(-1);
        // simple viscous drag
        x -= 1;
        expx = 1 - Math.exp(-x);
        val = start + (expx * (1 - start));
    }
    return val * pulseNormalize;
}

function computePulseScale() {
    pulseNormalize = 1 / pulse_(1);
}

/**
 * Viscous fluid with a pulse for part and decay for the rest
 */
function pulse(x) {
    if (x >= 1) return 1;
    if (x <= 0) return 0;

    if (pulseNormalize == 1) {
        computePulseScale();
    }
    return pulse_(x);
}

addEvent("mousedown", mousedown);
addEvent("mousewheel", wheel);
addEvent("load", init);
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var api = require('./routes/api');
var sha1 = require('sha1');

var app = express();
const SECRET = "DEFINITELY_NOT_USING_THIS_IN_PRODUCTION";

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

const isTimeValid = (requestTime, currentTime) => {
  let fiveMinutesAgo = new Date(currentTime);
  fiveMinutesAgo = fiveMinutesAgo.setMinutes(fiveMinutesAgo.getMinutes() - 5);
  let fiveMinutesFromNow = new Date(currentTime);
  fiveMinutesFromNow = fiveMinutesFromNow.setMinutes(fiveMinutesFromNow.getMinutes() + 5);
  if (requestTime < fiveMinutesAgo  || requestTime > fiveMinutesFromNow) {
    return false;
  }
  return true;
};

// auth - if they don't send us the right hash, reject the request!
const authMiddleware = (req, res, next) => {
  let error;
  const hash = req.query.hash;
  const time = req.query.time;
  const fullUrl = req.protocol + "://" + req.hostname + ":3000" + req.path + SECRET + time; //FIXFIX: this won't work in production
  const shaResult = sha1(fullUrl);
  const hasValidTime = isTimeValid(time, Date.now())
  if (shaResult !== hash || !hasValidTime) {
    error = new Error("Error: not authorized");
    error.status = 403;
    next(error);
  }
  next();
};

app.use(authMiddleware);

app.use('/', routes);
app.use('/api', api);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

module.exports = app;
<commit_msg>Listen on port 3000<commit_after>var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var api = require('./routes/api');
var sha1 = require('sha1');

var app = express();
const SECRET = "DEFINITELY_NOT_USING_THIS_IN_PRODUCTION";

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

const isTimeValid = (requestTime, currentTime) => {
  let fiveMinutesAgo = new Date(currentTime);
  fiveMinutesAgo = fiveMinutesAgo.setMinutes(fiveMinutesAgo.getMinutes() - 5);
  let fiveMinutesFromNow = new Date(currentTime);
  fiveMinutesFromNow = fiveMinutesFromNow.setMinutes(fiveMinutesFromNow.getMinutes() + 5);
  if (requestTime < fiveMinutesAgo  || requestTime > fiveMinutesFromNow) {
    return false;
  }
  return true;
};

// auth - if they don't send us the right hash, reject the request!
const authMiddleware = (req, res, next) => {
  let error;
  const hash = req.query.hash;
  const time = req.query.time;
  const fullUrl = req.protocol + "://" + req.hostname + ":3000" + req.path + SECRET + time; //FIXFIX: this won't work in production
  const shaResult = sha1(fullUrl);
  const hasValidTime = isTimeValid(time, Date.now())
  if (shaResult !== hash || !hasValidTime) {
    error = new Error("Error: not authorized");
    error.status = 403;
    next(error);
  }
  next();
};

app.use(authMiddleware);

app.use('/', routes);
app.use('/api', api);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
  app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
      message: err.message,
      error: err
    });
  });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
  res.status(err.status || 500);
  res.render('error', {
    message: err.message,
    error: {}
  });
});

app.listen(3000, () => {
  console.log("Starting hornung server...");
})

module.exports = app;
<|endoftext|>


<commit_before>var EventBridge;
var WebChannel;
$(document).ready(function(){
    document.addEventListener("contextmenu", function(event) {
        event.preventDefault();
    }, false);
    WebChannel = new QWebChannel(qt.webChannelTransport, function (channel) {
        EventBridge = WebChannel.objects.eventBridgeWrapper.eventBridge;
        webEventBridgeCallback(EventBridge);
    });
    $('input.searchbox').on('keyup paste change',function(){filterSearch(this)});

});

var repoList = [];

function testObj(obj,head){
    var o = {};
    for(var i in head){
        if(!obj.hasOwnProperty(head[i]))return false;
        o[head[i]] = obj[head[i]];
    }
    return o;
}

function getRepoListings(){
    alert("REPOS");
    //return;
    $.ajax({
        url: "repos.json",
        success: function(data){
            if(!(data instanceof Object)){
                alert("Not Object");
                data = JSON.parse(data);
            }
            else alert("OBJECT");
            webEvent({command:"setRepoList",value:data});
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert("Status: " + textStatus);
            alert("Error: " + errorThrown);
        }
    });
}

function renderRepoList(){
    var html = "";
    for(var k in repoList){
        var repo = repoList[k];
        if(repoUrls.indexOf(repo.url) < 0){
            html += '
' + repo.name + '
';
        }
    }
    $("tbody#repolist").html(html);
}

function webEventBridgeCallback(eb){
    if (EventBridge !== undefined) {
        EventBridge.scriptEventReceived.connect(scriptEvent);
        loadData();
    }
}

function getRepos()
{
    repositories = {};
    for(var i = 0; i < repoUrls.length; i++){
        var url = repoUrls[i];
        var repository = {};
        repository["categories"] = {};
        repository["packages"] = {};
        $.ajax({
            url: url,
            success: function(response){
                data = JSON.parse(response);
                repositories[url] = data;
            },
            async: false
        });
    }
    debug(repositories);
    webEvent({command:"setRepositories",value:repositories});
}

function renderRepositories(){
    var cats = "";
    var repos = "";
    var count = 0;
    var repoCount = 0;
    for(var k in repositories){
        var repo = repositories[k];
        repos += renderRepo(repo,repoCount++,k);
        for(var l in repo.categories){
            if(count == 0){
                cats += '
';
            }
            cats += '
';
            var category = repo.categories[l];
            cats += renderCategory(l,category,repo.packages,repo.meta,k);
            cats += "
";
            ++count;
            if(count == 2){
                cats += "
";
                count = 0;
            }
        }
    }
    if(count != 0){
        cats += "
";
    }

    $("#debugtext").html("
" + cats.replace("<","<").replace(">",">") + "
");

    $("div#categorieslist").html(cats);
    $("div#repolist").html(repos);
}

function renderCategory(cat,category,packages,repo,repoKey){
    var html = '

' +
        category.name + '
Active <input type="checkbox" ' +
        (isActiveCategory(repoKey,cat) ? ' checked="checked" ' : "") +
        'data-repo="' +  repoKey + '" data-cat="' + cat + '" class="catcheck"/>
' +
        '

' + category.description +
        '

' +
        '' + repo.name +
        '

';
    return html;
}

function filterSearch(elem){
    var search = "." + $(elem).data("search");
    var filter = $(elem).val();
    if(filter.length < 1){
        $(search).show();
        $(search + "-hide").show();
        return;
    }
    $(search + "-hide").hide();
    $(search).hide();
    $(search + '[data-tags*="' + filter + '"]').show();

}

function renderRepo(repo,c,repoKey){

    var tags = [];
    for(var k in repo.packages){
        var tgs = repo.packages[k].tags;
        for(var t in tgs){
            if(tags.indexOf(tgs[t]) < 0){
                tags.push(tgs[t]);
            }
        }
    }

    var html = '

' +
        repo.meta.name + '
Active ' +
        '<input type="checkbox" onchange="checkAllPkg(this,' + c + ');" ' +
        (isActivePkg(repoKey,"") ? 'checked="checked" ' : "") + 'class="repocheck" data-repo="' + repoKey + '" />
' +
        '

';

        //$(this).parent().siblings('.panel-body').eq(0).children('.pkgcheck').prop("checked",true)
    html += renderPackages(repo.packages, c,repoKey);

    html += '

' +
        '' + repo.meta.name +
        '

';
    return html;
}
function renderPackages(pkgs, c, repoKey){
    var html = "

";
    for(var k in pkgs){
        html += renderPackage(pkgs[k],k,c,repoKey);
    }
    return html + "

";
}

function renderPackage(pkg,k,c,repoKey){
    return '
<input type="checkbox" data-pkg="' + k + '" ' +
        (isActivePkg(repoKey,k) ? 'checked="checked" ' : "") +
        'data-repo="' + repoKey + '" ' +
        'class="pkgcheck pkgcheck-' + c + '" />	' + pkg.name + "
";
}

function post(val){
    alert(JSON.stringify(val));
}

function checkAllPkg(elem,c){
    $(".pkgcheck-" + c).each(function(index){
        $(this).prop("checked",$(elem).prop("checked"));
    });
}

function applyScripts(){
    var scripts = [];
    $("input.repocheck").each(function(i){
        if($(this).prop("checked")){
            scripts.push($(this).data("repo"));
        }
    });
    $("input.pkgcheck").each(function(i){
        if($(this).prop("checked")){
            var repo = $(this).data("repo");
            if(scripts.indexOf(repo) < 0){
                scripts.push(repo + ">" + $(this).data("pkg"));
            }
        }
    });
    var categories = [];
    $("input.catcheck").each(function(i){
        if($(this).prop("checked")){
            categories.push($(this).data("repo") + ">" + $(this).data("cat"));
        }
    });
    webEvent({command:"setActiveScripts",value:{scripts:scripts,categories:categories}});
}

var repoUrls = [];

function command(typ){
    return {command:typ};
}

function loadData()
{
    repoUrls = [];
    //getRepoListings();
    webEvent([command("getRepoList"),command("getRepoUrls"),command("getActiveScripts"),command("getRepositories"),command("getRunningScripts")]);
}

function webEvent(val){
    if(EventBridge !== undefined){
        EventBridge.emitWebEvent(JSON.stringify(val));
    }
}

function debug(data){
    //alert(JSON.stringify(data));
    $("#debugtext").html(JSON.stringify(data));
}

function removeRepo(repo){
    webEvent({command:"removeRepoUrl",value:repo});
}

function addRepoUrl(url){
    webEvent({command:"addRepoUrl",value:url});
}

function addRepo(){
    var newrepo = $("input#newrepo").val();
    if(newrepo.length < 5)return;
    $("input#newrepo").val("");
    addRepoUrl(newrepo);
}
var activeScripts = null;

function isActivePkg(repo,pkg){
    if(activeScripts == null) return false;
    return (activeScripts.scripts.indexOf(repo + ">" + pkg) >= 0 || activeScripts.scripts.indexOf(repo) >= 0);
}

function isActiveCategory(repo,cat){
    if(activeScripts == null) return false;
    return (activeScripts.categories.indexOf(repo + ">" + cat) >= 0);
}

function getRunningScripts(){
    webEvent({command:"getRunningScripts"});
}

function stopScript(scr){
    webEvent({command:"stopScript",value:scr});
}

function refreshScript(scr){
    webEvent({command:"refreshScript",value:scr})
}

function reset(){
    webEvent(command("reset"));
}

function scriptEvent(scriptEventData){
    //alert(scriptEventData);
    scriptEventData = JSON.parse(scriptEventData);
    if(!(scriptEventData instanceof Array)){
        scriptEventData = [scriptEventData];
    }
    for(var i = 0;i < scriptEventData.length; i++){
        data = scriptEventData[i];
        if(!data.hasOwnProperty("command"))continue;
        if(!data.hasOwnProperty("value"))continue;
        switch (data.command) {
            case "getRepoUrls":
                if(data.value instanceof Array){
                    var html = "";
                    for(var i = 0;i < data.value.length; i++){
                        html += '
' + data.value[i] + '
';
                    }
                    $("tbody#activerepolist").html(html);
                    repoUrls = data.value;
                    renderRepoList();
                    getRepos();
                }
                break;
            case "getRunningScripts":
                var html = "";
                for(var i in data.value){
                    var run = data.value[i];
                    html += '
' + run.name + '
';
                }
                $("tbody#runningscripts").html(html);
                break;
            case "getRepositories":
                    repositories = data.value;
                    renderRepositories();
                break;
            case "getActiveScripts":
                    activeScripts = data.value;
                    renderRepositories();
                break;
            case "getRepoList":
                repoList = data.value;
                renderRepoList();
                break;
        }
    }
}
<commit_msg>Debug finished, STUPID CACHING<commit_after>var EventBridge;
var WebChannel;
$(document).ready(function(){
    document.addEventListener("contextmenu", function(event) {
        event.preventDefault();
    }, false);
    WebChannel = new QWebChannel(qt.webChannelTransport, function (channel) {
        EventBridge = WebChannel.objects.eventBridgeWrapper.eventBridge;
        webEventBridgeCallback(EventBridge);
    });
    $('input.searchbox').on('keyup paste change',function(){filterSearch(this)});

});

var repoList = [];

function testObj(obj,head){
    var o = {};
    for(var i in head){
        if(!obj.hasOwnProperty(head[i]))return false;
        o[head[i]] = obj[head[i]];
    }
    return o;
}

function getRepoListings(){
    //alert("REPOS");
    //return;
    $.ajax({
        url: "repos.json",
        success: function(data){
            if(!(data instanceof Object)){
                //alert("Not Object");
                data = JSON.parse(data);
            }
            //else alert("OBJECT");
            webEvent({command:"setRepoList",value:data});
        },
        error: function(XMLHttpRequest, textStatus, errorThrown) {
            alert("Status: " + textStatus);
            alert("Error: " + errorThrown);
        }
    });
}

function renderRepoList(){
    var html = "";
    for(var k in repoList){
        var repo = repoList[k];
        if(repoUrls.indexOf(repo.url) < 0){
            html += '
' + repo.name + '
';
        }
    }
    $("tbody#repolist").html(html);
}

function webEventBridgeCallback(eb){
    if (EventBridge !== undefined) {
        EventBridge.scriptEventReceived.connect(scriptEvent);
        loadData();
    }
}

function getRepos()
{
    repositories = {};
    for(var i = 0; i < repoUrls.length; i++){
        var url = repoUrls[i];
        var repository = {};
        repository["categories"] = {};
        repository["packages"] = {};
        $.ajax({
            url: url,
            success: function(response){
                data = JSON.parse(response);
                repositories[url] = data;
            },
            async: false
        });
    }
    debug(repositories);
    webEvent({command:"setRepositories",value:repositories});
}

function renderRepositories(){
    var cats = "";
    var repos = "";
    var count = 0;
    var repoCount = 0;
    for(var k in repositories){
        var repo = repositories[k];
        repos += renderRepo(repo,repoCount++,k);
        for(var l in repo.categories){
            if(count == 0){
                cats += '
';
            }
            cats += '
';
            var category = repo.categories[l];
            cats += renderCategory(l,category,repo.packages,repo.meta,k);
            cats += "
";
            ++count;
            if(count == 2){
                cats += "
";
                count = 0;
            }
        }
    }
    if(count != 0){
        cats += "
";
    }

    $("#debugtext").html("
" + cats.replace("<","<").replace(">",">") + "
");

    $("div#categorieslist").html(cats);
    $("div#repolist").html(repos);
}

function renderCategory(cat,category,packages,repo,repoKey){
    var html = '

' +
        category.name + '
Active <input type="checkbox" ' +
        (isActiveCategory(repoKey,cat) ? ' checked="checked" ' : "") +
        'data-repo="' +  repoKey + '" data-cat="' + cat + '" class="catcheck"/>
' +
        '

' + category.description +
        '

' +
        '' + repo.name +
        '

';
    return html;
}

function filterSearch(elem){
    var search = "." + $(elem).data("search");
    var filter = $(elem).val();
    if(filter.length < 1){
        $(search).show();
        $(search + "-hide").show();
        return;
    }
    $(search + "-hide").hide();
    $(search).hide();
    $(search + '[data-tags*="' + filter + '"]').show();

}

function renderRepo(repo,c,repoKey){

    var tags = [];
    for(var k in repo.packages){
        var tgs = repo.packages[k].tags;
        for(var t in tgs){
            if(tags.indexOf(tgs[t]) < 0){
                tags.push(tgs[t]);
            }
        }
    }

    var html = '

' +
        repo.meta.name + '
Active ' +
        '<input type="checkbox" onchange="checkAllPkg(this,' + c + ');" ' +
        (isActivePkg(repoKey,"") ? 'checked="checked" ' : "") + 'class="repocheck" data-repo="' + repoKey + '" />
' +
        '

';

        //$(this).parent().siblings('.panel-body').eq(0).children('.pkgcheck').prop("checked",true)
    html += renderPackages(repo.packages, c,repoKey);

    html += '

' +
        '' + repo.meta.name +
        '

';
    return html;
}
function renderPackages(pkgs, c, repoKey){
    var html = "

";
    for(var k in pkgs){
        html += renderPackage(pkgs[k],k,c,repoKey);
    }
    return html + "

";
}

function renderPackage(pkg,k,c,repoKey){
    return '
<input type="checkbox" data-pkg="' + k + '" ' +
        (isActivePkg(repoKey,k) ? 'checked="checked" ' : "") +
        'data-repo="' + repoKey + '" ' +
        'class="pkgcheck pkgcheck-' + c + '" />	' + pkg.name + "
";
}

function post(val){
    alert(JSON.stringify(val));
}

function checkAllPkg(elem,c){
    $(".pkgcheck-" + c).each(function(index){
        $(this).prop("checked",$(elem).prop("checked"));
    });
}

function applyScripts(){
    var scripts = [];
    $("input.repocheck").each(function(i){
        if($(this).prop("checked")){
            scripts.push($(this).data("repo"));
        }
    });
    $("input.pkgcheck").each(function(i){
        if($(this).prop("checked")){
            var repo = $(this).data("repo");
            if(scripts.indexOf(repo) < 0){
                scripts.push(repo + ">" + $(this).data("pkg"));
            }
        }
    });
    var categories = [];
    $("input.catcheck").each(function(i){
        if($(this).prop("checked")){
            categories.push($(this).data("repo") + ">" + $(this).data("cat"));
        }
    });
    webEvent({command:"setActiveScripts",value:{scripts:scripts,categories:categories}});
}

var repoUrls = [];

function command(typ){
    return {command:typ};
}

function loadData()
{
    repoUrls = [];
    //getRepoListings();
    webEvent([command("getRepoList"),command("getRepoUrls"),command("getActiveScripts"),command("getRepositories"),command("getRunningScripts")]);
}

function webEvent(val){
    if(EventBridge !== undefined){
        EventBridge.emitWebEvent(JSON.stringify(val));
    }
}

function debug(data){
    //alert(JSON.stringify(data));
    $("#debugtext").html(JSON.stringify(data));
}

function removeRepo(repo){
    webEvent({command:"removeRepoUrl",value:repo});
}

function addRepoUrl(url){
    webEvent({command:"addRepoUrl",value:url});
}

function addRepo(){
    var newrepo = $("input#newrepo").val();
    if(newrepo.length < 5)return;
    $("input#newrepo").val("");
    addRepoUrl(newrepo);
}
var activeScripts = null;

function isActivePkg(repo,pkg){
    if(activeScripts == null) return false;
    return (activeScripts.scripts.indexOf(repo + ">" + pkg) >= 0 || activeScripts.scripts.indexOf(repo) >= 0);
}

function isActiveCategory(repo,cat){
    if(activeScripts == null) return false;
    return (activeScripts.categories.indexOf(repo + ">" + cat) >= 0);
}

function getRunningScripts(){
    webEvent({command:"getRunningScripts"});
}

function stopScript(scr){
    webEvent({command:"stopScript",value:scr});
}

function refreshScript(scr){
    webEvent({command:"refreshScript",value:scr})
}

function reset(){
    webEvent(command("reset"));
}

function scriptEvent(scriptEventData){
    //alert(scriptEventData);
    scriptEventData = JSON.parse(scriptEventData);
    if(!(scriptEventData instanceof Array)){
        scriptEventData = [scriptEventData];
    }
    for(var i = 0;i < scriptEventData.length; i++){
        data = scriptEventData[i];
        if(!data.hasOwnProperty("command"))continue;
        if(!data.hasOwnProperty("value"))continue;
        switch (data.command) {
            case "getRepoUrls":
                if(data.value instanceof Array){
                    var html = "";
                    for(var i = 0;i < data.value.length; i++){
                        html += '
' + data.value[i] + '
';
                    }
                    $("tbody#activerepolist").html(html);
                    repoUrls = data.value;
                    renderRepoList();
                    getRepos();
                }
                break;
            case "getRunningScripts":
                var html = "";
                for(var i in data.value){
                    var run = data.value[i];
                    html += '
' + run.name + '
';
                }
                $("tbody#runningscripts").html(html);
                break;
            case "getRepositories":
                    repositories = data.value;
                    renderRepositories();
                break;
            case "getActiveScripts":
                    activeScripts = data.value;
                    renderRepositories();
                break;
            case "getRepoList":
                repoList = data.value;
                renderRepoList();
                break;
        }
    }
}
<|endoftext|>