Ir ao conteúdo
  • Cadastre-se

Javascript Alterar ícone pela classe utilizando Javascript


Ir à solução Resolvido por Marcelo Calazans,

Posts recomendados

Estou iniciando em javascript e gostaria da ajuda de vocês. Gostaria de adicionar através de javascript uma ação para alterar o botão menu hambúrguer para o botão close (x) quando o menu mobile estiver visível (clicado, aberto). Tentei trocando a classe do botão header__btnMenu para header__btnMenu.open e header__btnMenu.close e através dessas classes tentei mudar o ícone do menu pelo javascript. Mas sem sucesso. Abaixo o código funcionando mas sem ação do menu hambúrger para close.

 

<!doctype html>
<html lang="pt-br">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css">
  <link rel="stylesheet" href="style/main.css">
</head>

<body>

  <header class="header">
    <a href="index.html" class="logo-text">xxxxx</a>

    <button style="display: none;" class="header__btnMenu"> <i class="faz fa-bars fa-2x"></i> <span class="sr-only">Menu</span></button>

    <nav class="header__nav">
      <ul>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
      </ul>
    </nav>
  </header>

  <script src="js/menu.js"></script>
</body>

</html>
body {
  margin: 0;
}

.header {
  background: #fff;
  width: 100%;
}

.logo-text {
  background-color: #333;
  margin: 0;
  padding: 20px;
  display: block;
  text-decoration: none;
  color: #fff;
  float: left;
  text-align: center;
}

.header__nav {
  clear: left;
}

.header__nav ul {
  margin: 0;
  padding: 0;
}

.header__nav li {
  list-style-type: none;
  background: #333;
  text-align: center;
}

.header__nav a {
  text-decoration: none;
  color: #999;
  display: block;
  padding: 25px 0;
}

.header__nav a:hover {
  color: #666;
}

.header__btnMenu {
  float: right;
  margin: 1.5em;
  border: none;
}

@media screen and (min-width: 1024px) {
  .logo-text {
    width: 25%;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
  }
  .header__btnMenu {
    display: none;
  }
  .header__nav {
    float: left;
    width: 75%;
    clear: none;
    max-width: 700px;
  }
  .header__nav ul {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-pack: distribute;
    justify-content: space-around;
  }
  .header__nav li {
    border-bottom: none;
    -webkit-box-flex: 1;
    -ms-flex-positive: 1;
    flex-grow: 1;
  }
  .header__nav a {
    background: white;
  }
}
(function() {
  var menu = new Menu({
    container: '.header__nav',
    toggleBtn: '.header__btnMenu',
    widthEnabled: 1024
  })
})()


function Menu(config) {
  this.nav = (typeof config.container === 'string') ? document.querySelector(config.container) : config.container

  this.btn = (typeof config.toggleBtn === 'string') ? document.querySelector(config.toggleBtn) : config.toggleBtn

  this.maxWidth = config.widthEnabled || false;

  var _opened = false;
  var _this = this;

  this.btn.removeAttribute('style')

  if (this.maxWidth) {
    window.addEventListener('resize', e => {
      if (window.innerWidth > _this.maxWidth) {
        _this.nav.removeAttribute('style')
        _opened = true;
      } else if (!this.nav.getAttribute('style')) {
        closeMenu();
      }
    })

    if (window.innerWidth <= _this.maxWidth) {
      closeMenu();
    }
  }

  this.btn.addEventListener('click', openOrClose)

  function openOrClose() {
    if (!_opened) {
      openMenu()
    } else {
      closeMenu()
    }
  }

  function openMenu() {
    var _top = _this.nav.getBoundingClientRect().top + 'px'

    var _style = {
      maxHeight: 'calc(100vh - ' + _top + ' )',
      overflow: 'hidden'
    }

    applyStyleToNav(_style)

    _opened = true;
  }

  function applyStyleToNav(_style) {
    Object.keys(_style).forEach(stl => {
      _this.nav.style[stl] = _style[stl]
    })
  }

  function closeMenu() {
    var _style = {
      maxHeight: '0px',
      overflow: 'hidden'
    }

    applyStyleToNav(_style)

    _opened = false;
  }

}

 

Link para o comentário
Compartilhar em outros sites

@EddK

Olá, colega.

 

Uma sugestão, é fazer o botão com imagens.

 

Pelo que entendi, seria basicamente trocar uma imagem pela outra ao clicar no ícone, no caso de você optar por usar uma imagem no botão.

 

Há várias maneiras de se fazer isso, e abaixo tem um código simples que executa essa tarefa.

 

Veja se você pode inclui-lo em seu código, e se fica bom no seu caso:

 

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
</head>

<body>

<script>
var onImg  = "https://ik.imagekit.io/vu1pwgp5n/fashion-6146328_1920_gQH9Z003_.jpg";
var offImg = "https://ik.imagekit.io/vu1pwgp5n/default-image.jpg";
</script>

<style> img {   
     cursor: pointer;
     position: absolute;
     top: 10px;
     left: 10px;
     width: 30px;
     height: 30px;
} 
</style>

<img src="https://ik.imagekit.io/vu1pwgp5n/fashion-6146328_1920_gQH9Z003_.jpg" onclick="this.src = this.src == offImg ? onImg : offImg;" alt="teste">

</body>
</html>

 

Outra opção, se não quiser usar imagens, é tentar com add class e remove class:

 

https://www.w3schools.com/howto/howto_js_add_class.asp

 

https://www.w3schools.com/howto/howto_js_remove_class.asp

 

Teste para ver se funciona no seu caso.

 

Como eu disse, há várias maneiras diferentes de se fazer isso, e se caso essa que eu sugeri não servir para você, aguarde para ver outras sugestões dos demais colegas.

 

Abraços.

Link para o comentário
Compartilhar em outros sites

@EddK Olá, boa tarde.

 

Você pode usar o Font Awesome para os ícones e ordenar a mudança de ícone de hambúrguer para ícone de X a partir de uma condição usada como um interruptor mostrando o botão somente em telas menores que 600px, ou seja, telefones celulares. Exemplo:

 

HTML:

<html lang="pt-BR">
  <head>
    <title>Exemplo</title>
    <link rel="stylesheet" href="test.css">
    <script src="https://kit.fontawesome.com/yourcode.js" crossorigin="anonymous"></script>
  </head>
  <body>
    <nav class="menu">
      <a href="#">LINK1</a>
      <a href="#">LINK2</a>
      <a href="#">LINK3</a>
      <a href="#">LINK4</a>
      <a id="btn" href="javascript:void(0)">
        <i class="fa fa-bars"></i>
      </a>
    </nav>
  </body>
</html>

 

  1.  Adicionei a classe "menu" no elemento "<nav>".
  2.  O último link é o botão que funcionará como abertura e fechamento do menu.
  3. Adicionei um id no link do botão com o valor "btn" para definir o evento no JavaScript.

 

CSS:

#btn {
  display: none;  
}

@media screen and (max-width: 600px) {
  .menu.responsivo {
    position: relative; 
  }
  
  .menu.responsivo a  {
    display: block;
    text-align: center;
  }
  
  #btn {
    display: block;
    position: absolute;
    right: 0;
    top: 0;
  }
}

 

  1.  A linha primeira linha selecionei o botão e defini o estilo para ele ser oculto no desktop(PC e tablets).
  2. O media query é usado em seguida para exibir o botão em telas menores que 600px.
  3. Depois utilizei uma nova classe "responsivo", ela será usada para a abertura vertical do menu

 

JavaScript:

window.onload = function() {
  let menu = document.getElementsByClassName("menu");
  let botao = document.getElementById("btn");
  
  function abreFechaMenu(e) {
    if (menu[0].className == "menu") {
      menu[0].className += " responsivo";
      e.target.children[0].className = "fa fa-times";
    } else {
      menu[0].className = "menu";
      e.target.children[0].className = "fa fa-bars";
    }
  }
  
  if (window.addEventListener) {
    // Navegadores atuais
  	botao.addEventListener("click", function() { abreFechaMenu(event) }, false); 
  } else {
    // Navegadores antigos (IE8 e anteriores)
    botao.attachEvent("onclick", function() { abreFechaMenu(event) }); 
  }
}

 

  1.  Primeira linha adicionei a função que será executada quando a página estiver totalmente carregada.
  2.  Criei dois "let" para armazenar o menu e a botão que serão usados adiante.
  3.  Criei uma função para abrir e fechar o menu quando clicado em um botão.
  4.  A condição verifica se o menu está somente com a classe menu se sim, adicione a classe responsivo e o botão passa a ter o ícone de X. 
  5.  Se ao contrário mantenha somente a classe menu e o botão passa a ter o ícone de hambúrguer.
  6.  No final uma condição verifica se o método "addEventListener" está disponível no navegador.
  7.  Se sim, use-o para adicionar a função "abreFechaMenu" no botão com ele.
  8.  Se não use outra forma usando o método "attatchEvent".

 

NOTA: Usei como parâmetro da função "abreFechaMenu" o "e" simbolizando o objeto Event para usar a sua propriedade target na função e pegar o ícone no elemento "<i>" no link "<a>".

Link para o comentário
Compartilhar em outros sites

Valeu Marcelo e Adriano, mas preciso alteração do ícone font-awesome através das classes por javascript.

No máximo adicionando header__btnMenu.open e header__btnMenu.close no lugar de  header__btnMenu para fazer a alteração pelo javascript. Não alterando muito os códigos enviados.

Link para o comentário
Compartilhar em outros sites

  • Solução

@EddK

É fácil usar a ideia do @Adriano_web , mesclar com o seu próprio código sem muitas alterações.

 

Abaixo tem dois exemplos que foram testados aqui e funcionam:

 

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
</head>

<body>

<!doctype html>
<html lang="pt-br">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css">
  <link rel="stylesheet" href="style/main.css">
</head>

<body>



  <header class="header">
    <a href="index.html" class="logo-text">xxxxx</a>

    <button style="display: none;" class="header__btnMenu"> <i id="muda" class="fa fa-bars"></i> <span class="sr-only">Menu</span></button>

    <nav class="header__nav">
      <ul>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
      </ul>
    </nav>
  </header>

  <script src="js/menu.js"></script>
</body>

</html>

<style>
body {
  margin: 0;
}

.header {
  background: #fff;
  width: 100%;
}

.logo-text {
  background-color: #333;
  margin: 0;
  padding: 20px;
  display: block;
  text-decoration: none;
  color: #fff;
  float: left;
  text-align: center;
}

.header__nav {
  clear: left;
}

.header__nav ul {
  margin: 0;
  padding: 0;
}

.header__nav li {
  list-style-type: none;
  background: #333;
  text-align: center;
}

.header__nav a {
  text-decoration: none;
  color: #999;
  display: block;
  padding: 25px 0;
}

.header__nav a:hover {
  color: #666;
}

.header__btnMenu {
  float: right;
  margin: 1.5em;
  border: none;
}

@media screen and (min-width: 1024px) {
  .logo-text {
    width: 25%;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
  }
  .header__btnMenu {
    display: none;
  }
  .header__nav {
    float: left;
    width: 75%;
    clear: none;
    max-width: 700px;
  }
  .header__nav ul {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-pack: distribute;
    justify-content: space-around;
  }
  .header__nav li {
    border-bottom: none;
    -webkit-box-flex: 1;
    -ms-flex-positive: 1;
    flex-grow: 1;
  }
  .header__nav a {
    background: white;
  }
}
</style>

<script>
(function() {
  var menu = new Menu({
    container: '.header__nav',
    toggleBtn: '.header__btnMenu',
    widthEnabled: 1024
  })
})()


function Menu(config) {
  this.nav = (typeof config.container === 'string') ? document.querySelector(config.container) : config.container

  this.btn = (typeof config.toggleBtn === 'string') ? document.querySelector(config.toggleBtn) : config.toggleBtn

  this.maxWidth = config.widthEnabled || false;

  var _opened = false;
  var _this = this;

  this.btn.removeAttribute('style')

  if (this.maxWidth) {
    window.addEventListener('resize', e => {
      if (window.innerWidth > _this.maxWidth) {
        _this.nav.removeAttribute('style')
        _opened = true;
      } else if (!this.nav.getAttribute('style')) {
        closeMenu();
      }
    })

    if (window.innerWidth <= _this.maxWidth) {
      closeMenu();
    }
  }

  this.btn.addEventListener('click', openOrClose)

  function openOrClose() {
    if (!_opened) {
      openMenu()
      
    } else {
      closeMenu()
      
    }
  }

  function openMenu() {
    document.getElementById("muda").className = "fa fa-window-close";
    var _top = _this.nav.getBoundingClientRect().top + 'px'

    var _style = {
      maxHeight: 'calc(100vh - ' + _top + ' )',
      overflow: 'hidden'
    }

    applyStyleToNav(_style)

    _opened = true;
  }

  function applyStyleToNav(_style) {
    Object.keys(_style).forEach(stl => {
      _this.nav.style[stl] = _style[stl]
    })
  }

  function closeMenu() {
    document.getElementById("muda").className = "fa fa-bars";
    var _style = {
      maxHeight: '0px',
      overflow: 'hidden'
    }

    applyStyleToNav(_style)

    _opened = false;
  }

}
</script>
</body>
</html>

 

Esse aqui também funciona, e altera menos ainda o seu código: (interagindo direto com o header__btnMenu)

 

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Documento sem título</title>
</head>

<body>

<!doctype html>
<html lang="pt-br">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css">
  <link rel="stylesheet" href="style/main.css">
</head>

<body>



  <header class="header">
    <a href="index.html" class="logo-text">xxxxx</a>

    <button style="display: none;" class="header__btnMenu"> <i class="fa fa-bars"></i> <span class="sr-only">Menu</span></button>

    <nav class="header__nav">
      <ul>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
        <li><a href="#">xxxxx</a></li>
      </ul>
    </nav>
  </header>

  <script src="js/menu.js"></script>
</body>

</html>

<style>
body {
  margin: 0;
}

.header {
  background: #fff;
  width: 100%;
}

.logo-text {
  background-color: #333;
  margin: 0;
  padding: 20px;
  display: block;
  text-decoration: none;
  color: #fff;
  float: left;
  text-align: center;
}

.header__nav {
  clear: left;
}

.header__nav ul {
  margin: 0;
  padding: 0;
}

.header__nav li {
  list-style-type: none;
  background: #333;
  text-align: center;
}

.header__nav a {
  text-decoration: none;
  color: #999;
  display: block;
  padding: 25px 0;
}

.header__nav a:hover {
  color: #666;
}

.header__btnMenu {
  float: right;
  margin: 1.5em;
  border: none;
}

@media screen and (min-width: 1024px) {
  .logo-text {
    width: 25%;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
  }
  .header__btnMenu {
    display: none;
  }
  .header__nav {
    float: left;
    width: 75%;
    clear: none;
    max-width: 700px;
  }
  .header__nav ul {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -ms-flex-pack: distribute;
    justify-content: space-around;
  }
  .header__nav li {
    border-bottom: none;
    -webkit-box-flex: 1;
    -ms-flex-positive: 1;
    flex-grow: 1;
  }
  .header__nav a {
    background: white;
  }
}
</style>

<script>
(function() {
  var menu = new Menu({
    container: '.header__nav',
    toggleBtn: '.header__btnMenu',
    widthEnabled: 1024
  })
})()


function Menu(config) {
  this.nav = (typeof config.container === 'string') ? document.querySelector(config.container) : config.container

  this.btn = (typeof config.toggleBtn === 'string') ? document.querySelector(config.toggleBtn) : config.toggleBtn

  this.maxWidth = config.widthEnabled || false;

  var _opened = false;
  var _this = this;

  this.btn.removeAttribute('style')

  if (this.maxWidth) {
    window.addEventListener('resize', e => {
      if (window.innerWidth > _this.maxWidth) {
        _this.nav.removeAttribute('style')
        _opened = true;
      } else if (!this.nav.getAttribute('style')) {
        closeMenu();
      }
    })

    if (window.innerWidth <= _this.maxWidth) {
      closeMenu();
    }
  }

  this.btn.addEventListener('click', openOrClose)

  function openOrClose() {
    if (!_opened) {
      openMenu()
      
    } else {
      closeMenu()
      
    }
  }

  function openMenu() {
    document.querySelector(".header__btnMenu i").className = "fa fa-window-close";
    var _top = _this.nav.getBoundingClientRect().top + 'px'

    var _style = {
      maxHeight: 'calc(100vh - ' + _top + ' )',
      overflow: 'hidden'
    }

    applyStyleToNav(_style)

    _opened = true;
  }

  function applyStyleToNav(_style) {
    Object.keys(_style).forEach(stl => {
      _this.nav.style[stl] = _style[stl]
    })
  }

  function closeMenu() {
    document.querySelector(".header__btnMenu i").className = "fa fa-bars";
    var _style = {
      maxHeight: '0px',
      overflow: 'hidden'
    }

    applyStyleToNav(_style)

    _opened = false;
  }

}
</script>
</body>
</html>

 

 Abraços colega.

Link para o comentário
Compartilhar em outros sites

@EddK Da maneira que está sendo feita aí é para algum tipo específico de projeto ou você esta aprendendo sobre construtores de objetos talvez, ou sobre operadores ternários tô certo? 

 

O código teria que ser mais curto que isso e com certeza daria certo, eu posso ver o que alterar nisso tudo, em seu JavaScript á medidas desnecessárias que prejudicam até a leitura de um analista. 

 

Tente pelo menos o uso de classes JavaScript para os construtores (o que não é nada necessário no caso). 

 

 

 

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...