2
\$\begingroup\$

I've written a simple JS that takes care to animate an icon.

At first I wrote it quickly and without paying attention to any kind of optimization:

import '../js/core/sidenav.js';

const SIDENAV_ITEM_USER = document.getElementById('sidenav-item-user');
const SIDENAV_ITEM_SEARCH = document.getElementById('sidenav-item-search');
const SIDENAV_ITEM_ORDER = document.getElementById('sidenav-item-order');
const SIDENAV_ITEM_FILTER = document.getElementById('sidenav-item-filter');

let sidenav_item_icon_angle_user = '0';
let sidenav_item_icon_angle_search = '0';
let sidenav_item_icon_angle_order = '0';
let sidenav_item_icon_angle_filter = '0';

SIDENAV_ITEM_USER.addEventListener('click', function() {
  rotate('user');
});

SIDENAV_ITEM_SEARCH.addEventListener('click', function() {
  rotate('search');
});

SIDENAV_ITEM_ORDER.addEventListener('click', function() {
  rotate('order');
});

SIDENAV_ITEM_FILTER.addEventListener('click', function() {
  rotate('filter');
});

function rotate(target) {
  if (target == 'user') {
    var element = document.getElementById('sidenav-item-icon-user');

    if (sidenav_item_icon_angle_user == 0) {
      sidenav_item_icon_angle_user = '180';
    } else {
      sidenav_item_icon_angle_user = '0';
    }

    element.style.transform = 'rotate(' + sidenav_item_icon_angle_user + 'deg)';
  }

  if (target == 'search') {
    var element = document.getElementById('sidenav-item-icon-search');

    if (sidenav_item_icon_angle_search == 0) {
      sidenav_item_icon_angle_search = '180';
    } else {
      sidenav_item_icon_angle_search = '0';
    }

    element.style.transform = 'rotate(' + sidenav_item_icon_angle_search + 'deg)';
  }

  if (target == 'order') {
    var element = document.getElementById('sidenav-item-icon-order');

    if (sidenav_item_icon_angle_order == 0) {
      sidenav_item_icon_angle_order = '180';
    } else {
      sidenav_item_icon_angle_order = '0';
    }

    element.style.transform = 'rotate(' + sidenav_item_icon_angle_order + 'deg)';
  }

  if (target == 'filter') {
    var element = document.getElementById('sidenav-item-icon-filter');

    if (sidenav_item_icon_angle_filter == 0) {
      sidenav_item_icon_angle_filter = '180';
    } else {
      sidenav_item_icon_angle_filter = '0';
    }

    element.style.transform = 'rotate(' + sidenav_item_icon_angle_filter + 'deg)';
  }
}

Subsequently, having verified that the animations work, I have optimized the code:

import '../js/core/sidenav.js';

const SIDENAV_CONTENT = document.getElementById('sidenav-content');
const SIDENAV_CONTENT_NODES = SIDENAV_CONTENT.querySelectorAll('a');

var angles = new Map();

SIDENAV_CONTENT_NODES.forEach(function(target) {
  if (target.getAttribute('id').includes('item')) {
    var identifier = target.getAttribute('href').split('-')[3];
    
    angles.set(identifier, '0');

    target.addEventListener('click', function() {
      rotate(identifier);
    });
  }
});

function rotate(target) {
  var element = document.getElementById(`sidenav-item-icon-${target}`);

  angles.get(target) == '0' ? angles.set(target, '180') : angles.set(target, '0');
  element.style.transform = `rotate(${angles.get(target)}deg)`;
}

To better understand, this is my HTML:

<div id="sidenav-content" class="sidenav-content">
  <div id="sidenav-general-mobile-view">
    <ul>
      <li>
        <a id="nav-icon" href="#"><img class="nav-icon" src="../assets/images/nav_cart.svg" height="25">Carrello<span class="badge rounded-pill bg-danger nav-badge">5</span></a>
      </li>
      <li>
        <div class="card card-user">
          <div class="card-header">
            <a data-bs-toggle="collapse" id="sidenav-item-user" href="#sidenav-item-body-user" role="button" aria-expanded="false" aria-controls="sidenav-item-body-user">
              <img class="icon" src="../assets/images/nav_user.svg" height="25">
              <p class="d-inline mb-0">Accedi</p>
              <img class="arrow" src="../assets/images/sn_general_down.svg" id="sidenav-item-icon-user" height="14" alt="sidenav_item_user_icon">
            </a>
          </div>
          <div class="card-body collapse" id="sidenav-item-body-user">
            <div class="p-16">
              <ul class="mb-0">
                <li>
                  <a id="nav-signup" href="#">Registrati</a>
                </li>
                <li>
                  <a id="nav-signin" href="#">Accedi</a>
                </li>
              </ul>
            </div>
          </div>
        </div>
      </li>
    </ul>
  </div>
  <div class="card">
    <div class="card-header">
      <a data-bs-toggle="collapse" id="sidenav-item-search" href="#sidenav-item-body-search" role="button" aria-expanded="false" aria-controls="sidenav-item-body-search">
        <p class="d-inline mb-0">Cerca</p>
        <img class="arrow" src="../assets/images/sn_general_down.svg" id="sidenav-item-icon-search" height="14" alt="sidenav_item_search_icon">
      </a>
    </div>
    <div class="card-body collapse" id="sidenav-item-body-search">
      <div class="p-16">
        <div class="input-group input-search">
          <span class="input-group-text">
          <img src="../assets/images/input_search.svg" height="14" alt="input-search-icon">
          </span>
          <input type="text" class="form-control" placeholder="Cerca nel catalogo" aria-label="input-search" aria-describedby="basic-addon1">
        </div>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header">
      <a data-bs-toggle="collapse" id="sidenav-item-order" href="#sidenav-item-body-order" role="button" aria-expanded="false" aria-controls="sidenav-item-body-order">
        <p class="d-inline mb-0">Ordina</p>
        <img class="arrow" src="../assets/images/sn_general_down.svg" id="sidenav-item-icon-order" height="14" alt="sidenav_item_order_icon">
      </a>
    </div>
    <div class="card-body collapse" id="sidenav-item-body-order">
      <div class="p-16">
        <div class="form-check">
          <input class="form-check-input" type="radio" name="flexRadioDefault" id="order-default" checked>
          <label class="form-check-label" for="order-default">Ultimi arrivi</label>
        </div>
        <div class="form-check">
          <input class="form-check-input" type="radio" name="flexRadioDefault" id="order-2">
          <label class="form-check-label" for="order-2">Prezzo crescente</label>
        </div>
        <div class="form-check">
          <input class="form-check-input" type="radio" name="flexRadioDefault" id="order-3">
          <label class="form-check-label" for="order-3">Prezzo decrescente</label>
        </div>
        <div class="form-check mb-0">
          <input class="form-check-input" type="radio" name="flexRadioDefault" id="order-4">
          <label class="form-check-label" for="order-4">In promozione</label>
        </div>
      </div>
    </div>
  </div>
  <div class="card">
    <div class="card-header">
      <a data-bs-toggle="collapse" id="sidenav-item-filter" href="#sidenav-item-body-filter" role="button" aria-expanded="false" aria-controls="sidenav-item-body-filter">
        <p class="d-inline mb-0">Filtra</p>
        <img class="arrow" src="../assets/images/sn_general_down.svg" id="sidenav-item-icon-filter" height="14" alt="sidenav_item_filter_icon">
      </a>
    </div>
    <div class="card-body collapse" id="sidenav-item-body-filter">
      <div class="p-16">
      </div>
    </div>
  </div>
</div>

And a video on how it works:

I would like to know if the "optimization" is necessary given the simplicity and length of the code.

Making my considerations:

Pro: A more streamlined and clean code and the ability to add new elements without having to touch the JS again. Against: Possible increased use of resources due to the use of objects and loops. (?)

Possibly do you know better ways to optimize this code?

\$\endgroup\$
3
  • 1
    \$\begingroup\$ All that isn't really necessary. It can be done much simpler with one line of CSS: [aria-expanded="true"] .arrow { transform: rotate(180deg) }. \$\endgroup\$ Commented Sep 16, 2021 at 17:10
  • 1
    \$\begingroup\$ @RoToRa thanks for your comment, I'm new to web development, can you be more detailed? \$\endgroup\$ Commented Sep 16, 2021 at 21:43
  • 1
    \$\begingroup\$ Here is an example: jsfiddle.net/14j9k8he \$\endgroup\$ Commented Sep 17, 2021 at 10:08

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.