<commit_before>/** @jsx React.DOM */

var CONSTANTS = require('../constants');
var TagListStore = require('../stores/tag_list_store');

(function() {
  var TC = CONSTANTS.TYPEAHEAD;
  var TAG_LIST = CONSTANTS.TAG_LIST;

  var TagList = React.createClass({
    componentWillMount: function() {
      if (this.props.destination) {
        TagListStore.setTags(this.props.tags);
      }

      TagListStore.addChangeListener(this.onChange);
    },

    componentWillUnmount: function() {
      TagListStore.removeChangeListener(this.onChange);
    },

    getDefaultProps: function() {
      return {
        tags: []
      }
    },

    getInitialState: function() {
      return {
        adding: false,
        popoverShown: false,
        tags: this.props.tags
      }
    },

    handleClick: function(tag) {
      var self = this;

      return function(e) {
        e.stopPropagation();

        Dispatcher.dispatch({
          action: TAG_LIST.ACTIONS.ADD_TAG,
          data: {
            tag: tag,
            url: self.props.url
          },
        });

        self.setState({
          tags: self.state.tags
        });
      };
    },

    handleHide: function() {
      this.setState({
        popoverShown: false
      });
    },

    onChange: function() {
      var tags = TagListStore.getTags();

      if (this.props.destination) {
        this.setState({
          tags: tags
        });

        var tagListHack = $('#tag-list-hack');

        if (tagListHack.length) {
          if (_.isEmpty(tags)) {
            tagListHack.empty();
          }

          var selected = tagListHack.val();

          $(tagListHack).append(_.map(tags, function(tag) {
            if ((selected && selected.indexOf(tag) === -1) || !selected) {
              return '<option value=' + tag + ' selected="true">' + tag + '</option>';
            }
          }));
        }
      } else {
        this.setState({
          tags: this.props.tags
        });
      }
    },

    popoverButton: function() {
      if (this.props.destination &&
          !this.props.newBounty &&
          this.state.tags.length > 0 &&
          this.state.tags[this.state.tags.length - 1] !== '') {

        return (
          <li>
            <BsPopover
                content={this.suggestedTags()}
                placement="bottom"
                visible={this.state.popoverShown}
                onHide={this.handleHide}>
              <a
                  href="javascript:"
                  onClick={this.togglePopover}
                  className="btn btn-default btn-sm">
                {this.tagPopoverText()}
              </a>
            </BsPopover>
          </li>
        );
      }
    },

    removeButton: function(tag) {
      if (this.props.destination) {
        return (
          <span className="remove" onClick={this.removeTag(tag)}>
            &times;
          </span>
        );
      }

      return null;
    },

    removeTag: function(tag) {
      var self = this;

      return function(e) {
        e.stopPropagation();
        e.preventDefault();

        Dispatcher.dispatch({
          action: TAG_LIST.ACTIONS.REMOVE_TAG,
          data: {
            tag: tag,
            url: self.props.url
          },
        });
      };
    },

    render: function() {
      return (
        <ul className="list-inline omega">
          {this.tags(this.state.tags)}
          {this.popoverButton()}
        </ul>
      );
    },

    suggestedTags: function() {
      return (
        <div style={{ 'text-align': 'center' }}>
          <TagList
              destination={false}
              url={this.props.url}
              tags={window.app.suggestedTags()} />
          <hr />
          <TextInput
              url={this.props.url}
              label="Custom tag"
              width="80px"
              prompt="+"
              size="small" />
        </div>
      );
    },

    tagPopoverText: function() {
      if (this.props.newBounty) {
        return null;
      }

      return this.state.popoverShown ? 'Hide' : 'Add tag';
    },

    tags: function(tags) {
      var self = this;
      var addedTags = TagListStore.getTags();

      var mappedTags = _.map(tags, function(tag) {
        if (!tag) {
          return;
        }

        var style = {};

        if (!self.props.destination && addedTags && addedTags.indexOf(tag) >= 0) {
          style.cursor = 'default';
        }

        return (
          <li key={tag} style={{'margin': '0px'}}>
            <a style={style}
                className="tag"
                href={self.props.filterUrl && self.props.destination ?
                  self.props.filterUrl + '?tag=' + tag :
                  'javascript:void(0);'}
                onClick={self.handleClick(tag)}>
              {tag}
              {self.removeButton(tag)}
            </a>
          </li>
        );
      });

      // FIXME: When there are no tags, the client just receives [""], which requires weird checks like this.
      if (this.props.destination &&
          !this.props.newBounty &&
          (_.isEmpty(mappedTags) ||
            (mappedTags[0] == undefined &&<commit_msg>Fix vertical tag margin<commit_after>/** @jsx React.DOM */

var CONSTANTS = require('../constants');
var TagListStore = require('../stores/tag_list_store');

(function() {
  var TC = CONSTANTS.TYPEAHEAD;
  var TAG_LIST = CONSTANTS.TAG_LIST;

  var TagList = React.createClass({
    componentWillMount: function() {
      if (this.props.destination) {
        TagListStore.setTags(this.props.tags);
      }

      TagListStore.addChangeListener(this.onChange);
    },

    componentWillUnmount: function() {
      TagListStore.removeChangeListener(this.onChange);
    },

    getDefaultProps: function() {
      return {
        tags: []
      }
    },

    getInitialState: function() {
      return {
        adding: false,
        popoverShown: false,
        tags: this.props.tags
      }
    },

    handleClick: function(tag) {
      var self = this;

      return function(e) {
        e.stopPropagation();

        Dispatcher.dispatch({
          action: TAG_LIST.ACTIONS.ADD_TAG,
          data: {
            tag: tag,
            url: self.props.url
          },
        });

        self.setState({
          tags: self.state.tags
        });
      };
    },

    handleHide: function() {
      this.setState({
        popoverShown: false
      });
    },

    onChange: function() {
      var tags = TagListStore.getTags();

      if (this.props.destination) {
        this.setState({
          tags: tags
        });

        var tagListHack = $('#tag-list-hack');

        if (tagListHack.length) {
          if (_.isEmpty(tags)) {
            tagListHack.empty();
          }

          var selected = tagListHack.val();

          $(tagListHack).append(_.map(tags, function(tag) {
            if ((selected && selected.indexOf(tag) === -1) || !selected) {
              return '<option value=' + tag + ' selected="true">' + tag + '</option>';
            }
          }));
        }
      } else {
        this.setState({
          tags: this.props.tags
        });
      }
    },

    popoverButton: function() {
      if (this.props.destination &&
          !this.props.newBounty &&
          this.state.tags.length > 0 &&
          this.state.tags[this.state.tags.length - 1] !== '') {

        return (
          <li>
            <BsPopover
                content={this.suggestedTags()}
                placement="bottom"
                visible={this.state.popoverShown}
                onHide={this.handleHide}>
              <a
                  href="javascript:"
                  onClick={this.togglePopover}
                  className="btn btn-default btn-sm">
                {this.tagPopoverText()}
              </a>
            </BsPopover>
          </li>
        );
      }
    },

    removeButton: function(tag) {
      if (this.props.destination) {
        return (
          <span className="remove" onClick={this.removeTag(tag)}>
            &times;
          </span>
        );
      }

      return null;
    },

    removeTag: function(tag) {
      var self = this;

      return function(e) {
        e.stopPropagation();
        e.preventDefault();

        Dispatcher.dispatch({
          action: TAG_LIST.ACTIONS.REMOVE_TAG,
          data: {
            tag: tag,
            url: self.props.url
          },
        });
      };
    },

    render: function() {
      return (
        <ul className="list-inline">
          {this.tags(this.state.tags)}
          {this.popoverButton()}
        </ul>
      );
    },

    suggestedTags: function() {
      return (
        <div style={{ 'text-align': 'center' }}>
          <TagList
              destination={false}
              url={this.props.url}
              tags={window.app.suggestedTags()} />
          <hr />
          <TextInput
              url={this.props.url}
              label="Custom tag"
              width="80px"
              prompt="+"
              size="small" />
        </div>
      );
    },

    tagPopoverText: function() {
      if (this.props.newBounty) {
        return null;
      }

      return this.state.popoverShown ? 'Hide' : 'Add tag';
    },

    tags: function(tags) {
      var self = this;
      var addedTags = TagListStore.getTags();

      var mappedTags = _.map(tags, function(tag) {
        if (!tag) {
          return;
        }

        var style = {};

        if (!self.props.destination && addedTags && addedTags.indexOf(tag) >= 0) {
          style.cursor = 'default';
        }

        return (
          <li key={tag} style={{'margin': '10px 0 0 0'}}>
            <a style={style}
                className="tag"
                href={self.props.filterUrl && self.props.destination ?
                  self.props.filterUrl + '?tag=' + tag :
                  'javascript:void(0);'}
                onClick={self.handleClick(tag)}>
              {tag}
              {self.removeButton(tag)}
            </a>
          </li>
        );
      });

      // FIXME: When there are no tags, the client just receives [""], which requires weird checks like this.
      if (this.props.destination &&
          !this.props.newBounty &&
          (_.isEmpty(mappedTags) ||
            (mappedTags[0] == undefined &&
{'fraction_non_alphanumeric': 0.139214735821619, 'fraction_numerical': 0.002132816286960737, 'mean_word_length': 1.4667623146819704, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3948000', 'n_tokens_mistral': 3041, 'n_tokens_neox': 2945, 'n_words': 533}