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

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

import Dropdown from '../Dropdown';
import Tree from '../Tree';
import Theme from '../Theme';
import TextField from '../TextField';

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

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

class TreeSelect extends Component {

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

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.dropdown = createRef();
        this.dropdownInstance = null;
        this.filter = createRef();

        this.state = {
            filter: '',
            value: props.value,
            popupVisible: false,
            path: props.selectMode === SelectMode.SINGLE_SELECT ?
                TreeCalculation.calPath(props.value, props.data, props) : undefined
        };

    }

    /**
     * public
     */
    startRipple = (e, props) => {
        this.dropdownInstance && this.dropdownInstance.startRipple(e, props);
    };

    /**
     * public
     */
    endRipple = () => {
        this.dropdownInstance && this.dropdownInstance.endRipple();
    };

    /**
     * public
     */
    triggerRipple = (e, props) => {
        this.dropdownInstance && this.dropdownInstance.triggerRipple(e, props);
    };

    /**
     * public
     */
    resetPopupPosition = () => {
        this.dropdownInstance && this.dropdownInstance.resetPosition();
    };

    /**
     * public
     */
    openPopup = () => {
        this.dropdownInstance && this.dropdownInstance.openPopup();
    };

    /**
     * public
     */
    closePopup = () => {
        this.dropdownInstance && this.dropdownInstance.closePopup();
    };

    getTriggerValue = (props = this.props) => {

        const {data, selectMode, placeholder, triggerRenderer, renderer, displayField, valueField} = props,
            {value, path} = this.state,
            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        if (triggerRenderer) {
            return typeof triggerRenderer === 'function' ? triggerRenderer(value, path) : triggerRenderer;
        }

        if (!value) {
            return placeholder;
        }

        if (isMultiSelect) {
            return value.length > 0 ?
                value.length + ' selected'
                :
                placeholder;
        }

        let result = [];

        function addNode(node, i) {
            result.push(
                renderer ?

                        {renderer(node, path && path.slice(0, i + 1))}

                    :
                    Util.getTextByDisplayField(node, displayField, valueField)
            );
        }

        addNode(data, -1);

        if (path) {
            for (let i = 0, len = path.length; i < len; i++) {

                result.push(

                );

                addNode(path[i].node, i);

            }
        }

        return result;

    };

    handleNodeSelect = (value, path) => {

        if (this.props.selectMode !== SelectMode.SINGLE_SELECT) {
            return;
        }

        this.setState({
            path
        });

    };

    handleChange = value => {

        const {autoClose} = this.props;
        if (autoClose) {
            this.closePopup();
        }

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

    };

    handlePopupOpen = e => {

        const {useFilter, onOpenPopup} = this.props;

        if (useFilter) {
            this.filter && this.filter.current && this.filter.current.focus();
        }

        onOpenPopup && onOpenPopup(e);

    };

    handlePopupClosed = e => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup} = this.props;
            onClosePopup && onClosePopup(e);
        });
    };

    handleFilterChange = filter => {
        this.setState({
            filter
        }, () => {
            this.dropdownInstance && this.dropdownInstance.resetPopupPosition();
        });
    };

    handleSelectAllClick = () => {

        const {data} = this.props,
            {value} = this.state;

        if (value && value.length > 0 && value.length === this.total) {
            this.handleChange([]);
            return;
        }

        let result = [];
        TreeCalculation.addRecursiveValue(isArray(data) ? {children: data} : data, result, this.props);
        this.handleChange(TreeCalculation.updateValue(result, this.props));

    };

    isEmpty = (filter = this.state.filter, data = this.props.data) => {

        if (!filter) {
            return !data;
        }

        const {displayField} = this.props;
        let result = true;

        Util.preOrderTraverse(isArray(data) ? {[VirtualRoot]: true, children: data} : data, node => {
            if (node && !!node[displayField]
                && node[displayField].toString().toUpperCase().includes(filter.toUpperCase())) {
                return result = false;
            }
        });

        return result;

    };

    componentDidMount() {
        this.dropdownInstance = this.dropdown && this.dropdown.current;
    }

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

    render() {

        const {

                className, triggerClassName, popupClassName, style, name, data, popupTheme, renderer,
                selectMode, valueField, displayField, descriptionField, triggerRenderer,
                useFilter, filterIconCls, useSelectAll, selectAllText, isSelectRecursive, allowCollapse, collapsed,
                indentWidth,
                onNodeClick, popupChildren, noMatchedMsg,
                collapsedIconCls, expandedIconCls, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                // not passing down these props
                onChange,

                ...restProps

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

            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        this.total = TreeCalculation.getTotalCount(data);

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <Dropdown {...restProps}
                          ref={this.dropdown}
                          triggerClassName={classNames({
                              activated: popupVisible,
                              empty: !triggerRenderer && (!value || value.length < 1),
                              [triggerClassName]: triggerClassName
                          })}
                          popupClassName={classNames('tree-select-popup', {
                              [popupClassName]: popupClassName
                          })}
                          popupTheme={popupTheme}
                          triggerValue={this.getTriggerValue()}
                          onOpenPopup={this.handlePopupOpen}
                          onClosePopup={this.handlePopupClosed}>

                        {
                            useFilter ?
                                <TextField ref={this.filter}
                                           className="tree-select-filter"
                                           value={filter}
                                           rightIconCls={filterIconCls}
                                           onChange={this.handleFilterChange}/>
                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?
                                <div className="tree-node tree-select-all-wrapper"
                                     style={{padding: `0 ${indentWidth}px`}}
                                     onClick={this.handleSelectAllClick}>

                                        <Checkbox className="tree-node-select"
                                                  checked={value && value.length === this.total}
                                                  indeterminate={value && value.length > 0 && value.length < this.total}
                                                  uncheckedIconCls={checkboxUncheckedIconCls}
                                                  checkedIconCls={checkboxCheckedIconCls}
                                                  indeterminateIconCls={checkboxIndeterminateIconCls}/>
                                        {selectAllText}

                                :
                                null
                        }

                        {
                            useFilter ?

                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?

                                :
                                null
                        }

                        {
                            this.isEmpty() ?

                                    {
                                        noMatchedMsg ?
                                            noMatchedMsg
                                            :

                                                No matched value.

                                    }

                                :
                                <Tree className="tree-select-list"
                                      theme={popupTheme}
                                      selectMode={selectMode}
                                      data={data}
                                      filter={filter}
                                      value={value}
                                      valueField={valueField}
                                      displayField={displayField}
                                      descriptionField={descriptionField}
                                      isSelectRecursive={isSelectRecursive}
                                      allowCollapse={allowCollapse}
                                      collapsed={collapsed}
                                      indentWidth={indentWidth}
                                      collapsedIconCls={collapsedIconCls}
                                      expandedIconCls={expandedIconCls}
                                      radioUncheckedIconCls={radioUncheckedIconCls}
                                      radioCheckedIconCls={radioCheckedIconCls}
                                      checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                                      checkboxCheckedIconCls={checkboxCheckedIconCls}
                                      checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                                      renderer={renderer}
                                      onNodeClick={onNodeClick}
                                      onNodeSelect={this.handleNodeSelect}
                                      onChange={this.handleChange}/>
                        }

                    {popupChildren}

                </Dropdown>

        );

    }
}

TreeSelect.propTypes = {

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

    /**
     * The CSS class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

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

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

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

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

    title: PropTypes.string,
    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),
    triggerValue: PropTypes.string,
    rightIconCls: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the tree node.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the tree node.
         */
        style: PropTypes.object,

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

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

        /**
         * The tree node's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

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

        /**
         * If true,the tree node will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: 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,

        /**
         * The message of tip.
         */
        title: PropTypes.string,

        children: PropTypes.array,

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

        /**
         * Callback function fired when a tree node touch-tapped.
         */
        onClick: PropTypes.func

    }), PropTypes.array]),

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

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

    /**
     * The select mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

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

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    useFilter: PropTypes.bool,
    filterIconCls: PropTypes.string,
    useSelectAll: PropTypes.bool,
    selectAllText: PropTypes.string,
    noMatchedMsg: PropTypes.string,
    isSelectRecursive: PropTypes.bool,
    allowCollapse: PropTypes.bool,
    collapsed: PropTypes.bool,
    autoPopupWidth: PropTypes.bool,
    collapsedIconCls: PropTypes.string,
    expandedIconCls: PropTypes.string,
    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    popupChildren: PropTypes.any,

    resetPopPositionWait: PropTypes.number,
    indentWidth: PropTypes.number,

    renderer: PropTypes.func,

    triggerRenderer: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.func]),

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onNodeClick: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func,

    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onOpenPopup: PropTypes.func

};

TreeSelect.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    placeholder: 'Please select ...',
    rightIconCls: 'fas fa-angle-down',
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,
    tipPosition: Position.BOTTOM,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    autoClose: true,
    useFilter: false,
    filterIconCls: 'fas fa-search',
    useSelectAll: false,
    selectAllText: 'Select All',

    isSelectRecursive: false,
    allowCollapse: true,
    collapsed: false,
    autoPopupWidth: true,
    resetPopPositionWait: 250,
    indentWidth: 20

};

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

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

import Dropdown from '../Dropdown';
import Tree from '../Tree';
import Theme from '../Theme';
import TextField from '../TextField';

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

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

class TreeSelect extends Component {

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

    constructor(props, ...restArgs) {

        super(props, ...restArgs);

        this.dropdown = createRef();
        this.dropdownInstance = null;
        this.filter = createRef();

        this.state = {
            filter: '',
            value: props.value,
            popupVisible: false,
            path: props.selectMode === SelectMode.SINGLE_SELECT ?
                TreeCalculation.calPath(props.value, props.data, props) : undefined
        };

    }

    /**
     * public
     */
    startRipple = (e, props) => {
        this.dropdownInstance && this.dropdownInstance.startRipple(e, props);
    };

    /**
     * public
     */
    endRipple = () => {
        this.dropdownInstance && this.dropdownInstance.endRipple();
    };

    /**
     * public
     */
    triggerRipple = (e, props) => {
        this.dropdownInstance && this.dropdownInstance.triggerRipple(e, props);
    };

    /**
     * public
     */
    resetPopupPosition = () => {
        this.dropdownInstance && this.dropdownInstance.resetPosition();
    };

    /**
     * public
     */
    openPopup = () => {
        this.dropdownInstance && this.dropdownInstance.openPopup();
    };

    /**
     * public
     */
    closePopup = () => {
        this.dropdownInstance && this.dropdownInstance.closePopup();
    };

    getTriggerValue = (props = this.props) => {

        const {data, selectMode, placeholder, triggerRenderer, renderer, displayField, valueField} = props,
            {value, path} = this.state,
            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        if (triggerRenderer) {
            return typeof triggerRenderer === 'function' ? triggerRenderer(value, path) : triggerRenderer;
        }

        if (!value) {
            return placeholder;
        }

        if (isMultiSelect) {
            return value.length > 0 ?
                value.length + ' selected'
                :
                placeholder;
        }

        let result = [];

        function addNode(node, i) {
            result.push(
                renderer ?

                        {renderer(node, path && path.slice(0, i + 1))}

                    :
                    Util.getTextByDisplayField(node, displayField, valueField)
            );
        }

        addNode(data, -1);

        if (path) {
            for (let i = 0, len = path.length; i < len; i++) {

                result.push(

                );

                addNode(path[i].node, i);

            }
        }

        return result;

    };

    handleNodeSelect = (value, path) => {

        if (this.props.selectMode !== SelectMode.SINGLE_SELECT) {
            return;
        }

        this.setState({
            path
        });

    };

    handleChange = value => {

        const {autoClose} = this.props;
        if (autoClose) {
            this.closePopup();
        }

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

    };

    handlePopupOpen = e => {

        const {useFilter, onOpenPopup} = this.props;

        if (useFilter) {
            this.filter && this.filter.current && this.filter.current.focus();
        }

        onOpenPopup && onOpenPopup(e);

    };

    handlePopupClosed = e => {
        this.setState({
            popupVisible: false
        }, () => {
            const {onClosePopup} = this.props;
            onClosePopup && onClosePopup(e);
        });
    };

    handleFilterChange = filter => {
        this.setState({
            filter
        }, () => {
            this.dropdownInstance && this.dropdownInstance.resetPopupPosition();
        });
    };

    handleSelectAllClick = () => {

        const {data} = this.props,
            {value} = this.state;

        if (value && value.length > 0 && value.length === this.total) {
            this.handleChange([]);
            return;
        }

        let result = [];
        TreeCalculation.addRecursiveValue(isArray(data) ? {children: data} : data, result, this.props);
        this.handleChange(TreeCalculation.updateValue(result, this.props));

    };

    isEmpty = (filter = this.state.filter, data = this.props.data) => {

        if (!filter) {
            return !data;
        }

        const {displayField} = this.props;
        let result = true;

        Util.preOrderTraverse(isArray(data) ? {[VirtualRoot]: true, children: data} : data, node => {
            if (node && !!node[displayField]
                && node[displayField].toString().toUpperCase().includes(filter.toUpperCase())) {
                return result = false;
            }
        });

        return result;

    };

    componentDidMount() {
        this.dropdownInstance = this.dropdown && this.dropdown.current;
    }

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

    render() {

        const {

                className, triggerClassName, popupClassName, style, name, data, popupTheme, renderer,
                selectMode, valueField, displayField, descriptionField, triggerRenderer,
                useFilter, filterIconCls, filterPlaceholder, useSelectAll, selectAllText, isSelectRecursive,
                allowCollapse, collapsed, indentWidth,
                onNodeClick, popupChildren, noMatchedMsg,
                collapsedIconCls, expandedIconCls, radioUncheckedIconCls, radioCheckedIconCls,
                checkboxUncheckedIconCls, checkboxCheckedIconCls, checkboxIndeterminateIconCls,

                // not passing down these props
                onChange,

                ...restProps

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

            isMultiSelect = selectMode === SelectMode.MULTI_SELECT;

        this.total = TreeCalculation.getTotalCount(data);

        return (

                {
                    name ?
                        <input type="hidden"
                               name={name}
                               value={Util.getValueByValueField(value, valueField, displayField)}/>
                        :
                        null
                }

                <Dropdown {...restProps}
                          ref={this.dropdown}
                          triggerClassName={classNames({
                              activated: popupVisible,
                              empty: !triggerRenderer && (!value || value.length < 1),
                              [triggerClassName]: triggerClassName
                          })}
                          popupClassName={classNames('tree-select-popup', {
                              [popupClassName]: popupClassName
                          })}
                          popupTheme={popupTheme}
                          triggerValue={this.getTriggerValue()}
                          onOpenPopup={this.handlePopupOpen}
                          onClosePopup={this.handlePopupClosed}>

                        {
                            useFilter ?
                                <TextField ref={this.filter}
                                           className="tree-select-filter"
                                           value={filter}
                                           placeholder={filterPlaceholder}
                                           rightIconCls={filterIconCls}
                                           onChange={this.handleFilterChange}/>
                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?
                                <div className="tree-node tree-select-all-wrapper"
                                     style={{padding: `0 ${indentWidth}px`}}
                                     onClick={this.handleSelectAllClick}>

                                        <Checkbox className="tree-node-select"
                                                  checked={value && value.length === this.total}
                                                  indeterminate={value && value.length > 0 && value.length < this.total}
                                                  uncheckedIconCls={checkboxUncheckedIconCls}
                                                  checkedIconCls={checkboxCheckedIconCls}
                                                  indeterminateIconCls={checkboxIndeterminateIconCls}/>
                                        {selectAllText}

                                :
                                null
                        }

                        {
                            useFilter ?

                                :
                                null
                        }

                        {
                            isMultiSelect && useSelectAll ?

                                :
                                null
                        }

                        {
                            this.isEmpty() ?

                                    {
                                        noMatchedMsg ?
                                            noMatchedMsg
                                            :

                                                No matched value.

                                    }

                                :
                                <Tree className="tree-select-list"
                                      theme={popupTheme}
                                      selectMode={selectMode}
                                      data={data}
                                      filter={filter}
                                      value={value}
                                      valueField={valueField}
                                      displayField={displayField}
                                      descriptionField={descriptionField}
                                      isSelectRecursive={isSelectRecursive}
                                      allowCollapse={allowCollapse}
                                      collapsed={collapsed}
                                      indentWidth={indentWidth}
                                      collapsedIconCls={collapsedIconCls}
                                      expandedIconCls={expandedIconCls}
                                      radioUncheckedIconCls={radioUncheckedIconCls}
                                      radioCheckedIconCls={radioCheckedIconCls}
                                      checkboxUncheckedIconCls={checkboxUncheckedIconCls}
                                      checkboxCheckedIconCls={checkboxCheckedIconCls}
                                      checkboxIndeterminateIconCls={checkboxIndeterminateIconCls}
                                      renderer={renderer}
                                      onNodeClick={onNodeClick}
                                      onNodeSelect={this.handleNodeSelect}
                                      onChange={this.handleChange}/>
                        }

                    {popupChildren}

                </Dropdown>

        );

    }
}

TreeSelect.propTypes = {

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

    /**
     * The CSS class name of the trigger element.
     */
    triggerClassName: PropTypes.string,

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

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

    /**
     * The name of the dropDownSelect.
     */
    name: PropTypes.string,

    /**
     * The value of the dropDownSelect.
     */
    value: PropTypes.any,

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

    title: PropTypes.string,
    tip: PropTypes.string,
    tipPosition: PropTypes.oneOf(Util.enumerateValue(Position)),
    triggerValue: PropTypes.string,
    rightIconCls: PropTypes.string,

    /**
     * The options data.
     */
    data: PropTypes.oneOfType([PropTypes.shape({

        /**
         * The CSS class name of the tree node.
         */
        className: PropTypes.string,

        /**
         * Override the styles of the tree node.
         */
        style: PropTypes.object,

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

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

        /**
         * The tree node's display text. Type can be string, number or bool.
         */
        text: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),

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

        /**
         * If true,the tree node will be disabled.
         */
        disabled: PropTypes.bool,

        /**
         * If true,the button will be have loading effect.
         */
        isLoading: 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,

        /**
         * The message of tip.
         */
        title: PropTypes.string,

        children: PropTypes.array,

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

        /**
         * Callback function fired when a tree node touch-tapped.
         */
        onClick: PropTypes.func

    }), PropTypes.array]),

    /**
     * The invalid message of dropDownSelect.
     */
    invalidMsg: PropTypes.string,

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

    /**
     * The select mode of listItem.Can be normal,checkbox.
     */
    selectMode: PropTypes.oneOf(Util.enumerateValue(SelectMode)),

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

    /**
     * The message of the dropDownSelect.
     */
    infoMsg: PropTypes.string,

    /**
     * Use this function to format the options's text.
     */
    textFormat: PropTypes.func,

    /**
     * If true,the drop-down box automatically closed after selection.
     */
    autoClose: PropTypes.bool,

    useFilter: PropTypes.bool,
    filterIconCls: PropTypes.string,
    filterPlaceholder: PropTypes.string,
    useSelectAll: PropTypes.bool,
    selectAllText: PropTypes.string,
    noMatchedMsg: PropTypes.string,
    isSelectRecursive: PropTypes.bool,
    allowCollapse: PropTypes.bool,
    collapsed: PropTypes.bool,
    autoPopupWidth: PropTypes.bool,
    collapsedIconCls: PropTypes.string,
    expandedIconCls: PropTypes.string,
    radioUncheckedIconCls: PropTypes.string,
    radioCheckedIconCls: PropTypes.string,
    checkboxUncheckedIconCls: PropTypes.string,
    checkboxCheckedIconCls: PropTypes.string,
    checkboxIndeterminateIconCls: PropTypes.string,

    popupChildren: PropTypes.any,

    resetPopPositionWait: PropTypes.number,
    indentWidth: PropTypes.number,

    renderer: PropTypes.func,

    triggerRenderer: PropTypes.oneOfType([PropTypes.number, PropTypes.string, PropTypes.func]),

    /**
     * Callback function fired when the button is touch-tapped.
     */
    onNodeClick: PropTypes.func,

    /**
     * Callback function fired when the popup is closed.
     */
    onClosePopup: PropTypes.func,

    /**
     * Callback function fired when a menu item is selected.
     */
    onChange: PropTypes.func,

    onFocus: PropTypes.func,
    onBlur: PropTypes.func,
    onMouseOver: PropTypes.func,
    onMouseOut: PropTypes.func,
    onOpenPopup: PropTypes.func

};

TreeSelect.defaultProps = {

    theme: Theme.DEFAULT,
    popupTheme: Theme.DEFAULT,

    placeholder: 'Please select ...',
    rightIconCls: 'fas fa-angle-down',
    disabled: false,
    selectMode: SelectMode.SINGLE_SELECT,
    tipPosition: Position.BOTTOM,

    valueField: 'value',
    displayField: 'text',
    descriptionField: 'desc',

    autoClose: true,
    useFilter: false,
    filterIconCls: 'fas fa-search',
    filterPlaceholder: 'Search ...',
    useSelectAll: false,
    selectAllText: 'Select All',

    isSelectRecursive: false,
    allowCollapse: true,
    collapsed: false,
    autoPopupWidth: true,
    resetPopPositionWait: 250,
    indentWidth: 20

};

export default TreeSelect;
<|endoftext|>


<commit_before>"use strict";

var CityTour = CityTour || {};
CityTour.Scene = CityTour.Scene || {};

CityTour.Scene.BuildingGeometryBuilder = function() {
  var buildMaterials = function() {
    var i;
    var random;
    var r, g, b;
    var buildingMaterials = [];

    for (i = 0; i < CityTour.Config.MAX_BUILDING_MATERIALS; i++) {
      random = Math.random() * 0.7;
      r = random;
      g = random;
      b = random;

      buildingMaterials.push(new THREE.MeshLambertMaterial({ color: new THREE.Color(r, g, b), }));
    }

    return buildingMaterials;
  };

  var buildEmptyGeometriesForBuildings = function() {
    var i;
    var buildingGeometries = [];

    for (i = 0; i < CityTour.Config.MAX_BUILDING_MATERIALS; i++) {
      buildingGeometries.push(new THREE.Geometry());
    }

    return buildingGeometries;
  };

  var generateBuildingGeometries = function(buildings, buildingGeometries) {
    var HALF_STREET_WIDTH = CityTour.Config.STREET_WIDTH / 2;
    var HALF_STREET_DEPTH = CityTour.Config.STREET_DEPTH / 2;
    var MIN_STORIES_FOR_ANTENNA = 25;
    var PROBABILITY_OF_TALL_BUILDING_ANTENNA = 0.3;

    var mapX, mapZ, sceneX, sceneZ;
    var block;
    var storyHeight, buildingHeight;
    var materialIndex;

    var mapLotXMidpoint, mapLotZMidpoint;

    var reusableBuildingMesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1));
    var cylinderMesh;

    for (mapX = -CityTour.Config.HALF_BLOCK_COLUMNS; mapX < CityTour.Config.HALF_BLOCK_COLUMNS; mapX++) {
      sceneX = CityTour.Coordinates.mapXToSceneX(mapX) + HALF_STREET_WIDTH;

      for (mapZ = -CityTour.Config.HALF_BLOCK_ROWS; mapZ < CityTour.Config.HALF_BLOCK_ROWS; mapZ++) {
        sceneZ = CityTour.Coordinates.mapZToSceneZ(mapZ) + HALF_STREET_DEPTH;

        block = buildings.blockAtCoordinates(mapX, mapZ) || [];

        block.forEach(function(lot) {
          storyHeight = ((CityTour.Config.MAX_STORY_HEIGHT - CityTour.Config.MIN_STORY_HEIGHT) * Math.random()) + CityTour.Config.MIN_STORY_HEIGHT;
          buildingHeight = storyHeight * lot.stories + (lot.ySurface - lot.yFloor);

          reusableBuildingMesh.scale.x = lot.dimensions.width * CityTour.Config.BLOCK_WIDTH;
          reusableBuildingMesh.position.x = sceneX + (CityTour.Config.BLOCK_WIDTH * lot.dimensions.midpointX);

          reusableBuildingMesh.scale.y = buildingHeight;
          reusableBuildingMesh.position.y = (buildingHeight / 2) + lot.yFloor;

          reusableBuildingMesh.scale.z = lot.dimensions.depth * CityTour.Config.BLOCK_DEPTH;
          reusableBuildingMesh.position.z = sceneZ + (CityTour.Config.BLOCK_DEPTH * lot.dimensions.midpointZ);

          reusableBuildingMesh.updateMatrix();

          materialIndex = Math.floor(Math.random() * CityTour.Config.MAX_BUILDING_MATERIALS);
          buildingGeometries[materialIndex].merge(reusableBuildingMesh.geometry, reusableBuildingMesh.matrix);

          // Add antenna to tall buildings
          if (lot.stories > MIN_STORIES_FOR_ANTENNA && (Math.random() < PROBABILITY_OF_TALL_BUILDING_ANTENNA)) {
            cylinderMesh = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.2, 10, 4));
            cylinderMesh.position.x = sceneX + (CityTour.Config.BLOCK_WIDTH * lot.dimensions.midpointX);
            cylinderMesh.position.y = lot.yFloor + buildingHeight + 5;
            cylinderMesh.position.z = sceneZ + (CityTour.Config.BLOCK_DEPTH * lot.dimensions.midpointZ);
            cylinderMesh.updateMatrix();
            buildingGeometries[materialIndex].merge(cylinderMesh.geometry, cylinderMesh.matrix);
          }
        });
      }
    }
  };

  var buildingGeometryBuilder = {};

  buildingGeometryBuilder.build = function(buildings) {
    var i;
    var buildingMaterials = buildMaterials();
    var buildingGeometries = buildEmptyGeometriesForBuildings();
    var buildingMeshes = [];

    generateBuildingGeometries(buildings, buildingGeometries);

    for (i = 0; i < CityTour.Config.MAX_BUILDING_MATERIALS; i++) {
      buildingMeshes.push(new THREE.Mesh(buildingGeometries[i], buildingMaterials[i]));
    }

    return buildingMeshes;
  };

  return buildingGeometryBuilder;
};
<commit_msg>Removing unused variables<commit_after>"use strict";

var CityTour = CityTour || {};
CityTour.Scene = CityTour.Scene || {};

CityTour.Scene.BuildingGeometryBuilder = function() {
  var buildMaterials = function() {
    var i;
    var random;
    var r, g, b;
    var buildingMaterials = [];

    for (i = 0; i < CityTour.Config.MAX_BUILDING_MATERIALS; i++) {
      random = Math.random() * 0.7;
      r = random;
      g = random;
      b = random;

      buildingMaterials.push(new THREE.MeshLambertMaterial({ color: new THREE.Color(r, g, b), }));
    }

    return buildingMaterials;
  };

  var buildEmptyGeometriesForBuildings = function() {
    var i;
    var buildingGeometries = [];

    for (i = 0; i < CityTour.Config.MAX_BUILDING_MATERIALS; i++) {
      buildingGeometries.push(new THREE.Geometry());
    }

    return buildingGeometries;
  };

  var generateBuildingGeometries = function(buildings, buildingGeometries) {
    var HALF_STREET_WIDTH = CityTour.Config.STREET_WIDTH / 2;
    var HALF_STREET_DEPTH = CityTour.Config.STREET_DEPTH / 2;
    var MIN_STORIES_FOR_ANTENNA = 25;
    var PROBABILITY_OF_TALL_BUILDING_ANTENNA = 0.3;

    var mapX, mapZ, sceneX, sceneZ;
    var block;
    var storyHeight, buildingHeight;
    var materialIndex;

    var reusableBuildingMesh = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1));
    var cylinderMesh;

    for (mapX = -CityTour.Config.HALF_BLOCK_COLUMNS; mapX < CityTour.Config.HALF_BLOCK_COLUMNS; mapX++) {
      sceneX = CityTour.Coordinates.mapXToSceneX(mapX) + HALF_STREET_WIDTH;

      for (mapZ = -CityTour.Config.HALF_BLOCK_ROWS; mapZ < CityTour.Config.HALF_BLOCK_ROWS; mapZ++) {
        sceneZ = CityTour.Coordinates.mapZToSceneZ(mapZ) + HALF_STREET_DEPTH;

        block = buildings.blockAtCoordinates(mapX, mapZ) || [];

        block.forEach(function(lot) {
          storyHeight = ((CityTour.Config.MAX_STORY_HEIGHT - CityTour.Config.MIN_STORY_HEIGHT) * Math.random()) + CityTour.Config.MIN_STORY_HEIGHT;
          buildingHeight = storyHeight * lot.stories + (lot.ySurface - lot.yFloor);

          reusableBuildingMesh.scale.x = lot.dimensions.width * CityTour.Config.BLOCK_WIDTH;
          reusableBuildingMesh.position.x = sceneX + (CityTour.Config.BLOCK_WIDTH * lot.dimensions.midpointX);

          reusableBuildingMesh.scale.y = buildingHeight;
          reusableBuildingMesh.position.y = (buildingHeight / 2) + lot.yFloor;

          reusableBuildingMesh.scale.z = lot.dimensions.depth * CityTour.Config.BLOCK_DEPTH;
          reusableBuildingMesh.position.z = sceneZ + (CityTour.Config.BLOCK_DEPTH * lot.dimensions.midpointZ);

          reusableBuildingMesh.updateMatrix();

          materialIndex = Math.floor(Math.random() * CityTour.Config.MAX_BUILDING_MATERIALS);
          buildingGeometries[materialIndex].merge(reusableBuildingMesh.geometry, reusableBuildingMesh.matrix);

          // Add antenna to tall buildings
          if (lot.stories > MIN_STORIES_FOR_ANTENNA && (Math.random() < PROBABILITY_OF_TALL_BUILDING_ANTENNA)) {
            cylinderMesh = new THREE.Mesh(new THREE.CylinderGeometry(0.2, 0.2, 10, 4));
            cylinderMesh.position.x = sceneX + (CityTour.Config.BLOCK_WIDTH * lot.dimensions.midpointX);
            cylinderMesh.position.y = lot.yFloor + buildingHeight + 5;
            cylinderMesh.position.z = sceneZ + (CityTour.Config.BLOCK_DEPTH * lot.dimensions.midpointZ);
            cylinderMesh.updateMatrix();
            buildingGeometries[materialIndex].merge(cylinderMesh.geometry, cylinderMesh.matrix);
          }
        });
      }
    }
  };

  var buildingGeometryBuilder = {};

  buildingGeometryBuilder.build = function(buildings) {
    var i;
    var buildingMaterials = buildMaterials();
    var buildingGeometries = buildEmptyGeometriesForBuildings();
    var buildingMeshes = [];

    generateBuildingGeometries(buildings, buildingGeometries);

    for (i = 0; i < CityTour.Config.MAX_BUILDING_MATERIALS; i++) {
      buildingMeshes.push(new THREE.Mesh(buildingGeometries[i], buildingMaterials[i]));
    }

    return buildingMeshes;
  };

  return buildingGeometryBuilder;
};
<|endoftext|>


<commit_before>/* global define:true */
define(['pixi', 'experience/mode', 'experience/issue'], function (PIXI, Mode, Issue) {
    'use strict';

    var ExploreMode = function (canvas) {
        this._canvas = canvas;
        Mode.MODES.push(this);
        Mode.DEFAULT_MODE = this;

        ExploreMode.AUTO_MODE_TIME = 4000;
        ExploreMode.AUTO_MODE_TIMEOUT = 4000;

        this._safeZone = {x: 0, y: 0, width: 0, height: 0};

        return this;
    };

    ExploreMode.prototype = new Mode();
    ExploreMode.prototype.constructor = ExploreMode;

    ExploreMode.prototype.init = function () {
        Mode.prototype.init.call(this);
        // set explore radius based on smallest canvas dimension
        var dimension = Math.min(this._canvas.canvasSize.x, this._canvas.canvasSize.y);
        this._exploreRadius = dimension / 1.7;

        var seed;
        var rSeed;
        var elm;
        var i;
        var isInsideBounds;
        var isOnSafeZone;
        var tries;

        // set issue positions
        for (i = 0; i < this._canvas.issues.length; i ++) {
            elm = this._canvas.issues[i];
            tries = 0;

            do {
                // make it evenly distributed
                seed = (i / this._canvas.issues.length) * Math.PI * 2;
                rSeed = Math.pow(Math.random(), 1/2) * (this._exploreRadius - 20);
                elm.exploreX = Math.sin(seed) * rSeed;
                elm.exploreY = Math.cos(seed) * rSeed;

                isInsideBounds = (
                    elm.exploreX > -this._canvas.canvasSize.x / 2 &&
                    elm.exploreX < this._canvas.canvasSize.x / 2 &&
                    elm.exploreY > -this._canvas.canvasSize.y / 2 &&
                    elm.exploreY < this._canvas.canvasSize.y / 2
                );

                isOnSafeZone = (
                    elm.exploreX > this._safeZone.x &&
                    elm.exploreX < this._safeZone.x + this._safeZone.width &&
                    elm.exploreY > this._safeZone.y &&
                    elm.exploreY < this._safeZone.y + this._safeZone.height
                );
            } while ((!isInsideBounds || isOnSafeZone) && tries++ < 64);

            elm.moveTo(0, 0);
        }

        // set tags positions
        for (i = 0; i < this._canvas.tags.length; i ++) {
            elm = this._canvas.tags[i];

            do {
                seed = Math.random() * Math.PI * 2;
                rSeed = this._exploreRadius + (Math.random() * 5);
                elm.exploreX = Math.sin(seed) * rSeed;
                elm.exploreY = Math.cos(seed) * rSeed;
            } while (
                !(elm.exploreX > -this._canvas.canvasSize.x / 2 &&
                elm.exploreX < this._canvas.canvasSize.x / 2 &&
                elm.exploreY > -this._canvas.canvasSize.y / 2 &&
                elm.exploreY < this._canvas.canvasSize.y / 2) && // outside bounds
                !((elm.exploreX > this._safeZone.x &&
                elm.exploreX < this._safeZone.x + this._safeZone.width) ||
                (elm.exploreY > this._safeZone.y &&
                elm.exploreY < this._safeZone.y + this._safeZone.height)) // inside the safe zone
            );
        }

        // set fakes positions
        for (i = 0; i < this._canvas.fakes.length; i ++) {
            seed = Math.random() * Math.PI * 2;
            rSeed = Math.pow(Math.random(), 1/3) * (this._exploreRadius - 20);

            elm = this._canvas.fakes[i];
            elm.elm.alpha = 0.1 + (0.3 * rSeed / this._exploreRadius);
            elm.exploreX = Math.sin(seed) * rSeed;
            elm.exploreY = Math.cos(seed) * rSeed;
        }

        // var sZ = new PIXI.Graphics();
        // sZ.beginFill(0xFF0000);
        // sZ.drawRect(this._safeZone.x, this._safeZone.y, this._safeZone.width, this._safeZone.height);
        // this._canvas._particlesContainer.addChild(sZ);
    };

    ExploreMode.prototype.setSafeZone = function (safeZone) {
        this._safeZone = safeZone;
    };

    ExploreMode.prototype._startAutoMode = function () {
        this._autoMode = true;

        this._autoModeIssue = this._canvas.issues[Math.floor(Math.random() * this._canvas.issues.length)];
        this._canvas.mousePosition = this._canvas.autoModePosition = new PIXI.Point(
            this._autoModeIssue.elm.x,
            this._autoModeIssue.elm.y
        );
        this._mouseOverIssue(this._autoModeIssue);

        clearTimeout(this._autoModeTimeout);
        this._autoModeTimeout = setTimeout(
            this._endAutoMode.bind(this),
            ExploreMode.AUTO_MODE_TIMEOUT,
            true
        );
    };

    ExploreMode.prototype._endAutoMode = function (startAnother) {
        if (this._autoModeIssue) {
            this._mouseOutIssue(this._autoModeIssue);
        }

        this._autoMode = false;
        this._canvas.autoModePosition = null;

        clearTimeout(this._autoModeTimeout);
        if (startAnother) {
            this._autoModeTimeout = setTimeout(
                this._startAutoMode.bind(this),
                ExploreMode.AUTO_MODE_TIME
            );
        }
    };

    ExploreMode.prototype._drawLines = function () {
        var i;
        var j;
        var issue;
        var related;
        var relatedItem;
        var tags;
        var isOver;

        this._canvas.clearLines();

        for (i = 0; i < this._canvas.issues.length; i ++) {
            issue = this._canvas.issues[i];
            related = issue.data.getRelated();
            tags = issue.data.getTags();

            // draw lines connecting related issues
            for (j = 0; j < related.length; j ++) {
                relatedItem = this._canvas.getElementByData(related[j]);
                isOver = (issue.isOver || relatedItem.isOver);

                this._canvas.drawLine(issue, relatedItem, 0x0, isOver ? 0.10 : 0.02);
            }

            // draw lines connecting related tags
            for (j = 0; j < tags.length; j ++) {
                relatedItem = this._canvas.getElementByData(tags[j]);
                isOver = (issue.isOver || relatedItem.isOver);

                this._canvas.drawLine(issue, relatedItem, 0x0, isOver ? 0.10 : 0.02);
            }
        }
    };

    ExploreMode.prototype._mouseOverIssue = function (issue) {
        this.selectedIssue = issue;

        var related = issue.data.getRelated();
        var tags;
        var relatedIssue;
        var i;

        if (issue.data.getTags) {
            tags =  issue.data.getTags();
        }

        if (issue !== this._autoModeIssue) {
            this._endAutoMode();
        }

        issue.mouseOver(this._canvas.mousePosition);

        for(i = 0; i < related.length; i ++) {
            relatedIssue = this._canvas.getElementByData(related[i]);
            relatedIssue.lightUp();
            relatedIssue.stopMoving();
        }

        if (tags) {
            for(i = 0; i < tags.length; i ++) {
                relatedIssue = this._canvas.getElementByData(tags[i]);
                relatedIssue.lightUp();
                relatedIssue.stopMoving();
            }
        }
    };

    ExploreMode.prototype._mouseOutIssue = function (issue) {
        this.selectedIssue = null;

        var related = issue.data.getRelated();
        var tags;
        var relatedIssue;
        var i;

        if (issue.data.getTags) {
            tags =  issue.data.getTags();
        }

        if (issue !== this._autoModeIssue) {
            this._endAutoMode(true);
        }

        issue.mouseOut();

        for(i = 0; i < related.length; i ++) {
            if (related[i] === issue.data) {
                continue;
            }
            relatedIssue = this._canvas.getElementByData(related[i]);
            relatedIssue.lightDown();
            relatedIssue._resumeStaticAnimation();
        }

        if (tags) {
            for(i = 0; i < tags.length; i ++) {
                relatedIssue = this._canvas.getElementByData(tags[i]);
                relatedIssue.lightDown();
                relatedIssue._resumeStaticAnimation();
            }
        }
    };

    ExploreMode.prototype._tapIssue = function (issue) {
        if (!this.selectedIssue) {
            issue._onMouseOver();
        } else if (this.selectedIssue === issue) {
            issue._onPress();
        } else {
            this.selectedIssue._onMouseOut();
            issue._onMouseOver();
        }
    };

    ExploreMode.prototype._onStartShow = function () {
        // set position for issues
        var issue;
        var i;

        for (i = 0; i < this._canvas.issues.length; i ++) {
            issue = this._canvas.issues[i];
            issue.setMode(Issue.MODE_EXPLORE);
            issue.moveTo(
                issue.exploreX,
                issue.exploreY,
                issue._resumeStaticAnimation.bind(issue),
                {alpha: 1});
            issue.exploreMouseOver = this._mouseOverIssue.bind(this);
            issue.exploreMouseOut = this._mouseOutIssue.bind(this);
            issue.exploreTap = this._tapIssue.bind(this);
            issue.mouseOverS.add(issue.exploreMouseOver);
            issue.mouseOutS.add(issue.exploreMouseOut);
            issue.tapS.add(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.tags.length; i ++) {
            issue = this._canvas.tags[i];
            issue.setMode(Issue.MODE_TAG);
            issue._x0 = issue.exploreX;
            issue._y0 = issue.exploreY;
            issue.implode();
            issue.exploreMouseOver = this._mouseOverIssue.bind(this);
            issue.exploreMouseOut = this._mouseOutIssue.bind(this);
            issue.exploreTap = this._tapIssue.bind(this);
            issue.mouseOverS.add(issue.exploreMouseOver);
            issue.mouseOutS.add(issue.exploreMouseOut);
            issue.tapS.add(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.fakes.length; i ++) {
            issue = this._canvas.fakes[i];
            issue._x0 = issue.exploreX;
            issue._y0 = issue.exploreY;
            issue.implode();
        }

        this._drawLinesBind = this._drawLines.bind(this);
        this._canvas.renderStartS.add(this._drawLinesBind);

        // start a new autoMode timeout
        this._endAutoMode(true);

        setTimeout(this._onShow.bind(this), 500);
    };

    ExploreMode.prototype._onStartHide = function () {
        var issue;
        var i;

        for (i = 0; i < this._canvas.issues.length; i ++) {
            issue = this._canvas.issues[i];
            issue.explode(this._exploreRadius);
            issue.mouseOverS.remove(issue.exploreMouseOver);
            issue.mouseOutS.remove(issue.exploreMouseOut);
            issue.tapS.remove(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.tags.length; i ++) {
            issue = this._canvas.tags[i];
            issue.explode(this._exploreRadius);
            issue.mouseOverS.remove(issue.exploreMouseOver);
            issue.mouseOutS.remove(issue.exploreMouseOut);
            issue.tapS.remove(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.fakes.length; i ++) {
            this._canvas.fakes[i].explode(this._exploreRadius);
        }

        this._canvas.clearLines();
        this._canvas.renderStartS.remove(this._drawLinesBind);

        this._endAutoMode();

        setTimeout(this._onHide.bind(this), 0);
    };

    return ExploreMode;
});<commit_msg>limited tag positions on explore mode<commit_after>/* global define:true */
define(['pixi', 'experience/mode', 'experience/issue'], function (PIXI, Mode, Issue) {
    'use strict';

    var ExploreMode = function (canvas) {
        this._canvas = canvas;
        Mode.MODES.push(this);
        Mode.DEFAULT_MODE = this;

        ExploreMode.AUTO_MODE_TIME = 4000;
        ExploreMode.AUTO_MODE_TIMEOUT = 4000;

        this._safeZone = {x: 0, y: 0, width: 0, height: 0};

        return this;
    };

    ExploreMode.prototype = new Mode();
    ExploreMode.prototype.constructor = ExploreMode;

    ExploreMode.prototype.init = function () {
        Mode.prototype.init.call(this);
        // set explore radius based on smallest canvas dimension
        var dimension = Math.min(this._canvas.canvasSize.x, this._canvas.canvasSize.y);
        this._exploreRadius = dimension / 1.7;

        var seed;
        var rSeed;
        var elm;
        var i;
        var isInsideBounds;
        var isOnSafeZone;
        var tries;

        // set issue positions
        for (i = 0; i < this._canvas.issues.length; i ++) {
            elm = this._canvas.issues[i];
            tries = 0;

            do {
                // make it evenly distributed
                seed = (i / this._canvas.issues.length) * Math.PI * 2;
                rSeed = Math.pow(Math.random(), 1/2) * (this._exploreRadius - 20);
                elm.exploreX = Math.sin(seed) * rSeed;
                elm.exploreY = Math.cos(seed) * rSeed;

                isInsideBounds = (
                    elm.exploreX > -this._canvas.canvasSize.x / 2 &&
                    elm.exploreX < this._canvas.canvasSize.x / 2 &&
                    elm.exploreY > -this._canvas.canvasSize.y / 2 &&
                    elm.exploreY < this._canvas.canvasSize.y / 2
                );

                isOnSafeZone = (
                    elm.exploreX > this._safeZone.x &&
                    elm.exploreX < this._safeZone.x + this._safeZone.width &&
                    elm.exploreY > this._safeZone.y &&
                    elm.exploreY < this._safeZone.y + this._safeZone.height
                );
            } while ((!isInsideBounds || isOnSafeZone) && tries++ < 64);

            elm.moveTo(0, 0);
        }

        // set tags positions
        for (i = 0; i < this._canvas.tags.length; i ++) {
            elm = this._canvas.tags[i];

            do {
                seed = Math.random() * Math.PI * 2;
                rSeed = this._exploreRadius + (Math.random() * 5);
                elm.exploreX = Math.sin(seed) * rSeed;
                elm.exploreY = Math.cos(seed) * rSeed;

                isInsideBounds = (
                    elm.exploreX > -this._canvas.canvasSize.x / 2 &&
                    elm.exploreX < this._canvas.canvasSize.x / 2 &&
                    elm.exploreY > -this._canvas.canvasSize.y / 2 &&
                    elm.exploreY < this._canvas.canvasSize.y / 2
                );
            } while (!isInsideBounds);
        }

        // set fakes positions
        for (i = 0; i < this._canvas.fakes.length; i ++) {
            seed = Math.random() * Math.PI * 2;
            rSeed = Math.pow(Math.random(), 1/3) * (this._exploreRadius - 20);

            elm = this._canvas.fakes[i];
            elm.elm.alpha = 0.1 + (0.3 * rSeed / this._exploreRadius);
            elm.exploreX = Math.sin(seed) * rSeed;
            elm.exploreY = Math.cos(seed) * rSeed;
        }

        // var sZ = new PIXI.Graphics();
        // sZ.beginFill(0xFF0000);
        // sZ.drawRect(this._safeZone.x, this._safeZone.y, this._safeZone.width, this._safeZone.height);
        // this._canvas._particlesContainer.addChild(sZ);
    };

    ExploreMode.prototype.setSafeZone = function (safeZone) {
        this._safeZone = safeZone;
    };

    ExploreMode.prototype._startAutoMode = function () {
        this._autoMode = true;

        this._autoModeIssue = this._canvas.issues[Math.floor(Math.random() * this._canvas.issues.length)];
        this._canvas.mousePosition = this._canvas.autoModePosition = new PIXI.Point(
            this._autoModeIssue.elm.x,
            this._autoModeIssue.elm.y
        );
        this._mouseOverIssue(this._autoModeIssue);

        clearTimeout(this._autoModeTimeout);
        this._autoModeTimeout = setTimeout(
            this._endAutoMode.bind(this),
            ExploreMode.AUTO_MODE_TIMEOUT,
            true
        );
    };

    ExploreMode.prototype._endAutoMode = function (startAnother) {
        if (this._autoModeIssue) {
            this._mouseOutIssue(this._autoModeIssue);
        }

        this._autoMode = false;
        this._canvas.autoModePosition = null;

        clearTimeout(this._autoModeTimeout);
        if (startAnother) {
            this._autoModeTimeout = setTimeout(
                this._startAutoMode.bind(this),
                ExploreMode.AUTO_MODE_TIME
            );
        }
    };

    ExploreMode.prototype._drawLines = function () {
        var i;
        var j;
        var issue;
        var related;
        var relatedItem;
        var tags;
        var isOver;

        this._canvas.clearLines();

        for (i = 0; i < this._canvas.issues.length; i ++) {
            issue = this._canvas.issues[i];
            related = issue.data.getRelated();
            tags = issue.data.getTags();

            // draw lines connecting related issues
            for (j = 0; j < related.length; j ++) {
                relatedItem = this._canvas.getElementByData(related[j]);
                isOver = (issue.isOver || relatedItem.isOver);

                this._canvas.drawLine(issue, relatedItem, 0x0, isOver ? 0.10 : 0.02);
            }

            // draw lines connecting related tags
            for (j = 0; j < tags.length; j ++) {
                relatedItem = this._canvas.getElementByData(tags[j]);
                isOver = (issue.isOver || relatedItem.isOver);

                this._canvas.drawLine(issue, relatedItem, 0x0, isOver ? 0.10 : 0.02);
            }
        }
    };

    ExploreMode.prototype._mouseOverIssue = function (issue) {
        this.selectedIssue = issue;

        var related = issue.data.getRelated();
        var tags;
        var relatedIssue;
        var i;

        if (issue.data.getTags) {
            tags =  issue.data.getTags();
        }

        if (issue !== this._autoModeIssue) {
            this._endAutoMode();
        }

        issue.mouseOver(this._canvas.mousePosition);

        for(i = 0; i < related.length; i ++) {
            relatedIssue = this._canvas.getElementByData(related[i]);
            relatedIssue.lightUp();
            relatedIssue.stopMoving();
        }

        if (tags) {
            for(i = 0; i < tags.length; i ++) {
                relatedIssue = this._canvas.getElementByData(tags[i]);
                relatedIssue.lightUp();
                relatedIssue.stopMoving();
            }
        }
    };

    ExploreMode.prototype._mouseOutIssue = function (issue) {
        this.selectedIssue = null;

        var related = issue.data.getRelated();
        var tags;
        var relatedIssue;
        var i;

        if (issue.data.getTags) {
            tags =  issue.data.getTags();
        }

        if (issue !== this._autoModeIssue) {
            this._endAutoMode(true);
        }

        issue.mouseOut();

        for(i = 0; i < related.length; i ++) {
            if (related[i] === issue.data) {
                continue;
            }
            relatedIssue = this._canvas.getElementByData(related[i]);
            relatedIssue.lightDown();
            relatedIssue._resumeStaticAnimation();
        }

        if (tags) {
            for(i = 0; i < tags.length; i ++) {
                relatedIssue = this._canvas.getElementByData(tags[i]);
                relatedIssue.lightDown();
                relatedIssue._resumeStaticAnimation();
            }
        }
    };

    ExploreMode.prototype._tapIssue = function (issue) {
        if (!this.selectedIssue) {
            issue._onMouseOver();
        } else if (this.selectedIssue === issue) {
            issue._onPress();
        } else {
            this.selectedIssue._onMouseOut();
            issue._onMouseOver();
        }
    };

    ExploreMode.prototype._onStartShow = function () {
        // set position for issues
        var issue;
        var i;

        for (i = 0; i < this._canvas.issues.length; i ++) {
            issue = this._canvas.issues[i];
            issue.setMode(Issue.MODE_EXPLORE);
            issue.moveTo(
                issue.exploreX,
                issue.exploreY,
                issue._resumeStaticAnimation.bind(issue),
                {alpha: 1});
            issue.exploreMouseOver = this._mouseOverIssue.bind(this);
            issue.exploreMouseOut = this._mouseOutIssue.bind(this);
            issue.exploreTap = this._tapIssue.bind(this);
            issue.mouseOverS.add(issue.exploreMouseOver);
            issue.mouseOutS.add(issue.exploreMouseOut);
            issue.tapS.add(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.tags.length; i ++) {
            issue = this._canvas.tags[i];
            issue.setMode(Issue.MODE_TAG);
            issue._x0 = issue.exploreX;
            issue._y0 = issue.exploreY;
            issue.implode();
            issue.exploreMouseOver = this._mouseOverIssue.bind(this);
            issue.exploreMouseOut = this._mouseOutIssue.bind(this);
            issue.exploreTap = this._tapIssue.bind(this);
            issue.mouseOverS.add(issue.exploreMouseOver);
            issue.mouseOutS.add(issue.exploreMouseOut);
            issue.tapS.add(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.fakes.length; i ++) {
            issue = this._canvas.fakes[i];
            issue._x0 = issue.exploreX;
            issue._y0 = issue.exploreY;
            issue.implode();
        }

        this._drawLinesBind = this._drawLines.bind(this);
        this._canvas.renderStartS.add(this._drawLinesBind);

        // start a new autoMode timeout
        this._endAutoMode(true);

        setTimeout(this._onShow.bind(this), 500);
    };

    ExploreMode.prototype._onStartHide = function () {
        var issue;
        var i;

        for (i = 0; i < this._canvas.issues.length; i ++) {
            issue = this._canvas.issues[i];
            issue.explode(this._exploreRadius);
            issue.mouseOverS.remove(issue.exploreMouseOver);
            issue.mouseOutS.remove(issue.exploreMouseOut);
            issue.tapS.remove(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.tags.length; i ++) {
            issue = this._canvas.tags[i];
            issue.explode(this._exploreRadius);
            issue.mouseOverS.remove(issue.exploreMouseOver);
            issue.mouseOutS.remove(issue.exploreMouseOut);
            issue.tapS.remove(issue.exploreTap);
        }

        for (i = 0; i < this._canvas.fakes.length; i ++) {
            this._canvas.fakes[i].explode(this._exploreRadius);
        }

        this._canvas.clearLines();
        this._canvas.renderStartS.remove(this._drawLinesBind);

        this._endAutoMode();

        setTimeout(this._onHide.bind(this), 0);
    };

    return ExploreMode;
});<|endoftext|>


<commit_before>'use strict';

const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication');
const _ = require('lodash');
const ClassModel = require('../model').classModel;
const CourseModel = require('../model').courseModel;

const restrictToCurrentSchool = globalHooks.ifNotLocal(globalHooks.restrictToCurrentSchool);

/**
 * adds all students to a course when a class is added to the course
 * @param hook - contains created/patched object and request body
 */
const addWholeClassToCourse = (hook) => {
	let requestBody = hook.data;
	let course = hook.result;
	if ((requestBody.classIds || []).length > 0) { // just courses do have a property "classIds"
		return Promise.all(requestBody.classIds.map(classId => {
			return ClassModel.findById(classId).exec().then(c =>  c.userIds);
		})).then(studentIds => {
			// flatten deep arrays and remove duplicates
			studentIds = _.uniqWith(_.flattenDeep(studentIds), (e1, e2) => JSON.stringify(e1) === JSON.stringify(e2));

			// add all students of classes to course, if not already added
			return Promise.all(studentIds.map(s => {
				if (course.userIds.indexOf(s) < 0) {
					return CourseModel.update({_id: course._id}, {$push: {userIds: s}}).exec();
				} else {
					return {};
				}
			})).then(_ => hook);
		});
	} else {
		return hook;
	}
};

/**
 * deletes all students from a course when a class is removed from the course
 * this function goes into a before hook before we have to check whether there is a class missing
 * in the patch-body which was in the course before
 * @param hook - contains and request body
 */
const deleteWholeClassFromCourse = (hook) => {
	let requestBody = hook.data;
	let courseId = hook.id;
	return CourseModel.findById(courseId).exec().then(course => {
		if (!course) return hook;

		let removedClasses = _.differenceBy(course.classIds, requestBody.classIds, (v) => JSON.stringify(v));
		if (removedClasses.length < 1) return hook;
		return Promise.all(removedClasses.map(classId => {
			return ClassModel.findById(classId).exec().then(c =>  (c || []).userIds);
		})).then(studentIds => {
			// flatten deep arrays and remove duplicates
            studentIds = _.uniqWith(_.flattenDeep(studentIds), (e1, e2) => JSON.stringify(e1) === JSON.stringify(e2));

			// remove all students of classes from course, if they are in course
			return Promise.all(studentIds.map(s => {
				if (course.userIds.indexOf(s) >= 0) {
					return CourseModel.update({_id: course._id}, {$pull: {userIds: s}}).exec();
				} else {
					return {};
				}
			})).then(result => {

				// also remove all students from request body for not reading them in after hook
				requestBody.userIds = _.differenceBy(requestBody.userIds, studentIds, (v) => JSON.stringify(v));
				hook.data = requestBody;
				return hook;
			});
		});
	});
};

exports.before = {
	all: [auth.hooks.authenticate('jwt')],
	find: [restrictToCurrentSchool],
	get: [],
	create: [],
	update: [restrictToCurrentSchool],
	patch: [restrictToCurrentSchool, deleteWholeClassFromCourse],
	remove: [restrictToCurrentSchool]
};

exports.after = {
	all: [],
	find: [],
	get: [globalHooks.ifNotLocal(globalHooks.denyIfNotCurrentSchool({errorMessage: 'Die angefragte Gruppe gehört nicht zur eigenen Schule!'}))],
	create: [addWholeClassToCourse],
	update: [],
	patch: [addWholeClassToCourse],
	remove: []
};
<commit_msg>fix bug in after hook of user-groups (#267)<commit_after>'use strict';

const globalHooks = require('../../../hooks');
const hooks = require('feathers-hooks');
const auth = require('feathers-authentication');
const _ = require('lodash');
const ClassModel = require('../model').classModel;
const CourseModel = require('../model').courseModel;

const restrictToCurrentSchool = globalHooks.ifNotLocal(globalHooks.restrictToCurrentSchool);

/**
 * adds all students to a course when a class is added to the course
 * @param hook - contains created/patched object and request body
 */
const addWholeClassToCourse = (hook) => {
	let requestBody = hook.data;
	let course = hook.result;
	if ((requestBody.classIds || []).length > 0) { // just courses do have a property "classIds"
		return Promise.all(requestBody.classIds.map(classId => {
			return ClassModel.findById(classId).exec().then(c =>  c.userIds);
		})).then(studentIds => {
			// flatten deep arrays and remove duplicates
			studentIds = _.uniqWith(_.flattenDeep(studentIds), (e1, e2) => JSON.stringify(e1) === JSON.stringify(e2));

			// add all students of classes to course, if not already added
			return Promise.all(studentIds.map(s => {
				if (!_.some(course.userIds, u => JSON.stringify(u) === JSON.stringify(s))) {
					return CourseModel.update({_id: course._id}, {$push: {userIds: s}}).exec();
				} else {
					return {};
				}
			})).then(_ => hook);
		});
	} else {
		return hook;
	}
};

/**
 * deletes all students from a course when a class is removed from the course
 * this function goes into a before hook before we have to check whether there is a class missing
 * in the patch-body which was in the course before
 * @param hook - contains and request body
 */
const deleteWholeClassFromCourse = (hook) => {
	let requestBody = hook.data;
	let courseId = hook.id;
	return CourseModel.findById(courseId).exec().then(course => {
		if (!course) return hook;

		let removedClasses = _.differenceBy(course.classIds, requestBody.classIds, (v) => JSON.stringify(v));
		if (removedClasses.length < 1) return hook;
		return Promise.all(removedClasses.map(classId => {
			return ClassModel.findById(classId).exec().then(c =>  (c || []).userIds);
		})).then(studentIds => {
			// flatten deep arrays and remove duplicates
      studentIds = _.uniqWith(_.flattenDeep(studentIds), (e1, e2) => JSON.stringify(e1) === JSON.stringify(e2));

			// remove all students of classes from course, if they are in course
			return Promise.all(studentIds.map(s => {
				if (!_.some(course.userIds, u => JSON.stringify(u) === JSON.stringify(s))) {
					return CourseModel.update({_id: course._id}, {$pull: {userIds: s}}).exec();
				} else {
					return {};
				}
			})).then(result => {

				// also remove all students from request body for not reading them in after hook
				requestBody.userIds = _.differenceBy(requestBody.userIds, studentIds, (v) => JSON.stringify(v));
				hook.data = requestBody;
				return hook;
			});
		});
	});
};

exports.before = {
	all: [auth.hooks.authenticate('jwt')],
	find: [restrictToCurrentSchool],
	get: [],
	create: [],
	update: [restrictToCurrentSchool],
	patch: [restrictToCurrentSchool, deleteWholeClassFromCourse],
	remove: [restrictToCurrentSchool]
};

exports.after = {
	all: [],
	find: [],
	get: [globalHooks.ifNotLocal(globalHooks.denyIfNotCurrentSchool({errorMessage: 'Die angefragte Gruppe gehört nicht zur eigenen Schule!'}))],
	create: [addWholeClassToCourse],
	update: [],
	patch: [addWholeClassToCourse],
	remove: []
};
<|endoftext|>


<commit_before>
/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2016, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function() {
  'use strict';

  /**
   * Registers your Extension API methods
   */
  module.exports.api = {
    test: function(env, http, resolve, reject, args) {
      resolve('This is a response from your extension');
    }
  };

})();
<commit_msg>Fixed wrong usage og extension api in template<commit_after>
/*!
 * OS.js - JavaScript Cloud/Web Desktop Platform
 *
 * Copyright (c) 2011-2016, Anders Evenrud <andersevenrud@gmail.com>
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @author  Anders Evenrud <andersevenrud@gmail.com>
 * @licence Simplified BSD License
 */
(function() {
  'use strict';

  /**
   * Registers your Extension API methods
   */
  module.exports.api = {
    test: function(http, data) {
      return Promise.resolve('This is a response from your extension');
    }
  };

})();
<|endoftext|>


<commit_before>// let inp = `
// Modern NLP algorithms are based on machine learning, especially statistical machine learning. The paradigm of machine learning is different from that of most prior attempts at language processing. Prior implementations of language-processing tasks typically involved the direct hand coding of large sets of rules. The machine-learning paradigm calls instead for using general learning algorithms — often, although not always, grounded in statistical inference — to automatically learn such rules through the analysis of large corpora of typical real-world examples. A corpus (plural, "corpora") is a set of documents (or sometimes, individual sentences) that have been hand-annotated with the correct values to be learned.

// Many different classes of machine learning algorithms have been applied to NLP tasks. These algorithms take as input a large set of "features" that are generated from the input data. Some of the earliest-used algorithms, such as decision trees, produced systems of hard if-then rules similar to the systems of hand-written rules that were then common. Increasingly, however, research has focused on statistical models, which make soft, probabilistic decisions based on attaching real-valued weights to each input feature. Such models have the advantage that they can express the relative certainty of many different possible answers rather than only one, producing more reliable results when such a model is included as a component of a larger system.
// `
// if word ends a sentence

'use strict';

const isLastWord = word => (
  word[word.length-1] === '.' ||
  word[word.length-1] === '\n' && word[word.length-2] === '.'
);
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1);

function markov(input, limit) {
  let tokenized = input.split(' ');
  let textLen = tokenized.length;
  limit = limit || textLen;

  let nextWords = {};

  let startingWords = [];

  for (let i = 0; i < textLen - 1; i++) {
    let currentWord = tokenized[i];
    let nextWord = tokenized[i+1];
    let previousWord = i && tokenized[i-1];

    if (currentWord && !previousWord || isLastWord(previousWord)) {
      startingWords.push(currentWord);
    }

    if (nextWords[currentWord]) {
      nextWords[currentWord].push(nextWord);
    }
    else {
      nextWords[currentWord] = [nextWord];
    }
  }

  let output = [capitalize(sample(startingWords))]

  let previousWord;
  for (let i = 1; i < limit; i++) {
    previousWord = output[i-1].toLowerCase();
    let nextWord = nextWords[previousWord] && sample(nextWords[previousWord])

    // this one's an edge case; if it encounters the last word in the text
    if (!nextWord) {
      output.push(capitalize(sample(startingWords)))
    }
    // if sentence just ended, start a new sentence
    else if (isLastWord(previousWord)) {
      output.push(capitalize(nextWord));
    }
    else {
      output.push(nextWord);
    }
  }

  // close out last sentence
  while (!isLastWord(previousWord)) {
    let nextWord = sample(nextWords[previousWord])
    output.push(nextWord);
    previousWord = nextWord
  }
  console.log(output.join(' '))
  return output.join(' ')
}
<commit_msg>fixed the bug fix<commit_after>// var inp = `
// Modern NLP algorithms are based on machine learning, especially statistical machine learning. The paradigm of machine learning is different from that of most prior attempts at language processing. Prior implementations of language-processing tasks typically involved the direct hand coding of large sets of rules. The machine-learning paradigm calls instead for using general learning algorithms — often, although not always, grounded in statistical inference — to automatically learn such rules through the analysis of large corpora of typical real-world examples. A corpus (plural, "corpora") is a set of documents (or sometimes, individual sentences) that have been hand-annotated with the correct values to be learned.

// Many different classes of machine learning algorithms have been applied to NLP tasks. These algorithms take as input a large set of "features" that are generated from the input data. Some of the earliest-used algorithms, such as decision trees, produced systems of hard if-then rules similar to the systems of hand-written rules that were then common. Increasingly, however, research has focused on statistical models, which make soft, probabilistic decisions based on attaching real-valued weights to each input feature. Such models have the advantage that they can express the relative certainty of many different possible answers rather than only one, producing more reliable results when such a model is included as a component of a larger system.
// `
// if word ends a sentence
const isLastWord = word => (
  word[word.length-1] === '.' ||
  word[word.length-1] === '\n' && word[word.length-2] === '.'
);
const sample = arr => arr[Math.floor(Math.random() * arr.length)];
const capitalize = str => str.charAt(0).toUpperCase() + str.slice(1);

function markov(input, limit) {
  let tokenized = input.split(' ');
  let textLen = tokenized.length;
  limit = limit || textLen;

  let nextWords = {};

  let startingWords = [];

  for (let i = 0; i < textLen - 1; i++) {
    let currentWord = tokenized[i];
    let nextWord = tokenized[i+1];
    let previousWord = i && tokenized[i-1];

    if (currentWord && !previousWord || isLastWord(previousWord)) {
      startingWords.push(currentWord);
    }

    if (nextWords[currentWord]) {
      nextWords[currentWord].push(nextWord);
    }
    else {
      nextWords[currentWord] = [nextWord];
    }
  }

  let output = [capitalize(sample(startingWords))]

  let previousWord;
  for (let i = 1; i < limit; i++) {
    previousWord = output[i-1];
    let nextWord = nextWords[previousWord] && sample(nextWords[previousWord])

    // this one's an edge case; if it encounters the last word in the text
    if (!nextWord) {
      output.push(capitalize(sample(startingWords)))
    }
    // if sentence just ended, start a new sentence
    else if (isLastWord(previousWord)) {
      output.push(capitalize(nextWord));
    }
    else {
      output.push(nextWord);
    }
  }

  // close out last sentence
  while (!isLastWord(previousWord) && nextWords[previousWord]) {
    let nextWord = sample(nextWords[previousWord])
    output.push(nextWord);
    previousWord = nextWord
  }

  return output.join(' ')
}
<|endoftext|>


<commit_before>/*
* matchMedia() polyfill - test whether a CSS media type or media query applies
* authors: Scott Jehl, Paul Irish, Nicholas Zakas
* Copyright (c) 2011 Scott, Paul and Nicholas.
* Dual MIT/BSD license
*/

window.matchMedia = window.matchMedia || (function(doc, undefined){

  var bool,
      docElem  = doc.documentElement,
      refNode  = docElem.firstElementChild || docElem.firstChild,
      // fakeBody required for <FF4 when executed in <head>
      fakeBody = doc.createElement('body'),
      div      = doc.createElement('div');

  div.id = 'mq-test-1';
  div.style.cssText = "position:absolute;top:-100em";
  fakeBody.appendChild(div);

  return function(q){

    div.innerHTML = '_<style media="'+q+'"> #mq-test-1 { width: 42px; }</style>';

    docElem.insertBefore(fakeBody, refNode);
    div.removeChild(div.firstChild);
    bool = div.offsetWidth == 42;
    docElem.removeChild(fakeBody);

    return { matches: bool, media: q };
  };

})(document);

<commit_msg>use a  to fix the noScope issue with innerHTML injection. thanks ryan seddong for the technique.<commit_after>/*
* matchMedia() polyfill - test whether a CSS media type or media query applies
* authors: Scott Jehl, Paul Irish, Nicholas Zakas
* Copyright (c) 2011 Scott, Paul and Nicholas.
* Dual MIT/BSD license
*/

window.matchMedia = window.matchMedia || (function(doc, undefined){

  var bool,
      docElem  = doc.documentElement,
      refNode  = docElem.firstElementChild || docElem.firstChild,
      // fakeBody required for <FF4 when executed in <head>
      fakeBody = doc.createElement('body'),
      div      = doc.createElement('div');

  div.id = 'mq-test-1';
  div.style.cssText = "position:absolute;top:-100em";
  fakeBody.appendChild(div);

  return function(q){

    div.innerHTML = '<style media="'+q+'"> #mq-test-1 { width: 42px; }</style>';

    docElem.insertBefore(fakeBody, refNode);
    bool = div.offsetWidth == 42;
    docElem.removeChild(fakeBody);

    return { matches: bool, media: q };
  };

})(document);

<|endoftext|>