Reputation: 105
I am trying to set separate background and border for each element in the array using JavaScript something like this. Until now what I have done outputis below. As I add a new element to the array, it will stretch the background.
let skills = [];
function displayname() {
console.log(document.getElementById("namehere").value);
x = document.getElementById("namehere").value;
skills.push(x);
console.log(skills)
document.getElementById("skill-set").innerHTML = skills
document.getElementById("skill-set").style.border = "1px solid blue";
document.getElementById("skill-set").style.backgroundColor = "yellow";
document.getElementById("skill-set").style.padding = "5px";
document.getElementById("skill-set").style.display = "inline-block";
document.getElementById('namehere').value = " ";
}
<label>Enter the skills: </label><br>
<input type=t ext id="namehere" onchange="displayname()">
<div id="skill-set"></div>
Upvotes: 4
Views: 1552
Reputation: 48693
If you want a type-ahead list, you can try the following.
It was adapted from this code: http://jsfiddle.net/bebarr89/tZDAd/
const skills = [ 'Java', 'JavaScript', 'Perl', 'Python', 'HTML', 'CSS' ];
const selectedSkills = new Set();
const autoComplete = document.querySelector('.autocomplete input');
const autoCompleteList = document.querySelector('#autocomplete-list');
const skillSet = document.querySelector('#skill-set');
autoComplete.addEventListener('keyup', dropdownShow);
autoComplete.addEventListener('change', dropdownShow);
autoComplete.addEventListener('focus', dropdownShow);
function addToSkills(skill) {
const skillItem = document.createElement('div'); // Create element
skillItem.textContent = skill; // Set element text
skillItem.classList.add('skill');
skillSet.appendChild(skillItem);
}
function dropdownHide() {
autoCompleteList.innerHTML = '';
autoCompleteList.style.display = 'none';
}
function dropdownShow() {
if (!autoComplete.value) {
dropdownHide();
return;
}
const expression = new RegExp('^' + autoComplete.value, 'i');
const fragment = document.createDocumentFragment();
skills.sort()
.filter(skill =>
!selectedSkills.has(skill) && expression.test(skill))
.forEach(skill => {
var item = document.createElement('div');
item.classList.add('autocomplete-item');
item.innerText = skill;
item.addEventListener('click', selectAndClose);
fragment.appendChild(item);
});
if (fragment.children.length) {
autoCompleteList.innerHTML = '';
autoCompleteList.style.display = 'block';
autoCompleteList.appendChild(fragment);
return;
}
dropdownHide();
}
function selectAndClose(e) {
const skill = this.textContent;
autoComplete.value = skill;
if (!selectedSkills.has(skill)) {
selectedSkills.add(skill);
autoComplete.value = ''; // Clear?
addToSkills(skill);
}
dropdownHide();
}
#skill-set {
margin-top: 0.5em;
}
.skill {
display: inline-block;
margin-right: 0.5em;
border: 1px solid blue;
background-color: yellow;
padding: 5px;
display: inline-block;
}
.autocomplete {
display: inline-block;
}
.autocomplete input {
border: 1px solid silver;
outline: none;
margin: 0;
background: #fff;
padding: 0.25em;
}
#autocomplete-list {
border: 1px solid silver;
border-top: 0;
position: absolute;
overflow: auto;
max-height: 93px;
background: #fff;
}
.autocomplete input, #autocomplete-list {
width: 200px;
box-sizing: border-box;
}
#autocomplete-list .autocomplete-item {
padding: 0.25em;
}
#autocomplete-list .autocomplete-item:nth-child(2n+1) {
background: #f6f6f6;
}
#autocomplete-list .autocomplete-item:hover {
background: #e5e5e5;
cursor: pointer;
}
<form name="skills" onsubmit="return false">
<label>Choose skill(s):</label>
<div class="autocomplete">
<input type="text" name="skill" autocomplete="off">
<div id="autocomplete-list" style="display:none"></div>
</div>
</form>
<div id="skill-set"></div>
You need to create a new element for each skill you add. Do not modify the inner HTML of the entire div.
const input = document.getElementById('namehere');
const skillSet = document.getElementById('skill-set');
const skills = [];
function displayname() {
const value = input.value.trim(); // Capture value
input.value = ''; // Reset field
skills.push(value); // Add text to skill list
const skillItem = document.createElement('div'); // Create element
skillItem.textContent = value; // Set element text
skillItem.classList.add('skill');
// Apply style
Object.assign(skillItem.style, {
border : "1px solid blue",
backgroundColor : "yellow",
padding : "5px",
display : "inline-block"
});
skillSet.appendChild(skillItem);
}
#skill-set {
margin-top: 0.5em;
}
.skill {
display: inline-block;
margin-right: 0.5em;
}
<label>Enter the skills: </label><br>
<input type="text" id="namehere" onchange="displayname()">
<div id="skill-set"></div>
Also, instead of applying style via JavaScript, just add a class with CSS.
Upvotes: 1
Reputation: 8162
Why not create div ? like:
function displayname(el) {
var skilldiv = document.getElementById("skill-set");
var div = document.createElement("div");
div.classList.add("mystyle");
var content = document.createTextNode(el.value);
div.appendChild(content);
skilldiv.appendChild(div);
}
#skill-set div {
display: inline-block;
border: 1px solid blue;
background-color: yellow;
padding: 5px;
margin: 5px 5px 0 0;
}
<label>Enter the skills: </label><br>
<input type="text" id="namehere" onchange="displayname(this)">
<div id="skill-set"></div>
Everytime you set new skill, function will create a new div.
Edit from your comment:
function displayname(el) {
var skilldiv = document.getElementById("skill-set");
var div = document.createElement("div");
div.classList.add("mystyle");
var content = document.createTextNode(el.value);
div.appendChild(content);
skilldiv.appendChild(div);
}
#skill-set div {
display: inline-block;
border: 1px solid blue;
background-color: yellow;
padding: 5px;
margin: 5px 5px 0 0;
}
<label>Enter the skills: </label><br>
<select name="namehere" id="namehere" onChange="displayname(this)">
<option value=""></option>
<option value="java">Java</option>
<option value="php">PHP</option>
<option value="html">Html</option>
</select>
<div id="skill-set"></div>
Upvotes: 4
Reputation: 6525
Instead of appending the text inside the same div you could create a new element and append that instead. This way the styling can be used for each individual item.
By using a CSS class instead of JS we don't have the set the styling each time but we can just append the classname.
const skills = [];
const skillSet = document.getElementById("skill-set");
const input = document.getElementById("namehere");
function displayname() {
const skill = document.createElement("span");
skill.textContent = input.value;
skill.classList.add("box");
skillSet.appendChild(skill);
skills.push(input.value);
input.value = " ";
}
.box {
border: 1px solid blue;
background: yellow;
padding: 5px;
margin: 5px 5px 0 0;
display: inline-block;
}
<label>Enter the skills: </label><br>
<input type=t ext id="namehere" onchange="displayname()">
<div id="skill-set"></div>
Upvotes: 2
Reputation: 20944
Instead of setting the array as the innerHTML
value, try to loop over the skills
array and create an element for each skill. This way you can add classes or other properties to identify these elements and style them through CSS.
let skills = [];
const nameHere = document.getElementById("namehere");
const skillSet = document.getElementById("skill-set")
function displayname() {
let skill = nameHere.value;
skills.push(skill);
while(skillSet.firstElementChild) {
skillSet.firstElementChild.remove();
}
skills.forEach(function(skill) {
let div = document.createElement('div');
div.classList.add('skill');
div.textContent = skill;
skillSet.append(div);
});
nameHere.value = '';
}
#skill-set {
display: flex;
margin-top: 5px;
}
.skill {
border: 1px solid blue;
background-color: yellow;
padding: 5px;
}
.skill + .skill {
margin-left: 5px;
}
<label>Enter the skills: </label><br>
<input type=t ext id="namehere" onchange="displayname()">
<div id="skill-set"></div>
Upvotes: 1
Reputation: 337627
To achieve what you describe you should separate each tag in to its own element. That way the background and border apply to that specific tag only.
In addition you should set the styling rules through CSS directly, not on each element at the point you create them. Try this:
let skills = [];
let skillSet = document.querySelector('#skill-set');
document.querySelector('#namehere').addEventListener('change', e => {
skills.push(e.target.value);
e.target.value = '';
displaySkills();
});
let displaySkills = () => {
let tags = skills.map(skill => `<span>${skill}</span>`).join('');
skillSet.innerHTML = tags;
}
#skill-set span {
display: inline-block;
border: 1px solid blue;
background-color: yellow;
padding: 5px;
margin: 5px 5px 0 0;
}
<label>Enter the skills: </label><br>
<input type="text" id="namehere" />
<div id="skill-set"></div>
Upvotes: 2