<commit_before>/**
 * The main module
 *
 * @context atl.general
 */
var $ = require('speakeasy/jquery').jQuery;
var images = $.map(
        [ 'alert.jpg', 'bad_ass.jpg', 'thumb_up.jpg' ],
        function(idx, img) {
            require('speakeasy/resources').getImageUrl(module, img);
        });

$(document).ready(function() {
    var imageIndex = 0;
    $('.welcome-message').prepend('

');

    $('#chuck').bind('click', function() {
        $.ajax({
            url: 'http://api.icndb.com/jokes/random',
            success: function(data) {
                var joke = JSON.parse(data);

                if (joke.type === 'success') {
                    $('#chuck-norris-facts').html(joke.value.joke);
                }
                $('#chuckImage').attr('src', images[imageIndex]);
                imageIndex = (imageIndex + 1) / 3;
            }
        });
    }).trigger('click');
});
<commit_msg>fix map<commit_after>/**
 * The main module
 *
 * @context atl.general
 */
var $ = require('speakeasy/jquery').jQuery;
var images = $.map(
        [ 'alert.jpg', 'bad_ass.jpg', 'thumb_up.jpg' ],
        function(img) {
            require('speakeasy/resources').getImageUrl(module, img);
        });

$(document).ready(function() {
    var imageIndex = 0;
    $('.welcome-message').prepend('

');

    $('#chuck').bind('click', function() {
        $.ajax({
            url: 'http://api.icndb.com/jokes/random',
            success: function(data) {
                var joke = JSON.parse(data);

                if (joke.type === 'success') {
                    $('#chuck-norris-facts').html(joke.value.joke);
                }
                $('#chuckImage').attr('src', images[imageIndex]);
                imageIndex = (imageIndex + 1) / 3;
            }
        });
    }).trigger('click');
});
<|endoftext|>


<commit_before>//Module is a Singelton
define(function(require) {

  var $ = require('jquery');
  var _ = require('underscore');
  var Backbone = require('backbone');
  var Store = require('localstorage');
  var Doc = require('models/doc');
  var settings = require('models/settings');

  var remoteStorageDocuments = require('remotestorage-documents');

  remoteStorage.claimAccess('documents', 'rw');

  var Docs = Backbone.Collection.extend({

    model: Doc,

    localStorage: remoteStorageDocuments.getBackboneStore('notes'),

    initialize: function(models) {

      this.fetch({
        success: _.bind(function() {
          if (this.isEmpty()) {
            this.addNew();
          }
        }, this)
      });

      this
        .on('reset', this.updateColor)
        .on('change:content', this.sort)
        .on('change:lastEdited', this.saveWhenIdle)
        .on('change:title', this.updateUrl);
    },

    addNew: function() {
      this.create({
        id: _.uniqueId(),
        lastEdited: new Date().getTime()
      });
    },

    // Sort by 'lastEdited'
    comparator: function(first, second) {
      return first.get('lastEdited') > second.get('lastEdited') ? -1 : 1 ;
    },

    updateColor: _.throttle(function() {
      this.each(function(doc) {
        doc.calculateColor();
      });
    }, 3000),

    saveTimeout: undefined,
    saveWhenIdle: function(doc) {
      clearTimeout(this.saveTimeout);
      this.saveTimeout = setTimeout(_.bind(doc.save, doc), 300);
    },

    updateUrl: function(doc) {
      var url = encodeURI(doc.get('title').toLowerCase().replace(/\s| /g, '-'));
      if (url.length < 1) {
        doc.set('url', '');
        return;
      }
      var len = this.filter(function(doc) {
	return new RegExp('^' + url + '(-[0-9]|$)').test(doc.get('url'));
      }).length;
      url = len < 1 ? url : url + '-' + len;
      doc.set('url', url);
    },

    deleteEmpty: function() {
      var previousDoc = this.get(settings.previous('openDocId'));
      if (previousDoc && previousDoc.isEmpty()) {
        this.remove(previousDoc);
      }
    }

  });

  var docs = new Docs();

  var hasConnected = false;

  remoteStorage.onWidget('state', function(state) {
    if ((! hasConnected) && state == 'connected') {
      hasConnected = true;

      docs.reset(docs.localStorage.findAll());
    } else if ( state == 'disconnected') {
      docs.reset();
    }
  });

  return docs;

});
<commit_msg>clear editor on disconnect<commit_after>//Module is a Singelton
define(function(require) {

  var $ = require('jquery');
  var _ = require('underscore');
  var Backbone = require('backbone');
  var Store = require('localstorage');
  var Doc = require('models/doc');
  var settings = require('models/settings');

  var remoteStorageDocuments = require('remotestorage-documents');

  remoteStorage.claimAccess('documents', 'rw');

  var Docs = Backbone.Collection.extend({

    model: Doc,

    localStorage: remoteStorageDocuments.getBackboneStore('notes'),

    initialize: function(models) {

      this.fetch({
        success: _.bind(function() {
          if (this.isEmpty()) {
            this.addNew();
          }
        }, this)
      });

      this
        .on('reset', this.updateColor)
        .on('change:content', this.sort)
        .on('change:lastEdited', this.saveWhenIdle)
        .on('change:title', this.updateUrl);
    },

    addNew: function() {
      this.create({
        id: _.uniqueId(),
        lastEdited: new Date().getTime()
      });
    },

    // Sort by 'lastEdited'
    comparator: function(first, second) {
      return first.get('lastEdited') > second.get('lastEdited') ? -1 : 1 ;
    },

    updateColor: _.throttle(function() {
      this.each(function(doc) {
        doc.calculateColor();
      });
    }, 3000),

    saveTimeout: undefined,
    saveWhenIdle: function(doc) {
      clearTimeout(this.saveTimeout);
      this.saveTimeout = setTimeout(_.bind(doc.save, doc), 300);
    },

    updateUrl: function(doc) {
      var url = encodeURI(doc.get('title').toLowerCase().replace(/\s| /g, '-'));
      if (url.length < 1) {
        doc.set('url', '');
        return;
      }
      var len = this.filter(function(doc) {
	return new RegExp('^' + url + '(-[0-9]|$)').test(doc.get('url'));
      }).length;
      url = len < 1 ? url : url + '-' + len;
      doc.set('url', url);
    },

    deleteEmpty: function() {
      var previousDoc = this.get(settings.previous('openDocId'));
      if (previousDoc && previousDoc.isEmpty()) {
        this.remove(previousDoc);
      }
    }

  });

  var docs = new Docs();

  var hasConnected = false;

  remoteStorage.onWidget('state', function(state) {
    if ((! hasConnected) && state == 'connected') {
      hasConnected = true;

      docs.reset(docs.localStorage.findAll());
    } else if ( state == 'disconnected') {
      docs.reset().addNew();
    }
  });

  return docs;

});
<|endoftext|>


<commit_before>import React from 'react'
import { View } from 'react-native'
import ScrollableTabView from 'react-native-scrollable-tab-view'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import * as actions from '../store/reducer/navigation'
import { modalState } from '../store/reducer/navigation'
import { openLoginForm } from '../store/reducer/login'
import TabBar from './tabbar/TabBar'
import SearchTab from './searchTab/SearchTab'
import NetworkConnection from './NetworkConnection'
import SpendingTab from './spending/SpendingTab'
import Account from './Account'
import LoginToView, { emptyStateImage } from './loggedOutState/LoginToView'
import TraderScreen from './TraderScreen'
import PersonScreen from './PersonScreen'
import DeveloperOptions from './DeveloperOptions'
import color from '../util/colors'
import { LOGIN_STATUSES } from '../store/reducer/login'
import Modal from './Modal'
import PaymentConfirmation from './PaymentConfirmation'

const style = {
  tabs: {
    flex: 1,
    backgroundColor: color.white
  },
  hiddenTabBar: {
    height: 0
  },
  flex: {
    flex: 1
  }
}

const componentForModalState = (state) => {
  switch (state) {
    case modalState.traderScreen:
      return <TraderScreen/>
    case modalState.personScreen:
      return <PersonScreen/>
    case modalState.developerOptions:
      return <DeveloperOptions/>
  }
}

const WithNetworkConnection = (props) =>
  <View style={style.flex}>
    {props.children}
    <NetworkConnection/>
  </View>

const Tabs = (props) =>
  <View style={style.flex}>
    <ScrollableTabView
        // On Android devices, when the keyboard is visible it pushes the entire
        // view upwards. In this instance we want to hide the tab bar
        renderTabBar={() => (props.dialogOpen && props.modalVisible) ? <View style={style.hiddenTabBar}/> : <TabBar/>}
        tabBarPosition='bottom'
        initialPage={props.tabIndex}
        tabBarActiveTextColor={color.bristolBlue}
        style={style.tabs}
        page={props.tabIndex}
        tabBarBackgroundColor={color.lightGray}
        scrollWithoutAnimation={true}
        locked={true}
        onChangeTab={({i}) => props.navigateToTab(i)}
        tabBarUnderlineColor={color.transparent}>
      <WithNetworkConnection tabLabel='Search'>
        <SearchTab/>
      </WithNetworkConnection>
      <WithNetworkConnection tabLabel='Spending'>
        { props.loggedIn
          ? <SpendingTab/>
          : <LoginToView
              image={emptyStateImage.spending}
              lineOne='Log in to view'
              lineTwo='your spending history' />
        }
      </WithNetworkConnection>
      <WithNetworkConnection tabLabel='Account'>
        { props.loggedIn
          ? <Account/>
          : <LoginToView
                  image={emptyStateImage.account}
                  lineOne='Log in to view'
                  lineTwo='your account details' />
        }
      </WithNetworkConnection>
    </ScrollableTabView>
    <Modal visible={props.modalVisible} hideModal={!props.confirmationOpen && props.hideModal} modalOpened={props.modalOpened}>
      {componentForModalState(props.modalState)}
    </Modal>
    <Modal visible={props.confirmationOpen} hideModal={props.closeConfirmation}>
      <PaymentConfirmation />
    </Modal>
  </View>

const mapDispatchToProps = (dispatch) =>
  bindActionCreators({ ...actions, openLoginForm }, dispatch)

const mapStateToProps = (state) => ({
  tabIndex: state.navigation.tabIndex,
  modalState: state.navigation.modalState,
  modalVisible: state.navigation.modalVisible,
  loggedIn: state.login.loginStatus === LOGIN_STATUSES.LOGGED_IN,
  status: state.status,
  dialogOpen: state.login.loginFormOpen,
  online: state.networkConnection.status,
  confirmationOpen: state.navigation.confirmationOpen
})

export default connect(mapStateToProps, mapDispatchToProps)(Tabs)
<commit_msg>fixed back button problems<commit_after>import React from 'react'
import { View } from 'react-native'
import ScrollableTabView from 'react-native-scrollable-tab-view'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import * as actions from '../store/reducer/navigation'
import { modalState } from '../store/reducer/navigation'
import { openLoginForm } from '../store/reducer/login'
import TabBar from './tabbar/TabBar'
import SearchTab from './searchTab/SearchTab'
import NetworkConnection from './NetworkConnection'
import SpendingTab from './spending/SpendingTab'
import { updatePage, resetForm } from '../store/reducer/sendMoney'
import Account from './Account'
import LoginToView, { emptyStateImage } from './loggedOutState/LoginToView'
import TraderScreen from './TraderScreen'
import PersonScreen from './PersonScreen'
import DeveloperOptions from './DeveloperOptions'
import color from '../util/colors'
import { LOGIN_STATUSES } from '../store/reducer/login'
import Modal from './Modal'
import PaymentConfirmation from './PaymentConfirmation'

const style = {
  tabs: {
    flex: 1,
    backgroundColor: color.white
  },
  hiddenTabBar: {
    height: 0
  },
  flex: {
    flex: 1
  }
}

const componentForModalState = (state) => {
  switch (state) {
    case modalState.traderScreen:
      return <TraderScreen/>
    case modalState.personScreen:
      return <PersonScreen/>
    case modalState.developerOptions:
      return <DeveloperOptions/>
  }
}

const WithNetworkConnection = (props) =>
  <View style={style.flex}>
    {props.children}
    <NetworkConnection/>
  </View>

const Tabs = (props) =>
  <View style={style.flex}>
    <ScrollableTabView
        // On Android devices, when the keyboard is visible it pushes the entire
        // view upwards. In this instance we want to hide the tab bar
        renderTabBar={() => (props.dialogOpen && props.modalVisible) ? <View style={style.hiddenTabBar}/> : <TabBar/>}
        tabBarPosition='bottom'
        initialPage={props.tabIndex}
        tabBarActiveTextColor={color.bristolBlue}
        style={style.tabs}
        page={props.tabIndex}
        tabBarBackgroundColor={color.lightGray}
        scrollWithoutAnimation={true}
        locked={true}
        onChangeTab={({i}) => props.navigateToTab(i)}
        tabBarUnderlineColor={color.transparent}>
      <WithNetworkConnection tabLabel='Search'>
        <SearchTab/>
      </WithNetworkConnection>
      <WithNetworkConnection tabLabel='Spending'>
        { props.loggedIn
          ? <SpendingTab/>
          : <LoginToView
              image={emptyStateImage.spending}
              lineOne='Log in to view'
              lineTwo='your spending history' />
        }
      </WithNetworkConnection>
      <WithNetworkConnection tabLabel='Account'>
        { props.loggedIn
          ? <Account/>
          : <LoginToView
                  image={emptyStateImage.account}
                  lineOne='Log in to view'
                  lineTwo='your account details' />
        }
      </WithNetworkConnection>
    </ScrollableTabView>
    <Modal visible={props.modalVisible} hideModal={() => {!props.confirmationOpen && props.hideModal() && props.resetForm()}} modalOpened={props.modalOpened}>
      {componentForModalState(props.modalState)}
    </Modal>
    <Modal visible={props.confirmationOpen} hideModal={() => {props.closeConfirmation() && props.updatePage(0)}}>
      <PaymentConfirmation />
    </Modal>
  </View>

const mapDispatchToProps = (dispatch) =>
  bindActionCreators({ ...actions, openLoginForm, updatePage, resetForm }, dispatch)

const mapStateToProps = (state) => ({
  tabIndex: state.navigation.tabIndex,
  modalState: state.navigation.modalState,
  modalVisible: state.navigation.modalVisible,
  loggedIn: state.login.loginStatus === LOGIN_STATUSES.LOGGED_IN,
  status: state.status,
  dialogOpen: state.login.loginFormOpen,
  online: state.networkConnection.status,
  confirmationOpen: state.navigation.confirmationOpen
})

export default connect(mapStateToProps, mapDispatchToProps)(Tabs)
<|endoftext|>


<commit_before>import React from 'react';
import { useIntl } from 'react-intl';
import PropTypes from 'prop-types';
import basename from '../../../../../../../../admin/src/core/utils/basename';
import MagicLinkWrapper from '../../../../../../../../admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper';

// FIXME replace with parts compo when ready
const MagicLink = ({ registrationToken }) => {
  const { formatMessage } = useIntl();

  if (registrationToken) {
    return (
      <MagicLinkWrapper
        target={`${window.location.origin}${basename}auth/register?registrationToken=${registrationToken}`}
      >
        {formatMessage({
          id: 'app.components.Users.MagicLink.connect',
          defaultMessage: 'Send this link to the user for them to connect.',
        })}
      </MagicLinkWrapper>
    );
  }

  return (
    <MagicLinkWrapper target={`${window.location.origin}${basename}auth/register`}>
      {formatMessage({
        id: 'app.components.Users.MagicLink.connect.sso',
        defaultMessage:
          'Send this link to the user, the first login can be made via a SSO provider.',
      })}
    </MagicLinkWrapper>
  );
};

MagicLink.defaultProps = {
  registrationToken: '',
};

MagicLink.propTypes = {
  registrationToken: PropTypes.string,
};

export default MagicLink;
<commit_msg>Fix magiclink with sso<commit_after>import React from 'react';
import { useIntl } from 'react-intl';
import PropTypes from 'prop-types';
import basename from '../../../../../../../../admin/src/core/utils/basename';
import MagicLinkWrapper from '../../../../../../../../admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper';

// FIXME replace with parts compo when ready
const MagicLink = ({ registrationToken }) => {
  const { formatMessage } = useIntl();

  if (registrationToken) {
    return (
      <MagicLinkWrapper
        target={`${window.location.origin}${basename}auth/register?registrationToken=${registrationToken}`}
      >
        {formatMessage({
          id: 'app.components.Users.MagicLink.connect',
          defaultMessage: 'Send this link to the user for them to connect.',
        })}
      </MagicLinkWrapper>
    );
  }

  return (
    <MagicLinkWrapper target={`${window.location.origin}${basename}auth/login`}>
      {formatMessage({
        id: 'app.components.Users.MagicLink.connect.sso',
        defaultMessage:
          'Send this link to the user, the first login can be made via a SSO provider.',
      })}
    </MagicLinkWrapper>
  );
};

MagicLink.defaultProps = {
  registrationToken: '',
};

MagicLink.propTypes = {
  registrationToken: PropTypes.string,
};

export default MagicLink;
<|endoftext|>


<commit_before>var System = require('../../entities/systems/System');

// has to stay here because it's used by traverseFunc below
// it's pretty crappy how it's sprinkled over the code
var numUpdates;

/**
 * Processes all entities with transform components, making sure they are up to date and valid according to the "scenegraph"
 * @example-link http://code.gooengine.com/latest/visual-test/goo/entities/components/TransformComponent/TransformComponent-vtest.html Working example
 * @extends System
 */
function TransformSystem() {
	System.call(this, 'TransformSystem', ['TransformComponent']);
	this.numUpdates = 0;
}

TransformSystem.prototype = Object.create(System.prototype);
TransformSystem.prototype.constructor = TransformSystem;

TransformSystem.prototype.process = function () {
	var entities = this._activeEntities;

	numUpdates = 0;
	var i, transformComponent;
	var l = entities.length;
	for (i = 0; i < l; i++) {
		transformComponent = entities[i].transformComponent;
		if (transformComponent._localTransformDirty) {
			transformComponent.updateTransform();
		}
	}

	// Traverse from root nodes and down, depth first
	for (i = 0; i < l; i++) {
		var entity = entities[i];
		transformComponent = entity.transformComponent;
		if (transformComponent.parent === null) {
			entity.traverse(traverseFunc);
		}
	}

	this.numUpdates = numUpdates;

	for (i = 0; i < l; i++) {
		transformComponent = entities[i].transformComponent;
		transformComponent.updatedDuringLastFrame = false;
	}
};

function traverseFunc(entity) {
	if (entity.transformComponent._worldTransformDirty) {
		entity.transformComponent.updateWorldTransform();
		numUpdates++;
		// Set children to dirty
		var children = entity.transformComponent.children;
		for (var j = 0; j < children.length; j++) {
			children[j]._worldTransformDirty = true;
		}
	}
}

module.exports = TransformSystem;<commit_msg>Invalidate updatedDuringLastFrame before marking dirty<commit_after>var System = require('../../entities/systems/System');

// has to stay here because it's used by traverseFunc below
// it's pretty crappy how it's sprinkled over the code
var numUpdates;

/**
 * Processes all entities with transform components, making sure they are up to date and valid according to the "scenegraph"
 * @example-link http://code.gooengine.com/latest/visual-test/goo/entities/components/TransformComponent/TransformComponent-vtest.html Working example
 * @extends System
 */
function TransformSystem() {
	System.call(this, 'TransformSystem', ['TransformComponent']);
	this.numUpdates = 0;
}

TransformSystem.prototype = Object.create(System.prototype);
TransformSystem.prototype.constructor = TransformSystem;

TransformSystem.prototype.process = function () {
	var entities = this._activeEntities;

	numUpdates = 0;
	var i, transformComponent;
	var l = entities.length;
	for (i = 0; i < l; i++) {
		transformComponent = entities[i].transformComponent;
		transformComponent.updatedDuringLastFrame = false;
		if (transformComponent._localTransformDirty) {
			transformComponent.updateTransform();
		}
	}

	// Traverse from root nodes and down, depth first
	for (i = 0; i < l; i++) {
		var entity = entities[i];
		transformComponent = entity.transformComponent;
		if (transformComponent.parent === null) {
			entity.traverse(traverseFunc);
		}
	}

	this.numUpdates = numUpdates;
};

function traverseFunc(entity) {
	if (entity.transformComponent._worldTransformDirty) {
		entity.transformComponent.updateWorldTransform();
		numUpdates++;
		// Set children to dirty
		var children = entity.transformComponent.children;
		for (var j = 0; j < children.length; j++) {
			children[j]._worldTransformDirty = true;
		}
	}
}

module.exports = TransformSystem;<|endoftext|>


<commit_before>var piece = (function() {
  var m = require('mithril');

  var zIndexCount = 0;
  var addClass = dom.addClass;
  var removeClass = dom.removeClass;
  function create(src) {
    var p = Object.create(this);
    zIndexCount += 1;
    p._zIndex = zIndexCount;
    p._src = src;
    p._isLoading = true;
    p._portMap = {};
    return p;
  }
  function initializeElement(node) {
    this._element = node;
    this.updatePosition();
  }
  function destroy() {
    var pieceID = this._id;
    var portMap = this._portMap;
    for (var portName in portMap) {
      boardEvent.removePortConnection(pieceID + '/' + portName);
    }
  }
  function vitalize() {
    this.updatePosition();
    this._isLoading = false;
  }
  function id(value) {
    if (!value)
      return this._id;
    this._id = value;
  }
  function label(value) {
    if (!value)
      return this._label || '';
    this._label = value;
  }
  function src() {
    return this._src;
  }
  function position(point) {
    if (!point)
      return {x: this._x, y: this._y};
    if ('x' in point)
      this._x = Math.max(point.x, 0);
    if ('y' in point)
      this._y = Math.max(point.y, 0);
  }
  function componentHeight(value) {
    if (!value)
      return this._componentHeight || 0;
    this._componentHeight = value;
  }
  function updatePosition() {
    var element = this._element;
    this._x = Math.max(this._x, (this._isShowingInConnector) ? 46 : 0);
    if (element) {
      dom.translate(element, this._x, this._y);
      element.style.zIndex = this._zIndex;
    }
  }
  function updateIsShowingInConnector() {
    this._isShowingInConnector = this.ports().some(function(port) {
      return port.isShowing() && port.hasIn();
    });
  }
  function element() {
    return this._element;
  }
  function setPorts(ports) {
    var pieceID = this._id;
    var map = {};
    for (var i = 0, len = ports.length; i < len; i += 1) {
      var port = ports[i];
      var portName = port.type() + '/' + port.key();
      var portID = pieceID + '/' + portName;
      port.id(portID);
      if (port.isDefault())
        this.showPort(port);
      else
        this.hidePort(port);
      map[portName] = port;
    }
    this._portMap = map;
    this.updateIsShowingInConnector();
  }
  function showPort(port) {
    port.show();
    this.updateIsShowingInConnector();
    this.updatePosition();
    m.redraw();
  }
  function hidePort(port) {
    port.hide();
    this.updateIsShowingInConnector();
    this.updatePosition();
    m.redraw();
  }
  function portMap() {
    return this._portMap;
  }
  function ports() {
    var portMap = this._portMap;
    return Object.keys(portMap).map(function(key) {
      return portMap[key];
    });
  }
  function toFront() {
    zIndexCount += 1;
    this._zIndex = zIndexCount;
  }
  function getAttribute() {
    return {
      id: this._id,
      src: this._src,
      x: this._x,
      y: this._y
    };
  }
  function isLoading() {
    return this._isLoading;
  }
  function getComponentElement() {
    return this._element.children[1].children[0];
  }
  return {
    create: create,
    initializeElement: initializeElement,
    destroy: destroy,
    vitalize: vitalize,
    id: id,
    label: label,
    src: src,
    position: position,
    componentHeight: componentHeight,
    updatePosition: updatePosition,
    updateIsShowingInConnector: updateIsShowingInConnector,
    element: element,
    setPorts: setPorts,
    showPort: showPort,
    hidePort: hidePort,
    portMap: portMap,
    ports: ports,
    toFront: toFront,
    getAttribute: getAttribute,
    isLoading: isLoading,
    getComponentElement: getComponentElement
  };
}());<commit_msg>Change order of showing port<commit_after>var piece = (function() {
  var m = require('mithril');

  var zIndexCount = 0;
  var addClass = dom.addClass;
  var removeClass = dom.removeClass;
  function create(src) {
    var p = Object.create(this);
    zIndexCount += 1;
    p._zIndex = zIndexCount;
    p._src = src;
    p._isLoading = true;
    p._portMap = {};
    return p;
  }
  function initializeElement(node) {
    this._element = node;
    this.updatePosition();
  }
  function destroy() {
    var pieceID = this._id;
    var portMap = this._portMap;
    for (var portName in portMap) {
      boardEvent.removePortConnection(pieceID + '/' + portName);
    }
  }
  function vitalize() {
    this.updatePosition();
    this._isLoading = false;
  }
  function id(value) {
    if (!value)
      return this._id;
    this._id = value;
  }
  function label(value) {
    if (!value)
      return this._label || '';
    this._label = value;
  }
  function src() {
    return this._src;
  }
  function position(point) {
    if (!point)
      return {x: this._x, y: this._y};
    if ('x' in point)
      this._x = Math.max(point.x, 0);
    if ('y' in point)
      this._y = Math.max(point.y, 0);
  }
  function componentHeight(value) {
    if (!value)
      return this._componentHeight || 0;
    this._componentHeight = value;
  }
  function updatePosition() {
    var element = this._element;
    this._x = Math.max(this._x, (this._isShowingInConnector) ? 46 : 0);
    if (element) {
      dom.translate(element, this._x, this._y);
      element.style.zIndex = this._zIndex;
    }
  }
  function updateIsShowingInConnector() {
    this._isShowingInConnector = this.ports().some(function(port) {
      return port.isShowing() && port.hasIn();
    });
  }
  function element() {
    return this._element;
  }
  function setPorts(ports) {
    var pieceID = this._id;
    var map = {};
    for (var i = 0, len = ports.length; i < len; i += 1) {
      var port = ports[i];
      var portName = port.type() + '/' + port.key();
      var portID = pieceID + '/' + portName;
      port.id(portID);
      if (port.isDefault())
        this.showPort(port);
      else
        this.hidePort(port);
      map[portName] = port;
    }
    this._portMap = map;
    this.updateIsShowingInConnector();
  }
  function showPort(port) {
    var portMap = this._portMap;
    var portName = port.type() + '/' + port.key();

    // XXX: change port order
    delete portMap[portName];
    portMap[portName] = port;

    port.show();
    this.updateIsShowingInConnector();
    this.updatePosition();
    m.redraw();
  }
  function hidePort(port) {
    port.hide();
    this.updateIsShowingInConnector();
    this.updatePosition();
    m.redraw();
  }
  function portMap() {
    return this._portMap;
  }
  function ports() {
    var portMap = this._portMap;
    return Object.keys(portMap).map(function(key) {
      return portMap[key];
    });
  }
  function toFront() {
    zIndexCount += 1;
    this._zIndex = zIndexCount;
  }
  function getAttribute() {
    return {
      id: this._id,
      src: this._src,
      x: this._x,
      y: this._y
    };
  }
  function isLoading() {
    return this._isLoading;
  }
  function getComponentElement() {
    return this._element.children[1].children[0];
  }
  return {
    create: create,
    initializeElement: initializeElement,
    destroy: destroy,
    vitalize: vitalize,
    id: id,
    label: label,
    src: src,
    position: position,
    componentHeight: componentHeight,
    updatePosition: updatePosition,
    updateIsShowingInConnector: updateIsShowingInConnector,
    element: element,
    setPorts: setPorts,
    showPort: showPort,
    hidePort: hidePort,
    portMap: portMap,
    ports: ports,
    toFront: toFront,
    getAttribute: getAttribute,
    isLoading: isLoading,
    getComponentElement: getComponentElement
  };
}());<|endoftext|>


<commit_before>/*global dat,ga*/
/**
 * Demo show a bunch of fish and a dat.gui controls
 * @class
 * @extends PIXI.Application
 */
export default class DemoApplication extends PIXI.Application {

    constructor() {

        const gui = new dat.GUI();
        gui.useLocalStorage = false;

        // Get the initial dementions for the application
        const domElement = document.querySelector('#container');
        const initWidth = domElement.offsetWidth;
        const initHeight = domElement.offsetHeight;

        super({
            view: document.querySelector('#stage'),
            width: initWidth,
            height: initHeight,
            autoStart: false,
            backgroundColor:0x000000,
        });

        this.domElement = domElement;

        this.initWidth = initWidth;
        this.initHeight = initHeight;
        this.paused = false;
        this.renderPaused = false;
        this.events = new PIXI.utils.EventEmitter();
        this.animateTimer = 0;
        this.bg = null;
        this.pond = null;
        this.fishes = [];
        this.fishFilters = [];
        this.pondFilters = [];
        this.filterArea = new PIXI.Rectangle();
        this.padding = 100;
        this.bounds = new PIXI.Rectangle(
            -this.padding,
            -this.padding,
            initWidth + this.padding * 2,
            initHeight + this.padding * 2
        );

        const app = this;

        this.gui = gui;
        this.gui.add(this, 'renderPaused').name('* Pause Render')
            .onChange(function(value){
                if (value) {
                    app.stop();
                }
                else {
                    app.start();
                }
            });
        this.gui.add(this, 'paused').name('* Pause animate');
    }

    /**
     * Convenience for getting resources
     * @member {object}
     */
    get resources() {
        return this.loader.resources;
    }

    /**
     * Load resources
     * @param {object} manifest Collection of resources to load
     */
    load(manifest, callback) {
        this.loader.add(manifest).load(() => {
            callback();
            this.init();
            this.start();
        });
    }

    /**
     * Called when the load is completed
     */
    init() {

        const {resources} = this.loader;
        const {bounds, initWidth, initHeight} = this;

        // Setup the container
        this.pond = new PIXI.Container();
        this.pond.filterArea = this.filterArea;
        this.pond.filters = this.pondFilters;
        this.stage.addChild(this.pond);

        // Setup the background image
        this.bg = new PIXI.Sprite(resources.background.texture);
        this.pond.addChild(this.bg);

        // Create and add the fish
        for (let i = 0; i < 20; i++) {
            const id = 'fish' + ((i % 4) + 1);
            const fish = new PIXI.Sprite(resources[id].texture);
            fish.anchor.set(0.5);
            fish.filters = this.fishFilters;

            fish.direction = Math.random() * Math.PI * 2;
            fish.speed = 2 + Math.random() * 2;
            fish.turnSpeed = Math.random() - 0.8;

            fish.x = Math.random() * bounds.width;
            fish.y = Math.random() * bounds.height;

            fish.scale.set(0.8 + Math.random() * 0.3);
            this.pond.addChild(fish);
            this.fishes.push(fish);
        }

        // Setup the tiling sprite
        this.overlay = new PIXI.extras.TilingSprite(
            resources.overlay.texture,
            initWidth,
            initHeight
        );

        // Add the overlay
        this.pond.addChild(this.overlay);

        // Handle window resize event
        window.addEventListener('resize', this.resize.bind(this));
        this.resize();

        // Handle fish animation
        this.ticker.add(this.animate, this);
    }

    /**
     * Toggle fish moving
     */
    togglePause() {
        this.paused = !this.paused;
    }

    /**
     * Resize the demo when the window resizes
     */
    resize() {

        const {padding, bg, overlay, filterArea, bounds} = this;

        const width = this.domElement.offsetWidth;
        const height = this.domElement.offsetHeight;
        const filterAreaPadding = 4;

        // Use equivalent of CSS's contain for the background
        // so that it scales proportionally
        const bgAspect = bg.texture.width / bg.texture.height;
        const winAspect = width / height;

        if (winAspect > bgAspect) {
            bg.width = width;
            bg.height = width / bgAspect;
        }
        else {
            bg.height = height;
            bg.width = height * bgAspect;
        }

        bg.x = (width - bg.width) / 2;
        bg.y = (height - bg.height) / 2;

        overlay.width = width;
        overlay.height = height;

        bounds.x = -padding;
        bounds.y = -padding;
        bounds.width = width + padding * 2;
        bounds.height = height + padding * 2;

        filterArea.x = filterAreaPadding;
        filterArea.y = filterAreaPadding;
        filterArea.width = width - filterAreaPadding * 2;
        filterArea.height = height - filterAreaPadding * 2;

        this.events.emit('resize', width, height);

        this.renderer.resize(width, height);

        this.render();
    }

    /**
     * Animate the fish, overlay and filters (if applicable)
     * @param {number} delta - % difference in time from last frame render
     */
    animate(delta) {

        this.animateTimer += 0.1 * delta;

        const {bounds, animateTimer, overlay} = this;

        this.events.emit('animate', delta, animateTimer);

        if (this.paused) {
            return;
        }

        // Animate the overlay
        overlay.tilePosition.x = animateTimer * -10;
        overlay.tilePosition.y = animateTimer * -10;

        for (let i = 0; i < this.fishes.length; i++) {

            const fish = this.fishes[i];

            fish.direction += fish.turnSpeed * 0.01;

            fish.x += Math.sin(fish.direction) * fish.speed;
            fish.y += Math.cos(fish.direction) * fish.speed;

            fish.rotation = -fish.direction - Math.PI/2;

            if (fish.x < bounds.x) {
                fish.x += bounds.width;
            }
            if (fish.x > bounds.x + bounds.width) {
                fish.x -= bounds.width;
            }
            if (fish.y < bounds.y) {
                fish.y += bounds.height;
            }
            if (fish.y > bounds.y + bounds.height) {
                fish.y -= bounds.height;
            }

        }
    }

    /**
     * Add a new filter
     * @param {string} id Class name
     * @param {object|function} options The class name of filter or options
     * @param {string} [options.id] The name of the PIXI.filters class
     * @param {boolean} [options.global] Filter is in pixi.js
     * @param {array} [options.args] Constructor arguments
     * @param {boolean} [options.fishOnly=false] Apply to fish only, not whole scene
     * @param {boolean} [options.enabled=false] Filter is enabled by default
     * @param {boolean} [options.opened=false] Filter Folder is opened by default
     * @param {function} [oncreate] Function takes filter and gui folder as
     *        arguments and is scoped to the Demo application.
     * @return {PIXI.Filter} Instance of new filter
     */
    addFilter(id, options) {

        if (typeof options === 'function') {
            options = { oncreate: options };
        }

        options = Object.assign({
            name: id,
            enabled: false,
            opened: false,
            args: null,
            fishOnly: false,
            global: false,
            oncreate: null
        }, options);

        if (options.global) {
            options.name += ' (pixi.js)';
        }

        const folder = this.gui.addFolder(options.name);
        const ClassRef = PIXI.filters[id];

        if (!ClassRef) {
            throw `Unable to find class name with "${id}"`;
        }

        let filter;
        if (options.args) {
            const ClassRefArgs = function(a) {
                ClassRef.apply(this, a);
            };
            ClassRefArgs.prototype = ClassRef.prototype;
            filter = new ClassRefArgs(options.args);
        }
        else {
            filter = new ClassRef();
        }

        // Set enabled status
        filter.enabled = options.enabled;

        // Track enabled change with analytics
        folder.add(filter, 'enabled').onChange((enabled) => {
            ga('send', 'event', id, enabled ? 'enabled' : 'disabled');
            this.render();
            if (enabled) {
                folder.domElement.className += ' enabled';
            }
            else {
                folder.domElement.className = folder.domElement.className.replace(' enabled', '');
            }
        });

        if (options.opened) {
            folder.open();
        }

        if (options.enabled) {
            folder.domElement.className += ' enabled';
        }

        if (options.oncreate) {
            options.oncreate.call(filter, folder);
        }

        if (options.fishOnly) {
            this.fishFilters.push(filter);
        }
        else {
            this.pondFilters.push(filter);
        }

        return filter;
    }
}
<commit_msg>add `fishCount` for config fish-count<commit_after>/*global dat,ga*/
/**
 * Demo show a bunch of fish and a dat.gui controls
 * @class
 * @extends PIXI.Application
 */
export default class DemoApplication extends PIXI.Application {

    constructor() {

        const gui = new dat.GUI();
        gui.useLocalStorage = false;

        // Get the initial dementions for the application
        const domElement = document.querySelector('#container');
        const initWidth = domElement.offsetWidth;
        const initHeight = domElement.offsetHeight;

        super({
            view: document.querySelector('#stage'),
            width: initWidth,
            height: initHeight,
            autoStart: false,
            backgroundColor:0x000000,
        });

        this.domElement = domElement;

        this.initWidth = initWidth;
        this.initHeight = initHeight;
        this.paused = false;
        this.renderPaused = false;
        this.events = new PIXI.utils.EventEmitter();
        this.animateTimer = 0;
        this.bg = null;
        this.pond = null;
        this.fishCount = 20;
        this.fishes = [];
        this.fishFilters = [];
        this.pondFilters = [];
        this.filterArea = new PIXI.Rectangle();
        this.padding = 100;
        this.bounds = new PIXI.Rectangle(
            -this.padding,
            -this.padding,
            initWidth + this.padding * 2,
            initHeight + this.padding * 2
        );

        const app = this;

        this.gui = gui;
        this.gui.add(this, 'renderPaused').name('* Pause Render')
            .onChange(function(value){
                if (value) {
                    app.stop();
                }
                else {
                    app.start();
                }
            });
        this.gui.add(this, 'paused').name('* Pause animate');
    }

    /**
     * Convenience for getting resources
     * @member {object}
     */
    get resources() {
        return this.loader.resources;
    }

    /**
     * Load resources
     * @param {object} manifest Collection of resources to load
     */
    load(manifest, callback) {
        this.loader.add(manifest).load(() => {
            callback();
            this.init();
            this.start();
        });
    }

    /**
     * Called when the load is completed
     */
    init() {

        const {resources} = this.loader;
        const {bounds, initWidth, initHeight} = this;

        // Setup the container
        this.pond = new PIXI.Container();
        this.pond.filterArea = this.filterArea;
        this.pond.filters = this.pondFilters;
        this.stage.addChild(this.pond);

        // Setup the background image
        this.bg = new PIXI.Sprite(resources.background.texture);
        this.pond.addChild(this.bg);

        // Create and add the fish
        for (let i = 0; i < this.fishCount; i++) {
            const id = 'fish' + ((i % 4) + 1);
            const fish = new PIXI.Sprite(resources[id].texture);
            fish.anchor.set(0.5);
            fish.filters = this.fishFilters;

            fish.direction = Math.random() * Math.PI * 2;
            fish.speed = 2 + Math.random() * 2;
            fish.turnSpeed = Math.random() - 0.8;

            fish.x = Math.random() * bounds.width;
            fish.y = Math.random() * bounds.height;

            fish.scale.set(0.8 + Math.random() * 0.3);
            this.pond.addChild(fish);
            this.fishes.push(fish);
        }

        // Setup the tiling sprite
        this.overlay = new PIXI.extras.TilingSprite(
            resources.overlay.texture,
            initWidth,
            initHeight
        );

        // Add the overlay
        this.pond.addChild(this.overlay);

        // Handle window resize event
        window.addEventListener('resize', this.resize.bind(this));
        this.resize();

        // Handle fish animation
        this.ticker.add(this.animate, this);
    }

    /**
     * Toggle fish moving
     */
    togglePause() {
        this.paused = !this.paused;
    }

    /**
     * Resize the demo when the window resizes
     */
    resize() {

        const {padding, bg, overlay, filterArea, bounds} = this;

        const width = this.domElement.offsetWidth;
        const height = this.domElement.offsetHeight;
        const filterAreaPadding = 4;

        // Use equivalent of CSS's contain for the background
        // so that it scales proportionally
        const bgAspect = bg.texture.width / bg.texture.height;
        const winAspect = width / height;

        if (winAspect > bgAspect) {
            bg.width = width;
            bg.height = width / bgAspect;
        }
        else {
            bg.height = height;
            bg.width = height * bgAspect;
        }

        bg.x = (width - bg.width) / 2;
        bg.y = (height - bg.height) / 2;

        overlay.width = width;
        overlay.height = height;

        bounds.x = -padding;
        bounds.y = -padding;
        bounds.width = width + padding * 2;
        bounds.height = height + padding * 2;

        filterArea.x = filterAreaPadding;
        filterArea.y = filterAreaPadding;
        filterArea.width = width - filterAreaPadding * 2;
        filterArea.height = height - filterAreaPadding * 2;

        this.events.emit('resize', width, height);

        this.renderer.resize(width, height);

        this.render();
    }

    /**
     * Animate the fish, overlay and filters (if applicable)
     * @param {number} delta - % difference in time from last frame render
     */
    animate(delta) {

        this.animateTimer += 0.1 * delta;

        const {bounds, animateTimer, overlay} = this;

        this.events.emit('animate', delta, animateTimer);

        if (this.paused) {
            return;
        }

        // Animate the overlay
        overlay.tilePosition.x = animateTimer * -10;
        overlay.tilePosition.y = animateTimer * -10;

        for (let i = 0; i < this.fishes.length; i++) {

            const fish = this.fishes[i];

            fish.direction += fish.turnSpeed * 0.01;

            fish.x += Math.sin(fish.direction) * fish.speed;
            fish.y += Math.cos(fish.direction) * fish.speed;

            fish.rotation = -fish.direction - Math.PI/2;

            if (fish.x < bounds.x) {
                fish.x += bounds.width;
            }
            if (fish.x > bounds.x + bounds.width) {
                fish.x -= bounds.width;
            }
            if (fish.y < bounds.y) {
                fish.y += bounds.height;
            }
            if (fish.y > bounds.y + bounds.height) {
                fish.y -= bounds.height;
            }

        }
    }

    /**
     * Add a new filter
     * @param {string} id Class name
     * @param {object|function} options The class name of filter or options
     * @param {string} [options.id] The name of the PIXI.filters class
     * @param {boolean} [options.global] Filter is in pixi.js
     * @param {array} [options.args] Constructor arguments
     * @param {boolean} [options.fishOnly=false] Apply to fish only, not whole scene
     * @param {boolean} [options.enabled=false] Filter is enabled by default
     * @param {boolean} [options.opened=false] Filter Folder is opened by default
     * @param {function} [oncreate] Function takes filter and gui folder as
     *        arguments and is scoped to the Demo application.
     * @return {PIXI.Filter} Instance of new filter
     */
    addFilter(id, options) {

        if (typeof options === 'function') {
            options = { oncreate: options };
        }

        options = Object.assign({
            name: id,
            enabled: false,
            opened: false,
            args: null,
            fishOnly: false,
            global: false,
            oncreate: null
        }, options);

        if (options.global) {
            options.name += ' (pixi.js)';
        }

        const folder = this.gui.addFolder(options.name);
        const ClassRef = PIXI.filters[id];

        if (!ClassRef) {
            throw `Unable to find class name with "${id}"`;
        }

        let filter;
        if (options.args) {
            const ClassRefArgs = function(a) {
                ClassRef.apply(this, a);
            };
            ClassRefArgs.prototype = ClassRef.prototype;
            filter = new ClassRefArgs(options.args);
        }
        else {
            filter = new ClassRef();
        }

        // Set enabled status
        filter.enabled = options.enabled;

        // Track enabled change with analytics
        folder.add(filter, 'enabled').onChange((enabled) => {
            ga('send', 'event', id, enabled ? 'enabled' : 'disabled');
            this.render();
            if (enabled) {
                folder.domElement.className += ' enabled';
            }
            else {
                folder.domElement.className = folder.domElement.className.replace(' enabled', '');
            }
        });

        if (options.opened) {
            folder.open();
        }

        if (options.enabled) {
            folder.domElement.className += ' enabled';
        }

        if (options.oncreate) {
            options.oncreate.call(filter, folder);
        }

        if (options.fishOnly) {
            this.fishFilters.push(filter);
        }
        else {
            this.pondFilters.push(filter);
        }

        return filter;
    }
}
<|endoftext|>


<commit_before>/* @flow */

import EventEmitter from 'event-emitter';
import State from './State';

const ENTER_EVENT:string = 'enter';
const TRANSITION_COMPLETE_EVENT:string = 'transition_complete';
const TRANSITION_DENIED_EVENT:string = 'transition_denied';

const emitter = new EventEmitter();
/**
 * Creates a generic StateMachine. Available states can be set with addState and initial state can
 * be set using initialState setter.
 * @example This sample creates a state machine for a player model with 3 states (Playing, paused and stopped)
 *

 *	playerSM = new StateMachine();
 *
 *	playerSM.addState("playing",{ enter: onPlayingEnter, exit: onPlayingExit, from:["paused","stopped"] });
 *	playerSM.addState("paused",{ enter: onPausedEnter, from:"playing"});
 *	playerSM.addState("stopped",{ enter: onStoppedEnter, from:"*"});
 *
 *	playerSM.addEventListener(StateMachineEvents.TRANSITION_DENIED,transitionDeniedFunction);
 *	playerSM.addEventListener(StateMachineEvents.TRANSITION_COMPLETE,transitionCompleteFunction);
 *
 *	playerSM.initialState = "stopped";
 *

 *
 * It's also possible to create hierarchical state machines using the argument "parent" in the addState method
 * @example This example shows the creation of a hierarchical state machine for the monster of a game
 * (Its a simplified version of the state machine used to control the AI in the original Quake game)
 *

 *	monsterSM = new StateMachine()
 *
 *	monsterSM.addState("idle",{enter:onIdle, from:"attack"})
 *	monsterSM.addState("attack",{enter:onAttack, from:"idle"})
 *	monsterSM.addState("melee attack",{parent:"atack", enter:onMeleeAttack, from:"attack"})
 *	monsterSM.addState("smash",{parent:"melle attack", enter:onSmash})
 *	monsterSM.addState("punch",{parent:"melle attack", enter:onPunch})
 *	monsterSM.addState("missle attack",{parent:"attack", enter:onMissle})
 *	monsterSM.addState("die",{enter:onDead, from:"attack", enter:onDie})
 *
 *	monsterSM.initialState = "idle"
 *

*/
export default class StateMachine {
	_state:string;
	_states:Array<State>;
	parentState:State;
	parentStates:Array<State>;
	path:Array<number>;

  constructor(){
    this._states = [];
    this.parentStates = [];
    this.path = [];

  }

	emit(){
		emitter.emit(...arguments);
	}

  hasState(stateName:string):boolean {
    return Object.keys(this._states).indexOf(stateName) !== -1;
  }

  /**
   * Adds a new state
   * stateName	The name of the new State
   * stateData	An objct containing state enter and exit callbacks and allowed states to transition from
   * The "from" property can be a string or and array with the state names or * to allow any transition
  **/
  addState(stateName:string, stateData:Object = {}):void {
    if(this.hasState(stateName)){
      console.log("[StateMachine] Overriding existing state " + stateName);
    }

    this._states[stateName] = new State(stateName, stateData.from, stateData.enter, stateData.exit, this._states[stateData.parent]);
  }

  /**
   * Sets the first state, calls enter callback and dispatches TRANSITION_COMPLETE
   * These will only occour if no state is defined
   * stateName	The name of the State
  **/
  set initialState(stateName:string):void {
    if (this._state === undefined && this.hasState(stateName)) {
      this._state = stateName;

      // Invoke the enter callback for all parent states down from the root parent of the state we're transitioning into

      if(typeof this._states[this._state].root !== "undefined" && this._states[this._state].root !== null){
        let parentStates:Array<State> = this._states[this._state].parents;
        for (parentState of parentStates) {

          if(parentState.enter !== null && typeof parentState.enter === "function"){
            parentState.enter.call(this, {toState: stateName});
          }
        };
      }

      // Invoke the enter callback of the state we're transitioning into
      if(this._states[this._state].enter !== null && typeof this._states[this._state].enter === "function"){
        this._states[this._state].enter.call(this, {currentState: this._state});
      }

      this.emit(TRANSITION_COMPLETE_EVENT, {toState:stateName});
    }
  }

	/**
	 *	Getters for the current state and for the Dictionary of states
	 */
	get state():string {
		return this._states[this._state];
	}

	get states():Object {
		return this._states;
	}

	getStateByName(name:string):any	{
		for (state of this._states) {
			if(state.name === name){
				return state;
			}
		}
		return null;
	}

	/**
	 * Verifies if a transition can be made from the current state to the state passed as param
	 * stateName	The name of the State
	**/
	canChangeStateTo(stateName:string):boolean {
		return (stateName !== this._state && ( this._states[stateName].from.indexOf(this._state)!== -1) || this._states[stateName].from === '*' );
	}

	/**
	 * Discovers the how many "exits" and how many "enters" are there between two
	 * given states and returns an array with these two integers
	 * stateFrom The state to exit
	 * stateTo The state to enter
	**/
	findPath(stateFrom:string, stateTo:string):Array<number> {
		// Verifies if the states are in the same "branch" or have a common parent
		let fromState:State = this._states[stateFrom];
		let c:number = 0;
		let d:number = 0;
		while (fromState)
		{
			d=0;
			let toState:State = this._states[stateTo];
			while (toState)
			{
				if(fromState == toState)
				{
					// They are in the same brach or have a common parent Common parent
					return [c,d];
				}
				d++;
				toState = toState.parent;
			}
			c++;
			fromState = fromState.parent;
		}
		// No direct path, no commom parent: exit until root then enter until element
		return [c,d];
	}

	/**
	 * Changes the current state
	 * This will only be done if the intended state allows the transition from the current state
	 * Changing states will call the exit callback for the exiting state and enter callback for the entering state
	 * stateTo	The name of the state to transition to
	**/
	changeState(stateTo:string):void {
		// If there is no state that maches stateTo
		if (!this.hasState(stateTo)){
			console.warn("[StateMachine] Cannot make transition: State "+ stateTo +" is not defined");
			return;
		}

		// If current state is not allowed to make this transition
		if(!this.canChangeStateTo(stateTo))
		{
			console.warn("[StateMachine] Transition to "+ stateTo +" denied");
			this.emit(TRANSITION_COMPLETE_EVENT, {
				fromState:this._state,
				toState:stateTo,
				allowedStates: this._states[stateTo].from
			});
			return;
		}

		// call exit and enter callbacks (if they exits)
		let path:Array<number> = this.findPath(this._state,stateTo);
		if(path[0]>0){
			if(this._states[this._state].exit !== null && typeof this._states[this._state].exit === "function"){
				this._states[this._state].exit.call(null,{currentState: this._state});
			};

			let parentState:State = this._states[this._state];

			for(let i:number=0; i<path[0]-1; i++)
			{
				parentState = parentState.parent;
				if(parentState.exit !== null && typeof parentState.exit === "function"){
					parentState.exit.call(null,{currentState: parentState.name});
				}
			}
		}
		let oldState:String = this._state;
		this._state = stateTo;
		if(path[1]>0)
		{
			if(typeof this._states[stateTo].root !== "undefined" && this._states[stateTo].root !== null){
				let parentStates:Array<State> = this._states[stateTo].parents;
				for(var k:number = path[1]-2; k>=0; k--){
					if(typeof parentStates[k] !== "undefined" &&
					parentStates[k] !== null &&
					parentStates[k].enter !== null &&
					typeof parentStates[k].enter === "function"){
						parentStates[k].enter.call(null,{currentState: parentStates[k].name});
					}
				}
			}
			if(this._states[this._state].enter !== null && typeof this._states[this._state].enter === "function"){
				this._states[this._state].enter.call(null,{currentState: this._state});
			}
		}
		console.log("[StateMachine] State Changed to " + this._state);

		// Transition is complete. dispatch TRANSITION_COMPLETE
		this.emit(TRANSITION_COMPLETE_EVENT, {fromState:oldState, toState:stateTo});
	}
}
<commit_msg>Updated documentation + corrected some typos<commit_after>/* @flow */

import EventEmitter from 'event-emitter';
import State from './State';

const ENTER_EVENT:string = 'enter';
const TRANSITION_COMPLETE_EVENT:string = 'transition_complete';
const TRANSITION_DENIED_EVENT:string = 'transition_denied';

const emitter = new EventEmitter();
/**
 * Creates a generic StateMachine. Available states can be set with addState and initial state can
 * be set using initialState setter.
 * @example This sample creates a state machine for a player model with 3 states (Playing, paused and stopped)
 *

 *	playerSM = new StateMachine();
 *
 *	playerSM.addState("playing",{ enter: onPlayingEnter, exit: onPlayingExit, from:["paused","stopped"] });
 *	playerSM.addState("paused",{ enter: onPausedEnter, from:"playing"});
 *	playerSM.addState("stopped",{ enter: onStoppedEnter, from:"*"});
 *
 *	playerSM.addEventListener(StateMachineEvents.TRANSITION_DENIED,transitionDeniedFunction);
 *	playerSM.addEventListener(StateMachineEvents.TRANSITION_COMPLETE,transitionCompleteFunction);
 *
 *	playerSM.initialState = "stopped";
 *

 *
 * It's also possible to create hierarchical state machines using the argument "parent" in the addState method
 * @example This example shows the creation of a hierarchical state machine for the monster of a game
 * (Its a simplified version of the state machine used to control the AI in the original Quake game)
 *

 *  var monsterSM = new StateMachine()
 *  monsterSM.addState("idle",{enter:this.onIdle, from:["smash", "punch", "missle attack"]})
 *  monsterSM.addState("attack",{enter:this.onAttack, from:"idle"})
 *  monsterSM.addState("melee attack",{parent:"attack", enter:this.onMeleeAttack, from:"attack"})
 *  monsterSM.addState("smash",{parent:"melee attack", enter:this.onSmash})
 *  monsterSM.addState("punch",{parent:"melee attack", enter:this.onPunch})
 *  monsterSM.addState("missle attack",{parent:"attack", enter:this.onMissle})
 *  monsterSM.addState("die",{enter:this.onDead, from:["smash", "punch", "missle attack"]})
 *
 *  monsterSM.initialState = "idle"
 *

*/
export default class StateMachine {
	_state:string;
	_states:Object;
	parentState:State;
	parentStates:Array<State>;
	path:Array<number>;

  constructor(){
    this._states = {};
    this.parentStates = [];
    this.path = [];

  }

	emit(){
		emitter.emit(...arguments);
	}

	on(){
		emitter.on(...arguments);
	}

	off(){
		emitter.off(...arguments);
	}

  hasState(stateName:string):boolean {
    return Object.keys(this._states).indexOf(stateName) !== -1;
  }

  /**
   * Adds a new state
   * stateName	The name of the new State
   * stateData	An objct containing state enter and exit callbacks and allowed states to transition from
   * The "from" property can be a string or and array with the state names or * to allow any transition
  **/
  addState(stateName:string, stateData:Object = {}):void {
    if(this.hasState(stateName)){
      console.log("[StateMachine] Overriding existing state " + stateName);
    }

    this._states[stateName] = new State(stateName, stateData.from, stateData.enter, stateData.exit, this._states[stateData.parent]);
  }

  /**
   * Sets the first state, calls enter callback and dispatches TRANSITION_COMPLETE
   * These will only occour if no state is defined
   * stateName	The name of the State
  **/
  set initialState(stateName:string):void {
    if (this._state === undefined && this.hasState(stateName)) {
      this._state = stateName;

      // Invoke the enter callback for all parent states down from the root parent of the state we're transitioning into

      if(typeof this._states[this._state].root !== "undefined" && this._states[this._state].root !== null){
        let parentStates:Array<State> = this._states[this._state].parents;
        for (parentState of parentStates) {

          if(parentState.enter !== null && typeof parentState.enter === "function"){
            parentState.enter.call(this, {toState: stateName});
          }
        };
      }

      // Invoke the enter callback of the state we're transitioning into
      if(this._states[this._state].enter !== null && typeof this._states[this._state].enter === "function"){
        this._states[this._state].enter.call(this, {currentState: this._state});
      }

      this.emit(TRANSITION_COMPLETE_EVENT, {toState:stateName});
    }
  }

	/**
	 *	Getters for the current state and for the Dictionary of states
	 */
	get state():string {
		return this._states[this._state];
	}

	get states():Object {
		return this._states;
	}

	getStateByName(name:string):any	{
		for (state of this._states) {
			if(state.name === name){
				return state;
			}
		}
		return null;
	}

	/**
	 * Verifies if a transition can be made from the current state to the state passed as param
	 * stateName	The name of the State
	**/
	canChangeStateTo(stateName:string):boolean {
		return (stateName !== this._state && ( this._states[stateName].from.indexOf(this._state)!== -1) || this._states[stateName].from === '*' );
	}

	/**
	 * Discovers the how many "exits" and how many "enters" are there between two
	 * given states and returns an array with these two integers
	 * stateFrom The state to exit
	 * stateTo The state to enter
	**/
	findPath(stateFrom:string, stateTo:string):Array<number> {
		// Verifies if the states are in the same "branch" or have a common parent
		let fromState:State = this._states[stateFrom];
		let c:number = 0;
		let d:number = 0;
		while (fromState)
		{
			d=0;
			let toState:State = this._states[stateTo];
			while (toState)
			{
				if(fromState == toState)
				{
					// They are in the same brach or have a common parent Common parent
					return [c,d];
				}
				d++;
				toState = toState.parent;
			}
			c++;
			fromState = fromState.parent;
		}
		// No direct path, no commom parent: exit until root then enter until element
		return [c,d];
	}

	/**
	 * Changes the current state
	 * This will only be done if the intended state allows the transition from the current state
	 * Changing states will call the exit callback for the exiting state and enter callback for the entering state
	 * stateTo	The name of the state to transition to
	**/
	changeState(stateTo:string):void {
		// If there is no state that maches stateTo
		if (!this.hasState(stateTo)){
			console.warn("[StateMachine] Cannot make transition: State "+ stateTo +" is not defined");
			return;
		}

		// If current state is not allowed to make this transition
		if(!this.canChangeStateTo(stateTo))
		{
			console.warn("[StateMachine] Transition to "+ stateTo +" denied");
			this.emit(TRANSITION_DENIED_EVENT, {
				fromState:this._state,
				toState:stateTo,
				allowedStates: this._states[stateTo].from
			});
			return;
		}

		// call exit and enter callbacks (if they exits)
		let path:Array<number> = this.findPath(this._state,stateTo);
		if(path[0]>0){
			if(this._states[this._state].exit !== null && typeof this._states[this._state].exit === "function"){
				this._states[this._state].exit.call(null,{currentState: this._state});
			};

			let parentState:State = this._states[this._state];

			for(let i:number=0; i<path[0]-1; i++)
			{
				parentState = parentState.parent;
				if(parentState.exit !== null && typeof parentState.exit === "function"){
					parentState.exit.call(null,{currentState: parentState.name});
				}
			}
		}
		let oldState:String = this._state;
		this._state = stateTo;
		if(path[1]>0)
		{
			if(typeof this._states[stateTo].root !== "undefined" && this._states[stateTo].root !== null){
				let parentStates:Array<State> = this._states[stateTo].parents;
				for(var k:number = path[1]-2; k>=0; k--){
					if(typeof parentStates[k] !== "undefined" &&
					parentStates[k] !== null &&
					parentStates[k].enter !== null &&
					typeof parentStates[k].enter === "function"){
						parentStates[k].enter.call(null,{currentState: parentStates[k].name});
					}
				}
			}
			if(this._states[this._state].enter !== null && typeof this._states[this._state].enter === "function"){
				this._states[this._state].enter.call(null,{currentState: this._state});
			}
		}
		console.log("[StateMachine] State Changed to " + this._state);

		// Transition is complete. dispatch TRANSITION_COMPLETE
		this.emit(TRANSITION_COMPLETE_EVENT, {fromState:oldState, toState:stateTo});
	}
}
<|endoftext|>


<commit_before>"use strict";

let EventEmitter = require("events");
let moment = require("moment");
let util = require("util");
let Command = require("../core/commands").Command;

class Polls {
  constructor(database) {
    this.events = new EventEmitter;
    this.db = database;
    this.activePoll = null;
  }

  create(question, options, expires, user) {
    return new Promise((resolve, reject) => {
      if (this.activePoll) {
        throw new Error("Cannot start a new poll when there is another one active");
      }

      this.activePoll = new Poll(question, options, expires, user);
      let col_sql = options.map((option, i) => "option_" + ++i);
      let pm_sql = options.map((option, i) => "$option_" + ++i);

      let sql = util.format("INSERT INTO polls (question, %s, expires, user, nick) \
        VALUES ($question, %s, $expires, $user, $nick)", col_sql, pm_sql);

      let params = {
        $question: question,
        $user: user.user,
        $nick: user.nick,
        // $created: this.activePoll.created,
        $expires: this.activePoll.expires,
      };

      options.forEach((option, i) => {
        params["$option_" + ++i] = option;
      });

      // NOTE: Cannot use an arrow function as we need to access the context for lastID.
      let self = this;
      this.db.run(sql, params, function(error) {
        if (error) {
          self.activePoll = null;
          return reject(error);
        }
        self.activePoll.id = this.lastID;
        self.watchActivePoll();
        return resolve();
      });
    });
  }

  vote(vote, user) {
    if (!this.activePoll) {
      return Promise.reject(new Error("There is no active poll"));
    }
    let options = this.activePoll.options.map(option => option.toLowerCase());
    if (options.indexOf(vote.toLowerCase()) == -1) {
      return Promise.reject(new Error(util.format("Invalid option '%s'", vote)));
    }
    return new Promise((resolve, reject) => {
      let sql = "INSERT INTO polls_votes (question_id, vote, user, nick) VALUES ($question, $vote, $user, $nick)";
      let params = {
        $question: this.activePoll.id,
        $vote: $vote,
        $user: user.user,
        $nick: user.nick,
      };
      this.db.run(sql, params, error => {
        error ? reject(new Error("You have already voted in this poll")) : resolve();
      });
    });
  }

  wait() {
    if (this.activePoll) {
      return this.activePoll.wait().then(stats => {
        this.activePoll = null;
        return stats;
      });
    } else {
      return Promise.reject(new Error("No active poll"));
    }
  }

  _initDatabase() {
    this.db.serialize(() => {
      this.db.run("CREATE TABLE IF NOT EXISTS polls( \
        id INTEGER PRIMARY KEY AUTOINCREMENT, \
        question TEXT NOT NULL, \
        option_1 TEXT NOT NULL, \
        option_2 TEXT NOT NULL, \
        option_3 TEXT, \
        option_4 TEXT, \
        option_5 TEXT, \
        option_6 TEXT, \
        user TEXT NOT NULL, \
        nick TEXT NOT NULL, \
        created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, \
        expires TIMESTAMP NOT NULL \
      )");
      this.db.run("CREATE TABLE IF NOT EXISTS polls_votes( \
        id INTEGER PRIMARY KEY AUTOINCREMENT, \
        question_id INTEGER NOT NULL, \
        vote TEXT NOT NULL, \
        user TEXT NOT NULL, \
        nick TEXT NOT NULL, \
        created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, \
        UNIQUE(question_id, user) \
      )");
    });
  }
}

class Poll {
  constructor(question, options, expires, user) {
    this.id = null;
    this.created = new Date;
    this.question = question.replace(/\??$/, "?");
    this.options = options;
    this.expires = expires;
    this.user = user;
    this.votes = [];
  }

  wait() {
    return new Promise((resolve, reject) => {
      let diff = moment(this.expires).diff();

      setTimeout(() => {
        resolve(this.stats);
      }, diff);
    });
  }

  get stats() {
    return new Stats(this)
  }
}

class Stats {
  constructor(poll) {
    this.poll = poll;
  }

  toString() {
    let cache = new Map(this.poll.options.map(option => [option.toLowerCase(), option]));
    let votes = new Map(this.poll.options.map(option => [option, 0]));

    this.votes.forEach(vote => {
      let key = cache.get(vote.toLowerCase());
      votes.set(key, votes.get(key) + 1);
    });

    let output = [...votes.items()]
      .sort((a, b) => a[1] - b[1])
      .map(item => item.join(": "))
      .join(", ");
    return output;
  }

  get votes() {
    return this.poll.votes;
  }
}

exports.configure = (connection, modules) => {
  let commands = connection.commands;
  let polls = new Polls(modules.get("database"));
  let config = connection.config.modules.polls;

  polls._initDatabase();

  connection.addCommand("poll", Command.ALLOW_AUTHED, (user, params, message) => {
    let options = params.slice();
    let question = options.shift();
    let expires = moment().add(options.pop(), "seconds");

    if (!question) {
      return Promise.reject(new Error("Usage: !poll question [options...] [expires]"));
    }

    if (!expires.isAfter(new Date)) {
      expires = moment().add(config.expires, "seconds");
    }

    if (!options.length) {
      options = config.options.slice();
    }

    return user.whois()
      .then(info => polls.create(question, options, expires, info))
      .then(poll => {
        poll.options.forEach(option => {
          commands.addCommand(option.toLowerCase(), (user, params) => {
            user.whois().then(info => {
              return polls.vote(params.shift(), info).then(() => { }, reject);
            })
          });
        });

        poll.wait().then(stats => {
          message.reply(["Poll finished!", stats.toString()]);
          poll.options.forEach(option => commands.delete(option.toLowerCase()));
        });

        return Promise.resolve("Poll: " + poll.question);
      });
  });

  return polls;
};
<commit_msg>Convert Date to timestamp string<commit_after>"use strict";

let EventEmitter = require("events");
let moment = require("moment");
let util = require("util");
let Command = require("../core/commands").Command;

class Polls {
  constructor(database) {
    this.events = new EventEmitter;
    this.db = database;
    this.activePoll = null;
  }

  create(question, options, expires, user) {
    return new Promise((resolve, reject) => {
      if (this.activePoll) {
        throw new Error("Cannot start a new poll when there is another one active");
      }

      this.activePoll = new Poll(question, options, expires, user);
      let col_sql = options.map((option, i) => "option_" + ++i);
      let pm_sql = options.map((option, i) => "$option_" + ++i);

      let sql = util.format("INSERT INTO polls (question, %s, expires, user, nick) \
        VALUES ($question, %s, $expires, $user, $nick)", col_sql, pm_sql);

      let params = {
        $question: question,
        $user: user.user,
        $nick: user.nick,
        // $created: this.activePoll.created,
        $expires: moment(this.activePoll.expires).format("YYYY-MM-DD HH:mm:ss"),
      };

      options.forEach((option, i) => {
        params["$option_" + ++i] = option;
      });

      // NOTE: Cannot use an arrow function as we need to access the context for lastID.
      let self = this;
      this.db.run(sql, params, function(error) {
        if (error) {
          self.activePoll = null;
          return reject(error);
        }
        self.activePoll.id = this.lastID;
        self.watchActivePoll();
        return resolve();
      });
    });
  }

  vote(vote, user) {
    if (!this.activePoll) {
      return Promise.reject(new Error("There is no active poll"));
    }
    let options = this.activePoll.options.map(option => option.toLowerCase());
    if (options.indexOf(vote.toLowerCase()) == -1) {
      return Promise.reject(new Error(util.format("Invalid option '%s'", vote)));
    }
    return new Promise((resolve, reject) => {
      let sql = "INSERT INTO polls_votes (question_id, vote, user, nick) VALUES ($question, $vote, $user, $nick)";
      let params = {
        $question: this.activePoll.id,
        $vote: $vote,
        $user: user.user,
        $nick: user.nick,
      };
      this.db.run(sql, params, error => {
        error ? reject(new Error("You have already voted in this poll")) : resolve();
      });
    });
  }

  wait() {
    if (this.activePoll) {
      return this.activePoll.wait().then(stats => {
        this.activePoll = null;
        return stats;
      });
    } else {
      return Promise.reject(new Error("No active poll"));
    }
  }

  _initDatabase() {
    this.db.serialize(() => {
      this.db.run("CREATE TABLE IF NOT EXISTS polls( \
        id INTEGER PRIMARY KEY AUTOINCREMENT, \
        question TEXT NOT NULL, \
        option_1 TEXT NOT NULL, \
        option_2 TEXT NOT NULL, \
        option_3 TEXT, \
        option_4 TEXT, \
        option_5 TEXT, \
        option_6 TEXT, \
        user TEXT NOT NULL, \
        nick TEXT NOT NULL, \
        created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, \
        expires TIMESTAMP NOT NULL \
      )");
      this.db.run("CREATE TABLE IF NOT EXISTS polls_votes( \
        id INTEGER PRIMARY KEY AUTOINCREMENT, \
        question_id INTEGER NOT NULL, \
        vote TEXT NOT NULL, \
        user TEXT NOT NULL, \
        nick TEXT NOT NULL, \
        created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, \
        UNIQUE(question_id, user) \
      )");
    });
  }
}

class Poll {
  constructor(question, options, expires, user) {
    this.id = null;
    this.created = new Date;
    this.question = question.replace(/\??$/, "?");
    this.options = options;
    this.expires = expires;
    this.user = user;
    this.votes = [];
  }

  wait() {
    return new Promise((resolve, reject) => {
      let diff = moment(this.expires).diff();

      setTimeout(() => {
        resolve(this.stats);
      }, diff);
    });
  }

  get stats() {
    return new Stats(this)
  }
}

class Stats {
  constructor(poll) {
    this.poll = poll;
  }

  toString() {
    let cache = new Map(this.poll.options.map(option => [option.toLowerCase(), option]));
    let votes = new Map(this.poll.options.map(option => [option, 0]));

    this.votes.forEach(vote => {
      let key = cache.get(vote.toLowerCase());
      votes.set(key, votes.get(key) + 1);
    });

    let output = [...votes.items()]
      .sort((a, b) => a[1] - b[1])
      .map(item => item.join(": "))
      .join(", ");
    return output;
  }

  get votes() {
    return this.poll.votes;
  }
}

exports.configure = (connection, modules) => {
  let commands = connection.commands;
  let polls = new Polls(modules.get("database"));
  let config = connection.config.modules.polls;

  polls._initDatabase();

  connection.addCommand("poll", Command.ALLOW_AUTHED, (user, params, message) => {
    let options = params.slice();
    let question = options.shift();
    let expires = moment().add(options.pop(), "seconds");

    if (!question) {
      return Promise.reject(new Error("Usage: !poll question [options...] [expires]"));
    }

    if (!expires.isAfter(new Date)) {
      expires = moment().add(config.expires, "seconds");
    }

    if (!options.length) {
      options = config.options.slice();
    }

    return user.whois()
      .then(info => polls.create(question, options, expires, info))
      .then(poll => {
        poll.options.forEach(option => {
          commands.addCommand(option.toLowerCase(), (user, params) => {
            user.whois().then(info => {
              return polls.vote(params.shift(), info).then(() => { }, reject);
            })
          });
        });

        poll.wait().then(stats => {
          message.reply(["Poll finished!", stats.toString()]);
          poll.options.forEach(option => commands.delete(option.toLowerCase()));
        });

        return Promise.resolve("Poll: " + poll.question);
      });
  });

  return polls;
};
<|endoftext|>


<commit_before>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CoursesTitle");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CoursesHeader");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    gvm.addAvailableLocations = function(id, name) {
        var selectObject = {id: id, locationName: name};
        gvm.availableLocations.push(selectObject);
    }
    gvm.addAvailableTrainings = function(id, name) {
        var selectObject = {id: id, trainingName: name};
        gvm.availableTrainings.push(selectObject);
    }

    gvm.addAvailableCourses = function(id, name) {
        var selectObject = {id: id, courseName: name};
        gvm.availableCourses.push(selectObject);
    }

    gvm.clearAll = function() {
        gvm.availableLocations.removeAll();
        gvm.availableTrainings.removeAll();
        gvm.availableCourses.removeAll();
    }
}

function loadAllSelects($locationid, $trainingid)
{
    $.getJSON('/api/locations', function(data){
        // Load table data
        $.each(data, function(i, item) {
            viewModel.addAvailableLocations(item.id, item.name);
        });
    });
    $.getJSON('/api/trainings/' + $locationid, function(data){
        // Load table data
        $.each(data, function(i, item) {
            viewModel.addAvailableTrainings(item.id, item.name);
        });
    });
    $.getJSON('/api/courses/' + $trainingid, function(data) {
        $.each(data, function(i, item) {
            viewModel.addAvailableCourses(item.id, item.name);
        });
    });
}

function initPage() {
    loadAllSelects(1,1);

    $(".location").on("change", function(event) {
        loadAllSelects(this.val(), 1)
    });
}<commit_msg>coursespage updated<commit_after>// View model for the courses page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("CoursesTitle");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CoursesHeader");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    gvm.addAvailableLocations = function(id, name) {
        var selectObject = {id: id, locationName: name};
        gvm.availableLocations.push(selectObject);
    }
    gvm.addAvailableTrainings = function(id, name) {
        var selectObject = {id: id, trainingName: name};
        gvm.availableTrainings.push(selectObject);
    }

    gvm.addAvailableCourses = function(id, name) {
        var selectObject = {id: id, courseName: name};
        gvm.availableCourses.push(selectObject);
    }

    gvm.clearAll = function() {
        gvm.availableLocations.removeAll();
        gvm.availableTrainings.removeAll();
        gvm.availableCourses.removeAll();
    }
}

function loadAllSelects($locationid, $trainingid)
{
    $.getJSON('/api/locations', function(data){
        // Load table data
        $.each(data, function(i, item) {
            viewModel.addAvailableLocations(item.id, item.name);
        });
    });
    $.getJSON('/api/trainings/' + $locationid, function(data){
        // Load table data
        $.each(data, function(i, item) {
            viewModel.addAvailableTrainings(item.id, item.name);
        });
    });
    $.getJSON('/api/courses/' + $trainingid, function(data) {
        $.each(data, function(i, item) {
            viewModel.addAvailableCourses(item.id, item.name);
        });
    });
}

function initPage() {
    loadAllSelects(1,1);

    $(".location").on("change", function(event) {
        alert("hallo");
        loadAllSelects(this.val(), 1)
    });
}<|endoftext|>


<commit_before>const ExtensionUtils = imports.misc.extensionUtils
const Main = imports.ui.main
const UPower = imports.gi.UPowerGlib

let batteryWatching, settingsWatching, settings, disabled

function show() {
  getBattery((proxy, icon) => {
    icon.show()
  })
}

function hide() {
  getBattery((proxy, icon) => {
    icon.hide()
  })
}

function update() {
  let hideOn = settings.get_int('hide-on')
  getBattery(proxy => {
    let isDischarging = proxy.State === UPower.DeviceState.DISCHARGING
    let isFullyCharged = proxy.State === UPower.DeviceState.FULLY_CHARGED
    if (proxy.Type !== UPower.DeviceKind.BATTERY) {
      show()
    } else if (isFullyCharged) {
      hide()
    } else if (proxy.Percentage >= hideOn && !isDischarging) {
      hide()
    } else {
      show()
    }
  })
}

function getBattery(callback) {
  if (Main.panel.statusArea.quickSettings) {
    let system = Main.panel.statusArea.quickSettings._system
    if (system._systemItem._powerToggle) {
      callback(system._systemItem._powerToggle._proxy, system)
    }
  }
  else {
    let menu = Main.panel.statusArea.aggregateMenu
    if (menu && menu._power) {
      callback(menu._power._proxy, menu._power)
    }
  }
}

function init() {
  disabled = true
}

function enable() {
  if (disabled) {
    disabled = false
    settings = ExtensionUtils.getSettings('ru.sitnik.autohide-battery')
    settingsWatching = settings.connect('changed::hide-on', update)
    getBattery(proxy => {
      batteryWatching = proxy.connect('g-properties-changed', update)
    })
    update()
  }
}

function disable() {
  if (Main.sessionMode.currentMode !== 'unlock-dialog') {
    disabled = true
    if (settings) settings.disconnect(settingsWatching)
    getBattery(proxy => {
      proxy.disconnect(batteryWatching)
    })
    show()
  }
}
<commit_msg>Fix code format<commit_after>const ExtensionUtils = imports.misc.extensionUtils
const Main = imports.ui.main
const UPower = imports.gi.UPowerGlib

let batteryWatching, settingsWatching, settings, disabled

function show() {
  getBattery((proxy, icon) => {
    icon.show()
  })
}

function hide() {
  getBattery((proxy, icon) => {
    icon.hide()
  })
}

function update() {
  let hideOn = settings.get_int('hide-on')
  getBattery(proxy => {
    let isDischarging = proxy.State === UPower.DeviceState.DISCHARGING
    let isFullyCharged = proxy.State === UPower.DeviceState.FULLY_CHARGED
    if (proxy.Type !== UPower.DeviceKind.BATTERY) {
      show()
    } else if (isFullyCharged) {
      hide()
    } else if (proxy.Percentage >= hideOn && !isDischarging) {
      hide()
    } else {
      show()
    }
  })
}

function getBattery(callback) {
  if (Main.panel.statusArea.quickSettings) {
    let system = Main.panel.statusArea.quickSettings._system
    if (system._systemItem._powerToggle) {
      callback(system._systemItem._powerToggle._proxy, system)
    }
  } else {
    let menu = Main.panel.statusArea.aggregateMenu
    if (menu && menu._power) {
      callback(menu._power._proxy, menu._power)
    }
  }
}

function init() {
  disabled = true
}

function enable() {
  if (disabled) {
    disabled = false
    settings = ExtensionUtils.getSettings('ru.sitnik.autohide-battery')
    settingsWatching = settings.connect('changed::hide-on', update)
    getBattery(proxy => {
      batteryWatching = proxy.connect('g-properties-changed', update)
    })
    update()
  }
}

function disable() {
  if (Main.sessionMode.currentMode !== 'unlock-dialog') {
    disabled = true
    if (settings) settings.disconnect(settingsWatching)
    getBattery(proxy => {
      proxy.disconnect(batteryWatching)
    })
    show()
  }
}
<|endoftext|>


<commit_before>import React, { PropTypes, Component } from 'react';
import { Link } from 'react-router';
import R from 'ramda';
import {Grid, Col, Row} from 'react-flexbox-grid/lib';

import Header from './Header';
import getPosts from '../helpers/getPosts';
import urlSlug from '../helpers/urlSlug';

export default class App extends Component {
  static propTypes = {
    children: PropTypes.element.isRequired,
    routes: PropTypes.array.isRequired,
  };

  generateMapMenu() {
    let path = '';

    function nextPath(route) {
      path += (
        (path.slice(-1) === '/' ? '' : '/') +
        (route.path === '/' ? '' : route.path)
      );
      return path;
    }

    return (
      this.props.routes.filter(route => route.mapMenuTitle)
        .map((route, index, array) => (

            <Link to={nextPath(route)}>{route.mapMenuTitle}</Link>
            {(index + 1) < array.length && ' / '}

        ))
    );
  }

  getCategories() {
    const posts = getPosts();
    const val =(o) => R.path(['category'], o);
    return R.uniq(R.map(val, posts));
  }

  generateCategoriesUrls() {
    const categories = this.getCategories();
    return (
        categories.map(c => (

              <Link to={`/categories/${urlSlug(c)}/`}>{c}</Link>

        ))
      )
  }

  render () {
    const { children } = this.props;
    return (

          <Grid>
            <Row>
              <Col xs={0} sm={0} md={3} lg={2}>

Категориялар

                  {this.generateCategoriesUrls()}

              </Col>
              <Col xsOffset={1} xs={11} smOffset={1} sm={11} mdOffset={0} md={9} lgOffset={0} lg={10}>

                  {this.generateMapMenu()}

                {children}
              </Col>
            </Row>
          </Grid>

    );
  }
}
<commit_msg>Add getCategoryBySlug method<commit_after>import React, { PropTypes, Component } from 'react';
import { Link } from 'react-router';
import R from 'ramda';
import {Grid, Col, Row} from 'react-flexbox-grid/lib';

import Header from './Header';
import getPosts from '../helpers/getPosts';
import urlSlug from '../helpers/urlSlug';

export default class App extends Component {
  static propTypes = {
    children: PropTypes.element.isRequired,
    routes: PropTypes.array.isRequired,
  };

  generateMapMenu() {
    let path = '';

    function nextPath(route) {
      path += (
        (path.slice(-1) === '/' ? '' : '/') +
        (route.path === '/' ? '' : route.path)
      );
      return path;
    }

    return (
      this.props.routes.filter(route => route.mapMenuTitle)
        .map((route, index, array) => (

            <Link to={nextPath(route)}>{route.mapMenuTitle}</Link>
            {(index + 1) < array.length && ' / '}

        ))
    );
  }

  getCategoryBySlug(slug) {
    const categories = this.getCategories()
    let mapping = {}
    for (let i = 0; i < categories.length; i++) {
      const currentCategory = categories[i]
      mapping[urlSlug(currentCategory)] = currentCategory
    }
    return mapping[slug]
  }

  getCategories() {
    const posts = getPosts();
    const val =(o) => R.path(['category'], o);
    return R.uniq(R.map(val, posts));
  }

  generateCategoriesUrls() {
    const categories = this.getCategories();
    return (
        categories.map(c => (

              <Link to={`/categories/${urlSlug(c)}/`}>{c}</Link>

        ))
      )
  }

  render () {
    const { children } = this.props;
    return (

          <Grid>
            <Row>
              <Col xs={0} sm={0} md={3} lg={2}>

Категориялар

                  {this.generateCategoriesUrls()}

              </Col>
              <Col xsOffset={1} xs={11} smOffset={1} sm={11} mdOffset={0} md={9} lgOffset={0} lg={10}>

                  {this.generateMapMenu()}

                {children}
              </Col>
            </Row>
          </Grid>

    );
  }
}
<|endoftext|>