How to count state changes in fields with a given class inside a function?

6

How do I count how many changes occur in all fields of a form with a given class?

Update: What I want to know is if there was any change in each field ( one ), not how many times there was change in each field (even if the user changes the option, counts only once - the first. ..). In short, just how many fields with the class in question have been modified once (at least).

For example:

$("select, input").one('change', function () {

    var totalSelect = $('select').length;
    var totalInputs = $('input').length;
    var ocultosOuOpcionais = $('.ocultosOuOpcionais').length;
    var ocultosOuOpcionaisMudados = ?????
    var total = (totalInputs + totalSelect + ocultosOuOpcionaisMudados) - ocultosOuOpcionais;
});

Whenever there is a state change in some of the fields with class .ocultosOuOpcionais , I want to update the variable ocultosOuOpcionaisMudados . How can I do this?

    
asked by anonymous 21.12.2015 / 18:51

2 answers

2

You can use data-attributes to "store" the state of the element. For example, having an element ( input, select, textarea ) with the attribute data-foi-modificado :

<input type='text' data-foi-modificado />

And with JQuery you can change this property:

$('input').one('change', function(){
  $(this).data('foi-modificado', true);
});

Later you can make a filter or use the selector itself to get only elements that are foi-modificado = "true" . Here's an example testing some elements:

$(function(){

  // Quando houver mudança ou perder o foco, o atributo 'foi-modificado'
  // passará a ter valor 'true'.
  $('.ocultosOuOpcionais').one('change', function(){
  	$(this).data('foi-modificado', true);
  });


  $('button').on('click', function(){
	// Filtrando todos em que 'foi-modificado' é true.
    var modificados = $('.ocultosOuOpcionais').filter(function(){
  	  return $(this).data('foi-modificado');
    });
  
    var mensagem = 'Modificados: ';
    modificados.each(function(indice, elemento){
  	  mensagem += $(elemento).prop('name') + ', ';
    });
    alert(mensagem);
  });
});
span { display: inline-block; width: 100% }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<span>
  1. <input class='ocultosOuOpcionais' type='text' name='1' data-foi-modificado/>
</span>

<span>
  2. <input class='ocultosOuOpcionais' type='number' name='2' data-foi-modificado/>
</span>

<span>
  3. <input class='ocultosOuOpcionais' type='color' name='3' data-foi-modificado/>
</span>

<span>
  4. <input class='ocultosOuOpcionais' type='tel' name='4' data-foi-modificado/>
</span>

<span>
  5. <select class='ocultosOuOpcionais' name='5' data-foi-modificado>
    <option selected>A</option>
    <option>B</option>
  </select>
</span>

<span>
  6. <input class='ocultosOuOpcionais' type='radio' name='6' data-foi-modificado/>
</span>

<span>
  7. <input class='ocultosOuOpcionais' type='checkbox' name='7' data-foi-modificado/>
</span>

<button>Quem foi Modificado?</button>
    
22.12.2015 / 02:45
2

Well, basically what I understood is that you want to capture the changes of each element of class ocultosOuOpcionais and then add them:

Capturing character difference

As explained, in this question the best way to calculate the difference between two strings is to use the Distance from Levenshtein :

function levenshtein(str1, str2) {
  var m = str1.length,
      n = str2.length,
      d = [],
      i, j;

  if (!m) return n;
  if (!n) return m;

  for (i = 0; i <= m; i++) d[i] = [i];
  for (j = 0; j <= n; j++) d[0][j] = j;

  for (j = 1; j <= n; j++) {
    for (i = 1; i <= m; i++) {
      if (str1[i-1] == str2[j-1]) d[i][j] = d[i-1][j-1];
      else d[i][j] = Math.min(d[i-1][j], d[i][j-1], d[i-1][j-1])+1;
    }
  }
  return d[m][n];
}

In my example, the function is named captureChanges() .

To capture this difference of the initial and current value of a input , use .defaultValue and .value , respectively. I've adapted it to your code as follows:

var ocultosOuOpcionais = [].slice.call(document.querySelectorAll(".ocultosOuOpcionais"));
var mudados = [];
var mudancas = [];
var ocultosOuOpcionaisMudados = 0; 

ocultosOuOpcionais.forEach(function (input, indice) {
  input.addEventListener("input", function (event) {
    if (event.target.defaultValue == event.target.value) {
      mudados[event.target.id] = 0;
    } else {
      mudados[event.target.id] = event.target.defaultValue;
    }
    mudancas[indice] = captureChanges(mudados[event.target.id], event.target.value);
  });

The above code is an adaptation to TobyMosque's JsFiddle present in the question comments.

Once this is done, just add the differences of each input :

input.addEventListener('keyup', function(){
  mudancas.forEach(function(el, index){
    ocultosOuOpcionaisMudados += parseFloat(el);
  })
  ocultosOuOpcionaisMudados = 0; // É importante que ao final se zere o valor para que não se acumule exacerbadamente
})

Putting the whole code together

function captureChanges(str1, str2) {
  var m = str1.length,
    n = str2.length,
    d = [],
    i, j;

  if (!m) return n;
  if (!n) return m;

  for (i = 0; i <= m; i++) d[i] = [i];
  for (j = 0; j <= n; j++) d[0][j] = j;

  for (j = 1; j <= n; j++) {
    for (i = 1; i <= m; i++) {
      if (str1[i - 1] == str2[j - 1]) d[i][j] = d[i - 1][j - 1];
      else d[i][j] = Math.min(d[i - 1][j], d[i][j - 1], d[i - 1][j - 1]) + 1;
    }
  }
  return d[m][n];
}

var ocultosOuOpcionais = [].slice.call(document.querySelectorAll(".ocultosOuOpcionais"));
var mudados = [];
var mudancas = [];
var n = 0;
var ocultosOuOpcionaisMudados = 0;

ocultosOuOpcionais.forEach(function(input, indice) {
  input.addEventListener("input", function(event) {
    if (event.target.defaultValue == event.target.value) {
      mudados[event.target.id] = 0;
    } else {
      mudados[event.target.id] = event.target.defaultValue;
    }
    mudancas[indice] = captureChanges(mudados[event.target.id], event.target.value);
  });
  input.addEventListener('keyup', function() {
    mudancas.forEach(function(el, index) {
      n += parseFloat(el);
    })
    ocultosOuOpcionaisMudados = n;
    n = 0;

    document.getElementsByTagName("h4")[0].innerHTML = "Mudanças no total:";
    document.getElementsByTagName("p")[0].innerHTML = ocultosOuOpcionaisMudados;
  })
});
<input type="text" class="ocultosOuOpcionais">
<br>
<input type="text" class="ocultosOuOpcionais">
<br>
<input type="text" class="ocultosOuOpcionais">
<br>
<input type="text" class="ocultosOuOpcionais">
<br>
<h4></h4>
<p></p>
    
22.12.2015 / 03:24