In my project, players can generate items with random name and stats. Each item has its own set of properties as a name, attack value, defense value, etc.
I want to make a tooltip that show the item values on hover knowing :
1- I can't hard write it in HTML (I might create a div with element inside for each item and link a class to show/hide on hover... But it would be tedious and I'm not sure it would be performance-wise in the long run (100 items ?).
2- I want to avoid JQuery / boostrap and other library unless impossible without them.
I've seen basic solution with data attribute but each item should have maybe a dozen key:value to show among hundreds, so, probably not useful to me. I tried to make a CSS variable modified by a JS function but... Well, that's not how CSS var. works apparently.
let myObject = {
prop1 : "name",
prop2 : 12,
};
document.getElementById("myID").addEventListener('mouseenter', function() {
displayEquipmentStats(myObject);
})
function displayEquipmentStats(item) {
let toDisplayContent = "";
toDisplayContent = item.prop1 " att : ";
toDisplayContent = item.prop2;
document.body.style.setProperty("--EquipmentStats", toDisplayContent);
}
:root {
--Content: "";
}
#myID:hover::after {
white-space: pre;
content: "hi there"; /* I wanted to display var(--Content) here, sadly, it's not possible */
position: absolute;
top: 1.5em;
left: 3em;
z-index: 1;
padding: 0.4em;
background: #413219;
color: #fff;
border-radius: 4px;
}
<div id="myID"> some random text</div>
Here is a snippet showing more or less what I want to achieve (Again, I understand that CSS var won't work like that).
Any insight for a similar method welcome at this point, thank you.
CodePudding user response:
Without knowing anything about your data structure, data delivery method, etc etc etc and basically being an overly broad question all together that could very well be closed for such, here's a quickie example of something you could do that on modern evergreen browsers should do just fine even with hundred elements.
It's just a proof-of-concept example, anything more most folks will charge you for their time for since it's generally out-of-scope for a quickie Q&A site but might get your creativity flowing. You could also change to mouseover
event and just display the tooltip in static position from where the event began. Cheers.
const tooltip = document.getElementById('tooltip-example'),
dummyData = [
{
"id": "0",
"name": "Mickey Mouse",
"attack": "melee",
"damage": "42",
"range": "157",
"defense": "turrets",
"faction": "lost souls"
},
{
"id": "1",
"name": "Tinker Bell",
"attack": "sword",
"damage": "34",
"range": "157",
"defense": "cannons",
"faction": "south side"
},
{
"id": "2",
"name": "Goofy",
"attack": "archer",
"damage": "55",
"range": "987",
"defense": "tigers",
"faction": "westside"
},
{
"id": "3",
"name": "Donald Duck",
"attack": "fire",
"damage": "97",
"range": "533",
"defense": "bears",
"faction": "killer koalas"
},
{
"id": "4",
"name": "Minnie Mouse",
"attack": "roundhouse",
"damage": "76",
"range": "234",
"defense": "squirrels",
"faction": "rabid kittens"
},
{
"id": "5",
"name": "Daisy Duck",
"attack": "lightning",
"damage": "45",
"range": "534",
"defense": "looks",
"faction": "angry puppies"
}
];
handleEvents = () => {
const items = document.querySelectorAll('[data-attribs]');
items.forEach(
item => item.addEventListener('mousemove', function (e) {
tooltip.style.display = 'block';
let x = event.clientX,
y = event.clientY;
const attribs = JSON.parse(e.target.dataset.attribs);
tooltip.style.left = `${x}px`;
tooltip.style.top = `${y}px`;
tooltip.innerHTML = `
<table>
<tr><td>Name [id]</td><td>${attribs.name} [${attribs.id}]</td></tr>
<tr><td>Attack</td><td>${attribs.attack}</td></tr>
<tr><td>Damage</td><td>${attribs.damage}</td></tr>
<tr><td>Range</td><td>${attribs.range}</td></tr>
<tr><td>Defense</td><td>${attribs.defense}</td></tr>
<tr><td>Faction</td><td>${attribs.faction}</td></tr>
</table>
`;
}));
items.forEach(
item => item.addEventListener('mouseout', function (e) {
tooltip.style.display = 'none';
}));
}
generateItems = () => {
for (let i = 0, x = dummyData.length; i < x; i ) {
const newItem = document.createElement('div');
newItem.className = 'default-item';
newItem.style.backgroundColor = `#${(Math.random()*0xFFFFFF<<0).toString(16)}`;
newItem.style.color = "#000";
newItem.innerText = dummyData[i].name;
newItem.dataset.attribs = JSON.stringify(dummyData[i]);
document.body.appendChild(newItem);
}
handleEvents();
}
generateItems();
body {
padding: 2rem;
}
.default-item {
display: inline-block;
padding: .5rem;
margin: .25rem;
color: #212121;
cursor: pointer;
border: #212121 1px solid;
}
#tooltip-example {
color: #fff;
background-color: rgba(0,0,0,.8);
position: absolute;
z-index: 99999999;
cursor: pointer;
padding: .5rem;
pointer-events: none;
display: none;
}
#tooltip-example table {
border-collapse: collapse;
}
#tooltip-example table td {
padding: .15rem .5rem;
white-space: nowrap;
}
#tooltip-example table td:first-child {
text-align: right;
border-right: #fff 1px solid;
}
<div id="tooltip-example"></div>