<commit_before>// **Github:** https://github.com/teambition/ilog
//
// **License:** MIT
'use strict'

const format = require('util').format
const jlog   = require('../util/jcolorz')
const ccase  = require('../string/sentenceCase')
const slice  = require('../array/slice')

const levels = [
  'FATAL',    // level 0
  'CRITICAL', // level 1
  'ERROR',    // level 2
  'WARNING',  // level 3
  'ALERT',    // level 4
  'NOTICE',   // level 5
  'INFO',     // level 6
  'DEBUG'     // level 7
  ]

function ilog () {
  if (arguments.length) {
    ilog._stdout.write(ilog._assembleLog(format.apply(null, arguments)))
  }
}

ilog.display = true
ilog.level = 7
ilog.levels = levels.slice()

// ilog.fatal, ilog.critical, ilog.error, ilog.warning, ilog.alert
levels.slice(0, 5).map((level, index) => {
  ilog[level.toLowerCase()] = function (error, stack) {
    if (error != null && index <= ilog.level) {
      // allow the ability to pass a debugging message of this level
      if (typeof error === 'string') error = {message: error}
      if (stack) error.stack = ilog._errorify(stack)

      error.name = ccase(level)

      if (ilog.display) {
        // reformatting output for jcolorz
        // error = ilog._stringify(ilog._errorify(error))
        error = ilog._errorify(error)

        ilog._stderr.write(ilog._assembleLog(error.message, '\u001b[31m'+level+'\u001b[39m', ilog._time(new Date())))
        jlog(error)
      }

      else {
        error = ilog._stringify(ilog._errorify(error))
        ilog._stderr.write(ilog._assembleLog(error, level, ilog._time(new Date())))
      }
    }
  }
})

// ilog.notice, ilog.info
levels.slice(5, 7).map((level, index) => {
  index += 5
  ilog[level.toLowerCase()] = function (message) {
    if (message != null && index <= ilog.level) {
      message = ilog._stringify(message)
      ilog._stdout.write(ilog._assembleLog(message, '\u001b[90m'+level+'\u001b[39m', ilog._time(new Date())))
    }
  }
})

ilog.debug = function () {
  // ilog.level === -1 turns off all levels
  // ilog.level === -2 turns on debug logging
  if (arguments.length && (ilog.level >= 7 || ilog.level === -2)) {
    let messages

    if (arguments.length === 1) {
      messages = ilog._stringify(arguments[0])
    }

    else if (arguments.length === 2
      && typeof arguments[1] === 'object'
      && 'name' in arguments[1]
      && 'message' in arguments[1]
    ) {
      messages = arguments[0]
      var stack = {
        name: 'Debug',
        message: arguments[0],
        stack: ilog._errorify(arguments[1])
      }
    }

    else messages = format.apply(null, arguments)

    ilog._stdout.write(ilog._assembleLog(messages, '\u001b[34mDEBUG\u001b[39m', ilog._time(new Date())))
    if (stack) jlog(stack)
  }
}

ilog.trace = function () {
  if (arguments.length && ilog.level >= 8) {
    let messages = format.apply(null, arguments)

    ilog._stdout.write(ilog._assembleLog(messages, 'LOGR', ilog._time(new Date())))
  }
}

ilog.assert = function (expression, label) {
  var title = 'Assertion expression'
  var stack = {
    name: 'Assert',
    message: label,
    result: !!expression
  }

  if (!!expression) ilog.debug(title, stack)
  else ilog.error(title, stack)
}

ilog.auto = function (error) {
  if (error instanceof Error) return ilog.error(error)
  let args = slice(arguments, +(error == null))
  if (args.length === 1) ilog.info(args[0])
  else if (args.length > 1) ilog.debug.apply(null, args)
}

ilog.log = ilog
ilog._stdout = process.stdout
ilog._stderr = process.stderr
ilog._procname = process.argv[1].split('/').pop()
ilog._pointer = {
  tick: '✔',
  check: '√',
  cross: '✖',
  star: '★',
  bullet: '*',
  info: 'i',
  info2: 'ℹ',
  warning: '‼',
  warning2: '⚠',
  clip: '❯',
  single: '›',
  double: '»',
  arrowUp: '↑',
  arrowDown: '↓',
  arrowLeft: '←',
  arrowRight: '→',
  radioOn: '◉',
  radioOff: '◯',
}

ilog._time = function (time) {
  return `${ilog._procname} ${ilog._pointer.double}`
  // making generic
  // return `[${time.toISOString()}]`
}

ilog._stringify = function (obj) {
  try {
    return JSON.stringify(obj)
  } catch (e) {
    return format(obj)
  }
}

ilog._assembleLog = function (log, level, time) {
  if (level) log = `${level} ${log}`

  // doing this to enable "time" to be configured as
  // a generic component prompt
  if (time) log = `${time} ${log}\n`
  else log = `${ilog._time()} ${log}\n`

  return log
}

ilog._errorify = function (error) {
  return new Errorify(error)
}

function Errorify (error) {
  this.name = error.name || 'Error'
  this.message = error.message || format(error)

  if (error.code) this.code = error.code
  if (error.errno) this.errno = error.errno
  if (error.status) this.status = error.status
  if (error.syscall) this.syscall = error.syscall
  if (!Array.isArray(error)) {
    Object.keys(error).map((key) => {
      if (!this[key]) this[key] = error[key]
    })
  }
  if (error.stack) this.stack = error.stack
}

module.exports = ilog
<commit_msg>update debug/ilog -- refactor complete<commit_after>// adopted from: ilog <https://github.com/teambition/ilog>
// Copyright (c) 2015 Teambition (License: MIT)

'use strict'

const format = require('util').format
const jlog   = require('../util/jcolorz')
const ccase  = require('../string/sentenceCase')
const map    = require('../array/map')
const slice  = require('../array/slice')

const levels = [
  'FATAL',    // level 0
  'CRITICAL', // level 1
  'ERROR',    // level 2
  'WARNING',  // level 3
  'ALERT',    // level 4
  'NOTICE',   // level 5
  'INFO',     // level 6
  'DEBUG'     // level 7
]

const clrs = {
  black   : [30, 39],
  gray    : [90, 39],
  grey    : [90, 39],
  red     : [31, 39],
  green   : [32, 39],
  yellow  : [33, 39],
  blue    : [34, 39],
  magenta : [35, 39],
  cyan    : [36, 39],
  white   : [37, 39]
}

// Original version
function ilog () {
  if (arguments.length) {
    ilog._stdout.write(ilog._assembleLog(format.apply(null, arguments)))
  }
}

// Own version: meant for raw string output to log
ilog.log = function () {
  if (arguments.length) {
    ilog._stdout.write(ilog._assembleLog(slice(arguments).join(' ')))
  }
}

// options for display, preserving the original functionality by reversing values.
ilog.display = {
  colors: true,
  dates: false
}

ilog.level = 7
ilog.levels = levels.slice()

// ilog.fatal, ilog.critical, ilog.error, ilog.warning, ilog.alert
map(levels.slice(0, 5), (level, index) => {
  ilog[level.toLowerCase()] = function (error, stack) {
    if (error != null && index <= ilog.level) {
      // allow the ability to pass debugging messages as strings
      if (typeof error === 'string') error = {message: error}
      if (stack) error.stack = ilog._errorify(stack)

      error.name = ccase(level)

      let color = ilog.display.colors ? ilog._color(level, 'red') : level
      let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

      error = ilog.display.colors
        ? ilog._errorify(error)
        : ilog._stringify(ilog._errorify(error))

      let type = function (obj) {
        return typeof obj === 'string'
          ? obj
          : obj.message
      }

      ilog._stderr.write(ilog._assembleLog(type(error), color, label))
      if (ilog.display.colors) jlog(error)
    }
  }
})

// ilog.notice, ilog.info
map(levels.slice(5, 7), (level, index) => {
  index += 5
  ilog[level.toLowerCase()] = function (message) {
    if (message != null && index <= ilog.level) {
      message = ilog._stringify(message)

      let color = ilog.display.colors ? ilog._color(level, 'grey') : level
      let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

      ilog._stdout.write(ilog._assembleLog(message, color, label))
    }
  }
})

ilog.debug = function () {
  // ilog.level === -1 turns off all levels
  // ilog.level === -2 turns on debug logging only
  if (arguments.length && (ilog.level >= 7 || ilog.level === -2)) {
    let messages

    if (arguments.length === 1) {
      messages = ilog._stringify(arguments[0])
    }

    else if (arguments.length === 2
      && typeof arguments[1] === 'object'
      && 'name' in arguments[1]
      && 'message' in arguments[1]
    ) {
      messages = arguments[0]
      var stack = {
        name: 'Debug',
        message: arguments[0],
        stack: ilog._errorify(arguments[1])
      }
    }

    else messages = format.apply(null, arguments)

    let color = ilog.display.colors
      ? ilog._color('DEBUG', 'blue')
      : 'DEBUG'

    let label = ilog.display.dates
      ? ilog._label(new Date())
      : ilog._label()

    ilog._stdout.write(ilog._assembleLog(messages, color, label))
    if (ilog.display.colors && stack) jlog(stack)
  }
}

ilog.trace = function () {
  if (arguments.length && ilog.level >= 8) {
    // contruct components
    let messages = format.apply(null, arguments)
    let color = ilog.display.color ? ilog._color('LOGR', 'yellow') : 'LOGR'
    let label = ilog.display.dates ? ilog._label(new Date()) : ilog._label()

    // compose message
    let assemble = ilog._assembleLog(messages, color, label)

    // log message
    ilog._stdout.write(assemble)
  }
}

ilog.assert = function (expression, label) {
  let title = 'Assertion expression'
  let stack = {
    name: 'Assert',
    message: label,
    result: !!expression
  }

  if (!!expression) ilog.debug(title, stack)
  else ilog.alert(title, stack)
}

ilog.auto = function (error) {
  if (error instanceof Error) return ilog.error(error)
  let args = slice(arguments, +(error == null))
  if (args.length === 1) ilog.info(args[0])
  else if (args.length > 1) ilog.debug.apply(null, args)
}

ilog._stdout = process.stdout
ilog._stderr = process.stderr
ilog._procname = process.argv[1].split('/').pop()
ilog._pointer = {
  tick: '✔',
  check: '√',
  cross: '✖',
  star: '★',
  bullet: '*',
  info: 'i',
  info2: 'ℹ',
  warning: '‼',
  warning2: '⚠',
  clip: '❯',
  single: '›',
  double: '»',
  arrowUp: '↑',
  arrowDown: '↓',
  arrowLeft: '←',
  arrowRight: '→',
  radioOn: '◉',
  radioOff: '◯',
}

ilog._color = function (label, color) {
  return `\u001b[${clrs[color][0]}m${label}\u001b[${clrs[color][1]}m`
}

ilog._label = function (label) {
  return `${ilog._procname} ${ilog._pointer.double}`
}

ilog._assembleLog = function (log, level, label) {
  if (level) log = `${level} ${log}`
  if (label) log = `${label} ${log}\n`
  else log = `${ilog._label()} ${log}\n`

  return log
}

ilog._stringify = function (obj) {
  try {
    return JSON.stringify(obj)
  } catch (e) {
    return format(obj)
  }
}

ilog._errorify = function (error) {
  return new Errorify(error)
}

function Errorify (error) {
  this.name = error.name || 'Error'
  this.message = error.message || format(error)

  if (error.code) this.code = error.code
  if (error.errno) this.errno = error.errno
  if (error.status) this.status = error.status
  if (error.syscall) this.syscall = error.syscall
  if (!Array.isArray(error)) {
    Object.keys(error).map((key) => {
      if (!this[key]) this[key] = error[key]
    })
  }
  if (error.stack) this.stack = error.stack
}

module.exports = ilog
<|endoftext|>


<commit_before>/* NODE MODULES */
var net = require('net'),
    tcpEventify = require('../utils/tcpEventify');

/** LOCAL OBJECT
 * @property {} -
 */
var FIND = {
    basepath: __dirname + '/../sockets/',
    retry: {
        attempts: 10,
        timeout: {
            local: 100,
            remote: 1000
        }
    }
};

/** MODULE INTERFACE
 *@method {function} -
 */
module.exports = {
    globalNamespace: globalNamespace
};

/*----------------------------------------------------------------------------*/

/**
 * @param
 * @returns
 */
function globalNamespace(name, found) {
    console.log('Searching global namespace "/' + name + '"');
    connectToNamespace(name, found, undefined, FIND.retry.timeout.remote);
}

/**
 * @param
 * @returns
 */
function connectToNamespace(name, found, maxAttempts, retryTimeout) {
    var numAttempts = maxAttempts || FIND.retry.attempts,
        timeout = retryTimeout || FIND.retry.timeout,
        theEventerface,
        attempts = 0,
        socket;

    (function connect() {
        socket = net.connect(FIND.basepath + name + '.sock', function () {
            var eventedSocket = tcpEventify(socket);
            theEventerface = {
                emit: function (eventName, message) {
                    eventedSocket.send(eventName, message);
                },
                on: function (eventName, listener) {
                    eventedSocket.on(eventName, listener);
                }
            };
            found(theEventerface);
        });
        socket.on('error', function (err) {
            if (err.errno === 'ECONNREFUSED') {
                if (++attempts <= numAttempts) {
                    setTimeout(function () {
                        connect();
                    }, timeout);
                }
            }
        });
    })();
}<commit_msg>Added documentation and inline comments, and renamed the found namespace object.<commit_after>/* NODE MODULES */
var net = require('net'),
    tcpEventify = require('../utils/tcpEventify');

/** LOCAL OBJECT
 * @property {string} basepath - The path to look for unix sockets
 * @property {object} retry - Describes the number and delay between connection retries
 */
var FIND = {
    basepath: __dirname + '/../sockets/',
    retry: {
        attempts: 10,
        timeout: {
            local: 100,
            remote: 1000
        }
    }
};

/** MODULE INTERFACE
 *@method {function} globalNamespace - Looks for an existing global namespace
 */
module.exports = {
    globalNamespace: globalNamespace
};

/*----------------------------------------------------------------------------*/

/** Looks for an existing global namespace
 * @param {string} name - The name of the namespace
 * @returns {function} found - A function to be called when the namespace is found
 */
function globalNamespace(name, found) {
    console.log('Searching global namespace "/' + name + '"');
    connectToNamespace(name, found, undefined, FIND.retry.timeout.remote);
}

/** Connects to a unix-socket-based namespace
 * @param {string} name - The name of the namespace
 * @returns {function} found - A function to be called when the namespace is found
 * @param {number} maxAttempts - The max number of connection attempts to be done
 * @param {number} retryTimeout - The delay between unsuccessful connection attempts
 * @returns
 */
function connectToNamespace(name, found, maxAttempts, retryTimeout) {
    var numAttempts = maxAttempts || FIND.retry.attempts,
        timeout = retryTimeout || FIND.retry.timeout,
        namespace,
        attempts = 0,
        socket;

    // Try to connect to the namespace's unix socket server
    (function connect() {
        socket = net.connect(FIND.basepath + name + '.sock', function () {
            var eventedSocket = tcpEventify(socket);
            // Expose the socket methods through the 'emit' and 'on' methods
            // of the namespace object to be returned
            namespace = {
                emit: function (eventName, message) {
                    eventedSocket.send(eventName, message);
                },
                on: function (eventName, listener) {
                    eventedSocket.on(eventName, listener);
                }
            };
            // Return the found namespace object by invoking the callback
            found(namespace);
        });
        socket.on('error', function (err) {
            // Retry on unsuccessful connection attempts
            if (err.errno === 'ECONNREFUSED') {
                if (++attempts <= numAttempts) {
                    setTimeout(function () {
                        connect();
                    }, timeout);
                }
            }
        });
    })();
}<|endoftext|>


<commit_before>import React from 'react';
import d3 from 'd3';
import {MODE} from './Constant';
import WhiteboardBase from './WhiteboardBase';
import Canvas from './Canvas';

export default class Whiteboard extends WhiteboardBase {

    constructor(props) {
        super(props);
        this.state = {
            dataset: [],
            undoStack: [],
            mode: MODE.HAND,
            strokeWidth: 5,
            strokeColor: 'black',
            doingUndo: false,
            doingRedo: false,
        };
    }

    componentDidMount() {
        d3.select('body').on('keydown.body', () => {
            this.emitter.emit('keydown.body', d3.event.keyCode);
        });

        let that = this;
        this.emitter.on('keydown.body', (keyCode) => {
            if (keyCode === 48) { // 0'
                that.toggleMode();
            }
            if (keyCode >= 49 && keyCode <= 57) { // '1' - '9'
                that.changeStrokeWidth(keyCode - 48);
            }
            if (keyCode === 67) { // 'c'
                that.toggleStrokeColor();
            }
        });
        this.emitter.on('mousemove.canvas', (point) => {
            that.pushPoint(point);
        });
        this.emitter.on('click.canvas', (point) => {
            that.toggleMode(point);
        });
        this.emitter.on('undo.pallete', (doing) => {
            that.undoPoint(doing);
        });
        this.emitter.on('redo.pallete', (doing) => {
            that.redoPoint(doing);
        });
    }

    toggleMode(point) {
        if (this.state.mode === MODE.LINE) {
            this.setState({
                mode: MODE.HAND,
            });
        } else {
            const dataset = this.state.dataset;
            dataset.push({
                strokeWidth: this.state.strokeWidth,
                strokeColor: this.state.strokeColor,
                values: point ? [point] : [],
            });
            this.setState({
                mode: MODE.LINE,
                dataset: dataset,
            });
        }
    }

    changeStrokeWidth(width) {
        this.setState({
            strokeWidth: width,
        });
    }

    toggleStrokeColor() {
        if (this.state.strokeColor === 'black') {
            this.setState({
                strokeColor: 'red',
            });
        } else if (this.state.strokeColor === 'red') {
            this.setState({
                strokeColor: 'green',
            });
        } else if (this.state.strokeColor === 'green') {
            this.setState({
                strokeColor: 'blue',
            });
        } else {
            this.setState({
                strokeColor: 'black',
            });
        }
    }

    pushPoint(point) {
        if (this.state.mode === MODE.HAND) {
            return;
        }

        const dataset = this.state.dataset;
        const current = dataset[dataset.length - 1];

        if (current &&
                current.strokeWidth === this.state.strokeWidth &&
                current.strokeColor === this.state.strokeColor) {
            current.values.push(point);
            this.setState({
                dataset: dataset,
                undoStack: [],
            });
        } else {
            dataset.push({
                strokeWidth: this.state.strokeWidth,
                strokeColor: this.state.strokeColor,
                values: [point],
            });
            this.setState({
                dataset: dataset,
                undoStack: [],
            });
        }
    }

    undoPoint(doing) {
        if (doing) {
            const dataset = this.state.dataset;
            const current = dataset[dataset.length - 1];
            const undoStack = this.state.undoStack;

            if (current && current.values.length > 1) {
                const point = current.values.pop();
                const undoOperation = (newState) => {
                    const dataset = this.state.dataset;
                    const current = dataset[dataset.length - 1];
                    current.values.push(point);
                    newState.dataset = dataset;
                    this.setState(newState);
                };
                undoStack.push(undoOperation);
                this.setState({
                    dataset: dataset,
                    undoStack: undoStack,
                    doingUndo: true,
                });

            } else if (current && current.values.length === 1) {
                dataset.pop();
                const undoOperation = (newState) => {
                    const dataset = this.state.dataset;
                    dataset.push(current);
                    newState.dataset = dataset;
                    this.setState(newState);
                };
                undoStack.push(undoOperation);
                this.setState({
                    dataset: dataset,
                    undoStack: undoStack,
                    doingUndo: true,
                });

            } else {
                this.setState({
                    doingUndo: false,
                });
            }
        } else {
            this.setState({
                doingUndo: false,
            });
        }
    }

    redoPoint(doing) {
        if (doing) {
            const undoStack = this.state.undoStack;
            const redoOperation = undoStack.pop();
            if (redoOperation) {
                redoOperation({
                    undoStack: undoStack,
                    doingRedo: true,
                });
            } else {
                this.setState({
                    doingRedo: false,
                });
            }
        } else {
            this.setState({
                doingRedo: false,
            });
        }
    }

    clearPoint() {
        this.setState({
            dataset: [],
            undoStack: [],
        });
    }

    render() {
        return (

                <Canvas {...this.props} {...this.state} />

        );
    }

}
<commit_msg>Remove doingUndo/Redo state<commit_after>import React from 'react';
import d3 from 'd3';
import {MODE} from './Constant';
import WhiteboardBase from './WhiteboardBase';
import Canvas from './Canvas';

export default class Whiteboard extends WhiteboardBase {

    constructor(props) {
        super(props);
        this.state = {
            dataset: [],
            undoStack: [],
            mode: MODE.HAND,
            strokeWidth: 5,
            strokeColor: 'black',
        };
    }

    componentDidMount() {
        d3.select('body').on('keydown.body', () => {
            this.emitter.emit('keydown.body', d3.event.keyCode);
        });

        let that = this;
        this.emitter.on('keydown.body', (keyCode) => {
            if (keyCode === 48) { // 0'
                that.toggleMode();
            }
            if (keyCode >= 49 && keyCode <= 57) { // '1' - '9'
                that.changeStrokeWidth(keyCode - 48);
            }
            if (keyCode === 67) { // 'c'
                that.toggleStrokeColor();
            }
        });
        this.emitter.on('mousemove.canvas', (point) => {
            that.pushPoint(point);
        });
        this.emitter.on('click.canvas', (point) => {
            that.toggleMode(point);
        });
        this.emitter.on('undo.pallete', () => {
            that.undoPoint();
        });
        this.emitter.on('redo.pallete', () => {
            that.redoPoint();
        });
    }

    toggleMode(point) {
        if (this.state.mode === MODE.LINE) {
            this.setState({
                mode: MODE.HAND,
            });
        } else {
            const dataset = this.state.dataset;
            dataset.push({
                strokeWidth: this.state.strokeWidth,
                strokeColor: this.state.strokeColor,
                values: point ? [point] : [],
            });
            this.setState({
                mode: MODE.LINE,
                dataset: dataset,
            });
        }
    }

    changeStrokeWidth(width) {
        this.setState({
            strokeWidth: width,
        });
    }

    toggleStrokeColor() {
        if (this.state.strokeColor === 'black') {
            this.setState({
                strokeColor: 'red',
            });
        } else if (this.state.strokeColor === 'red') {
            this.setState({
                strokeColor: 'green',
            });
        } else if (this.state.strokeColor === 'green') {
            this.setState({
                strokeColor: 'blue',
            });
        } else {
            this.setState({
                strokeColor: 'black',
            });
        }
    }

    pushPoint(point) {
        if (this.state.mode === MODE.HAND) {
            return;
        }

        const dataset = this.state.dataset;
        const current = dataset[dataset.length - 1];

        if (current &&
                current.strokeWidth === this.state.strokeWidth &&
                current.strokeColor === this.state.strokeColor) {
            current.values.push(point);
            this.setState({
                dataset: dataset,
                undoStack: [],
            });
        } else {
            dataset.push({
                strokeWidth: this.state.strokeWidth,
                strokeColor: this.state.strokeColor,
                values: [point],
            });
            this.setState({
                dataset: dataset,
                undoStack: [],
            });
        }
    }

    undoPoint() {
        const dataset = this.state.dataset;
        const current = dataset[dataset.length - 1];
        const undoStack = this.state.undoStack;

        if (current && current.values.length > 1) {
            const point = current.values.pop();
            const undoOperation = (newState) => {
                const dataset = this.state.dataset;
                const current = dataset[dataset.length - 1];
                current.values.push(point);
                newState.dataset = dataset;
                this.setState(newState);
            };
            undoStack.push(undoOperation);
            this.setState({
                dataset: dataset,
                undoStack: undoStack,
            });

        } else if (current && current.values.length === 1) {
            dataset.pop();
            const undoOperation = (newState) => {
                const dataset = this.state.dataset;
                dataset.push(current);
                newState.dataset = dataset;
                this.setState(newState);
            };
            undoStack.push(undoOperation);
            this.setState({
                dataset: dataset,
                undoStack: undoStack,
            });
        }
    }

    redoPoint() {
        const undoStack = this.state.undoStack;
        const redoOperation = undoStack.pop();
        if (redoOperation) {
            redoOperation({
                undoStack: undoStack,
            });
        }
    }

    clearPoint() {
        this.setState({
            dataset: [],
            undoStack: [],
        });
    }

    render() {
        return (

                <Canvas {...this.props} {...this.state} />

        );
    }

}
<|endoftext|>


<commit_before>$((function () {
  displaySubHeader();

  $('#customers-main').slick({
    infinite: false,
    dots: true,
  });
}));

function displaySubHeader() {
  let inAboutSection = () =>
    $(window).scrollTop() + 101 >= $("#about-portfolio").offset().top &&
    $(window).scrollTop() + 160 < $("#team").offset().top;

  $(window).scroll(function() {
    if (inAboutSection()) {
      setTimeout(function() {
        if (inAboutSection()) {
          $(".subheader-section").css({
            display: "block"
          });
        }
      }, 1000);
    } else {
      $(".subheader-section").css({
        display: "none"
      });
    }

    if (
      $(window).scrollTop() + 120 >= $("#about-portfolio").offset().top &&
      $(window).scrollTop() + 200 < $("#about-hackathons").offset().top
    ) {
      $("#portfolio-a").addClass("selected-a");
      $("#portfolio-a-mobile").addClass("selected-a");
    } else {
      $("#portfolio-a")
        .removeClass("selected-a")
        .blur();
      $("#portfolio-a-mobile")
        .removeClass("selected-a")
        .blur();
    }

    if (
      $(window).scrollTop() + 120 >= $("#about-hackathons").offset().top &&
      $(window).scrollTop() + 200 < $("#about-customers").offset().top
    ) {
      $("#hackathon-a").addClass("selected-a");
      $("#hackathon-a-mobile").addClass("selected-a");
    } else {
      $("#hackathon-a")
        .removeClass("selected-a")
        .blur();
      $("#hackathon-a-mobile")
        .removeClass("selected-a")
        .blur();
    }

    if (
      $(window).scrollTop() + 180 >= $("#about-customers").offset().top &&
      $(window).scrollTop() + 200 < $("#team").offset().top
    ) {
      $("#customers-a").addClass("selected-a");
      $("#customers-a-mobile").addClass("selected-a");
    } else {
      $("#customers-a")
        .removeClass("selected-a")
        .blur();
      $("#customers-a-mobile")
        .removeClass("selected-a")
        .blur();
    }
  });
}
<commit_msg>CML-63: changed deprecated syntax<commit_after>$((function () {
  displaySubHeader();

  $('#customers-main').slick({
    infinite: false,
    dots: true,
  });
}));

function displaySubHeader() {
  let inAboutSection = () =>
    $(window).scrollTop() + 101 >= $("#about-portfolio").offset().top &&
    $(window).scrollTop() + 160 < $("#team").offset().top;

  $(window).on("scroll", (function() {
    if (inAboutSection()) {
      setTimeout(function() {
        if (inAboutSection()) {
          $(".subheader-section").css({
            display: "block"
          });
        }
      }, 1000);
    } else {
      $(".subheader-section").css({
        display: "none"
      });
    }

    if (
      $(window).scrollTop() + 120 >= $("#about-portfolio").offset().top &&
      $(window).scrollTop() + 200 < $("#about-hackathons").offset().top
    ) {
      $("#portfolio-a").addClass("selected-a");
      $("#portfolio-a-mobile").addClass("selected-a");
    } else {
      $("#portfolio-a")
        .removeClass("selected-a")
        .trigger("blur");
      $("#portfolio-a-mobile")
        .removeClass("selected-a")
        .trigger("blur");
    }

    if (
      $(window).scrollTop() + 120 >= $("#about-hackathons").offset().top &&
      $(window).scrollTop() + 200 < $("#about-customers").offset().top
    ) {
      $("#hackathon-a").addClass("selected-a");
      $("#hackathon-a-mobile").addClass("selected-a");
    } else {
      $("#hackathon-a")
        .removeClass("selected-a")
        .trigger("blur");
      $("#hackathon-a-mobile")
        .removeClass("selected-a")
        .trigger("blur");
    }

    if (
      $(window).scrollTop() + 180 >= $("#about-customers").offset().top &&
      $(window).scrollTop() + 200 < $("#team").offset().top
    ) {
      $("#customers-a").addClass("selected-a");
      $("#customers-a-mobile").addClass("selected-a");
    } else {
      $("#customers-a")
        .removeClass("selected-a")
        .trigger("blur");
      $("#customers-a-mobile")
        .removeClass("selected-a")
        .trigger("blur");
    }
  }));
}
<|endoftext|>


<commit_before>/**
 *  class Element.Layout
**/
Element.Layout = Class.create({
  /**
   *  new Element.Layout(element[, options])
   *  Returns a versatile measurement object that quacks several ways. Can be
   *  coerced into a hash, an object, or JSON.
  **/
  initialize: function(element, options) {
    this.element = $(element);
    this.options = Object.extend({
      dimensions: true,
      offsets:    false
    }, options || {});

    this.layout = new Hash();

    this.getDimensions();
  },

  getDimensions: function() {
    var element = this.element,
        display = element.getStyle('display'),
        noOffsetWidth;

    // The style object is inaccessible in Safari <= 2.0 when the element
    // is hidden.
    var isNotShown = display === "none" || display === null;
    var isTable = element.tagName.toUpperCase() == 'TABLE';

    // If the element is hidden, we show it for an instant
    // to grab its dimensions.
    if (isNotShown) {
      var style = element.style;
      var originalStyle = {
        visibility: style.visibility,
        position:   style.position,
        display:    style.display
      };

      Object.extend(style, {
        visibility: 'hidden',
        position:   'absolute',
        display:    'block'
      });
    }

    if (this.options.dimensions === true) {
      // clientWidth includes margin offsets of a table in Mozilla,
      // set offsets to 0, get width value, then revert back
      if (isTable) {
        var originalLeft = element.style.marginLeft;
        var originalRight = element.style.marginRight;
        element.style.marginLeft = '0px';
        element.style.marginRight = '0px';
        noOffsetWidth = element.clientWidth;
        element.style.marginLeft = originalLeft;
        element.style.marginRight = originalRight;
      }

      var paddingBox = {
        width:  noOffsetWidth || element.clientWidth,
        height: element.clientHeight
      };

      // For backwards-compatibility, the returned object will have
      // width and height equal to the padding-box values.
      this.layout.update(paddingBox);

      this.layout.set('paddingBox', paddingBox);

      var padding = this.getStyleValuesFor('padding', 'trbl');
      this.layout.set('padding', padding);

      var contentBox = {
        width:  paddingBox.width  - padding.left - padding.right,
        height: paddingBox.height - padding.top  - padding.bottom
      };

      this.layout.set('contentBox', contentBox);

      var border = this.getStyleValuesFor('border', 'trbl');
      this.layout.set('border', border);

      var borderBox = {
        width:  paddingBox.width  + border.left + border.right,
        height: paddingBox.height + border.top  + border.bottom
      };

      this.layout.set('borderBox', borderBox);

    } // dimensions

    if (this.options.offsets === true) {
      var offsets = {};

      offsets.positioned = this.offset();
      offsets.viewport   = this.viewportOffset();
      offsets.scroll     = this.scrollOffset();
      offsets.document   = this.documentOffset();

      this.layout.update('offsets', offsets);
    } // offsets

    // If we altered the element's styles, return them to their
    // original values.
    if (isNotShown) {
      Object.extend(style, originalStyle);
    }

    return this.layout;
  },

  // Converts a raw CSS value like '9px' or '1em' to
  // a number (in pixels).
  // IE: Redefined below
  cssToNumber: function(property) {
    return window.parseFloat(this.element.getStyle(property));
  },

  // sidesNeeded argument is a string.
  // "trbl" = top, right, bottom, left
  // "tb"   = top, bottom
  getStyleValuesFor: function(property, sidesNeeded) {
    var sides = $w('top bottom left right');
    var propertyNames = sides.map( function(s) {
      return property + s.capitalize();
    });

    if (property === 'border') {
      propertyNames = propertyNames.map( function(p) {
        return p + 'Width';
      });
    }

    var values = {};

    sides.each( function(side, index) {
      if (!sidesNeeded.include(side.charAt(0))) return;
      values[side] = this.cssToNumber(propertyNames[index]);
    }, this);

    return values;
  },

  toObject: function() {
    return this.layout.toObject();
  },

  toHash: function() {
    return this.layout;
  },

  toJSON: function() {
    return this.layout.toJSON();
  },

  toCSS: function() {
    var css = {}, d = this.layout;
    if (this.options.dimensions) {
      var margins = $w('top right bottom left').map( function(side) {
        return d.margin[side] + 'px';
      }).join(' ');
      var padding = $w('top right bottom left').map( function(side) {
        return d.padding[side] + 'px';
      }).join(' ');

      Object.extend(css, {
        width:   d.contentBox.width  + 'px',
        height:  d.contentBox.height + 'px',
        margin:  margins,
        padding: padding
      });
    }

    if (this.options.offsets) {
      Object.extend(css, {
        left: d.offset.left + 'px',
        top:  d.offset.top  + 'px'
      });
    }

    return css;
  },

  /**
   *  Element.Layout#dimensions() -> Element.Coordinates
   *  Reports the dimensions of the given element.
  **/
  dimensions: function() {
    var box = this.layout.get('contentBox');
    return { width: box.width, height: box.height };
  },

  /**
   *  Element.Layout#offset([element=document]) -> Element.Coordinates
   *  Positioned offset. Measured from offset parent.
  **/
  offset: function() {
    return this.layout.offsets.positioned;
  },

  /**
   *  Element.Layout#viewportOffset() -> Element.Coordinates
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of the viewport.
  **/
  viewportOffset: function() {
    var element = this.element;

    // IE and FF >= 3 provide getBoundingClientRect, a much quicker path
    // to retrieving viewport offset.
    if (element.getBoundingClientRect) {
      var d = element.getBoundingClientRect();
      return { left: Math.round(d.left), top: Math.round(d.top) };
    }

    var valueT = 0, valueL = 0, element = this.element;

    // First collect cumulative offsets
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent == document.body &&
        Element.getStyle(element, 'position') === 'absolute') break;

    } while (element = element.offsetParent);

    // Then subtract cumulative scroll offsets
    element = this.element;
    do {
      if (!Prototype.Browser.Opera || element.tagName.toUpperCase() == 'BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return { left: valueL, top: valueT };
  },

  /**
   *  Element.Layout#documentOffset() -> Element.Coords
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of its containing document.
  **/
  documentOffset: function() {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return Element.Layout.normalize({ left: valueL, top: valueT });
  },

  /**
   *  Element.Layout#offsetParent() -> Element
   *  Returns the element's positioning context — the nearest ancestor
   *  with a CSS "position" value other than "static."
  **/
  offsetParent: function(element) {
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element !== document.body)
      if (Element.getStyle(element, 'position') !== 'static')
        return element;

    return $(document.body);
  },

  /**
   *  Element.Layout#scrollOffset(@element) -> Object
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of its containing document, compensating for the scroll
   *  offsets of any ancestors.
  **/
  scrollOffset: function(element) {
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return Element.Layout.normalize({ left: valueL, top: valueT });
  }

});

if (Prototype.Browser.IE) {
  Element.Layout.addMethods({
    // IE gives the literal cascaded style, not the computed style.
    // We need to ensure pixel values are returned.
    cssToNumber: function(property) {
      var value = this.element.getStyle(property);

      if ((/^\d+(px)?$/i).test(value))
        return window.parseFloat(value);

      // If the unit is something other than a pixel (em, pt, %), set it on
      // something we can grab a pixel value from.
      var element = this.element;

      var sl = element.style.left, rsl = element.runtimeStyle.left;

      element.runtimeStyle.left = element.currentStyle.left;
      element.style.left = value || 0;

      value = element.style.pixelLeft;

      element.style.left = sl;
      element.runtimeStyle.left = rsl;

      return value;
    }
  });
}

// Acts like an array for backwards-compatibility.
Element.Layout.normalize = function(obj) {
  var arr = [];
  arr[0] = ('left' in obj) ? obj.left : obj.width;
  arr[1] = ('top'  in obj) ? obj.top  : obj.height;
  return Object.extend(arr, obj);
};

Object.extend(Element.Methods, {
  /**
   *  Element#getLayout(@element[, options]) -> Object
   *  Reports the dimensions and offsets of the given element.
   *
   *  By default, `getLayout` will return as much information about the
   *  element as possible: dimensions for the content, padding, and border
   *  boxes; and viewport, cumulative, scroll, and positioned offsets.
   *  The `options` argument can be used to bypass checks you don't need
   *  when speed is of the utmost importance.
  **/
  getLayout: function(element, options) {
    return new Element.Layout(element, options).toObject();
  },

  getDimensions: function(element) {
    return new Element.Layout(element, { offsets: false }).toObject();
  },

  getHeight: function(element) {
    return Element.getDimensions(element).height;
  },

  getWidth: function(element) {
    return Element.getDimensions(element).width;
  },

  getOffsets: function(element) {
    return new Element.Layout(element, { dimensions: false}).toObject();
  },

  viewportOffset: function(element) {
    return Element.getOffsets(element).viewport;
  },

  cumulativeOffset: function(element) {
    return Element.getOffsets(element).document;
  },

  /**
   *  Element#cumulativeScrollOffset(@element) -> Object
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of its containing document, compensating for the scroll
   *  offsets of any ancestors.
  **/
  cumulativeScrollOffset: function(element) {
    return Element.getOffsets(element).scroll;
  },

  /**
   *  Element#cumulativeOffset(@element) -> Object
   *  Reports the element's top- and left-distance from its positioning
   *  parent.
  **/
  positionedOffset: function(element) {
    return Element.getOffsets(element).positioned;
  },

  /**
   *  Element#absolutize(@element) -> Element
   *  Switches element from static/relative positioning to absolute
   *  positioning while maintaining the element's size and position.
  **/
  absolutize: function(element) {
    element = $(element);
    if (element.getStyle('position') === 'absolute') return element;

    var offsets = element.positionedOffset();
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    Object.extend(element, {
      _originalLeft:   left - parseFloat(element.style.left || 0),
      _originalTop:    top  - parseFloat(element.style.top  || 0),
      _originalWidth:  element.style.width,
      _originalHeight: element.style.height
    });

    element.setStyle({
      position: 'absolute',
      top:      top + 'px',
      left:     left + 'px',
      width:    width + 'px',
      height:   height + 'px'
    });

    return element;
  },

  /**
   *  Element#relativize(@element) -> Element
   *  Reverts element from absolute positioning to relative positioning
   *  while maintaining the element's size and position.
  **/
  relativize: function(element) {
    element = $(element);
    if (element.getStyle('position') === 'relative') return element;

    if (Object.isUndefined(element._originalTop)) {
      throw "Element#absolutize must be called first.";
    }

    element.setStyle({ position: 'relative' });

    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.setStyle({
      top:      top + 'px',
      left:     left + 'px',
      width:    element._originalHeight + 'px',
      height:   element._originalWidth  + 'px'
    });

    return element;
  },

  /**
   *  Element#getOffsetParent(@element) -> Element
   *  Returns the element's positioning context — the nearest ancestor
   *  with a CSS "position" value other than "static."
  **/
  getOffsetParent: function(element) {
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element !== document.body)
      if (Element.getStyle(element, 'position') !== 'static')
        return element;

    return $(document.body);
  },

  clonePosition: function(element, source) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || { });

    // find page position of source
    source = $(source);
    var sourceLayout = new Element.Layout(source).toCSS();

    if (!options.setHeight) delete sourceLayout.height;
    if (!options.setWidth)  delete sourceLayout.width;
    if (!options.setLeft)   delete sourceLayout.left;
    if (!options.setTop)    delete sourceLayout.top;

    $(element).setStyle(souceLayout);

    return element;
  }
});

document.viewport = {
  /**
   *  document.viewport.getDimensions () -> Object
   *  Returns the height and width of the browser viewport.
  **/
  getDimensions: function() {
    var dimensions = { };
    var B = Prototype.Browser;
    $w('width height').each(function(d) {
      var D = d.capitalize();
      dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
        (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
    });
    return dimensions;
  },

  /**
   *  document.viewport.getWidth() -> Number
   *  Returns the width of the browser viewport.
  **/
  getWidth: function() {
    return this.getDimensions().width;
  },

  /**
   *  document.viewport.getHeight() -> Number
   *  Returns the height of the browser viewport.
  **/
  getHeight: function() {
    return this.getDimensions().height;
  },

  /**
   *  document.viewport.getScrollOffsets() -> Object
   *  Returns the distances the viewport has been scrolled in the
   *  horizontal and vertical directions.
  **/
  getScrollOffsets: function() {
    return Element.Dimensions.normalize({
      left: window.pageXOffset
        || document.documentElement.scrollLeft
        || document.body.scrollLeft,
      top: window.pageYOffset
        || document.documentElement.scrollTop
        || document.body.scrollTop
    });
  }
};
<commit_msg>All dimensions tests pass once again.<commit_after>/**
 *  class Element.Layout
**/
Element.Layout = Class.create({
  /**
   *  new Element.Layout(element[, options])
   *  Returns a versatile measurement object that quacks several ways. Can be
   *  coerced into a hash, an object, or JSON.
  **/
  initialize: function(element, options) {
    this.element = $(element);
    this.options = Object.extend({
      dimensions: true,
      offsets:    true
    }, options || {});

    this.layout = {};
    this.getLayout();
  },

  getLayout: function() {
    var element = this.element,
        display = element.getStyle('display'),
        noOffsetWidth;

    // The style object is inaccessible in Safari <= 2.0 when the element
    // is hidden.
    var isNotShown = display === "none" || display === null;
    var isTable = element.tagName.toUpperCase() == 'TABLE';

    // If the element is hidden, we show it for an instant
    // to grab its dimensions.
    if (isNotShown) {
      var style = element.style;
      var originalStyle = {
        visibility: style.visibility,
        position:   style.position,
        display:    style.display
      };

      Object.extend(style, {
        visibility: 'hidden',
        position:   'absolute',
        display:    'block'
      });
    }

    if (this.options.dimensions === true) {
      // clientWidth includes margin offsets of a table in Mozilla,
      // set offsets to 0, get width value, then revert back
      if (isTable) {
        var originalLeft = element.style.marginLeft;
        var originalRight = element.style.marginRight;
        element.style.marginLeft = '0px';
        element.style.marginRight = '0px';
        noOffsetWidth = element.clientWidth;
        element.style.marginLeft = originalLeft;
        element.style.marginRight = originalRight;
      }

      var paddingBox = {
        width:  noOffsetWidth || element.clientWidth,
        height: element.clientHeight
      };

      // For backwards-compatibility, the returned object will have
      // width and height equal to the padding-box values.
      Object.extend(this.layout, paddingBox);

      this.layout.paddingBox = paddingBox;

      var padding = this.getStyleValuesFor('padding', 'trbl');
      this.layout.padding = padding;

      var contentBox = {
        width:  paddingBox.width  - padding.left - padding.right,
        height: paddingBox.height - padding.top  - padding.bottom
      };

      this.layout.contentBox = contentBox;

      var border = this.getStyleValuesFor('border', 'trbl');
      this.layout.border = border;

      var borderBox = {
        width:  paddingBox.width  + border.left + border.right,
        height: paddingBox.height + border.top  + border.bottom
      };

      this.layout.borderBox = borderBox;

    } // dimensions

    if (this.options.offsets === true) {
      var offsets = {};

      offsets.positioned = this.offset();
      offsets.viewport   = this.viewportOffset();
      offsets.scroll     = this.scrollOffset();
      offsets.document   = this.documentOffset();

      this.layout.offsets = offsets;
    } // offsets

    // If we altered the element's styles, return them to their
    // original values.
    if (isNotShown) {
      Object.extend(style, originalStyle);
    }

    return this.layout;
  },

  // Converts a raw CSS value like '9px' or '1em' to
  // a number (in pixels).
  // IE: Redefined below
  cssToNumber: function(property) {
    return window.parseFloat(this.element.getStyle(property));
  },

  // sidesNeeded argument is a string.
  // "trbl" = top, right, bottom, left
  // "tb"   = top, bottom
  getStyleValuesFor: function(property, sidesNeeded) {
    var sides = $w('top bottom left right');
    var propertyNames = sides.map( function(s) {
      return property + s.capitalize();
    });

    if (property === 'border') {
      propertyNames = propertyNames.map( function(p) {
        return p + 'Width';
      });
    }

    var values = {};

    sides.each( function(side, index) {
      if (!sidesNeeded.include(side.charAt(0))) return;
      values[side] = this.cssToNumber(propertyNames[index]);
    }, this);

    return values;
  },

  toObject: function() {
    return this.layout;
  },

  toHash: function() {
    return $H(this.layout);
  },

  toJSON: function() {
    return Object.toJSON(this.layout);
  },

  toCSS: function() {
    var css = {}, d = this.layout;
    if (this.options.dimensions) {
      var margins = $w('top right bottom left').map( function(side) {
        return d.margin[side] + 'px';
      }).join(' ');
      var padding = $w('top right bottom left').map( function(side) {
        return d.padding[side] + 'px';
      }).join(' ');

      Object.extend(css, {
        width:   d.contentBox.width  + 'px',
        height:  d.contentBox.height + 'px',
        margin:  margins,
        padding: padding
      });
    }

    if (this.options.offsets) {
      Object.extend(css, {
        left: d.offset.left + 'px',
        top:  d.offset.top  + 'px'
      });
    }

    return css;
  },

  /**
   *  Element.Layout#dimensions() -> Element.Coordinates
   *  Reports the dimensions of the given element.
  **/
  dimensions: function() {
    var box = this.layout.contentBox;
    return { width: box.width, height: box.height };
  },

  /**
   *  Element.Layout#offset([element=document]) -> Element.Coordinates
   *  Positioned offset. Measured from offset parent.
  **/
  offset: function() {
    var element = this.element;
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
      if (element) {
        if (element.tagName.toUpperCase() == 'BODY') break;
        var p = Element.getStyle(element, 'position');
        if (p !== 'static') break;
      }
    } while (element);
    return Element.Layout.normalize({ left: valueL, top: valueT });
  },

  /**
   *  Element.Layout#viewportOffset() -> Element.Coordinates
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of the viewport.
  **/
  viewportOffset: function() {
    var element = this.element;

    // IE and FF >= 3 provide getBoundingClientRect, a much quicker path
    // to retrieving viewport offset.
    if (element.getBoundingClientRect) {
      var d = element.getBoundingClientRect();
      return { left: Math.round(d.left), top: Math.round(d.top) };
    }

    var valueT = 0, valueL = 0, element = this.element;

    // First collect cumulative offsets
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;

      // Safari fix
      if (element.offsetParent == document.body &&
        Element.getStyle(element, 'position') === 'absolute') break;

    } while (element = element.offsetParent);

    // Then subtract cumulative scroll offsets
    element = this.element;
    do {
      if (!Prototype.Browser.Opera || element.tagName.toUpperCase() == 'BODY') {
        valueT -= element.scrollTop  || 0;
        valueL -= element.scrollLeft || 0;
      }
    } while (element = element.parentNode);

    return { left: valueL, top: valueT };
  },

  /**
   *  Element.Layout#documentOffset() -> Element.Coords
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of its containing document.
  **/
  documentOffset: function() {
    var element = this.element;
    var valueT = 0, valueL = 0;
    do {
      valueT += element.offsetTop  || 0;
      valueL += element.offsetLeft || 0;
      element = element.offsetParent;
    } while (element);
    return Element.Layout.normalize({ left: valueL, top: valueT });
  },

  /**
   *  Element.Layout#offsetParent() -> Element
   *  Returns the element's positioning context — the nearest ancestor
   *  with a CSS "position" value other than "static."
  **/
  offsetParent: function() {
    var element = this.element;
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element !== document.body)
      if (Element.getStyle(element, 'position') !== 'static')
        return element;

    return $(document.body);
  },

  /**
   *  Element.Layout#scrollOffset(@element) -> Object
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of its containing document, compensating for the scroll
   *  offsets of any ancestors.
  **/
  scrollOffset: function() {
    var element = this.element;
    var valueT = 0, valueL = 0;
    do {
      valueT += element.scrollTop  || 0;
      valueL += element.scrollLeft || 0;
      element = element.parentNode;
    } while (element);
    return Element.Layout.normalize({ left: valueL, top: valueT });
  }

});

if (Prototype.Browser.IE) {
  Element.Layout.addMethods({
    // IE gives the literal cascaded style, not the computed style.
    // We need to ensure pixel values are returned.
    cssToNumber: function(property) {
      var value = this.element.getStyle(property);

      if ((/^\d+(px)?$/i).test(value))
        return window.parseFloat(value);

      // If the unit is something other than a pixel (em, pt, %), set it on
      // something we can grab a pixel value from.
      var element = this.element;

      var sl = element.style.left, rsl = element.runtimeStyle.left;

      element.runtimeStyle.left = element.currentStyle.left;
      element.style.left = value || 0;

      value = element.style.pixelLeft;

      element.style.left = sl;
      element.runtimeStyle.left = rsl;

      return value;
    }
  });
}

// Acts like an array for backwards-compatibility.
Element.Layout.normalize = function(obj) {
  var arr = [];
  arr[0] = ('left' in obj) ? obj.left : obj.width;
  arr[1] = ('top'  in obj) ? obj.top  : obj.height;
  return Object.extend(arr, obj);
};

Object.extend(Element.Methods, {
  /**
   *  Element#getLayout(@element[, options]) -> Object
   *  Reports the dimensions and offsets of the given element.
   *
   *  By default, `getLayout` will return as much information about the
   *  element as possible: dimensions for the content, padding, and border
   *  boxes; and viewport, cumulative, scroll, and positioned offsets.
   *  The `options` argument can be used to bypass checks you don't need
   *  when speed is of the utmost importance.
  **/
  getLayout: function(element, options) {
    return new Element.Layout(element, options).toObject();
  },

  getDimensions: function(element) {
    var d = new Element.Layout(element, { offsets: false }).toObject();
    return Object.extend(Element.Layout.normalize(d), d);
  },

  getHeight: function(element) {
    return Element.getDimensions(element).height;
  },

  getWidth: function(element) {
    return Element.getDimensions(element).width;
  },

  getOffsets: function(element) {
    return new Element.Layout(element, { dimensions: false }).toObject().offsets;
  },

  viewportOffset: function(element) {
    var o = Element.getOffsets(element).viewport;
    return Element.Layout.normalize(o);
  },

  cumulativeOffset: function(element) {
    var o = Element.getOffsets(element).document;
    return Element.Layout.normalize(o);
  },

  /**
   *  Element#cumulativeScrollOffset(@element) -> Object
   *  Reports the element's top- and left-distance from the upper-left
   *  corner of its containing document, compensating for the scroll
   *  offsets of any ancestors.
  **/
  cumulativeScrollOffset: function(element) {
    var o = Element.getOffsets(element).scroll;
    return Element.Layout.normalize(o);
  },

  /**
   *  Element#cumulativeOffset(@element) -> Object
   *  Reports the element's top- and left-distance from its positioning
   *  parent.
  **/
  positionedOffset: function(element) {
    var o = Element.getOffsets(element).positioned;
    return Element.Layout.normalize(o);
  },

  /**
   *  Element#absolutize(@element) -> Element
   *  Switches element from static/relative positioning to absolute
   *  positioning while maintaining the element's size and position.
  **/
  absolutize: function(element) {
    element = $(element);
    if (element.getStyle('position') === 'absolute') return element;

    var offsets = element.positionedOffset();
    var top     = offsets[1];
    var left    = offsets[0];
    var width   = element.clientWidth;
    var height  = element.clientHeight;

    Object.extend(element, {
      _originalLeft:   left - parseFloat(element.style.left || 0),
      _originalTop:    top  - parseFloat(element.style.top  || 0),
      _originalWidth:  element.style.width,
      _originalHeight: element.style.height
    });

    element.setStyle({
      position: 'absolute',
      top:      top + 'px',
      left:     left + 'px',
      width:    width + 'px',
      height:   height + 'px'
    });

    return element;
  },

  /**
   *  Element#relativize(@element) -> Element
   *  Reverts element from absolute positioning to relative positioning
   *  while maintaining the element's size and position.
  **/
  relativize: function(element) {
    element = $(element);
    if (element.getStyle('position') === 'relative') return element;

    if (Object.isUndefined(element._originalTop)) {
      throw "Element#absolutize must be called first.";
    }

    element.setStyle({ position: 'relative' });

    var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
    var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);

    element.setStyle({
      top:      top + 'px',
      left:     left + 'px',
      width:    element._originalHeight + 'px',
      height:   element._originalWidth  + 'px'
    });

    return element;
  },

  /**
   *  Element#getOffsetParent(@element) -> Element
   *  Returns the element's positioning context — the nearest ancestor
   *  with a CSS "position" value other than "static."
  **/
  getOffsetParent: function(element) {
    if (element.offsetParent) return $(element.offsetParent);
    if (element == document.body) return $(element);

    while ((element = element.parentNode) && element !== document.body)
      if (Element.getStyle(element, 'position') !== 'static')
        return element;

    return $(document.body);
  },

  clonePosition: function(element, source) {
    var options = Object.extend({
      setLeft:    true,
      setTop:     true,
      setWidth:   true,
      setHeight:  true,
      offsetTop:  0,
      offsetLeft: 0
    }, arguments[2] || { });

    // find page position of source
    source = $(source);
    var sourceLayout = new Element.Layout(source).toCSS();

    if (!options.setHeight) delete sourceLayout.height;
    if (!options.setWidth)  delete sourceLayout.width;
    if (!options.setLeft)   delete sourceLayout.left;
    if (!options.setTop)    delete sourceLayout.top;

    $(element).setStyle(souceLayout);

    return element;
  }
});

document.viewport = {
  /**
   *  document.viewport.getDimensions () -> Object
   *  Returns the height and width of the browser viewport.
  **/
  getDimensions: function() {
    var dimensions = { };
    var B = Prototype.Browser;
    $w('width height').each(function(d) {
      var D = d.capitalize();
      dimensions[d] = (B.WebKit && !document.evaluate) ? self['inner' + D] :
        (B.Opera) ? document.body['client' + D] : document.documentElement['client' + D];
    });
    return dimensions;
  },

  /**
   *  document.viewport.getWidth() -> Number
   *  Returns the width of the browser viewport.
  **/
  getWidth: function() {
    return this.getDimensions().width;
  },

  /**
   *  document.viewport.getHeight() -> Number
   *  Returns the height of the browser viewport.
  **/
  getHeight: function() {
    return this.getDimensions().height;
  },

  /**
   *  document.viewport.getScrollOffsets() -> Object
   *  Returns the distances the viewport has been scrolled in the
   *  horizontal and vertical directions.
  **/
  getScrollOffsets: function() {
    return Element.Layout.normalize({
      left: window.pageXOffset
        || document.documentElement.scrollLeft
        || document.body.scrollLeft,
      top: window.pageYOffset
        || document.documentElement.scrollTop
        || document.body.scrollTop
    });
  }
};
<|endoftext|>


<commit_before>const wiki = require('./wiki')
const { EventEmitter } = require('events')
const debug = require('debug')('WikiBattle:game')

let $id = 0
const HINT_TIMEOUT = 40 // seconds
const BACKLINKS_TIMEOUT = 90 // seconds

module.exports = WikiBattle

function WikiBattle (io, origin, goal) {
  if (!(this instanceof WikiBattle)) return new WikiBattle(io, origin, goal)
  EventEmitter.call(this)
  $id %= 2e15 // should be enough for anyone!
  this.id = `game:${++$id}`
  this.players = []
  this.origin = origin
  this.goal = goal
  this.io = io
}

WikiBattle.prototype.emitSocket = function (...args) {
  return this.players.forEach(player => {
    const sock = player.sock
    if (sock) {
      sock.emit(...args)
    }
  })
}

WikiBattle.prototype.connect = function (connectingPlayer) {
  debug('connect player', connectingPlayer.id)
  this.players.forEach(player => {
    player.notifyConnect(connectingPlayer)
    connectingPlayer.notifyConnect(player)
  })
  this.players.push(connectingPlayer)
  return this
}

WikiBattle.prototype.disconnect = function (disconnectingPlayer) {
  debug('disconnect player', disconnectingPlayer.id)
  disconnectingPlayer.disconnect()
  this.navigate(disconnectingPlayer, null)

  var connected = this.players.filter(p => p.connected)
  connected.forEach(p => {
    p.notifyDisconnect(disconnectingPlayer)
  })
  if (connected.length === 1) {
    connected[0].win()
    this.end()
  }
}

WikiBattle.prototype.checkWin = function () {
  const hasWon = p => p.current() === this.goal
  if (this.players.some(hasWon)) {
    this.players.forEach(p => {
      hasWon(p) ? p.win() : p.lose()
    })
    this.end()
  }
}

WikiBattle.prototype.navigateInner = function (player, to) {
  player.navigateTo(to)
  this.emitSocket('navigated', player.id, to)
  this.checkWin()
}

WikiBattle.prototype.navigate = function (player, to) {
  debug('navigate (maybe)', player.id, `${player.current()} -> ${to}`)
  if (!player.current()) {
    return this.navigateInner(player, to)
  }
  wiki.get(player.current(), (e, page) => {
    if(!e && page.linksTo(to)){
      this.navigateInner(player, to)
    } else {
      //Maybe put some fancy "Do not cheat" page here?
    }
  })
}

WikiBattle.prototype.sendHint = function () {
  wiki.get(this.goal, (e, page) => {
    this.emitSocket('hint', e || page.getHint())
  })
}

WikiBattle.prototype.sendBacklinks = function () {
  wiki.get(this.goal, (e, page) => {
    if (e) return this.emitSocket('backlinks', e)
    page.getBacklinks((e, back) => {
      this.emitSocket('backlinks', e, back)
    })
  })
}

WikiBattle.prototype.sendPaths = function () {
  const paths = this.players.reduce((paths, p) => {
    paths[p.id] = p.path
    return paths
  }, {})
  this.emitSocket('paths', paths)
}

WikiBattle.prototype.start = function () {
  this.emitSocket('start', this.origin, this.goal)

  this.players.forEach(p => {
    this.navigate(p, this.origin)
  })

  this.hintTimeout = setTimeout(this.sendHint.bind(this), HINT_TIMEOUT * 1000)
  this.backlinksTimeout = setTimeout(this.sendBacklinks.bind(this), BACKLINKS_TIMEOUT * 1000)
}

WikiBattle.prototype.end = function () {
  this.sendPaths()
  clearTimeout(this.hintTimeout)
  clearTimeout(this.backlinksTimeout)
}

WikiBattle.prototype.notifyScroll = function (scroller, top, width) {
  this.players.forEach(player => {
    if (scroller !== player) {
      player.notifyScroll(scroller, top, width)
    }
  })
}
<commit_msg>do not check linksTo() when navigating to null after disconnect<commit_after>const wiki = require('./wiki')
const { EventEmitter } = require('events')
const debug = require('debug')('WikiBattle:game')

let $id = 0
const HINT_TIMEOUT = 40 // seconds
const BACKLINKS_TIMEOUT = 90 // seconds

module.exports = WikiBattle

function WikiBattle (io, origin, goal) {
  if (!(this instanceof WikiBattle)) return new WikiBattle(io, origin, goal)
  EventEmitter.call(this)
  $id %= 2e15 // should be enough for anyone!
  this.id = `game:${++$id}`
  this.players = []
  this.origin = origin
  this.goal = goal
  this.io = io
}

WikiBattle.prototype.emitSocket = function (...args) {
  return this.players.forEach(player => {
    const sock = player.sock
    if (sock) {
      sock.emit(...args)
    }
  })
}

WikiBattle.prototype.connect = function (connectingPlayer) {
  debug('connect player', connectingPlayer.id)
  this.players.forEach(player => {
    player.notifyConnect(connectingPlayer)
    connectingPlayer.notifyConnect(player)
  })
  this.players.push(connectingPlayer)
  return this
}

WikiBattle.prototype.disconnect = function (disconnectingPlayer) {
  debug('disconnect player', disconnectingPlayer.id)
  disconnectingPlayer.disconnect()
  this.navigate(disconnectingPlayer, null)

  var connected = this.players.filter(p => p.connected)
  connected.forEach(p => {
    p.notifyDisconnect(disconnectingPlayer)
  })
  if (connected.length === 1) {
    connected[0].win()
    this.end()
  }
}

WikiBattle.prototype.checkWin = function () {
  const hasWon = p => p.current() === this.goal
  if (this.players.some(hasWon)) {
    this.players.forEach(p => {
      hasWon(p) ? p.win() : p.lose()
    })
    this.end()
  }
}

WikiBattle.prototype.navigateInner = function (player, to) {
  player.navigateTo(to)
  this.emitSocket('navigated', player.id, to)
  this.checkWin()
}

WikiBattle.prototype.navigate = function (player, to) {
  debug('navigate (maybe)', player.id, `${player.current()} -> ${to}`)
  if (to === null || !player.current()) {
    return this.navigateInner(player, to)
  }
  wiki.get(player.current(), (e, page) => {
    if(!e && page.linksTo(to)){
      this.navigateInner(player, to)
    } else {
      //Maybe put some fancy "Do not cheat" page here?
    }
  })
}

WikiBattle.prototype.sendHint = function () {
  wiki.get(this.goal, (e, page) => {
    this.emitSocket('hint', e || page.getHint())
  })
}

WikiBattle.prototype.sendBacklinks = function () {
  wiki.get(this.goal, (e, page) => {
    if (e) return this.emitSocket('backlinks', e)
    page.getBacklinks((e, back) => {
      this.emitSocket('backlinks', e, back)
    })
  })
}

WikiBattle.prototype.sendPaths = function () {
  const paths = this.players.reduce((paths, p) => {
    paths[p.id] = p.path
    return paths
  }, {})
  this.emitSocket('paths', paths)
}

WikiBattle.prototype.start = function () {
  this.emitSocket('start', this.origin, this.goal)

  this.players.forEach(p => {
    this.navigate(p, this.origin)
  })

  this.hintTimeout = setTimeout(this.sendHint.bind(this), HINT_TIMEOUT * 1000)
  this.backlinksTimeout = setTimeout(this.sendBacklinks.bind(this), BACKLINKS_TIMEOUT * 1000)
}

WikiBattle.prototype.end = function () {
  this.sendPaths()
  clearTimeout(this.hintTimeout)
  clearTimeout(this.backlinksTimeout)
}

WikiBattle.prototype.notifyScroll = function (scroller, top, width) {
  this.players.forEach(player => {
    if (scroller !== player) {
      player.notifyScroll(scroller, top, width)
    }
  })
}
<|endoftext|>


<commit_before>/* global $, L, d3: false */
/* global station_data: true */
(function () {
  'use strict';

  // Lets us turn json dates into javascript dates
  var isoToDate = d3.time.format('%Y-%m-%dT%H:%M:%SZ');
  var tzOffset = new Date().getTimezoneOffset() / -60;
  var updated_at = d3.time.hour.offset(isoToDate.parse(station_data.updated_at), tzOffset);

  //*******************
  //* D3 AWWWW YISSSS *
  //*******************

  var buildChart = function ($el, data) {
    var plotBox = {
      width: Math.max(300, $(window).width() >> 1),
      height: 200
    };
    var plotMargin = {
      top: 8,
      left: 24,
      bottom: 42,
      right: 7
    };

    var cleaner = function (days) {
      return function (d) {
        return {
          date: d3.time.day.offset(
            d3.time.hour.offset(isoToDate.parse(d[0]), tzOffset),
            days
          ),
          bikes: d[2],
          docks: d[3]
        };
      };
    };
    var cleanedData = {
      recent: data.recent.map(cleaner(0)),
      yesterday: data.yesterday.map(cleaner(1)),
      lastweek: data.lastweek.map(cleaner(7))
    };

    $el.find('.loading').remove();

    var svg = d3.select($el[0])
      .append('svg')
      .attr('width', plotBox.width + plotMargin.left + plotMargin.right)
      .attr('height', plotBox.height + plotMargin.top + plotMargin.bottom)
      .attr('viewBox', [0, 0,
          plotBox.width + plotMargin.left + plotMargin.right,
          plotBox.height + plotMargin.top + plotMargin.bottom,
        ].join(' '))
      .attr('preserveAspectRatio', 'xMinYMin meet');

    var plot = svg
      .append('g')
      .attr('class', 'plot')
      .attr('width', plotBox.width)
      .attr('height', plotBox.height)
      .attr('transform', 'translate(' + plotMargin.left + ', ' + plotMargin.top + ')');

    var minValues = [cleanedData.recent[0].date],
        maxValues = [cleanedData.recent[cleanedData.recent.length - 1].date];
    if (cleanedData.yesterday.length) {
      minValues.push(cleanedData.yesterday[0].date);
      maxValues.push(cleanedData.yesterday[cleanedData.yesterday.length - 1].date);
    }
    var xScale = d3.time.scale()
      .range([0, plotBox.width])
      .domain([
        Math.min.apply(undefined, minValues),
        Math.max.apply(undefined, maxValues)
      ]);

    var yScale = d3.scale.linear()
      .range([0, plotBox.height])
      .domain([data.capacity, 0]);

    var xAxis = d3.svg.axis()
      .scale(xScale)
      .orient('bottom');

    var yAxis = d3.svg.axis()
      .scale(yScale)
      .orient('left');
    if (data.capacity < 10) {
      // Because you can't have 3.5 bikes
      yAxis.ticks(data.capacity);
    }

    var line = d3.svg.line()
      .x(function (d) { return xScale(d.date); })
      .y(function (d) { return yScale(d.bikes); });
    var area = d3.svg.area()
      .x(function (d) { return xScale(d.date); })
      .y0(plotBox.height)
      .y1(function (d) { return yScale(d.bikes); });

    svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(' + plotMargin.left + ', ' + (plotBox.height + plotMargin.top) + ')')
      .call(xAxis)
      .selectAll('text')
        .style('text-anchor', 'end')
        .attr('dx', '-0.8em')
        .attr('dy', '0.15em')
        .attr('transform', 'rotate(-35)');

    svg.append('g')
      .attr('class', 'y axis')
      .attr('transform', 'translate(' + plotMargin.left + ', ' + plotMargin.top + ')')
      .call(yAxis);

    $.each(['yesterday', 'recent'], function (idx, dataset) {
      plot.append('path')
        .datum(cleanedData[dataset])
        .attr('class', 'area ' + dataset)
        .attr('d', area);
      plot.append('path')
        .datum(cleanedData[dataset])
        .attr('class', 'line ' + dataset)
        .attr('d', line);
    });

    plot.append('line')
      .attr('class', 'now')
      .attr('x1', 0)
      .attr('y1', 0)
      .attr('x2', 0)
      .attr('y2', plotBox.height)
      .attr('stroke-dasharray', '5, 5')
      .attr('transform', 'translate(' + xScale(new Date()) + ', 0)');
  };

  // *************
  // * MAP POPUP *
  // *************

  var showStandInfo = function (stand, latlng) {
    var popup = L.popup({
      // keep popup from cutting off chart
      maxWidth: 10000
    });
    var $paper = $('

Bike Availability at ' + stand.name + '
' +
      '
Bikes: ' + stand.bikes + '' +
      ' Docks: ' + stand.docks + '' +
      ' Status: ' + stand.status + '' +
      '
' +
      '
Loading...
' +
      '
');
    $.getJSON(stand.url, function (data) {
      buildChart($paper, data);
      popup.setContent($paper[0]);
    });
    popup
      .setLatLng(latlng)
      .setContent($paper[0])
      .openOn(map);
  };

  // **************
  // * CREATE MAP *
  // **************

  var getIcon = function (stand) {
    // http://leafletjs.com/reference.html#divicon
    var filled = Math.round(stand.bikes / (stand.bikes + stand.docks) * 10);
    return L.divIcon({
      className: 'filled-marker',
      html: '
X
',
      iconSize: [16, 19],
      iconAnchor: null
    });
  };

  var map = L.map('map', {
        // scrollWheelZoom: false
      }),
      markers = {},
      bounds = [];

  var createMap = function () {
    $.each(station_data.stations, function (idx, stand) {
      bounds.push([stand.latitude, stand.longitude]);
      var marker = L.marker([stand.latitude, stand.longitude], {
        icon: getIcon(stand),
        title: stand.name + '\nBikes: ' + stand.bikes + '\nDocks: ' + stand.docks
      }).addTo(map);
      marker.on('click', function (e) {
        showStandInfo(stand, e.latlng);
      });
      markers[stand.url] = marker;
    });

    // add an OpenStreetMap tile layer
    L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png', {
      attribution: 'Tiles Courtesy of MapQuest '
    }).addTo(map);

    map.fitBounds(bounds);
  };
  var lastUpdate = Date.now();
  var updateMap = function () {
    var url = location.pathname + 'data.json';
    return $.getJSON(url, function (data) {
      station_data = data;  // update local storage
      updated_at = d3.time.hour.offset(isoToDate.parse(station_data.updated_at), tzOffset);
      lastUpdate = Date.now() + 15 * 1000;  // lie and set `lastUpdate` to the future
      $.each(station_data.stations, function (idx, stand) {
        var marker = markers[stand.url];
        marker.setIcon(getIcon(stand));
      });
    });
  };
  createMap();

  // **********
  // * LEGEND *
  // **********

  var legend = L.control({position: 'bottomleft'}),
      $legend = $('
Last Update: s' +
        ' Next Update: s
');
  legend.onAdd = function () {
    var $last = $legend.find('.last'),
        $next = $legend.find('.next');
    var next = 10 * 60;  // 10 minutes
    var _update = function () {
      var diff = (Date.now() - updated_at) / 1000,
          nextDiff = next - diff;
      $last.html(Math.floor(diff));
      if (nextDiff < 0) {
        $next.html('in progres');
      } else {
        $next.html(Math.floor(nextDiff));
      }
      var now = Date.now();
      if (nextDiff < 0 &&
          // wait at least 5 seconds between updates
          (now - lastUpdate) > 5000) {
        lastUpdate = now;
        updateMap();
      }
    };
    _update();
    setInterval(_update, 1000);
    return $legend[0];
  };
  legend.addTo(map);

  // ***************
  // * GEOLOCATION *
  // ***************

  var myLocation = null;

  var zoomMap = function (position) {
    myLocation = L.latLng(position.coords.latitude, position.coords.longitude);
    if (!map.getBounds().contains(myLocation)) {
      // user's location is not worth panning to
      return;
    }
    map.panTo(myLocation);
    map.setZoom(16);
    L.marker(myLocation).addTo(map);
    map.addControl(new GoHomeControl());
  };

  var updatePosition = function (position) {
    myLocation = L.latLng(position.coords.latitude, position.coords.longitude);
    map.panTo(myLocation);
  };

  var GoHomeControl = L.Control.extend({
    options: {
      position: 'topright'
    },
    onAdd: function (map) {
      var container = L.DomUtil.create('div', 'leaflet-control-home leaflet-bar');
      // WISHLIST add system map button even if geolocation is off
      $(container).html(
        '' +
        ''
        )
        .find('a.action-home').on('click', function (e) {
          e.preventDefault();
          navigator.geolocation.getCurrentPosition(updatePosition);
        }).end()
        .find('a.action-all').on('click', function (e) {
          e.preventDefault();
          map.fitBounds(bounds);
        });
      return container;
    }
  });

  navigator.geolocation.getCurrentPosition(zoomMap);

  // ***********
  // * EXPORTS *
  // ***********

  window.map = map;
  window.markers = markers;
  window.updateMap = updateMap;
  window.isoToDate = isoToDate;
  window.tzOffset = tzOffset;
  window.updated_at = updated_at;
})();
<commit_msg>stop updates for non 200 response<commit_after>/* global $, L, d3: false */
/* global station_data: true */
(function () {
  'use strict';

  // Lets us turn json dates into javascript dates
  var isoToDate = d3.time.format('%Y-%m-%dT%H:%M:%SZ');
  var tzOffset = new Date().getTimezoneOffset() / -60;
  var updated_at = d3.time.hour.offset(isoToDate.parse(station_data.updated_at), tzOffset);

  //*******************
  //* D3 AWWWW YISSSS *
  //*******************

  var buildChart = function ($el, data) {
    var plotBox = {
      width: Math.max(300, $(window).width() >> 1),
      height: 200
    };
    var plotMargin = {
      top: 8,
      left: 24,
      bottom: 42,
      right: 7
    };

    var cleaner = function (days) {
      return function (d) {
        return {
          date: d3.time.day.offset(
            d3.time.hour.offset(isoToDate.parse(d[0]), tzOffset),
            days
          ),
          bikes: d[2],
          docks: d[3]
        };
      };
    };
    var cleanedData = {
      recent: data.recent.map(cleaner(0)),
      yesterday: data.yesterday.map(cleaner(1)),
      lastweek: data.lastweek.map(cleaner(7))
    };

    $el.find('.loading').remove();

    var svg = d3.select($el[0])
      .append('svg')
      .attr('width', plotBox.width + plotMargin.left + plotMargin.right)
      .attr('height', plotBox.height + plotMargin.top + plotMargin.bottom)
      .attr('viewBox', [0, 0,
          plotBox.width + plotMargin.left + plotMargin.right,
          plotBox.height + plotMargin.top + plotMargin.bottom,
        ].join(' '))
      .attr('preserveAspectRatio', 'xMinYMin meet');

    var plot = svg
      .append('g')
      .attr('class', 'plot')
      .attr('width', plotBox.width)
      .attr('height', plotBox.height)
      .attr('transform', 'translate(' + plotMargin.left + ', ' + plotMargin.top + ')');

    var minValues = [cleanedData.recent[0].date],
        maxValues = [cleanedData.recent[cleanedData.recent.length - 1].date];
    if (cleanedData.yesterday.length) {
      minValues.push(cleanedData.yesterday[0].date);
      maxValues.push(cleanedData.yesterday[cleanedData.yesterday.length - 1].date);
    }
    var xScale = d3.time.scale()
      .range([0, plotBox.width])
      .domain([
        Math.min.apply(undefined, minValues),
        Math.max.apply(undefined, maxValues)
      ]);

    var yScale = d3.scale.linear()
      .range([0, plotBox.height])
      .domain([data.capacity, 0]);

    var xAxis = d3.svg.axis()
      .scale(xScale)
      .orient('bottom');

    var yAxis = d3.svg.axis()
      .scale(yScale)
      .orient('left');
    if (data.capacity < 10) {
      // Because you can't have 3.5 bikes
      yAxis.ticks(data.capacity);
    }

    var line = d3.svg.line()
      .x(function (d) { return xScale(d.date); })
      .y(function (d) { return yScale(d.bikes); });
    var area = d3.svg.area()
      .x(function (d) { return xScale(d.date); })
      .y0(plotBox.height)
      .y1(function (d) { return yScale(d.bikes); });

    svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(' + plotMargin.left + ', ' + (plotBox.height + plotMargin.top) + ')')
      .call(xAxis)
      .selectAll('text')
        .style('text-anchor', 'end')
        .attr('dx', '-0.8em')
        .attr('dy', '0.15em')
        .attr('transform', 'rotate(-35)');

    svg.append('g')
      .attr('class', 'y axis')
      .attr('transform', 'translate(' + plotMargin.left + ', ' + plotMargin.top + ')')
      .call(yAxis);

    $.each(['yesterday', 'recent'], function (idx, dataset) {
      plot.append('path')
        .datum(cleanedData[dataset])
        .attr('class', 'area ' + dataset)
        .attr('d', area);
      plot.append('path')
        .datum(cleanedData[dataset])
        .attr('class', 'line ' + dataset)
        .attr('d', line);
    });

    plot.append('line')
      .attr('class', 'now')
      .attr('x1', 0)
      .attr('y1', 0)
      .attr('x2', 0)
      .attr('y2', plotBox.height)
      .attr('stroke-dasharray', '5, 5')
      .attr('transform', 'translate(' + xScale(new Date()) + ', 0)');
  };

  // *************
  // * MAP POPUP *
  // *************

  var showStandInfo = function (stand, latlng) {
    var popup = L.popup({
      // keep popup from cutting off chart
      maxWidth: 10000
    });
    var $paper = $('

Bike Availability at ' + stand.name + '
' +
      '
Bikes: ' + stand.bikes + '' +
      ' Docks: ' + stand.docks + '' +
      ' Status: ' + stand.status + '' +
      '
' +
      '
Loading...
' +
      '
');
    $.getJSON(stand.url, function (data) {
      buildChart($paper, data);
      popup.setContent($paper[0]);
    });
    popup
      .setLatLng(latlng)
      .setContent($paper[0])
      .openOn(map);
  };

  // **************
  // * CREATE MAP *
  // **************

  var getIcon = function (stand) {
    // http://leafletjs.com/reference.html#divicon
    var filled = Math.round(stand.bikes / (stand.bikes + stand.docks) * 10);
    return L.divIcon({
      className: 'filled-marker',
      html: '
X
',
      iconSize: [16, 19],
      iconAnchor: null
    });
  };

  var map = L.map('map', {
        // scrollWheelZoom: false
      }),
      markers = {},
      bounds = [];

  var createMap = function () {
    $.each(station_data.stations, function (idx, stand) {
      bounds.push([stand.latitude, stand.longitude]);
      var marker = L.marker([stand.latitude, stand.longitude], {
        icon: getIcon(stand),
        title: stand.name + '\nBikes: ' + stand.bikes + '\nDocks: ' + stand.docks
      }).addTo(map);
      marker.on('click', function (e) {
        showStandInfo(stand, e.latlng);
      });
      markers[stand.url] = marker;
    });

    // add an OpenStreetMap tile layer
    L.tileLayer('http://otile1.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png', {
      attribution: 'Tiles Courtesy of MapQuest '
    }).addTo(map);

    map.fitBounds(bounds);
  };
  var lastUpdate = Date.now();
  var updateMap = function () {
    var url = location.pathname + 'data.json';
    return $.getJSON(url, function (data) {
      station_data = data;  // update local storage
      updated_at = d3.time.hour.offset(isoToDate.parse(station_data.updated_at), tzOffset);
      lastUpdate = Date.now() + 15 * 1000;  // lie and set `lastUpdate` to the future
      $.each(station_data.stations, function (idx, stand) {
        var marker = markers[stand.url];
        marker.setIcon(getIcon(stand));
      });
    });
  };
  createMap();

  // **********
  // * LEGEND *
  // **********

  var legend = L.control({position: 'bottomleft'}),
      $legend = $('
Last Update: s' +
        ' Next Update: s
');
  legend.onAdd = function () {
    var $last = $legend.find('.last'),
        $next = $legend.find('.next');
    var next = 10 * 60;  // 10 minutes
    var _update = function () {
      var diff = (Date.now() - updated_at) / 1000,
          nextDiff = next - diff;
      $last.html(Math.floor(diff));
      if (nextDiff < 0) {
        var msg = lastUpdate ? 'in progres' : 'oop';
        $next.html('' + msg + '');
      } else {
        $next.html(Math.floor(nextDiff));
      }
      var now = Date.now();
      // wait at least 5 seconds between updates
      if (nextDiff < 0 && lastUpdate && (now - lastUpdate) > 5000) {
        updateMap()
          .fail(function () {
            lastUpdate = false;
          });
        lastUpdate = now;
      }
    };
    _update();
    setInterval(_update, 1000);
    return $legend[0];
  };
  legend.addTo(map);

  // ***************
  // * GEOLOCATION *
  // ***************

  var myLocation = null;

  var zoomMap = function (position) {
    myLocation = L.latLng(position.coords.latitude, position.coords.longitude);
    if (!map.getBounds().contains(myLocation)) {
      // user's location is not worth panning to
      return;
    }
    map.panTo(myLocation);
    map.setZoom(16);
    L.marker(myLocation).addTo(map);
    map.addControl(new GoHomeControl());
  };

  var updatePosition = function (position) {
    myLocation = L.latLng(position.coords.latitude, position.coords.longitude);
    map.panTo(myLocation);
  };

  var GoHomeControl = L.Control.extend({
    options: {
      position: 'topright'
    },
    onAdd: function (map) {
      var container = L.DomUtil.create('div', 'leaflet-control-home leaflet-bar');
      // WISHLIST add system map button even if geolocation is off
      $(container).html(
        '' +
        ''
        )
        .find('a.action-home').on('click', function (e) {
          e.preventDefault();
          navigator.geolocation.getCurrentPosition(updatePosition);
        }).end()
        .find('a.action-all').on('click', function (e) {
          e.preventDefault();
          map.fitBounds(bounds);
        });
      return container;
    }
  });

  navigator.geolocation.getCurrentPosition(zoomMap);

  // ***********
  // * EXPORTS *
  // ***********

  window.map = map;
  window.markers = markers;
  window.updateMap = updateMap;
  window.isoToDate = isoToDate;
  window.tzOffset = tzOffset;
  window.updated_at = updated_at;
})();
<|endoftext|>


<commit_before>'use strict';

//implmentation of merge sort;

function mergeSort(arr){
  let half = Math.floor(arr.length / 2);
  if(arr.length > 1){
    let arr1 = mergeSort(arr.splice(0, half));
    let arr2 = mergeSort(arr)
    return merge(arr1, arr2);
  } else{
    console.log('in else', arr)
    return arr;
  }
}

function merge(_arr1, _arr2){
  let result = [];
  while(_arr1.length || _arr2.length){
    if(_arr1.length && _arr1[0] < _arr2[0]){
      result.push(_arr1.shift());
    } else if(!_arr2[0]){
      result.push(_arr1.shift());
    } else {
      result.push(_arr2.shift());
    }
  }
  return result;
}

let test = [5,3,9,4,8,6,12,14];
let test2 = [5,3,15,17,18,6];

console.log(mergeSort(test));
console.log(mergeSort(test2));
console.log(mergeSort([]));
console.log(mergeSort([2,1]));
<commit_msg>adding mergeSort practice<commit_after>'use strict';

//implmentation of merge sort;

function mergeSort(arr){
  let half = Math.floor(arr.length / 2);
  if(arr.length > 1){
    let arr1 = mergeSort(arr.splice(0, half));
    let arr2 = mergeSort(arr)
    return merge(arr1, arr2);
  } else{
    return arr;
  }
}

function merge(_arr1, _arr2){
  let result = [];
  while(_arr1.length || _arr2.length){
    if(_arr1.length && _arr1[0] < _arr2[0]){
      result.push(_arr1.shift());
    } else if(!_arr2[0]){
      result.push(_arr1.shift());
    } else {
      result.push(_arr2.shift());
    }
  }
  return result;
}

let test = [5,3,9,4,8,6,12,14];
let test2 = [5,3,15,17,18,6];

console.log(mergeSort(test));
console.log(mergeSort(test2));
console.log(mergeSort([]));
console.log(mergeSort([2,1]));
<|endoftext|>


<commit_before>const { createWriteStream, existsSync, mkdirSync } = require('fs')
const { resolve } = require('path')

const http = require('http')

function download (lessonInfo, videoUrl) {
  if (!existsSync(resolve(__dirname, '../downloads'))) {
    mkdirSync(resolve(__dirname, '../downloads'))
  }
  const file = createWriteStream(resolve(__dirname, `../downloads/NO.${lessonInfo.index + 1} ${lessonInfo.title}.mp4`))
  http.get(videoUrl, response => {
    response.pipe(file)
  })
  return new Promise(resolve => {
    file.on('finish', () => {
      file.close()
      resolve()
    })
  })
}

module.exports = download
<commit_msg>:speech_balloon: Tweak download file name<commit_after>const { createWriteStream, existsSync, mkdirSync } = require('fs')
const { resolve } = require('path')

const http = require('http')

function download (lessonInfo, videoUrl) {
  if (!existsSync(resolve(__dirname, '../downloads'))) {
    mkdirSync(resolve(__dirname, '../downloads'))
  }
  const file = createWriteStream(resolve(__dirname, `../downloads/No.${lessonInfo.index + 1} ${lessonInfo.title}.mp4`))
  http.get(videoUrl, response => {
    response.pipe(file)
  })
  return new Promise(resolve => {
    file.on('finish', () => {
      file.close()
      resolve()
    })
  })
}

module.exports = download
<|endoftext|>


<commit_before>module.exports = {
  normalizeEntityName: function () {
    // this prevents an error when the entityName is
    // not specified (since that doesn't actually matter to us)
  }
}
<commit_msg>Remove unneeded blueprints folder<commit_after><|endoftext|>


<commit_before>import {Plugin} from "prosemirror-state"
import {Decoration, DecorationSet} from "prosemirror-view"

const gecko = typeof navigator != "undefined" && /gecko\/\d/i.test(navigator.userAgent)
const linux = typeof navigator != "undefined" && /linux/i.test(navigator.platform)

export function dropCursor(options) {
  function dispatch(view, data) {
    view.dispatch(view.state.tr.setMeta(plugin, data))
  }

  let timeout = null
  function scheduleRemoval(view) {
    clearTimeout(timeout)
    timeout = setTimeout(() => {
      if (plugin.getState(view.state)) dispatch(view, {type: "remove"})
    }, 1000)
  }

  let plugin = new Plugin({
    state: {
      init() { return null },
      apply(tr, prev, state) {
        // Firefox on Linux gets really confused an breaks dragging when we
        // mess with the nodes around the target node during a drag. So
        // disable this plugin there. See https://bugzilla.mozilla.org/show_bug.cgi?id=1323170
        if (gecko && linux) return null
        let command = tr.getMeta(plugin)
        if (!command) return prev
        if (command.type == "set") return pluginStateFor(state, command.pos, options)
        return null
      }
    },
    props: {
      handleDOMEvents: {
        dragover(view, event) {
          let active = plugin.getState(view.state)
          let pos = view.posAtCoords({left: event.clientX, top: event.clientY})
          if (pos && (!active || active.pos != pos.pos))
            dispatch(view, {type: "set", pos: pos.pos})
          scheduleRemoval(view)
          return false
        },

        dragend(view) {
          if (plugin.getState(view.state)) dispatch(view, {type: "remove"})
          return false
        },

        drop(view) {
          if (plugin.getState(view.state)) dispatch(view, {type: "remove"})
          return false
        },

        dragleave(view, event) {
          if (event.target == view.dom) dispatch(view, {type: "remove"})
          return false
        }
      },
      decorations(state) {
        let active = plugin.getState(state)
        return active && active.deco
      }
    }
  })
  return plugin
}

function style(options, side) {
  let width = (options && options.width) || 1
  let color = (options && options.color) || "black"
  return `border-${side}: ${width}px solid ${color}; margin-${side}: -${width}px`
}

function pluginStateFor(state, pos, options) {
  let $pos = state.doc.resolve(pos), deco
  if (!$pos.parent.inlineContent) {
    let before, after
    if (before = $pos.nodeBefore)
      deco = Decoration.node(pos - before.nodeSize, pos, {nodeName: "div", style: style(options, "right")})
    else if (after = $pos.nodeAfter)
      deco = Decoration.node(pos, pos + after.nodeSize, {nodeName: "div", style: style(options, "left")})
  }
  if (!deco) {
    let node = document.createElement("span")
    node.textContent = "\u200b"
    node.style.cssText = style(options, "left") + "; display: inline-block; pointer-events: none"
    deco = Decoration.widget(pos, node)
  }
  return {pos, deco: DecorationSet.create(state.doc, [deco])}
}
<commit_msg>Use view.dragging to get a more accurate drop position<commit_after>import {Plugin} from "prosemirror-state"
import {Decoration, DecorationSet} from "prosemirror-view"

const gecko = typeof navigator != "undefined" && /gecko\/\d/i.test(navigator.userAgent)
const linux = typeof navigator != "undefined" && /linux/i.test(navigator.platform)

export function dropCursor(options) {
  function dispatch(view, data) {
    view.dispatch(view.state.tr.setMeta(plugin, data))
  }

  let timeout = null
  function scheduleRemoval(view) {
    clearTimeout(timeout)
    timeout = setTimeout(() => {
      if (plugin.getState(view.state)) dispatch(view, {type: "remove"})
    }, 1000)
  }

  let plugin = new Plugin({
    state: {
      init() { return null },
      apply(tr, prev, state) {
        // Firefox on Linux gets really confused an breaks dragging when we
        // mess with the nodes around the target node during a drag. So
        // disable this plugin there. See https://bugzilla.mozilla.org/show_bug.cgi?id=1323170
        if (gecko && linux) return null
        let command = tr.getMeta(plugin)
        if (!command) return prev
        if (command.type == "set") return pluginStateFor(state, command.pos, options)
        return null
      }
    },
    props: {
      handleDOMEvents: {
        dragover(view, event) {
          let active = plugin.getState(view.state)
          let pos = view.posAtCoords({left: event.clientX, top: event.clientY})
          if (pos) {
            let target = pos.pos
            if (view.dragging)
              target = dropPos(view.dragging.slice, view.state.doc.resolve(target))
            if (!active || active.pos != target)
              dispatch(view, {type: "set", pos: target})
          }
          scheduleRemoval(view)
          return false
        },

        dragend(view) {
          if (plugin.getState(view.state)) dispatch(view, {type: "remove"})
          return false
        },

        drop(view) {
          if (plugin.getState(view.state)) dispatch(view, {type: "remove"})
          return false
        },

        dragleave(view, event) {
          if (event.target == view.dom) dispatch(view, {type: "remove"})
          return false
        }
      },
      decorations(state) {
        let active = plugin.getState(state)
        return active && active.deco
      }
    }
  })
  return plugin
}

function style(options, side) {
  let width = (options && options.width) || 1
  let color = (options && options.color) || "black"
  return `border-${side}: ${width}px solid ${color}; margin-${side}: -${width}px`
}

function pluginStateFor(state, pos, options) {
  let $pos = state.doc.resolve(pos), deco
  if (!$pos.parent.inlineContent) {
    let before, after
    if (before = $pos.nodeBefore)
      deco = Decoration.node(pos - before.nodeSize, pos, {nodeName: "div", style: style(options, "right")})
    else if (after = $pos.nodeAfter)
      deco = Decoration.node(pos, pos + after.nodeSize, {nodeName: "div", style: style(options, "left")})
  }
  if (!deco) {
    let node = document.createElement("span")
    node.textContent = "\u200b"
    node.style.cssText = style(options, "left") + "; display: inline-block; pointer-events: none"
    deco = Decoration.widget(pos, node)
  }
  return {pos, deco: DecorationSet.create(state.doc, [deco])}
}

function dropPos(slice, $pos) {
  if (!slice || !slice.content.size) return $pos.pos
  let content = slice.content
  for (let i = 0; i < slice.openStart; i++) content = content.firstChild.content
  for (let d = $pos.depth; d >= 0; d--) {
    let bias = d == $pos.depth ? 0 : $pos.pos <= ($pos.start(d + 1) + $pos.end(d + 1)) / 2 ? -1 : 1
    let insertPos = $pos.index(d) + (bias > 0 ? 1 : 0)
    if ($pos.node(d).canReplace(insertPos, insertPos, content))
      return bias == 0 ? $pos.pos : bias < 0 ? $pos.before(d + 1) : $pos.after(d + 1)
  }
  return $pos.pos
}
<|endoftext|>