<commit_before>import React, {Component, PropTypes} from 'react'

import _ from 'lodash'
import classnames from 'classnames'
import {Link} from 'react-router'
import uuid from 'node-uuid'

import FancyScrollbar from 'shared/components/FancyScrollbar'

import {ALERTS_TABLE} from 'src/alerts/constants/tableSizing'

class AlertsTable extends Component {
  constructor(props) {
    super(props)

    this.state = {
      searchTerm: '',
      filteredAlerts: this.props.alerts,
      sortDirection: null,
      sortKey: null,
    }
  }

  componentWillReceiveProps(newProps) {
    this.filterAlerts(this.state.searchTerm, newProps.alerts)
  }

  filterAlerts = (searchTerm, newAlerts) => {
    const alerts = newAlerts || this.props.alerts
    const filterText = searchTerm.toLowerCase()
    const filteredAlerts = alerts.filter(h => {
      if (h.host === null || h.name === null || h.level === null) {
        return false
      }

      return (
        h.name.toLowerCase().includes(filterText) ||
        h.host.toLowerCase().includes(filterText) ||
        h.level.toLowerCase().includes(filterText)
      )
    })
    this.setState({searchTerm, filteredAlerts})
  }

  changeSort = key => () => {
    // if we're using the key, reverse order; otherwise, set it with ascending
    if (this.state.sortKey === key) {
      const reverseDirection =
        this.state.sortDirection === 'asc' ? 'desc' : 'asc'
      this.setState({sortDirection: reverseDirection})
    } else {
      this.setState({sortKey: key, sortDirection: 'asc'})
    }
  }

  sortableClasses = key => () => {
    if (this.state.sortKey === key) {
      if (this.state.sortDirection === 'asc') {
        return 'alert-history-table--th sortable-header sorting-ascending'
      }
      return 'alert-history-table--th sortable-header sorting-descending'
    }
    return 'alert-history-table--th sortable-header'
  }

  sort = (alerts, key, direction) => {
    switch (direction) {
      case 'asc':
        return _.sortBy(alerts, e => e[key])
      case 'desc':
        return _.sortBy(alerts, e => e[key]).reverse()
      default:
        return alerts
    }
  }

  renderTable() {
    const {source: {id}} = this.props
    const alerts = this.sort(
      this.state.filteredAlerts,
      this.state.sortKey,
      this.state.sortDirection
    )
    const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
    return this.props.alerts.length
      ?

              Name

              Level

              Time

              Host

              Value

          <FancyScrollbar
            className="alert-history-table--tbody"
            autoHide={false}
          >
            {alerts.map(({name, level, time, host, value}) => {
              return (

                    {name}

                  <div
                    className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
                    style={{width: colLevel}}
                  >

                    {new Date(Number(time)).toISOString()}

                    <Link to={`/sources/${id}/hosts/${host}`} title={host}>
                      {host}
                    </Link>

                    {value}

              )
            })}
          </FancyScrollbar>

      : this.renderTableEmpty()
  }

  renderTableEmpty() {
    const {source: {id}, shouldNotBeFilterable} = this.props

    return shouldNotBeFilterable
      ?

            Learn how to configure your first Rule in

            the Getting Started guide

      :

There are no Alerts to display

            Try changing the Time Range or
            <Link
              style={{marginLeft: '10px'}}
              to={`/sources/${id}/alert-rules/new`}
              className="btn btn-primary btn-sm"
            >
              Create an Alert Rule
            </Link>

  }

  render() {
    const {
      shouldNotBeFilterable,
      limit,
      onGetMoreAlerts,
      isAlertsMaxedOut,
      alertsCount,
    } = this.props

    return shouldNotBeFilterable
      ?

          {this.renderTable()}
          {limit && alertsCount
            ? <button
                className="btn btn-sm btn-default btn-block"
                onClick={onGetMoreAlerts}
                disabled={isAlertsMaxedOut}
                style={{marginBottom: '20px'}}
              >
                {isAlertsMaxedOut
                  ? `All ${alertsCount} Alerts displayed`
                  : 'Load next 30 Alerts'}
              </button>
            : null}

      :

              {this.props.alerts.length} Alerts

            {this.props.alerts.length
              ? <SearchBar onSearch={this.filterAlerts} />
              : null}

            {this.renderTable()}

  }
}

class SearchBar extends Component {
  constructor(props) {
    super(props)

    this.state = {
      searchTerm: '',
    }

    this.handleSearch = ::this.handleSearch
    this.handleChange = ::this.handleChange
  }

  componentWillMount() {
    const waitPeriod = 300
    this.handleSearch = _.debounce(this.handleSearch, waitPeriod)
  }

  handleSearch() {
    this.props.onSearch(this.state.searchTerm)
  }

  handleChange(e) {
    this.setState({searchTerm: e.target.value}, this.handleSearch)
  }

  render() {
    return (

        <input
          type="text"
          className="form-control"
          placeholder="Filter Alerts..."
          onChange={this.handleChange}
          value={this.state.searchTerm}
        />

    )
  }
}

const {arrayOf, bool, func, number, shape, string} = PropTypes

AlertsTable.propTypes = {
  alerts: arrayOf(
    shape({
      name: string,
      time: string,
      value: string,
      host: string,
      level: string,
    })
  ),
  source: shape({
    id: string.isRequired,
    name: string.isRequired,
  }).isRequired,
  shouldNotBeFilterable: bool,
  limit: number,
  onGetMoreAlerts: func,
  isAlertsMaxedOut: bool,
  alertsCount: number,
}

SearchBar.propTypes = {
  onSearch: func.isRequired,
}

export default AlertsTable
<commit_msg>Fix alerts table to display if alerts are missing a host, name, or level<commit_after>import React, {Component, PropTypes} from 'react'

import _ from 'lodash'
import classnames from 'classnames'
import {Link} from 'react-router'
import uuid from 'node-uuid'

import FancyScrollbar from 'shared/components/FancyScrollbar'

import {ALERTS_TABLE} from 'src/alerts/constants/tableSizing'

class AlertsTable extends Component {
  constructor(props) {
    super(props)

    this.state = {
      searchTerm: '',
      filteredAlerts: this.props.alerts,
      sortDirection: null,
      sortKey: null,
    }
  }

  componentWillReceiveProps(newProps) {
    this.filterAlerts(this.state.searchTerm, newProps.alerts)
  }

  filterAlerts = (searchTerm, newAlerts) => {
    const alerts = newAlerts || this.props.alerts
    const filterText = searchTerm.toLowerCase()
    const filteredAlerts = alerts.filter(({name, host, level}) => {
      return (
        (name && name.toLowerCase().includes(filterText)) ||
        (host && host.toLowerCase().includes(filterText)) ||
        (level && level.toLowerCase().includes(filterText))
      )
    })
    this.setState({searchTerm, filteredAlerts})
  }

  changeSort = key => () => {
    // if we're using the key, reverse order; otherwise, set it with ascending
    if (this.state.sortKey === key) {
      const reverseDirection =
        this.state.sortDirection === 'asc' ? 'desc' : 'asc'
      this.setState({sortDirection: reverseDirection})
    } else {
      this.setState({sortKey: key, sortDirection: 'asc'})
    }
  }

  sortableClasses = key => () => {
    if (this.state.sortKey === key) {
      if (this.state.sortDirection === 'asc') {
        return 'alert-history-table--th sortable-header sorting-ascending'
      }
      return 'alert-history-table--th sortable-header sorting-descending'
    }
    return 'alert-history-table--th sortable-header'
  }

  sort = (alerts, key, direction) => {
    switch (direction) {
      case 'asc':
        return _.sortBy(alerts, e => e[key])
      case 'desc':
        return _.sortBy(alerts, e => e[key]).reverse()
      default:
        return alerts
    }
  }

  renderTable() {
    const {source: {id}} = this.props
    const alerts = this.sort(
      this.state.filteredAlerts,
      this.state.sortKey,
      this.state.sortDirection
    )
    const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
    return this.props.alerts.length
      ?

              Name

              Level

              Time

              Host

              Value

          <FancyScrollbar
            className="alert-history-table--tbody"
            autoHide={false}
          >
            {alerts.map(({name, level, time, host, value}) => {
              return (

                    {name}

                  <div
                    className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
                    style={{width: colLevel}}
                  >

                    {new Date(Number(time)).toISOString()}

                    <Link to={`/sources/${id}/hosts/${host}`} title={host}>
                      {host}
                    </Link>

                    {value}

              )
            })}
          </FancyScrollbar>

      : this.renderTableEmpty()
  }

  renderTableEmpty() {
    const {source: {id}, shouldNotBeFilterable} = this.props

    return shouldNotBeFilterable
      ?

            Learn how to configure your first Rule in

            the Getting Started guide

      :

There are no Alerts to display

            Try changing the Time Range or
            <Link
              style={{marginLeft: '10px'}}
              to={`/sources/${id}/alert-rules/new`}
              className="btn btn-primary btn-sm"
            >
              Create an Alert Rule
            </Link>

  }

  render() {
    const {
      shouldNotBeFilterable,
      limit,
      onGetMoreAlerts,
      isAlertsMaxedOut,
      alertsCount,
    } = this.props

    return shouldNotBeFilterable
      ?

          {this.renderTable()}
          {limit && alertsCount
            ? <button
                className="btn btn-sm btn-default btn-block"
                onClick={onGetMoreAlerts}
                disabled={isAlertsMaxedOut}
                style={{marginBottom: '20px'}}
              >
                {isAlertsMaxedOut
                  ? `All ${alertsCount} Alerts displayed`
                  : 'Load next 30 Alerts'}
              </button>
            : null}

      :

              {this.props.alerts.length} Alerts

            {this.props.alerts.length
              ? <SearchBar onSearch={this.filterAlerts} />
              : null}

            {this.renderTable()}

  }
}

class SearchBar extends Component {
  constructor(props) {
    super(props)

    this.state = {
      searchTerm: '',
    }

    this.handleSearch = ::this.handleSearch
    this.handleChange = ::this.handleChange
  }

  componentWillMount() {
    const waitPeriod = 300
    this.handleSearch = _.debounce(this.handleSearch, waitPeriod)
  }

  handleSearch() {
    this.props.onSearch(this.state.searchTerm)
  }

  handleChange(e) {
    this.setState({searchTerm: e.target.value}, this.handleSearch)
  }

  render() {
    return (

        <input
          type="text"
          className="form-control"
          placeholder="Filter Alerts..."
          onChange={this.handleChange}
          value={this.state.searchTerm}
        />

    )
  }
}

const {arrayOf, bool, func, number, shape, string} = PropTypes

AlertsTable.propTypes = {
  alerts: arrayOf(
    shape({
      name: string,
      time: string,
      value: string,
      host: string,
      level: string,
    })
  ),
  source: shape({
    id: string.isRequired,
    name: string.isRequired,
  }).isRequired,
  shouldNotBeFilterable: bool,
  limit: number,
  onGetMoreAlerts: func,
  isAlertsMaxedOut: bool,
  alertsCount: number,
}

SearchBar.propTypes = {
  onSearch: func.isRequired,
}

export default AlertsTable
<|endoftext|>


<commit_before>'use strict'
import React from 'react'
import './quick.less'
import Palettes from 'stores/palettes'
import _ from 'lodash'
import lang from 'i18n/lang'
let QuickStyler = React.createClass({
  onMouseEvent: function (evt, idx) {
    let p = new Palettes()
    switch (this.props.selectedStyleTarget) {
      case 'defaultSlide':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('defaultSlideStyle', p[idx])
            break
          case 'click':
            this.props.onSelectedWidgetUpdated({
              container: this.props.deck,
              index: -1
            }, {defaultSlideStyle: p[idx]}, lang.setAppearance + ' ' + lang.defaultSlide)
          default:
            this.props.setTargetStyle('defaultSlideStyle', null)
        }
        break
      case 'thisSlide':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('thisSlideStyle', p[idx])
            break
          case 'click':
            this.props.onSelectedWidgetUpdated({
              container: this.props.deck.getActiveSlide(),
              index: -1
            }, {style: p[idx]}, lang.setAppearance + ' ' + lang.thisSlide)
          default:
            this.props.setTargetStyle('thisSlideStyle', null)
        }
        break
      case 'selectedSlides':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('selectedSlideStyle', p[idx])
            break
          case 'click':
          default:
            this.props.setTargetStyle('selectedSlideStyle', null)
        }
        break
      case 'entirePresentation':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('deckStyle', p[idx])
            break
          case 'click':
          default:
            this.props.setTargetStyle('deckStyle', this.props.deck.style)
        }
    }
  },
  render: function () {
    let p = new Palettes()
    let pDivs = _.map(p, (e, i)=> {
      return
 {
                    this.onMouseEvent(evt, i)
                  } }
                  onMouseLeave={
                    (evt)=> {
                      this.onMouseEvent(evt, i)
                    }
                  }
                  onClick={
                    (evt) => {
                      this.onMouseEvent(evt, i)
                    }
                  }
                  key={i}>

    })
    return

      {pDivs}

  }
})
module.exports = QuickStyler
<commit_msg>added onclick handler for selected slides<commit_after>'use strict'
import React from 'react'
import './quick.less'
import Palettes from 'stores/palettes'
import _ from 'lodash'
import lang from 'i18n/lang'
let QuickStyler = React.createClass({
  onMouseEvent: function (evt, idx) {
    let p = new Palettes()
    switch (this.props.selectedStyleTarget) {
      case 'defaultSlide':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('defaultSlideStyle', p[idx])
            break
          case 'click':
            this.props.onSelectedWidgetUpdated({
              container: this.props.deck,
              index: -1
            }, {defaultSlideStyle: p[idx]}, lang.setAppearance + ' ' + lang.defaultSlide)
          default:
            this.props.setTargetStyle('defaultSlideStyle', null)
        }
        break
      case 'thisSlide':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('thisSlideStyle', p[idx])
            break
          case 'click':
            this.props.onSelectedWidgetUpdated({
              container: this.props.deck.getActiveSlide(),
              index: -1
            }, {style: p[idx]}, lang.setAppearance + ' ' + lang.thisSlide)
          default:
            this.props.setTargetStyle('thisSlideStyle', null)
        }
        break
      case 'selectedSlides':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('selectedSlideStyle', p[idx])
            break
          case 'click':
            this.props.deck.components.forEach((e)=> {
              if (e.selected) {
                this.props.onSelectedWidgetUpdated({
                  container: e,
                  index: -1
                }, {style: p[idx]})
              }
            })
            this.props.deck.markUndo(lang.setAppearance + ' ' + lang.selectedSlides)
          default:
            this.props.setTargetStyle('selectedSlideStyle', null)
        }
        break
      case 'entirePresentation':
        switch (evt.type) {
          case 'mouseover':
            this.props.setTargetStyle('deckStyle', p[idx])
            break
          case 'click':
          default:
            this.props.setTargetStyle('deckStyle', this.props.deck.style)
        }
    }
  },
  render: function () {
    let p = new Palettes()
    let pDivs = _.map(p, (e, i)=> {
      return
 {
                    this.onMouseEvent(evt, i)
                  } }
                  onMouseLeave={
                    (evt)=> {
                      this.onMouseEvent(evt, i)
                    }
                  }
                  onClick={
                    (evt) => {
                      this.onMouseEvent(evt, i)
                    }
                  }
                  key={i}>

    })
    return

      {pDivs}

  }
})
module.exports = QuickStyler
<|endoftext|>


<commit_before>function kirkiObjectToArray( obj ) {
	var arr = [];
	if ( null !== obj ) {
		_.each( obj, function( value ) {
			if ( undefined !== value ) {
				arr.push( value );
			}
		})
	}
	return arr;
}
<commit_msg>added missing semicolon<commit_after>function kirkiObjectToArray( obj ) {
	var arr = [];
	if ( null !== obj ) {
		_.each( obj, function( value ) {
			if ( undefined !== value ) {
				arr.push( value );
			}
		});
	}
	return arr;
}
<|endoftext|>


<commit_before>import nodeResolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';

export default {
  input: 'src/index.js',
  plugins: [
    nodeResolve(),
    babel(),
  ],
  output: [
    {
      format: 'umd',
      name: 'VueMask',
      exports: 'named',
      file: 'dist/v-mask.js',
    },
    {
      format: 'es',
      file: 'dist/v-mask.esm.js',
    },
  ],
}
<commit_msg>fix: typo<commit_after>import nodeResolve from 'rollup-plugin-node-resolve';
import babel from 'rollup-plugin-babel';

export default {
  input: 'src/index.js',
  plugins: [
    nodeResolve(),
    babel(),
  ],
  output: [
    {
      format: 'umd',
      name: 'VueMask',
      exports: 'named',
      file: 'dist/v-mask.js',
    },
    {
      format: 'esm',
      file: 'dist/v-mask.esm.js',
    },
  ],
}
<|endoftext|>


<commit_before>angular.module('demo', [
  'ionic',
  'ngCordova',

  // modules
  // 'demo.adMob.ctrl',  // not working???
  'demo.appAvailability.ctrl',
  'demo.appRate.ctrl',
  'demo.barcodeScanner.ctrl',
  'demo.batteryStatus.ctrl',
  'demo.camera.ctrl',
  'demo.clipboard.ctrl',
  'demo.contacts.ctrl',
  'demo.datePicker.ctrl',
  'demo.device.ctrl',
  'demo.deviceMotion.ctrl',
  'demo.deviceOrientation.ctrl',
  'demo.dialogs.ctrl',
  'demo.facebook.ctrl',
  'demo.file.ctrl',
  'demo.flashlight.ctrl',
  'demo.geolocation.ctrl',
  'demo.globalization.ctrl',
  'demo.googleAnalytics.ctrl',
  'demo.localNotification.ctrl',
  'demo.media.ctrl',
  'demo.network.ctrl',
  'demo.oauth.ctrl',
  'demo.preferences.ctrl',
  'demo.printer.ctrl',
  'demo.pushNotifications.ctrl',
  'demo.socialSharing.ctrl',
  'demo.sqlite.ctrl',
  'demo.statusbar.ctrl',
  'demo.toast.ctrl',
  'demo.touchid.ctrl',
  'demo.vibration.ctrl'
])

  .run(function ($rootScope, $ionicPlatform, $cordovaNetwork, $cordovaBatteryStatus) {

    $ionicPlatform.ready(function () {
      if (window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if (window.StatusBar) {
        StatusBar.styleDefault();
      }

      $cordovaNetwork.watchOffline();
      $cordovaNetwork.watchOnline();

      $rootScope.$on("networkOffline", function () {
        alert("Device is now Offline!");
      });

      $rootScope.$on("networkOnline", function () {
        alert("Device is Online!");
      });

      $cordovaBatteryStatus.$on("batterystatus", function (status) {
        alert("status :" + status);
      })
    })
  })

  .config(function ($stateProvider, $urlRouterProvider, $cordovaFacebookProvider) {

    if (!window.cordova) {
      var appID = 1234567890;
      var version = "v2.0"; // or leave blank and default is v2.0
      $cordovaFacebookProvider.browserInit(appID, version);
    }

    $stateProvider

      .state('menu', {
        url: "/menu",
        templateUrl: "app/menu.html"
      })

      .state('appAvailability', {
        url: '/appAvailability',
        templateUrl: 'app/appAvailability/appAvailability.html',
        controller: "AppAvailabilityCtrl"
      })

      .state('appRate', {
        url: '/appRate',
        templateUrl: 'app/appRate/appRate.html',
        controller: "AppRateCtrl"
      })

      .state('barcodeScanner', {
        url: '/barcodeScanner',
        templateUrl: 'app/barcodeScanner/barcodeScanner.html',
        controller: "BarcodeScannerCtrl"
      })

      .state('batteryStatus', {
        url: '/batteryStatus',
        templateUrl: 'app/batteryStatus/batteryStatus.html',
        controller: "BatteryStatusCtrl"
      })

      .state('camera', {
        url: '/camera',
        templateUrl: 'app/camera/camera.html',
        controller: "CameraCtrl"
      })

      .state('clipboard', {
        url: '/clipboard',
        templateUrl: 'app/clipboard/clipboard.html',
        controller: "ClipboardCtrl"
      })

      .state('contacts', {
        url: '/contacts',
        templateUrl: 'app/contacts/contacts.html',
        controller: "ContactsCtrl"
      })

      .state('datePicker', {
        url: '/datePicker',
        templateUrl: 'app/datePicker/datePicker.html',
        controller: "DatePickerCtrl"
      })

      .state('device', {
        url: '/device',
        templateUrl: 'app/device/device.html',
        controller: "DeviceCtrl"
      })

      .state('deviceMotion', {
        url: '/deviceMotion',
        templateUrl: 'app/deviceMotion/deviceMotion.html',
        controller: "DeviceMotionCtrl"
      })

      .state('deviceOrientation', {
        url: '/deviceOrientation',
        templateUrl: 'app/deviceOrientation/deviceOrientation.html',
        controller: "DeviceOrientationCtrl"
      })

      .state('dialogs', {
        url: '/dialogs',
        templateUrl: 'app/dialogs/dialogs.html',
        controller: "DialogsCtrl"
      })

      .state('facebook', {
        url: '/facebook',
        templateUrl: 'app/facebook/facebook.html',
        controller: "FacebookCtrl"
      })

      .state('file', {
        url: '/file',
        templateUrl: 'app/file/file.html',
        controller: "FileCtrl"
      })

      .state('flashlight', {
        url: '/flashlight',
        templateUrl: 'app/flashlight/flashlight.html',
        controller: "FlashlightCtrl"
      })

      .state('geolocation', {
        url: '/geolocation',
        templateUrl: 'app/geolocation/geolocation.html',
        controller: "GeolocationCtrl"
      })

      .state('globalization', {
        url: '/global',
        templateUrl: 'app/globalization/globalization.html',
        controller: "GlobalizationCtrl"
      })

      .state('googleAnalytics', {
        url: '/googleAnalytics',
        templateUrl: 'app/googleAnalytics/googleAnalytics.html',
        controller: "GoogleAnalyticsCtrl"
      })

      .state('localNotification', {
        url: '/localNotification',
        templateUrl: 'app/localNotification/localNotification.html',
        controller: "LocalNotificationCtrl"
      })

      .state('media', {
        url: '/media',
        templateUrl: 'app/media/media.html',
        controller: "MediaCtrl"
      })

      .state('network', {
        url: '/network',
        templateUrl: 'app/network/network.html',
        controller: "NetworkCtrl"
      })

      .state('oauth', {
        url: '/oauth',
        templateUrl: 'app/oauth/oauth.html',
        controller: "OauthCtrl"
      })

      .state('preferences', {
        url: '/preferences',
        templateUrl: 'app/preferences/preferences.html',
        controller: "PreferencesCtrl"
      })

      .state('printer', {
        url: '/printer',
        templateUrl: 'app/printer/printer.html',
        controller: "PrinterCtrl"
      })

      .state('pushNotifications', {
        url: '/pushNotifications',
        templateUrl: 'app/pushNotifications/pushNotifications.html',
        controller: "PushNotificationsCtrl"
      })

      .state('socialSharing', {
        url: '/socialSharing',
        templateUrl: 'app/socialSharing/socialSharing.html',
        controller: "SocialSharingCtrl"
      })

      .state('sqlite', {
        url: '/sqlite',
        templateUrl: 'app/sqlite/sqlite.html',
        controller: "SqliteCtrl"
      })

      .state('statusbar', {
        url: '/statusbar',
        templateUrl: 'app/statusbar/statusbar.html',
        controller: "StatusbarCtrl"
      })

      .state('toast', {
        url: '/toast',
        templateUrl: 'app/toast/toast.html',
        controller: "ToastCtrl"
      })

      .state('touchid', {
        url: '/touchid',
        templateUrl: 'app/touchid/touchid.html',
        controller: "TouchIDCtrl"
      })

      .state('vibration', {
        url: '/vibration',
        templateUrl: 'app/vibration/vibration.html',
        controller: "VibrationCtrl"
      });

    $urlRouterProvider.otherwise('/menu');
  });
<commit_msg>created new route and import fileOpener2 dependencies<commit_after>angular.module('demo', [
  'ionic',
  'ngCordova',
  'ngCordova.plugins.fileOpener2',

  // modules
  // 'demo.adMob.ctrl',  // not working???
  'demo.appAvailability.ctrl',
  'demo.appRate.ctrl',
  'demo.barcodeScanner.ctrl',
  'demo.batteryStatus.ctrl',
  'demo.camera.ctrl',
  'demo.clipboard.ctrl',
  'demo.contacts.ctrl',
  'demo.datePicker.ctrl',
  'demo.device.ctrl',
  'demo.deviceMotion.ctrl',
  'demo.deviceOrientation.ctrl',
  'demo.dialogs.ctrl',
  'demo.facebook.ctrl',
  'demo.file.ctrl',
  'demo.fileOpener2.ctrl',
  'demo.flashlight.ctrl',
  'demo.geolocation.ctrl',
  'demo.globalization.ctrl',
  'demo.googleAnalytics.ctrl',
  'demo.localNotification.ctrl',
  'demo.media.ctrl',
  'demo.network.ctrl',
  'demo.oauth.ctrl',
  'demo.preferences.ctrl',
  'demo.printer.ctrl',
  'demo.pushNotifications.ctrl',
  'demo.socialSharing.ctrl',
  'demo.sqlite.ctrl',
  'demo.statusbar.ctrl',
  'demo.toast.ctrl',
  'demo.touchid.ctrl',
  'demo.vibration.ctrl'
])

  .run(function ($rootScope, $ionicPlatform, $cordovaNetwork, $cordovaBatteryStatus) {

    $ionicPlatform.ready(function () {
      if (window.cordova && window.cordova.plugins.Keyboard) {
        cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      }
      if (window.StatusBar) {
        StatusBar.styleDefault();
      }

      $cordovaNetwork.watchOffline();
      $cordovaNetwork.watchOnline();

      $rootScope.$on("networkOffline", function () {
        alert("Device is now Offline!");
      });

      $rootScope.$on("networkOnline", function () {
        alert("Device is Online!");
      });

      $cordovaBatteryStatus.$on("batterystatus", function (status) {
        alert("status :" + status);
      })
    })
  })

  .config(function ($stateProvider, $urlRouterProvider, $cordovaFacebookProvider) {

    if (!window.cordova) {
      var appID = 1234567890;
      var version = "v2.0"; // or leave blank and default is v2.0
      $cordovaFacebookProvider.browserInit(appID, version);
    }

    $stateProvider

      .state('menu', {
        url: "/menu",
        templateUrl: "app/menu.html"
      })

      .state('appAvailability', {
        url: '/appAvailability',
        templateUrl: 'app/appAvailability/appAvailability.html',
        controller: "AppAvailabilityCtrl"
      })

      .state('appRate', {
        url: '/appRate',
        templateUrl: 'app/appRate/appRate.html',
        controller: "AppRateCtrl"
      })

      .state('barcodeScanner', {
        url: '/barcodeScanner',
        templateUrl: 'app/barcodeScanner/barcodeScanner.html',
        controller: "BarcodeScannerCtrl"
      })

      .state('batteryStatus', {
        url: '/batteryStatus',
        templateUrl: 'app/batteryStatus/batteryStatus.html',
        controller: "BatteryStatusCtrl"
      })

      .state('camera', {
        url: '/camera',
        templateUrl: 'app/camera/camera.html',
        controller: "CameraCtrl"
      })

      .state('clipboard', {
        url: '/clipboard',
        templateUrl: 'app/clipboard/clipboard.html',
        controller: "ClipboardCtrl"
      })

      .state('contacts', {
        url: '/contacts',
        templateUrl: 'app/contacts/contacts.html',
        controller: "ContactsCtrl"
      })

      .state('datePicker', {
        url: '/datePicker',
        templateUrl: 'app/datePicker/datePicker.html',
        controller: "DatePickerCtrl"
      })

      .state('device', {
        url: '/device',
        templateUrl: 'app/device/device.html',
        controller: "DeviceCtrl"
      })

      .state('deviceMotion', {
        url: '/deviceMotion',
        templateUrl: 'app/deviceMotion/deviceMotion.html',
        controller: "DeviceMotionCtrl"
      })

      .state('deviceOrientation', {
        url: '/deviceOrientation',
        templateUrl: 'app/deviceOrientation/deviceOrientation.html',
        controller: "DeviceOrientationCtrl"
      })

      .state('dialogs', {
        url: '/dialogs',
        templateUrl: 'app/dialogs/dialogs.html',
        controller: "DialogsCtrl"
      })

      .state('facebook', {
        url: '/facebook',
        templateUrl: 'app/facebook/facebook.html',
        controller: "FacebookCtrl"
      })

      .state('file', {
        url: '/file',
        templateUrl: 'app/file/file.html',
        controller: "FileCtrl"
      })

      .state('fileOpener2', {
        url: '/fileOpener2',
        templateUrl: 'app/fileOpener2/fileOpener2.html',
        controller: "FileOpener2Ctrl"
      })

      .state('flashlight', {
        url: '/flashlight',
        templateUrl: 'app/flashlight/flashlight.html',
        controller: "FlashlightCtrl"
      })

      .state('geolocation', {
        url: '/geolocation',
        templateUrl: 'app/geolocation/geolocation.html',
        controller: "GeolocationCtrl"
      })

      .state('globalization', {
        url: '/global',
        templateUrl: 'app/globalization/globalization.html',
        controller: "GlobalizationCtrl"
      })

      .state('googleAnalytics', {
        url: '/googleAnalytics',
        templateUrl: 'app/googleAnalytics/googleAnalytics.html',
        controller: "GoogleAnalyticsCtrl"
      })

      .state('localNotification', {
        url: '/localNotification',
        templateUrl: 'app/localNotification/localNotification.html',
        controller: "LocalNotificationCtrl"
      })

      .state('media', {
        url: '/media',
        templateUrl: 'app/media/media.html',
        controller: "MediaCtrl"
      })

      .state('network', {
        url: '/network',
        templateUrl: 'app/network/network.html',
        controller: "NetworkCtrl"
      })

      .state('oauth', {
        url: '/oauth',
        templateUrl: 'app/oauth/oauth.html',
        controller: "OauthCtrl"
      })

      .state('preferences', {
        url: '/preferences',
        templateUrl: 'app/preferences/preferences.html',
        controller: "PreferencesCtrl"
      })

      .state('printer', {
        url: '/printer',
        templateUrl: 'app/printer/printer.html',
        controller: "PrinterCtrl"
      })

      .state('pushNotifications', {
        url: '/pushNotifications',
        templateUrl: 'app/pushNotifications/pushNotifications.html',
        controller: "PushNotificationsCtrl"
      })

      .state('socialSharing', {
        url: '/socialSharing',
        templateUrl: 'app/socialSharing/socialSharing.html',
        controller: "SocialSharingCtrl"
      })

      .state('sqlite', {
        url: '/sqlite',
        templateUrl: 'app/sqlite/sqlite.html',
        controller: "SqliteCtrl"
      })

      .state('statusbar', {
        url: '/statusbar',
        templateUrl: 'app/statusbar/statusbar.html',
        controller: "StatusbarCtrl"
      })

      .state('toast', {
        url: '/toast',
        templateUrl: 'app/toast/toast.html',
        controller: "ToastCtrl"
      })

      .state('touchid', {
        url: '/touchid',
        templateUrl: 'app/touchid/touchid.html',
        controller: "TouchIDCtrl"
      })

      .state('vibration', {
        url: '/vibration',
        templateUrl: 'app/vibration/vibration.html',
        controller: "VibrationCtrl"
      });

    $urlRouterProvider.otherwise('/menu');
  });
<|endoftext|>


<commit_before>var path = require('path');
var webpack = require('webpack');
var config = require('./webpack.config.js');

delete config.devtool;
delete config.watch;
delete config.plugins;
delete config.vue.loaders;

config.entry = {
    UiAlert: ['./src/UiAlert.vue'],
    UiAutocomplete: ['./src/UiAutocomplete.vue'],
    UiButton: ['./src/UiButton.vue'],
    UiCheckbox: ['./src/UiCheckbox.vue'],
    UiCollapsible: ['./src/UiCollapsible.vue'],
    UiConfirm: ['./src/UiConfirm.vue'],
    UiFab: ['./src/UiFab.vue'],
    UiIcon: ['./src/UiIcon.vue'],
    UiIconButton: ['./src/UiIconButton.vue'],
    UiMenu: ['./src/UiMenu.vue'],
    UiMenuItem: ['./src/UiMenuItem.vue'],
    UiModal: ['./src/UiModal.vue'],
    UiPopover: ['./src/UiPopover.vue'],
    UiPreloader: ['./src/UiPreloader.vue'],
    UiProgressCircular: ['./src/UiProgressCircular.vue'],
    UiProgressLinear: ['./src/UiProgressLinear.vue'],
    UiRadio: ['./src/UiRadio.vue'],
    UiRadioGroup: ['./src/UiRadioGroup.vue'],
    UiRating: ['./src/UiRating.vue'],
    UiRatingIcon: ['./src/UiRatingIcon.vue'],
    UiRatingPreview: ['./src/UiRatingPreview.vue'],
    UiRippleInk: ['./src/UiRippleInk.vue'],
    UiSnackbar: ['./src/UiSnackbar.vue'],
    UiSnackbarContainer: ['./src/UiSnackbarContainer.vue'],
    UiSwitch: ['./src/UiSwitch.vue'],
    UiTab: ['./src/UiTab.vue'],
    UiTabs: ['./src/UiTabs.vue'],
    UiTextbox: ['./src/UiTextbox.vue'],
    UiToolbar: ['./src/UiToolbar.vue'],
    UiTooltip: ['./src/UiTooltip.vue']
};

config.plugins = [
    new webpack.BannerPlugin(config.banner, {
        raw: true,
        entryOnly: true
    }),

    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: '"production"'
        }
    }),

    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),

    new webpack.optimize.OccurenceOrderPlugin()
];

config.output = {
    path: path.join(__dirname, 'lib'),
    filename: '[name].js',
    library: ['Keen', '[name]'],
    libraryTarget: 'umd'
};

module.exports = config;
<commit_msg>Add UiSlider to lib webpack config<commit_after>var path = require('path');
var webpack = require('webpack');
var config = require('./webpack.config.js');

delete config.devtool;
delete config.watch;
delete config.plugins;
delete config.vue.loaders;

config.entry = {
    UiAlert: ['./src/UiAlert.vue'],
    UiAutocomplete: ['./src/UiAutocomplete.vue'],
    UiButton: ['./src/UiButton.vue'],
    UiCheckbox: ['./src/UiCheckbox.vue'],
    UiCollapsible: ['./src/UiCollapsible.vue'],
    UiConfirm: ['./src/UiConfirm.vue'],
    UiFab: ['./src/UiFab.vue'],
    UiIcon: ['./src/UiIcon.vue'],
    UiIconButton: ['./src/UiIconButton.vue'],
    UiMenu: ['./src/UiMenu.vue'],
    UiMenuItem: ['./src/UiMenuItem.vue'],
    UiModal: ['./src/UiModal.vue'],
    UiPopover: ['./src/UiPopover.vue'],
    UiPreloader: ['./src/UiPreloader.vue'],
    UiProgressCircular: ['./src/UiProgressCircular.vue'],
    UiProgressLinear: ['./src/UiProgressLinear.vue'],
    UiRadio: ['./src/UiRadio.vue'],
    UiRadioGroup: ['./src/UiRadioGroup.vue'],
    UiRating: ['./src/UiRating.vue'],
    UiRatingIcon: ['./src/UiRatingIcon.vue'],
    UiRatingPreview: ['./src/UiRatingPreview.vue'],
    UiRippleInk: ['./src/UiRippleInk.vue'],
    UiSlider: ['./src/UiSlider.vue'],
    UiSnackbar: ['./src/UiSnackbar.vue'],
    UiSnackbarContainer: ['./src/UiSnackbarContainer.vue'],
    UiSwitch: ['./src/UiSwitch.vue'],
    UiTab: ['./src/UiTab.vue'],
    UiTabs: ['./src/UiTabs.vue'],
    UiTextbox: ['./src/UiTextbox.vue'],
    UiToolbar: ['./src/UiToolbar.vue'],
    UiTooltip: ['./src/UiTooltip.vue']
};

config.plugins = [
    new webpack.BannerPlugin(config.banner, {
        raw: true,
        entryOnly: true
    }),

    new webpack.DefinePlugin({
        'process.env': {
            NODE_ENV: '"production"'
        }
    }),

    new webpack.optimize.UglifyJsPlugin({
        compress: {
            warnings: false
        }
    }),

    new webpack.optimize.OccurenceOrderPlugin()
];

config.output = {
    path: path.join(__dirname, 'lib'),
    filename: '[name].js',
    library: ['Keen', '[name]'],
    libraryTarget: 'umd'
};

module.exports = config;
<|endoftext|>


<commit_before>// @flow
/* eslint-disable class-methods-use-this */
import * as React from "react";
import ReactDOM from "react-dom";

import { of } from "rxjs/observable/of";
import { fromEvent } from "rxjs/observable/fromEvent";
import type { Subscription } from "rxjs";
import { switchMap } from "rxjs/operators";

import { Map as ImmutableMap } from "immutable";

import { RichestMime } from "@nteract/display-area";

import { debounce, merge } from "lodash";

export type { EditorChange, Options };

import "monaco-editor/esm/vs/editor/browser/controller/coreCommands.js";
import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

function normalizeLineEndings(str) {
  if (!str) return str;
  return str.replace(/\r\n|\r/g, "\n");
}

export type MonacoEditorProps = {
  editorFocused: boolean,
  theme: string,
  channels: ?any,
  // TODO: We only check if this is idle, so the completion provider should only
  //       care about this when kernelStatus === idle _and_ we're the active cell
  //       could instead call it `canTriggerCompletion` and reduce our current re-renders
  kernelStatus: string,
  onChange: (value: string, change: EditorChange) => void,
  onFocusChange: ?(focused: boolean) => void,
  value: string,
  defaultValue?: string,
  options: Options
};

type MonacoEditorState = {
  isFocused: boolean
};

class MonacoEditor extends React.Component<
  MonacoEditorProps,
  MonacoEditorState
> {
  executeTab: (editor: Object) => void;
  keyupEventsSubscriber: Subscription;

  static defaultProps = {
    onChange: null,
    onFocusChange: null
  };

  constructor(props: MonacoEditorProps): void {
    super(props);
    this.state = { isFocused: true, tipElement: null };
  }

  componentWillMount() {
    (this: any).componentWillReceiveProps = debounce(
      this.componentWillReceiveProps,
      0
    );
  }

  componentDidMount(): void {
    const { editorFocused, kernelStatus, focusAbove, focusBelow } = this.props;
    window.MonacoEnvironment = {
      getWorkerUrl: function(moduleId, label) {
        return "./editor.worker.bundle.js";
      }
    };
    console.log(this);
    this.monaco = monaco.editor.create(this.monacoContainer, {
      value: this.props.value
    });
  }

  componentDidUpdate(prevProps: MonacoEditorProps): void {
    if (!this.monaco) return;
  }

  componentWillReceiveProps(nextProps: MonacoEditorProps) {
    console.log(nextProps);
    if (
      this.monaco &&
      nextProps.value !== undefined &&
      normalizeLineEndings(this.cm.getValue()) !==
        normalizeLineEndings(nextProps.value)
    ) {
      if (this.props.options.preserveScrollPosition) {
        var prevScrollPosition = this.cm.getScrollInfo();
        this.cm.setValue(nextProps.value);
        this.cm.scrollTo(prevScrollPosition.left, prevScrollPosition.top);
      } else {
        this.cm.setValue(nextProps.value);
      }
    }
    if (typeof nextProps.options === "object") {
      for (let optionName in nextProps.options) {
        if (
          nextProps.options.hasOwnProperty(optionName) &&
          this.props.options[optionName] === nextProps.options[optionName]
        ) {
          this.cm.setOption(optionName, nextProps.options[optionName]);
        }
      }
    }
  }

  componentWillUnmount() {
    // TODO: is there a lighter weight way to remove the codemirror instance?
    if (this.cm) {
      this.cm.toTextArea();
    }
    this.keyupEventsSubscriber.unsubscribe();
  }

  focusChanged(focused: boolean) {
    this.setState({
      isFocused: focused
    });
    this.props.onFocusChange && this.props.onFocusChange(focused);
  }

  render(): React$Element<any> {
    return (
      <div
        className="monaco cm-s-composition"
        ref={container => {
          this.monacoContainer = container;
        }}
      />
    );
  }
}

export default MonacoEditor;
<commit_msg>Save file changes with Monaco Editor<commit_after>// @flow
/* eslint-disable class-methods-use-this */
import * as React from "react";
import ReactDOM from "react-dom";

import { of } from "rxjs/observable/of";
import { fromEvent } from "rxjs/observable/fromEvent";
import type { Subscription } from "rxjs";
import { switchMap } from "rxjs/operators";

import { Map as ImmutableMap } from "immutable";

import { RichestMime } from "@nteract/display-area";

import { debounce, merge } from "lodash";

export type { EditorChange, Options };

import "monaco-editor/esm/vs/editor/standalone/browser/accessibilityHelp/accessibilityHelp.js";
import "monaco-editor/esm/vs/editor/contrib/find/findController.js";
import "monaco-editor/esm/vs/editor/browser/controller/coreCommands.js";

import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";

function normalizeLineEndings(str) {
  if (!str) return str;
  return str.replace(/\r\n|\r/g, "\n");
}

export type MonacoEditorProps = {
  editorFocused: boolean,
  theme: string,
  channels: ?any,
  // TODO: We only check if this is idle, so the completion provider should only
  //       care about this when kernelStatus === idle _and_ we're the active cell
  //       could instead call it `canTriggerCompletion` and reduce our current re-renders
  kernelStatus: string,
  onChange: (value: string, change: EditorChange) => void,
  onFocusChange: ?(focused: boolean) => void,
  value: string,
  defaultValue?: string,
  options: Options
};

type MonacoEditorState = {
  isFocused: boolean
};

class MonacoEditor extends React.Component<
  MonacoEditorProps,
  MonacoEditorState
> {
  executeTab: (editor: Object) => void;
  keyupEventsSubscriber: Subscription;

  static defaultProps = {
    onChange: null,
    onFocusChange: null
  };

  constructor(props: MonacoEditorProps): void {
    super(props);
    this.state = { isFocused: true, tipElement: null };
  }

  componentWillMount() {
    (this: any).componentWillReceiveProps = debounce(
      this.componentWillReceiveProps,
      0
    );
  }

  onDidChangeModelContent(e): void {
    this.props.onChange(this.monaco.getValue());
  }
  componentDidMount(): void {
    const { editorFocused, kernelStatus, focusAbove, focusBelow } = this.props;
    window.MonacoEnvironment = {
      getWorkerUrl: function(moduleId, label) {
        return "./editor.worker.bundle.js";
      }
    };
    console.log(this);
    this.monaco = monaco.editor.create(this.monacoContainer, {
      value: this.props.value,
      language: "python",
      minimap: {
        enabled: false
      }
    });

    this.monaco.onDidChangeModelContent(
      this.onDidChangeModelContent.bind(this)
    );
  }

  componentDidUpdate(prevProps: MonacoEditorProps): void {
    if (!this.monaco) return;
  }

  componentWillReceiveProps(nextProps: MonacoEditorProps) {
    console.log(nextProps);
    if (
      this.monaco &&
      nextProps.value !== undefined &&
      normalizeLineEndings(this.cm.getValue()) !==
        normalizeLineEndings(nextProps.value)
    ) {
      if (this.props.options.preserveScrollPosition) {
        var prevScrollPosition = this.cm.getScrollInfo();
        this.cm.setValue(nextProps.value);
        this.cm.scrollTo(prevScrollPosition.left, prevScrollPosition.top);
      } else {
        this.cm.setValue(nextProps.value);
      }
    }
    if (typeof nextProps.options === "object") {
      for (let optionName in nextProps.options) {
        if (
          nextProps.options.hasOwnProperty(optionName) &&
          this.props.options[optionName] === nextProps.options[optionName]
        ) {
          this.cm.setOption(optionName, nextProps.options[optionName]);
        }
      }
    }
  }

  componentWillUnmount() {
    // TODO: is there a lighter weight way to remove the codemirror instance?
    if (this.cm) {
      this.cm.toTextArea();
    }
    this.keyupEventsSubscriber.unsubscribe();
  }

  focusChanged(focused: boolean) {
    this.setState({
      isFocused: focused
    });
    this.props.onFocusChange && this.props.onFocusChange(focused);
  }

  render(): React$Element<any> {
    return (
      <div
        className="monaco cm-s-composition"
        ref={container => {
          this.monacoContainer = container;
        }}
      />
    );
  }
}

export default MonacoEditor;
<|endoftext|>


<commit_before><commit_msg>absolute layout<commit_after><|endoftext|>


<commit_before>
function Genre(name) {
    this.name = name
    this.items = []

    this.sortItems = function(items) {
        return _.sortBy(items, function(item){
            var badgesSortFactor = _.reduce(item.dict.awards, function(memo, award){
                return memo + ((award.isHighly) ? 10 : 1)
            }, 0)
            return badgesSortFactor
        }).reverse()
    }

    this.render = function(){
        this.items = this.sortItems(this.items)

        var genre$ = $(ich.genreTemplate({name:this.name}, true))

        var renderedItems = []
        var itemsWithoutActivity = []
        for (var i=0;i<this.items.length;i++){
            var thisItem = this.items[i]
            if (thisItem.dict.awards.length) {
                renderedItems.push(thisItem.render())
            }
            else {
                itemsWithoutActivity.push(thisItem.render())
            }
        }
        genre$.find("ul.items.active").append(renderedItems)
        genre$.find("ul.items.inactive").append(itemsWithoutActivity)
        if (itemsWithoutActivity.length) {
            genre$.find("h4.plus-more")
                .toggle(
                    function(){
                        $(this).addClass("showing").siblings("ul.items.inactive").slideDown()
                        $(this).find("span.show-hide").html("(hide)")
                    },
                    function() {
                        $(this).removeClass("showing").siblings("ul.items.inactive").slideUp()
                        $(this).find("span.show-hide").html("(show)")
                    }
                )
                .find("span.value")
                .html(itemsWithoutActivity.length)
        }
        else {
            genre$.find("h4.plus-more").hide()
        }

        return genre$
    }
    return true
}

function GenreList(items) {
    var itemGroupsByGenre = _.groupBy(items, function(item) {
        return item.dict.biblio.genre
    })
    this.genres = _.map(itemGroupsByGenre, function(items, genreName){
        var genre = new Genre(genreName)
        genre.items = items
        return genre
    })

    this.render = function(){

        var renderedGenres = _.chain(this.genres)
            .sortBy("name")
            .map(function(genre){
                return genre.render()
            })
            .value()

        $("div.genre").remove()
        $("div.tooltip").remove() // otherwise tooltips from removed badges stick around
        $("#metrics div.wrapper").append(renderedGenres)
    }
}

function Coll(collViews){
    this.views = collViews;
    this.id = null
    this.items = {}

    this.addItemsFromDicts = function(newItemDicts) {
        for (var i=0; i<newItemDicts.length; i++) {
            var tiid = newItemDicts[i]["_id"]
            this.items[tiid] = new Item(newItemDicts[i], new ItemView($), $)
        }
    }

    this.create = function(aliases, title) {
        /*
        *   Make a new collection. On success, add it to the user's list of colls,
        *   and redirect to the webapp's /collection/<cid> report page.
         */

        // @todo: remove. this is no longer used, as coll being created on server.

        var that = this
        var requestObj = {
            aliases: aliases,
            title:title
        }

        console.log("making the collection now.")
        $.ajax({
                   url: api_root+'/collection',
                   type: "POST",
                   dataType: "json",
                   contentType: "application/json; charset=utf-8",
                   data:  JSON.stringify(requestObj),
                   success: function(data){
                       console.log("finished making the collection!")
                       var cid=data.collection._id

                       ISCookies.lastActionUserDidToCollection("create")

                       // you could pass this in, but you pretty much only want it to redirect:
                       var redirect = function(){location.href = "/collection/" + cid}
                   }
               })
    }

    this.read = function(interval, lastCollAction, startTime) {
        console.log("reading collection")
        var startTime = startTime || new Date()

        var thisThing = this
        this.views.startUpdating()

        $.ajax({
            url: api_root+'/v1/collection/'+thisThing.id+'?key='+api_key,
            type: "GET",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            statusCode: {
               210: function(data){
                   console.log("still updating")
                   thisThing.title = data.title
                   thisThing.alias_tiids = data.alias_tiids
                   thisThing.addItemsFromDicts(data.items)

                   thisThing.render.call(thisThing)

                   var elapsedSeconds = (new Date() - startTime)/1000
                   if (elapsedSeconds > 60) { // give up after 1 minute...
                        console.log("failed to finish update; giving up after 1 minute")

                        analytics.track("Timed out profile load", {
                            "seconds": elapsedSeconds,
                            "collection id": thisThing.id,
                            "number products": data.items.length,
                            "prev collection action": lastCollAction
                        })

                   thisThing.views.finishUpdating(thisThing.items, "error")

                   }
                   else {
                       console.log("trying again, so far " + elapsedSeconds + " seconds")
                       setTimeout(function(){
                           thisThing.read(interval, lastCollAction, startTime)
                       }, interval)
                   }
               },
               200: function(data) {
                   console.log("collection done updating")
                   console.log("sending the last collection action to analytics: ", lastCollAction)

                   var elapsedSeconds = (new Date() - startTime)/1000
                   analytics.track("Completed profile load", {
                        "seconds": elapsedSeconds,
                        "collection id": thisThing.id,
                        "number products": data.items.length,
                        "prev collection action": lastCollAction

                    })

                   thisThing.alias_tiids = data.alias_tiids
                   thisThing.title = data.title
                   thisThing.addItemsFromDicts(data.items)

                   thisThing.render.call(thisThing)
                   thisThing.views.finishUpdating(thisThing.items, "ready")

                   return false;
               },
               404: function(){
                   // add this later when the collection create call is asynch on the server.
                   console.log("got a 404; the collection hasn't been created yet. That's ok, trying again.")
               }
            }
        });
    }

    this.updateTitle = function(newTitle){
        // implement later.
    }

    this.deleteItem = function(tiidToDelete, callbacks) {
        callbacks.start()
        this.update({"tiids": [tiidToDelete]}, "DELETE", callbacks.success)
        return false
    }

    this.addItems = function(itemsToAdd, callbacks) {
        if (!this.userCanEdit(callbacks)) return false
        ISCookies.lastActionUserDidToCollection("add_products")

        this.update({"aliases": itemsToAdd}, "PUT", callbacks.onSuccess)
    }

    this.update = function(payload, httpType, onSuccess){
        /* note this is NOT the same as refreshing metrics on items; it's just
        updating things about the collection itself, like number of items or title.
        See this.refreshItemData() for the former case.
         */

        var url = webapp_root+'/user/'+impactstoryUserId+'/products?'
            + 'api_admin_key='+api_key

        $.ajax({
                   url: url,
                   type: httpType,
                   dataType: "json",
                   contentType: "application/json; charset=utf-8",
                   data:  JSON.stringify(payload),
                   success: function(data){
                       console.log("finished updating the collection!")
                       onSuccess(data)
                   }
               })
    }

    this.refreshItemData = function() {
        var thisThing = this
        this.views.startUpdating()
        $.ajax({
            url: api_root+'/v1/collection/'+this.id+'?key='+api_key,
            type: "POST",
            success: function(data){
               console.log("refreshing collection.")
               thisThing.read(1000, "refresh");
            }});
        }

    this.userCanEdit = function(callbacks){
        // @todo make it so this figures out  status based on vars loaded server-side

        if (!$("body").hasClass("logged-in")) {
            callbacks.onNotLoggedIn()
            return false
        }

        if (!$("body").hasClass("can-edit")) {
            callbacks.onNotOwner()
            return false
        }
        return true
    }

    this.render = function(){
        this.views.renderItems(this.items)
//        this.views.renderTitle(this.title)

    }
}

function CollViews() {
    this.startUpdating = function(){
        $("img.loading").remove()

        $("body.report h2").before(ajaxLoadImg)
        changeElemState(
            $("body.user-profile #num-items"),
            "working"
        )
    }

    this.badgesWeight = function(dict) {
        return _.reduce(dict.awards, function(memo, metric){
            return memo + (metric.isHighly) ? 10 : 1
        }, 0)
    }

    // state is "ready" or "error"  (error if timed out while still loading)
    this.finishUpdating = function(items, state){
        // setup page header
        $("#page-header img").remove()
        changeElemState(
            $("body.user-profile #num-items"),
            state
        )

        console.log("number of items in collection:", _.size(items))
        $("#num-items span.value").text(_.size(items))

        // setup item-level zooming
        $("ul.active li.item div.item-header").addClass("zoomable")
        $("a.item-expand-button")
            .show()
            .css({color: tiLinkColor})
            .fadeOut(1500, function(){
                $(this).removeAttr("style")
            })
    }

    this.renderItems = function(itemObjsDict) {
        var itemObjs = _.values(itemObjsDict)
        var genreList = new GenreList(itemObjs)
        genreList.render()

    }

    this.renderIsEditable = function(isEditable) {
        if (isEditable){
            $("div#report").addClass("editable")
        }
    }

    this.onEditNotOwner = function(){
        $("#edit-not-owner").modal("show")
    }

    this.onEditNotLoggedIn = function() {
        $("#edit-not-logged-in").modal("show")
    }
}

function CollController(coll, collViews) {
    this.coll = coll
    this.collViews = collViews

    this.collReportPageInit = function() {
        this.coll.id = reportId // global loaded by the server
        this.coll.render()

        this.coll.read(1000, ISCookies.lastActionUserDidToCollection()+"")
        ISCookies.lastActionUserDidToCollection(null)
        var that = this

        // refresh all the items
        $("#update-report-button").click(function(){
            analytics.track("Clicked refresh button")
            coll.refreshItemData();
            return false;
        })

        // show/hide all zoom divs
        $("div#num-items a").toggle(
            function(){
                $(this).html("(collapse all)")
                $("li.item").not(".no-data").addClass("zoomed").find("div.zoom").show()
            },
            function(){
                $(this).html("(expand all)")
                $("li.item").not(".no-data").removeClass("zoomed").find("div.zoom").hide()
            }
        )

        // show the import-products dialog when you ask for it
        $("#import-products-button").click(function(){
            var callbacks = {
                onNotLoggedIn: that.collViews.onEditNotLoggedIn,
                onNotOwner: that.collViews.onEditNotOwner
            }
            if (!that.coll.userCanEdit(callbacks)) return false
            $("#import-products-modal").modal("show")
            return false
        })

        // delete items
        $("a.item-delete-button").live("click", function(){
            var item$ = $(this).parents("li.item")

            var callbacks = {
                onNotLoggedIn: that.collViews.onEditNotLoggedIn,
                onNotOwner: that.collViews.onEditNotOwner
            }

            if (!that.coll.userCanEdit(callbacks)) return false

            var callbacks2 = {
                start: function() {item$.slideUp();},
                success: function(data){
                    console.log("deleted, done. blam.", data)
                    $("#num-items span.value").text(_.size(data.alias_tiids))
                },
                onNotLoggedIn: that.collViews.onEditNotLoggedIn,
                onNotOwner: that.collViews.onEditNotOwner
            }

            that.coll.deleteItem( item$.attr("id"), callbacks2)
            return false;
        })
    }

}
<commit_msg>Move ti-coll 210 callback out into function.<commit_after>
function Genre(name) {
    this.name = name
    this.items = []

    this.sortItems = function(items) {
        return _.sortBy(items, function(item){
            var badgesSortFactor = _.reduce(item.dict.awards, function(memo, award){
                return memo + ((award.isHighly) ? 10 : 1)
            }, 0)
            return badgesSortFactor
        }).reverse()
    }

    this.render = function(){
        this.items = this.sortItems(this.items)

        var genre$ = $(ich.genreTemplate({name:this.name}, true))

        var renderedItems = []
        var itemsWithoutActivity = []
        for (var i=0;i<this.items.length;i++){
            var thisItem = this.items[i]
            if (thisItem.dict.awards.length) {
                renderedItems.push(thisItem.render())
            }
            else {
                itemsWithoutActivity.push(thisItem.render())
            }
        }
        genre$.find("ul.items.active").append(renderedItems)
        genre$.find("ul.items.inactive").append(itemsWithoutActivity)
        if (itemsWithoutActivity.length) {
            genre$.find("h4.plus-more")
                .toggle(
                    function(){
                        $(this).addClass("showing").siblings("ul.items.inactive").slideDown()
                        $(this).find("span.show-hide").html("(hide)")
                    },
                    function() {
                        $(this).removeClass("showing").siblings("ul.items.inactive").slideUp()
                        $(this).find("span.show-hide").html("(show)")
                    }
                )
                .find("span.value")
                .html(itemsWithoutActivity.length)
        }
        else {
            genre$.find("h4.plus-more").hide()
        }

        return genre$
    }
    return true
}

function GenreList(items) {
    var itemGroupsByGenre = _.groupBy(items, function(item) {
        return item.dict.biblio.genre
    })
    this.genres = _.map(itemGroupsByGenre, function(items, genreName){
        var genre = new Genre(genreName)
        genre.items = items
        return genre
    })

    this.render = function(){

        var renderedGenres = _.chain(this.genres)
            .sortBy("name")
            .map(function(genre){
                return genre.render()
            })
            .value()

        $("div.genre").remove()
        $("div.tooltip").remove() // otherwise tooltips from removed badges stick around
        $("#metrics div.wrapper").append(renderedGenres)
    }
}

function Coll(collViews){
    this.views = collViews;
    this.id = null
    this.items = {}

    this.addItemsFromDicts = function(newItemDicts) {
        for (var i=0; i<newItemDicts.length; i++) {
            var tiid = newItemDicts[i]["_id"]
            this.items[tiid] = new Item(newItemDicts[i], new ItemView($), $)
        }
    }

    this.create = function(aliases, title) {
        /*
        *   Make a new collection. On success, add it to the user's list of colls,
        *   and redirect to the webapp's /collection/<cid> report page.
         */

        // @todo: remove. this is no longer used, as coll being created on server.

        var that = this
        var requestObj = {
            aliases: aliases,
            title:title
        }

        console.log("making the collection now.")
        $.ajax({
                   url: api_root+'/collection',
                   type: "POST",
                   dataType: "json",
                   contentType: "application/json; charset=utf-8",
                   data:  JSON.stringify(requestObj),
                   success: function(data){
                       console.log("finished making the collection!")
                       var cid=data.collection._id

                       ISCookies.lastActionUserDidToCollection("create")

                       // you could pass this in, but you pretty much only want it to redirect:
                       var redirect = function(){location.href = "/collection/" + cid}
                   }
               })
    }

    this.read = function(interval, lastCollAction, startTime) {
        console.log("reading collection")
        var startTime = startTime || new Date()

        var thisThing = this
        this.views.startUpdating()

        var incompleteAnswerCallback = function(data){
            console.log("still updating")
            thisThing.title = data.title
            thisThing.alias_tiids = data.alias_tiids
            thisThing.addItemsFromDicts(data.items)

            thisThing.render.call(thisThing)

            var elapsedSeconds = (new Date() - startTime)/1000
            if (elapsedSeconds > 60) { // give up after 1 minute...
                console.log("failed to finish update; giving up after 1 minute")

                analytics.track("Timed out profile load", {
                    "seconds": elapsedSeconds,
                    "collection id": thisThing.id,
                    "number products": data.items.length,
                    "prev collection action": lastCollAction
                })

                thisThing.views.finishUpdating(thisThing.items, "error")

            }
            else {
                console.log("trying again, so far " + elapsedSeconds + " seconds")
                setTimeout(function(){
                    thisThing.read(interval, lastCollAction, startTime)
                }, interval)
            }
        }

        $.ajax({
            url: api_root+'/v1/collection/'+thisThing.id+'?key='+api_key,
            type: "GET",
            dataType: "json",
            contentType: "application/json; charset=utf-8",
            statusCode: {
               210: function(data){
                    incompleteAnswerCallback(data)
               },
               200: function(data) {
                   console.log("collection done updating")
                   console.log("sending the last collection action to analytics: ", lastCollAction)

                   var elapsedSeconds = (new Date() - startTime)/1000
                   analytics.track("Completed profile load", {
                        "seconds": elapsedSeconds,
                        "collection id": thisThing.id,
                        "number products": data.items.length,
                        "prev collection action": lastCollAction

                    })

                   thisThing.alias_tiids = data.alias_tiids
                   thisThing.title = data.title
                   thisThing.addItemsFromDicts(data.items)

                   thisThing.render.call(thisThing)
                   thisThing.views.finishUpdating(thisThing.items, "ready")

                   return false;
               },
               404: function(){
                   // add this later when the collection create call is asynch on the server.
                   console.log("got a 404; the collection hasn't been created yet. That's ok, trying again.")
               }
            }
        });
    }

    this.updateTitle = function(newTitle){
        // implement later.
    }

    this.deleteItem = function(tiidToDelete, callbacks) {
        callbacks.start()
        this.update({"tiids": [tiidToDelete]}, "DELETE", callbacks.success)
        return false
    }

    this.addItems = function(itemsToAdd, callbacks) {
        if (!this.userCanEdit(callbacks)) return false
        ISCookies.lastActionUserDidToCollection("add_products")

        this.update({"aliases": itemsToAdd}, "PUT", callbacks.onSuccess)
    }

    this.update = function(payload, httpType, onSuccess){
        /* note this is NOT the same as refreshing metrics on items; it's just
        updating things about the collection itself, like number of items or title.
        See this.refreshItemData() for the former case.
         */

        var url = webapp_root+'/user/'+impactstoryUserId+'/products?'
            + 'api_admin_key='+api_key

        $.ajax({
                   url: url,
                   type: httpType,
                   dataType: "json",
                   contentType: "application/json; charset=utf-8",
                   data:  JSON.stringify(payload),
                   success: function(data){
                       console.log("finished updating the collection!")
                       onSuccess(data)
                   }
               })
    }

    this.refreshItemData = function() {
        var thisThing = this
        this.views.startUpdating()
        $.ajax({
            url: api_root+'/v1/collection/'+this.id+'?key='+api_key,
            type: "POST",
            success: function(data){
               console.log("refreshing collection.")
               thisThing.read(1000, "refresh");
            }});
        }

    this.userCanEdit = function(callbacks){
        // @todo make it so this figures out  status based on vars loaded server-side

        if (!$("body").hasClass("logged-in")) {
            callbacks.onNotLoggedIn()
            return false
        }

        if (!$("body").hasClass("can-edit")) {
            callbacks.onNotOwner()
            return false
        }
        return true
    }

    this.render = function(){
        this.views.renderItems(this.items)
//        this.views.renderTitle(this.title)

    }
}

function CollViews() {
    this.startUpdating = function(){
        $("img.loading").remove()

        $("body.report h2").before(ajaxLoadImg)
        changeElemState(
            $("body.user-profile #num-items"),
            "working"
        )
    }

    this.badgesWeight = function(dict) {
        return _.reduce(dict.awards, function(memo, metric){
            return memo + (metric.isHighly) ? 10 : 1
        }, 0)
    }

    // state is "ready" or "error"  (error if timed out while still loading)
    this.finishUpdating = function(items, state){
        // setup page header
        $("#page-header img").remove()
        changeElemState(
            $("body.user-profile #num-items"),
            state
        )

        console.log("number of items in collection:", _.size(items))
        $("#num-items span.value").text(_.size(items))

        // setup item-level zooming
        $("ul.active li.item div.item-header").addClass("zoomable")
        $("a.item-expand-button")
            .show()
            .css({color: tiLinkColor})
            .fadeOut(1500, function(){
                $(this).removeAttr("style")
            })
    }

    this.renderItems = function(itemObjsDict) {
        var itemObjs = _.values(itemObjsDict)
        var genreList = new GenreList(itemObjs)
        genreList.render()

    }

    this.renderIsEditable = function(isEditable) {
        if (isEditable){
            $("div#report").addClass("editable")
        }
    }

    this.onEditNotOwner = function(){
        $("#edit-not-owner").modal("show")
    }

    this.onEditNotLoggedIn = function() {
        $("#edit-not-logged-in").modal("show")
    }
}

function CollController(coll, collViews) {
    this.coll = coll
    this.collViews = collViews

    this.collReportPageInit = function() {
        this.coll.id = reportId // global loaded by the server
        this.coll.render()

        this.coll.read(1000, ISCookies.lastActionUserDidToCollection()+"")
        ISCookies.lastActionUserDidToCollection(null)
        var that = this

        // refresh all the items
        $("#update-report-button").click(function(){
            analytics.track("Clicked refresh button")
            coll.refreshItemData();
            return false;
        })

        // show/hide all zoom divs
        $("div#num-items a").toggle(
            function(){
                $(this).html("(collapse all)")
                $("li.item").not(".no-data").addClass("zoomed").find("div.zoom").show()
            },
            function(){
                $(this).html("(expand all)")
                $("li.item").not(".no-data").removeClass("zoomed").find("div.zoom").hide()
            }
        )

        // show the import-products dialog when you ask for it
        $("#import-products-button").click(function(){
            var callbacks = {
                onNotLoggedIn: that.collViews.onEditNotLoggedIn,
                onNotOwner: that.collViews.onEditNotOwner
            }
            if (!that.coll.userCanEdit(callbacks)) return false
            $("#import-products-modal").modal("show")
            return false
        })

        // delete items
        $("a.item-delete-button").live("click", function(){
            var item$ = $(this).parents("li.item")

            var callbacks = {
                onNotLoggedIn: that.collViews.onEditNotLoggedIn,
                onNotOwner: that.collViews.onEditNotOwner
            }

            if (!that.coll.userCanEdit(callbacks)) return false

            var callbacks2 = {
                start: function() {item$.slideUp();},
                success: function(data){
                    console.log("deleted, done. blam.", data)
                    $("#num-items span.value").text(_.size(data.alias_tiids))
                },
                onNotLoggedIn: that.collViews.onEditNotLoggedIn,
                onNotOwner: that.collViews.onEditNotOwner
            }

            that.coll.deleteItem( item$.attr("id"), callbacks2)
            return false;
        })
    }

}
<|endoftext|>


<commit_before>var XEncoder;

XEncoder = (function () {
    'use strict';

    var defaultChars,
        charsetLength,
        XEncoder,
        getEncodingLength,
        encode,
        decode,
        toString,
        toCharCodes,
        validateString,
        validateCharCodes;

    defaultChars = '+/'
        + '0123456789'
        + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        + 'abcdefghijklmnopqrstuvwxyz';

    XEncoder = function XEncoder(chars) {
        var charString,
            delimiter,
            patternString,
            pattern,
            context;

        charString = chars
        || defaultChars;

        delimiter = '='
            + charsetLength
            + '=';

        patternString = '^(['
            + charString.replace(/(\[|\])/g, '\\$1')
            + ']+)=(\\d+)=$';

        pattern = new RegExp(patternString);

        context = {
            chars: charString,
            delimiter: delimiter,
            pattern: pattern,
            encodingLength: getEncodingLength(charString.length)
        };

        return {
            encode: encode.bind(context, validateCharCodes.bind(context)),
            decode: decode.bind(context, validateString.bind(context))
        };
    };

    getEncodingLength = function getEncodingLength(charsLength) {
        var encodingLength,
            rest;

        encodingLength = 0;

        rest = charsetLength - 1;

        for (; rest!== 0; encodingLength += 1) {
            rest = (rest - rest % charsLength) / charsLength;
        }

        return encodingLength;
    };

    encode = function encode(validate, data) {
        var chars,
            delimiter,
            encodingLength,
            charsLength,
            encodedData,
            dataIndex,
            dataLength,
            charCodes,
            charCode,
            encodedChar,
            rest;

        chars = this.chars;
        delimiter = this.delimiter;
        encodingLength = this.encodingLength;
        charsLength = chars.length;
        encodedData = '';
        dataIndex = 0;
        dataLength = data.length;

        charCodes = toCharCodes(data);

        validate(charCodes);

        for (; dataIndex < dataLength; dataIndex += 1) {
            charCode = charCodes[dataIndex];
            encodedChar = '';

            while (encodedChar.length < encodingLength) {
                rest = charCode % charsLength;
                charCode = (charCode - rest) / charsLength;
                encodedChar = chars.charAt(rest) + encodedChar;
            }

            encodedData += encodedChar;
        }

        encodedData += delimiter;

        return encodedData;
    };

    decode = function decode(validate, data) {
        var chars,
            delimiter,
            encodingLength,
            charsLength,
            charCodes,
            dataIndex,
            dataLength,
            charCode,
            charIndex,
            encodedChar,
            rest,
            decodedData;

        validate(data);

        chars = this.chars;
        delimiter = this.delimiter;
        encodingLength = this.encodingLength;
        charsLength = chars.length;
        charCodes = [];
        dataIndex = 0;
        dataLength = data.length - delimiter.length;

        for (; dataIndex < dataLength; dataIndex += encodingLength) {
            charCode = 0;
            charIndex = 0;

            for (; charIndex < encodingLength; charIndex += 1) {
                rest = chars.indexOf(data[dataIndex + charIndex]);

                charCode = rest * Math.pow(
                    charsLength,
                    encodingLength - charIndex - 1
                ) + charCode;
            }

            charCodes.push(charCode);
        }

        decodedData = toString(charCodes);

        return decodedData;
    };

    toString = (function () {
        var fromCharCode,
            toStr,
            toString;

        fromCharCode = String.fromCharCode;

        toStr = fromCharCode.apply.bind(fromCharCode, String);

        toString = function toString(data) {
            var isArray,
                charCodes,
                str;

            isArray = data instanceof Array;

            charCodes = isArray
                ? data
                : arguments;

            str = toStr(charCodes);

            return str;
        };

        return toString;
    }());

    toCharCodes = (function () {
        var charCodeAt,
            toCharCode,
            toCharCodes;

        charCodeAt = String.prototype.charCodeAt;
        toCharCode = charCodeAt.call.bind(charCodeAt);

        toCharCodes = function toCharCodes(str) {
            var iterator,
                charCodes,
                length,
                charCode;

            iterator = 0;
            charCodes = [];
            length = str.length;

            for (; iterator < length; iterator += 1) {
                charCode = toCharCode(str, iterator);

                charCodes.push(charCode);
            }

            return charCodes;
        };

        return toCharCodes;
    }());

    validateString = function validateString(data) {
        var delimiter,
            pattern,
            encodingLength,
            lastIndex,
            isValid,
            hasSameCharsetLength;

        delimiter = this.delimiter;
        pattern = this.pattern;
        encodingLength = this.encodingLength;
        lastIndex = data.length - delimiter.length;

        isValid = data === ''
        || data.indexOf(delimiter) === lastIndex
        && lastIndex % encodingLength === 0;

        if (!isValid) {
            throw new Error('Invalid XEncoder string: ' + data);
        }

        hasSameCharsetLength = + data.match(pattern)[2] === charsetLength;

        if (hasSameCharsetLength) {
            return true;
        }

        throw new Error('Invalid XEncoder charset: ' + data);
    };

    validateCharCodes = function validateCharCodes(data) {
        var chars,
            dataLength,
            charCodeIndex,
            isValid;

        chars = this.chars;
        dataLength = data.length;
        charCodeIndex = 0;
        isValid = true;

        for (; isValid && charCodeIndex < dataLength; charCodeIndex += 1) {
            isValid = data[charCodeIndex] < charsetLength;
        }

        if (isValid) {
            return true;
        }

        throw new Error('Invalid XEncoder data: ' + data);
    };

    (function detectCharsetLength() {
        var firstChar;

        charsetLength = 1;
        firstChar = toString([0]);

        for (; toString([charsetLength]) !== firstChar; charsetLength += 1);
    }());

    return XEncoder;
}());
<commit_msg>Update XEncoder.js<commit_after>/*
Copyright 2014 Lcf.vs
Released under the MIT license
https://github.com/Lcfvs/XEncoder.js
*/
var XEncoder;

XEncoder = (function () {
    'use strict';

    var defaultChars,
        charsetLength,
        XEncoder,
        getEncodingLength,
        encode,
        decode,
        toString,
        toCharCodes,
        validateString,
        validateCharCodes;

    defaultChars = '+/'
        + '0123456789'
        + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        + 'abcdefghijklmnopqrstuvwxyz';

    XEncoder = function XEncoder(chars) {
        var charString,
            delimiter,
            patternString,
            pattern,
            context;

        charString = chars
        || defaultChars;

        delimiter = '='
            + charsetLength
            + '=';

        patternString = '^(['
            + charString.replace(/(\[|\])/g, '\\$1')
            + ']+)=(\\d+)=$';

        pattern = new RegExp(patternString);

        context = {
            chars: charString,
            delimiter: delimiter,
            pattern: pattern,
            encodingLength: getEncodingLength(charString.length)
        };

        return {
            encode: encode.bind(context, validateCharCodes.bind(context)),
            decode: decode.bind(context, validateString.bind(context))
        };
    };

    getEncodingLength = function getEncodingLength(charsLength) {
        var encodingLength,
            rest;

        encodingLength = 0;

        rest = charsetLength - 1;

        for (; rest!== 0; encodingLength += 1) {
            rest = (rest - rest % charsLength) / charsLength;
        }

        return encodingLength;
    };

    encode = function encode(validate, data) {
        var chars,
            delimiter,
            encodingLength,
            charsLength,
            encodedData,
            dataIndex,
            dataLength,
            charCodes,
            charCode,
            encodedChar,
            rest;

        chars = this.chars;
        delimiter = this.delimiter;
        encodingLength = this.encodingLength;
        charsLength = chars.length;
        encodedData = '';
        dataIndex = 0;
        dataLength = data.length;

        charCodes = toCharCodes(data);

        validate(charCodes);

        for (; dataIndex < dataLength; dataIndex += 1) {
            charCode = charCodes[dataIndex];
            encodedChar = '';

            while (encodedChar.length < encodingLength) {
                rest = charCode % charsLength;
                charCode = (charCode - rest) / charsLength;
                encodedChar = chars.charAt(rest) + encodedChar;
            }

            encodedData += encodedChar;
        }

        encodedData += delimiter;

        return encodedData;
    };

    decode = function decode(validate, data) {
        var chars,
            delimiter,
            encodingLength,
            charsLength,
            charCodes,
            dataIndex,
            dataLength,
            charCode,
            charIndex,
            encodedChar,
            rest,
            decodedData;

        validate(data);

        chars = this.chars;
        delimiter = this.delimiter;
        encodingLength = this.encodingLength;
        charsLength = chars.length;
        charCodes = [];
        dataIndex = 0;
        dataLength = data.length - delimiter.length;

        for (; dataIndex < dataLength; dataIndex += encodingLength) {
            charCode = 0;
            charIndex = 0;

            for (; charIndex < encodingLength; charIndex += 1) {
                rest = chars.indexOf(data[dataIndex + charIndex]);

                charCode = rest * Math.pow(
                    charsLength,
                    encodingLength - charIndex - 1
                ) + charCode;
            }

            charCodes.push(charCode);
        }

        decodedData = toString(charCodes);

        return decodedData;
    };

    toString = (function () {
        var fromCharCode,
            toStr,
            toString;

        fromCharCode = String.fromCharCode;

        toStr = fromCharCode.apply.bind(fromCharCode, String);

        toString = function toString(data) {
            var isArray,
                charCodes,
                str;

            isArray = data instanceof Array;

            charCodes = isArray
                ? data
                : arguments;

            str = toStr(charCodes);

            return str;
        };

        return toString;
    }());

    toCharCodes = (function () {
        var charCodeAt,
            toCharCode,
            toCharCodes;

        charCodeAt = String.prototype.charCodeAt;
        toCharCode = charCodeAt.call.bind(charCodeAt);

        toCharCodes = function toCharCodes(str) {
            var iterator,
                charCodes,
                length,
                charCode;

            iterator = 0;
            charCodes = [];
            length = str.length;

            for (; iterator < length; iterator += 1) {
                charCode = toCharCode(str, iterator);

                charCodes.push(charCode);
            }

            return charCodes;
        };

        return toCharCodes;
    }());

    validateString = function validateString(data) {
        var delimiter,
            pattern,
            encodingLength,
            lastIndex,
            isValid,
            hasSameCharsetLength;

        delimiter = this.delimiter;
        pattern = this.pattern;
        encodingLength = this.encodingLength;
        lastIndex = data.length - delimiter.length;

        isValid = data === ''
        || data.indexOf(delimiter) === lastIndex
        && lastIndex % encodingLength === 0;

        if (!isValid) {
            throw new Error('Invalid XEncoder string: ' + data);
        }

        hasSameCharsetLength = + data.match(pattern)[2] === charsetLength;

        if (hasSameCharsetLength) {
            return true;
        }

        throw new Error('Invalid XEncoder charset: ' + data);
    };

    validateCharCodes = function validateCharCodes(data) {
        var chars,
            dataLength,
            charCodeIndex,
            isValid;

        chars = this.chars;
        dataLength = data.length;
        charCodeIndex = 0;
        isValid = true;

        for (; isValid && charCodeIndex < dataLength; charCodeIndex += 1) {
            isValid = data[charCodeIndex] < charsetLength;
        }

        if (isValid) {
            return true;
        }

        throw new Error('Invalid XEncoder data: ' + data);
    };

    (function detectCharsetLength() {
        var firstChar;

        charsetLength = 1;
        firstChar = toString([0]);

        for (; toString([charsetLength]) !== firstChar; charsetLength += 1);
    }());

    return XEncoder;
}());
<|endoftext|>


<commit_before>/* global require, module */

var EmberApp = require('ember-cli/lib/broccoli/ember-app'),
    funnel = require('broccoli-funnel');

var app = new EmberApp({
	hinting: false
});

// Use `app.import` to add additional libraries to the generated
// output files.

app.import('bower_components/material-design-lite/material.min.css');
app.import('bower_components/material-design-lite/material.min.js');
// app.import('bower_components/mdi/css/materialdesignicons.min.css');

app.import('bower_components/font-awesome/css/font-awesome.min.css');

app.import('vendor/ember-droplet/dist/ember-droplet.js');

app.import('vendor/node-uuid/uuid.js');

app.import('bower_components/leaflet/dist/leaflet.js');
app.import('bower_components/leaflet/dist/leaflet.css');

app.import('bower_components/d3/d3.min.js');

app.import('vendor/jsc3d/bin/jsc3d.min.js');

app.import('bower_components/underscore/underscore-min.js');

var fontFiles = funnel('bower_components/font-awesome/fonts', {
    destDir: 'fonts'
});

var adaptivePlaceholders = funnel('vendor/adaptive-placeholders', {
    destDir: 'vendor/adaptive-placeholders'
});

funnel('vendor/numeral', {
    destDir: 'vendor/numeral'
});
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree([fontFiles, adaptivePlaceholders]);
<commit_msg>temporarily disable 'ember-droplet' due to errors during loading<commit_after>/* global require, module */

var EmberApp = require('ember-cli/lib/broccoli/ember-app'),
    funnel = require('broccoli-funnel');

var app = new EmberApp({
	hinting: false
});

// Use `app.import` to add additional libraries to the generated
// output files.

app.import('bower_components/material-design-lite/material.min.css');
app.import('bower_components/material-design-lite/material.min.js');
// app.import('bower_components/mdi/css/materialdesignicons.min.css');

app.import('bower_components/font-awesome/css/font-awesome.min.css');

// app.import('vendor/ember-droplet/dist/ember-droplet.js');

app.import('vendor/node-uuid/uuid.js');

app.import('bower_components/leaflet/dist/leaflet.js');
app.import('bower_components/leaflet/dist/leaflet.css');

app.import('bower_components/d3/d3.min.js');

app.import('vendor/jsc3d/bin/jsc3d.min.js');

app.import('bower_components/underscore/underscore-min.js');

var fontFiles = funnel('bower_components/font-awesome/fonts', {
    destDir: 'fonts'
});

var adaptivePlaceholders = funnel('vendor/adaptive-placeholders', {
    destDir: 'vendor/adaptive-placeholders'
});

funnel('vendor/numeral', {
    destDir: 'vendor/numeral'
});
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree([fontFiles, adaptivePlaceholders]);
<|endoftext|>


<commit_before>import { closestParentTag } from '../../util/helpers'

export default {
  name: 'tab-item',

  data () {
    return {
      isActive: false
    }
  },

  props: {
    disabled: Boolean,

    href: {
      type: String,
      required: true
    },

    ripple: Boolean,

    router: Boolean
  },

  computed: {
    classes () {
      return {
        'tab__item': true,
        'tab__item--active': this.isActive,
        'tab__item--disabled': this.disabled
      }
    },

    target () {
      return this.href.replace('#', '')
    },

    tabs () {
      return closestParentTag.call(this, 'v-tabs')
    }
  },

  methods: {
    click (e) {
      this.tabs.tabClick(this.target)
    },

    toggle (target) {
      this.isActive = this.target === target
    }
  },

  render (h) {
    const data = {
      attrs: {},
      class: this.classes,
      props: {},
      directives: [
        {
          name: 'ripple',
          value: this.ripple || false
        }
      ]
    }

    let tag

    if (this.href && this.router) {
      tag = 'router-link'
      data.props.to = this.href
      data.props.exact = this.href === '/'
      data.props.activeClass = 'tab__item--active'
      data.nativeOn = { click: this.click }
    } else {
      tag = 'a'
      data.attrs.href = this.href || 'javascript:;'
      data.on = { click: this.click }
    }

    const tab = h(tag, data, [this.$slots.default])

    return h('li', {}, [tab])
  }
}
<commit_msg>added back preventDefault for tabs<commit_after>import { closestParentTag } from '../../util/helpers'

export default {
  name: 'tab-item',

  data () {
    return {
      isActive: false
    }
  },

  props: {
    disabled: Boolean,

    href: {
      type: String,
      required: true
    },

    ripple: Boolean,

    router: Boolean
  },

  computed: {
    classes () {
      return {
        'tab__item': true,
        'tab__item--active': this.isActive,
        'tab__item--disabled': this.disabled
      }
    },

    target () {
      return this.href.replace('#', '')
    },

    tabs () {
      return closestParentTag.call(this, 'v-tabs')
    }
  },

  methods: {
    click (e) {
      e.preventDefault()

      this.tabs.tabClick(this.target)
    },

    toggle (target) {
      this.isActive = this.target === target
    }
  },

  render (h) {
    const data = {
      attrs: {},
      class: this.classes,
      props: {},
      directives: [
        {
          name: 'ripple',
          value: this.ripple || false
        }
      ]
    }

    let tag

    if (this.href && this.router) {
      tag = 'router-link'
      data.props.to = this.href
      data.props.exact = this.href === '/'
      data.props.activeClass = 'tab__item--active'
      data.nativeOn = { click: this.click }
    } else {
      tag = 'a'
      data.attrs.href = this.href || 'javascript:;'
      data.on = { click: this.click }
    }

    const tab = h(tag, data, [this.$slots.default])

    return h('li', {}, [tab])
  }
}
<|endoftext|>


<commit_before>draw_hitrate = function(hitrate_points, hitrate_lines, weapons) {
	/* calculate line data. For 0.0 values use the value of the predecessor */
	var n_weapons = hitrate_points.length;
	var visible = Array(n_weapons);
	for (w = 0; w < n_weapons; ++w) {
		var data = hitrate_points[w];
		var allZero = true;
		for (d = 0; d < data.length; ++d) {
			if (data[d] > 0.0) {
				allZero = false;
			}
		}
		visible[w] = !allZero;
	}

	var datapoints_h = hitrate_points[0].length;

	/* color scale */
	var c = pv.Colors.category20();

	var vis = new pv.Panel()
		.width(100 + datapoints_h * 30)
		.height(150)
		.bottom(20);

	vis.add(pv.Panel)
		.left(100)
		.data(hitrate_lines)
		.add(pv.Line)
			.strokeStyle(function() c(this.parent.index))
			.data(function(d) d)
			.bottom(function(d) d * 140)
			.left(function() this.index * 30)
			.visible(function() visible[this.parent.index])
		.add(pv.Dot)
			.data(function() hitrate_points[this.parent.index])
			.visible(function(d) d > 0);

	/* Legend */
	legende = vis.add(pv.Panel);

	legende.add(pv.Dot)
		.data(weapons)
		.left(10)
		.top(function() this.index * 12 + 10)
		.strokeStyle(null)
		.fillStyle(function(d) visible[this.index] ? c(this.index) : "#BBBBBB")
	.anchor("right").add(pv.Label)
		.text(function(d) d)
		.textStyle(function(d) visible[this.index] ? "black" : "#BBBBBB");

	vis.render();
}
<commit_msg>Use quake colors in hitrate diagram<commit_after>draw_hitrate = function(hitrate_points, hitrate_lines, weapons) {
	/* calculate line data. For 0.0 values use the value of the predecessor */
	var n_weapons = hitrate_points.length;
	var visible = Array(n_weapons);
	for (w = 0; w < n_weapons; ++w) {
		var data = hitrate_points[w];
		var allZero = true;
		for (d = 0; d < data.length; ++d) {
			if (data[d] > 0.0) {
				allZero = false;
			}
		}
		visible[w] = !allZero;
	}

	var datapoints_h = hitrate_points[0].length;

	/* color scale */
	var c = pv.colors(
		"#3cf", // gauntlet
		"#ff0", // machine gun
		"orange", // shotgun
		"#d00", // rocket launcher
		"#c09", // plasma gun
		"#390", // grenade launcher
		"#fc0", // lighning gun
		"#5d0", // railgun
		"lightblue", // bfg
		"black" // teleport
	);

	var vis = new pv.Panel()
		.width(100 + datapoints_h * 30)
		.height(150)
		.bottom(20);

	vis.add(pv.Panel)
		.left(100)
		.data(hitrate_lines)
		.add(pv.Line)
			.strokeStyle(function() c(this.parent.index))
			.data(function(d) d)
			.bottom(function(d) d * 140)
			.left(function() this.index * 30)
		.add(pv.Dot)
			.data(function() hitrate_points[this.parent.index])
			.visible(function(d) d > 0);

	/* Legend */
	legende = vis.add(pv.Panel);

	legende.add(pv.Dot)
		.data(weapons)
		.left(10)
		.top(function() this.index * 12 + 10)
		.strokeStyle(null)
		.fillStyle(function(d) visible[this.index] ? c(this.index) : "#BBBBBB")
	.anchor("right").add(pv.Label)
		.text(function(d) d)
		.textStyle(function(d) visible[this.index] ? "black" : "#BBBBBB");

	vis.render();
}
<|endoftext|>