<commit_before>import React, { Component } from 'react'
import { render } from 'react-dom'

import Toggle from '../component'
// In your code this would be:
// import Toggle from 'react-toggle'

import '../../style.css'
import './style.css'

class App extends Component {
  constructor (props) {
    super(props)
    this.handleMilkChange = this.handleMilkChange.bind(this)
    this.handleEggsChange = this.handleChange.bind(this, 'eggsAreReady')
    this.handleBaconChange = this.handleChange.bind(this, 'baconIsReady')
    this.handleToastChange = this.handleChange.bind(this, 'toastIsReady')
    this.handleCheeseChange = this.handleChange.bind(this, 'cheeseIsReady')
    this.handleBiscuitChange = this.handleChange.bind(this, 'biscuitIsReady')
    this.handleBurritoChange = this.handleChange.bind(this, 'burritoIsReady')
    this.handleAubergineChange = this.handleChange.bind(this, 'aubergineIsReady')

    this.state = {
      aubergineIsReady: true,
      cheeseIsReady: false,
      baconIsReady: false,
      biscuitIsReady: false,
      milkIsReady: false,
      eggsAreReady: false,
      burritoIsReady: false,
      toastIsReady: false,
      formData: {},
    }
  }

  handleChange (key, event) {
    this.setState({ [key]: event.target.checked })
  }

  handleMilkChange (event) {
    const form = this.refs.breakfastForm
    this.setState({formData: form.milkIsReady.checked ? {milkIsReady: form.milkIsReady.value} : {}})
  }

  render () {
    return (
      <form ref='breakfastForm'>

react-toggle

        {/* Installation */}

Installation

            {`npm install react-toggle --save-dev`}

{`import Toggle from 'react-toggle'`}

Or if you're not using the ES6 module format yet:

{`var Toggle = require('react-toggle')`}

Include the component's CSS.

        {/* Bacon */}

            <Toggle
              defaultChecked={this.state.baconIsReady}
              onChange={this.handleBaconChange} />
            Wrapper label tag

            {`
  <Toggle
    defaultChecked={this.state.baconIsReady}
    onChange={this.handleBaconChange} />
  Wrapper label tag
`}

            this.state.baconIsReady: {JSON.stringify(this.state.baconIsReady)}

        {/* Cheese */}

          <Toggle
            id='cheese-status'
            defaultChecked={this.state.cheeseIsReady}
            onChange={this.handleCheeseChange} />
          Adjacent label tag

            {`<Toggle
  id='cheese-status'
  defaultChecked={this.state.cheeseIsReady}
  onChange={this.handleCheeseChange} />
Adjacent label tag`}

            this.state.cheeseIsReady: {JSON.stringify(this.state.cheeseIsReady)}

        {/* Biscuit */}

          <Toggle
            id='biscuit-status'
            defaultChecked={this.state.biscuitIsReady}
            aria-labelledby='biscuit-label'
            onChange={this.handleBiscuitChange} />
          Adjacent label, but not standard tag

            {`<Toggle
  id='biscuit-status'
  defaultChecked={this.state.biscuitIsReady}
  aria-labelledby='biscuit-label'
  onChange={this.handleBiscuitChange} />
Adjacent label, but not standard tag`}

            this.state.biscuitIsReady: {JSON.stringify(this.state.biscuitIsReady)}

        {/* Eggs */}

          <Toggle
            defaultChecked={this.state.eggsAreReady}
            aria-label='No label'
            onChange={this.handleEggsChange} />
          No label tag

            {`<Toggle
  defaultChecked={this.state.eggsAreReady}
  aria-label='No label tag'
  onChange={this.handleEggsChange} />
No label tag`}

            this.state.eggsAreReady: {JSON.stringify(this.state.eggsAreReady)}

        {/* Handle change */}

Handle change

            {`handleChange(event) {
  // do something with event.target.checked
}`}

        {/* Using form data */}

            <Toggle
              defaultChecked={!!this.state.milkIsReady}
              name='milkIsReady'
              value='yes'
              onChange={this.handleMilkChange} />
            Using form data

            {`<Toggle
  defaultChecked={this.state.milkIsReady}
  name='milkIsReady'
  value='yes' />`}

            formData: {JSON.stringify(this.state.formData)}

        {/* Controlled Component */}

            <input
              type='checkbox'
              checked={this.state.burritoIsReady}
              name='burritoIsReady2'
              onChange={this.handleBurritoChange} />
             Controlled Component

            {`<Toggle
  checked={this.state.burritoIsReady}
  name='burritoIsReady'
  value='yes'
  onChange={this.handleBurritoChange}/>`}

          <Toggle
            checked={this.state.burritoIsReady}
            name='burritoIsReady'
            value='yes'
            onChange={this.handleBurritoChange} />

        {/* Controlled Component without onChange */}

            <input
              type='checkbox'
              checked={this.state.toastIsReady}
              name='toastIsReady2'
              onChange={this.handleToastChange} />
             Controlled Component without onChange

            {`<Toggle
  checked={this.state.toastIsReady}
  name='toastIsReady'
  value='yes' />`}

          <Toggle
            checked={this.state.toastIsReady}
            name='toastIsReady'
            value='yes' />

        {/* Disabled */}

              <Toggle
                defaultChecked={false}
                disabled />
              Diabled, Unchecked

              <Toggle
                defaultChecked
                disabled />
              Disabled, Checked

            {`
  <Toggle
    defaultChecked={false}
    disabled={true} />
  Diabled, Unchecked

  <Toggle
    defaultChecked={true}
    disabled={true} />
  Disabled, Checked
`}

        {/* Custom className */}

            <Toggle
              defaultChecked={this.state.aubergineIsReady}
              className='custom-classname'
              onChange={this.handleAubergineChange} />
            Custom className

            {`
  <Toggle
    defaultChecked={this.state.aubergineIsReady}
    className='custom-classname'
    onChange={this.handleAubergineChange} />
  Custom className
`}

            {`.custom-classname.react-toggle--checked .react-toggle-track {
  background-color: #ab199f;
}`}

      </form>
    )
  }
}

App.displayName = 'App'

render(<App />, document.getElementById('application'))
<commit_msg>Add docs for custom icons<commit_after>import React, { Component } from 'react'
import { render } from 'react-dom'

import Toggle from '../component'
// In your code this would be:
// import Toggle from 'react-toggle'

import '../../style.css'
import './style.css'

const Heart = () => (

  ❤

)

class App extends Component {
  constructor (props) {
    super(props)
    this.handleMilkChange = this.handleMilkChange.bind(this)
    this.handleSoupChange = this.handleChange.bind(this, 'soupIsReady')
    this.handleTofuChange = this.handleChange.bind(this, 'tofuIsReady')
    this.handleEggsChange = this.handleChange.bind(this, 'eggsAreReady')
    this.handleBaconChange = this.handleChange.bind(this, 'baconIsReady')
    this.handleToastChange = this.handleChange.bind(this, 'toastIsReady')
    this.handleCheeseChange = this.handleChange.bind(this, 'cheeseIsReady')
    this.handleBiscuitChange = this.handleChange.bind(this, 'biscuitIsReady')
    this.handleBurritoChange = this.handleChange.bind(this, 'burritoIsReady')
    this.handleAubergineChange = this.handleChange.bind(this, 'aubergineIsReady')

    this.state = {
      aubergineIsReady: true,
      cheeseIsReady: false,
      baconIsReady: false,
      biscuitIsReady: false,
      milkIsReady: false,
      eggsAreReady: false,
      soupIsReady: true,
      tofuIsReady: false,
      burritoIsReady: false,
      toastIsReady: false,
      formData: {},
    }
  }

  handleChange (key, event) {
    this.setState({ [key]: event.target.checked })
  }

  handleMilkChange (event) {
    const form = this.refs.breakfastForm
    this.setState({formData: form.milkIsReady.checked ? {milkIsReady: form.milkIsReady.value} : {}})
  }

  render () {
    return (
      <form ref='breakfastForm'>

react-toggle

        {/* Installation */}

Installation

            {`npm install react-toggle --save-dev`}

{`import Toggle from 'react-toggle'`}

Or if you're not using the ES6 module format yet:

{`var Toggle = require('react-toggle')`}

Include the component's CSS.

        {/* Bacon */}

            <Toggle
              defaultChecked={this.state.baconIsReady}
              onChange={this.handleBaconChange} />
            Wrapper label tag

            {`
  <Toggle
    defaultChecked={this.state.baconIsReady}
    onChange={this.handleBaconChange} />
  Wrapper label tag
`}

            this.state.baconIsReady: {JSON.stringify(this.state.baconIsReady)}

        {/* Cheese */}

          <Toggle
            id='cheese-status'
            defaultChecked={this.state.cheeseIsReady}
            onChange={this.handleCheeseChange} />
          Adjacent label tag

            {`<Toggle
  id='cheese-status'
  defaultChecked={this.state.cheeseIsReady}
  onChange={this.handleCheeseChange} />
Adjacent label tag`}

            this.state.cheeseIsReady: {JSON.stringify(this.state.cheeseIsReady)}

        {/* Biscuit */}

          <Toggle
            id='biscuit-status'
            defaultChecked={this.state.biscuitIsReady}
            aria-labelledby='biscuit-label'
            onChange={this.handleBiscuitChange} />
          Adjacent label, but not standard tag

            {`<Toggle
  id='biscuit-status'
  defaultChecked={this.state.biscuitIsReady}
  aria-labelledby='biscuit-label'
  onChange={this.handleBiscuitChange} />
Adjacent label, but not standard tag`}

            this.state.biscuitIsReady: {JSON.stringify(this.state.biscuitIsReady)}

        {/* Eggs */}

          <Toggle
            defaultChecked={this.state.eggsAreReady}
            aria-label='No label'
            onChange={this.handleEggsChange} />
          No label tag

            {`<Toggle
  defaultChecked={this.state.eggsAreReady}
  aria-label='No label tag'
  onChange={this.handleEggsChange} />
No label tag`}

            this.state.eggsAreReady: {JSON.stringify(this.state.eggsAreReady)}

        {/* Handle change */}

Handle change

            {`handleChange(event) {
  // do something with event.target.checked
}`}

        {/* Using form data */}

            <Toggle
              defaultChecked={!!this.state.milkIsReady}
              name='milkIsReady'
              value='yes'
              onChange={this.handleMilkChange} />
            Using form data

            {`<Toggle
  defaultChecked={this.state.milkIsReady}
  name='milkIsReady'
  value='yes' />`}

            formData: {JSON.stringify(this.state.formData)}

        {/* Controlled Component */}

            <input
              type='checkbox'
              checked={this.state.burritoIsReady}
              name='burritoIsReady2'
              onChange={this.handleBurritoChange} />
             Controlled Component

            {`<Toggle
  checked={this.state.burritoIsReady}
  name='burritoIsReady'
  value='yes'
  onChange={this.handleBurritoChange}/>`}

          <Toggle
            checked={this.state.burritoIsReady}
            name='burritoIsReady'
            value='yes'
            onChange={this.handleBurritoChange} />

        {/* Controlled Component without onChange */}

            <input
              type='checkbox'
              checked={this.state.toastIsReady}
              name='toastIsReady2'
              onChange={this.handleToastChange} />
             Controlled Component without onChange

            {`<Toggle
  checked={this.state.toastIsReady}
  name='toastIsReady'
  value='yes' />`}

          <Toggle
            checked={this.state.toastIsReady}
            name='toastIsReady'
            value='yes' />

        {/* Disabled */}

              <Toggle
                defaultChecked={false}
                disabled />
              Diabled, Unchecked

              <Toggle
                defaultChecked
                disabled />
              Disabled, Checked

            {`
  <Toggle
    defaultChecked={false}
    disabled={true} />
  Diabled, Unchecked

  <Toggle
    defaultChecked={true}
    disabled={true} />
  Disabled, Checked
`}

        {/* Custom className */}

            <Toggle
              defaultChecked={this.state.aubergineIsReady}
              className='custom-classname'
              onChange={this.handleAubergineChange} />
            Custom className

            {`
  <Toggle
    defaultChecked={this.state.aubergineIsReady}
    className='custom-classname'
    onChange={this.handleAubergineChange} />
  Custom className
`}

            {`.custom-classname.react-toggle--checked .react-toggle-track {
  background-color: #ab199f;
}`}

        {/* Custom icons */}

            <Toggle
              defaultChecked={this.state.soupIsReady}
              icons={{
                checked: <Heart />,
                unchecked: null,
              }}
              onChange={this.handleSoupChange} />
            Custom icons

            {`
  <Toggle
    defaultChecked={this.state.soupIsReady}
    icons={{
      checked: <Heart />,
      unchecked: null,
    }}
    onChange={this.handleSoupChange} />
  Custom icons
`}

        {/* No icons */}

            <Toggle
              defaultChecked={this.state.tofuIsReady}
              icons={false}
              onChange={this.handleTofuChange} />
            No icons

            {`
  <Toggle
    defaultChecked={this.state.tofuIsReady}
    icons={false}
    onChange={this.handleTofuChange} />
  No icons
`}

      </form>
    )
  }
}

App.displayName = 'App'

render(<App />, document.getElementById('application'))
<|endoftext|>


<commit_before>/*
 * ESUI (Enterprise Simple UI)
 * Copyright 2010 Baidu Inc. All rights reserved.
 *
 * path:    esui/Layer.js
 * desc:    浮动面板层
 * author:  erik
 */

///import esui.Control;
///import baidu.lang.inherits;
///import baidu.event.on;
///import baidu.event.un;
///import baidu.event.getTarget;

/**
 * 浮动面板层控件
 *
 * @param {Object} options 参数
 */
esui.Layer = function ( options ) {
    esui.Control.call( this, options );

    // 类型声明，用于生成控件子dom的id和class
    this._type = this.retype || 'layer';

    // 标识鼠标事件触发自动状态转换
    this._autoState = 0;

    this.top = 0;
    this.left = 0;
    this.autoHide = this.autoHide || '';
};

esui.Layer.prototype = {
    /**
     * 绘制控件
     *
     * @public
     * @param {HTMLElement} main 控件挂载的DOM
     */
    render: function () {
        var main = this.main;
        esui.Control.prototype.render.call( this );

        main.style.position = 'absolute';
        main.style.left     = this._HIDE_POS;
        main.style.top      = this._HIDE_POS;
        this.zIndex && ( main.style.zIndex = this.zIndex );
        this.width  && ( main.style.width  = this.width + 'px' );
        this.height && ( main.style.height = this.height + 'px' );

        // 初始化autohide行为
        if ( this._autoHideInited ) {
            return;
        }

        switch ( this.autoHide.toLowerCase() ) {
        case 'click':
            this._clickHandler = this._getClickHider();
            baidu.on( document, 'click', this._clickHandler );
            break;
        case 'out':
            main.onmouseout = this._getOutHandler();
            main.onmouseover = this._getOverHandler();
            break;
        }

        this._autoHideInited = 1;
    },

    /**
     * 获取鼠标移入的事件handler
     *
     * @private
     * @return {Function}
     */
    _getOverHandler: function () {
        var me = this;
        return function () {
            me.show();
        };
    },

    /**
     * 获取鼠标移出的事件handler
     *
     * @private
     * @return {Function}
     */
    _getOutHandler: function () {
        var me = this;
        return function () {
            me.onhide();
            me.hide();
        };
    },

    onhide: new Function(),

    /**
     * 获取点击自动隐藏的处理handler
     *
     * @private
     * @return {Function}
     */
    _getClickHider: function () {
        var me = this;
        return function ( e ) {
            if ( me._isHidePrevent ) {
                me._isHidePrevent = 0;
                return;
            }

            var tar = baidu.event.getTarget( e );
            while ( tar && tar != document.body ) {
                if ( tar == me.main ) {
                    return;
                }
                tar = tar.parentNode;
            }

            me.onhide();
            me.hide();
        };
    },

    /**
     * 在一次点击中阻止隐藏层
     *
     * @private
     */
    _preventHide: function () {
        this._isHidePrevent = 1;
    },

    _HIDE_POS: '-10000px',

    /**
     * 设置浮动层的宽度
     *
     * @public
     * @param {number} width 宽度
     */
    setWidth: function ( width ) {
        this.main.style.width = width + 'px';
        this.width = width;
    },

    /**
     * 获取浮动层的宽度
     *
     * @public
     * @return {number}
     */
    getWidth: function () {
        return this.width || this.main.offsetWidth;
    },

    /**
     * 设置浮动层的高度
     *
     * @public
     * @param {number} height 高度
     */
    setHeight: function ( height ) {
        this.main.style.height = height + 'px';
        this.height = height;
    },

    /**
     * 获取浮动层的高度
     *
     * @public
     * @return {number}
     */
    getHeight: function () {
        return this.height || this.main.offsetHeight;
    },

    /**
     * 显示层
     *
     * @public
     */
    show: function ( left, top ) {
        this._isShow = 1;
        this.left = left || this.left;
        this.top = top || this.top;

        this.main.style.left = this.left + 'px';
        this.main.style.top = this.top + 'px';
    },

    /**
     * 隐藏层
     *
     * @public
     */
    hide: function () {
        this._isShow = 0;
        this.main.style.left = this._HIDE_POS;
        this.main.style.top = this._HIDE_POS;
    },

    /**
     * 获取层是否显示
     *
     * @public
     * @return {boolean}
     */
    isShow: function () {
        return !!this._isShow;
    },

    /**
     * 释放控件
     *
     * @private
     */
    __dispose: function () {
        var main = this.main;

        if ( this._clickHandler ) {
            baidu.un( document, 'click', this._clickHandler );
            this._clickHandler = null;
        }

        this.onhide = null;
        esui.Control.prototype.__dispose.call( this );

        main.innerHTML = '';
        main.parentNode && main.parentNode.removeChild( main );
    }
};

baidu.inherits( esui.Layer, esui.Control );
<commit_msg>add partName support when Layer is a part of Control<commit_after>/*
 * ESUI (Enterprise Simple UI)
 * Copyright 2010 Baidu Inc. All rights reserved.
 *
 * path:    esui/Layer.js
 * desc:    浮动面板层
 * author:  erik
 */

///import esui.Control;
///import baidu.lang.inherits;
///import baidu.event.on;
///import baidu.event.un;
///import baidu.event.getTarget;

/**
 * 浮动面板层控件
 *
 * @param {Object} options 参数
 */
esui.Layer = function ( options ) {
    esui.Control.call( this, options );

    // 类型声明，用于生成控件子dom的id和class
    this._type = this.retype || 'layer';

    // 标识鼠标事件触发自动状态转换
    this._autoState = 0;

    this.top = 0;
    this.left = 0;
    this.autoHide = this.autoHide || '';
};

esui.Layer.prototype = {
    /**
     * 绘制控件
     *
     * @public
     * @param {HTMLElement} main 控件挂载的DOM
     */
    render: function () {
        var main = this.main;
        esui.Control.prototype.render.call( this );

        main.style.position = 'absolute';
        main.style.left     = this._HIDE_POS;
        main.style.top      = this._HIDE_POS;
        this.zIndex && ( main.style.zIndex = this.zIndex );
        this.width  && ( main.style.width  = this.width + 'px' );
        this.height && ( main.style.height = this.height + 'px' );

        // 初始化autohide行为
        if ( this._autoHideInited ) {
            return;
        }

        switch ( this.autoHide.toLowerCase() ) {
        case 'click':
            this._clickHandler = this._getClickHider();
            baidu.on( document, 'click', this._clickHandler );
            break;
        case 'out':
            main.onmouseout = this._getOutHandler();
            main.onmouseover = this._getOverHandler();
            break;
        }

        this._autoHideInited = 1;
    },

    /**
     * 获取部件的css class
     *
     * @override
     * @return {string}
     */
    __getClass: function ( name ) {
        name = name || this.partName;

        return esui.Control.prototype.__getClass.call( this, name );
    },

    /**
     * 获取鼠标移入的事件handler
     *
     * @private
     * @return {Function}
     */
    _getOverHandler: function () {
        var me = this;
        return function () {
            me.show();
        };
    },

    /**
     * 获取鼠标移出的事件handler
     *
     * @private
     * @return {Function}
     */
    _getOutHandler: function () {
        var me = this;
        return function () {
            me.onhide();
            me.hide();
        };
    },

    onhide: new Function(),

    /**
     * 获取点击自动隐藏的处理handler
     *
     * @private
     * @return {Function}
     */
    _getClickHider: function () {
        var me = this;
        return function ( e ) {
            if ( me._isHidePrevent ) {
                me._isHidePrevent = 0;
                return;
            }

            var tar = baidu.event.getTarget( e );
            while ( tar && tar != document.body ) {
                if ( tar == me.main ) {
                    return;
                }
                tar = tar.parentNode;
            }

            me.onhide();
            me.hide();
        };
    },

    /**
     * 在一次点击中阻止隐藏层
     *
     * @private
     */
    _preventHide: function () {
        this._isHidePrevent = 1;
    },

    _HIDE_POS: '-10000px',

    /**
     * 设置浮动层的宽度
     *
     * @public
     * @param {number} width 宽度
     */
    setWidth: function ( width ) {
        this.main.style.width = width + 'px';
        this.width = width;
    },

    /**
     * 获取浮动层的宽度
     *
     * @public
     * @return {number}
     */
    getWidth: function () {
        return this.width || this.main.offsetWidth;
    },

    /**
     * 设置浮动层的高度
     *
     * @public
     * @param {number} height 高度
     */
    setHeight: function ( height ) {
        this.main.style.height = height + 'px';
        this.height = height;
    },

    /**
     * 获取浮动层的高度
     *
     * @public
     * @return {number}
     */
    getHeight: function () {
        return this.height || this.main.offsetHeight;
    },

    /**
     * 显示层
     *
     * @public
     */
    show: function ( left, top ) {
        this._isShow = 1;
        this.left = left || this.left;
        this.top = top || this.top;

        this.main.style.left = this.left + 'px';
        this.main.style.top = this.top + 'px';
    },

    /**
     * 隐藏层
     *
     * @public
     */
    hide: function () {
        this._isShow = 0;
        this.main.style.left = this._HIDE_POS;
        this.main.style.top = this._HIDE_POS;
    },

    /**
     * 获取层是否显示
     *
     * @public
     * @return {boolean}
     */
    isShow: function () {
        return !!this._isShow;
    },

    /**
     * 释放控件
     *
     * @private
     */
    __dispose: function () {
        var main = this.main;

        if ( this._clickHandler ) {
            baidu.un( document, 'click', this._clickHandler );
            this._clickHandler = null;
        }

        this.onhide = null;
        esui.Control.prototype.__dispose.call( this );

        main.innerHTML = '';
        main.parentNode && main.parentNode.removeChild( main );
    }
};

baidu.inherits( esui.Layer, esui.Control );
<|endoftext|>


<commit_before>/* globals angular */
angular.module('gc.fastRepeat', []).directive('fastRepeat', ['$compile', '$parse', '$animate', '$rootScope', function ($compile, $parse, $animate, $rootScope) {
    'use strict';

    var fastRepeatId = 0,
        showProfilingInfo = false;

    // JSON.stringify replacer function which removes any keys that start with $$.
    // This prevents unnecessary updates when we watch a JSON stringified value.
    function JSONStripper(key, value) {
        if(key.slice && key.slice(0,2) == '$$') { return undefined; }
        return value;
    }

    function getTime() { // For profiling
        if(window.performance && window.performance.now) { return window.performance.now(); }
        else { return (new Date()).getTime(); }
    }

    var debounce = function(func, wait, immediate) { // Underscore JS debounce function
        // Underscore.js 1.7.0
        // http://underscorejs.org
        // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
        // Underscore may be freely distributed under the MIT license

        var timeout, args, context, timestamp, result;

        var now = Date.now || function() { return new Date().getTime(); };

        var later = function() {
          var last = now() - timestamp;

          if (last < wait && last > 0) {
            timeout = setTimeout(later, wait - last);
          } else {
            timeout = null;
            if (!immediate) {
              result = func.apply(context, args);
              if (!timeout) { context = args = null; }
            }
          }
        };

        return function() {
          context = this;
          args = arguments;
          timestamp = now();
          var callNow = immediate && !timeout;
          if (!timeout) { timeout = setTimeout(later, wait); }
          if (callNow) {
            result = func.apply(context, args);
            context = args = null;
          }

          return result;
        };
      };

    return {
        restrict: 'A',
        transclude: 'element',
        priority: 1000,
        compile: function(tElement, tAttrs) {
            return function link(listScope, element, attrs, ctrl, transclude) {
                var repeatParts = attrs.fastRepeat.split(' in ');
                var repeatListName = repeatParts[1], repeatVarName = repeatParts[0];
                var getter = $parse(repeatListName); // getter(scope) should be the value of the list.
                var currentRowEls = {};
                var t;

                // The rowTpl will be digested once -- want to make sure it has valid data for the first wasted digest.  Default to first row or {} if no rows
                var scope = listScope.$new();
                scope[repeatVarName] = getter(scope)[0] || {};
                scope.fastRepeatStatic = true; scope.fastRepeatDynamic = false;

                // Transclude the contents of the fast repeat.
                // This function is called for every row. It reuses the rowTpl and scope for each row.
                var rowTpl = transclude(scope, function(rowTpl, scope) {
                    $animate.enabled(false, rowTpl);
                });

                // Create an offscreen div for the template
                var tplContainer = $("<div/>");
                $('body').append(tplContainer);
                scope.$on('$destroy', function() {
                    tplContainer.detach();
                });
                tplContainer.css({position: 'absolute', top: '110%'});
                var elParent = element.parents().filter(function() { return $(this).css('display') !== 'inline'; }).first();
                tplContainer.width(elParent.width());
                tplContainer.height(elParent.height());

                tplContainer.append(rowTpl);

                var updateList = function(rowTpl, scope, forceUpdate) {
                    function render(item) {
                        scope[repeatVarName] = item;
                        scope.$digest();
                        rowTpl.attr('fast-repeat-id', item.$$fastRepeatId);
                        return rowTpl.clone();
                    }

                    var list = getter(scope);
                    // Generate ids if necessary and arrange in a hash map
                    var listByIds = {};
                    angular.forEach(list, function(item) {
                        if(!item.$$fastRepeatId) {
                            if(item.id) { item.$$fastRepeatId = item.id; }
                            else if(item._id) { item.$$fastRepeatId = item._id; }
                            else { item.$$fastRepeatId = ++fastRepeatId; }
                        }
                        listByIds[item.$$fastRepeatId] = item;
                    });

                    // Delete removed rows
                    angular.forEach(currentRowEls, function(row, id) {
                        if(!listByIds[id]) {
                            row.el.detach();
                        }
                    });
                    // Add/rearrange all rows
                    var previousEl = element;
                    angular.forEach(list, function(item) {
                        var id = item.$$fastRepeatId;
                        var row=currentRowEls[id];
                        if(row) {
                            // We've already seen this one
                            if(!row.compiled && (forceUpdate || !angular.equals(row.copy, item))) {
                                // This item has not been compiled and it apparently has changed -- need to rerender
                                var newEl = render(item);
                                row.el.replaceWith(newEl);
                                row.el = newEl;
                                row.copy = angular.copy(item);
                            }
                        } else {
                            // This must be a new node
                            row = {
                                copy: angular.copy(item),
                                item: item,
                                el: render(item)
                            };
                            currentRowEls[id] =  row;
                        }
                        previousEl.after(row.el.last());
                        previousEl = row.el.last();
                    });

                };

                // Here is the main watch. Testing has shown that watching the stringified list can
                // save roughly 500ms per digest in certain cases.
                // JSONStripper is used to remove the $$fastRepeatId that we attach to the objects.
                var busy=false;
                listScope.$watch(function(scp){ return JSON.stringify(getter(scp), JSONStripper); }, function(list) {
                    tplContainer.width(elParent.width());
                    tplContainer.height(elParent.height());

                    if(busy) { return; }
                    busy=true;

                    if (showProfilingInfo) {
                        t = getTime();
                    }

                    // Rendering is done in a postDigest so that we are outside of the main digest cycle.
                    // This allows us to digest the individual row scope repeatedly without major hackery.
                    listScope.$$postDigest(function() {
                        tplContainer.width(elParent.width());
                        tplContainer.height(elParent.height());
                        scope.$digest();

                        updateList(rowTpl, scope);
                        if (showProfilingInfo) {
                            t = getTime() - t;
                            console.log("Total time: ", t, "ms");
                            console.log("time per row: ", t/list.length);
                        }
                        busy=false;
                    });
                }, false);

                element.parent().on('click', '[fast-repeat-id]', function(evt) {
                    var $target = $(this);
                    var rowId = $target.attr('fast-repeat-id');
                    var newScope = scope.$new(false);
                    // Find index of clicked dom element in list of all children element of the row.
                    // -1 would indicate the row itself was clicked.
                    var elIndex = $target.find('*').index(evt.target);

                    newScope[repeatVarName] = currentRowEls[rowId].item;
                    newScope.fastRepeatStatic = false; newScope.fastRepeatDynamic = true;
                    var clone;

                    clone = transclude(newScope, function(clone, scope) {
                        tplContainer.append(clone);
                    });

                    newScope.$$postDigest(function() {
                        $target.replaceWith(clone);
                        currentRowEls[rowId] = {
                            compiled: true,
                            el: clone
                        };

                        if(elIndex >= 0) {
                            clone.find('*').eq(elIndex).trigger('click');
                        } else {
                            clone.trigger('click');
                        }
                    });
                    newScope.$digest();
                });

                // Handle resizes
                //
                var onResize = debounce(function() {
                    tplContainer.width(elParent.width());
                    tplContainer.height(elParent.height());
                    scope.$digest();

                    if(busy) { return; }
                    updateList(rowTpl, scope, true);
                }, 500);

                var jqWindow = $(window);
                jqWindow.on('resize', onResize);
                element.on('$destroy', function() { jqWindow.off('resize', onResize); });

            };
        },
    };
}]);
<commit_msg>Removed rerendering of rows on resize.<commit_after>/* globals angular */
angular.module('gc.fastRepeat', []).directive('fastRepeat', ['$compile', '$parse', '$animate', '$rootScope', function ($compile, $parse, $animate, $rootScope) {
    'use strict';

    var fastRepeatId = 0,
        showProfilingInfo = false;

    // JSON.stringify replacer function which removes any keys that start with $$.
    // This prevents unnecessary updates when we watch a JSON stringified value.
    function JSONStripper(key, value) {
        if(key.slice && key.slice(0,2) == '$$') { return undefined; }
        return value;
    }

    function getTime() { // For profiling
        if(window.performance && window.performance.now) { return window.performance.now(); }
        else { return (new Date()).getTime(); }
    }

    var debounce = function(func, wait, immediate) { // Underscore JS debounce function
        // Underscore.js 1.7.0
        // http://underscorejs.org
        // (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
        // Underscore may be freely distributed under the MIT license

        var timeout, args, context, timestamp, result;

        var now = Date.now || function() { return new Date().getTime(); };

        var later = function() {
          var last = now() - timestamp;

          if (last < wait && last > 0) {
            timeout = setTimeout(later, wait - last);
          } else {
            timeout = null;
            if (!immediate) {
              result = func.apply(context, args);
              if (!timeout) { context = args = null; }
            }
          }
        };

        return function() {
          context = this;
          args = arguments;
          timestamp = now();
          var callNow = immediate && !timeout;
          if (!timeout) { timeout = setTimeout(later, wait); }
          if (callNow) {
            result = func.apply(context, args);
            context = args = null;
          }

          return result;
        };
      };

    return {
        restrict: 'A',
        transclude: 'element',
        priority: 1000,
        compile: function(tElement, tAttrs) {
            return function link(listScope, element, attrs, ctrl, transclude) {
                var repeatParts = attrs.fastRepeat.split(' in ');
                var repeatListName = repeatParts[1], repeatVarName = repeatParts[0];
                var getter = $parse(repeatListName); // getter(scope) should be the value of the list.
                var currentRowEls = {};
                var t;

                // The rowTpl will be digested once -- want to make sure it has valid data for the first wasted digest.  Default to first row or {} if no rows
                var scope = listScope.$new();
                scope[repeatVarName] = getter(scope)[0] || {};
                scope.fastRepeatStatic = true; scope.fastRepeatDynamic = false;

                // Transclude the contents of the fast repeat.
                // This function is called for every row. It reuses the rowTpl and scope for each row.
                var rowTpl = transclude(scope, function(rowTpl, scope) {
                    $animate.enabled(false, rowTpl);
                });

                // Create an offscreen div for the template
                var tplContainer = $("<div/>");
                $('body').append(tplContainer);
                scope.$on('$destroy', function() {
                    tplContainer.detach();
                });
                tplContainer.css({position: 'absolute', top: '110%'});
                var elParent = element.parents().filter(function() { return $(this).css('display') !== 'inline'; }).first();
                tplContainer.width(elParent.width());
                tplContainer.height(elParent.height());

                tplContainer.append(rowTpl);

                var updateList = function(rowTpl, scope, forceUpdate) {
                    function render(item) {
                        scope[repeatVarName] = item;
                        scope.$digest();
                        rowTpl.attr('fast-repeat-id', item.$$fastRepeatId);
                        return rowTpl.clone();
                    }

                    var list = getter(scope);
                    // Generate ids if necessary and arrange in a hash map
                    var listByIds = {};
                    angular.forEach(list, function(item) {
                        if(!item.$$fastRepeatId) {
                            if(item.id) { item.$$fastRepeatId = item.id; }
                            else if(item._id) { item.$$fastRepeatId = item._id; }
                            else { item.$$fastRepeatId = ++fastRepeatId; }
                        }
                        listByIds[item.$$fastRepeatId] = item;
                    });

                    // Delete removed rows
                    angular.forEach(currentRowEls, function(row, id) {
                        if(!listByIds[id]) {
                            row.el.detach();
                        }
                    });
                    // Add/rearrange all rows
                    var previousEl = element;
                    angular.forEach(list, function(item) {
                        var id = item.$$fastRepeatId;
                        var row=currentRowEls[id];
                        if(row) {
                            // We've already seen this one
                            if(!row.compiled && (forceUpdate || !angular.equals(row.copy, item))) {
                                // This item has not been compiled and it apparently has changed -- need to rerender
                                var newEl = render(item);
                                row.el.replaceWith(newEl);
                                row.el = newEl;
                                row.copy = angular.copy(item);
                            }
                        } else {
                            // This must be a new node
                            row = {
                                copy: angular.copy(item),
                                item: item,
                                el: render(item)
                            };
                            currentRowEls[id] =  row;
                        }
                        previousEl.after(row.el.last());
                        previousEl = row.el.last();
                    });

                };

                // Here is the main watch. Testing has shown that watching the stringified list can
                // save roughly 500ms per digest in certain cases.
                // JSONStripper is used to remove the $$fastRepeatId that we attach to the objects.
                var busy=false;
                listScope.$watch(function(scp){ return JSON.stringify(getter(scp), JSONStripper); }, function(list) {
                    tplContainer.width(elParent.width());
                    tplContainer.height(elParent.height());

                    if(busy) { return; }
                    busy=true;

                    if (showProfilingInfo) {
                        t = getTime();
                    }

                    // Rendering is done in a postDigest so that we are outside of the main digest cycle.
                    // This allows us to digest the individual row scope repeatedly without major hackery.
                    listScope.$$postDigest(function() {
                        tplContainer.width(elParent.width());
                        tplContainer.height(elParent.height());
                        scope.$digest();

                        updateList(rowTpl, scope);
                        if (showProfilingInfo) {
                            t = getTime() - t;
                            console.log("Total time: ", t, "ms");
                            console.log("time per row: ", t/list.length);
                        }
                        busy=false;
                    });
                }, false);

                element.parent().on('click', '[fast-repeat-id]', function(evt) {
                    var $target = $(this);
                    var rowId = $target.attr('fast-repeat-id');
                    var newScope = scope.$new(false);
                    // Find index of clicked dom element in list of all children element of the row.
                    // -1 would indicate the row itself was clicked.
                    var elIndex = $target.find('*').index(evt.target);

                    newScope[repeatVarName] = currentRowEls[rowId].item;
                    newScope.fastRepeatStatic = false; newScope.fastRepeatDynamic = true;
                    var clone;

                    clone = transclude(newScope, function(clone, scope) {
                        tplContainer.append(clone);
                    });

                    newScope.$$postDigest(function() {
                        $target.replaceWith(clone);
                        currentRowEls[rowId] = {
                            compiled: true,
                            el: clone
                        };

                        if(elIndex >= 0) {
                            clone.find('*').eq(elIndex).trigger('click');
                        } else {
                            clone.trigger('click');
                        }
                    });
                    newScope.$digest();
                });

                // Handle resizes
                //
                var onResize = function() {
                    tplContainer.width(elParent.width());
                    tplContainer.height(elParent.height());
                };

                var jqWindow = $(window);
                jqWindow.on('resize', onResize);
                element.on('$destroy', function() { jqWindow.off('resize', onResize); });

            };
        },
    };
}]);
<|endoftext|>


<commit_before>import CoreForm from './core'

export default CoreForm
<commit_msg>Make the API-aware OmniForm the default Form component<commit_after>import OmniForm from './omni'

export default OmniForm

export * from './core'
<|endoftext|>


<commit_before>"use strict";

var f = require('util').format;

exports['Should correctly perform awaitdata'] = {
  metadata: {
    requires: { topology: ["single", "replicaset", "sharded"] }
  },

  test: function(configuration, test) {
    configuration.newTopology(function(err, server) {
      var ns = f("%s.cursor_tailable", configuration.db);
      // Add event listeners
      server.on('connect', function(_server) {
        // Create a capped collection
        _server.command(f("%s.$cmd", configuration.db), {create: 'cursor_tailable', capped:true, size: 10000}, function(err, r) {
          // Execute the write
          _server.insert(ns, [{a:1}], {
            writeConcern: {w:1}, ordered:true
          }, function(err, results) {
            test.equal(null, err);
            test.equal(1, results.result.n);

            // Execute find
            var cursor = _server.cursor(ns, {
                find: ns
              , query: {}
              , batchSize: 2
              , tailable: true
              , awaitData: true
            });

            // Execute next
            cursor.next(function(err, d) {
              // console.log("==================================== Should correctly perform awaitdata 0")
              test.equal(null, err);
              var s = new Date();

              cursor.next(function(err, d) {
                var e = new Date();
                // console.log("==================================== Should correctly perform awaitdata")
                // console.log((e.getTime() - s.getTime()));

                test.ok((e.getTime() - s.getTime()) >= 300);

                // Destroy the server connection
                _server.destroy();
                // Finish the test
                test.done();
              });

              setTimeout(function() {
                cursor.kill();
              }, 300)
            });
          });
        });
      })

      // Start connection
      server.connect();
    });
  }
}
<commit_msg>test(tailable_cursor_tests): convert tailable_cursor_tests to run with mocha<commit_after>'use strict';

var expect = require('chai').expect,
    f = require('util').format;

describe('Tailable cursor tests', function() {
  it('should correctly perform awaitdata', {
    metadata: {
      requires: { topology: ['single', 'replicaset', 'sharded'] }
    },

    test: function(done) {
      var self = this;

      this.configuration.newTopology(function(err, server) {
        var ns = f('%s.cursor_tailable', self.configuration.db);
        // Add event listeners
        server.on('connect', function(_server) {
          // Create a capped collection
          _server.command(f('%s.$cmd', self.configuration.db), {create: 'cursor_tailable', capped: true, size: 10000}, function(cmdErr, cmdRes) {
            // Execute the write
            _server.insert(ns, [{a: 1}], {
              writeConcern: {w: 1}, ordered: true
            }, function(insertErr, results) {
              expect(insertErr).to.be.null;
              expect(results.result.n).to.equal(1);

              // Execute find
              var cursor = _server.cursor(ns, {
                find: ns,
                query: {},
                batchSize: 2,
                tailable: true,
                awaitData: true
              });

              // Execute next
              cursor.next(function(cursorErr, cursorD) {
                expect(cursorErr).to.be.null;
                var s = new Date();

                cursor.next(function(secondCursorErr, secondCursorD) {
                  var e = new Date();
                  expect(e.getTime() - s.getTime()).to.be.at.least(300);

                  // Destroy the server connection
                  _server.destroy();
                  // Finish the test
                  done();
                });

                setTimeout(function() {
                  cursor.kill();
                }, 300);
              });
            });
          });
        });

        // Start connection
        server.connect();
      });
    }
  });
});
<|endoftext|>


<commit_before>var gameModule = angular.module('app', []).
	controller("gameTheoryControl", function gameTheoryControl($scope){

	    	function number(num){
	    		this.name = num;
	    		this.selected = false;
	    		return this;
	    	}

	    	$scope.numbers=[];
	    	$scope.solutions=[];

	    	$scope.getStarter = function(){
	    		var isEven = ($scope.solutions % 2) == 0;

	    		if(isEven){
	    			return "Alice";
	    		}
	    		else{
	    			return "Bob";
	    		}
	    	}

	    	function solution(x, parts){
	    		this.number = x;
	    		this.parts = parts;
	    	}

	    	$scope.amount = 10;

	    	$scope.newNumbers = function(){
			$scope.numbers = [];

			intAmount = parseInt($scope.amount);

			for(var i = 1; i < intAmount + 1; i++){
				$scope.numbers.push(new number(i));
			}
		}

		$scope.deleteSelected = function(){
			for(var num in $scope.numbers){
				if($scope.numbers[num].selected){
					$scope.numbers.splice(num, 1);
				}
			}
		}

		function sumOf(parts){
			var num = 0;
			for(var i = 0; i < parts.length; i++){
				num += parts[i];
			}
			return num;
		}

		function getSmallerNumbers(number){
			var newArray = [];
			for(var i = 0; i < $scope.numbers.length; i++){
				if($scope.numbers[i].name <= number){
					newArray.push($scope.numbers[i].name);
				}
				else{
					break;
				}
			}
			return newArray;
		}

		var getCombinations2 = function(firstParts, parts, solutions) {
			var results = [];
		    	for (var i = 0; i < parts.length; i++) {
			      solutions.push(firstParts.concat(parts[i]));
			      solutions.concat(getCombinations(firstParts.concat(parts[i]), parts.splice(i + 1)), solutions);
		    	}
		   return solutions;
		}

		var getCombinations = function(startArray, arrayOfNumbers){
			var results = [];
			for(var i = 0; i < arrayOfNumbers.length; i++){
				results.push(startArray.concat(arrayOfNumbers[i]));

				var tempArray = [];
				for(var j = 0; j < arrayOfNumbers.length; j++){
					if(i != j){
						tempArray.push(arrayOfNumbers[j]);
					}
				}

				results = results.concat(getCombinations(startArray.concat(arrayOfNumbers[i]), tempArray));
			}
			return results;
		}

		$scope.getSolutions = function(){
			$scope.solutions = [];
			var calculable = true;
			var currentNumber = 1;

			while(calculable){
				parts = [];

				var solved = false;

				var smallerNums = getSmallerNumbers(currentNumber);

				if(smallerNums.length == 0){
					calculable = false; break;
				}

				var combinations = getCombinations([], smallerNums);

					for(var i = 0; i < combinations.length; i++){
						if(sumOf(combinations[i]) == currentNumber){
							$scope.solutions.push(new solution(currentNumber, combinations[i]));
							solved = true;
							break;
						}
						if(solved){break;}
					}

				if(!solved){
					calculable = false; break;
				}

				currentNumber++;
			}
		}

		$scope.newNumbers();

	});
<commit_msg>Update gameTheoryController.js<commit_after>var gameModule = angular.module('app', []).
	controller("gameTheoryControl", function gameTheoryControl($scope){

	    	function number(num){
	    		this.name = num;
	    		this.selected = false;
	    		return this;
	    	}

	    	$scope.numbers=[];
	    	$scope.solutions=[];

	    	$scope.getStarter = function(){
	    		var isEven = ($scope.solutions % 2) == 0;

	    		if(isEven){
	    			return "Alice";
	    		}
	    		else{
	    			return "Bob";
	    		}
	    	}

	    	function solution(x, parts){
	    		this.number = x;
	    		this.parts = parts;
	    	}

	    	$scope.amount = 10;

	    	$scope.newNumbers = function(){
			$scope.numbers = [];

			intAmount = parseInt($scope.amount);

			for(var i = 1; i < intAmount + 1; i++){
				$scope.numbers.push(new number(i));
			}
		}

		$scope.deleteSelected = function(){
			for(var num in $scope.numbers){
				if($scope.numbers[num].selected){
					$scope.numbers.splice(num, 1);
					num--;
				}
			}
		}

		function sumOf(parts){
			var num = 0;
			for(var i = 0; i < parts.length; i++){
				num += parts[i];
			}
			return num;
		}

		function getSmallerNumbers(number){
			var newArray = [];
			for(var i = 0; i < $scope.numbers.length; i++){
				if($scope.numbers[i].name <= number){
					newArray.push($scope.numbers[i].name);
				}
				else{
					break;
				}
			}
			return newArray;
		}

		var getCombinations2 = function(firstParts, parts, solutions) {
			var results = [];
		    	for (var i = 0; i < parts.length; i++) {
			      solutions.push(firstParts.concat(parts[i]));
			      solutions.concat(getCombinations(firstParts.concat(parts[i]), parts.splice(i + 1)), solutions);
		    	}
		   return solutions;
		}

		var getCombinations = function(startArray, arrayOfNumbers){
			var results = [];
			for(var i = 0; i < arrayOfNumbers.length; i++){
				results.push(startArray.concat(arrayOfNumbers[i]));

				var tempArray = [];
				for(var j = 0; j < arrayOfNumbers.length; j++){
					if(i != j){
						tempArray.push(arrayOfNumbers[j]);
					}
				}

				results = results.concat(getCombinations(startArray.concat(arrayOfNumbers[i]), tempArray));
			}
			return results;
		}

		$scope.getSolutions = function(){
			$scope.solutions = [];
			var calculable = true;
			var currentNumber = 1;

			while(calculable){
				parts = [];

				var solved = false;

				var smallerNums = getSmallerNumbers(currentNumber);

				if(smallerNums.length == 0){
					calculable = false; break;
				}

				var combinations = getCombinations([], smallerNums);

					for(var i = 0; i < combinations.length; i++){
						if(sumOf(combinations[i]) == currentNumber){
							$scope.solutions.push(new solution(currentNumber, combinations[i]));
							solved = true;
							break;
						}
						if(solved){break;}
					}

				if(!solved){
					calculable = false; break;
				}

				currentNumber++;
			}
		}

		$scope.newNumbers();

	});
<|endoftext|>


<commit_before>'use strict';

// This code uses ES2015 syntax that requires at least Node.js v4.
// For Node.js ES2015 support details, reference http://node.green/

function validateArgumentType(arg, argName, expectedType) {
    if (typeof arg === 'undefined') {
        throw new Error('Missing argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + '.');
    } else if (typeof arg !== expectedType) {
        throw new Error('Invalid argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + ', got: ' + (typeof arg));
    }
}

var deviceHvacModeToTranslatorHvacModeMap = {
    'cool': 'coolOnly',
    'heat': 'heatOnly',
    'heat-cool': 'auto',
    'off': 'off'
}

var translatorHvacModeToDeviceHvacModeMap = {
    'coolOnly': 'cool',
    'heatOnly': 'heat',
    'auto': 'heat-cool',
    'off': 'off'
}

function deviceHvacModeToTranslatorHvacMode(mode) {
    return deviceHvacModeToTranslatorHvacModeMap[mode];
}

function translatorHvacModeToDeviceHvacMode(mode) {
    return translatorHvacModeToDeviceHvacModeMap[mode];
}

function readHvacMode(deviceSchema) {
    // Assume 'auto' and 'off' are always supported
    var supportedHvacModes = [
        'auto',
        'off'
    ];

    if (deviceSchema['can_cool']) {
        supportedHvacModes.push('coolOnly');
    }
    if (deviceSchema['can_heat']) {
        supportedHvacModes.push('heatOnly');
    }

    var hvacMode = deviceHvacModeToTranslatorHvacMode(deviceSchema['hvac_mode']);
    if (hvacMode === undefined) deviceHvacModeToTranslatorHvacMode(deviceSchema['hvac_state']);

    return {
        supportedModes: supportedHvacModes,
        modes: [hvacMode]
    };
}

function createResource(resourceType, accessLevel, id, expand, state) {
    var resource = {
        href: '/' + id,
        rt: [resourceType],
        if: [accessLevel, 'oic.if.baseline']
    }

    if (expand) {
        resource.id = id;
        Object.assign(resource, state);
    }

    return resource;
}

// Helper method to convert the provider schema to the platform schema.
function providerSchemaToPlatformSchema(providerSchema, expand) {

    // Quirks:
    // - Nest does not have an external temperature field, so that is left out.
    // - Away Mode is not implemented at this time.

    // Get temperature scale
    var ts = providerSchema['temperature_scale'] !== undefined ? providerSchema['temperature_scale'].toLowerCase() : undefined;

    var ambientTemperature = createResource('oic.r.temperature', 'oic.if.s', 'ambientTemperature', expand, {
        temperature: providerSchema['ambient_temperature_' + ts],
        units: ts
    });

    var targetTemperature = createResource('oic.r.temperature', 'oic.if.a', 'targetTemperature', expand, {
        temperature: providerSchema['target_temperature_' + ts],
        units: ts
    });

    var targetTemperatureHigh = createResource('oic.r.temperature', 'oic.if.a', 'targetTemperatureHigh', expand, {
        temperature: providerSchema['target_temperature_high_' + ts],
        units: ts
    });

    var targetTemperatureLow = createResource('oic.r.temperature', 'oic.if.a', 'targetTemperatureLow', expand, {
        temperature: providerSchema['target_temperature_low_' + ts],
        units: ts
    });

    var awayTemperatureHigh = createResource('oic.r.temperature', 'oic.if.s', 'awayTemperatureHigh', expand, {
        temperature: providerSchema['away_temperature_high_' + ts],
        units: ts
    });

    var awayTemperatureLow = createResource('oic.r.temperature', 'oic.if.s', 'awayTemperatureLow', expand, {
        temperature: providerSchema['away_temperature_low_' + ts],
        units: ts
    });

    var humidity = createResource('oic.r.humidity', 'oic.if.s', 'humidity', expand, {
        humidity: providerSchema['humidity']
    });

    var awayMode = createResource('oic.r.mode', 'oic.if.a', 'awayMode', expand, {
        modes:  providerSchema['away'],
        supportedModes: ['home', 'away']
    });

    var ecoMode = createResource('oic.r.sensor', 'oic.if.s', 'ecoMode', expand, {
        value: providerSchema['has_leaf']
    });

    var hvacMode = createResource('oic.r.mode', 'oic.if.a', 'hvacMode', expand, readHvacMode(providerSchema));

    var hasFan = createResource('oic.r.sensor', 'oic.if.s', 'hasFan', expand, {
        value: providerSchema['has_fan']
    });

    var fanActive = createResource('oic.r.sensor', 'oic.if.a', 'fanActive', expand, {
        value: providerSchema['fan_timer_active']
    });

    var fanTimerActive = createResource('oic.r.sensor', 'oic.if.a', 'fanTimerActive', expand, {
        value: providerSchema['fan_timer_active']
    });

    return {
        opent2t: {
            schema: 'org.opent2t.sample.thermostat.superpopular',
            translator: 'opent2t-translator-com-nest-thermostat',
            controlId: providerSchema['device_id']
        },
        pi: providerSchema['device_id'],
        mnmn: 'Nest',
        mnmo: 'Undefined',
        n: providerSchema['name_long'],
        rt: ['org.opent2t.sample.thermostat.superpopular'],
        entities: [
            {
                rt: ['opent2t.d.thermostat'],
                di: providerSchema['device_id'],
                resources: [
                    ambientTemperature,
                    targetTemperature,
                    targetTemperatureHigh,
                    targetTemperatureLow,
                    awayTemperatureHigh,
                    awayTemperatureLow,
                    humidity,
                    awayMode,
                    ecoMode,
                    hvacMode,
                    hasFan,
                    fanActive,
                    fanTimerActive
                ]
            }
        ]
    };
}

// Helper method to convert the translator schema to the device schema.
function resourceSchemaToProviderSchema(resourceId, resourceSchema) {
    // build the object with desired state
    var result = {};

    switch (resourceId) {
        case 'targetTemperature':
            result['target_temperature_' + resourceSchema.units.toLowerCase()] = resourceSchema.temperature;
            break;
        case 'targetTemperatureHigh':
            result['target_temperature_high_' + resourceSchema.units.toLowerCase()] = resourceSchema.temperature;
            break;
        case 'targetTemperatureLow':
            result['target_temperature_low_' + resourceSchema.units.toLowerCase()] = resourceSchema.temperature;
            break;
        case 'hvacMode':
            result['hvac_mode'] = translatorHvacModeToDeviceHvacMode(resourceSchema.modes[0]);
            break;
        case 'fanActive':
        case 'fanTimerActive':
            result['fan_timer_active'] = resourceSchema.value;
            break;
        case 'ambientTemperature':
        case 'awayTemperatureHigh':
        case 'awayTemperatureLow':
        case 'humidity':
        case 'ecoMode':
        case 'fanTimerTimeout':
            throw new Error('NotMutable');
        default:
            throw new Error('NotFound');
    }

    return result;
}

function validateResourceGet(resourceId) {
    switch (resourceId) {
        case 'heatingFuelSource':
        case 'fanMode':
        case 'fanTimerTimeout':
        case 'awayMode':
            throw new Error('NotImplemented');
    }
}

function findResource(schema, di, resourceId) {
    var entity = schema.entities.find((d) => {
        return d.di === di;
    });

    if (!entity) {
        throw new Error('NotFound');
    }

    var resource = entity.resources.find((r) => {
        return r.id === resourceId;
    });

    if (!resource) {
        throw new Error('NotFound');
    }

    return resource;
}

function getDeviceResource(translator, di, resourceId) {
    validateResourceGet(resourceId);

    return translator.get(true)
        .then(response => {
            return findResource(response, di, resourceId);
        });
}

function postDeviceResource(di, resourceId, payload) {
    if (di === controlId)
    {
        var putPayload = resourceSchemaToProviderSchema(resourceId, payload);

        return nestHub.putDeviceDetailsAsync(deviceType, controlId, putPayload)
            .then((response) => {
                var schema = providerSchemaToPlatformSchema(response, true);
                return findResource(schema, di, resourceId);
            });
    } else {
        throw new Error('NotFound');
    }
}

var controlId;
var deviceType = 'thermostats';
var nestHub;

// This translator class implements the 'org.opent2t.sample.thermostat.superpopular' interface.
class Translator {

    constructor(deviceInfo) {
        console.log('Nest Thermostat initializing...');

        validateArgumentType(deviceInfo, "deviceInfo", "object");
        controlId = deviceInfo.deviceInfo.opent2t.controlId;
        nestHub = deviceInfo.hub;

        console.log('Nest Thermostat initializing...Done');
    }

    // Queries the entire state of the binary switch
    // and returns an object that maps to the json schema opent2t.p.thermostat
    get(expand, payload) {
        if (payload) {
            return providerSchemaToPlatformSchema(payload, expand);
        } else {
            return nestHub.getDeviceDetailsAsync(deviceType, controlId)
                .then((response) => {
                    return providerSchemaToPlatformSchema(response, expand);
                });
        }
    }

    getDevicesAmbientTemperature(di) {
        return getDeviceResource(this, di, 'ambientTemperature');
    }

    getDevicesTargetTemperature(di) {
        return getDeviceResource(this, di, 'targetTemperature');
    }

    postDevicesTargetTemperature(di, payload) {
        return postDeviceResource(di, 'targetTemperature', payload);
    }

    getDevicesHumidity(di) {
        return getDeviceResource(this, di, 'humidity');
    }

    getDevicesTargetTemperatureHigh(di) {
        return getDeviceResource(this, di, 'targetTemperatureHigh');
    }

    postDevicesTargetTemperatureHigh(di, payload) {
        return postDeviceResource(di, 'targetTemperatureHigh', payload);
    }

    getDevicesTargetTemperatureLow(di) {
        return getDeviceResource(this, di, 'targetTemperatureLow');
    }

    postDevicesTargetTemperatureLow(di, payload) {
        return postDeviceResource(di, 'targetTemperatureLow', payload);
    }

    getDevicesAwayMode(di) {
        return getDeviceResource(this, di, 'awayMode');
    }

    postDevicesAwayMode(di, payload) {
        return postDeviceResource(di, 'awayMode', payload);
    }

    getDevicesAwayTemperatureHigh(di) {
        return getDeviceResource(this, di, 'awayTemperatureHigh');
    }

    postDevicesAwayTemperatureHigh(di, payload) {
        return postDeviceResource(di, 'awayTemperatureHigh', payload);
    }

    getDevicesAwayTemperatureLow(di) {
        return getDeviceResource(this, di, 'awayTemperatureLow');
    }

    postDevicesAwayTemperatureLow(di, payload) {
        return postDeviceResource(di, 'awayTemperatureLow', payload);
    }

    getDevicesEcoMode(di) {
        return getDeviceResource(this, di, 'ecoMode');
    }

    getDevicesHvacMode(di) {
        return getDeviceResource(this, di, 'hvacMode');
    }

    postDevicesHvacMode(di, payload) {
        return postDeviceResource(di, 'hvacMode', payload);
    }

    getDevicesHeatingFuelSource(di) {
        return getDeviceResource(this, di, 'heatingFuelSource');
    }

    getDevicesHasFan(di) {
        return getDeviceResource(this, di, 'hasFan');
    }

    getDevicesFanActive(di) {
        return getDeviceResource(this, di, 'fanActive');
    }

    getDevicesFanTimerActive(di) {
        return getDeviceResource(this, di, 'fanTimerActive');
    }

    getDevicesFanTimerTimeout(di) {
        return getDeviceResource(this, di, 'fanTimerTimeout');
    }

    postDevicesFanTimerTimeout(di, payload) {
        return postDeviceResource(di, 'fanTimerTimeout', payload);
    }

    getDevicesFanMode(di) {
        return getDeviceResource(this, di, 'fanMode');
    }

    postDevicesFanMode(di, payload) {
        return postDeviceResource(di, 'fanMode', payload);
    }

    postSubscribe(subscriptionInfo) {
        subscriptionInfo.controlId = controlId;
        return nestHub.postSubscribe(subscriptionInfo);
    }

    deleteSubscribe(subscriptionInfo) {
        subscriptionInfo.controlId = controlId;
        return nestHub._unsubscribe(subscriptionInfo);
    }
}

// Export the translator from the module.
module.exports = Translator;
<commit_msg>Add error handling.<commit_after>'use strict';

// This code uses ES2015 syntax that requires at least Node.js v4.
// For Node.js ES2015 support details, reference http://node.green/

function validateArgumentType(arg, argName, expectedType) {
    if (typeof arg === 'undefined') {
        throw new Error('Missing argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + '.');
    } else if (typeof arg !== expectedType) {
        throw new Error('Invalid argument: ' + argName + '. ' +
            'Expected type: ' + expectedType + ', got: ' + (typeof arg));
    }
}

var deviceHvacModeToTranslatorHvacModeMap = {
    'cool': 'coolOnly',
    'heat': 'heatOnly',
    'heat-cool': 'auto',
    'off': 'off'
}

var translatorHvacModeToDeviceHvacModeMap = {
    'coolOnly': 'cool',
    'heatOnly': 'heat',
    'auto': 'heat-cool',
    'off': 'off'
}

function deviceHvacModeToTranslatorHvacMode(mode) {
    return deviceHvacModeToTranslatorHvacModeMap[mode];
}

function translatorHvacModeToDeviceHvacMode(mode) {
    return translatorHvacModeToDeviceHvacModeMap[mode];
}

function readHvacMode(deviceSchema) {
    // Assume 'auto' and 'off' are always supported
    var supportedHvacModes = [
        'auto',
        'off'
    ];

    if (deviceSchema['can_cool']) {
        supportedHvacModes.push('coolOnly');
    }
    if (deviceSchema['can_heat']) {
        supportedHvacModes.push('heatOnly');
    }

    var hvacMode = deviceHvacModeToTranslatorHvacMode(deviceSchema['hvac_mode']);
    if (hvacMode === undefined) deviceHvacModeToTranslatorHvacMode(deviceSchema['hvac_state']);

    return {
        supportedModes: supportedHvacModes,
        modes: [hvacMode]
    };
}

function createResource(resourceType, accessLevel, id, expand, state) {
    var resource = {
        href: '/' + id,
        rt: [resourceType],
        if: [accessLevel, 'oic.if.baseline']
    }

    if (expand) {
        resource.id = id;
        Object.assign(resource, state);
    }

    return resource;
}

// Helper method to convert the provider schema to the platform schema.
function providerSchemaToPlatformSchema(providerSchema, expand) {

    // Quirks:
    // - Nest does not have an external temperature field, so that is left out.
    // - Away Mode is not implemented at this time.

    // Get temperature scale
    var ts = providerSchema['temperature_scale'] !== undefined ? providerSchema['temperature_scale'].toLowerCase() : undefined;

    var ambientTemperature = createResource('oic.r.temperature', 'oic.if.s', 'ambientTemperature', expand, {
        temperature: providerSchema['ambient_temperature_' + ts],
        units: ts
    });

    var targetTemperature = createResource('oic.r.temperature', 'oic.if.a', 'targetTemperature', expand, {
        temperature: providerSchema['target_temperature_' + ts],
        units: ts
    });

    var targetTemperatureHigh = createResource('oic.r.temperature', 'oic.if.a', 'targetTemperatureHigh', expand, {
        temperature: providerSchema['target_temperature_high_' + ts],
        units: ts
    });

    var targetTemperatureLow = createResource('oic.r.temperature', 'oic.if.a', 'targetTemperatureLow', expand, {
        temperature: providerSchema['target_temperature_low_' + ts],
        units: ts
    });

    var awayTemperatureHigh = createResource('oic.r.temperature', 'oic.if.s', 'awayTemperatureHigh', expand, {
        temperature: providerSchema['away_temperature_high_' + ts],
        units: ts
    });

    var awayTemperatureLow = createResource('oic.r.temperature', 'oic.if.s', 'awayTemperatureLow', expand, {
        temperature: providerSchema['away_temperature_low_' + ts],
        units: ts
    });

    var humidity = createResource('oic.r.humidity', 'oic.if.s', 'humidity', expand, {
        humidity: providerSchema['humidity']
    });

    var awayMode = createResource('oic.r.mode', 'oic.if.a', 'awayMode', expand, {
        modes:  providerSchema['away'],
        supportedModes: ['home', 'away']
    });

    var ecoMode = createResource('oic.r.sensor', 'oic.if.s', 'ecoMode', expand, {
        value: providerSchema['has_leaf']
    });

    var hvacMode = createResource('oic.r.mode', 'oic.if.a', 'hvacMode', expand, readHvacMode(providerSchema));

    var hasFan = createResource('oic.r.sensor', 'oic.if.s', 'hasFan', expand, {
        value: providerSchema['has_fan']
    });

    var fanActive = createResource('oic.r.sensor', 'oic.if.a', 'fanActive', expand, {
        value: providerSchema['fan_timer_active']
    });

    var fanTimerActive = createResource('oic.r.sensor', 'oic.if.a', 'fanTimerActive', expand, {
        value: providerSchema['fan_timer_active']
    });

    return {
        opent2t: {
            schema: 'org.opent2t.sample.thermostat.superpopular',
            translator: 'opent2t-translator-com-nest-thermostat',
            controlId: providerSchema['device_id']
        },
        pi: providerSchema['device_id'],
        mnmn: 'Nest',
        mnmo: 'Undefined',
        n: providerSchema['name_long'],
        rt: ['org.opent2t.sample.thermostat.superpopular'],
        entities: [
            {
                rt: ['opent2t.d.thermostat'],
                di: providerSchema['device_id'],
                resources: [
                    ambientTemperature,
                    targetTemperature,
                    targetTemperatureHigh,
                    targetTemperatureLow,
                    awayTemperatureHigh,
                    awayTemperatureLow,
                    humidity,
                    awayMode,
                    ecoMode,
                    hvacMode,
                    hasFan,
                    fanActive,
                    fanTimerActive
                ]
            }
        ]
    };
}

// Helper method to convert the translator schema to the device schema.
function resourceSchemaToProviderSchema(resourceId, resourceSchema) {
    // build the object with desired state
    var result = {};

    switch (resourceId) {
        case 'targetTemperature':
            if (resourceSchema.units === undefined) throw new Error('Resource Schema missing temperature units.');
            result['target_temperature_' + resourceSchema.units.toLowerCase()] = resourceSchema.temperature;
            break;
        case 'targetTemperatureHigh':
            if (resourceSchema.units === undefined) throw new Error('Resource Schema missing temperature units.');
            result['target_temperature_high_' + resourceSchema.units.toLowerCase()] = resourceSchema.temperature;
            break;
        case 'targetTemperatureLow':
            if (resourceSchema.units === undefined) throw new Error('Resource Schema missing temperature units.');
            result['target_temperature_low_' + resourceSchema.units.toLowerCase()] = resourceSchema.temperature;
            break;
        case 'hvacMode':
            result['hvac_mode'] = translatorHvacModeToDeviceHvacMode(resourceSchema.modes[0]);
            break;
        case 'fanActive':
        case 'fanTimerActive':
            result['fan_timer_active'] = resourceSchema.value;
            break;
        case 'ambientTemperature':
        case 'awayTemperatureHigh':
        case 'awayTemperatureLow':
        case 'humidity':
        case 'ecoMode':
        case 'awayMode':
        case 'fanTimerTimeout':
            throw new Error('NotMutable');
        default:
            throw new Error('NotFound');
    }

    return result;
}

function validateResourceGet(resourceId) {
    switch (resourceId) {
        case 'heatingFuelSource':
        case 'fanMode':
        case 'fanTimerTimeout':
            throw new Error('NotImplemented');
    }
}

function findResource(schema, di, resourceId) {
    var entity = schema.entities.find((d) => {
        return d.di === di;
    });

    if (!entity) {
        throw new Error('NotFound');
    }

    var resource = entity.resources.find((r) => {
        return r.id === resourceId;
    });

    if (!resource) {
        throw new Error('NotFound');
    }

    return resource;
}

function getDeviceResource(translator, di, resourceId) {
    validateResourceGet(resourceId);

    return translator.get(true)
        .then(response => {
            return findResource(response, di, resourceId);
        });
}

function postDeviceResource(di, resourceId, payload) {
    if (di === controlId)
    {
        var putPayload = resourceSchemaToProviderSchema(resourceId, payload);

        return nestHub.putDeviceDetailsAsync(deviceType, controlId, putPayload)
            .then((response) => {
                var schema = providerSchemaToPlatformSchema(response, true);
                return findResource(schema, di, resourceId);
            });
    } else {
        throw new Error('NotFound');
    }
}

var controlId;
var deviceType = 'thermostats';
var nestHub;

// This translator class implements the 'org.opent2t.sample.thermostat.superpopular' interface.
class Translator {

    constructor(deviceInfo) {
        console.log('Nest Thermostat initializing...');

        validateArgumentType(deviceInfo, "deviceInfo", "object");
        controlId = deviceInfo.deviceInfo.opent2t.controlId;
        nestHub = deviceInfo.hub;

        console.log('Nest Thermostat initializing...Done');
    }

    // Queries the entire state of the binary switch
    // and returns an object that maps to the json schema opent2t.p.thermostat
    get(expand, payload) {
        if (payload) {
            return providerSchemaToPlatformSchema(payload, expand);
        } else {
            return nestHub.getDeviceDetailsAsync(deviceType, controlId)
                .then((response) => {
                    return providerSchemaToPlatformSchema(response, expand);
                });
        }
    }

    getDevicesAmbientTemperature(di) {
        return getDeviceResource(this, di, 'ambientTemperature');
    }

    getDevicesTargetTemperature(di) {
        return getDeviceResource(this, di, 'targetTemperature');
    }

    postDevicesTargetTemperature(di, payload) {
        return postDeviceResource(di, 'targetTemperature', payload);
    }

    getDevicesHumidity(di) {
        return getDeviceResource(this, di, 'humidity');
    }

    getDevicesTargetTemperatureHigh(di) {
        return getDeviceResource(this, di, 'targetTemperatureHigh');
    }

    postDevicesTargetTemperatureHigh(di, payload) {
        return postDeviceResource(di, 'targetTemperatureHigh', payload);
    }

    getDevicesTargetTemperatureLow(di) {
        return getDeviceResource(this, di, 'targetTemperatureLow');
    }

    postDevicesTargetTemperatureLow(di, payload) {
        return postDeviceResource(di, 'targetTemperatureLow', payload);
    }

    getDevicesAwayMode(di) {
        return getDeviceResource(this, di, 'awayMode');
    }

    postDevicesAwayMode(di, payload) {
        return postDeviceResource(di, 'awayMode', payload);
    }

    getDevicesAwayTemperatureHigh(di) {
        return getDeviceResource(this, di, 'awayTemperatureHigh');
    }

    postDevicesAwayTemperatureHigh(di, payload) {
        return postDeviceResource(di, 'awayTemperatureHigh', payload);
    }

    getDevicesAwayTemperatureLow(di) {
        return getDeviceResource(this, di, 'awayTemperatureLow');
    }

    postDevicesAwayTemperatureLow(di, payload) {
        return postDeviceResource(di, 'awayTemperatureLow', payload);
    }

    getDevicesEcoMode(di) {
        return getDeviceResource(this, di, 'ecoMode');
    }

    getDevicesHvacMode(di) {
        return getDeviceResource(this, di, 'hvacMode');
    }

    postDevicesHvacMode(di, payload) {
        return postDeviceResource(di, 'hvacMode', payload);
    }

    getDevicesHeatingFuelSource(di) {
        return getDeviceResource(this, di, 'heatingFuelSource');
    }

    getDevicesHasFan(di) {
        return getDeviceResource(this, di, 'hasFan');
    }

    getDevicesFanActive(di) {
        return getDeviceResource(this, di, 'fanActive');
    }

    getDevicesFanTimerActive(di) {
        return getDeviceResource(this, di, 'fanTimerActive');
    }

    getDevicesFanTimerTimeout(di) {
        return getDeviceResource(this, di, 'fanTimerTimeout');
    }

    postDevicesFanTimerTimeout(di, payload) {
        return postDeviceResource(di, 'fanTimerTimeout', payload);
    }

    getDevicesFanMode(di) {
        return getDeviceResource(this, di, 'fanMode');
    }

    postDevicesFanMode(di, payload) {
        return postDeviceResource(di, 'fanMode', payload);
    }

    postSubscribe(subscriptionInfo) {
        subscriptionInfo.controlId = controlId;
        return nestHub.postSubscribe(subscriptionInfo);
    }

    deleteSubscribe(subscriptionInfo) {
        subscriptionInfo.controlId = controlId;
        return nestHub._unsubscribe(subscriptionInfo);
    }
}

// Export the translator from the module.
module.exports = Translator;
<|endoftext|>


<commit_before>import React, {useEffect, useState} from 'react'
import {Redirect} from 'react-router-dom'
import PropTypes from 'prop-types'

const ShowOutputJobsAction = props => {
  const [doRedirect, setDoRedirect] = useState(false)

  useEffect(() => {
    // If we redirect to the Output_job list right away, the UI gets stuck between
    // two views because of some race conditions. This `setTimeout` makes sure all
    // running sagas have completed when we redirect to avoid messing up the state.
    setTimeout(() => setDoRedirect(true), 0)
  }, [])

  return doRedirect
    ? <Redirect to={{
      pathname: '/e/Output_job/list',
      search: `tql=${encodeURIComponent(`entity=="${props.selection.entityName}"`)}`
    }}/>
    : null
}

ShowOutputJobsAction.propTypes = {
  selection: PropTypes.shape({
    entityName: PropTypes.string.isRequired
  }).isRequired
}

export default ShowOutputJobsAction
<commit_msg>fix(admin): remove unnecessary timeout in ShowOutputJobsAction<commit_after>import React from 'react'
import {Redirect} from 'react-router-dom'
import PropTypes from 'prop-types'

const ShowOutputJobsAction = props => <Redirect to={{
  pathname: '/e/Output_job/list',
  search: `tql=${encodeURIComponent(`entity=="${props.selection.entityName}"`)}`
}}/>

ShowOutputJobsAction.propTypes = {
  selection: PropTypes.shape({
    entityName: PropTypes.string.isRequired
  }).isRequired
}

export default ShowOutputJobsAction
<|endoftext|>


<commit_before>'use strict';

var MIN_HEIGHT = 200;
var IFRAME_NAME = "datacamp-light-iframe";
var DATACAMP_LIGHT_URL = "https://light.datacamp.com/";

/**
 * Inspired by https://github.com/sindresorhus/strip-indent
 */
function stripIndent(code_block) {
	var match = code_block.match(/^[ \t]*(?=\S)/gm);

	if (!match) {
		return code_block;
	}

	var indent = Math.min.apply(Math, match.map(function (el) {
		return el.length;
	}));

	var re = new RegExp('^[ \\t]{' + indent + '}', 'gm');

	code_block = indent > 0 ? code_block.replace(re, '') : code_block;
	var lines = code_block.split(/\r?\n/);
	if (lines[lines.length-1].trim() === "") {
		lines.splice(lines.length-1, 1);
	}
	if (lines[0].trim() === "") {
		lines.splice(0, 1);
	}
	return lines.join("\n");
}

function unescapeHtml(safe) {
	return safe.replace(/&/g, '&')
		.replace(/</g, '<')
		.replace(/>/g, '>')
		.replace(/"/g, '"')
		.replace(/'/g, "'");
}

function processCodeTags(result_object, code_tags) {
	for (var i = 0; i < code_tags.length; i++) {
		if ("type" in code_tags[i].dataset) {
			var text = unescapeHtml(code_tags[i].innerHTML);
			var type = code_tags[i].dataset["type"];
			if (type === "pre-exercise-code") {
				result_object["pre-exercise-code"] = text;
			}
			else if (type === "sample-code") {
				result_object["sample-code"] = text;
			}
			else if (type === "solution") {
				result_object["solution"] = text;
			}
			else if (type === "sct") {
				result_object["sct"] = text;
			}
		}
	}
}

function processParagraphTags(result_object, paragraphs) {
	for (var i = 0; i < paragraphs.length; i++) {
		if ("type" in paragraphs[i].dataset) {
			var type = paragraphs[i].dataset["type"];
			if (type === "hint") {
				result_object["hint"] = paragraphs[i].innerHTML;
			}
		}
	}
}

function createURLData(data) {
	var result = [];
	for (var entry in data) {
		if (data.hasOwnProperty(entry))
			result.push(encodeURIComponent(entry) + "=" + encodeURIComponent(data[entry]));
	}
	return result.join("&");
}

function createIFrame(exercise_DOM, exercise_data) {
	var iframe = document.createElement("iframe");
	iframe.setAttribute("name", IFRAME_NAME);
	var style_attribute = "border: 1px solid #d5eaef;";

	// Calculate height of iframe
	var doHeightCalculation = true;
	var height;
	if ("height" in exercise_DOM.dataset) {
		var user_height = Math.round(exercise_DOM.dataset["height"]);
		if (!isNaN(user_height)) {
			if (user_height > MIN_HEIGHT) {
				height = user_height;
				doHeightCalculation = false;
			} else {
				console.log("The height attribute should be larger than " + MIN_HEIGHT + ".");
			}
		} else {
			console.log("Invalid height attribute.");
		}
	}

	if (doHeightCalculation) {
		// Get min-height
		var min_height = MIN_HEIGHT;
		if ("minHeight" in exercise_DOM.dataset) {
			var user_min_height = Math.round(exercise_DOM.dataset["minHeight"]);
			if (!isNaN(user_min_height)) {
				if (user_min_height > MIN_HEIGHT) {
					min_height = user_min_height;
				} else {
					console.log("The min-height attribute should be larger than " + MIN_HEIGHT + ".");
				}
			} else {
				console.log("Invalid min-height attribute.");
			}
		}

		// Get height based on sample-code
		var sample_lines_length = exercise_data["sample-code"].split(/\r?\n/).length;
		height = Math.max(
			47 + (sample_lines_length-2) * 18,
			min_height
		);

		if ("maxHeight" in exercise_DOM.dataset) {
			var user_max_height = Math.round(exercise_DOM.dataset["maxHeight"]);
			if (!isNaN(user_max_height)) {
				if (user_max_height > MIN_HEIGHT) {
					height = Math.min(height, user_max_height);
				} else {
					console.log("The max-height attribute should be larger than " + MIN_HEIGHT + ".");
				}
			} else {
				console.log("Invalid max-height attribute.");
			}
		}
	}

	iframe.style.height = height + "px";
	style_attribute += "height:" + height + "px;"

	// Set width and min-width
	iframe.style.width = "100%";
	iframe.style.minWidth = "600px";
	style_attribute += "width:100%;min-width:600px;"

	// Set style attribute of iframe
	iframe.setAttribute("style", style_attribute);
	return iframe;
}

function createDataForm(exercise_data) {
	var url = DATACAMP_LIGHT_URL + (window.location.hostname ? window.location.hostname + "/?" : "?") +
	createURLData({

	});
    var form = document.createElement("form");
    form.setAttribute("method", "post");
    form.setAttribute("action", DATACAMP_LIGHT_URL);
    form.setAttribute("target", IFRAME_NAME);

    for(var key in exercise_data) {
        if(exercise_data.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", stripIndent(exercise_data[key]));

            form.appendChild(hiddenField);
         }
    }

    return form;
}

function replaceDataCampExercises() {
	var exercises = document.querySelectorAll("[data-datacamp-exercise]");
	for (var i = 0; i < exercises.length; i++) {
		var exercise_DOM = exercises[i];

		if (!("lang" in exercise_DOM.dataset)) {
			console.log("DataCamp-Light: Missing the data-lang attribute.");
			return;
		}

		var exercise_data = {
			"language": exercise_DOM.dataset["lang"],
			"pre-exercise-code": "",
			"sample-code": "",
			"solution": "",
			"sct": "",
			"hint": "",
		}

		processParagraphTags(exercise_data, exercise_DOM.getElementsByTagName('p'));
		processCodeTags(exercise_data, exercise_DOM.getElementsByTagName('code'));

		// Actually replace
		while (exercise_DOM.lastChild) {
		    exercise_DOM.removeChild(exercise_DOM.lastChild);
		}

		// Append iframe
		exercise_DOM.appendChild(createIFrame(exercise_DOM, exercise_data));

		// Create form to send exercise data
		var form = createDataForm(exercise_data);
		exercise_DOM.appendChild(form);
		form.submit();

		// Remove the form again so no data is visible to the user in the HTML
		exercise_DOM.removeChild(form);
	}
}

document.addEventListener('DOMContentLoaded', replaceDataCampExercises, false);
<commit_msg>use different names for the iframes, so that multiple ones work on one web page<commit_after>'use strict';

var MIN_HEIGHT = 200;
var IFRAME_NAME = "datacamp-light-iframe-";
var DATACAMP_LIGHT_URL = "https://light.datacamp.com/";

/**
 * Inspired by https://github.com/sindresorhus/strip-indent
 */
function stripIndent(code_block) {
	var match = code_block.match(/^[ \t]*(?=\S)/gm);

	if (!match) {
		return code_block;
	}

	var indent = Math.min.apply(Math, match.map(function (el) {
		return el.length;
	}));

	var re = new RegExp('^[ \\t]{' + indent + '}', 'gm');

	code_block = indent > 0 ? code_block.replace(re, '') : code_block;
	var lines = code_block.split(/\r?\n/);
	if (lines[lines.length-1].trim() === "") {
		lines.splice(lines.length-1, 1);
	}
	if (lines[0].trim() === "") {
		lines.splice(0, 1);
	}
	return lines.join("\n");
}

function unescapeHtml(safe) {
	return safe.replace(/&/g, '&')
		.replace(/</g, '<')
		.replace(/>/g, '>')
		.replace(/"/g, '"')
		.replace(/'/g, "'");
}

function processCodeTags(result_object, code_tags) {
	for (var i = 0; i < code_tags.length; i++) {
		if ("type" in code_tags[i].dataset) {
			var text = unescapeHtml(code_tags[i].innerHTML);
			var type = code_tags[i].dataset["type"];
			if (type === "pre-exercise-code") {
				result_object["pre-exercise-code"] = text;
			}
			else if (type === "sample-code") {
				result_object["sample-code"] = text;
			}
			else if (type === "solution") {
				result_object["solution"] = text;
			}
			else if (type === "sct") {
				result_object["sct"] = text;
			}
		}
	}
}

function processParagraphTags(result_object, paragraphs) {
	for (var i = 0; i < paragraphs.length; i++) {
		if ("type" in paragraphs[i].dataset) {
			var type = paragraphs[i].dataset["type"];
			if (type === "hint") {
				result_object["hint"] = paragraphs[i].innerHTML;
			}
		}
	}
}

function createURLData(data) {
	var result = [];
	for (var entry in data) {
		if (data.hasOwnProperty(entry))
			result.push(encodeURIComponent(entry) + "=" + encodeURIComponent(data[entry]));
	}
	return result.join("&");
}

function createIFrame(exercise_DOM, exercise_data, index) {
	var iframe = document.createElement("iframe");
	iframe.name = IFRAME_NAME + index;
	var style_attribute = "border: 1px solid #d5eaef;";

	// Calculate height of iframe
	var doHeightCalculation = true;
	var height;
	if ("height" in exercise_DOM.dataset) {
		var user_height = Math.round(exercise_DOM.dataset["height"]);
		if (!isNaN(user_height)) {
			if (user_height > MIN_HEIGHT) {
				height = user_height;
				doHeightCalculation = false;
			} else {
				console.log("The height attribute should be larger than " + MIN_HEIGHT + ".");
			}
		} else {
			console.log("Invalid height attribute.");
		}
	}

	if (doHeightCalculation) {
		// Get min-height
		var min_height = MIN_HEIGHT;
		if ("minHeight" in exercise_DOM.dataset) {
			var user_min_height = Math.round(exercise_DOM.dataset["minHeight"]);
			if (!isNaN(user_min_height)) {
				if (user_min_height > MIN_HEIGHT) {
					min_height = user_min_height;
				} else {
					console.log("The min-height attribute should be larger than " + MIN_HEIGHT + ".");
				}
			} else {
				console.log("Invalid min-height attribute.");
			}
		}

		// Get height based on sample-code
		var sample_lines_length = exercise_data["sample-code"].split(/\r?\n/).length;
		height = Math.max(
			47 + (sample_lines_length-2) * 18,
			min_height
		);

		if ("maxHeight" in exercise_DOM.dataset) {
			var user_max_height = Math.round(exercise_DOM.dataset["maxHeight"]);
			if (!isNaN(user_max_height)) {
				if (user_max_height > MIN_HEIGHT) {
					height = Math.min(height, user_max_height);
				} else {
					console.log("The max-height attribute should be larger than " + MIN_HEIGHT + ".");
				}
			} else {
				console.log("Invalid max-height attribute.");
			}
		}
	}

	iframe.style.height = height + "px";
	style_attribute += "height:" + height + "px;"

	// Set width and min-width
	iframe.style.width = "100%";
	iframe.style.minWidth = "600px";
	style_attribute += "width:100%;min-width:600px;"

	// Set style attribute of iframe
	iframe.setAttribute("style", style_attribute);
	return iframe;
}

function createDataForm(exercise_data , index) {
	var url = DATACAMP_LIGHT_URL + (window.location.hostname ? window.location.hostname + "/?" : "?") +
	createURLData({

	});
    var form = document.createElement("form");
    form.setAttribute("method", "post");
    form.setAttribute("action", DATACAMP_LIGHT_URL);
    form.setAttribute("target", IFRAME_NAME + index);

    for(var key in exercise_data) {
        if(exercise_data.hasOwnProperty(key)) {
            var hiddenField = document.createElement("input");
            hiddenField.setAttribute("type", "hidden");
            hiddenField.setAttribute("name", key);
            hiddenField.setAttribute("value", stripIndent(exercise_data[key]));

            form.appendChild(hiddenField);
         }
    }

    return form;
}

function replaceDataCampExercises() {
	var exercises = document.querySelectorAll("[data-datacamp-exercise]");
	for (var i = 0; i < exercises.length; i++) {
		var exercise_DOM = exercises[i];

		if (!("lang" in exercise_DOM.dataset)) {
			console.log("DataCamp-Light: Missing the data-lang attribute.");
			return;
		}

		var exercise_data = {
			"language": exercise_DOM.dataset["lang"],
			"pre-exercise-code": "",
			"sample-code": "",
			"solution": "",
			"sct": "",
			"hint": "",
		}

		processParagraphTags(exercise_data, exercise_DOM.getElementsByTagName('p'));
		processCodeTags(exercise_data, exercise_DOM.getElementsByTagName('code'));

		// Actually replace
		while (exercise_DOM.lastChild) {
		    exercise_DOM.removeChild(exercise_DOM.lastChild);
		}

		// Create iframe
		exercise_DOM.appendChild(createIFrame(exercise_DOM, exercise_data , i));

		// Create form to send exercise data
		var form = createDataForm(exercise_data, i);
		exercise_DOM.appendChild(form);
		form.submit();

		// Remove the form again so no data is visible to the user in the HTML
		exercise_DOM.removeChild(form);
	}
}

document.addEventListener('DOMContentLoaded', replaceDataCampExercises, false);
<|endoftext|>


<commit_before>export { default as ActivityIcon } from 'react-feather/dist/icons/activity'
export { default as GitlabIcon } from 'react-feather/dist/icons/gitlab'
export { default as BarChartIcon } from 'react-feather/dist/icons/bar-chart'
export { default as UsersIcon } from 'react-feather/dist/icons/users'
export { default as GitBranchIcon } from 'react-feather/dist/icons/git-branch'
export { default as ClockIcon } from 'react-feather/dist/icons/clock'
export { default as LockIcon } from 'react-feather/dist/icons/lock'
export { default as UnlockIcon } from 'react-feather/dist/icons/unlock'
export { default as StarIcon } from 'react-feather/dist/icons/star'
export { default as TagIcon } from 'react-feather/dist/icons/tag'
export { default as GridIcon } from 'react-feather/dist/icons/grid'
export { default as InfoIcon } from 'react-feather/dist/icons/info'
export { default as PackageIcon } from 'react-feather/dist/icons/package'
export { default as HelpIcon } from 'react-feather/dist/icons/help-circle'
export { default as CheckCircleIcon } from 'react-feather/dist/icons/check-circle'
export { default as AlertTriangleIcon } from 'react-feather/dist/icons/alert-triangle'
export { default as AlertCircleIcon } from 'react-feather/dist/icons/alert-circle'
export { default as SlidersIcon } from 'react-feather/dist/icons/sliders'
export { default as FolderIcon } from 'react-feather/dist/icons/folder'
export { default as LoaderIcon } from 'react-feather/dist/icons/loader'
export { default as CalendarIcon } from 'react-feather/dist/icons/calendar'
export { default as GitCommitIcon } from 'react-feather/dist/icons/git-commit'
export { default as PauseCircleIcon } from 'react-feather/dist/icons/pause-circle'
export { default as FastForwardIcon } from 'react-feather/dist/icons/fast-forward'
export { default as GithubIcon } from 'react-feather/dist/icons/github'
export { default as SlashIcon } from 'react-feather/dist/icons/slash'
<commit_msg>feat(ui): add new icons<commit_after>export { default as ActivityIcon } from 'react-feather/dist/icons/activity'
export { default as GitlabIcon } from 'react-feather/dist/icons/gitlab'
export { default as BarChartIcon } from 'react-feather/dist/icons/bar-chart'
export { default as UsersIcon } from 'react-feather/dist/icons/users'
export { default as GitBranchIcon } from 'react-feather/dist/icons/git-branch'
export { default as ClockIcon } from 'react-feather/dist/icons/clock'
export { default as LockIcon } from 'react-feather/dist/icons/lock'
export { default as UnlockIcon } from 'react-feather/dist/icons/unlock'
export { default as StarIcon } from 'react-feather/dist/icons/star'
export { default as TagIcon } from 'react-feather/dist/icons/tag'
export { default as GridIcon } from 'react-feather/dist/icons/grid'
export { default as InfoIcon } from 'react-feather/dist/icons/info'
export { default as PackageIcon } from 'react-feather/dist/icons/package'
export { default as HelpIcon } from 'react-feather/dist/icons/help-circle'
export { default as CheckCircleIcon } from 'react-feather/dist/icons/check-circle'
export { default as AlertTriangleIcon } from 'react-feather/dist/icons/alert-triangle'
export { default as AlertCircleIcon } from 'react-feather/dist/icons/alert-circle'
export { default as SlidersIcon } from 'react-feather/dist/icons/sliders'
export { default as FolderIcon } from 'react-feather/dist/icons/folder'
export { default as LoaderIcon } from 'react-feather/dist/icons/loader'
export { default as CalendarIcon } from 'react-feather/dist/icons/calendar'
export { default as GitCommitIcon } from 'react-feather/dist/icons/git-commit'
export { default as PauseCircleIcon } from 'react-feather/dist/icons/pause-circle'
export { default as FastForwardIcon } from 'react-feather/dist/icons/fast-forward'
export { default as GithubIcon } from 'react-feather/dist/icons/github'
export { default as SlashIcon } from 'react-feather/dist/icons/slash'
export { default as PlayCircleIcon } from 'react-feather/dist/icons/play-circle'
<|endoftext|>