<commit_before>import Ember from 'ember';
import ListFormController from 'ember-flexberry/controllers/i-i-s-caseberry-logging-objects-application-log-l';
const { getOwner } = Ember;

export default ListFormController.extend({
  /**
  Flexberry Logging Service

   @property flexberryLoggingService
   @type String[]
   */
  flexberryLoggingService: Ember.inject.service('flexberry-logging'),

  _messageNumber: 0,

  logLevel: 0,

  /**
    Available test application level settings

    @property settings
    @type String[]
   */
  settings: [],

  /**
   Default choise in settings

   @property text
   @type String[]
   */
  text: '',

  /**
   List buttons describers for Supported actions
   */
  customButtons:  [{
      buttonName: 'Assert',
      buttonAction: 'assertAction',
      buttonClasses: 'ui orange button'
    }, {
      buttonName: 'Error',
      buttonAction: 'errorAction',
      buttonClasses: 'ui orange button'
    }, {
      buttonName: 'Throw',
      buttonAction: 'throwAction',
      buttonClasses: 'ui orange button'
    }, {
      buttonName: 'Warn',
      buttonAction: 'warnAction',
      buttonClasses: 'ui teal button'

    }, {
      buttonName: 'Log',
      buttonAction: 'logAction',
      buttonClasses: 'ui teal button'
    }, {
      buttonName: 'Info',
      buttonAction: 'infoAction',
      buttonClasses: 'ui teal button'
    }, {
      buttonName: 'Debug',
      buttonAction: 'debugAction',
      buttonClasses: 'ui yellow button'

    }, {
      buttonName: 'Deprecation',
      buttonAction: 'deprecationAction',
      buttonClasses: 'ui yellow button'
    }],

  _router: undefined,

  /**
   *    Selected jQuery object, containing HTML of confirm modal dialog.
   *
   *    @property confirmModalDialog
   *    @type Object
   *    @default null
   */
  confirmModalDialog: undefined,

  /**
   *    Content to be displayed in confirm modal dialog.
   *    It will be displayed only if some confirm needs.
   *
   *    @property confirmModalDialogContent
   *    @type String
   *    @default 't('components.flexberry-file.confirm-dialog-content')'
   */
  confirmModalDialogContent: '',

<<<<<<< HEAD
  /**
=======
/**
>>>>>>> 2826c5db4fedf5bc40671c07987bd72ff54e8b88
   *    Category to be passed in action confirm modal dialog.
   *
   *    @property confirmModalDialogCategory
   *    @type String
   *    @default ''
   */
  confirmModalDialogCategory: '',

  init() {
    this._router = getOwner(this).lookup('router:main');
    this.logLevel = this.get('flexberryLoggingService').flexberryLogLevel;
    let enumsLoglevel = this.get('flexberryLoggingService').enumsLoglevel;
    this.settings[0] = '0: OFF';
    for (let level = 1; level < enumsLoglevel.length; level++) {
      this.settings[level] = level + ': ' + enumsLoglevel.slice(1, level + 1).join('s, ') + 's';
    }

    this.text = this.settings[this.logLevel];
  },

  /**
    Supported actions
 */
  actions: {
    /**
     j hghhjl*k

     */
    setLogLevel(choosed) {
      this.logLevel = parseInt(choosed.substr(0, 1));
      this.get('flexberryLoggingService').flexberryLogLevel = this.logLevel;
    },

    /**
jhghhjlk

     */
    assertAction() {
      if (this.logLevel < 1) {
        this.showConfirmModalDialog('Assert');
        return;
      }

      this.makeAssert();
    },

    /**
jhghhjlk

     */
    errorAction() {
      if (this.logLevel < 1) {
        this.showConfirmModalDialog('Error');
        return;
      }

      this.makeError();
    },

    /**
     j hghh*jlk

     */
    throwAction() {
      if (this.logLevel < 1) {
        this.showConfirmModalDialog('Throw');
        return;
      }

      this.makeThrow();
    },

    /**
     * jhghhjlk
     *
     */
    deprecationAction() {
      if (this.logLevel < 6) {
        this.showConfirmModalDialog('Deprecation');
        return;
      }

      this.makeDeprecation();
    },

    /**
     * jhghhjlk
     *
     */
    debugAction() {
      if (this.logLevel < 5) {
        this.showConfirmModalDialog('Debug');
        return;
      }

      this.makeDebug();
    },

    /**
jhghhjlk

  */
    infoAction() {
      if (this.logLevel < 4) {
        this.showConfirmModalDialog('Info');
        return;
      }

      this.makeInfo();
    },
    /**
jhghhjlk

     */
    logAction() {
      if (this.logLevel < 3) {
        this.showConfirmModalDialog('Log');
        return;
      }

      this.makeLog();
    },

    /**
     * jhghhjlk
     *
     */
    warnAction() {
      if (this.logLevel < 2) {
        this.showConfirmModalDialog('Warn');
        return;
      }

      this.makeWarn();
    },

    confirmed(category) {
      switch (category) {
        case 'Assert':
          this.makeAssert();
          break;
        case 'Error':
          this.makeError();
          break;
        case 'Throw':
          this.makeThrow();
          break;
        case 'Warn':
          this.makeWarn();
          break;
        case 'Deprecation':
          this.makeDeprecation();
          break;
        case 'Debug':
          this.makeDebug();
          break;
        case 'Info':
          this.makeInfo();
          break;
        case 'Log':
          this.makeLog();
          break;
        case 'Warn':
          this.makeWarn();
          break;
      }
    },

    /**
     *    Close confirm modal dialog.
     *
     *    @method hideConfirmModalDialog
     *    @param {String} confirmCaption Confirm caption (window header caption).
     *    @param {String} confirmContent Confirm content (window body content).
     *    @returns {String} Confirm content.
     */
    closeDialog() {
      if (this.confirmModalDialog === undefined) {
        return;
      }

      this.set('confirmModalDialogContent', undefined);
      this.set('confirmModalDialogCategory', undefined);
      this.confirmModalDialog.modal('hide');
    }

  },

  makeAssert() {
    let message = this._getMessageNumber() + 'Assert invocation testing';
    try {
      Ember.assert(message, false);
    } catch (e) {
      Ember.Logger.error(e);
      this._router.router.refresh();
    }

  },

  makeError() {
    try {
      eval('error_operator');
    } catch (e) {
      e.message = this._getMessageNumber() + e.message;
      Ember.Logger.error(e);
      this._router.router.refresh();
    }

  },

  makeThrow() {
    try {
      let message = this._getMessageNumber() + 'Throw invocation testing';
      throw new Error(message);
    } catch (e) {
      Ember.Logger.error(e);
      this._router.router.refresh();
    }

  },

  makeDeprecation() {
    let message = 'DEPRECATION:' + this._getMessageNumber() + 'Deprecation invocation testing';
    Ember.Logger.warn(message);
    this._router.router.refresh();
  },

  makeDebug() {
    let message = this._getMessageNumber() + 'Debug invocation testing';
    Ember.Logger.debug(message);
    this._router.router.refresh();
  },

  makeInfo() {
    let message = this._getMessageNumber() + 'Info invocation testing';
    Ember.Logger.info(message);
    this._router.router.refresh();
  },

  makeLog() {
    let message = this._getMessageNumber() + 'Log invocation testing';
    Ember.Logger.log(message);
    this._router.router.refresh();
  },

  makeWarn() {
    let message = this._getMessageNumber() + 'Warning invocation testing';
    Ember.Logger.warn(message);
    this._router.router.refresh();
  },

  /**
   *    Shows confirm modal dialog.
   *
   *    @method showConfirmModalDialog
   *    @param {String} Confirm category
   *    @returns {String} Confirm content.
   */
  showConfirmModalDialog(category) {
    if (this.confirmModalDialog === undefined) {
      this.confirmModalDialog = Ember.$('.application-log-modal-dialog');
      this.confirmModalDialog.modal('setting', 'closable', false);
    }

    let confirmContent = 'Текущий уровень отладки (' +
      this.logLevel +
      ') не обеспечивает удаленное логирование сообщений категории ' +
      category +
      '. Продолжить?';
    this.set('confirmModalDialogContent', confirmContent);
    this.set('confirmModalDialogCategory', category);
    this.confirmModalDialog.modal('show');
    return confirmContent;
  },

  _getMessageNumber() {
    this._messageNumber += 1;
    let ret =  this.get('moment').moment().format('hh:mm:ss a') + ' №' + this._messageNumber + ': ';
    return ret;
  }
});
<commit_msg>Style+<commit_after>import Ember from 'ember';
import ListFormController from 'ember-flexberry/controllers/i-i-s-caseberry-logging-objects-application-log-l';
const { getOwner } = Ember;

export default ListFormController.extend({
  /**
  Flexberry Logging Service

   @property flexberryLoggingService
   @type String[]
   */
  flexberryLoggingService: Ember.inject.service('flexberry-logging'),

  _messageNumber: 0,

  logLevel: 0,

  /**
    Available test application level settings

    @property settings
    @type String[]
   */
  settings: [],

  /**
   Default choise in settings

   @property text
   @type String[]
   */
  text: '',

  /**
   List buttons describers for Supported actions
   */
  customButtons:  [{
      buttonName: 'Assert',
      buttonAction: 'assertAction',
      buttonClasses: 'ui orange button'
    }, {
      buttonName: 'Error',
      buttonAction: 'errorAction',
      buttonClasses: 'ui orange button'
    }, {
      buttonName: 'Throw',
      buttonAction: 'throwAction',
      buttonClasses: 'ui orange button'
    }, {
      buttonName: 'Warn',
      buttonAction: 'warnAction',
      buttonClasses: 'ui teal button'

    }, {
      buttonName: 'Log',
      buttonAction: 'logAction',
      buttonClasses: 'ui teal button'
    }, {
      buttonName: 'Info',
      buttonAction: 'infoAction',
      buttonClasses: 'ui teal button'
    }, {
      buttonName: 'Debug',
      buttonAction: 'debugAction',
      buttonClasses: 'ui yellow button'

    }, {
      buttonName: 'Deprecation',
      buttonAction: 'deprecationAction',
      buttonClasses: 'ui yellow button'
    }],

  _router: undefined,

  /**
   *    Selected jQuery object, containing HTML of confirm modal dialog.
   *
   *    @property confirmModalDialog
   *    @type Object
   *    @default null
   */
  confirmModalDialog: undefined,

  /**
   *    Content to be displayed in confirm modal dialog.
   *    It will be displayed only if some confirm needs.
   *
   *    @property confirmModalDialogContent
   *    @type String
   *    @default 't('components.flexberry-file.confirm-dialog-content')'
   */
  confirmModalDialogContent: '',

  /**
   *    Category to be passed in action confirm modal dialog.
   *
   *    @property confirmModalDialogCategory
   *    @type String
   *    @default ''
   */
  confirmModalDialogCategory: '',

  init() {
    this._router = getOwner(this).lookup('router:main');
    this.logLevel = this.get('flexberryLoggingService').flexberryLogLevel;
    let enumsLoglevel = this.get('flexberryLoggingService').enumsLoglevel;
    this.settings[0] = '0: OFF';
    for (let level = 1; level < enumsLoglevel.length; level++) {
      this.settings[level] = level + ': ' + enumsLoglevel.slice(1, level + 1).join('s, ') + 's';
    }

    this.text = this.settings[this.logLevel];
  },

  /**
    Supported actions
 */
  actions: {
    /**
     j hghhjl*k

     */
    setLogLevel(choosed) {
      this.logLevel = parseInt(choosed.substr(0, 1));
      this.get('flexberryLoggingService').flexberryLogLevel = this.logLevel;
    },

    /**
jhghhjlk

     */
    assertAction() {
      if (this.logLevel < 1) {
        this.showConfirmModalDialog('Assert');
        return;
      }

      this.makeAssert();
    },

    /**
jhghhjlk

     */
    errorAction() {
      if (this.logLevel < 1) {
        this.showConfirmModalDialog('Error');
        return;
      }

      this.makeError();
    },

    /**
     j hghh*jlk

     */
    throwAction() {
      if (this.logLevel < 1) {
        this.showConfirmModalDialog('Throw');
        return;
      }

      this.makeThrow();
    },

    /**
     * jhghhjlk
     *
     */
    deprecationAction() {
      if (this.logLevel < 6) {
        this.showConfirmModalDialog('Deprecation');
        return;
      }

      this.makeDeprecation();
    },

    /**
     * jhghhjlk
     *
     */
    debugAction() {
      if (this.logLevel < 5) {
        this.showConfirmModalDialog('Debug');
        return;
      }

      this.makeDebug();
    },

    /**
jhghhjlk

  */
    infoAction() {
      if (this.logLevel < 4) {
        this.showConfirmModalDialog('Info');
        return;
      }

      this.makeInfo();
    },
    /**
jhghhjlk

     */
    logAction() {
      if (this.logLevel < 3) {
        this.showConfirmModalDialog('Log');
        return;
      }

      this.makeLog();
    },

    /**
     * jhghhjlk
     *
     */
    warnAction() {
      if (this.logLevel < 2) {
        this.showConfirmModalDialog('Warn');
        return;
      }

      this.makeWarn();
    },

    confirmed(category) {
      switch (category) {
        case 'Assert':
          this.makeAssert();
          break;
        case 'Error':
          this.makeError();
          break;
        case 'Throw':
          this.makeThrow();
          break;
        case 'Warn':
          this.makeWarn();
          break;
        case 'Deprecation':
          this.makeDeprecation();
          break;
        case 'Debug':
          this.makeDebug();
          break;
        case 'Info':
          this.makeInfo();
          break;
        case 'Log':
          this.makeLog();
          break;
        case 'Warn':
          this.makeWarn();
          break;
      }
    },

    /**
     *    Close confirm modal dialog.
     *
     *    @method hideConfirmModalDialog
     *    @param {String} confirmCaption Confirm caption (window header caption).
     *    @param {String} confirmContent Confirm content (window body content).
     *    @returns {String} Confirm content.
     */
    closeDialog() {
      if (this.confirmModalDialog === undefined) {
        return;
      }

      this.set('confirmModalDialogContent', undefined);
      this.set('confirmModalDialogCategory', undefined);
      this.confirmModalDialog.modal('hide');
    }

  },

  makeAssert() {
    let message = this._getMessageNumber() + 'Assert invocation testing';
    try {
      Ember.assert(message, false);
    } catch (e) {
      Ember.Logger.error(e);
      this._router.router.refresh();
    }

  },

  makeError() {
    try {
      eval('error_operator');
    } catch (e) {
      e.message = this._getMessageNumber() + e.message;
      Ember.Logger.error(e);
      this._router.router.refresh();
    }

  },

  makeThrow() {
    try {
      let message = this._getMessageNumber() + 'Throw invocation testing';
      throw new Error(message);
    } catch (e) {
      Ember.Logger.error(e);
      this._router.router.refresh();
    }

  },

  makeDeprecation() {
    let message = 'DEPRECATION:' + this._getMessageNumber() + 'Deprecation invocation testing';
    Ember.Logger.warn(message);
    this._router.router.refresh();
  },

  makeDebug() {
    let message = this._getMessageNumber() + 'Debug invocation testing';
    Ember.Logger.debug(message);
    this._router.router.refresh();
  },

  makeInfo() {
    let message = this._getMessageNumber() + 'Info invocation testing';
    Ember.Logger.info(message);
    this._router.router.refresh();
  },

  makeLog() {
    let message = this._getMessageNumber() + 'Log invocation testing';
    Ember.Logger.log(message);
    this._router.router.refresh();
  },

  makeWarn() {
    let message = this._getMessageNumber() + 'Warning invocation testing';
    Ember.Logger.warn(message);
    this._router.router.refresh();
  },

  /**
   *    Shows confirm modal dialog.
   *
   *    @method showConfirmModalDialog
   *    @param {String} Confirm category
   *    @returns {String} Confirm content.
   */
  showConfirmModalDialog(category) {
    if (this.confirmModalDialog === undefined) {
      this.confirmModalDialog = Ember.$('.application-log-modal-dialog');
      this.confirmModalDialog.modal('setting', 'closable', false);
    }

    let confirmContent = 'Текущий уровень отладки (' +
      this.logLevel +
      ') не обеспечивает удаленное логирование сообщений категории ' +
      category +
      '. Продолжить?';
    this.set('confirmModalDialogContent', confirmContent);
    this.set('confirmModalDialogCategory', category);
    this.confirmModalDialog.modal('show');
    return confirmContent;
  },

  _getMessageNumber() {
    this._messageNumber += 1;
    let ret =  this.get('moment').moment().format('hh:mm:ss a') + ' №' + this._messageNumber + ': ';
    return ret;
  }
});
<|endoftext|>


<commit_before>'use strict';

import React from 'react';
import {AppRegistry, asset, NativeModules, Pano, StyleSheet, Text, View} from 'react-vr';

const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');

class PressState extends React.Component {
  constructor() {
    super();
    this.state = {hasFocus: false};
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.pressed !== this.props.pressed) {
      return true;
    }
    if (nextState.hasFocus !== this.state.hasFocus) {
      return true;
    }
    return false;
  }

  render() {
    return (
      <View
        style={{
          flex: 1,
          flexDirection: 'row',
          backgroundColor: this.state.hasFocus ? '#333333' : 'black',
        }}
        onEnter={() => this.setState({hasFocus: true})}
        onExit={() => this.setState({hasFocus: false})}
      >
        <View style={{width: 0.5, height: 0.1}}>
          <Text style={{fontSize: 0.08, textAlign: 'center'}}>
            {this.props.id}
          </Text>
        </View>
        <View
          style={{
            width: 0.1,
            height: 0.1,
            backgroundColor: this.props.pressed ? 'blue' : 'black',
          }}
        />
      </View>
    );
  }
}

class SliderState extends React.Component {
  constructor() {
    super();
    this.state = {hasFocus: false};
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.value !== this.props.value) {
      return true;
    }
    if (nextState.hasFocus !== this.state.hasFocus) {
      return true;
    }
    return false;
  }

  render() {
    return (
      <View
        style={{
          flex: 1,
          flexDirection: 'row',
          backgroundColor: this.state.hasFocus ? '#333333' : 'black',
        }}
        onEnter={() => this.setState({hasFocus: true})}
        onExit={() => this.setState({hasFocus: false})}
      >
        <View style={{width: 0.5, height: 0.1}}>
          <Text style={{fontSize: 0.08, textAlign: 'center'}}>
            {this.props.id}
          </Text>
        </View>
        <View style={{width: 0.4, height: 0.1}}>
          <View
            style={{
              width: 0.4 * (this.props.value + 1) / 2,
              height: 0.1,
              backgroundColor: 'yellow',
            }}
          />
        </View>
      </View>
    );
  }
}

class ControllerState extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      buttons: [],
      axes: [],
    };

    RCTDeviceEventEmitter.addListener('onReceivedInputEvent', e => {
      if (e.type !== 'GamepadInputEvent' || this.props.controller.index !== e.gamepad) {
        return;
      }
      if (e.eventType === 'keydown') {
        const buttons = this.state.buttons.concat([]);
        buttons[e.button] = true;
        this.setState({buttons});
      } else if (e.eventType === 'keyup') {
        const buttons = this.state.buttons.concat([]);
        buttons[e.button] = false;
        this.setState({buttons});
      } else if (e.eventType === 'axismove') {
        const axes = this.state.axes.concat([]);
        axes[e.axis] = e.value;
        this.setState({axes});
      }
    });
  }

  render() {
    const style = {
      flex: 1,
      flexDirection: 'column',
      marginLeft: 0.1,
      marginRight: 0.1,
    };
    const buttons = [];
    for (let i = 0; i < this.props.controller.buttons; i++) {
      buttons.push(
        <PressState key={'btn' + i} id={'Btn ' + i} pressed={this.state.buttons[i] || false} />
      );
    }
    const axes = [];
    for (let i = 0; i < this.props.controller.axes; i++) {
      axes.push(<SliderState key={'axis' + i} id={'Axis ' + i} value={this.state.axes[i] || 0} />);
    }
    return (
      <View style={style}>
        {buttons}
        {axes}
      </View>
    );
  }
}

const ControllerList = controllers => {
  if (controllers.length < 1) {
    return (
      <View style={{backgroundColor: '#000000', padding: 0.2}}>
        <Text>No controllers</Text>
      </View>
    );
  }
  return controllers.map(c => <ControllerState key={c.index} controller={c} />);
};

class ControllerDemo extends React.Component {
  constructor() {
    super();

    this.state = {
      controllers: null,
    };

    NativeModules.ControllerInfo.getControllers().then(controllers => {
      this.setState({controllers: controllers});
    });

    RCTDeviceEventEmitter.addListener('controllerConnected', e => {
      console.log('controller', e);
      let added = false;
      const nextControllers = this.state.controllers.map(c => {
        if (c.index === e.index) {
          added = true;
          return e;
        } else {
          return c;
        }
      });
      if (!added) {
        nextControllers.push(e);
      }
      this.setState({controllers: nextControllers});
    });
  }

  render() {
    const controllers = this.state.controllers === null
      ? <Text style={styles.waiting}>Waiting...</Text>
      : <View style={styles.controllers}>
          {ControllerList(this.state.controllers)}
        </View>;
    return (
      <View style={{layoutOrigin: [0.5, 0.5]}}>
        <Pano source={asset('chess-world.jpg')} />
        {controllers}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  waiting: {
    backgroundColor: '#000000',
    fontSize: 0.3,
    layoutOrigin: [0.5, 0.5],
    paddingLeft: 0.2,
    paddingRight: 0.2,
    textAlign: 'center',
    textAlignVertical: 'center',
    transform: [{translate: [0, 0, -3]}],
  },
  controllers: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-around',
    transform: [{translate: [0, 0, -3]}],
  },
});

AppRegistry.registerComponent('ControllerDemo', () => ControllerDemo);
<commit_msg>Simplified shouldComponentUpdate function in Controller example<commit_after>'use strict';

import React from 'react';
import {AppRegistry, asset, NativeModules, Pano, StyleSheet, Text, View} from 'react-vr';

const RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');

class PressState extends React.Component {
  constructor() {
    super();
    this.state = {hasFocus: false};
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.pressed !== this.props.pressed) {
      return true;
    }
    return nextState.hasFocus !== this.state.hasFocus;
  }

  render() {
    return (
      <View
        style={{
          flex: 1,
          flexDirection: 'row',
          backgroundColor: this.state.hasFocus ? '#333333' : 'black',
        }}
        onEnter={() => this.setState({hasFocus: true})}
        onExit={() => this.setState({hasFocus: false})}
      >
        <View style={{width: 0.5, height: 0.1}}>
          <Text style={{fontSize: 0.08, textAlign: 'center'}}>
            {this.props.id}
          </Text>
        </View>
        <View
          style={{
            width: 0.1,
            height: 0.1,
            backgroundColor: this.props.pressed ? 'blue' : 'black',
          }}
        />
      </View>
    );
  }
}

class SliderState extends React.Component {
  constructor() {
    super();
    this.state = {hasFocus: false};
  }

  shouldComponentUpdate(nextProps, nextState) {
    if (nextProps.value !== this.props.value) {
      return true;
    }
    if (nextState.hasFocus !== this.state.hasFocus) {
      return true;
    }
    return false;
  }

  render() {
    return (
      <View
        style={{
          flex: 1,
          flexDirection: 'row',
          backgroundColor: this.state.hasFocus ? '#333333' : 'black',
        }}
        onEnter={() => this.setState({hasFocus: true})}
        onExit={() => this.setState({hasFocus: false})}
      >
        <View style={{width: 0.5, height: 0.1}}>
          <Text style={{fontSize: 0.08, textAlign: 'center'}}>
            {this.props.id}
          </Text>
        </View>
        <View style={{width: 0.4, height: 0.1}}>
          <View
            style={{
              width: 0.4 * (this.props.value + 1) / 2,
              height: 0.1,
              backgroundColor: 'yellow',
            }}
          />
        </View>
      </View>
    );
  }
}

class ControllerState extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      buttons: [],
      axes: [],
    };

    RCTDeviceEventEmitter.addListener('onReceivedInputEvent', e => {
      if (e.type !== 'GamepadInputEvent' || this.props.controller.index !== e.gamepad) {
        return;
      }
      if (e.eventType === 'keydown') {
        const buttons = this.state.buttons.concat([]);
        buttons[e.button] = true;
        this.setState({buttons});
      } else if (e.eventType === 'keyup') {
        const buttons = this.state.buttons.concat([]);
        buttons[e.button] = false;
        this.setState({buttons});
      } else if (e.eventType === 'axismove') {
        const axes = this.state.axes.concat([]);
        axes[e.axis] = e.value;
        this.setState({axes});
      }
    });
  }

  render() {
    const style = {
      flex: 1,
      flexDirection: 'column',
      marginLeft: 0.1,
      marginRight: 0.1,
    };
    const buttons = [];
    for (let i = 0; i < this.props.controller.buttons; i++) {
      buttons.push(
        <PressState key={'btn' + i} id={'Btn ' + i} pressed={this.state.buttons[i] || false} />
      );
    }
    const axes = [];
    for (let i = 0; i < this.props.controller.axes; i++) {
      axes.push(<SliderState key={'axis' + i} id={'Axis ' + i} value={this.state.axes[i] || 0} />);
    }
    return (
      <View style={style}>
        {buttons}
        {axes}
      </View>
    );
  }
}

const ControllerList = controllers => {
  if (controllers.length < 1) {
    return (
      <View style={{backgroundColor: '#000000', padding: 0.2}}>
        <Text>No controllers</Text>
      </View>
    );
  }
  return controllers.map(c => <ControllerState key={c.index} controller={c} />);
};

class ControllerDemo extends React.Component {
  constructor() {
    super();

    this.state = {
      controllers: null,
    };

    NativeModules.ControllerInfo.getControllers().then(controllers => {
      this.setState({controllers: controllers});
    });

    RCTDeviceEventEmitter.addListener('controllerConnected', e => {
      console.log('controller', e);
      let added = false;
      const nextControllers = this.state.controllers.map(c => {
        if (c.index === e.index) {
          added = true;
          return e;
        } else {
          return c;
        }
      });
      if (!added) {
        nextControllers.push(e);
      }
      this.setState({controllers: nextControllers});
    });
  }

  render() {
    const controllers = this.state.controllers === null
      ? <Text style={styles.waiting}>Waiting...</Text>
      : <View style={styles.controllers}>
          {ControllerList(this.state.controllers)}
        </View>;
    return (
      <View style={{layoutOrigin: [0.5, 0.5]}}>
        <Pano source={asset('chess-world.jpg')} />
        {controllers}
      </View>
    );
  }
}

const styles = StyleSheet.create({
  waiting: {
    backgroundColor: '#000000',
    fontSize: 0.3,
    layoutOrigin: [0.5, 0.5],
    paddingLeft: 0.2,
    paddingRight: 0.2,
    textAlign: 'center',
    textAlignVertical: 'center',
    transform: [{translate: [0, 0, -3]}],
  },
  controllers: {
    flex: 1,
    flexDirection: 'row',
    justifyContent: 'space-around',
    transform: [{translate: [0, 0, -3]}],
  },
});

AppRegistry.registerComponent('ControllerDemo', () => ControllerDemo);
<|endoftext|>


<commit_before>var Emitter = require('component-emitter');
var qs = require('qs');
var trim = require('trim-character');
var extend = require('extend-merge').extend;
var merge = require('extend-merge').merge;
var Route = require('./route');
var Transition = require('./transition');

class Router {

  constructor(options) {
    this._options = extend({
      basePath: '',
      handler: (name, routes) => {
        throw new Error('Missing dispatching handler, you need to define a dispatching handler.');
      },
      interval: 100
    }, options);

    if (!this._options.basePath) {
      var bases = document.getElementsByTagName('base');
      this._options.basePath = bases.length > 0 ? bases[0].href.replace(/^(?:\/\/|[^\/]+)*\//, "") : '';
    }
    /**
     * The router base path
     *
     * var String
     */
    this._basePath = trim(this._options.basePath, '/');
    this._basePath = this._basePath ?  '/' + this._basePath : '';

    /**
     * The router base path regexp
     *
     * var RegExp
     */
    var basePath = this._basePath.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    this._basePathRegExp =  new RegExp('^' + '(' + basePath + '$|' + basePath + '\/)');

    /**
     * The router's tree
     *
     * var Object
     */
    this._route = new Route();

    /**
     * The current route instance
     *
     * var Object
     */
    this._currentRoute = null;

    /**
     * The current params
     *
     * var Object
     */
    this._currentParams = {};

    /**
     * The current location
     *
     * var String
     */
    this._currentLocation = null;

    /**
     * The URL listener
     *
     * var Function
     */
    this._listener = null;
  }

  /**
   * Gets/sets the router dispatch handler.
   *
   * @param  Function      handler The dispatch handler.
   * @return Function|self         The dispatch handler on get or `this` on set.
   */
  handler(handler) {
    if (!arguments.length) {
      return this._options.handler;
    }
    this._options.handler = handler;
    return this;
  }

  /**
   * Adds a route state.
   *
   * @param  mixed   names   The dotted route name string or a route name array.
   * @param  String  pattern A string pattern.
   * @param  Object  content The custom route content to attach to the pattern
   *
   * @return self
   */
  add(name, pattern, content) {
    this._route.add(name, pattern, content);
    return this;
  }

  /**
   * Get/set the current route.
   *
   * @param  Object|undefined The current route to set or none to get the setted one.
   * @return Object|self
   */
  currentRoute(route) {
    if (!arguments.length) {
      return this._currentRoute;
    }
    this._currentRoute = route;
    return this;
  }

  /**
   * Get/set the current params.
   *
   * @param  Object|undefined The current params to set or none to get the setted one.
   * @return Object|self
   */
  currentParams(params) {
    if (!arguments.length) {
      return this._currentParams;
    }
    this._currentParams = params;
    return this;
  }

  /**
   * Get/set the current URL.
   *
   * @param  String|undefined location The current location to set or none to get the setted one.
   * @return String|self
   */
  currentLocation(location) {
    if (!arguments.length) {
      return this._currentLocation;
    }
    var path = '/' + trim.left(location, '/');
    this._currentLocation = '/' + trim.left(path.replace(this._basePathRegExp, '').replace(/index\.html$/, ''), '/');
    return this;
  }

  /**
   * Check is a state is active or not.
   *
   * @param  params Object  The params of the state.
   * @return        Boolean
   */
  isActive(name, params) {
    var currentRoute = this.currentRoute();
    if (!this._currentRoute) {
      return false;
    }
    function paramsMatch(currentParams, params) {
      if (currentParams === params) {
        return true;
      }
      for (var name in params) {
        if (String(currentParams[name]) !== String(params[name])) {
          return false;
        }
      }
      return true;
    }
    var currentRouteName = currentRoute.name();
    return (name === currentRouteName || currentRouteName.indexOf(name + '.') === 0) && paramsMatch(this.currentParams(), params);
  }

  /**
   * Generate an URL from a route name and route params.
   *
   * @param  String name    The route name
   * @param  Object params  The route params (key-value pairs)
   * @param  Object options Some link generation options
   * @return String         The built URL
   */
  link(name, params, options) {
    if (name && name.match(/^(.*:)?\/\/.*/)) {
      return name;
    }

    if (name === '.') {
      var currentRoute = this.currentRoute();
      if (currentRoute) {
        name =currentRoute.name();
      } else {
        throw new Error("No current route available, the `'.'` shortcut can't be used.");
      }
    }
    var defaults = {
      basePath: this._basePath,
      query: undefined
    };
    options = extend({}, defaults, options);

    var route, content;

    do {
      route = this._route.fetch(name);
      content = route.content();
      if (content.redirectTo) {
        name = content.redirectTo;
      }
    } while(content.redirectTo);

    if (typeof options.query === 'string') {
      options.query = qs.parse(options.query);
    } else if (options.query == null) {
      options.query = this.buildQueryParams(name, params);
    }

    return route.link(params, options);
  }

  /**
   * Build query string params.
   *
   * @param  mixed  names   The dotted route name string or a route name array.
   * @param  Array  params  The route parameters.
   * @return Object         The query string parameters.
   */
  buildQueryParams(names, params) {
    if (names == null) {
      throw new Error("A route's name can't be empty.");
    }

    names = Array.isArray(names) ? names : names.split('.');

    var route = this._route;
    var params = params || {};
    var result = {}

    while(names.length) {
      var route = route.getChildren(names[0]);
      result = extend(result, route.buildQueryParams(params));
      names.shift();
    }
    return result;
  }

  /**
   * Return a transition matching a defined URL.
   *
   * @param  String location The location to match
   * @return Object          The matched transition object (undefined if no match found)
   */
  match(location) {
    var parts = location.split('?');
    var path = trim.left(parts[0], '/');
    var bag = this._route.match(path, parts[1] ? qs.parse(parts[1]) : {});

    if (!bag) {
      return;
    }

    var content = bag.route.content();

    while (content.redirectTo) {
      var name = content.redirectTo;
      bag.route = this._route.fetch(name);
      content = bag.route.content();
    }

    return new Transition({
      from: this.currentRoute(),
      to: bag.route,
      params: bag.params
    });
  }

  /**
   * Return a route instance from a route name.
   *
   * @param  mixed  name The dotted route name string or a route name array.
   * @return Object      Returns the corresponding route.
   */
  fetch(name) {
    return this._route.fetch(name);
  }

  /**
   * Return the browser location.
   *
   * @return String The browser location.
   */
  location() {
    var path = '';
    path = decodeURI(location.pathname + location.search);
    return '/' + trim.left(path.replace(this._basePathRegExp, '').replace(/index\.html$/, ''), '/');
  }

  /**
   * Navigate to an new location to the browser.
   *
   * @param  mixed  name The dotted route name string or a route name array.
   * @param  Object params The route params (key-value pairs)
   */
  push(name, params, replace) {
    var location = this.link(name, params);
    this.navigate(location, replace);
  }

  /**
   * Navigate to an new location to the browser without pushing a new history entry.
   *
   * @param  mixed  name The dotted route name string or a route name array.
   * @param  Object params The route params (key-value pairs)
   */
  replace(name, params) {
    this.push(name, params, true);
  }

  /**
   * Navigate to an new location to the browser.
   *
   * @param  String  location The location URL.
   * @param  Boolean replace  If `true` replace the url without pushing a new history entry.
   */
  navigate(location, replace) {
    history[replace ? 'replaceState' : 'pushState'](null, null, location);
    this.dispatch(this.location());
  }

  /**
   * Move forwards/backwards in the history stack.
   * This method takes a single integer as parameter that indicates by how many steps to go forwards or go backwards in the history stack
   *
   * @param Number step How many steps to go forwards or go backwards.
   */
  go(step) {
    return history.go(step);
  }

  /**
   * Dispatch an URL.
   *
   * @param String|undefined location The URL to dispatch.
   */
  dispatch(location) {
    location = location || this.location();
    location = '/' + trim.left(location, '/');
    if (this.currentLocation() === location) {
      return;
    }
    this.currentLocation(location);

    var transition = this.match(location);

    if (!transition) {
      this.emit('404', location);
      return;
    }
    var to = transition.to();
    var toLocation = this.link(to.name(), transition.params());

    // It happens when transition has been redirected through redirectTo
    if (location.split('?')[0] !== toLocation.split('?')[0]) {
      this.currentLocation(toLocation);
      history.replaceState(null, null, toLocation);
    }

    let oldRoute = this.currentRoute();
    let oldParams = this.currentParams();

    return this._options.handler(transition, this).then((updated) => {
      this.currentRoute(transition.to());
      this.currentParams(transition.params());
      this.emit('transitioned', transition);
    }, () => {
      this.emit('424', transition);
      if (oldRoute) {
        this.push(oldRoute.name(), oldParams);
      }
    });
  };

  /**
   * Listen for browser URL changes.
   */
  listen() {
    if (this._listener) {
      return;
    }
    this._listener = setInterval(this.dispatch.bind(this), this._options.interval);
  }

  /**
   * Stop listening.
   */
  stop() {
    if (!this._listener) {
      return;
    }
    clearInterval(this._listener);
  }
}

Emitter(Router.prototype);

module.exports = Router;
<commit_msg>Store params as immutable data to avoid some possible reference issues.<commit_after>var Emitter = require('component-emitter');
var qs = require('qs');
var trim = require('trim-character');
var extend = require('extend-merge').extend;
var merge = require('extend-merge').merge;
var Route = require('./route');
var Transition = require('./transition');

class Router {

  constructor(options) {
    this._options = extend({
      basePath: '',
      handler: (name, routes) => {
        throw new Error('Missing dispatching handler, you need to define a dispatching handler.');
      },
      interval: 100
    }, options);

    if (!this._options.basePath) {
      var bases = document.getElementsByTagName('base');
      this._options.basePath = bases.length > 0 ? bases[0].href.replace(/^(?:\/\/|[^\/]+)*\//, "") : '';
    }
    /**
     * The router base path
     *
     * var String
     */
    this._basePath = trim(this._options.basePath, '/');
    this._basePath = this._basePath ?  '/' + this._basePath : '';

    /**
     * The router base path regexp
     *
     * var RegExp
     */
    var basePath = this._basePath.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    this._basePathRegExp =  new RegExp('^' + '(' + basePath + '$|' + basePath + '\/)');

    /**
     * The router's tree
     *
     * var Object
     */
    this._route = new Route();

    /**
     * The current route instance
     *
     * var Object
     */
    this._currentRoute = null;

    /**
     * The current params
     *
     * var Object
     */
    this._currentParams = {};

    /**
     * The current location
     *
     * var String
     */
    this._currentLocation = null;

    /**
     * The URL listener
     *
     * var Function
     */
    this._listener = null;
  }

  /**
   * Gets/sets the router dispatch handler.
   *
   * @param  Function      handler The dispatch handler.
   * @return Function|self         The dispatch handler on get or `this` on set.
   */
  handler(handler) {
    if (!arguments.length) {
      return this._options.handler;
    }
    this._options.handler = handler;
    return this;
  }

  /**
   * Adds a route state.
   *
   * @param  mixed   names   The dotted route name string or a route name array.
   * @param  String  pattern A string pattern.
   * @param  Object  content The custom route content to attach to the pattern
   *
   * @return self
   */
  add(name, pattern, content) {
    this._route.add(name, pattern, content);
    return this;
  }

  /**
   * Get/set the current route.
   *
   * @param  Object|undefined The current route to set or none to get the setted one.
   * @return Object|self
   */
  currentRoute(route) {
    if (!arguments.length) {
      return this._currentRoute;
    }
    this._currentRoute = route;
    return this;
  }

  /**
   * Get/set the current params.
   *
   * @param  Object|undefined The current params to set or none to get the setted one.
   * @return Object|self
   */
  currentParams(params) {
    if (!arguments.length) {
      return this._currentParams;
    }
    this._currentParams = extend({}, params);
    return this;
  }

  /**
   * Get/set the current URL.
   *
   * @param  String|undefined location The current location to set or none to get the setted one.
   * @return String|self
   */
  currentLocation(location) {
    if (!arguments.length) {
      return this._currentLocation;
    }
    var path = '/' + trim.left(location, '/');
    this._currentLocation = '/' + trim.left(path.replace(this._basePathRegExp, '').replace(/index\.html$/, ''), '/');
    return this;
  }

  /**
   * Check is a state is active or not.
   *
   * @param  params Object  The params of the state.
   * @return        Boolean
   */
  isActive(name, params) {
    var currentRoute = this.currentRoute();
    if (!this._currentRoute) {
      return false;
    }
    function paramsMatch(currentParams, params) {
      if (currentParams === params) {
        return true;
      }
      for (var name in params) {
        if (String(currentParams[name]) !== String(params[name])) {
          return false;
        }
      }
      return true;
    }
    var currentRouteName = currentRoute.name();
    return (name === currentRouteName || currentRouteName.indexOf(name + '.') === 0) && paramsMatch(this.currentParams(), params);
  }

  /**
   * Generate an URL from a route name and route params.
   *
   * @param  String name    The route name
   * @param  Object params  The route params (key-value pairs)
   * @param  Object options Some link generation options
   * @return String         The built URL
   */
  link(name, params, options) {
    if (name && name.match(/^(.*:)?\/\/.*/)) {
      return name;
    }

    if (name === '.') {
      var currentRoute = this.currentRoute();
      if (currentRoute) {
        name =currentRoute.name();
      } else {
        throw new Error("No current route available, the `'.'` shortcut can't be used.");
      }
    }
    var defaults = {
      basePath: this._basePath,
      query: undefined
    };
    options = extend({}, defaults, options);

    var route, content;

    do {
      route = this._route.fetch(name);
      content = route.content();
      if (content.redirectTo) {
        name = content.redirectTo;
      }
    } while(content.redirectTo);

    if (typeof options.query === 'string') {
      options.query = qs.parse(options.query);
    } else if (options.query == null) {
      options.query = this.buildQueryParams(name, params);
    }

    return route.link(params, options);
  }

  /**
   * Build query string params.
   *
   * @param  mixed  names   The dotted route name string or a route name array.
   * @param  Array  params  The route parameters.
   * @return Object         The query string parameters.
   */
  buildQueryParams(names, params) {
    if (names == null) {
      throw new Error("A route's name can't be empty.");
    }

    names = Array.isArray(names) ? names : names.split('.');

    var route = this._route;
    var params = params || {};
    var result = {}

    while(names.length) {
      var route = route.getChildren(names[0]);
      result = extend(result, route.buildQueryParams(params));
      names.shift();
    }
    return result;
  }

  /**
   * Return a transition matching a defined URL.
   *
   * @param  String location The location to match
   * @return Object          The matched transition object (undefined if no match found)
   */
  match(location) {
    var parts = location.split('?');
    var path = trim.left(parts[0], '/');
    var bag = this._route.match(path, parts[1] ? qs.parse(parts[1]) : {});

    if (!bag) {
      return;
    }

    var content = bag.route.content();

    while (content.redirectTo) {
      var name = content.redirectTo;
      bag.route = this._route.fetch(name);
      content = bag.route.content();
    }

    return new Transition({
      from: this.currentRoute(),
      to: bag.route,
      params: bag.params
    });
  }

  /**
   * Return a route instance from a route name.
   *
   * @param  mixed  name The dotted route name string or a route name array.
   * @return Object      Returns the corresponding route.
   */
  fetch(name) {
    return this._route.fetch(name);
  }

  /**
   * Return the browser location.
   *
   * @return String The browser location.
   */
  location() {
    var path = '';
    path = decodeURI(location.pathname + location.search);
    return '/' + trim.left(path.replace(this._basePathRegExp, '').replace(/index\.html$/, ''), '/');
  }

  /**
   * Navigate to an new location to the browser.
   *
   * @param  mixed  name The dotted route name string or a route name array.
   * @param  Object params The route params (key-value pairs)
   */
  push(name, params, replace) {
    var location = this.link(name, params);
    this.navigate(location, replace);
  }

  /**
   * Navigate to an new location to the browser without pushing a new history entry.
   *
   * @param  mixed  name The dotted route name string or a route name array.
   * @param  Object params The route params (key-value pairs)
   */
  replace(name, params) {
    this.push(name, params, true);
  }

  /**
   * Navigate to an new location to the browser.
   *
   * @param  String  location The location URL.
   * @param  Boolean replace  If `true` replace the url without pushing a new history entry.
   */
  navigate(location, replace) {
    history[replace ? 'replaceState' : 'pushState'](null, null, location);
    this.dispatch(this.location());
  }

  /**
   * Move forwards/backwards in the history stack.
   * This method takes a single integer as parameter that indicates by how many steps to go forwards or go backwards in the history stack
   *
   * @param Number step How many steps to go forwards or go backwards.
   */
  go(step) {
    return history.go(step);
  }

  /**
   * Dispatch an URL.
   *
   * @param String|undefined location The URL to dispatch.
   */
  dispatch(location) {
    location = location || this.location();
    location = '/' + trim.left(location, '/');
    if (this.currentLocation() === location) {
      return;
    }
    this.currentLocation(location);

    var transition = this.match(location);

    if (!transition) {
      this.emit('404', location);
      return;
    }
    var to = transition.to();
    var toLocation = this.link(to.name(), transition.params());

    // It happens when transition has been redirected through redirectTo
    if (location.split('?')[0] !== toLocation.split('?')[0]) {
      this.currentLocation(toLocation);
      history.replaceState(null, null, toLocation);
    }

    let oldRoute = this.currentRoute();
    let oldParams = this.currentParams();

    return this._options.handler(transition, this).then((updated) => {
      this.currentRoute(transition.to());
      this.currentParams(transition.params());
      this.emit('transitioned', transition);
    }, () => {
      this.emit('424', transition);
      if (oldRoute) {
        this.push(oldRoute.name(), oldParams);
      }
    });
  };

  /**
   * Listen for browser URL changes.
   */
  listen() {
    if (this._listener) {
      return;
    }
    this._listener = setInterval(this.dispatch.bind(this), this._options.interval);
  }

  /**
   * Stop listening.
   */
  stop() {
    if (!this._listener) {
      return;
    }
    clearInterval(this._listener);
  }
}

Emitter(Router.prototype);

module.exports = Router;
<|endoftext|>


<commit_before>var JST = {
    templates : {},
    parse : function (body, name) {
        var src = ['JST.templates["' + name + '"] = function() {}; '];
        var tagstack = [];
        var toptag = function() { return tagstack.length > 0 ? tagstack[tagstack.length - 1] : null; };
        var line = 1;
        var linepos = 1;
        var inEval = false;
        var inText = false;
        var textparts = [];
        var fcount = 0;
        var toks = [];
        var groups;
        // split body into toks of either newline, value, opentag, closetag, text
        while (body.length > 0) {
            if ((groups = /^\/\/[^\r\n]*/.exec(body)) != null) { // comment - ignore
            } else if ((groups = /^[ \t]*\r?\n/.exec(body)) != null) { // newline
                toks.push({type: "newline", tok: groups[0], value: groups[0]});
            } else if ((groups = /^\$?{\/?([^\r\n{}]+)}/.exec(body)) != null) { // value, opentag, closetag
                var type = body[0] == "$" ? "value" : body[1] == "/" ? "closetag" : "opentag";
                var value = groups[1].replace(/^\s+|\s+$/g, ""); // trim space
                toks.push({type: type, tok: groups[0], value: value, words: value.split(/\s+/)});
            } else if ((groups = /^[^\r\n${]+/.exec(body)) != null || (groups = /^[^\r\n]+/.exec(body)) != null) { // text
                toks.push({type: "text", tok: groups[0], value: groups[0]});
            } else {
                continue;
            }
            body = body.substring(groups[0].length);
        }

        var text = function() {
            if (textparts.length > 0) {
                src.push('out.write("' + textparts.join('').replace(/\r?\n/g, '\\n\\\n').replace(/"/g, '\\"') + '"); ');
                textparts = [];
            }
        };
        var error = function(desc) {
            throw new Error(desc + ", line: " + line + "." + linepos + ", tagstack: [" + tagstack.join(" > ") + "]");
        };

        // skip blank lines at start
        while (toks.length > 0 && toks[0].type === "newline") {
            src.push(toks.shift().tok)
        }

        // if first non-newline tok not 'prototype' then wrap with 'function render'
        if (toks.length > 0 && (toks[0].type !== "opentag" || toks[0].words[0] !== "prototype")) {
            toks.unshift({type: "opentag", tok: "{function render}", value: "function render", words: ["function", "render"]});
            toks.push({type: "closetag", tok: "{/function render}", value: "function render", words: ["function", "render"]});
        }

        for each (tok in toks) {
            //print('tok: ' + tok.type + ", " + (tok.type == "newline" ? "" : tok.value))
            // newline
            if (tok.type === "newline") {
                line++;
                linepos = 1 - tok.value.length; // pos increased at bottom of for-loop
                if (inEval || fcount === 0) {
                    src.push(tok.value);
                } else {
                    textparts.push(tok.value);
                }

            // are we at end of {text?}...{/text?} or {eval}...{/eval}
            } else if ((inText || inEval) && tok.type === "closetag" && tok.value === toptag()) {
                text();
                inText = inEval = false; // we are now finished 'text' or 'eval' section
            } else if (inText) { // still in text
                textlines.push(tok);
            } else if (inEval) { // still in eval
                src.push(tok);

            // value substitution
            } else if (tok.type === "value") {
                text(); // dump existing text
                src.push('out.write(' + tok.value + ' || ""); ')

            // open tag
            } else if (tok.type === "opentag") {
                if (tok.words[0] === "prototype") {
                    if (tok.words.length !== 2) { error("invalid tag format: " + tok.tok); }
                    text();
                    src.push('JST.templates["' + name + '"].prototype = new JST.templates["' + tok.words[1] + '"](); ');
                } else if (tok.words[0] === "function") {
                    if (tok.words.length !== 2) { error("invalid tag format: " + tok.tok); }
                    fcount++;
                    text();
                    src.push('if (typeof JST.templates["' + name + '"].prototype.' + tok.words[1] + ' === "undefined") { JST.templates["' + name + '"].prototype.' + tok.words[1] + ' = function (out, cx) { with (cx) { ');
                    tagstack.push(tok.value); // push 'function <fname>'
                } else if (tok.words[0] === "if") {
                    text();
                    src.push(tok.value + " {");
                    tagstack.push("if");
                } else if (tok.words[0].match(/^els?e?if$/)) {
                    if (!toptag().match(/^(else?)?if$/)) { error("unexpected /else?if/ tag"); }
                    text();
                    src.push("} else if " + words.slice(1).join(" ") + " {");
                } else if (tok.words[0] === "for") {
                    text();
                    src.push("var forcounter = 0; " + tok.value + " { forcounter++; ");
                    tagstack.push("for");
                } else if (tok.words[0] === "forelse") {
                    if (toptag() !== "for") { error("unexpected forelse tag"); }
                    text();
                    src.push("} if (forcounter === 0) { ");
                } else if (tok.words[0] === "eval") {
                    text();
                    if (tok.words.length === 1) {
                         inEval = true;
                         tagstack.push("eval");
                    } else { // inline eval
                        src.push(tok.words.slice(1).join(" "));
                    }
                } else if (tok.words[0].match(/^text/)) {
                    inText = true;
                    tagstack.push(tok.value);
                } else {
                    error("unrecognised tag " + tok.tok);
                }

            // close tag
            } else if (tok.type === "closetag") {
                if (toptag() !== tok.value) { error("unexepcted closetag " + tok.tok); }
                tagstack.pop();
                text();
                if (tok.words[0] === "function") {
                    fcount--;
                    src.push(fcount > 0 ? "}}}; this." + tok.words[1] + "(out, cx); " : "}}}; ");
                } else {
                    src.push("} ");
                }

            // text
            } else if (tok.type === "text") {
                textparts.push(tok.value);
            } else {
            	error("invalid token type: " + tok.type)
            }
            linepos += tok.value.length
        }
        text();
        return src.join("");
    }
}<commit_msg>removed toptag function<commit_after>// Copyright 2010 Joel Hockey (joel.hockey@gmail.com).  MIT Licence

var JST = {
    templates : {},
    parse : function (body, name) {
        var src = ['JST.templates["' + name + '"] = function() {}; '];
        var tagstack = [];
        var line = 1;
        var linepos = 1;
        var inEval = false;
        var inText = false;
        var textparts = [];
        var fcount = 0;
        var toks = [];
        var groups;
        // split body into toks of either newline, value, opentag, closetag, text
        while (body.length > 0) {
            if ((groups = /^\/\/[^\r\n]*/.exec(body)) != null) { // comment - ignore
            } else if ((groups = /^[ \t]*\r?\n/.exec(body)) != null) { // newline
                toks.push({type: "newline", tok: groups[0], value: groups[0]});
            } else if ((groups = /^\$?{\/?([^\r\n{}]+)}/.exec(body)) != null) { // value, opentag, closetag
                var type = body[0] == "$" ? "value" : body[1] == "/" ? "closetag" : "opentag";
                var value = groups[1].replace(/^\s+|\s+$/g, ""); // trim space
                toks.push({type: type, tok: groups[0], value: value, words: value.split(/\s+/)});
            } else if ((groups = /^[^\r\n${]+/.exec(body)) != null || (groups = /^[^\r\n]+/.exec(body)) != null) { // text
                toks.push({type: "text", tok: groups[0], value: groups[0]});
            } else {
                continue;
            }
            body = body.substring(groups[0].length);
        }

        var text = function() {
            if (textparts.length > 0) {
                src.push('out.write("' + textparts.join('').replace(/\r?\n/g, '\\n\\\n').replace(/"/g, '\\"') + '"); ');
                textparts = [];
            }
        };
        var error = function(desc) {
            throw new Error(desc + ", line: " + line + "." + linepos + ", tagstack: [" + tagstack.join(" > ") + "]");
        };

        // skip blank lines at start
        while (toks.length > 0 && toks[0].type === "newline") {
            src.push(toks.shift().tok)
        }

        // if first non-newline tok not 'prototype' then wrap with 'function render'
        if (toks.length > 0 && (toks[0].type !== "opentag" || toks[0].words[0] !== "prototype")) {
            toks.unshift({type: "opentag", tok: "{function render}", value: "function render", words: ["function", "render"]});
            toks.push({type: "closetag", tok: "{/function render}", value: "function render", words: ["function", "render"]});
        }

print("should be an error: " + a.b)
        for each (tok in toks) {
            //print('tok: ' + tok.type + ", " + (tok.type == "newline" ? "" : tok.value))
            var toptag = tagstack[tagstack.length - 1];
            // newline
            if (tok.type === "newline") {
                line++;
                linepos = 1 - tok.value.length; // pos increased at bottom of for-loop
                if (inEval || fcount === 0) {
                    src.push(tok.value);
                } else {
                    textparts.push(tok.value);
                }

            // are we at end of {text?}...{/text?} or {eval}...{/eval}
            } else if ((inText || inEval) && tok.type === "closetag" && tok.value === toptag) {
                text();
                inText = inEval = false; // we are now finished 'text' or 'eval' section
            } else if (inText) { // still in text
                textlines.push(tok);
            } else if (inEval) { // still in eval
                src.push(tok);

            // value substitution
            } else if (tok.type === "value") {
                text(); // dump existing text
                src.push('out.write(' + tok.value + ' || ""); ')

            // open tag
            } else if (tok.type === "opentag") {
                if (tok.words[0] === "prototype") {
                    if (tok.words.length !== 2) { error("invalid tag format: " + tok.tok); }
                    text();
                    src.push('JST.templates["' + name + '"].prototype = new JST.templates["' + tok.words[1] + '"](); ');
                } else if (tok.words[0] === "function") {
                    if (tok.words.length !== 2) { error("invalid tag format: " + tok.tok); }
                    fcount++;
                    text();
                    src.push('if (typeof JST.templates["' + name + '"].prototype.' + tok.words[1] + ' === "undefined") { JST.templates["' + name + '"].prototype.' + tok.words[1] + ' = function (out, cx) { with (cx) { ');
                    tagstack.push(tok.value); // push 'function <fname>'
                } else if (tok.words[0] === "if") {
                    text();
                    src.push(tok.value + " {");
                    tagstack.push("if");
                } else if (tok.words[0].match(/^els?e?if$/)) {
                    if (!toptag || !toptag.match(/^(else?)?if$/)) { error("unexpected /else?if/ tag"); }
                    text();
                    src.push("} else if " + words.slice(1).join(" ") + " {");
                } else if (tok.words[0] === "for") {
                    text();
                    src.push("var forcounter = 0; " + tok.value + " { forcounter++; ");
                    tagstack.push("for");
                } else if (tok.words[0] === "forelse") {
                    if (toptag !== "for") { error("unexpected forelse tag"); }
                    text();
                    src.push("} if (forcounter === 0) { ");
                } else if (tok.words[0] === "eval") {
                    text();
                    if (tok.words.length === 1) {
                         inEval = true;
                         tagstack.push("eval");
                    } else { // inline eval
                        src.push(tok.words.slice(1).join(" "));
                    }
                } else if (tok.words[0].match(/^text/)) {
                    inText = true;
                    tagstack.push(tok.value);
                } else {
                    error("unrecognised tag " + tok.tok);
                }

            // close tag
            } else if (tok.type === "closetag") {
                if (toptag !== tok.value) { error("unexepcted closetag " + tok.tok); }
                tagstack.pop();
                text();
                if (tok.words[0] === "function") {
                    fcount--;
                    src.push(fcount > 0 ? "}}}; this." + tok.words[1] + "(out, cx); " : "}}}; ");
                } else {
                    src.push("} ");
                }

            // text
            } else if (tok.type === "text") {
                textparts.push(tok.value);
            } else {
            	error("invalid token type: " + tok.type)
            }
            linepos += tok.value.length
        }
        text();
        return src.join("");
    }
}<|endoftext|>


<commit_before>function* product(head, ...tail) {
  if (tail.length) {
    const last = tail.pop();
    for (const h of product(head, ...tail)) {
      for (const t of last) {
        yield [...h, t];
      }
    }
  } else {
    for (const h of head) {
      yield [h];
    }
  }
}

function reducer(reduce) {
  return values => reduce(...values);
}

export default function cross(...values) {
  const reduce = typeof values[values.length - 1] === "function" ? reducer(values.pop()) : undefined;
  return Array.from(product(...values), reduce);
}
<commit_msg>Rename for clarity.<commit_after>function* product(head, ...rest) {
  if (rest.length) {
    const tail = rest.pop();
    for (const p of product(head, ...rest)) {
      for (const t of tail) {
        yield [...p, t];
      }
    }
  } else {
    for (const h of head) {
      yield [h];
    }
  }
}

function reducer(reduce) {
  return values => reduce(...values);
}

export default function cross(...values) {
  const reduce = typeof values[values.length - 1] === "function" ? reducer(values.pop()) : undefined;
  return Array.from(product(...values), reduce);
}
<|endoftext|>


<commit_before>define([
    'spoon',
    './{{name}}View'
], function (spoon, {{name}}View) {

    'use strict';

    return spoon.Controller.extend({
        $name: '{{name}}Controller',

        /*_defaultState: 'index',
        _states: {
            'index': '_indexState'
        }*/

        _view: null,

        ////////////////////////////////////////////////////////////

        /**
         * Constructor.
         *
         * @param {Element} element The element in which the module will work on
         */
        initialize: function (element) {
            this.$super();

            this._view = this._link(new {{name}}View());
            this._view
                .appendTo(element)
                .render();
        },

        /**
         * Index state handler.
         *
         * @param {Object} state The state parameter bag
         */
        /*_indexState: function (state) {
            // The index state implementation goes here
            // The state might instantiate another module or simply a view
            // See the default ApplicationController implementation for an example
        },*/

        /**
         * {@inheritDoc}
         */
        _onDestroy: function () {
            if (this._view) {
                this._view.destroy();
                this._view = null;
            }

            this.$super();
        }
    });
});
<commit_msg>Forgot commas.<commit_after>define([
    'spoon',
    './{{name}}View'
], function (spoon, {{name}}View) {

    'use strict';

    return spoon.Controller.extend({
        $name: '{{name}}Controller',

        /*_defaultState: 'index',
        _states: {
            'index': '_indexState'
        },*/

        _view: null,

        ////////////////////////////////////////////////////////////

        /**
         * Constructor.
         *
         * @param {Element} element The element in which the module will work on
         */
        initialize: function (element) {
            this.$super();

            this._view = this._link(new {{name}}View());
            this._view
                .appendTo(element)
                .render();
        },

        /**
         * Index state handler.
         *
         * @param {Object} state The state parameter bag
         */
        /*_indexState: function (state) {
            // The index state implementation goes here
            // The state might instantiate another module or simply a view
            // See the default ApplicationController implementation for an example
        },*/

        /**
         * {@inheritDoc}
         */
        _onDestroy: function () {
            if (this._view) {
                this._view.destroy();
                this._view = null;
            }

            this.$super();
        }
    });
});
<|endoftext|>


<commit_before>const Response = require("./response"),
    CustomResponse = require("./customResponse"),
    qs = require("querystring");

/**
 * Router class that will handle the routing
 */
class Router {

    /**
     * Router constructor
     *
     * @param event
     * @param context
     */
    constructor(event, context) {
        this.routes = {};

        this.event = event;
        this.context = context;

        this.defaultBody = {
            event,
            context
        };
    }

    /**
     * Method used to register a route
     *
     * @param route
     * @param method
     * @param handler
     */
    route (route, method, handler) {
        if (typeof handler !== "function") {
            throw new Error("Route handler is not a function");
        }

        if (this.routes[route] === undefined) {
            this.routes[route] = {};
        }

        this.routes[route][method.toUpperCase()] = handler;
    }

    /**
     * Method used to remove a route
     *
     * @param route
     */
    removeRoute (route) {
        if (this.routes[route] === undefined) {
            throw new Error('Invalid route');
        }

        delete this.routes[route];
    }

    /**
     * Method used to process the request according to the
     * route visited
     *
     * @param responseInstance
     * @param callback
     */
    process (callback, responseInstance) {
        const requestEvent = this.event,
            requestMethod = this.event.httpMethod;

        let functionParameters = {
            requestBody: {},
            pathParameters: {},
            queryStringParameters: {},
            headers: {},
            stageVariables: {},
            requestContext: this.event.requestContext,
            callback: callback
        };

        if (this.routes[requestEvent.resource] === undefined
            || this.routes[requestEvent.resource][requestMethod] === undefined) {

            return callback(null, new Response({
                success: false,
                errorMessage: 'Route not found: ' +
                requestEvent.resource + ' called with method: ' + requestMethod
            }, 404));
        }

        const parsedContentType = parseContentType(requestEvent.headers);

        functionParameters['charset'] = parsedContentType.charset;

        if (requestEvent.body && requestEvent.body !== null) {

            // As headers are case insensitive they should be converted to lowercase before the check
            if (parsedContentType.contentType === "application/x-www-form-urlencoded") {
                try {
                    functionParameters['requestBody'] = qs.parse(requestEvent.body);
                } catch (err) {
                    console.log("Error parsing request body from x-www-form-urlencoded : ", err, requestEvent.body);

                    functionParameters['requestBody'] = requestEvent.body;
                }
            } else {
                try {
                    functionParameters['requestBody'] = JSON.parse(requestEvent.body);
                } catch (err) {
                    console.log("Error parsing request body from JSON: ", err, requestEvent.body);

                    functionParameters['requestBody'] = requestEvent.body;
                }
            }
        }

        if (requestEvent.pathParameters && requestEvent.pathParameters !== null) {
            functionParameters['pathParameters'] = requestEvent.pathParameters;
        }

        if (requestEvent.queryStringParameters && requestEvent.queryStringParameters !== null) {
            functionParameters['queryStringParameters'] = requestEvent.queryStringParameters;
        }

        if (requestEvent.headers && requestEvent.headers !== null) {
            functionParameters['headers'] = requestEvent.headers;
        }

        if (requestEvent.stageVariables && requestEvent.stageVariables !== null) {
            functionParameters['stageVariables'] = requestEvent.stageVariables;
        }

        if (responseInstance === undefined) {
            responseInstance = new CustomResponse();
        }

        const response = this.routes[requestEvent.resource][requestMethod](functionParameters, responseInstance);

        if (response !== undefined && response !== null) {
            if (response.headers === undefined
                || response.isBase64Encoded === undefined
                || response.statusCode === undefined) {
                console.error("Response object: ", response);
                throw new Error("Handler return value must be in a correct format");
            }

            callback(null, response);
        }
    }

}

/**
 * Converts all of the object contents to lowercase, both keys and values
 *
 * @param object
 * @returns {*}
 */
function convertObjectKeysToLowercase(object) {
    if (!object) {
        return object;
    }

    try {
        return JSON.parse(JSON.stringify(object).toLowerCase());
    } catch (err) {
        return object;
    }
}

/**
 * Parses content type header to extract data and charset
 *
 * @param headers
 * @returns {*}
 */
function parseContentType(headers) {
    if (!headers) {
        return false;
    }

    const contentTypeHeader = convertObjectKeysToLowercase(headers)['content-type'].split(";").map(value => value.trim()),
        contentType = contentTypeHeader[0] ? contentTypeHeader[0] : false,
        otherData = contentTypeHeader[1] ? contentTypeHeader[1] : false,
        returnData = {contentType};

    if (otherData) {
        contentTypeHeader.shift();

        contentTypeHeader.forEach(value => {
            returnData[value.split("=")[0].trim().toLowerCase()] = value.split("=")[1].trim().toLowerCase();
        });
    }

    return returnData;
}

module.exports = Router;<commit_msg>Fix parsing of content type<commit_after>const Response = require("./response"),
    CustomResponse = require("./customResponse"),
    qs = require("querystring");

/**
 * Router class that will handle the routing
 */
class Router {

    /**
     * Router constructor
     *
     * @param event
     * @param context
     */
    constructor(event, context) {
        this.routes = {};

        this.event = event;
        this.context = context;

        this.defaultBody = {
            event,
            context
        };
    }

    /**
     * Method used to register a route
     *
     * @param route
     * @param method
     * @param handler
     */
    route (route, method, handler) {
        if (typeof handler !== "function") {
            throw new Error("Route handler is not a function");
        }

        if (this.routes[route] === undefined) {
            this.routes[route] = {};
        }

        this.routes[route][method.toUpperCase()] = handler;
    }

    /**
     * Method used to remove a route
     *
     * @param route
     */
    removeRoute (route) {
        if (this.routes[route] === undefined) {
            throw new Error('Invalid route');
        }

        delete this.routes[route];
    }

    /**
     * Method used to process the request according to the
     * route visited
     *
     * @param responseInstance
     * @param callback
     */
    process (callback, responseInstance) {
        const requestEvent = this.event,
            requestMethod = this.event.httpMethod;

        let functionParameters = {
            requestBody: {},
            pathParameters: {},
            queryStringParameters: {},
            headers: {},
            stageVariables: {},
            requestContext: this.event.requestContext,
            callback: callback
        };

        if (this.routes[requestEvent.resource] === undefined
            || this.routes[requestEvent.resource][requestMethod] === undefined) {

            return callback(null, new Response({
                success: false,
                errorMessage: 'Route not found: ' +
                requestEvent.resource + ' called with method: ' + requestMethod
            }, 404));
        }

        const parsedContentType = parseContentType(requestEvent.headers);

        if (parsedContentType && parsedContentType.charset) {
            functionParameters['charset'] = parsedContentType.charset;
        }

        if (requestEvent.body && requestEvent.body !== null) {

            // As headers are case insensitive they should be converted to lowercase before the check
            if (parsedContentType && parsedContentType.contentType === "application/x-www-form-urlencoded") {
                try {
                    functionParameters['requestBody'] = qs.parse(requestEvent.body);
                } catch (err) {
                    console.log("Error parsing request body from x-www-form-urlencoded : ", err, requestEvent.body);

                    functionParameters['requestBody'] = requestEvent.body;
                }
            } else {
                try {
                    functionParameters['requestBody'] = JSON.parse(requestEvent.body);
                } catch (err) {
                    console.log("Error parsing request body from JSON: ", err, requestEvent.body);

                    functionParameters['requestBody'] = requestEvent.body;
                }
            }
        }

        if (requestEvent.pathParameters && requestEvent.pathParameters !== null) {
            functionParameters['pathParameters'] = requestEvent.pathParameters;
        }

        if (requestEvent.queryStringParameters && requestEvent.queryStringParameters !== null) {
            functionParameters['queryStringParameters'] = requestEvent.queryStringParameters;
        }

        if (requestEvent.headers && requestEvent.headers !== null) {
            functionParameters['headers'] = requestEvent.headers;
        }

        if (requestEvent.stageVariables && requestEvent.stageVariables !== null) {
            functionParameters['stageVariables'] = requestEvent.stageVariables;
        }

        if (responseInstance === undefined) {
            responseInstance = new CustomResponse();
        }

        const response = this.routes[requestEvent.resource][requestMethod](functionParameters, responseInstance);

        if (response !== undefined && response !== null) {
            if (response.headers === undefined
                || response.isBase64Encoded === undefined
                || response.statusCode === undefined) {
                console.error("Response object: ", response);
                throw new Error("Handler return value must be in a correct format");
            }

            callback(null, response);
        }
    }

}

/**
 * Converts all of the object contents to lowercase, both keys and values
 *
 * @param object
 * @returns {*}
 */
function convertObjectKeysToLowercase(object) {
    if (!object) {
        return object;
    }

    try {
        return JSON.parse(JSON.stringify(object).toLowerCase());
    } catch (err) {
        return object;
    }
}

/**
 * Parses content type header to extract data and charset
 *
 * @param headers
 * @returns {*}
 */
function parseContentType(headers) {
    if (!headers) {
        return false;
    }

    let contentTypeHeader = convertObjectKeysToLowercase(headers)['content-type'];

    if (!contentTypeHeader) {
        return false;
    }

    contentTypeHeader = contentTypeHeader.split(";").map(value => value.trim());

    const contentType = contentTypeHeader[0] ? contentTypeHeader[0] : false,
        otherData = contentTypeHeader[1] ? contentTypeHeader[1] : false,
        returnData = {contentType};

    if (otherData) {
        contentTypeHeader.shift();

        contentTypeHeader.forEach(value => {
            returnData[value.split("=")[0].trim().toLowerCase()] = value.split("=")[1].trim().toLowerCase();
        });
    }

    return returnData;
}

module.exports = Router;<|endoftext|>


<commit_before>
/* API LEVEL TOGGLE */
addLoadEvent(changeApiLevel);
var API_LEVEL_COOKIE = "api_level";
var minLevel = 1;

function buildApiLevelToggle() {
	var maxLevel = SINCE_DATA.length;
	var userApiLevel = readCookie(API_LEVEL_COOKIE);

	if (userApiLevel != 0) {
		selectedLevel = userApiLevel;
	} else {
	  selectedLevel = maxLevel;
	}

  minLevel = $("body").attr("class");
	var select = $("#apiLevelControl").html("").change(changeApiLevel);
	for (var i = maxLevel-1; i >= 0; i--) {
		var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
//		if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
		select.append(option);
	}

  // get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true)
	var selectedLevelItem = $("#apiLevelControl option[value='"+selectedLevel+"']").get(0);
  selectedLevelItem.setAttribute('selected',true);
}

function changeApiLevel() {
	var selectedLevel = $("#apiLevelControl option:selected").val();
	var apis = $(".api");
	apis.each(function(i) {
		var obj = $(this);
		var className = obj.attr("class");
		var apiLevelIndex = className.lastIndexOf("-")+1;
		var apiLevelEndIndex = className.indexOf(" ", apiLevelIndex);
		apiLevelEndIndex = apiLevelEndIndex != -1 ? apiLevelEndIndex : className.length;
		var apiLevel = className.substring(apiLevelIndex, apiLevelEndIndex);
		if (apiLevel > selectedLevel) obj.addClass("absent").attr("title","Requires API Level "+apiLevel+" or higher");
		else obj.removeClass("absent").removeAttr("title");
	});

  var date = new Date();
  date.setTime(date.getTime()+(50*365*24*60*60*1000)); // keep this for 50 years
  writeCookie(API_LEVEL_COOKIE, selectedLevel, null, date);

	if (selectedLevel < minLevel) {
	  var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
	  $("#naMessage").show().html("

This " + thing + " is not available with API Level " + selectedLevel + ".
"
                              + "
To use this " + thing + ", your application must specify API Level " + minLevel + " or higher in its manifest "
                              + "and be compiled against a version of the Android library that supports an equal or higher API Level. To reveal this "
                              + "document, change the value of the API Level filter above.
"
                              + "
What is the API Level?

");
	} else {
    $("#naMessage").hide();
  }
}

/* NAVTREE */

function new_node(me, mom, text, link, children_data, api_level)
{
  var node = new Object();
  node.children = Array();
  node.children_data = children_data;
  node.depth = mom.depth + 1;

  node.li = document.createElement("li");
  mom.get_children_ul().appendChild(node.li);

  node.label_div = document.createElement("div");
  node.label_div.className = "label";
  if (api_level != null) {
    $(node.label_div).addClass("api");
    $(node.label_div).addClass("api-level-"+api_level);
  }
  node.li.appendChild(node.label_div);
  node.label_div.style.paddingLeft = 10*node.depth + "px";

  if (children_data == null) {
    // 12 is the width of the triangle and padding extra space
    node.label_div.style.paddingLeft = ((10*node.depth)+12) + "px";
  } else {
    node.label_div.style.paddingLeft = 10*node.depth + "px";
    node.expand_toggle = document.createElement("a");
    node.expand_toggle.href = "javascript:void(0)";
    node.expand_toggle.onclick = function() {
          if (node.expanded) {
            $(node.get_children_ul()).slideUp("fast");
            node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
            node.expanded = false;
          } else {
            expand_node(me, node);
          }
       };
    node.label_div.appendChild(node.expand_toggle);

    node.plus_img = document.createElement("img");
    node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
    node.plus_img.className = "plus";
    node.plus_img.border = "0";
    node.expand_toggle.appendChild(node.plus_img);

    node.expanded = false;
  }

  var a = document.createElement("a");
  node.label_div.appendChild(a);
  node.label = document.createTextNode(text);
  a.appendChild(node.label);
  if (link) {
    a.href = me.toroot + link;
  } else {
    if (children_data != null) {
      a.className = "nolink";
      a.href = "javascript:void(0)";
      a.onclick = node.expand_toggle.onclick;
      // This next line shouldn't be necessary.  I'll buy a beer for the first
      // person who figures out how to remove this line and have the link
      // toggle shut on the first try. --joeo@android.com
      node.expanded = false;
    }
  }

  node.children_ul = null;
  node.get_children_ul = function() {
      if (!node.children_ul) {
        node.children_ul = document.createElement("ul");
        node.children_ul.className = "children_ul";
        node.children_ul.style.display = "none";
        node.li.appendChild(node.children_ul);
      }
      return node.children_ul;
    };

  return node;
}

function expand_node(me, node)
{
  if (node.children_data && !node.expanded) {
    if (node.children_visited) {
      $(node.get_children_ul()).slideDown("fast");
    } else {
      get_node(me, node);
      if ($(node.label_div).hasClass("absent")) $(node.get_children_ul()).addClass("absent");
      $(node.get_children_ul()).slideDown("fast");
    }
    node.plus_img.src = me.toroot + "assets/images/triangle-opened-small.png";
    node.expanded = true;
  }
}

function get_node(me, mom)
{
  mom.children_visited = true;
  for (var i in mom.children_data) {
    var node_data = mom.children_data[i];
    mom.children[i] = new_node(me, mom, node_data[0], node_data[1],
        node_data[2], node_data[3]);
  }
}

function this_page_relative(toroot)
{
  var full = document.location.pathname;
  var file = "";
  if (toroot.substr(0, 1) == "/") {
    if (full.substr(0, toroot.length) == toroot) {
      return full.substr(toroot.length);
    } else {
      // the file isn't under toroot.  Fail.
      return null;
    }
  } else {
    if (toroot != "./") {
      toroot = "./" + toroot;
    }
    do {
      if (toroot.substr(toroot.length-3, 3) == "../" || toroot == "./") {
        var pos = full.lastIndexOf("/");
        file = full.substr(pos) + file;
        full = full.substr(0, pos);
        toroot = toroot.substr(0, toroot.length-3);
      }
    } while (toroot != "" && toroot != "/");
    return file.substr(1);
  }
}

function find_page(url, data)
{
  var nodes = data;
  var result = null;
  for (var i in nodes) {
    var d = nodes[i];
    if (d[1] == url) {
      return new Array(i);
    }
    else if (d[2] != null) {
      result = find_page(url, d[2]);
      if (result != null) {
        return (new Array(i).concat(result));
      }
    }
  }
  return null;
}

function load_navtree_data(toroot) {
  var navtreeData = document.createElement("script");
  navtreeData.setAttribute("type","text/javascript");
  navtreeData.setAttribute("src", toroot+"navtree_data.js");
  $("head").append($(navtreeData));
}

function init_default_navtree(toroot) {
  init_navtree("nav-tree", toroot, NAVTREE_DATA);
}

function init_navtree(navtree_id, toroot, root_nodes)
{
  var me = new Object();
  me.toroot = toroot;
  me.node = new Object();

  me.node.li = document.getElementById(navtree_id);
  me.node.children_data = root_nodes;
  me.node.children = new Array();
  me.node.children_ul = document.createElement("ul");
  me.node.get_children_ul = function() { return me.node.children_ul; };
  //me.node.children_ul.className = "children_ul";
  me.node.li.appendChild(me.node.children_ul);
  me.node.depth = 0;

  get_node(me, me.node);

  me.this_page = this_page_relative(toroot);
  me.breadcrumbs = find_page(me.this_page, root_nodes);
  if (me.breadcrumbs != null && me.breadcrumbs.length != 0) {
    var mom = me.node;
    for (var i in me.breadcrumbs) {
      var j = me.breadcrumbs[i];
      mom = mom.children[j];
      expand_node(me, mom);
    }
    mom.label_div.className = mom.label_div.className + " selected";
    addLoadEvent(function() {
      scrollIntoView("nav-tree");
      });
  }
}
<commit_msg>am e06d28ec: am dab571d6: Merge change 22524 into donut<commit_after>
/* API LEVEL TOGGLE */
addLoadEvent(changeApiLevel);
var API_LEVEL_COOKIE = "api_level";
var minLevel = 1;

function buildApiLevelToggle() {
	var maxLevel = SINCE_DATA.length;
	var userApiLevel = readCookie(API_LEVEL_COOKIE);

	if (userApiLevel != 0) {
		selectedLevel = userApiLevel;
	} else {
	  selectedLevel = maxLevel;
	}

  minLevel = $("body").attr("class");
	var select = $("#apiLevelControl").html("").change(changeApiLevel);
	for (var i = maxLevel-1; i >= 0; i--) {
		var option = $("<option />").attr("value",""+SINCE_DATA[i]).append(""+SINCE_DATA[i]);
//		if (SINCE_DATA[i] < minLevel) option.addClass("absent"); // always false for strings (codenames)
		select.append(option);
	}

  // get the DOM element and use setAttribute cuz IE6 fails when using jquery .attr('selected',true)
	var selectedLevelItem = $("#apiLevelControl option[value='"+selectedLevel+"']").get(0);
  selectedLevelItem.setAttribute('selected',true);
}

function changeApiLevel() {
	var selectedLevel = $("#apiLevelControl option:selected").val();
  toggleVisisbleApis(selectedLevel, "body");

  var date = new Date();
  date.setTime(date.getTime()+(50*365*24*60*60*1000)); // keep this for 50 years
  writeCookie(API_LEVEL_COOKIE, selectedLevel, null, date);

	if (selectedLevel < minLevel) {
	  var thing = ($("#jd-header").html().indexOf("package") != -1) ? "package" : "class";
	  $("#naMessage").show().html("

This " + thing + " is not available with API Level " + selectedLevel + ".
"
                              + "
To use this " + thing + ", your application must specify API Level " + minLevel + " or higher in its manifest "
                              + "and be compiled against a version of the Android library that supports an equal or higher API Level. To reveal this "
                              + "document, change the value of the API Level filter above.
"
                              + "
What is the API Level?

");
	} else {
    $("#naMessage").hide();
  }
}

function toggleVisisbleApis(selectedLevel, context) {
	var apis = $(".api",context);
	apis.each(function(i) {
		var obj = $(this);
		var className = obj.attr("class");
		var apiLevelIndex = className.lastIndexOf("-")+1;
		var apiLevelEndIndex = className.indexOf(" ", apiLevelIndex);
		apiLevelEndIndex = apiLevelEndIndex != -1 ? apiLevelEndIndex : className.length;
		var apiLevel = className.substring(apiLevelIndex, apiLevelEndIndex);
		if (apiLevel > selectedLevel) obj.addClass("absent").attr("title","Requires API Level "+apiLevel+" or higher");
		else obj.removeClass("absent").removeAttr("title");
	});
}

/* NAVTREE */

function new_node(me, mom, text, link, children_data, api_level)
{
  var node = new Object();
  node.children = Array();
  node.children_data = children_data;
  node.depth = mom.depth + 1;

  node.li = document.createElement("li");
  mom.get_children_ul().appendChild(node.li);

  node.label_div = document.createElement("div");
  node.label_div.className = "label";
  if (api_level != null) {
    $(node.label_div).addClass("api");
    $(node.label_div).addClass("api-level-"+api_level);
  }
  node.li.appendChild(node.label_div);
  node.label_div.style.paddingLeft = 10*node.depth + "px";

  if (children_data == null) {
    // 12 is the width of the triangle and padding extra space
    node.label_div.style.paddingLeft = ((10*node.depth)+12) + "px";
  } else {
    node.label_div.style.paddingLeft = 10*node.depth + "px";
    node.expand_toggle = document.createElement("a");
    node.expand_toggle.href = "javascript:void(0)";
    node.expand_toggle.onclick = function() {
          if (node.expanded) {
            $(node.get_children_ul()).slideUp("fast");
            node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
            node.expanded = false;
          } else {
            expand_node(me, node);
          }
       };
    node.label_div.appendChild(node.expand_toggle);

    node.plus_img = document.createElement("img");
    node.plus_img.src = me.toroot + "assets/images/triangle-closed-small.png";
    node.plus_img.className = "plus";
    node.plus_img.border = "0";
    node.expand_toggle.appendChild(node.plus_img);

    node.expanded = false;
  }

  var a = document.createElement("a");
  node.label_div.appendChild(a);
  node.label = document.createTextNode(text);
  a.appendChild(node.label);
  if (link) {
    a.href = me.toroot + link;
  } else {
    if (children_data != null) {
      a.className = "nolink";
      a.href = "javascript:void(0)";
      a.onclick = node.expand_toggle.onclick;
      // This next line shouldn't be necessary.  I'll buy a beer for the first
      // person who figures out how to remove this line and have the link
      // toggle shut on the first try. --joeo@android.com
      node.expanded = false;
    }
  }

  node.children_ul = null;
  node.get_children_ul = function() {
      if (!node.children_ul) {
        node.children_ul = document.createElement("ul");
        node.children_ul.className = "children_ul";
        node.children_ul.style.display = "none";
        node.li.appendChild(node.children_ul);
      }
      return node.children_ul;
    };

  return node;
}

function expand_node(me, node)
{
  if (node.children_data && !node.expanded) {
    if (node.children_visited) {
      $(node.get_children_ul()).slideDown("fast");
    } else {
      get_node(me, node);
      if ($(node.label_div).hasClass("absent")) $(node.get_children_ul()).addClass("absent");
      $(node.get_children_ul()).slideDown("fast");
    }
    node.plus_img.src = me.toroot + "assets/images/triangle-opened-small.png";
    node.expanded = true;

    // perform api level toggling because new nodes are new to the DOM
	  var selectedLevel = $("#apiLevelControl option:selected").val();
    toggleVisisbleApis(selectedLevel, "#side-nav");
  }
}

function get_node(me, mom)
{
  mom.children_visited = true;
  for (var i in mom.children_data) {
    var node_data = mom.children_data[i];
    mom.children[i] = new_node(me, mom, node_data[0], node_data[1],
        node_data[2], node_data[3]);
  }
}

function this_page_relative(toroot)
{
  var full = document.location.pathname;
  var file = "";
  if (toroot.substr(0, 1) == "/") {
    if (full.substr(0, toroot.length) == toroot) {
      return full.substr(toroot.length);
    } else {
      // the file isn't under toroot.  Fail.
      return null;
    }
  } else {
    if (toroot != "./") {
      toroot = "./" + toroot;
    }
    do {
      if (toroot.substr(toroot.length-3, 3) == "../" || toroot == "./") {
        var pos = full.lastIndexOf("/");
        file = full.substr(pos) + file;
        full = full.substr(0, pos);
        toroot = toroot.substr(0, toroot.length-3);
      }
    } while (toroot != "" && toroot != "/");
    return file.substr(1);
  }
}

function find_page(url, data)
{
  var nodes = data;
  var result = null;
  for (var i in nodes) {
    var d = nodes[i];
    if (d[1] == url) {
      return new Array(i);
    }
    else if (d[2] != null) {
      result = find_page(url, d[2]);
      if (result != null) {
        return (new Array(i).concat(result));
      }
    }
  }
  return null;
}

function load_navtree_data(toroot) {
  var navtreeData = document.createElement("script");
  navtreeData.setAttribute("type","text/javascript");
  navtreeData.setAttribute("src", toroot+"navtree_data.js");
  $("head").append($(navtreeData));
}

function init_default_navtree(toroot) {
  init_navtree("nav-tree", toroot, NAVTREE_DATA);

  // perform api level toggling because because the whole tree is new to the DOM
	var selectedLevel = $("#apiLevelControl option:selected").val();
  toggleVisisbleApis(selectedLevel, "#side-nav");
}

function init_navtree(navtree_id, toroot, root_nodes)
{
  var me = new Object();
  me.toroot = toroot;
  me.node = new Object();

  me.node.li = document.getElementById(navtree_id);
  me.node.children_data = root_nodes;
  me.node.children = new Array();
  me.node.children_ul = document.createElement("ul");
  me.node.get_children_ul = function() { return me.node.children_ul; };
  //me.node.children_ul.className = "children_ul";
  me.node.li.appendChild(me.node.children_ul);
  me.node.depth = 0;

  get_node(me, me.node);

  me.this_page = this_page_relative(toroot);
  me.breadcrumbs = find_page(me.this_page, root_nodes);
  if (me.breadcrumbs != null && me.breadcrumbs.length != 0) {
    var mom = me.node;
    for (var i in me.breadcrumbs) {
      var j = me.breadcrumbs[i];
      mom = mom.children[j];
      expand_node(me, mom);
    }
    mom.label_div.className = mom.label_div.className + " selected";
    addLoadEvent(function() {
      scrollIntoView("nav-tree");
      });
  }
}
<|endoftext|>