-1

I'm trying to make a blue background color to stay on the SVG icon that is active displaying the text using pure JavaScript. I'm also getting icons from semantic UI.

This is the code of the current menu list, and so far clg prints me the items inside for:

HTML

<span class="menu-bar">
  <a href="javascript:void(0)" class="itemList"> <svg><svg/> </a>
  <a href="javascript:void(0)" class="itemList"> <svg><svg/> </a>
  <a href="javascript:void(0)" class="itemList"> <svg><svg/> </a>
  <a href="javascript:void(0)" class="itemList"> <svg><svg/> </a>
  <i class="angle left icon iconColor tooltip" id="angle_icon"></i>
  <i class="text height icon iconColor tooltip" id="measure_icon"></i>
</span>

CSS

.menu-bar {
   display: block;
   width: 100%;
   height: 100%;
   margin-top: -10px;
}

.menu-bar svg {
    display: inline-block;
    width: 1em;
    padding: 0.3em;
    border-radius: 4px;
    margin-right: 20px;
}

.menu-bar a.toggle-state  {
   background-color: #1A41B5;
}

JavaScript code (so far)

function changeIndex(){
    for (let i = 0; i <= items.length; i++) {
        console.log(items[i])
    }
}

I managed to fixed it with:

function _clearIcon() {
    for (const icon of items) {
        if(icon.classList.contains('menu-barActive')) {
            icon.classList.remove('menu-barActive')
        }
    }
}

function changeIndex() {
    for (const icon of items) {
        icon.onclick=()=> {
            _clearIcon()
            let activeId = document.getElementById(icon.id)
            activeId.classList.add('menu-barActive')
        }
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131

3 Answers3

1

Rather than having:

items[i].style["1a41b5"] = color;

You should put:

items[i].style.color = "#1a41b5";

Because color is a built in object to the style property. I think you may have confused style as a method instead of a property. A method includes parenthesis and a parameter, such as .getElementById("parameter"). You can think of a method as a function that does stuff to an object. For example in...

var x = document.getElementById("some-id");

...getElementById() is actively getting the element(s) with the id of some-id. However, think of a property as an extension of a variable: you have to assign it a value. So adding on to our previous example...

x.innerHTML = "<p>Hello World</p>";

As you can see, you have to assign a value to a property. In this case, the above code is assigning <p>Hello World</p> to the inner HTML of the elements with id some-id (because we assigned x the value of the elements with the id some-id). In this case this is putting "Hello World" on the screen.

So remember that .style and .color are both properties, and they need to be set values, unlike methods which can be used to do things to a variable/object.

Hope this helps. Happy coding! :)

  • Yes, i just checked it was wrong, right now im trying to add an eventListener down the for element to check if now it gets to change the bg color of the clicked icon, also fixing some css and html mistakes i made, let's see if it works now – Jose Moreno Aug 11 '20 at 02:47
  • Great! I'd be happy to also take at the other code, but I'm not that good at web dev, so I'll just try my best :P – The Cat Coder Aug 11 '20 at 02:53
  • hahahaha i'm still working on that! it takes time im still a beginner – Jose Moreno Aug 11 '20 at 02:55
  • No problem, I know how it feels like :). Tell me if the code works well, would love to see the final product. If not, feel free to comment anything you'd like me to look at. But don't feel rushed or obligated :) – The Cat Coder Aug 11 '20 at 02:57
  • I managed to make the bg-color change when click, but now i have to store the value of i so when i click other icon the one i was change it's color to #171717 and the new active changes to the blue one and not have all blue – Jose Moreno Aug 11 '20 at 03:32
  • It's a bit hard for me to understand what you mean. Perhaps you could copy paste your code into a JS fiddle, save it, and then send me the link? https://jsfiddle.net – The Cat Coder Aug 11 '20 at 03:34
  • https://jsfiddle.net/egjfL0hc/ – Jose Moreno Aug 11 '20 at 03:36
  • Do you mind also adding the html and css into the jsfiddle :). You'll have to save it again and then send me the link again I think. – The Cat Coder Aug 11 '20 at 04:33
  • https://jsfiddle.net/hLj7t1pq/ There you go – Jose Moreno Aug 11 '20 at 14:12
  • Welp, looks like you fixed it. Good job! – The Cat Coder Aug 12 '20 at 15:09
1

In modern browsers you can use Custom Elements to create your own HTML tags.

After defining your Custom Elements <icon-toolbar> and <svg-icon> once

All you write is:

    <icon-toolbar>
      <svg-icon is="icon1"></svg-icon>
      <svg-icon is="icon2"></svg-icon>
      <svg-icon is="icon3"></svg-icon>
      <svg-icon is="icon4"></svg-icon>
    </icon-toolbar>

SO Snippet below.

customElements.define("icon-toolbar", class extends HTMLElement {
    connectedCallback() {
      this.icons = [...this.querySelectorAll("svg-icon")];
      this.addEventListener("click", (evt) => {
        const select = (icon, selected = true) => {
          if (selected) icon.setAttribute("selected", "selected");
          else icon.removeAttribute("selected");
        }
        const clickedicon = evt.target.closest("svg-icon");
        if (evt.ctrlKey) select(clickedicon, !clickedicon.hasAttribute("selected"));
        else {
          this.icons.map(icon => icon.hasAttribute("selected") && select(icon, false));
          select(clickedicon);
        }
      });
    }
  })
  customElements.define("svg-icon", class extends HTMLElement {
    connectedCallback() {
      const path = {
        icon1: "M80 35a5 5 0 01-5-6V17a7 7 0 00-7-6H56a5 5 0 010-11h12a17 17 0 0118 17v12a5 5 0 01-6 6zM5 35a5 5 0 01-5-6V17A17 17 0 0117 0h12a5 5 0 010 11H17a7 7 0 00-6 6v12a5 5 0 01-6 6z",
        icon2: "M43 86a5 5 0 01-6-6V5a5 5 0 0111 0v75a5 5 0 01-5 6zm37-38H5a5 5 0 010-11h75a5 5 0 110 11zM43 86a5 5 0 01-4-2L28 73a5 5 0 014-9h22a5 5 0 014 9L47 84a5 5 0 01-4 2zm11-64H32a5 5 0 01-4-9L39 2a5 5 0 014-2 5 5 0 014 2l11 11a5 5 0 01-4 9z",
        icon3: "M5 43a38 38 0 0038 38V5A38 38 0 005 43z",
        icon4: "M86 86H5a5 5 0 110-11h81a5 5 0 110 11zm-25 0H27a5 5 0 01-3-2L6 66a19 19 0 010-27l17-17a5 5 0 017 0l45 45a5 5 0 010 7L65 84a5 5 0 01-4 2zM30 75h29l5-5-37-37-14 14a8 8 0 000 12z",
      } [this.getAttribute("is")];
      this.innerHTML = `<svg viewBox='0 0 85 85'><path d='${path}'/></svg>`
    }
  })
icon-toolbar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(20px, 1fr));
    grid-gap: 5px;
  }
  svg-icon {
    cursor: pointer;
    background: black;
    fill: #b8b8b8;
  }
  svg-icon:hover {
    background:lightgreen;
    fill:black;
  }
  svg-icon[selected] {
    background: green;
    fill: gold;
  }
  svg-icon[selected]:hover {
    background: lightcoral;
    fill: grey;
  }
Select multiple with Control Key
<icon-toolbar>
  <svg-icon is="icon1"></svg-icon>
  <svg-icon is="icon2"></svg-icon>
  <svg-icon is="icon3"></svg-icon>
  <svg-icon is="icon4"></svg-icon>
</icon-toolbar>

A more advanced <svg-icon> is at https://IconMeister.github.io

Should work fine in Angular, Vue or Svelte. For React you have to jump through some hoops... as React only for 71% supports this modern W3C standard (https://custom-elements-everywhere.com/)

Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49
0

I am not that much good in scalable vector graphics (svg). However, it clearly shows you forgot to end the svg tag properly...

It looks like

<svg></svg>

And there should be a followed tag of <svg>. That can be a <rect /> tag

For example

<svg width="20" height="20"> <rect width="20" height="20" /> </svg>

An important thing is that you need to use fill property to apply background color in svg icons.

You can see the more examples and tutorials here in https://www.w3schools.com/graphics/svg_rect.asp about svg.

I have tried to revise your codes and made something like the below code... I think this is what you want.

In the following code, addEventListener is used to call wherever the click event is delivered inside the menu-bar. And the children property is used to return the child elements of the particular node or tag.

Check out the below code:

<!DOCTYPE html>
<html>
<head>
    <title>HTML/jQuery</title>
    <style type="text/css">
        menu-bar {
  display: block;
  
  margin-top: -10px;
}

.menu-bar svg {
  display: inline-block;

}
.menu-bar a.toggle-state  {
  background-color: #1a41b5;
}
    </style>
</head>
<body>


<span class="menu-bar">
    <a href="javascript:void(0)" class="itemList"><svg width="20" height="20"><rect width="20" height="20" style="fill:rgb(0,0,255)" /></svg></a>
    <a href="javascript:void(0)" class="itemList"><svg width="20" height="20"><rect width="20" height="20" style="fill:rgb(0,0,255)" /></svg></a>
    <a href="javascript:void(0)" class="itemList"><svg width="20" height="20"><rect width="20" height="20" style="fill:rgb(0,0,255)" /></svg></a>
    <a href="javascript:void(0)" class="itemList"><svg width="20" height="20"><rect width="20" height="20" style="fill:rgb(0,0,255)" /></svg></a>
    <a href="javascript:void(0)" class="itemList"><svg width="20" height="20"><rect width="20" height="20" style="fill:rgb(0,0,255)" /></svg></a>
   <i class="angle left icon iconColor tooltip" id="angle_icon"></i>
   <i class="text height icon iconColor tooltip" id="measure_icon"></i>
</span>

<script type="text/javascript">

    (function(){
        
        var c = document.getElementsByClassName('itemList');
        
        for (var i = 0; i < c.length; i++) {
            

            c[i].addEventListener('click',function(){

                this.children[0].children[0].style.fill = "red";
                
            })
            
        }

    })();
    
</script>
</body>
</html>