<commit_before>/**
 * Copyright 2015-present Tuan Le.
 *
 * Licensed under the MIT License.
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/mit-license.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *------------------------------------------------------------------------
 *
 * @module FixtureFactory
 * @description - A generic test fixture factory module.
 *
 * @author Tuan Le (tuan.t.lei@gmail.com)
 *
 * @flow
 */
'use strict'; // eslint-disable-line

/* load Hyperflow */
import { Hf } from '../../hyperflow';

/* load EventStreamComposite */
import EventStreamComposite from './composites/event-stream-composite';

/* load Composer */
import Composer from '../composer';

/* factory Ids */
import {
    FIXTURE_FACTORY_CODE
} from './factory-code';

/**
 * @description - A generic test fixture factory module.
 *
 * @module TestkitFactory
 */
export default Composer({
    composites: [
        EventStreamComposite
    ],
    state: {
        name: {
            value: `unnamed`,
            required: true
        },
        fId: {
            computable: {
                contexts: [
                    `name`
                ],
                compute () {
                    return `${FIXTURE_FACTORY_CODE}-${this.name}`;
                }
            }
        }
    },
    FixtureFactory: function FixtureFactory () {
        /* ----- Private Variables ------------- */
        /* ----- Public Functions -------------- */
        /**
         * @description - Initialize service.
         *
         * @method $init
         * @return void
         */
        this.$init = function $init () {
            Hf.log(`warn0`, `FixtureFactory.$init - Method is not implemented by default.`);
        };
        /**
         * @description - Setup fixture event stream.
         *
         * @method setup
         * @param {function} done
         * @return void
         */
        this.setup = function setup (done) { // eslint-disable-line
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.setup - Input done function is invalid.`);
                }
            }

            done();
        };
        /**
         * @description - Teardown fixture event stream.
         *
         * @method teardown
         * @param {function} done
         * @return void
         */
        this.teardown = function teardown (done) { // eslint-disable-line
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.teardown - Input done function is invalid.`);
                }
            }

            done();
        };
        /**
         * @description - Check if domain has started.
         *
         * @method hasStarted
         * @return {boolean}
         */
        this.hasStarted = function hasStarted () {
            return false;
        };
        /**
         * @description - Register testable domain, interface, service, or store.
         *
         * @method register
         * @param {object} definition - Test fixture registration definition for domain, interface, service, or store.
         * @return void
         */
        this.register = function register (definition) { // eslint-disable-line
            Hf.log(`error`, `FixtureFactory.register - Method is not implemented by default. Implementation required.`);
        };
        /**
         * @description - Start the test fixture.
         *
         * @method start
         * @param {object} option
         * @param {function} done
         * @return void
         */
        this.start = function start (option = {}, done) { // eslint-disable-line
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.start - Input done function is invalid.`);
                }
            }

            // TODO: Implement use case for fixture start option.
            option = Hf.isObject(option) ? option : {};
            done();
        };
        /**
         * @description - Stop the test fixture.
         *
         * @method stop
         * @param {function} done
         * @return void
         */
        this.stop = function stop (done) {
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.start - Input done function is invalid.`);
                }
            }

            done();
        };
        /**
         * @description - Restart test fixture.
         *
         * @method restart
         * @param {object} option
         * @param {function} done
         * @return void
         */
        this.restart = function restart (option = {}, done) {
            const fixture = this;

            // TODO: Implement use case for fixture start option.
            option = Hf.isObject(option) ? option : {};

            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.restart - Input done function is invalid.`);
                }
            }

            fixture.stop(() => {
                fixture.start(option, done);
            });
        };
        /**
         * @description - Perform unit testing...
         *
         * @method test
         * @param {function} tester
         * @param {string} description
         * @return void
         */
        this.test = function test (tester, description = ``) { // eslint-disable-line
            Hf.log(`error`, `FixtureFactory.stop - Method is not implemented by default. Implementation required.`);
        };
    }
});
<commit_msg>Added getTestRunner and registerTestRunner methods<commit_after>/**
 * Copyright 2015-present Tuan Le.
 *
 * Licensed under the MIT License.
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/mit-license.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *------------------------------------------------------------------------
 *
 * @module FixtureFactory
 * @description - A generic test fixture factory module.
 *
 * @author Tuan Le (tuan.t.lei@gmail.com)
 *
 * @flow
 */
'use strict'; // eslint-disable-line

/* load Hyperflow */
import { Hf } from '../../hyperflow';

/* load EventStreamComposite */
import EventStreamComposite from './composites/event-stream-composite';

/* load Composer */
import Composer from '../composer';

/* factory Ids */
import {
    FIXTURE_FACTORY_CODE
} from './factory-code';

/**
 * @description - A generic test fixture factory module.
 *
 * @module TestkitFactory
 */
export default Composer({
    composites: [
        EventStreamComposite
    ],
    state: {
        name: {
            value: `unnamed`,
            required: true
        },
        fId: {
            computable: {
                contexts: [
                    `name`
                ],
                compute () {
                    return `${FIXTURE_FACTORY_CODE}-${this.name}`;
                }
            }
        }
    },
    FixtureFactory: function FixtureFactory () {
        /* ----- Private Variables ------------- */
        let _testRunner;
        /* ----- Public Functions -------------- */
        /**
         * @description - Initialize service.
         *
         * @method $init
         * @return void
         */
        this.$init = function $init () {
            Hf.log(`warn0`, `FixtureFactory.$init - Method is not implemented by default.`);
        };
        /**
         * @description - Get fixture test runner.
         *
         * @method getTestRunner
         * @return {object}
         */
        this.getTestRunner = function getTestRunner () {
            const fixture = this;

            if (Hf.DEVELOPMENT) {
                if (!Hf.isObject(_testRunner)) {
                    Hf.log(`error`, `FixtureFactory.getTestRunner - Test fixture:${fixture.name} is not registered with a test runner.`);
                }
            }

            return _testRunner;
        };
        /**
         * @description - Register fixture with a test runner.
         *
         * @method registerTestRunner
         * @param {function} definition - Test fixture test runner function.
         * @return void
         */
        this.registerTestRunner = function registerTestRunner (testRunner) {
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(testRunner)) {
                    Hf.log(`error`, `FixtureFactory.registerTestRunner - Input test runner function is invalid.`);
                }
            }

            _testRunner = testRunner;
        };
        /**
         * @description - Setup fixture event stream.
         *
         * @method setup
         * @param {function} done
         * @return void
         */
        this.setup = function setup (done) { // eslint-disable-line
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.setup - Input done function is invalid.`);
                }
            }

            done();
        };
        /**
         * @description - Teardown fixture event stream.
         *
         * @method teardown
         * @param {function} done
         * @return void
         */
        this.teardown = function teardown (done) { // eslint-disable-line
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.teardown - Input done function is invalid.`);
                }
            }

            done();
        };
        /**
         * @description - Check if domain has started.
         *
         * @method hasStarted
         * @return {boolean}
         */
        this.hasStarted = function hasStarted () {
            return false;
        };
        /**
         * @description - Register testable domain, interface, service, or store.
         *
         * @method register
         * @param {object} definition - Test fixture registration definition for domain, interface, service, or store.
         * @return void
         */
        this.register = function register (definition) { // eslint-disable-line
            Hf.log(`error`, `FixtureFactory.register - Method is not implemented by default. Implementation required.`);
        };
        /**
         * @description - Start the test fixture.
         *
         * @method start
         * @param {object} option
         * @param {function} done
         * @return void
         */
        this.start = function start (option = {}, done) { // eslint-disable-line
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.start - Input done function is invalid.`);
                }
            }

            // TODO: Implement use case for fixture start option.
            option = Hf.isObject(option) ? option : {};
            done();
        };
        /**
         * @description - Stop the test fixture.
         *
         * @method stop
         * @param {function} done
         * @return void
         */
        this.stop = function stop (done) {
            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.start - Input done function is invalid.`);
                }
            }

            done();
        };
        /**
         * @description - Restart test fixture.
         *
         * @method restart
         * @param {object} option
         * @param {function} done
         * @return void
         */
        this.restart = function restart (option = {}, done) {
            const fixture = this;

            // TODO: Implement use case for fixture start option.
            option = Hf.isObject(option) ? option : {};

            if (Hf.DEVELOPMENT) {
                if (!Hf.isFunction(done)) {
                    Hf.log(`error`, `FixtureFactory.restart - Input done function is invalid.`);
                }
            }

            fixture.stop(() => {
                fixture.start(option, done);
            });
        };
        /**
         * @description - Perform unit testing...
         *
         * @method test
         * @param {function} tester
         * @param {string} description
         * @return void
         */
        this.test = function test (tester, description = ``) { // eslint-disable-line
            Hf.log(`error`, `FixtureFactory.stop - Method is not implemented by default. Implementation required.`);
        };
    }
});
<|endoftext|>


<commit_before>import xhr from 'xhr'
import {parse as parseUrl, format as formatUrl} from 'url'

function joinPath (a = '', b = '') {
  if (!a && !b) return ''
  const leadingSlash = a.charAt(0) === '/'
  const trailingSlash = b.charAt(b.length - 1) === '/'
  const tokens = `${a}/${b}`.split('/').filter(Boolean)
  for (let i = 0; i < tokens.length; i++) {
    let token = tokens[i]
    if (token === '..') {
      tokens.splice(i - 1, 2)
      i--
    } else if (token === '.') {
      tokens.splice(i, 1)
      i--
    }
  }
  let path = tokens.join('/')
  if (leadingSlash) path = `/${path}`
  if (trailingSlash) path = `${path}/`
  return path
}

export default function (baseUrl, options) {
  if (!options) options = {}
  const baseUrlParts = parseUrl(baseUrl)
  const i = baseUrlParts.auth ? baseUrlParts.auth.indexOf(':') : -1
  const username = i !== -1 ? baseUrlParts.auth.slice(0, i) : (baseUrlParts.auth || undefined)
  const password = i !== -1 ? baseUrlParts.auth.slice(i + 1) : (baseUrlParts.auth ? '' : undefined)
  delete baseUrlParts.auth

  const queue = []
  const maxTasks = typeof options.maxSockets === 'number' ? options.maxSockets * 2 : Infinity
  let activeTasks = 0

  function drainQueue () {
    if (!queue.length || activeTasks >= maxTasks) return
    const task = queue.shift()
    activeTasks += 1
    task(() => {
      activeTasks -= 1
      drainQueue()
    })
  }

  return function request ({method, url, headers, body}, cb) {
    const auth = typeof username === 'string' ? {username, password} : {}
    const urlParts = {
      ...baseUrlParts,
      pathname: url.pathname ? (
        baseUrlParts.pathname ? joinPath(baseUrlParts.pathname, url.pathname) : url.pathname
      ) : baseUrlParts.pathname,
      search: url.search ? (
        baseUrlParts.search ? `${baseUrlParts.search}&${url.search.slice(1)}` : url.search
      ) : baseUrlParts.search
    }

    queue.push((next) => {
      let callback = (...args) => {
        callback = () => undefined
        next()
        cb(...args)
      }
      const req = xhr({
        responseType: 'text',
        ...options,
        ...auth,
        url: formatUrl(urlParts),
        body,
        method,
        headers
      }, (err, res) => {
        if (!err) callback(null, res)
        else {
          err.request = req
          callback(err)
        }
      })
    })

    drainQueue()
  }
}
<commit_msg>Adding Authorization header for ajax requests.<commit_after>import xhr from 'xhr'
import {parse as parseUrl, format as formatUrl} from 'url'

function joinPath (a = '', b = '') {
  if (!a && !b) return ''
  const leadingSlash = a.charAt(0) === '/'
  const trailingSlash = b.charAt(b.length - 1) === '/'
  const tokens = `${a}/${b}`.split('/').filter(Boolean)
  for (let i = 0; i < tokens.length; i++) {
    let token = tokens[i]
    if (token === '..') {
      tokens.splice(i - 1, 2)
      i--
    } else if (token === '.') {
      tokens.splice(i, 1)
      i--
    }
  }
  let path = tokens.join('/')
  if (leadingSlash) path = `/${path}`
  if (trailingSlash) path = `${path}/`
  return path
}

export default function (baseUrl, options) {
  if (!options) options = {}
  const baseUrlParts = parseUrl(baseUrl)
  const i = baseUrlParts.auth ? baseUrlParts.auth.indexOf(':') : -1
  const username = i !== -1 ? baseUrlParts.auth.slice(0, i) : (baseUrlParts.auth || undefined)
  const password = i !== -1 ? baseUrlParts.auth.slice(i + 1) : (baseUrlParts.auth ? '' : undefined)
  delete baseUrlParts.auth

  const queue = []
  const maxTasks = typeof options.maxSockets === 'number' ? options.maxSockets * 2 : Infinity
  let activeTasks = 0

  function drainQueue () {
    if (!queue.length || activeTasks >= maxTasks) return
    const task = queue.shift()
    activeTasks += 1
    task(() => {
      activeTasks -= 1
      drainQueue()
    })
  }

  return function request ({method, url, headers, body}, cb) {
    const auth = typeof username === 'string' ? {username, password} : {}

    if(typeof window !== "undefined" && auth.username !== undefined && headers['Authorization'] === undefined) {
      const btoa = window.btoa ? window.btoa : base64.encode;
      headers['Authorization'] = "Basic " + btoa(auth.username + ":" + auth.password);
    }

    const urlParts = {
      ...baseUrlParts,
      pathname: url.pathname ? (
        baseUrlParts.pathname ? joinPath(baseUrlParts.pathname, url.pathname) : url.pathname
      ) : baseUrlParts.pathname,
      search: url.search ? (
        baseUrlParts.search ? `${baseUrlParts.search}&${url.search.slice(1)}` : url.search
      ) : baseUrlParts.search
    }

    queue.push((next) => {
      let callback = (...args) => {
        callback = () => undefined
        next()
        cb(...args)
      }
      const req = xhr({
        responseType: 'text',
        ...options,
        ...auth,
        url: formatUrl(urlParts),
        body,
        method,
        headers
      }, (err, res) => {
        if (!err) callback(null, res)
        else {
          err.request = req
          callback(err)
        }
      })
    })

    drainQueue()
  }
}
<|endoftext|>


<commit_before>import {
  alphanumerics,
  BACKSPACE,
  modifiers,
} from './__test__/keys';
import {
  kbdCommand,
  isValidKbdCommand,
} from './constructor';
import {
  defaultCommands,
} from './defaults';
import * as e from './__test__/events';

const singleKey = key =>
  ({ key, ctrlKey: false, altKey: false, shiftKey: false });
describe('keyboard.constructor', function () {
  describe('kbdCommand', function () {
    describe('string inputs', function () {
      it('should handle valid single keys on their own', function () {
        expect(kbdCommand('Enter')).to.deep.equal(singleKey('Enter'));
        expect(kbdCommand('=')).to.deep.equal(singleKey('='));
        expect(kbdCommand('ArrowLeft')).to.deep.equal(singleKey('ArrowLeft'));
      });
      it('should throw a syntax error when given a single key that requires a modifier', function () {
        const commands = [...alphanumerics, BACKSPACE];
        let i;
        for (i = 0; i < commands.length; i++) {
          const key = commands[i];
          expect(function () {
            kbdCommand(key);
          }).to.throw(`${key} is not a valid command string!`);
        }
      });
      it('should interpret ctrl+single-keys', function () {
        expect(kbdCommand('Ctrl+K')).to.deep.equal({
          key: 'K',
          ctrlKey: true,
          altKey: false,
          shiftKey: false,
        });
        expect(kbdCommand('Alt+ArrowUp')).to.deep.equal({
          key: 'ArrowUp',
          ctrlKey: false,
          altKey: true,
          shiftKey: false,
        });
      });
      it('should interpret multiple modifiers properly', function () {
        expect(kbdCommand('Meta+Shift+F')).to.deep.equal({
          key: 'F',
          ctrlKey: true,
          shiftKey: true,
          altKey: false,
        });
        expect(kbdCommand('Ctrl+Alt+Z')).to.deep.equal({
          key: 'Z',
          ctrlKey: true,
          shiftKey: false,
          altKey: true,
        });
        expect(kbdCommand('Alt+Shift+`')).to.deep.equal({
          key: '`',
          ctrlKey: false,
          shiftKey: true,
          altKey: true,
        });
      });
      it('should interpret meta keys as a ctrl', function () {
        expect(kbdCommand('Meta+Z')).to.deep.equal(kbdCommand('Ctrl+Z'));
        expect(
          kbdCommand('Meta+Ctrl+Z'),
        ).to.deep.equal(kbdCommand('Ctrl+Z'));
      });

      describe('default keybindings', function () {
        const defaultBindings = [
          'Ctrl+Backspace',
          'Enter',
          'ArrowUp',
          'ArrowDown',
          'ArrowRight',
          'ArrowLeft',
          'Alt+R',
          'Alt+P',
          'Alt+C',
          'Alt+B',
          'Alt+Shift+D',
        ];
        for (const binding of defaultBindings) {
          it(`should have no errors on ${binding}`, function () {
            expect(kbdCommand(binding).error).to.be.undefined;
          });
        }
      });

    });
    describe('event inputs', function () {
      it('should handle a Ctrl+Shift+F event', function () {
        expect(kbdCommand(e.eventCtrlShiftF)).to.deep.equal({
          key: 'F',
          ctrlKey: true,
          shiftKey: true,
          altKey: false,
        });
      });
      it('should handle Ctrl+`', function () {
        expect(kbdCommand(e.eventCtrlBacktick)).to.deep.equal({
          key: '`',
          ctrlKey: true,
          shiftKey: false,
          altKey: false,
        });
      });
      it('should treat meta the same as Ctrl', function () {
        expect(kbdCommand(e.eventMeta1)).to.deep.equal({
          key: '1',
          ctrlKey: true,
          shiftKey: false,
          altKey: false,
        });
        expect(kbdCommand(e.eventCtrl1)).to.deep.equal(kbdCommand(e.eventMeta1));
      });
      it('should allow a valid single key <[>', function () {
        expect(kbdCommand(e.eventBracketLeft).error).be.undefined;
        expect(kbdCommand(e.eventBracketLeft)).to.deep.equal({
          key: '[',
          ctrlKey: false,
          shiftKey: false,
          altKey: false,
        });
      });
      it('should allow a valid single key <Enter>', function () {
        expect(kbdCommand(e.eventEnter).error).to.be.undefined;
        expect(kbdCommand(e.eventEnter)).to.deep.equal(singleKey('Enter'));
      });
      it('should have an error key on an invalid single key', function () {
        expect(kbdCommand(e.eventG).error).to.not.be.undefined;
      });
    });
  });
  describe('isValidKbdCommand', function () {
    describe('defaults', function () {
      const commands = Object.values(defaultCommands);
      for (const command of commands) {
        it(`should return true for ${command.key}`, function () {
          expect(isValidKbdCommand(command.command)).to.be.true;
        });
      }
    });
    describe('modifiers', function () {
      describe('handling all single modifier keys', function () {
        for (const m of modifiers) {
          const ctrlKey = /ctrl/i.test(m);
          const shiftKey = /shift/i.test(m);
          const altKey = /alt/i.test(m);
          it(`should return false for ${m}`, function () {
            expect(isValidKbdCommand({
              key: m,
              ctrlKey,
              shiftKey,
              altKey,
            })).to.be.false;
          });
        }
      });
    });
  });
});

<commit_msg>Test error passing<commit_after>import {
  alphanumerics,
  BACKSPACE,
  modifiers,
} from './__test__/keys';
import {
  kbdCommand,
  isValidKbdCommand,
} from './constructor';
import {
  defaultCommands,
} from './defaults';
import * as constants from './constants';
import * as e from './__test__/events';

const singleKey = key =>
  ({ key, ctrlKey: false, altKey: false, shiftKey: false });
describe('keyboard.constructor', function () {
  describe('kbdCommand', function () {
    describe('string inputs', function () {
      it('should handle valid single keys on their own', function () {
        expect(kbdCommand('Enter')).to.deep.equal(singleKey('Enter'));
        expect(kbdCommand('=')).to.deep.equal(singleKey('='));
        expect(kbdCommand('ArrowLeft')).to.deep.equal(singleKey('ArrowLeft'));
      });
      it('should throw a syntax error when given a single key that requires a modifier', function () {
        const commands = [...alphanumerics, BACKSPACE];
        let i;
        for (i = 0; i < commands.length; i++) {
          const key = commands[i];
          expect(function () {
            kbdCommand(key);
          }).to.throw(`${key} is not a valid command string!`);
        }
      });
      it('should interpret ctrl+single-keys', function () {
        expect(kbdCommand('Ctrl+K')).to.deep.equal({
          key: 'K',
          ctrlKey: true,
          altKey: false,
          shiftKey: false,
        });
        expect(kbdCommand('Alt+ArrowUp')).to.deep.equal({
          key: 'ArrowUp',
          ctrlKey: false,
          altKey: true,
          shiftKey: false,
        });
      });
      it('should interpret multiple modifiers properly', function () {
        expect(kbdCommand('Meta+Shift+F')).to.deep.equal({
          key: 'F',
          ctrlKey: true,
          shiftKey: true,
          altKey: false,
        });
        expect(kbdCommand('Ctrl+Alt+Z')).to.deep.equal({
          key: 'Z',
          ctrlKey: true,
          shiftKey: false,
          altKey: true,
        });
        expect(kbdCommand('Alt+Shift+`')).to.deep.equal({
          key: '`',
          ctrlKey: false,
          shiftKey: true,
          altKey: true,
        });
      });
      it('should interpret meta keys as a ctrl', function () {
        expect(kbdCommand('Meta+Z')).to.deep.equal(kbdCommand('Ctrl+Z'));
        expect(
          kbdCommand('Meta+Ctrl+Z'),
        ).to.deep.equal(kbdCommand('Ctrl+Z'));
      });

      describe('default keybindings', function () {
        const defaultBindings = [
          'Ctrl+Backspace',
          'Enter',
          'ArrowUp',
          'ArrowDown',
          'ArrowRight',
          'ArrowLeft',
          'Alt+R',
          'Alt+P',
          'Alt+C',
          'Alt+B',
          'Alt+Shift+D',
        ];
        for (const binding of defaultBindings) {
          it(`should have no errors on ${binding}`, function () {
            expect(kbdCommand(binding).error).to.be.undefined;
          });
        }
      });
    });
    describe('event inputs', function () {
      it('should return with an error key on an invalid final key <F1>', function () {
        expect(kbdCommand({ key: 'F1' })).to.have.property('error', constants.ERROR_MSG_NOT_VALID_SINGLE_KEY);
        expect(kbdCommand({ ctrlKey: true, key: 'F1' })).to.have.property('error', constants.ERROR_MSG_NOT_VALID_FINAL_COMBO_KEY);
      });
      it('should handle a Ctrl+Shift+F event', function () {
        expect(kbdCommand(e.eventCtrlShiftF)).to.deep.equal({
          key: 'F',
          ctrlKey: true,
          shiftKey: true,
          altKey: false,
        });
      });
      it('should handle Ctrl+`', function () {
        expect(kbdCommand(e.eventCtrlBacktick)).to.deep.equal({
          key: '`',
          ctrlKey: true,
          shiftKey: false,
          altKey: false,
        });
      });
      it('should treat meta the same as Ctrl', function () {
        expect(kbdCommand(e.eventMeta1)).to.deep.equal({
          key: '1',
          ctrlKey: true,
          shiftKey: false,
          altKey: false,
        });
        expect(kbdCommand(e.eventCtrl1)).to.deep.equal(kbdCommand(e.eventMeta1));
      });
      it('should allow a valid single key <[>', function () {
        expect(kbdCommand(e.eventBracketLeft).error).be.undefined;
        expect(kbdCommand(e.eventBracketLeft)).to.deep.equal({
          key: '[',
          ctrlKey: false,
          shiftKey: false,
          altKey: false,
        });
      });
      it('should allow a valid single key <Enter>', function () {
        expect(kbdCommand(e.eventEnter).error).to.be.undefined;
        expect(kbdCommand(e.eventEnter)).to.deep.equal(singleKey('Enter'));
      });
      it('should have an error key on an invalid single key', function () {
        expect(kbdCommand(e.eventG).error).to.not.be.undefined;
      });
    });
  });
  describe('isValidKbdCommand', function () {
    describe('defaults', function () {
      const commands = Object.values(defaultCommands);
      for (const command of commands) {
        it(`should return true for ${command.key}`, function () {
          expect(isValidKbdCommand(command.command)).to.be.true;
        });
      }
    });
    describe('modifiers', function () {
      describe('handling all single modifier keys', function () {
        for (const m of modifiers) {
          const ctrlKey = /ctrl/i.test(m);
          const shiftKey = /shift/i.test(m);
          const altKey = /alt/i.test(m);
          it(`should return false for ${m}`, function () {
            expect(isValidKbdCommand({
              key: m,
              ctrlKey,
              shiftKey,
              altKey,
            })).to.be.false;
          });
        }
      });
    });
  });
});

<|endoftext|>


<commit_before>'use strict';

/**
 *
 * @constructor
 */
export default class Events {

  /**
   * Adds a native event listener for an event. Does cross-browser Kung Fu stuff.
   *
   * @param {EventTarget} el - The target (element) to add the event listener to.
   * @param {string} type - A string representing the event type to listen for.
   * @param {Function} listener - The callback to be called on the event.
   * @param {boolean} [useCapture] - Optional, defaults to false. Native useCapture
   *     parameter. Read MDN.
   * @returns {*}
   */
  static addListener(el, type, listener, lazy = false, useCapture = false) {

    const multiple = type.split(' ');
    const modListener = lazy ? () => window.setTimeout(listener, 0) : listener;

    for (type of multiple) {
      if (el.addEventListener) {
        el.addEventListener(type, modListener, useCapture);
      } else if (el.attachEvent) {
        el.attachEvent('on' + type, modListener);
      }
    }

    return this;
  };

  /**
   * Removes a native event listener from an event. Does cross-browser Kung Fu stuff.
   *
   * @param {EventTarget} el - The target (element) to remove the event listener from.
   * @param {string} type - A string representing the event type to listen for.
   * @param {Function} listener - The callback to be removed from the event.
   * @param {boolean} [useCapture] - Optional, defaults to false. Native useCapture
   *     parameter. Read MDN.
   * @returns {*}
   */
  static removeListener(el, type, listener, useCapture = false) {

    if (el.removeEventListener) {
      el.removeEventListener(type, listener, useCapture);
    } else if (el.detachEvent) {
      el.detachEvent('on' + type, listener);
    }

    return this;
  };

}<commit_msg>wrote documentation<commit_after>'use strict';

/**
 *
 * @constructor
 */
export default class Events {

  /**
   * Adds a native event listener for an event. Does cross-browser Kung Fu stuff.
   *
   * @param {EventTarget} el - The target (element) to add the event listener to.
   * @param {string} type - A string representing the event type to listen for.
   * @param {Function} listener - The callback to be called on the event.
   * @param {boolean} [lazy] - Optional, defaults to false. Whether or not the listener
   *     should be called after the event has completed firing.
   * @param {boolean} [useCapture] - Optional, defaults to false. Native useCapture
   *     parameter. Read MDN.
   * @returns {*}
   */
  static addListener(el, type, listener, lazy = false, useCapture = false) {

    const multiple = type.split(' ');
    const modListener = lazy ? () => window.setTimeout(listener, 0) : listener;

    for (type of multiple) {
      if (el.addEventListener) {
        el.addEventListener(type, modListener, useCapture);
      } else if (el.attachEvent) {
        el.attachEvent('on' + type, modListener);
      }
    }

    return this;
  };

  /**
   * Removes a native event listener from an event. Does cross-browser Kung Fu stuff.
   *
   * @param {EventTarget} el - The target (element) to remove the event listener from.
   * @param {string} type - A string representing the event type to listen for.
   * @param {Function} listener - The callback to be removed from the event.
   * @param {boolean} [useCapture] - Optional, defaults to false. Native useCapture
   *     parameter. Read MDN.
   * @returns {*}
   */
  static removeListener(el, type, listener, useCapture = false) {

    if (el.removeEventListener) {
      el.removeEventListener(type, listener, useCapture);
    } else if (el.detachEvent) {
      el.detachEvent('on' + type, listener);
    }

    return this;
  };

}<|endoftext|>


<commit_before>define(function() {
    /**
     * @ngInject
     */
    var Controller = function($state, $window) {
        /** @private */
        this.location = $window.location;

        this.menuItems = [{
            href: $state.href('index'),
            label: 'Home',
            icon: 'home',
        }, {
            href: $state.href('photos'),
            label: 'Photos',
            icon: 'photo',
        }, {
            href: $state.href('blog'),
            label: 'Blog',
            icon: 'none',
        }, {
            href: $state.href('posts'),
            label: 'Posts',
            icon: 'none'
        }, {
            href: $state.href('events'),
            label: 'Events',
            icon: 'none',
        }, {
            href: $state.href('login'),
            label: "Log in",
            icon: 'none'
        }];
    };

    Controller.prototype.reload = function() {
        this.location.reload();
    };

    return Controller;
});
<commit_msg>feature(menus/site): add "Send feedback" link for reporting bugs/ideas<commit_after>define(function() {
    /**
     * @ngInject
     */
    var Controller = function($state, $window) {
        /** @private */
        this.location = $window.location;

        this.menuItems = [{
            href: $state.href('index'),
            label: 'Home',
            icon: 'home',
        }, {
            href: $state.href('photos'),
            label: 'Photos',
            icon: 'photo',
        }, {
            href: $state.href('blog'),
            label: 'Blog',
            icon: 'none',
        }, {
            href: $state.href('posts'),
            label: 'Posts',
            icon: 'none'
        }, {
            href: $state.href('events'),
            label: 'Events',
            icon: 'none',
        }, {
            href: 'https://github.com/ewinslow/ng-elgg/issues/new',
            label: 'Send feedback',
            icon: 'none'
        }, {
            href: $state.href('login'),
            label: "Log in",
            icon: 'none'
        }];
    };

    Controller.prototype.reload = function() {
        this.location.reload();
    };

    return Controller;
});
<|endoftext|>


<commit_before>import {primaryHost as githubHost, org as defaultOrg} from '../constants/github'
import pages from '../pages'
import {parse as parseUrl} from './url'
import {pathToMeta, isReadme} from './github'

/**
 * Add to the structure:
 *  - name
 *  - org
 */
const addDefaults = (root) => {
  const newRoot = {}

  for (const name in root) {
    const page = newRoot[name] = {...root[name], name}
    if (!page.org) page.org = defaultOrg
    const {children} = page
    if (children) page.children = addDefaults(children)
  }

  return newRoot
}

/**
 * Transformed pages structure.
 */
export const tree = addDefaults(pages)

/**
 * A flat map of pages.
 */
export const map = (function iterate(root, result) {
  for (const name in root) {
    const page = root[name]
    result[name] = page
    if (page.children) iterate(page.children, result)
  }
  return result
}(tree, {}))

const isSameUrl = (url0, url1) => {
  const {host: host0, pathname: path0} = parseUrl(url0)
  const {host: host1, pathname: path1} = parseUrl(url1)
  // Trim trailing slash.
  const trim = str => str.replace(/\/$/, '')

  return host0 === host1 && trim(path0) === trim(path1)
}

/**
 * Get a page object by URL.
 */
export const findPage = (url) => {
  const {host, pathname} = parseUrl(url)

  for (const name in map) {
    const page = map[name]
    if (page.hidden || page.iframe) continue
    // Its an external page, we can compare by `url`.
    if (page.url && isSameUrl(page.url, url)) return page
    if (host === githubHost) {
      const meta = pathToMeta(pathname)
      if (meta.org === page.org && meta.repo === page.repo && meta.view !== 'tree') {
        if (meta.path === page.path || isReadme(meta.path)) {
          return page
        }
      }
    }
  }

  return null
}

/**
 * Get first page, which has `home: true`.
 */
export const home = (() => {
  for (const name in map) {
    const page = map[name]
    if (page.home) return page
  }
  return null
})()

const stripSlashes = str => str.replace(/\//g, '')

const names = Object.keys(map)

/**
 * Returns true if path2 is after path1 in the navigation.
 */
export const isAfter = (path0, path1) => {
  const name0 = stripSlashes(path0)
  const name1 = stripSlashes(path1)
  return names.indexOf(name0) < names.indexOf(name1)
}
<commit_msg>fix url parser<commit_after>import {primaryHost as githubHost, org as defaultOrg} from '../constants/github'
import pages from '../pages'
import {parse as parseUrl} from './url'
import {pathToMeta, isReadme} from './github'

/**
 * Add to the structure:
 *  - name
 *  - org
 */
const addDefaults = (root) => {
  const newRoot = {}

  for (const name in root) {
    const page = newRoot[name] = {...root[name], name}
    if (!page.org) page.org = defaultOrg
    const {children} = page
    if (children) page.children = addDefaults(children)
  }

  return newRoot
}

/**
 * Transformed pages structure.
 */
export const tree = addDefaults(pages)

/**
 * A flat map of pages.
 */
export const map = (function iterate(root, result) {
  for (const name in root) {
    const page = root[name]
    result[name] = page
    if (page.children) iterate(page.children, result)
  }
  return result
}(tree, {}))

const isSameUrl = (url0, url1) => {
  const {host: host0, pathname: path0} = parseUrl(url0)
  const {host: host1, pathname: path1} = parseUrl(url1)
  // Trim trailing slash.
  const trim = str => str.replace(/\/$/, '')

  return host0 === host1 && trim(path0) === trim(path1)
}

/**
 * Get a page object by URL.
 */
export const findPage = (url) => {
  const {host, pathname} = parseUrl(url)

  for (const name in map) {
    const page = map[name]
    if (page.hidden || page.iframe) continue
    // Its an external page, we can compare by `url`.
    if (page.url && isSameUrl(page.url, url)) return page
    if (host === githubHost) {
      const meta = pathToMeta(pathname)
      if (
          meta.org === page.org &&
          meta.repo === page.repo &&
          (!meta.view || meta.view === 'blob') &&
          (meta.path === page.path || isReadme(meta.path))
      ) {
        return page
      }
    }
  }

  return null
}

/**
 * Get first page, which has `home: true`.
 */
export const home = (() => {
  for (const name in map) {
    const page = map[name]
    if (page.home) return page
  }
  return null
})()

const stripSlashes = str => str.replace(/\//g, '')

const names = Object.keys(map)

/**
 * Returns true if path2 is after path1 in the navigation.
 */
export const isAfter = (path0, path1) => {
  const name0 = stripSlashes(path0)
  const name1 = stripSlashes(path1)
  return names.indexOf(name0) < names.indexOf(name1)
}
<|endoftext|>


<commit_before>/**
 * DialogView.js
 */
(function (spiderOakApp, window, undefined) {
  "use strict";
  var console = window.console || {};
  console.log = console.log || function(){};
  var Backbone    = window.Backbone,
      _           = window._,
      $           = window.$,
      s           = window.s;

  spiderOakApp.DialogView = spiderOakApp.ViewBase.extend({
    className: "modal",
    events: {
      "tap .cancel-btn a": "cancel_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
      var supportsOrientationChange = "onorientationchange" in window;
      this.orientationEvent = supportsOrientationChange ?
                                "orientationchange" :
                                "resize";
    },
    render: function() {
      $("body").append(this.el);
      return this;
    },
    showWait: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      this.$el.html(window.tmpl["waitDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    showNotifyErrorResponse: function(response, options) {
      options = options ? _.clone(options) : {};
      options.title = options.title || " Error";
      options.duration = options.duration || 4000;
      options.subtitle = ((options.subtitle && (options.subtitle + ": ")) ||
                          "");
      options.subtitle += (response.statusText || "Network timeout " +
                           "
(status: " + response.status || 0 + ")");
      return this.showNotify(options);
    },
    showNotify: function(options) {
      options = options || {};
      options.title = options.title || "Done"; // terrible default ;)
      options.subtitle = options.subtitle || "";
      options.duration = options.duration || 2000; // in ms
      this.$el.html(window.tmpl["waitDialog"](options));
      this.$(".fadingBarsG").hide();
      this.$el.show();
      window.setTimeout(function() {
        this.hide();
      }.bind(this), options.duration);
    },
    showToast: function(options) {
      options = options || {};
      options.title = options.title || "Done"; // terrible default ;)
      options.duration = options.duration || 1000; // in ms
      options.onShow = options.onShow || function(){};
      options.onHide = options.onHide || function(){};
      this.$el.html(window.tmpl["toastDialog"](options));
      this.$el.css({
        backgroundColor: "rgba(0,0,0,0)"
      });
      this.$el.show();
      options.onShow();
      window.setTimeout(function() {
        this.hide();
        options.onHide();
        this.$el.css({
          backgroundColor: "rgba(0,0,0,0.7)"
        });
      }.bind(this), options.duration);
    },
    cancel_tapHandler: function(event) {
      event.preventDefault();
      $(document).trigger("backbutton");
    },
    hide: function() {
      $(window).off(this.orientationEvent);
      this.$el.hide();
      this.$el.empty();
    },
    showProgress: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      options.start = options.start || 0;
      this.$el.html(window.tmpl["progressDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    updateProgress: function(progressPercent) {
      progressPercent = progressPercent * 2; // WHY?! GAH!!
      if (progressPercent > 100) {
        progressPercent = 100;
      }
      this.$(".meter .progress").animate({"width":progressPercent+"%"});
    },
    showDialogView: function(view) {
      $(window).on(this.orientationEvent, function() {
        // alert("The rotation is " + window.orientation + " and the resolution is " + screen.width + " x " + screen.height);
        if (window.orientation === -90 || window.orientation === 90) {
          view.$el.css({"margin-top":"0", "max-height":"300px"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
        else {
          view.$el.css({"margin-top":"10%", "max-height":"94%"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
      }, false);
      this.$el.html(view.render().el);
      if (window.orientation === -90 || window.orientation === 90) {
        view.$el.css({"margin-top":"0", "max-height":"300px"});
      }
      window.setTimeout(function(){
        view.scroller.refresh();
      },10);
      if ($.os.ios) {
        // the stupid -50% is to keep it centered on iPad
        var _this = this;
        view.$el.css({"-webkit-transform":"translate3d(-50%,100%,0)"});
        this.$el.show();
        window.setTimeout(function(){
          view.$el.animate(
            {"-webkit-transform":"translate3d(-50%,0,0)"}, 150, 'ease-in-out');
        },50);
      } else {
        this.$el.show();
      }
    },
    close: function(){
      this.remove();
      this.unbind();
      // handle other unbinding needs, here
      _.each(this.subViews, function(subViews){
        if (subViews.close){
          subViews.close();
        }
      });
    }
  });
  spiderOakApp.dialogView = new spiderOakApp.DialogView().render();

  spiderOakApp.ContextPopup = spiderOakApp.ViewBase.extend({
    className: "context-popup",
    events: {
      "tap a": "a_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
    },
    render: function() {
      this.$el.html(
        window.tmpl["contextPopup"]({
          items: this.options.items
        })
      );
      this.scroller = new window.iScroll(this.el, {
        bounce: !$.os.android,
        vScrollbar: false,
        hScrollbar: false
      });
      return this;
    },
    a_tapHandler: function(event) {
      this.trigger("item:tapped", event);
    },
    remove: function() {
      this.close();
      this.$el.remove();
      this.stopListening();
      return this;
    },
    close: function() {
      this.scroller.destroy();
    }
  });

})(window.spiderOakApp = window.spiderOakApp || {}, window);
<commit_msg>Cheeky fix to master for progress discrepancy between iOS and Android<commit_after>/**
 * DialogView.js
 */
(function (spiderOakApp, window, undefined) {
  "use strict";
  var console = window.console || {};
  console.log = console.log || function(){};
  var Backbone    = window.Backbone,
      _           = window._,
      $           = window.$,
      s           = window.s;

  spiderOakApp.DialogView = spiderOakApp.ViewBase.extend({
    className: "modal",
    events: {
      "tap .cancel-btn a": "cancel_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
      var supportsOrientationChange = "onorientationchange" in window;
      this.orientationEvent = supportsOrientationChange ?
                                "orientationchange" :
                                "resize";
    },
    render: function() {
      $("body").append(this.el);
      return this;
    },
    showWait: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      this.$el.html(window.tmpl["waitDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    showNotifyErrorResponse: function(response, options) {
      options = options ? _.clone(options) : {};
      options.title = options.title || " Error";
      options.duration = options.duration || 4000;
      options.subtitle = ((options.subtitle && (options.subtitle + ": ")) ||
                          "");
      options.subtitle += (response.statusText || "Network timeout " +
                           "
(status: " + response.status || 0 + ")");
      return this.showNotify(options);
    },
    showNotify: function(options) {
      options = options || {};
      options.title = options.title || "Done"; // terrible default ;)
      options.subtitle = options.subtitle || "";
      options.duration = options.duration || 2000; // in ms
      this.$el.html(window.tmpl["waitDialog"](options));
      this.$(".fadingBarsG").hide();
      this.$el.show();
      window.setTimeout(function() {
        this.hide();
      }.bind(this), options.duration);
    },
    showToast: function(options) {
      options = options || {};
      options.title = options.title || "Done"; // terrible default ;)
      options.duration = options.duration || 1000; // in ms
      options.onShow = options.onShow || function(){};
      options.onHide = options.onHide || function(){};
      this.$el.html(window.tmpl["toastDialog"](options));
      this.$el.css({
        backgroundColor: "rgba(0,0,0,0)"
      });
      this.$el.show();
      options.onShow();
      window.setTimeout(function() {
        this.hide();
        options.onHide();
        this.$el.css({
          backgroundColor: "rgba(0,0,0,0.7)"
        });
      }.bind(this), options.duration);
    },
    cancel_tapHandler: function(event) {
      event.preventDefault();
      $(document).trigger("backbutton");
    },
    hide: function() {
      $(window).off(this.orientationEvent);
      this.$el.hide();
      this.$el.empty();
    },
    showProgress: function(options) {
      options = options || {};
      options.title = options.title || "Please wait";
      options.subtitle = options.subtitle || "";
      options.start = options.start || 0;
      this.$el.html(window.tmpl["progressDialog"](options));
      if (options.showCancel && $.os.ios) $(".cancel-btn").show();
      this.$el.show();
    },
    updateProgress: function(progressPercent) {
      if ($.os.ios) progressPercent = progressPercent * 2; // WHY?! GAH!!
      if (progressPercent > 100) {
        progressPercent = 100;
      }
      this.$(".meter .progress").animate({"width":progressPercent+"%"});
    },
    showDialogView: function(view) {
      $(window).on(this.orientationEvent, function() {
        // alert("The rotation is " + window.orientation + " and the resolution is " + screen.width + " x " + screen.height);
        if (window.orientation === -90 || window.orientation === 90) {
          view.$el.css({"margin-top":"0", "max-height":"300px"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
        else {
          view.$el.css({"margin-top":"10%", "max-height":"94%"});
          window.setTimeout(function(){
            view.scroller.refresh();
          },10);
        }
      }, false);
      this.$el.html(view.render().el);
      if (window.orientation === -90 || window.orientation === 90) {
        view.$el.css({"margin-top":"0", "max-height":"300px"});
      }
      window.setTimeout(function(){
        view.scroller.refresh();
      },10);
      if ($.os.ios) {
        // the stupid -50% is to keep it centered on iPad
        var _this = this;
        view.$el.css({"-webkit-transform":"translate3d(-50%,100%,0)"});
        this.$el.show();
        window.setTimeout(function(){
          view.$el.animate(
            {"-webkit-transform":"translate3d(-50%,0,0)"}, 150, 'ease-in-out');
        },50);
      } else {
        this.$el.show();
      }
    },
    close: function(){
      this.remove();
      this.unbind();
      // handle other unbinding needs, here
      _.each(this.subViews, function(subViews){
        if (subViews.close){
          subViews.close();
        }
      });
    }
  });
  spiderOakApp.dialogView = new spiderOakApp.DialogView().render();

  spiderOakApp.ContextPopup = spiderOakApp.ViewBase.extend({
    className: "context-popup",
    events: {
      "tap a": "a_tapHandler"
    },
    initialize: function() {
      window.bindMine(this);
    },
    render: function() {
      this.$el.html(
        window.tmpl["contextPopup"]({
          items: this.options.items
        })
      );
      this.scroller = new window.iScroll(this.el, {
        bounce: !$.os.android,
        vScrollbar: false,
        hScrollbar: false
      });
      return this;
    },
    a_tapHandler: function(event) {
      this.trigger("item:tapped", event);
    },
    remove: function() {
      this.close();
      this.$el.remove();
      this.stopListening();
      return this;
    },
    close: function() {
      this.scroller.destroy();
    }
  });

})(window.spiderOakApp = window.spiderOakApp || {}, window);
<|endoftext|>


<commit_before>var showcase_width;

$(document).ready(function() {
	var animation_time = 2000;
	showcase_width = $('#showcase').css('width');   //set the initial showcase width

	$('#slide-reel').css({
		'width': String($('.slide-wrapper').length) + '00%',  //set the slide reel width to n*100% for n slides
		//set some initial padding in case the user wants to click left first
		'left': '-' + showcase_width,
		'padding-left': showcase_width,
	});
	$('.slide-wrapper').css('width', showcase_width);   //make the slide-wrappers the same width as the showcase

	$(document).on('click', '.slide-button.right', function() {   //handle a click to move forward one slide
		$('#slide-reel').animate({left: '-=' + showcase_width, }, animation_time, function() {   //move the slide-reel to the left
			$('#slide-reel').css('padding-left', '+=' + showcase_width);   //pad the left of the slide-reel
			$('#slide-reel').append($('.slide-wrapper:first'));   //move the first slide to the end of the reel
		});
	});

	$(document).on('click', '.slide-button.left', function() {   //handle a click to move backward one slide
		$('#slide-reel').css('padding-left', '-=' + showcase_width);   //make some room on the left side of the slide-reel for an additional slide
		$('#slide-reel').prepend($('.slide-wrapper:last'));   //move the last slide to the beginning of the reel
		$('#slide-reel').animate({'padding-left': '+=' + showcase_width, }, animation_time);   //move the slide-reel to the right
	});
});

//resize the slideshow
$(window).resize(function() {
	showcase_width = $('#showcase').css('width');
	$('.slide-wrapper').css('width', showcase_width);   //update the slide-wrappers on resize
});<commit_msg>added a setInterval timer to slideshow.js<commit_after>var showcase_width;
var animation_time = 2000;

var next_slide = function() {
	$('#slide-reel').animate({left: '-=' + showcase_width, }, animation_time, function() {   //move the slide-reel to the left
		$('#slide-reel').css('padding-left', '+=' + showcase_width);   //pad the left of the slide-reel
		$('#slide-reel').append($('.slide-wrapper:first'));   //move the first slide to the end of the reel
	});
};

var previous_slide = function() {
	$('#slide-reel').css('padding-left', '-=' + showcase_width);   //make some room on the left side of the slide-reel for an additional slide
	$('#slide-reel').prepend($('.slide-wrapper:last'));   //move the last slide to the beginning of the reel
	$('#slide-reel').animate({'padding-left': '+=' + showcase_width, }, animation_time);   //move the slide-reel to the right
};

$(document).ready(function() {

	showcase_width = $('#showcase').css('width');   //set the initial showcase width

	$('#slide-reel').css({
		'width': String($('.slide-wrapper').length) + '00%',  //set the slide reel width to n*100% for n slides
		//set some initial padding in case the user wants to click left first
		'left': '-' + showcase_width,
		'padding-left': showcase_width,
	});
	$('.slide-wrapper').css('width', showcase_width);   //make the slide-wrappers the same width as the showcase

	$(document).on('click', '.slide-button.right', next_slide);

	$(document).on('click', '.slide-button.left', previous_slide);

	setInterval(next_slide, 10000);
});

//resize the slideshow
$(window).resize(function() {
	showcase_width = $('#showcase').css('width');
	$('.slide-wrapper').css('width', showcase_width);   //update the slide-wrappers on resize
});<|endoftext|>


<commit_before>;(function($$){ 'use strict';

  var defaults = {
    fit: true, // whether to fit the viewport to the graph
    ready: undefined, // callback on layoutready
    stop: undefined, // callback on layoutstop
    directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)
    padding: 30, // padding on fit
    circle: false, // put depths in concentric circles if true, put depths top down if false
    roots: undefined, // the roots of the trees
    maximalAdjustments: 0 // how many times to try to position the nodes in a maximal way (i.e. no backtracking)
  };

  function BreadthFirstLayout( options ){
    this.options = $$.util.extend({}, defaults, options);
  }

  BreadthFirstLayout.prototype.run = function(){
    var params = this.options;
    var options = params;

    var cy = params.cy;
    var nodes = cy.nodes();
    var edges = cy.edges();
    var graph = nodes.add(edges);
    var container = cy.container();

    var width = container.clientWidth;
    var height = container.clientHeight;

    var roots;
    if( $$.is.elementOrCollection(options.roots) ){
      roots = options.roots;
    } else if( $$.is.array(options.roots) ){
      var rootsArray = [];

      for( var i = 0; i < options.roots.length; i++ ){
        var id = options.roots[i];
        var ele = cy.getElementById( id );
        rootsArray.push( ele );
      }

      roots = new $$.Collection( cy, rootsArray );
    } else if( $$.is.string(options.roots) ){
      roots = cy.$( options.roots );

    } else {
      if( options.directed ){
        roots = nodes.roots();
      } else {
        var maxDegree = nodes.maxDegree( false );
        roots = nodes.filter('[[degree = ' + maxDegree + ']]');
      }
    }

    var depths = [];
    var foundByBfs = {};
    var id2depth = {};

    // find the depths of the nodes
    graph.bfs(roots, function(i, depth){
      var ele = this[0];

      if( !depths[depth] ){
        depths[depth] = [];
      }

      depths[depth].push( ele );
      foundByBfs[ ele.id() ] = true;
      id2depth[ ele.id() ] = depth;
    }, options.directed);

    // check for nodes not found by bfs
    var orphanNodes = [];
    for( var i = 0; i < nodes.length; i++ ){
      var ele = nodes[i];

      if( foundByBfs[ ele.id() ] ){
        continue;
      } else {
        orphanNodes.push( ele );
      }
    }

    // assign orphan nodes a depth from their neighborhood
    var maxChecks = orphanNodes.length * 3;
    var checks = 0;
    while( orphanNodes.length !== 0 && checks < maxChecks ){
      var node = orphanNodes.shift();
      var neighbors = node.neighborhood().nodes();
      var assignedDepth = false;

      for( var i = 0; i < neighbors.length; i++ ){
        var depth = id2depth[ neighbors[i].id() ];

        if( depth !== undefined ){
          depths[depth].push( node );
          assignedDepth = true;
          break;
        }
      }

      if( !assignedDepth ){
        orphanNodes.push( node );
      }

      checks++;
    }

    // assign orphan nodes that are still left to the depth of their subgraph
    while( orphanNodes.length !== 0 ){
      var node = orphanNodes.shift();
      //var subgraph = graph.bfs( node ).path;
      var assignedDepth = false;

      // for( var i = 0; i < subgraph.length; i++ ){
      //   var depth = id2depth[ subgraph[i].id() ];

      //   if( depth !== undefined ){
      //     depths[depth].push( node );
      //     assignedDepth = true;
      //     break;
      //   }
      // }

      if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0
        if( depths.length === 0 ){
          depths.push([]);
        }

        depths[0].push( node );
      }
    }

    // assign the nodes a depth and index
    var assignDepthsToEles = function(){
      for( var i = 0; i < depths.length; i++ ){
        var eles = depths[i];

        for( var j = 0; j < eles.length; j++ ){
          var ele = eles[j];

          ele._private.scratch.BreadthFirstLayout = {
            depth: i,
            index: j
          };
        }
      }
    };
    assignDepthsToEles();

    var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth
      var edges = node.connectedEdges('[target = "' + node.id() + '"]');
      var thisInfo = node._private.scratch.BreadthFirstLayout;
      var highestDepthOfOther = 0;
      var highestOther;
      for( var i = 0; i < edges.length; i++ ){
        var edge = edges[i];
        var otherNode = edge.source()[0];
        var otherInfo = otherNode._private.scratch.BreadthFirstLayout;

        if( thisInfo.depth < otherInfo.depth && highestDepthOfOther < otherInfo.depth ){
          highestDepthOfOther = otherInfo.depth;
          highestOther = otherNode;
        }
      }

      return highestOther;
    };

     // make maximal if so set by adjusting depths
    for( var adj = 0; adj < options.maximalAdjustments; adj++ ){

      var nDepths = depths.length;
      var elesToMove = [];
      for( var i = 0; i < nDepths; i++ ){
        var depth = depths[i];

        var nDepth = depth.length;
        for( var j = 0; j < nDepth; j++ ){
          var ele = depth[j];
          var info = ele._private.scratch.BreadthFirstLayout;
          var intEle = intersectsDepth(ele);

          if( intEle ){
            info.intEle = intEle;
            elesToMove.push( ele );
          }
        }
      }

      for( var i = 0; i < elesToMove.length; i++ ){
        var ele = elesToMove[i];
        var info = ele._private.scratch.BreadthFirstLayout;
        var intEle = info.intEle;
        var intInfo = intEle._private.scratch.BreadthFirstLayout;

        depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index

        // add to end of new depth
        var newDepth = intInfo.depth + 1;
        while( newDepth > depths.length - 1 ){
          depths.push([]);
        }
        depths[ newDepth ].push( ele );

        info.depth = newDepth;
        info.index = depths[newDepth].length - 1;
      }

      assignDepthsToEles();
    }

    // find min distance we need to leave between nodes
    var minDistance = 0;
    for( var i = 0; i < nodes.length; i++ ){
      var w = nodes[i].outerWidth();
      var h = nodes[i].outerHeight();

      minDistance = Math.max(minDistance, w, h);
    }
    minDistance *= 1.75; // just to have some nice spacing

    // get the weighted percent for an element based on its connectivity to other levels
    var cachedWeightedPercent = {};
    var getWeightedPercent = function( ele ){
      if( cachedWeightedPercent[ ele.id() ] ){
        return cachedWeightedPercent[ ele.id() ];
      }

      var eleDepth = ele._private.scratch.BreadthFirstLayout.depth;
      var neighbors = ele.neighborhood().nodes();
      var percent = 0;
      var samples = 0;

      for( var i = 0; i < neighbors.length; i++ ){
        var neighbor = neighbors[i];
        var nEdges = neighbor.edgesWith( ele );
        var index = neighbor._private.scratch.BreadthFirstLayout.index;
        var depth = neighbor._private.scratch.BreadthFirstLayout.depth;
        var nDepth = depths[depth].length;

        if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above
          percent += index / nDepth;
          samples++;
        }
      }

      samples = Math.max(1, samples);
      percent = percent / samples;

      if( samples === 0 ){ // so lone nodes have a "don't care" state in sorting
        percent = undefined;
      }

      cachedWeightedPercent[ ele.id() ] = percent;
      return percent;
    };

    // rearrange the indices in each depth level based on connectivity
    for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result

      for( var i = 0; i < depths.length; i++ ){
        var depth = i;
        var newDepths = [];

        depths[i] = depths[i].sort(function(a, b){
          var apct = getWeightedPercent( a );
          var bpct = getWeightedPercent( b );

          return apct - bpct;
        });
      }
      assignDepthsToEles(); // and update

    }

    var center = {
      x: width/2,
      y: height/2
    };
    nodes.positions(function(){
      var ele = this[0];
      var info = ele._private.scratch.BreadthFirstLayout;
      var depth = info.depth;
      var index = info.index;
      var depthSize = depths[depth].length;

      var distanceX = Math.max( width / (depthSize + 1), minDistance );
      var distanceY = Math.max( height / (depths.length + 1), minDistance );
      var radiusStepSize = Math.min( width / 2 / depths.length, height / 2 / depths.length );
      radiusStepSize = Math.max( radiusStepSize, minDistance );

      if( options.circle ){
        var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize/2 : 0);
        var theta = 2 * Math.PI / depths[depth].length * index;

        if( depth === 0 && depths[0].length === 1 ){
          radius = 1;
        }

        return {
          x: center.x + radius * Math.cos(theta),
          y: center.y + radius * Math.sin(theta)
        };

      } else {
        return {
          x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,
          y: (depth + 1) * distanceY
        };
      }

    });

    if( params.fit ){
      cy.fit( options.padding );
    }

    cy.one('layoutready', params.ready);
    cy.trigger('layoutready');

    cy.one('layoutstop', params.stop);
    cy.trigger('layoutstop');
  };

  BreadthFirstLayout.prototype.stop = function(){
    // not a continuous layout
  };

  $$('layout', 'breadthfirst', BreadthFirstLayout);

})( cytoscape );
<commit_msg>put child ele one level down the parent<commit_after>;(function($$){ 'use strict';

  var defaults = {
    fit: true, // whether to fit the viewport to the graph
    ready: undefined, // callback on layoutready
    stop: undefined, // callback on layoutstop
    directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)
    padding: 30, // padding on fit
    circle: false, // put depths in concentric circles if true, put depths top down if false
    roots: undefined, // the roots of the trees
    maximalAdjustments: 0 // how many times to try to position the nodes in a maximal way (i.e. no backtracking)
  };

  function BreadthFirstLayout( options ){
    this.options = $$.util.extend({}, defaults, options);
  }

  BreadthFirstLayout.prototype.run = function(){
    var params = this.options;
    var options = params;

    var cy = params.cy;
    var nodes = cy.nodes();
    var edges = cy.edges();
    var graph = nodes.add(edges);
    var container = cy.container();

    var width = container.clientWidth;
    var height = container.clientHeight;

    var roots;
    if( $$.is.elementOrCollection(options.roots) ){
      roots = options.roots;
    } else if( $$.is.array(options.roots) ){
      var rootsArray = [];

      for( var i = 0; i < options.roots.length; i++ ){
        var id = options.roots[i];
        var ele = cy.getElementById( id );
        rootsArray.push( ele );
      }

      roots = new $$.Collection( cy, rootsArray );
    } else if( $$.is.string(options.roots) ){
      roots = cy.$( options.roots );

    } else {
      if( options.directed ){
        roots = nodes.roots();
      } else {
        var maxDegree = nodes.maxDegree( false );
        roots = nodes.filter('[[degree = ' + maxDegree + ']]');
      }
    }

    var depths = [];
    var foundByBfs = {};
    var id2depth = {};

    // find the depths of the nodes
    graph.bfs(roots, function(i, depth){
      var ele = this[0];

      if( !depths[depth] ){
        depths[depth] = [];
      }

      depths[depth].push( ele );
      foundByBfs[ ele.id() ] = true;
      id2depth[ ele.id() ] = depth;
    }, options.directed);

    // check for nodes not found by bfs
    var orphanNodes = [];
    for( var i = 0; i < nodes.length; i++ ){
      var ele = nodes[i];

      if( foundByBfs[ ele.id() ] ){
        continue;
      } else {
        orphanNodes.push( ele );
      }
    }

    // assign orphan nodes a depth from their neighborhood
    var maxChecks = orphanNodes.length * 3;
    var checks = 0;
    while( orphanNodes.length !== 0 && checks < maxChecks ){
      var node = orphanNodes.shift();
      var neighbors = node.neighborhood().nodes();
      var assignedDepth = false;

      for( var i = 0; i < neighbors.length; i++ ){
        var depth = id2depth[ neighbors[i].id() ];

        if( depth !== undefined ){
          depths[depth].push( node );
          assignedDepth = true;
          break;
        }
      }

      if( !assignedDepth ){
        orphanNodes.push( node );
      }

      checks++;
    }

    // assign orphan nodes that are still left to the depth of their subgraph
    while( orphanNodes.length !== 0 ){
      var node = orphanNodes.shift();
      //var subgraph = graph.bfs( node ).path;
      var assignedDepth = false;

      // for( var i = 0; i < subgraph.length; i++ ){
      //   var depth = id2depth[ subgraph[i].id() ];

      //   if( depth !== undefined ){
      //     depths[depth].push( node );
      //     assignedDepth = true;
      //     break;
      //   }
      // }

      if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0
        if( depths.length === 0 ){
          depths.push([]);
        }

        depths[0].push( node );
      }
    }

    // assign the nodes a depth and index
    var assignDepthsToEles = function(){
      for( var i = 0; i < depths.length; i++ ){
        var eles = depths[i];

        for( var j = 0; j < eles.length; j++ ){
          var ele = eles[j];

          ele._private.scratch.BreadthFirstLayout = {
            depth: i,
            index: j
          };
        }
      }
    };
    assignDepthsToEles();

    var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth
      var edges = node.connectedEdges('[target = "' + node.id() + '"]');
      var thisInfo = node._private.scratch.BreadthFirstLayout;
      var highestDepthOfOther = 0;
      var highestOther;
      for( var i = 0; i < edges.length; i++ ){
        var edge = edges[i];
        var otherNode = edge.source()[0];
        var otherInfo = otherNode._private.scratch.BreadthFirstLayout;

        if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){
          highestDepthOfOther = otherInfo.depth;
          highestOther = otherNode;
        }
      }

      return highestOther;
    };

     // make maximal if so set by adjusting depths
    for( var adj = 0; adj < options.maximalAdjustments; adj++ ){

      var nDepths = depths.length;
      var elesToMove = [];
      for( var i = 0; i < nDepths; i++ ){
        var depth = depths[i];

        var nDepth = depth.length;
        for( var j = 0; j < nDepth; j++ ){
          var ele = depth[j];
          var info = ele._private.scratch.BreadthFirstLayout;
          var intEle = intersectsDepth(ele);

          if( intEle ){
            info.intEle = intEle;
            elesToMove.push( ele );
          }
        }
      }

      for( var i = 0; i < elesToMove.length; i++ ){
        var ele = elesToMove[i];
        var info = ele._private.scratch.BreadthFirstLayout;
        var intEle = info.intEle;
        var intInfo = intEle._private.scratch.BreadthFirstLayout;

        depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index

        // add to end of new depth
        var newDepth = intInfo.depth + 1;
        while( newDepth > depths.length - 1 ){
          depths.push([]);
        }
        depths[ newDepth ].push( ele );

        info.depth = newDepth;
        info.index = depths[newDepth].length - 1;
      }

      assignDepthsToEles();
    }

    // find min distance we need to leave between nodes
    var minDistance = 0;
    for( var i = 0; i < nodes.length; i++ ){
      var w = nodes[i].outerWidth();
      var h = nodes[i].outerHeight();

      minDistance = Math.max(minDistance, w, h);
    }
    minDistance *= 1.75; // just to have some nice spacing

    // get the weighted percent for an element based on its connectivity to other levels
    var cachedWeightedPercent = {};
    var getWeightedPercent = function( ele ){
      if( cachedWeightedPercent[ ele.id() ] ){
        return cachedWeightedPercent[ ele.id() ];
      }

      var eleDepth = ele._private.scratch.BreadthFirstLayout.depth;
      var neighbors = ele.neighborhood().nodes();
      var percent = 0;
      var samples = 0;

      for( var i = 0; i < neighbors.length; i++ ){
        var neighbor = neighbors[i];
        var nEdges = neighbor.edgesWith( ele );
        var index = neighbor._private.scratch.BreadthFirstLayout.index;
        var depth = neighbor._private.scratch.BreadthFirstLayout.depth;
        var nDepth = depths[depth].length;

        if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above
          percent += index / nDepth;
          samples++;
        }
      }

      samples = Math.max(1, samples);
      percent = percent / samples;

      if( samples === 0 ){ // so lone nodes have a "don't care" state in sorting
        percent = undefined;
      }

      cachedWeightedPercent[ ele.id() ] = percent;
      return percent;
    };

    // rearrange the indices in each depth level based on connectivity
    for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result

      for( var i = 0; i < depths.length; i++ ){
        var depth = i;
        var newDepths = [];

        depths[i] = depths[i].sort(function(a, b){
          var apct = getWeightedPercent( a );
          var bpct = getWeightedPercent( b );

          return apct - bpct;
        });
      }
      assignDepthsToEles(); // and update

    }

    var center = {
      x: width/2,
      y: height/2
    };
    nodes.positions(function(){
      var ele = this[0];
      var info = ele._private.scratch.BreadthFirstLayout;
      var depth = info.depth;
      var index = info.index;
      var depthSize = depths[depth].length;

      var distanceX = Math.max( width / (depthSize + 1), minDistance );
      var distanceY = Math.max( height / (depths.length + 1), minDistance );
      var radiusStepSize = Math.min( width / 2 / depths.length, height / 2 / depths.length );
      radiusStepSize = Math.max( radiusStepSize, minDistance );

      if( options.circle ){
        var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize/2 : 0);
        var theta = 2 * Math.PI / depths[depth].length * index;

        if( depth === 0 && depths[0].length === 1 ){
          radius = 1;
        }

        return {
          x: center.x + radius * Math.cos(theta),
          y: center.y + radius * Math.sin(theta)
        };

      } else {
        return {
          x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,
          y: (depth + 1) * distanceY
        };
      }

    });

    if( params.fit ){
      cy.fit( options.padding );
    }

    cy.one('layoutready', params.ready);
    cy.trigger('layoutready');

    cy.one('layoutstop', params.stop);
    cy.trigger('layoutstop');
  };

  BreadthFirstLayout.prototype.stop = function(){
    // not a continuous layout
  };

  $$('layout', 'breadthfirst', BreadthFirstLayout);

})( cytoscape );
<|endoftext|>


<commit_before> /* global module, require, L */
'use strict';

/** This module, caching-geocoder, geo-codes location names: it maps
  * from names to coordinates, returning Promises.
  *
  * caching-geocoder also maintains a cache of said Promises. Further
  * there is a mechanism for pre-fetching individual mappings, so
  * that the cache can be pre-populated without network traffic, say,
  * during app initiation i.e. provide a primed cache.
  *
  * Note, using Google's terminology:
  * 1. "geocoding" is mapping from names to coordinates
  * 2. "reserve geocoding" is mapping location to name
  * See: https://developers.google.com/maps/documentation/geocoding/
  *
  * OSM uses the same terminology:
  * ttp://wiki.openstreetmap.org/wiki/Nominatim
  *
  * At this time, caching-geocoder does not do reverse geocoding.
  */

module.exports = {
  locate:        locate,
  setPrefetched: setPrefetched,
  resetCache:    resetCache,
  exportCache:   exportCache,
  getCacheSize:  getCacheSize
  };

// naming: if superAgent is the plain SuperAgent module, then supestAgent is that wrapped in Bluebird Promises.
var supestAgent = require('superagent-bluebird-promise');

// JFT-TODO: kill off, once SuperAgent is wired in.
var http = require('http');
// Supposedly this is not needed
//var superAgent = require('superagent');

var urlQueryTermer = require('querystring');
var Promise = require('bluebird');

var logger = require('../utils/logger.js')('jft');
logger.level('debug');

var cachedPromises = {};
var cacheMembersCount = 0;

function getCacheSize(){
  return cacheMembersCount;
  // JFT-TODO: style-wise, this seems overly complex. Why not just let them access the prop directly?
  }

function exportCache(){
  return cachedPromises.toJSON();
  // JFT-TODO: a one statement function. Really?
  // Again, could just users of this module just access cachedPromises and let them decide to toJSON() it if desired.
  // What is the gain of encapsulation here?
  }

function setPrefetched(aLocName, aLat, aLong){
  if(cachedPromises[aLocName]){
    logger.info('setPrefetched(): cache already has:' + aLocName);
    }
    else{
      var aCannedPromise = Promise.resolve([{lat: aLat, lon: aLong}]);
      addToCache(aLocName, aCannedPromise);
      }
  }

function resetCache(){
  cacheMembersCount = 0;
  cachedPromises = {};
  }

function addToCache(aName, aPromise){
  cachedPromises[aName] = aPromise;
  cacheMembersCount++;
  }

function locate(aName){
  logger.debug('getLocationPromise(' + aName + ') and cache for it is:' + cachedPromises[aName]);

  if(cachedPromises[aName]){
    logger.debug('cache already has:' + aName);
    }
    else{
      logger.debug('cache does not have:' + aName);
      //addToCache(aName, DEAD_makePromiseForLoc(aName));
      addToCache(aName, promiseLocCoords(aName));
      }
  logger.debug('getLocationPromise returning:' + cachedPromises[aName]);

  return cachedPromises[aName];
  }

/*
JFT-TODO:
need to test in browser now.
!!!!!So that's the next level-up in my testing.
  also need to have elegant way of detecting both cases.
Not sure if I have to adopt Browserify fully.
  Browserify does makes nodes http.request work in the browser.
  can just that be pulled out of browserify? Indeed:
  https://github.com/substack/http-browserify
  Nice compatibility: https://github.com/substack/http-browserify#compatibility

This also gets to CORS
  http://visionmedia.github.io/superagent/#cors
  browserify does it this way
    http://stackoverflow.com/questions/23896619/make-http-request-in-node-js-work-for-browser
      withCredentials: false // this is the important part
  If CORS is not setup, Nominatim can do jsonp and I thought I saw source code of Nominatim v3(?) doing CORS:
    http://wiki.openstreetmap.org/wiki/Nominatim
    json_callback=<string>
*/

function promiseLocCoords(aName){
  var host = 'nominatim.openstreetmap.org';
  var path = '/search/?q=' + urlQueryTermer.escape(aName) + '&limit=5&format=json&addressdetails=1';
  var builtUpUrl = "http://" + host + path;

  logger.debug('requesting ' + builtUpUrl);

  return supestAgent.get(builtUpUrl).then(function(aResp){
    return aResp.body;
    });
  // JFT-TODO: superagent-bluebird-promise replaces SuperAgent's end() with a then()
  // Could add a null then() here to start if off but probably not needed.

/*

        .then(function(aResp){
//THIS CHUNK HERE is the DCer
//Just calling then does it w or w/o any statements
          //must(aResp.status).equal(200);
          // The following form give lame error message like: AssertionError: false must be true
          // must(/John Tigue/.test(aResp.text)).true();
	  // So instead the following (at cost of no regexp but better message):
//          must(aResp.text).include('foo bar');
          console.log(aResp);

          })
        .catch(function(aReason){
          console.log(aReason);
          });
    .then(function(aResp){
      return aResp.body;
      })
    .catch(function(aProblem){
console.log(aProblem);
      throw aProblem;
      });
var foo = {}
foo.then = function(){};
return foo;
//  return new Promise(function fuckIt(resolve){resolve([{lat:48,lon:-122}]);});
//      must(seattleResult.long).between(-122.8, -121.8);
//      must(seattleResult.lat).between(47.1, 48.1);
 */

  }

// This is the pre-SuperAgent implementation. http.request() is a node thing.
// Browserify could get a syntactically identical implementation in the browers.
// Yet Promise.promisify can be more efficient and SuperAgent has a more elegant
// API than http.request.
function DEAD_makePromiseForLoc(aName){
  var aPromise = new Promise(function(resolve, reject){
    var host = 'nominatim.openstreetmap.org';
    var path = '/search/?q=' + urlQueryTermer.escape(aName) + '&limit=5&format=json&addressdetails=1';
    var builtUpUrl = "http://" + host + path;

    logger.debug('requesting ' + builtUpUrl);

    var nominatimRequestOpts = {
      hostname: host,
      port: 80,
      method: 'GET',
      path: path
      };

    // JFT-TODO: This is the sort of thing that a debugger should be used for....
    //logger.warn("requestURL:"+host+path);
    var aReq = http.request(nominatimRequestOpts, function(response){
      logger.debug('http.request called back');
      var respBody = '';
      response.on('data', function(aChunk){
        respBody += aChunk;
        });
      response.on('end', function(){
        logger.debug('response ended');
        try{
          resolve(JSON.parse(respBody));
          }
          catch(e){
            reject(e);
            }
        });
      })
      .on('error', function(anErr){
        logger.error(anErr);
        throw anErr;
        });
    aReq.end();
    });
  return aPromise;
  }

// JFT-TODO: is this dead code now?
// It could be used but looks like I just stopped at resolve(JSON.parse(respBod)).
// Currently caching-geocoder.spec.js dots into the data raw.
// The unbound var L is ugly and makes it Leaflet specific (with it's global object in a server...)
// Really, why have it? Can I just duck type it?
//   what does L.latLngBounds() and L.latLng() return?

/* Ripped straight out of Control.Geocoder.js geocode(), re-formatted a bit.
 * This just rearranges the data a bit, parses strings to numbers, and Leaflets it up (the unbound var L)
 */
function parseNominatimResponse(aResponseBody){
  var results = [];
  var data = JSON.parse(aResponseBody);
  for(var i = data.length - 1; i >= 0; i--){
    var bbox = data[i].boundingbox;
    for(var j = 0; j < 4; j++) bbox[j] = parseFloat(bbox[j]);
    results[i] = {
      icon: data[i].icon,
      name: data[i].display_name,
      html: null,
      bbox: L.latLngBounds([bbox[0], bbox[2]], [bbox[1], bbox[3]]),
      center: L.latLng(data[i].lat, data[i].lon),
      properties: data[i]
      };
    }
  return results;
  }
<commit_msg>was renamed to CahcingGeocoder.j<commit_after><|endoftext|>


<commit_before>/* Poll commands
 * by Legit
 */

 //This is the line that controls what tiers are in tierpoll !_!
 var tiers = 'other, ru, tier shift, [Gen 5] OU, [Gen 5] Smogon Doubles, random doubles, random triples, custom, reg1v1, lc, nu, cap, cc, oumono, doubles, balanced hackmons, hackmons, ubers, random battle, ou, cc1v1, uu, anything goes, super staff bros, inverse', random ubers, random haxmons, random lc, random monotype, random sky battle, challenge cup 2vs2 metronome, challenge cup metronome';

 function splint(target) {
 	var cmdArr = target.split(",");
 	for (var i = 0; i < cmdArr.length; i++) cmdArr[i] = cmdArr[i].trim();
 		return cmdArr;
 }

 exports.commands = {
	poll: function (target, room, user) {
		if (!user.can('broadcast',null,room)) return this.sendReply('You do not have enough authority to use this command.');
		if (!this.canTalk()) return this.sendReply('You currently can not speak in this room.');
		if (room.question) return this.sendReply('There is currently a poll going on already.');
		if (!target) return false;
		if (target.length > 500) return this.sendReply('Polls can not be this long.');
		var separacion = "  ";
		var answers = splint(target);
		var formats = [];
		for (var u in Tools.data.Formats) {
			if (Tools.data.Formats[u].name && Tools.data.Formats[u].challengeShow && Tools.data.Formats[u].mod != 'gen4' && Tools.data.Formats[u].mod != 'gen3' && Tools.data.Formats[u].mod != 'gen3' && Tools.data.Formats[u].mod != 'gen2' && Tools.data.Formats[u].mod != 'gen1') formats.push(Tools.data.Formats[u].name);
		}
		formats = 'Tournament,'+formats.join(',');
		if (answers[0] == 'tournament' || answers[0] == 'tour') answers = splint(formats);
		if (answers.length < 3) return this.sendReply('Correct syntax for this command is /poll question, option, option...');
		var question = answers[0];
		question = Tools.escapeHTML(question);
		answers.splice(0, 1);
		var answers = answers.join(',').toLowerCase().split(',');
		room.question = question;
		room.answerList = answers;
		room.usergroup = Config.groupsranking.indexOf(user.group);
		var output = '';
		for (var u in room.answerList) {
			if (!room.answerList[u] || room.answerList[u].length < 1) continue;
			output += '<button name="send" value="/vote '+room.answerList[u]+'">'+Tools.escapeHTML(room.answerList[u])+'</button> ';
		}
		room.addRaw('

' + room.question + separacion + '/vote OPTION
Poll started by '+user.name+'

' + separacion + separacion + output + '
');
	},

	ep: 'endpoll',
	endpoll: function (target, room, user) {
		if (!user.can('broadcast',null,room)) return this.sendReply('You do not have enough authority to use this command.');
		if (!this.canTalk()) return this.sendReply('You currently can not speak in this room.');
		if (!room.question) return this.sendReply('There is no poll to end in this room.');
		if (!room.answers) room.answers = new Object();
		var votes = Object.keys(room.answers).length;
		if (votes == 0) {
			room.question = undefined;
			room.answerList = new Array();
			room.answers = new Object();
			return room.addRaw("
The poll was canceled because of lack of voters.
");
		}
		var options = new Object();
		var obj = Rooms.get(room);
		for (var i in obj.answerList) options[obj.answerList[i]] = 0;
		for (var i in obj.answers) options[obj.answers[i]]++;
		var sortable = new Array();
		for (var i in options) sortable.push([i, options[i]]);
		sortable.sort(function(a, b) {return a[1] - b[1]});
		var html = "";
		for (var i = sortable.length - 1; i > -1; i--) {
			var option = sortable[i][0];
			var value = sortable[i][1];
			if (value > 0) html += "• " + Tools.escapeHTML(option) + " - " + Math.floor(value / votes * 100) + "% (" + value + ")
";
		}
		room.addRaw('

Results to "' + obj.question + '"
Poll ended by '+user.name+'

' + html + '
'); room.question = undefined;
		room.answerList = new Array();
		room.answers = new Object();
	},

	votes: function (target, room, user) {
		if (!room.answers) room.answers = new Object();
		if (!room.question) return this.sendReply('There is no poll currently going on in this room.');
		if (!this.canBroadcast()) return;
		this.sendReply('NUMBER OF VOTES: ' + Object.keys(room.answers).length);
	},

	vote: function (target, room, user) {
		var ips = JSON.stringify(user.ips);
		if (!room.question) return this.sendReply('There is no poll currently going on in this room.');
		if (!target) return this.parse('/help vote');
		if (room.answerList.indexOf(target.toLowerCase()) == -1) return this.sendReply('\'' + target + '\' is not an option for the current poll.');
		if (!room.answers) room.answers = new Object();
		room.answers[ips] = target.toLowerCase();
		return this.sendReply('You are now voting for ' + target + '.');
	},

	tpoll: 'tierpoll',
	tierpoll: function (room, user, cmd) {
		return this.parse('/poll Next Tournament Tier:, ' + tiers);
	}
};
<commit_msg>Update poll.js<commit_after>/* Poll commands
 * by Legit
 */

 //This is the line that controls what tiers are in tierpoll !_!
 var tiers = 'other, ru, tier shift, [Gen 5] OU, [Gen 5] Smogon Doubles, random doubles, random triples, custom, reg1v1, lc, nu, cap, cc, oumono, doubles, balanced hackmons, hackmons, ubers, random battle, ou, cc1v1, uu, anything goes, super staff bros,  inverse, random ubers, random haxmons, random lc, random monotype, random sky battle, challenge cup 2vs2 metronome, challenge cup metronome';

 function splint(target) {
 	var cmdArr = target.split(",");
 	for (var i = 0; i < cmdArr.length; i++) cmdArr[i] = cmdArr[i].trim();
 		return cmdArr;
 }

 exports.commands = {
	poll: function (target, room, user) {
		if (!user.can('broadcast',null,room)) return this.sendReply('You do not have enough authority to use this command.');
		if (!this.canTalk()) return this.sendReply('You currently can not speak in this room.');
		if (room.question) return this.sendReply('There is currently a poll going on already.');
		if (!target) return false;
		if (target.length > 500) return this.sendReply('Polls can not be this long.');
		var separacion = "  ";
		var answers = splint(target);
		var formats = [];
		for (var u in Tools.data.Formats) {
			if (Tools.data.Formats[u].name && Tools.data.Formats[u].challengeShow && Tools.data.Formats[u].mod != 'gen4' && Tools.data.Formats[u].mod != 'gen3' && Tools.data.Formats[u].mod != 'gen3' && Tools.data.Formats[u].mod != 'gen2' && Tools.data.Formats[u].mod != 'gen1') formats.push(Tools.data.Formats[u].name);
		}
		formats = 'Tournament,'+formats.join(',');
		if (answers[0] == 'tournament' || answers[0] == 'tour') answers = splint(formats);
		if (answers.length < 3) return this.sendReply('Correct syntax for this command is /poll question, option, option...');
		var question = answers[0];
		question = Tools.escapeHTML(question);
		answers.splice(0, 1);
		var answers = answers.join(',').toLowerCase().split(',');
		room.question = question;
		room.answerList = answers;
		room.usergroup = Config.groupsranking.indexOf(user.group);
		var output = '';
		for (var u in room.answerList) {
			if (!room.answerList[u] || room.answerList[u].length < 1) continue;
			output += '<button name="send" value="/vote '+room.answerList[u]+'">'+Tools.escapeHTML(room.answerList[u])+'</button> ';
		}
		room.addRaw('

' + room.question + separacion + '/vote OPTION
Poll started by '+user.name+'

' + separacion + separacion + output + '
');
	},

	ep: 'endpoll',
	endpoll: function (target, room, user) {
		if (!user.can('broadcast',null,room)) return this.sendReply('You do not have enough authority to use this command.');
		if (!this.canTalk()) return this.sendReply('You currently can not speak in this room.');
		if (!room.question) return this.sendReply('There is no poll to end in this room.');
		if (!room.answers) room.answers = new Object();
		var votes = Object.keys(room.answers).length;
		if (votes == 0) {
			room.question = undefined;
			room.answerList = new Array();
			room.answers = new Object();
			return room.addRaw("
The poll was canceled because of lack of voters.
");
		}
		var options = new Object();
		var obj = Rooms.get(room);
		for (var i in obj.answerList) options[obj.answerList[i]] = 0;
		for (var i in obj.answers) options[obj.answers[i]]++;
		var sortable = new Array();
		for (var i in options) sortable.push([i, options[i]]);
		sortable.sort(function(a, b) {return a[1] - b[1]});
		var html = "";
		for (var i = sortable.length - 1; i > -1; i--) {
			var option = sortable[i][0];
			var value = sortable[i][1];
			if (value > 0) html += "• " + Tools.escapeHTML(option) + " - " + Math.floor(value / votes * 100) + "% (" + value + ")
";
		}
		room.addRaw('

Results to "' + obj.question + '"
Poll ended by '+user.name+'

' + html + '
'); room.question = undefined;
		room.answerList = new Array();
		room.answers = new Object();
	},

	votes: function (target, room, user) {
		if (!room.answers) room.answers = new Object();
		if (!room.question) return this.sendReply('There is no poll currently going on in this room.');
		if (!this.canBroadcast()) return;
		this.sendReply('NUMBER OF VOTES: ' + Object.keys(room.answers).length);
	},

	vote: function (target, room, user) {
		var ips = JSON.stringify(user.ips);
		if (!room.question) return this.sendReply('There is no poll currently going on in this room.');
		if (!target) return this.parse('/help vote');
		if (room.answerList.indexOf(target.toLowerCase()) == -1) return this.sendReply('\'' + target + '\' is not an option for the current poll.');
		if (!room.answers) room.answers = new Object();
		room.answers[ips] = target.toLowerCase();
		return this.sendReply('You are now voting for ' + target + '.');
	},

	tpoll: 'tierpoll',
	tierpoll: function (room, user, cmd) {
		return this.parse('/poll Next Tournament Tier:, ' + tiers);
	}
};
<|endoftext|>