<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { fromJS } from 'immutable';
import { throttle } from 'lodash';
import classNames from 'classnames';
import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen';
import { displaySensitiveMedia } from '../../initial_state';

const messages = defineMessages({
  play: { id: 'video.play', defaultMessage: 'Play' },
  pause: { id: 'video.pause', defaultMessage: 'Pause' },
  mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
  unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
  hide: { id: 'video.hide', defaultMessage: 'Hide video' },
  expand: { id: 'video.expand', defaultMessage: 'Expand video' },
  close: { id: 'video.close', defaultMessage: 'Close video' },
  fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
  exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
});

const formatTime = secondsNum => {
  let hours   = Math.floor(secondsNum / 3600);
  let minutes = Math.floor((secondsNum - (hours * 3600)) / 60);
  let seconds = secondsNum - (hours * 3600) - (minutes * 60);

  if (hours   < 10) hours   = '0' + hours;
  if (minutes < 10) minutes = '0' + minutes;
  if (seconds < 10) seconds = '0' + seconds;

  return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
};

export const findElementPosition = el => {
  let box;

  if (el.getBoundingClientRect && el.parentNode) {
    box = el.getBoundingClientRect();
  }

  if (!box) {
    return {
      left: 0,
      top: 0,
    };
  }

  const docEl = document.documentElement;
  const body  = document.body;

  const clientLeft = docEl.clientLeft || body.clientLeft || 0;
  const scrollLeft = window.pageXOffset || body.scrollLeft;
  const left       = (box.left + scrollLeft) - clientLeft;

  const clientTop = docEl.clientTop || body.clientTop || 0;
  const scrollTop = window.pageYOffset || body.scrollTop;
  const top       = (box.top + scrollTop) - clientTop;

  return {
    left: Math.round(left),
    top: Math.round(top),
  };
};

export const getPointerPosition = (el, event) => {
  const position = {};
  const box = findElementPosition(el);
  const boxW = el.offsetWidth;
  const boxH = el.offsetHeight;
  const boxY = box.top;
  const boxX = box.left;

  let pageY = event.pageY;
  let pageX = event.pageX;

  if (event.changedTouches) {
    pageX = event.changedTouches[0].pageX;
    pageY = event.changedTouches[0].pageY;
  }

  position.y = Math.max(0, Math.min(1, (pageY - boxY) / boxH));
  position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));

  return position;
};

@injectIntl
export default class Video extends React.PureComponent {

  static propTypes = {
    preview: PropTypes.string,
    src: PropTypes.string.isRequired,
    alt: PropTypes.string,
    width: PropTypes.number,
    height: PropTypes.number,
    sensitive: PropTypes.bool,
    startTime: PropTypes.number,
    onOpenVideo: PropTypes.func,
    onCloseVideo: PropTypes.func,
    detailed: PropTypes.bool,
    inline: PropTypes.bool,
    intl: PropTypes.object.isRequired,
  };

  state = {
    currentTime: 0,
    duration: 0,
    paused: true,
    dragging: false,
    containerWidth: false,
    fullscreen: false,
    hovered: false,
    muted: false,
    revealed: !this.props.sensitive || displaySensitiveMedia,
  };

  setPlayerRef = c => {
    this.player = c;

    if (c) {
      this.setState({
        containerWidth: c.offsetWidth,
      });
    }
  }

  setVideoRef = c => {
    this.video = c;
  }

  setSeekRef = c => {
    this.seek = c;
  }

  handleClickRoot = e => e.stopPropagation();

  handlePlay = () => {
    this.setState({ paused: false });
  }

  handlePause = () => {
    this.setState({ paused: true });
  }

  handleTimeUpdate = () => {
    this.setState({
      currentTime: Math.floor(this.video.currentTime),
      duration: Math.floor(this.video.duration),
    });
  }

  handleMouseDown = e => {
    document.addEventListener('mousemove', this.handleMouseMove, true);
    document.addEventListener('mouseup', this.handleMouseUp, true);
    document.addEventListener('touchmove', this.handleMouseMove, true);
    document.addEventListener('touchend', this.handleMouseUp, true);

    this.setState({ dragging: true });
    this.video.pause();
    this.handleMouseMove(e);
  }

  handleMouseUp = () => {
    document.removeEventListener('mousemove', this.handleMouseMove, true);
    document.removeEventListener('mouseup', this.handleMouseUp, true);
    document.removeEventListener('touchmove', this.handleMouseMove, true);
    document.removeEventListener('touchend', this.handleMouseUp, true);

    this.setState({ dragging: false });
    this.video.play();
  }

  handleMouseMove = throttle(e => {
    const { x } = getPointerPosition(this.seek, e);
    const currentTime = Math.floor(this.video.duration * x);

    this.video.currentTime = currentTime;
    this.setState({ currentTime });
  }, 60);

  togglePlay = () => {
    if (this.state.paused) {
      this.video.play();
    } else {
      this.video.pause();
    }
  }

  toggleFullscreen = () => {
    if (isFullscreen()) {
      exitFullscreen();
    } else {
      requestFullscreen(this.player);
    }
  }

  componentDidMount () {
    document.addEventListener('fullscreenchange', this.handleFullscreenChange, true);
    document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
    document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
    document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
  }

  componentWillUnmount () {
    document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true);
    document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
    document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
    document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
  }

  handleFullscreenChange = () => {
    this.setState({ fullscreen: isFullscreen() });
  }

  handleMouseEnter = () => {
    this.setState({ hovered: true });
  }

  handleMouseLeave = () => {
    this.setState({ hovered: false });
  }

  toggleMute = () => {
    this.video.muted = !this.video.muted;
    this.setState({ muted: this.video.muted });
  }

  toggleReveal = () => {
    if (this.state.revealed) {
      this.video.pause();
    }

    this.setState({ revealed: !this.state.revealed });
  }

  handleLoadedData = () => {
    if (this.props.startTime) {
      this.video.currentTime = this.props.startTime;
      this.video.play();
    }
  }

  handleProgress = () => {
    if (this.video.buffered.length > 0) {
      this.setState({ buffer: this.video.buffered.end(0) / this.video.duration * 100 });
    }
  }

  handleOpenVideo = () => {
    const { src, preview, width, height } = this.props;
    const media = fromJS({
      type: 'video',
      url: src,
      preview_url: preview,
      width,
      height,
    });

    this.video.pause();
    this.props.onOpenVideo(media, this.video.currentTime);
  }

  handleCloseVideo = () => {
    this.video.pause();
    this.props.onCloseVideo();
  }

  render () {
    const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props;
    const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
    const progress = (currentTime / duration) * 100;
    const playerStyle = {};

    let { width, height } = this.props;

    if (inline && containerWidth) {
      width  = containerWidth;
      height = containerWidth / (16/9);

      playerStyle.width  = width;
      playerStyle.height = height;
    }

    return (

        <video
          ref={this.setVideoRef}
          src={src}
          poster={preview}
          preload={startTime ? 'auto' : 'none'}
          loop
          role='button'
          tabIndex='0'
          aria-label={alt}
          width={width}
          height={height}
          onClick={this.togglePlay}
          onPlay={this.handlePlay}
          onPause={this.handlePause}
          onTimeUpdate={this.handleTimeUpdate}
          onLoadedData={this.handleLoadedData}
          onProgress={this.handleProgress}
        />

        <button type='button' className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}>
          <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />
          <FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' />
        </button>

            <div className='video-player__seek__buffer' style={{ width: `${buffer}%` }} />
            <div className='video-player__seek__progress' style={{ width: `${progress}%` }} />

            <span
              className={classNames('video-player__seek__handle', { active: dragging })}
              tabIndex='0'
              style={{ left: `${progress}%` }}
            />

              <button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}></button>
              <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}></button>

              {!onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}></button>}

              {(detailed || fullscreen) &&

                  {formatTime(currentTime)}
                  /
                  {formatTime(duration)}

              }

              {(!fullscreen && onOpenVideo) && <button type='button' aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}></button>}
              {onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}></button>}
              <button type='button' aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}></button>

    );
  }

}
<commit_msg>Various fixes regarding the video position slider (#8201)<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { fromJS } from 'immutable';
import { throttle } from 'lodash';
import classNames from 'classnames';
import { isFullscreen, requestFullscreen, exitFullscreen } from '../ui/util/fullscreen';
import { displaySensitiveMedia } from '../../initial_state';

const messages = defineMessages({
  play: { id: 'video.play', defaultMessage: 'Play' },
  pause: { id: 'video.pause', defaultMessage: 'Pause' },
  mute: { id: 'video.mute', defaultMessage: 'Mute sound' },
  unmute: { id: 'video.unmute', defaultMessage: 'Unmute sound' },
  hide: { id: 'video.hide', defaultMessage: 'Hide video' },
  expand: { id: 'video.expand', defaultMessage: 'Expand video' },
  close: { id: 'video.close', defaultMessage: 'Close video' },
  fullscreen: { id: 'video.fullscreen', defaultMessage: 'Full screen' },
  exit_fullscreen: { id: 'video.exit_fullscreen', defaultMessage: 'Exit full screen' },
});

const formatTime = secondsNum => {
  let hours   = Math.floor(secondsNum / 3600);
  let minutes = Math.floor((secondsNum - (hours * 3600)) / 60);
  let seconds = secondsNum - (hours * 3600) - (minutes * 60);

  if (hours   < 10) hours   = '0' + hours;
  if (minutes < 10) minutes = '0' + minutes;
  if (seconds < 10) seconds = '0' + seconds;

  return (hours === '00' ? '' : `${hours}:`) + `${minutes}:${seconds}`;
};

export const findElementPosition = el => {
  let box;

  if (el.getBoundingClientRect && el.parentNode) {
    box = el.getBoundingClientRect();
  }

  if (!box) {
    return {
      left: 0,
      top: 0,
    };
  }

  const docEl = document.documentElement;
  const body  = document.body;

  const clientLeft = docEl.clientLeft || body.clientLeft || 0;
  const scrollLeft = window.pageXOffset || body.scrollLeft;
  const left       = (box.left + scrollLeft) - clientLeft;

  const clientTop = docEl.clientTop || body.clientTop || 0;
  const scrollTop = window.pageYOffset || body.scrollTop;
  const top       = (box.top + scrollTop) - clientTop;

  return {
    left: Math.round(left),
    top: Math.round(top),
  };
};

export const getPointerPosition = (el, event) => {
  const position = {};
  const box = findElementPosition(el);
  const boxW = el.offsetWidth;
  const boxH = el.offsetHeight;
  const boxY = box.top;
  const boxX = box.left;

  let pageY = event.pageY;
  let pageX = event.pageX;

  if (event.changedTouches) {
    pageX = event.changedTouches[0].pageX;
    pageY = event.changedTouches[0].pageY;
  }

  position.y = Math.max(0, Math.min(1, (pageY - boxY) / boxH));
  position.x = Math.max(0, Math.min(1, (pageX - boxX) / boxW));

  return position;
};

@injectIntl
export default class Video extends React.PureComponent {

  static propTypes = {
    preview: PropTypes.string,
    src: PropTypes.string.isRequired,
    alt: PropTypes.string,
    width: PropTypes.number,
    height: PropTypes.number,
    sensitive: PropTypes.bool,
    startTime: PropTypes.number,
    onOpenVideo: PropTypes.func,
    onCloseVideo: PropTypes.func,
    detailed: PropTypes.bool,
    inline: PropTypes.bool,
    intl: PropTypes.object.isRequired,
  };

  state = {
    currentTime: 0,
    duration: 0,
    paused: true,
    dragging: false,
    containerWidth: false,
    fullscreen: false,
    hovered: false,
    muted: false,
    revealed: !this.props.sensitive || displaySensitiveMedia,
  };

  setPlayerRef = c => {
    this.player = c;

    if (c) {
      this.setState({
        containerWidth: c.offsetWidth,
      });
    }
  }

  setVideoRef = c => {
    this.video = c;
  }

  setSeekRef = c => {
    this.seek = c;
  }

  handleClickRoot = e => e.stopPropagation();

  handlePlay = () => {
    this.setState({ paused: false });
  }

  handlePause = () => {
    this.setState({ paused: true });
  }

  handleTimeUpdate = () => {
    this.setState({
      currentTime: Math.floor(this.video.currentTime),
      duration: Math.floor(this.video.duration),
    });
  }

  handleMouseDown = e => {
    document.addEventListener('mousemove', this.handleMouseMove, true);
    document.addEventListener('mouseup', this.handleMouseUp, true);
    document.addEventListener('touchmove', this.handleMouseMove, true);
    document.addEventListener('touchend', this.handleMouseUp, true);

    this.setState({ dragging: true });
    this.video.pause();
    this.handleMouseMove(e);

    e.preventDefault();
    e.stopPropagation();
  }

  handleMouseUp = () => {
    document.removeEventListener('mousemove', this.handleMouseMove, true);
    document.removeEventListener('mouseup', this.handleMouseUp, true);
    document.removeEventListener('touchmove', this.handleMouseMove, true);
    document.removeEventListener('touchend', this.handleMouseUp, true);

    this.setState({ dragging: false });
    this.video.play();
  }

  handleMouseMove = throttle(e => {
    const { x } = getPointerPosition(this.seek, e);
    const currentTime = Math.floor(this.video.duration * x);

    if (!isNaN(currentTime)) {
      this.video.currentTime = currentTime;
      this.setState({ currentTime });
    }
  }, 60);

  togglePlay = () => {
    if (this.state.paused) {
      this.video.play();
    } else {
      this.video.pause();
    }
  }

  toggleFullscreen = () => {
    if (isFullscreen()) {
      exitFullscreen();
    } else {
      requestFullscreen(this.player);
    }
  }

  componentDidMount () {
    document.addEventListener('fullscreenchange', this.handleFullscreenChange, true);
    document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
    document.addEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
    document.addEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
  }

  componentWillUnmount () {
    document.removeEventListener('fullscreenchange', this.handleFullscreenChange, true);
    document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange, true);
    document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange, true);
    document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange, true);
  }

  handleFullscreenChange = () => {
    this.setState({ fullscreen: isFullscreen() });
  }

  handleMouseEnter = () => {
    this.setState({ hovered: true });
  }

  handleMouseLeave = () => {
    this.setState({ hovered: false });
  }

  toggleMute = () => {
    this.video.muted = !this.video.muted;
    this.setState({ muted: this.video.muted });
  }

  toggleReveal = () => {
    if (this.state.revealed) {
      this.video.pause();
    }

    this.setState({ revealed: !this.state.revealed });
  }

  handleLoadedData = () => {
    if (this.props.startTime) {
      this.video.currentTime = this.props.startTime;
      this.video.play();
    }
  }

  handleProgress = () => {
    if (this.video.buffered.length > 0) {
      this.setState({ buffer: this.video.buffered.end(0) / this.video.duration * 100 });
    }
  }

  handleOpenVideo = () => {
    const { src, preview, width, height } = this.props;
    const media = fromJS({
      type: 'video',
      url: src,
      preview_url: preview,
      width,
      height,
    });

    this.video.pause();
    this.props.onOpenVideo(media, this.video.currentTime);
  }

  handleCloseVideo = () => {
    this.video.pause();
    this.props.onCloseVideo();
  }

  render () {
    const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, detailed } = this.props;
    const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state;
    const progress = (currentTime / duration) * 100;
    const playerStyle = {};

    let { width, height } = this.props;

    if (inline && containerWidth) {
      width  = containerWidth;
      height = containerWidth / (16/9);

      playerStyle.width  = width;
      playerStyle.height = height;
    }

    let preload;
    if (startTime || fullscreen || dragging) {
      preload = 'auto';
    } else if (detailed) {
      preload = 'metadata';
    } else {
      preload = 'none';
    }

    return (

        <video
          ref={this.setVideoRef}
          src={src}
          poster={preview}
          preload={preload}
          loop
          role='button'
          tabIndex='0'
          aria-label={alt}
          width={width}
          height={height}
          onClick={this.togglePlay}
          onPlay={this.handlePlay}
          onPause={this.handlePause}
          onTimeUpdate={this.handleTimeUpdate}
          onLoadedData={this.handleLoadedData}
          onProgress={this.handleProgress}
        />

        <button type='button' className={classNames('video-player__spoiler', { active: !revealed })} onClick={this.toggleReveal}>
          <FormattedMessage id='status.sensitive_warning' defaultMessage='Sensitive content' />
          <FormattedMessage id='status.sensitive_toggle' defaultMessage='Click to view' />
        </button>

            <div className='video-player__seek__buffer' style={{ width: `${buffer}%` }} />
            <div className='video-player__seek__progress' style={{ width: `${progress}%` }} />

            <span
              className={classNames('video-player__seek__handle', { active: dragging })}
              tabIndex='0'
              style={{ left: `${progress}%` }}
            />

              <button type='button' aria-label={intl.formatMessage(paused ? messages.play : messages.pause)} onClick={this.togglePlay}></button>
              <button type='button' aria-label={intl.formatMessage(muted ? messages.unmute : messages.mute)} onClick={this.toggleMute}></button>

              {!onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.hide)} onClick={this.toggleReveal}></button>}

              {(detailed || fullscreen) &&

                  {formatTime(currentTime)}
                  /
                  {formatTime(duration)}

              }

              {(!fullscreen && onOpenVideo) && <button type='button' aria-label={intl.formatMessage(messages.expand)} onClick={this.handleOpenVideo}></button>}
              {onCloseVideo && <button type='button' aria-label={intl.formatMessage(messages.close)} onClick={this.handleCloseVideo}></button>}
              <button type='button' aria-label={intl.formatMessage(fullscreen ? messages.exit_fullscreen : messages.fullscreen)} onClick={this.toggleFullscreen}></button>

    );
  }

}
<|endoftext|>


<commit_before>'use strict';

nyplViewer.controller('SettingsDialogCtrl',
  function ($mdDialog, lodash, DatabaseConnection, $q, NyplApiCalls) {
    var ctrl = this;
    ctrl.readonly = false;
    ctrl.selectedItem = null;
    ctrl.searchText = null;
    ctrl.selectedInterests = [];
    ctrl.autocompleteDemoRequireMatch = true;
    ctrl.topics = [];
    ctrl.isResultsForNewTopic = false;
    ctrl.isSearchRun = false;
    ctrl.newTopicName = '';
    ctrl.newTopicResultCount = 0;

    ctrl.getTopics = function () {
      var deferred = $q.defer();
      if (ctrl.topics.length == 0) {
        DatabaseConnection.getTopics().then(function (result) {
          ctrl.topics = result;
          deferred.resolve();
        })
      } else {
        deferred.resolve();
      }
      return deferred.promise;
    }

    ctrl.querySearch = function (query) {
      return ctrl.getTopics().then(function () {
        var results = query ? ctrl.topics.filter(ctrl.createFilterFor(query)) : [];
        return results;
      })

    }
    ctrl.createFilterFor = function (query) {
      var lowercaseQuery = angular.lowercase(query);

      return function filterFn(topic) {
        return (topic.topicName.indexOf(lowercaseQuery) === 0) || (topic.topicName.indexOf(lowercaseQuery) === 0);
      };

    }

    ctrl.addTopic = function () {
      ctrl.selectedInterests.push(ctrl.newTopicName);
      ctrl.isResultsForNewTopic = false;
      ctrl.isSearchRun = false;
      if ((lodash.find(ctrl.topics, ctrl.newTopicName)) == undefined) { // topic not in the firebase master list, add it
        DatabaseConnection.addTopic(ctrl.newTopicName);
      }
      ctrl.newTopicName = '';
    }

    ctrl.newTopicSearchChange = function () {
      ctrl.isSearchRun = false;
      ctrl.isResultsForNewTopic = false;
      if (ctrl.newTopicName != '') {
        ctrl.isSearchRun = false;
        NyplApiCalls.nyplSearch(ctrl.newTopicName, 1).then(function (results) {
          var numResults = results.data.nyplAPI.response.numResults;
          if (numResults > 0) {
            ctrl.newTopicResultCount = numResults;
            ctrl.isResultsForNewTopic = true;
          }
          ctrl.isSearchRun = true;
        })
      }

    }

    //ctrl.interests = [];
    //ctrl.interests = ['Steam engine', 'New York', 'Samurai', 'Dresses', 'Israel Putnam'];
    ctrl.initSelectedInterests = function () {
      DatabaseConnection.getSettings().then(function (settings) {
        ctrl.settings = settings;
        if (ctrl.settings == null) {
          ctrl.selectedInterests = [];
        } else {
          ctrl.selectedInterests = ctrl.settings.interests;
        }

      })
    }

    ctrl.hide = function () {
      $mdDialog.hide();
    };

    ctrl.cancel = function () {
      $mdDialog.hide();
    };

    ctrl.save = function () {
      DatabaseConnection.saveSettings({
        interests: ctrl.selectedInterests,
      }
      );
      $mdDialog.hide();
    };

    ctrl.initSelectedInterests();

  });<commit_msg>fixed some duplication errors<commit_after>'use strict';

nyplViewer.controller('SettingsDialogCtrl',
  function ($mdDialog, lodash, DatabaseConnection, $q, NyplApiCalls, $mdToast) {
    var ctrl = this;
    ctrl.readonly = false;
    ctrl.selectedItem = null;
    ctrl.searchText = null;
    ctrl.selectedInterests = [];
    ctrl.autocompleteDemoRequireMatch = true;
    ctrl.topics = [];
    ctrl.isResultsForNewTopic = false;
    ctrl.isSearchRun = false;
    ctrl.newTopicName = '';
    ctrl.newTopicResultCount = 0;

    ctrl.getTopics = function () {
      var deferred = $q.defer();

      if (ctrl.topics.length == 0) {
        DatabaseConnection.getTopics().then(function (result) {
          //ctrl.topics = result;
          angular.forEach(result, function (topic) {
            ctrl.topics.push(topic);
          })
          deferred.resolve();
        })
      } else {
        deferred.resolve();
      }
      return deferred.promise;
    }

    ctrl.querySearch = function (query) {
        var results = query ? ctrl.topics.filter(ctrl.createFilterFor(query)) : [];
        return results;
    }

    ctrl.createFilterFor = function (query) {
      var lowercaseQuery = angular.lowercase(query);

      return function filterFn(topic) {
        return (topic.topicName.indexOf(lowercaseQuery) === 0) || (topic.topicName.indexOf(lowercaseQuery) === 0);
      };

    }

    ctrl.showToast = function (text) {
        $mdToast.show(
            $mdToast.simple()
                .textContent(text)
                .position('top right')
                .hideDelay(1500)
        );
    };

    ctrl.isDuplicateObject = function (collectionToCheck, key, value) {
      return ( lodash.find(collectionToCheck, function(obj) { return obj.topicName == value; }) );
    }

    ctrl.isDuplicateArrayElement = function (array, value) {
      return (lodash.find(array, function(ele) { return ele == value; }) != undefined);
    }

    ctrl.addTopic = function () {
      if (! ctrl.isDuplicateArrayElement(ctrl.selectedInterests, ctrl.newTopicName)) {
        ctrl.selectedInterests.push(ctrl.newTopicName);
        ctrl.isResultsForNewTopic = false;
        ctrl.isSearchRun = false;
        if (! ctrl.isDuplicateObject(ctrl.topics, 'topicName', ctrl.newTopicName)) { // topic not in the firebase master list, add it
          DatabaseConnection.addTopic(ctrl.newTopicName);
          ctrl.showToast('Topic sucessfully created.');
        }
        ctrl.newTopicName = '';
      } else {
        ctrl.showToast('Topic already in your Interests!');
      }

    }

    ctrl.newTopicSearchChange = function () {
      ctrl.isSearchRun = false;
      ctrl.isResultsForNewTopic = false;
      if (ctrl.newTopicName != '') {
        ctrl.isSearchRun = false;
        NyplApiCalls.nyplSearch(ctrl.newTopicName, 1).then(function (results) {
          var numResults = results.data.nyplAPI.response.numResults;
          if (numResults > 0) {
            ctrl.newTopicResultCount = numResults;
            ctrl.isResultsForNewTopic = true;
          }
          ctrl.isSearchRun = true;
        })
      }

    }

    //ctrl.interests = [];
    //ctrl.interests = ['Steam engine', 'New York', 'Samurai', 'Dresses', 'Israel Putnam'];
    ctrl.initSelectedInterests = function () {
      DatabaseConnection.getSettings().then(function (settings) {
        ctrl.settings = settings;
        if (ctrl.settings == null) {
          ctrl.selectedInterests = [];
        } else {
          ctrl.selectedInterests = ctrl.settings.interests;
        }

      })
    }

    ctrl.hide = function () {
      $mdDialog.hide();
    };

    ctrl.cancel = function () {
      $mdDialog.hide();
    };

    ctrl.save = function () {
      DatabaseConnection.saveSettings({
        interests: ctrl.selectedInterests,
      }
      );
      $mdDialog.hide();
    };

    ctrl.getTopics();
    ctrl.initSelectedInterests();

  });<|endoftext|>


<commit_before>import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import * as models from '../../../models';
import {DEBOUNCE_MILLIS} from '../../../common/constants';
import {trackEvent} from '../../../analytics/index';
import Modal from '../base/modal';
import ModalBody from '../base/modal-body';
import ModalHeader from '../base/modal-header';
import ModalFooter from '../base/modal-footer';
import OneLineEditor from '../codemirror/one-line-editor';

@autobind
class CookieModifyModal extends PureComponent {
  constructor (props) {
    super(props);

    this.state = {
      cookieJar: null,
      defaultCookie: {
        key: 'foo',
        value: 'bar',
        domain: 'domain.tld',
        path: '/',
        expires: Infinity,
        secure: false,
        httpOnly: false
      },
      cookie: null,
      isValid: {
        key: true,
        value: true,
        domain: true,
        path: true,
        expires: true
      }
    };
  }

  _setModalRef (n) {
    this.modal = n;
  }

  async _load () {
    const {workspace} = this.props;
    const cookieJar = await models.cookieJar.getOrCreateForWorkspace(workspace);
    this.setState({cookieJar});
  }

  async show (cookie) {
    await this._load();

    // Dunno why this is sent as an array
    cookie = cookie[0] || cookie;
    this.setState({cookie});

    this.modal.show();

    trackEvent('Cookie Modifier', 'Show');
  }

  hide () {
    this.modal.hide();
  }

  async _saveChanges () {
    const {cookieJar} = this.state;
    await models.cookieJar.update(cookieJar);
    this.props.reloadCookiesModal();
    this._load();
  }

  _handleCookieUpdate (oldCookie, cookie) {
    const {cookieJar} = this.state;
    const {cookies} = cookieJar;
    const index = cookies.findIndex(c => c.domain === oldCookie.domain && c.key === oldCookie.key);

    cookieJar.cookies = [
      ...cookies.slice(0, index),
      cookie,
      ...cookies.slice(index + 1)
    ];

    this._saveChanges(cookieJar);
    trackEvent('Cookie', 'Update');
  }

  _handleChange (input, field) {
    const {cookie} = this.state;
    let valid = true;

    if (typeof input === 'object') {
      input = input.target.checked;
    }

    if (valid) {
      clearTimeout(this._cookieUpdateTimeout);
      this._cookieUpdateTimeout = setTimeout(() => {
        this._handleCookieUpdate(cookie, Object.assign({}, cookie, {[field]: input}));
      }, DEBOUNCE_MILLIS * 2);
    }

    this.setState({
      isValid: {
        ...this.state.isValid,
        [field]: valid
      },
      cookie: {
        ...cookie,
        [field]: input
      }
    });
  }

  _capitalize (str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }

  render () {
    const {
      handleRender,
      handleGetRenderContext
    } = this.props;
    const {
      isValid,
      cookie,
      defaultCookie
    } = this.state;

    const textFields = ['key', 'value', 'domain', 'path', 'expires'];
    const checkFields = ['secure', 'httpOnly'];

    return (
      <Modal ref={this._setModalRef} {...this.props}>
        <ModalHeader>Modify Cookie</ModalHeader>
        <ModalBody className="cookie-modify">

            {textFields.map((field, i) => {
              const val = Object.assign({}, defaultCookie, cookie)[field].toString();

              return (

                  {this._capitalize(field)}
                    <OneLineEditor
                      className={isValid[field] ? '' : 'input--error'}
                      ref={this._setInputRef}
                      forceEditor
                      type="text"
                      render={handleRender}
                      getRenderContext={handleGetRenderContext}
                      defaultValue={val || ''}
                      onChange={(i) => this._handleChange(i, field)}/>

              );
            })}

            {checkFields.map((field, i) => {
              const checked = Object.assign({}, defaultCookie, cookie)[field];

              return (
                {this._capitalize(field)}
                  <input
                    type="checkbox"
                    name={field}
                    defaultChecked={checked || false}
                    onChange={(e) => this._handleChange(e, field)}
                  />

              );
            })}

        </ModalBody>
        <ModalFooter>

            * cookies are automatically sent with relevant requests

          <button className="btn" onClick={this.hide}>
            Done
          </button>
        </ModalFooter>
      </Modal>
    );
  }
}

CookieModifyModal.propTypes = {
  reloadCookiesModal: PropTypes.func.isRequired,
  handleRender: PropTypes.func.isRequired,
  handleGetRenderContext: PropTypes.func.isRequired,
  workspace: PropTypes.object.isRequired
};

// export CookieModifyModal;
export default CookieModifyModal;
<commit_msg>fixed cookie edit saving logic<commit_after>import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import autobind from 'autobind-decorator';
import * as models from '../../../models';
import {DEBOUNCE_MILLIS} from '../../../common/constants';
import {trackEvent} from '../../../analytics/index';
import Modal from '../base/modal';
import ModalBody from '../base/modal-body';
import ModalHeader from '../base/modal-header';
import ModalFooter from '../base/modal-footer';
import OneLineEditor from '../codemirror/one-line-editor';

@autobind
class CookieModifyModal extends PureComponent {
  constructor (props) {
    super(props);

    this.state = {
      cookieJar: null,
      defaultCookie: {
        key: 'foo',
        value: 'bar',
        domain: 'domain.tld',
        path: '/',
        expires: Infinity,
        secure: false,
        httpOnly: false
      },
      cookie: null,
      isValid: {
        key: true,
        value: true,
        domain: true,
        path: true,
        expires: true
      }
    };
  }

  _setModalRef (n) {
    this.modal = n;
  }

  async _load () {
    const {workspace} = this.props;
    const cookieJar = await models.cookieJar.getOrCreateForWorkspace(workspace);
    this.setState({cookieJar});
  }

  async show (cookie) {
    await this._load();

    // Dunno why this is sent as an array
    cookie = cookie[0] || cookie;
    this.setState({cookie});

    this.modal.show();

    trackEvent('Cookie Modifier', 'Show');
  }

  hide () {
    this.modal.hide();
  }

  async _saveChanges () {
    const {cookieJar} = this.state;
    await models.cookieJar.update(cookieJar);
    this.props.reloadCookiesModal();
    this._load();
  }

  _handleCookieUpdate (oldCookie, cookie) {
    const {cookieJar} = this.state;
    const {cookies} = cookieJar;
    const index = cookies.findIndex(c => c.domain === oldCookie.domain && c.key === oldCookie.key);

    cookieJar.cookies = [
      ...cookies.slice(0, index),
      cookie,
      ...cookies.slice(index + 1)
    ];

    this._saveChanges(cookieJar);
    trackEvent('Cookie', 'Update');
  }

  _handleChange (input, field) {
    const {cookie} = this.state;
    let valid = true;

    if (typeof input === 'object') {
      input = input.target.checked;
    }

    if (valid) {
      const newCookie = Object.assign({}, cookie, {[field]: input});

      clearTimeout(this._cookieUpdateTimeout);
      this._cookieUpdateTimeout = setTimeout(() => {
        this._handleCookieUpdate(cookie, newCookie);
        this.setState({cookie: newCookie});
      }, DEBOUNCE_MILLIS * 2);
    }

    this.setState({
      isValid: {
        ...this.state.isValid,
        [field]: valid
      }
    });
  }

  _capitalize (str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }

  render () {
    const {
      handleRender,
      handleGetRenderContext
    } = this.props;
    const {
      isValid,
      cookie,
      defaultCookie
    } = this.state;

    const textFields = ['key', 'value', 'domain', 'path', 'expires'];
    const checkFields = ['secure', 'httpOnly'];

    return (
      <Modal ref={this._setModalRef} {...this.props}>
        <ModalHeader>Modify Cookie</ModalHeader>
        <ModalBody className="cookie-modify">

            {textFields.map((field, i) => {
              const val = Object.assign({}, defaultCookie, cookie)[field].toString();

              return (

                  {this._capitalize(field)}
                    <OneLineEditor
                      className={isValid[field] ? '' : 'input--error'}
                      ref={this._setInputRef}
                      forceEditor
                      type="text"
                      render={handleRender}
                      getRenderContext={handleGetRenderContext}
                      defaultValue={val || ''}
                      onChange={(i) => this._handleChange(i, field)}/>

              );
            })}

            {checkFields.map((field, i) => {
              const checked = Object.assign({}, defaultCookie, cookie)[field];

              return (
                {this._capitalize(field)}
                  <input
                    type="checkbox"
                    name={field}
                    defaultChecked={checked || false}
                    onChange={(e) => this._handleChange(e, field)}
                  />

              );
            })}

        </ModalBody>
        <ModalFooter>

            * cookies are automatically sent with relevant requests

          <button className="btn" onClick={this.hide}>
            Done
          </button>
        </ModalFooter>
      </Modal>
    );
  }
}

CookieModifyModal.propTypes = {
  reloadCookiesModal: PropTypes.func.isRequired,
  handleRender: PropTypes.func.isRequired,
  handleGetRenderContext: PropTypes.func.isRequired,
  workspace: PropTypes.object.isRequired
};

// export CookieModifyModal;
export default CookieModifyModal;
<|endoftext|>


<commit_before>if(typeof zJS == "undefined") {
    zJS = {};
}

if(typeof zJS.Page == "undefined") {
    zJS.Page = {};
}
/*
 classes in TR:
 .mission_icon.plunder - набег
 .mission_icon.blockade - блокада
 .mission_icon.transport - транспортировка
 .mission_icon.deployarmy - размещение войска
 .mission_icon.deployfleet - размещение флота
 .mission_icon.defend - защита
 .mission_icon.defend_port - защита порта
 .mission_icon.occupy - окупация
 Who's movements:
 .mission.arrow_right_green - Мои войска в пути
 .mission.arrow_left_green - Мои войска возращаются

 */

//
<input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="plunder" id="ikaeasy_militaryView_cb_plunder" checked/> Набег	 <input type="checkbox" class="ikaeasy_militaryView_cb"  id="ikaeasy_militaryView_cb_blockade" data-ikaeztype="blockade" checked/> Блокада	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="transport" id="ikaeasy_militaryView_cb_transport" checked/> Транпортировка	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="deployarmy" id="ikaeasy_militaryView_cb_deployarmy" checked/> размещение войска	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="defend"  id="ikaeasy_militaryView_cb_defend" checked/> Защита	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="deployfleet"  id="ikaeasy_militaryView_cb_deployfleet" checked/> размещение флота

zJS.Page.militaryAdvisor = {
    init: function() {
        var $js_MilitaryMovementsFleetMovementsTable = $('#js_MilitaryMovementsFleetMovementsTable');
        var tab_moves={
            all: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon').length,
            plunder: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.plunder').length,
            occupy: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.occupy').length,
            blockade: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.blockade').length,
            transport: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.transport').length,
            deployarmy: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.deployarmy').length,
            deployfleet: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.deployfleet').length,
            defend: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.defend').length,
            defend_port: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.defend_port').length
        };
        $js_MilitaryMovementsFleetMovementsTable.find('table:not(.ikaeasy_complete)').before('

'+zJS.Lang.movements.all+'

'+tab_moves.all+'

'+tab_moves.transport+'

'+tab_moves.plunder+'

'+tab_moves.occupy+'

'+tab_moves.blockade+'

'+tab_moves.deployarmy+'

'+tab_moves.deployfleet+'

'+tab_moves.defend+'

'+tab_moves.defend_port+'

').addClass('ikaeasy_complete');
        var $ikaeasy_militaryView_cb=$("#ikaeasy_military_movements a");

        $ikaeasy_militaryView_cb.on("click", function() {
            var action=$(this).data('ikaeztype');
            $ikaeasy_militaryView_cb.removeClass('ikaez_active');
            $(this).addClass('ikaez_active');
            updateTableActions(action);
            zJS.Utils.settingsStorage.setItem('MilitaryMovements_tab', action);
        });

var active_tab=zJS.Utils.settingsStorage.getItem('MilitaryMovements_tab');
        $('#js_MilitaryMovementsFleetMovementsTable a[data-ikaeztype='+active_tab+']').addClass('ikaez_active');
        if(active_tab!="all") {
            console.log('not true '+zJS.Utils.settingsStorage.getItem('MilitaryMovements_tab'));
            $js_MilitaryMovementsFleetMovementsTable.find('tr:not(.ikaeasy_complete, '+active_tab+')').has('.mission_icon').hide();
        }

        function updateTableActions(action){
            console.log('update table actions');
            if(action=="all") {
                $js_MilitaryMovementsFleetMovementsTable.find('tr').show("fast");
            }else{
                $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon').hide("fast");
                $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.' + action).show("fast");
            }
        }

        $js_MilitaryMovementsFleetMovementsTable.find('td').each(function() {
            $(this).css('padding', '4px 0px').removeClass('right');
        });

        // Отображение войск и флотов в военном советнике.
        $js_MilitaryMovementsFleetMovementsTable.find('tr:not(.ikaeasy_complete)').has('td').each(function() {
            console.time('TR movements select');
            var wrapper = $('

');

            if($('.unit_detail_icon', this)[0] != null) {
                console.log($('.unit_detail_icon', this));
                $('.unit_detail_icon', this).each(function() {
                    $(wrapper).append($(this));
                });

                $('td', this).eq(3).empty().append(wrapper).attr('colspan', '2');
                $('td', this).eq(4).remove();
            }
            var $arrival_time = $('span[id$="ArrivalTime"]', this);
            var arrival_time = $arrival_time.text();
            var arrival_array = arrival_time.split(' ');
            var Arrival_time = 0;

            for(var i = 0; i < arrival_array.length; i++) {
                if(arrival_array[i].indexOf(zJS.Lang.char_second) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 1000;
                else if(arrival_array[i].indexOf(zJS.Lang.char_minute) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 60000;//60*1000
                else if(arrival_array[i].indexOf(zJS.Lang.char_hour) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 3600000;//60*1000*60
                else if(arrival_array[i].indexOf(zJS.Lang.char_day) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 86400000;//60*1000*60*24
            }
            var now = Date.now();
            var now_date = new Date();
            now += Arrival_time;
            var arrival_date = new Date(now);

            var dformat = '';
            if(arrival_date.getDate() != now_date.getDate() || arrival_date.getMonth() != now_date.getMonth())
                dformat = [arrival_date.getDate().padLeft(), (arrival_date.getMonth() + 1).padLeft()].join('.') + ' ';

            dformat += [arrival_date.getHours().padLeft(), arrival_date.getMinutes().padLeft()].join(':');
            $arrival_time.parent().append('' + dformat + '');
            $(this).addClass('ikaeasy_complete');
            console.timeEnd('TR movements select');
        });

    },

    refresh: function() {
        this.init();
    }
};<commit_msg>show\hide animation of tabs removed. bugs.<commit_after>if(typeof zJS == "undefined") {
    zJS = {};
}

if(typeof zJS.Page == "undefined") {
    zJS.Page = {};
}
/*
 classes in TR:
 .mission_icon.plunder - набег
 .mission_icon.blockade - блокада
 .mission_icon.transport - транспортировка
 .mission_icon.deployarmy - размещение войска
 .mission_icon.deployfleet - размещение флота
 .mission_icon.defend - защита
 .mission_icon.defend_port - защита порта
 .mission_icon.occupy - окупация
 Who's movements:
 .mission.arrow_right_green - Мои войска в пути
 .mission.arrow_left_green - Мои войска возращаются

 */

//
<input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="plunder" id="ikaeasy_militaryView_cb_plunder" checked/> Набег	 <input type="checkbox" class="ikaeasy_militaryView_cb"  id="ikaeasy_militaryView_cb_blockade" data-ikaeztype="blockade" checked/> Блокада	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="transport" id="ikaeasy_militaryView_cb_transport" checked/> Транпортировка	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="deployarmy" id="ikaeasy_militaryView_cb_deployarmy" checked/> размещение войска	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="defend"  id="ikaeasy_militaryView_cb_defend" checked/> Защита	 <input type="checkbox" class="ikaeasy_militaryView_cb" data-ikaeztype="deployfleet"  id="ikaeasy_militaryView_cb_deployfleet" checked/> размещение флота

zJS.Page.militaryAdvisor = {
    init: function() {
        var $js_MilitaryMovementsFleetMovementsTable = $('#js_MilitaryMovementsFleetMovementsTable');
        var tab_moves={
            all: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon').length,
            plunder: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.plunder').length,
            occupy: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.occupy').length,
            blockade: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.blockade').length,
            transport: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.transport').length,
            deployarmy: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.deployarmy').length,
            deployfleet: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.deployfleet').length,
            defend: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.defend').length,
            defend_port: $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon.defend_port').length
        };
        $js_MilitaryMovementsFleetMovementsTable.find('table:not(.ikaeasy_complete)').before('

'+zJS.Lang.movements.all+'

'+tab_moves.all+'

'+tab_moves.transport+'

'+tab_moves.plunder+'

'+tab_moves.occupy+'

'+tab_moves.blockade+'

'+tab_moves.deployarmy+'

'+tab_moves.deployfleet+'

'+tab_moves.defend+'

'+tab_moves.defend_port+'

').addClass('ikaeasy_complete');
        var $ikaeasy_militaryView_cb=$("#ikaeasy_military_movements a");

        $ikaeasy_militaryView_cb.on("click", function() {
            var action=$(this).data('ikaeztype');
            $ikaeasy_militaryView_cb.removeClass('ikaez_active');
            $(this).addClass('ikaez_active');
            updateTableActions(action);
            zJS.Utils.settingsStorage.setItem('MilitaryMovements_tab', action);
        });

var active_tab=zJS.Utils.settingsStorage.getItem('MilitaryMovements_tab');
        $('#js_MilitaryMovementsFleetMovementsTable a[data-ikaeztype='+active_tab+']').addClass('ikaez_active');
        if(active_tab!="all") {
            console.log('not true '+zJS.Utils.settingsStorage.getItem('MilitaryMovements_tab'));
            $js_MilitaryMovementsFleetMovementsTable.find('tr:not(.ikaeasy_complete, '+active_tab+')').has('.mission_icon').hide();
        }

        function updateTableActions(action){
            console.log('update table actions');
            if(action=="all") {
                $js_MilitaryMovementsFleetMovementsTable.find('tr').show();
            }else{
                $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.mission_icon').hide();
                $js_MilitaryMovementsFleetMovementsTable.find('tr').has('.' + action).show();
            }
        }

        $js_MilitaryMovementsFleetMovementsTable.find('td').each(function() {
            $(this).css('padding', '4px 0px').removeClass('right');
        });

        // Отображение войск и флотов в военном советнике.
        $js_MilitaryMovementsFleetMovementsTable.find('tr:not(.ikaeasy_complete)').has('td').each(function() {
            console.time('TR movements select');
            var wrapper = $('

');

            if($('.unit_detail_icon', this)[0] != null) {
                console.log($('.unit_detail_icon', this));
                $('.unit_detail_icon', this).each(function() {
                    $(wrapper).append($(this));
                });

                $('td', this).eq(3).empty().append(wrapper).attr('colspan', '2');
                $('td', this).eq(4).remove();
            }
            var $arrival_time = $('span[id$="ArrivalTime"]', this);
            var arrival_time = $arrival_time.text();
            var arrival_array = arrival_time.split(' ');
            var Arrival_time = 0;

            for(var i = 0; i < arrival_array.length; i++) {
                if(arrival_array[i].indexOf(zJS.Lang.char_second) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 1000;
                else if(arrival_array[i].indexOf(zJS.Lang.char_minute) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 60000;//60*1000
                else if(arrival_array[i].indexOf(zJS.Lang.char_hour) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 3600000;//60*1000*60
                else if(arrival_array[i].indexOf(zJS.Lang.char_day) !== -1)
                    Arrival_time += arrival_array[i].replace(/[^\d+]/g, '') * 86400000;//60*1000*60*24
            }
            var now = Date.now();
            var now_date = new Date();
            now += Arrival_time;
            var arrival_date = new Date(now);

            var dformat = '';
            if(arrival_date.getDate() != now_date.getDate() || arrival_date.getMonth() != now_date.getMonth())
                dformat = [arrival_date.getDate().padLeft(), (arrival_date.getMonth() + 1).padLeft()].join('.') + ' ';

            dformat += [arrival_date.getHours().padLeft(), arrival_date.getMinutes().padLeft()].join(':');
            $arrival_time.parent().append('' + dformat + '');
            $(this).addClass('ikaeasy_complete');
            console.timeEnd('TR movements select');
        });

    },

    refresh: function() {
        this.init();
    }
};<|endoftext|>


<commit_before>import { c } from 'ttag';

import { propertyToUTCDate } from 'proton-shared/lib/calendar/vcalConverter';
import { toUTCDate, fromUTCDate, convertUTCDateTimeToZone } from 'proton-shared/lib/date/timezone';
import formatUTC from 'proton-shared/lib/date-fns-utc/format';
import { isSameDay, isNextDay, isSameMonth, isSameYear } from 'proton-shared/lib/date-fns-utc/index';

/**
 * Given a list of existing alarms ordered by a Occurrence key,
 * insert a new alarm in the proper place in the list
 * @param {Object} newAlarm
 * @param {Array} existingAlarms
 *
 * @return {Array}
 */
export const insertAlarm = (newAlarm, existingAlarms = []) => {
    const { Occurrence } = newAlarm;
    const { newAlarms } = existingAlarms.reduce(
        (acc, alarm) => {
            if (!acc.done && Occurrence <= alarm.Occurrence) {
                acc.newAlarms.push(newAlarm, alarm);
                acc.done = true;
            } else {
                acc.newAlarms.push(alarm);
            }
            return acc;
        },
        { newAlarms: [], done: false }
    );
    // if the new alarm was not added (either because it must be added last or there were no existing alarms), add it at the end
    return newAlarms.length === existingAlarms.length ? [...existingAlarms, newAlarm] : [...newAlarms];
};

export const getAlarmMessage = (rawEvent, now, tzid) => {
    const {
        dtstart,
        summary: { value: title }
    } = rawEvent;

    // Determine if the event is happening in timezoned today, tomorrow, this month or this year.
    // For that, compute the UTC times of the timezoned end of today, end of month and end of year
    const UTCStartDate = propertyToUTCDate(dtstart);
    const startTimeZoned = convertUTCDateTimeToZone(fromUTCDate(UTCStartDate), tzid);
    const startDateTimeZoned = toUTCDate(startTimeZoned);
    const nowTimezoned = convertUTCDateTimeToZone(fromUTCDate(new Date(now)), tzid);
    const nowDateTimezoned = toUTCDate(nowTimezoned);

    const isToday = isSameDay(nowDateTimezoned, startDateTimeZoned);
    const isTomorrow = isNextDay(nowDateTimezoned, startDateTimeZoned);
    const isThisMonth = isSameMonth(nowDateTimezoned, startDateTimeZoned);
    const isThisYear = isSameYear(nowDateTimezoned, startDateTimeZoned);

    if (isToday) {
        return c('Alarm notification').t`${title} will start at ${formatUTC(startDateTimeZoned, 'p')}`;
    }
    if (isTomorrow) {
        return c('Alarm notification').t`${title} will start tomorrow at ${formatUTC(startDateTimeZoned, 'p')}`;
    }
    if (isThisMonth) {
        return c('Alarm notification').t`${title} will start ${formatUTC(startDateTimeZoned, 'eeee do')} at ${formatUTC(
            startDateTimeZoned,
            'p'
        )}`;
    }
    if (isThisYear) {
        return c('Alarm notification').t`${title} will start ${formatUTC(
            startDateTimeZoned,
            'eeee do MMMM'
        )} at ${formatUTC(startDateTimeZoned, 'p')}`;
    }
    return c('Alarm notification').t`${title} will start on ${formatUTC(startDateTimeZoned, 'PPPp')}`;
};
<commit_msg>add dateLocale to format<commit_after>import { c } from 'ttag';

import { propertyToUTCDate } from 'proton-shared/lib/calendar/vcalConverter';
import { toUTCDate, fromUTCDate, convertUTCDateTimeToZone } from 'proton-shared/lib/date/timezone';
import formatUTC from 'proton-shared/lib/date-fns-utc/format';
import { dateLocale } from 'proton-shared/lib/i18n';
import { isSameDay, isNextDay, isSameMonth, isSameYear } from 'proton-shared/lib/date-fns-utc/index';

/**
 * Given a list of existing alarms ordered by a Occurrence key,
 * insert a new alarm in the proper place in the list
 * @param {Object} newAlarm
 * @param {Array} existingAlarms
 *
 * @return {Array}
 */
export const insertAlarm = (newAlarm, existingAlarms = []) => {
    const { Occurrence } = newAlarm;
    const { newAlarms } = existingAlarms.reduce(
        (acc, alarm) => {
            if (!acc.done && Occurrence <= alarm.Occurrence) {
                acc.newAlarms.push(newAlarm, alarm);
                acc.done = true;
            } else {
                acc.newAlarms.push(alarm);
            }
            return acc;
        },
        { newAlarms: [], done: false }
    );
    // if the new alarm was not added (either because it must be added last or there were no existing alarms), add it at the end
    return newAlarms.length === existingAlarms.length ? [...existingAlarms, newAlarm] : [...newAlarms];
};

export const getAlarmMessage = (rawEvent, now, tzid) => {
    const {
        dtstart,
        summary: { value: title }
    } = rawEvent;

    // Determine if the event is happening in timezoned today, tomorrow, this month or this year.
    // For that, compute the UTC times of the timezoned end of today, end of month and end of year
    const UTCStartDate = propertyToUTCDate(dtstart);
    const startTimeZoned = convertUTCDateTimeToZone(fromUTCDate(UTCStartDate), tzid);
    const startDateTimeZoned = toUTCDate(startTimeZoned);
    const nowTimezoned = convertUTCDateTimeToZone(fromUTCDate(new Date(now)), tzid);
    const nowDateTimezoned = toUTCDate(nowTimezoned);

    const isToday = isSameDay(nowDateTimezoned, startDateTimeZoned);
    const isTomorrow = isNextDay(nowDateTimezoned, startDateTimeZoned);
    const isThisMonth = isSameMonth(nowDateTimezoned, startDateTimeZoned);
    const isThisYear = isSameYear(nowDateTimezoned, startDateTimeZoned);

    if (isToday) {
        return c('Alarm notification').t`${title} will start at ${formatUTC(startDateTimeZoned, 'p', {
            locale: dateLocale
        })}`;
    }
    if (isTomorrow) {
        return c('Alarm notification').t`${title} will start tomorrow at ${formatUTC(startDateTimeZoned, 'p', {
            locale: dateLocale
        })}`;
    }
    if (isThisMonth) {
        return c('Alarm notification').t`${title} will start ${formatUTC(startDateTimeZoned, 'eeee do', {
            locale: dateLocale
        })} at ${formatUTC(startDateTimeZoned, 'p', { locale: dateLocale })}`;
    }
    if (isThisYear) {
        return c('Alarm notification').t`${title} will start ${formatUTC(startDateTimeZoned, 'eeee do MMMM', {
            locale: dateLocale
        })} at ${formatUTC(startDateTimeZoned, 'p')}`;
    }
    return c('Alarm notification').t`${title} will start on ${formatUTC(startDateTimeZoned, 'PPPp', {
        locale: dateLocale
    })}`;
};
<|endoftext|>


<commit_before>/*
  Setup user details for exception handling
 */

App.then(function(app) {
    App.CurrentUser.find('current').then(function(user) {
        if (typeof Raven == 'object') {
            Raven.setUser({
                id: user.get('id_for_ember'),
                name: user.get('full_name'),
                email: user.get('email')
            });
        }
    });

    // This is called from the router automatically if the route being loaded
    // has a googleConversion property, otherwise it can be called manually.
    // Pass Google conversion code - 'gc'
    app.trackConversion = function (gc) {
        Ember.run.next(function() {
            if (gc &! DEBUG) {
                var google_conversion_id = gc.id || 986941294;
                var google_conversion_language = gc.language || 'en';
                var google_conversion_format = gc.format || '3';
                var google_conversion_color = gc.color || 'ffffff';
                var google_conversion_label = gc.label;
                var google_remarketing_only = false;
                $.getScript("https://www.googleadservices.com/pagead/conversion.js");
            }
        });
    };

    // Override the BB project / status search list
    // TODO: we should just define the 'list' when initializing
    //       and then BB should use it when setting up the list
    App.ProjectPhase.find().then(function(data){
        var list = [
            {id: 5, name: gettext("Running campaigns")},
            {id: [7,8], name: gettext("Finished campaigns")}
        ];
        App.ProjectPhaseSelectView.reopen({
            content: list
        });
    });

    // Facebook API ID
    if (FACEBOOK_AUTH_ID)
        App.set('appId', FACEBOOK_AUTH_ID);

    app.fbLogin = function (fbResponse) {
        var _this = this,
            currentUsercontroller = App.__container__.lookup('controller:currentUser');

        // Clear any existing tokens which might be present but expired. clearJwtToken action is on the App.ApplicationRoute
        // FIXME: should call the clearJwtToken action here but it isn't being called.
        // currentUsercontroller.send('clearJwtToken');
        delete localStorage.jwtToken;
        App.set('jwtToken', null);

        return Ember.RSVP.Promise(function (resolve, reject) {
            var hash = {
              url: "/api/social-login/facebook/",
              dataType: "json",
              type: 'post',
              data: fbResponse
            };

            hash.success = function (response) {

                App.AuthJwt.processSuccessResponse(response).then(function (user) {

                    // If success
                    currentUsercontroller.set('model', user);
                    currentUsercontroller.send('close');

                    // For some reason the currentUserController keeps failing to have a reference to 'tracker'
                    var loginController = App.__container__.lookup('controller:login'),
                        tracker = loginController.get('tracker');

                    if (tracker) {
                        tracker.identify(user.get('id_for_ember'));
                        tracker.peopleSet({
                            "$first_name": user.get('first_name'),
                            "$last_name": user.get('last_name'),
                            "$email": user.get('email'),
                            has_facebook: "yes",
                            last_login_type: "facebook"
                        })

                    }

                    if (user.get('firstLogin')) {
                        currentUsercontroller.send('setFlash', currentUsercontroller.get('welcomeMessage'));
                        // Register the successful Facebook signup with Mixpanel
                        if (tracker) {
                            tracker.trackEvent("Signup", {"type": "facebook"});
                            tracker.peopleSet({
                                facebook_shares: 0,
                                twitter_shares: 0
                            });
                        }
                    } else {
                        // Register the successful Facebook signin with Mixpanel
                        if (tracker) {
                            tracker.trackEvent("Login", {"type": "facebook"});
                            tracker.peopleSet({has_facebook: "yes"});
                        }
                    }

                    Ember.run(null, resolve, user);

                    // Trigger next transition in case a user was accesing a restricted page
                    currentUsercontroller.send('loadNextTransition');

                 }, function (error) {
                    // If Facebook login succeeded but something goes wrong on the token side we end up here
                    currentUsercontroller.send('setFlash', error, 'error');
                    Ember.run(null, reject, error);
                });
            };

            hash.error = function (response) {

                currentUsercontroller.send('setFlash', gettext('There was an error connecting Facebook'), 'error');
                var error = JSON.parse(response.responseText);
                Ember.run(null, reject, error);
            };

            Ember.$.ajax(hash);
        });
    };
});

/*
  Bluebottle Route Overrides
 */

App.ApplicationRoute.reopen(App.LogoutJwtMixin, {
    actions: {
        logout: function (redirect) {
            // call the standard logout code => clear JWT token etc
            this._super(redirect);

            // If the has logged in via FB, eg there is a FBUser then they should
            // be logged out so that the user can log in with user/email
            if (FB && !Em.isEmpty(FB.getUserID()))
                FB.logout();
        },
        addDonation: function (project, fundraiser) {
            var route = this;
            App.CurrentOrder.find('current').then(function(order) {
                var store = route.get('store');

                var projectHasDonation = order.get('donations').anyBy('project', project);
                var fundraiserHasDonation = false;
                if(fundraiser !== undefined){
                    fundraiserHasDonation = order.get('donations').anyBy('fundraiser', fundraiser);
                }

                // TODO: functional test this.
                // *  Donate directly to project: check if no direct donations exist
                // *  Donate through fundraiser: check if donation for that fundraiser exists
                // *  We can have the same project multiple times, but all different fundraisers

                if (fundraiserHasDonation ||
                    (projectHasDonation && !fundraiserHasDonation && fundraiser === undefined)) {
                    // Donation for this already exists in this order.
                } else {
                    var donation = store.createRecord(App.CurrentOrderDonation);
                    donation.set('project', project);
                    if(fundraiser !== undefined){
                        donation.set('fundraiser', fundraiser);
                    }
                    donation.set('order', order);
                    donation.save();

                    if (route.get('tracker')) route.get('tracker').trackEvent("Support Campaign", {project: project.get('title')});
                }
                route.transitionTo('currentOrder.donationList');
            });
        }
    }
});

/*
  Bluebottle Controller Overrides
 */
App.ApplicationController.reopen({
    needs: ['currentOrder', 'myProjectList'],

    missingCurrentUser: function () {
        // FIXME: should call the clearJwtToken action here but it isn't being called.
        delete localStorage.jwtToken;
        App.set('jwtToken', null);
    }
});

App.EventMixin = Em.Mixin.create({

  bindScrolling: function(opts) {
    var onScroll, self = this;

    onScroll = function() {
      var scrollTop = $(this).scrollTop();
      return self.scrolled(scrollTop);
    };

    $(window).bind('scroll', onScroll);
    $(document).bind('touchmove', onScroll);
  },

  startStopScrolling: function(elm, nameClass) {
    var lastScroll = 0,
        st, startScroll;

    startScroll = function() {
        st = $(this).scrollTop();

        if (st > lastScroll) {
            $(elm).removeClass(nameClass);
        } else {
            $(elm).addClass(nameClass);
        }

        lastScroll = st;
    };

    $(window).bind('scroll', startScroll);
    $(document).bind('touchmove', startScroll);
  },

  unbindScrolling: function () {
    $(window).unbind('scroll');
    $(document).unbind('touchmove');
  },

  bindMobileClick: function() {
    toggleMenu = function() {
      $('.mobile-nav-holder').toggleClass('is-active');
    };

    closeMenu = function(event) {
      $('.mobile-nav-holder').removeClass('is-active');
    };

    $('.mobile-nav-btn').bind('click', toggleMenu);
    $('#content').bind('hover', closeMenu);
  }
});

Ember.View.reopen({
    touchStart: Ember.alias('click')
})

/*
  Bluebottle View Overrides
*/

App.ApplicationView.reopen(App.EventMixin, {
    setBindScrolling: function() {
        this.bindScrolling();
        this.startStopScrolling('#cheetah-header', 'is-active');
    }.on('didInsertElement'),

    setUnbindScrolling: function() {
        this.unbindScrolling();
    }.on('didInsertElement'),

    setBindClick: function() {
        this.bindMobileClick();
    }.on('didInsertElement'),

    scrolled: function(dist) {
        top = $('#content').offset();
        elm = top.screen.availTop;

        if (dist <= 53) {
            $('#header').removeClass('is-scrolled');
            $('.nav-member-dropdown').removeClass('is-scrolled');
            $('.mobile-nav-holder').removeClass('is-scrolled');
            //$('#content').append('

');
        } else {
            $('#header').addClass('is-scrolled');
            $('.nav-member-dropdown').addClass('is-scrolled');
            $('.mobile-nav-holder').addClass('is-scrolled');
        }
    }
});

// Enable Google Ad Words with Ember
App.Router.reopen({

    // If you want to add Google conversion codes to a route just add:
    // googleConversion: {
    //      label: 'my_page_label'
    // }

    didTransition: function(infos) {
        this._super(infos);

        var currentRoute = infos.get('lastObject').handler,
            gc = currentRoute.get('googleConversion');

        if (gc) App.trackConversion(gc);
    },
});
<commit_msg>[feature/alias-fix] use alias instead of identify on signup<commit_after>/*
  Setup user details for exception handling
 */

App.then(function(app) {
    App.CurrentUser.find('current').then(function(user) {
        if (typeof Raven == 'object') {
            Raven.setUser({
                id: user.get('id_for_ember'),
                name: user.get('full_name'),
                email: user.get('email')
            });
        }
    });

    // This is called from the router automatically if the route being loaded
    // has a googleConversion property, otherwise it can be called manually.
    // Pass Google conversion code - 'gc'
    app.trackConversion = function (gc) {
        Ember.run.next(function() {
            if (gc &! DEBUG) {
                var google_conversion_id = gc.id || 986941294;
                var google_conversion_language = gc.language || 'en';
                var google_conversion_format = gc.format || '3';
                var google_conversion_color = gc.color || 'ffffff';
                var google_conversion_label = gc.label;
                var google_remarketing_only = false;
                $.getScript("https://www.googleadservices.com/pagead/conversion.js");
            }
        });
    };

    // Override the BB project / status search list
    // TODO: we should just define the 'list' when initializing
    //       and then BB should use it when setting up the list
    App.ProjectPhase.find().then(function(data){
        var list = [
            {id: 5, name: gettext("Running campaigns")},
            {id: [7,8], name: gettext("Finished campaigns")}
        ];
        App.ProjectPhaseSelectView.reopen({
            content: list
        });
    });

    // Facebook API ID
    if (FACEBOOK_AUTH_ID)
        App.set('appId', FACEBOOK_AUTH_ID);

    app.fbLogin = function (fbResponse) {
        var _this = this,
            currentUsercontroller = App.__container__.lookup('controller:currentUser');

        // Clear any existing tokens which might be present but expired. clearJwtToken action is on the App.ApplicationRoute
        // FIXME: should call the clearJwtToken action here but it isn't being called.
        // currentUsercontroller.send('clearJwtToken');
        delete localStorage.jwtToken;
        App.set('jwtToken', null);

        return Ember.RSVP.Promise(function (resolve, reject) {
            var hash = {
              url: "/api/social-login/facebook/",
              dataType: "json",
              type: 'post',
              data: fbResponse
            };

            hash.success = function (response) {

                App.AuthJwt.processSuccessResponse(response).then(function (user) {

                    // If success
                    currentUsercontroller.set('model', user);
                    currentUsercontroller.send('close');

                    // For some reason the currentUserController keeps failing to have a reference to 'tracker'
                    var loginController = App.__container__.lookup('controller:login'),
                        tracker = loginController.get('tracker');

                    if (tracker) {
                        if (user.get('firstLogin') {
                            tracker.alias(user.get('id_for_ember'));
                        } else {
                            tracker.identify(user.get('id_for_ember'));
                        }

                        tracker.peopleSet({
                            "$first_name": user.get('first_name'),
                            "$last_name": user.get('last_name'),
                            "$email": user.get('email'),
                            has_facebook: "yes",
                            last_login_type: "facebook"
                        });

                    }

                    if (user.get('firstLogin')) {
                        currentUsercontroller.send('setFlash', currentUsercontroller.get('welcomeMessage'));
                        // Register the successful Facebook signup with Mixpanel
                        if (tracker) {
                            tracker.trackEvent("Signup", {"type": "facebook"});
                            tracker.peopleSet({
                                facebook_shares: 0,
                                twitter_shares: 0
                            });
                        }
                    } else {
                        // Register the successful Facebook signin with Mixpanel
                        if (tracker) {
                            tracker.trackEvent("Login", {"type": "facebook"});
                            tracker.peopleSet({has_facebook: "yes"});
                        }
                    }

                    Ember.run(null, resolve, user);

                    // Trigger next transition in case a user was accesing a restricted page
                    currentUsercontroller.send('loadNextTransition');

                 }, function (error) {
                    // If Facebook login succeeded but something goes wrong on the token side we end up here
                    currentUsercontroller.send('setFlash', error, 'error');
                    Ember.run(null, reject, error);
                });
            };

            hash.error = function (response) {

                currentUsercontroller.send('setFlash', gettext('There was an error connecting Facebook'), 'error');
                var error = JSON.parse(response.responseText);
                Ember.run(null, reject, error);
            };

            Ember.$.ajax(hash);
        });
    };
});

/*
  Bluebottle Route Overrides
 */

App.ApplicationRoute.reopen(App.LogoutJwtMixin, {
    actions: {
        logout: function (redirect) {
            // call the standard logout code => clear JWT token etc
            this._super(redirect);

            // If the has logged in via FB, eg there is a FBUser then they should
            // be logged out so that the user can log in with user/email
            if (FB && !Em.isEmpty(FB.getUserID()))
                FB.logout();
        },
        addDonation: function (project, fundraiser) {
            var route = this;
            App.CurrentOrder.find('current').then(function(order) {
                var store = route.get('store');

                var projectHasDonation = order.get('donations').anyBy('project', project);
                var fundraiserHasDonation = false;
                if(fundraiser !== undefined){
                    fundraiserHasDonation = order.get('donations').anyBy('fundraiser', fundraiser);
                }

                // TODO: functional test this.
                // *  Donate directly to project: check if no direct donations exist
                // *  Donate through fundraiser: check if donation for that fundraiser exists
                // *  We can have the same project multiple times, but all different fundraisers

                if (fundraiserHasDonation ||
                    (projectHasDonation && !fundraiserHasDonation && fundraiser === undefined)) {
                    // Donation for this already exists in this order.
                } else {
                    var donation = store.createRecord(App.CurrentOrderDonation);
                    donation.set('project', project);
                    if(fundraiser !== undefined){
                        donation.set('fundraiser', fundraiser);
                    }
                    donation.set('order', order);
                    donation.save();

                    if (route.get('tracker')) route.get('tracker').trackEvent("Support Campaign", {project: project.get('title')});
                }
                route.transitionTo('currentOrder.donationList');
            });
        }
    }
});

/*
  Bluebottle Controller Overrides
 */
App.ApplicationController.reopen({
    needs: ['currentOrder', 'myProjectList'],

    missingCurrentUser: function () {
        // FIXME: should call the clearJwtToken action here but it isn't being called.
        delete localStorage.jwtToken;
        App.set('jwtToken', null);
    }
});

App.EventMixin = Em.Mixin.create({

  bindScrolling: function(opts) {
    var onScroll, self = this;

    onScroll = function() {
      var scrollTop = $(this).scrollTop();
      return self.scrolled(scrollTop);
    };

    $(window).bind('scroll', onScroll);
    $(document).bind('touchmove', onScroll);
  },

  startStopScrolling: function(elm, nameClass) {
    var lastScroll = 0,
        st, startScroll;

    startScroll = function() {
        st = $(this).scrollTop();

        if (st > lastScroll) {
            $(elm).removeClass(nameClass);
        } else {
            $(elm).addClass(nameClass);
        }

        lastScroll = st;
    };

    $(window).bind('scroll', startScroll);
    $(document).bind('touchmove', startScroll);
  },

  unbindScrolling: function () {
    $(window).unbind('scroll');
    $(document).unbind('touchmove');
  },

  bindMobileClick: function() {
    toggleMenu = function() {
      $('.mobile-nav-holder').toggleClass('is-active');
    };

    closeMenu = function(event) {
      $('.mobile-nav-holder').removeClass('is-active');
    };

    $('.mobile-nav-btn').bind('click', toggleMenu);
    $('#content').bind('hover', closeMenu);
  }
});

Ember.View.reopen({
    touchStart: Ember.alias('click')
})

/*
  Bluebottle View Overrides
*/

App.ApplicationView.reopen(App.EventMixin, {
    setBindScrolling: function() {
        this.bindScrolling();
        this.startStopScrolling('#cheetah-header', 'is-active');
    }.on('didInsertElement'),

    setUnbindScrolling: function() {
        this.unbindScrolling();
    }.on('didInsertElement'),

    setBindClick: function() {
        this.bindMobileClick();
    }.on('didInsertElement'),

    scrolled: function(dist) {
        top = $('#content').offset();
        elm = top.screen.availTop;

        if (dist <= 53) {
            $('#header').removeClass('is-scrolled');
            $('.nav-member-dropdown').removeClass('is-scrolled');
            $('.mobile-nav-holder').removeClass('is-scrolled');
            //$('#content').append('

');
        } else {
            $('#header').addClass('is-scrolled');
            $('.nav-member-dropdown').addClass('is-scrolled');
            $('.mobile-nav-holder').addClass('is-scrolled');
        }
    }
});

// Enable Google Ad Words with Ember
App.Router.reopen({

    // If you want to add Google conversion codes to a route just add:
    // googleConversion: {
    //      label: 'my_page_label'
    // }

    didTransition: function(infos) {
        this._super(infos);

        var currentRoute = infos.get('lastObject').handler,
            gc = currentRoute.get('googleConversion');

        if (gc) App.trackConversion(gc);
    },
});
<|endoftext|>


<commit_before>/**
 * This file contains all necessary Angular service definitions for 'frontend.core.layout' module.
 *
 * Note that this file should only contain services and nothing else.
 */
(function() {
  'use strict';

  // Generic service to return all available menu items for main level navigation.
  angular.module('frontend.core.layout')
    .factory('HeaderNavigationItems', [
      'AccessLevels','AuthService','$rootScope','UserService',
      function factory(AccessLevels,AuthService,$rootScope,UserService) {
        return [
          {
            state: 'dashboard',
            show : function() {
              return AuthService.isAuthenticated() && UserService.user().node
            },
            title: 'Dashboard',
            access: AccessLevels.user
          },
          {
            state: 'info',
            show : function() {
              return AuthService.isAuthenticated() && UserService.user().node
            },
            title: 'Node info',
            access: AccessLevels.user
          },
          {
            state: 'apis',
            show : function() {
              return AuthService.isAuthenticated() && UserService.user().node
            },
            title: 'APIs',
            access: AccessLevels.user
          },
          {
            state: 'consumers',
            show : function() {
              return AuthService.isAuthenticated() && UserService.user().node
            },
            title: 'Consumers',
            access: AccessLevels.user
          },
          {
            state: 'plugins',
            show : function() {
              return AuthService.isAuthenticated() && UserService.user().node
            },
            title: 'Plugins',
            access: AccessLevels.anon
          },
          {
            state: 'upstreams',
            show : function() {
              return AuthService.isAuthenticated() && UserService.user().node && $rootScope.Gateway && $rootScope.Gateway.version.indexOf("0.10.") > -1
            },
            title: 'Upstreams',
            access: AccessLevels.anon
          }
        ];
      }
    ])
  ;
}());
<commit_msg>Use $rootScope.Gateway to show/hide menu items<commit_after>/**
 * This file contains all necessary Angular service definitions for 'frontend.core.layout' module.
 *
 * Note that this file should only contain services and nothing else.
 */
(function() {
  'use strict';

  // Generic service to return all available menu items for main level navigation.
  angular.module('frontend.core.layout')
    .factory('HeaderNavigationItems', [
      'AccessLevels','AuthService','$rootScope','UserService',
      function factory(AccessLevels,AuthService,$rootScope,UserService) {

        console.log("################",$rootScope.Gateway)
        return [
          {
            state: 'dashboard',
            show : function() {
              return AuthService.isAuthenticated()
            },
            title: 'Dashboard',
            access: AccessLevels.user
          },
          {
            state: 'info',
            show : function() {
              return AuthService.isAuthenticated() && $rootScope.Gateway
            },
            title: 'Node info',
            access: AccessLevels.user
          },
          {
            state: 'apis',
            show : function() {
              return AuthService.isAuthenticated() && $rootScope.Gateway
            },
            title: 'APIs',
            access: AccessLevels.user
          },
          {
            state: 'consumers',
            show : function() {
              return AuthService.isAuthenticated() && $rootScope.Gateway
            },
            title: 'Consumers',
            access: AccessLevels.user
          },
          {
            state: 'plugins',
            show : function() {
              return AuthService.isAuthenticated() && $rootScope.Gateway
            },
            title: 'Plugins',
            access: AccessLevels.anon
          },
          {
            state: 'upstreams',
            show : function() {
              return AuthService.isAuthenticated() && $rootScope.Gateway && $rootScope.Gateway.version.indexOf("0.10.") > -1
            },
            title: 'Upstreams',
            access: AccessLevels.anon
          }
        ];
      }
    ])
  ;
}());
<|endoftext|>


<commit_before>(function ($) {

    /**
     *
     * KAYZEN
     * @module: 'google-map'
     * @author: @esr360
     *
     */

    $.fn.googleMap = function(custom) {

        // Options

        // Fetch the map colors from the CSS
        var _mapColor = _modules['google-map']['colors'];

        var options = $.extend({
            styles: [
                {
                    "featureType" : "water",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['water']
                    }]
                },
                {
                    "featureType" : "landscape",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['landscape']
                    }]
                },
                {
                    "featureType" : "road",
                    "elementType" : "geometry",
                    "stylers" : [
                        { "color" : _mapColor['road'] },
                        { "lightness" : -37 }
                    ]
                },
                {
                    "featureType" : "poi",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['poi']
                    }]
                },
                {
                    "featureType" : "transit",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['transit']
                    }]
                },
                {
                    "elementType" : "labels.text.stroke",
                    "stylers" : [
                        { "visibility" : "on" },
                        { "color" : _mapColor['stroke'] },
                        { "weight" : 2 },
                        { "gamma" : 0.84 }
                    ]
                },
                {
                    "featureType": "road.highway",
                    "elementType": "geometry",
                    "stylers": [
                        { "color": _mapColor['highway'] }
                    ]
                },
                {
                    "elementType" : "labels.text.fill",
                    "stylers" : [{
                        "color" : "#ffffff"
                    }]
                },
                {
                    "featureType" : "administrative",
                    "elementType" : "geometry",
                    "stylers" : [
                        { "weight" : 0.6 },
                        { "color" : _mapColor['administrative'] }
                    ]
                },
                {
                    "elementType" : "labels.icon",
                    "stylers" : [{
                        "visibility" : "off"
                    }]
                },
                {
                    "featureType" : "poi.park",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['park']
                    }]
                }
            ],
            longitude: _modules['google-map']['location'][0],
            latitude: _modules['google-map']['location'][1],
            zoom: 14,
            headerTrigger : '#toggleHeader'
        }, custom);

        // Run the code on each occurance of the element
        return this.each(function() {

            // When the window has finished loading create our google map
            google.maps.event.addDomListener(window, 'load', init);

            // Get the HTML DOM element that will contain your map
            var mapElement = $(this)[0];

            function init() {

                // When the window has finished loading create our google map
                if($(this).length == 1) {
                    google.maps.event.addDomListener(window, 'load', init);
                }

                // Basic options for a simple Google Map
                // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
                var mapOptions = {

                    // How zoomed in you want the map to start at (always required)
                    zoom: options.zoom,

                    // Disable scroll-wheel zoom
                    scrollwheel: false,

                    draggable: false,

                    // The latitude and longitude to center the map (always required)
                    center: new google.maps.LatLng(options.longitude, options.latitude),

                    // How you would like to style the map?
                    // This is where you would paste any style found on Snazzy Maps.

                    styles: options.styles

                };

                // Create the Google Map using our element and options defined above
                var map = new google.maps.Map(mapElement, mapOptions);

            } // init()

        }); // this.each

    }; // googleMap()

}(jQuery));<commit_msg>removing supurfluous option<commit_after>(function ($) {

    /**
     * KAYZEN
     * @module: 'google-map'
     * @author: @esr360
     */
    $.fn.googleMap = function(custom) {

        // Options

        // Fetch the map colors from the CSS
        var _mapColor = _modules['google-map']['colors'];

        var options = $.extend({
            styles: [
                {
                    "featureType" : "water",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['water']
                    }]
                },
                {
                    "featureType" : "landscape",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['landscape']
                    }]
                },
                {
                    "featureType" : "road",
                    "elementType" : "geometry",
                    "stylers" : [
                        { "color" : _mapColor['road'] },
                        { "lightness" : -37 }
                    ]
                },
                {
                    "featureType" : "poi",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['poi']
                    }]
                },
                {
                    "featureType" : "transit",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['transit']
                    }]
                },
                {
                    "elementType" : "labels.text.stroke",
                    "stylers" : [
                        { "visibility" : "on" },
                        { "color" : _mapColor['stroke'] },
                        { "weight" : 2 },
                        { "gamma" : 0.84 }
                    ]
                },
                {
                    "featureType": "road.highway",
                    "elementType": "geometry",
                    "stylers": [
                        { "color": _mapColor['highway'] }
                    ]
                },
                {
                    "elementType" : "labels.text.fill",
                    "stylers" : [{
                        "color" : "#ffffff"
                    }]
                },
                {
                    "featureType" : "administrative",
                    "elementType" : "geometry",
                    "stylers" : [
                        { "weight" : 0.6 },
                        { "color" : _mapColor['administrative'] }
                    ]
                },
                {
                    "elementType" : "labels.icon",
                    "stylers" : [{
                        "visibility" : "off"
                    }]
                },
                {
                    "featureType" : "poi.park",
                    "elementType" : "geometry",
                    "stylers" : [{
                        "color" : _mapColor['park']
                    }]
                }
            ],
            longitude: _modules['google-map']['location'][0],
            latitude: _modules['google-map']['location'][1],
            zoom: 14
        }, custom);

        // Run the code on each occurance of the element
        return this.each(function() {

            // When the window has finished loading create our google map
            google.maps.event.addDomListener(window, 'load', init);

            // Get the HTML DOM element that will contain your map
            var mapElement = $(this)[0];

            function init() {

                // When the window has finished loading create our google map
                if($(this).length == 1) {
                    google.maps.event.addDomListener(window, 'load', init);
                }

                // Basic options for a simple Google Map
                // For more options see: https://developers.google.com/maps/documentation/javascript/reference#MapOptions
                var mapOptions = {

                    // How zoomed in you want the map to start at (always required)
                    zoom: options.zoom,

                    // Disable scroll-wheel zoom
                    scrollwheel: false,

                    draggable: false,

                    // The latitude and longitude to center the map (always required)
                    center: new google.maps.LatLng(options.longitude, options.latitude),

                    // How you would like to style the map?
                    // This is where you would paste any style found on Snazzy Maps.
                    styles: options.styles

                };

                // Create the Google Map using our element and options defined above
                var map = new google.maps.Map(mapElement, mapOptions);

            } // init()

        }); // this.each

    }; // googleMap()

}(jQuery));<|endoftext|>