<commit_before>import { actionReverse } from '../actions/reverse';
import { osmIsInterestingTag } from './tags';
import { osmWay } from './way';

// For fixing up rendering of multipolygons with tags on the outer member.
// https://github.com/openstreetmap/iD/issues/613
export function osmIsSimpleMultipolygonOuterMember(entity, graph) {
    if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0)
        return false;

    var parents = graph.parentRelations(entity);
    if (parents.length !== 1)
        return false;

    var parent = parents[0];
    if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
        return false;

    var members = parent.members, member;
    for (var i = 0; i < members.length; i++) {
        member = members[i];
        if (member.id === entity.id && member.role && member.role !== 'outer')
            return false; // Not outer member
        if (member.id !== entity.id && (!member.role || member.role === 'outer'))
            return false; // Not a simple multipolygon
    }

    return parent;
}

export function osmSimpleMultipolygonOuterMember(entity, graph) {
    if (entity.type !== 'way')
        return false;

    var parents = graph.parentRelations(entity);
    if (parents.length !== 1)
        return false;

    var parent = parents[0];
    if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
        return false;

    var members = parent.members, member, outerMember;
    for (var i = 0; i < members.length; i++) {
        member = members[i];
        if (!member.role || member.role === 'outer') {
            if (outerMember)
                return false; // Not a simple multipolygon
            outerMember = member;
        }
    }

    if (!outerMember)
        return false;

    var outerEntity = graph.hasEntity(outerMember.id);
    if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length)
        return false;

    return outerEntity;
}

// Join `toJoin` array into sequences of connecting ways.

// Segments which share identical start/end nodes will, as much as possible,
// be connected with each other.
//
// The return value is a nested array. Each constituent array contains elements
// of `toJoin` which have been determined to connect.
//
// Each consitituent array also has a `nodes` property whose value is an
// ordered array of member nodes, with appropriate order reversal and
// start/end coordinate de-duplication.
//
// Members of `toJoin` must have, at minimum, `type` and `id` properties.
// Thus either an array of `osmWay`s or a relation member array may be used.
//
// If an member is an `osmWay`, its tags and childnodes may be reversed via
// `actionReverse` in the output.
//
// The returned sequences array also has an `actions` array property, containing
// any reversal actions that should be applied to the graph, should the calling
// code attempt to actually join the given ways.
//
// Incomplete members (those for which `graph.hasEntity(element.id)` returns
// false) and non-way members are ignored.
//
export function osmJoinWays(toJoin, graph) {
    function resolve(member) {
        return graph.childNodes(graph.entity(member.id));
    }

    function reverse(item) {
        var action = actionReverse(item.id, { reverseOneway: true });
        sequences.actions.push(action);
        return (item instanceof osmWay) ? action(graph).entity(item.id) : item;
    }

    // make a copy containing only the items to join
    toJoin = toJoin.filter(function(member) {
        return member.type === 'way' && graph.hasEntity(member.id);
    });

    // Are the things we are joining relation members or `osmWays`?
    // If `osmWays`, skip the "prefer a forward path" code below (see #4872)
    var i;
    var joinAsMembers = true;
    for (i = 0; i < toJoin.length; i++) {
        if (toJoin[i] instanceof osmWay) {
            joinAsMembers = false;
            break;
        }
    }

    var sequences = [];
    sequences.actions = [];

    while (toJoin.length) {
        // start a new sequence
        var item = toJoin.shift();
        var currWays = [item];
        var currNodes = resolve(item).slice();
        var doneSequence = false;

        // add to it
        while (toJoin.length && !doneSequence) {
            var start = currNodes[0];
            var end = currNodes[currNodes.length - 1];
            var fn = null;
            var nodes = null;

            // Find the next way/member to join.
            for (i = 0; i < toJoin.length; i++) {
                item = toJoin[i];
                nodes = resolve(item);

                // (for member ordering only, not way ordering - see #4872)
                // Strongly prefer to generate a forward path that preserves the order
                // of the members array. For multipolygons and most relations, member
                // order does not matter - but for routes, it does. If we started this
                // sequence backwards (i.e. next member way attaches to the start node
                // and not the end node), reverse the initial way before continuing.
                if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end &&
                    (nodes[nodes.length - 1] === start || nodes[0] === start)
                ) {
                    currWays[0] = reverse(currWays[0]);
                    currNodes.reverse();
                    start = currNodes[0];
                    end = currNodes[currNodes.length - 1];
                }

                if (nodes[0] === end) {
                    fn = currNodes.push;               // join to end
                    nodes = nodes.slice(1);
                    break;
                } else if (nodes[nodes.length - 1] === end) {
                    fn = currNodes.push;               // join to end
                    nodes = nodes.slice(0, -1).reverse();
                    item = reverse(item);
                    break;
                } else if (nodes[nodes.length - 1] === start) {
                    fn = currNodes.unshift;            // join to beginning
                    nodes = nodes.slice(0, -1);
                    break;
                } else if (nodes[0] === start) {
                    fn = currNodes.unshift;            // join to beginning
                    nodes = nodes.slice(1).reverse();
                    item = reverse(item);
                    break;
                } else {
                    fn = nodes = null;
                }
            }

            if (!nodes) {     // couldn't find a joinable way/member
                doneSequence = true;
                break;
            }

            fn.apply(currWays, [item]);
            fn.apply(currNodes, nodes);

            toJoin.splice(i, 1);
        }

        currWays.nodes = currNodes;
        sequences.push(currWays);
    }

    return sequences;
}
<commit_msg>Link to relevant issues in comment<commit_after>import { actionReverse } from '../actions/reverse';
import { osmIsInterestingTag } from './tags';
import { osmWay } from './way';

// For fixing up rendering of multipolygons with tags on the outer member.
// https://github.com/openstreetmap/iD/issues/613
export function osmIsSimpleMultipolygonOuterMember(entity, graph) {
    if (entity.type !== 'way' || Object.keys(entity.tags).filter(osmIsInterestingTag).length === 0)
        return false;

    var parents = graph.parentRelations(entity);
    if (parents.length !== 1)
        return false;

    var parent = parents[0];
    if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
        return false;

    var members = parent.members, member;
    for (var i = 0; i < members.length; i++) {
        member = members[i];
        if (member.id === entity.id && member.role && member.role !== 'outer')
            return false; // Not outer member
        if (member.id !== entity.id && (!member.role || member.role === 'outer'))
            return false; // Not a simple multipolygon
    }

    return parent;
}

export function osmSimpleMultipolygonOuterMember(entity, graph) {
    if (entity.type !== 'way')
        return false;

    var parents = graph.parentRelations(entity);
    if (parents.length !== 1)
        return false;

    var parent = parents[0];
    if (!parent.isMultipolygon() || Object.keys(parent.tags).filter(osmIsInterestingTag).length > 1)
        return false;

    var members = parent.members, member, outerMember;
    for (var i = 0; i < members.length; i++) {
        member = members[i];
        if (!member.role || member.role === 'outer') {
            if (outerMember)
                return false; // Not a simple multipolygon
            outerMember = member;
        }
    }

    if (!outerMember)
        return false;

    var outerEntity = graph.hasEntity(outerMember.id);
    if (!outerEntity || !Object.keys(outerEntity.tags).filter(osmIsInterestingTag).length)
        return false;

    return outerEntity;
}

// Join `toJoin` array into sequences of connecting ways.

// Segments which share identical start/end nodes will, as much as possible,
// be connected with each other.
//
// The return value is a nested array. Each constituent array contains elements
// of `toJoin` which have been determined to connect.
//
// Each consitituent array also has a `nodes` property whose value is an
// ordered array of member nodes, with appropriate order reversal and
// start/end coordinate de-duplication.
//
// Members of `toJoin` must have, at minimum, `type` and `id` properties.
// Thus either an array of `osmWay`s or a relation member array may be used.
//
// If an member is an `osmWay`, its tags and childnodes may be reversed via
// `actionReverse` in the output.
//
// The returned sequences array also has an `actions` array property, containing
// any reversal actions that should be applied to the graph, should the calling
// code attempt to actually join the given ways.
//
// Incomplete members (those for which `graph.hasEntity(element.id)` returns
// false) and non-way members are ignored.
//
export function osmJoinWays(toJoin, graph) {
    function resolve(member) {
        return graph.childNodes(graph.entity(member.id));
    }

    function reverse(item) {
        var action = actionReverse(item.id, { reverseOneway: true });
        sequences.actions.push(action);
        return (item instanceof osmWay) ? action(graph).entity(item.id) : item;
    }

    // make a copy containing only the items to join
    toJoin = toJoin.filter(function(member) {
        return member.type === 'way' && graph.hasEntity(member.id);
    });

    // Are the things we are joining relation members or `osmWays`?
    // If `osmWays`, skip the "prefer a forward path" code below (see #4872)
    var i;
    var joinAsMembers = true;
    for (i = 0; i < toJoin.length; i++) {
        if (toJoin[i] instanceof osmWay) {
            joinAsMembers = false;
            break;
        }
    }

    var sequences = [];
    sequences.actions = [];

    while (toJoin.length) {
        // start a new sequence
        var item = toJoin.shift();
        var currWays = [item];
        var currNodes = resolve(item).slice();
        var doneSequence = false;

        // add to it
        while (toJoin.length && !doneSequence) {
            var start = currNodes[0];
            var end = currNodes[currNodes.length - 1];
            var fn = null;
            var nodes = null;

            // Find the next way/member to join.
            for (i = 0; i < toJoin.length; i++) {
                item = toJoin[i];
                nodes = resolve(item);

                // (for member ordering only, not way ordering - see #4872)
                // Strongly prefer to generate a forward path that preserves the order
                // of the members array. For multipolygons and most relations, member
                // order does not matter - but for routes, it does. (see #4859)
                // If we started this sequence backwards (i.e. next member way attaches to
                // the start node and not the end node), reverse the initial way before continuing.
                if (joinAsMembers && currWays.length === 1 && nodes[0] !== end && nodes[nodes.length - 1] !== end &&
                    (nodes[nodes.length - 1] === start || nodes[0] === start)
                ) {
                    currWays[0] = reverse(currWays[0]);
                    currNodes.reverse();
                    start = currNodes[0];
                    end = currNodes[currNodes.length - 1];
                }

                if (nodes[0] === end) {
                    fn = currNodes.push;               // join to end
                    nodes = nodes.slice(1);
                    break;
                } else if (nodes[nodes.length - 1] === end) {
                    fn = currNodes.push;               // join to end
                    nodes = nodes.slice(0, -1).reverse();
                    item = reverse(item);
                    break;
                } else if (nodes[nodes.length - 1] === start) {
                    fn = currNodes.unshift;            // join to beginning
                    nodes = nodes.slice(0, -1);
                    break;
                } else if (nodes[0] === start) {
                    fn = currNodes.unshift;            // join to beginning
                    nodes = nodes.slice(1).reverse();
                    item = reverse(item);
                    break;
                } else {
                    fn = nodes = null;
                }
            }

            if (!nodes) {     // couldn't find a joinable way/member
                doneSequence = true;
                break;
            }

            fn.apply(currWays, [item]);
            fn.apply(currNodes, nodes);

            toJoin.splice(i, 1);
        }

        currWays.nodes = currNodes;
        sequences.push(currWays);
    }

    return sequences;
}
<|endoftext|>


<commit_before>  /*!
  * ----------------
  * Treasure Core JS
  * ----------------
  */

  /**
   * Creates a new Treasure logger
   * @constructor Treasure
   * @param {Object} config - Configuration object
   * @param {String} config.database - Database to which the events should get saved
   * @param {String} config.writeKey - Write-only API key for your account
   * @param {String} [config.protocol="auto"] - Protocol to use for url, allowed values: auto, http, https
   * @param {String} [config.requestType="auto"] - Request type for sending events, allowed values: auto, xhr, jsonp
   * @param {String} [config.host="in.treasuredata.com"] - Host to which events get sent
   */
  function Treasure() {
    return _init.apply(this, arguments);
  }

  function _validate(config) {
    if (_isUndefined(config)) {
      throw new Error('Check out our JavaScript SDK Usage Guide: http://docs.treasuredata.com/articles/javascript-sdk/');
    }
    if (_isUndefined(config.database) || _type(config.database) !== 'String' || !config.database.length) {
      throw new Error('Please provide a database');
    }
    if (!(/^[a-z0-9_]{3,255}$/.test(config.database))) {
      throw new Error('Database must be between 3 and 255 characters and must consist only of lower case letters, numbers, and _');
    }
  }

  function _init(config) {
    _validate(config);
    this.configure(config);
  }

  Treasure.prototype.configure = function(config){
    _validate(config);
    config.host = (_isUndefined(config.host)) ? 'in.treasuredata.com' : config.host.replace(/.*?:\/\//g, '');
    config.protocol = _set_protocol(config.protocol);
    config.requestType = _set_request_type(config.requestType);

    this.client = {
      database: config.database,
      writeKey: config.writeKey,
      globalProperties: null,

      endpoint: config.protocol + '://' + config.host,
      requestType: config.requestType
    };

    Treasure.trigger('client', this, config);
    this.trigger('ready');

    return this;
  };

  // Private
  // --------------------------------

  function _extend(target){
    for (var i = 1; i < arguments.length; i++) {
      for (var prop in arguments[i]){
        // if ((target[prop] && _type(target[prop]) == 'Object') && (arguments[i][prop] && _type(arguments[i][prop]) == 'Object')){
        target[prop] = arguments[i][prop];
      }
    }
    return target;
  }

  function _isUndefined(obj) {
    return obj === void 0;
  }

  function _type(obj){
    var text = (obj && obj.constructor) ? obj.constructor.toString() : void 0;
	  return (text) ? text.match(/function (.*)\(/)[1] : 'Null';
  }

  function _each(o, cb, s){
    var n;
    if (!o){
      return 0;
    }
    s = !s ? o : s;
    if (_type(o)==='array'){ // is(o.length)
      // Indexed arrays, needed for Safari
      for (n=0; n<o.length; n++) {
        if (cb.call(s, o[n], n, o) === false){
          return 0;
        }
      }
    } else {
      // Hashtables
      for (n in o){
        if (o.hasOwnProperty(n)) {
          if (cb.call(s, o[n], n, o) === false){
            return 0;
          }
        }
      }
    }
    return 1;
  }

  function _parse_params(str){
    // via http://stackoverflow.com/a/2880929/2511985
    var urlParams = {},
        match,
        pl     = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) { return decodeURIComponent(s.replace(pl, ' ')); },
        query  = str.split('?')[1];

    while (!!(match=search.exec(query))) {
      urlParams[decode(match[1])] = decode(match[2]);
    }
    return urlParams;
  }

  function _set_protocol(value) {
    value = value || 'auto';
    switch(value) {
      case 'http':
        return 'http';
      case 'https':
        return 'https';
      default:
        return location.protocol.replace(/:/g, '');
    }
  }

  function _set_request_type(value) {
    var configured = value || 'jsonp';
    var capableXHR = false;
    //if ((typeof XMLHttpRequest === 'object' || typeof XMLHttpRequest === 'function') && 'withCredentials' in new XMLHttpRequest()) {
    if ((_type(XMLHttpRequest)==='Object'||_type(XMLHttpRequest)==='Function') && 'withCredentials' in new XMLHttpRequest()) {
      capableXHR = true;
    }
    //var capableXHR = (void 0 !== XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());

    if (configured == null || configured == 'xhr') {
      if (capableXHR) {
        return 'xhr';
      } else {
        return 'jsonp';
      }
    } else {
      return configured;
    }
  }

  function _build_url(path) {
    return this.client.endpoint + '/js/v3/event/' + this.client.database + path;
  }

  var _request = {

    xhr: function(method, url, headers, body, apiKey, success, error){
      if (!apiKey) {
        return Treasure.log('Please provide an apikey from https://console.treasuredata.com/users/current');
      }
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status >= 200 && xhr.status < 300) {
            var response;
            try {
              response = JSON.parse(xhr.responseText);
            } catch (e) {
              Treasure.log('Could not JSON parse HTTP response: ' + xhr.responseText);
              if (error) {
                error(xhr, e);
              }
            }
            if (success && response) {
              success(response);
            }
          } else {
            Treasure.log('HTTP request failed.');
            if (error) {
              error(xhr, null);
            }
          }
        }
      };
      xhr.open(method, url, true);
      if (apiKey) {
        xhr.setRequestHeader('X-TD-WRITE-KEY', apiKey);
      }
      if (body) {
        xhr.setRequestHeader('Content-Type', 'application/json');
      }
      if (headers) {
        for (var headerName in headers) {
          if (headers.hasOwnProperty(headerName)) {
            xhr.setRequestHeader(headerName, headers[headerName]);
          }
        }
      }
      var toSend = body ? JSON.stringify(body) : null;
      xhr.send(toSend);
    },

    jsonp: function(url, apiKey, success, error){
      if (!apiKey) {
        return Treasure.log('Please provide an apikey from https://console.treasuredata.com/users/current');
      }
      if (apiKey && url.indexOf('api_key') < 0) {
        var delimiterChar = url.indexOf('?') > 0 ? '&' : '?';
        url = url + delimiterChar + 'api_key=' + apiKey;
      }

      var callbackName = 'TreasureJSONPCallback' + new Date().getTime();
      while (callbackName in window) {
        callbackName += 'a';
      }
      var loaded = false;
      window[callbackName] = function (response) {
        loaded = true;
        if (success && response) {
          success(response);
        }
        // Remove this from the namespace
        window[callbackName] = undefined;
      };
      url = url + '&callback=' + callbackName;
      var script = document.createElement('script');
      script.id = 'td-js-sdk-jsonp';
      script.src = url;
      document.getElementsByTagName('head')[0].appendChild(script);
      // for early IE w/ no onerror event
      script.onreadystatechange = function() {
        if (loaded === false && this.readyState === 'loaded') {
          loaded = true;
          if (error) {
            error();
          }
        }
      };
      // non-ie, etc
      script.onerror = function() {
        if (loaded === false) { // on IE9 both onerror and onreadystatechange are called
          loaded = true;
          if (error) {
            error();
          }
        }
      };
    }

    // beacon: function(url, apiKey, success, error){
    //   if (apiKey && url.indexOf('api_key') < 0) {
    //     var delimiterChar = url.indexOf('?') > 0 ? '&' : '?';
    //     url = url + delimiterChar + 'api_key=' + apiKey;
    //   }
    //   var loaded = false, img = document.createElement('img');
    //   img.onload = function() {
    //     loaded = true;
    //     if ('naturalHeight' in this) {
    //       if (this.naturalHeight + this.naturalWidth === 0) {
    //         this.onerror(); return;
    //       }
    //     } else if (this.width + this.height === 0) {
    //       this.onerror(); return;
    //     }
    //     if (success) {
    //       success({created: true});
    //     }
    //   };
    //   img.onerror = function() {
    //     loaded = true;
    //     if (error) {
    //       error();
    //     }
    //   };
    //   img.src = url;
    // }
  };

  // -------------------------------
  // Treasure.Events
  // -------------------------------

  var Events = Treasure.Events = {
    on: function(name, callback) {
      this.listeners = this.listeners || {};
      var events = this.listeners[name] || (this.listeners[name] = []);
      events.push({callback: callback});
      return this;
    },
    off: function(name, callback) {
      if (!name && !callback) {
        this.listeners = void 0;
        delete this.listeners;
        return this;
      }
      var events = this.listeners[name] || [];
      for (var i = events.length; i--;) {
        if (callback && callback === events[i].callback) {
          this.listeners[name].splice(i, 1);
        }
        if (!callback || events.length === 0) {
          this.listeners[name] = void 0;
          delete this.listeners[name];
        }
      }
      return this;
    },
    trigger: function(name) {
      if (!this.listeners) {
        return this;
      }
      var args = Array.prototype.slice.call(arguments, 1);
      var events = this.listeners[name] || [];
      for (var i = 0; i < events.length; i++) {
        events[i].callback.apply(this, args);
      }
      return this;
    }
  };
  _extend(Treasure.prototype, Events);
  _extend(Treasure, Events);

  Treasure.loaded = true;

  // Expose utils
  Treasure.utils = {
    each: _each,
    extend: _extend,
    parseParams: _parse_params
  };

  Treasure.ready = function(callback){
    Treasure.on('ready', callback);
  };

  Treasure.log = function(message) {
    if (typeof console === 'object') {
      console.log('[Treasure]', message);
    }
  };

  // -------------------------------
  // Treasure.Plugins
  // -------------------------------

  var Plugins = Treasure.Plugins = {};
<commit_msg>feat(core): add auto option to _set_request_type<commit_after>  /*!
  * ----------------
  * Treasure Core JS
  * ----------------
  */

  /**
   * Creates a new Treasure logger
   * @constructor Treasure
   * @param {Object} config - Configuration object
   * @param {String} config.database - Database to which the events should get saved
   * @param {String} config.writeKey - Write-only API key for your account
   * @param {String} [config.protocol="auto"] - Protocol to use for url, allowed values: auto, http, https
   * @param {String} [config.requestType="auto"] - Request type for sending events, allowed values: auto, xhr, jsonp
   * @param {String} [config.host="in.treasuredata.com"] - Host to which events get sent
   */
  function Treasure() {
    return _init.apply(this, arguments);
  }

  function _validate(config) {
    if (_isUndefined(config)) {
      throw new Error('Check out our JavaScript SDK Usage Guide: http://docs.treasuredata.com/articles/javascript-sdk/');
    }
    if (_isUndefined(config.database) || _type(config.database) !== 'String' || !config.database.length) {
      throw new Error('Please provide a database');
    }
    if (!(/^[a-z0-9_]{3,255}$/.test(config.database))) {
      throw new Error('Database must be between 3 and 255 characters and must consist only of lower case letters, numbers, and _');
    }
  }

  function _init(config) {
    _validate(config);
    this.configure(config);
  }

  Treasure.prototype.configure = function(config){
    _validate(config);
    config.host = (_isUndefined(config.host)) ? 'in.treasuredata.com' : config.host.replace(/.*?:\/\//g, '');
    config.protocol = _set_protocol(config.protocol);
    config.requestType = _set_request_type(config.requestType);

    this.client = {
      database: config.database,
      writeKey: config.writeKey,
      globalProperties: null,

      endpoint: config.protocol + '://' + config.host,
      requestType: config.requestType
    };

    Treasure.trigger('client', this, config);
    this.trigger('ready');

    return this;
  };

  // Private
  // --------------------------------

  function _extend(target){
    for (var i = 1; i < arguments.length; i++) {
      for (var prop in arguments[i]){
        // if ((target[prop] && _type(target[prop]) == 'Object') && (arguments[i][prop] && _type(arguments[i][prop]) == 'Object')){
        target[prop] = arguments[i][prop];
      }
    }
    return target;
  }

  function _isUndefined(obj) {
    return obj === void 0;
  }

  function _type(obj){
    var text = (obj && obj.constructor) ? obj.constructor.toString() : void 0;
	  return (text) ? text.match(/function (.*)\(/)[1] : 'Null';
  }

  function _each(o, cb, s){
    var n;
    if (!o){
      return 0;
    }
    s = !s ? o : s;
    if (_type(o)==='array'){ // is(o.length)
      // Indexed arrays, needed for Safari
      for (n=0; n<o.length; n++) {
        if (cb.call(s, o[n], n, o) === false){
          return 0;
        }
      }
    } else {
      // Hashtables
      for (n in o){
        if (o.hasOwnProperty(n)) {
          if (cb.call(s, o[n], n, o) === false){
            return 0;
          }
        }
      }
    }
    return 1;
  }

  function _parse_params(str){
    // via http://stackoverflow.com/a/2880929/2511985
    var urlParams = {},
        match,
        pl     = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) { return decodeURIComponent(s.replace(pl, ' ')); },
        query  = str.split('?')[1];

    while (!!(match=search.exec(query))) {
      urlParams[decode(match[1])] = decode(match[2]);
    }
    return urlParams;
  }

  function _set_protocol(value) {
    value = value || 'auto';
    switch(value) {
      case 'http':
        return 'http';
      case 'https':
        return 'https';
      default:
        return location.protocol.replace(/:/g, '');
    }
  }

  function _set_request_type(value) {
    value = value || 'auto';
    if (value !== 'auto') {
      return value;
    } else {
      if ((_type(XMLHttpRequest)==='Object'||_type(XMLHttpRequest)==='Function') && 'withCredentials' in new XMLHttpRequest()) {
        return 'xhr';
      } else {
        return 'jsonp';
      }
    }
  }

  function _build_url(path) {
    return this.client.endpoint + '/js/v3/event/' + this.client.database + path;
  }

  var _request = {

    xhr: function(method, url, headers, body, apiKey, success, error){
      if (!apiKey) {
        return Treasure.log('Please provide an apikey from https://console.treasuredata.com/users/current');
      }
      var xhr = new XMLHttpRequest();
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status >= 200 && xhr.status < 300) {
            var response;
            try {
              response = JSON.parse(xhr.responseText);
            } catch (e) {
              Treasure.log('Could not JSON parse HTTP response: ' + xhr.responseText);
              if (error) {
                error(xhr, e);
              }
            }
            if (success && response) {
              success(response);
            }
          } else {
            Treasure.log('HTTP request failed.');
            if (error) {
              error(xhr, null);
            }
          }
        }
      };
      xhr.open(method, url, true);
      if (apiKey) {
        xhr.setRequestHeader('X-TD-WRITE-KEY', apiKey);
      }
      if (body) {
        xhr.setRequestHeader('Content-Type', 'application/json');
      }
      if (headers) {
        for (var headerName in headers) {
          if (headers.hasOwnProperty(headerName)) {
            xhr.setRequestHeader(headerName, headers[headerName]);
          }
        }
      }
      var toSend = body ? JSON.stringify(body) : null;
      xhr.send(toSend);
    },

    jsonp: function(url, apiKey, success, error){
      if (!apiKey) {
        return Treasure.log('Please provide an apikey from https://console.treasuredata.com/users/current');
      }
      if (apiKey && url.indexOf('api_key') < 0) {
        var delimiterChar = url.indexOf('?') > 0 ? '&' : '?';
        url = url + delimiterChar + 'api_key=' + apiKey;
      }

      var callbackName = 'TreasureJSONPCallback' + new Date().getTime();
      while (callbackName in window) {
        callbackName += 'a';
      }
      var loaded = false;
      window[callbackName] = function (response) {
        loaded = true;
        if (success && response) {
          success(response);
        }
        // Remove this from the namespace
        window[callbackName] = undefined;
      };
      url = url + '&callback=' + callbackName;
      var script = document.createElement('script');
      script.id = 'td-js-sdk-jsonp';
      script.src = url;
      document.getElementsByTagName('head')[0].appendChild(script);
      // for early IE w/ no onerror event
      script.onreadystatechange = function() {
        if (loaded === false && this.readyState === 'loaded') {
          loaded = true;
          if (error) {
            error();
          }
        }
      };
      // non-ie, etc
      script.onerror = function() {
        if (loaded === false) { // on IE9 both onerror and onreadystatechange are called
          loaded = true;
          if (error) {
            error();
          }
        }
      };
    }

    // beacon: function(url, apiKey, success, error){
    //   if (apiKey && url.indexOf('api_key') < 0) {
    //     var delimiterChar = url.indexOf('?') > 0 ? '&' : '?';
    //     url = url + delimiterChar + 'api_key=' + apiKey;
    //   }
    //   var loaded = false, img = document.createElement('img');
    //   img.onload = function() {
    //     loaded = true;
    //     if ('naturalHeight' in this) {
    //       if (this.naturalHeight + this.naturalWidth === 0) {
    //         this.onerror(); return;
    //       }
    //     } else if (this.width + this.height === 0) {
    //       this.onerror(); return;
    //     }
    //     if (success) {
    //       success({created: true});
    //     }
    //   };
    //   img.onerror = function() {
    //     loaded = true;
    //     if (error) {
    //       error();
    //     }
    //   };
    //   img.src = url;
    // }
  };

  // -------------------------------
  // Treasure.Events
  // -------------------------------

  var Events = Treasure.Events = {
    on: function(name, callback) {
      this.listeners = this.listeners || {};
      var events = this.listeners[name] || (this.listeners[name] = []);
      events.push({callback: callback});
      return this;
    },
    off: function(name, callback) {
      if (!name && !callback) {
        this.listeners = void 0;
        delete this.listeners;
        return this;
      }
      var events = this.listeners[name] || [];
      for (var i = events.length; i--;) {
        if (callback && callback === events[i].callback) {
          this.listeners[name].splice(i, 1);
        }
        if (!callback || events.length === 0) {
          this.listeners[name] = void 0;
          delete this.listeners[name];
        }
      }
      return this;
    },
    trigger: function(name) {
      if (!this.listeners) {
        return this;
      }
      var args = Array.prototype.slice.call(arguments, 1);
      var events = this.listeners[name] || [];
      for (var i = 0; i < events.length; i++) {
        events[i].callback.apply(this, args);
      }
      return this;
    }
  };
  _extend(Treasure.prototype, Events);
  _extend(Treasure, Events);

  Treasure.loaded = true;

  // Expose utils
  Treasure.utils = {
    each: _each,
    extend: _extend,
    parseParams: _parse_params
  };

  Treasure.ready = function(callback){
    Treasure.on('ready', callback);
  };

  Treasure.log = function(message) {
    if (typeof console === 'object') {
      console.log('[Treasure]', message);
    }
  };

  // -------------------------------
  // Treasure.Plugins
  // -------------------------------

  var Plugins = Treasure.Plugins = {};
<|endoftext|>


<commit_before>/**
* @license GrapeFruit Game Engine
* Copyright (x) 2012, Chad Engler
*
* GrapeFruit is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
*/

/****************************************************************************
 * Global GrapeFruit Object with constants
 ****************************************************************************/
window.gf = window.gf || {
    types: {
        //Entity types
        ENTITY: {
            PLAYER: 'player',
            ENEMY: 'enemy',
            FRIENDLY: 'friendly',
            NEUTRAL: 'neutral',
            COLLECTABLE: 'collectable'
        },
        //Layer types
        LAYER: {
            TILE_LAYER: 'tilelayer',
            OBJECT_GROUP: 'objectgroup' // each zone is defined as an object group
        },
        //Tile collision types
        COLLISION: {
            NONE: 'none',
            SOLID: 'solid',
            CLIFF: 'cliff',
            LADDER: 'ladder',
            WATER: 'water',
            DEEP_WATER: 'deep_water'
        },
        //pubsub events
        EVENT: {
            ENTITY_MOVE: 'gf.entity.move',
            LOADER_START: 'gf.loader.start',
            LOADER_ERROR: 'gf.loader.error',
            LOADER_PROGRESS: 'gf.loader.progress',
            LOADER_LOAD: 'gf.loader.load',
            LOADER_COMPLETE: 'gf.loader.complete'
        },
        //Bindable keycodes
        KEY: {
            BACKSPACE: 8,
            TAB: 9,
            ENTER: 13,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            PAUSE: 19,
            ESC: 27,
            SPACE: 32,
            PAGE_UP: 33,
            PAGE_DOWN: 34,
            END: 35,
            HOME: 36,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            INSERT: 45,
            DELETE: 46,
            NUM0: 48,
            NUM1: 49,
            NUM2: 50,
            NUM3: 51,
            NUM4: 52,
            NUM5: 53,
            NUM6: 54,
            NUM7: 55,
            NUM8: 56,
            NUM9: 57,
            PLUS: 61,
            A : 65,
            B : 66,
            C : 67,
            D : 68,
            E : 69,
            F : 70,
            G : 71,
            H : 72,
            I : 73,
            J : 74,
            K : 75,
            L : 76,
            M : 77,
            N : 78,
            O : 79,
            P : 80,
            Q : 81,
            R : 82,
            S : 83,
            T : 84,
            U : 85,
            V : 86,
            W : 87,
            X : 88,
            Y : 89,
            Z : 90,
            NUMPAD0: 96,
            NUMPAD1: 97,
            NUMPAD2: 98,
            NUMPAD3: 99,
            NUMPAD4: 100,
            NUMPAD5: 101,
            NUMPAD6: 102,
            NUMPAD7: 103,
            NUMPAD8: 104,
            NUMPAD9: 105,
            NUMPAD_STAR: 106,
            NUMPAD_PLUS: 107,
            NUMPAD_MINUS: 109,
            NUMPAD_DOT: 110,
            NUMPAD_SLASH: 111,
            F1: 112,
            F2: 113,
            F3: 114,
            F4: 115,
            MINUS: 173,
            TILDE: 192
        }
    },
    support: {
        canvas: !! window.CanvasRenderingContext2D,
        webgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(),
        workers: !! window.Worker,
        fileapi: window.File && window.FileReader && window.FileList && window.Blob,
    }
};

/****************************************************************************
 * Javascript Inheritance Helper (use functional mixins instead?)
 ****************************************************************************/

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

// The base Class implementation (does nothing)
Class = function() {};

// Create a new Class that inherits from this class
Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
        // Check if we're overwriting an existing function
        prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
                return function() {
                    var tmp = this._super;

                    // Add a new ._super() method that is the same method
                    // but on the super-class
                    this._super = _super[name];

                    // The method only need to be bound temporarily, so we
                    // remove it when we're done executing
                    var ret = fn.apply(this, arguments);
                    this._super = tmp;

                    return ret;
                };
            })(name, prop[name]) :
            prop[name];
    }

    // The dummy class constructor
    Class = function () {
        // All construction is actually done in the init method
        if ( !initializing && this.init )
            this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
};

/****************************************************************************
 * Main game object
 ****************************************************************************/

(function() {
    gf.game = {
        //array of objects in the scene
        objects: {},
        numObjects: 0,

        //special user-defined entity types
        entTypes: {},

        //maximum Z index, where the camera lies
        MAX_Z: 500,

        //raw THREE objects that will control rendering
        _scene: new THREE.Scene(),
        _clock: new THREE.Clock(false),
        _renderer: null,
        _camera: null,

        //id for the next entity to be added
        _nextId: Date.now(),

        //the object that will contain the render domElement
        _$cont: null,

        //have we initialized the game already?
        _initialized: false,

        init: function(contId, width, height, renderMethod) {
            if(gf.controls._initialized) return;

            //if they speciy a method, check if it is available
            if(renderMethod) {
                if(!gf.support[renderMethod]) {
                    throw 'Render method ' + renderMethod + ' is not supported by this browser!';
                    return;
                }
            }
            //if they don't specify a method, guess the best to use
            else {
                if(gf.support.webgl) renderMethod = 'webgl';
                else if(gf.support.canvas) renderMethod = 'canvas';
                else {
                    throw 'Neither WebGL nor Canvas is supported by this browser!';
                    return;
                }
            }

            //initialize the correct renderer
            renderMethod = 'webgl';
            if(renderMethod == 'webgl') {
                gf.game._renderer = new THREE.WebGLRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                    precision: 'highp',
                    alpha: true,
                    premultipliedAlpha: true,
                    antialias: false,
                    clearColor: 0xff00ff,
                    clearAlpha: 0,
                    maxLights: 4
                });
            } else if(renderMethod == 'canvas') {
                gf.game._renderer = new THREE.CanvasRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                });
            }

            gf.game._renderMethod = renderMethod;

            //cache the container object
            gf.game._$cont = $('#' + contId);

            var w = width || gf.game._$cont.width(),
                h = height || gf.game._$cont.height();

            //initialize the renderer
            gf.game._renderer.setSize(w, h);
            gf.game._$cont.append(gf.game._renderer.domElement);
            gf.game._$domElement = $(gf.game._renderer.domElement);

            //initialize the camera
            gf.game._camera = new THREE.OrthographicCamera(w / -2, w / 2, h / 2, h / -2, 1, 1000);
            gf.game._camera.position.z = gf.game.MAX_Z;

            gf.game._scene.add(this.camera);

            //add ambient light to the scene
            gf.game._scene.add(new THREE.AmbientLight(0xffffff));

            //initialize the controls
            gf.controls.init();

            //initialize the audio player
            gf.audio.init();

            //initialize the GUI (HUD, menus, etc)
            gf.gui.init();

            //fps counter
            if(gf.debug.showFps) {
                gf.debug._fpsCounter = new gf.debug.FpsCounter();
                gf.utils.each(gf.debug.fpsStyle, function(k, v) { gf.debug._fpsCounter.domElement.style[k] = v; });
                document.body.appendChild(gf.debug._fpsCounter.domElement);
            }

            //debug info
            if(gf.debug.showInfo) {
                gf.debug._info = new gf.debug.Info();
                gf.utils.each(gf.debug.infoStyle, function(k, v) { gf.debug._info.domElement.style[k] = v; });
                document.body.appendChild(gf.debug._info.domElement);
            }

            gf.game._initialized = true;

            return this;
        },
        getNextObjectId: function() {
            return gf.game._nextId++;
        },
        addObject: function(obj) {
            if(!obj) return;

            if(!obj.id) obj.id = gf.game.getNextObjectId();
            gf.game.objects[obj.id] = obj;
            gf.game.numObjects++;

            if(obj.addToScene) obj.addToScene(gf.game._scene);

            if(obj.type == gf.types.ENTITY.PLAYER)
                gf.game.player = obj;

            return this;
        },
        removeObject: function(obj) {
            if(!obj) return;

            //remove object from our list
            delete gf.game.objects[obj.id];
            gf.game.numObjects--;

            if(obj.removeFromScene) obj.removeFromScene(gf.game._scene);

            if(obj.type == gf.types.ENTITY.PLAYER)
                gf.game.player = null;

            //deallocate resources for this entity
            gf.game._renderer.deallocateObject(obj._mesh);
            gf.game._renderer.deallocateObject(obj._hitboxMesh);

            return this;
        },
        loadWorld: function(world) {
            if(typeof world == 'string'){
                if(gf.resources[world]) world = gf.resources[world].data;
                else {
                    throw 'World not found in resources!';
                    return;
                }
            }

            gf.game.world = new gf.TiledMap(world);
            gf.game.addObject(gf.game.world);
        },
        render: function() {
            gf.game._clock.start();
            gf.game._tick();

            return this;
        },
        //Check if passed entity collides with any others
        checkCollisions: function(obj) {
            var colliders = [];

            $.each(gf.game.objects, function(id, o) {
                //check if this object collides with any others
                if(o.inViewport && o.isVisible && o.isCollidable && o.isEntity && (o != obj)) {
                    var collisionVector = o.checkCollision(obj);
                    if(!collisionVector.isZero()) {
                        colliders.push({
                            entity: o,
                            vector: collisionVector
                        });
                        o.onCollision(obj);
                    }
                }
            });

            return colliders;
        },
        //check if passed entity collides with any map tile after applying the velocity movement
        checkMapCollision: function() {

        },
        //lock the camera on an entity
        //I need an event system :/
        cameraTrack: function(ent) {
            if(ent.isEntity) {
                if(this._trackedEntMoveHandle) {
                    gf.event.unsubscribe(this._trackedEntMoveHandle);
                }

                this._trackedEntMoveHandle = gf.event.subscribe(gf.types.EVENT.ENTITY_MOVE + '.' + ent.id, function(velocity) {
                    gf.game._camera.translateX(velocity.x);
                    gf.game._camera.translateY(velocity.y);

                    //If this gets heavy, then just remove it
                    //update if each object is within the viewport

                    //update matrices
                    //gf.game._camera.updateMatrix(); // make sure camera's local matrix is updated
                    //gf.game._camera.updateMatrixWorld(); // make sure camera's world matrix is updated
                    //gf.game._camera.matrixWorldInverse.getInverse( camera.matrixWorld );
                    var frustum = new THREE.Frustum();
                    frustum.setFromMatrix(new THREE.Matrix4().multiply(gf.game._camera.projectionMatrix, gf.game._camera.matrixWorldInverse));
                    gf.utils.each(gf.game.objects, function(id, o) {
                        if(o.isEntity) {
                            //o._mesh.updateMatrix(); // make sure plane's local matrix is updated
                            //o._mesh.updateMatrixWorld(); // make sure plane's world matrix is updated
                            o.inViewport = frustum.contains(o._mesh);
                        }
                    });
                });
            }

            return this;
        },
        _tick: function() {
            //start render loop
            requestAnimationFrame(gf.game._tick);

            //get clock delta
            gf.game._delta = gf.game._clock.getDelta();

            //update fps box
            if(gf.debug._fpsCounter) gf.debug._fpsCounter.update();

            //update debug info
            if(gf.debug._info) gf.debug._info.update();

            //update each object
            gf.utils.each(gf.game.objects, function(id, o) {
                if(o.inViewport && o.isVisible) {
                    o.update();
                }
            });

            //render scene
            gf.game._renderer.render(gf.game._scene, gf.game._camera);
        }
    };
})();<commit_msg>fixing potential bugs<commit_after>/**
* @license GrapeFruit Game Engine
* Copyright (x) 2012, Chad Engler
*
* GrapeFruit is licensed under the MIT License.
* http://www.opensource.org/licenses/mit-license.php
*
*/

/****************************************************************************
 * Global GrapeFruit Object with constants
 ****************************************************************************/
window.gf = window.gf || {
    types: {
        //Entity types
        ENTITY: {
            PLAYER: 'player',
            ENEMY: 'enemy',
            FRIENDLY: 'friendly',
            NEUTRAL: 'neutral',
            COLLECTABLE: 'collectable'
        },
        //Layer types
        LAYER: {
            TILE_LAYER: 'tilelayer',
            OBJECT_GROUP: 'objectgroup' // each zone is defined as an object group
        },
        //Tile collision types
        COLLISION: {
            NONE: 'none',
            SOLID: 'solid',
            CLIFF: 'cliff',
            LADDER: 'ladder',
            WATER: 'water',
            DEEP_WATER: 'deep_water'
        },
        //pubsub events
        EVENT: {
            ENTITY_MOVE: 'gf.entity.move',
            LOADER_START: 'gf.loader.start',
            LOADER_ERROR: 'gf.loader.error',
            LOADER_PROGRESS: 'gf.loader.progress',
            LOADER_LOAD: 'gf.loader.load',
            LOADER_COMPLETE: 'gf.loader.complete'
        },
        //Bindable keycodes
        KEY: {
            BACKSPACE: 8,
            TAB: 9,
            ENTER: 13,
            SHIFT: 16,
            CTRL: 17,
            ALT: 18,
            PAUSE: 19,
            ESC: 27,
            SPACE: 32,
            PAGE_UP: 33,
            PAGE_DOWN: 34,
            END: 35,
            HOME: 36,
            LEFT: 37,
            UP: 38,
            RIGHT: 39,
            DOWN: 40,
            INSERT: 45,
            DELETE: 46,
            NUM0: 48,
            NUM1: 49,
            NUM2: 50,
            NUM3: 51,
            NUM4: 52,
            NUM5: 53,
            NUM6: 54,
            NUM7: 55,
            NUM8: 56,
            NUM9: 57,
            PLUS: 61,
            A : 65,
            B : 66,
            C : 67,
            D : 68,
            E : 69,
            F : 70,
            G : 71,
            H : 72,
            I : 73,
            J : 74,
            K : 75,
            L : 76,
            M : 77,
            N : 78,
            O : 79,
            P : 80,
            Q : 81,
            R : 82,
            S : 83,
            T : 84,
            U : 85,
            V : 86,
            W : 87,
            X : 88,
            Y : 89,
            Z : 90,
            NUMPAD0: 96,
            NUMPAD1: 97,
            NUMPAD2: 98,
            NUMPAD3: 99,
            NUMPAD4: 100,
            NUMPAD5: 101,
            NUMPAD6: 102,
            NUMPAD7: 103,
            NUMPAD8: 104,
            NUMPAD9: 105,
            NUMPAD_STAR: 106,
            NUMPAD_PLUS: 107,
            NUMPAD_MINUS: 109,
            NUMPAD_DOT: 110,
            NUMPAD_SLASH: 111,
            F1: 112,
            F2: 113,
            F3: 114,
            F4: 115,
            MINUS: 173,
            TILDE: 192
        }
    },
    support: {
        canvas: !! window.CanvasRenderingContext2D,
        webgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(),
        workers: !! window.Worker,
        fileapi: window.File && window.FileReader && window.FileList && window.Blob,
    }
};

/****************************************************************************
 * Javascript Inheritance Helper (use functional mixins instead?)
 ****************************************************************************/

/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype
var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

// The base Class implementation (does nothing)
Class = function() {};

// Create a new Class that inherits from this class
Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
        // Check if we're overwriting an existing function
        prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
                return function() {
                    var tmp = this._super;

                    // Add a new ._super() method that is the same method
                    // but on the super-class
                    this._super = _super[name];

                    // The method only need to be bound temporarily, so we
                    // remove it when we're done executing
                    var ret = fn.apply(this, arguments);
                    this._super = tmp;

                    return ret;
                };
            })(name, prop[name]) :
            prop[name];
    }

    // The dummy class constructor
    Class = function () {
        // All construction is actually done in the init method
        if ( !initializing && this.init )
            this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
};

/****************************************************************************
 * Main game object
 ****************************************************************************/

(function() {
    gf.game = {
        //array of objects in the scene
        objects: {},
        numObjects: 0,

        //special user-defined entity types
        entTypes: {},

        //maximum Z index, where the camera lies
        MAX_Z: 500,

        //raw THREE objects that will control rendering
        _scene: new THREE.Scene(),
        _clock: new THREE.Clock(false),
        _renderer: null,
        _camera: null,

        //id for the next entity to be added
        _nextId: Date.now(),

        //the object that will contain the render domElement
        _$cont: null,

        //have we initialized the game already?
        _initialized: false,

        init: function(contId, width, height, renderMethod) {
            if(gf.controls._initialized) return;

            //if they speciy a method, check if it is available
            if(renderMethod) {
                if(!gf.support[renderMethod]) {
                    throw 'Render method ' + renderMethod + ' is not supported by this browser!';
                    return;
                }
            }
            //if they don't specify a method, guess the best to use
            else {
                if(gf.support.webgl) renderMethod = 'webgl';
                else if(gf.support.canvas) renderMethod = 'canvas';
                else {
                    throw 'Neither WebGL nor Canvas is supported by this browser!';
                    return;
                }
            }

            //initialize the correct renderer
            renderMethod = 'webgl';
            if(renderMethod == 'webgl') {
                gf.game._renderer = new THREE.WebGLRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                    precision: 'highp',
                    alpha: true,
                    premultipliedAlpha: true,
                    antialias: false,
                    clearColor: 0xff00ff,
                    clearAlpha: 0,
                    maxLights: 4
                });
            } else if(renderMethod == 'canvas') {
                gf.game._renderer = new THREE.CanvasRenderer({
                    //can also specify 'canvas' dom element, but we just let THREE generate one
                });
            }

            gf.game._renderMethod = renderMethod;

            //cache the container object
            gf.game._$cont = $('#' + contId);

            var w = width || gf.game._$cont.width(),
                h = height || gf.game._$cont.height();

            //initialize the renderer
            gf.game._renderer.setSize(w, h);
            gf.game._$cont.append(gf.game._renderer.domElement);
            gf.game._$domElement = $(gf.game._renderer.domElement);

            //initialize the camera
            gf.game._camera = new THREE.OrthographicCamera(w / -2, w / 2, h / 2, h / -2, 1, 1000);
            gf.game._camera.position.z = gf.game.MAX_Z;

            gf.game._scene.add(this.camera);

            //add ambient light to the scene
            gf.game._scene.add(new THREE.AmbientLight(0xffffff));

            //initialize the controls
            gf.controls.init();

            //initialize the audio player
            gf.audio.init();

            //initialize the GUI (HUD, menus, etc)
            gf.gui.init();

            //fps counter
            if(gf.debug.showFps) {
                gf.debug._fpsCounter = new gf.debug.FpsCounter();
                gf.utils.each(gf.debug.fpsStyle, function(k, v) { gf.debug._fpsCounter.domElement.style[k] = v; });
                document.body.appendChild(gf.debug._fpsCounter.domElement);
            }

            //debug info
            if(gf.debug.showInfo) {
                gf.debug._info = new gf.debug.Info();
                gf.utils.each(gf.debug.infoStyle, function(k, v) { gf.debug._info.domElement.style[k] = v; });
                document.body.appendChild(gf.debug._info.domElement);
            }

            gf.game._initialized = true;

            return this;
        },
        getNextObjectId: function() {
            return gf.game._nextId++;
        },
        addObject: function(obj) {
            if(!obj) return;

            if(!obj.id) obj.id = gf.game.getNextObjectId();
            gf.game.objects[obj.id] = obj;
            gf.game.numObjects++;

            if(obj.addToScene) obj.addToScene(gf.game._scene);

            if(obj.type == gf.types.ENTITY.PLAYER)
                gf.game.player = obj;

            return this;
        },
        removeObject: function(obj) {
            if(!obj) return;

            //remove object from our list
            delete gf.game.objects[obj.id];
            gf.game.numObjects--;

            if(obj.removeFromScene) obj.removeFromScene(gf.game._scene);

            if(obj.type == gf.types.ENTITY.PLAYER)
                gf.game.player = null;

            //deallocate resources for this entity
            gf.game._renderer.deallocateObject(obj._mesh);
            gf.game._renderer.deallocateObject(obj._hitboxMesh);

            return this;
        },
        loadWorld: function(world) {
            if(typeof world == 'string'){
                if(gf.resources[world]) world = gf.resources[world].data;
                else {
                    throw 'World not found in resources!';
                    return;
                }
            }

            gf.game.world = new gf.TiledMap(world);
            gf.game.addObject(gf.game.world);
        },
        render: function() {
            gf.game._clock.start();
            gf.game._tick();

            return this;
        },
        //Check if passed entity collides with any others
        checkCollisions: function(obj) {
            var colliders = [];

            $.each(gf.game.objects, function(id, o) {
                //check if this object collides with any others
                if(o.inViewport && o.isVisible && o.isCollidable && o.isEntity && (o != obj)) {
                    var collisionVector = o.checkCollision(obj);
                    if(!collisionVector.isZero()) {
                        colliders.push({
                            entity: o,
                            vector: collisionVector
                        });
                        o.onCollision(obj);
                    }
                }
            });

            return colliders;
        },
        //check if passed entity collides with any map tile after applying the velocity movement
        checkMapCollision: function() {

        },
        //lock the camera on an entity
        cameraTrack: function(ent) {
            if(ent.isEntity) {
                if(this._trackedEntMoveHandle) {
                    gf.event.unsubscribe(this._trackedEntMoveHandle);
                }

                this._trackedEntMoveHandle = gf.event.subscribe(gf.types.EVENT.ENTITY_MOVE + '.' + ent.id, function(velocity) {
                    gf.game._camera.translateX(velocity.x);
                    gf.game._camera.translateY(velocity.y);

                    //If this gets heavy, then just remove it
                    //update if each object is within the viewport

                    //update matrices
                    //gf.game._camera.updateMatrix(); // make sure camera's local matrix is updated
                    //gf.game._camera.updateMatrixWorld(); // make sure camera's world matrix is updated
                    //gf.game._camera.matrixWorldInverse.getInverse( camera.matrixWorld );
                    var frustum = new THREE.Frustum();
                    frustum.setFromMatrix(new THREE.Matrix4().multiply(gf.game._camera.projectionMatrix, gf.game._camera.matrixWorldInverse));
                    gf.utils.each(gf.game.objects, function(id, o) {
                        if(o.isEntity) {
                            //o._mesh.updateMatrix(); // make sure plane's local matrix is updated
                            //o._mesh.updateMatrixWorld(); // make sure plane's world matrix is updated
                            o.inViewport = frustum.contains(o._mesh);
                        }
                    });
                });
            }

            return this;
        },
        _tick: function() {
            //start render loop
            requestAnimationFrame(gf.game._tick);

            //get clock delta
            gf.game._delta = gf.game._clock.getDelta();

            //update fps box
            if(gf.debug._fpsCounter) gf.debug._fpsCounter.update();

            //update debug info
            if(gf.debug._info) gf.debug._info.update();

            //update each object
            gf.utils.each(gf.game.objects, function(id, o) {
                if(o.inViewport && o.isVisible && o.update) {
                    o.update();
                }
            });

            //render scene
            gf.game._renderer.render(gf.game._scene, gf.game._camera);
        }
    };
})();<|endoftext|>


<commit_before>/*!
 * jQuery Lifestream Plug-in
 * @version 0.1.4
 * Show a stream of your online activity
 *
 * Copyright 2011, Christian Vuerings - http://denbuzze.com
 */
/*globals jQuery, $ */
;(function( $ ){

  /**
   * Initialize the lifestream plug-in
   * @param {Object} config Configuration object
   */
  $.fn.lifestream = function( config ) {

    // Make the plug-in chainable
    return this.each(function() {

      // The element where the lifestream is linked to
      var outputElement = $(this),

      // Extend the default settings with the values passed
      settings = jQuery.extend({
        // The name of the main lifestream class
        // We use this for the main ul class e.g. lifestream
        // and for the specific feeds e.g. lifestream-twitter
        classname: "lifestream",
        // Callback function which will be triggered when a feed is loaded
        feedloaded: null,
        // The amount of feed items you want to show
        limit: 10,
        // An array of feed items which you want to use
        list: []
      }, config),

      // The data object contains all the feed items
      data = {
        count: settings.list.length,
        items: []
      },

      // We use the item settings to pass the global settings variable to
      // every feed
      itemsettings = jQuery.extend( true, {}, settings ),

      /**
       * This method will be called every time a feed is loaded. This means
       * that several DOM changes will occur. We did this because otherwise it
       * takes to look before anything shows up.
       * We allow 1 request per feed - so 1 DOM change per feed
       * @private
       * @param {Array} inputdata an array containing all the feeditems for a
       * specific feed.
       */
      finished = function( inputdata ) {

        // Merge the feed items we have from other feeds, with the feeditems
        // from the new feed
        $.merge( data.items, inputdata );

        // Sort the feeditems by date - we want the most recent one first
        data.items.sort( function( a, b ) {
            return ( b.date - a.date );
        });

        var items = data.items,

            // We need to check whether the amount of current feed items is
            // smaller than the main limit. This parameter will be used in the
            // for loop
            length = ( items.length < settings.limit ) ?
              items.length :
              settings.limit,
            i = 0, item,

            // We create an unordered list which will create all the feed
            // items
            ul = $('
');

        // Run over all the feed items + add them as list items to the
        // unordered list
        for ( ; i < length; i++ ) {
          item = items[i];
          if ( item.html ) {
            $('
').append( item.html )
                                           .appendTo( ul );
          }
        }

        // Change the innerHTML with a list of all the feeditems in
        // chronological order
        outputElement.html( ul );

        // Trigger the feedloaded callback, if it is a function
        if ( $.isFunction( settings.feedloaded ) ) {
          settings.feedloaded();
        }

      },

      /**
       * Fire up all the feeds and pass them the right arugments.
       * @private
       */
      load = function() {

        var i = 0, j = settings.list.length;

        // We don't pass the list array to each feed  because this will create
        // a recursive JavaScript object
        delete itemsettings.list;

        // Run over all the items in the list
        for( ; i < j; i++ ) {

          var config = settings.list[i];

          // Check whether the feed exists, if the feed is a function and if a
          // user has been filled in
          if ( $.fn.lifestream.feeds[config.service] &&
               $.isFunction( $.fn.lifestream.feeds[config.service] )
               && config.user) {

            // You'll be able to get the global settings by using
            // config._settings in your feed
            config._settings = itemsettings;

            // Call the feed with a config object and finished callback
            $.fn.lifestream.feeds[config.service]( config, finished );
          }

        }

      };

      // Load the jQuery templates plug-in if it wasn't included in the page.
      // At then end we call the load method.
      if( !jQuery.tmpl ) {
        jQuery.getScript(
          "https://raw.github.com/jquery/jquery-tmpl/master/"
            + "jquery.tmpl.min.js",
          load);
      } else {
        load();
      }

    });

  };

  /**
   * Create a valid YQL URL by passing in a query
   * @param {String} query The query you want to convert into a valid yql url
   * @return {String} A valid YQL URL
   */
  $.fn.lifestream.createYqlUrl = function( query ) {
      return ( "http://query.yahooapis.com/v1/public/yql?q=__QUERY__&env=" +
      "store://datatables.org/alltableswithkeys&format=json")
        .replace( "__QUERY__" , encodeURIComponent( query ) );
  };

  /**
   * A big container which contains all available feeds
   */
  $.fn.lifestream.feeds = $.fn.lifestream.feeds || {};

}( jQuery ));
<commit_msg>Update core.js with main jquery-lifestream.js file<commit_after>/*!
 * jQuery Lifestream Plug-in
 * @version 0.1.5
 * Show a stream of your online activity
 *
 * Copyright 2011, Christian Vuerings - http://denbuzze.com
 */
/*globals jQuery, $ */
;(function( $ ){

  /**
   * Initialize the lifestream plug-in
   * @param {Object} config Configuration object
   */
  $.fn.lifestream = function( config ) {

    // Make the plug-in chainable
    return this.each(function() {

      // The element where the lifestream is linked to
      var outputElement = $(this),

      // Extend the default settings with the values passed
      settings = jQuery.extend({
        // The name of the main lifestream class
        // We use this for the main ul class e.g. lifestream
        // and for the specific feeds e.g. lifestream-twitter
        classname: "lifestream",
        // Callback function which will be triggered when a feed is loaded
        feedloaded: null,
        // The amount of feed items you want to show
        limit: 10,
        // An array of feed items which you want to use
        list: []
      }, config),

      // The data object contains all the feed items
      data = {
        count: settings.list.length,
        items: []
      },

      // We use the item settings to pass the global settings variable to
      // every feed
      itemsettings = jQuery.extend( true, {}, settings ),

      /**
       * This method will be called every time a feed is loaded. This means
       * that several DOM changes will occur. We did this because otherwise it
       * takes to look before anything shows up.
       * We allow 1 request per feed - so 1 DOM change per feed
       * @private
       * @param {Array} inputdata an array containing all the feeditems for a
       * specific feed.
       */
      finished = function( inputdata ) {

        // Merge the feed items we have from other feeds, with the feeditems
        // from the new feed
        $.merge( data.items, inputdata );

        // Sort the feeditems by date - we want the most recent one first
        data.items.sort( function( a, b ) {
            return ( b.date - a.date );
        });

        var items = data.items,

            // We need to check whether the amount of current feed items is
            // smaller than the main limit. This parameter will be used in the
            // for loop
            length = ( items.length < settings.limit ) ?
              items.length :
              settings.limit,
            i = 0, item,

            // We create an unordered list which will create all the feed
            // items
            ul = $('
');

        // Run over all the feed items + add them as list items to the
        // unordered list
        for ( ; i < length; i++ ) {
          item = items[i];
          if ( item.html ) {
            $('
').data( "time", item.date )
                                           .append( item.html )
                                           .appendTo( ul );
          }
        }

        // Change the innerHTML with a list of all the feeditems in
        // chronological order
        outputElement.html( ul );

        // Trigger the feedloaded callback, if it is a function
        if ( $.isFunction( settings.feedloaded ) ) {
          settings.feedloaded();
        }

      },

      /**
       * Fire up all the feeds and pass them the right arugments.
       * @private
       */
      load = function() {

        var i = 0, j = settings.list.length;

        // We don't pass the list array to each feed  because this will create
        // a recursive JavaScript object
        delete itemsettings.list;

        // Run over all the items in the list
        for( ; i < j; i++ ) {

          var config = settings.list[i];

          // Check whether the feed exists, if the feed is a function and if a
          // user has been filled in
          if ( $.fn.lifestream.feeds[config.service] &&
               $.isFunction( $.fn.lifestream.feeds[config.service] )
               && config.user) {

            // You'll be able to get the global settings by using
            // config._settings in your feed
            config._settings = itemsettings;

            // Call the feed with a config object and finished callback
            $.fn.lifestream.feeds[config.service]( config, finished );
          }

        }

      };

      // Load the jQuery templates plug-in if it wasn't included in the page.
      // At then end we call the load method.
      if( !jQuery.tmpl ) {
        jQuery.getScript(
          "https://raw.github.com/jquery/jquery-tmpl/master/"
            + "jquery.tmpl.min.js",
          load);
      } else {
        load();
      }

    });

  };

  /**
   * Create a valid YQL URL by passing in a query
   * @param {String} query The query you want to convert into a valid yql url
   * @return {String} A valid YQL URL
   */
  $.fn.lifestream.createYqlUrl = function( query ) {
      return ( "http://query.yahooapis.com/v1/public/yql?q=__QUERY__&env=" +
      "store://datatables.org/alltableswithkeys&format=json")
        .replace( "__QUERY__" , encodeURIComponent( query ) );
  };

  /**
   * A big container which contains all available feeds
   */
  $.fn.lifestream.feeds = $.fn.lifestream.feeds || {};

}( jQuery ));<|endoftext|>


<commit_before>/**
 * Created by keyvan on 8/16/16.
 */

import {v1 as neo4j} from 'neo4j-driver';
import fs from 'file-system';
import chalk from 'chalk';
import parseNeo4jResponse from './parser';
import {parseNeo4jInts} from './preprocess';
import {pipe} from './util';

class Neo4jConnection {
    constructor({boltUrl, user, password} = {}) {
        this.queryDict = {};

        this.driver = neo4j.driver(boltUrl, neo4j.auth.basic(user, password));
        const session = this.driver.session();
        this.initialized = session.run('RETURN "Neo4j instance successfully connected."')
            .then((result) => {
                console.log(chalk.green(parseNeo4jResponse(result)));
                session.close();
            })
            .catch(error => {
                console.error(
                    chalk.red('Error connecting to the Neo4j instance, check connection options'));
                throw error;
            });
    }

    addCypherQueryFile(cypherQueryFilePath) {
        this.queryDict[cypherQueryFilePath] = fs.readFileSync(cypherQueryFilePath, 'utf8');
    }

    executeCypher(cypherQueryFilePath, queryParams) {
        return new Promise((resolve, reject) => {
            if (!this.queryDict[cypherQueryFilePath])
                this.addCypherQueryFile(cypherQueryFilePath);

            const query = this.queryDict[cypherQueryFilePath];
            const session = this.driver.session();

            session.run(query, queryParams)
                .then(result => {
                    resolve(result);
                    session.close();
                })
                .catch(reject);
        })
            .then(parseNeo4jResponse);
    }
}

class API {
    constructor(neo4jConnection, {method, route, cypherQueryFile,
        allowedRoles = [], parseIdSkipLimit = true,
        preProcess = params => params, postProcess = result => result} = {}) {
        this.neo4jConnection = neo4jConnection;
        this.method = method;
        this.route = route;
        this.allowedRoles = allowedRoles;
        this.requiresJwtAuthentication = allowedRoles &&
            Array.isArray(allowedRoles) && allowedRoles.length > 0;

        this.response = params => {
            let preProcessToUse = preProcess;
            if (parseIdSkipLimit) {
                const keys = [];
                for (const key of ['id', 'skip', 'limit'])
                    if (params[key])
                        keys.push(key);
                if (keys.length > 0)
                    preProcessToUse = pipe(parseNeo4jInts(...keys), preProcess);
            }
            return Promise.resolve(preProcessToUse.apply(this, [params]))
                .then(params => neo4jConnection.executeCypher(cypherQueryFile, params))
                .then(postProcess);
        };
    }
}

export {API, Neo4jConnection};
<commit_msg>back to bolt<commit_after>/**
 * Created by keyvan on 8/16/16.
 */

import {v1 as neo4j} from 'neo4j-driver';
import fs from 'file-system';
import chalk from 'chalk';
import parseNeo4jResponse from './parser';
import {parseNeo4jInts} from './preprocess';
import {pipe} from './util';

class Neo4jConnection {
    constructor({boltUrl, user, password} = {}) {
        this.queryDict = {};

        this.driver = neo4j.driver(boltUrl, neo4j.auth.basic(user, password));
        const session = this.driver.session();
        this.initialized = session.run('RETURN "Neo4j instance successfully connected."')
            .then((result) => {
                console.log(chalk.green(parseNeo4jResponse(result)));
                session.close();
            })
            .catch(error => {
                console.error(
                    chalk.red('Error connecting to the Neo4j instance, check connection options'));
                console.log(error);
                throw error;
            });
    }

    addCypherQueryFile(cypherQueryFilePath) {
        this.queryDict[cypherQueryFilePath] = fs.readFileSync(cypherQueryFilePath, 'utf8');
    }

    executeCypher(cypherQueryFilePath, queryParams) {
        return new Promise((resolve, reject) => {
            if (!this.queryDict[cypherQueryFilePath])
                this.addCypherQueryFile(cypherQueryFilePath);

            const query = this.queryDict[cypherQueryFilePath];
            const session = this.driver.session();

            session.run(query, queryParams)
                .then(result => {
                    resolve(result);
                    session.close();
                })
                .catch(reject);
        })
            .then(parseNeo4jResponse);
    }
}

class API {
    constructor(neo4jConnection, {method, route, cypherQueryFile,
        allowedRoles = [], parseIdSkipLimit = true,
        preProcess = params => params, postProcess = result => result} = {}) {
        this.neo4jConnection = neo4jConnection;
        this.method = method;
        this.route = route;
        this.allowedRoles = allowedRoles;
        this.requiresJwtAuthentication = allowedRoles &&
            Array.isArray(allowedRoles) && allowedRoles.length > 0;

        this.response = params => {
            let preProcessToUse = preProcess;
            if (parseIdSkipLimit) {
                const keys = [];
                for (const key of ['id', 'skip', 'limit'])
                    if (params[key])
                        keys.push(key);
                if (keys.length > 0)
                    preProcessToUse = pipe(parseNeo4jInts(...keys), preProcess);
            }
            return Promise.resolve(preProcessToUse.apply(this, [params]))
                .then(params => neo4jConnection.executeCypher(cypherQueryFile, params))
                .then(postProcess);
        };
    }
}

export {API, Neo4jConnection};
<|endoftext|>


<commit_before>'use strict'

const assert = require('assert')

const { parse } = require('./parser')
const Bitmask = require('./bitmask')

const P = new WeakMap()
const U = new WeakMap()
const A = new WeakMap()
const X = new WeakMap()

class ExtDate extends Date {
  static parse(input) {
    return parse(input, { types: ['date'] })
  }

  constructor(...args) { // eslint-disable-line complexity
    let precision, uncertain, approximate, unspecified

    switch (args.length) {
    case 0:
      break

    case 1:
      switch (typeof args[0]) {
      case 'number':
        break

      case 'string':
        args = [ExtDate.parse(args[0])]
        // eslint-disable-line no-fallthrough

      case 'object':
        {
          let obj = args[0]

          //assert.equal('date', obj.type)
          assert(obj.values)
          assert(obj.values.length)

          precision = obj.values.length
          args = obj.values.slice()

          // ECMA Date constructor needs at least two date parts!
          if (args.length < 2) args.push(0)

          // TODO handle 0-99 years ECMA Date constructor
          // TODO handle offset!

          args = [Date.UTC(...args)]

          //;({ uncertain, approximate, unspecified, offset } = obj)
        }
        break

      default:
        throw new RangeError('Invalid time value')
      }

      break

    default:
      precision = args.length
    }

    super(...args)

    this.precision = precision

    this.uncertain = uncertain
    this.approximate = approximate
    this.unspecified = unspecified
  }

  set precision(value) {
    P[this] = Number(value)
  }

  get precision() {
    return P[this]
  }

  set uncertain(value) {
    U[this] = new Bitmask(value)
  }

  get uncertain() {
    return U[this]
  }

  set approximate(value) {
    A[this] = new Bitmask(value)
  }

  get approximate() {
    return A[this]
  }

  set unspecified(value) {
    X[this] = new Bitmask(value)
  }

  get unspecified() {
    return X[this]
  }

  toISOString() {
    //return super()
  }

  toJSON() {
    return this.toISOString()
  }
}

module.exports = ExtDate
<commit_msg>Ensure dates are dates<commit_after>'use strict'

const assert = require('assert')

const { parse } = require('./parser')
const Bitmask = require('./bitmask')

const P = new WeakMap()
const U = new WeakMap()
const A = new WeakMap()
const X = new WeakMap()

class ExtDate extends Date {
  static parse(input) {
    return parse(input, { types: ['date'] })
  }

  constructor(...args) { // eslint-disable-line complexity
    let precision, uncertain, approximate, unspecified

    switch (args.length) {
    case 0:
      break

    case 1:
      switch (typeof args[0]) {
      case 'number':
        break

      case 'string':
        args = [ExtDate.parse(args[0])]
        // eslint-disable-line no-fallthrough

      case 'object':
        {
          let obj = args[0]

          assert.equal('Date', obj.type)
          assert(obj.values)
          assert(obj.values.length)

          precision = obj.values.length
          args = obj.values.slice()

          // ECMA Date constructor needs at least two date parts!
          if (args.length < 2) args.push(0)

          // TODO handle 0-99 years ECMA Date constructor
          // TODO handle offset!

          args = [Date.UTC(...args)]

          //;({ uncertain, approximate, unspecified, offset } = obj)
        }
        break

      default:
        throw new RangeError('Invalid time value')
      }

      break

    default:
      precision = args.length
    }

    super(...args)

    this.precision = precision

    this.uncertain = uncertain
    this.approximate = approximate
    this.unspecified = unspecified
  }

  set precision(value) {
    P[this] = Number(value)
  }

  get precision() {
    return P[this]
  }

  set uncertain(value) {
    U[this] = new Bitmask(value)
  }

  get uncertain() {
    return U[this]
  }

  set approximate(value) {
    A[this] = new Bitmask(value)
  }

  get approximate() {
    return A[this]
  }

  set unspecified(value) {
    X[this] = new Bitmask(value)
  }

  get unspecified() {
    return X[this]
  }

  toISOString() {
    //return super()
  }

  toJSON() {
    return this.toISOString()
  }
}

module.exports = ExtDate
<|endoftext|>


<commit_before>import constant from "./constant";
import {dispatch} from "d3-dispatch";
import {event, customEvent, select, mouse, touch} from "d3-selection";
import DragEvent from "./event";

var ignore = {};

function nodefault() {
  event.preventDefault();
}

function defaultX(d) {
  return d && d.x;
}

function defaultY(d) {
  return d && d.y;
}

// Ignore right-click, since that should open the context menu.
function defaultFilter() {
  return !event.sourceEvent.button;
}

function defaultContainer() {
  return this.parentNode;
}

function nodrag() {
  select(event.sourceEvent.view).on("dragstart.nodrag-" + event.identifier, nodefault, true);
}

function yesdrag() {
  select(event.sourceEvent.view).on("dragstart.nodrag-" + event.identifier, null);
}

function noselect() {
  select(event.sourceEvent.view).on("selectstart.noselect-" + event.identifier, nodefault, true);
}

function yesselect() {
  select(event.sourceEvent.view).on("selectstart.noselect-" + event.identifier, null);
}

function noclick() {
  event.on("drag.noclick", null).on("end.noclick", function() {
    var click = "click.noclick-" + event.identifier,
        view = select(event.sourceEvent.view).on(click, nodefault, true);
    setTimeout(function() { view.on(click, null); }, 0);
  });
}

export default function(started) {
  var x = defaultX,
      y = defaultY,
      filter = defaultFilter,
      container = defaultContainer,
      active = {};

  // I’d like to call preventDefault on mousedown to disable native dragging
  // of links or images and native text selection. However, in Chrome this
  // causes mousemove and mouseup events outside an iframe to be dropped:
  // https://bugs.chromium.org/p/chromium/issues/detail?id=269917
  // And if you preventDefault on touchstart on iOS, it prevents the click
  // event on touchend, even if there was no touchmove! So instead, we
  // cancel the specific undesirable behaviors. If you want to change this
  // behavior, you can unregister these listeners!

  var listeners = dispatch("start", "drag", "end")
      .on("start.nodrag", nodrag)
      .on("start.noselect", noselect)
      .on("start", started)
      .on("drag.noclick", noclick)
      .on("drag.noscroll", nodefault)
      .on("end.noselect", yesselect)
      .on("end.nodrag", yesdrag);

  function drag(selection) {
    selection
        .on("mousedown.drag", mousedowned)
        .on("touchstart.drag", touchstarted)
        .on("touchmove.drag", touchmoved)
        .on("touchend.drag touchcancel.drag", touchended)
        .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
  }

  function mousedowned() {
    if (!start("mouse", mouse, this, arguments)) return;
    select(event.view).on("mousemove.drag", mousemoved).on("mouseup.drag", mouseupped);
  }

  function mousemoved() {
    active.mouse("drag");
  }

  function mouseupped() {
    var m = active.mouse;
    select(event.view).on("mousemove.drag mouseup.drag", null);
    delete active.mouse;
    m("end");
  }

  function touchstarted() {
    for (var touches = event.changedTouches, i = 0, n = touches.length; i < n; ++i) {
      start(touches[i].identifier, touch, this, arguments);
    }
  }

  function touchmoved() {
    for (var touches = event.changedTouches, i = 0, n = touches.length, t; i < n; ++i) {
      if (t = active[touches[i].identifier]) {
        t("drag");
      }
    }
  }

  function touchended() {
    for (var touches = event.changedTouches, i = 0, n = touches.length, t; i < n; ++i) {
      if (t = active[touches[i].identifier]) {
        delete active[touches[i].identifier];
        t("end");
      }
    }
  }

  function beforestart() {
    return filter.apply(this, arguments) ? container.apply(this, arguments) : ignore;
  }

  function start(id, point, that, args) {
    if ((parent = customEvent(new DragEvent("beforestart", id), beforestart, that, args)) === ignore) return false;

    var parent,
        sublisteners = listeners.copy(),
        p0 = point(parent, id),
        dx = x.apply(that, args) - p0[0] || 0,
        dy = y.apply(that, args) - p0[1] || 0;

    (active[id] = function(type, p) {
      if (p == null) p = point(parent, id);
      customEvent(new DragEvent(type, id, p[0] + dx, p[1] + dy, sublisteners), sublisteners.apply, sublisteners, [type, that, args]);
    })("start", p0);

    return true;
  }

  drag.filter = function(_) {
    return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter;
  };

  drag.container = function(_) {
    return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container;
  };

  drag.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), drag) : x;
  };

  drag.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), drag) : y;
  };

  drag.on = function() {
    var value = listeners.on.apply(listeners, arguments);
    return value === listeners ? drag : value;
  };

  return drag;
}
<commit_msg>Consistent order.<commit_after>import constant from "./constant";
import {dispatch} from "d3-dispatch";
import {event, customEvent, select, mouse, touch} from "d3-selection";
import DragEvent from "./event";

var ignore = {};

function nodefault() {
  event.preventDefault();
}

function defaultX(d) {
  return d && d.x;
}

function defaultY(d) {
  return d && d.y;
}

// Ignore right-click, since that should open the context menu.
function defaultFilter() {
  return !event.sourceEvent.button;
}

function defaultContainer() {
  return this.parentNode;
}

function nodrag() {
  select(event.sourceEvent.view).on("dragstart.nodrag-" + event.identifier, nodefault, true);
}

function yesdrag() {
  select(event.sourceEvent.view).on("dragstart.nodrag-" + event.identifier, null);
}

function noselect() {
  select(event.sourceEvent.view).on("selectstart.noselect-" + event.identifier, nodefault, true);
}

function yesselect() {
  select(event.sourceEvent.view).on("selectstart.noselect-" + event.identifier, null);
}

function noclick() {
  event.on("drag.noclick", null).on("end.noclick", function() {
    var click = "click.noclick-" + event.identifier,
        view = select(event.sourceEvent.view).on(click, nodefault, true);
    setTimeout(function() { view.on(click, null); }, 0);
  });
}

export default function(started) {
  var x = defaultX,
      y = defaultY,
      filter = defaultFilter,
      container = defaultContainer,
      active = {};

  // I’d like to call preventDefault on mousedown to disable native dragging
  // of links or images and native text selection. However, in Chrome this
  // causes mousemove and mouseup events outside an iframe to be dropped:
  // https://bugs.chromium.org/p/chromium/issues/detail?id=269917
  // And if you preventDefault on touchstart on iOS, it prevents the click
  // event on touchend, even if there was no touchmove! So instead, we
  // cancel the specific undesirable behaviors. If you want to change this
  // behavior, you can unregister these listeners!

  var listeners = dispatch("start", "drag", "end")
      .on("start.nodrag", nodrag)
      .on("start.noselect", noselect)
      .on("start", started)
      .on("drag.noclick", noclick)
      .on("drag.noscroll", nodefault)
      .on("end.nodrag", yesdrag)
      .on("end.noselect", yesselect);

  function drag(selection) {
    selection
        .on("mousedown.drag", mousedowned)
        .on("touchstart.drag", touchstarted)
        .on("touchmove.drag", touchmoved)
        .on("touchend.drag touchcancel.drag", touchended)
        .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
  }

  function mousedowned() {
    if (!start("mouse", mouse, this, arguments)) return;
    select(event.view).on("mousemove.drag", mousemoved).on("mouseup.drag", mouseupped);
  }

  function mousemoved() {
    active.mouse("drag");
  }

  function mouseupped() {
    var m = active.mouse;
    select(event.view).on("mousemove.drag mouseup.drag", null);
    delete active.mouse;
    m("end");
  }

  function touchstarted() {
    for (var touches = event.changedTouches, i = 0, n = touches.length; i < n; ++i) {
      start(touches[i].identifier, touch, this, arguments);
    }
  }

  function touchmoved() {
    for (var touches = event.changedTouches, i = 0, n = touches.length, t; i < n; ++i) {
      if (t = active[touches[i].identifier]) {
        t("drag");
      }
    }
  }

  function touchended() {
    for (var touches = event.changedTouches, i = 0, n = touches.length, t; i < n; ++i) {
      if (t = active[touches[i].identifier]) {
        delete active[touches[i].identifier];
        t("end");
      }
    }
  }

  function beforestart() {
    return filter.apply(this, arguments) ? container.apply(this, arguments) : ignore;
  }

  function start(id, point, that, args) {
    if ((parent = customEvent(new DragEvent("beforestart", id), beforestart, that, args)) === ignore) return false;

    var parent,
        sublisteners = listeners.copy(),
        p0 = point(parent, id),
        dx = x.apply(that, args) - p0[0] || 0,
        dy = y.apply(that, args) - p0[1] || 0;

    (active[id] = function(type, p) {
      if (p == null) p = point(parent, id);
      customEvent(new DragEvent(type, id, p[0] + dx, p[1] + dy, sublisteners), sublisteners.apply, sublisteners, [type, that, args]);
    })("start", p0);

    return true;
  }

  drag.filter = function(_) {
    return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter;
  };

  drag.container = function(_) {
    return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container;
  };

  drag.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), drag) : x;
  };

  drag.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), drag) : y;
  };

  drag.on = function() {
    var value = listeners.on.apply(listeners, arguments);
    return value === listeners ? drag : value;
  };

  return drag;
}
<|endoftext|>