How does stackoverflow make its Tag input field?

HtmlInputTags

Html Problem Overview


How does StackOverflow create its tag system. How can it format the html in a text area?

I just don't know where to begin. If someone could guide me, then I can know what direction to take so I can write some code that someone can check.

Like this:

enter image description here

EDIT: Basically, when I press space, how do i add a new element/div to the inside of the div?

Html Solutions


Solution 1 - Html

What about Bootstrap solution?

You can try this :

HTML Code:

<input type="text" value="html,input,tag" data-role="tagsinput"></input>

For CSS, call these two files:

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="http://bootstrap-tagsinput.github.io/bootstrap-tagsinput/dist/bootstrap-tagsinput.css">

For Javascript, call these two files:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="http://bootstrap-tagsinput.github.io/bootstrap-tagsinput/dist/bootstrap-tagsinput.min.js"></script>

The code will generate the result below:

enter image description here

Check it out.

Solution 2 - Html

What I would do is:

  • Create a master DIV with a border (like here the border 1px solid #000)
  • After, inside this DIV, I will create another DIV (float: left;), another DIV (float: right) and an input inside the right div.

When you write inside the input and let's say you select HTML, it creates a span in the left DIV and reduces the width of the right div to match the remaining size. Of course, inside your span there's the text HTML with the delete sign.

You could do it easily using jQuery.

Example:

<div id="master_div">
	<div id="categories">
	
	</div>
	<div id="input">
		<input type="text" value="" />
	</div>
</div>

And you write some jQuery / JS

Solution 3 - Html

It doesn't. If you look at the DOM, you see initially just an input box. Once you add a tag, it inserts a <span> tag before the input box with that tag and it's delete icon. The input box is now to the right of this <span> tag. When you click on a tag to edit it, it puts a textbox in its place so you can edit it. All this is done with Javascript and there are some JQuery plugins to help you do this. Here's one from a quick Google search: http://xoxco.com/projects/code/tagsinput/

As far as styling goes, the <span> elements can have whatever CSS you want on them.

Solution 4 - Html

var es = document.querySelectorAll('.input-categories');
for (var i = 0; i < es.length; i++) {
  es[i]._list = es[i].querySelector('ul');
  es[i]._input = es[i].querySelector('input');
  es[i]._input._icategories = es[i];
  es[i].onkeydown = function(e){
    var e = event || e;
    if(e.keyCode == 13) {
      var c = e.target._icategories;
      var li = document.createElement('li');
      li.innerHTML = c._input.value;
      c._list.appendChild(li);
      c._input.value = '';
      e.preventDefault();
    }
  }
}

*{
  margin: 0px;
  padding: 0px;
}

.input-categories{
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  border: 1px solid black;
}

.input-categories ul{
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  list-style-type: none;
  flex-wrap: wrap;
}

.input-categories li{
  border: 1px solid black;
  border-radius: 2px;
  padding: 1px;
  margin: 1px;
}
.input-categories input{
  flex: 1 1 auto;
  align-self: flex-start;
}

<div class="input-categories">
  <ul>
    <li>moscow</li>
    <li>new york</li>
  </ul>
  <input type="text"/>
</div>

<div class="input-categories">
  <ul>
    <li>CSS</li>
    <li>PHP</li>
  </ul>
  <input type="text"/>
</div>

Solution 5 - Html

React functional component

const AutoList=()=>{
const [currentTagText, setCurrentTagText] = useState("");
const [tags, setTags] = useState(["javascript"]);

const handleTag = (e) => {
   setCurrentTagText(e.target.value);
   if (e.keyCode == 13 && currentTagText) {
    setTags((prevTags) => [...prevTags, currentTagText]);
    setCurrentTagText("");
   } else if (e.keyCode == 32 && currentTagText) {
    setTags((prevTags) => [...prevTags, currentTagText]);
    setCurrentTagText("");
   }
};
const removeTag = (index) => {
   const newTagArray = tags;
   newTagArray.splice(index, 1);
   setTags([...newTagArray]);
};

return (

  <div className="masterStackDiv">
          <div
            className="stackTags"
            style={{ display: tags.length > 0 ? "flex" : "none" }}
          >
            {tags.map((tag) => {
              return (
              <div className="stackTag">
                 <button
                    onClick={() => removeTag(index)}
                    className="tagCloseBtn"
                  >
                    x
                  </button>
                  #{tag}
              </div>
               )
            })}
          </div>
          <div className="stackInput">
            <input
              type="text"
              onKeyDown={handleTag}
              onChange={handleTag}
              value={currentTagText}
            />
          </div>
        </div>
 )

}

CSS:-

.masterStackDiv {
  width: auto;
  background-color: transparent;
  border: none;
  display: flex;
  align-items: center;
}
.stackInput input[type="text"] {
  border: none;
  background-color: transparent;
  color: white;
  font-family: "Segoe UI";
  font-size: 0.8em;
  float: right;
  margin-left: 5px;
  width: auto;
  border-bottom: 2px solid white;
}

.stackTag {
  background-color: #707070;
  color: white;
  height: 20px;
  width: auto;
  border-radius: 10px;
  font-size: 0.7em;
  padding: 5px;
  margin: 3px;
  display: flex;
  align-items: center;
}

.stackTags {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 30px;
  width: auto;
}
.tagCloseBtn {
  border: none;
  background-color: transparent;
  border-radius: 5px;
}
.tagCloseBtn:hover {
  background-color: white;
  cursor: pointer;
}

const {useState} = React
 
const StackTag=()=>{
 const [currentTagText, setCurrentTagText] = useState("");
 const [tags, setTags] = useState(["javascript"]);
 
 const handleTag = (e) => {
    setCurrentTagText(e.target.value);
    if (e.keyCode == 13 && currentTagText) {
      setTags((prevTags) => [...prevTags, currentTagText]);
      setCurrentTagText("");
    } else if (e.keyCode == 32 && currentTagText) {
      setTags((prevTags) => [...prevTags, currentTagText]);
      setCurrentTagText("");
    }
  };
  
  const removeTag = (index) => {
    const newTagArray = tags;
    newTagArray.splice(index, 1);
    setTags([...newTagArray]);
  };

  return (
       <div className="masterStackDiv">
              <div
                className="stackTags"
                style={{ display: tags.length > 0 ? "flex":"none"}} 
              >
                {tags.map((tag, index) => {
                  return (
                    <div className="stackTag" key={index}>
                      <button
                        onClick={() => removeTag(index)}
                        className="tagCloseBtn"
                      >
                        x
                      </button>
                      #{tag}
                    </div>
                  );
                })}
              </div>
              <div className="stackInput">
                <input
                  type="text"
                  onKeyDown={handleTag}
                  onChange={handleTag}
                  value={currentTagText}
                />
              </div>
            </div>
            )
       }
ReactDOM.render(<StackTag/>,document.getElementById("react"))

.masterStackDiv {
  width: auto;
  background-color: transparent;
  border: none;
  display: flex;
  align-items: center;
}
.stackInput input[type="text"] {
  border: none;
  background-color: transparent;
  color: black;
  font-family: "Segoe UI";
  font-size: 0.8em;
  float: right;
  margin-left: 5px;
  width: auto;
  border-bottom: 2px solid black;
}

.stackTag {
  background-color: #707070;
  color: white;
  height: 20px;
  width: auto;
  border-radius: 10px;
  font-size: 0.7em;
  padding: 5px;
  margin: 3px;
  display: flex;
  align-items: center;
}

.stackTags {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 30px;
  width: auto;
}
.tagCloseBtn {
  border: none;
  background-color: transparent;
  border-radius: 5px;
}
.tagCloseBtn:hover {
  background-color: white;
  cursor: pointer;
}

<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
</head>
<body>
<div id="react"></div>
</body>
</html>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMathew KurianView Question on Stackoverflow
Solution 1 - HtmlJad ChahineView Answer on Stackoverflow
Solution 2 - HtmlDavid BélangerView Answer on Stackoverflow
Solution 3 - HtmlsachleenView Answer on Stackoverflow
Solution 4 - HtmlMaximView Answer on Stackoverflow
Solution 5 - Htmlalvin lalView Answer on Stackoverflow