Home Reference Source Repository

src/Region.js

/**
 * @file melon/Region
 * @author cxtom([email protected])
 */

import React, {PropTypes} from 'react';

import Selector from './region/Selector';
import Area from './region/Area';
import * as helper from './region/helper';
import InputComponent from 'melon-core/InputComponent';
import {create} from 'melon-core/classname/cxBuilder';

const cx = create('Region');

export default class Region extends InputComponent {

    constructor(props, context) {

        super(props, context);

        this.state = {
            ...this.state,
            datasource: this.props.datasource
        };

        this.onChange = this.onChange.bind(this);
        this.onSelectorChange = this.onSelectorChange.bind(this);

    }

    onChange(rawValue) {

        super.onChange({
            type: 'change',
            target: this,
            value: this.stringifyValue(rawValue)
        });

    }

    onAreaChange(index, cIndex, e) {

        const data = e.data;
        const datasource = this.state.datasource;

        helper.isAllSelected(data);
        datasource[cIndex].children[index] = data;
        helper.isAllSelected(datasource[cIndex]);

        this.setState({datasource}, function () {
            this.onChange(datasource);
        });

    }

    onSelectorChange(index, {value}) {

        const datasource = this.state.datasource;

        helper[value ? 'selectAll' : 'cancelAll'](datasource[index]);

        this.setState({datasource}, function () {
            this.onChange(datasource);
        });

    }

    parseValue(value) {
        value = value.split(',');
        return this.props.datasource.map(helper.parse.bind(this, value));
    }

    stringifyValue(datasource) {
        return datasource
            ? datasource.reduce(
                (...args) => this.format(...args),
                []
            ).join(',')
            : '';
    }

    format(result, child, index) {

        if (child.selected) {
            result.push(child.id);
        }

        return child.children
            ? child.children.reduce(
                (...args) => this.format(...args),
                result
            )
            : result;



    }

    renderCountry(country, index) {
        return (
            <div className={cx().part('country').build()} key={index}>
                <h1>
                    <Selector
                        label={country.text}
                        id={country.id}
                        index={index}
                        checked={country.selected}
                        onChange={e => {
                            this.onSelectorChange(index, e);
                        }} />
                </h1>
                {this.renderArea(country.children, index)}
            </div>
        );
    }

    renderArea(area, cIndex) {
        return Array.isArray(area) && area.length > 0
            ? (
                <ul>
                    {area.map((a, index) =>
                        <Area
                            key={index}
                            variants={index % 2 ? ['even'] : []}
                            datasource={a}
                            onChange={e => {
                                this.onAreaChange(index, cIndex, e);
                            }} />
                    )}
                </ul>
            ) : null;
    }

    render() {

        const datasource = this.state.datasource;

        return (
            <div className={cx(this.props).build()}>
                {datasource.map((...args) => this.renderCountry(...args))}
            </div>
        );

    }


}


Region.defaultProps = {
    ...InputComponent.defaultProps,
    datasource: []
};

Region.propTypes = {
    ...InputComponent.propTypes,
    selected: PropTypes.bool,
    datasource: PropTypes.arrayOf(PropTypes.object)
};

Region.childContextTypes = InputComponent.childContextTypes;
Region.contextTypes = InputComponent.contextTypes;