<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * @fileoverview
 *
 * Provides unified configuration for all features.
 *
 * This is a custom shindig library that has not yet been submitted for
 * standardization. It is designed to make developing of features for the
 * opensocial / gadgets platforms easier and is intended as a supplemental
 * tool to Shindig's standardized feature loading mechanism.
 *
 * Usage:
 * First, you must register a component that needs configuration:
 *

 *   var config = {
 *     name : gadgets.config.NonEmptyStringValidator,
 *     url : new gadgets.config.RegExValidator(/.+%mySpecialValue%.+/)
 *   };
 *   gadgets.config.register("my-feature", config, myCallback);
 *

 *
 * This will register a component named "my-feature" that expects input config
 * containing a "name" field with a value that is a non-empty string, and a
 * "url" field with a value that matches the given regular expression.
 *
 * When gadgets.config.init is invoked by the container, it will automatically
 * validate your registered configuration and will throw an exception if
 * the provided configuration does not match what was required.
 *
 * Your callback will be invoked by passing all configuration data passed to
 * gadgets.config.init, which allows you to optionally inspect configuration
 * from other features, if present.
 *
 * Note that the container may optionally bypass configuration validation for
 * performance reasons. This does not mean that you should duplicate validation
 * code, it simply means that validation will likely only be performed in debug
 * builds, and you should assume that production builds always have valid
 * configuration.
 */

var gadgets = gadgets || {};

gadgets.config = function() {
  var components = {};

  return {
    /**
     * Registers a configurable component and its configuration parameters.
     *
     * @param {String} component The name of the component to register. Should
     *     be the same as the fully qualified name of the <Require> feature or
     *     the fully qualified javascript object reference (e.g. gadgets.io).
     * @param {Object} opt_validators Mapping of option name to validation
     *     functions that take the form function(data) {return isValid(data);}
     * @param {Function} opt_callback A function to be invoked when a
     *     configuration is registered. If passed, this function will be invoked
     *     immediately after a call to init has been made. Do not assume that
     *     dependent libraries have been configured until after init is
     *     complete. If you rely on this, it is better to defer calling
     *     dependent libraries until you can be sure that configuration is
     *     complete. Takes the form function(config), where config will be
     *     all registered config data for all components. This allows your
     *     component to read configuration from other components.
     * @throws {Error} If the component has already been registered.
     */
    register: function(component, opt_validators, opt_callback) {
      if (components[component]) {
        throw new Error('Component "' + component + '" is already registered.');
      }
      components[component] = {
        validators: opt_validators || {},
        callback: opt_callback
      };
    },

    /**
     * Retrieves configuration data on demand.
     *
     * @param {String} opt_component The component to fetch. If not provided
     *     all configuration will be returned.
     * @return {Object} The requested configuration.
     * @throws {Error} If the given component has not been registered
     */
    get: function(opt_component) {
      if (opt_component) {
        if (!components[opt_component]) {
          throw new Error('Component "' + opt_component + '" not registered.');
        }
        return configuration[opt_component] || {};
      }
      return configuration;
    },

    /**
     * Initializes the configuration.
     *
     * @param {Object} config The full set of configuration data.
     * @param {Boolean} opt_noValidation True if you want to skip validation.
     * @throws {Error} If there is a configuration error.
     */
    init: function(config, opt_noValidation) {
      configuration = config;
      for (var name in components) if (components.hasOwnProperty(name)) {
        var component = components[name],
            conf = config[name],
            validators = component.validators;
        if (!opt_noValidation) {
          for (var v in validators) if (validators.hasOwnProperty(v)) {
            if (!validators[v](conf[v])) {
              throw new Error('Invalid config value "' + conf[v] +
                  '" for parameter "' + v + '" in component "' +
                  name + '"');
            }
          }
        }
        if (component.callback) {
          component.callback(config);
        }
      }
    },

    // Standard validators go here.

    /**
     * Ensures that data is one of a fixed set of items.
     * @param {Array.<String>} list The list of valid values.
     * Also supports argument sytax: EnumValidator("Dog", "Cat", "Fish");
     */
    EnumValidator: function(list) {
      var listItems = [];
      if (arguments.length > 1) {
        for (var i = 0, arg; arg = arguments[i]; ++i) {
          listItems.push(arg);
        }
      } else {
        listItems = list;
      }
      return function(data) {
        for (var i = 0, test; test = listItems[i]; ++i) {
          if (data === listItems[i]) {
            return true;
          }
        }
      }
      return false;
    },

    /**
     * Tests the value against a regular expression.
     */
    RegExValidator: function(re) {
      return function(data) {
        return re.test(data);
      }
    },

    /**
     * Validates that a value was provided.
     */
    ExistsValidator: function(data) {
      return typeof data !== "undefined";
    },

    /**
     * Validates that a value is a non-empty string.
     */
    NonEmptyStringValidator: function(data) {
      return typeof data === "string" && data.length > 0
    },

    /**
     * Validates that the value is a boolean.
     */
    BooleanValidator: function(data) {
      return !!data;
    },

    /**
     * Similar to the ECMAScript4 virtual typing system, ensures that
     * whatever object was passed in is "like" the existing object.
     * Doesn't actually do type validation though, but instead relies
     * on other validators.
     *
     * example:
     *
     *  var validator = new gadgets.config.LikeValidator(
     *    "booleanField" : gadgets.config.BooleanValidator,
     *    "regexField" : new gadgets.config.RegExValidator(/foo.+/);
     *  );
     *
     * This can be used recursively as well to validate sub-objects.
     *
     * @param {Object} test The object to test against.
     */
    LikeValidator : function(test) {
      return function(data) {
        for (var member in test) {
          var t = test[member];
          if (!t(data[member])) {
            return false;
          }
        }
        return true;
      };
    }
  };
}();<commit_msg>Fixed BooleanValidator to actually validate that the data was a boolean rather than validating that it was true.<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

/**
 * @fileoverview
 *
 * Provides unified configuration for all features.
 *
 * This is a custom shindig library that has not yet been submitted for
 * standardization. It is designed to make developing of features for the
 * opensocial / gadgets platforms easier and is intended as a supplemental
 * tool to Shindig's standardized feature loading mechanism.
 *
 * Usage:
 * First, you must register a component that needs configuration:
 *

 *   var config = {
 *     name : gadgets.config.NonEmptyStringValidator,
 *     url : new gadgets.config.RegExValidator(/.+%mySpecialValue%.+/)
 *   };
 *   gadgets.config.register("my-feature", config, myCallback);
 *

 *
 * This will register a component named "my-feature" that expects input config
 * containing a "name" field with a value that is a non-empty string, and a
 * "url" field with a value that matches the given regular expression.
 *
 * When gadgets.config.init is invoked by the container, it will automatically
 * validate your registered configuration and will throw an exception if
 * the provided configuration does not match what was required.
 *
 * Your callback will be invoked by passing all configuration data passed to
 * gadgets.config.init, which allows you to optionally inspect configuration
 * from other features, if present.
 *
 * Note that the container may optionally bypass configuration validation for
 * performance reasons. This does not mean that you should duplicate validation
 * code, it simply means that validation will likely only be performed in debug
 * builds, and you should assume that production builds always have valid
 * configuration.
 */

var gadgets = gadgets || {};

gadgets.config = function() {
  var components = {};

  return {
    /**
     * Registers a configurable component and its configuration parameters.
     *
     * @param {String} component The name of the component to register. Should
     *     be the same as the fully qualified name of the <Require> feature or
     *     the fully qualified javascript object reference (e.g. gadgets.io).
     * @param {Object} opt_validators Mapping of option name to validation
     *     functions that take the form function(data) {return isValid(data);}
     * @param {Function} opt_callback A function to be invoked when a
     *     configuration is registered. If passed, this function will be invoked
     *     immediately after a call to init has been made. Do not assume that
     *     dependent libraries have been configured until after init is
     *     complete. If you rely on this, it is better to defer calling
     *     dependent libraries until you can be sure that configuration is
     *     complete. Takes the form function(config), where config will be
     *     all registered config data for all components. This allows your
     *     component to read configuration from other components.
     * @throws {Error} If the component has already been registered.
     */
    register: function(component, opt_validators, opt_callback) {
      if (components[component]) {
        throw new Error('Component "' + component + '" is already registered.');
      }
      components[component] = {
        validators: opt_validators || {},
        callback: opt_callback
      };
    },

    /**
     * Retrieves configuration data on demand.
     *
     * @param {String} opt_component The component to fetch. If not provided
     *     all configuration will be returned.
     * @return {Object} The requested configuration.
     * @throws {Error} If the given component has not been registered
     */
    get: function(opt_component) {
      if (opt_component) {
        if (!components[opt_component]) {
          throw new Error('Component "' + opt_component + '" not registered.');
        }
        return configuration[opt_component] || {};
      }
      return configuration;
    },

    /**
     * Initializes the configuration.
     *
     * @param {Object} config The full set of configuration data.
     * @param {Boolean} opt_noValidation True if you want to skip validation.
     * @throws {Error} If there is a configuration error.
     */
    init: function(config, opt_noValidation) {
      configuration = config;
      for (var name in components) if (components.hasOwnProperty(name)) {
        var component = components[name],
            conf = config[name],
            validators = component.validators;
        if (!opt_noValidation) {
          for (var v in validators) if (validators.hasOwnProperty(v)) {
            if (!validators[v](conf[v])) {
              throw new Error('Invalid config value "' + conf[v] +
                  '" for parameter "' + v + '" in component "' +
                  name + '"');
            }
          }
        }
        if (component.callback) {
          component.callback(config);
        }
      }
    },

    // Standard validators go here.

    /**
     * Ensures that data is one of a fixed set of items.
     * @param {Array.<String>} list The list of valid values.
     * Also supports argument sytax: EnumValidator("Dog", "Cat", "Fish");
     */
    EnumValidator: function(list) {
      var listItems = [];
      if (arguments.length > 1) {
        for (var i = 0, arg; arg = arguments[i]; ++i) {
          listItems.push(arg);
        }
      } else {
        listItems = list;
      }
      return function(data) {
        for (var i = 0, test; test = listItems[i]; ++i) {
          if (data === listItems[i]) {
            return true;
          }
        }
      }
      return false;
    },

    /**
     * Tests the value against a regular expression.
     */
    RegExValidator: function(re) {
      return function(data) {
        return re.test(data);
      }
    },

    /**
     * Validates that a value was provided.
     */
    ExistsValidator: function(data) {
      return typeof data !== "undefined";
    },

    /**
     * Validates that a value is a non-empty string.
     */
    NonEmptyStringValidator: function(data) {
      return typeof data === "string" && data.length > 0
    },

    /**
     * Validates that the value is a boolean.
     */
    BooleanValidator: function(data) {
      return typeof data === "boolean";
    },

    /**
     * Similar to the ECMAScript4 virtual typing system, ensures that
     * whatever object was passed in is "like" the existing object.
     * Doesn't actually do type validation though, but instead relies
     * on other validators.
     *
     * example:
     *
     *  var validator = new gadgets.config.LikeValidator(
     *    "booleanField" : gadgets.config.BooleanValidator,
     *    "regexField" : new gadgets.config.RegExValidator(/foo.+/);
     *  );
     *
     * This can be used recursively as well to validate sub-objects.
     *
     * @param {Object} test The object to test against.
     */
    LikeValidator : function(test) {
      return function(data) {
        for (var member in test) {
          var t = test[member];
          if (!t(data[member])) {
            return false;
          }
        }
        return true;
      };
    }
  };
}();
<|endoftext|>


<commit_before>import { Actions } from 'flummox';
import request from 'superagent-bluebird-promise'

const API_BASENAME = "http://localhost:3000"

async function apiGetRequest(uri) {
  let response = await request
    .get(`${API_BASENAME}${uri}`)
    .withCredentials()
    .promise()
  return response.body
}

async function apiPostRequest(uri, payload) {
  let response = await request
    .post(`${API_BASENAME}${uri}`)
    .send(payload)
    .withCredentials()
    .promise()
  return response.body
}

export default class ApiActions extends Actions {
  async login() {
    return apiGetRequest('/logged-in')
  }
  async logout() {
    return apiGetRequest('/logout')
  }
  async getGame(id) {
    return apiGetRequest(`/games/${id}`)
  }
  async getGames() {
    return apiGetRequest('/games/all')
  }
  async newGame(payload) {
    return apiPostRequest('/games/new', payload)
  }
  async getEvent(id) {
    return apiGetRequest(`/events/${id}`)
  }
  async getEvents() {
    return apiGetRequest('/events/all')
  }
  async newEvent() {
    return apiGetRequest('/events/new')
  }
  async getUser(id) {
    return apiGetRequest(`/users/${id}`)
  }
  async getUsers() {
    return apiGetRequest('/users/all')
  }
  async newUser() {
    return apiGetRequest('/users/new')
  }
  async getChallenge(id) {
    return apiGetRequest(`/challenges/${id}`)
  }
  async getChallenges() {
    return apiGetRequest('/challenges/all')
  }
  async newChallenge() {
    return apiGetRequest('/challenges/new')
  }
}<commit_msg>Converted requests to new to post requests<commit_after>import { Actions } from 'flummox';
import request from 'superagent-bluebird-promise'

const API_BASENAME = "http://localhost:3000"

async function apiGetRequest(uri) {
  let response = await request
    .get(`${API_BASENAME}${uri}`)
    .withCredentials()
    .promise()
  return response.body
}

async function apiPostRequest(uri, payload) {
  let response = await request
    .post(`${API_BASENAME}${uri}`)
    .send(payload)
    .withCredentials()
    .promise()
  return response.body
}

export default class ApiActions extends Actions {
  async login() {
    return apiGetRequest('/logged-in')
  }
  async logout() {
    return apiGetRequest('/logout')
  }
  async getGame(id) {
    return apiGetRequest(`/games/${id}`)
  }
  async getGames() {
    return apiGetRequest('/games/all')
  }
  async newGame(payload) {
    return apiPostRequest('/games/new', payload)
  }
  async getEvent(id) {
    return apiGetRequest(`/events/${id}`)
  }
  async getEvents() {
    return apiGetRequest('/events/all')
  }
  async newEvent(payload) {
    return apiPostRequest('/events/new', payload)
  }
  async getUser(id) {
    return apiGetRequest(`/users/${id}`)
  }
  async getUsers() {
    return apiGetRequest('/users/all')
  }
  async newUser(payload) {
    return apiPostRequest('/users/new', payload)
  }
  async getChallenge(id) {
    return apiGetRequest(`/challenges/${id}`)
  }
  async getChallenges() {
    return apiGetRequest('/challenges/all')
  }
  async newChallenge(payload) {
    return apiGetRequest('/challenges/new', payload)
  }
}<|endoftext|>


<commit_before>var CONSTANTS = require('../constants.json');
var utils = require('../utils.js');
var bidfactory = require('../bidfactory.js');
var bidmanager = require('../bidmanager.js');
var adloader = require('../adloader');

/**
 * Adapter for requesting bids from Brightcom
 */
var BrightcomAdapter = function BrightcomAdapter() {

  // Set Brightcom Bidder URL
  var brightcomUrl = 'hb.iselephant.com/auc/ortb';

  // Define the bidder code
  var brightcomBidderCode = 'brightcom';

  // Define the callback function
  var brightcomCallbackFunction = 'window.$$PREBID_GLOBAL$$=window.$$PREBID_GLOBAL$$||window.parent.$$PREBID_GLOBAL$$||window.top.$$PREBID_GLOBAL$$;window.$$PREBID_GLOBAL$$.brightcomResponse';

  // Manage the requested and received ad units' codes, to know which are invalid (didn't return)
  var reqAdUnitsCode = [],
      resAdUnitsCode = [];

  function _callBids(params) {

    var bidRequests = params.bids || [];

    // Get page data
    var siteDomain = window.location.host;
    var sitePage = window.location.href;

    // Prepare impressions object
    var brightcomImps = [];

    // Prepare a variable for publisher id
    var pubId = '';

    // Go through the requests and build array of impressions
    utils._each(bidRequests, function(bid) {

      // Get impression details
      var tagId = utils.getBidIdParameter('tagId', bid.params);
      var ref = utils.getBidIdParameter('ref', bid.params);
      var adWidth=0;
      var adHeight=0;

      // If no publisher id is set, use the current
      if (pubId === '') {
        // Get the current publisher id (if it doesn't exist, it'll return '')
        pubId = utils.getBidIdParameter('pubId', bid.params);
      }

      // Brightcom supports only 1 size per impression
      // Check if the array contains 1 size or array of sizes
      if (bid.sizes.length === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') {
        // The array contains 1 size (the items are the values)
        adWidth = bid.sizes[0];
        adHeight = bid.sizes[1];
      } else {
        // The array contains array of sizes, use the first size
        adWidth = bid.sizes[0][0];
        adHeight = bid.sizes[0][1];
      }

      // Build the impression
      var imp = {
        id: utils.getUniqueIdentifierStr(),
        banner: {
          w: adWidth,
          h: adHeight
        },
        tagid: tagId
      };

      // If ref exists, create it (in the "ext" object)
      if (ref !== '') {
        imp.ext = {
          refoverride: ref
        };
      }

      // Add current impression to collection
      brightcomImps.push(imp);
      // Add mapping to current bid via impression id
      //bidmanager.pbCallbackMap[imp.id] = bid;

      // Add current ad unit's code to tracking
      reqAdUnitsCode.push(bid.placementCode);

    });

    // Build the bid request
    var brightcomBidReq = {
      id: utils.getUniqueIdentifierStr(),
      imp: brightcomImps,
      site:{
        publisher: {
          id: pubId
        },
        domain: siteDomain,
        page: sitePage
      }
    };

    // Add timeout data, if available
    var PREBID_TIMEOUT = PREBID_TIMEOUT || 0;
    var curTimeout = PREBID_TIMEOUT;
    if (curTimeout > 0) {
      brightcomBidReq.tmax = curTimeout;
    }

    // Define the bid request call URL
    var bidRequestCallUrl = 'https://' + brightcomUrl +
        '?callback=' + brightcomCallbackFunction +
        '&request=' + encodeURIComponent(JSON.stringify(brightcomBidReq));

    // Add the call to get the bid
    adloader.loadScript(bidRequestCallUrl);
  }

  //expose the callback to the global object:
  $$PREBID_GLOBAL$$.brightcomResponse = function(brightcomResponseObj) {

    var bid = {};

    // Make sure response is valid
    if (
        (brightcomResponseObj) && (brightcomResponseObj.id) &&
        (brightcomResponseObj.seatbid) && (brightcomResponseObj.seatbid.length !== 0) &&
        (brightcomResponseObj.seatbid[0].bid) && (brightcomResponseObj.seatbid[0].bid.length !== 0)
    ) {

      // Go through the received bids
      brightcomResponseObj.seatbid[0].bid.forEach( function(curBid) {

        // Get the bid request data
        var bidRequest = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'brightcom').bids[0]; // this assumes a single request only

        // Make sure the bid exists
        if (bidRequest) {

          var placementCode = bidRequest.placementCode;
          bidRequest.status = CONSTANTS.STATUS.GOOD;

          curBid.placementCode = placementCode;
          curBid.size = bidRequest.sizes;

          // Get the creative
          var responseCreative = curBid.adm;
          // Build the NURL element
          var responseNurl = '';
          // Build the ad to display:
          var responseAd = decodeURIComponent(responseCreative + responseNurl);

          // Create a valid bid
          bid = bidfactory.createBid(1);

          // Set the bid data
          bid.creative_id = curBid.Id;
          bid.bidderCode = brightcomBidderCode;
          bid.cpm = parseFloat(curBid.price);

          // Brightcom tag is in


<commit_before>stateMachine = TestCase("StateMachineBasics");

stateMachine.prototype.testNoState = function() {
	sm = new nitch.statemachine({});
	assertUndefined(sm.current);
}

stateMachine.prototype.testCurrentState = function() {
	sm = new nitch.statemachine({ initial: 'green' });

	assertEquals('green', sm.current);
}

stateMachine.prototype.testAvailableEvents = function() {
	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	]});

	assertFunction(sm.can);
	assertFunction(sm.cannot);

	assertFunction(sm.warn);
	assertFunction(sm.panic);
	assertFunction(sm.calm);
	assertFunction(sm.clear);
}

stateMachine.prototype.testCanFunctions = function() {
	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	]});

	assertTrue(sm.can('warn'));
	assertEquals('green', sm.current);
	assertFalse(sm.can('panic'));
	assertTrue(sm.cannot('calm'));
	assertFalse(sm.can('clear'));
}

stateMachine.prototype.testMoveStates = function() {
	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	]});

	sm.warn();
	assertEquals('yellow', sm.current);
	assertTrue(sm.is('yellow'));

	sm.panic();
	assertEquals('red', sm.current);

	sm.calm();
	assertEquals('yellow', sm.current);

	sm.clear();
	assertEquals('green', sm.current);
}

stateMachine.prototype.testOnStates = function() {
	var changestate = false;
	var onbefore = false;
	var onleave = false;
	var onenter = false;
	var onafter = false;

	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	  ],
	  callbacks: {
	  	onchangestate: function(event,from,to) { changestate = event + ' from ' + from + ' to ' + to; },
		onBeforewarn: function() { onbefore = true; },
		onLeaveyellow: function() { onleave = true; },
		onEnteryellow: function() { onenter = true; },
		onAfterwarn: function() { onafter = true; }
	  }
	});

	assertEquals('startup from none to green', changestate);
	assertEquals('green', sm.current);
	assertFalse(onbefore);
	assertFalse(onenter);
	assertFalse(onleave);
	assertFalse(onafter);

	sm.warn();
	assertEquals('warn from green to yellow', changestate);
	assertTrue(onbefore);
	assertTrue(onenter);
	sm.panic();
	assertTrue(onleave);
	assertTrue(onafter);

}<commit_msg>Fix test for onChangeState callback method change<commit_after>stateMachine = TestCase("StateMachineBasics");

stateMachine.prototype.testNoState = function() {
	sm = new nitch.statemachine({});
	assertUndefined(sm.current);
}

stateMachine.prototype.testCurrentState = function() {
	sm = new nitch.statemachine({ initial: 'green' });

	assertEquals('green', sm.current);
}

stateMachine.prototype.testAvailableEvents = function() {
	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	]});

	assertFunction(sm.can);
	assertFunction(sm.cannot);

	assertFunction(sm.warn);
	assertFunction(sm.panic);
	assertFunction(sm.calm);
	assertFunction(sm.clear);
}

stateMachine.prototype.testCanFunctions = function() {
	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	]});

	assertTrue(sm.can('warn'));
	assertEquals('green', sm.current);
	assertFalse(sm.can('panic'));
	assertTrue(sm.cannot('calm'));
	assertFalse(sm.can('clear'));
}

stateMachine.prototype.testMoveStates = function() {
	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	]});

	sm.warn();
	assertEquals('yellow', sm.current);
	assertTrue(sm.is('yellow'));

	sm.panic();
	assertEquals('red', sm.current);

	sm.calm();
	assertEquals('yellow', sm.current);

	sm.clear();
	assertEquals('green', sm.current);
}

stateMachine.prototype.testOnStates = function() {
	var changestate = false;
	var onbefore = false;
	var onleave = false;
	var onenter = false;
	var onafter = false;

	var sm = new nitch.statemachine({
	  initial: 'green',
	  events: [
		{ name: 'warn',  from: 'green',  to: 'yellow' },
		{ name: 'panic', from: 'yellow', to: 'red'    },
		{ name: 'calm',  from: 'red',    to: 'yellow' },
		{ name: 'clear', from: 'yellow', to: 'green'  }
	  ],
	  callbacks: {
	  	onChangeState: function(event,from,to) { changestate = event + ' from ' + from + ' to ' + to; },
		onBeforewarn: function() { onbefore = true; },
		onLeaveyellow: function() { onleave = true; },
		onEnteryellow: function() { onenter = true; },
		onAfterwarn: function() { onafter = true; }
	  }
	});

	assertEquals('startup from none to green', changestate);
	assertEquals('green', sm.current);
	assertFalse(onbefore);
	assertFalse(onenter);
	assertFalse(onleave);
	assertFalse(onafter);

	sm.warn();
	assertEquals('warn from green to yellow', changestate);
	assertTrue(onbefore);
	assertTrue(onenter);
	sm.panic();
	assertTrue(onleave);
	assertTrue(onafter);

}<|endoftext|>


<commit_before>import 'aframe';
import 'aframe-extras';
import 'aframe-forcegraph-component';

import Kapsule from 'kapsule';
import accessorFn from 'accessor-fn';

//

export default Kapsule({

  props: {
    width: { default: window.innerWidth, triggerUpdate: false, onChange(width, state) { if(state.container) state.container.style.width = width }},
    height: { default: window.innerHeight, triggerUpdate: false, onChange(height, state) { if(state.container) state.container.style.height = height }},
    jsonUrl: {},
    graphData: { default: { nodes: [], links: [] }},
    numDimensions: { default: 3 },
    dagMode: {},
    dagLevelDistance: {},
    dagNodeFilter: { default: () => true },
    onDagError: { default: undefined },
    backgroundColor: { default: '#002' },
    showNavInfo: { default: true },
    nodeRelSize: { default: 4 }, // volume per val unit
    nodeId: { default: 'id' },
    nodeLabel: { default: 'name' },
    nodeDesc: { default: 'desc' },
    onNodeHover: {},
    onNodeClick: {},
    nodeVal: { default: 'val' },
    nodeResolution: { default: 8 }, // how many slice segments in the sphere's circumference
    nodeVisibility: { default: true },
    nodeColor: { default: 'color' },
    nodeAutoColorBy: {},
    nodeOpacity: { default: 0.75 },
    nodeThreeObject: {},
    nodeThreeObjectExtend: { default: false },
    linkSource: { default: 'source' },
    linkTarget: { default: 'target' },
    linkLabel: { default: 'name' },
    linkDesc: { default: 'desc' },
    onLinkHover: {},
    onLinkClick: {},
    linkVisibility: { default: true },
    linkColor: { default: 'color' },
    linkAutoColorBy: {},
    linkOpacity: { default: 0.2 },
    linkWidth: { default: 0 },
    linkResolution: { default: 6 }, // how many radial segments in each line cylinder's geometry
    linkCurvature: { default: 0 },
    linkCurveRotation: { default: 0 },
    linkMaterial: {},
    linkThreeObject: {},
    linkThreeObjectExtend: { default: false },
    linkPositionUpdate: {},
    linkDirectionalArrowLength: { default: 0 },
    linkDirectionalArrowColor: {},
    linkDirectionalArrowRelPos: { default: 0.5 }, // value between 0<>1 indicating the relative pos along the (exposed) line
    linkDirectionalArrowResolution: { default: 8 }, // how many slice segments in the arrow's conic circumference
    linkDirectionalParticles: { default: 0 }, // animate photons travelling in the link direction
    linkDirectionalParticleSpeed: { default: 0.01 }, // in link length ratio per frame
    linkDirectionalParticleWidth: { default: 0.5 },
    linkDirectionalParticleColor: {},
    linkDirectionalParticleResolution: { default: 4 }, // how many slice segments in the particle sphere's circumference
    forceEngine: { default: 'd3' }, // d3 or ngraph
    d3AlphaMin: { default: 0 },
    d3AlphaDecay: { default: 0.0228 },
    d3VelocityDecay: { default: 0.4 },
    ngraphPhysics: {},
    warmupTicks: { default: 0 }, // how many times to tick the force engine at init before starting to render
    cooldownTicks: {},
    cooldownTime: { default: 15000 }, // ms
    onEngineTick: {},
    onEngineStop: {}
  },

  methods: {
    // pass-through methods
    ...Object.assign({}, ...[
      'getGraphBbox',
      'emitParticle',
      'd3Force',
      'd3ReheatSimulation',
      'refresh'
    ].map(method => ({
      [method]: function (state, ...args) {
        const aframeComp = state.forcegraph.components.forcegraph;
        const returnVal = aframeComp[method](...args);

        return returnVal === aframeComp
          ? this // chain based on this object, not the inner aframe component
          : returnVal;
      }
    }))),
    _destructor: function() {
      this.graphData({ nodes: [], links: [] });
    }
  },

  init(domNode, state) {
    // Wipe DOM
    domNode.innerHTML = '';

    state.container = document.createElement('div');
    domNode.appendChild(state.container);
    state.container.style.position = 'relative';
    state.container.style.width = state.width;
    state.container.style.height = state.height;

    // Add nav info section
    state.container.appendChild(state.navInfo = document.createElement('div'));
    state.navInfo.className = 'graph-nav-info';
    state.navInfo.textContent = 'Mouse drag: look, gamepad/arrow/wasd keys: move';

    // Create scene
    const scene = document.createElement('a-scene');
    scene.setAttribute('embedded', '');
    //scene.setAttribute('stats', null);
    state.container.appendChild(scene); // attach scene

    scene.appendChild(state.sky = document.createElement('a-sky'));
    state.sky.setAttribute('radius', 3000);

    // Setup mouse cursor and laser raycasting controls
    let mouseCursor;
    scene.appendChild(mouseCursor = document.createElement('a-entity'));
    mouseCursor.setAttribute('cursor', 'rayOrigin: mouse; mouseCursorStylesEnabled: true');
    mouseCursor.setAttribute('raycaster', 'objects: [forcegraph]');

    ['left', 'right'].forEach(hand => {
      let laser;
      scene.appendChild(laser = document.createElement('a-entity'));
      laser.setAttribute('laser-controls', `hand: ${hand}`);
      laser.setAttribute('raycaster', 'objects: [forcegraph]; lineColor: steelblue; lineOpacity: 0.85');
    });

    // Add camera
    let cameraG;
    scene.appendChild(cameraG = document.createElement('a-entity'));
    cameraG.setAttribute('position', '0 0 300');
    cameraG.setAttribute('movement-controls', 'fly: true; speed: 7');

    let camera;
    cameraG.appendChild(camera = document.createElement('a-entity'));
    camera.setAttribute('camera', '');
    camera.setAttribute('position', '0 0.001 0');
    camera.setAttribute('look-controls', 'reverseMouseDrag: false; pointerLockEnabled: false');

    // display cursor in middle of screen
    // let cursor;
    // camera.appendChild(cursor = document.createElement('a-cursor'));
    // cursor.setAttribute('color', 'lavender');
    // cursor.setAttribute('opacity', 0.5);
    // cursor.setAttribute('raycaster', 'objects: ----none----'); // disable cursor raycaster

    // Setup tooltip
    let tooltipEl;
    camera.appendChild(tooltipEl = document.createElement('a-text'));
    tooltipEl.setAttribute('position', '0 -0.3 -1');
    tooltipEl.setAttribute('width', 2);
    tooltipEl.setAttribute('align', 'center');
    tooltipEl.setAttribute('color', 'lavender');
    tooltipEl.setAttribute('value', '');

    // Setup sub-tooltip
    let subTooltipEl;
    camera.appendChild(subTooltipEl = document.createElement('a-text'));
    subTooltipEl.setAttribute('position', '0 -0.4 -1');
    subTooltipEl.setAttribute('width', 1.3);
    subTooltipEl.setAttribute('align', 'center');
    subTooltipEl.setAttribute('color', 'lavender');
    subTooltipEl.setAttribute('value', '');

    // Add forcegraph entity
    scene.appendChild(state.forcegraph = document.createElement('a-entity'));
    state.forcegraph.setAttribute('forcegraph', null);

    // update tooltips
    state.forcegraph.setAttribute('forcegraph', Object.assign(...['node', 'link'].map(t => {
      const cct = { node: 'Node', link: 'Link' }[t]; // camel-case version
      return {[`on${cct}Hover`]: (obj, prevObj) => {
        const label = obj ? accessorFn(state[`${t}Label`])(obj) || '' : '';
        const subLabel = obj ? accessorFn(state[`${t}Desc`])(obj) || '' : '';
        tooltipEl.setAttribute('value', label);
        subTooltipEl.setAttribute('value', subLabel);
        state[`on${cct}Hover`] && state[`on${cct}Hover`](obj, prevObj);
      }};
    })));
  },

  update(state, changedProps) {
    changedProps.hasOwnProperty('backgroundColor') && state.sky.setAttribute('color', state.backgroundColor);
    changedProps.hasOwnProperty('showNavInfo') && (state.navInfo.style.display = state.showNavInfo ? null : 'none');

    const passThroughProps = [
      'jsonUrl',
      'numDimensions',
      'dagMode',
      'dagLevelDistance',
      'dagNodeFilter',
      'onDagError',
      'nodeRelSize',
      'nodeId',
      'onNodeClick',
      'nodeVal',
      'nodeResolution',
      'nodeVisibility',
      'nodeColor',
      'nodeAutoColorBy',
      'nodeOpacity',
      'nodeThreeObject',
      'nodeThreeObjectExtend',
      'linkSource',
      'linkTarget',
      'onLinkClick',
      'linkVisibility',
      'linkColor',
      'linkAutoColorBy',
      'linkOpacity',
      'linkWidth',
      'linkResolution',
      'linkCurvature',
      'linkCurveRotation',
      'linkMaterial',
      'linkThreeObject',
      'linkThreeObjectExtend',
      'linkPositionUpdate',
      'linkDirectionalArrowLength',
      'linkDirectionalArrowColor',
      'linkDirectionalArrowRelPos',
      'linkDirectionalArrowResolution',
      'linkDirectionalParticles',
      'linkDirectionalParticleSpeed',
      'linkDirectionalParticleWidth',
      'linkDirectionalParticleColor',
      'linkDirectionalParticleResolution',
      'forceEngine',
      'd3AlphaMin',
      'd3AlphaDecay',
      'd3VelocityDecay',
      'ngraphPhysics',
      'warmupTicks',
      'cooldownTicks',
      'cooldownTime',
      'onEngineTick',
      'onEngineStop'
    ];

    const newProps = Object.assign({},
      ...Object.entries(state)
        .filter(([prop, val]) => changedProps.hasOwnProperty(prop) && passThroughProps.indexOf(prop) !== -1 && val !== undefined && val !== null)
        .map(([key, val]) => ({ [key]: val })),
      ...Object.entries(state.graphData)
        .map(([key, val]) => ({ [key]: val })) // pass nodes & links as separate props
    );

    state.forcegraph.setAttribute('forcegraph', newProps);
  }
});
<commit_msg>Attach laser-controls to camera rig<commit_after>import 'aframe';
import 'aframe-extras';
import 'aframe-forcegraph-component';

import Kapsule from 'kapsule';
import accessorFn from 'accessor-fn';

//

export default Kapsule({

  props: {
    width: { default: window.innerWidth, triggerUpdate: false, onChange(width, state) { if(state.container) state.container.style.width = width }},
    height: { default: window.innerHeight, triggerUpdate: false, onChange(height, state) { if(state.container) state.container.style.height = height }},
    jsonUrl: {},
    graphData: { default: { nodes: [], links: [] }},
    numDimensions: { default: 3 },
    dagMode: {},
    dagLevelDistance: {},
    dagNodeFilter: { default: () => true },
    onDagError: { default: undefined },
    backgroundColor: { default: '#002' },
    showNavInfo: { default: true },
    nodeRelSize: { default: 4 }, // volume per val unit
    nodeId: { default: 'id' },
    nodeLabel: { default: 'name' },
    nodeDesc: { default: 'desc' },
    onNodeHover: {},
    onNodeClick: {},
    nodeVal: { default: 'val' },
    nodeResolution: { default: 8 }, // how many slice segments in the sphere's circumference
    nodeVisibility: { default: true },
    nodeColor: { default: 'color' },
    nodeAutoColorBy: {},
    nodeOpacity: { default: 0.75 },
    nodeThreeObject: {},
    nodeThreeObjectExtend: { default: false },
    linkSource: { default: 'source' },
    linkTarget: { default: 'target' },
    linkLabel: { default: 'name' },
    linkDesc: { default: 'desc' },
    onLinkHover: {},
    onLinkClick: {},
    linkVisibility: { default: true },
    linkColor: { default: 'color' },
    linkAutoColorBy: {},
    linkOpacity: { default: 0.2 },
    linkWidth: { default: 0 },
    linkResolution: { default: 6 }, // how many radial segments in each line cylinder's geometry
    linkCurvature: { default: 0 },
    linkCurveRotation: { default: 0 },
    linkMaterial: {},
    linkThreeObject: {},
    linkThreeObjectExtend: { default: false },
    linkPositionUpdate: {},
    linkDirectionalArrowLength: { default: 0 },
    linkDirectionalArrowColor: {},
    linkDirectionalArrowRelPos: { default: 0.5 }, // value between 0<>1 indicating the relative pos along the (exposed) line
    linkDirectionalArrowResolution: { default: 8 }, // how many slice segments in the arrow's conic circumference
    linkDirectionalParticles: { default: 0 }, // animate photons travelling in the link direction
    linkDirectionalParticleSpeed: { default: 0.01 }, // in link length ratio per frame
    linkDirectionalParticleWidth: { default: 0.5 },
    linkDirectionalParticleColor: {},
    linkDirectionalParticleResolution: { default: 4 }, // how many slice segments in the particle sphere's circumference
    forceEngine: { default: 'd3' }, // d3 or ngraph
    d3AlphaMin: { default: 0 },
    d3AlphaDecay: { default: 0.0228 },
    d3VelocityDecay: { default: 0.4 },
    ngraphPhysics: {},
    warmupTicks: { default: 0 }, // how many times to tick the force engine at init before starting to render
    cooldownTicks: {},
    cooldownTime: { default: 15000 }, // ms
    onEngineTick: {},
    onEngineStop: {}
  },

  methods: {
    // pass-through methods
    ...Object.assign({}, ...[
      'getGraphBbox',
      'emitParticle',
      'd3Force',
      'd3ReheatSimulation',
      'refresh'
    ].map(method => ({
      [method]: function (state, ...args) {
        const aframeComp = state.forcegraph.components.forcegraph;
        const returnVal = aframeComp[method](...args);

        return returnVal === aframeComp
          ? this // chain based on this object, not the inner aframe component
          : returnVal;
      }
    }))),
    _destructor: function() {
      this.graphData({ nodes: [], links: [] });
    }
  },

  init(domNode, state) {
    // Wipe DOM
    domNode.innerHTML = '';

    state.container = document.createElement('div');
    domNode.appendChild(state.container);
    state.container.style.position = 'relative';
    state.container.style.width = state.width;
    state.container.style.height = state.height;

    // Add nav info section
    state.container.appendChild(state.navInfo = document.createElement('div'));
    state.navInfo.className = 'graph-nav-info';
    state.navInfo.textContent = 'Mouse drag: look, gamepad/arrow/wasd keys: move';

    // Create scene
    const scene = document.createElement('a-scene');
    scene.setAttribute('embedded', '');
    //scene.setAttribute('stats', null);

    scene.appendChild(state.sky = document.createElement('a-sky'));
    state.sky.setAttribute('radius', 3000);

    // Add camera
    let cameraG;
    scene.appendChild(cameraG = document.createElement('a-entity'));
    cameraG.setAttribute('position', '0 0 300');
    cameraG.setAttribute('movement-controls', 'fly: true; speed: 7');

    let camera;
    cameraG.appendChild(camera = document.createElement('a-entity'));
    camera.setAttribute('camera', '');
    camera.setAttribute('position', '0 0.001 0');
    camera.setAttribute('look-controls', 'reverseMouseDrag: false; pointerLockEnabled: false');

    // display cursor in middle of screen
    // let cursor;
    // camera.appendChild(cursor = document.createElement('a-cursor'));
    // cursor.setAttribute('color', 'lavender');
    // cursor.setAttribute('opacity', 0.5);
    // cursor.setAttribute('raycaster', 'objects: ----none----'); // disable cursor raycaster

    // Setup tooltip
    let tooltipEl;
    camera.appendChild(tooltipEl = document.createElement('a-text'));
    tooltipEl.setAttribute('position', '0 -0.3 -1');
    tooltipEl.setAttribute('width', 2);
    tooltipEl.setAttribute('align', 'center');
    tooltipEl.setAttribute('color', 'lavender');
    tooltipEl.setAttribute('value', '');

    // Setup sub-tooltip
    let subTooltipEl;
    camera.appendChild(subTooltipEl = document.createElement('a-text'));
    subTooltipEl.setAttribute('position', '0 -0.4 -1');
    subTooltipEl.setAttribute('width', 1.3);
    subTooltipEl.setAttribute('align', 'center');
    subTooltipEl.setAttribute('color', 'lavender');
    subTooltipEl.setAttribute('value', '');

    // Setup mouse cursor and laser raycasting controls
    let mouseCursor;
    scene.appendChild(mouseCursor = document.createElement('a-entity'));
    mouseCursor.setAttribute('cursor', 'rayOrigin: mouse; mouseCursorStylesEnabled: true');
    mouseCursor.setAttribute('raycaster', 'objects: [forcegraph]');

    ['left', 'right'].forEach(hand => {
      let laser;
      cameraG.appendChild(laser = document.createElement('a-entity'));
      laser.setAttribute('laser-controls', `hand: ${hand}`);
      laser.setAttribute('raycaster', 'objects: [forcegraph]; lineColor: steelblue; lineOpacity: 0.85');
    });

    // Add forcegraph entity
    scene.appendChild(state.forcegraph = document.createElement('a-entity'));
    state.forcegraph.setAttribute('forcegraph', null);

    // attach scene
    state.container.appendChild(scene);

    // update tooltips
    state.forcegraph.setAttribute('forcegraph', Object.assign(...['node', 'link'].map(t => {
      const cct = { node: 'Node', link: 'Link' }[t]; // camel-case version
      return {[`on${cct}Hover`]: (obj, prevObj) => {
        const label = obj ? accessorFn(state[`${t}Label`])(obj) || '' : '';
        const subLabel = obj ? accessorFn(state[`${t}Desc`])(obj) || '' : '';
        tooltipEl.setAttribute('value', label);
        subTooltipEl.setAttribute('value', subLabel);
        state[`on${cct}Hover`] && state[`on${cct}Hover`](obj, prevObj);
      }};
    })));
  },

  update(state, changedProps) {
    changedProps.hasOwnProperty('backgroundColor') && state.sky.setAttribute('color', state.backgroundColor);
    changedProps.hasOwnProperty('showNavInfo') && (state.navInfo.style.display = state.showNavInfo ? null : 'none');

    const passThroughProps = [
      'jsonUrl',
      'numDimensions',
      'dagMode',
      'dagLevelDistance',
      'dagNodeFilter',
      'onDagError',
      'nodeRelSize',
      'nodeId',
      'onNodeClick',
      'nodeVal',
      'nodeResolution',
      'nodeVisibility',
      'nodeColor',
      'nodeAutoColorBy',
      'nodeOpacity',
      'nodeThreeObject',
      'nodeThreeObjectExtend',
      'linkSource',
      'linkTarget',
      'onLinkClick',
      'linkVisibility',
      'linkColor',
      'linkAutoColorBy',
      'linkOpacity',
      'linkWidth',
      'linkResolution',
      'linkCurvature',
      'linkCurveRotation',
      'linkMaterial',
      'linkThreeObject',
      'linkThreeObjectExtend',
      'linkPositionUpdate',
      'linkDirectionalArrowLength',
      'linkDirectionalArrowColor',
      'linkDirectionalArrowRelPos',
      'linkDirectionalArrowResolution',
      'linkDirectionalParticles',
      'linkDirectionalParticleSpeed',
      'linkDirectionalParticleWidth',
      'linkDirectionalParticleColor',
      'linkDirectionalParticleResolution',
      'forceEngine',
      'd3AlphaMin',
      'd3AlphaDecay',
      'd3VelocityDecay',
      'ngraphPhysics',
      'warmupTicks',
      'cooldownTicks',
      'cooldownTime',
      'onEngineTick',
      'onEngineStop'
    ];

    const newProps = Object.assign({},
      ...Object.entries(state)
        .filter(([prop, val]) => changedProps.hasOwnProperty(prop) && passThroughProps.indexOf(prop) !== -1 && val !== undefined && val !== null)
        .map(([key, val]) => ({ [key]: val })),
      ...Object.entries(state.graphData)
        .map(([key, val]) => ({ [key]: val })) // pass nodes & links as separate props
    );

    state.forcegraph.setAttribute('forcegraph', newProps);
  }
});
<|endoftext|>


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

  angular.module('nywton.chessboard', [])

  .value('nywtonChessboardDefaultConfig', {
    position: undefined,
    showNotation: true,
    orientation: 'white',
    draggable: false,
    dropOffBoard: 'snapback',
    appearSpeed: 200,
    moveSpeed: 200,
    snapbackSpeed: 50,
    snapSpeed: 25,
    trashSpeed: 100,
    sparePieces:false,
    showErrors: false,
    pieceTheme: undefined, // defaults to 'img/chesspieces/wikipedia/{piece}.png'
    onDragStart: angular.noop,
    onDrop: angular.noop,
    onSnapEnd: angular.noop,
    onChange: angular.noop,
    onDragMove: angular.noop,
    onSnapbackEnd: angular.noop,
    onMoveEnd: angular.noop,
    onMouseoutSquare: angular.noop,
    onMouseoverSquare: angular.noop,
  })

  // TODO: all attributes should be configurable
  .provider('nywtonChessboardConfig', [function NywtonChessboardConfigProvider() {
    var config = {};

    this.pieceTheme = function pieceThemeF(pieceTheme) {
      config.pieceTheme = pieceTheme;
      return this;
    };
    this.position = function positionF(position) {
      config.position = position;
      return this;
    };
    this.draggable = function draggableF(draggable) {
      config.draggable = draggable;
      return this;
    };
    this.sparePieces = function sparePiecesF(sparePieces) {
      config.sparePieces = sparePieces;
      return this;
    };

    this.$get = ['nywtonChessboardDefaultConfig', function getF(defaultConfig) {
      return angular.extend(defaultConfig, config);
    }];
  }])

  .config(['nywtonChessboardConfigProvider', function nywtonChessboardConfigProviderConfig(configProvider) {
    configProvider.position('empty');
  }])

  .directive('nywtonChessboard', [
    '$window',
    '$log',
    '$timeout',
    'nywtonChessboardConfig',
    function($window, $log, $timeout, nywtonChessConfig) {
      var _configAttrs = [
        'draggable',
        'dropOffBoard',
        'position',
        'orientation',
        'showNotation',
        'sparePieces',
        'showErrors',
        'pieceTheme',
        'appearSpeed',
        'moveSpeed',
        'snapbackSpeed',
        'snapSpeed',
        'trashSpeed',
      ];

      var _callbackAttrs = [
        'onChange',
        'onDragStart',
        'onDragMove',
        'onDrop',
        'onSnapbackEnd',
        'onMoveEnd',
        'onMouseoutSquare',
        'onMouseoverSquare',
        'onSnapEnd',
      ];

      var directive = {
        restrict: 'EA',
        scope: {
          name: '@',
          board: '=',
          // callbacks
          onChange:'&',
          onDragMove: '&',
          onDrop: '&',
          onSnapbackEnd: '&',
          onMoveEnd: '&',
          onMouseoutSquare: '&',
          onMouseoverSquare: '&',
          onSnapEnd: '&',
          // workaround because angular does not like 'onDragStart'
          onDragStart:'&onDragStartCb',
        },
        priority: 1000,
        template: '

',
        controller: ['$scope', function NywtonChessboardCtrl($scope) {
          var $ctrl = this;
          var _cfg = [];

          $scope.name = $scope.name || 'board'+$scope.$id;

          this.config_push = function config_pushF(incoming) {
            if(angular.isArray(incoming) && incoming.length === 2 && angular.isString(incoming[0]) && !angular.isUndefined(incoming[1])) {
              _cfg.push(incoming);
            }
          };

          this.config = function configF() {
            var cfg = {};
            angular.forEach(_cfg, function(pair) {
              cfg[pair[0]] = pair[1];
            });
            var combined_config = angular.extend(angular.copy(nywtonChessConfig), cfg);
            $log.debug(combined_config);
            return combined_config;
          };

          this.board = function boardF() {
            return $scope.board;
          };

          var safeDigest = function safeDigestF() {
            return ($scope.$$phase || $scope.$root.$$phase) ? 0 : $scope.$parent.$digest();
          };

          var safeApply = function safeApplyF(scope, fn) {
            return (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
          };

          // TODO: make this configurable
          // calling $digest may on e.g. 'onMouseoverSquare'
          // be overkill in some contexts
          var invokeDigestOnCallbacks = true;
          var applyWrapper = function applyWrapperF(func) {
            return function wrappedApplyInvokation() {
              var args = arguments;
              return safeApply($scope.$parent, function wrappedApplyInner() {
                return func.apply(this, args);
              });
            };
          };

          // callback attributes e.g. on-mouse-square="myCallback"
          angular.forEach(_callbackAttrs, function(attr) {
            if(angular.isFunction($scope[attr])) {
              var expressionHandler = $scope[attr]();
              // check if callback is a function (or given at all)
              if(angular.isFunction(expressionHandler)) {
                // wrap in an $apply() call if needed
                var callback = invokeDigestOnCallbacks ? applyWrapper(expressionHandler) : expressionHandler;
                $ctrl.config_push([attr, callback]);
              }
              // otherwise push the default callback calling $digest
              else {
                $ctrl.config_push([attr, safeDigest]);
              }
            }
          });
        }],
        link: function link($scope, $element, $attrs, $ctrl) {
          angular.forEach(_configAttrs, function(attr) {
            $log.debug('attr: ' + attr + ' = ' + $scope.$eval($attrs[attr]));
            if($attrs.hasOwnProperty(attr)) {
              $ctrl.config_push([attr, $scope.$eval($attrs[attr])]);
            }
          });

          var board_config = $ctrl.config();
          var board_element = angular.element('

');
          $element.prepend(board_element);

          $scope.board = new $window.ChessBoard(board_element, board_config);
          $scope.board.name = $scope.name || 'board' + $scope.$id;

          $scope.$on('$destroy', function onDestroyF() {
            $scope.board.destroy();
          });
        },
      };

      return directive;
    }
  ])

  .directive('nywtonPositionRuyLopez', [function() {

    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $ctrl.config_push(['position', 'r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R']);
      },
    };

    return directive;
  }])

  .directive('nywtonPositionStart', [function() {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $ctrl.config_push(['position', 'start']);
      },
    };

    return directive;
  }])

  .directive('nywtonChessboardAutoresize', ['$window','$timeout', function($window, $timeout) {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        var resizeBoard = function resizeBoardF() {
          if(angular.isDefined($ctrl.board())) {
            $ctrl.board().resize();
          }
        };
        var resizeTimeoutPromise;
        angular.element($window).bind('resize', function() {
          $timeout.cancel(resizeTimeoutPromise);
          resizeTimeoutPromise = $timeout(resizeBoard, 113);
        });
        $scope.$on('$destroy', function onDestroyF() {
          $timeout.cancel(resizeTimeoutPromise);
        });
      },
    };

    return directive;
  }]);

})();<commit_msg>make all chessboardjs settings configurable<commit_after>(function (window, ChessBoard, undefined) {
  'use strict';

  var chessboardDefaultConfig = {
    position: undefined,
    showNotation: true,
    orientation: 'white',
    draggable: false,
    dropOffBoard: 'snapback',
    appearSpeed: 200,
    moveSpeed: 200,
    snapbackSpeed: 50,
    snapSpeed: 25,
    trashSpeed: 100,
    sparePieces:false,
    showErrors: false,
    pieceTheme: undefined, // defaults to 'img/chesspieces/wikipedia/{piece}.png'
    onDragStart: angular.noop,
    onDrop: angular.noop,
    onSnapEnd: angular.noop,
    onChange: angular.noop,
    onDragMove: angular.noop,
    onSnapbackEnd: angular.noop,
    onMoveEnd: angular.noop,
    onMouseoutSquare: angular.noop,
    onMouseoverSquare: angular.noop,
  };

  angular.module('nywton.chessboard', [])

  .value('nywtonChessboardDefaultConfig', angular.copy(chessboardDefaultConfig))

  // TODO: all attributes should be configurable
  .provider('nywtonChessboardConfig', [function NywtonChessboardConfigProvider() {
    var config = {};

      // add a setter function for all properties
    var that = this;
    angular.forEach(chessboardDefaultConfig, function(value, key) {
      that[key] = function(propertyValue) {
        config[key] = propertyValue;
        return that;
      };
    });

    this.$get = ['nywtonChessboardDefaultConfig', function getF(defaultConfig) {
      return angular.extend(defaultConfig, config);
    }];
  }])

  .config(['nywtonChessboardConfigProvider', function nywtonChessboardConfigProviderConfig(configProvider) {
    configProvider.position('empty').orientation('white');
  }])

  .directive('nywtonChessboard', [
    '$window',
    '$log',
    '$timeout',
    'nywtonChessboardConfig',
    function($window, $log, $timeout, nywtonChessConfig) {
      var _configAttrs = [
        'draggable',
        'dropOffBoard',
        'position',
        'orientation',
        'showNotation',
        'sparePieces',
        'showErrors',
        'pieceTheme',
        'appearSpeed',
        'moveSpeed',
        'snapbackSpeed',
        'snapSpeed',
        'trashSpeed',
      ];

      var _callbackAttrs = [
        'onChange',
        'onDragStart',
        'onDragMove',
        'onDrop',
        'onSnapbackEnd',
        'onMoveEnd',
        'onMouseoutSquare',
        'onMouseoverSquare',
        'onSnapEnd',
      ];

      var directive = {
        restrict: 'EA',
        scope: {
          name: '@',
          board: '=',
          // callbacks
          onChange:'&',
          onDragMove: '&',
          onDrop: '&',
          onSnapbackEnd: '&',
          onMoveEnd: '&',
          onMouseoutSquare: '&',
          onMouseoverSquare: '&',
          onSnapEnd: '&',
          // workaround because angular does not like 'onDragStart'
          onDragStart:'&onDragStartCb',
        },
        priority: 1000,
        template: '

',
        controller: ['$scope', function NywtonChessboardCtrl($scope) {
          var $ctrl = this;
          var _cfg = [];

          $scope.name = $scope.name || 'board'+$scope.$id;

          this.config_push = function config_pushF(incoming) {
            if(angular.isArray(incoming) && incoming.length === 2 && angular.isString(incoming[0]) && !angular.isUndefined(incoming[1])) {
              _cfg.push(incoming);
            }
          };

          this.config = function configF() {
            var cfg = {};
            angular.forEach(_cfg, function(pair) {
              cfg[pair[0]] = pair[1];
            });
            var combined_config = angular.extend(angular.copy(nywtonChessConfig), cfg);
            $log.debug(combined_config);
            return combined_config;
          };

          this.board = function boardF() {
            return $scope.board;
          };

          var safeDigest = function safeDigestF() {
            return ($scope.$$phase || $scope.$root.$$phase) ? 0 : $scope.$parent.$digest();
          };

          var safeApply = function safeApplyF(scope, fn) {
            return (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
          };

          // TODO: make this configurable
          // calling $digest may on e.g. 'onMouseoverSquare'
          // be overkill in some contexts
          var invokeDigestOnCallbacks = true;
          var applyWrapper = function applyWrapperF(func) {
            return function wrappedApplyInvokation() {
              var args = arguments;
              return safeApply($scope.$parent, function wrappedApplyInner() {
                return func.apply(this, args);
              });
            };
          };

          // callback attributes e.g. on-mouse-square="myCallback"
          angular.forEach(_callbackAttrs, function(attr) {
            if(angular.isFunction($scope[attr])) {
              var expressionHandler = $scope[attr]();
              // check if callback is a function (or given at all)
              if(angular.isFunction(expressionHandler)) {
                // wrap in an $apply() call if needed
                var callback = invokeDigestOnCallbacks ? applyWrapper(expressionHandler) : expressionHandler;
                $ctrl.config_push([attr, callback]);
              }
              // otherwise push the default callback calling $digest
              else {
                $ctrl.config_push([attr, safeDigest]);
              }
            }
          });
        }],
        link: function link($scope, $element, $attrs, $ctrl) {
          angular.forEach(_configAttrs, function(attr) {
            $log.debug('attr: ' + attr + ' = ' + $scope.$eval($attrs[attr]));
            if($attrs.hasOwnProperty(attr)) {
              $ctrl.config_push([attr, $scope.$eval($attrs[attr])]);
            }
          });

          var board_config = $ctrl.config();
          var board_element = angular.element('

');
          $element.prepend(board_element);

          $scope.board = new ChessBoard(board_element, board_config);
          $scope.board.name = $scope.name || 'board' + $scope.$id;

          $scope.$on('$destroy', function onDestroyF() {
            $scope.board.destroy();
          });
        },
      };

      return directive;
    }
  ])

  .directive('nywtonPositionRuyLopez', [function() {

    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $ctrl.config_push(['position', 'r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R']);
      },
    };

    return directive;
  }])

  .directive('nywtonPositionStart', [function() {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $ctrl.config_push(['position', 'start']);
      },
    };

    return directive;
  }])

  .directive('nywtonChessboardAutoresize', ['$window','$timeout', function($window, $timeout) {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        var resizeBoard = function resizeBoardF() {
          if(angular.isDefined($ctrl.board())) {
            $ctrl.board().resize();
          }
        };
        var resizeTimeoutPromise;
        angular.element($window).bind('resize', function() {
          $timeout.cancel(resizeTimeoutPromise);
          resizeTimeoutPromise = $timeout(resizeBoard, 113);
        });
        $scope.$on('$destroy', function onDestroyF() {
          $timeout.cancel(resizeTimeoutPromise);
        });
      },
    };

    return directive;
  }]);

})(window, ChessBoard);
<|endoftext|>


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

  angular.module('nywton.chessboard', [])

  .value('nywtonChessboardDefaultConfig', {
    position: undefined,
    showNotation: true,
    orientation: 'white',
    draggable: false,
    dropOffBoard: 'snapback',
    appearSpeed: 200,
    moveSpeed: 200,
    snapbackSpeed: 50,
    snapSpeed: 25,
    trashSpeed: 100,
    onDragStart: angular.noop,
    onDrop: angular.noop,
    onSnapEnd: angular.noop,
    onChange: angular.noop,
    onDragMove: angular.noop,
    onSnapbackEnd: angular.noop,
    onMoveEnd: angular.noop,
    onMouseoutSquare: angular.noop,
    onMouseoverSquare: angular.noop,
  })

  .provider('nywtonChessboardConfig', [function NywtonChessboardConfigProvider() {
    var config = {};

    this.pieceTheme = function pieceThemeF(pieceTheme) {
      config.pieceTheme = pieceTheme;
      return this;
    };
    this.position = function positionF(position) {
      config.position = position;
      return this;
    };
    this.draggable = function draggableF(draggable) {
      config.draggable = draggable;
      return this;
    };

    this.$get = ['nywtonChessboardDefaultConfig', function getF(defaultConfig) {
      return angular.extend(defaultConfig, config);
    }];
  }])

  .config(['nywtonChessboardConfigProvider', function nywtonChessboardConfigProviderConfig(configProvider) {
    configProvider.draggable(true).position('start');
  }])

  .directive('nywtonChessboard', [
    '$window',
    '$log',
    '$timeout',
    'nywtonChessboardConfig',
    function($window, $log, $timeout, nywtonChessConfig) {
      var _configAttrs = [
        'draggable',
        'dropOffBoard',
        'position',
        'orientation',
        'showNotation',
        'sparePieces',
        'showErrors',
        'pieceTheme',
        'appearSpeed',
        'moveSpeed',
        'snapbackSpeed',
        'snapSpeed',
        'trashSpeed',
      ];

      var _callbackAttrs = [
        'onChange',
        'onDragStart',
        'onDragMove',
        'onDrop',
        'onSnapbackEnd',
        'onMoveEnd',
        'onMouseoutSquare',
        'onMouseoverSquare',
        'onSnapEnd',
      ];

      var directive = {
        restrict: 'EA',
        scope: {
          name: '@',
          board: '=',
          // callbacks
          onChange:'&',
          onDragMove: '&',
          onDrop: '&',
          onSnapbackEnd: '&',
          onMoveEnd: '&',
          onMouseoutSquare: '&',
          onMouseoverSquare: '&',
          onSnapEnd: '&',
          // workaround because angular does not like 'onDragStart'
          onDragStart:'&onDragStartCb',
        },
        priority: 1000,
        template: '

',
        controller: ['$scope', function NywtonChessboardCtrl($scope) {
          var $ctrl = this;
          var _cfg = [];

          $scope.name = $scope.name || 'board'+$scope.$id;

          this.config_push = function config_pushF(incoming) {
            if(angular.isArray(incoming) && incoming.length === 2 && angular.isString(incoming[0]) && !angular.isUndefined(incoming[1])) {
              _cfg.push(incoming);
            }
          };

          this.config = function configF() {
            var cfg = {};
            angular.forEach(_cfg, function(pair) {
              cfg[pair[0]] = pair[1];
            });
            var combined_config = angular.extend(angular.copy(nywtonChessConfig), cfg);
            $log.debug(combined_config);
            return combined_config;
          };

          this.board = function boardF() {
            return $scope.board;
          };

          var defaultCallback = function defaultCallbackF() {
            // calling $digest() because callbacks are invoked from external lib
            $scope.$parent.$digest();
          };

          angular.forEach(_callbackAttrs, function(attr) {
            if(angular.isFunction($scope[attr])) {
              var expressionHandler = $scope[attr]();
              if(!angular.isFunction(expressionHandler)) {
                // push default callback if attr was not specified
                $ctrl.config_push([attr, defaultCallback]);
              } else {
                $log.debug('callback attr: ' + attr + ' = ' + expressionHandler);
                $ctrl.config_push([attr, expressionHandler]);
              }
            }
          });
        }],
        link: function link($scope, $element, $attrs, $ctrl) {
          angular.forEach(_configAttrs, function(attr) {
            $log.debug('attr: ' + attr + ' = ' + $scope.$eval($attrs[attr]));
            if($attrs.hasOwnProperty(attr)) {
              $ctrl.config_push([attr, $scope.$eval($attrs[attr])]);
            }
          });

          var board_config = $ctrl.config();
          var board_element = angular.element('

')[0];
          $element.prepend(board_element);

          $scope.board = new $window.ChessBoard(board_element, board_config);
          $scope.board.name = $scope.name || 'board' + $scope.$id;
        },
      };

      return directive;
    }
  ])

  .directive('nywtonPositionRuyLopez', ['$log', function($log) {

    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $log.debug('pushing config "position" with Ruy Lopez fen-string');
        $ctrl.config_push(['position', 'r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R']);
      },
    };

    return directive;
  }])

  .directive('nywtonPositionStart', ['$log', function($log) {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $log.debug('pushing config "position" with start position');
        $ctrl.config_push(['position', 'start']);
      },
    };

    return directive;
  }])

  .directive('nywtonChessboardAutoresize', ['$window','$timeout', function($window, $timeout) {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        var resizeBoard = function resizeBoardF() {
          if(angular.isDefined($ctrl.board())) {
            $ctrl.board().resize();
          }
        };
        var resizeTimeoutPromise;
        // TODO: find better solution than using jquery for resize events o_0
        $window.$($window).resize(function onWindowSizeChangeResizeBoardF() {
          $timeout.cancel(resizeTimeoutPromise);
          resizeTimeoutPromise = $timeout(resizeBoard, 200);
        });
        $scope.$on('$destroy', function onDestroyF() {
          $timeout.cancel(resizeTimeoutPromise);
        });
      },
    };

    return directive;
  }]);

})();<commit_msg>added remaining default options<commit_after>(function () {
  'use strict';

  angular.module('nywton.chessboard', [])

  .value('nywtonChessboardDefaultConfig', {
    position: undefined,
    showNotation: true,
    orientation: 'white',
    draggable: false,
    dropOffBoard: 'snapback',
    appearSpeed: 200,
    moveSpeed: 200,
    snapbackSpeed: 50,
    snapSpeed: 25,
    trashSpeed: 100,
    sparePieces:false,
    showErrors: false,
    pieceTheme: undefined, // defaults to 'img/chesspieces/wikipedia/{piece}.png'
    onDragStart: angular.noop,
    onDrop: angular.noop,
    onSnapEnd: angular.noop,
    onChange: angular.noop,
    onDragMove: angular.noop,
    onSnapbackEnd: angular.noop,
    onMoveEnd: angular.noop,
    onMouseoutSquare: angular.noop,
    onMouseoverSquare: angular.noop,
  })

  .provider('nywtonChessboardConfig', [function NywtonChessboardConfigProvider() {
    var config = {};

    this.pieceTheme = function pieceThemeF(pieceTheme) {
      config.pieceTheme = pieceTheme;
      return this;
    };
    this.position = function positionF(position) {
      config.position = position;
      return this;
    };
    this.draggable = function draggableF(draggable) {
      config.draggable = draggable;
      return this;
    };
    this.sparePieces = function sparePiecesF(sparePieces) {
      config.draggable = sparePieces ? true : config.draggable;
      config.sparePieces = sparePieces;
      return this;
    };

    this.$get = ['nywtonChessboardDefaultConfig', function getF(defaultConfig) {
      return angular.extend(defaultConfig, config);
    }];
  }])

  .config(['nywtonChessboardConfigProvider', function nywtonChessboardConfigProviderConfig(configProvider) {
    configProvider.draggable(true).position('start');
  }])

  .directive('nywtonChessboard', [
    '$window',
    '$log',
    '$timeout',
    'nywtonChessboardConfig',
    function($window, $log, $timeout, nywtonChessConfig) {
      var _configAttrs = [
        'draggable',
        'dropOffBoard',
        'position',
        'orientation',
        'showNotation',
        'sparePieces',
        'showErrors',
        'pieceTheme',
        'appearSpeed',
        'moveSpeed',
        'snapbackSpeed',
        'snapSpeed',
        'trashSpeed',
      ];

      var _callbackAttrs = [
        'onChange',
        'onDragStart',
        'onDragMove',
        'onDrop',
        'onSnapbackEnd',
        'onMoveEnd',
        'onMouseoutSquare',
        'onMouseoverSquare',
        'onSnapEnd',
      ];

      var directive = {
        restrict: 'EA',
        scope: {
          name: '@',
          board: '=',
          // callbacks
          onChange:'&',
          onDragMove: '&',
          onDrop: '&',
          onSnapbackEnd: '&',
          onMoveEnd: '&',
          onMouseoutSquare: '&',
          onMouseoverSquare: '&',
          onSnapEnd: '&',
          // workaround because angular does not like 'onDragStart'
          onDragStart:'&onDragStartCb',
        },
        priority: 1000,
        template: '

',
        controller: ['$scope', function NywtonChessboardCtrl($scope) {
          var $ctrl = this;
          var _cfg = [];

          $scope.name = $scope.name || 'board'+$scope.$id;

          this.config_push = function config_pushF(incoming) {
            if(angular.isArray(incoming) && incoming.length === 2 && angular.isString(incoming[0]) && !angular.isUndefined(incoming[1])) {
              _cfg.push(incoming);
            }
          };

          this.config = function configF() {
            var cfg = {};
            angular.forEach(_cfg, function(pair) {
              cfg[pair[0]] = pair[1];
            });
            var combined_config = angular.extend(angular.copy(nywtonChessConfig), cfg);
            $log.debug(combined_config);
            return combined_config;
          };

          this.board = function boardF() {
            return $scope.board;
          };

          var defaultCallback = function defaultCallbackF() {
            // calling $digest() because callbacks are invoked from external lib
            $scope.$parent.$digest();
          };

          angular.forEach(_callbackAttrs, function(attr) {
            if(angular.isFunction($scope[attr])) {
              var expressionHandler = $scope[attr]();
              if(!angular.isFunction(expressionHandler)) {
                // push default callback if attr was not specified
                $ctrl.config_push([attr, defaultCallback]);
              } else {
                $log.debug('callback attr: ' + attr + ' = ' + expressionHandler);
                $ctrl.config_push([attr, expressionHandler]);
              }
            }
          });
        }],
        link: function link($scope, $element, $attrs, $ctrl) {
          angular.forEach(_configAttrs, function(attr) {
            $log.debug('attr: ' + attr + ' = ' + $scope.$eval($attrs[attr]));
            if($attrs.hasOwnProperty(attr)) {
              $ctrl.config_push([attr, $scope.$eval($attrs[attr])]);
            }
          });

          var board_config = $ctrl.config();
          var board_element = angular.element('

')[0];
          $element.prepend(board_element);

          $scope.board = new $window.ChessBoard(board_element, board_config);
          $scope.board.name = $scope.name || 'board' + $scope.$id;
        },
      };

      return directive;
    }
  ])

  .directive('nywtonPositionRuyLopez', ['$log', function($log) {

    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $log.debug('pushing config "position" with Ruy Lopez fen-string');
        $ctrl.config_push(['position', 'r1bqkbnr/pppp1ppp/2n5/1B2p3/4P3/5N2/PPPP1PPP/RNBQK2R']);
      },
    };

    return directive;
  }])

  .directive('nywtonPositionStart', ['$log', function($log) {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        $log.debug('pushing config "position" with start position');
        $ctrl.config_push(['position', 'start']);
      },
    };

    return directive;
  }])

  .directive('nywtonChessboardAutoresize', ['$window','$timeout', function($window, $timeout) {
    var directive = {
      restrict: 'A',
      priority: 1,
      require: 'nywtonChessboard',
      link: function link($scope, $element, $attrs, $ctrl) {
        var resizeBoard = function resizeBoardF() {
          if(angular.isDefined($ctrl.board())) {
            $ctrl.board().resize();
          }
        };
        var resizeTimeoutPromise;
        // TODO: find better solution than using jquery for resize events o_0
        $window.$($window).resize(function onWindowSizeChangeResizeBoardF() {
          $timeout.cancel(resizeTimeoutPromise);
          resizeTimeoutPromise = $timeout(resizeBoard, 200);
        });
        $scope.$on('$destroy', function onDestroyF() {
          $timeout.cancel(resizeTimeoutPromise);
        });
      },
    };

    return directive;
  }]);

})();<|endoftext|>


<commit_before>/*
 *  Copyright 2014 TWO SIGMA OPEN SOURCE, LLC
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

var BeakerPageObject = require('../../beaker.po.js');
var path = require('path');
var beakerPO;

describe('HeatMap Tutorial', function () {

    beforeAll(function(done) {
        beakerPO = new BeakerPageObject();
        browser.get(beakerPO.baseURL + "beaker/#/open?uri=file:config%2Ftutorials%2Fheatmap.bkr&readOnly=true").then(done);
        beakerPO.waitUntilLoadingFinished();
        browser.driver.manage().window().maximize();
    });

    afterAll(function(done){
        beakerPO.createScreenshot('heatmapTutorial1');
        done();
    });

    it('Basic HeatMap Example', function () {
        var idCell = "codeFh3TtJ";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        beakerPO.checkLegendIsPresentByIdCell(idCell);
        beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('#plotLegend')).getCssValue('top').then(function(legendTop){
            beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('.plot-plotcontainer')).getCssValue('top').then(function(plotTop){
                expect(parseInt(plotTop)).toBeLessThan(parseInt(legendTop));
            });
        });
    });

    it('Title, Labels and Legend', function () {
        var idCell = "code4GJtht";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        beakerPO.checkLegendIsPresentByIdCell(idCell);
        expect(beakerPO.getCodeCellOutputContainerXLabelByIdCell(idCell)).toBe("X Label");
        expect(beakerPO.getCodeCellOutputContainerYLabelByIdCell(idCell)).toBe("Y Label");
        expect(beakerPO.getCodeCellOutputContainerTitleByIdCell(idCell)).toBe("Heatmap Second Example");
        beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('#plotLegend')).getCssValue('top').then(function(legendTop){
            beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('.plot-plotcontainer')).getCssValue('top').then(function(plotTop){
                expect(parseInt(legendTop)).toBeLessThan(parseInt(plotTop));
            });
        });
    });

    it('Setting colors, hiding the legend', function () {
        var idCell = "codeVDjdY4";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        expect(beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('#plotLegend')).isPresent()).toBe(false);
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getCssValue('fill')).toBe('rgb(45, 185, 0)');
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_1')).getCssValue('fill')).toBe('rgb(50, 187, 0)');

        idCell = "codehVlhId";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getCssValue('fill')).toBe('rgb(93, 93, 0)');
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_1')).getCssValue('fill')).toBe('rgb(179, 179, 0)');
        expect(beakerPO.getCodeCellOutputContainerTitleByIdCell(idCell)).toBe("Custom Gradient Example");
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).toBeNull();
        browser.actions().mouseMove(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0'))).perform().then(function(){
            beakerPO.createScreenshot('heatmapTooltip');
            browser.sleep(1000);
            expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).not.toBeNull();
        });
    });

    it('Custom size, no tooltips', function () {
        var idCell = "codebYcLcg";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        beakerPO.checkSize(beakerPO.getPlotSvgByIdCell(idCell), 900, 300);
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).toBeNull();
        browser.actions().mouseMove(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0'))).perform().then(function(){
            expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).toBeNull();
        });
    });

});<commit_msg>fix error in 'heatmap' test<commit_after>/*
 *  Copyright 2014 TWO SIGMA OPEN SOURCE, LLC
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

var BeakerPageObject = require('../../beaker.po.js');
var beakerPO;

describe('HeatMap Tutorial', function () {

    beforeAll(function(done) {
        beakerPO = new BeakerPageObject();
        browser.get(beakerPO.baseURL + "beaker/#/open?uri=file:config%2Ftutorials%2Fheatmap.bkr&readOnly=true").then(done);
        beakerPO.waitUntilLoadingFinished();
        browser.driver.manage().window().maximize();
    });

    afterAll(function(done){
        beakerPO.createScreenshot('heatmapTutorial1');
        done();
    });

    it('Basic HeatMap Example', function () {
        var idCell = "codeFh3TtJ";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        beakerPO.checkLegendIsPresentByIdCell(idCell);
        beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('#plotLegend')).getCssValue('top').then(function(legendTop){
            beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('.plot-plotcontainer')).getCssValue('top').then(function(plotTop){
                expect(parseInt(plotTop)).toBeLessThan(parseInt(legendTop));
            });
        });
    });

    it('Title, Labels and Legend', function () {
        var idCell = "code4GJtht";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        beakerPO.checkLegendIsPresentByIdCell(idCell);
        expect(beakerPO.getCodeCellOutputContainerXLabelByIdCell(idCell)).toBe("X Label");
        expect(beakerPO.getCodeCellOutputContainerYLabelByIdCell(idCell)).toBe("Y Label");
        expect(beakerPO.getCodeCellOutputContainerTitleByIdCell(idCell)).toBe("Heatmap Second Example");
        beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('#plotLegend')).getCssValue('top').then(function(legendTop){
            beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('.plot-plotcontainer')).getCssValue('top').then(function(plotTop){
                expect(parseInt(legendTop)).toBeLessThan(parseInt(plotTop));
            });
        });
    });

    it('Setting colors, hiding the legend', function () {
        var idCell = "codeVDjdY4";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        expect(beakerPO.getPlotLegendContainerByIdCell(idCell).element(by.css('#plotLegend')).isPresent()).toBe(false);
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getCssValue('fill')).toBe('rgb(45, 185, 0)');
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_1')).getCssValue('fill')).toBe('rgb(50, 187, 0)');

        idCell = "codehVlhId";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getCssValue('fill')).toBe('rgb(93, 93, 0)');
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_1')).getCssValue('fill')).toBe('rgb(179, 179, 0)');
        expect(beakerPO.getCodeCellOutputContainerTitleByIdCell(idCell)).toBe("Custom Gradient Example");
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).toBeNull();
        browser.actions().mouseMove(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0'))).perform();
        beakerPO.createScreenshot('heatmapTooltip');
        browser.wait(function(){
            return beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')
                .then(function(result) {
                    return (result ? true : false);
                });
        }, 10000);
    });

    it('Custom size, no tooltips', function () {
        var idCell = "codebYcLcg";
        beakerPO.scrollToBkCellByIdCell(idCell);
        beakerPO.clickCodeCellInputButtonByIdCell(idCell, 'Plot');
        beakerPO.checkPlotIsPresentByIdCell(idCell);
        beakerPO.checkSize(beakerPO.getPlotSvgByIdCell(idCell), 900, 300);
        expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).toBeNull();
        browser.actions().mouseMove(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0'))).perform().then(function(){
            expect(beakerPO.getPlotSvgByIdCell(idCell).element(by.css('rect#i0_0')).getAttribute('filter')).toBeNull();
        });
    });

});<|endoftext|>


<commit_before>// @flow

import React, { Component } from 'react';
import { Navigator, StyleSheet } from 'react-native';

import Carousel from './components/Carousel';

const styles = StyleSheet.create({
  navigator: {
    flex: 1,
    backgroundColor: 'black',
  },
});

type Props = {
  onShow?: () => void;
  onDismiss?: () => void;
  show?: boolean;
  carouselStyle?: any;
  children: any;
}

const defaultProps = {
  onShow: () => {},
  onDismiss: () => {},
  carouselStyle: null,
  show: false,
};

class CarouselComponent extends Component {
  props: Props

  static defaultProps = defaultProps

  constructor(props: Props) {
    super(props);

    (this: any).renderScene = this.renderScene.bind(this);
    (this: any).show = this.show.bind(this);
    (this: any).dismiss = this.dismiss.bind(this);
    (this: any).didFocus = this.didFocus.bind(this);
  }

  show(callback?: Function = () => {}): void {
    this.navigator.push({ show: true });
    callback();
  }

  dismiss(callback?: Function = () => {}): void {
    this.navigator.pop();
    callback();
  }

  didFocus({ show }) {
    const callback = show ? this.props.onShow : this.props.onDismiss;
    callback();
  }

  configureScene() {
    return Navigator.SceneConfigs.FloatFromBottom;
  }

  renderScene(route, navigator) {
    if (route.show) {
      return (
        <Carousel
          {...this.props}
          style={this.props.carouselStyle}
          navigator={navigator}
        />
      );
    }
    return this.props.children;
  }

  render() {
    return (
      <Navigator
        ref={(navigator) => { this.navigator = navigator; }}
        initialRoute={{ show: this.props.show }}
        configureScene={this.configureScene}
        renderScene={this.renderScene}
        onDidFocus={this.didFocus}
        style={styles.navigator}
      />
    );
  }
}

export default CarouselComponent;
<commit_msg>add handle android hardware back press event<commit_after>// @flow

import React, { Component } from 'react';
import { Navigator, StyleSheet, BackAndroid, Platform } from 'react-native';

import Carousel from './components/Carousel';

const HARDWARE_BACK_PRESS_EVENT: string = 'hardwareBackPress';

const styles = StyleSheet.create({
  navigator: {
    flex: 1,
    backgroundColor: 'black',
  },
});

type Props = {
  onShow?: () => void;
  onDismiss?: () => void;
  dismissOnHardwareBackPress?: boolean;
  show?: boolean;
  carouselStyle?: any;
  children: any;
}

const defaultProps = {
  onShow: () => {},
  onDismiss: () => {},
  dismissOnHardwareBackPress: true,
  carouselStyle: null,
  show: false,
};

class CarouselComponent extends Component {
  props: Props

  static defaultProps = defaultProps

  constructor(props: Props) {
    super(props);

    (this: any).renderScene = this.renderScene.bind(this);
    (this: any).show = this.show.bind(this);
    (this: any).dismiss = this.dismiss.bind(this);
    (this: any).didFocus = this.didFocus.bind(this);
  }

  componentDidMount() {
    if (Platform.OS === 'android') {
      const { dismissOnHardwareBackPress, onDismiss } = this.props;

      BackAndroid.addEventListener(HARDWARE_BACK_PRESS_EVENT, () => {
        if (dismissOnHardwareBackPress) {
          this.dismiss(onDismiss);
          return false;
        }
        return true;
      });
    }
  }

  componentWillUnmount() {
    if (Platform.OS === 'android') {
      BackAndroid.removeEventListener(HARDWARE_BACK_PRESS_EVENT);
    }
  }

  show(callback?: Function = () => {}): void {
    this.navigator.push({ show: true });
    callback();
  }

  dismiss(callback?: Function = () => {}): void {
    this.navigator.pop();
    callback();
  }

  didFocus({ show }) {
    const callback = show ? this.props.onShow : this.props.onDismiss;
    callback();
  }

  configureScene() {
    return Navigator.SceneConfigs.FloatFromBottom;
  }

  renderScene(route, navigator) {
    if (route.show) {
      return (
        <Carousel
          {...this.props}
          style={this.props.carouselStyle}
          navigator={navigator}
        />
      );
    }
    return this.props.children;
  }

  render() {
    return (
      <Navigator
        ref={(navigator) => { this.navigator = navigator; }}
        initialRoute={{ show: this.props.show }}
        configureScene={this.configureScene}
        renderScene={this.renderScene}
        onDidFocus={this.didFocus}
        style={styles.navigator}
      />
    );
  }
}

export default CarouselComponent;
<|endoftext|>