<commit_before>var imageUpload, commentBox;

var FaveCounter = React.createClass({
  getInitialState: function() {
    return {faves: [], state: 0, postId: 0};
  },
  click: function(e) {
    e.preventDefault();
    if(this.state.postId > 0) {
      var c = this;
      $.ajax({url:"/posts/"+this.state.postId+"/fave", dataType: "json", type: "post"}).done(function(msg) {
        c.setState({state: msg.status ? 1 : 0, faves: msg.faves});
      });
    }
  },
  render: function() {
    var icon = <span className="octicon octicon-star" />;
    var inner = null;
    if(!this.state.faves || this.state.faves.length == 0) inner = <span>{icon}{'0'}</span>;
    else inner = <span>{icon}{this.state.faves.length}</span>;
    var className = "";
    if(this.state.faves.length > 0) className = "faved";
    if(this.state.state == 1) className = "on";
    return <a href="#" title={(this.state.faves ? this.state.faves : []).join(", ")} onClick={this.click} className={className}>{inner}</a>;
  }
});

var ImageUploader = React.createClass({
  getInitialState: function() {
    return {url: null, message: "", filename: null};
  },
  startUpload: function(filename, form) {
    var u = this;
    var xhr = new XMLHttpRequest();
    xhr.open('POST', this.state.url, true)
    var token = $('meta[name="csrf-token"]').attr('content');
    xhr.setRequestHeader('X_CSRF_TOKEN', token);

    xhr.onreadystatechange = function(e) {
      if(xhr.readyState == 4) {
        if(xhr.status == 201 || xhr.status == 202) {
          u.setState({message: "Finished uploading \""+filename+"\"", filename: filename});
          if(commentBox) {
            commentBox.insert("![]("+JSON.parse(xhr.responseText).url+")", "\n\n");
          }
        } else {
          u.setState({message: xhr.responseText, filename: filename});
        }
      }
    };
    xhr.onerror = function(e) {
      u.setState({message: "error", filename: filename});
    }

    if(xhr.upload)
      xhr.upload.onprogress = function(e) {
        var percentage = Math.round((e.loaded / e.total) * 100);
        u.setState({message: "Uploading \""+filename+"\" ("+percentage+"%)", filename: filename})
      };

    var f = new FormData(form[0]);
    xhr.send(f);
  },
  click: function(e) {
    e.preventDefault();
    var form = $(this.getDOMNode()).parents("form");
    var file = form.find("input.file");
    var u = this;
    file.off('change');
    file.on('change', function(e) {
      u.selectFile();
    });
    file.trigger("click");
  },
  selectFile: function(e) {
    var form = $(this.getDOMNode()).parents("form");
    var file = form.find("input.file");
    var f = file.val().split("\\");
    var filename = f[f.length - 1];
    this.startUpload(filename, form);
  },
  render: function() {
    if(this.state.url)
      return <div>
        <input type='file' className='file' name='image[image_file]' />
        <button onClick={this.click} className="response-button content-button upload-image"><span className="octicon octicon-device-camera"></span></button>
        <span className="info">{this.state.message}</span>
      </div>;
    else
      return null;
  }
})

var AutoCompleterResult = React.createClass({
  render: function() {
    var className = "result "+ (this.props.highlight ? "highlight" : "");
    var title = this.props.value.login ? this.props.value.login : this.props.value;
    var image = this.props.imageUrl ? this.props.imageUrl(this.props.value) : this.props.value.image ? this.props.value.image : null;
    return <li className={className} onClick={this.props.clickCallback} data-value={title}><img src={image} />{title}</li>;
  }
});

var AutoCompleter = React.createClass({
  render: function() {
    var input = this.props.input;
    var selection = this.props.selection;
    var imageUrl = this.props.imageUrl;
    var clickCallback = this.props.clickCallback;
    var n = 0;
    var results = this.props.objects.map(function(r, i) {
      var s = r;
      if(r.login) {
        s = r.login;
        imageUrl = function() { return r.avatar_url; };
      }
      var highlight = selection == i;
      return <AutoCompleterResult key={s} value={r} highlight={highlight} imageUrl={imageUrl} clickCallback={clickCallback} />;
    })
    return <ul className="autocompleter">
      {results}
    </ul>;
  }
});

var CommentBox = React.createClass({
  getInitialState: function() {
    var syntax = $('#syntax').val();
    if(!syntax || syntax.length == 0) syntax = "md"
    return {text: "", valueName: "post[body]", syntax: syntax, autocomplete: null, autocompleteobjects: [], autocompleteinput: "", autocompletestart: null, autocompleteselection: 0};
  },
  insert: function(text, prefix) {
    var s = this.state.text;
    if(prefix && s.length > 0) s += prefix;
    s += text;
    this.setState({text: s});
    $(this.getDOMNode()).find(".comment-box").focus();
  },
  submit: function(e) {
    e.preventDefault();
    var c = this;
    var data = {};
    data[this.state.valueName] = this.state.text;
    $.ajax({type: "POST", dataType: "json", url: $(this.getDOMNode()).parents("form").attr("action"), data: data,
      success: function(data) {
        var d = $(data.rendered)
        window.updateTimestamps(d.find(".update-ts"));
        if(!window.socket.active) $("#content .channel-posts").append(d)
        c.setState({text: ""})
      }, error: function() {
        $('.comment-box-form textarea').val(c.state.text)
        imageUpload.setState({message: "Error sending post. Please try again."})
      }
    });
  },
  input: function(e) {
    var cursorE = $(this.getDOMNode()).find(".comment-box").get(0).selectionEnd;
    var cursorS = $(this.getDOMNode()).find(".comment-box").get(0).selectionStart;

    if(this.state.autocomplete && cursorE < this.state.autocompletestart) {
      this.setState({autocomplete: null});
    }
    switch(e.key) {<commit_msg>Fix image upload with html editor<commit_after>var imageUpload, commentBox;

var FaveCounter = React.createClass({
  getInitialState: function() {
    return {faves: [], state: 0, postId: 0};
  },
  click: function(e) {
    e.preventDefault();
    if(this.state.postId > 0) {
      var c = this;
      $.ajax({url:"/posts/"+this.state.postId+"/fave", dataType: "json", type: "post"}).done(function(msg) {
        c.setState({state: msg.status ? 1 : 0, faves: msg.faves});
      });
    }
  },
  render: function() {
    var icon = <span className="octicon octicon-star" />;
    var inner = null;
    if(!this.state.faves || this.state.faves.length == 0) inner = <span>{icon}{'0'}</span>;
    else inner = <span>{icon}{this.state.faves.length}</span>;
    var className = "";
    if(this.state.faves.length > 0) className = "faved";
    if(this.state.state == 1) className = "on";
    return <a href="#" title={(this.state.faves ? this.state.faves : []).join(", ")} onClick={this.click} className={className}>{inner}</a>;
  }
});

var ImageUploader = React.createClass({
  getInitialState: function() {
    return {url: null, message: "", filename: null};
  },
  startUpload: function(filename, form) {
    var u = this;
    var xhr = new XMLHttpRequest();
    xhr.open('POST', this.state.url, true)
    var token = $('meta[name="csrf-token"]').attr('content');
    xhr.setRequestHeader('X_CSRF_TOKEN', token);

    xhr.onreadystatechange = function(e) {
      if(xhr.readyState == 4) {
        if(xhr.status == 201 || xhr.status == 202) {
          u.setState({message: "Finished uploading \""+filename+"\"", filename: filename});
          if(commentBox) {
            commentBox.insertImage(JSON.parse(xhr.responseText).url, "\n\n");
          }
        } else {
          u.setState({message: xhr.responseText, filename: filename});
        }
      }
    };
    xhr.onerror = function(e) {
      u.setState({message: "error", filename: filename});
    }

    if(xhr.upload)
      xhr.upload.onprogress = function(e) {
        var percentage = Math.round((e.loaded / e.total) * 100);
        u.setState({message: "Uploading \""+filename+"\" ("+percentage+"%)", filename: filename})
      };

    var f = new FormData(form[0]);
    xhr.send(f);
  },
  click: function(e) {
    e.preventDefault();
    var form = $(this.getDOMNode()).parents("form");
    var file = form.find("input.file");
    var u = this;
    file.off('change');
    file.on('change', function(e) {
      u.selectFile();
    });
    file.trigger("click");
  },
  selectFile: function(e) {
    var form = $(this.getDOMNode()).parents("form");
    var file = form.find("input.file");
    var f = file.val().split("\\");
    var filename = f[f.length - 1];
    this.startUpload(filename, form);
  },
  render: function() {
    if(this.state.url)
      return <div>
        <input type='file' className='file' name='image[image_file]' />
        <button onClick={this.click} className="response-button content-button upload-image"><span className="octicon octicon-device-camera"></span></button>
        <span className="info">{this.state.message}</span>
      </div>;
    else
      return null;
  }
})

var AutoCompleterResult = React.createClass({
  render: function() {
    var className = "result "+ (this.props.highlight ? "highlight" : "");
    var title = this.props.value.login ? this.props.value.login : this.props.value;
    var image = this.props.imageUrl ? this.props.imageUrl(this.props.value) : this.props.value.image ? this.props.value.image : null;
    return <li className={className} onClick={this.props.clickCallback} data-value={title}><img src={image} />{title}</li>;
  }
});

var AutoCompleter = React.createClass({
  render: function() {
    var input = this.props.input;
    var selection = this.props.selection;
    var imageUrl = this.props.imageUrl;
    var clickCallback = this.props.clickCallback;
    var n = 0;
    var results = this.props.objects.map(function(r, i) {
      var s = r;
      if(r.login) {
        s = r.login;
        imageUrl = function() { return r.avatar_url; };
      }
      var highlight = selection == i;
      return <AutoCompleterResult key={s} value={r} highlight={highlight} imageUrl={imageUrl} clickCallback={clickCallback} />;
    })
    return <ul className="autocompleter">
      {results}
    </ul>;
  }
});

var CommentBox = React.createClass({
  getInitialState: function() {
    var syntax = $('#syntax').val();
    if(!syntax || syntax.length == 0) syntax = "md"
    return {text: "", valueName: "post[body]", syntax: syntax, autocomplete: null, autocompleteobjects: [], autocompleteinput: "", autocompletestart: null, autocompleteselection: 0};
  },
  insertImage: function(url, prefix) {
    if(this.state.syntax == "html") {
      this.insert("<img src=\""+url+"\" />");
    } else {
      this.insert("![]("+url+")");
    }
  },
  insert: function(text, prefix) {
    var s = this.state.text;
    if(this.state.syntax == "html") {
      $.markItUp({target: $('.comment-box'), placeHolder: text})
      this.setState({text: $('.comment-box').val()});
    } else {
      if(prefix && s.length > 0) s += prefix;
      s += text;
      this.setState({text: s});
      $(this.getDOMNode()).find(".comment-box").focus();
    }
  },
  submit: function(e) {
    e.preventDefault();
    var c = this;
    var data = {};
    data[this.state.valueName] = this.state.text;
    $.ajax({type: "POST", dataType: "json", url: $(this.getDOMNode()).parents("form").attr("action"), data: data,
      success: function(data) {
        var d = $(data.rendered)
        window.updateTimestamps(d.find(".update-ts"));
        if(!window.socket.active) $("#content .channel-posts").append(d)
        c.setState({text: ""})
      }, error: function() {
        $('.comment-box-form textarea').val(c.state.text)
        imageUpload.setState({message: "Error sending post. Please try again."})
      }
    });
  },
  input: function(e) {
    var cursorE = $(this.getDOMNode()).find(".comment-box").get(0).selectionEnd;
    var cursorS = $(this.getDOMNode()).find(".comment-box").get(0).selectionStart;

    if(this.state.autocomplete && cursorE < this.state.autocompletestart) {
      this.setState({autocomplete: null});
    }
    switch(e.key) {
{'fraction_non_alphanumeric': 0.1881693854012193, 'fraction_numerical': 0.004448838358872961, 'mean_word_length': 3.110734845919404, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 0, '>': 54, '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': '1680524', 'n_tokens_mistral': 3995, 'n_tokens_neox': 3931, 'n_words': 775}