<commit_before>'use strict'

import Style from './Style.js'

var React = require('react')
var ReactNative = require('react-native')
var {
  Text,
  View,
  TouchableOpacity,
  TouchableWithoutFeedback,
  LayoutAnimation,
  Platform,
  UIManager
} = ReactNative

export default class RadioForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      is_active_index: props.initial
    }
    if (Platform.OS === 'android') {
      UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
    }
    this._renderButton = this._renderButton.bind(this);
  }
  static defaultProps = {
    radio_props: [],
    initial: 0,
    buttonColor: '#2196f3',
    selectedButtonColor: '#2196f3',
    formHorizontal: false,
    labelHorizontal: true,
    animation: true,
    labelColor: '#000',
    selectedLabelColor: '#000',
    wrapStyle: {},
    disabled: false
  }

  updateIsActiveIndex(index) {
    this.setState({ is_active_index: index });
    this.props.onPress(this.props.radio_props[index], index)
  }

  _renderButton(obj, i) {
    return (
      <RadioButton
        accessible={this.props.accessible}
        accessibilityLabel={(this.props.accessibilityLabel)
          ? (this.props.accessibilityLabel + '|' + i) : ('radioButton' + '|' + i)}
        testID={(this.props.testID)
          ? (this.props.testID + '|' + i) : ('radioButton' + '|' + i)}
        isSelected={this.state.is_active_index === i}
        obj={obj}
        key={i}
        index={i}
        buttonColor={this.state.is_active_index === i ? this.props.selectedButtonColor : this.props.buttonColor}
        buttonSize={this.props.buttonSize}
        buttonOuterSize={this.props.buttonOuterSize}
        labelHorizontal={this.props.labelHorizontal}
        labelColor={this.state.is_active_index === i ? this.props.selectedLabelColor : this.props.labelColor}
        labelStyle={this.props.labelStyle}
        style={this.props.radioStyle}
        animation={this.props.animation}
        disabled={this.props.disabled}
        onPress={(value, index) => {
          this.props.onPress(value, index)
          this.setState({is_active_index: index})
        }}
      />
    )
  }

  render() {
    var render_content = false
    if (this.props.radio_props.length) {
      render_content = this.props.radio_props.map(this._renderButton)
    } else {
      render_content = this.props.children
    }
    return (
      <View style={[
        Style.radioFrom,
        this.props.style,
        this.props.formHorizontal && Style.formHorizontal
      ]}>
        {render_content}
      </View>
    )
  }
}

export class RadioButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  shouldComponentUpdate(nextProps, nextState) {
    return true
  }
  static defaultProps = {
    isSelected: false,
    buttonColor: '#2196f3',
    selectedButtonColor: '#2196f3',
    labelHorizontal: true,
    disabled: false,
    idSeparator: '|'
  }
  componentWillUpdate () {
    if (this.props.animation) {
      LayoutAnimation.spring()
    }
  }
  render () {
    var c = this.props.children

    var idSeparator = (this.props.idSeparator) ? this.props.idSeparator : '|'
    var idSeparatorAccessibilityLabelIndex = (this.props.accessibilityLabel)
    ? this.props.accessibilityLabel.indexOf(idSeparator) : -1
    var idSeparatorTestIdIndex = (this.props.testID)
    ? this.props.testID.indexOf(idSeparator) : -1

    var accessibilityLabel = (this.props.accessibilityLabel)
    ? (idSeparatorAccessibilityLabelIndex !== -1
    ? this.props.accessibilityLabel.substring(0, idSeparatorAccessibilityLabelIndex) : this.props.accessibilityLabel) : 'radioButton'
    var testID = (this.props.testID)
    ? (idSeparatorTestIdIndex !== -1
    ? this.props.testID.substring(0, idSeparatorTestIdIndex) : this.props.testID) : 'radioButton'

    var accessibilityLabelIndex = (this.props.accessibilityLabel && idSeparatorAccessibilityLabelIndex !== -1)
    ? this.props.accessibilityLabel.substring(idSeparatorAccessibilityLabelIndex + 1) : ''
    var testIDIndex = (this.props.testID && testIDIndex !== -1)
    ? this.props.testID.split(testIDIndex + 1) : ''

    var renderContent = false
    renderContent = c ? (
      <View style={[
        Style.radioWrap,
        this.props.style,
        !this.props.labelHorizontal && Style.labelVerticalWrap
      ]}>
        {c}
      </View>
    ) : (
      <View style={[
        Style.radioWrap,
        this.props.style,
        !this.props.labelHorizontal && Style.labelVerticalWrap
      ]}>
        <RadioButtonInput {...this.props}
          accessibilityLabel={accessibilityLabel + 'Input' + accessibilityLabelIndex}
          testID={testID + 'Input' + testIDIndex} />
        <RadioButtonLabel {...this.props}
          accessibilityLabel={accessibilityLabel + 'Label' + accessibilityLabelIndex}
          testID={testID + 'Label' + testIDIndex} />
      </View>
    )
    return (
      <View style={this.props.wrapStyle}>
        {renderContent}
      </View>
    )
  }
}

export class RadioButtonInput extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      isSelected: false,
      buttonColor: props.buttonColor || '#2196f3'
    }
  }
  render () {
    var innerSize = {width: 20, height:20, borderRadius: 20/2 }
    var outerSize = {width: 20+10, height:20+10, borderRadius: (20+10)/2 }
    if (this.props.buttonSize) {
      innerSize.width = this.props.buttonSize
      innerSize.height = this.props.buttonSize
      innerSize.borderRadius = this.props.buttonSize /2
      outerSize.width = this.props.buttonSize + 10
      outerSize.height = this.props.buttonSize + 10
      outerSize.borderRadius = (this.props.buttonSize + 10) / 2
    }
    if (this.props.buttonOuterSize) {
      outerSize.width = this.props.buttonOuterSize
      outerSize.height = this.props.buttonOuterSize
      outerSize.borderRadius = this.props.buttonOuterSize / 2
    }
    var outerColor = this.props.buttonOuterColor
    var borderWidth = this.props.borderWidth || 3
    var innerColor = this.props.buttonInnerColor
    if (this.props.buttonColor) {
      outerColor = this.props.buttonColor
      innerColor = this.props.buttonColor
    }
    var c = (
      <View style={[
        Style.radioNormal,
        this.props.isSelected && Style.radioActive,
        this.props.isSelected && innerSize,
        this.props.isSelected && {backgroundColor:innerColor}
      ]}></View>
    )
    var radioStyle = [
      Style.radio,
      {
        borderColor:outerColor,
        borderWidth:borderWidth
      },
      this.props.buttonStyle,
      outerSize
    ]

    if (this.props.disabled) {
      return (
        <View style={this.props.buttonWrapStyle} >
          <View style={radioStyle}>
            {c}
          </View>
        </View>
      )
    }

    return (
      <View style={this.props.buttonWrapStyle} >
        <TouchableOpacity
          accessible={this.props.accessible}
          accessibilityLabel={this.props.accessibilityLabel}
          testID={this.props.testID}
          style={radioStyle}
          onPress={() => { this.props.onPress( this.props.obj.value, this.props.index) }
          }>
         {c}
        </TouchableOpacity>
      </View>
    )
  }
}

RadioButtonInput.defaultProps = {
  buttonInnerColor: '#2196f3',
  buttonOuterColor: '#2196f3',
  disabled: false
}

export class RadioButtonLabel extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      isSelected: false,
      buttonColor: '#2196f3',
    }
  }
  render () {
    return (
      <TouchableWithoutFeedback
        accessible={this.props.accessible}
        accessibilityLabel={this.props.accessibilityLabel}
        testID={this.props.testID}
        onPress={() => {
        if (!this.props.disabled) {
          this.props.onPress( this.props.obj.value, this.props.index)}
        }
      }>
        <View style={[
          this.props.labelWrapStyle,
          Style.labelWrapStyle,
        ]} >
          <Text style={[
            Style.radioLabel,
            !this.props.labelHorizontal && Style.labelVertical,
            {color: this.props.labelColor},
            this.props.labelStyle
          ]}>{this.props.obj.label}</Text>
        </View>
      </TouchableWithoutFeedback>
    )
  }
}
<commit_msg>Update SimpleRadioButton.js<commit_after>'use strict'

import Style from './Style.js'

var React = require('react')
var ReactNative = require('react-native')
var {
  Text,
  View,
  TouchableOpacity,
  TouchableWithoutFeedback,
  LayoutAnimation,
  Platform,
  UIManager
} = ReactNative

export default class RadioForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      is_active_index: props.initial
    }
    if (Platform.OS === 'android') {
      UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true);
    }
    this._renderButton = this._renderButton.bind(this);
  }
  static defaultProps = {
    radio_props: [],
    initial: 0,
    buttonColor: '#2196f3',
    selectedButtonColor: '#2196f3',
    formHorizontal: false,
    labelHorizontal: true,
    animation: true,
    labelColor: '#000',
    selectedLabelColor: '#000',
    wrapStyle: {},
    disabled: false
  }

  updateIsActiveIndex(index) {
    this.setState({ is_active_index: index });
    this.props.onPress(this.props.radio_props[index], index)
  }

  //This function is for clear the selection when we are using the library in multiple choice questions
  clearSelection(){
    this.setState({is_active_index:-1});
  }

  _renderButton(obj, i) {
    return (
      <RadioButton
        accessible={this.props.accessible}
        accessibilityLabel={(this.props.accessibilityLabel)
          ? (this.props.accessibilityLabel + '|' + i) : ('radioButton' + '|' + i)}
        testID={(this.props.testID)
          ? (this.props.testID + '|' + i) : ('radioButton' + '|' + i)}
        isSelected={this.state.is_active_index === i}
        obj={obj}
        key={i}
        index={i}
        buttonColor={this.state.is_active_index === i ? this.props.selectedButtonColor : this.props.buttonColor}
        buttonSize={this.props.buttonSize}
        buttonOuterSize={this.props.buttonOuterSize}
        labelHorizontal={this.props.labelHorizontal}
        labelColor={this.state.is_active_index === i ? this.props.selectedLabelColor : this.props.labelColor}
        labelStyle={this.props.labelStyle}
        style={this.props.radioStyle}
        animation={this.props.animation}
        disabled={this.props.disabled}
        onPress={(value, index) => {
          this.props.onPress(value, index)
          this.setState({is_active_index: index})
        }}
      />
    )
  }

  render() {
    var render_content = false
    if (this.props.radio_props.length) {
      render_content = this.props.radio_props.map(this._renderButton)
    } else {
      render_content = this.props.children
    }
    return (
      <View style={[
        Style.radioFrom,
        this.props.style,
        this.props.formHorizontal && Style.formHorizontal
      ]}>
        {render_content}
      </View>
    )
  }
}

export class RadioButton extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }
  shouldComponentUpdate(nextProps, nextState) {
    return true
  }
  static defaultProps = {
    isSelected: false,
    buttonColor: '#2196f3',
    selectedButtonColor: '#2196f3',
    labelHorizontal: true,
    disabled: false,
    idSeparator: '|'
  }
  componentWillUpdate () {
    if (this.props.animation) {
      LayoutAnimation.spring()
    }
  }
  render () {
    var c = this.props.children

    var idSeparator = (this.props.idSeparator) ? this.props.idSeparator : '|'
    var idSeparatorAccessibilityLabelIndex = (this.props.accessibilityLabel)
    ? this.props.accessibilityLabel.indexOf(idSeparator) : -1
    var idSeparatorTestIdIndex = (this.props.testID)
    ? this.props.testID.indexOf(idSeparator) : -1

    var accessibilityLabel = (this.props.accessibilityLabel)
    ? (idSeparatorAccessibilityLabelIndex !== -1
    ? this.props.accessibilityLabel.substring(0, idSeparatorAccessibilityLabelIndex) : this.props.accessibilityLabel) : 'radioButton'
    var testID = (this.props.testID)
    ? (idSeparatorTestIdIndex !== -1
    ? this.props.testID.substring(0, idSeparatorTestIdIndex) : this.props.testID) : 'radioButton'

    var accessibilityLabelIndex = (this.props.accessibilityLabel && idSeparatorAccessibilityLabelIndex !== -1)
    ? this.props.accessibilityLabel.substring(idSeparatorAccessibilityLabelIndex + 1) : ''
    var testIDIndex = (this.props.testID && testIDIndex !== -1)
    ? this.props.testID.split(testIDIndex + 1) : ''

    var renderContent = false
    renderContent = c ? (
      <View style={[
        Style.radioWrap,
        this.props.style,
        !this.props.labelHorizontal && Style.labelVerticalWrap
      ]}>
        {c}
      </View>
    ) : (
      <View style={[
        Style.radioWrap,
        this.props.style,
        !this.props.labelHorizontal && Style.labelVerticalWrap
      ]}>
        <RadioButtonInput {...this.props}
          accessibilityLabel={accessibilityLabel + 'Input' + accessibilityLabelIndex}
          testID={testID + 'Input' + testIDIndex} />
        <RadioButtonLabel {...this.props}
          accessibilityLabel={accessibilityLabel + 'Label' + accessibilityLabelIndex}
          testID={testID + 'Label' + testIDIndex} />
      </View>
    )
    return (
      <View style={this.props.wrapStyle}>
        {renderContent}
      </View>
    )
  }
}

export class RadioButtonInput extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      isSelected: false,
      buttonColor: props.buttonColor || '#2196f3'
    }
  }
  render () {
    var innerSize = {width: 20, height:20, borderRadius: 20/2 }
    var outerSize = {width: 20+10, height:20+10, borderRadius: (20+10)/2 }
    if (this.props.buttonSize) {
      innerSize.width = this.props.buttonSize
      innerSize.height = this.props.buttonSize
      innerSize.borderRadius = this.props.buttonSize /2
      outerSize.width = this.props.buttonSize + 10
      outerSize.height = this.props.buttonSize + 10
      outerSize.borderRadius = (this.props.buttonSize + 10) / 2
    }
    if (this.props.buttonOuterSize) {
      outerSize.width = this.props.buttonOuterSize
      outerSize.height = this.props.buttonOuterSize
      outerSize.borderRadius = this.props.buttonOuterSize / 2
    }
    var outerColor = this.props.buttonOuterColor
    var borderWidth = this.props.borderWidth || 3
    var innerColor = this.props.buttonInnerColor
    if (this.props.buttonColor) {
      outerColor = this.props.buttonColor
      innerColor = this.props.buttonColor
    }
    var c = (
      <View style={[
        Style.radioNormal,
        this.props.isSelected && Style.radioActive,
        this.props.isSelected && innerSize,
        this.props.isSelected && {backgroundColor:innerColor}
      ]}></View>
    )
    var radioStyle = [
      Style.radio,
      {
        borderColor:outerColor,
        borderWidth:borderWidth
      },
      this.props.buttonStyle,
      outerSize
    ]

    if (this.props.disabled) {
      return (
        <View style={this.props.buttonWrapStyle} >
          <View style={radioStyle}>
            {c}
          </View>
        </View>
      )
    }

    return (
      <View style={this.props.buttonWrapStyle} >
        <TouchableOpacity
          accessible={this.props.accessible}
          accessibilityLabel={this.props.accessibilityLabel}
          testID={this.props.testID}
          style={radioStyle}
          onPress={() => { this.props.onPress( this.props.obj.value, this.props.index) }
          }>
         {c}
        </TouchableOpacity>
      </View>
    )
  }
}

RadioButtonInput.defaultProps = {
  buttonInnerColor: '#2196f3',
  buttonOuterColor: '#2196f3',
  disabled: false
}

export class RadioButtonLabel extends React.Component {
  constructor (props) {
    super(props)
    this.state = {
      isSelected: false,
      buttonColor: '#2196f3',
    }
  }
  render () {
    return (
      <TouchableWithoutFeedback
        accessible={this.props.accessible}
        accessibilityLabel={this.props.accessibilityLabel}
        testID={this.props.testID}
        onPress={() => {
        if (!this.props.disabled) {
          this.props.onPress( this.props.obj.value, this.props.index)}
        }
      }>
        <View style={[
          this.props.labelWrapStyle,
          Style.labelWrapStyle,
        ]} >
          <Text style={[
            Style.radioLabel,
            !this.props.labelHorizontal && Style.labelVertical,
            {color: this.props.labelColor},
            this.props.labelStyle
          ]}>{this.props.obj.label}</Text>
        </View>
      </TouchableWithoutFeedback>
    )
  }
}
<|endoftext|>


<commit_before>UI.addSubObject({
  name:'say',
  mainFn:function(param){
    alert(param.word);
  },
  //isConstructor:false,
  properties:{
    test:'hoi',
  },
});
<commit_msg>Update say.js<commit_after>UI.say = {
 say:function(param){
   alert(param.word)
 },
}
<|endoftext|>


<commit_before>"use strict";
var logger = require('./logger');
var config = require('./config');
var net    = require('net');
var punycode = require('punycode');

// Regexp to match private IPv4 ranges
var re_private_ipv4 = /^(?:10|127|169\.254|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;

var public_suffix_list = {};
load_public_suffix_list();

exports.is_public_suffix = function (host) {
    if (!host) return false;
    host = host.toLowerCase();
    if (public_suffix_list[host]) return true;

    var up_one_level = host.split('.').slice(1).join('.'); // co.uk -> uk
    if (!up_one_level) return false;   // no dot?

    var wildHost = '*.' + up_one_level;
    if (public_suffix_list[wildHost]) {
        if (public_suffix_list['!'+host]) return false; // on exception list
        return true;           // matched a wildcard, ex: *.uk
    }

    try { var puny = punycode.toUnicode(host); }
    catch(e) {}
    if (puny && public_suffix_list[puny]) return true;

    return false;
};

exports.get_organizational_domain = function (host) {
    // the domain that was registered with a domain name registrar
    // See https://datatracker.ietf.org/doc/draft-kucherawy-dmarc-base/?include_text=1
    //   section 3.2

    if (!host) return null;
    host = host.toLowerCase();

    // www.example.com -> [ com, example, www ]
    var labels = host.split('.').reverse();

    // 4.3 Search the public suffix list for the name that matches the
    //     largest number of labels found in the subject DNS domain.
    var greatest = 0;
    for (var i = 1; i <= labels.length; i++) {
        if (!labels[i-1]) return null;                   // dot w/o label
        var tld = labels.slice(0,i).reverse().join('.');
        if (this.is_public_suffix(tld)) {
            greatest = +(i + 1);
        }
        else if (public_suffix_list['!'+tld]) {
            greatest = i;
        }
    }

    // 4.4 Construct a new DNS domain name using the name that matched
    //     from the public suffix list and prefixing to it the "x+1"th
    //     label from the subject domain.
    if (greatest === 0) return null;             // no valid TLD
    if (greatest  >  labels.length) return null; // not enough labels
    if (greatest === labels.length) return host; // same

    var orgName = labels.slice(0,greatest).reverse().join('.');
    return orgName;
};

var top_level_tlds = {};
var two_level_tlds = {};
var three_level_tlds = {};
load_tld_files();

exports.top_level_tlds = top_level_tlds;
exports.two_level_tlds = two_level_tlds;
exports.three_level_tlds = three_level_tlds;

exports.split_hostname = function(host,level) {
    if (!level || (level && !(level >= 1 && level <= 3))) {
        level = 2;
    }
    var split = host.toLowerCase().split(/\./).reverse();
    var domain = "";
    // TLD
    if (level >= 1 && split[0] && top_level_tlds[split[0]]) {
        domain = split.shift() + domain;
    }
    // 2nd TLD
    if (level >= 2 && split[0] && two_level_tlds[split[0] + '.' + domain]) {
        domain = split.shift() + '.' + domain;
    }
    // 3rd TLD
    if (level >= 3 && split[0] && three_level_tlds[split[0] + '.' + domain]) {
        domain = split.shift() + '.' + domain;
    }
    // Domain
    if (split[0]) {
        domain = split.shift() + '.' + domain;
    }
    return [split.reverse().join('.'), domain];
}

exports.long_to_ip = function (n) {
    var d = n%256;
    for (var i=3; i>0; i--) {
        n = Math.floor(n/256);
        d = n%256 + '.' + d;
    }
    return d;
}

exports.dec_to_hex = function (d) {
    return d.toString(16);
}

exports.hex_to_dec = function (h) {
    return parseInt(h, 16);
}

exports.ip_to_long = function (ip) {
    if (!net.isIPv4(ip)) {
        return false;
    }
    else {
        var d = ip.split('.');
        return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]);
    }
};

exports.is_ip_in_str = function(ip, str) {
    // Only IPv4 for now
    if (!str) { return false; }
    if (!ip) { return false; }
    if (net.isIPv4(ip)) {
        var host_part = (this.split_hostname(str,1))[0].toString();
        var ip_split = ip.split('.');
        // See if the 3rd and 4th octets appear in the string
        // We test the largest of the two octets first
        if (ip_split[3].length >= ip_split[2].length) {
            var oct4 = host_part.lastIndexOf(ip_split[3]);
            if (oct4 !== -1) {
                var oct3 = (host_part.substring(0, oct4) + host_part.substring(oct4 + ip_split[3].length));
                if (oct3.lastIndexOf(ip_split[2]) !== -1) {
                    return true;
                }
            }
        }
        else {
            var oct3 = host_part.indexOf(ip_split[2]);
            if (oct3 !== -1) {
                var oct4 = (host_part.substring(0, oct3) + host_part.substring(oct3 + ip_split[2].length));
                if (oct4.lastIndexOf(ip_split[3]) !== -1) {
                    return true;
                }
            }
        }
        // 1st and 2nd octets
        if (ip_split[1].length >= ip_split[2].length) {
            var oct2 = host_part.lastIndexOf(ip_split[1]);
            if (oct2 !== -1) {
                var oct1 = (host_part.substring(0, oct2) + host_part.substring(oct2 + ip_split[1].length));
                if (oct1.lastIndexOf(ip_split[0]) !== -1) {
                    return true;
                }
            }
        }
        else {
            var oct1 = host_part.lastIndexOf(ip_split[0]);
            if (oct1 !== -1) {
                var oct2 = (host_part.substring(0, oct1) + host_part.substring(oct1 + ip_split[0].length));
                if (oct2.lastIndexOf(ip_split[1]) !== -1) {
                    return true;
                }
            }
        }
        // Whole IP in hex
        var host_part_copy = host_part;
        var ip_hex = this.dec_to_hex(this.ip_to_long(ip));
        for (var i=0; i<4; i++) {
            var part = host_part_copy.indexOf(ip_hex.substring(i*2, (i*2)+2));
            if (part === -1) break;
            if (i === 3) return true;
            host_part_copy = host_part_copy.substring(0, part) + host_part_copy.substring(part+2);
        }
    }
    return false;
}

exports.is_rfc1918 = function (ip) {
    return (net.isIPv4(ip) && re_private_ipv4.test(ip));
}

exports.is_ipv4_literal = function (host) {
    return /^\[(\d{1,3}\.){3}\d{1,3}\]$/.test(host) ? true : false;
};

exports.same_ipv4_network = function (ip, ipList) {
    if (!ipList || !ipList.length) {
        logger.logerror('same_ipv4_network, no ip list!');
        return false;
    }
    if (!net.isIPv4(ip)) {
        logger.logerror('same_ipv4_network, IP is not IPv4!');
        return false;
    }

    var first3 = ip.split('.').slice(0,3).join('.');

    for (var i=0; i < ipList.length; i++) {
        if (!net.isIPv4(ipList[i])) {
            logger.logerror('same_ipv4_network, IP in list is not IPv4!');
            continue;
        }
        if (first3 === ipList[i].split('.').slice(0,3).join('.'))
            return true;
    }
    return false;
};

function load_tld_files () {
    config.get('top-level-tlds','list').forEach(function (tld) {
        top_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('two-level-tlds', 'list').forEach(function (tld) {
        two_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('three-level-tlds', 'list').forEach(function (tld) {
        three_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('extra-tlds', 'list').forEach(function (tld) {
        var s = tld.split(/\./);
        if (s.length === 2) {
            two_level_tlds[tld.toLowerCase()] = 1;
        }
        else if (s.length === 3) {
            three_level_tlds[tld.toLowerCase()] = 1;
        }
    });

    logger.loginfo('loaded TLD files:' +
    ' 1=' + Object.keys(top_level_tlds).length +
    ' 2=' + Object.keys(two_level_tlds).length +
    ' 3=' + Object.keys(three_level_tlds).length
    );
}

function load_public_suffix_list() {
    config.get('public-suffix-list','list').forEach(function (entry) {
        // Parsing rules: http://publicsuffix.org/list/
        // Each line is only read up to the first whitespace
        var suffix = entry.split(/\s/).shift().toLowerCase();

        // Each line which is not entirely whitespace or begins with a comment contains a rule.
        if (!suffix) return;                            // empty string
        if ('/' === suffix.substring(0,1)) return;      // comment

        // A rule may begin with a "!" (exclamation mark). If it does, it is
        // labelled as a "exception rule" and then treated as if the exclamation
        // mark is not present.
        if ('!' === suffix.substring(0,1)) {
            var eName = suffix.substring(1);   // remove ! prefix
            var up_one = suffix.split('.').slice(1).join('.'); // bbc.co.uk -> co.uk
            if (public_suffix_list[up_one]) {
                public_suffix_list[up_one].push(eName);
            }
            else if (public_suffix_list['*.'+up_one]) {
                public_suffix_list['*.'+up_one].push(eName);
            }
            else {
                logger.logerror("unable to find parent for exception: "+eName);
            }
        }

        public_suffix_list[suffix] = [];
    });
    var entries = Object.keys(public_suffix_list).length;
    logger.loginfo('loaded '+ entries +' Public Suffixes');
}

exports.same_ipv4_network = function (ip, ipList) {
    if (!ipList || !ipList.length) {
        logger.logerror('same_ipv4_network, no ip list!');
        return false;
    }
    if (!net.isIPv4(ip)) {
        logger.logerror('same_ipv4_network, IP is not IPv4!');
        return false;
    }

    var first3 = ip.split('.').slice(0,3).join('.');

    for (var i=0; i < ipList.length; i++) {
        if (!net.isIPv4(ipList[i])) {
            logger.logerror('same_ipv4_network, IP in list is not IPv4!');
            continue;
        }
        if (first3 === ipList[i].split('.').slice(0,3).join('.'))
            return true;
    }
    return false;
};

function load_tld_files () {
    config.get('top-level-tlds','list').forEach(function (tld) {
        top_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('two-level-tlds', 'list').forEach(function (tld) {
        two_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('three-level-tlds', 'list').forEach(function (tld) {
        three_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('extra-tlds', 'list').forEach(function (tld) {
        var s = tld.split(/\./);
        if (s.length === 2) {
            two_level_tlds[tld.toLowerCase()] = 1;
        }
        else if (s.length === 3) {
            three_level_tlds[tld.toLowerCase()] = 1;
        }
    });

    logger.loginfo('loaded TLD files:' +
    ' 1=' + Object.keys(top_level_tlds).length +
    ' 2=' + Object.keys(two_level_tlds).length +
    ' 3=' + Object.keys(three_level_tlds).length
    );
}

function loadPublicSuffixList() {
    config.get('public_suffix_list','list').forEach(function (entry) {
        // Parsing rules: http://publicsuffix.org/list/
        // Each line is only read up to the first whitespace
        var suffix = entry.split(/\s/).shift().toLowerCase();

        // Each line which is not entirely whitespace or begins with a comment contains a rule.
        if (!suffix) return;                            // empty string
        if ('/' === suffix.substring(0,1)) return;      // comment

        // A rule may begin with a "!" (exclamation mark). If it does, it is
        // labelled as a "exception rule" and then treated as if the exclamation
        // mark is not present.
        if ('!' === suffix.substring(0,1)) {
            var eName = suffix.substring(1);   // remove ! prefix
            var up_one = suffix.split('.').slice(1).join('.'); // bbc.co.uk -> co.uk
            if (public_suffix_list[up_one]) {
                public_suffix_list[up_one].push(eName);
            }
            else if (public_suffix_list['*.'+up_one]) {
                public_suffix_list['*.'+up_one].push(eName);
            }
            else {
                logger.logerror("unable to find parent for exception: "+eName);
            }
        }

        public_suffix_list[suffix] = [];
    });
    var entries = Object.keys(public_suffix_list).length;
    logger.loginfo('loaded '+ entries +' Public Suffixes');
}

exports.get_public_ip = function (cb) {
    var nu = this;
    if (nu.public_ip) {
        return cb(null, nu.public_ip);  // cache
    }

    // manual config override, for the cases where we can't figure it out
    if (config.get('smtp.ini').public_ip) {
        nu.public_ip = config.get('smtp.ini').public_ip;
        return cb(null, nu.public_ip);
    }

    try {
        nu.stun = require('vs-stun');
    }
    catch (e) {
        e.install = 'Please install stun: "npm install -g vs-stun"';
        logger.logerror(e.msg + "\n" + e.install);
        return cb(e);
    }

    var timeout = 10;
    var timer;

    var st_cb = function (error, socket) {
        if (timer) clearTimeout(timer);
        if (error) {
            return cb(error);
        };
        socket.close();
        /*          sample socket.stun response
         *
         *  { local: { host: '127.0.0.30', port: 26163 },
         *  public: { host: '50.115.0.94', port: 57345, family: 'IPv4' },
         *  type: 'Full Cone NAT'
         *  }
        */
        return cb(null, socket.stun.public.host);
    };

    // Connect to STUN Server
    nu.stun.connect({ host: get_stun_server(), port: 19302 }, st_cb);

    timer = setTimeout(function () {
        return cb(new Error('STUN timeout'));
    }, (timeout || 10) * 1000);
};

function get_stun_server () {
    // STUN servers by Google
    var servers = [
        'stun.l.google.com',
        'stun1.l.google.com',
        'stun2.l.google.com',
        'stun3.l.google.com',
        'stun4.l.google.com',
    ];
    return servers[Math.floor(Math.random()*servers.length)];
}
<commit_msg>remove duplicate methods<commit_after>"use strict";
var logger = require('./logger');
var config = require('./config');
var net    = require('net');
var punycode = require('punycode');

// Regexp to match private IPv4 ranges
var re_private_ipv4 = /^(?:10|127|169\.254|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\..*/;

var public_suffix_list = {};
load_public_suffix_list();

exports.is_public_suffix = function (host) {
    if (!host) return false;
    host = host.toLowerCase();
    if (public_suffix_list[host]) return true;

    var up_one_level = host.split('.').slice(1).join('.'); // co.uk -> uk
    if (!up_one_level) return false;   // no dot?

    var wildHost = '*.' + up_one_level;
    if (public_suffix_list[wildHost]) {
        if (public_suffix_list['!'+host]) return false; // on exception list
        return true;           // matched a wildcard, ex: *.uk
    }

    try { var puny = punycode.toUnicode(host); }
    catch(e) {}
    if (puny && public_suffix_list[puny]) return true;

    return false;
};

exports.get_organizational_domain = function (host) {
    // the domain that was registered with a domain name registrar
    // See https://datatracker.ietf.org/doc/draft-kucherawy-dmarc-base/?include_text=1
    //   section 3.2

    if (!host) return null;
    host = host.toLowerCase();

    // www.example.com -> [ com, example, www ]
    var labels = host.split('.').reverse();

    // 4.3 Search the public suffix list for the name that matches the
    //     largest number of labels found in the subject DNS domain.
    var greatest = 0;
    for (var i = 1; i <= labels.length; i++) {
        if (!labels[i-1]) return null;                   // dot w/o label
        var tld = labels.slice(0,i).reverse().join('.');
        if (this.is_public_suffix(tld)) {
            greatest = +(i + 1);
        }
        else if (public_suffix_list['!'+tld]) {
            greatest = i;
        }
    }

    // 4.4 Construct a new DNS domain name using the name that matched
    //     from the public suffix list and prefixing to it the "x+1"th
    //     label from the subject domain.
    if (greatest === 0) return null;             // no valid TLD
    if (greatest  >  labels.length) return null; // not enough labels
    if (greatest === labels.length) return host; // same

    var orgName = labels.slice(0,greatest).reverse().join('.');
    return orgName;
};

var top_level_tlds = {};
var two_level_tlds = {};
var three_level_tlds = {};
load_tld_files();

exports.top_level_tlds = top_level_tlds;
exports.two_level_tlds = two_level_tlds;
exports.three_level_tlds = three_level_tlds;

exports.split_hostname = function(host,level) {
    if (!level || (level && !(level >= 1 && level <= 3))) {
        level = 2;
    }
    var split = host.toLowerCase().split(/\./).reverse();
    var domain = "";
    // TLD
    if (level >= 1 && split[0] && top_level_tlds[split[0]]) {
        domain = split.shift() + domain;
    }
    // 2nd TLD
    if (level >= 2 && split[0] && two_level_tlds[split[0] + '.' + domain]) {
        domain = split.shift() + '.' + domain;
    }
    // 3rd TLD
    if (level >= 3 && split[0] && three_level_tlds[split[0] + '.' + domain]) {
        domain = split.shift() + '.' + domain;
    }
    // Domain
    if (split[0]) {
        domain = split.shift() + '.' + domain;
    }
    return [split.reverse().join('.'), domain];
}

exports.long_to_ip = function (n) {
    var d = n%256;
    for (var i=3; i>0; i--) {
        n = Math.floor(n/256);
        d = n%256 + '.' + d;
    }
    return d;
}

exports.dec_to_hex = function (d) {
    return d.toString(16);
}

exports.hex_to_dec = function (h) {
    return parseInt(h, 16);
}

exports.ip_to_long = function (ip) {
    if (!net.isIPv4(ip)) {
        return false;
    }
    else {
        var d = ip.split('.');
        return ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]);
    }
};

exports.is_ip_in_str = function(ip, str) {
    // Only IPv4 for now
    if (!str) { return false; }
    if (!ip) { return false; }
    if (net.isIPv4(ip)) {
        var host_part = (this.split_hostname(str,1))[0].toString();
        var ip_split = ip.split('.');
        // See if the 3rd and 4th octets appear in the string
        // We test the largest of the two octets first
        if (ip_split[3].length >= ip_split[2].length) {
            var oct4 = host_part.lastIndexOf(ip_split[3]);
            if (oct4 !== -1) {
                var oct3 = (host_part.substring(0, oct4) + host_part.substring(oct4 + ip_split[3].length));
                if (oct3.lastIndexOf(ip_split[2]) !== -1) {
                    return true;
                }
            }
        }
        else {
            var oct3 = host_part.indexOf(ip_split[2]);
            if (oct3 !== -1) {
                var oct4 = (host_part.substring(0, oct3) + host_part.substring(oct3 + ip_split[2].length));
                if (oct4.lastIndexOf(ip_split[3]) !== -1) {
                    return true;
                }
            }
        }
        // 1st and 2nd octets
        if (ip_split[1].length >= ip_split[2].length) {
            var oct2 = host_part.lastIndexOf(ip_split[1]);
            if (oct2 !== -1) {
                var oct1 = (host_part.substring(0, oct2) + host_part.substring(oct2 + ip_split[1].length));
                if (oct1.lastIndexOf(ip_split[0]) !== -1) {
                    return true;
                }
            }
        }
        else {
            var oct1 = host_part.lastIndexOf(ip_split[0]);
            if (oct1 !== -1) {
                var oct2 = (host_part.substring(0, oct1) + host_part.substring(oct1 + ip_split[0].length));
                if (oct2.lastIndexOf(ip_split[1]) !== -1) {
                    return true;
                }
            }
        }
        // Whole IP in hex
        var host_part_copy = host_part;
        var ip_hex = this.dec_to_hex(this.ip_to_long(ip));
        for (var i=0; i<4; i++) {
            var part = host_part_copy.indexOf(ip_hex.substring(i*2, (i*2)+2));
            if (part === -1) break;
            if (i === 3) return true;
            host_part_copy = host_part_copy.substring(0, part) + host_part_copy.substring(part+2);
        }
    }
    return false;
}

exports.is_rfc1918 = function (ip) {
    return (net.isIPv4(ip) && re_private_ipv4.test(ip));
}

exports.is_ipv4_literal = function (host) {
    return /^\[(\d{1,3}\.){3}\d{1,3}\]$/.test(host) ? true : false;
};

exports.same_ipv4_network = function (ip, ipList) {
    if (!ipList || !ipList.length) {
        logger.logerror('same_ipv4_network, no ip list!');
        return false;
    }
    if (!net.isIPv4(ip)) {
        logger.logerror('same_ipv4_network, IP is not IPv4!');
        return false;
    }

    var first3 = ip.split('.').slice(0,3).join('.');

    for (var i=0; i < ipList.length; i++) {
        if (!net.isIPv4(ipList[i])) {
            logger.logerror('same_ipv4_network, IP in list is not IPv4!');
            continue;
        }
        if (first3 === ipList[i].split('.').slice(0,3).join('.'))
            return true;
    }
    return false;
};

function load_public_suffix_list() {
    config.get('public-suffix-list','list').forEach(function (entry) {
        // Parsing rules: http://publicsuffix.org/list/
        // Each line is only read up to the first whitespace
        var suffix = entry.split(/\s/).shift().toLowerCase();

        // Each line which is not entirely whitespace or begins with a comment contains a rule.
        if (!suffix) return;                            // empty string
        if ('/' === suffix.substring(0,1)) return;      // comment

        // A rule may begin with a "!" (exclamation mark). If it does, it is
        // labelled as a "exception rule" and then treated as if the exclamation
        // mark is not present.
        if ('!' === suffix.substring(0,1)) {
            var eName = suffix.substring(1);   // remove ! prefix
            var up_one = suffix.split('.').slice(1).join('.'); // bbc.co.uk -> co.uk
            if (public_suffix_list[up_one]) {
                public_suffix_list[up_one].push(eName);
            }
            else if (public_suffix_list['*.'+up_one]) {
                public_suffix_list['*.'+up_one].push(eName);
            }
            else {
                logger.logerror("unable to find parent for exception: "+eName);
            }
        }

        public_suffix_list[suffix] = [];
    });
    var entries = Object.keys(public_suffix_list).length;
    logger.loginfo('loaded '+ entries +' Public Suffixes');
}

exports.same_ipv4_network = function (ip, ipList) {
    if (!ipList || !ipList.length) {
        logger.logerror('same_ipv4_network, no ip list!');
        return false;
    }
    if (!net.isIPv4(ip)) {
        logger.logerror('same_ipv4_network, IP is not IPv4!');
        return false;
    }

    var first3 = ip.split('.').slice(0,3).join('.');

    for (var i=0; i < ipList.length; i++) {
        if (!net.isIPv4(ipList[i])) {
            logger.logerror('same_ipv4_network, IP in list is not IPv4!');
            continue;
        }
        if (first3 === ipList[i].split('.').slice(0,3).join('.'))
            return true;
    }
    return false;
};

function load_tld_files () {
    config.get('top-level-tlds','list').forEach(function (tld) {
        top_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('two-level-tlds', 'list').forEach(function (tld) {
        two_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('three-level-tlds', 'list').forEach(function (tld) {
        three_level_tlds[tld.toLowerCase()] = 1;
    });

    config.get('extra-tlds', 'list').forEach(function (tld) {
        var s = tld.split(/\./);
        if (s.length === 2) {
            two_level_tlds[tld.toLowerCase()] = 1;
        }
        else if (s.length === 3) {
            three_level_tlds[tld.toLowerCase()] = 1;
        }
    });

    logger.loginfo('loaded TLD files:' +
    ' 1=' + Object.keys(top_level_tlds).length +
    ' 2=' + Object.keys(two_level_tlds).length +
    ' 3=' + Object.keys(three_level_tlds).length
    );
}

exports.get_public_ip = function (cb) {
    var nu = this;
    if (nu.public_ip) {
        return cb(null, nu.public_ip);  // cache
    }

    // manual config override, for the cases where we can't figure it out
    if (config.get('smtp.ini').public_ip) {
        nu.public_ip = config.get('smtp.ini').public_ip;
        return cb(null, nu.public_ip);
    }

    try {
        nu.stun = require('vs-stun');
    }
    catch (e) {
        e.install = 'Please install stun: "npm install -g vs-stun"';
        logger.logerror(e.msg + "\n" + e.install);
        return cb(e);
    }

    var timeout = 10;
    var timer;

    var st_cb = function (error, socket) {
        if (timer) clearTimeout(timer);
        if (error) {
            return cb(error);
        };
        socket.close();
        /*          sample socket.stun response
         *
         *  { local: { host: '127.0.0.30', port: 26163 },
         *  public: { host: '50.115.0.94', port: 57345, family: 'IPv4' },
         *  type: 'Full Cone NAT'
         *  }
        */
        return cb(null, socket.stun.public.host);
    };

    // Connect to STUN Server
    nu.stun.connect({ host: get_stun_server(), port: 19302 }, st_cb);

    timer = setTimeout(function () {
        return cb(new Error('STUN timeout'));
    }, (timeout || 10) * 1000);
};

function get_stun_server () {
    // STUN servers by Google
    var servers = [
        'stun.l.google.com',
        'stun1.l.google.com',
        'stun2.l.google.com',
        'stun3.l.google.com',
        'stun4.l.google.com',
    ];
    return servers[Math.floor(Math.random()*servers.length)];
}
<|endoftext|>


<commit_before>"no use strict";

var console = {
    log: function(msg) {
        postMessage({type: "log", data: msg});
    }
};
var window = {
    console: console
};

var normalizeModule = function(parentId, moduleName) {
    // normalize plugin requires
    if (moduleName.indexOf("!") !== -1) {
        var chunks = moduleName.split("!");
        return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
    }
    // normalize relative requires
    if (moduleName.charAt(0) == ".") {
        var base = parentId.split("/").slice(0, -1).join("/");
        var moduleName = base + "/" + moduleName;

        while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
            var previous = moduleName;
            var moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
        }
    }

    return moduleName;
};

var require = function(parentId, id) {
    var id = normalizeModule(parentId, id);

    var module = require.modules[id];
    if (module) {
        if (!module.initialized) {
            module.initialized = true;
            module.exports = module.factory().exports;
        }
        return module.exports;
    }

    var chunks = id.split("/");
    chunks[0] = require.tlns[chunks[0]] || chunks[0];
    var path = chunks.join("/") + ".js";

    require.id = id;
    importScripts(path);
    return require(parentId, id);
};

require.modules = {};
require.tlns = {};

var define = function(id, deps, factory) {
    if (arguments.length == 2) {
        factory = deps;
        if (typeof id != "string") {
            deps = id;
            id = require.id;
        }
    } else if (arguments.length == 1) {
        factory = id;
        id = require.id;
    }

    if (id.indexOf("text!") === 0)
        return;

    var req = function(deps, factory) {
        return require(id, deps, factory);
    };

    require.modules[id] = {
        factory: function() {
            var module = {
                exports: {}
            };
            var returnExports = factory(req, module.exports, module);
            if (returnExports)
                module.exports = returnExports;
            return module;
        }
    };
};

function initBaseUrls(topLevelNamespaces) {
    require.tlns = topLevelNamespaces;
}

function initSender() {

    var EventEmitter = require(null, "ace/lib/event_emitter").EventEmitter;
    var oop = require(null, "ace/lib/oop");

    var Sender = function() {};

    (function() {

        oop.implement(this, EventEmitter);

        this.callback = function(data, callbackId) {
            postMessage({
                type: "call",
                id: callbackId,
                data: data
            });
        };

        this.emit = function(name, data) {
            postMessage({
                type: "event",
                name: name,
                data: data
            });
        };

    }).call(Sender.prototype);

    return new Sender();
}

var main;
var sender;

onmessage = function(e) {
    var msg = e.data;
    if (msg.command) {
        main[msg.command].apply(main, msg.args);
    }
    else if (msg.init) {
        initBaseUrls(msg.tlns);
        require(null, "ace/lib/fixoldbrowsers");
        sender = initSender();
        var clazz = require(null, msg.module)[msg.classname];
        main = new clazz(sender);
    }
    else if (msg.event && sender) {
        sender._emit(msg.event, msg.data);
    }
};
<commit_msg>Add varargs console.log to worker<commit_after>"no use strict";

var console = {
    log: function(msgs) {
        postMessage({type: "log", data: arguments.join(" ")});
    }
};
var window = {
    console: console
};

var normalizeModule = function(parentId, moduleName) {
    // normalize plugin requires
    if (moduleName.indexOf("!") !== -1) {
        var chunks = moduleName.split("!");
        return normalizeModule(parentId, chunks[0]) + "!" + normalizeModule(parentId, chunks[1]);
    }
    // normalize relative requires
    if (moduleName.charAt(0) == ".") {
        var base = parentId.split("/").slice(0, -1).join("/");
        var moduleName = base + "/" + moduleName;

        while(moduleName.indexOf(".") !== -1 && previous != moduleName) {
            var previous = moduleName;
            var moduleName = moduleName.replace(/\/\.\//, "/").replace(/[^\/]+\/\.\.\//, "");
        }
    }

    return moduleName;
};

var require = function(parentId, id) {
    var id = normalizeModule(parentId, id);

    var module = require.modules[id];
    if (module) {
        if (!module.initialized) {
            module.initialized = true;
            module.exports = module.factory().exports;
        }
        return module.exports;
    }

    var chunks = id.split("/");
    chunks[0] = require.tlns[chunks[0]] || chunks[0];
    var path = chunks.join("/") + ".js";

    require.id = id;
    importScripts(path);
    return require(parentId, id);
};

require.modules = {};
require.tlns = {};

var define = function(id, deps, factory) {
    if (arguments.length == 2) {
        factory = deps;
        if (typeof id != "string") {
            deps = id;
            id = require.id;
        }
    } else if (arguments.length == 1) {
        factory = id;
        id = require.id;
    }

    if (id.indexOf("text!") === 0)
        return;

    var req = function(deps, factory) {
        return require(id, deps, factory);
    };

    require.modules[id] = {
        factory: function() {
            var module = {
                exports: {}
            };
            var returnExports = factory(req, module.exports, module);
            if (returnExports)
                module.exports = returnExports;
            return module;
        }
    };
};

function initBaseUrls(topLevelNamespaces) {
    require.tlns = topLevelNamespaces;
}

function initSender() {

    var EventEmitter = require(null, "ace/lib/event_emitter").EventEmitter;
    var oop = require(null, "ace/lib/oop");

    var Sender = function() {};

    (function() {

        oop.implement(this, EventEmitter);

        this.callback = function(data, callbackId) {
            postMessage({
                type: "call",
                id: callbackId,
                data: data
            });
        };

        this.emit = function(name, data) {
            postMessage({
                type: "event",
                name: name,
                data: data
            });
        };

    }).call(Sender.prototype);

    return new Sender();
}

var main;
var sender;

onmessage = function(e) {
    var msg = e.data;
    if (msg.command) {
        main[msg.command].apply(main, msg.args);
    }
    else if (msg.init) {
        initBaseUrls(msg.tlns);
        require(null, "ace/lib/fixoldbrowsers");
        sender = initSender();
        var clazz = require(null, msg.module)[msg.classname];
        main = new clazz(sender);
    }
    else if (msg.event && sender) {
        sender._emit(msg.event, msg.data);
    }
};
<|endoftext|>


<commit_before>(function() {
/**
 * PLUTO
 * Native HTML Template Rendering
 *
 *
 * The MIT License (MIT)
 * Copyright (c) 2013 Roi Avinoam
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
class Template extends HTMLTemplateElement {
    render(obj) {
        var compiled = this.compile()
        return new Renderer(compiled).render(obj)
    }

    compile() {
        var exprs = []
        var elements = [{ el: this.content, path: [] }]
        while (elements.length > 0) {
            var { el, path } = elements.shift()

            // inner content expressions
            if (el.nodeName === '#text') {
                var expr = isExpressions(el.textContent)
                if (expr) {
                    exprs.push({ expr, path })
                }
            }

            // attributes
            [].forEach.call(el.attributes || [], function(attr) {
                var expr = isExpressions(attr.value)
                if (expr !== null) {
                    attr = attr.name
                    var evName, prop
                    if (attr.startsWith('on-')) {
                        evName = attr.slice(3)
                    } else {
                        prop = snakeToCamelCase(attr)
                    }
                    exprs.push({ expr, path, attr, evName, prop })
                }
            }, this)

            // children, enqueue.
            el.childNodes.forEach(function(el, i) {
                maybeUpgrade(el)
                var subpath = path.concat(['childNodes', i])
                if (el instanceof Template) {
                    exprs.push({ path: subpath, tpl: true })
                    return
                }

                elements.push({ el, path: subpath })
            })
        }

        // remove attributes or expressions before rendering in order to hide
        // the placeholder expressions from the constructor of custom elements.
        var clone = this.cloneNode(true)
        exprs.forEach(function(expr) {
            var el = select(clone.content, expr.path)
            if (!expr.attr) {
                el.textContent = ''
            } else {
                el.removeAttribute(expr.attr)
            }
        }, this)

        clone.items = (obj) => [[obj.item]]
        var repeat = this.getAttribute('repeat')
        if (repeat) {
            clone.items = compileExpressions([{ expr: repeat }])
        }

        var cond = this.getAttribute('if')
        if (cond) {
            var items = compileExpressions([{ expr: cond }])
            clone.items = (obj) => items(obj).map(Boolean) // coerce to bool
        }

        // we opt to compile the repeat/cond expressions separately than the
        // rest of this template - because (a) the template might relay on a
        // repeated ${item} property that doesn't yet exist in the repeat
        // expression, and (b) it's must smaller/faster than the complete
        // expressions list.
        // NB: It might not be that beneficial for cond though.
        clone.exprs = Object.assign(exprs, { eval: compileExpressions(exprs) })
        return clone
    }
}

class Renderer {
    constructor(tpl) {
        this.tpl = tpl
        this.children = []
        this.exprs = tpl.exprs
        this.items = tpl.items
    }

    remove() {
        while (this.children.length > 0) {
            this.children.pop().remove()
        }
    }

    init() {
        var doc = new DocumentFragment()
        doc.render = (obj) => (this.render(obj), doc)
        doc.remove = () => this.remove()

        this.placeholder = document.createTextNode('')
        doc.appendChild(this.placeholder)

        return doc
    }

    render(obj) {
        if (!this._doc) {
            this._doc = this.init()
        }

        var items = this.items(obj)[0] || []
        var item = obj.item
        if (!Array.isArray(items) && typeof items === 'object') {
            items = Object.keys(items).map(function(k) {
                return { key: k, value: items[k] }
            })
        }

        if (typeof items === 'boolean') {
            items = Number(items) // 0 or 1
        }

        if (typeof items === 'number') {
            items = new Array(items) // range-items, repeat N times.
            items = Array.from(items).map(() => item)
        }

        // remove obsolete items
        while (this.children.length > items.length) {
            this.children.pop().remove()
        }

        // update existing items
        for (var i = 0; i < this.children.length; i += 1) {
            obj.item = items[i]
            this.children[i].render(obj)
        }

        // create new items
        while (this.children.length < items.length) {
            var i = this.children.length
            obj.item = items[i]
            var doc = this._renderOne(obj)// new Renderer(this.tpl).render(obj)
            this.children.push(doc)
            this.placeholder.before(doc)
        }

        obj.item = item // restore previous item value.
        return this._doc
    }

    _renderOne(obj) {
        var doc = document.importNode(this.tpl.content, true)
        // doc.render = (obj) => (this.render(obj), doc)
        // doc.remove = () => this.remove()

        // generate hard links from expressions to the generated elements in
        // order to avoid re-computing them on every render.
        doc.paths = this.exprs.reduce(function (paths, expr, idx) {
            var el = select(doc, expr.path)

            if (expr.tpl) {
                el.render = function() {
                    delete el.render
                    var subdoc = pluto(this).render(obj)
                    this.replaceWith(subdoc)
                    this.render = subdoc.render.bind(subdoc)
                    this.remove = subdoc.remove.bind(subdoc)
                }
            }

            paths[idx] = { el }

            return paths
        }, {})

        // copy the list of generated elements from the template in order
        // to support removals
        doc.generated = [].map.call(doc.childNodes, child => child)

        doc.remove = function() {
            while(this.generated.length > 0) {
                this.generated.pop().remove()
            }
        }

        doc.render = function(obj) {
            var values = this.exprs.eval(obj)
            for (var i = 0 ; i < this.exprs.length ; i += 1) {
                var expr = this.exprs[i]
                var { el, listener } = doc.paths[i]
                var v = values[i]

                // nested template
                if (expr.tpl) {
                    el.render(obj)
                    continue
                }

                // event handlers
                if (expr.evName) {
                    if (listener) {
                        el.removeEventListener(expr.evName, listener)
                    }

                    if (typeof v === 'function') {
                        v = v._bound || v
                        el.addEventListener(expr.evName, v)
                        doc.paths[i].listener = v // remember it for next render
                    }

                    continue
                }

                // handle flat text
                if (!expr.attr) {
                    el.textContent = v || ''
                    continue
                }

                // set attributes
                if (v === undefined) {
                    el[expr.prop] = undefined
                } else {
                    el[expr.prop] = v
                    if (expr.attr === 'class' && typeof v === 'object') {
                        if (!Array.isArray(v)) {
                            v = Object.keys(v).filter(function (k) {
                                return v[k]
                            })
                        }

                        v = v.join(' ')
                    } else if (expr.attr === 'style' && typeof v === 'object') {
                        v = Object.keys(v).map(function(k) {
                            return k + ': ' + v[k]
                        }).join('; ')
                    }

                    if (['class', 'style'].indexOf(expr.attr) !== -1) {
                        if (!v) {
                            el.removeAttribute(expr.attr)
                        } else {
                            el.setAttribute(expr.attr, v)
                        }
                    }
                }
            }
            return doc
        }.bind(this)

        return doc.render(obj)
    }
}

// -- HELPER FUNCTIONS

function maybeUpgrade(el) {
    // don't match #text, #comment, etc.
    if (el.nodeName[0] !== '#' && el.matches('template')) {
        pluto(el) // auto-upgrade nested templates.
    }
}

// Searches for an element from root based on the property-path to the child
// example: root = <body>, path = childNodes.3.childNode.7. Resolved by walking
// the path down to the child.
function select(root, path) {
    var current = root
    for (var i = 0; current !== undefined && i < path.length; i += 1) {
        current = current[path[i]]
    }
    return current
}

const SNAKE_RE = /-([a-z])/g
function snakeToCamelCase(s) {
    return s.replace(SNAKE_RE, g => g[1].toUpperCase())
}

// extract expressions in template-literal syntax out of a string
var EXPR_RE = /\$\{[^\}]*\}/
function isExpressions(s) {
    return EXPR_RE.test(s) ? s : null
}

// compile a list of template-literal expressions into a function that evaluates
// these expression for the provided input object
function compileExpressions(exprs) {
    var refs = []
    var code = 'this.__plutoT || (this.__plutoT = T.bind(this));\n'
    code += exprs.map(function(expr, i) {
        if (expr.expr) {
            refs = refs.concat(getIdentifiers(expr.expr))
        }

        return `arguments[0][${i}] = this.__plutoT\`${expr.expr}\``
    }).join(';\n')

    var keys = refs.reduce((keys, k) => (keys[k] = true, keys), {})
    var locals = `var { ${Object.keys(keys)} } = this`
    var fn = eval('(function () {\n' + locals + '\n' + code + '\n})')
    return function(obj) {
        var res = []
        try {
            fn.call(obj, res)
        } catch (e) {
            console.warn(fn)
            throw e
        }

        return res
    }

    function T(s, v) {
        if (arguments.length > 2 || typeof v === 'string') {
            return String.raw.apply(null, arguments)
        }

        if (typeof v === 'function' && this[v.name] === v) {
            if (v._plutoBound !== this) {
                v._plutoBound = v.bind(this)
            }
            return v._plutoBound
        }

        return v
    }
}

// generate the list of identifiers found in the code.
function getIdentifiers(expr) {
    var re = /[$A-Z_][0-9A-Z_$]*/ig
    var whitespace = ' \n\r\t'
    var disallowed = '\'\".'
    var skip = ['true', 'false', 'if', 'for', 'while', 'do', 'try', 'catch',
        'break', 'continue', 'switch', 'throw', 'this', 'instanceof', 'in',
        'function', 'delete', 'default', 'case', 'debugger', 'const', 'var',
        'with', 'typeof', 'super', 'class', 'new', 'null', 'return', 'let',
        'import', 'else', 'enum', 'extends', 'finally', '$']

    // We first match for the valid identifier, and then check the previous
    // non-whitespace character preceeding the identifier to verify that it's
    // not a string or nested element.
    var refs = {}
    var match
    while (match = re.exec(expr)) {
        if (skip.indexOf(match[0]) !== -1) {
            continue // skipped or reserved keyword
        }

        if (window[match[0]] !== undefined) {
            continue // keep global functions (Object, Array, etc.)
        }

        var lastChar = undefined
        do {
            match.index -= 1
            if (whitespace.indexOf(expr[match.index]) === -1) {
                lastChar = expr[match.index]
            }
        } while (match.index > -1 && !lastChar)

        if (disallowed.indexOf(lastChar) === -1) {
            refs[match[0]] = true
        }
    }

    return Object.keys(refs)
}

// upgrade an element
// NOTE this will be unnecessary with customElements
function pluto(el) {
    if (typeof el === 'string') {
        // support HTML-imported selections
        var doc = document._currentScript // used by pollyfills
            || document.currentScript // native.
            || document // not an import.
        el = (doc.ownerDocument || doc).querySelector(el)
    }

    return !el || el instanceof Template
        ? el
        : Object.setPrototypeOf(el, Template.prototype)
}

pluto.Template = Template
pluto.RepeatRenderer = Renderer
window.pluto = pluto
})();

(function() {

    // placed here in order to have its own scope clear of any of the pluto
    // local variables.
    pluto._eval = function(code) {
        return eval(code)
    }
})();
<commit_msg>Rename 'children' to 'elements' because this list doesn't necessarily contains child elements (as in the case of repeated templates), but a list of generated elements<commit_after>(function() {
/**
 * PLUTO
 * Native HTML Template Rendering
 *
 *
 * The MIT License (MIT)
 * Copyright (c) 2013 Roi Avinoam
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
class Template extends HTMLTemplateElement {
    render(obj) {
        var compiled = this.compile()
        return new Renderer(compiled).render(obj)
    }

    compile() {
        var exprs = []
        var elements = [{ el: this.content, path: [] }]
        while (elements.length > 0) {
            var { el, path } = elements.shift()

            // inner content expressions
            if (el.nodeName === '#text') {
                var expr = isExpressions(el.textContent)
                if (expr) {
                    exprs.push({ expr, path })
                }
            }

            // attributes
            [].forEach.call(el.attributes || [], function(attr) {
                var expr = isExpressions(attr.value)
                if (expr !== null) {
                    attr = attr.name
                    var evName, prop
                    if (attr.startsWith('on-')) {
                        evName = attr.slice(3)
                    } else {
                        prop = snakeToCamelCase(attr)
                    }
                    exprs.push({ expr, path, attr, evName, prop })
                }
            }, this)

            // children, enqueue.
            el.childNodes.forEach(function(el, i) {
                maybeUpgrade(el)
                var subpath = path.concat(['childNodes', i])
                if (el instanceof Template) {
                    exprs.push({ path: subpath, tpl: true })
                    return
                }

                elements.push({ el, path: subpath })
            })
        }

        // remove attributes or expressions before rendering in order to hide
        // the placeholder expressions from the constructor of custom elements.
        var clone = this.cloneNode(true)
        exprs.forEach(function(expr) {
            var el = select(clone.content, expr.path)
            if (!expr.attr) {
                el.textContent = ''
            } else {
                el.removeAttribute(expr.attr)
            }
        }, this)

        clone.items = (obj) => [[obj.item]]
        var repeat = this.getAttribute('repeat')
        if (repeat) {
            clone.items = compileExpressions([{ expr: repeat }])
        }

        var cond = this.getAttribute('if')
        if (cond) {
            var items = compileExpressions([{ expr: cond }])
            clone.items = (obj) => items(obj).map(Boolean) // coerce to bool
        }

        // we opt to compile the repeat/cond expressions separately than the
        // rest of this template - because (a) the template might relay on a
        // repeated ${item} property that doesn't yet exist in the repeat
        // expression, and (b) it's must smaller/faster than the complete
        // expressions list.
        // NB: It might not be that beneficial for cond though.
        clone.exprs = Object.assign(exprs, { eval: compileExpressions(exprs) })
        return clone
    }
}

class Renderer {
    constructor(tpl) {
        this.tpl = tpl
        this.elements = []
        this.exprs = tpl.exprs
        this.items = tpl.items
    }

    remove() {
        while (this.elements.length > 0) {
            this.elements.pop().remove()
        }
    }

    init() {
        var doc = new DocumentFragment()
        doc.render = (obj) => (this.render(obj), doc)
        doc.remove = () => this.remove()

        this.placeholder = document.createTextNode('')
        doc.appendChild(this.placeholder)

        return doc
    }

    render(obj) {
        if (!this._doc) {
            this._doc = this.init()
        }

        var items = this.items(obj)[0] || []
        var item = obj.item
        if (!Array.isArray(items) && typeof items === 'object') {
            items = Object.keys(items).map(function(k) {
                return { key: k, value: items[k] }
            })
        }

        if (typeof items === 'boolean') {
            items = Number(items) // 0 or 1
        }

        if (typeof items === 'number') {
            items = new Array(items) // range-items, repeat N times.
            items = Array.from(items).map(() => item)
        }

        // remove obsolete items
        while (this.elements.length > items.length) {
            this.elements.pop().remove()
        }

        // update existing items
        for (var i = 0; i < this.elements.length; i += 1) {
            obj.item = items[i]
            this.elements[i].render(obj)
        }

        // create new items
        while (this.elements.length < items.length) {
            var i = this.elements.length
            obj.item = items[i]
            var doc = this._renderOne(obj)// new Renderer(this.tpl).render(obj)
            this.elements.push(doc)
            this.placeholder.before(doc)
        }

        obj.item = item // restore previous item value.
        return this._doc
    }

    _renderOne(obj) {
        var doc = document.importNode(this.tpl.content, true)
        // doc.render = (obj) => (this.render(obj), doc)
        // doc.remove = () => this.remove()

        // generate hard links from expressions to the generated elements in
        // order to avoid re-computing them on every render.
        doc.paths = this.exprs.reduce(function (paths, expr, idx) {
            var el = select(doc, expr.path)

            if (expr.tpl) {
                el.render = function() {
                    delete el.render
                    var subdoc = pluto(this).render(obj)
                    this.replaceWith(subdoc)
                    this.render = subdoc.render.bind(subdoc)
                    this.remove = subdoc.remove.bind(subdoc)
                }
            }

            paths[idx] = { el }

            return paths
        }, {})

        // copy the list of generated elements from the template in order
        // to support removals
        doc.elements = [].map.call(doc.childNodes, child => child)

        doc.remove = function() {
            while(this.elements.length > 0) {
                this.elements.pop().remove()
            }
        }

        doc.render = function(obj) {
            var values = this.exprs.eval(obj)
            for (var i = 0 ; i < this.exprs.length ; i += 1) {
                var expr = this.exprs[i]
                var { el, listener } = doc.paths[i]
                var v = values[i]

                // nested template
                if (expr.tpl) {
                    el.render(obj)
                    continue
                }

                // event handlers
                if (expr.evName) {
                    if (listener) {
                        el.removeEventListener(expr.evName, listener)
                    }

                    if (typeof v === 'function') {
                        v = v._bound || v
                        el.addEventListener(expr.evName, v)
                        doc.paths[i].listener = v // remember it for next render
                    }

                    continue
                }

                // handle flat text
                if (!expr.attr) {
                    el.textContent = v || ''
                    continue
                }

                // set attributes
                if (v === undefined) {
                    el[expr.prop] = undefined
                } else {
                    el[expr.prop] = v
                    if (expr.attr === 'class' && typeof v === 'object') {
                        if (!Array.isArray(v)) {
                            v = Object.keys(v).filter(function (k) {
                                return v[k]
                            })
                        }

                        v = v.join(' ')
                    } else if (expr.attr === 'style' && typeof v === 'object') {
                        v = Object.keys(v).map(function(k) {
                            return k + ': ' + v[k]
                        }).join('; ')
                    }

                    if (['class', 'style'].indexOf(expr.attr) !== -1) {
                        if (!v) {
                            el.removeAttribute(expr.attr)
                        } else {
                            el.setAttribute(expr.attr, v)
                        }
                    }
                }
            }
            return doc
        }.bind(this)

        return doc.render(obj)
    }
}

// -- HELPER FUNCTIONS

function maybeUpgrade(el) {
    // don't match #text, #comment, etc.
    if (el.nodeName[0] !== '#' && el.matches('template')) {
        pluto(el) // auto-upgrade nested templates.
    }
}

// Searches for an element from root based on the property-path to the child
// example: root = <body>, path = childNodes.3.childNode.7. Resolved by walking
// the path down to the child.
function select(root, path) {
    var current = root
    for (var i = 0; current !== undefined && i < path.length; i += 1) {
        current = current[path[i]]
    }
    return current
}

const SNAKE_RE = /-([a-z])/g
function snakeToCamelCase(s) {
    return s.replace(SNAKE_RE, g => g[1].toUpperCase())
}

// extract expressions in template-literal syntax out of a string
var EXPR_RE = /\$\{[^\}]*\}/
function isExpressions(s) {
    return EXPR_RE.test(s) ? s : null
}

// compile a list of template-literal expressions into a function that evaluates
// these expression for the provided input object
function compileExpressions(exprs) {
    var refs = []
    var code = 'this.__plutoT || (this.__plutoT = T.bind(this));\n'
    code += exprs.map(function(expr, i) {
        if (expr.expr) {
            refs = refs.concat(getIdentifiers(expr.expr))
        }

        return `arguments[0][${i}] = this.__plutoT\`${expr.expr}\``
    }).join(';\n')

    var keys = refs.reduce((keys, k) => (keys[k] = true, keys), {})
    var locals = `var { ${Object.keys(keys)} } = this`
    var fn = eval('(function () {\n' + locals + '\n' + code + '\n})')
    return function(obj) {
        var res = []
        try {
            fn.call(obj, res)
        } catch (e) {
            console.warn(fn)
            throw e
        }

        return res
    }

    function T(s, v) {
        if (arguments.length > 2 || typeof v === 'string') {
            return String.raw.apply(null, arguments)
        }

        if (typeof v === 'function' && this[v.name] === v) {
            if (v._plutoBound !== this) {
                v._plutoBound = v.bind(this)
            }
            return v._plutoBound
        }

        return v
    }
}

// generate the list of identifiers found in the code.
function getIdentifiers(expr) {
    var re = /[$A-Z_][0-9A-Z_$]*/ig
    var whitespace = ' \n\r\t'
    var disallowed = '\'\".'
    var skip = ['true', 'false', 'if', 'for', 'while', 'do', 'try', 'catch',
        'break', 'continue', 'switch', 'throw', 'this', 'instanceof', 'in',
        'function', 'delete', 'default', 'case', 'debugger', 'const', 'var',
        'with', 'typeof', 'super', 'class', 'new', 'null', 'return', 'let',
        'import', 'else', 'enum', 'extends', 'finally', '$']

    // We first match for the valid identifier, and then check the previous
    // non-whitespace character preceeding the identifier to verify that it's
    // not a string or nested element.
    var refs = {}
    var match
    while (match = re.exec(expr)) {
        if (skip.indexOf(match[0]) !== -1) {
            continue // skipped or reserved keyword
        }

        if (window[match[0]] !== undefined) {
            continue // keep global functions (Object, Array, etc.)
        }

        var lastChar = undefined
        do {
            match.index -= 1
            if (whitespace.indexOf(expr[match.index]) === -1) {
                lastChar = expr[match.index]
            }
        } while (match.index > -1 && !lastChar)

        if (disallowed.indexOf(lastChar) === -1) {
            refs[match[0]] = true
        }
    }

    return Object.keys(refs)
}

// upgrade an element
// NOTE this will be unnecessary with customElements
function pluto(el) {
    if (typeof el === 'string') {
        // support HTML-imported selections
        var doc = document._currentScript // used by pollyfills
            || document.currentScript // native.
            || document // not an import.
        el = (doc.ownerDocument || doc).querySelector(el)
    }

    return !el || el instanceof Template
        ? el
        : Object.setPrototypeOf(el, Template.prototype)
}

pluto.Template = Template
pluto.RepeatRenderer = Renderer
window.pluto = pluto
})();

(function() {

    // placed here in order to have its own scope clear of any of the pluto
    // local variables.
    pluto._eval = function(code) {
        return eval(code)
    }
})();
<|endoftext|>


<commit_before>import React from 'react';
import { Navbar, Nav, NavItem, Row, Col, Grid } from 'react-bootstrap';
import { NavbarHeader, NavbarToggle, NavbarCollapse, NavbarBrand } from 'react-bootstrap/lib/NavbarHeader';
import { LinkContainer } from 'react-router-bootstrap';
import { Router, Route, browserHistory, IndexRoute, Link } from 'react-router';
import { inject, observer } from 'mobx-react';
// import 'bootstrap/dist/css/bootstrap.css';
import { render } from 'react-dom';
import Checkbox from './Checkbox';
import PowerTools from './PowerTools';
import Gardening from './Gardening';

class Browse extends React.Component {
  constructor() {
    super();
    this.state = {
      category: ""
    };
    this.componentWillMount = this.componentWillMount.bind(this);
    this.toggleCheckbox = this.toggleCheckbox.bind(this);
    this.createCheckbox = this.createCheckbox.bind(this);
    this.createCheckboxes = this.createCheckboxes.bind(this);
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  componentWillMount ()  {
    this.selectedCheckboxes = new Set();
  }

  toggleCheckbox (label)  {
    if (this.selectedCheckboxes.has(label)) {
      this.selectedCheckboxes.delete(label);
    } else {
      this.selectedCheckboxes.add(label);
    }
  }

  handleFormSubmit(formSubmitEvent) {
    formSubmitEvent.preventDefault();

    for (const checkbox of this.selectedCheckboxes) {

      console.log(checkbox, 'is selected.');

    }
  }

  createCheckbox(label) {
    render(
      <Checkbox
        label={label}
        handleCheckboxChange={this.toggleCheckbox}
        key={label}
      />
    );
  }

  createCheckboxes () {
    const items = [
      'Power Tools',
      'Kitchen Appliances',
      'Gardening',
      'Hobby',
      'Outdoor Gear'
    ];
    items.map(this.createCheckbox);
  } //look up map function

  searchCategory () {
    const categories = [
      'Power Tools',
      'Gardening',
      'Hobby',
      'Outdoor'
    ];
  }

  render() {
    return(

          <Navbar inverse collapseOnSelect>
            <Navbar.Header>
              <Navbar.Brand>
                <Link to="/"/>
              </Navbar.Brand>
              <Navbar.Toggle/>
            </Navbar.Header>
            <Navbar.Collapse>

                <LinkContainer to={{pathname: '/'}}><NavItem>Main</NavItem></LinkContainer>
                {/*<LinkContainer to={{pathname: '/Activity'}}><NavItem>Activity</NavItem></LinkContainer>*/}
                {/*<LinkContainer to={{pathname: '/MyNeighbors'}}><NavItem>My Neighbors</NavItem></LinkContainer>*/}
                <LinkContainer to={{pathname: '/Login'}}><NavItem>Be Neighborly!</NavItem></LinkContainer>

            </Navbar.Collapse>
          </Navbar>
          {this.props.children}

Browse the Neighborhood!

          <Col md={3} mdPush={1}>
            <form method="" role="form">

                <input type="text" className="form-control" id="Item" placeholder="Search for an item..."/>

            </form>
          </Col>

            <Col md={1} mdPull={2}>
              <form onSubmit={this.searchCategory}>

                  {this.createCheckboxes}

                <button className="btn btn-success" smPull={2} type="warning">Power Tools</button>

                <button className="btn btn-success" smPull={2} type="warning">Gardening</button>

                <button className="btn btn-success" smPull={2} type="warning">Kitchen</button>

                <button className="btn btn-success" smPull={2} type="warning">Outdoor</button>

                <button className="btn btn-success" smPull={2} type="warning">Hobby</button>

                <button className="btn btn-default" smPull={2} type="submit">Search</button>
              </form>
            </Col>
            <PowerTools/>

    );
  }
 }

Browse.propTypes = {
  children: React.PropTypes.object,
  userStore: React.PropTypes.object,
  itemStore: React.PropTypes.object
};

export default inject('userStore')(observer(Browse));
<commit_msg>this is annoying<commit_after>import React from 'react';
import { Navbar, Nav, NavItem, Row, Col, Grid } from 'react-bootstrap';
import { NavbarHeader, NavbarToggle, NavbarCollapse, NavbarBrand } from 'react-bootstrap/lib/NavbarHeader';
import { LinkContainer } from 'react-router-bootstrap';
import { Router, Route, browserHistory, IndexRoute, Link } from 'react-router';
import { inject, observer } from 'mobx-react';
// import 'bootstrap/dist/css/bootstrap.css';
import { render } from 'react-dom';
import Checkbox from './Checkbox';
import PowerTools from './PowerTools';

class Browse extends React.Component {
  constructor() {
    super();
    this.state = {
      category: ""
    };
    this.componentWillMount = this.componentWillMount.bind(this);
    this.toggleCheckbox = this.toggleCheckbox.bind(this);
    this.createCheckbox = this.createCheckbox.bind(this);
    this.createCheckboxes = this.createCheckboxes.bind(this);
    this.handleFormSubmit = this.handleFormSubmit.bind(this);
  }

  componentWillMount ()  {
    this.selectedCheckboxes = new Set();
  }

  toggleCheckbox (label)  {
    if (this.selectedCheckboxes.has(label)) {
      this.selectedCheckboxes.delete(label);
    } else {
      this.selectedCheckboxes.add(label);
    }
  }

  handleFormSubmit(formSubmitEvent) {
    formSubmitEvent.preventDefault();

    for (const checkbox of this.selectedCheckboxes) {

      console.log(checkbox, 'is selected.');

    }
  }

  createCheckbox(label) {
    render(
      <Checkbox
        label={label}
        handleCheckboxChange={this.toggleCheckbox}
        key={label}
      />
    );
  }

  createCheckboxes () {
    const items = [
      'Power Tools',
      'Kitchen Appliances',
      'Gardening',
      'Hobby',
      'Outdoor Gear'
    ];
    items.map(this.createCheckbox);
  } //look up map function

  searchCategory () {
    const categories = [
      'Power Tools',
      'Gardening',
      'Hobby',
      'Outdoor'
    ];
  }

  render() {
    return(

          <Navbar inverse collapseOnSelect>
            <Navbar.Header>
              <Navbar.Brand>
                <Link to="/"/>
              </Navbar.Brand>
              <Navbar.Toggle/>
            </Navbar.Header>
            <Navbar.Collapse>

                <LinkContainer to={{pathname: '/'}}><NavItem>Main</NavItem></LinkContainer>
                {/*<LinkContainer to={{pathname: '/Activity'}}><NavItem>Activity</NavItem></LinkContainer>*/}
                {/*<LinkContainer to={{pathname: '/MyNeighbors'}}><NavItem>My Neighbors</NavItem></LinkContainer>*/}
                <LinkContainer to={{pathname: '/Login'}}><NavItem>Be Neighborly!</NavItem></LinkContainer>

            </Navbar.Collapse>
          </Navbar>
          {this.props.children}

Browse the Neighborhood!

          <Col md={3} mdPush={1}>
            <form method="" role="form">

                <input type="text" className="form-control" id="Item" placeholder="Search for an item..."/>

            </form>
          </Col>

            <Col md={1} mdPull={2}>
              <form onSubmit={this.searchCategory}>

                  {this.createCheckboxes}

                <button className="btn btn-success" smPull={2} type="warning">Power Tools</button>

                <button className="btn btn-success" smPull={2} type="warning">Gardening</button>

                <button className="btn btn-success" smPull={2} type="warning">Kitchen</button>

                <button className="btn btn-success" smPull={2} type="warning">Outdoor</button>

                <button className="btn btn-success" smPull={2} type="warning">Hobby</button>

                <button className="btn btn-default" smPull={2} type="submit">Search</button>
              </form>
            </Col>
            <PowerTools/>

    );
  }
 }

Browse.propTypes = {
  children: React.PropTypes.object,
  userStore: React.PropTypes.object,
  itemStore: React.PropTypes.object
};

export default inject('userStore')(observer(Browse));
<|endoftext|>