<commit_before>/* eslint no-underscore-dangle: 0 */
import { AppState, NetInfo } from 'react-native'; // eslint-disable-line import/no-unresolved

class DetectNetwork {
  constructor(callback) {
    this._reach = null;
    this._isConnected = null;
    this._isConnectionExpensive = null;
    this._callback = callback;

    this._init();
    this._addListeners();
  }

  /**
   * Sets the connection reachability prop
   * @param reach - connection reachability.
   *     - iOS: [none, wifi, cell, unknown]
   *     - Android: [NONE, BLUETOOTH, DUMMY, ETHERNET, MOBILE, MOBILE_DUN, MOBILE_HIPRI, MOBILE_MMS, MOBILE_SUPL, VPN, WIFI, WIMAX, UNKNOWN]
   * @private
   */
  _setReach = (reach) => {
    this._reach = reach;
    this._setIsConnected(reach.toUpperCase());
  }
  /**
   * Sets the isConnected prop depending on the connection reachability's value
   * @param reach
   * @private
   */
  _setIsConnected = (reach) => {
    this._isConnected = (reach !== 'NONE' && reach !== 'UNKNOWN');
  }
  /**
   * Sets the isConnectionExpensive prop
   * @returns {Promise.<void>}
   * @private
   */
  _setIsConnectionExpensive = async () => {
    try {
      this._isConnectionExpensive = await NetInfo.isConnectionExpensive();
    } catch (err) {
      // err means that isConnectionExpensive is not supported
      this._isConnectionExpensive = null;
    }
  }
  /**
   * Fetches and sets the connection reachability and the isConnected props
   * @returns {Promise.<void>}
   * @private
   */
  _init = async () => {
    this._setReach(await NetInfo.fetch());
    this._updateState();
  }

  /**
   * Adds listeners for when connection reachability and app state changes to update props
   * @private
   */
  _addListeners() {
    NetInfo.addEventListener('change', (reach) => {
      this._setReach(reach);
      this._updateState();
    });
    AppState.addEventListener('change', this._init);
  }

  /**
   * Executes the given callback to update redux's store with the new internal props
   * @returns {Promise.<void>}
   * @private
   */
  _updateState = async () => {
    await this._setIsConnectionExpensive();
    this._callback({
      online: this._isConnected,
      netInfo: {
        isConnectionExpensive: this._isConnectionExpensive,
        reach: this._reach
      }
    });
  }
}

export default callback => new DetectNetwork(callback);
<commit_msg>fix: always save in uppercase for consistency<commit_after>/* eslint no-underscore-dangle: 0 */
import { AppState, NetInfo } from 'react-native'; // eslint-disable-line import/no-unresolved

class DetectNetwork {
  constructor(callback) {
    this._reach = null;
    this._isConnected = null;
    this._isConnectionExpensive = null;
    this._callback = callback;

    this._init();
    this._addListeners();
  }

  /**
   * Sets the connection reachability prop
   * @param reach - connection reachability.
   *     - iOS: [none, wifi, cell, unknown]
   *     - Android: [NONE, BLUETOOTH, DUMMY, ETHERNET, MOBILE, MOBILE_DUN, MOBILE_HIPRI, MOBILE_MMS, MOBILE_SUPL, VPN, WIFI, WIMAX, UNKNOWN]
   * @private
   */
  _setReach = (reach) => {
    this._reach = reach.toUpperCase();
    this._setIsConnected(reach.toUpperCase());
  }
  /**
   * Sets the isConnected prop depending on the connection reachability's value
   * @param reach
   * @private
   */
  _setIsConnected = (reach) => {
    this._isConnected = (reach !== 'NONE' && reach !== 'UNKNOWN');
  }
  /**
   * Sets the isConnectionExpensive prop
   * @returns {Promise.<void>}
   * @private
   */
  _setIsConnectionExpensive = async () => {
    try {
      this._isConnectionExpensive = await NetInfo.isConnectionExpensive();
    } catch (err) {
      // err means that isConnectionExpensive is not supported
      this._isConnectionExpensive = null;
    }
  }
  /**
   * Fetches and sets the connection reachability and the isConnected props
   * @returns {Promise.<void>}
   * @private
   */
  _init = async () => {
    this._setReach(await NetInfo.fetch());
    this._updateState();
  }

  /**
   * Adds listeners for when connection reachability and app state changes to update props
   * @private
   */
  _addListeners() {
    NetInfo.addEventListener('change', (reach) => {
      this._setReach(reach);
      this._updateState();
    });
    AppState.addEventListener('change', this._init);
  }

  /**
   * Executes the given callback to update redux's store with the new internal props
   * @returns {Promise.<void>}
   * @private
   */
  _updateState = async () => {
    await this._setIsConnectionExpensive();
    this._callback({
      online: this._isConnected,
      netInfo: {
        isConnectionExpensive: this._isConnectionExpensive,
        reach: this._reach
      }
    });
  }
}

export default callback => new DetectNetwork(callback);
<|endoftext|>


<commit_before>function showDiv(divName) {
  $('.all').hide();
  $(divName).show();
}

// When the user clicks the button
$('.btn-username').click(processForm, function(){
	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},3000);

});

// When the user clicks the button
$('.btn-prep').click(function(){
	showDiv(".instruction");
	setTimeout(function() {$('.btn-instruction').show();},3000);
})

// Get the form, listen to its submit event

$('.form-set-username').on('submit', processForm);

$('.btn-instruction').click(finishedOnboarding);

// function to run when the form is submitted
function processForm() {

	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},3000);
 // get the entered user name from the input
	var username = $('input').val();
 	localStorage.setItem('username', username);
		database.ref('users/'+ username).set({
    	username: username
    });
 	return false;
};

showDiv(".username")
startCurrentView();

<commit_msg>Update onboarding.js<commit_after>function showDiv(divName) {
  $('.all').hide();
  $(divName).show();
}

// When the user clicks the button
$('.btn-username').click(processForm, function(){
	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},3000);

});

// When the user clicks the button
$('.btn-prep').click(function(){
	showDiv(".instruction");
	setTimeout(function() {$('.btn-instruction').show();},3000);
})

// Get the form, listen to its submit event

$('.form-set-username').on('submit', processForm);

$('.btn-instruction').click(finishedOnboarding);

// function to run when the form is submitted
function processForm() {

	showDiv(".prep");
	$('.btn-all').hide();
	setTimeout(function() {$('.btn-prep').show();},3000);
 // get the entered user name from the input
	var username = $('input').val();
	if (username == null || username == ""){
 -		username = "anonymous";
 -	}
 	localStorage.setItem('username', username);
		database.ref('users/'+ username).set({
    	username: username
    });
 	return false;
};

showDiv(".username")
startCurrentView();

<|endoftext|>


<commit_before>/**
 * @file MaterialDropdownFilter component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, createRef} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import DropdownFilter from '../DropdownFilter';
import MaterialProvider from '../MaterialProvider';
import Theme from '../Theme';

import SelectMode from '../_statics/SelectMode';
import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import ComponentUtil from '../_vendors/ComponentUtil';

class MaterialDropdownFilter extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.dropdownFilter = createRef();
        this.dropdownFilterInstance = null;

        this.state = {
            value: props.value,
            filter: ''
        };

    }

    handleTriggerFilterChange = filter => {
        this.setState({
            filter
        }, () => {
            const {onFilterChange} = this.props;
            onFilterChange && onFilterChange(filter);
        });
    };

    handleTriggerChange = value => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });
    };

    closePopup = () => {
        this.dropdownFilterInstance && this.dropdownFilterInstance.closePopup();
    };

    componentDidMount() {
        this.dropdownFilterInstance = this.dropdownFilter && this.dropdownFilter.current;
    }

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            value: ComponentUtil.getDerivedState(props, state, 'value')
        };
    }

    render() {

        const {
                className, style, theme, label, isLabelAnimate, popupClassName, required,
                ...restProps
            } = this.props,
            {value, filter} = this.state,

            wrapperClassName = classNames('material-dropdown-filter', {
                [className]: className
            }),

            filterClassName = classNames('material-dropdown-filter-popup', {
                [popupClassName]: popupClassName
            });

        return (
            <MaterialProvider className={wrapperClassName}
                              style={style}
                              theme={theme}
                              label={label}
                              isLabelAnimate={isLabelAnimate}
                              hasValue={!!filter}
                              required={required}>
                <DropdownFilter {...restProps}
                                ref={this.dropdownFilter}
                                popupClassName={filterClassName}
                                theme={theme}
                                value={value}
                                onFilterChange={this.handleTriggerFilterChange}
                                onChange={this.handleTriggerChange}/>
            </MaterialProvider>
        );

    }
}

MaterialDropdownFilter.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The name of the auto complete.
     */
    name: PropTypes.string,

    /**
     * The placeholder of the field.
     */
    placeholder: PropTypes.string,

    label: PropTypes.any,

    /**
     * Children passed into the List.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            itemRenderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onClick: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    value: PropTypes.any,

    /**
     * If true, the auto complete will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the popup list automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    /**
     * The type of dropDown list,can be normal,checkbox,radio.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * Callback function fired when filter changed.
     */
    filterCallback: PropTypes.func,

    /**
     * Use this property to display an icon.
     */
    iconCls: PropTypes.string,

    /**
     * Use this property to display an icon.
     */
    rightIconCls: PropTypes.string,

    /**
     * The visiblity of no matched popup.
     */
    noMatchedPopupVisible: PropTypes.bool,

    /**
     * The message of no matched value.
     */
    noMatchedMsg: PropTypes.string,

    /**
     * If true,the list data will be grouped.
     */
    isGrouped: PropTypes.bool,

    isLabelAnimate: PropTypes.bool,
    required: PropTypes.bool,
    popupChildren: PropTypes.any,
    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * The function that trigger when filter changes.
     */
    onFilterChange: PropTypes.func,

    /**
     * The function that trigger when press enter.
     */
    onFilterPressEnter: PropTypes.func,

    /**
     * The function that trigger when filter cleared.
     */
    onFilterClear: PropTypes.func,

    /**
     * The function that trigger when value changed.
     */
    onChange: PropTypes.func,

    /**
     * The function that trigger when touch-tap the list items.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when DropdownFilter get focus.
     */
    onFocus: PropTypes.func,

    /**
     * Callback function fired when DropdownFilter lose focus.
     */
    onBlur: PropTypes.func,

    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func

};

MaterialDropdownFilter.defaultProps = {

    theme: Theme.DEFAULT,

    name: '',
    placeholder: '',
    label: '',
    isLabelAnimate: true,
    data: [],
    disabled: false,
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    autoClose: false,
    iconCls: '',
    rightIconCls: 'fas fa-search',
    noMatchedPopupVisible: true,
    noMatchedMsg: '',
    isGrouped: false,
    selectMode: SelectMode.SINGLE_SELECT,

    radioUncheckedIconCls: 'fas fa-check',
    radioCheckedIconCls: 'fas fa-check',
    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square'

};

export default MaterialDropdownFilter;
<commit_msg>update MaterialDropdownFilter<commit_after>/**
 * @file MaterialDropdownFilter component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component, createRef} from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

import DropdownFilter from '../DropdownFilter';
import MaterialProvider from '../MaterialProvider';
import Theme from '../Theme';

import SelectMode from '../_statics/SelectMode';
import Position from '../_statics/Position';

import Util from '../_vendors/Util';
import ComponentUtil from '../_vendors/ComponentUtil';

class MaterialDropdownFilter extends Component {

    static SelectMode = SelectMode;
    static Theme = Theme;
    static Position = Position;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.dropdownFilter = createRef();
        this.dropdownFilterInstance = null;

        this.state = {
            value: props.value,
            filter: ''
        };

    }

    handleTriggerFilterChange = filter => {
        this.setState({
            filter
        }, () => {
            const {onFilterChange} = this.props;
            onFilterChange && onFilterChange(filter);
        });
    };

    handleTriggerChange = value => {
        this.setState({
            value
        }, () => {
            const {onChange} = this.props;
            onChange && onChange(value);
        });
    };

    closePopup = () => {
        this.dropdownFilterInstance && this.dropdownFilterInstance.closePopup();
    };

    componentDidMount() {
        this.dropdownFilterInstance = this.dropdownFilter && this.dropdownFilter.current;
    }

    static getDerivedStateFromProps(props, state) {
        return {
            prevProps: props,
            value: ComponentUtil.getDerivedState(props, state, 'value')
        };
    }

    render() {

        const {
                className, style, theme, label, isLabelAnimate, popupClassName, required,
                ...restProps
            } = this.props,
            {value, filter} = this.state;

        return (
            <MaterialProvider className={classNames('material-dropdown-filter', {
                [className]: className
            })}
                              style={style}
                              theme={theme}
                              label={label}
                              isLabelAnimate={isLabelAnimate}
                              hasValue={!!filter}
                              required={required}>
                <DropdownFilter {...restProps}
                                ref={this.dropdownFilter}
                                popupClassName={classNames('material-dropdown-filter-popup', {
                                    [popupClassName]: popupClassName
                                })}
                                theme={theme}
                                value={value}
                                onFilterChange={this.handleTriggerFilterChange}
                                onChange={this.handleTriggerChange}/>
            </MaterialProvider>
        );

    }
}

MaterialDropdownFilter.propTypes = {

    /**
     * The CSS class name of the root element.
     */
    className: PropTypes.string,

    /**
     * The CSS class name of the popup element.
     */
    popupClassName: PropTypes.string,

    /**
     * Override the styles of the root element.
     */
    style: PropTypes.object,

    /**
     * Override the styles of the popup element.
     */
    popupStyle: PropTypes.object,

    /**
     * The theme.
     */
    theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

    position: PropTypes.oneOf(Util.enumerateValue(Position)),

    /**
     * The name of the auto complete.
     */
    name: PropTypes.string,

    /**
     * The placeholder of the field.
     */
    placeholder: PropTypes.string,

    label: PropTypes.any,

    /**
     * Children passed into the List.
     */
    data: PropTypes.oneOfType([

        // not grouped
        PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.shape({

            /**
             * The CSS class name of the list button.
             */
            className: PropTypes.string,

            /**
             * Override the styles of the list button.
             */
            style: PropTypes.object,

            /**
             * The theme of the list button.
             */
            theme: PropTypes.oneOf(Util.enumerateValue(Theme)),

            /**
             * The text value of the list button.Type can be string or number.
             */
            value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * The desc value of the list button. Type can be string or number.
             */
            desc: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

            /**
             * If true, the list button will be disabled.
             */
            disabled: PropTypes.bool,

            /**
             * If true,the button will be have loading effect.
             */
            isLoading: PropTypes.bool,

            /**
             * If true,the element's ripple effect will be disabled.
             */
            disableTouchRipple: PropTypes.bool,

            /**
             * Use this property to display an icon. It will display on the left.
             */
            iconCls: PropTypes.string,

            /**
             * Use this property to display an icon. It will display on the right.
             */
            rightIconCls: PropTypes.string,

            /**
             * You can create a complicated renderer callback instead of value and desc prop.
             */
            itemRenderer: PropTypes.func,

            /**
             * Callback function fired when a list item touch-tapped.
             */
            onClick: PropTypes.func

        }), PropTypes.string, PropTypes.number])),

        // grouped
        PropTypes.array

    ]).isRequired,

    value: PropTypes.any,

    /**
     * If true, the auto complete will be disabled.
     */
    disabled: PropTypes.bool,

    /**
     * The value field name in data. (default: "value")
     */
    valueField: PropTypes.string,

    /**
     * The display field name in data. (default: "text")
     */
    displayField: PropTypes.string,

    /**
     * The description field name in data. (default: "desc")
     */
    descriptionField: PropTypes.string,

    /**
     * If true, the popup list automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    /**
     * The type of dropDown list,can be normal,checkbox,radio.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

    /**
     * Callback function fired when filter changed.
     */
    filterCallback: PropTypes.func,

    /**
     * Use this property to display an icon.
     */
    iconCls: PropTypes.string,

    /**
     * Use this property to display an icon.
     */
    rightIconCls: PropTypes.string,

    /**
     * The visiblity of no matched popup.
     */
    noMatchedPopupVisible: PropTypes.bool,

    /**
     * The message of no matched value.
     */
    noMatchedMsg: PropTypes.string,

    /**
     * If true,the list data will be grouped.
     */
    isGrouped: PropTypes.bool,

    isLabelAnimate: PropTypes.bool,
    required: PropTypes.bool,
    popupChildren: PropTypes.any,
    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    /**
     * You can create a complicated renderer callback instead of value and desc prop.
     */
    renderer: PropTypes.func,

    /**
     * The function that trigger when filter changes.
     */
    onFilterChange: PropTypes.func,

    /**
     * The function that trigger when press enter.
     */
    onFilterPressEnter: PropTypes.func,

    /**
     * The function that trigger when filter cleared.
     */
    onFilterClear: PropTypes.func,

    /**
     * The function that trigger when value changed.
     */
    onChange: PropTypes.func,

    /**
     * The function that trigger when touch-tap the list items.
     */
    onItemClick: PropTypes.func,

    /**
     * Callback function fired when DropdownFilter get focus.
     */
    onFocus: PropTypes.func,

    /**
     * Callback function fired when DropdownFilter lose focus.
     */
    onBlur: PropTypes.func,

    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func

};

MaterialDropdownFilter.defaultProps = {

    theme: Theme.DEFAULT,

    name: '',
    placeholder: '',
    label: '',
    isLabelAnimate: true,
    data: [],
    disabled: false,
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    autoClose: false,
    iconCls: '',
    rightIconCls: 'fas fa-search',
    noMatchedPopupVisible: true,
    noMatchedMsg: '',
    isGrouped: false,
    selectMode: SelectMode.SINGLE_SELECT,

    radioUncheckedIconCls: 'fas fa-check',
    radioCheckedIconCls: 'fas fa-check',
    checkboxUncheckedIconCls: 'far fa-square',
    checkboxCheckedIconCls: 'fas fa-check-square',
    checkboxIndeterminateIconCls: 'fas fa-minus-square'

};

export default MaterialDropdownFilter;
<|endoftext|>


<commit_before>/*
 * This file is part of the ONGR package.
 *
 * (c) NFQ Technologies UAB <info@nfq.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

(function ($) {

})(jQuery);
<commit_msg>topbar & footer js<commit_after>/*
 * This file is part of the ONGR package.
 *
 * (c) NFQ Technologies UAB <info@nfq.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

(function ($) {
    var topbarDropdown = '.topbar-dropdown-content';

    $('.topbar-dropdown')
        .mouseenter(function() {
            $(this).addClass('opened');
            $(this).find(topbarDropdown).slideDown('fast');
        })
        .mouseleave(function() {
            $(this).removeClass('opened');
            $(this).find(topbarDropdown).slideUp('fast');
        });

    $('.js-footer-dropdown-trigger').click(function() {
        var trigger = $(this);

        if ($(this).hasClass('opened')) {
            $(this).next().slideUp('fast', function() {
                trigger.removeClass('opened');
            });
        } else {
            trigger.addClass('opened');
            $(this).next().slideDown('fast');
        }
    });
})(jQuery);
<|endoftext|>


<commit_before>import ITEMS from 'common/ITEMS';
import SPELLS from 'common/SPELLS';
import Module from 'Parser/Core/Module';
import Combatants from 'Parser/Core/Modules/Combatants';
import getDamageBonus from '../MageCore/GetDamageBonus';

const DAMAGE_BONUS = .35;

class ZannesuJourney extends Module {

  static dependencies = {
		combatants: Combatants,
	};

  damage = 0;
  stackCount = 0;
  previousStackCount = 0;

  on_initialized() {
    this.active = this.combatants.selected.hasWaist(ITEMS.ZANNESU_JOURNEY.id);
  }

  on_byPlayer_cast(event) {
    if (event.ability.guid !== SPELLS.BLIZZARD.id) {
      return;
    }
    this.previousStackCount = this.stackCount;
  }

  on_byPlayer_damage(event) {
    if (event.ability.guid !== SPELLS.BLIZZARD_DAMAGE.id) {
      return;
    }
      this.damage += getDamageBonus(event, DAMAGE_BONUS * this.previousStackCount);
      console.log('Blizzard Cast');
      console.log(this.previousStackCount);
      console.log(this.damage);
  }

  on_toPlayer_applybuff(event) {
    if (event.ability.guid !== SPELLS.ZANNESU_JOURNEY_BUFF.id) {
      return;
    }
    this.stackCount += 1;
  }

  on_toPlayer_applybuffstack(event) {
    if (event.ability.guid !== SPELLS.ZANNESU_JOURNEY_BUFF.id || this.stackCount === 5) {
      return;
    }
    this.stackCount += 1;
  }

  on_toPlayer_removebuff(event) {
    if (event.ability.guid !== SPELLS.ZANNESU_JOURNEY_BUFF.id) {
      return;
    }
    this.stackCount = 0;
  }

  item() {
    return {
      item: ITEMS.ZANNESU_JOURNEY,
      result: `${this.owner.formatItemDamageDone(this.damage)}`,
    };
  }
}

export default ZannesuJourney;
<commit_msg>Fix for Zannesu Journey<commit_after>import ITEMS from 'common/ITEMS';
import SPELLS from 'common/SPELLS';
import Module from 'Parser/Core/Module';
import Combatants from 'Parser/Core/Modules/Combatants';
import getDamageBonus from '../MageCore/GetDamageBonus';

const DAMAGE_BONUS = .35;

class ZannesuJourney extends Module {

  static dependencies = {
		combatants: Combatants,
	};

  damage = 0;
  stackCount = 0;

  on_initialized() {
    this.active = this.combatants.selected.hasWaist(ITEMS.ZANNESU_JOURNEY.id);
  }

  on_byPlayer_cast(event) {
    if (event.ability.guid !== SPELLS.BLIZZARD.id) {
      return;
    }
    const buff = this.combatants.selected.getBuff(SPELLS.ZANNESU_JOURNEY_BUFF.id,event.timestamp);
    this.stackCount = buff && buff.stacks || 0;
  }

  on_byPlayer_damage(event) {
    if (event.ability.guid !== SPELLS.BLIZZARD_DAMAGE.id) {
      return;
    }
      this.damage += getDamageBonus(event, DAMAGE_BONUS * this.stackCount);
  }

  item() {
    return {
      item: ITEMS.ZANNESU_JOURNEY,
      result: `${this.owner.formatItemDamageDone(this.damage)}`,
    };
  }
}

export default ZannesuJourney;
<|endoftext|>


<commit_before>define(function(require) {

// imports
var Kai = require('core/Kai');
var World = require('entities/World');
var Grid = require('physics/CollisionGrid');
var GamepadController = require('components/input/GamepadController');
var DOMTools = require('utils/DOMTools');
var DebugDraw = require('utils/DebugDraw');

var Player = require('entities/GamepadPlayer');

/*
TODO

- change component naming convention to [ACCESSOR]_[THING]

- player management component
track active controllers, fire signal when all players pressed start.
control respawning.
tally scores.

- background (tilemap)
- camera (scroll and zoom to fit)

- point totals next to radar

at this point, remove other game code (references to minions) and push to github.
copy everything over to new private repo and continue work from there.

- create new input component
input components are specific to games, so we have our arena shooter twin stick controls and affect accel and rotation

- point plates (touch to control, time = points)
sitting nearby, player can press bumper to convert 10 points to a minion

- new player graphic
- resize minion to be smaller?

- minions
wander in squads of 5 (first 4 always follow owner)
dpad switch minion modes

- game timer
- radar at top?
*/

var XboxPadTest = function() {
	Kai.pads = new GamepadController();

	this.players = [];
	this.things = [];
};

XboxPadTest.prototype = {

	preload: function () {
		// console.log('[XboxPadTest.preload]');
		Kai.load.image('players', '../img/players.png');
		Kai.load.image('bullet', '../img/bullet.png');
		Kai.load.image('tileset', '../img/hex_tiles_b0rked.png');

		// crimson land?
	},

	create: function () {
		// console.log('[XboxPadTest.create]');
		Kai.pads.onConnect.add(this.padAdded, this);
		Kai.pads.onDisconnect.add(this.padRemoved, this);

		World.set({
			width: 2000,
			height: 2000,
			friction: 0.9,
			gravity: 0
		});
		World.broadphase = new Grid(150);

		var canvas = document.getElementById('stage');
		canvas.width = Kai.width = window.innerWidth;
		canvas.height = Kai.height = window.innerHeight;

		Kai.stage = new createjs.Stage(canvas);

		for (var i = 0; i < 4; i++) {
			this.players[i] = new Player(100 * i + 200, 100 * i + 200, i);
		}

		Kai.renderHook = this.draw.bind(this);

		// DEBUG
		var debugCanvas = document.getElementById('debug');
		Kai.debugCtx = debugCanvas.getContext('2d');
		DOMTools.copySpatial(canvas, debugCanvas);
		// END DEBUG

		console.log('[XboxPadTest.create] Running');
	},

	padAdded: function(pad) {
		this.players[pad.id].activate(100 * pad.id + 200, 100 * pad.id + 200);
		console.log('[XboxPadTest.padRemoved] Player '+(pad.id+1)+' joined');
	},

	padRemoved: function(pad) {
		this.players[pad.id].disable();
		console.log('[XboxPadTest.padRemoved] Player '+(pad.id+1)+' left');
	},

	update: function () {
		Kai.debugCtx.clearRect(0, 0, Kai.width, Kai.height);
		Kai.pads.update();

		World.broadphase.update();
		// World.map.update();
	},

	draw: function () {
		Kai.stage.update();
	},

	dispose: function() {
		Kai.pads.onConnect.remove(this.padAdded, this);
		Kai.pads.onDisconnect.remove(this.padRemoved, this);
		Kai.pads.dispose();
		for (var i = 0; i < this.things.length; i++) {
			this.things[i].dispose();
		}
		this.things = null;
	}
};

return XboxPadTest;

});<commit_msg>clean comments<commit_after>define(function(require) {

// imports
var Kai = require('core/Kai');
var World = require('entities/World');
var Grid = require('physics/CollisionGrid');
var GamepadController = require('components/input/GamepadController');
var DOMTools = require('utils/DOMTools');
var DebugDraw = require('utils/DebugDraw');

var Player = require('entities/GamepadPlayer');

var XboxPadTest = function() {
	Kai.pads = new GamepadController();

	this.players = [];
	this.things = [];
};

XboxPadTest.prototype = {

	preload: function () {
		// console.log('[XboxPadTest.preload]');
		Kai.load.image('players', '../img/players.png');
		Kai.load.image('bullet', '../img/bullet.png');
		Kai.load.image('tileset', '../img/hex_tiles_b0rked.png');

		// crimson land?
	},

	create: function () {
		// console.log('[XboxPadTest.create]');
		Kai.pads.onConnect.add(this.padAdded, this);
		Kai.pads.onDisconnect.add(this.padRemoved, this);

		World.set({
			width: 2000,
			height: 2000,
			friction: 0.9,
			gravity: 0
		});
		World.broadphase = new Grid(150);

		var canvas = document.getElementById('stage');
		canvas.width = Kai.width = window.innerWidth;
		canvas.height = Kai.height = window.innerHeight;

		Kai.stage = new createjs.Stage(canvas);

		for (var i = 0; i < 4; i++) {
			this.players[i] = new Player(100 * i + 200, 100 * i + 200, i);
		}

		Kai.renderHook = this.draw.bind(this);

		// DEBUG
		var debugCanvas = document.getElementById('debug');
		Kai.debugCtx = debugCanvas.getContext('2d');
		DOMTools.copySpatial(canvas, debugCanvas);
		// END DEBUG

		console.log('[XboxPadTest.create] Running');
	},

	padAdded: function(pad) {
		this.players[pad.id].activate(100 * pad.id + 200, 100 * pad.id + 200);
		console.log('[XboxPadTest.padRemoved] Player '+(pad.id+1)+' joined');
	},

	padRemoved: function(pad) {
		this.players[pad.id].disable();
		console.log('[XboxPadTest.padRemoved] Player '+(pad.id+1)+' left');
	},

	update: function () {
		Kai.debugCtx.clearRect(0, 0, Kai.width, Kai.height);
		Kai.pads.update();

		World.broadphase.update();
		// World.map.update();
	},

	draw: function () {
		Kai.stage.update();
	},

	dispose: function() {
		Kai.pads.onConnect.remove(this.padAdded, this);
		Kai.pads.onDisconnect.remove(this.padRemoved, this);
		Kai.pads.dispose();
		for (var i = 0; i < this.things.length; i++) {
			this.things[i].dispose();
		}
		this.things = null;
	}
};

return XboxPadTest;

});<|endoftext|>


<commit_before>//----------------------------------------------------------------------------
//  Copyright (C) 2013 The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// Base Widget Model and View classes
//============================================================================

/**
 * @module IPython
 * @namespace IPython
 **/

define(["notebook/js/widgetmanager",
        "underscore",
        "backbone"],
function(WidgetManager, _, Backbone){

    var WidgetModel = Backbone.Model.extend({
        constructor: function (widget_manager, model_id, comm) {
            // Constructor
            //
            // Creates a WidgetModel instance.
            //
            // Parameters
            // ----------
            // widget_manager : WidgetManager instance
            // model_id : string
            //      An ID unique to this model.
            // comm : Comm instance (optional)
            this.widget_manager = widget_manager;
            this.pending_msgs = 0;
            this.msg_throttle = 3;
            this.msg_buffer = null;
            this.key_value_lock = null;
            this.id = model_id;
            this.views = [];

            if (comm !== undefined) {
                // Remember comm associated with the model.
                this.comm = comm;
                comm.model = this;

                // Hook comm messages up to model.
                comm.on_close($.proxy(this._handle_comm_closed, this));
                comm.on_msg($.proxy(this._handle_comm_msg, this));
            }
            return Backbone.Model.apply(this);
        },

        send: function (content, callbacks) {
            // Send a custom msg over the comm.
            if (this.comm !== undefined) {
                var data = {method: 'custom', content: content};
                this.comm.send(data, callbacks);
                this.pending_msgs++;
            }
        },

        _handle_comm_closed: function (msg) {
            // Handle when a widget is closed.
            this.trigger('comm:close');
            delete this.comm.model; // Delete ref so GC will collect widget model.
            delete this.comm;
            delete this.model_id; // Delete id from model so widget manager cleans up.
            _.each(this.views, function(view, i) {
                view.remove();
            });
        },

        _handle_comm_msg: function (msg) {
            // Handle incoming comm msg.
            var method = msg.content.data.method;
            switch (method) {
                case 'update':
                    this.apply_update(msg.content.data.state);
                    break;
                case 'custom':
                    this.trigger('msg:custom', msg.content.data.content);
                    break;
                case 'display':
                    this.widget_manager.display_view(msg, this);
                    break;
            }
        },

        apply_update: function (state) {
            // Handle when a widget is updated via the python side.
            var that = this;
            _.each(state, function(value, key) {
                that.key_value_lock = [key, value];
                try {
                    that.set(key, that._unpack_models(value));
                } finally {
                    that.key_value_lock = null;
                }
            });
        },

        _handle_status: function (msg, callbacks) {
            // Handle status msgs.

            // execution_state : ('busy', 'idle', 'starting')
            if (this.comm !== undefined) {
                if (msg.content.execution_state ==='idle') {
                    // Send buffer if this message caused another message to be
                    // throttled.
                    if (this.msg_buffer !== null &&
                        this.msg_throttle === this.pending_msgs) {
                        var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
                        this.comm.send(data, callbacks);
                        this.msg_buffer = null;
                    } else {
                        --this.pending_msgs;
                    }
                }
            }
        },

        callbacks: function(view) {
            // Create msg callbacks for a comm msg.
            var callbacks = this.widget_manager.callbacks(view);

            if (callbacks.iopub === undefined) {
                callbacks.iopub = {};
            }

            var that = this;
            callbacks.iopub.status = function (msg) {
                that._handle_status(msg, callbacks);
            };
            return callbacks;
        },

        sync: function (method, model, options) {
            // Handle sync to the back-end.  Called when a model.save() is called.

            // Make sure a comm exists.
            var error = options.error || function() {
                console.error('Backbone sync error:', arguments);
            };
            if (this.comm === undefined) {
                error();
                return false;
            }

            // Delete any key value pairs that the back-end already knows about.
            var attrs = (method === 'patch') ? options.attrs : model.toJSON(options);
            if (this.key_value_lock !== null) {
                var key = this.key_value_lock[0];
                var value = this.key_value_lock[1];
                if (attrs[key] === value) {
                    delete attrs[key];
                }
            }

            // Only sync if there are attributes to send to the back-end.
            if (_.size(attrs) > 0) {

                // If this message was sent via backbone itself, it will not
                // have any callbacks.  It's important that we create callbacks
                // so we can listen for status messages, etc...
                var callbacks = options.callbacks || this.callbacks();

                // Check throttle.
                if (this.pending_msgs >= this.msg_throttle) {
                    // The throttle has been exceeded, buffer the current msg so
                    // it can be sent once the kernel has finished processing
                    // some of the existing messages.

                    // Combine updates if it is a 'patch' sync, otherwise replace updates
                    switch (method) {
                        case 'patch':
                            this.msg_buffer = $.extend(this.msg_buffer || {}, attrs);
                            break;
                        case 'update':
                        case 'create':
                            this.msg_buffer = attrs;
                            break;
                        default:
                            error();
                            return false;
                    }
                    this.msg_buffer_callbacks = callbacks;

                } else {
                    // We haven't exceeded the throttle, send the message like
                    // normal.
                    var data = {method: 'backbone', sync_data: attrs};
                    this.comm.send(data, callbacks);
                    this.pending_msgs++;
                }
            }
            // Since the comm is a one-way communication, assume the message
            // arrived.  Don't call success since we don't have a model back from the server
            // this means we miss out on the 'sync' event.
        },

        save_changes: function(callbacks) {
            // Push this model's state to the back-end
            //
            // This invokes a Backbone.Sync.
            this.save(this.changedAttributes(), {patch: true, callbacks: callbacks});
        },

        _pack_models: function(value) {
            // Replace models with model ids recursively.
            if (value instanceof Backbone.Model) {
                return value.id;

            } else if ($.isArray(value)) {
                var packed = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed.push(that._pack_models(sub_value));
                });
                return packed;

            } else if (value instanceof Object) {
                var packed = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed[key] = that._pack_models(sub_value);
                });
                return packed;

            } else {
                return value;
            }
        },

        _unpack_models: function(value) {
            // Replace model ids with models recursively.
            if ($.isArray(value)) {
                var unpacked = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked.push(that._unpack_models(sub_value));
                });
                return unpacked;

            } else if (value instanceof Object) {
                var unpacked = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked[key] = that._unpack_models(sub_value);
                });
                return unpacked;

            } else {
                var model = this.widget_manager.get_model(value);
                if (model) {
                    return model;
                } else {
                    return value;
                }
            }
        },

    });
    WidgetManager.register_widget_model('WidgetModel', WidgetModel);

    var WidgetView = Backbone.View.extend({
        initialize: function(parameters) {
            // Public constructor.
            this.model.on('change',this.update,this);
            this.options = parameters.options;
            this.child_views = [];
            this.model.views.push(this);
        },

        update: function(){
            // Triggered on model change.
            //
            // Update view to be consistent with this.model
        },

        create_child_view: function(child_model, options) {
            // Create and return a child view.
            //
            // -given a model and (optionally) a view name if the view name is
            // not given, it defaults to the model's default view attribute.

            // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
            // it would be great to have the widget manager add the cell metadata
            // to the subview without having to add it here.
            var child_view = this.model.widget_manager.create_view(child_model, options || {}, this);
            this.child_views[child_model.id] = child_view;
            return child_view;
        },

        delete_child_view: function(child_model, options) {
            // Delete a child view that was previously created using create_child_view.
            var view = this.child_views[child_model.id];
            if (view !== undefined) {
                delete this.child_views[child_model.id];
                view.remove();
            }
        },

        do_diff: function(old_list, new_list, removed_callback, added_callback) {
            // Difference a changed list and call remove and add callbacks for
            // each removed and added item in the new list.
            //
            // Parameters
            // ----------
            // old_list : array
            // new_list : array
            // removed_callback : Callback(item)
            //      Callback that is called for each item removed.
            // added_callback : Callback(item)
            //      Callback that is called for each item added.

            // removed items
            _.each(_.difference(old_list, new_list), function(item, index, list) {
                removed_callback(item);
            }, this);

            // added items
            _.each(_.difference(new_list, old_list), function(item, index, list) {
                added_callback(item);
            }, this);
        },

        callbacks: function(){
            // Create msg callbacks for a comm msg.
            return this.model.callbacks(this);
        },

        render: function(){
            // Render the view.
            //
            // By default, this is only called the first time the view is created
        },

        send: function (content) {
            // Send a custom msg associated with this view.
            this.model.send(content, this.callbacks());
        },

        touch: function () {
            this.model.save_changes(this.callbacks());
        },
    });

    var DOMWidgetView = WidgetView.extend({
        initialize: function (options) {
            // Public constructor

            // In the future we may want to make changes more granular
            // (e.g., trigger on visible:change).
            this.model.on('change', this.update, this);
            this.model.on('msg:custom', this.on_msg, this);
            DOMWidgetView.__super__.initialize.apply(this, arguments);
        },

        on_msg: function(msg) {
            // Handle DOM specific msgs.
            switch(msg.msg_type) {
                case 'add_class':
                    this.add_class(msg.selector, msg.class_list);
                    break;
                case 'remove_class':
                    this.remove_class(msg.selector, msg.class_list);
                    break;
            }
        },

        add_class: function (selector, class_list) {
            // Add a DOM class to an element.
            this._get_selector_element(selector).addClass(class_list);
        },

        remove_class: function (selector, class_list) {
            // Remove a DOM class from an element.
            this._get_selector_element(selector).removeClass(class_list);
        },

        update: function () {
            // Update the contents of this view
            //
            // Called when the model is changed.  The model may have been
            // changed by another view or by a state update from the back-end.
            //      The very first update seems to happen before the element is
            // finished rendering so we use setTimeout to give the element time
            // to render
            var e = this.$el;
            var visible = this.model.get('visible');
            setTimeout(function() {e.toggle(visible);},0);

            var css = this.model.get('_css');
            if (css === undefined) {return;}
            var that = this;
            _.each(css, function(css_traits, selector){
                // Apply the css traits to all elements that match the selector.
                var elements = that._get_selector_element(selector);
                if (elements.length > 0) {
                    _.each(css_traits, function(css_value, css_key){
                        elements.css(css_key, css_value);
                    });
                }
            });
        },

        _get_selector_element: function (selector) {
            // Get the elements via the css selector.

            // If the selector is blank, apply the style to the $el_to_style
            // element.  If the $el_to_style element is not defined, use apply
            // the style to the view's element.
            var elements;
            if (!selector) {
                if (this.$el_to_style === undefined) {
                    elements = this.$el;
                } else {
                    elements = this.$el_to_style;
                }
            } else {
                elements = this.$el.find(selector);
            }
            return elements;
        },
    });

    IPython.WidgetModel = WidgetModel;
    IPython.WidgetView = WidgetView;
    IPython.DOMWidgetView = DOMWidgetView;

    // Pass through WidgetManager namespace.
    return WidgetManager;
});
<commit_msg>Only send diff message if diff isn't corrupt.<commit_after>//----------------------------------------------------------------------------
//  Copyright (C) 2013 The IPython Development Team
//
//  Distributed under the terms of the BSD License.  The full license is in
//  the file COPYING, distributed as part of this software.
//----------------------------------------------------------------------------

//============================================================================
// Base Widget Model and View classes
//============================================================================

/**
 * @module IPython
 * @namespace IPython
 **/

define(["notebook/js/widgetmanager",
        "underscore",
        "backbone"],
function(WidgetManager, _, Backbone){

    var WidgetModel = Backbone.Model.extend({
        constructor: function (widget_manager, model_id, comm) {
            // Constructor
            //
            // Creates a WidgetModel instance.
            //
            // Parameters
            // ----------
            // widget_manager : WidgetManager instance
            // model_id : string
            //      An ID unique to this model.
            // comm : Comm instance (optional)
            this.widget_manager = widget_manager;
            this._set_calls = 0;
            this.pending_msgs = 0;
            this.msg_throttle = 3;
            this.msg_buffer = null;
            this.key_value_lock = null;
            this.id = model_id;
            this.views = [];

            if (comm !== undefined) {
                // Remember comm associated with the model.
                this.comm = comm;
                comm.model = this;

                // Hook comm messages up to model.
                comm.on_close($.proxy(this._handle_comm_closed, this));
                comm.on_msg($.proxy(this._handle_comm_msg, this));
            }
            return Backbone.Model.apply(this);
        },

        send: function (content, callbacks) {
            // Send a custom msg over the comm.
            if (this.comm !== undefined) {
                var data = {method: 'custom', content: content};
                this.comm.send(data, callbacks);
                this.pending_msgs++;
            }
        },

        _handle_comm_closed: function (msg) {
            // Handle when a widget is closed.
            this.trigger('comm:close');
            delete this.comm.model; // Delete ref so GC will collect widget model.
            delete this.comm;
            delete this.model_id; // Delete id from model so widget manager cleans up.
            _.each(this.views, function(view, i) {
                view.remove();
            });
        },

        _handle_comm_msg: function (msg) {
            // Handle incoming comm msg.
            var method = msg.content.data.method;
            switch (method) {
                case 'update':
                    this.apply_update(msg.content.data.state);
                    break;
                case 'custom':
                    this.trigger('msg:custom', msg.content.data.content);
                    break;
                case 'display':
                    this.widget_manager.display_view(msg, this);
                    break;
            }
        },

        apply_update: function (state) {
            // Handle when a widget is updated via the python side.
            var that = this;
            _.each(state, function(value, key) {
                that.key_value_lock = [key, value];
                try {
                    that.set(key, that._unpack_models(value));
                } finally {
                    that.key_value_lock = null;
                }
            });
        },

        _handle_status: function (msg, callbacks) {
            // Handle status msgs.

            // execution_state : ('busy', 'idle', 'starting')
            if (this.comm !== undefined) {
                if (msg.content.execution_state ==='idle') {
                    // Send buffer if this message caused another message to be
                    // throttled.
                    if (this.msg_buffer !== null &&
                        this.msg_throttle === this.pending_msgs) {
                        var data = {method: 'backbone', sync_method: 'update', sync_data: this.msg_buffer};
                        this.comm.send(data, callbacks);
                        this.msg_buffer = null;
                    } else {
                        --this.pending_msgs;
                    }
                }
            }
        },

        callbacks: function(view) {
            // Create msg callbacks for a comm msg.
            var callbacks = this.widget_manager.callbacks(view);

            if (callbacks.iopub === undefined) {
                callbacks.iopub = {};
            }

            var that = this;
            callbacks.iopub.status = function (msg) {
                that._handle_status(msg, callbacks);
            };
            return callbacks;
        },

        set: function(key, val, options) {
            // Set a value.
            this._set_calls++;
            return WidgetModel.__super__.set.apply(this, arguments);
        },

        sync: function (method, model, options) {
            // Handle sync to the back-end.  Called when a model.save() is called.

            // Make sure a comm exists.
            var error = options.error || function() {
                console.error('Backbone sync error:', arguments);
            };
            if (this.comm === undefined) {
                error();
                return false;
            }

            // Delete any key value pairs that the back-end already knows about.
            var attrs = (method === 'patch') ? options.attrs : model.toJSON(options);
            if (this.key_value_lock !== null) {
                var key = this.key_value_lock[0];
                var value = this.key_value_lock[1];
                if (attrs[key] === value) {
                    delete attrs[key];
                }
            }

            // Only sync if there are attributes to send to the back-end.
            attrs = this._pack_models(attrs);
            if (_.size(attrs) > 0) {

                // If this message was sent via backbone itself, it will not
                // have any callbacks.  It's important that we create callbacks
                // so we can listen for status messages, etc...
                var callbacks = options.callbacks || this.callbacks();

                // Check throttle.
                if (this.pending_msgs >= this.msg_throttle) {
                    // The throttle has been exceeded, buffer the current msg so
                    // it can be sent once the kernel has finished processing
                    // some of the existing messages.

                    // Combine updates if it is a 'patch' sync, otherwise replace updates
                    switch (method) {
                        case 'patch':
                            this.msg_buffer = $.extend(this.msg_buffer || {}, attrs);
                            break;
                        case 'update':
                        case 'create':
                            this.msg_buffer = attrs;
                            break;
                        default:
                            error();
                            return false;
                    }
                    this.msg_buffer_callbacks = callbacks;

                } else {
                    // We haven't exceeded the throttle, send the message like
                    // normal.
                    var data = {method: 'backbone', sync_data: attrs};
                    this.comm.send(data, callbacks);
                    this.pending_msgs++;
                }
            }
            // Since the comm is a one-way communication, assume the message
            // arrived.  Don't call success since we don't have a model back from the server
            // this means we miss out on the 'sync' event.
            this._set_calls = 0;
        },

        save_changes: function(callbacks) {
            // Push this model's state to the back-end
            //
            // This invokes a Backbone.Sync.

            // Backbone only remembers the diff of the most recent set()
            // opertation.  Calling set multiple times in a row results in a
            // loss of diff information which means we need to send a full
            // state.  If diffing is important to the user, model.set(...) should
            // only be called once prior to a view.touch().  If multiple
            // parameters need to be set, use the model.set({key1: val1, key2: val2, ...})
            // signature.
            if (self._set_calls <= 1) {
                this.save(this.changedAttributes(), {patch: true, callbacks: callbacks});
            } else {
                this.save(null, {patch: false, callbacks: callbacks});
            }
        },

        _pack_models: function(value) {
            // Replace models with model ids recursively.
            if (value instanceof Backbone.Model) {
                return value.id;

            } else if ($.isArray(value)) {
                var packed = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed.push(that._pack_models(sub_value));
                });
                return packed;

            } else if (value instanceof Object) {
                var packed = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    packed[key] = that._pack_models(sub_value);
                });
                return packed;

            } else {
                return value;
            }
        },

        _unpack_models: function(value) {
            // Replace model ids with models recursively.
            if ($.isArray(value)) {
                var unpacked = [];
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked.push(that._unpack_models(sub_value));
                });
                return unpacked;

            } else if (value instanceof Object) {
                var unpacked = {};
                var that = this;
                _.each(value, function(sub_value, key) {
                    unpacked[key] = that._unpack_models(sub_value);
                });
                return unpacked;

            } else {
                var model = this.widget_manager.get_model(value);
                if (model) {
                    return model;
                } else {
                    return value;
                }
            }
        },

    });
    WidgetManager.register_widget_model('WidgetModel', WidgetModel);

    var WidgetView = Backbone.View.extend({
        initialize: function(parameters) {
            // Public constructor.
            this.model.on('change',this.update,this);
            this.options = parameters.options;
            this.child_views = [];
            this.model.views.push(this);
        },

        update: function(){
            // Triggered on model change.
            //
            // Update view to be consistent with this.model
        },

        create_child_view: function(child_model, options) {
            // Create and return a child view.
            //
            // -given a model and (optionally) a view name if the view name is
            // not given, it defaults to the model's default view attribute.

            // TODO: this is hacky, and makes the view depend on this cell attribute and widget manager behavior
            // it would be great to have the widget manager add the cell metadata
            // to the subview without having to add it here.
            var child_view = this.model.widget_manager.create_view(child_model, options || {}, this);
            this.child_views[child_model.id] = child_view;
            return child_view;
        },

        delete_child_view: function(child_model, options) {
            // Delete a child view that was previously created using create_child_view.
            var view = this.child_views[child_model.id];
            if (view !== undefined) {
                delete this.child_views[child_model.id];
                view.remove();
            }
        },

        do_diff: function(old_list, new_list, removed_callback, added_callback) {
            // Difference a changed list and call remove and add callbacks for
            // each removed and added item in the new list.
            //
            // Parameters
            // ----------
            // old_list : array
            // new_list : array
            // removed_callback : Callback(item)
            //      Callback that is called for each item removed.
            // added_callback : Callback(item)
            //      Callback that is called for each item added.

            // removed items
            _.each(_.difference(old_list, new_list), function(item, index, list) {
                removed_callback(item);
            }, this);

            // added items
            _.each(_.difference(new_list, old_list), function(item, index, list) {
                added_callback(item);
            }, this);
        },

        callbacks: function(){
            // Create msg callbacks for a comm msg.
            return this.model.callbacks(this);
        },

        render: function(){
            // Render the view.
            //
            // By default, this is only called the first time the view is created
        },

        send: function (content) {
            // Send a custom msg associated with this view.
            this.model.send(content, this.callbacks());
        },

        touch: function () {
            this.model.save_changes(this.callbacks());
        },
    });

    var DOMWidgetView = WidgetView.extend({
        initialize: function (options) {
            // Public constructor

            // In the future we may want to make changes more granular
            // (e.g., trigger on visible:change).
            this.model.on('change', this.update, this);
            this.model.on('msg:custom', this.on_msg, this);
            DOMWidgetView.__super__.initialize.apply(this, arguments);
        },

        on_msg: function(msg) {
            // Handle DOM specific msgs.
            switch(msg.msg_type) {
                case 'add_class':
                    this.add_class(msg.selector, msg.class_list);
                    break;
                case 'remove_class':
                    this.remove_class(msg.selector, msg.class_list);
                    break;
            }
        },

        add_class: function (selector, class_list) {
            // Add a DOM class to an element.
            this._get_selector_element(selector).addClass(class_list);
        },

        remove_class: function (selector, class_list) {
            // Remove a DOM class from an element.
            this._get_selector_element(selector).removeClass(class_list);
        },

        update: function () {
            // Update the contents of this view
            //
            // Called when the model is changed.  The model may have been
            // changed by another view or by a state update from the back-end.
            //      The very first update seems to happen before the element is
            // finished rendering so we use setTimeout to give the element time
            // to render
            var e = this.$el;
            var visible = this.model.get('visible');
            setTimeout(function() {e.toggle(visible);},0);

            var css = this.model.get('_css');
            if (css === undefined) {return;}
            var that = this;
            _.each(css, function(css_traits, selector){
                // Apply the css traits to all elements that match the selector.
                var elements = that._get_selector_element(selector);
                if (elements.length > 0) {
                    _.each(css_traits, function(css_value, css_key){
                        elements.css(css_key, css_value);
                    });
                }
            });
        },

        _get_selector_element: function (selector) {
            // Get the elements via the css selector.

            // If the selector is blank, apply the style to the $el_to_style
            // element.  If the $el_to_style element is not defined, use apply
            // the style to the view's element.
            var elements;
            if (!selector) {
                if (this.$el_to_style === undefined) {
                    elements = this.$el;
                } else {
                    elements = this.$el_to_style;
                }
            } else {
                elements = this.$el.find(selector);
            }
            return elements;
        },
    });

    IPython.WidgetModel = WidgetModel;
    IPython.WidgetView = WidgetView;
    IPython.DOMWidgetView = DOMWidgetView;

    // Pass through WidgetManager namespace.
    return WidgetManager;
});
<|endoftext|>