<commit_before>import { createParamString } from '../../core/utils';

export const createQuery = (queries) => {

  return `query {
    ${queries.join(`
    `)}
  }`;

};

export const getTripEntity = () => {
  return  `
    {
      uuid,
      name,
      firstCheckIn {
        uuid,
        locality,
        formattedAddress
      },
      lastCheckIn {
        uuid,
        locality,
        formattedAddress
      }
    }
  `;
};

export const getCommentEntity = () => {
  return `
    {
      uuid,
      replyToUuid,
      checkInUuid,
      terminalUuid,
      text,
      likes,
      likedByUser,
      user {
        uuid,
        firstName,
        lastName,
        username,
        photo
      }
    }
  `;
};

export const getCommentsQuery = () => {
  return `
    comments ${getCommentEntity()}
  `;
};

export const getCheckInEntity = () => {
  return `
    {
      uuid,
      clientId,
      user,
      userUuid,
      userImage,
      date,
      latitude,
      longitude
      placeId,
      formattedAddress,
      locality,
      country,
      tags,
      likes,
      likedByUser,
      departure {
        uuid,
        localDateTime,
        locality,
        formattedAddress,
        transport
      }
      trip ${getTripEntity()}
      comments ${getCommentEntity()}

    }
  `;
};

export const getFeedItemEntity = () => {
  return `
    {
      userAccess,
      checkIn ${getCheckInEntity()},
      inbound {
        uuid,
        latitude,
        longitude,
        placeId,
        formattedAddress,
        locality,
        country,
        tags
      },
      outbound {
        uuid,
          latitude,
          longitude,
          placeId,
          formattedAddress,
          locality,
          country
      },
      posts {
        uuid,
          text,
          user,
          mediaItems {
          uuid,
            type,
            url,
            latitude,
            longitude,
            date
        }
      },
      terminals {
        uuid,
          type,
          transport,
          transportId,
          description,
          localDateTime,
          utcDateTime,
          priceAmount,
          priceCurrency,
          comments ${getCommentEntity()},
          linkedTerminal {
          uuid,
            type,
            transport,
            transportId,
            description,
            localDateTime,
            utcDateTime,
            priceAmount,
            priceCurrency,
            checkIn {
            uuid,
              latitude,
              longitude,
              placeId,
              formattedAddress,
              locality,
              country
          }
        }
      }
    }`;
};

export const getFeedItemsQuery = () => {
  return `feedItems ${getFeedItemEntity()}`;
};

export const getFeedItemQuery = (checkInUuid) => {
  return `feedItem (checkInUuid:"${checkInUuid}") ${getFeedItemEntity()}`;
};

export const getDiscoverQuery = (params) => {
  return `
    discover ${createParamString(params)} {
      discoveries {
        groupType,
        groupName,
        groupId,
        checkInCount,
        postCount,
        connectionCount,
        localityCount,
        localities,
        tags {
          tag,
          userUuid
        },
        feedItem ${getFeedItemEntity()},
        posts {
          uuid,
          text,
          user,
          mediaItems {
            uuid,
            type,
            url
          },
          checkIn {
            uuid
          }
        },
        connectionsFrom,
        connectionsTo
      },
      localityOffset,
      tagOffset,
      userOffset
    }
  `;
};

export const getLinksQuery = (params) => {

  const query = {
    ...params
  };

  delete query.view;
  delete query.route;

  const paramsString = createParamString(query);

  return `
    transitLinks ${paramsString} {
      searchResultType,
      locality,
      linkedLocality,
      from,
      to,
      user,
      userImage,
      tripName,
      links {
        locality,
        latitude,
        longitude,
        routeId,
        departures {
          uuid,
          type,
          latitude,
          longitude,
          locality,
          transport,
          transportId,
          priceAmount,
          priceCurrency,
          routeId,
          routeIndex,
          localDateTime,
          utcDateTime,
          checkInUuid,
          formattedAddress,
          description,
          linkCount,
          reverseLinkCount,
          linkedTerminal {
            latitude,
            longitude,
            locality,
            transport,
            transportId,
            priceAmount,
            priceCurrency,
            localDateTime,
            utcDateTime,
            checkInUuid,
            formattedAddress,
            description
          }
          route { lat, lng },
          tags { tag, userUuid },
          comments ${getCommentEntity()}
        },
        arrivals {
          uuid,
          type,
          latitude,
          longitude,
          locality,
          transport,
          transportId,
          priceAmount,
          priceCurrency,
          localDateTime,
          utcDateTime,
          checkInUuid,
          formattedAddress,
          description,
          linkCount,
          reverseLinkCount,
          routeId,
          routeIndex,
          linkedTerminal {
            uuid,
            latitude,
            longitude,
            locality,
            transport,
            transportId,
            priceAmount,
            priceCurrency,
            localDateTime,
            utcDateTime,
            checkInUuid,
            formattedAddress,
            description
          }
          route { lat, lng },
          tags { tag, userUuid },
          comments ${getCommentEntity()}
        },
        internal {
          uuid,
          latitude,
          longitude,
          locality,
          transport,
          transportId,
          priceAmount,
          priceCurrency,
          localDateTime,
          utcDateTime,
          checkInUuid,
          formattedAddress,
          description,
          linkCount,
          routeId,
          routeIndex,
          linkedTerminal {
            uuid,
            latitude,
            longitude,
            locality,
            transport,
            transportId,
            priceAmount,
            priceCurrency,
            localDateTime,
            utcDateTime,
            checkInUuid,
            formattedAddress,
            description
          }
          route { lat, lng },
          comments ${getCommentEntity()}
        },
        departureCount,
        arrivalCount,
        linkedDepartures {
          locality,
          linkedLocality,
          from,
          to,
          linkedTerminalType,
          linkedTerminalUuid,
          linkedLocalityLatitude,
          linkedLocalityLongitude,
          linkCount
        },
        linkedArrivals {
          locality,
          linkedLocality,
          from,
          to,
          linkedTerminalType,
          linkedTerminalUuid,
          linkedLocalityLatitude,
          linkedLocalityLongitude,
          linkCount
        },
        tags { tag, userUuid }
      }
    }
  `;

};

export const getTripsQuery = (params) => {
  const query = { ...params };
  const queryStr = createParamString(query);
  return `trips ${queryStr} ${getTripEntity()}`;
};
<commit_msg>Fixed trip offset<commit_after>import { createParamString } from '../../core/utils';

export const createQuery = (queries) => {

  return `query {
    ${queries.join(`
    `)}
  }`;

};

export const getTripEntity = () => {
  return  `
    {
      uuid,
      name,
      firstCheckIn {
        uuid,
        locality,
        formattedAddress
      },
      lastCheckIn {
        uuid,
        locality,
        formattedAddress
      }
    }
  `;
};

export const getCommentEntity = () => {
  return `
    {
      uuid,
      replyToUuid,
      checkInUuid,
      terminalUuid,
      text,
      likes,
      likedByUser,
      user {
        uuid,
        firstName,
        lastName,
        username,
        photo
      }
    }
  `;
};

export const getCommentsQuery = () => {
  return `
    comments ${getCommentEntity()}
  `;
};

export const getCheckInEntity = () => {
  return `
    {
      uuid,
      clientId,
      user,
      userUuid,
      userImage,
      date,
      latitude,
      longitude
      placeId,
      formattedAddress,
      locality,
      country,
      tags,
      likes,
      likedByUser,
      departure {
        uuid,
        localDateTime,
        locality,
        formattedAddress,
        transport
      }
      trip ${getTripEntity()}
      comments ${getCommentEntity()}

    }
  `;
};

export const getFeedItemEntity = () => {
  return `
    {
      userAccess,
      checkIn ${getCheckInEntity()},
      inbound {
        uuid,
        latitude,
        longitude,
        placeId,
        formattedAddress,
        locality,
        country,
        tags
      },
      outbound {
        uuid,
          latitude,
          longitude,
          placeId,
          formattedAddress,
          locality,
          country
      },
      posts {
        uuid,
          text,
          user,
          mediaItems {
          uuid,
            type,
            url,
            latitude,
            longitude,
            date
        }
      },
      terminals {
        uuid,
          type,
          transport,
          transportId,
          description,
          localDateTime,
          utcDateTime,
          priceAmount,
          priceCurrency,
          comments ${getCommentEntity()},
          linkedTerminal {
          uuid,
            type,
            transport,
            transportId,
            description,
            localDateTime,
            utcDateTime,
            priceAmount,
            priceCurrency,
            checkIn {
            uuid,
              latitude,
              longitude,
              placeId,
              formattedAddress,
              locality,
              country
          }
        }
      }
    }`;
};

export const getFeedItemsQuery = () => {
  return `feedItems ${getFeedItemEntity()}`;
};

export const getFeedItemQuery = (checkInUuid) => {
  return `feedItem (checkInUuid:"${checkInUuid}") ${getFeedItemEntity()}`;
};

export const getDiscoverQuery = (params) => {
  return `
    discover ${createParamString(params)} {
      discoveries {
        groupType,
        groupName,
        groupId,
        checkInCount,
        postCount,
        connectionCount,
        localityCount,
        localities,
        tags {
          tag,
          userUuid
        },
        feedItem ${getFeedItemEntity()},
        posts {
          uuid,
          text,
          user,
          mediaItems {
            uuid,
            type,
            url
          },
          checkIn {
            uuid
          }
        },
        connectionsFrom,
        connectionsTo
      },
      localityOffset,
      tagOffset,
      tripOffset,
      userOffset
    }
  `;
};

export const getLinksQuery = (params) => {

  const query = {
    ...params
  };

  delete query.view;
  delete query.route;

  const paramsString = createParamString(query);

  return `
    transitLinks ${paramsString} {
      searchResultType,
      locality,
      linkedLocality,
      from,
      to,
      user,
      userImage,
      tripName,
      links {
        locality,
        latitude,
        longitude,
        routeId,
        departures {
          uuid,
          type,
          latitude,
          longitude,
          locality,
          transport,
          transportId,
          priceAmount,
          priceCurrency,
          routeId,
          routeIndex,
          localDateTime,
          utcDateTime,
          checkInUuid,
          formattedAddress,
          description,
          linkCount,
          reverseLinkCount,
          linkedTerminal {
            latitude,
            longitude,
            locality,
            transport,
            transportId,
            priceAmount,
            priceCurrency,
            localDateTime,
            utcDateTime,
            checkInUuid,
            formattedAddress,
            description
          }
          route { lat, lng },
          tags { tag, userUuid },
          comments ${getCommentEntity()}
        },
        arrivals {
          uuid,
          type,
          latitude,
          longitude,
          locality,
          transport,
          transportId,
          priceAmount,
          priceCurrency,
          localDateTime,
          utcDateTime,
          checkInUuid,
          formattedAddress,
          description,
          linkCount,
          reverseLinkCount,
          routeId,
          routeIndex,
          linkedTerminal {
            uuid,
            latitude,
            longitude,
            locality,
            transport,
            transportId,
            priceAmount,
            priceCurrency,
            localDateTime,
            utcDateTime,
            checkInUuid,
            formattedAddress,
            description
          }
          route { lat, lng },
          tags { tag, userUuid },
          comments ${getCommentEntity()}
        },
        internal {
          uuid,
          latitude,
          longitude,
          locality,
          transport,
          transportId,
          priceAmount,
          priceCurrency,
          localDateTime,
          utcDateTime,
          checkInUuid,
          formattedAddress,
          description,
          linkCount,
          routeId,
          routeIndex,
          linkedTerminal {
            uuid,
            latitude,
            longitude,
            locality,
            transport,
            transportId,
            priceAmount,
            priceCurrency,
            localDateTime,
            utcDateTime,
            checkInUuid,
            formattedAddress,
            description
          }
          route { lat, lng },
          comments ${getCommentEntity()}
        },
        departureCount,
        arrivalCount,
        linkedDepartures {
          locality,
          linkedLocality,
          from,
          to,
          linkedTerminalType,
          linkedTerminalUuid,
          linkedLocalityLatitude,
          linkedLocalityLongitude,
          linkCount
        },
        linkedArrivals {
          locality,
          linkedLocality,
          from,
          to,
          linkedTerminalType,
          linkedTerminalUuid,
          linkedLocalityLatitude,
          linkedLocalityLongitude,
          linkCount
        },
        tags { tag, userUuid }
      }
    }
  `;

};

export const getTripsQuery = (params) => {
  const query = { ...params };
  const queryStr = createParamString(query);
  return `trips ${queryStr} ${getTripEntity()}`;
};
<|endoftext|>


<commit_before>var _ = require('../util')
var templateParser = require('../parsers/template')

module.exports = {

  isLiteral: true,

  /**
   * Setup. Two possible usages:
   *
   * - static:
   *   v-component="comp"
   *
   * - dynamic:
   *   v-component="{{currentView}}"
   */

  bind: function () {
    if (!this.el.__vue__) {
      // create a ref anchor
      this.anchor = _.createAnchor('v-component')
      _.replace(this.el, this.anchor)
      // check keep-alive options.
      // If yes, instead of destroying the active vm when
      // hiding (v-if) or switching (dynamic literal) it,
      // we simply remove it from the DOM and save it in a
      // cache object, with its constructor id as the key.
      this.keepAlive = this._checkParam('keep-alive') != null
      // wait for event before insertion
      this.readyEvent = this._checkParam('wait-for')
      // check ref
      this.refID = _.attr(this.el, 'ref')
      if (this.keepAlive) {
        this.cache = {}
      }
      // check inline-template
      if (this._checkParam('inline-template') !== null) {
        // extract inline template as a DocumentFragment
        this.template = _.extractContent(this.el, true)
      }
      // component resolution related state
      this._pendingCb =
      this.ctorId =
      this.Ctor = null
      // if static, build right now.
      if (!this._isDynamicLiteral) {
        this.resolveCtor(this.expression, _.bind(this.initStatic, this))
      } else {
        // check dynamic component params
        this.transMode = this._checkParam('transition-mode')
      }
    } else {
      _.warn(
        'Do not create a component that only contains ' +
        'a single other component - they will be mounted to ' +
        'the same element and cause conflict. Wrap it with ' +
        'an outer element.'
      )
    }
  },

  /**
   * Initialize a static component.
   */

  initStatic: function () {
    var child = this.build()
    var anchor = this.anchor
    this.setCurrent(child)
    if (!this.readyEvent) {
      child.$before(anchor)
    } else {
      child.$once(this.readyEvent, function () {
        child.$before(anchor)
      })
    }
  },

  /**
   * Public update, called by the watcher in the dynamic
   * literal scenario, e.g. v-component="{{view}}"
   */

  update: function (value) {
    this.setComponent(value)
  },

  /**
   * Switch dynamic components. May resolve the component
   * asynchronously, and perform transition based on
   * specified transition mode. Accepts a few additional
   * arguments specifically for vue-router.
   *
   * @param {String} value
   * @param {Object} data
   * @param {Function} afterBuild
   * @param {Function} afterTransition
   */

  setComponent: function (value, data, afterBuild, afterTransition) {
    this.invalidatePending()
    if (!value) {
      // just remove current
      this.unbuild()
      this.remove(this.childVM, afterTransition)
      this.unsetCurrent()
    } else {
      this.resolveCtor(value, _.bind(function () {
        this.unbuild()
        var newComponent = this.build(data)
        /* istanbul ignore if */
        if (afterBuild) afterBuild(newComponent)
        var self = this
        if (this.readyEvent) {
          newComponent.$once(this.readyEvent, function () {
            self.transition(newComponent, afterTransition)
          })
        } else {
          this.transition(newComponent, afterTransition)
        }
      }, this))
    }
  },

  /**
   * Resolve the component constructor to use when creating
   * the child vm.
   */

  resolveCtor: function (id, cb) {
    var self = this
    this._pendingCb = _.cancellable(function (ctor) {
      self.ctorId = id
      self.Ctor = ctor
      cb()
    })
    this.vm._resolveComponent(id, this._pendingCb)
  },

  /**
   * When the component changes or unbinds before an async
   * constructor is resolved, we need to invalidate its
   * pending callback.
   */

  invalidatePending: function () {
    if (this._pendingCb) {
      this._pendingCb.cancel()
      this._pendingCb = null
    }
  },

  /**
   * Instantiate/insert a new child vm.
   * If keep alive and has cached instance, insert that
   * instance; otherwise build a new one and cache it.
   *
   * @param {Object} [data]
   * @return {Vue} - the created instance
   */

  build: function (data) {
    if (this.keepAlive) {
      var cached = this.cache[this.ctorId]
      if (cached) {
        return cached
      }
    }
    if (this.Ctor) {
      var parent = this._host || this.vm
      var el = templateParser.clone(this.el)
      var child = parent.$addChild({
        el: el,
        data: data,
        template: this.template,
        // if no inline-template, then the compiled
        // linker can be cached for better performance.
        _linkerCachable: !this.template,
        _asComponent: true,
        _isRouterView: this._isRouterView,
        _context: this.vm
      }, this.Ctor)
      if (this.keepAlive) {
        this.cache[this.ctorId] = child
      }
      return child
    }
  },

  /**
   * Teardown the current child, but defers cleanup so
   * that we can separate the destroy and removal steps.
   */

  unbuild: function () {
    var child = this.childVM
    if (!child || this.keepAlive) {
      return
    }
    // the sole purpose of `deferCleanup` is so that we can
    // "deactivate" the vm right now and perform DOM removal
    // later.
    child.$destroy(false, true)
  },

  /**
   * Remove current destroyed child and manually do
   * the cleanup after removal.
   *
   * @param {Function} cb
   */

  remove: function (child, cb) {
    var keepAlive = this.keepAlive
    if (child) {
      child.$remove(function () {
        if (!keepAlive) child._cleanup()
        if (cb) cb()
      })
    } else if (cb) {
      cb()
    }
  },

  /**
   * Actually swap the components, depending on the
   * transition mode. Defaults to simultaneous.
   *
   * @param {Vue} target
   * @param {Function} [cb]
   */

  transition: function (target, cb) {
    var self = this
    var current = this.childVM
    this.unsetCurrent()
    this.setCurrent(target)
    switch (self.transMode) {
      case 'in-out':
        target.$before(self.anchor, function () {
          self.remove(current, cb)
        })
        break
      case 'out-in':
        self.remove(current, function () {
          if (!target._isDestroyed) {
            target.$before(self.anchor, cb)
          }
        })
        break
      default:
        self.remove(current)
        target.$before(self.anchor, cb)
    }
  },

  /**
   * Set childVM and parent ref
   */

  setCurrent: function (child) {
    this.childVM = child
    var refID = child._refID || this.refID
    if (refID) {
      this.vm.$[refID] = child
    }
  },

  /**
   * Unset childVM and parent ref
   */

  unsetCurrent: function () {
    var child = this.childVM
    this.childVM = null
    var refID = (child && child._refID) || this.refID
    if (refID) {
      this.vm.$[refID] = null
    }
  },

  /**
   * Unbind.
   */

  unbind: function () {
    this.invalidatePending()
    this.unbuild()
    // destroy all keep-alive cached instances
    if (this.cache) {
      for (var key in this.cache) {
        this.cache[key].$destroy()
      }
      this.cache = null
    }
  }
}
<commit_msg>clear ref when unbinding static component (fix #985)<commit_after>var _ = require('../util')
var templateParser = require('../parsers/template')

module.exports = {

  isLiteral: true,

  /**
   * Setup. Two possible usages:
   *
   * - static:
   *   v-component="comp"
   *
   * - dynamic:
   *   v-component="{{currentView}}"
   */

  bind: function () {
    if (!this.el.__vue__) {
      // create a ref anchor
      this.anchor = _.createAnchor('v-component')
      _.replace(this.el, this.anchor)
      // check keep-alive options.
      // If yes, instead of destroying the active vm when
      // hiding (v-if) or switching (dynamic literal) it,
      // we simply remove it from the DOM and save it in a
      // cache object, with its constructor id as the key.
      this.keepAlive = this._checkParam('keep-alive') != null
      // wait for event before insertion
      this.readyEvent = this._checkParam('wait-for')
      // check ref
      this.refID = _.attr(this.el, 'ref')
      if (this.keepAlive) {
        this.cache = {}
      }
      // check inline-template
      if (this._checkParam('inline-template') !== null) {
        // extract inline template as a DocumentFragment
        this.template = _.extractContent(this.el, true)
      }
      // component resolution related state
      this._pendingCb =
      this.ctorId =
      this.Ctor = null
      // if static, build right now.
      if (!this._isDynamicLiteral) {
        this.resolveCtor(this.expression, _.bind(this.initStatic, this))
      } else {
        // check dynamic component params
        this.transMode = this._checkParam('transition-mode')
      }
    } else {
      _.warn(
        'Do not create a component that only contains ' +
        'a single other component - they will be mounted to ' +
        'the same element and cause conflict. Wrap it with ' +
        'an outer element.'
      )
    }
  },

  /**
   * Initialize a static component.
   */

  initStatic: function () {
    var child = this.build()
    var anchor = this.anchor
    this.setCurrent(child)
    if (!this.readyEvent) {
      child.$before(anchor)
    } else {
      child.$once(this.readyEvent, function () {
        child.$before(anchor)
      })
    }
  },

  /**
   * Public update, called by the watcher in the dynamic
   * literal scenario, e.g. v-component="{{view}}"
   */

  update: function (value) {
    this.setComponent(value)
  },

  /**
   * Switch dynamic components. May resolve the component
   * asynchronously, and perform transition based on
   * specified transition mode. Accepts a few additional
   * arguments specifically for vue-router.
   *
   * @param {String} value
   * @param {Object} data
   * @param {Function} afterBuild
   * @param {Function} afterTransition
   */

  setComponent: function (value, data, afterBuild, afterTransition) {
    this.invalidatePending()
    if (!value) {
      // just remove current
      this.unbuild()
      this.remove(this.childVM, afterTransition)
      this.unsetCurrent()
    } else {
      this.resolveCtor(value, _.bind(function () {
        this.unbuild()
        var newComponent = this.build(data)
        /* istanbul ignore if */
        if (afterBuild) afterBuild(newComponent)
        var self = this
        if (this.readyEvent) {
          newComponent.$once(this.readyEvent, function () {
            self.transition(newComponent, afterTransition)
          })
        } else {
          this.transition(newComponent, afterTransition)
        }
      }, this))
    }
  },

  /**
   * Resolve the component constructor to use when creating
   * the child vm.
   */

  resolveCtor: function (id, cb) {
    var self = this
    this._pendingCb = _.cancellable(function (ctor) {
      self.ctorId = id
      self.Ctor = ctor
      cb()
    })
    this.vm._resolveComponent(id, this._pendingCb)
  },

  /**
   * When the component changes or unbinds before an async
   * constructor is resolved, we need to invalidate its
   * pending callback.
   */

  invalidatePending: function () {
    if (this._pendingCb) {
      this._pendingCb.cancel()
      this._pendingCb = null
    }
  },

  /**
   * Instantiate/insert a new child vm.
   * If keep alive and has cached instance, insert that
   * instance; otherwise build a new one and cache it.
   *
   * @param {Object} [data]
   * @return {Vue} - the created instance
   */

  build: function (data) {
    if (this.keepAlive) {
      var cached = this.cache[this.ctorId]
      if (cached) {
        return cached
      }
    }
    if (this.Ctor) {
      var parent = this._host || this.vm
      var el = templateParser.clone(this.el)
      var child = parent.$addChild({
        el: el,
        data: data,
        template: this.template,
        // if no inline-template, then the compiled
        // linker can be cached for better performance.
        _linkerCachable: !this.template,
        _asComponent: true,
        _isRouterView: this._isRouterView,
        _context: this.vm
      }, this.Ctor)
      if (this.keepAlive) {
        this.cache[this.ctorId] = child
      }
      return child
    }
  },

  /**
   * Teardown the current child, but defers cleanup so
   * that we can separate the destroy and removal steps.
   */

  unbuild: function () {
    var child = this.childVM
    if (!child || this.keepAlive) {
      return
    }
    // the sole purpose of `deferCleanup` is so that we can
    // "deactivate" the vm right now and perform DOM removal
    // later.
    child.$destroy(false, true)
  },

  /**
   * Remove current destroyed child and manually do
   * the cleanup after removal.
   *
   * @param {Function} cb
   */

  remove: function (child, cb) {
    var keepAlive = this.keepAlive
    if (child) {
      child.$remove(function () {
        if (!keepAlive) child._cleanup()
        if (cb) cb()
      })
    } else if (cb) {
      cb()
    }
  },

  /**
   * Actually swap the components, depending on the
   * transition mode. Defaults to simultaneous.
   *
   * @param {Vue} target
   * @param {Function} [cb]
   */

  transition: function (target, cb) {
    var self = this
    var current = this.childVM
    this.unsetCurrent()
    this.setCurrent(target)
    switch (self.transMode) {
      case 'in-out':
        target.$before(self.anchor, function () {
          self.remove(current, cb)
        })
        break
      case 'out-in':
        self.remove(current, function () {
          if (!target._isDestroyed) {
            target.$before(self.anchor, cb)
          }
        })
        break
      default:
        self.remove(current)
        target.$before(self.anchor, cb)
    }
  },

  /**
   * Set childVM and parent ref
   */

  setCurrent: function (child) {
    this.childVM = child
    var refID = child._refID || this.refID
    if (refID) {
      this.vm.$[refID] = child
    }
  },

  /**
   * Unset childVM and parent ref
   */

  unsetCurrent: function () {
    var child = this.childVM
    this.childVM = null
    var refID = (child && child._refID) || this.refID
    if (refID) {
      this.vm.$[refID] = null
    }
  },

  /**
   * Unbind.
   */

  unbind: function () {
    this.invalidatePending()
    this.unbuild()
    this.unsetCurrent()
    // destroy all keep-alive cached instances
    if (this.cache) {
      for (var key in this.cache) {
        this.cache[key].$destroy()
      }
      this.cache = null
    }
  }
}
<|endoftext|>


<commit_before>import { heightAtLine } from "../line/spans.js"
import { getLine, lineAtHeight, updateLineHeight } from "../line/utils_line.js"
import { paddingTop, textHeight } from "../measurement/position_measurement.js"
import { ie, ie_version } from "../util/browser.js"

// Read the actual heights of the rendered lines, and update their
// stored heights to match.
export function updateHeightsInViewport(cm) {
  let display = cm.display
  let prevBottom = display.lineDiv.offsetTop
  for (let i = 0; i < display.view.length; i++) {
    let cur = display.view[i], height
    if (cur.hidden) continue
    if (ie && ie_version < 8) {
      let bot = cur.node.offsetTop + cur.node.offsetHeight
      height = bot - prevBottom
      prevBottom = bot
    } else {
      let box = cur.node.getBoundingClientRect()
      height = box.bottom - box.top
    }
    let diff = cur.line.height - height
    if (height < 2) height = textHeight(display)
    if (diff > .005 || diff < -.005) {
      updateLineHeight(cur.line, height)
      updateWidgetHeight(cur.line)
      if (cur.rest) for (let j = 0; j < cur.rest.length; j++)
        updateWidgetHeight(cur.rest[j])
    }
  }
}

// Read and store the height of line widgets associated with the
// given line.
function updateWidgetHeight(line) {
  if (line.widgets) for (let i = 0; i < line.widgets.length; ++i) {
    let w = line.widgets[i], parent = w.node.parentNode
    if (parent) w.height = parent.offsetHeight
  }
}

// Compute the lines that are visible in a given viewport (defaults
// the the current scroll position). viewport may contain top,
// height, and ensure (see op.scrollToPos) properties.
export function visibleLines(display, doc, viewport) {
  let top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop
  top = Math.floor(top - paddingTop(display))
  let bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight

  let from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom)
  // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
  // forces those lines into the viewport (if possible).
  if (viewport && viewport.ensure) {
    let ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line
    if (ensureFrom < from) {
      from = ensureFrom
      to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)
    } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
      from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight)
      to = ensureTo
    }
  }
  return {from: from, to: Math.max(to, from + 1)}
}
<commit_msg>Notice when lines are sticking out of the width of the editor<commit_after>import { heightAtLine } from "../line/spans.js"
import { getLine, lineAtHeight, updateLineHeight } from "../line/utils_line.js"
import { paddingTop, textHeight, charWidth } from "../measurement/position_measurement.js"
import { ie, ie_version } from "../util/browser.js"

// Read the actual heights of the rendered lines, and update their
// stored heights to match.
export function updateHeightsInViewport(cm) {
  let display = cm.display
  let prevBottom = display.lineDiv.offsetTop
  for (let i = 0; i < display.view.length; i++) {
    let cur = display.view[i], wrapping = cm.options.lineWrapping
    let height, width = 0
    if (cur.hidden) continue
    if (ie && ie_version < 8) {
      let bot = cur.node.offsetTop + cur.node.offsetHeight
      height = bot - prevBottom
      prevBottom = bot
    } else {
      let box = cur.node.getBoundingClientRect()
      height = box.bottom - box.top
      // Check that lines don't extend past the right of the current
      // editor width
      if (!wrapping && cur.text.firstChild)
        width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1
    }
    let diff = cur.line.height - height
    if (height < 2) height = textHeight(display)
    if (diff > .005 || diff < -.005) {
      updateLineHeight(cur.line, height)
      updateWidgetHeight(cur.line)
      if (cur.rest) for (let j = 0; j < cur.rest.length; j++)
        updateWidgetHeight(cur.rest[j])
    }
    if (width > cm.display.sizerWidth) {
      let chWidth = Math.ceil(width / charWidth(cm.display))
      if (chWidth > cm.display.maxLineLength) {
        cm.display.maxLineLength = chWidth
        cm.display.maxLine = cur.line
        cm.display.maxLineChanged = true
      }
    }
  }
}

// Read and store the height of line widgets associated with the
// given line.
function updateWidgetHeight(line) {
  if (line.widgets) for (let i = 0; i < line.widgets.length; ++i) {
    let w = line.widgets[i], parent = w.node.parentNode
    if (parent) w.height = parent.offsetHeight
  }
}

// Compute the lines that are visible in a given viewport (defaults
// the the current scroll position). viewport may contain top,
// height, and ensure (see op.scrollToPos) properties.
export function visibleLines(display, doc, viewport) {
  let top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop
  top = Math.floor(top - paddingTop(display))
  let bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight

  let from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom)
  // Ensure is a {from: {line, ch}, to: {line, ch}} object, and
  // forces those lines into the viewport (if possible).
  if (viewport && viewport.ensure) {
    let ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line
    if (ensureFrom < from) {
      from = ensureFrom
      to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight)
    } else if (Math.min(ensureTo, doc.lastLine()) >= to) {
      from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight)
      to = ensureTo
    }
  }
  return {from: from, to: Math.max(to, from + 1)}
}
<|endoftext|>


<commit_before>import { isString, isFunction } from './lib/typeof.js';
import { dispatch } from './lib/dispatch.js';

const SPLIT_SELECTOR = /([^\s]+)(.*)?/;

function delegate(element, evName, selector, callback) {
    element.addEventListener(evName, (event) => {
        let target = event.target;
        while (target && target !== element) {
            if (target.matches(selector)) {
                if (callback.call(element, event, target) === false) {
                    return;
                }
            }
            target = target.parentNode;
        }
    });
}

/**
 * Simple Custom Component with events delegation,
 * It also implement a `dispatchEvent` wrapper named `trigger`.
 *
 * @example
 * my-component.js
 * ```js
 * import { EventsMixin, Component, mix } from 'dna/component';
 * export class MyComponent extends mix(Component).with(EventsMixin) {
 *   get events() {
 *     return {
 *       'click button': 'onButtonClick'
 *     }
 *   }
 *   onButtonClick() {
 *     console.log('button clicked');
 *   }
 * }
 * ```
 * app.js
 * ```js
 * import { define } from 'dna/component';
 * import { MyComponent } from './components/my-component/my-component.js';
 * define('my-component', MyComponent);
 * var element = new MyComponent();
 * var button = document.createElement('button');
 * button.innerText = 'Click me';
 * element.appendChild(button);
 * button.click(); // logs "button clicked"
 * ```
 */
export const EventsMixin = (SuperClass) => class extends SuperClass {
    /**
     * Fires when an instance of the element is created.
     */
    constructor() {
        super();
        // bind events
        let events = this.events || {};
        for (let k in events) {
            let callback = isString(events[k]) ?
                this[events[k]] :
                events[k];
            if (isFunction(callback)) {
                let rule = k.match(SPLIT_SELECTOR);
                let evName = rule[1];
                let selector = (rule[2] || '').trim();
                if (selector) {
                    delegate(this, evName, selector, (ev, target) => {
                        callback.call(this, ev, target);
                    });
                } else {
                    this.addEventListener(evName, (ev) => {
                        callback.call(this, ev, this);
                    });
                }
            } else {
                throw new TypeError('Invalid callback for event.');
            }
        }
    }
    /**
     * `Node.prototype.dispatchEvent` wrapper.
     * @param {String} evName The name of the event to fire.
     * @param {Object} data A set of custom data to pass to the event.
     * @param {Boolean} bubbles Should the event bubble throw the DOM tree.
     * @param {Boolean} cancelable Can be the event cancel by a callback.
     */
    trigger(evName, data, bubbles = true, cancelable = true) {
        return dispatch(this, evName, data, bubbles, cancelable);
    }
};
<commit_msg>refactor: add delegate method to EventsMixin<commit_after>import { isString, isFunction } from './lib/typeof.js';
import { dispatch } from './lib/dispatch.js';

const SPLIT_SELECTOR = /([^\s]+)(.*)?/;

/**
 * Simple Custom Component with events delegation,
 * It also implement a `dispatchEvent` wrapper named `trigger`.
 *
 * @example
 * my-component.js
 * ```js
 * import { EventsMixin, Component, mix } from 'dna/component';
 * export class MyComponent extends mix(Component).with(EventsMixin) {
 *   get events() {
 *     return {
 *       'click button': 'onButtonClick'
 *     }
 *   }
 *   onButtonClick() {
 *     console.log('button clicked');
 *   }
 * }
 * ```
 * app.js
 * ```js
 * import { define } from 'dna/component';
 * import { MyComponent } from './components/my-component/my-component.js';
 * define('my-component', MyComponent);
 * var element = new MyComponent();
 * var button = document.createElement('button');
 * button.innerText = 'Click me';
 * element.appendChild(button);
 * button.click(); // logs "button clicked"
 * ```
 */
export const EventsMixin = (SuperClass) => class extends SuperClass {
    /**
     * Fires when an instance of the element is created.
     */
    constructor() {
        super();
        // bind events
        let events = this.events || {};
        for (let k in events) {
            let callback = isString(events[k]) ?
                this[events[k]] :
                events[k];
            if (isFunction(callback)) {
                let rule = k.match(SPLIT_SELECTOR);
                let evName = rule[1];
                let selector = (rule[2] || '').trim();
                if (selector) {
                    this.delegate(evName, selector, callback);
                } else {
                    this.addEventListener(evName, (ev) => {
                        callback.call(this, ev, this);
                    });
                }
            } else {
                throw new TypeError('Invalid callback for event.');
            }
        }
    }
    delegate(evName, selector, callback) {
        this.addEventListener(evName, (event) => {
            let target = event.target;
            while (target && target !== this) {
                if (target.matches(selector)) {
                    callback.call(this, event, target);
                }
                target = target.parentNode;
            }
        });
    }
    /**
     * `Node.prototype.dispatchEvent` wrapper.
     * @param {String} evName The name of the event to fire.
     * @param {Object} data A set of custom data to pass to the event.
     * @param {Boolean} bubbles Should the event bubble throw the DOM tree.
     * @param {Boolean} cancelable Can be the event cancel by a callback.
     */
    trigger(evName, data, bubbles = true, cancelable = true) {
        return dispatch(this, evName, data, bubbles, cancelable);
    }
};
<|endoftext|>


<commit_before>/*
 * touchmouse.js
 * Fabian Irsara
 * Copyright 2015, Licensed GPL & MIT
 */
define(['../../config', '../../utils/dispatch'], function(config, dispatch){

  /**
   * handles mouse and touch events
   * dispatches tap and doubletap events
   * dispatches idle and active events
   * unifies mouse and touch events to touchmouse events
   * checks if click and tap events really are click events by tracking moved positions and time between last click
   *
   * @example
   * document.getElementById('slider').addEventListener('touchmousedown', down);
   * document.getElementById('slider').addEventListener('tap', tap);
   * document.getElementById('slider').addEventListener('doubletap', doubletap);
   * window.addEventListener('idle', idle);
   * window.addEventListener('active', active);
   *
   * @namespace touchmouse
   * @memberof dom.utils
   **/
  var touchmouse = {
    activeTouches: 0
  };

  // event constants that should be dispatched
  var EVENTS = {
    DOWN: 'touchmousedown',
    UP: 'touchmouseup',
    MOVE: 'touchmousemove',
    TAP: 'tap',
    DOUBLE_TAP: 'doubletap',
    IDLE: 'idle',
    ACTIVE: 'active'
  };

  // tracked touches via pointer id
  var trackedTouches = [];

  // tracked positions (for pointer events only first finger gets tracked)
  var trackedPositions = {start: {}, end: {}, hadMultiple: false};

  // stored idle timeout id for dispatching idle event, gets resetted on every action
  var idleTimeout = null;

  // stores if was idle before when reactivating
  var wasIdle = false;

  // if tracking both events prevent them by default
  var tracksBoth = config.trackTouch && config.trackMouse;

  // keep track of mouse down and up events
  var isMouseDown = false;

  // if touch just fired a touchend event
  var preventMouseEvents = false;

  // reset touch end timeout
  var resetTouchEndTimeout = null;

  /**
   * creates a custom event and returns it
   *
   * @method touchmouse.createEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @public
   * @param {String} type of event that should be created
   * @param {Event} originalEvent (if available) to store for later usage
   * @param {Number} x position of event
   * @param {Number} y position of event
   * @param {Number} pointerID that was used (multiple fingers)
   * @returns {Event} the created event
   **/
  touchmouse.createEvent = function(type, originalEvent, x, y, pointerID) {
    var event = new Event(type, {
      bubbles: true,
      cancelable: true
    });

    event.originalEvent = originalEvent;
    event.pageX = x;
    event.pageY = y;
    event.pointerID = pointerID;

    return event;
  };

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onMouseEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onMouseEvent = function(event) {
    if (preventMouseEvents) return;

    var type, evt;

    switch (event.type) {
      case 'mousedown': type = EVENTS.DOWN; touchmouse.activeTouches = 1; break;
      case 'mouseup':   type = EVENTS.UP;   touchmouse.activeTouches = 0; break;
      case 'mousemove': type = EVENTS.MOVE; break;
      default:
        return;
    }

    // create appropriate touchmouse event based on original event
    evt = touchmouse.createEvent(type, event, event.pageX, event.pageY, -1);

    var target = event.target;

    if (isMouseDown) {
      target = isMouseDown;
    }

    if (type === EVENTS.DOWN && ! isMouseDown) {
      isMouseDown = event.target;
    } else if (type === EVENTS.UP) {
      isMouseDown = false;
    }

    // dispatch touchmouse event on target
    if (! event.__prevented) target.dispatchEvent(evt);

    if (type === EVENTS.DOWN) {
      // store start mouse position
      trackedPositions.start = {x: evt.pageX, y: evt.pageY};
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: evt.pageX, y: evt.pageY};

      // check if it was a tap
      checkTap(event.target, event, evt.pageX, evt.pageY, -1);
    }

    // reset idle status
    _resetIdle();
  };

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onTouchEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onTouchEvent = function(event) {
    var type, i, _len, target, touch, touches, k, evt;

    switch (event.type) {
      case 'touchstart':  type = EVENTS.DOWN; break;
      case 'touchend':    type = EVENTS.UP;   break;
      case 'touchcancel': type = EVENTS.UP;   break;
      case 'touchmove':   type = EVENTS.MOVE; break;
      default:
        return;
    }

    // store changed touches
    touches = event.changedTouches;

    // loop through all events and create and dispatch event for each changed pointer id
    // NOTE: this is not so performant but easier to use in subclasses
    for (i = 0, _len = touches.length; i < _len; i++) {
      // store current touch
      touch = touches[i];

      // create appropriate event
      evt = touchmouse.createEvent(type, event, touch.pageX, touch.pageY, touch.identifier);

      // if already has a tracked target for current pointerID
      // NOTE: maybe always used document.elementFromPoint as touch could move over multiple objects?
      if (trackedTouches[touch.identifier]) {
        // get cached, tracked target
        target = trackedTouches[touch.identifier].target;
      } else {
        // find target through document.elementFromPoint and cache target
        target = document.elementFromPoint(touch.pageX, touch.pageY);
        trackedTouches[touch.identifier] = {target: target};
      }

      // dispatch event on target
      if (! event.__prevented) target.dispatchEvent(evt);
    }

    // delete unused tracked touches
    if (type === EVENTS.UP) {
      var activeTouchIdentifiers = [];
      var eventFiringIdentifiers = [];

      // store currently active touch ids
      for (i = 0, _len = event.touches.length; i < _len; i++) {
        activeTouchIdentifiers.push(event.touches[i].identifier);
      }

      // store touch id's that fired ended event (i.e. fingers that left the screen)
      for (i = 0, _len = event.changedTouches.length; i < _len; i++) {
        eventFiringIdentifiers.push(event.changedTouches[i].identifier);
      }

      // check all tracked touches
      for (k in trackedTouches) {
        k = parseFloat(k);

        // if the checked finger is not active anymore
        if (activeTouchIdentifiers.indexOf(k) === -1) {
          // if that finger will not fire a touchend
          // (i.e. if it actually isn't actively on the screen anymore, but is still be tracked)
          if (eventFiringIdentifiers.indexOf(k) === -1) {
            // fake touchend event on that element
            evt = touchmouse.createEvent(type, event, touch.pageX, touch.pageY, k);
            if (trackedTouches[k].target && ! event.__prevented) {
              trackedTouches[k].target.dispatchEvent(evt);
            }
          }

          // remove it from tracking list
          delete trackedTouches[k];
        }
      }
    }

    // if finger count changed (via touchstart or touchend)
    if (type === EVENTS.DOWN || type === EVENTS.UP) {
      // calculate active touches
      touchmouse.activeTouches = 0;

      for (k in trackedTouches) {
        if (trackedTouches[k].target) {
          touchmouse.activeTouches++;
        }
      }
    }

    if (tracksBoth) {
      // prevent calling mouse events that fire right after touch events (i.e. fallback click)
      preventMouseEvents = true;
    }

    if (type === EVENTS.DOWN) {
      // store if had multiple fingers throughout transformations before ending a touch (i.e. before tapping)
      trackedPositions.hadMultiple = touchmouse.activeTouches > 1;

      // if it was the first finger
      if (touchmouse.activeTouches === 1) {
        // store start mouse position
        trackedPositions.start = {x: touches[0].pageX, y: touches[0].pageY};
      }
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: touches[0].pageX, y: touches[0].pageY};

      // check if it was a tap on last found target
      checkTap(target, event, touches[0].pageX, touches[0].pageY, touches[0].identifier);

      // re-track mouse events when no active touch is detected anymore
      if (tracksBoth) {
        if (resetTouchEndTimeout) clearTimeout(resetTouchEndTimeout);
        resetTouchEndTimeout = setTimeout(_resetTouchEnd, 17);
      }
    }

    // reset idle status
    _resetIdle();
  };

  // resets touch end to its default state
  var _resetTouchEnd = function(){
    preventMouseEvents = false;
    resetTouchEndTimeout = null;
  };

  /**
   * dispatches active event on window
   *
   * @method dispatchActive
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchActive = function(){
    wasIdle = false;
    dispatch(window, EVENTS.ACTIVE);
  };

  /**
   * dispatches idle event on window
   *
   * @method dispatchIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchIdle = function(){
    // check if was not idle before (prevent internal logic bug)
    if (wasIdle) return;
    wasIdle = true;
    dispatch(window, EVENTS.IDLE);
  };

  /**
   * checks if event was a valid tap
   * i.e. if not moved too far and did not have multiple fingers
   * also checks for double taps
   *
   * @method checkTap
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {DomElement} target that was tapped and stores multiple tap counts
   **/
  var checkTap = function(target, originalEvent, x, y, pointerID){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (! (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20)
    ) {
      var evt = null;
      var wasDoubleTap = false;

      var now = Date.now();

      // if tapped again within 350 ms
      if (now - target._lastTapTime < 350) {
        // and is an even tap count
        if ((target._taps + 1) % 2 === 0) {
          // create double tap event
          wasDoubleTap = true;
        }
      } else {
        // otherwise reset taps
        target._taps = 0;
      }

      // store last tap time on dom element
      target._lastTapTime = now;

      // increment tap count on dom element
      target._taps++;

      // if it was a valid tap: dispatch event, pass tap count to event
      evt = touchmouse.createEvent(EVENTS.TAP, originalEvent, x, y, pointerID);
      evt.taps = target._taps;
      if (! originalEvent.__prevented) target.dispatchEvent(evt);

      // if also was a double tap
      if (wasDoubleTap) {
        // dispatch a double tap event on target, pass tap count to event
        evt = touchmouse.createEvent(EVENTS.DOUBLE_TAP, originalEvent, x, y, pointerID);
        evt.taps = target._taps;
        if (! originalEvent.__prevented) target.dispatchEvent(evt);
      }
    }
  };

  /**
   * checks moved distance and if had multiple fingers
   * prevents event if distance was too long
   *
   * @method onClickEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from click listener
   **/
  var onClickEvent = function(event){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20
    ) {
      event.stopPropagation();
    }
  };

  /**
   * resets idle state and dispatches active on window if was idle before
   *
   * @method _resetIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var _resetIdle = function(){
    // if was idle before: dispatch active event
    if (wasIdle) dispatchActive();

    // reset idle timeout (idle every 15 seconds)
    if (idleTimeout) clearTimeout(idleTimeout);
    idleTimeout = setTimeout(dispatchIdle, 15000);
  };

  // check if supports touch events
  if (config.isTouch || config.trackTouch) {
    // if it does: listen to appropriate touch events in whole window
    window.addEventListener('touchstart', onTouchEvent);
    window.addEventListener('touchmove', onTouchEvent);
    window.addEventListener('touchend', onTouchEvent);
    window.addEventListener('touchcancel', onTouchEvent);
  }

  if (! config.isTouch || config.trackMouse) {
    // otherwise check mouse events and convert them
    window.addEventListener('mousedown', onMouseEvent);
    window.addEventListener('mouseup', onMouseEvent);
    window.addEventListener('mousemove', onMouseEvent);
  }

  // TODO: is buggy, maybe leave mouse events as they are and only check for tap events as they are used internally and not by libraries?
  // check for click events (if moved while trying to click: do not dispatch click)
  //document.addEventListener('click', onClickEvent, true);

  _resetIdle();

  return touchmouse;

});
<commit_msg>allow assigning touchmouse to different windows<commit_after>/*
 * touchmouse.js
 * Fabian Irsara
 * Copyright 2015, Licensed GPL & MIT
 */
define(['../../config', '../../utils/dispatch'], function(config, dispatch){

  /**
   * handles mouse and touch events
   * dispatches tap and doubletap events
   * dispatches idle and active events
   * unifies mouse and touch events to touchmouse events
   * checks if click and tap events really are click events by tracking moved positions and time between last click
   *
   * @example
   * document.getElementById('slider').addEventListener('touchmousedown', down);
   * document.getElementById('slider').addEventListener('tap', tap);
   * document.getElementById('slider').addEventListener('doubletap', doubletap);
   * window.addEventListener('idle', idle);
   * window.addEventListener('active', active);
   *
   * @namespace touchmouse
   * @memberof dom.utils
   **/
  var touchmouse = {
    activeTouches: 0
  };

  // event constants that should be dispatched
  var EVENTS = {
    DOWN: 'touchmousedown',
    UP: 'touchmouseup',
    MOVE: 'touchmousemove',
    TAP: 'tap',
    DOUBLE_TAP: 'doubletap',
    IDLE: 'idle',
    ACTIVE: 'active'
  };

  // tracked touches via pointer id
  var trackedTouches = [];

  // tracked positions (for pointer events only first finger gets tracked)
  var trackedPositions = {start: {}, end: {}, hadMultiple: false};

  // stored idle timeout id for dispatching idle event, gets resetted on every action
  var idleTimeout = null;

  // stores if was idle before when reactivating
  var wasIdle = false;

  // if tracking both events prevent them by default
  var tracksBoth = config.trackTouch && config.trackMouse;

  // keep track of mouse down and up events
  var isMouseDown = false;

  // if touch just fired a touchend event
  var preventMouseEvents = false;

  // reset touch end timeout
  var resetTouchEndTimeout = null;

  /**
   * creates a custom event and returns it
   *
   * @method touchmouse.createEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @public
   * @param {String} type of event that should be created
   * @param {Event} originalEvent (if available) to store for later usage
   * @param {Number} x position of event
   * @param {Number} y position of event
   * @param {Number} pointerID that was used (multiple fingers)
   * @returns {Event} the created event
   **/
  touchmouse.createEvent = function(type, originalEvent, x, y, pointerID) {
    var event = new Event(type, {
      bubbles: true,
      cancelable: true
    });

    event.originalEvent = originalEvent;
    event.pageX = x;
    event.pageY = y;
    event.pointerID = pointerID;

    return event;
  };

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onMouseEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onMouseEvent = function(event) {
    if (preventMouseEvents) return;

    var type, evt;

    switch (event.type) {
      case 'mousedown': type = EVENTS.DOWN; touchmouse.activeTouches = 1; break;
      case 'mouseup':   type = EVENTS.UP;   touchmouse.activeTouches = 0; break;
      case 'mousemove': type = EVENTS.MOVE; break;
      default:
        return;
    }

    // create appropriate touchmouse event based on original event
    evt = touchmouse.createEvent(type, event, event.pageX, event.pageY, -1);

    var target = event.target;

    if (isMouseDown) {
      target = isMouseDown;
    }

    if (type === EVENTS.DOWN && ! isMouseDown) {
      isMouseDown = event.target;
    } else if (type === EVENTS.UP) {
      isMouseDown = false;
    }

    // dispatch touchmouse event on target
    if (! event.__prevented) target.dispatchEvent(evt);

    if (type === EVENTS.DOWN) {
      // store start mouse position
      trackedPositions.start = {x: evt.pageX, y: evt.pageY};
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: evt.pageX, y: evt.pageY};

      // check if it was a tap
      checkTap(event.target, event, evt.pageX, evt.pageY, -1);
    }

    // reset idle status
    _resetIdle();
  };

  /**
   * checks event type, tracks positions, converts to touchmouse event, etc.
   *
   * @method onTouchEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from mouse listener
   **/
  var onTouchEvent = function(event) {
    var type, i, _len, target, touch, touches, k, evt;

    switch (event.type) {
      case 'touchstart':  type = EVENTS.DOWN; break;
      case 'touchend':    type = EVENTS.UP;   break;
      case 'touchcancel': type = EVENTS.UP;   break;
      case 'touchmove':   type = EVENTS.MOVE; break;
      default:
        return;
    }

    // store changed touches
    touches = event.changedTouches;

    // loop through all events and create and dispatch event for each changed pointer id
    // NOTE: this is not so performant but easier to use in subclasses
    for (i = 0, _len = touches.length; i < _len; i++) {
      // store current touch
      touch = touches[i];

      // create appropriate event
      evt = touchmouse.createEvent(type, event, touch.pageX, touch.pageY, touch.identifier);

      // if already has a tracked target for current pointerID
      // NOTE: maybe always used document.elementFromPoint as touch could move over multiple objects?
      if (trackedTouches[touch.identifier]) {
        // get cached, tracked target
        target = trackedTouches[touch.identifier].target;
      } else {
        // find target through document.elementFromPoint and cache target
        target = document.elementFromPoint(touch.pageX, touch.pageY);
        trackedTouches[touch.identifier] = {target: target};
      }

      // dispatch event on target
      if (! event.__prevented) target.dispatchEvent(evt);
    }

    // delete unused tracked touches
    if (type === EVENTS.UP) {
      var activeTouchIdentifiers = [];
      var eventFiringIdentifiers = [];

      // store currently active touch ids
      for (i = 0, _len = event.touches.length; i < _len; i++) {
        activeTouchIdentifiers.push(event.touches[i].identifier);
      }

      // store touch id's that fired ended event (i.e. fingers that left the screen)
      for (i = 0, _len = event.changedTouches.length; i < _len; i++) {
        eventFiringIdentifiers.push(event.changedTouches[i].identifier);
      }

      // check all tracked touches
      for (k in trackedTouches) {
        k = parseFloat(k);

        // if the checked finger is not active anymore
        if (activeTouchIdentifiers.indexOf(k) === -1) {
          // if that finger will not fire a touchend
          // (i.e. if it actually isn't actively on the screen anymore, but is still be tracked)
          if (eventFiringIdentifiers.indexOf(k) === -1) {
            // fake touchend event on that element
            evt = touchmouse.createEvent(type, event, touch.pageX, touch.pageY, k);
            if (trackedTouches[k].target && ! event.__prevented) {
              trackedTouches[k].target.dispatchEvent(evt);
            }
          }

          // remove it from tracking list
          delete trackedTouches[k];
        }
      }
    }

    // if finger count changed (via touchstart or touchend)
    if (type === EVENTS.DOWN || type === EVENTS.UP) {
      // calculate active touches
      touchmouse.activeTouches = 0;

      for (k in trackedTouches) {
        if (trackedTouches[k].target) {
          touchmouse.activeTouches++;
        }
      }
    }

    if (tracksBoth) {
      // prevent calling mouse events that fire right after touch events (i.e. fallback click)
      preventMouseEvents = true;
    }

    if (type === EVENTS.DOWN) {
      // store if had multiple fingers throughout transformations before ending a touch (i.e. before tapping)
      trackedPositions.hadMultiple = touchmouse.activeTouches > 1;

      // if it was the first finger
      if (touchmouse.activeTouches === 1) {
        // store start mouse position
        trackedPositions.start = {x: touches[0].pageX, y: touches[0].pageY};
      }
    } else if (type === EVENTS.UP) {
      // store end mouse position
      trackedPositions.end = {x: touches[0].pageX, y: touches[0].pageY};

      // check if it was a tap on last found target
      checkTap(target, event, touches[0].pageX, touches[0].pageY, touches[0].identifier);

      // re-track mouse events when no active touch is detected anymore
      if (tracksBoth) {
        if (resetTouchEndTimeout) clearTimeout(resetTouchEndTimeout);
        resetTouchEndTimeout = setTimeout(_resetTouchEnd, 17);
      }
    }

    // reset idle status
    _resetIdle();
  };

  // resets touch end to its default state
  var _resetTouchEnd = function(){
    preventMouseEvents = false;
    resetTouchEndTimeout = null;
  };

  /**
   * dispatches active event on window
   *
   * @method dispatchActive
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchActive = function(){
    wasIdle = false;
    dispatch(window, EVENTS.ACTIVE);
  };

  /**
   * dispatches idle event on window
   *
   * @method dispatchIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var dispatchIdle = function(){
    // check if was not idle before (prevent internal logic bug)
    if (wasIdle) return;
    wasIdle = true;
    dispatch(window, EVENTS.IDLE);
  };

  /**
   * checks if event was a valid tap
   * i.e. if not moved too far and did not have multiple fingers
   * also checks for double taps
   *
   * @method checkTap
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {DomElement} target that was tapped and stores multiple tap counts
   **/
  var checkTap = function(target, originalEvent, x, y, pointerID){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (! (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20)
    ) {
      var evt = null;
      var wasDoubleTap = false;

      var now = Date.now();

      // if tapped again within 350 ms
      if (now - target._lastTapTime < 350) {
        // and is an even tap count
        if ((target._taps + 1) % 2 === 0) {
          // create double tap event
          wasDoubleTap = true;
        }
      } else {
        // otherwise reset taps
        target._taps = 0;
      }

      // store last tap time on dom element
      target._lastTapTime = now;

      // increment tap count on dom element
      target._taps++;

      // if it was a valid tap: dispatch event, pass tap count to event
      evt = touchmouse.createEvent(EVENTS.TAP, originalEvent, x, y, pointerID);
      evt.taps = target._taps;
      if (! originalEvent.__prevented) target.dispatchEvent(evt);

      // if also was a double tap
      if (wasDoubleTap) {
        // dispatch a double tap event on target, pass tap count to event
        evt = touchmouse.createEvent(EVENTS.DOUBLE_TAP, originalEvent, x, y, pointerID);
        evt.taps = target._taps;
        if (! originalEvent.__prevented) target.dispatchEvent(evt);
      }
    }
  };

  /**
   * checks moved distance and if had multiple fingers
   * prevents event if distance was too long
   *
   * @method onClickEvent
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   * @param {Event} event dispatched from click listener
   **/
  var onClickEvent = function(event){
    // allow a maximum of 20 pixels to let a click event be dispatched
    // and only one finger while pressing an object
    if (trackedPositions.hadMultiple ||
      Math.abs(trackedPositions.end.x - trackedPositions.start.x) > 20 ||
      Math.abs(trackedPositions.end.y - trackedPositions.start.y) > 20
    ) {
      event.stopPropagation();
    }
  };

  /**
   * resets idle state and dispatches active on window if was idle before
   *
   * @method _resetIdle
   * @memberof dom.utils.touchmouse
   * @instance
   * @private
   **/
  var _resetIdle = function(){
    // if was idle before: dispatch active event
    if (wasIdle) dispatchActive();

    // reset idle timeout (idle every 15 seconds)
    if (idleTimeout) clearTimeout(idleTimeout);
    idleTimeout = setTimeout(dispatchIdle, 15000);
  };

  _resetIdle();

  touchmouse.init = function(target){
    // check if supports touch events
    if (config.isTouch || config.trackTouch) {
      // if it does: listen to appropriate touch events in whole window
      target.addEventListener('touchstart', onTouchEvent);
      target.addEventListener('touchmove', onTouchEvent);
      target.addEventListener('touchend', onTouchEvent);
      target.addEventListener('touchcancel', onTouchEvent);
    }

    if (! config.isTouch || config.trackMouse) {
      // otherwise check mouse events and convert them
      target.addEventListener('mousedown', onMouseEvent);
      target.addEventListener('mouseup', onMouseEvent);
      target.addEventListener('mousemove', onMouseEvent);
    }

    // TODO: is buggy, maybe leave mouse events as they are and only check for tap events as they are used internally and not by libraries?
    // check for click events (if moved while trying to click: do not dispatch click)
    //document.addEventListener('click', onClickEvent, true);
  };

  touchmouse.init(window);

  return touchmouse;

});
<|endoftext|>


<commit_before>if (typeof define !== 'function') { var define = require('amdefine')(module) }

define(function() {

  var keyboardUtil = {
    addKeyDownListener: function() {},
    addKeyUpListener: function() {}
  };

  return keyboardUtil;
});
<commit_msg>Implement the event listeners for keyUp and keyDown.<commit_after>if (typeof define !== 'function') { var define = require('amdefine')(module) }

define(function() {

  var keyboardUtil = {
    addKeyDownListener: function(fn) {
      document.addEventListener('keydown', function(evt) {
        fn(evt.keyCode);
//        evt.preventDefault();
      });
    },

    addKeyUpListener: function(fn) {
      document.addEventListener('keyup', function(evt) {
        fn(evt.keyCode);
      });
    }
  };

  return keyboardUtil;
});
<|endoftext|>


<commit_before>var Path = (function ($, Data, Log, Network) {
    var exports = {};

    // Data objects here
    var waypoints = [];

    // Interactive map objects here
    var map;
    var popup = L.popup();

    // Handle button clicks
    $(document).ready(function () {

        $('#lockOn').on('click', function () {
            // TODO Decouple this from plane marker & figure out somewhere to store last "sensible GPS coordinates"
            // (to prevent bug with erroneous GPS coordinates crashing Leaflet)
            if (planeMarker) {
                map.panTo(planeMarker.getLatLng());
            }
        });

        $('#sendWaypoints').on('click', function () {
            for (i = 0; i < waypoints.length; i++) {
                var latLng = waypoints[i];
                command = "new_Waypoint:" + latLng.lat + "," + latLng.lng + "\r\n";
                Network.write(command);
                Log.write(command);
            }
        });

        $('#clearWaypoints').on('click', function () {
            waypoints = [];
            redrawMap();
        });
    });

    function mapClick(e) {
        popup
            .setLatLng(e.latlng)
            .setContent('
Add Waypoint
')
            .openOn(map);

        $('#addWaypoint').on('click', function () {
            map.closePopup();
            waypoints.push(e.latlng);
            redrawMap();
        });
    }

    var planeMarker;
    var waypointMarkerGroup;
    var waypointPolyline;
    var historyPolyline;

    Network.on('data', redrawMap);

    function redrawMap() {

        // Check for GPS fix, assuming we'll never fly off the coast of West Africa
        // (No GPS fix if coordinates close to (0; 0) or impossibly big)
        if (Math.abs(lat) < 1 || Math.abs(lon) < 1 || Math.abs(lat) > 360 || Math.abs(lon) > 360) {
            return;
        }

        lat = Data.state.lat;
        lon = Data.state.lon;
        heading = Data.state.heading;

        // Init map if necessary
        if (!map) {
            map = L.map('map').setView([lat, lon], 17);
            L.tileLayer('sat_tiles/{z}/{x}/{y}.png', {
                maxZoom: 19
            }).addTo(map);
            map.on('click', mapClick);
        }

        // Init planeMarker if necessary
        if (!planeMarker) {
            planeMarker = new L.RotatedMarker([lat, lon], {
                icon: L.icon({
                    iconUrl: 'plane.png',
                    iconSize: [30, 30], // size of the icon
                }),
            }).addTo(map);
        }

        // Init waypoint marker layer-group if necessary
        if (!waypointMarkerGroup) {
            waypointMarkerGroup = L.layerGroup().addTo(map);
        }

        // Init waypointPolyline if necessary
        if (!waypointPolyline) {
            waypointPolyline = new L.Polyline(waypoints, {
                color: 'red',
                weight: 3,
                opacity: 0.5,
                clickable: false,
            }).addTo(map);
        }

        // Init historyPolyline if necessary
        if (!historyPolyline) {
            historyPolyline = new L.Polyline([], {
                color: '#0000ff',
                weight: 5,
                clickable: false,
            }).addTo(map);
        }

        // Update plane marker
        planeMarker.setLatLng(new L.LatLng(lat, lon));
        planeMarker.options.angle = heading;
        planeMarker.options.title = lat + "°, " + lon + "°, " + heading + "°";
        planeMarker.update();

        // Redraw waypoint markers
        waypointMarkerGroup.clearLayers();
        for (var i = 0; i < waypoints.length; ++i) {
            waypointMarkerGroup.addLayer(new L.marker(waypoints[i]));
        }

        // Redraw waypoint polyline
        waypointPolyline.setLatLngs(waypoints).spliceLatLngs(0, 0, new L.LatLng(lat, lon));

        // Draw points on historyPolyline
        historyPolyline.addLatLng(L.latLng(lat, lon));
    }

    // Export what needs to be
    return exports;

})($, Data, Log, Network);<commit_msg>Fix blank map on start up because incorrectly initialized (Partial fix for issue 14)<commit_after>var Path = (function ($, Data, Log, Network) {
    var exports = {};

    // Data objects here: array of L.LatLng objects
    var waypoints = [];

    // Interactive map objects here
    var map;
    var popup = L.popup();

    // Initialize map if necessary
    $(document).ready(function () {
        if (!map) {
            map = L.map('map').setView([43.53086, -80.5772], 17);
            L.tileLayer('sat_tiles/{z}/{x}/{y}.png', {
                maxZoom: 19
            }).addTo(map);
        }
    });

    // Handle button clicks
    $(document).ready(function () {

        $('#lockOn').on('click', function () {
            // TODO Decouple this from plane marker & figure out somewhere to store last "sensible GPS coordinates"
            // (to prevent bug with erroneous GPS coordinates crashing Leaflet)
            if (planeMarker) {
                map.panTo(planeMarker.getLatLng());
            }
        });

        $('#sendWaypoints').on('click', function () {
            for (i = 0; i < waypoints.length; i++) {
                var latLng = waypoints[i];
                command = "new_Waypoint:" + latLng.lat + "," + latLng.lng + "\r\n";
                Network.write(command);
                Log.write(command);
            }
        });

        $('#clearWaypoints').on('click', function () {
            waypoints = [];
            redrawMap();
        });
    });

    function mapClick(e) {
        popup
            .setLatLng(e.latlng)
            .setContent('
Add Waypoint
')
            .openOn(map);

        $('#addWaypoint').on('click', function () {
            map.closePopup();
            waypoints.push(e.latlng);
            redrawMap();
        });
    }

    var planeMarker;
    var waypointMarkerGroup;
    var waypointPolyline;
    var historyPolyline;

    Network.on('data', redrawMap);

    function redrawMap() {

        // Check for GPS fix, assuming we'll never fly off the coast of West Africa
        // (No GPS fix if coordinates close to (0; 0) or impossibly big)
        if (Math.abs(lat) < 1 || Math.abs(lon) < 1 || Math.abs(lat) > 360 || Math.abs(lon) > 360) {
            return;
        }

        lat = Data.state.lat;
        lon = Data.state.lon;
        heading = Data.state.heading;

        // Init planeMarker if necessary
        if (!planeMarker) {
            planeMarker = new L.RotatedMarker([lat, lon], {
                icon: L.icon({
                    iconUrl: 'plane.png',
                    iconSize: [30, 30], // size of the icon
                }),
            }).addTo(map);
        }

        // Init waypoint marker layer-group if necessary
        if (!waypointMarkerGroup) {
            waypointMarkerGroup = L.layerGroup().addTo(map);
        }

        // Init waypointPolyline if necessary
        if (!waypointPolyline) {
            waypointPolyline = new L.Polyline(waypoints, {
                color: 'red',
                weight: 3,
                opacity: 0.5,
                clickable: false,
            }).addTo(map);
        }

        // Init historyPolyline if necessary
        if (!historyPolyline) {
            historyPolyline = new L.Polyline([], {
                color: '#0000ff',
                weight: 5,
                clickable: false,
            }).addTo(map);
        }

        // Update plane marker
        planeMarker.setLatLng(new L.LatLng(lat, lon));
        planeMarker.options.angle = heading;
        planeMarker.options.title = lat + "°, " + lon + "°, " + heading + "°";
        planeMarker.update();

        // Redraw waypoint markers
        waypointMarkerGroup.clearLayers();
        for (var i = 0; i < waypoints.length; ++i) {
            waypointMarkerGroup.addLayer(new L.marker(waypoints[i]));
        }

        // Redraw waypoint polyline
        waypointPolyline.setLatLngs(waypoints).spliceLatLngs(0, 0, new L.LatLng(lat, lon));

        // Draw points on historyPolyline
        historyPolyline.addLatLng(L.latLng(lat, lon));
    }

    // Export what needs to be
    return exports;

})($, Data, Log, Network);<|endoftext|>


<commit_before>import 'colors';
import { spawn } from 'child_process';
import fs from 'fs-promise';
import path from 'path';
import program from 'commander';
import ora from 'ora';

import './util/terminate';
import rebuild from './util/rebuild';
import resolveDir from './util/resolve-dir';

const main = async () => {
  const startSpinner = ora.ora('Launching Application').start();
  let dir = process.cwd();
  program
    .version(require('../package.json').version)
    .arguments('[cwd]')
    .option('-l, --enable-logging', 'Enable advanced logging.  This will log internal Electron things')
    .action((cwd) => {
      if (!cwd) return;
      if (path.isAbsolute(cwd) && fs.existsSync(cwd)) {
        dir = cwd;
      } else if (fs.existsSync(path.resolve(dir, cwd))) {
        dir = path.resolve(dir, cwd);
      }
    })
    .parse(process.argv);

  dir = await resolveDir(dir);
  if (!dir) {
    startSpinner.fail();
    console.error('Failed to locate startable Electron application'.red);
    if (global._resolveError) global._resolveError();
    process.exit(1);
  }

  const packageJSON = JSON.parse(await fs.readFile(path.resolve(dir, 'package.json'), 'utf8'));

  await rebuild(dir, packageJSON.devDependencies['electron-prebuilt-compile'], process.platform, process.arch);
  spawn(process.execPath, [path.resolve(dir, 'node_modules/.bin/electron'), '.'].concat(process.argv.slice(2)), {
    cwd: dir,
    stdio: 'inherit',
    env: Object.assign({}, process.env, program.enableLogging ? {
      ELECTRON_ENABLE_LOGGING: true,
      ELECTRON_ENABLE_STACK_DUMPING: true,
    } : {}),
  });

  startSpinner.succeed();
};

main();
<commit_msg>fix(starter): fix launching on newest yarn<commit_after>import 'colors';
import { spawn } from 'child_process';
import fs from 'fs-promise';
import path from 'path';
import program from 'commander';
import ora from 'ora';

import './util/terminate';
import rebuild from './util/rebuild';
import resolveDir from './util/resolve-dir';

const main = async () => {
  const startSpinner = ora.ora('Launching Application').start();
  let dir = process.cwd();
  program
    .version(require('../package.json').version)
    .arguments('[cwd]')
    .option('-l, --enable-logging', 'Enable advanced logging.  This will log internal Electron things')
    .action((cwd) => {
      if (!cwd) return;
      if (path.isAbsolute(cwd) && fs.existsSync(cwd)) {
        dir = cwd;
      } else if (fs.existsSync(path.resolve(dir, cwd))) {
        dir = path.resolve(dir, cwd);
      }
    })
    .parse(process.argv);

  dir = await resolveDir(dir);
  if (!dir) {
    startSpinner.fail();
    console.error('Failed to locate startable Electron application'.red);
    if (global._resolveError) global._resolveError();
    process.exit(1);
  }

  const packageJSON = JSON.parse(await fs.readFile(path.resolve(dir, 'package.json'), 'utf8'));

  await rebuild(dir, packageJSON.devDependencies['electron-prebuilt-compile'], process.platform, process.arch);
  const spawnOpts = {
    cwd: dir,
    stdio: 'inherit',
    env: Object.assign({}, process.env, program.enableLogging ? {
      ELECTRON_ENABLE_LOGGING: true,
      ELECTRON_ENABLE_STACK_DUMPING: true,
    } : {}),
  };
  if (process.platform === 'win32') {
    spawn(path.resolve(dir, 'node_modules/.bin/electron.cmd'), ['.'].concat(process.argv.slice(2)), spawnOpts);
  } else {
    spawn(path.resolve(dir, 'node_modules/.bin/electron'), ['.'].concat(process.argv.slice(2)), spawnOpts);
  }

  startSpinner.succeed();
};

main();
<|endoftext|>


<commit_before>/* @flow */
import { createSelector } from 'reselect';
import { getRawRealmEmoji } from '../directSelectors';
import { getAuth } from '../account/accountSelectors';
import { getFullUrl } from '../utils/url';

export const getAllRealmEmojiById = createSelector(getAuth, getRawRealmEmoji, (auth, emojis) =>
  Object.keys(emojis).reduce((result, key) => {
    result[key] = { ...emojis[key], source_url: getFullUrl(emojis[key].source_url, auth.realm) };
    return result;
  }, {}),
);

export const getActiveRealmEmojiById = createSelector(getAllRealmEmojiById, emojis =>
  Object.keys(emojis)
    .filter(emoji => !emojis[emoji].deactivated)
    .reduce((result, key) => {
      result[key] = emojis[key];
      return result;
    }, {}),
);
<commit_msg>emoji: Clarify what these "key"s are.<commit_after>/* @flow */
import { createSelector } from 'reselect';
import { getRawRealmEmoji } from '../directSelectors';
import { getAuth } from '../account/accountSelectors';
import { getFullUrl } from '../utils/url';

export const getAllRealmEmojiById = createSelector(getAuth, getRawRealmEmoji, (auth, emojis) =>
  Object.keys(emojis).reduce((result, id) => {
    result[id] = { ...emojis[id], source_url: getFullUrl(emojis[id].source_url, auth.realm) };
    return result;
  }, {}),
);

export const getActiveRealmEmojiById = createSelector(getAllRealmEmojiById, emojis =>
  Object.keys(emojis)
    .filter(id => !emojis[id].deactivated)
    .reduce((result, id) => {
      result[id] = emojis[id];
      return result;
    }, {}),
);
<|endoftext|>


<commit_before>var norma     = require('norma');
var url       = require('url');
var request   = require('request');
var debug     = require('debug')('waif:pipe');
var Uri       = require('./state/uri');
var pathToUrl = require('path-to-url');
var _         = require('lodash');

module.exports = function(config) {
  var service = this.service;

  var args = norma('url:s, opts:o?, rest:.*', arguments);
  debug('service %s piped to %s', service.name, args.url);

  return function(req, res, next) {

    var proxyUrl = pathToUrl(args.url, req.params) + req.url;

    debug('service %s piping to %s', service.name, proxyUrl);

    var uri = new Uri();
    uri.set(proxyUrl);

    var reqUrl = uri.requestUrl(proxyUrl);

    var opts = {
      url: reqUrl,
      headers: {
        host: url.parse(reqUrl).hostname
      }
    };

    if (args.opts && args.opts.headers) {
      _.extend(opts.headers, args.opts.headers);
    }

    var proxy = request(opts);
    proxy.on('error', errorHandler);
    req.pipe(proxy);
    proxy.pipe(res);

    function errorHandler(err) {
      return res.status(500).send(err);
    }
  };
};
<commit_msg>add redirect option to pipe<commit_after>var norma     = require('norma');
var url       = require('url');
var request   = require('request');
var debug     = require('debug')('waif:pipe');
var Uri       = require('./state/uri');
var pathToUrl = require('path-to-url');
var _         = require('lodash');

module.exports = function(config) {
  var service = this.service;

  var args = norma('url:s, opts:o?, rest:.*', arguments);
  debug('service %s piped to %s', service.name, args.url);

  return function(req, res, next) {

    var proxyUrl = pathToUrl(args.url, req.params) + req.url;

    debug('service %s piping to %s', service.name, proxyUrl);

    var uri = new Uri();
    uri.set(proxyUrl);

    var reqUrl = uri.requestUrl(proxyUrl);

    if (args.opts && args.opts.redirect) {
      return res.redirect(301, reqUrl);
    }

    var opts = {
      url: reqUrl,
      headers: {
        host: url.parse(reqUrl).hostname
      }
    };

    if (args.opts && args.opts.headers) {
      _.extend(opts.headers, args.opts.headers);
    }

    var proxy = request(opts);
    proxy.on('error', errorHandler);
    req.pipe(proxy);
    proxy.pipe(res);

    function errorHandler(err) {
      return res.status(500).send(err);
    }
  };
};
<|endoftext|>


<commit_before>/*
@name mag-templater
@author Michael Glazer (c)
@License MIT
@date January 29th, 2017, updated February 6th, 2017
@description allows for existing functionality in Mag.JS to include template Urls
@example mag|mag.module|mag.create('templateFile.html', Module)
@example mag|mag.module|mag.create({templateUrl: 'template.html', view: function(state){}} )
@requires - Mag.JS - addons and core latest
@link http://github.com/magnumjs/mag.js
*/

mag = (function(_super) {

  var findIdTemplate = function(idOrNode, mod, props, fun) {
    //CASE: if idOrNode is an object not HTMLElement
    //load templateUrl from object if it has one
    if (mag.utils.isObject(idOrNode) && idOrNode.templateUrl) {
      return getTemplate(idOrNode.templateUrl, idOrNode, mod, fun)
    } else if (typeof idOrNode == 'string' && ~idOrNode.indexOf(".html")) {
      return getTemplate(idOrNode, mod, props, fun)
    } else {
      return fun(idOrNode, mod, props);
    }
  }

  var getTemplate = function(url, mod, props, orig) {
    return mag.request(url)
      .then(function(data) {

        var template = mag.doc.createElement('template');
        template.innerHTML = data;

        return orig(mag.getNode(mag._isNode(template.content.children[0])), mod, props || {});
      })
  };

  // return our new `mag()` function
  var extended = function(idOrNode, mod, props) {
    //original constructor
    var fun = _super;
    return findIdTemplate(idOrNode, mod, props, fun)
  };

  mag.utils.merge(extended, _super)

  //Redundant - reuse above func?
  extended.module = function(idOrNode, mod, props) {
    var fun = _super.module;
    return findIdTemplate(idOrNode, mod, props, fun)
  }
  //Should this be here since in Addons not core?
  extended.create = function(idOrNode, mod, props) {
    var fun = _super.create;
    return findIdTemplate(idOrNode, mod, props, fun)
  }

  return extended

})(mag);
<commit_msg>Update mag-template.js<commit_after>/*
@name mag-templater
@author Michael Glazer (c)
@License MIT
@version 0.1.3
@date January 29th, 2017, updated February 6th, 2017, updated February 13th, 2017
@description allows for existing functionality in Mag.JS to include template Urls
@example mag|mag.module|mag.create('templateFile.html', Module)
@example mag|mag.module|mag.create({templateUrl: 'template.html', view: function(state){}} )
@requires - Mag.JS - addons and core latest
@link http://github.com/magnumjs/mag.js
*/

mag = (function(_super) {

  var findIdTemplate = function(idOrNode, mod, props, fun) {
    //CASE: if idOrNode is an object not HTMLElement
    //load templateUrl from object if it has one
    if (mag.utils.isObject(idOrNode) && idOrNode.templateUrl) {
      return getTemplate(idOrNode.templateUrl, idOrNode, mod, fun)
    } else if (typeof idOrNode == 'string' && ~idOrNode.indexOf(".html")) {
      return getTemplate(idOrNode, mod, props, fun)
    } else {
      return fun(idOrNode, mod, props);
    }
  }

  var getTemplate = function(url, mod, props, orig) {

    var req = url;

    //cache for prod?
    if(mag.ENV == 'prod'){
      req = {url: url, cache: 1}
    }
    return mag.request(req)
      .then(function(data) {

        var template = mag.doc.createElement('template');
        template.innerHTML = data;

        return orig(mag.getNode(mag._isNode(template.content.children[0])), mod, props || {});
      })
  };

  // return our new `mag()` function
  var extended = function(idOrNode, mod, props) {
    //original constructor
    var fun = _super;
    return findIdTemplate(idOrNode, mod, props, fun)
  };

  mag.utils.merge(extended, _super)

  //Redundant - reuse above func?
  extended.module = function(idOrNode, mod, props) {
    var fun = _super.module;
    return findIdTemplate(idOrNode, mod, props, fun)
  }
  //Should this be here since in Addons not core?
  extended.create = function(idOrNode, mod, props) {
    var fun = _super.create;
    return findIdTemplate(idOrNode, mod, props, fun)
  }

  return extended

})(mag);
<|endoftext|>