Play sound when changing content in a table

2

I'm trying to create a function that will play a sound when some element of a table changes, I was trying it in the following way:

$(document).ready(function(){
 $("#hor-zebra").change(function(){
     document.getElementById('bflat').play()
 });
});

This would be the HTML:

<audio id="bflat" src="timbre.mp3"></audio>

<table id="hor-zebra" class="col-6" summary="">
<thead>
<tr>
    <th scope="col">Ticket</th>
    <th scope="col">Puesto</th>
</tr>
</thead>
<tbody>
<tr class="odd first">
    <td class="first">A083</td>
    <td class="first">MESA 1</td>
</tr>
<tr class="odd">
    <td>B064</td>
    <td>MESA 9</td>
</tr>
<tr>
    <td>C028</td>
    <td>MESA 5</td>
</tr>
</tbody>

Any ideas on how to do it? Thanks.

    
asked by Luis 07.11.2017 в 13:26
source

2 answers

1

With the API MutationObserver you can watch for changes in the DOM and act accordingly thereto. Note that this API does not have full support from older browsers, so for these browsers it is very likely that you have to have some kind of fallback. You can see a compatibility table in caniuse .

Example

const table = document.querySelector('#hor-zebra tbody');
const form = document.querySelector('#new-ticket');
const ctx = new AudioContext();
const audio = 'https://dl.dropboxusercontent.com/s/1gjdrndza3egi9e/communication-channel.mp3?dl=0';

const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.type === 'childList') {
      fetchAudio().then(buffer => play(buffer));
    }
  });
});

observer.observe(table, { childList: true });

form.addEventListener('submit', (e) => {
  e.preventDefault();
  const ticket = form.ticket.value;
  const place = form.place.value;
  const tr = document.createElement('tr');
  const tdTicket = document.createElement('td');
  const tdPlace = document.createElement('td');
  tdTicket.textContent = ticket;
  tdPlace.textContent = place;
  tr.appendChild(tdTicket);
  tr.appendChild(tdPlace);
  table.appendChild(tr);
  form.reset();
  form.ticket.focus();
});

const fetchAudio = () => (
  fetch(audio).then(res => res.arrayBuffer())
);

const play = (buffer) => {
  const source = ctx.createBufferSource();
  ctx.decodeAudioData(buffer, (data) => {
    source.buffer = data;
    source.connect(ctx.destination);
    source.start(0)
  });
};
.row {
  display: flex;
  justify-content: space-around;
}
.form-group {
  align-items: center;
  display: flex;
  flex: 0 0 47.5%;
}
input {
  border: 1px solid #ccc;
  border-radius: 4px;
  flex: 1;
  margin-left: 5px;
  padding: 8px 12px;
}
.row:last-of-type {
  justify-content: flex-end;
}
button {
  border: none;
  border-radius: 4px;
  background-color: #3498db;
  color: #fff;
  margin-top: 10px;
  padding: 8px 12px;
}
table {
  border-collapse: collapse;
  margin-top: 20px;
  width: 100%;
}
th, td {
  font-size: 15px;
  padding: 10px 12px;
  text-align: center;
}
th {
  background-color: #f5f5f5;
}
tbody tr {
  border-bottom: 1px solid #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fetch/2.0.3/fetch.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-promise/4.1.1/es6-promise.min.js"></script>

<form id="new-ticket">
  <div class="row">
    <div class="form-group">
      <label for="ticket">Ticket</label>
      <input type="text" name="ticket" required />
    </div>
    <div class="form-group">
      <label for="place">Puesto</label>
      <input type="text" name="place" required />
    </div>
  </div>
  <div class="row">
    <button type="submit">Add</button>
  </div>
</form>

<table id="hor-zebra">
  <thead>
    <tr>
      <th>Ticket</th>
      <th>Puesto</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>A083</td>
      <td>MESA 1</td>
    </tr>
    <tr>
      <td>B064</td>
      <td>MESA 9</td>
    </tr>
    <tr>
      <td>C028</td>
      <td>MESA 5</td>
    </tr>
  </tbody>
</table>
    
answered by 07.11.2017 в 15:04
0

The change event only works on those elements that have a value as input, select, textarea . What you need is to add the event DOMSubtreeModified , which is executed when a node is deleted or added to an element.

$(document).ready(function () {
  $('.js_add_row').click(function () {
    $('#hor-zebra > tbody').append(
      '<tr><td>Test</td><td>Mesa Test</td></tr>'
    );
  });
  
  $('#hor-zebra').on('DOMSubtreeModified', function() {
    document.getElementById('bflat').play()
    console.log('beep');
  });
})
<audio id="bflat" src="timbre.mp3"></audio>
<button type="button" class="js_add_row">Agregar Columna</button>
<table id="hor-zebra" class="col-6" summary="">
<thead>
<tr>
    <th scope="col">Ticket</th>
    <th scope="col">Puesto</th>
</tr>
</thead>
<tbody>
<tr class="odd first">
    <td class="first">A083</td>
    <td class="first">MESA 1</td>
</tr>
<tr class="odd">
    <td>B064</td>
    <td>MESA 9</td>
</tr>
<tr>
    <td>C028</td>
    <td>MESA 5</td>
</tr>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
answered by 07.11.2017 в 13:53