<commit_before>import React from 'react';
import Immutable from 'seamless-immutable';

import { actions } from './actions';

// ver como inicializar activeTabIndex
const defaultState = Immutable({
  activeTabIndex: null,
  [null]: {
    routeStack: [],
    activeRoute: null,
    method: null
  }
});

export default function reducer(state = defaultState, { type, payload }) {
  switch (type) {
    case actions.PUSH: {
      const tabState = state[state.activeTabIndex];
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: [...tabState.routeStack, tabState.activeRoute],
          activeRoute: payload.route,
          method: type
        }
      });
    }
    case actions.RESET_TO: {
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: [],
          activeRoute: payload.route,
          method: type
        }
      });
    }
    case actions.POP: {
      const tabState = state[state.activeTabIndex];
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: tabState.routeStack.slice(0, -2),
          activeRoute: tabState.routeStack.length > 0 ? tabState.routeStack.slice(-1)[0] : tabState.activeRoute,
          method: type
        }
      });
    }
    case actions.POP_TO_TOP: {
      const tabState = state[state.activeTabIndex];
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: [],
          activeRoute: tabState.routeStack.length > 0 ? tabState.routeStack[0] : tabState.activeRoute,
          method: type
        }
      });
    }
    case actions.INIT_TABS: {
      if (Number.isInteger(state.activeTabIndex)) {
        // in android. the init_tabs action is fired whenever the app restores from the background but we
        // only want to handle the first dispatch of this action.
        return state;
      }
      const tabsState = {};
      for (let tabIndex = 0; tabIndex < payload.tabsCount; tabIndex++) {
        tabsState[tabIndex] = {
          routeStack: [],
          activeRoute: null,
          method: null
        };
      }
      return state.merge({
        ...tabsState,
        activeTabIndex: payload.initialTab
      });
    }
    case actions.TAB_CHANGED: {
      return state.merge({
        activeTabIndex: payload.tabIndex
      });
    }
    default: {
      return state;
    }
  }
}

const routePropType = React.PropTypes.shape({
  name: React.PropTypes.string.isRequired,
  params: React.PropTypes.object
});

export const propTypes = {
  activeRoute: routePropType,
  routeStack: React.PropTypes.arrayOf(routePropType).isRequired,
  method: React.PropTypes.string,
  activeTabIndex(props, propName) {
    const value = props[propName];
    return Number.isInteger(value) || value === null;
  }
};
<commit_msg>Fix on POP action handler of reducer<commit_after>import React from 'react';
import Immutable from 'seamless-immutable';

import { actions } from './actions';

// ver como inicializar activeTabIndex
const defaultState = Immutable({
  activeTabIndex: null,
  [null]: {
    routeStack: [],
    activeRoute: null,
    method: null
  }
});

export default function reducer(state = defaultState, { type, payload }) {
  switch (type) {
    case actions.PUSH: {
      const tabState = state[state.activeTabIndex];
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: [...tabState.routeStack, tabState.activeRoute],
          activeRoute: payload.route,
          method: type
        }
      });
    }
    case actions.RESET_TO: {
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: [],
          activeRoute: payload.route,
          method: type
        }
      });
    }
    case actions.POP: {
      const tabState = state[state.activeTabIndex];
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: tabState.routeStack.slice(0, -1),
          activeRoute: tabState.routeStack.length > 0 ? tabState.routeStack.slice(-1)[0] : tabState.activeRoute,
          method: type
        }
      });
    }
    case actions.POP_TO_TOP: {
      const tabState = state[state.activeTabIndex];
      return state.merge({
        [state.activeTabIndex]: {
          routeStack: [],
          activeRoute: tabState.routeStack.length > 0 ? tabState.routeStack[0] : tabState.activeRoute,
          method: type
        }
      });
    }
    case actions.INIT_TABS: {
      if (Number.isInteger(state.activeTabIndex)) {
        // in android. the init_tabs action is fired whenever the app restores from the background but we
        // only want to handle the first dispatch of this action.
        return state;
      }
      const tabsState = {};
      for (let tabIndex = 0; tabIndex < payload.tabsCount; tabIndex++) {
        tabsState[tabIndex] = {
          routeStack: [],
          activeRoute: null,
          method: null
        };
      }
      return state.merge({
        ...tabsState,
        activeTabIndex: payload.initialTab
      });
    }
    case actions.TAB_CHANGED: {
      return state.merge({
        activeTabIndex: payload.tabIndex
      });
    }
    default: {
      return state;
    }
  }
}

const routePropType = React.PropTypes.shape({
  name: React.PropTypes.string.isRequired,
  params: React.PropTypes.object
});

export const propTypes = {
  activeRoute: routePropType,
  routeStack: React.PropTypes.arrayOf(routePropType).isRequired,
  method: React.PropTypes.string,
  activeTabIndex(props, propName) {
    const value = props[propName];
    return Number.isInteger(value) || value === null;
  }
};
<|endoftext|>


<commit_before>"use strict";

var app = angular.module("VinculacionApp", ['ui.router', 'ngAnimate']);

app.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
	$urlRouterProvider.otherwise('/');

	$stateProvider

		.state('landing', {
			url: '/',
			templateUrl: '../templates/landing.html'
		})

		.state('registro', {
			url: '/registro',
			templateUrl: '../templates/registro.html'
		})

		.state('home', {
			url: '/home',
			templateUrl: '../templates/dashboard.html'
		})

		.state('home.proyectos', {
			url: '/proyectos',
			templateUrl: '../templates/proyectos.html'
		})

		.state('home.proyecto', {
			url: '/proyecto',
			templateUrl: '../templates/proyecto.html'
		})

		.state('home.horas', {
			url: '/horas',
			templateUrl: '../templates/horas.html'
		})

		.state('home.solicitudes', {
			url: '/solicitudes',
			templateUrl: '../templates/solicitudes.html'
		})

		.state('home.solicitud', {
			url: '/solicitud',
			templateUrl: '../templates/solicitud.html'
		});

}]);
<commit_msg>Set controller for register view<commit_after>"use strict";

var app = angular.module("VinculacionApp", ['ui.router', 'ngAnimate']);

app.config(['$stateProvider', '$urlRouterProvider',function($stateProvider, $urlRouterProvider) {
	$urlRouterProvider.otherwise('/');

	$stateProvider

		.state('landing', {
			url: '/',
			templateUrl: '../templates/landing.html'
		})

		.state('registro', {
			url: '/registro',
			templateUrl: '../templates/registro.html',
			controller: 'RegistroCtrl as registro'
		})

		.state('home', {
			url: '/home',
			templateUrl: '../templates/dashboard.html'
		})

		.state('home.proyectos', {
			url: '/proyectos',
			templateUrl: '../templates/proyectos.html'
		})

		.state('home.proyecto', {
			url: '/proyecto',
			templateUrl: '../templates/proyecto.html'
		})

		.state('home.horas', {
			url: '/horas',
			templateUrl: '../templates/horas.html'
		})

		.state('home.solicitudes', {
			url: '/solicitudes',
			templateUrl: '../templates/solicitudes.html'
		})

		.state('home.solicitud', {
			url: '/solicitud',
			templateUrl: '../templates/solicitud.html'
		});

}]);
<|endoftext|>


<commit_before>import { FIELD_ON_CHANGE } from './action-types.js';

// ensure the keys being passed is an array of key paths
// example: 'a.b' becomes ['a', 'b'] unless it was already ['a', 'b']
const keys = ks => (Array.isArray(ks) ? ks : ks.split('.'));

// traverse the set of keys left to right,
// returning the current value in each iteration.
// if at any point the value for the current key does not exist,
// return the default value
const deepGet = (o, kp, d) => keys(kp).reduce((o, k) => o && o[k] || d, o);

/**
 * traverse the set of keys right to left,
 * returning a new object containing both properties from the object
 * we were originally passed and our new property.
 * Example:
 * If o = { a: { b: { c: 1 } } }
 * deepSet(o, ['a', 'b', 'c'], 2) will progress thus:
 * 1. c = Object.assign({}, {c: 1}, { c: 2 })
 * 2. b = Object.assign({}, { b: { c: 1 } }, { b: c })
 * 3. returned = Object.assign({}, { a: { b: { c: 1 } } }, { a: b })
 * @param  {object} o  [description]
 * @param  {string} kp [description]
 * @param  {any} v     [description]
 * @return {object}    [description]
 */
const deepSet = (o, kp, v) =>
  keys(kp).reduceRight((v, k, i, ks) =>
    Object.assign({}, deepGet(o, ks.slice(0, i)), { [k]: v }), v);

function getComplexValue(value) {
  if (
    value !== null &&
    typeof value === 'object' &&
    typeof value.value !== 'undefined'
  ) {
    if (typeof value.parser === 'function') {
      return value.parser(value.value);
    }
    return value.value;
  }
  return value;
}

export default function formReducer(formName, defaultState = {}, options = {}) {
  return (state = defaultState, action) => {
    switch (action.type) {
      case FIELD_ON_CHANGE:
        let newState = state;
        let nameInReducer;
        const fields = Object.keys(action.payload);
        if (fields[0] === formName && options.putInRoot) {
          return { ...action.payload[formName] };
        }
        fields.forEach((name) => {
          if (name.startsWith(`${formName}.`) || name === formName) {
            if (options.putInRoot) nameInReducer = name.slice(formName.length + 1);
            if (name.endsWith('[]')) {
              nameInReducer = nameInReducer ? nameInReducer.slice(0, -2) : name.slice(0, -2);
              const value = deepGet(newState, nameInReducer) || [];
              const valueFromAction = getComplexValue(action.payload[name]);
              const index = value.indexOf(valueFromAction);
              const nextValue = index > -1 ?
                value.slice(0, index).concat(value.slice(index + 1)) :
                value.concat(valueFromAction);
              newState = deepSet(newState, nameInReducer, nextValue);
            } else {
              newState = deepSet(newState, nameInReducer, getComplexValue(action.payload[name]));
            }
          }
        });
        return newState;
      default:
        return state;
    }
  };
}
<commit_msg>when set default nameInReducer undefined so || name<commit_after>import { FIELD_ON_CHANGE } from './action-types.js';

// ensure the keys being passed is an array of key paths
// example: 'a.b' becomes ['a', 'b'] unless it was already ['a', 'b']
const keys = ks => (Array.isArray(ks) ? ks : ks.split('.'));

// traverse the set of keys left to right,
// returning the current value in each iteration.
// if at any point the value for the current key does not exist,
// return the default value
const deepGet = (o, kp, d) => keys(kp).reduce((o, k) => o && o[k] || d, o);

/**
 * traverse the set of keys right to left,
 * returning a new object containing both properties from the object
 * we were originally passed and our new property.
 * Example:
 * If o = { a: { b: { c: 1 } } }
 * deepSet(o, ['a', 'b', 'c'], 2) will progress thus:
 * 1. c = Object.assign({}, {c: 1}, { c: 2 })
 * 2. b = Object.assign({}, { b: { c: 1 } }, { b: c })
 * 3. returned = Object.assign({}, { a: { b: { c: 1 } } }, { a: b })
 * @param  {object} o  [description]
 * @param  {string} kp [description]
 * @param  {any} v     [description]
 * @return {object}    [description]
 */
const deepSet = (o, kp, v) =>
  keys(kp).reduceRight((v, k, i, ks) =>
    Object.assign({}, deepGet(o, ks.slice(0, i)), { [k]: v }), v);

function getComplexValue(value) {
  if (
    value !== null &&
    typeof value === 'object' &&
    typeof value.value !== 'undefined'
  ) {
    if (typeof value.parser === 'function') {
      return value.parser(value.value);
    }
    return value.value;
  }
  return value;
}

export default function formReducer(formName, defaultState = {}, options = {}) {
  return (state = defaultState, action) => {
    switch (action.type) {
      case FIELD_ON_CHANGE:
        let newState = state;
        let nameInReducer;
        const fields = Object.keys(action.payload);
        if (fields[0] === formName && options.putInRoot) {
          return { ...action.payload[formName] };
        }
        fields.forEach((name) => {
          if (name.startsWith(`${formName}.`) || name === formName) {
            if (options.putInRoot) nameInReducer = name.slice(formName.length + 1);
            if (name.endsWith('[]')) {
              nameInReducer = nameInReducer ? nameInReducer.slice(0, -2) : name.slice(0, -2);
              const value = deepGet(newState, nameInReducer) || [];
              const valueFromAction = getComplexValue(action.payload[name]);
              const index = value.indexOf(valueFromAction);
              const nextValue = index > -1 ?
                value.slice(0, index).concat(value.slice(index + 1)) :
                value.concat(valueFromAction);
              newState = deepSet(newState, nameInReducer, nextValue);
            } else {
              newState = deepSet(newState, nameInReducer || name, getComplexValue(action.payload[name]));
            }
          }
        });
        return newState;
      default:
        return state;
    }
  };
}
<|endoftext|>


<commit_before>define(['topBar', 'principalContent', 'services'], function(topBar, pCont, services) {
    'use strict';

    var _init = function() {
        var menuOptions = {
            op1: 'Videos',
            op2: 'Posts',
            op3: 'Books'
        };
        // top bar
        topBar.upMenu('Sphere');
        topBar.upMenu.prototype.insertTitle();
        topBar.upMenu.prototype.insertMenu(menuOptions);
        // post content
        //services.configCall(pCont.pContent);
        services.parseRSS('http://www.echojs.com/rss', pCont.pContent);
    };

    return {
        init: _init
    };
});
<commit_msg>Added all rss references, now printing echoJS content<commit_after>define(['topBar', 'principalContent', 'services'], function(topBar, pCont, services) {
    'use strict';

    var infoWorld = 'http://www.infoworld.com/news/index.rss',
        echoJS = 'http://www.echojs.com/rss',
        dailyJS = 'http://dailyjs.com/rss/',
        fiveJS = 'https://fivejs.codeschool.com/feed.rss',
        jsRocks = 'http://jsrocks.org/rss',
        frontEndLabs = 'http://frontendlabs.io/feed';

    var _init = function() {
        var menuOptions = {
            op1: 'Videos',
            op2: 'Posts',
            op3: 'Books'
        };
        // top bar
        topBar.upMenu('Sphere');
        topBar.upMenu.prototype.insertTitle();
        topBar.upMenu.prototype.insertMenu(menuOptions);
        // post content (echoJS)
        services.parseRSS(echoJS, pCont.echoContent);
    };

    return {
        init: _init
    };
});
<|endoftext|>


<commit_before>import isFunction from 'lodash.isfunction';
import isObject from 'lodash.isobject';
import isArray from 'lodash.isarray';
import merge from 'lodash.merge';
import { fromJS } from 'immutable';

import { LOAD } from './constants';

function myMerge(oldState, newState) {
    // Whole state is ImmutableJS? Easiest way to merge
    if (isFunction(oldState.mergeDeep)) {
        return oldState.mergeDeep(newState);
    }

    // newState is ImmutableJS? We can safely use fromJS and merge
    if (isFunction(newState.mergeDeep)) {
        return fromJS(oldState).mergeDeep(newState);
    }

    // Otherwise we need to carefully merge to avoid deprecated warnings from
    // ImmutableJS see #8. We inspect only the first object level, as this is
    // a common pattern with redux!
    const result = { ...oldState };
    // Note: Iterate using OLD STYLE and avoid Symbols for old browsers
    for (const key in newState) {
        if (!newState.hasOwnProperty(key)) {
            continue;
        }
        const value = newState[key];

        // Assign if we don't need to merge at all
        if (!result.hasOwnProperty(key)) {
            result[key] = isObject(value) && !isArray(value)
                ? merge({}, value)
                : value;
            continue;
        }

        const oldValue = result[key];
        if (isFunction(oldValue.mergeDeep)) {
            result[key] = oldValue.mergeDeep(value);
        } else if (isFunction(value.mergeDeep)) {
            result[key] = fromJS(oldValue).mergeDeep(value);
        } else if (isObject(value) && !isArray(value)) {
            result[key] = merge({}, oldValue, value);
        } else {
            result[key] = value;
        }
    }

    return result;
}

export default (reducer) => {
    return (state, action) => reducer(
        action.type === LOAD
            ? myMerge(state, action.payload)
            : state,
        action
    );
};
<commit_msg>Handle `null` or `undefined` while merge state<commit_after>import isFunction from 'lodash.isfunction';
import isObject from 'lodash.isobject';
import isArray from 'lodash.isarray';
import isNull from 'lodash.isnull';
import isUndefined from 'lodash.isundefined';
import merge from 'lodash.merge';
import { fromJS } from 'immutable';

import { LOAD } from './constants';

function myMerge(oldState, newState) {
    // Whole state is ImmutableJS? Easiest way to merge
    if (isFunction(oldState.mergeDeep)) {
        return oldState.mergeDeep(newState);
    }

    // newState is ImmutableJS? We can safely use fromJS and merge
    if (isFunction(newState.mergeDeep)) {
        return fromJS(oldState).mergeDeep(newState);
    }

    // Otherwise we need to carefully merge to avoid deprecated warnings from
    // ImmutableJS see #8. We inspect only the first object level, as this is
    // a common pattern with redux!
    const result = { ...oldState };
    // Note: Iterate using OLD STYLE and avoid Symbols for old browsers
    for (const key in newState) {
        if (!newState.hasOwnProperty(key)) {
            continue;
        }
        const value = newState[key];

        // Assign if we don't need to merge at all
        if (!result.hasOwnProperty(key)) {
            result[key] = isObject(value) && !isArray(value)
                ? merge({}, value)
                : value;
            continue;
        }

        const oldValue = result[key];

        if (!isNull(oldValue) && !isUndefined(oldValue)) {
            if (isFunction(oldValue.mergeDeep)) {
                result[key] = oldValue.mergeDeep(value);
            } else if (isFunction(value.mergeDeep)) {
                result[key] = fromJS(oldValue).mergeDeep(value);
            } else if (isObject(value) && !isArray(value)) {
                result[key] = merge({}, oldValue, value);
            } else {
                result[key] = value;
            }
        } else {
            result[key] = value;
        }
    }

    return result;
}

export default (reducer) => {
    return (state, action) => reducer(
        action.type === LOAD
            ? myMerge(state, action.payload)
            : state,
        action
    );
};
<|endoftext|>


<commit_before>/* Application Sripts */

$(function () {
  'use strict';
  // Initialize the IDB
  var db = new Dexie("tasks");
  db.version(1).stores({
  });

  main();

  function main() {
    // Initialize Material Bootstrap Theme
    $.material.init();
    initUI();

    db.open();
  }
});
<commit_msg>DB Work<commit_after>/* Application Sripts */

$(function () {
  'use strict';
  // Initialize the IDB
  var db = new Dexie("OnTrack");
  db.version(1).stores({
    // subject (string), title (string), dueDate (string),
    // completed (bool), notify (bool)
    task: '++id,subject,title,dueDate,completed,notify',
    settings: 'label,value'
  });

  main();

  function main() {
    // Initialize Material Bootstrap Theme
    $.material.init();

    var date = new Date(Date.parse(task.dueDate));

    db.open();
    addTask({
      subject: "CSC 360",
      title: "Finish Prototype",
      dueDate: date.toLocaleString(),
      completed: false,
      notify: true
    });
  }

  /*
   * @param task (containing information to be added to the DB) | @type object
   */
  function addTask(task) {
    db.task.add({
      subject: task.subject,
      title: task.title,
      dueDate: task.dueDate,
      completed: task.completed,
      notify: task.notify
    });
  }
});
<|endoftext|>


<commit_before>'use strict'

;(function () {
  /**
   * The application name.
   * @type {String}
   */
  const APP_NAME = 'GITHUB_RELEASE_WATCHER'

  /**
   * Storage key to cache DB URL.
   * @type {String}
   */
  const STORE_DB_URL = `${APP_NAME}-DB_URL`

  /**
   * Reference to the HTML Element used to display announcements.
   * @type {HTML Element}
   */
  const announceDOM = document.querySelector('.app-watcher__announce')

  /**
   * Referene to the button used to submit the DB URL.
   * @type {HTML Element}
   */
  const btn = document.querySelector('.app-watcher__submit-btn')

  /**
   * Reference to the Input Field used to get the DB URL.
   * @type {HTML Element}
   */
  const dbURLField = document.querySelector('.app-watcher__db')

  /**
   * Reference to the table HTML Element.
   * @type {HTML Element}
   */
  const table = document.querySelector('.app-watcher__table')

  /**
   * Reference to the HTML Element which will display any new updates.
   * @type {HTML Element}
   */
  const tableBody = document.querySelector('.app-watcher__table-updates')

  /**
   * Contains info about the different announcement types.
   * @type {Object}
   */
  const announceTypes = {
    INFO: 0,
    ERROR: 1
  }

  // Add a listener to the submit button so that when it is clicked it starts
  // the checking.
  btn.addEventListener('click', run)

  announce('Checking for cached DB URL')

  // Check whether the user has a cached DB URL and if so, use it.
  chrome.storage.sync.get(STORE_DB_URL, info => {
    const dbURL = info[STORE_DB_URL]
    if (dbURL === undefined) return toggleVisibility(announceDOM, false)
    dbURLField.value = dbURL
    run()
  })

  /**
   * Function used to check whether there are any updates to the repos inside
   * the provided DB URL.
   * @return {Promise}  Resolved on successful check, rejected otherwise.
   */
  function run () {
    // Hide table.
    toggleVisibility(table, false)

    // Get the DB URL entered.
    const dbURL = dbURLField.value

    // If no DB URL is provided, do nothing.
    if (dbURL.length === 0) return

    announce('Caching DB URL...')

    // Cache DB URL.
    chrome.storage.sync.set({ [STORE_DB_URL]: dbURL })

    announce('Retrieving JSON DB File...')
    // Retrieve DB JSON file.
    return retrieveDBFile(dbURLField.value).then(xhr => {
      announce('JSON DB File retrieved!')

      const entries = JSON.parse(xhr.responseText)
      const promises = []

      announce('Retrieving Repos Info...')

      // Make sure that DB File structure is valid
      if (typeof entries.forEach !== 'function') {
        return Promise.reject({
          entity: APP_NAME,
          message: 'Invalid DB File structure'
        })
      }

      // Retrieve the latest release for each repo.
      entries.forEach(entry => {
        promises.push(retrieveLatestRelease(entry))
      })

      return Promise.all(promises)
    }).then(repos => {
      announce('Checking Repos...')

      // Clear table
      tableBody.innerHTML = ''

      // Finally if releases version does not match, display the update in the
      // DOM.
      repos.forEach(({ entry, release }) => {
        if (entry.version !== release['tag_name']) addUpdate({ entry, release})
      })

      announce(table.classList.contains('app-watcher--hide')
        ? 'Repos are up-to-date!'
        : 'Done :)')
    }).catch(err => {
      const annouceError = announceTypes.ERROR
      if (err.entity === APP_NAME) return announce(err.message, annouceError)
      announce('An error had occured.', annouceError)
    })
  }

  /**
   * Function used to retrieve the DB JSON File.
   * @param  {String} url The URL of the DB JSON File.
   * @return {Promise}  Resolved on retrieval of DB JSON File, rejected
   *                    otherwise.
   */
  function retrieveDBFile (url) {
    return doRequest(url).catch(xhr => {
      if (xhr.status === 404) {
        return Promise.reject({
          entity: APP_NAME,
          message: 'DB URL unreachable'
        })
      }
    })
  }

  /**
   * Function used to retrieve the latest release info of a repo.
   * @param  {String} entry.user        The repo's owner name.
   * @param  {String} entry.repository  The repo's name.
   * @return {Promise}  Resolved with the release & entry details, rejected
   *                    otherwise.
   */
  function retrieveLatestRelease (entry) {
    const url = `https://api.github.com/repos/${entry.user}/` +
      `${entry.repository}/releases/latest`
    return doRequest(url).then(xhr => {
      return {
        entry: entry,
        release: JSON.parse(xhr.responseText)
      }
    })
  }

  /**
   * Function used to display an update.
   * @param {Object} options.entry    DB Entry info.
   * @param {Object} options.release  Github Release info.
   */
  function addUpdate ({entry, release}) {
    const row = document.createElement('tr')
    const repoName = document.createElement('td')
    const repoVersion = document.createElement('td')
    const repoLatest = document.createElement('td')
    const repoLink = document.createElement('a')

    repoName.innerHTML = `${entry.user}/${entry.repository}`
    repoVersion.innerHTML = entry.version

    repoLink.href = "javascript:;"
    repoLink.innerHTML = release['tag_name']
    repoLink.title = `${repoName.innerHTML} release page`
    repoLink.addEventListener('click', function () {
      openURL(release['html_url'])
    })

    repoLatest.appendChild(repoLink)

    row.appendChild(repoName)
    row.appendChild(repoVersion)
    row.appendChild(repoLatest)

    tableBody.appendChild(row)
    toggleVisibility(table, true)
  }

  /**
   * Function used to make an async HTTP GET Request.
   * @param  {String} url  The URL of the Request.
   * @return {Promise}     Resolved once on successful request, rejected
   *                       otherwise.
   */
  function doRequest (url) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()

      xhr.open('GET', url)
      xhr.addEventListener('load', function () {
        if (this.status !== 200) return reject(this)
        resolve(this)
      })
      xhr.addEventListener('abort', function () { reject(this) })
      xhr.addEventListener('error', function () { reject(this) })

      xhr.send()
    })
  }

  /**
   * Function used to open a page.
   * @param  {String} url  The URL to open.
   */
  function openURL (url) {
    chrome.tabs.create({ active: true, url: url })
  }

  /**
   * Function used to announce something to the user.
   * @param  {String} message  Message to be displayed
   * @param  {String} type     Announcement type.
   */
  function announce (message, type) {
    switch (type) {
      case announceTypes.ERROR: {
        announceDOM.classList.remove('app-watcher__announce--info')
        announceDOM.classList.add('app-watcher__announce--error')
        break
      }
      default: {
        announceDOM.classList.remove('app-watcher__announce--error')
        announceDOM.classList.add('app-watcher__announce--info')
      }
    }

    // Set the message.
    announceDOM.innerHTML = message

    // Display announce HTML Element.
    toggleVisibility(announceDOM, true)
  }

  /**
   * Function used to toggle the visibility of an HTML Element.
   * @param  {HTML Element} elem  HTML Element to be shown/hidden.
   * @param  {Boolean}      show  Indicates whether to show or hide the element.
   */
  function toggleVisibility (elem, show) {
    if (show === true) return elem.classList.remove('app-watcher--hide')
    elem.classList.add('app-watcher--hide')
  }
}())
<commit_msg>Handle repos with no releases<commit_after>'use strict'

;(function () {
  /**
   * The application name.
   * @type {String}
   */
  const APP_NAME = 'GITHUB_RELEASE_WATCHER'

  /**
   * Storage key to cache DB URL.
   * @type {String}
   */
  const STORE_DB_URL = `${APP_NAME}-DB_URL`

  /**
   * Reference to the HTML Element used to display announcements.
   * @type {HTML Element}
   */
  const announceDOM = document.querySelector('.app-watcher__announce')

  /**
   * Referene to the button used to submit the DB URL.
   * @type {HTML Element}
   */
  const btn = document.querySelector('.app-watcher__submit-btn')

  /**
   * Reference to the Input Field used to get the DB URL.
   * @type {HTML Element}
   */
  const dbURLField = document.querySelector('.app-watcher__db')

  /**
   * Reference to the table HTML Element.
   * @type {HTML Element}
   */
  const table = document.querySelector('.app-watcher__table')

  /**
   * Reference to the HTML Element which will display any new updates.
   * @type {HTML Element}
   */
  const tableBody = document.querySelector('.app-watcher__table-updates')

  /**
   * Contains info about the different announcement types.
   * @type {Object}
   */
  const announceTypes = {
    INFO: 0,
    ERROR: 1
  }

  // Add a listener to the submit button so that when it is clicked it starts
  // the checking.
  btn.addEventListener('click', run)

  announce('Checking for cached DB URL')

  // Check whether the user has a cached DB URL and if so, use it.
  chrome.storage.sync.get(STORE_DB_URL, info => {
    const dbURL = info[STORE_DB_URL]
    if (dbURL === undefined) return toggleVisibility(announceDOM, false)
    dbURLField.value = dbURL
    run()
  })

  /**
   * Function used to check whether there are any updates to the repos inside
   * the provided DB URL.
   * @return {Promise}  Resolved on successful check, rejected otherwise.
   */
  function run () {
    // Hide table.
    toggleVisibility(table, false)

    // Get the DB URL entered.
    const dbURL = dbURLField.value

    // If no DB URL is provided, do nothing.
    if (dbURL.length === 0) return

    announce('Caching DB URL...')

    // Cache DB URL.
    chrome.storage.sync.set({ [STORE_DB_URL]: dbURL })

    announce('Retrieving JSON DB File...')
    // Retrieve DB JSON file.
    return retrieveDBFile(dbURLField.value).then(xhr => {
      announce('JSON DB File retrieved!')

      const entries = JSON.parse(xhr.responseText)
      const promises = []

      announce('Retrieving Repos Info...')

      // Make sure that DB File structure is valid
      if (typeof entries.forEach !== 'function') {
        return Promise.reject({
          entity: APP_NAME,
          message: 'Invalid DB File structure'
        })
      }

      // Retrieve the latest release for each repo.
      entries.forEach(entry => {
        promises.push(retrieveLatestRelease(entry))
      })

      return Promise.all(promises)
    }).then(repos => {
      announce('Checking Repos...')

      // Clear table
      tableBody.innerHTML = ''

      // Finally if releases version does not match, display the update in the
      // DOM.
      repos.forEach(({ entry, release }) => {
        if (entry.version !== release['tag_name']) addUpdate({ entry, release})
      })

      announce(table.classList.contains('app-watcher--hide')
        ? 'Repos are up-to-date!'
        : 'Done :)')
    }).catch(err => {
      const annouceError = announceTypes.ERROR
      if (err.entity === APP_NAME) return announce(err.message, annouceError)
      announce('An error had occured.', annouceError)
    })
  }

  /**
   * Function used to retrieve the DB JSON File.
   * @param  {String} url The URL of the DB JSON File.
   * @return {Promise}  Resolved on retrieval of DB JSON File, rejected
   *                    otherwise.
   */
  function retrieveDBFile (url) {
    return doRequest(url).catch(xhr => {
      if (xhr.status === 404) {
        return Promise.reject({
          entity: APP_NAME,
          message: 'DB URL unreachable'
        })
      }
    })
  }

  /**
   * Function used to retrieve the latest release info of a repo.
   * @param  {String} entry.user        The repo's owner name.
   * @param  {String} entry.repository  The repo's name.
   * @return {Promise}  Resolved with the release & entry details, rejected
   *                    otherwise.
   */
  function retrieveLatestRelease (entry) {
    const url = `https://api.github.com/repos/${entry.user}/` +
      `${entry.repository}/releases/latest`

    const payload = { entry }

    return doRequest(url).then(xhr => {
      payload.release = JSON.parse(xhr.responseText)
      return payload
    }).catch(xhr => {
      payload.release = { 'tag_name': 'N/A' }
      return payload
    })
  }

  /**
   * Function used to display an update.
   * @param {Object} options.entry    DB Entry info.
   * @param {Object} options.release  Github Release info.
   */
  function addUpdate ({entry, release}) {
    const row = document.createElement('tr')
    const repoName = document.createElement('td')
    const repoVersion = document.createElement('td')
    const repoLatest = document.createElement('td')
    const repoLink = document.createElement('a')

    repoName.innerHTML = `${entry.user}/${entry.repository}`
    repoVersion.innerHTML = entry.version

    repoLink.href = "javascript:;"
    repoLink.innerHTML = release['tag_name']
    repoLink.title = `${repoName.innerHTML} release page`
    repoLink.addEventListener('click', function () {
      openURL(release['html_url'])
    })

    repoLatest.appendChild(repoLink)

    row.appendChild(repoName)
    row.appendChild(repoVersion)
    row.appendChild(repoLatest)

    tableBody.appendChild(row)
    toggleVisibility(table, true)
  }

  /**
   * Function used to make an async HTTP GET Request.
   * @param  {String} url  The URL of the Request.
   * @return {Promise}     Resolved once on successful request, rejected
   *                       otherwise.
   */
  function doRequest (url) {
    return new Promise((resolve, reject) => {
      const xhr = new XMLHttpRequest()

      xhr.open('GET', url)
      xhr.addEventListener('load', function () {
        if (this.status !== 200) return reject(this)
        resolve(this)
      })
      xhr.addEventListener('abort', function () { reject(this) })
      xhr.addEventListener('error', function () { reject(this) })

      xhr.send()
    })
  }

  /**
   * Function used to open a page.
   * @param  {String} url  The URL to open.
   */
  function openURL (url) {
    chrome.tabs.create({ active: true, url: url })
  }

  /**
   * Function used to announce something to the user.
   * @param  {String} message  Message to be displayed
   * @param  {String} type     Announcement type.
   */
  function announce (message, type) {
    switch (type) {
      case announceTypes.ERROR: {
        announceDOM.classList.remove('app-watcher__announce--info')
        announceDOM.classList.add('app-watcher__announce--error')
        break
      }
      default: {
        announceDOM.classList.remove('app-watcher__announce--error')
        announceDOM.classList.add('app-watcher__announce--info')
      }
    }

    // Set the message.
    announceDOM.innerHTML = message

    // Display announce HTML Element.
    toggleVisibility(announceDOM, true)
  }

  /**
   * Function used to toggle the visibility of an HTML Element.
   * @param  {HTML Element} elem  HTML Element to be shown/hidden.
   * @param  {Boolean}      show  Indicates whether to show or hide the element.
   */
  function toggleVisibility (elem, show) {
    if (show === true) return elem.classList.remove('app-watcher--hide')
    elem.classList.add('app-watcher--hide')
  }
}())
<|endoftext|>


<commit_before>/* global sharing */
var nouns = [],
    verbs = [];

Array.prototype.pick = function() {
  return this[Math.floor(Math.random()*this.length)];
};

function generate(nounPlural, verb) {
  nounPlural = nounPlural || nouns.pick().pluralize();
  verb = verb || nouns.pick().pluralize();
  var generatedText = ' ' + verb + '  are the jQuery of  ' + nounPlural + ' ';
  var shareText = verb + ' are the jQuery of ' + nounPlural;
  $('#content').html(generatedText);
  var shareUrl = window.location.href.split('?')[0]+'?word='+sharing.encodeStr(verb)+'$'+sharing.encodeStr(nounPlural);
  $('#share').attr('href', shareUrl);
  $('.twitter-share-button').remove();
  $('#twitterShare').html('Tweet');
  if (twttr.widgets) {
    twttr.widgets.load();
  }
}

function getWords(suppressGenerate) {
  $.when(
    $.ajax({
      url: 'http://api.wordnik.com/v4/words.json/randomWords?minCorpusCount=10000&minDictionaryCount=5&excludePartOfSpeech=proper-noun,proper-noun-plural,proper-noun-posessive,suffix,family-name,idiom,affix&hasDictionaryDef=true&includePartOfSpeech=noun&limit=1000&maxLength=22&api_key='+key.API_KEY,
      async: false,
      dataType:'json'
    }),
    $.ajax({
      url: 'http://api.wordnik.com//v4/words.json/randomWords?limit=1000&excludePartOfSpeech=adjective&hasDictionaryDef=true&includePartOfSpeech=verb-transitive&minCorpusCount=1000&api_key='+key.API_KEY,
      async: false,
      dataType:'json'
    })
  ).done(function(noun_data, verb_data) {
    nouns = $.map(noun_data[0], function(el) { return el.word; });
    verbs = $.map(verb_data[0], function(el) { return el.word; });
    if (!suppressGenerate) {
      generate();
    }
  });
}

$('#generate').click(function() { generate(); });
if (sharing.gup('word') === '') {
  getWords();
}
else {
  var verb = sharing.decodeStr(unescape(sharing.gup('word')).split('$')[0]);
  var nounPlural = sharing.decodeStr(unescape(sharing.gup('word')).split('$')[1]);
  getWords(true);
  generate(nounPlural, verb);
}
<commit_msg>fix wordnik url<commit_after>/* global sharing */
var nouns = [],
    verbs = [];

Array.prototype.pick = function() {
  return this[Math.floor(Math.random()*this.length)];
};

function generate(nounPlural, verb) {
  nounPlural = nounPlural || nouns.pick().pluralize();
  verb = verb || nouns.pick().pluralize();
  var generatedText = ' ' + verb + '  are the jQuery of  ' + nounPlural + ' ';
  var shareText = verb + ' are the jQuery of ' + nounPlural;
  $('#content').html(generatedText);
  var shareUrl = window.location.href.split('?')[0]+'?word='+sharing.encodeStr(verb)+'$'+sharing.encodeStr(nounPlural);
  $('#share').attr('href', shareUrl);
  $('.twitter-share-button').remove();
  $('#twitterShare').html('Tweet');
  if (twttr.widgets) {
    twttr.widgets.load();
  }
}

function getWords(suppressGenerate) {
  $.when(
    $.ajax({
      url: 'http://api.wordnik.com/v4/words.json/randomWords?minCorpusCount=10000&minDictionaryCount=5&excludePartOfSpeech=proper-noun,proper-noun-plural,proper-noun-posessive,suffix,family-name,idiom,affix&hasDictionaryDef=true&includePartOfSpeech=noun&limit=1000&maxLength=22&api_key='+key.API_KEY,
      async: false,
      dataType:'json'
    }),
    $.ajax({
      url: 'http://api.wordnik.com/v4/words.json/randomWords?limit=1000&excludePartOfSpeech=adjective&hasDictionaryDef=true&includePartOfSpeech=verb-transitive&minCorpusCount=1000&api_key='+key.API_KEY,
      async: false,
      dataType:'json'
    })
  ).done(function(noun_data, verb_data) {
    nouns = $.map(noun_data[0], function(el) { return el.word; });
    verbs = $.map(verb_data[0], function(el) { return el.word; });
    if (!suppressGenerate) {
      generate();
    }
  });
}

$('#generate').click(function() { generate(); });
if (sharing.gup('word') === '') {
  getWords();
}
else {
  var verb = sharing.decodeStr(unescape(sharing.gup('word')).split('$')[0]);
  var nounPlural = sharing.decodeStr(unescape(sharing.gup('word')).split('$')[1]);
  getWords(true);
  generate(nounPlural, verb);
}
<|endoftext|>


<commit_before>angular
  .module('chariotApp', ['ui-router', 'ngResource'])
  .config(MainConfig);

function MainConfig($stateProvider, $urlRouterProvider) {
  $stateProvider
  .state('landing', {
    url: '/',
    templateUrl: '_landing.html',
  })
  .state('vote', {
    url: '/vote',
    templateUrl: '_votepage.html',
  });

  $urlRouterProvider.otherwise('/');
};
<commit_msg>Adding donation route<commit_after>angular
  .module('chariotApp', ['ui-router', 'ngResource'])
  .config(MainConfig);

function MainConfig($stateProvider, $urlRouterProvider) {
  $stateProvider
  .state('landing', {
    url: '/',
    templateUrl: '_landing.html',
  })
  .state('vote', {
    url: '/vote',
    templateUrl: '_votepage.html',
  })
  .state('donate', {
    url: '/donate',
    templateUrl: '_donation.html',
  });

  $urlRouterProvider.otherwise('/');
};
<|endoftext|>


<commit_before>'use strict';

angular
.module('debateMyEF', ['ngCountdown', 'ngAnimate'])
.controller('CountdownCtrl', function($scope, $ngCountdown, $timeout){

    var now = new Date();

    var final = new Date('Tue Mar 17 2015 18:00:00 GMT-0500 (COT)');

    var times = $ngCountdown.units.hours | $ngCountdown.units.minutes
    | $ngCountdown.units.seconds | $ngCountdown.units.days;

    function repaint(){
        $(document.body).css('background-color', '#eee');
        $('footer a').css('color', 'black');
        $('#youtube').css('color', 'black');
        $('section').css('color', 'black');
    };

    function initCountdown(){

        now = new Date();

        $scope.date = $ngCountdown.init(now, final, times)

        if(now < final) $timeout(initCountdown, 1000);
        else {
            $scope.validateDate = false;
            repaint();
        }
    };

    if(now < final){
        $scope.validateDate = true;
        initCountdown();
    }
    else{
        repaint();
    }

});
<commit_msg>5 minutos<commit_after>'use strict';

angular
.module('debateMyEF', ['ngCountdown', 'ngAnimate'])
.controller('CountdownCtrl', function($scope, $ngCountdown, $timeout){

    var now = new Date();

    var final = new Date('Tue Mar 17 2015 20:45:00 GMT-0500 (COT)');

    var times = $ngCountdown.units.hours | $ngCountdown.units.minutes
    | $ngCountdown.units.seconds | $ngCountdown.units.days;

    function repaint(){
        $(document.body).css('background-color', '#eee');
        $('footer a').css('color', 'black');
        $('#youtube').css('color', 'black');
        $('section').css('color', 'black');
    };

    function initCountdown(){

        now = new Date();

        $scope.date = $ngCountdown.init(now, final, times)

        if(now < final) $timeout(initCountdown, 1000);
        else {
            $scope.validateDate = false;
            repaint();
        }
    };

    if(now < final){
        $scope.validateDate = true;
        initCountdown();
    }
    else{
        repaint();
    }

});
<|endoftext|>


<commit_before>// variables to hold values...
var player_base_move = 30;
var allEnemies = [];
var allGems = [];
var score = 0;
var lives = 3;
var pngWidth = 56; //total width of png: 101
var pngHeight = 56; // total height of png : 171
const WINNING_SCORE = 4; // arbitrary WIN condition

/////////////////////////////////////////////////////////////////////////////
// Gems
var Gem = function(gem_x, gem_y) {
    this.x = gem_x;
    this.y = gem_y;
    //image sprite
    this.sprite = 'images/Gem Blue.png';
};

Gem.prototype.update = function(gem_x, gem_y) {
    this.x = gem_x;
    this.y = gem_y;
};

Gem.prototype.reset = function() {
    var place_x = Math.floor(Math.random() * 450 + 30);
    var place_y = Math.floor(Math.random() * 250 + 30);
    //console.log("Gem reset, now x:" + place_x + " y:" + place_y + "!");
    this.update(place_x, place_y);
};
// Draw the enemy on the screen, required method for game
Gem.prototype.render = function() {
    ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};

// place the gems
for (var gem = 0; gem < 3; gem++) {
    var place_x = Math.floor(Math.random() * 300 + 30);
    var place_y = Math.floor(Math.random() * 300 + 30);
    var newGem = new Gem(place_x, place_y);
    //console.log(newGem);
    allGems.push(newGem);
}
console.log(allGems);

// if we restart the game, all gems have to be replaced on teh board
function resetAllGems() {
    for (var gem = 0; gem < 3; gem++) {
        allGems[gem].y = Math.floor(Math.random() * 300 + 30);
        allGems[gem].x = Math.floor(Math.random() * 300 + 30);
    }
}

/////////////////////////////////////////////////////////////////
// Enemies our player must avoid
var Enemy = function(enemy_x, enemy_y, startSpeed) {
    // Variables applied to each of our instances go here,
    // we've provided one for you to get started
    this.x = enemy_x;
    this.y = enemy_y;
    this.speed = startSpeed;
    // The image/sprite for our enemies, this uses
    // a helper we've provided to easily load images
    this.sprite = 'images/enemy-bug.png';
};

// Update the enemy's position, required method for game
// Parameter: dt, a time delta between ticks
Enemy.prototype.update = function(dt) {
    this.x = this.x + this.speed * dt;
    if (this.x > 505) {
        this.speed = this.reset();
    }
    // invoke collision detection
    this.findCollision();
    this.gemCollision();
};

Enemy.prototype.reset = function(speed) {
    this.x = -100;
    var speed = Math.floor(Math.random() * 140 + 40);
    //console.log("Bug reset, new speed is " + speed + "!");
    return speed;
};

// Draw the enemy on the screen, required method for game
Enemy.prototype.render = function() {
    ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};

// method to handle collisions!
Enemy.prototype.findCollision = function() {

    if (player.x < this.x + pngWidth &&
        player.x + pngWidth > this.x &&
        player.y < this.y + pngHeight &&
        player.y + pngHeight > this.y) {
        //collision?
        console.log("Enemy Collision!!!1!");
        lives--;
        document.getElementById("lives").value = lives;
        if (lives < 1) {
            parkEnemies();
            score = 0;
            lives = 0;
            gameMessage("
Sorry, you're out of lives!
Start over?
");
            hideStart();
            hideRestart();
            showReplay();
        } else {
            player.reset(lives + " lives left, continue?");
        }
    }

};

// method to handle collisions!
Enemy.prototype.gemCollision = function() {

    // there are multiple gems!
    for (var gem = 0; gem < allGems.length; gem++) {
        if (allGems[gem].x < this.x + pngWidth &&
            allGems[gem].x + pngWidth > this.x &&
            allGems[gem].y < this.y + pngHeight &&
            allGems[gem].y + pngHeight > this.y) {
            //collision?
            //console.log("Gem Collision!!!1!");
            allGems[gem].reset();
        }
    }
};

// Now write your own player class ////////////////////////////////////////////
// This class requires an update(), render() and
// a handleInput() method.
// Now write your own player class
var Player = function() {
    this.x = 200;
    this.y = 410;
    // NOTE: default player is a girl!
    this.sprite = 'images/char-pink-girl.png';
};

Player.prototype.update = function() {
    //check to see if we've scored a gem.
    this.gemCollision();
    //NOTE: incrementing the score inside here means that it updates multiple times!
};

// event is win or lose, restart the player back to start square
//  and, send on the game message.
Player.prototype.reset = function(msg) {
    this.x = 200;
    this.y = 410;
    console.log("Player starts over!");

    gameMessage(msg);
    // get enemies into position to start over
    parkEnemies();

}

Player.prototype.render = function() {
    ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};

Player.prototype.handleInput = function(event) {
    this.ctlKey = event;
    //console.log(this.ctlKey);

    if (this.ctlKey === 'left' && this.x > 0) {
        this.x -= player_base_move;
    } else if (this.ctlKey === 'right' && this.x < 410) {
        this.x = this.x + player_base_move;
    } else if (this.ctlKey === 'up' && this.y > 18) {
        this.y = this.y - player_base_move;
    } else if (this.ctlKey === 'down' && this.y < 410) {
        this.y = this.y + player_base_move;
    }

    if (player.y === -10) {
        adjustScore();
        var leftToGo = WINNING_SCORE - score;
        if (score >= WINNING_SCORE || leftToGo === 0) {
            restartGame();
        } else {
            player.reset("You WON this round!
Only " + leftToGo + " points to go!");
        }
    }
    //console.log(this.ctlKey + ": I am at x" + this.x + ", y" + this.y);
};

// method to handle collisions!
Player.prototype.gemCollision = function() {

    // there are multiple gems!
    for (var gem = 0; gem < allGems.length; gem++) {
        if (allGems[gem].x < this.x + pngWidth &&
            allGems[gem].x + pngWidth > this.x &&
            allGems[gem].y < this.y + pngHeight &&
            allGems[gem].y + pngHeight > this.y) {
            //collision?
            console.log("Player Gem Collision!!!1!");
            // move the gem offscreen where it won't count anymore
            allGems[gem].y = 1000;
            // increment the score
            adjustScore();
            // test if we've gotten to WIN...
            if (score >= WINNING_SCORE) {
                restartGame();
            }
        }
    }

};

////////////////////////////////////////////////////////////////////////////
// Game functions
////////////////////////////////////////////////////////////////////////////

// decided I wanted predictable paths for bugs, hence the array.
var paths = [65, 145, 226];

for (var path = 0; path < paths.length; path++) {
    //var speed = Math.floor(Math.random() * 140 + 40);
    //var startingLine = Math.floor(Math.random() * 300 + 100);
    // now we START all enemies offscreen, and let the player 'restart' them
    // when they are ready to actually START
    var newEnemy = new Enemy(-200, paths[path], 0);
    //console.log(newEnemy);
    allEnemies.push(newEnemy);
}
console.log(allEnemies);

// all bugs start off at 0 speed offscreen, only get moving when we tell them to
function startEnemies() {
    // add activity to offscreen enemies
    for (var enemy = 0; enemy < allEnemies.length; enemy++) {
        var speed = Math.floor(Math.random() * 140 + 40);
        var startingLine = Math.floor(Math.random() * 300 + 100);
        allEnemies[enemy].x = -startingLine;
        allEnemies[enemy].speed = speed;
    }
    console.log("Restarted enemies!");
    console.log(allEnemies);
}

function parkEnemies() {
    // hide them offscreen until player is ready to restart
    for (var enemy = 0; enemy < allEnemies.length; enemy++) {
        allEnemies[enemy].x = -200;
        allEnemies[enemy].speed = 0;
    }
}

//this is all it takes to start the player object.
var player = new Player();

// This listens for key presses and sends the keys to your
// Player.handleInput() method.
document.addEventListener('keyup', function(e) {
    var allowedKeys = {
        37: 'left',
        38: 'up',
        39: 'right',
        40: 'down'
    };
    player.handleInput(allowedKeys[e.keyCode]);
});

// increment the score
function adjustScore() {
    score++;
    document.getElementById("score").value = score;
}

///////////////////////////////////////////////////////////////////////////////
// Game Messaging

// take the success/failure/whatever message and send it on to the headline div
function gameMessage(msg) {
    document.getElementById("headline").style.display = "block";
    document.getElementById("headline").innerHTML = msg;
    document.getElementById("game").style.display = "none";
}

// 'Start' button to begin game binding
document.getElementById("start").addEventListener("click", function() {
    showStart();
    hideRestart();
    document.getElementById("game").style.display = "inline";
    document.getElementById("headline").style.display = "none";
    startEnemies();
});

// Next turn button binding
document.getElementById("restart").addEventListener("click", function() {
    showReplay();
    document.getElementById("game").style.display = "inline";
    document.getElementById("headline").style.display = "none";
    startEnemies();
});

// Start over button binding
document.getElementById("replay").addEventListener("click", function() {
    restartGame();
});

// Choose Avatar Button
document.getElementById("chooseAvatar").addEventListener("click", function() {
    console.log("Calling avatar function");
    chooseAvatar();
});

// ABOUT button...
document.getElementById("about").addEventListener("click", function() {
    document.getElementById("aboutThisGame").style.display = "block";
});
// close ABOUT button...
document.getElementById("closeAbout").addEventListener("click", function() {
    document.getElementById("aboutThisGame").style.display = "none";
});

// make the restart a function so that we can call it from player.reset too.
function restartGame() {
    console.log("Resetting game over, score: " + score + " / lives: " + lives);
    if (lives === 0) {
        document.getElementById("headline").style.display = "none";
        document.getElementById("game").style.display = "inline";
    } else {
        document.getElementById("headline").style.display = "block";
        // get current player icon (it can have been changeed) and display it with
        //  won msg
        var sprite = player.sprite;
        var playerPic = "";
        document.getElementById("headline").innerHTML = playerPic +
            "
Terrific! You WON!
 Play Again?
";
        document.getElementById("game").style.display = "none";
    }
    hideReplay();
    hideRestart();
    showStart();
    player.x = 200;
    player.y = 410;
    score = 0;
    document.getElementById("score").value = score;
    console.log("score reset to " + score);
    lives = 3;
    document.getElementById("lives").value = lives;
    //startEnemies();
    resetAllGems();

}

// what the Choose Player Avatar button DOES
//
function chooseAvatar() {
    document.getElementById("avatar").style.display = "block";
    document.getElementById("gameArea").style.display = "none";
    document.getElementById("menu").style.display = "none";
}

function hideRestart() {
    document.getElementById("restart").style.display = "none";
}

function showRestart() {
    document.getElementById("restart").style.display = "inline";
}

function showReplay() {
    document.getElementById("replay").style.display = "inline";
}

function hideReplay() {
    document.getElementById("replay").style.display = "none";
}

function showStart() {
    document.getElementById("start").style.display = "inline";
}

function hideStart() {
    document.getElementById("start").style.display = "none";
}

/////////////////////////////////////////////////////////////////////////////
// Avatars-specific
// first, narrow down the buttons that get the click event added -- only
// the "characters" buttons

var allButtons = document.getElementsByTagName("button");
var characterButtons = [];
for (var btn = 0; btn < allButtons.length; btn++) {
    if (allButtons[btn].parentNode.id === "characters") {
        characterButtons.push(allButtons[btn]);
    }
}
console.log(characterButtons);

// now take that set of character buttons and assign click actions to them
// but we'll have to make it a CLOSURE FUNCTION

// actual action called by callback
function changeCharacter(playerIcon) {
    player.sprite = "images/char-" + playerIcon + ".png";
    //And when we've changed the image, put the screen back the way it was...
    document.getElementById("avatar").style.display = "none";
    document.getElementById("menu").style.display = "inline";
    document.getElementById("gameArea").style.display = "block";
}

// callback to send on the data to the sprite change
function makeChangeCallback(playerIcon) {
    return function() {
        changeCharacter(playerIcon);
    };
}

// function to go through the character buttons, set up the value to be passed
// on to the callback, and instantiate the onclick eventlistener.
function setupPlayerIcon() {

    for (var btn = 0; btn < characterButtons.length; btn++) {
        var playerIcon = characterButtons[btn].id;
        console.log("Setting up onclick for " + playerIcon);
        characterButtons[btn].onclick = makeChangeCallback(playerIcon);
    }
}

// and run the function now!
setupPlayerIcon();<commit_msg>Started moving global variables into protected app. ones.<commit_after>// variables to hold values...
//var player_base_move = 30;
var allEnemies = [];
var allGems = [];
var score = 0;
var lives = 3;
var pngWidth = 56; //total width of png: 101
var pngHeight = 56; // total height of png : 171
const WINNING_SCORE = 4; // arbitrary WIN condition

var app = app || {};
app.player_base_move = 30;

/////////////////////////////////////////////////////////////////////////////
// Gems
var Gem = function(gem_x, gem_y) {
    this.x = gem_x;
    this.y = gem_y;
    //image sprite
    this.sprite = 'images/Gem Blue.png';
};

Gem.prototype.update = function(gem_x, gem_y) {
    this.x = gem_x;
    this.y = gem_y;
};

Gem.prototype.reset = function() {
    var place_x = Math.floor(Math.random() * 450 + 30);
    var place_y = Math.floor(Math.random() * 250 + 30);
    //console.log("Gem reset, now x:" + place_x + " y:" + place_y + "!");
    this.update(place_x, place_y);
};
// Draw the enemy on the screen, required method for game
Gem.prototype.render = function() {
    ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};

// place the gems
for (var gem = 0; gem < 3; gem++) {
    var place_x = Math.floor(Math.random() * 300 + 30);
    var place_y = Math.floor(Math.random() * 300 + 30);
    var newGem = new Gem(place_x, place_y);
    //console.log(newGem);
    allGems.push(newGem);
}
console.log(allGems);

// if we restart the game, all gems have to be replaced on teh board
function resetAllGems() {
    for (var gem = 0; gem < 3; gem++) {
        allGems[gem].y = Math.floor(Math.random() * 300 + 30);
        allGems[gem].x = Math.floor(Math.random() * 300 + 30);
    }
}

/////////////////////////////////////////////////////////////////
// Enemies our player must avoid
var Enemy = function(enemy_x, enemy_y, startSpeed) {
    // Variables applied to each of our instances go here,
    // we've provided one for you to get started
    this.x = enemy_x;
    this.y = enemy_y;
    this.speed = startSpeed;
    // The image/sprite for our enemies, this uses
    // a helper we've provided to easily load images
    this.sprite = 'images/enemy-bug.png';
};

// Update the enemy's position, required method for game
// Parameter: dt, a time delta between ticks
Enemy.prototype.update = function(dt) {
    this.x = this.x + this.speed * dt;
    if (this.x > 505) {
        this.speed = this.reset();
    }
    // invoke collision detection
    this.findCollision();
    this.gemCollision();
};

Enemy.prototype.reset = function(speed) {
    this.x = -100;
    var speed = Math.floor(Math.random() * 140 + 40);
    //console.log("Bug reset, new speed is " + speed + "!");
    return speed;
};

// Draw the enemy on the screen, required method for game
Enemy.prototype.render = function() {
    ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};

// method to handle collisions!
Enemy.prototype.findCollision = function() {

    if (player.x < this.x + pngWidth &&
        player.x + pngWidth > this.x &&
        player.y < this.y + pngHeight &&
        player.y + pngHeight > this.y) {
        //collision?
        console.log("Enemy Collision!!!1!");
        lives--;
        document.getElementById("lives").value = lives;
        if (lives < 1) {
            parkEnemies();
            score = 0;
            lives = 0;
            gameMessage("
Sorry, you're out of lives!
Start over?
");
            hideStart();
            hideRestart();
            showReplay();
        } else {
            player.reset(lives + " lives left, continue?");
        }
    }

};

// method to handle collisions!
Enemy.prototype.gemCollision = function() {

    // there are multiple gems!
    for (var gem = 0; gem < allGems.length; gem++) {
        if (allGems[gem].x < this.x + pngWidth &&
            allGems[gem].x + pngWidth > this.x &&
            allGems[gem].y < this.y + pngHeight &&
            allGems[gem].y + pngHeight > this.y) {
            //collision?
            //console.log("Gem Collision!!!1!");
            allGems[gem].reset();
        }
    }
};

// Now write your own player class ////////////////////////////////////////////
// This class requires an update(), render() and
// a handleInput() method.
// Now write your own player class
var Player = function() {
    this.x = 200;
    this.y = 410;
    // NOTE: default player is a girl!
    this.sprite = 'images/char-pink-girl.png';
};

Player.prototype.update = function() {
    //check to see if we've scored a gem.
    this.gemCollision();
    //NOTE: incrementing the score inside here means that it updates multiple times!
};

// event is win or lose, restart the player back to start square
//  and, send on the game message.
Player.prototype.reset = function(msg) {
    this.x = 200;
    this.y = 410;
    console.log("Player starts over!");

    gameMessage(msg);
    // get enemies into position to start over
    parkEnemies();

}

Player.prototype.render = function() {
    ctx.drawImage(Resources.get(this.sprite), this.x, this.y);
};

Player.prototype.handleInput = function(event) {
    this.ctlKey = event;
    //console.log(this.ctlKey);

    if (this.ctlKey === 'left' && this.x > 0) {
        this.x -= app.player_base_move;
    } else if (this.ctlKey === 'right' && this.x < 410) {
        this.x = this.x + app.player_base_move;
    } else if (this.ctlKey === 'up' && this.y > 18) {
        this.y = this.y - app.player_base_move;
    } else if (this.ctlKey === 'down' && this.y < 410) {
        this.y = this.y + app.player_base_move;
    }

    if (player.y === -10) {
        adjustScore();
        var leftToGo = WINNING_SCORE - score;
        if (score >= WINNING_SCORE || leftToGo === 0) {
            restartGame();
        } else {
            player.reset("You WON this round!
Only " + leftToGo + " points to go!");
        }
    }
    //console.log(this.ctlKey + ": I am at x" + this.x + ", y" + this.y);
};

// method to handle collisions!
Player.prototype.gemCollision = function() {

    // there are multiple gems!
    for (var gem = 0; gem < allGems.length; gem++) {
        if (allGems[gem].x < this.x + pngWidth &&
            allGems[gem].x + pngWidth > this.x &&
            allGems[gem].y < this.y + pngHeight &&
            allGems[gem].y + pngHeight > this.y) {
            //collision?
            console.log("Player Gem Collision!!!1!");
            // move the gem offscreen where it won't count anymore
            allGems[gem].y = 1000;
            // increment the score
            adjustScore();
            // test if we've gotten to WIN...
            if (score >= WINNING_SCORE) {
                restartGame();
            }
        }
    }

};

////////////////////////////////////////////////////////////////////////////
// Game functions
////////////////////////////////////////////////////////////////////////////

// decided I wanted predictable paths for bugs, hence the array.
var paths = [65, 145, 226];

for (var path = 0; path < paths.length; path++) {
    //var speed = Math.floor(Math.random() * 140 + 40);
    //var startingLine = Math.floor(Math.random() * 300 + 100);
    // now we START all enemies offscreen, and let the player 'restart' them
    // when they are ready to actually START
    var newEnemy = new Enemy(-200, paths[path], 0);
    //console.log(newEnemy);
    allEnemies.push(newEnemy);
}
console.log(allEnemies);

// all bugs start off at 0 speed offscreen, only get moving when we tell them to
function startEnemies() {
    // add activity to offscreen enemies
    for (var enemy = 0; enemy < allEnemies.length; enemy++) {
        var speed = Math.floor(Math.random() * 140 + 40);
        var startingLine = Math.floor(Math.random() * 300 + 100);
        allEnemies[enemy].x = -startingLine;
        allEnemies[enemy].speed = speed;
    }
    console.log("Restarted enemies!");
    console.log(allEnemies);
}

function parkEnemies() {
    // hide them offscreen until player is ready to restart
    for (var enemy = 0; enemy < allEnemies.length; enemy++) {
        allEnemies[enemy].x = -200;
        allEnemies[enemy].speed = 0;
    }
}

//this is all it takes to start the player object.
var player = new Player();

// This listens for key presses and sends the keys to your
// Player.handleInput() method.
document.addEventListener('keyup', function(e) {
    var allowedKeys = {
        37: 'left',
        38: 'up',
        39: 'right',
        40: 'down'
    };
    player.handleInput(allowedKeys[e.keyCode]);
});

// increment the score
function adjustScore() {
    score++;
    document.getElementById("score").value = score;
}

///////////////////////////////////////////////////////////////////////////////
// Game Messaging

// take the success/failure/whatever message and send it on to the headline div
function gameMessage(msg) {
    document.getElementById("headline").style.display = "block";
    document.getElementById("headline").innerHTML = msg;
    document.getElementById("game").style.display = "none";
}

// 'Start' button to begin game binding
document.getElementById("start").addEventListener("click", function() {
    showStart();
    hideRestart();
    document.getElementById("game").style.display = "inline";
    document.getElementById("headline").style.display = "none";
    startEnemies();
});

// Next turn button binding
document.getElementById("restart").addEventListener("click", function() {
    showReplay();
    document.getElementById("game").style.display = "inline";
    document.getElementById("headline").style.display = "none";
    startEnemies();
});

// Start over button binding
document.getElementById("replay").addEventListener("click", function() {
    restartGame();
});

// Choose Avatar Button
document.getElementById("chooseAvatar").addEventListener("click", function() {
    console.log("Calling avatar function");
    chooseAvatar();
});

// ABOUT button...
document.getElementById("about").addEventListener("click", function() {
    document.getElementById("aboutThisGame").style.display = "block";
});
// close ABOUT button...
document.getElementById("closeAbout").addEventListener("click", function() {
    document.getElementById("aboutThisGame").style.display = "none";
});

// make the restart a function so that we can call it from player.reset too.
function restartGame() {
    console.log("Resetting game over, score: " + score + " / lives: " + lives);
    if (lives === 0) {
        document.getElementById("headline").style.display = "none";
        document.getElementById("game").style.display = "inline";
    } else {
        document.getElementById("headline").style.display = "block";
        // get current player icon (it can have been changeed) and display it with
        //  won msg
        var sprite = player.sprite;
        var playerPic = "";
        document.getElementById("headline").innerHTML = playerPic +
            "
Terrific! You WON!
 Play Again?
";
        document.getElementById("game").style.display = "none";
    }
    hideReplay();
    hideRestart();
    showStart();
    player.x = 200;
    player.y = 410;
    score = 0;
    document.getElementById("score").value = score;
    console.log("score reset to " + score);
    lives = 3;
    document.getElementById("lives").value = lives;
    //startEnemies();
    resetAllGems();

}

// what the Choose Player Avatar button DOES
//
function chooseAvatar() {
    document.getElementById("avatar").style.display = "block";
    document.getElementById("gameArea").style.display = "none";
    document.getElementById("menu").style.display = "none";
}

function hideRestart() {
    document.getElementById("restart").style.display = "none";
}

function showRestart() {
    document.getElementById("restart").style.display = "inline";
}

function showReplay() {
    document.getElementById("replay").style.display = "inline";
}

function hideReplay() {
    document.getElementById("replay").style.display = "none";
}

function showStart() {
    document.getElementById("start").style.display = "inline";
}

function hideStart() {
    document.getElementById("start").style.display = "none";
}

/////////////////////////////////////////////////////////////////////////////
// Avatars-specific
// first, narrow down the buttons that get the click event added -- only
// the "characters" buttons

var allButtons = document.getElementsByTagName("button");
var characterButtons = [];
for (var btn = 0; btn < allButtons.length; btn++) {
    if (allButtons[btn].parentNode.id === "characters") {
        characterButtons.push(allButtons[btn]);
    }
}
console.log(characterButtons);

// now take that set of character buttons and assign click actions to them
// but we'll have to make it a CLOSURE FUNCTION

// actual action called by callback
function changeCharacter(playerIcon) {
    player.sprite = "images/char-" + playerIcon + ".png";
    //And when we've changed the image, put the screen back the way it was...
    document.getElementById("avatar").style.display = "none";
    document.getElementById("menu").style.display = "inline";
    document.getElementById("gameArea").style.display = "block";
}

// callback to send on the data to the sprite change
function makeChangeCallback(playerIcon) {
    return function() {
        changeCharacter(playerIcon);
    };
}

// function to go through the character buttons, set up the value to be passed
// on to the callback, and instantiate the onclick eventlistener.
function setupPlayerIcon() {

    for (var btn = 0; btn < characterButtons.length; btn++) {
        var playerIcon = characterButtons[btn].id;
        console.log("Setting up onclick for " + playerIcon);
        characterButtons[btn].onclick = makeChangeCallback(playerIcon);
    }
}

// and run the function now!
setupPlayerIcon();<|endoftext|>


<commit_before>var fixcolumns = {

    highest: 0,

    init: function () {
        if (!document.getElementById || !document.createTextNode) {
            return;
        }

        fixcolumns.node = document.getElementById('recent');

        if (!fixcolumns.node) {
            return;
        }
        fixcolumns.fix('h2');
        fixcolumns.fix('p');
    },

    fix: function (elm) {
        fixcolumns.getHighest(elm);
        fixcolumns.fixElements(elm);
    },

    getHighest: function (elm) {
        fixcolumns.highest = 0;
        var temp = fixcolumns.node.getElementsByTagName(elm);
        for (var i = 0; i < temp.length; i++) {
            if (!temp[i].offsetHeight) {
                continue;
            }
            if (temp[i].offsetHeight > fixcolumns.highest) {
                fixcolumns.highest = temp[i].offsetHeight;
            }
        }
    },

    fixElements: function (elm) {
        var temp = fixcolumns.node.getElementsByTagName(elm);
        for (var i = 0; i < temp.length; i++) {
            temp[i].style.height = parseInt(fixcolumns.highest) + 'px';
        }
    }
}

var navHeader = document.querySelector('.navbar-toggle');
var collapsed = document.querySelector('.collapse');

navHeader.addEventListener("click", function () {
    if (collapsed.className.match(' collapse')) {
        collapsed.className = collapsed.className.replace(" collapse", ' ')
    } else {
        collapsed.className += ' collapse                               '
    }
});

fixcolumns.init();

/**
 * Made edits to cbpAnimatedHeader.js v1.0.0 to use vanilla JS for it's class toggling functionality than use another js library it ships with
 * cbpAnimatedHeader.js is licensed under the MIT by http://www.codrops.com
 */
var cbpAnimatedHeader = (function () {

    var docElem = document.documentElement,
        header = document.querySelector('.navbar-fixed-top'),
        fixed = document.querySelector('.fixed'),
        didScroll = false,
        changeHeaderOn = 300;

    function init() {
        window.addEventListener('scroll', function (event) {
            if (!didScroll) {
                didScroll = true;
                setTimeout(scrollPage, 250);
            }
        }, false);
    }

    function scrollPage() {
        var sy = scrollY();
        if (sy >= changeHeaderOn) {

            if (!isMatch()) {
                header.className += ' shrink';
            }
        } else {

            if (isMatch()) {
                header.className = header.className.replace(' shrink', '');
            }
        }
        didScroll = false;
    }

    function scrollY() {
        return window.pageYOffset || docElem.scrollTop;
    }

    function isMatch() {
        return header.className.match(' shrink');
    }

    init();
})();<commit_msg>javascript file<commit_after>var fixcolumns = {

    highest: 0,

    init: function () {
        if (!document.getElementById || !document.createTextNode) {
            return;
        }

        fixcolumns.node = document.getElementById('recent');

        if (!fixcolumns.node) {
            return;
        }
        fixcolumns.fix('h2');
        fixcolumns.fix('p');
    },

    fix: function (elm) {
        fixcolumns.getHighest(elm);
        fixcolumns.fixElements(elm);
    },

    getHighest: function (elm) {
        fixcolumns.highest = 0;
        var temp = fixcolumns.node.getElementsByTagName(elm);
        for (var i = 0; i < temp.length; i++) {
            if (!temp[i].offsetHeight) {
                continue;
            }
            if (temp[i].offsetHeight > fixcolumns.highest) {
                fixcolumns.highest = temp[i].offsetHeight;
            }
        }
    },

    fixElements: function (elm) {
        var temp = fixcolumns.node.getElementsByTagName(elm);
        for (var i = 0; i < temp.length; i++) {
            temp[i].style.height = parseInt(fixcolumns.highest) + 'px';
        }
    }
}

var navHeader = document.querySelector('.navbar-toggle');
var collapsed = document.querySelector('.collapse');

navHeader.addEventListener("click", function () {
    if (collapsed.className.match(' collapse')) {
        collapsed.className = collapsed.className.replace(" collapse", ' ')
    } else {
        collapsed.className += ' collapse                               '
    }
});

fixcolumns.init();

/**
 * Made edits to cbpAnimatedHeader.js v1.0.0 to use vanilla JS for it's class toggling functionality than use another js library it ships with
 * cbpAnimatedHeader.js is licensed under the MIT by http://www.codrops.com
 */
var cbpAnimatedHeader = (function () {

    var docElem = document.documentElement,
        header = document.querySelector('.navbar-fixed-top'),
        fixed = document.querySelector('.fixed'),
        didScroll = false,
        changeHeaderOn = 300;

    function init() {
        window.addEventListener('scroll', function (event) {
            if (!didScroll) {
                didScroll = true;
                setTimeout(scrollPage, 250);
            }
        }, false);
    }

    function scrollPage() {
        var sy = scrollY();
        if (sy >= changeHeaderOn) {

            if (!isMatch()) {
                header.className += ' shrink';
            }
        } else {

            if (isMatch()) {
                header.className = header.className.replace(' shrink', '');
            }
        }
        didScroll = false;
    }

    function scrollY() {
        return window.pageYOffset || docElem.scrollTop;
    }

    function isMatch() {
        return header.className.match(' shrink');
    }

    init();
})();

(function (i, s, o, g, r, a, m) {
    i['GoogleAnalyticsObject'] = r;
    i[r] = i[r] || function () {
        (i[r].q = i[r].q || []).push(arguments)
    }, i[r].l = 1 * new Date();
    a = s.createElement(o),
        m = s.getElementsByTagName(o)[0];
    a.async = 1;
    a.src = g;
    m.parentNode.insertBefore(a, m)
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');

ga('create', '{{ site.googleanalytics }}', 'auto');
ga('send', 'pageview');<|endoftext|>


<commit_before>/**
 * Created with JetBrains PhpStorm.
 * User: taoqili
 * Date: 13-2-21
 * Time: 下午1:31
 * To change this template use File | Settings | File Templates.
 */
function getTable(str) {
    var div = document.getElementById("testTable");
    if(!div){
        div = document.createElement("div");
        div.id = "testTable";
        document.body.appendChild(div);
    }
    div.innerHTML = "
" + str + "
";
    return div.firstChild;
}
UT = UE.UETable;
test("create UETable",function(){
    var table = getTable("
ddd
"),
        ut = new UT(table);
    ok(ut.table === table,"UT对象创建成功");
    ok(ut.colsNum == 1 && ut.rowsNum == 1,"单元格行、列数为1");
});

test("getMaxRows",function(){
    var table = getTable("
1	2	3
" +
                         "
1	2	3
"),
        ut = new UT(table);
    var maxRows = ut.getMaxRows();
    equal(maxRows,2,"最大行数为2");
    table = getTable("
1	2	3
" +
                     "
2
");
    ut = new UT(table);
    maxRows = ut.getMaxRows();
    equal(maxRows,3,"最大行数为3");
});
test("getMaxCols",function(){
    var table = getTable("
1	2	3
" +
                         "
1	2	3
"),
        ut = new UT(table);
    var maxCols = ut.getMaxCols();
    equal(maxCols,3,"最大列数为3");

    table = getTable("
1	2	3
" +
        "
2
");
    ut = new UT(table);
    maxCols = ut.getMaxCols();
    equal(maxCols,6,"最大列数为6");
});

test("getSameEndPosCells",function(){
    var table = getTable("
1	2	3
" +
                         "
2	3
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[0],
        cells1 = ut.getSameEndPosCells(cell,"x"),
        cells2 = ut.getSameEndPosCells(cell,"y");
    ok(cells1.length == 1, "获取到同样X轴结尾位置的cell1个");
    ok(cells2.length == 2, "获取到同样Y轴结尾位置的cell2个");
});

test("getHSideCell",function(){
    var table = getTable("
1	2	3
" +
        "
2	3
"),
        ut = new UT(table);
    var rows = table.rows,
        cell = rows[1].cells[1],
        cell1 = ut.getHSideCell(cell),
        cell2 = ut.getHSideCell(cell,true);
    equal(cell1,rows[1].cells[0],"左边单元格");
    equal(cell2,null,"位于右边缘的单元格无右邻居单元格");
    equal(ut.getHSideCell(rows[0][0]),null,"位于左边缘的单元格无左邻居单元格");
});

test("getVSideCell",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);
    var rows = table.rows,
        cell = rows[1].cells[1],
        cell1 = ut.getVSideCell(cell),
        cell2 = ut.getVSideCell(cell,true),
        cell3 = ut.getVSideCell(cell,true,true);
    equal(cell1,rows[0].cells[2],"上边单元格");
    equal(cell2,null,"位于下边缘的单元格无下邻居单元格");
    equal(cell3,null,"位于左边缘的单元格无左邻居单元格");
});
test("setCellContent",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[0];
    ut.setCellContent(cell,"这是测试内容");
    equal(cell.innerHTML,"这是测试内容","设置了正确的内容");
    ut.setCellContent(cell);
    equal(cell.innerHTML,browser.ie ? domUtils.fillChar : "
");
});

test("cloneCell",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);

    var cell = ut.cloneCell(table.rows[0].cells[0]);
    equal(cell.rowSpan,2,"clone了一个2行一列的单元格");
    equal(cell.style.borderTopColor,"green","上边框的颜色将会被下边框取代");
    cell = ut.cloneCell(table.rows[0].cells[0],true);
    ok(cell.rowSpan,1,"忽略被合并单元格时将会充值单元格的rowspan和colspan为1")
});

test("getCellsRange、getCells",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);
    var range = ut.getCellsRange(table.rows[0].cells[1],table.rows[1].cells[0]);
    ok(range.beginRowIndex===0 && range.beginColIndex===1 && range.endRowIndex===1 && range.endColIndex===1,"获取到range")

    var cells = ut.getCells(range);
    ok(cells.length ==2,"获取到2个单元格");
    ok(cells[0] == table.rows[0].cells[1],"第一个单元格存在");
});

test("insertRow、deleterRow",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);

    var cellPrototype = document.createElement("td");
    cellPrototype.innerHTML = "aa";
    cellPrototype.setAttribute("vAlign","top");
    ut.insertRow(2,cellPrototype);
    ok(table.rows.length ===3,"行数变成3行");
    ok(table.rows[2].cells[0].getAttribute("vAlign") =="top","新插入的单元格中包含原型单元格中的属性");

});

test("mergeRight,mergeDown",function(){
    var table = getTable("
1	2	3	4	5	6
" +
                         "
2	3	5	6
"+
                         "
2	3	4	5	6
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[1];
    ut.mergeDown(cell);
    ok(cell.rowSpan===2,"向下合并成功");

    ut.mergeDown(cell);
    ok(cell.rowSpan===3,"向下合并成功");

    cell = cell.previousSibling;
    ut.mergeRight(cell);
    ok(cell.rowSpan===3 && cell.colSpan ===2,"向右合并成功");

    equal(cell.parentNode.rowIndex,0,"合并到了正确的位置" )
});
test("split",function(){
    var table = getTable("
1	2	3	4	6	7
" +
            "
2	3	6	7
"+
            "
2	3	4	5	6	7
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[0],
        num = table.getElementsByTagName("td").length;
    ut.splitToCells(cell);
    ok(cell.rowSpan==1&&cell.colSpan==1,"单元格被成功拆分");

    var newNum = table.getElementsByTagName("td").length;
    ok(num+2 ==newNum,"单元格数量增加了2个");

    cell = table.rows[0].cells[3];
    ut.splitToCols(cell);
    ok(cell.colSpan===1 && cell.rowSpan==2 ,"被拆分成了2列");

});

<commit_msg>table.core<commit_after>/**
 * Created with JetBrains PhpStorm.
 * User: taoqili
 * Date: 13-2-21
 * Time: 下午1:31
 * To change this template use File | Settings | File Templates.
 */
function getTable(str) {
    var div = document.getElementById("testTable");
    if(!div){
        div = document.createElement("div");
        div.id = "testTable";
        document.body.appendChild(div);
    }
    div.innerHTML = "
" + str + "
";
    return div.firstChild;
}
UT = UE.UETable;
test("create UETable",function(){
    var table = getTable("
ddd
"),
        ut = new UT(table);
    ok(ut.table === table,"UT对象创建成功");
    ok(ut.colsNum == 1 && ut.rowsNum == 1,"单元格行、列数为1");
});

test("getMaxRows",function(){
    var table = getTable("
1	2	3
" +
                         "
1	2	3
"),
        ut = new UT(table);
    var maxRows = ut.getMaxRows();
    equal(maxRows,2,"最大行数为2");
    table = getTable("
1	2	3
" +
                     "
2
");
    ut = new UT(table);
    maxRows = ut.getMaxRows();
    equal(maxRows,3,"最大行数为3");
});
test("getMaxCols",function(){
    var table = getTable("
1	2	3
" +
                         "
1	2	3
"),
        ut = new UT(table);
    var maxCols = ut.getMaxCols();
    equal(maxCols,3,"最大列数为3");

    table = getTable("
1	2	3
" +
        "
2
");
    ut = new UT(table);
    maxCols = ut.getMaxCols();
    equal(maxCols,6,"最大列数为6");
});

test("getSameEndPosCells",function(){
    var table = getTable("
1	2	3
" +
                         "
2	3
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[0],
        cells1 = ut.getSameEndPosCells(cell,"x"),
        cells2 = ut.getSameEndPosCells(cell,"y");
    ok(cells1.length == 1, "获取到同样X轴结尾位置的cell1个");
    ok(cells2.length == 2, "获取到同样Y轴结尾位置的cell2个");
});

test("getHSideCell",function(){
    var table = getTable("
1	2	3
" +
        "
2	3
"),
        ut = new UT(table);
    var rows = table.rows,
        cell = rows[1].cells[1],
        cell1 = ut.getHSideCell(cell),
        cell2 = ut.getHSideCell(cell,true);
    equal(cell1,rows[1].cells[0],"左边单元格");
    equal(cell2,null,"位于右边缘的单元格无右邻居单元格");
    equal(ut.getHSideCell(rows[0][0]),null,"位于左边缘的单元格无左邻居单元格");
});

test("getVSideCell",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);
    var rows = table.rows,
        cell = rows[1].cells[1],
        cell1 = ut.getVSideCell(cell),
        cell2 = ut.getVSideCell(cell,true),
        cell3 = ut.getVSideCell(cell,true,true);
    equal(cell1,rows[0].cells[2],"上边单元格");
    equal(cell2,null,"位于下边缘的单元格无下邻居单元格");
    equal(cell3,null,"位于左边缘的单元格无左邻居单元格");
});
test("setCellContent",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[0];
    ut.setCellContent(cell,"这是测试内容");
    equal(cell.innerHTML,"这是测试内容","设置了正确的内容");
    ut.setCellContent(cell);
    equal(cell.innerHTML,browser.ie ? domUtils.fillChar : "
");
});

test("cloneCell",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);

    var cell = ut.cloneCell(table.rows[0].cells[0]);
    equal(cell.rowSpan,2,"clone了一个2行一列的单元格");
    equal(cell.style.borderTopColor,"green","上边框的颜色将会被下边框取代");
    cell = ut.cloneCell(table.rows[0].cells[0],true);
    ok(cell.rowSpan,1,"忽略被合并单元格时将会充值单元格的rowspan和colspan为1")
});

test("getCellsRange、getCells",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);
    var range = ut.getCellsRange(table.rows[0].cells[1],table.rows[1].cells[0]);
    ok(range.beginRowIndex===0 && range.beginColIndex===1 && range.endRowIndex===1 && range.endColIndex===1,"获取到range")

    var cells = ut.getCells(range);
    ok(cells.length ==2,"获取到2个单元格");
    ok(cells[0] == table.rows[0].cells[1],"第一个单元格存在");
});

test("insertRow、deleterRow",function(){
    var table = getTable("
1	2	3
" +
            "
2	3
"),
        ut = new UT(table);

    var cellPrototype = document.createElement("td");
    cellPrototype.innerHTML = "aa";
    cellPrototype.setAttribute("vAlign","top");
    ut.insertRow(2,cellPrototype);
    ok(table.rows.length ===3,"行数变成3行");
    ok(table.rows[2].cells[0].getAttribute("vAlign") =="top","新插入的单元格中包含原型单元格中的属性");

});

test("mergeRight,mergeDown",function(){
    var table = getTable("
1	2	3	4	5	6
" +
                         "
2	3	5	6
"+
                         "
2	3	4	5	6
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[1];
    ut.mergeDown(cell);
    ok(cell.rowSpan===2,"向下合并成功");

    ut.mergeDown(cell);
    ok(cell.rowSpan===3,"向下合并成功");

    cell = cell.previousSibling;
    ut.mergeRight(cell);
    ok(cell.rowSpan===3 && cell.colSpan ===2,"向右合并成功");

    equal(cell.parentNode.rowIndex,0,"合并到了正确的位置" )
});
test("split",function(){
    var table = getTable("
1	2	3	4	6	7
" +
            "
2	3	6	7
"+
            "
2	3	4	5	6	7
"),
        ut = new UT(table);
    var cell = table.rows[0].cells[0],
        num = table.getElementsByTagName("td").length;
    ut.splitToCells(cell);
    ok(cell.rowSpan==1&&cell.colSpan==1,"单元格被成功拆分");

    var newNum = table.getElementsByTagName("td").length;
    ok(num+2 ==newNum,"单元格数量增加了2个");

    cell = table.rows[0].cells[3];
    ut.splitToCols(cell);
    ok(cell.colSpan===1 && cell.rowSpan==2 ,"被拆分成了2列");

});

test("selectRow",function(){
    var table = getTable("
1	2	3	4	6	7
" +
            "
2	3	6	7
"+
            "
2	3	4	5	6	7
"),
        ut = new UT(table);
    ut.selectRow(1);
    equal(ut.selectedTds.length,table.getElementsByTagName("td").length,"选中了所有单元格")
    var cells = table.rows[1].cells,
        flag = false;
    utils.each(cells,function(cell){
        if(cell.className==""){
            flag = true;
        }
    });
    ok(!flag,"所有单元格都被选中");
    ok(ut.cellsRange.beginRowIndex===0,"cellsRange正确");

});
test("selectTable",function(){
    var table = getTable("
1	2	3	4	6	7
" +
            "
2	3	6	7
"+
            "
2	3	4	5	6	7
"),
        ut = new UT(table);
    ut.selectTable();
    ok(ut.selectedTds.length === table.getElementsByTagName("td").length,"选中了整个表格")

});

<|endoftext|>


<commit_before>//Hints for... JSHints
/*global Em */
/*global DS */
/*global console */
/*global Handlebars */
/*global confirm */

/*
Good Ember example:
 Nested routes: http://jsfiddle.net/dWcUp/171/
 CRUD Example: http://www.embersherpa.com/articles/crud-example-app-without-ember-data/

 Great blog example vid (source code in links) https://www.youtube.com/watch?v=Ga99hMi7wfY

Helpful websites:
 http://www.embersherpa.com/

*/

var App = Em.Application.create({
    LOG_TRANSITIONS: true//,
    //LOG_VIEW_LOOKUPS: true,
    //LOG_ACTIVE_GENERATION: true,
    //LOG_TRANSITIONS_INTERNAL: true,
    //LOG_BINDINGS: true
});

//routers
App.Router.map(function(){ //map URLs to controllers/templates
   this.resource('contacts',{path: '/'}, function(){
       this.resource('contact', {path: 'contact/:contact_id'});
       this.route('edit', {path: 'contact/:contact_id/edit'});
       this.route('new', {path: 'contact/new'});
   });
});

//define routes
App.ContactsRoute = Em.Route.extend({
    model: function(){
        return this.store.findAll(App.Contact);
    }
});
/*
App.ContactRoute = Em.Route.extend({
    model: function(params){
        return this.store.find(App.Contact, params.contact_id);
    }
});

App.ContactsEditRoute = Em.Route.extend({
    model: function(params){
        return this.store.find(App.Contact, params.contact_id);
    }
});
*/

//controllers
App.ContactController = Em.ObjectController.extend({
    needs: "contact",
    actions: {
        edit: function (params) {
            var model = this.store.find(App.Contact, params.id);
            this.transitionToRoute('contacts.edit', model);
        },
        delete: function(model){
            if(confirm('Are you sure?')){
                model.deleteRecord(App.Contact);
                this.transitionToRoute('contacts');
            }
        }
    },
    formattedDate: function() {
        var date = this.get('birthDate');

        if(date)
            return moment(date).format('MM-DD-YYYY');

        return null;

    }.property('birthDate')
});

App.ContactsNewController = Em.ObjectController.extend({
    actions:{
        save: function(){
            debugger;
            var nextId = parseInt(App.Contact.FIXTURES.sort(function(a,b) { return parseInt(a.id) > parseInt(b.id); })[App.Contact.FIXTURES.length-1].id) + 1;
            var contact = this.store.createRecord('contact', {id: nextId, firstName: this.get('firstName')});
            this.transitionToRoute('contact', contact);
        }
    },
    firstName: '',
    id: 0
});

App.ContactsController = Em.ArrayController.extend({
    sortProperties: ['fullName']
});

//models
//setup the store.  we are using the fixture adapter for testing
//other options exist, including the RESTAdapter
App.ApplicationAdapter = DS.FixtureAdapter.extend();
/*
App.Store = DS.Store.extend({
    adapter: DS.FixtureAdapter.create()
});
*/
App.Contact = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName: DS.attr('string'),
    phone: DS.attr('string'),
    email: DS.attr('string'),
    birthDate: DS.attr('date', {defaultValue: null}),
    fullName: function(){
        return this.get('lastName') + ', ' + this.get('firstName');
    }.property('firstName', 'lastName')//computed property
});

//fixture data
App.Contact.FIXTURES = [
  {
    id: 0,
    firstName: 'Paul',
    lastName: 'McCartney',
    email: 'pDiddy43234@contoso.com',
    phone: '555-232-1111',
    birthDate: new Date(1940, 10, 9)
},{
    id: 1,
    firstName: 'John',
    lastName: 'Lennon',
    email: 'biggerThanJesus@contoso.com',
    phone: '555-232-2222',
    birthDate: new Date(1941, 10, 9)

    },{
    id: 2,
    firstName: 'Ringo',
    lastName: 'Starr',
    email: 'starr@contoso.com',
    phone: '555-232-3333',
    birthDate: new Date(1942, 10, 9)
    },{
    id: 3,
    firstName: 'George',
    lastName: 'Harrison',
    email: 'george@contoso.com',
    phone: '555-232-4444',
    birthDate: new Date(1943, 10, 9)
    }
];

//Helpers
/*Ember.HandleBars.registerBoundHelper('date', function(date){
    return moment(date).format('MMM Do');
});*/

Handlebars.registerHelper("debug", function(optionalValue) {
    console.log("Current Context");
    console.log("====================");
    console.log(this);

    if (optionalValue) {
        console.log("Value");
        console.log("====================");
        console.log(optionalValue);
    }
});
<commit_msg>finish "new contact"<commit_after>//Hints for... JSHints
/*global Em */
/*global DS */
/*global console */
/*global Handlebars */
/*global confirm */

/*
Good Ember example:
 Nested routes: http://jsfiddle.net/dWcUp/171/
 CRUD Example: http://www.embersherpa.com/articles/crud-example-app-without-ember-data/

 Great blog example vid (source code in links) https://www.youtube.com/watch?v=Ga99hMi7wfY

Helpful websites:
 http://www.embersherpa.com/

*/

var App = Em.Application.create({
    LOG_TRANSITIONS: true//,
    //LOG_VIEW_LOOKUPS: true,
    //LOG_ACTIVE_GENERATION: true,
    //LOG_TRANSITIONS_INTERNAL: true,
    //LOG_BINDINGS: true
});

//routers
App.Router.map(function(){ //map URLs to controllers/templates
   this.resource('contacts',{path: '/'}, function(){
       this.resource('contact', {path: 'contact/:contact_id'});
       this.route('edit', {path: 'contact/:contact_id/edit'});
       this.route('new', {path: 'contact/new'});
   });
});

//define routes
App.ContactsRoute = Em.Route.extend({
    model: function(){
        return this.store.findAll(App.Contact);
    }
});
/*
App.ContactRoute = Em.Route.extend({
    model: function(params){
        return this.store.find(App.Contact, params.contact_id);
    }
});

App.ContactsEditRoute = Em.Route.extend({
    model: function(params){
        return this.store.find(App.Contact, params.contact_id);
    }
});
*/
App.ContactsNewRoute = Em.Route.extend({
    model: function(){
        return {id: 0, firstName: '', lastName: '', email: '', phone:'', birthDate:''};
    }
});

//controllers
App.ContactController = Em.ObjectController.extend({
    needs: "contact",
    actions: {
        edit: function (params) {
            var model = this.store.find(App.Contact, params.id);
            this.transitionToRoute('contacts.edit', model);
        },
        delete: function(model){
            if(confirm('Are you sure?')){
                model.deleteRecord(App.Contact);
                this.transitionToRoute('contacts');
            }
        }
    },
    formattedDate: function() {
        var date = this.get('birthDate');

        if(date)
            return moment(date).format('MM-DD-YYYY');

        return null;

    }.property('birthDate')
});

App.ContactsNewController = Em.ObjectController.extend({
    actions:{
        save: function(){
            var nextId = parseInt(App.Contact.FIXTURES.sort(function(a,b) { return parseInt(a.id) > parseInt(b.id); })[App.Contact.FIXTURES.length-1].id) + 1;
            var contact = this.store.createRecord('contact',
                {
                    id: nextId,
                    firstName: this.get('firstName'),
                    lastName: this.get('lastName'),
                    email: this.get('email'),
                    phone: this.get('phone'),
                    birthDate: this.get('birthDate')
                });
            this.transitionToRoute('contact', contact);
        }
    }
});

App.ContactsController = Em.ArrayController.extend({
    sortProperties: ['fullName']
});

App.ContactsEditController = Em.ObjectController.extend({
    actions:{
        save: function(){
            this.transitionToRoute('contact', this.model);
        }
    }
});
//models
//setup the store.  we are using the fixture adapter for testing
//other options exist, including the RESTAdapter
App.ApplicationAdapter = DS.FixtureAdapter.extend();
/*
App.Store = DS.Store.extend({
    adapter: DS.FixtureAdapter.create()
});
*/
App.Contact = DS.Model.extend({
    firstName: DS.attr('string'),
    lastName: DS.attr('string'),
    phone: DS.attr('string'),
    email: DS.attr('string'),
    birthDate: DS.attr('date', {defaultValue: null}),
    fullName: function(){
        return this.get('lastName') + ', ' + this.get('firstName');
    }.property('firstName', 'lastName')//computed property
});

//fixture data
App.Contact.FIXTURES = [
  {
    id: 0,
    firstName: 'Paul',
    lastName: 'McCartney',
    email: 'pDiddy43234@contoso.com',
    phone: '555-232-1111',
    birthDate: new Date(1940, 10, 9)
},{
    id: 1,
    firstName: 'John',
    lastName: 'Lennon',
    email: 'biggerThanJesus@contoso.com',
    phone: '555-232-2222',
    birthDate: new Date(1941, 10, 9)

    },{
    id: 2,
    firstName: 'Ringo',
    lastName: 'Starr',
    email: 'starr@contoso.com',
    phone: '555-232-3333',
    birthDate: new Date(1942, 10, 9)
    },{
    id: 3,
    firstName: 'George',
    lastName: 'Harrison',
    email: 'george@contoso.com',
    phone: '555-232-4444',
    birthDate: new Date(1943, 10, 9)
    }
];

//Helpers
/*Ember.HandleBars.registerBoundHelper('date', function(date){
    return moment(date).format('MMM Do');
});*/

Handlebars.registerHelper("debug", function(optionalValue) {
    console.log("Current Context");
    console.log("====================");
    console.log(this);

    if (optionalValue) {
        console.log("Value");
        console.log("====================");
        console.log(optionalValue);
    }
});
<|endoftext|>