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

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';

import TextField from '../TextField';
import Popup from '../Popup';
import List from '../List';
import DynamicRenderList from '../DynamicRenderList';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import Dom from '../_vendors/Dom';
import SelectMode from '../_statics/SelectMode';

export default class DropdownFilter extends Component {

    static SelectMode = SelectMode;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.triggerEl = null;

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

        this.isAbove = ::this.isAbove;
        this.filterData = ::this.filterData;
        this.triggerFocusHandler = ::this.triggerFocusHandler;
        this.triggerBlurHandler = ::this.triggerBlurHandler;
        this.filterChangeHandler = ::this.filterChangeHandler;
        this.filterPressEnterHandler = ::this.filterPressEnterHandler;
        this.closePopup = ::this.closePopup;
        this.popupRenderHandler = ::this.popupRenderHandler;
        this.changeHandler = ::this.changeHandler;

    }

    isAbove() {

        const autoComplete = this.refs.autoComplete;

        if (!this.popupHeight || !autoComplete) {
            return false;
        }

        const {top} = Dom.getOffset(autoComplete),
            scrollTop = Dom.getScrollTop();

        if (top + this.triggerHeight + this.popupHeight - scrollTop > window.innerHeight) {
            return true;
        }

        return false;

    }

    filterData(filter = this.state.filter, data = this.props.data) {

        if (!filter) {
            return data;
        }

        const {displayField, filterCallback} = this.props;

        if (filterCallback) {
            return filterCallback(filter, data);
        }

        const filterFunc = (originData) => {
            return originData.filter(item => typeof item === 'object' && !!item[displayField] ?
                item[displayField].toString().toUpperCase().includes(filter.toUpperCase())
                :
                item.toString().toUpperCase().includes(filter.toUpperCase()));
        };

        return filterFunc(data);

    }

    triggerFocusHandler(...args) {

        const {disabled, onFocus} = this.props,
            {filter} = this.state;

        onFocus && onFocus(...args);

        !disabled && filter && this.setState({
            popupVisible: true
        });

    }

    triggerBlurHandler(...args) {
        const {disabled, onBlur} = this.props;
        !disabled && onBlur && onBlur(...args);
    }

    filterChangeHandler(filter) {

        const value = this.state.value,
            state = {
                filter,
                popupVisible: !!filter
            };

        if (!filter) {
            state.value = undefined;
        }

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

    }

    filterPressEnterHandler(e, filter) {

        const {autoClose} = this.props,
            callback = () => {
                const {onFilterPressEnter} = this.props;
                onFilterPressEnter && onFilterPressEnter(filter);
            };

        if (autoClose) {
            this.setState({
                popupVisible: false
            }, () => {
                callback();
            });
        } else {
            callback();
        }

    }

    closePopup() {
        this.setState({
            popupVisible: false
        }, () => {
            const {onPopupClosed} = this.props;
            onPopupClosed && onPopupClosed();
        });
    }

    popupRenderHandler(popupEl) {

        this.popupEl = findDOMNode(popupEl);
        this.popupHeight = this.popupEl.offsetHeight;

        const isAbove = this.isAbove();

        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    }

    changeHandler(value) {

        const state = {value};

        if (this.props.autoClose) {
            state.popupVisible = false;
        }

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

    }

    componentDidMount() {
        this.triggerEl = findDOMNode(this.refs.trigger);
        this.triggerHeight = this.triggerEl.clientHeight;
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {

                className, popupClassName, style, popupStyle, theme, popupTheme, placeholder, selectMode,
                disabled, iconCls, rightIconCls, valueField, displayField, descriptionField,
                useDynamicRenderList, listHeight, itemHeight, scrollBuffer,
                noMatchedPopupVisible, noMatchedMsg, popupChildren, renderer,

                radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onItemTouchTap, onFilterClear, onTriggerMouseOver, onTriggerMouseOut

            } = this.props,
            {isAbove, value, filter, popupVisible} = this.state,

            emptyEl = [{
                itemRenderer() {
                    return (

                            {
                                noMatchedMsg ?
                                    noMatchedMsg
                                    :

                                        No matched value.

                            }

                    );
                },
                disableTouchRipple: true
            }],

            listData = this.filterData(),
            isEmpty = listData.length < 1,

            wrapperClassName = (className ? ' ' + className : ''),
            triggerClassName = (isEmpty && !noMatchedPopupVisible ? '' : (popupVisible ? ' activated' : ''))
                + (isAbove ? ' above' : ' blow'),
            autoCompletePopupClassName = (isAbove ? ' above' : ' blow') + (popupClassName ? ' ' + popupClassName : ''),
            autoCompletePopupStyle = Object.assign({
                width: this.triggerEl && getComputedStyle(this.triggerEl).width
            }, popupStyle);

        return (

                <TextField ref="trigger"
                           className={'dropdown-filter-trigger' + triggerClassName}
                           theme={theme}
                           value={filter}
                           placeholder={placeholder}
                           disabled={disabled}
                           iconCls={iconCls}
                           rightIconCls={rightIconCls}
                           onFocus={this.triggerFocusHandler}
                           onBlur={this.triggerBlurHandler}
                           onMouseOver={onTriggerMouseOver}
                           onMouseOut={onTriggerMouseOut}
                           onChange={this.filterChangeHandler}
                           onPressEnter={this.filterPressEnterHandler}
                           onClear={onFilterClear}
                           onRightIconTouchTap={this.filterPressEnterHandler}/>

                {
                    isEmpty && !noMatchedPopupVisible ?
                        null
                        :
                        <Popup className={'dropdown-filter-popup' + autoCompletePopupClassName}
                               style={autoCompletePopupStyle}
                               theme={popupTheme}
                               visible={popupVisible}
                               triggerEl={this.triggerEl}
                               hasTriangle={false}
                               triggerMode={Popup.TriggerMode.OPEN}
                               position={isAbove ? Popup.Position.TOP_LEFT : Popup.Position.BOTTOM_LEFT}
                               onRender={this.popupRenderHandler}
                               onRequestClose={this.closePopup}>

                            {
                                isEmpty ?
                                    <List className="dropdown-filter-list"
                                          theme={popupTheme}
                                          selectMode={List.SelectMode.NORMAL}
                                          data={emptyEl}/>
                                    :
                                    (
                                        useDynamicRenderList ?
                                            <DynamicRenderList className="dropdown-filter-list"
                                                               theme={popupTheme}
                                                               value={value}
                                                               selectMode={selectMode || List.SelectMode.NORMAL}
                                                               data={listData}
                                                               valueField={valueField}
                                                               displayField={displayField}
                                                               descriptionField={descriptionField}
                                                               renderer={renderer}
                                                               listHeight={listHeight}
                                                               itemHeight={itemHeight}
                                                               scrollBuffer={scrollBuffer}
                                                               radioUncheckedIconCls={radioUncheckedIconCls}
                                                               radioCheckedIconCls={radioCheckedIconCls}
                                                               checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                                                               checkboxCheckedIconCls={checkboxCheckedIconCls}
                                                               checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                                                               onItemTouchTap={onItemTouchTap}
                                                               onChange={this.changeHandler}/>
                                            :
                                            <List className="dropdown-filter-list"
                                                  theme={popupTheme}
                                                  value={value}
                                                  selectMode={selectMode || List.SelectMode.NORMAL}
                                                  data={listData}
                                                  valueField={valueField}
                                                  displayField={displayField}
                                                  descriptionField={descriptionField}
                                                  renderer={renderer}
                                                  radioUncheckedIconCls={radioUncheckedIconCls}
                                                  radioCheckedIconCls={radioCheckedIconCls}
                                                  checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                                                  checkboxCheckedIconCls={checkboxCheckedIconCls}
                                                  checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                                                  onItemTouchTap={onItemTouchTap}
                                                  onChange={this.changeHandler}/>
                                    )
                            }

                            {popupChildren}

                        </Popup>
                }

        );
    }

};

DropdownFilter.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)),

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

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

    /**
     * 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.
             */
            onTouchTap: PropTypes.func

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

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * 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,

    popupChildren: PropTypes.any,

    useDynamicRenderList: PropTypes.bool,
    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number,

    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.
     */
    onItemTouchTap: PropTypes.func,

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

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

    onTriggerMouseOver: PropTypes.func,
    onTriggerMouseOut: PropTypes.func,
    onPopupClosed: PropTypes.func

};

DropdownFilter.defaultProps = {

    className: null,
    popupClassName: null,
    style: null,
    popupStyle: null,
    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    placeholder: null,
    data: [],
    disabled: false,
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    autoClose: false,
    selectMode: SelectMode.NORMAL,
    iconCls: null,
    rightIconCls: 'fa fa-search',
    noMatchedPopupVisible: true,
    noMatchedMsg: null,

    popupChildren: null,

    useDynamicRenderList: false,

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

};<commit_msg>optimize DropdownFilter<commit_after>/**
 * @file DropdownFilter component
 * @author liangxiaojun(liangxiaojun@derbysoft.com)
 */

import React, {Component} from 'react';
import PropTypes from 'prop-types';
import {findDOMNode} from 'react-dom';

import TextField from '../TextField';
import Popup from '../Popup';
import List from '../List';
import DynamicRenderList from '../DynamicRenderList';
import Theme from '../Theme';

import Util from '../_vendors/Util';
import SelectMode from '../_statics/SelectMode';
import DropdownCalculation from '../_vendors/DropdownCalculation';

export default class DropdownFilter extends Component {

    static SelectMode = SelectMode;

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.triggerEl = null;

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

        this.filterData = ::this.filterData;
        this.triggerFocusHandler = ::this.triggerFocusHandler;
        this.triggerBlurHandler = ::this.triggerBlurHandler;
        this.filterChangeHandler = ::this.filterChangeHandler;
        this.filterPressEnterHandler = ::this.filterPressEnterHandler;
        this.closePopup = ::this.closePopup;
        this.popupRenderHandler = ::this.popupRenderHandler;
        this.changeHandler = ::this.changeHandler;

    }

    filterData(filter = this.state.filter, data = this.props.data) {

        if (!filter) {
            return data;
        }

        const {displayField, filterCallback} = this.props;

        if (filterCallback) {
            return filterCallback(filter, data);
        }

        const filterFunc = (originData) => {
            return originData.filter(item => typeof item === 'object' && !!item[displayField] ?
                item[displayField].toString().toUpperCase().includes(filter.toUpperCase())
                :
                item.toString().toUpperCase().includes(filter.toUpperCase()));
        };

        return filterFunc(data);

    }

    triggerFocusHandler(...args) {

        const {disabled, onFocus} = this.props,
            {filter} = this.state;

        onFocus && onFocus(...args);

        !disabled && filter && this.setState({
            popupVisible: true
        });

    }

    triggerBlurHandler(...args) {
        const {disabled, onBlur} = this.props;
        !disabled && onBlur && onBlur(...args);
    }

    filterChangeHandler(filter) {

        const value = this.state.value,
            state = {
                filter,
                popupVisible: !!filter
            };

        if (!filter) {
            state.value = undefined;
        }

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

    }

    filterPressEnterHandler(e, filter) {

        const {autoClose} = this.props,
            callback = () => {
                const {onFilterPressEnter} = this.props;
                onFilterPressEnter && onFilterPressEnter(filter);
            };

        if (autoClose) {
            this.setState({
                popupVisible: false
            }, () => {
                callback();
            });
        } else {
            callback();
        }

    }

    closePopup() {
        this.setState({
            popupVisible: false
        }, () => {
            const {onPopupClosed} = this.props;
            onPopupClosed && onPopupClosed();
        });
    }

    popupRenderHandler(popupEl) {

        const isAbove = DropdownCalculation.isAbove(this.dropdownFilterEl, this.triggerEl, findDOMNode(popupEl));

        if (isAbove !== this.state.isAbove) {
            this.setState({
                isAbove
            });
        }

    }

    changeHandler(value) {

        const state = {value};

        if (this.props.autoClose) {
            state.popupVisible = false;
        }

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

    }

    componentDidMount() {
        this.dropdownFilterEl = this.refs.dropdownFilter;
        this.triggerEl = findDOMNode(this.refs.trigger);
    }

    componentWillReceiveProps(nextProps) {
        if (nextProps.value !== this.state.value) {
            this.setState({
                value: nextProps.value
            });
        }
    }

    render() {

        const {

                className, popupClassName, style, popupStyle, theme, popupTheme, placeholder, selectMode,
                disabled, iconCls, rightIconCls, valueField, displayField, descriptionField,
                useDynamicRenderList, listHeight, itemHeight, scrollBuffer,
                noMatchedPopupVisible, noMatchedMsg, popupChildren, renderer,

                radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                onItemTouchTap, onFilterClear, onTriggerMouseOver, onTriggerMouseOut

            } = this.props,
            {isAbove, value, filter, popupVisible} = this.state,

            emptyEl = [{
                itemRenderer() {
                    return (

                            {
                                noMatchedMsg ?
                                    noMatchedMsg
                                    :

                                        No matched value.

                            }

                    );
                },
                disableTouchRipple: true
            }],

            listData = this.filterData(),
            isEmpty = listData.length < 1,

            wrapperClassName = (className ? ' ' + className : ''),
            triggerClassName = (isEmpty && !noMatchedPopupVisible ? '' : (popupVisible ? ' activated' : ''))
                + (isAbove ? ' above' : ' blow'),
            autoCompletePopupClassName = (isAbove ? ' above' : ' blow') + (popupClassName ? ' ' + popupClassName : ''),
            autoCompletePopupStyle = Object.assign({
                width: this.triggerEl && getComputedStyle(this.triggerEl).width
            }, popupStyle);

        return (

                <TextField ref="trigger"
                           className={'dropdown-filter-trigger' + triggerClassName}
                           theme={theme}
                           value={filter}
                           placeholder={placeholder}
                           disabled={disabled}
                           iconCls={iconCls}
                           rightIconCls={rightIconCls}
                           onFocus={this.triggerFocusHandler}
                           onBlur={this.triggerBlurHandler}
                           onMouseOver={onTriggerMouseOver}
                           onMouseOut={onTriggerMouseOut}
                           onChange={this.filterChangeHandler}
                           onPressEnter={this.filterPressEnterHandler}
                           onClear={onFilterClear}
                           onRightIconTouchTap={this.filterPressEnterHandler}/>

                {
                    isEmpty && !noMatchedPopupVisible ?
                        null
                        :
                        <Popup className={'dropdown-filter-popup' + autoCompletePopupClassName}
                               style={autoCompletePopupStyle}
                               theme={popupTheme}
                               visible={popupVisible}
                               triggerEl={this.triggerEl}
                               hasTriangle={false}
                               triggerMode={Popup.TriggerMode.OPEN}
                               position={isAbove ? Popup.Position.TOP_LEFT : Popup.Position.BOTTOM_LEFT}
                               onRender={this.popupRenderHandler}
                               onRequestClose={this.closePopup}>

                            {
                                isEmpty ?
                                    <List className="dropdown-filter-list"
                                          theme={popupTheme}
                                          selectMode={List.SelectMode.NORMAL}
                                          data={emptyEl}/>
                                    :
                                    (
                                        useDynamicRenderList ?
                                            <DynamicRenderList className="dropdown-filter-list"
                                                               theme={popupTheme}
                                                               value={value}
                                                               selectMode={selectMode || List.SelectMode.NORMAL}
                                                               data={listData}
                                                               valueField={valueField}
                                                               displayField={displayField}
                                                               descriptionField={descriptionField}
                                                               renderer={renderer}
                                                               listHeight={listHeight}
                                                               itemHeight={itemHeight}
                                                               scrollBuffer={scrollBuffer}
                                                               radioUncheckedIconCls={radioUncheckedIconCls}
                                                               radioCheckedIconCls={radioCheckedIconCls}
                                                               checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                                                               checkboxCheckedIconCls={checkboxCheckedIconCls}
                                                               checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                                                               onItemTouchTap={onItemTouchTap}
                                                               onChange={this.changeHandler}/>
                                            :
                                            <List className="dropdown-filter-list"
                                                  theme={popupTheme}
                                                  value={value}
                                                  selectMode={selectMode || List.SelectMode.NORMAL}
                                                  data={listData}
                                                  valueField={valueField}
                                                  displayField={displayField}
                                                  descriptionField={descriptionField}
                                                  renderer={renderer}
                                                  radioUncheckedIconCls={radioUncheckedIconCls}
                                                  radioCheckedIconCls={radioCheckedIconCls}
                                                  checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                                                  checkboxCheckedIconCls={checkboxCheckedIconCls}
                                                  checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                                                  onItemTouchTap={onItemTouchTap}
                                                  onChange={this.changeHandler}/>
                                    )
                            }

                            {popupChildren}

                        </Popup>
                }

        );
    }

};

DropdownFilter.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)),

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

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

    /**
     * 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.
             */
            onTouchTap: PropTypes.func

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

        // grouped
        PropTypes.array

    ]).isRequired,

    /**
     * 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,

    popupChildren: PropTypes.any,

    useDynamicRenderList: PropTypes.bool,
    listHeight: PropTypes.number,
    itemHeight: PropTypes.number,
    scrollBuffer: PropTypes.number,

    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.
     */
    onItemTouchTap: PropTypes.func,

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

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

    onTriggerMouseOver: PropTypes.func,
    onTriggerMouseOut: PropTypes.func,
    onPopupClosed: PropTypes.func

};

DropdownFilter.defaultProps = {

    className: null,
    popupClassName: null,
    style: null,
    popupStyle: null,
    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    placeholder: null,
    data: [],
    disabled: false,
    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',
    autoClose: false,
    selectMode: SelectMode.NORMAL,
    iconCls: null,
    rightIconCls: 'fa fa-search',
    noMatchedPopupVisible: true,
    noMatchedMsg: null,

    popupChildren: null,

    useDynamicRenderList: false,

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

};<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var bench = require( '@stdlib/bench' );
var randu = require( '@stdlib/random/base/randu' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var EPS = require( '@stdlib/constants/math/float64-eps' );
var pkg = require( './../package.json' ).name;
var iterator = require( './../lib' );

// MAIN //

bench( pkg, function benchmark( b ) {
	var sigma;
	var iter;
	var mu;
	var i;

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		mu = ( randu() * 100.0 ) - 50.0;
		sigma = ( randu()*10.0 ) + EPS;
		iter = iterator( mu, sigma );
		if ( typeof iter !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( typeof iter !== 'object' || typeof iter.next !== 'function' ) {
		b.fail( 'should return an iterator protocol-compliant object' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::iteration', function benchmark( b ) {
	var sigma;
	var rand;
	var mu;
	var z;
	var i;

	mu = -3.0;
	sigma = 10.0;
	rand = iterator( mu, sigma );

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		z = rand.next().value;
		if ( isnan( z ) ) {
			b.fail( 'should not return NaN' );
		}
	}
	b.toc();
	if ( isnan( z ) ) {
		b.fail( 'should not return NaN' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});
<commit_msg>Use consistent spacing<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var bench = require( '@stdlib/bench' );
var randu = require( '@stdlib/random/base/randu' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var EPS = require( '@stdlib/constants/math/float64-eps' );
var pkg = require( './../package.json' ).name;
var iterator = require( './../lib' );

// MAIN //

bench( pkg, function benchmark( b ) {
	var sigma;
	var iter;
	var mu;
	var i;

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		mu = ( randu()*100.0 ) - 50.0;
		sigma = ( randu()*10.0 ) + EPS;
		iter = iterator( mu, sigma );
		if ( typeof iter !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( typeof iter !== 'object' || typeof iter.next !== 'function' ) {
		b.fail( 'should return an iterator protocol-compliant object' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::iteration', function benchmark( b ) {
	var sigma;
	var rand;
	var mu;
	var z;
	var i;

	mu = -3.0;
	sigma = 10.0;
	rand = iterator( mu, sigma );

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		z = rand.next().value;
		if ( isnan( z ) ) {
			b.fail( 'should not return NaN' );
		}
	}
	b.toc();
	if ( isnan( z ) ) {
		b.fail( 'should not return NaN' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});
<|endoftext|>


<commit_before>function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
	var c = ca[i];
	while (c.charAt(0)==' ') c = c.substring(1);
	if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }
    return "";
}

function delCookie(cname) {
    document.cookie = cname + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

function createCookie(name, value, days) {
    var date, expires;
    if (days) {
        date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        expires = "; expires="+date.toGMTString();
    } else {
        expires = "";
    }
    document.cookie = name+"="+value+expires+"; path=/";
}

function mapType(selectObj) {
    var idx = selectObj.selectedIndex;
    var atype = selectObj.options[idx].value;
    var type = atype.split('-');
    document.cookie =  'MapType='+type+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    if (type[0] == 'Mapbox') {
	document.cookie =  'MapType='+type[0]+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
	document.cookie =  'MapTypeId='+type[1]+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    } else {
	document.cookie =  'MapType='+atype+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    }
    window.location.reload();
}

function terrainType(selectObj) {
    var idx = selectObj.selectedIndex;
    var atype = selectObj.options[idx].value;
    var type = atype.split('-');
    document.cookie =  'MapTerrain='+type+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}

function sattypes(selectObj) {
    var sattypes = [], sattype;
    for (var i=0, len=selectObj.options.length; i< len;i++) {
	sattype = selectObj.options[i];
	if (sattype.selected) {
	    sattypes.push(sattype.value);
	}
    }
    //document.cookie =  'sattypes='+sattypes.join()+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('sattypes',sattypes.join(),2);
    updateSat();
}
function airlines(selectObj) {
    var airs = [], air;
    for (var i=0, len=selectObj.options.length; i< len;i++) {
	air = selectObj.options[i];
	if (air.selected) {
	    airs.push(air.value);
	}
    }
    //document.cookie =  'filter_Airlines='+airs.join()+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_Airlines',airs.join(),2);
}
function airlinestype(selectObj) {
    var idx = selectObj.selectedIndex;
    var airtype = selectObj.options[idx].value;
    //document.cookie =  'filter_airlinestype='+airtype+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_airlinestype',airtype,2);
}
function alliance(selectObj) {
    var idx = selectObj.selectedIndex;
    var alliance = selectObj.options[idx].value;
    //document.cookie =  'filter_alliance='+alliance+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_alliance',alliance,2);
}
function identfilter() {
    var ident = $("#identfilter").value;
    //document.cookie =  'filter_ident='+ident+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_ident',ident,2);
}
function removefilters() {
    // Get an array of all cookie names (the regex matches what we don't want)
    var cookieNames = document.cookie.split(/=[^;]*(?:;\s*|$)/);
    // Remove any that match the pattern
    for (var i = 0; i < cookieNames.length; i++) {
    if (/^filter_/.test(cookieNames[i])) {
        document.cookie = cookieNames[i] + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
        }
    }
    window.location.reload();
}
function sources(selectObj) {
    var sources = [], source;
    for (var i=0, len=selectObj.options.length; i< len;i++) {
	source = selectObj.options[i];
	if (source.selected) {
	    sources.push(source.value);
	}
    }
    //document.cookie =  'filter_Sources='+sources.join()+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_Sources',sources.join(),2);
}

function show2D() {
    //document.cookie =  'MapFormat=2d; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('MapFormat','2d',10);
    window.location.reload();
}
function show3D() {
    //document.cookie =  'MapFormat=3d; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    createCookie('MapFormat','3d',10);
    window.location.reload();
}
function clickPolar(cb) {
    document.cookie =  'polar='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}
function clickDisplayAirports(cb) {
    document.cookie =  'displayairports='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}
function clickDisplayISS(cb) {
    document.cookie =  'displayiss='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    updateSat();
}
function clickDisplayMinimap(cb) {
    document.cookie =  'displayminimap='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}
function clickVATSIM(cb) {
    //document.cookie =  'filter_ShowVATSIM='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowVATSIM',cb.checked,2);
}
function clickIVAO(cb) {
     //document.cookie =  'filter_ShowIVAO='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
     createCookie('filter_ShowIVAO',cb.checked,2);
}
function clickphpVMS(cb) {
    //document.cookie =  'filter_ShowVMS='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowVMS',cb.checked,2);
}
function clickSBS1(cb) {
    //document.cookie =  'filter_ShowSBS1='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowSBS1',cb.checked,2);
}
function clickAPRS(cb) {
    //document.cookie =  'filter_ShowAPRS='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowAPRS',cb.checked,2);
}
function clickDisplayGroundStation(cb) {
    createCookie('show_GroundStation',cb.checked,2);
    window.location.reload();
}
function clickDisplayWeatherStation(cb) {
    createCookie('show_WeatherStation',cb.checked,2);
    window.location.reload();
}
function clickDisplayLightning(cb) {
    createCookie('show_Lightning',cb.checked,2);
    window.location.reload();
}
function clickDisplayFires(cb) {
    createCookie('show_Fires',cb.checked,2);
    window.location.reload();
}
function unitdistance(selectObj) {
    var idx = selectObj.selectedIndex;
    var unit = selectObj.options[idx].value;
    document.cookie =  'unitdistance='+unit+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/';
}
function unitspeed(selectObj) {
    var idx = selectObj.selectedIndex;
    var unit = selectObj.options[idx].value;
    document.cookie =  'unitspeed='+unit+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/';
}
function unitaltitude(selectObj) {
    var idx = selectObj.selectedIndex;
    var unit = selectObj.options[idx].value;
    document.cookie =  'unitaltitude='+unit+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/';
}
<commit_msg>mmsi for marine filter<commit_after>function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i=0; i<ca.length; i++) {
	var c = ca[i];
	while (c.charAt(0)==' ') c = c.substring(1);
	if (c.indexOf(name) == 0) return c.substring(name.length,c.length);
    }
    return "";
}

function delCookie(cname) {
    document.cookie = cname + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
}

function createCookie(name, value, days) {
    var date, expires;
    if (days) {
        date = new Date();
        date.setTime(date.getTime()+(days*24*60*60*1000));
        expires = "; expires="+date.toGMTString();
    } else {
        expires = "";
    }
    document.cookie = name+"="+value+expires+"; path=/";
}

function mapType(selectObj) {
    var idx = selectObj.selectedIndex;
    var atype = selectObj.options[idx].value;
    var type = atype.split('-');
    document.cookie =  'MapType='+type+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    if (type[0] == 'Mapbox') {
	document.cookie =  'MapType='+type[0]+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
	document.cookie =  'MapTypeId='+type[1]+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    } else {
	document.cookie =  'MapType='+atype+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    }
    window.location.reload();
}

function terrainType(selectObj) {
    var idx = selectObj.selectedIndex;
    var atype = selectObj.options[idx].value;
    var type = atype.split('-');
    document.cookie =  'MapTerrain='+type+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}

function sattypes(selectObj) {
    var sattypes = [], sattype;
    for (var i=0, len=selectObj.options.length; i< len;i++) {
	sattype = selectObj.options[i];
	if (sattype.selected) {
	    sattypes.push(sattype.value);
	}
    }
    //document.cookie =  'sattypes='+sattypes.join()+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('sattypes',sattypes.join(),2);
    updateSat();
}
function airlines(selectObj) {
    var airs = [], air;
    for (var i=0, len=selectObj.options.length; i< len;i++) {
	air = selectObj.options[i];
	if (air.selected) {
	    airs.push(air.value);
	}
    }
    //document.cookie =  'filter_Airlines='+airs.join()+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_Airlines',airs.join(),2);
}
function airlinestype(selectObj) {
    var idx = selectObj.selectedIndex;
    var airtype = selectObj.options[idx].value;
    //document.cookie =  'filter_airlinestype='+airtype+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_airlinestype',airtype,2);
}
function alliance(selectObj) {
    var idx = selectObj.selectedIndex;
    var alliance = selectObj.options[idx].value;
    //document.cookie =  'filter_alliance='+alliance+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_alliance',alliance,2);
}
function identfilter() {
    var ident = $("#identfilter").value;
    //document.cookie =  'filter_ident='+ident+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_ident',ident,2);
}
function mmsifilter() {
    var ident = $("#mmsifilter").value;
    //document.cookie =  'filter_ident='+ident+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/'
    createCookie('filter_mmsi',ident,2);
}
function removefilters() {
    // Get an array of all cookie names (the regex matches what we don't want)
    var cookieNames = document.cookie.split(/=[^;]*(?:;\s*|$)/);
    // Remove any that match the pattern
    for (var i = 0; i < cookieNames.length; i++) {
    if (/^filter_/.test(cookieNames[i])) {
        document.cookie = cookieNames[i] + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
        }
    }
    window.location.reload();
}
function sources(selectObj) {
    var sources = [], source;
    for (var i=0, len=selectObj.options.length; i< len;i++) {
	source = selectObj.options[i];
	if (source.selected) {
	    sources.push(source.value);
	}
    }
    //document.cookie =  'filter_Sources='+sources.join()+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_Sources',sources.join(),2);
}

function show2D() {
    //document.cookie =  'MapFormat=2d; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('MapFormat','2d',10);
    window.location.reload();
}
function show3D() {
    //document.cookie =  'MapFormat=3d; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    createCookie('MapFormat','3d',10);
    window.location.reload();
}
function clickPolar(cb) {
    document.cookie =  'polar='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}
function clickDisplayAirports(cb) {
    document.cookie =  'displayairports='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}
function clickDisplayISS(cb) {
    document.cookie =  'displayiss='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    updateSat();
}
function clickDisplayMinimap(cb) {
    document.cookie =  'displayminimap='+cb.checked+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/'
    window.location.reload();
}
function clickVATSIM(cb) {
    //document.cookie =  'filter_ShowVATSIM='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowVATSIM',cb.checked,2);
}
function clickIVAO(cb) {
     //document.cookie =  'filter_ShowIVAO='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
     createCookie('filter_ShowIVAO',cb.checked,2);
}
function clickphpVMS(cb) {
    //document.cookie =  'filter_ShowVMS='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowVMS',cb.checked,2);
}
function clickSBS1(cb) {
    //document.cookie =  'filter_ShowSBS1='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowSBS1',cb.checked,2);
}
function clickAPRS(cb) {
    //document.cookie =  'filter_ShowAPRS='+cb.checked+'; expires=<?php print date("D, j M Y G:i:s T",mktime(0, 0, 0, date("m")  , date("d")+2, date("Y"))); ?>; path=/';
    createCookie('filter_ShowAPRS',cb.checked,2);
}
function clickDisplayGroundStation(cb) {
    createCookie('show_GroundStation',cb.checked,2);
    window.location.reload();
}
function clickDisplayWeatherStation(cb) {
    createCookie('show_WeatherStation',cb.checked,2);
    window.location.reload();
}
function clickDisplayLightning(cb) {
    createCookie('show_Lightning',cb.checked,2);
    window.location.reload();
}
function clickDisplayFires(cb) {
    createCookie('show_Fires',cb.checked,2);
    window.location.reload();
}
function unitdistance(selectObj) {
    var idx = selectObj.selectedIndex;
    var unit = selectObj.options[idx].value;
    document.cookie =  'unitdistance='+unit+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/';
}
function unitspeed(selectObj) {
    var idx = selectObj.selectedIndex;
    var unit = selectObj.options[idx].value;
    document.cookie =  'unitspeed='+unit+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/';
}
function unitaltitude(selectObj) {
    var idx = selectObj.selectedIndex;
    var unit = selectObj.options[idx].value;
    document.cookie =  'unitaltitude='+unit+'; expires=Thu, 2 Aug 2100 20:47:11 UTC; path=/';
}
<|endoftext|>


<commit_before>describe("shared object storage", () => {
  beforeEach(() => {
    cy.elektraLogin(
      Cypress.env("TEST_DOMAIN"),
      Cypress.env("TEST_USER"),
      Cypress.env("TEST_PASSWORD")
    )
  })

  it("open object storage and check create container button", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/`)
    cy.contains('[data-test=page-title]','Object Storage')
    cy.contains('a','Create container').click()
    cy.contains('Inside a project, objects are stored in containers. Containers are where you define access permissions and quotas.')
    cy.contains('button','Cancel').click()
  })

  it("open object storage and check access control and check ACLs button", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/containers?overlay=elektra-test%2Fshow_access_control`)
    cy.contains('Read ACLs')
    cy.contains('textarea','.rlistings')
    cy.contains('a','Check ACLs').click()
    cy.contains('valid token required: false')
  })

  it("open object storage and check elektra-test container", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/containers/elektra-test`)
    cy.contains('Object count')
    cy.contains('Metadata')
  })

  it("open object storage and elektra-test container and check actions", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/`)
    cy.contains('[data-test=page-title]','Object Storage')
    cy.contains('a','elektra-test').click()
    cy.contains('a','Create folder').click()
    cy.contains('Folder name')
    cy.contains('button','Cancel').click()
    cy.contains('a','Upload file').click()
    cy.contains('This dialog only accepts files smaller than 1 MiB. To upload larger files, please use a different client.')
    cy.contains('button','Cancel').click()
  })

  it("open elektra-test container directly and check item", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/containers/elektra-test/list`)
    cy.contains('[data-test=page-title]','Object Storage')
    cy.contains('a','amiga.jpg')
    cy.get('div.btn-group').click()
    cy.contains('a','Properties').click()
    cy.contains('File: amiga.jpg')
    cy.contains('button','Cancel').click()

    cy.get('div.btn-group').click()
    cy.contains('a','Copy').click()
    cy.contains('Copy object: amiga.jpg')
    cy.contains('button','Cancel').click()

    cy.get('div.btn-group').click()
    cy.contains('a','Move/Rename').click()
    cy.contains('Move and/or rename object: amiga.jpg')
    cy.contains('button','Cancel').click()
  })

})<commit_msg>fix object storage cypress tests<commit_after>describe("shared object storage", () => {
  beforeEach(() => {
    cy.elektraLogin(
      Cypress.env("TEST_DOMAIN"),
      Cypress.env("TEST_USER"),
      Cypress.env("TEST_PASSWORD")
    )
  })

  it("open object storage and check create container button", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/`)
    cy.contains("[data-test=page-title]", "Object Storage")
    cy.contains("a", "Create container").click()
    cy.contains(
      "Inside a project, objects are stored in containers. Containers are where you define access permissions and quotas."
    )
    cy.contains("button", "Cancel").click()
  })

  it("open object storage and check access control and check ACLs button", () => {
    cy.visit(
      `/${Cypress.env(
        "TEST_DOMAIN"
      )}/admin/object-storage/containers?overlay=elektra-test%2Fshow_access_control`
    )
    cy.contains("Read ACLs")
    cy.contains("a", "Check ACLs").click()
    cy.contains("No Read ACLs found")
  })

  it("open object storage and check elektra-test container", () => {
    cy.visit(
      `/${Cypress.env(
        "TEST_DOMAIN"
      )}/admin/object-storage/containers/elektra-test`
    )
    cy.contains("Object count")
    cy.contains("Metadata")
  })

  it("open object storage and elektra-test container and check actions", () => {
    cy.visit(`/${Cypress.env("TEST_DOMAIN")}/admin/object-storage/`)
    cy.contains("[data-test=page-title]", "Object Storage")
    cy.contains("a", "elektra-test").click()
    cy.contains("a", "Create folder").click()
    cy.contains("Folder name")
    cy.contains("button", "Cancel").click()
    cy.contains("a", "Upload file").click()
    cy.contains(
      "This dialog only accepts files smaller than 1 MiB. To upload larger files, please use a different client."
    )
    cy.contains("button", "Cancel").click()
  })

  it("open elektra-test container directly and check item", () => {
    cy.visit(
      `/${Cypress.env(
        "TEST_DOMAIN"
      )}/admin/object-storage/containers/elektra-test/list/this+is+a+test%252F`
    )
    cy.contains("[data-test=page-title]", "Object Storage")
    cy.contains("a", "docker.jpg")
    cy.get("div.btn-group").click()
    cy.contains("a", "Properties").click()
    cy.contains("File: this is a test/docker.jpg")
    cy.contains("button", "Cancel").click()

    cy.get("div.btn-group").click()
    cy.contains("a", "Copy").click()
    cy.contains("Copy object: this is a test/docker.jpg")
    cy.contains("button", "Cancel").click()

    cy.get("div.btn-group").click()
    cy.contains("a", "Move/Rename").click()
    cy.contains("Move and/or rename object: this is a test/docker.jpg")
    cy.contains("button", "Cancel").click()
  })
})
<|endoftext|>


<commit_before>angular.module('ui.bootstrap-slider', [])
	.directive('slider', ['$parse', '$timeout', function ($parse, $timeout) {
		return {
			restrict: 'AE',
			replace: true,
			template: '<input type="text" />',
			require: 'ngModel',
			link: function ($scope, element, attrs, ngModelCtrl) {
				$.fn.slider.Constructor.prototype.disable = function () {
					this.picker.off();
				};

				$.fn.slider.Constructor.prototype.enable = function () {
					this.picker.on();
				};

                                if (attrs.ngChange) {
                                        ngModelCtrl.$viewChangeListeners.push(function() {
                                                    $scope.$apply(attrs.ngChange);
                                        });
                                }

                                var options = {};
				if(attrs.sliderid) options.id = attrs.sliderid;
				if(attrs.min) options.min = parseFloat(attrs.min);
				if(attrs.max) options.max = parseFloat(attrs.max);
				if(attrs.step) options.step = parseFloat(attrs.step);
				if(attrs.precision) options.precision = parseFloat(attrs.precision);
				if(attrs.orientation) options.orientation = attrs.orientation;
				if(attrs.value) {
					if (angular.isNumber(attrs.value) || angular.isArray(attrs.value)) {
						options.value = attrs.value;
					} else if (angular.isString(attrs.value)) {
						if (attrs.value.indexOf("[") === 0) {
							options.value = angular.fromJson(attrs.value);
						} else {
							options.value = parseFloat(attrs.value);
						}
					}

				}
				if(attrs.range) options.range = attrs.range === 'true';
				if(attrs.selection) options.selection = attrs.selection;
				if(attrs.tooltip) options.tooltip = attrs.tooltip;
				if(attrs.tooltipseparator) options.tooltip_separator = attrs.tooltipseparator;
				if(attrs.tooltipsplit) options.tooltip_split = attrs.tooltipsplit === 'true';
				if(attrs.handle) options.handle = attrs.handle;
				if(attrs.reversed) options.reversed = attrs.reversed === 'true';
				if(attrs.enabled) options.enabled = attrs.enabled === 'true';
				if(attrs.naturalarrowkeys) options.natural_arrow_keys = attrs.naturalarrowkeys === 'true';
                if(attrs.formater) options.formater = $scope.$eval(attrs.formater);

				if (options.range && !options.value) {
					options.value = [0,0]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
				}

				var slider = $(element[0]).slider(options);
				var updateEvent = attrs.updateevent || 'slide';

				slider.on(updateEvent, function(ev) {
					ngModelCtrl.$setViewValue(ev.value);
					$timeout(function() {
						$scope.$apply();
					});
				});

				$scope.$watch(attrs.ngModel, function(value) {
					if(value || value === 0) {
						slider.slider('setValue', value, false);
					}
				});

				if (angular.isDefined(attrs.ngDisabled)) {
					$scope.$watch(attrs.ngDisabled, function(value) {
						if (value) {
							slider.slider('disable');
						} else {
							slider.slider('enable');
						}
					});
				}
			}
		};
	}])
;
<commit_msg>fix indentation bugfix: rename $.fn.slider.Constructor to $.fn.slider.constructor<commit_after>angular.module('ui.bootstrap-slider', [])
	.directive('slider', ['$parse', '$timeout', function($parse, $timeout) {
		return {
			restrict: 'AE',
			replace: true,
			template: '<input type="text" />',
			require: 'ngModel',
			link: function($scope, element, attrs, ngModelCtrl) {
				$.fn.slider.constructor.prototype.disable = function() {
					this.picker.off();
				};

				$.fn.slider.constructor.prototype.enable = function() {
					this.picker.on();
				};

				if (attrs.ngChange) {
					ngModelCtrl.$viewChangeListeners.push(function() {
						$scope.$apply(attrs.ngChange);
					});
				}

				var options = {};
				if (attrs.sliderid) options.id = attrs.sliderid;
				if (attrs.min) options.min = parseFloat(attrs.min);
				if (attrs.max) options.max = parseFloat(attrs.max);
				if (attrs.step) options.step = parseFloat(attrs.step);
				if (attrs.precision) options.precision = parseFloat(attrs.precision);
				if (attrs.orientation) options.orientation = attrs.orientation;
				if (attrs.value) {
					if (angular.isNumber(attrs.value) || angular.isArray(attrs.value)) {
						options.value = attrs.value;
					} else if (angular.isString(attrs.value)) {
						if (attrs.value.indexOf("[") === 0) {
							options.value = angular.fromJson(attrs.value);
						} else {
							options.value = parseFloat(attrs.value);
						}
					}

				}
				if (attrs.range) options.range = attrs.range === 'true';
				if (attrs.selection) options.selection = attrs.selection;
				if (attrs.tooltip) options.tooltip = attrs.tooltip;
				if (attrs.tooltipseparator) options.tooltip_separator = attrs.tooltipseparator;
				if (attrs.tooltipsplit) options.tooltip_split = attrs.tooltipsplit === 'true';
				if (attrs.handle) options.handle = attrs.handle;
				if (attrs.reversed) options.reversed = attrs.reversed === 'true';
				if (attrs.enabled) options.enabled = attrs.enabled === 'true';
				if (attrs.naturalarrowkeys) options.natural_arrow_keys = attrs.naturalarrowkeys === 'true';
				if (attrs.formater) options.formater = $scope.$eval(attrs.formater);

				if (options.range && !options.value) {
					options.value = [0, 0]; // This is needed, because of value defined at $.fn.slider.defaults - default value 5 prevents creating range slider
				}

				var slider = $(element[0]).slider(options);
				var updateEvent = attrs.updateevent || 'slide';

				slider.on(updateEvent, function(ev) {
					ngModelCtrl.$setViewValue(ev.value);
					$timeout(function() {
						$scope.$apply();
					});
				});

				$scope.$watch(attrs.ngModel, function(value) {
					if (value || value === 0) {
						slider.slider('setValue', value, false);
					}
				});

				if (angular.isDefined(attrs.ngDisabled)) {
					$scope.$watch(attrs.ngDisabled, function(value) {
						if (value) {
							slider.slider('disable');
						} else {
							slider.slider('enable');
						}
					});
				}
			}
		};
	}]);<|endoftext|>


<commit_before>import assert from "assert";
import { relative } from "path";
import { transformFromAst } from "babel-core";
import { files } from "./all-files.js";
import { parse } from "../lib/parsers/babylon.js";
import reifyPlugin from "babel-plugin-transform-es2015-modules-reify";
import es2015Preset from "babel-preset-es2015";

var filesToTest = Object.create(null);

Object.keys(files).forEach(function (absPath) {
  var code = files[absPath];
  var relPath = relative(__dirname, absPath);

  // These files fail to transform with es2015 preset due to problems
  // unrelated to the functionality of the Reify Babel plugin.
  if (relPath === "import-tests.js" ||
      relPath === "export-tests.js" ||
      relPath === "setter-tests.js" ||
      relPath === "export-some.js") {
    return;
  }

  // Files without import or export tokens don't need to be tested.
  if (! /\b(?:im|ex)port\b/.test(code)) {
    return;
  }

  filesToTest[relPath] = code;
});

describe("babel-plugin-transform-es2015-modules-reify", function () {
  function check(code, options) {
    var ast = parse(code);
    delete ast.tokens;
    var result = transformFromAst(ast, code, options);
    assert.ok(/\bmodule\.(?:importSync|export)\b/.test(result.code));
    return result;
  }

  Object.keys(filesToTest).forEach(function (relPath) {
    var code = filesToTest[relPath];

    it("compiles " + relPath, function () {
      check(code, {
        plugins: [reifyPlugin]
      });
    });

    it("compiles " + relPath + " with es2015", function () {
      check(code, {
        plugins: [reifyPlugin],
        presets: [es2015Preset]
      });
    });
  });
});
<commit_msg>Test Babel plugin with { generateLetDeclarations: true }.<commit_after>import assert from "assert";
import { relative } from "path";
import { transformFromAst } from "babel-core";
import { files } from "./all-files.js";
import { parse } from "../lib/parsers/babylon.js";
import reifyPlugin from "babel-plugin-transform-es2015-modules-reify";
import es2015Preset from "babel-preset-es2015";

var filesToTest = Object.create(null);

Object.keys(files).forEach(function (absPath) {
  var code = files[absPath];
  var relPath = relative(__dirname, absPath);

  // These files fail to transform with es2015 preset due to problems
  // unrelated to the functionality of the Reify Babel plugin.
  if (relPath === "import-tests.js" ||
      relPath === "export-tests.js" ||
      relPath === "setter-tests.js" ||
      relPath === "export-some.js") {
    return;
  }

  // Files without import or export tokens don't need to be tested.
  if (! /\b(?:im|ex)port\b/.test(code)) {
    return;
  }

  filesToTest[relPath] = code;
});

describe("babel-plugin-transform-es2015-modules-reify", function () {
  function check(code, options) {
    var ast = parse(code);
    delete ast.tokens;
    var result = transformFromAst(ast, code, options);
    assert.ok(/\bmodule\.(?:importSync|export)\b/.test(result.code));
    return result;
  }

  Object.keys(filesToTest).forEach(function (relPath) {
    var code = filesToTest[relPath];
    var plugins = [[reifyPlugin, {
      generateLetDeclarations: true
    }]];

    it("compiles " + relPath, function () {
      check(code, { plugins: plugins });
    });

    it("compiles " + relPath + " with es2015", function () {
      check(code, {
        plugins: plugins,
        presets: [es2015Preset]
      });
    });
  });
});
<|endoftext|>


<commit_before>/*
 *
 * Navbar
 *
 */

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
// import Drawer from 'material-ui/Drawer';
// import AppBar from 'material-ui/AppBar';

import SideNav from 'components/SideNav';
import TopNav from 'components/TopNav';

import { makeSelectWidth, makeSelectUser } from './selectors';
// import messages from './messages';

export class Navbar extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      collapseDrawer: false,
    };
    this.handleCollapseDrawer = this.handleCollapseDrawer.bind(this);

    this.expandedSideNavWidth = 140;
    this.collapsedSideNavWidth = 50;
    this.allowedRoutes = ['/', '/play'];
    // const MenuItems = [
    //   {
    //     primaryText: 'Latr',
    //   },
    //   {
    //     primaryText: 'Home',
    //   },
    //   {
    //     primaryText: 'Play',
    //   },
    // ];
  }

  handleCollapseDrawer() {
    this.setState({ collapseDrawer: !this.state.collapseDrawer });
  }

  render() {
    if (!this.allowedRoutes.includes(this.props.location) || !this.props.user) {
      return null;
    }
    if (this.props.width >= 960) {
      const expanded = this.props.width >= 1280 && !this.state.collapseDrawer;
      return (
        <SideNav
          avatar={this.props.user.avatar}
          expanded={expanded}
          handleCollapse={this.handleCollapseDrawer}
        />
      );
    }
    return <TopNav />;
  }
}

Navbar.propTypes = {
  // dispatch: PropTypes.func.isRequired,
  location: React.PropTypes.string,
  user: {
    avatar: PropTypes.string,
  },
  width: PropTypes.number,
};

const mapStateToProps = createStructuredSelector({
  // Navbar: makeSelectNavbar(),
  user: makeSelectUser(),
  width: makeSelectWidth(),
  // route: makeSelectRoute(),
});

function mapDispatchToProps(dispatch) {
  return {
    dispatch,
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(Navbar);
<commit_msg>fix prop type<commit_after>/*
 *
 * Navbar
 *
 */

import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
// import Drawer from 'material-ui/Drawer';
// import AppBar from 'material-ui/AppBar';

import SideNav from 'components/SideNav';
import TopNav from 'components/TopNav';

import { makeSelectWidth, makeSelectUser } from './selectors';
// import messages from './messages';

export class Navbar extends React.PureComponent { // eslint-disable-line react/prefer-stateless-function
  constructor(props) {
    super(props);
    this.state = {
      collapseDrawer: false,
    };
    this.handleCollapseDrawer = this.handleCollapseDrawer.bind(this);

    this.expandedSideNavWidth = 140;
    this.collapsedSideNavWidth = 50;
    this.allowedRoutes = ['/', '/play'];
    // const MenuItems = [
    //   {
    //     primaryText: 'Latr',
    //   },
    //   {
    //     primaryText: 'Home',
    //   },
    //   {
    //     primaryText: 'Play',
    //   },
    // ];
  }

  handleCollapseDrawer() {
    this.setState({ collapseDrawer: !this.state.collapseDrawer });
  }

  render() {
    if (!this.allowedRoutes.includes(this.props.location) || !this.props.user) {
      return null;
    }
    if (this.props.width >= 960) {
      const expanded = this.props.width >= 1280 && !this.state.collapseDrawer;
      return (
        <SideNav
          avatar={this.props.user.avatar}
          expanded={expanded}
          handleCollapse={this.handleCollapseDrawer}
        />
      );
    }
    return <TopNav />;
  }
}

Navbar.propTypes = {
  // dispatch: PropTypes.func.isRequired,
  location: React.PropTypes.string,
  user: React.PropTypes.objectOf(PropTypes.string),
  width: PropTypes.number,
};

const mapStateToProps = createStructuredSelector({
  // Navbar: makeSelectNavbar(),
  user: makeSelectUser(),
  width: makeSelectWidth(),
  // route: makeSelectRoute(),
});

function mapDispatchToProps(dispatch) {
  return {
    dispatch,
  };
}

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


<commit_before>// ==========================================================================
//                            DG.PlotUtilities
//
//  DG.PlotUtilities is comprised of functions generally useful in plots.
//
//  Copyright (c) 2018 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

/**
 * PlotCaseArray functions _like_ an array of cases, but the order is determined by a mapping of indices.
 */

DG.PlotUtilities.PlotCaseArray = SC.Object.extend( {
  /**
   * @property [DG.Case]
   */
  _cases: null,
  /**
   * @property [Number]
   */
  _map: null,

  init: function() {
    sc_super();
    this._cases = this._cases || [];
    this._map = this._map || [];
  },

  length: function() {
    return this._cases.length;
  }.property( '_cases'),

  at: function( iIndex) {
    return this._cases[this._map[iIndex]];
  },

  /**
   * Return the case at the given index in the original array
   * @param iIndex {Number}
   * @return {DG.Case}
   */
  unorderedAt: function( iIndex) {
    return this._cases[iIndex];
  },

  push: function( iCase) {
    this._cases.push( iCase);
    this._map.push( this._cases.length - 1);
  },

  indexOf: function( iCase) {
    return this._cases.indexOf( iCase);
  },

  forEach: function( iDoF) {
    this._map.forEach( function( iMapValue, iIndex) {
      iDoF( this._cases[iMapValue], iMapValue, iIndex);
    }.bind( this));
  },

  forEachWithInvokeLater: function( iDoF, iEndF) {
    var tLoopIndex = 0,
        tNumCases = this._cases.length,
        // Get a bit happening early with two iterations.
        tFirstIncrement = Math.min(200, tNumCases / 20),
        tCountdown = (tNumCases > 1000) ? 5 : 0,
        tIncrement = tNumCases - tCountdown * tFirstIncrement,
        tContinue = true,

        loop = function () {
          var tStopIndex = tLoopIndex + (tCountdown > 0 ? tFirstIncrement : tIncrement);
          tCountdown--;
          if (tLoopIndex < tNumCases) {
            for (; tContinue && tLoopIndex < tNumCases && tLoopIndex < tStopIndex; tLoopIndex++) {
              if (iDoF)
                tContinue = iDoF(this.at(tLoopIndex), tLoopIndex, tLoopIndex === tNumCases - 1);
            }
            if (tContinue)
              this.invokeLater(loop, 100);
          }
          else {
            if (iEndF)
              iEndF();
          }
        }.bind(this);

    loop();
  },

  map: function( iTransF) {
    var tResult = DG.PlotUtilities.PlotCaseArray.create();
    this.forEach( function( iCase, iMapIndex) {
        tResult._cases[ iMapIndex] = iTransF( iCase, iMapIndex);
        tResult._map.push( iMapIndex);
      });
    return tResult;
  },

  filter: function( iBoolF) {
    var tResult = DG.PlotUtilities.PlotCaseArray.create();
    this.forEach( function( iCase, iMapIndex) {
      if( iBoolF( iCase, iMapIndex)) {
        tResult._cases[ iMapIndex] = iCase;
        tResult._map.push( iMapIndex);
      }
    }.bind( this));
    return tResult;
  },

  reduce: function( iReduceFunc, accumulator) {
    return this._cases.reduce(iReduceFunc, accumulator);
  },

  toArray: function() {
    return this._cases.slice();
  }
});<commit_msg>[#161137421] Bug fix: Adding legend attribute in graph should not cause points to move around<commit_after>// ==========================================================================
//                            DG.PlotUtilities
//
//  DG.PlotUtilities is comprised of functions generally useful in plots.
//
//  Copyright (c) 2018 by The Concord Consortium, Inc. All rights reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// ==========================================================================

/**
 * PlotCaseArray functions _like_ an array of cases, but the order is determined by a mapping of indices.
 */

DG.PlotUtilities.PlotCaseArray = SC.Object.extend( {
  /**
   * @property [DG.Case]
   */
  _cases: null,
  /**
   * @property [Number]
   */
  _map: null,

  init: function() {
    sc_super();
    this._cases = this._cases || [];
    this._map = this._map || [];
  },

  length: function() {
    return this._cases.length;
  }.property( '_cases'),

  at: function( iIndex) {
    return this._cases[this._map[iIndex]];
  },

  /**
   * Return the case at the given index in the original array
   * @param iIndex {Number}
   * @return {DG.Case}
   */
  unorderedAt: function( iIndex) {
    return this._cases[iIndex];
  },

  push: function( iCase) {
    this._cases.push( iCase);
    this._map.push( this._cases.length - 1);
  },

  indexOf: function( iCase) {
    return this._cases.indexOf( iCase);
  },

  forEach: function( iDoF) {
    this._map.forEach( function( iMapValue, iIndex) {
      iDoF( this._cases[iMapValue], iMapValue, iIndex);
    }.bind( this));
  },

  forEachWithInvokeLater: function( iDoF, iEndF) {
    var tLoopIndex = 0,
        tNumCases = this._cases.length,
        // Get a bit happening early with two iterations.
        tFirstIncrement = Math.min(200, tNumCases / 20),
        tCountdown = (tNumCases > 1000) ? 5 : 0,
        tIncrement = tNumCases - tCountdown * tFirstIncrement,
        tContinue = true,

        loop = function () {
          var tStopIndex = tLoopIndex + (tCountdown > 0 ? tFirstIncrement : tIncrement);
          tCountdown--;
          if (tLoopIndex < tNumCases) {
            for (; tContinue && tLoopIndex < tNumCases && tLoopIndex < tStopIndex; tLoopIndex++) {
              if (iDoF)
                tContinue = iDoF(this.at(tLoopIndex), this._map[ tLoopIndex],
                    tLoopIndex === tNumCases - 1);
            }
            if (tContinue)
              this.invokeLater(loop, 100);
          }
          else {
            if (iEndF)
              iEndF();
          }
        }.bind(this);

    loop();
  },

  map: function( iTransF) {
    var tResult = DG.PlotUtilities.PlotCaseArray.create();
    this.forEach( function( iCase, iMapIndex) {
        tResult._cases[ iMapIndex] = iTransF( iCase, iMapIndex);
        tResult._map.push( iMapIndex);
      });
    return tResult;
  },

  filter: function( iBoolF) {
    var tResult = DG.PlotUtilities.PlotCaseArray.create();
    this.forEach( function( iCase, iMapIndex) {
      if( iBoolF( iCase, iMapIndex)) {
        tResult._cases[ iMapIndex] = iCase;
        tResult._map.push( iMapIndex);
      }
    }.bind( this));
    return tResult;
  },

  reduce: function( iReduceFunc, accumulator) {
    return this._cases.reduce(iReduceFunc, accumulator);
  },

  toArray: function() {
    return this._cases.slice();
  }
});<|endoftext|>