<commit_before>var rewire = require('rewire'),
    expect = require('chai').expect,
    path = require('path'),
    utils = rewire('../../lib/utils');

utils.__set__('fs', { readFileSync: function(path) { return path; } });

var IMAGE_PREFIX = utils.__get__('IMAGE_PREFIX');

describe('Utils', function() {
    describe('.formatImage()', function() {
        context('when a repository is specified', function() {
            var language = 'ruby',
                tag = 'latest',
                formated = utils.formatImage('grounds', language, tag);

            it('formats image name with repository prefix', function() {
                var expected = 'grounds/'+IMAGE_PREFIX+'-'+language+':'+tag;

                expect(formated).to.equal(expected);
            });
        });

        context('when no repository is specified', function() {
            var language = 'java',
                tag      = '1.0.0',
                formated = utils.formatImage('', language, tag);

            it('formats image name without repository prefix', function() {
                expect(formated).to.equal(IMAGE_PREFIX+'-'+language+':'+tag);
            });
        });

        context('when no language is specified', function() {
            it("doesn't fail" function() {
                expect(function() {
                    utils.formatImage('grounds');
                }).not.to.throw(Error);
            });
        });

        context('when no tag is specified', function() {
            it("doesn't fail" function() {
                expect(function() {
                    utils.formatImage('grounds', 'ruby');
                }).not.to.throw(Error);
            });
        });
    });

    describe('.formatCmd()', function() {
        var formated = utils.formatCmd('puts "Hello world\\n\\r\\t"\r\n\t');

        it('returns an escaped string', function() {
            var escapedString = 'puts "Hello world\\\\n\\\\r\\\\t"\\r\\n\\t';

            expect(formated).to.equal(escapedString);
        });

        context('when code is not specified', function() {
            var formated = utils.formatCmd();

            expectEmptyString(formated);
        });
    });

    function expectEmptyString(formated) {
        it('returns an empty string', function() {
            expect(formated).to.equal('');
        });
    }

    describe('.formatStatus()', function() {
        it('returns a signed integer (range -128 to 127)', function() {
            var statusTable     = [0, 1, 128, 254, 255],
                statusExpected  = [0, 1, -128, -2, -1];

            for (var i in statusTable) {
                var formated = utils.formatStatus(statusTable[i]),
                    expected = statusExpected[i];

                expect(formated).to.equal(expected);
            }
        });
    });
});
<commit_msg>cleanup<commit_after>var rewire = require('rewire'),
    expect = require('chai').expect,
    path = require('path'),
    utils = rewire('../../lib/utils');

utils.__set__('fs', { readFileSync: function(path) { return path; } });

var IMAGE_PREFIX = utils.__get__('IMAGE_PREFIX');

describe('Utils', function() {
    describe('.formatImage()', function() {
        context('when a repository is specified', function() {
            var language = 'ruby',
                tag = 'latest',
                formated = utils.formatImage('grounds', language, tag);

            it('formats image name with repository prefix', function() {
                var expected = 'grounds/'+IMAGE_PREFIX+'-'+language+':'+tag;

                expect(formated).to.equal(expected);
            });
        });

        context('when no repository is specified', function() {
            var language = 'java',
                tag      = '1.0.0',
                formated = utils.formatImage('', language, tag);

            it('formats image name without repository prefix', function() {
                expect(formated).to.equal(IMAGE_PREFIX+'-'+language+':'+tag);
            });
        });

        context('when no language is specified', function() {
            it("doesn't fail" function() {
                expect(function() {
                    utils.formatImage('grounds');
                }).not.to.throw(Error);
            });
        });

        context('when no tag is specified', function() {
            it("doesn't fail" function() {
                expect(function() {
                    utils.formatImage('grounds', 'ruby');
                }).not.to.throw(Error);
            });
        });
    });

    describe('.formatCmd()', function() {
        var formated = utils.formatCmd('puts "Hello world\\n\\r\\t"\r\n\t');

        it('returns an escaped string', function() {
            var escapedString = 'puts "Hello world\\\\n\\\\r\\\\t"\\r\\n\\t';

            expect(formated).to.equal(escapedString);
        });

        context('when code is not specified', function() {
            var formated = utils.formatCmd();

            it('returns an empty string', function() {
                expect(formated).to.equal('');
            });
        });
    });

    describe('.formatStatus()', function() {
        it('returns a signed integer (range -128 to 127)', function() {
            var statusTable     = [0, 1, 128, 254, 255],
                statusExpected  = [0, 1, -128, -2, -1];

            for (var i in statusTable) {
                var formated = utils.formatStatus(statusTable[i]),
                    expected = statusExpected[i];

                expect(formated).to.equal(expected);
            }
        });
    });
});
<|endoftext|>


<commit_before>import Immutable from 'immutable'
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { POST } from '../constants/action_types'
import { scrollToPosition, scrollToSelector } from '../lib/jello'
import { selectIsLoggedIn } from '../selectors/authentication'
import { selectColumnCount, selectInnerHeight } from '../selectors/gui'
import { selectParamsToken, selectParamsUsername } from '../selectors/params'
import {
  selectPost,
  selectPostAuthor,
  selectPostDetailTabs,
  selectPostHasRelatedButton,
  selectPostIsEmpty,
  selectPropsLocationStateFrom,
} from '../selectors/post'
import { selectAvatar } from '../selectors/profile'
import { selectPropsLocationKey } from '../selectors/routing'
import { selectStreamType } from '../selectors/stream'
import { loadComments, loadPostDetail, loadRelatedPosts } from '../actions/posts'
import { ErrorState4xx } from '../components/errors/Errors'
import { Paginator } from '../components/streams/Paginator'
import { PostDetail, PostDetailError } from '../components/views/PostDetail'
import { postLovers, postReposters } from '../networking/api'
import { loadUserDrawer } from '../actions/user'

function mapStateToProps(state, props) {
  return {
    author: selectPostAuthor(state, props),
    avatar: selectAvatar(state),
    columnCount: selectColumnCount(state, props),
    hasRelatedPostsButton: selectPostHasRelatedButton(state, props),
    innerHeight: selectInnerHeight(state, props),
    isLoggedIn: selectIsLoggedIn(state),
    isPostEmpty: selectPostIsEmpty(state, props),
    locationKey: selectPropsLocationKey(state, props),
    locationStateFrom: selectPropsLocationStateFrom(state, props),
    paramsToken: selectParamsToken(state, props),
    paramsUsername: selectParamsUsername(state, props),
    post: selectPost(state, props),
    tabs: selectPostDetailTabs(state, props),
    streamType: selectStreamType(state),
  }
}

class PostDetailContainer extends Component {

  static propTypes = {
    author: PropTypes.object,
    avatar: PropTypes.object,
    columnCount: PropTypes.number.isRequired,
    dispatch: PropTypes.func.isRequired,
    hasRelatedPostsButton: PropTypes.bool.isRequired,
    innerHeight: PropTypes.number.isRequired,
    isLoggedIn: PropTypes.bool.isRequired,
    isPostEmpty: PropTypes.bool.isRequired,
    locationKey: PropTypes.string.isRequired,
    locationStateFrom: PropTypes.string,
    post: PropTypes.object,
    paramsToken: PropTypes.string.isRequired,
    paramsUsername: PropTypes.string.isRequired,
    streamType: PropTypes.string, // eslint-disable-line
    tabs: PropTypes.array.isRequired,
  }

  static defaultProps = {
    author: null,
    avatar: null,
    locationStateFrom: null,
    post: null,
    streamType: null,
  }

  static childContextTypes = {
    onClickDetailTab: PropTypes.func.isRequired,
    onClickScrollToRelatedPosts: PropTypes.func.isRequired,
  }

  static preRender = (store, routerState) => {
    const params = routerState.params
    const token = `~${params.token}`
    return Promise.all([
      store.dispatch(loadPostDetail(token, `~${params.username}`)),
      store.dispatch(loadRelatedPosts(token, 3)),
    ])
  }

  getChildContext() {
    return {
      onClickDetailTab: this.onClickDetailTab,
      onClickScrollToRelatedPosts: this.onClickScrollToRelatedPosts,
    }
  }

  componentWillMount() {
    const { dispatch, paramsToken, paramsUsername, post, isPostEmpty } = this.props
    if (!isPostEmpty) {
      this.lovesWasOpen = post.get('showLovers')
      this.repostsWasOpen = post.get('showReposters')
    }
    this.state = { activeType: 'comments', renderType: POST.DETAIL_REQUEST }
    dispatch(loadPostDetail(`~${paramsToken}`, `~${paramsUsername}`))
  }

  componentDidMount() {
    if (this.props.locationStateFrom === 'PaginatorLink') {
      requestAnimationFrame(() => {
        scrollToSelector('.TabListStreamContainer', { boundary: 'bottom', offset: 200 })
      })
    }
  }

  componentWillReceiveProps(nextProps) {
    const { dispatch, locationKey, paramsToken, paramsUsername } = this.props
    // a click on the notification post link when we are already on the post
    // should trigger the loading of additional content if it exists
    if ((paramsToken !== nextProps.paramsToken || paramsUsername !== nextProps.paramsUsername) ||
        (paramsToken === nextProps.paramsToken && locationKey !== nextProps.locationKey)) {
      // load the new detail or trigger a reload of the current
      dispatch(loadPostDetail(`~${nextProps.paramsToken}`, `~${nextProps.paramsUsername}`))
      const action = this.getStreamAction()
      if (action) { dispatch(action) }
    }
    switch (nextProps.streamType) {
      case POST.DETAIL_FAILURE:
      case POST.DETAIL_REQUEST:
      case POST.DETAIL_SUCCESS:
        this.setState({ renderType: nextProps.streamType })
        break
      default:
        break
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (!nextProps.author || !nextProps.post) { return false }
    return !Immutable.is(nextProps.post, this.props.post) ||
      ['hasRelatedPostsButton', 'paramsToken', 'paramsUsername'].some(prop =>
        nextProps[prop] !== this.props[prop],
      ) ||
      ['activeType', 'renderType'].some(prop => nextState[prop] !== this.state[prop])
  }

  onClickDetailTab = (vo) => {
    if (vo.type) {
      this.setState({ activeType: vo.type })
    }
  }

  onClickScrollToRelatedPosts = () => {
    const { innerHeight } = this.props
    const el = document.querySelector('.RelatedPostsStreamContainer')
    if (!el) { return }
    const rect = el.getBoundingClientRect()
    const dy = innerHeight < rect.height ? rect.height + (innerHeight - rect.height) : rect.height
    scrollToPosition(0, window.scrollY + dy + (rect.top - innerHeight))
  }

  getStreamAction() {
    const { author, post } = this.props
    const { activeType } = this.state
    const postId = post.get('id')
    switch (activeType) {
      case 'loves':
        return loadUserDrawer(postLovers(postId), postId, activeType)
      case 'reposts':
        return loadUserDrawer(postReposters(postId), postId, activeType)
      default:
        return author && author.get('hasCommentingEnabled') ? loadComments(post.get('id'), false) : null
    }
  }

  render() {
    const {
      author,
      avatar,
      columnCount,
      hasRelatedPostsButton,
      isLoggedIn,
      isPostEmpty,
      paramsToken,
      post,
      tabs,
    } = this.props
    const { activeType, renderType } = this.state
    // render loading/failure if we don't have an initial post
    if (isPostEmpty) {
      if (renderType === POST.DETAIL_REQUEST) {
        return (

            <Paginator className="isBusy" />

        )
      } else if (renderType === POST.DETAIL_FAILURE) {
        return (
          <PostDetailError>
            <ErrorState4xx />
          </PostDetailError>
        )
      }
      return null
    }
    const props = {
      activeType,
      author,
      avatar,
      columnCount,
      hasEditor: author && author.get('hasCommentingEnabled') && !(post.get('isReposting') || post.get('isEditing')),
      hasRelatedPostsButton,
      isLoggedIn,
      key: `postDetail_${paramsToken}`,
      post,
      streamAction: this.getStreamAction(),
      tabs,
    }
    return <PostDetail {...props} />
  }
}

export default connect(mapStateToProps)(PostDetailContainer)

<commit_msg>Fix proptype warning refreshing on post detail<commit_after>import Immutable from 'immutable'
import React, { Component, PropTypes } from 'react'
import { connect } from 'react-redux'
import { POST } from '../constants/action_types'
import { scrollToPosition, scrollToSelector } from '../lib/jello'
import { selectIsLoggedIn } from '../selectors/authentication'
import { selectColumnCount, selectInnerHeight } from '../selectors/gui'
import { selectParamsToken, selectParamsUsername } from '../selectors/params'
import {
  selectPost,
  selectPostAuthor,
  selectPostDetailTabs,
  selectPostHasRelatedButton,
  selectPostIsEmpty,
  selectPropsLocationStateFrom,
} from '../selectors/post'
import { selectAvatar } from '../selectors/profile'
import { selectPropsLocationKey } from '../selectors/routing'
import { selectStreamType } from '../selectors/stream'
import { loadComments, loadPostDetail, loadRelatedPosts } from '../actions/posts'
import { ErrorState4xx } from '../components/errors/Errors'
import { Paginator } from '../components/streams/Paginator'
import { PostDetail, PostDetailError } from '../components/views/PostDetail'
import { postLovers, postReposters } from '../networking/api'
import { loadUserDrawer } from '../actions/user'

function mapStateToProps(state, props) {
  return {
    author: selectPostAuthor(state, props),
    avatar: selectAvatar(state),
    columnCount: selectColumnCount(state, props),
    hasRelatedPostsButton: selectPostHasRelatedButton(state, props),
    innerHeight: selectInnerHeight(state, props),
    isLoggedIn: selectIsLoggedIn(state),
    isPostEmpty: selectPostIsEmpty(state, props),
    locationKey: selectPropsLocationKey(state, props),
    locationStateFrom: selectPropsLocationStateFrom(state, props),
    paramsToken: selectParamsToken(state, props),
    paramsUsername: selectParamsUsername(state, props),
    post: selectPost(state, props),
    tabs: selectPostDetailTabs(state, props),
    streamType: selectStreamType(state),
  }
}

class PostDetailContainer extends Component {

  static propTypes = {
    author: PropTypes.object,
    avatar: PropTypes.object,
    columnCount: PropTypes.number.isRequired,
    dispatch: PropTypes.func.isRequired,
    hasRelatedPostsButton: PropTypes.bool.isRequired,
    innerHeight: PropTypes.number.isRequired,
    isLoggedIn: PropTypes.bool.isRequired,
    isPostEmpty: PropTypes.bool.isRequired,
    locationKey: PropTypes.string,
    locationStateFrom: PropTypes.string,
    post: PropTypes.object,
    paramsToken: PropTypes.string.isRequired,
    paramsUsername: PropTypes.string.isRequired,
    streamType: PropTypes.string, // eslint-disable-line
    tabs: PropTypes.array.isRequired,
  }

  static defaultProps = {
    author: null,
    avatar: null,
    locationKey: null,
    locationStateFrom: null,
    post: null,
    streamType: null,
  }

  static childContextTypes = {
    onClickDetailTab: PropTypes.func.isRequired,
    onClickScrollToRelatedPosts: PropTypes.func.isRequired,
  }

  static preRender = (store, routerState) => {
    const params = routerState.params
    const token = `~${params.token}`
    return Promise.all([
      store.dispatch(loadPostDetail(token, `~${params.username}`)),
      store.dispatch(loadRelatedPosts(token, 3)),
    ])
  }

  getChildContext() {
    return {
      onClickDetailTab: this.onClickDetailTab,
      onClickScrollToRelatedPosts: this.onClickScrollToRelatedPosts,
    }
  }

  componentWillMount() {
    const { dispatch, paramsToken, paramsUsername, post, isPostEmpty } = this.props
    if (!isPostEmpty) {
      this.lovesWasOpen = post.get('showLovers')
      this.repostsWasOpen = post.get('showReposters')
    }
    this.state = { activeType: 'comments', renderType: POST.DETAIL_REQUEST }
    dispatch(loadPostDetail(`~${paramsToken}`, `~${paramsUsername}`))
  }

  componentDidMount() {
    if (this.props.locationStateFrom === 'PaginatorLink') {
      requestAnimationFrame(() => {
        scrollToSelector('.TabListStreamContainer', { boundary: 'bottom', offset: 200 })
      })
    }
  }

  componentWillReceiveProps(nextProps) {
    const { dispatch, locationKey, paramsToken, paramsUsername } = this.props
    // a click on the notification post link when we are already on the post
    // should trigger the loading of additional content if it exists
    if ((paramsToken !== nextProps.paramsToken || paramsUsername !== nextProps.paramsUsername) ||
        (paramsToken === nextProps.paramsToken && locationKey !== nextProps.locationKey)) {
      // load the new detail or trigger a reload of the current
      dispatch(loadPostDetail(`~${nextProps.paramsToken}`, `~${nextProps.paramsUsername}`))
      const action = this.getStreamAction()
      if (action) { dispatch(action) }
    }
    switch (nextProps.streamType) {
      case POST.DETAIL_FAILURE:
      case POST.DETAIL_REQUEST:
      case POST.DETAIL_SUCCESS:
        this.setState({ renderType: nextProps.streamType })
        break
      default:
        break
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (!nextProps.author || !nextProps.post) { return false }
    return !Immutable.is(nextProps.post, this.props.post) ||
      ['hasRelatedPostsButton', 'paramsToken', 'paramsUsername'].some(prop =>
        nextProps[prop] !== this.props[prop],
      ) ||
      ['activeType', 'renderType'].some(prop => nextState[prop] !== this.state[prop])
  }

  onClickDetailTab = (vo) => {
    if (vo.type) {
      this.setState({ activeType: vo.type })
    }
  }

  onClickScrollToRelatedPosts = () => {
    const { innerHeight } = this.props
    const el = document.querySelector('.RelatedPostsStreamContainer')
    if (!el) { return }
    const rect = el.getBoundingClientRect()
    const dy = innerHeight < rect.height ? rect.height + (innerHeight - rect.height) : rect.height
    scrollToPosition(0, window.scrollY + dy + (rect.top - innerHeight))
  }

  getStreamAction() {
    const { author, post } = this.props
    const { activeType } = this.state
    const postId = post.get('id')
    switch (activeType) {
      case 'loves':
        return loadUserDrawer(postLovers(postId), postId, activeType)
      case 'reposts':
        return loadUserDrawer(postReposters(postId), postId, activeType)
      default:
        return author && author.get('hasCommentingEnabled') ? loadComments(post.get('id'), false) : null
    }
  }

  render() {
    const {
      author,
      avatar,
      columnCount,
      hasRelatedPostsButton,
      isLoggedIn,
      isPostEmpty,
      paramsToken,
      post,
      tabs,
    } = this.props
    const { activeType, renderType } = this.state
    // render loading/failure if we don't have an initial post
    if (isPostEmpty) {
      if (renderType === POST.DETAIL_REQUEST) {
        return (

            <Paginator className="isBusy" />

        )
      } else if (renderType === POST.DETAIL_FAILURE) {
        return (
          <PostDetailError>
            <ErrorState4xx />
          </PostDetailError>
        )
      }
      return null
    }
    const props = {
      activeType,
      author,
      avatar,
      columnCount,
      hasEditor: author && author.get('hasCommentingEnabled') && !(post.get('isReposting') || post.get('isEditing')),
      hasRelatedPostsButton,
      isLoggedIn,
      key: `postDetail_${paramsToken}`,
      post,
      streamAction: this.getStreamAction(),
      tabs,
    }
    return <PostDetail {...props} />
  }
}

export default connect(mapStateToProps)(PostDetailContainer)

<|endoftext|>


<commit_before>import $ from 'jquery';
import '~/commons/bootstrap';

export default {
  bind(el) {
    $(el).tooltip({
      trigger: 'hover',
    });
  },

  componentUpdated(el) {
    $(el).tooltip('_fixTitle');

    // update visible tooltips
    const tooltipInstance = $(el).data('bs.tooltip');
    const tip = tooltipInstance.getTipElement();
    tooltipInstance.setElementContent(
      $(tip.querySelectorAll('.tooltip-inner')),
      tooltipInstance.getTitle(),
    );
  },

  unbind(el) {
    $(el).tooltip('dispose');
  },
};
<commit_msg>Add delay customization to tooltip.js<commit_after>import $ from 'jquery';
import '~/commons/bootstrap';

export default {
  bind(el) {
    const glTooltipDelay = localStorage.getItem('gl-tooltip-delay');
    const delay = glTooltipDelay ? JSON.parse(glTooltipDelay) : 0;

    $(el).tooltip({
      trigger: 'hover',
      delay,
    });
  },

  componentUpdated(el) {
    $(el).tooltip('_fixTitle');

    // update visible tooltips
    const tooltipInstance = $(el).data('bs.tooltip');
    const tip = tooltipInstance.getTipElement();
    tooltipInstance.setElementContent(
      $(tip.querySelectorAll('.tooltip-inner')),
      tooltipInstance.getTitle(),
    );
  },

  unbind(el) {
    $(el).tooltip('dispose');
  },
};
<|endoftext|>


<commit_before>import React, { useEffect, useState } from 'react';
import { PropTypes as T } from 'prop-types';
import { connect } from 'react-redux';
import qs from 'qs';

import {
  fetchLocations as fetchLocationsAction,
  invalidateLocations as invalidateLocationsAction,
  openDownloadModal as openDownloadModalAction,
} from '../../actions/action-creators';
import { buildQS } from '../../utils/url';

import Header from '../../components/header';
import Filter from './filter';
import Results from './results';

const PER_PAGE = 15;

function getPage(query) {
  if (query && query.page) {
    let page = query.page;
    page = isNaN(page) || page < 1 ? 1 : +page;
    return page;
  }
  return 1;
}

export default function LocationsHub({
  fetchLocations,
  invalidateLocations,
  openDownloadModal,
  parameters,
  countries,
  sources,
  fetching,
  fetched,
  error,
  results,
  meta,

  location,
  history,
}) {
  const [filters, setFilters] = useState({});
  const [page, setPage] = useState(1);

  useEffect(() => {
    // on url change
    let query = qs.parse(location.search, {
      ignoreQueryPrefix: true,
    });
    setPage(() => getPage(query));

    let isMobile;
    if (query.source_type) {
      if (query.source_type.includes('mobile')) {
        isMobile = true;
      } else if (query.source_type.includes('stationary')) {
        isMobile = false;
      }
    }
    setFilters({
      order_by: query.order_by && query.order_by.split(','),
      sort: 'asc',
      parameter:
        query.parameters &&
        query.parameters.split(',').map(param => param.toLowerCase()),
      country: query.countries && query.countries.split(','),
      source: query.sources && query.sources.split(','),
      isMobile,
    });
  }, [location]);

  useEffect(() => {
    fetchLocations(page, filters, PER_PAGE);
    return () => {
      invalidateLocations();
    };
  }, [page, filters]);

  function handlePageClick(d) {
    let query = qs.parse(location.search, { ignoreQueryPrefix: true });
    query.page = d.selected + 1;

    history.push(`/locations?${buildQS(query)}`);
  }

  const totalPages = Math.ceil(meta.found / PER_PAGE);

  return (

              <Filter
                parameters={parameters}
                countries={countries}
                sources={sources}
              />

Results

                  {meta.found ? (

                      A total of {meta.found} locations were
                      found

                  ) : null}

            <Results
              fetched={fetched}
              fetching={fetching}
              error={error}
              locations={results}
              totalPages={totalPages}
              page={page}
              openDownloadModal={openDownloadModal}
              handlePageClick={handlePageClick}
            />

  );
}

LocationsHub.propTypes = {
  parameters: T.array,

  fetching: T.bool,
  fetched: T.bool,
  error: T.object,
  results: T.array,
  meta: T.object,
  countries: T.array,
  sources: T.array,

  location: T.object,
  history: T.object,

  fetchLocations: T.func,
  invalidateLocations: T.func,
  openDownloadModal: T.func,
};

// /////////////////////////////////////////////////////////////////////
// Connect functions

function selector(state) {
  return {
    parameters: state.baseData.data.parameters,
    countries: state.baseData.data.countries,
    sources: state.baseData.data.sources,
    fetching: state.locations.fetching,
    fetched: state.locations.fetched,
    error: state.locations.error,
    results: state.locations.data.results,
    meta: state.locations.data.meta,
  };
}

function dispatcher(dispatch) {
  return {
    fetchLocations: (...args) => dispatch(fetchLocationsAction(...args)),
    invalidateLocations: (...args) =>
      dispatch(invalidateLocationsAction(...args)),
    openDownloadModal: (...args) => dispatch(openDownloadModalAction(...args)),
  };
}

module.exports = connect(selector, dispatcher)(LocationsHub);
<commit_msg>default locations sort by most recent<commit_after>import React, { useEffect, useState } from 'react';
import { PropTypes as T } from 'prop-types';
import { connect } from 'react-redux';
import qs from 'qs';

import {
  fetchLocations as fetchLocationsAction,
  invalidateLocations as invalidateLocationsAction,
  openDownloadModal as openDownloadModalAction,
} from '../../actions/action-creators';
import { buildQS } from '../../utils/url';

import Header from '../../components/header';
import Filter from './filter';
import Results from './results';

const PER_PAGE = 15;

function getPage(query) {
  if (query && query.page) {
    let page = query.page;
    page = isNaN(page) || page < 1 ? 1 : +page;
    return page;
  }
  return 1;
}

export default function LocationsHub({
  fetchLocations,
  invalidateLocations,
  openDownloadModal,
  parameters,
  countries,
  sources,
  fetching,
  fetched,
  error,
  results,
  meta,

  location,
  history,
}) {
  const [filters, setFilters] = useState({});
  const [page, setPage] = useState(1);

  useEffect(() => {
    // on url change
    let query = qs.parse(location.search, {
      ignoreQueryPrefix: true,
    });
    setPage(() => getPage(query));

    let isMobile;
    if (query.source_type) {
      if (query.source_type.includes('mobile')) {
        isMobile = true;
      } else if (query.source_type.includes('stationary')) {
        isMobile = false;
      }
    }
    setFilters({
      order_by: query.order_by && query.order_by.split(','),
      sort: 'desc',
      parameter:
        query.parameters &&
        query.parameters.split(',').map(param => param.toLowerCase()),
      country: query.countries && query.countries.split(','),
      source: query.sources && query.sources.split(','),
      isMobile,
    });
  }, [location]);

  useEffect(() => {
    fetchLocations(page, filters, PER_PAGE);
    return () => {
      invalidateLocations();
    };
  }, [page, filters]);

  function handlePageClick(d) {
    let query = qs.parse(location.search, { ignoreQueryPrefix: true });
    query.page = d.selected + 1;

    history.push(`/locations?${buildQS(query)}`);
  }

  const totalPages = Math.ceil(meta.found / PER_PAGE);

  return (

              <Filter
                parameters={parameters}
                countries={countries}
                sources={sources}
              />

Results

                  {meta.found ? (

                      A total of {meta.found} locations were
                      found

                  ) : null}

            <Results
              fetched={fetched}
              fetching={fetching}
              error={error}
              locations={results}
              totalPages={totalPages}
              page={page}
              openDownloadModal={openDownloadModal}
              handlePageClick={handlePageClick}
            />

  );
}

LocationsHub.propTypes = {
  parameters: T.array,

  fetching: T.bool,
  fetched: T.bool,
  error: T.object,
  results: T.array,
  meta: T.object,
  countries: T.array,
  sources: T.array,

  location: T.object,
  history: T.object,

  fetchLocations: T.func,
  invalidateLocations: T.func,
  openDownloadModal: T.func,
};

// /////////////////////////////////////////////////////////////////////
// Connect functions

function selector(state) {
  return {
    parameters: state.baseData.data.parameters,
    countries: state.baseData.data.countries,
    sources: state.baseData.data.sources,
    fetching: state.locations.fetching,
    fetched: state.locations.fetched,
    error: state.locations.error,
    results: state.locations.data.results,
    meta: state.locations.data.meta,
  };
}

function dispatcher(dispatch) {
  return {
    fetchLocations: (...args) => dispatch(fetchLocationsAction(...args)),
    invalidateLocations: (...args) =>
      dispatch(invalidateLocationsAction(...args)),
    openDownloadModal: (...args) => dispatch(openDownloadModalAction(...args)),
  };
}

module.exports = connect(selector, dispatcher)(LocationsHub);
<|endoftext|>


<commit_before>var User = function(id, token){
  this.id = id;
  this.token = token;
};

var geoJSON = {
  "type": "FeatureCollection",
  "features":[]
};

var Rides = function(ridesData) {
  this.rides=ridesData;
  this.date = Date.now();

};

Rides.prototype.getDestinations = function() {
  var d = this.rides.map(function(ride){
    return {id: ride.id,
      lat: ride.destination.lat,
      lng: ride.destination.lng
    };
  });
  return d;
};

Rides.prototype.getAddresses = function(){
  var a = this.rides.map(function(ride){
    return {
      id: ride.id,
      destination: ride.destination.address,
      start_point: ride.start_point.address
    };
  });
  return a;
};

Rides.prototype.refresh = function(){
  var now = Date.now;
  if (now - this.date >= 10000){
      rsapi.getRides(ridesCallback);
    }
};

Rides.prototype.findById = function(id){
  id = parseInt(id);
  return this.rides.filter(function(ride){

    return (ride.id === id);
  });
};

Rides.prototype.setProperties = function(){
  if (user) {
    this.rides.forEach(function(ride){
      // sets the number of passengers on the ride
      ride.numberOfPassengers = ride.passengers.length;
      // sets the number of seats left
      seatsLeft = ride.spots_available - ride.passengers.length;
      if (seatsLeft >= 0){
        ride.seats_left = seatsLeft;
      } else {
        ride.seats_left = 0;
      }
      // determine whether the user is a passenger
      if (ride.passengers.some(function(passenger){
        return passenger.id === user.id})) {
        ride.isPassenger = true;
      } else {
        ride.isPassenger = false;
      }
      //determine whether th user owns this ride
      if (user.id === ride.owner.id){
        ride.isOwner = true;
      } else {
        ride.isOwner = false;
      }
    });
  }
};

// "type": "FeatureCollection",
// "features": [
//   {
//     "type": "Feature",
//     "geometry": {
//       "type": "Point",
//       "coordinates": [
//         -77.034084142948,
//         38.909671288923
//       ]
//     },
//     "properties": {
//       "phoneFormatted": "(202) 234-7336",
//       "phone": "2022347336",
//       "address": "1471 P St NW",
//       "city": "Washington DC",
//       "country": "United States",
//       "crossStreet": "at 15th St NW",
//       "postalCode": "20005",
//       "state": "D.C."
//     }
//   }

Rides.prototype.getDestinationGeoJSON = function(){
  this.rides.forEach (function(ride){
    geoJSON.features.push({

    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [ride.destination.lng, ride.destination.lat]
    },
    "properties": {
      "address": ride.destination.address,
      "id": ride.id
    }

    });
  });

};

<commit_msg>Changes findRideBy id to return object rather than array of 1 item<commit_after>var User = function(id, token){
  this.id = id;
  this.token = token;
};

var geoJSON = {
  "type": "FeatureCollection",
  "features":[]
};

var Rides = function(ridesData) {
  this.rides=ridesData;
  this.date = Date.now();

};

Rides.prototype.getDestinations = function() {
  var d = this.rides.map(function(ride){
    return {id: ride.id,
      lat: ride.destination.lat,
      lng: ride.destination.lng
    };
  });
  return d;
};

Rides.prototype.getAddresses = function(){
  var a = this.rides.map(function(ride){
    return {
      id: ride.id,
      destination: ride.destination.address,
      start_point: ride.start_point.address
    };
  });
  return a;
};

Rides.prototype.refresh = function(){
  var now = Date.now;
  if (now - this.date >= 10000){
      rsapi.getRides(ridesCallback);
    }
};

Rides.prototype.findById = function(id){
  id = parseInt(id);
  return this.rides.filter(function(ride){

    return (ride.id === id);
  })[0];
};

Rides.prototype.setProperties = function(){
  if (user) {
    this.rides.forEach(function(ride){
      // sets the number of passengers on the ride
      ride.numberOfPassengers = ride.passengers.length;
      // sets the number of seats left
      seatsLeft = ride.spots_available - ride.passengers.length;
      if (seatsLeft >= 0){
        ride.seats_left = seatsLeft;
      } else {
        ride.seats_left = 0;
      }
      // determine whether the user is a passenger
      if (ride.passengers.some(function(passenger){
        return passenger.id === user.id})) {
        ride.isPassenger = true;
      } else {
        ride.isPassenger = false;
      }
      //determine whether th user owns this ride
      if (user.id === ride.owner.id){
        ride.isOwner = true;
      } else {
        ride.isOwner = false;
      }
    });
  }
};

// "type": "FeatureCollection",
// "features": [
//   {
//     "type": "Feature",
//     "geometry": {
//       "type": "Point",
//       "coordinates": [
//         -77.034084142948,
//         38.909671288923
//       ]
//     },
//     "properties": {
//       "phoneFormatted": "(202) 234-7336",
//       "phone": "2022347336",
//       "address": "1471 P St NW",
//       "city": "Washington DC",
//       "country": "United States",
//       "crossStreet": "at 15th St NW",
//       "postalCode": "20005",
//       "state": "D.C."
//     }
//   }

Rides.prototype.getDestinationGeoJSON = function(){
  this.rides.forEach (function(ride){
    geoJSON.features.push({

    "type": "Feature",
    "geometry": {
      "type": "Point",
      "coordinates": [ride.destination.lng, ride.destination.lat]
    },
    "properties": {
      "address": ride.destination.address,
      "id": ride.id
    }

    });
  });

};

<|endoftext|>


<commit_before>// Javascript for rendering a onebox link

// render links on page

// exists
(function($) {
	jQuery.fn.exists = function() {
		return this.length > 0;
	};
})(jQuery);

// onebox construction
(function($) {
	jQuery.fn.onebox = function() {
		if ($(this).exists()) {
			return this.each(function () {
				var $this = $(this),
					url = $(this).children().eq(0).attr("href"),
					title ="",
					description ="";
				if($(this).data("title")) title = $(this).data("title");
				if($(this).data("description")) description = $(this).data("description");

				var	requesturl = OneboxParams.renderURL
						+ (OneboxParams.renderURL.indexOf('?') != -1 ? "&onebox_url=" : "?onebox_url=") + encodeURIComponent(url)
						+ "&onebox_title=" + encodeURIComponent(title)
						+ "&onebox_description=" + encodeURIComponent(description);
				//console.log(requesturl);

				$.getJSON(requesturl, function (data) {
					//console.log(data.data); //uncomment this for debug
					if(data.data) {
						if(data.data.displayurl) url = data.data.displayurl;
						else url = data.data.url;

						var template = OneboxParams.template;

						if(OneboxParams.flat) data.classes +=' flat';
						if(OneboxParams.dark) data.classes +=' dark';

						template = template.replace(/{url}/g, url);
						template = template.replace(/{class}/g, data.classes);
						if(data.data.favicon) template = template.replace(/{favicon}/g, '');
						else template = template.replace(/{favicon}/g, '');
						template = template.replace(/{sitename}/g, data.data.sitename);
						if(data.data.image) template = template.replace(/{image}/g, '');
						else template = template.replace(/{image}/g, '');
						template = template.replace(/{title}/g, data.data.title);
						template = template.replace(/{description}/g, data.data.description);
						template = template.replace(/{additional}/g, data.data.additional);
						template = template.replace(/{footer}/g, data.data.footer);
						template = template.replace(/{title-button}/g, data.data.titlebutton);
						template = template.replace(/{footer-button}/g, data.data.footerbutton);

						$this.html(template);
						// convert ratings
						$this.find('.onebox-stars').oneboxstars();
					}
				});
			});
		}
	};
})(jQuery);

// stars
// http://stackoverflow.com/questions/1987524/turn-a-number-into-star-rating-display-using-jquery-and-css
(function($) {
	jQuery.fn.oneboxstars = function() {
		if ($(this).exists()) {
			return this.each(function() {
				// Get the value
				var val = parseFloat($(this).html());
				// Make sure that the value is in 0 - 5 range, multiply to get width
				var size = Math.max(0, (Math.min(5, val))) * 16;
				// Create stars holder
				var $span = $('').width(size);
				// Replace the numerical value with stars
				$(this).html($span);
			});
		}
	};
})(jQuery);

jQuery(document).ready(function() {
	if(OneboxParams.selector) jQuery(OneboxParams.selector).onebox();
});
<commit_msg>make plugin chainable<commit_after>// Javascript for rendering a onebox link

// render links on page

// exists
(function($) {
	jQuery.fn.exists = function() {
		return this.length > 0;
	};
})(jQuery);

// onebox construction
(function($) {
	jQuery.fn.onebox = function() {
		if ($(this).exists()) {
			return this.each(function () {
				var $this = $(this),
					url = $(this).children().eq(0).attr("href"),
					title ="",
					description ="";
				if($(this).data("title")) title = $(this).data("title");
				if($(this).data("description")) description = $(this).data("description");

				var	requesturl = OneboxParams.renderURL
						+ (OneboxParams.renderURL.indexOf('?') != -1 ? "&onebox_url=" : "?onebox_url=") + encodeURIComponent(url)
						+ "&onebox_title=" + encodeURIComponent(title)
						+ "&onebox_description=" + encodeURIComponent(description);
				//console.log(requesturl);

				$.getJSON(requesturl, function (data) {
					//console.log(data.data); //uncomment this for debug
					if(data.data) {
						if(data.data.displayurl) url = data.data.displayurl;
						else url = data.data.url;

						var template = OneboxParams.template;

						if(OneboxParams.flat) data.classes +=' flat';
						if(OneboxParams.dark) data.classes +=' dark';

						template = template.replace(/{url}/g, url);
						template = template.replace(/{class}/g, data.classes);
						if(data.data.favicon) template = template.replace(/{favicon}/g, '');
						else template = template.replace(/{favicon}/g, '');
						template = template.replace(/{sitename}/g, data.data.sitename);
						if(data.data.image) template = template.replace(/{image}/g, '');
						else template = template.replace(/{image}/g, '');
						template = template.replace(/{title}/g, data.data.title);
						template = template.replace(/{description}/g, data.data.description);
						template = template.replace(/{additional}/g, data.data.additional);
						template = template.replace(/{footer}/g, data.data.footer);
						template = template.replace(/{title-button}/g, data.data.titlebutton);
						template = template.replace(/{footer-button}/g, data.data.footerbutton);

						$this.html(template);
						// convert ratings
						$this.find('.onebox-stars').oneboxstars();
					}
				});
			});
		}
		else return this;
	};
})(jQuery);

// stars
// http://stackoverflow.com/questions/1987524/turn-a-number-into-star-rating-display-using-jquery-and-css
(function($) {
	jQuery.fn.oneboxstars = function() {
		if ($(this).exists()) {
			return this.each(function() {
				// Get the value
				var val = parseFloat($(this).html());
				// Make sure that the value is in 0 - 5 range, multiply to get width
				var size = Math.max(0, (Math.min(5, val))) * 16;
				// Create stars holder
				var $span = $('').width(size);
				// Replace the numerical value with stars
				$(this).html($span);
			});
		}
		else return this;
	};
})(jQuery);

jQuery(document).ready(function() {
	if(OneboxParams.selector) jQuery(OneboxParams.selector).onebox();
});
<|endoftext|>


<commit_before>/**
 * @preserve
 *
 *                                      .,,,;;,'''..
 *                                  .'','...     ..',,,.
 *                                .,,,,,,',,',;;:;,.  .,l,
 *                               .,',.     ...     ,;,   :l.
 *                              ':;.    .'.:do;;.    .c   ol;'.
 *       ';;'                   ;.;    ', .dkl';,    .c   :; .'.',::,,'''.
 *      ',,;;;,.                ; .,'     .'''.    .'.   .d;''.''''.
 *     .oxddl;::,,.             ',  .'''.   .... .'.   ,:;..
 *      .'cOX0OOkdoc.            .,'.   .. .....     'lc.
 *     .:;,,::co0XOko'              ....''..'.'''''''.
 *     .dxk0KKdc:cdOXKl............. .. ..,c....
 *      .',lxOOxl:'':xkl,',......'....    ,'.
 *           .';:oo:...                        .
 *                .cd,      ╔═╗┌┬┐┬┌┬┐┌─┐┬─┐    .
 *                  .l;     ║╣  │││ │ │ │├┬┘    '
 *                    'l.   ╚═╝─┴┘┴ ┴ └─┘┴└─   '.
 *                     .o.                   ...
 *                      .''''','.;:''.........
 *                           .'  .l
 *                          .:.   l'
 *                         .:.    .l.
 *                        .x:      :k;,.
 *                        cxlc;    cdc,,;;.
 *                       'l :..   .c  ,
 *                       o.
 *                      .,
 *
 *              ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐  ╔═╗┌┐  ┬┌─┐┌─┐┌┬┐┌─┐
 *              ╠═╣└┬┘├┴┐├┬┘│ ││  ║ ║├┴┐ │├┤ │   │ └─┐
 *              ╩ ╩ ┴ └─┘┴└─┴─┴┘  ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘
 *
 *
 * Created by Valentin on 10/22/14.
 *
 * Copyright (c) 2015 Valentin Heun
 *
 * All ascii characters above must be included in any redistribution.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
/*********************************************************************************************************************
 ******************************************** TODOS *******************************************************************
 **********************************************************************************************************************

 **
 * TODO -
 **

 **********************************************************************************************************************
 ******************************************** onload content **********************************************************
 **********************************************************************************************************************/

/**
 * @desc
 * @param
 * @param
 * @return
 **/

window.onload = function () {
    uiButtons = document.getElementById("GUI");
    overlayDiv = document.getElementById('overlay');
    overlayImg = document.getElementById('overlayImg');

    GUI();

    if (globalStates.platform !== 'iPad' && globalStates.platform !== 'iPhone' && globalStates.platform !== 'iPod') {
        globalStates.platform = false;
    }

    if (globalStates.platform === 'iPhone') {
        document.getElementById("logButtonDiv").style.visibility = "hidden";
       // document.getElementById("reloadButtonDiv").style.visibility = "hidden";
     //   document.getElementById("preferencesButtonDiv").style.bottom = "36px";

        var editingInterface = document.getElementById("content2title");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.left = "38%";
        editingInterface.style.right = "22%";

        editingInterface = document.getElementById("content1title");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.left = "2%";
        editingInterface.style.right = "65%";

        editingInterface = document.getElementById("content2");
        editingInterface.style.fontSize = "9px";
        editingInterface.style.left = "38%";
        editingInterface.style.right = "22%";
        editingInterface.style.bottom = "14%";

        editingInterface = document.getElementById("content11");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "40%";

        editingInterface = document.getElementById("content12");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "60%";

        editingInterface = document.getElementById("content13");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "40%";

        editingInterface = document.getElementById("content14");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "60%";

        editingInterface = document.getElementById("content15");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "40%";
        editingInterface.innerHTML = 'External Interface
';

        editingInterface = document.getElementById("content16");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "60%";

        editingInterface = document.getElementById("content18");
        editingInterface.style.visibility = 'hidden';

        editingInterface = document.getElementById("content1");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.left = "2%";
        editingInterface.style.right = "65%";
        editingInterface.style.bottom = "14%";

    } else {
        editingInterface = document.getElementById("content15");
        editingInterface.style.paddingTop = "13px";

        editingInterface = document.getElementById("content20");
        editingInterface.innerHTML = '<input id="newURLText"' +

            "style='text-align: left; font-family: Helvetica Neue, Helvetica, Arial; font-size: large;   -webkit-user-select: text;'" +
            'type="text" name="newURL"  size="27" placeholder="http://..."' + "oninput='newURLTextLoad()'>
";
    }

    globalCanvas.canvas = document.getElementById('canvas');
    globalCanvas.canvas.width = globalStates.height;
    globalCanvas.canvas.height = globalStates.width;

    globalCanvas.context = canvas.getContext('2d');

    if (globalStates.platform) {
        window.location.href = "of://kickoff";
    }

    document.handjs_forcePreventDefault = true;
    globalCanvas.canvas.handjs_forcePreventDefault = true;

    globalCanvas.canvas.addEventListener("pointerdown", canvasPointerDown, false);
    ec++;

    document.addEventListener("pointermove", getPossition, false);
    ec++;
    document.addEventListener("pointerdown", documentPointerDown, false);
    //document.addEventListener("pointerdown", getPossition, false);
    ec++;
    document.addEventListener("pointerup", documentPointerUp, false);
    ec++;
    window.addEventListener("message", postMessage, false);
    ec++;
    overlayDiv.addEventListener('touchstart', function (e) {
        e.preventDefault();
    });

    cout("onload");

};

/**
 * @desc
 * @param
 * @param
 * @return
 **/

var postMessage = function (e) {

    //  cout("received: "+ e.data);
    var msgContent = JSON.parse(e.data);

    var tempThisObject = false;

    var thisVersionNumber = 0;

    if (typeof msgContent.pos !== "undefined" && typeof msgContent.obj !== "undefined") {
        if (typeof objectExp[msgContent.obj] !== "undefined") {
            if (msgContent.pos === msgContent.obj) {
                tempThisObject = objectExp[msgContent.pos];
                thisVersionNumber  = parseInt(objectExp[msgContent.pos].version.replace(/\./g, ""));
            } else {
                if (typeof objectExp[msgContent.obj].objectValues[msgContent.pos] !== "undefined") {
                    tempThisObject = objectExp[msgContent.obj].objectValues[msgContent.pos];
                    thisVersionNumber  = parseInt(objectExp[msgContent.obj].version.replace(/\./g, ""));
                }
            }
        }
    }

    if (tempThisObject !== false) {

            if (typeof msgContent.width !== "undefined" && typeof msgContent.height !== "undefined") {

                document.getElementById(msgContent.pos).style.width = msgContent.width;
                document.getElementById(msgContent.pos).style.height = msgContent.height;
                document.getElementById(msgContent.pos).style.top = ((globalStates.width - msgContent.height) / 2);
                document.getElementById(msgContent.pos).style.left = ((globalStates.height - msgContent.width) / 2);

                document.getElementById("iframe" + msgContent.pos).style.width = msgContent.width;
                document.getElementById("iframe" + msgContent.pos).style.height = msgContent.height;
                document.getElementById("iframe" + msgContent.pos).style.top = ((globalStates.width - msgContent.height) / 2);
                document.getElementById("iframe" + msgContent.pos).style.left = ((globalStates.height - msgContent.width) / 2);

            }
        if (typeof msgContent.sendMatrix !== "undefined") {
                if (msgContent.sendMatrix === true) {
                    if(thisVersionNumber>=32) {
                        tempThisObject.sendMatrix = true;
                        document.getElementById("iframe" + msgContent.pos).contentWindow.postMessage(
                            '{"projectionMatrix":' + JSON.stringify(globalStates.realProjectionMatrix) + "}", '*');
                    }
                }
                // forward postMessages to all iFrames
            }
        if (typeof msgContent.ohGlobalMessage !== "undefined") {
                var iframes = document.getElementsByTagName('iframe');
                for (var i = 0; i < iframes.length; i++) {

                    if (iframes[i].id !== "iframe" + msgContent.pos && iframes[i].style.visibility !== "hidden") {
                        if(thisVersionNumber>=32) {
                            iframes[i].contentWindow.postMessage(
                                JSON.stringify(
                                    {
                                        "ohGlobalMessage": msgContent.ohGlobalMessage
                                    })
                                , "*");
                        }
                    }
                }
            }
        if (typeof msgContent.fullScreen !== "undefined") {
               // console.log("gotfullscreenmessage");
                if (msgContent.fullScreen === true) {
                    tempThisObject.fullScreen = true;

                    document.getElementById("thisObject" + msgContent.pos).style.webkitTransform =
                        'matrix3d(1, 0, 0, 0,' +
                        '0, 1, 0, 0,' +
                        '0, 0, 1, 0,' +
                        '0, 0, 0, 1)';

                }
            if (msgContent.fullScreen === false) {
                   // console.log("noFullscreen");
                    tempThisObject.fullScreen = false;
                }

            }
    }

    /* if (typeof msgContent.sendAcl !== "undefined") {
     if(msgContent.sendAcl === true) {
     objectExp[msgContent.obj].sendAcl = true;
     window.location.href = "of://sendAccelerationData";
     }
     }*/

    // cout("postMessage");

};
<commit_msg>Bugfix: Reality Editor works now on iPod touch<commit_after>/**
 * @preserve
 *
 *                                      .,,,;;,'''..
 *                                  .'','...     ..',,,.
 *                                .,,,,,,',,',;;:;,.  .,l,
 *                               .,',.     ...     ,;,   :l.
 *                              ':;.    .'.:do;;.    .c   ol;'.
 *       ';;'                   ;.;    ', .dkl';,    .c   :; .'.',::,,'''.
 *      ',,;;;,.                ; .,'     .'''.    .'.   .d;''.''''.
 *     .oxddl;::,,.             ',  .'''.   .... .'.   ,:;..
 *      .'cOX0OOkdoc.            .,'.   .. .....     'lc.
 *     .:;,,::co0XOko'              ....''..'.'''''''.
 *     .dxk0KKdc:cdOXKl............. .. ..,c....
 *      .',lxOOxl:'':xkl,',......'....    ,'.
 *           .';:oo:...                        .
 *                .cd,      ╔═╗┌┬┐┬┌┬┐┌─┐┬─┐    .
 *                  .l;     ║╣  │││ │ │ │├┬┘    '
 *                    'l.   ╚═╝─┴┘┴ ┴ └─┘┴└─   '.
 *                     .o.                   ...
 *                      .''''','.;:''.........
 *                           .'  .l
 *                          .:.   l'
 *                         .:.    .l.
 *                        .x:      :k;,.
 *                        cxlc;    cdc,,;;.
 *                       'l :..   .c  ,
 *                       o.
 *                      .,
 *
 *              ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐  ╔═╗┌┐  ┬┌─┐┌─┐┌┬┐┌─┐
 *              ╠═╣└┬┘├┴┐├┬┘│ ││  ║ ║├┴┐ │├┤ │   │ └─┐
 *              ╩ ╩ ┴ └─┘┴└─┴─┴┘  ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘
 *
 *
 * Created by Valentin on 10/22/14.
 *
 * Copyright (c) 2015 Valentin Heun
 *
 * All ascii characters above must be included in any redistribution.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
/*********************************************************************************************************************
 ******************************************** TODOS *******************************************************************
 **********************************************************************************************************************

 **
 * TODO -
 **

 **********************************************************************************************************************
 ******************************************** onload content **********************************************************
 **********************************************************************************************************************/

/**
 * @desc
 * @param
 * @param
 * @return
 **/

window.onload = function () {
    uiButtons = document.getElementById("GUI");
    overlayDiv = document.getElementById('overlay');
    overlayImg = document.getElementById('overlayImg');

    GUI();

    if (globalStates.platform !== 'iPad' && globalStates.platform !== 'iPhone' && globalStates.platform !== 'iPod touch') {
        globalStates.platform = false;
    }

    if (globalStates.platform === 'iPhone') {
        document.getElementById("logButtonDiv").style.visibility = "hidden";
       // document.getElementById("reloadButtonDiv").style.visibility = "hidden";
     //   document.getElementById("preferencesButtonDiv").style.bottom = "36px";

        var editingInterface = document.getElementById("content2title");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.left = "38%";
        editingInterface.style.right = "22%";

        editingInterface = document.getElementById("content1title");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.left = "2%";
        editingInterface.style.right = "65%";

        editingInterface = document.getElementById("content2");
        editingInterface.style.fontSize = "9px";
        editingInterface.style.left = "38%";
        editingInterface.style.right = "22%";
        editingInterface.style.bottom = "14%";

        editingInterface = document.getElementById("content11");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "40%";

        editingInterface = document.getElementById("content12");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "60%";

        editingInterface = document.getElementById("content13");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "40%";

        editingInterface = document.getElementById("content14");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "60%";

        editingInterface = document.getElementById("content15");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "40%";
        editingInterface.innerHTML = 'External Interface
';

        editingInterface = document.getElementById("content16");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.width = "60%";

        editingInterface = document.getElementById("content18");
        editingInterface.style.visibility = 'hidden';

        editingInterface = document.getElementById("content1");
        editingInterface.style.fontSize = "12px";
        editingInterface.style.left = "2%";
        editingInterface.style.right = "65%";
        editingInterface.style.bottom = "14%";

    } else {
        editingInterface = document.getElementById("content15");
        editingInterface.style.paddingTop = "13px";

        editingInterface = document.getElementById("content20");
        editingInterface.innerHTML = '<input id="newURLText"' +

            "style='text-align: left; font-family: Helvetica Neue, Helvetica, Arial; font-size: large;   -webkit-user-select: text;'" +
            'type="text" name="newURL"  size="27" placeholder="http://..."' + "oninput='newURLTextLoad()'>
";
    }

    globalCanvas.canvas = document.getElementById('canvas');
    globalCanvas.canvas.width = globalStates.height;
    globalCanvas.canvas.height = globalStates.width;

    globalCanvas.context = canvas.getContext('2d');

    if (globalStates.platform) {
        window.location.href = "of://kickoff";
    }

    document.handjs_forcePreventDefault = true;
    globalCanvas.canvas.handjs_forcePreventDefault = true;

    globalCanvas.canvas.addEventListener("pointerdown", canvasPointerDown, false);
    ec++;

    document.addEventListener("pointermove", getPossition, false);
    ec++;
    document.addEventListener("pointerdown", documentPointerDown, false);
    //document.addEventListener("pointerdown", getPossition, false);
    ec++;
    document.addEventListener("pointerup", documentPointerUp, false);
    ec++;
    window.addEventListener("message", postMessage, false);
    ec++;
    overlayDiv.addEventListener('touchstart', function (e) {
        e.preventDefault();
    });

    cout("onload");

};

/**
 * @desc
 * @param
 * @param
 * @return
 **/

var postMessage = function (e) {

    //  cout("received: "+ e.data);
    var msgContent = JSON.parse(e.data);

    var tempThisObject = false;

    var thisVersionNumber = 0;

    if (typeof msgContent.pos !== "undefined" && typeof msgContent.obj !== "undefined") {
        if (typeof objectExp[msgContent.obj] !== "undefined") {
            if (msgContent.pos === msgContent.obj) {
                tempThisObject = objectExp[msgContent.pos];
                thisVersionNumber  = parseInt(objectExp[msgContent.pos].version.replace(/\./g, ""));
            } else {
                if (typeof objectExp[msgContent.obj].objectValues[msgContent.pos] !== "undefined") {
                    tempThisObject = objectExp[msgContent.obj].objectValues[msgContent.pos];
                    thisVersionNumber  = parseInt(objectExp[msgContent.obj].version.replace(/\./g, ""));
                }
            }
        }
    }

    if (tempThisObject !== false) {

            if (typeof msgContent.width !== "undefined" && typeof msgContent.height !== "undefined") {

                document.getElementById(msgContent.pos).style.width = msgContent.width;
                document.getElementById(msgContent.pos).style.height = msgContent.height;
                document.getElementById(msgContent.pos).style.top = ((globalStates.width - msgContent.height) / 2);
                document.getElementById(msgContent.pos).style.left = ((globalStates.height - msgContent.width) / 2);

                document.getElementById("iframe" + msgContent.pos).style.width = msgContent.width;
                document.getElementById("iframe" + msgContent.pos).style.height = msgContent.height;
                document.getElementById("iframe" + msgContent.pos).style.top = ((globalStates.width - msgContent.height) / 2);
                document.getElementById("iframe" + msgContent.pos).style.left = ((globalStates.height - msgContent.width) / 2);

            }
        if (typeof msgContent.sendMatrix !== "undefined") {
                if (msgContent.sendMatrix === true) {
                    if(thisVersionNumber>=32) {
                        tempThisObject.sendMatrix = true;
                        document.getElementById("iframe" + msgContent.pos).contentWindow.postMessage(
                            '{"projectionMatrix":' + JSON.stringify(globalStates.realProjectionMatrix) + "}", '*');
                    }
                }
                // forward postMessages to all iFrames
            }
        if (typeof msgContent.ohGlobalMessage !== "undefined") {
                var iframes = document.getElementsByTagName('iframe');
                for (var i = 0; i < iframes.length; i++) {

                    if (iframes[i].id !== "iframe" + msgContent.pos && iframes[i].style.visibility !== "hidden") {
                        if(thisVersionNumber>=32) {
                            iframes[i].contentWindow.postMessage(
                                JSON.stringify(
                                    {
                                        "ohGlobalMessage": msgContent.ohGlobalMessage
                                    })
                                , "*");
                        }
                    }
                }
            }
        if (typeof msgContent.fullScreen !== "undefined") {
               // console.log("gotfullscreenmessage");
                if (msgContent.fullScreen === true) {
                    tempThisObject.fullScreen = true;

                    document.getElementById("thisObject" + msgContent.pos).style.webkitTransform =
                        'matrix3d(1, 0, 0, 0,' +
                        '0, 1, 0, 0,' +
                        '0, 0, 1, 0,' +
                        '0, 0, 0, 1)';

                }
            if (msgContent.fullScreen === false) {
                   // console.log("noFullscreen");
                    tempThisObject.fullScreen = false;
                }

            }
    }

    /* if (typeof msgContent.sendAcl !== "undefined") {
     if(msgContent.sendAcl === true) {
     objectExp[msgContent.obj].sendAcl = true;
     window.location.href = "of://sendAccelerationData";
     }
     }*/

    // cout("postMessage");

};
<|endoftext|>


<commit_before>$(document).ready(function () {

	function inView() {
		var desktopOffset = 60;
		var views = [];
		var cases = $('[data-isDark="0"]');
		for (var i = 0; i < cases.length; i++)
		{
			var caseBackgrd = cases.eq(i).children(".o-featured__background").eq(0);
			var caseWidth = caseBackgrd.width();
			var caseRightEdgePos = caseBackgrd.offset().left + caseWidth;
			var maxPos = $(window).width() - desktopOffset;
			var minPos = maxPos - caseWidth;
			views.push((caseRightEdgePos >= minPos) && (caseRightEdgePos <= maxPos));
		}
		return views;
	}

	function contInView() {
		var desktopOffset = 60;
		var cont = $('[data-isdark="true"]').eq(0);
		return cont.offset().left < ($(window).width() - desktopOffset);
	}

	$(window).on('wheel', function (event) {
		var views = inView();
		if (views.indexOf(true) > -1 || contInView()) {
			$(".c-ui__nav-items.js-invert").addClass("invert");
			$(".c-ui__burger.js-invert").addClass("invert");
		}
		else {
			$(".c-ui__nav-items.js-invert").removeClass("invert");
			$(".c-ui__burger.js-invert").removeClass("invert");
		}
	});

	function inViewM() {
		var curW = window.innerWidth || document.documentElement.clientWidth;
		var mOffset = 0.1 * curW;
		var maxRt = window.innerWidth;
		var minRt = window.innerWidth - mOffset - mOffset;
		var maxLft = document.documentElement.clientWidth - mOffset;
		var views = [];
		var cases = $('[data-isDark="1"]');
		for (var i = 0; i < cases.length; i++) {
			var caseBackgrd = cases.eq(i).children(".o-featured__background")[0];
			var rect = caseBackgrd.getBoundingClientRect();
			var leftInVp = (rect.left >= 0 && rect.left <= maxLft);
			var rightInVp = (rect.right > minRt && rect.right <= maxRt);
			views.push(leftInVp || rightInVp);
		}

		var cont = $('[data-isdark="true"]')[0];
		var cRect = cont.getBoundingClientRect();
		var cLeftInVp = (cRect.left >= 0 && cRect.left <= maxLft );
		var cRightInVp = (cRect.right > minRt && cRect.right <= maxRt);
		views.push(cLeftInVp || cRightInVp);

		return views;
	}

	$(".o-featured").on('touchmove', function (event) {
		var views = inViewM();
		if (views.indexOf(true) > -1) {
			$(".c-ui__burger.js-invert").addClass("invert");
			$(".c-ui__nav-items.js-invert").addClass("invert");
		}
		else {
			$(".c-ui__burger.js-invert").removeClass("invert");
			$(".c-ui__nav-items.js-invert").removeClass("invert");
		}
	});
});<commit_msg>added mouse events for IE<commit_after>$(document).ready(function () {

	function inView() {
		var desktopOffset = 60;
		var views = [];
		var cases = $('[data-isDark="0"]');
		for (var i = 0; i < cases.length; i++)
		{
			var caseBackgrd = cases.eq(i).children(".o-featured__background").eq(0);
			var caseWidth = caseBackgrd.width();
			var caseRightEdgePos = caseBackgrd.offset().left + caseWidth;
			var maxPos = $(window).width() - desktopOffset;
			var minPos = maxPos - caseWidth;
			views.push((caseRightEdgePos >= minPos) && (caseRightEdgePos <= maxPos));
		}
		return views;
	}

	function contInView() {
		var desktopOffset = 60;
		var cont = $('[data-isdark="true"]').eq(0);
		return cont.offset().left < ($(window).width() - desktopOffset);
	}

	$(window).on('wheel', function (event) {
		var views = inView();
		if (views.indexOf(true) > -1 || contInView()) {
			$(".c-ui__nav-items.js-invert").addClass("invert");
			$(".c-ui__burger.js-invert").addClass("invert");
		}
		else {
			$(".c-ui__nav-items.js-invert").removeClass("invert");
			$(".c-ui__burger.js-invert").removeClass("invert");
		}
	});

	$(".scrollbar-thumb").on('mouseup mouseleave', function (event) {
		var views = inView();
		if (views.indexOf(true) > -1 || contInView()) {
			$(".c-ui__nav-items.js-invert").addClass("invert");
			$(".c-ui__burger.js-invert").addClass("invert");
		}
		else {
			$(".c-ui__nav-items.js-invert").removeClass("invert");
			$(".c-ui__burger.js-invert").removeClass("invert");
		}
	});

	function inViewM() {
		var curW = window.innerWidth || document.documentElement.clientWidth;
		var mOffset = 0.1 * curW;
		var maxRt = window.innerWidth;
		var minRt = window.innerWidth - mOffset - mOffset;
		var maxLft = document.documentElement.clientWidth - mOffset;
		var views = [];
		var cases = $('[data-isDark="1"]');
		for (var i = 0; i < cases.length; i++) {
			var caseBackgrd = cases.eq(i).children(".o-featured__background")[0];
			var rect = caseBackgrd.getBoundingClientRect();
			var leftInVp = (rect.left >= 0 && rect.left <= maxLft);
			var rightInVp = (rect.right > minRt && rect.right <= maxRt);
			views.push(leftInVp || rightInVp);
		}

		var cont = $('[data-isdark="true"]')[0];
		var cRect = cont.getBoundingClientRect();
		var cLeftInVp = (cRect.left >= 0 && cRect.left <= maxLft );
		var cRightInVp = (cRect.right > minRt && cRect.right <= maxRt);
		views.push(cLeftInVp || cRightInVp);

		return views;
	}

	$(".o-featured").on('touchmove', function (event) {
		var views = inViewM();
		if (views.indexOf(true) > -1) {
			$(".c-ui__burger.js-invert").addClass("invert");
			$(".c-ui__nav-items.js-invert").addClass("invert");
		}
		else {
			$(".c-ui__burger.js-invert").removeClass("invert");
			$(".c-ui__nav-items.js-invert").removeClass("invert");
		}
	});
});<|endoftext|>


<commit_before>var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

document.body.appendChild(canvas);

//create game objects
var hero = {
	speed: 256
}

var oracle = {}
var oracle2 = {}

var portal2 = {}
var portal = {}

//background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
	bgReady = true;
};

bgImage.src = "images/background.png";

//background2 image
var bg2Ready = false;
var bg2Image = new Image();
bg2Image.onload = function () {
	bg2Ready = true;
};

bg2Image.src = "images/background2.png";

//portal image
var portalReady = false;
var portalImage = new Image();
portalImage.onload = new function () {
	portalReady = true;
	portal.height = portalImage.height;
	portal.width = portalImage.width;
};

portalImage.src = "images/portal.png";

//hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
	heroReady = true;
	hero.height = this.height;
	hero.width = this.width;
};

heroImage.src = "images/hero.png";

//oracle image
var oracleReady = false;
var oracleImage = new Image();
oracleImage.onload = function () {
	oracleReady = true;
	oracle.height = this.height;
	oracle.width = this.width;
};

oracleImage.src = "images/oracle.png";

//oracle2 image
var oracle2Ready = false;
var oracle2Image = new Image();
oracle2Image.onload = function () {
	oracle2Ready = true;
	oracle2.height = this.height;
	oracle2.width = this.width;
};

oracle2Image.src = "images/oracle2.png";

//text bubble image
var textBubbleReady = false;
var textBubble = new Image();
textBubble.onload = function () {
	textBubbleReady = true;
};

textBubble.src = "images/textbubble.png";

//handle keyboard controls
addEventListener("keydown", function(e) { update(e.keyCode, true); });

function update (code, page) {
	if (code == 37 && hero.left >= 10) { //holding left arrow
		console.log(hero.left);
		hero.left -= 31;
		hero.right = hero.left + heroImage.width;
	}
	if (code == 38 && hero.top >= 10) { //holding up arrow
		hero.top -= 23;
		hero.bottom = hero.top + heroImage.height;
	}
	if (code == 39 && hero.right <= (canvas.width - 10)) { //holding right arrow
		hero.left += 31;
		hero.right = hero.left + heroImage.width;
	}
	if (code == 40 && hero.bottom <= (canvas.height - 10)) { //holding down arrow
		hero.top += 23;
		hero.bottom = hero.top + heroImage.height;
	}

	//can we talk to the oracle??
	if (hero.left <= oracle.right
			&& hero.right >= oracle.left
			&& hero.top <= oracle.bottom
			&& hero.bottom >= oracle.top && page) {
		bubble = true;
	}
	else {
		bubble = false;
	}

	//can we travel through space and time?!
	if (hero.left <= portal.right
			&& hero.right >= portal.left
			&& hero.top <= portal.bottom
			&& hero.bottom >= portal.top && page) {
		console.log("hit p1");
		hitPortal = true;
	}
	//can we travel through space and time?!
	else if (hero.left <= portal2.right
			&& hero.right >= portal2.left
			&& hero.top <= portal2.bottom
			&& hero.bottom >= portal2.top && !page) {
		hitPortal = true;
	}
	else {
		hitPortal = false;
	}
}

var talk = function () {
	if (textBubbleReady) {
		ctx.drawImage(textBubble, oracle.right, oracle.top - textBubble.height + 20);
	}
};

var travelThroughTimeAndSpace = function () {
	if (hitPortal) {
		hitPortal = false;
		addEventListener("keydown", function(e) { update(e.keyCode, false); });
	}
	else {
		if (bg2Ready) {
			ctx.drawImage(bg2Image, 0, 0);
		}

		if (oracle2Ready) {
			ctx.drawImage(oracle2Image, 42, 42);
		}

		if (heroReady) {
			ctx.drawImage(heroImage, hero.left, hero.top);
		}

		if (portalReady) {
			ctx.drawImage(portalImage, portal2.left, portal2.top);
		}
	}
};

var render = function () {
	console.log(hitPortal);
	if (hitPortal) {
		console.log("travelingthroughsppppaaace");
		hitPortal = false;
		addEventListener("keydown", function(e) { update(e.keyCode, true); });
	}
	else{
		if (bgReady) {
			ctx.drawImage(bgImage, 0, 0);
		}

		if (heroReady) {
			ctx.drawImage(heroImage, hero.left, hero.top);
		}

		if (oracleReady) {
			ctx.drawImage(oracleImage, oracle.left, oracle.top);
		}

		if (portalReady) {
			ctx.drawImage(portalImage, portal.left, portal.top);
		}

		if (bubble) {
			talk();
		}
}
};

var init = function () {
	hero.left = 10;
	hero.right = hero.left + 31;
	hero.top = 10;
	hero.bottom = hero.top + 53;

	oracle.left = 382;
	oracle.right = oracle.left + 31;
	oracle.top = 441;
	oracle.bottom = oracle.top + 53;

	portal.left = 606;
	portal.right = portal.left + 101;
	portal.top = 599;
	portal.bottom = portal.top + 171;

	portal2.left = 55;
	portal2.top = 62;
	portal2.right = portal2.left + 101;
	portal2.bottom = portal2.top + 171;
};

var then = Date.now();
var bubble = false;
var hitPortal = false;
var page1 = true;
var page2 = false;
init();
<commit_msg>let\'s rennnder......<commit_after>var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

document.body.appendChild(canvas);

//create game objects
var hero = {
	speed: 256
}

var oracle = {}
var oracle2 = {}

var portal2 = {}
var portal = {}

//background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
	bgReady = true;
};

bgImage.src = "images/background.png";

//background2 image
var bg2Ready = false;
var bg2Image = new Image();
bg2Image.onload = function () {
	bg2Ready = true;
};

bg2Image.src = "images/background2.png";

//portal image
var portalReady = false;
var portalImage = new Image();
portalImage.onload = new function () {
	portalReady = true;
	portal.height = portalImage.height;
	portal.width = portalImage.width;
};

portalImage.src = "images/portal.png";

//hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
	heroReady = true;
	hero.height = this.height;
	hero.width = this.width;
};

heroImage.src = "images/hero.png";

//oracle image
var oracleReady = false;
var oracleImage = new Image();
oracleImage.onload = function () {
	oracleReady = true;
	oracle.height = this.height;
	oracle.width = this.width;
};

oracleImage.src = "images/oracle.png";

//oracle2 image
var oracle2Ready = false;
var oracle2Image = new Image();
oracle2Image.onload = function () {
	oracle2Ready = true;
	oracle2.height = this.height;
	oracle2.width = this.width;
};

oracle2Image.src = "images/oracle2.png";

//text bubble image
var textBubbleReady = false;
var textBubble = new Image();
textBubble.onload = function () {
	textBubbleReady = true;
};

textBubble.src = "images/textbubble.png";

//handle keyboard controls
addEventListener("keydown", function(e) { update(e.keyCode, true); });

function update (code, page) {
	if (code == 37 && hero.left >= 10) { //holding left arrow
		console.log(hero.left);
		hero.left -= 31;
		hero.right = hero.left + heroImage.width;
		render();
	}
	if (code == 38 && hero.top >= 10) { //holding up arrow
		hero.top -= 23;
		hero.bottom = hero.top + heroImage.height;
		render();
	}
	if (code == 39 && hero.right <= (canvas.width - 10)) { //holding right arrow
		hero.left += 31;
		hero.right = hero.left + heroImage.width;
		render();
	}
	if (code == 40 && hero.bottom <= (canvas.height - 10)) { //holding down arrow
		hero.top += 23;
		hero.bottom = hero.top + heroImage.height;
		render();
	}

	//can we talk to the oracle??
	if (hero.left <= oracle.right
			&& hero.right >= oracle.left
			&& hero.top <= oracle.bottom
			&& hero.bottom >= oracle.top && page) {
		bubble = true;
	}
	else {
		bubble = false;
	}

	//can we travel through space and time?!
	if (hero.left <= portal.right
			&& hero.right >= portal.left
			&& hero.top <= portal.bottom
			&& hero.bottom >= portal.top && page) {
		console.log("hit p1");
		hitPortal = true;
	}
	//can we travel through space and time?!
	else if (hero.left <= portal2.right
			&& hero.right >= portal2.left
			&& hero.top <= portal2.bottom
			&& hero.bottom >= portal2.top && !page) {
		hitPortal = true;
	}
	else {
		hitPortal = false;
	}
}

var talk = function () {
	if (textBubbleReady) {
		ctx.drawImage(textBubble, oracle.right, oracle.top - textBubble.height + 20);
	}
};

var travelThroughTimeAndSpace = function () {
	if (hitPortal) {
		hitPortal = false;
		addEventListener("keydown", function(e) { update(e.keyCode, false); });
		render();
	}
	else {
		if (bg2Ready) {
			ctx.drawImage(bg2Image, 0, 0);
		}

		if (oracle2Ready) {
			ctx.drawImage(oracle2Image, 42, 42);
		}

		if (heroReady) {
			ctx.drawImage(heroImage, hero.left, hero.top);
		}

		if (portalReady) {
			ctx.drawImage(portalImage, portal2.left, portal2.top);
		}
	}
};

var render = function () {
	if (hitPortal) {
		console.log("travelingthroughsppppaaace");
		hitPortal = false;
		addEventListener("keydown", function(e) { update(e.keyCode, true); });
		travelThroughTimeAndSpace();
	}
	else{
		if (bgReady) {
			ctx.drawImage(bgImage, 0, 0);
		}

		if (heroReady) {
			ctx.drawImage(heroImage, hero.left, hero.top);
		}

		if (oracleReady) {
			ctx.drawImage(oracleImage, oracle.left, oracle.top);
		}

		if (portalReady) {
			ctx.drawImage(portalImage, portal.left, portal.top);
		}

		if (bubble) {
			talk();
		}
}
};

var init = function () {
	hero.left = 10;
	hero.right = hero.left + 31;
	hero.top = 10;
	hero.bottom = hero.top + 53;

	oracle.left = 382;
	oracle.right = oracle.left + 31;
	oracle.top = 441;
	oracle.bottom = oracle.top + 53;

	portal.left = 606;
	portal.right = portal.left + 101;
	portal.top = 599;
	portal.bottom = portal.top + 171;

	portal2.left = 55;
	portal2.top = 62;
	portal2.right = portal2.left + 101;
	portal2.bottom = portal2.top + 171;
};

var then = Date.now();
var bubble = false;
var hitPortal = false;
var page1 = true;
var page2 = false;
init();
render();
<|endoftext|>