Joseph Castillo
Joseph Castillo

Reputation: 85

I want to display the ID of clicked Item in a class and delete it if clicked again

I am trying to make an interface where you can select tickets and buy them, I want that when I click on a seat it displays like "You are currently buying the next tickets + (The tickets chosen by the user)".

This is my code so far:

var seatsUnclicked = document.getElementsByClassName("seat-unique");
var seatsClicked = document.getElementsByClassName("seatClicked");
var images = document.getElementsByTagName("IMG");
var seatsOutput = document.getElementsById("seatsOutput");
var ticketsData = 0
for (let i = 0; i < seatsUnclicked.length; i++) {
  seatsUnclicked[i].onmouseover = function() {
    this.src = "chairclicked.svg";
    this.onmouseout = function() {
      this.src = "chair.svg"
    }

    if ($(this).hasClass('seatClicked')) {
      this.src = "chairclicked.svg";
      this.onmouseout = function() {
        this.src = "chairclicked.svg"
      }
    }
  }

  seatsUnclicked[i].onclick = function() {
    this.classList.add("new")

    if ($(this).hasClass('seatClicked')) {
      this.classList.remove("seatClicked")
      this.classList.remove("new")
      this.src = "chair.svg";
      this.onmouseout = function() {
        this.src = "chair.svg"
      }
      ticketsData = ticketsData - /* "the id of this element in a string" */
    }

    if ($(this).hasClass('new')) {
      this.src = "chairclicked.svg";
      this.classList.add("seatClicked")
      this.classList.remove("new")
      this.onmouseout = function() {
        this.src = "chairclicked.svg"
      }
      ticketsData = ticketsData + /* "the ID of this element in a string" */
    }

    seatsOutput.innerHTML = "THE TICKETS YOU HAVE CHOSEN ARE" + string(ticketsData)
  }
}
<div class="seats-row-A">
  <img id="A1" class="seat-unique " src="http://via.placeholder.com/100x100?text=A1">
  <img id="A2" class="seat-unique " src="http://via.placeholder.com/100x100?text=A2">
  <img id="A3" class="seat-unique " src="http://via.placeholder.com/100x100?text=A3">
  <img id="A4" class="seat-unique " src="http://via.placeholder.com/100x100?text=A4">
  <img id="A5" class="seat-unique" src="http://via.placeholder.com/100x100?text=A5">
  <img id="A6" class="seat-unique " src="http://via.placeholder.com/100x100?text=A6">
  <img id="A7" class="seat-unique " src="http://via.placeholder.com/100x100?text=A7">
</div>
<h2 id="seatsOutput">Chosen Tickets:</h2>

Upvotes: 3

Views: 75

Answers (1)

zer00ne
zer00ne

Reputation: 43930

jQuery


The only jQuery statement in OP code is: $(this).hasClass('seatClicked').

The plain JavaScript equivalent is: this.classList.contains('seatClicked').


Question


I couldn't follow the OP code because there was only a class, an id, and img tags that match the JavaScript, but it's not that clear because of the *.svg files (not provided.) Also, there's a curly bracket } missing (I think it belongs to the for loop, but I'm not wasting time on debugging typos.)

The Demo was built in mind with what the question and comments had mentioned:

  • "...I want that when I click on a seat it displays like "You are currently buying..."

  • Highlight icon when hovered over.

  • Reveal icon's id when hovered on.

All hover behavior is done with CSS: :hover, ::before, ::after, content: attr(id), content: '\a0\1f4ba'. Using JavaScript for behavior CSS can do will result in more CPU cycles. CSS will use GPU of your graphics card instead of the CPU.


Testing

The seats are dynamically generated with id="A* by entering a number in the input and clicking the View button. For each additional click of the button a new batch of seats are appended and have ids that correspond to it's group:

input: 55 and first click A0-A55,
input: 12 and second click B0-B12,
input: 222 and third click C0-C222
...
Last group is J


References


The Demo is basically a <form>. HTMLFormControlsCollection API is used to set/get form controls and values.

Reference the tag

const ui = document.forms.tickets;

This is a collection of all form controls in form#tickets

const t = ui.elements;

Now all form controls are now accessible by prefixing a form control's #id or [name] with the HTMLFormControlsCollection Object.

<textarea name='textA'></textarea>

Without HFCC API

var ta = document.querySelector('[name=textA]');

With HFCC API

var ta = t.textA;

The links are collected by Links Collection.

document.links


DocumentFragment is used to insert a huge amount of dynamic HTML in one shot efficiently and quickly.

document.createDocumentFragment();


Various array methods were used:


Demo


const ui = document.forms.tickets;
const t = ui.elements;
const seats = document.getElementById('seats');

t.btn.addEventListener('click', seatsAvailable);

seats.addEventListener('click', function(e) {
  let picked = [];
  pickSeat(e, picked);
}, false);


function pickSeat(e, picked) {
  const display = t.display;
  if (e.target.tagName === "A") {
    e.target.classList.toggle('picked');
    picked = Array.from(document.querySelectorAll('.picked'));
  }
  picked = picked.map(function(seat, index, picked) {
    return seat.id;
  });
  display.value = "";
  display.value = picked;
}

function seatsAvailable(e) {
  const qty = this.previousElementSibling;
  const last = document.links[document.links.length - 1].id;
  console.log(last);
  const limit = parseInt(qty.value, 10) + 1;
  const spots = new Array(limit);
  spots.fill(0, 0, limit);
  return generateSeats(spots, last);
}

function generateSeats(spots, last) {
  if (last.charAt(0) === "J") {
    t.display.textContent += "Last row available";
    return false;
  }
  const rowID = ['x', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'];
  let row = rowID.indexOf(last.charAt(0)) + 1;

  const frag = document.createDocumentFragment();
  const avSeats = spots.map(function(A, idx) {
    const seat = document.createElement('a');
    seat.id = rowID[row] + idx;
    seat.href = "#/";
    frag.appendChild(seat);
    return seat;
  });
  seats.appendChild(frag);
  if (document.links[0].id === 'x') {
    const x = document.getElementById('x');
    x.parentElement.removeChild(x);
  }
  if (document.links.length > 114) {
    const ext = (Math.round(document.links.length / 114)*600)+600;
    seats.style.maxHeight = ext+'px';
  }
  return avSeats;
}
html,
body {
  width: 100%;
  height: 10%;
  font: 400 16px/1.3 Consolas;
}

#seats {
  display: flex;
  flex-flow: column wrap;
  max-height: 600px;
  width: auto;
  border: 3px ridge grey;
}

.box {
  display: table
}

input,
button,
label {
  font: inherit
}

#qty {
  text-align: right
}

#display {
  display: table-cell;
}

.tag {
  overflow-x: scroll;
  overflow-y: hidden;
  display: block;
  width: 400px;
  line-height: 1.3
}

a,
a:link,
a:visited {
  display: inline-block;
  margin: 0;
  text-align: center;
  text-decoration: none;
  transition: all 500ms ease;
}

a:hover,
a:active {
  background: rgba(0, 0, 0, 0);
  color: #2468ac;
  box-shadow: 0 0 0 3px #2468ac;
}

a::before {
  content: attr(id);
  color: transparent;
}

a:hover::before {
  color: #2468ac;
}

a.picked::before {
  color: #000;
}

a::after {
  content: '\a0\1f4ba';
  font-size: 1.5rem;
}

#x {
  pointer-events: none
}

.as-console-wrapper {
  width: 30%;
  margin-left: 70%
}
<form id='tickets'>

  <fieldset class='box'>
    <legend>Available Seats</legend>

    <fieldset class='box'>
      <input id='qty' type='number' min='0' max='50' value='1'> <button id='btn' type='button'>View</button>

      <label class='tag'>Current ticket purchases to seats: 
       <output id='display'></output>
     </label>

    </fieldset>

    <section id='seats'>
      <a id='x' href='#/'></a>
    </section>

  </fieldset>

</form>

Upvotes: 1

Related Questions