2

Actually, I am trying to get a single table column value after search. If I select = operator and type column any input value and then after a search, the input value will get like one or more row that matches the similar value. In the same way, if I select < operator and this column any input value the less than input value will get if I select > operator and this column any input value the greater than input value will get if I select <= operator and this column any input value the less than or equal input value will get if I select >= operator and this column input value the greater than or equal input value will get. But I can't do this column search. How can I solve this search problem?

$('button').click(function(){
  var avlQuantity = new Array();
  var aggOperator = $('#aggregate_condition').val();
  var inputValue = $('#available_quantity').val();
  console.log(aggOperator,inputValue,idValue)
  $('table tbody tr').each(function(){
      avlQuantity.push($(this).find('td').text());
      console.log($(this).find('td').text());
  });

  if(aggOperator,inputValue){
      avlQuantity.push($(this).find('td').text());
      // console.log(avlQuantity.push($(this).find('td').text()));
      console.log(aggOperator,inputValue)
  }

  var counter = 0;
  $('table tbody tr').each(function(){
      counter++
      var rowId = $(this);
      rowId.addClass("rowId_"+counter);
      $(this).find("rowId"+counter).text();
      console.log("rowId_"+counter);

      avlQuantity.forEach(function(rowId){
          if(rowId == "rowId_"+counter){
              $("rowId_"+counter).show();
          }
      })
  })

  console.log('end');

})
table {
      width: 100%;
  }
  table thead th {
      padding: 15px;
  }
  table tbody tr td{
      padding: 10px;
      text-align: center;
  }
  .text-center{
      text-align: center;
  }
  .header-name{
      display: flex;
      justify-content: center;
      align-items: center;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<table>
<thead>
    <th class="text-center">
        Regular Price
        <div class="header-name">
            <div>
                <select id="aggregate_condition">
                    <option value="=">=</option>
                    <option value="<">&lt;</option>
                    <option value=">">&gt;</option>
                    <option value="<=">≤</option>
                    <option value=">=">≥</option>
                </select>
            </div>
            <div>
                <input type="text" id="available_quantity">
            </div>
            <div>
                <button type="submit">Apply</button>
            </div>
        </div>
    </th>
</thead>
<tbody>
    <tr>
        <td>4</td>
    </tr>
    <tr>
        <td>9</td>
    </tr>
    <tr>
        <td>1</td>
    </tr>
    <tr>
        <td>0</td>
    </tr>
    <tr>
        <td>6</td>
    </tr>
    <tr>
        <td>1</td>
    </tr>
    <tr>
        <td>6</td>
    </tr>
</tbody>
</table>
  • 1
    HTML basics: Use `<` and `>` instead of `< >` – Roko C. Buljan Feb 27 '21 at 17:46
  • Thanks for your comment, but I couldn't solve it yet. – Solaiman Hossain Feb 27 '21 at 18:01
  • There's some strange code - you loop over the rows to find ids to then display later - why not just display them as you find them? `$("rowId_"+counter)` - missing `#`? No, missing `.` as you `addClass(rowId...)` – freedomn-m Feb 27 '21 at 18:03
  • `id="id-value"` you're not using that element - what's the purpose of it – Roko C. Buljan Feb 27 '21 at 18:04
  • To go with HTML basics - code basics - name variables for what they are so you don't confuse them later `var rowId = $(this)` refers to a jquery object, so `if (rowId == "rowId...`) - it won't because it's not a string. Not really sure what you wanted, but could be `var rowId = $(this).find("td").first().text()` – freedomn-m Feb 27 '21 at 18:05
  • for identifying the column name @ Roko C. Buljan – Solaiman Hossain Feb 27 '21 at 18:05
  • @SolaimanHossain I'll remove it for my example. I have no idea what's for – Roko C. Buljan Feb 27 '21 at 18:08
  • @Roko C. Buljan, I remove it already. Its nothing for using. – Solaiman Hossain Feb 27 '21 at 18:11
  • My bad above, you've confusingly used the same variable name inside the loop `.forEach(function(rowId)` which hides the outer rowId = element. Don't do that. – freedomn-m Feb 27 '21 at 18:13
  • 1
    *single table column* - you only have 1 column, so probably mean "table row". `.each(function() { counter++` - you don't need a `counter` here, `.each` comes with one `.each(index, element)` https://api.jquery.com/each/ `if(aggOperator,inputValue)` - the `,` comma operator is a very esoteric operator - it's *highly unlikely* this is what you want here - and if it is, there's clearer (KISS) ways of doing this - this is probably where you want a `switch`. `var rowid=$(this)`..`.each(rowid)` - try not to reuse variable names. – freedomn-m Feb 27 '21 at 18:15
  • @ freedomn-m Thanks for your suggestions. – Solaiman Hossain Feb 27 '21 at 18:26

3 Answers3

3
  • You don't need any <button>.
  • Use jQuery's .filter() method to filter your elements and toggle a class accordingly using .removeClass() and .addClass()
  • Use an object aggrFn to reference your functions that will do the calculations depending on the used operator < > = <= >= that will triggered on "input" event of both the input and select box.

const $avail = $("#available_quantity");
const $table = $avail.closest("table");
const $aggre = $("#aggregate_condition");

const aggrFn = {
  "=":  (a,b) => a == b,
  "<":  (a,b) => a  < b,
  ">":  (a,b) => a  > b,
  "<=": (a,b) => a <= b,
  ">=": (a,b) => a >= b,
};

function filterTableByQty() {
  const ag = $aggre.val();
  const av = $avail.val().trim();  
  const $rowsQty = $table.find("[data-qty]")
  $rowsQty.removeClass("u-none");
  if (av === "") return;
  $rowsQty.filter((i, el) => !aggrFn[ag](el.dataset.qty, +av)).addClass("u-none");
}

$avail.add($aggre).on("input", filterTableByQty);
* {margin:0; box-sizing: border-box;}

.header-name {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* UTILITY CLASSES */

.u-none {
  display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<table>
  <thead>
    <th>
      Available Quantity
      <div class="header-name">
        <div>
          <select id="aggregate_condition">
            <option value="=">=</option>
            <option value="<">&lt;</option>
            <option value=">">&gt;</option>
            <option value="<=">≤</option>
            <option value=">=">≥</option>
          </select>
        </div>
        <div>
          <input type="text" id="available_quantity">
        </div>
      </div>
    </th>
  </thead>
  <tbody>
    <tr data-qty="4"><td>4</td></tr>
    <tr data-qty="9"><td>9</td></tr>
    <tr data-qty="1"><td>1</td></tr>
    <tr data-qty="0"><td>0</td></tr>
    <tr data-qty="6"><td>6</td></tr>
    <tr data-qty="1"><td>1</td></tr>
    <tr data-qty="6"><td>6</td></tr>
  </tbody>
</table>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • For the multiple columns like regular price, base price, available quantity, how can I handle this aggregate input value column search individually? After applying your formula I am facing this problem right now. – Solaiman Hossain Mar 01 '21 at 06:53
  • Have a look at this problem - https://stackoverflow.com/questions/66419395/table-each-column-search-by-using-aggregate-operator-javascript – Solaiman Hossain Mar 01 '21 at 10:00
2

you can use eval("3" + ">" + 1) or function like below

var compare = {
  '==': function(a, b) { return a == b; },
  '<': function(a, b) { return a < b; },
  '>': function(a, b) { return a > b; },
  '>=': function(a, b) { return a >= b; },
  '<=': function(a, b) { return a <= b; },
};

$('button').click(function() {
  $('tbody tr').hide()
  var aggOperator = $('#aggregate_condition').val();
  var inputValue = $('#available_quantity').val();
  $.each($('tbody tr'), function(i, tr) {
    var rowText = tr.innerText.trim();
    // var isTrue = eval(rowText +aggOperator+ inputValue); <==== using eval()
    var isTrue = compare[aggOperator](rowText, inputValue)
    if (isTrue) {
      $(tr).show()
    }
  })
})
table {
  border-collapse: collapse;
}
table, td, th {
  border: 1px solid #bbb;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<table>
  <thead>
    <th class="text-center">
      Regular Price
      <div class="header-name">
        <div>
          <select id="aggregate_condition">
            <option value="==">==</option>
            <option value="<">&lt;</option>
            <option value=">">&gt;</option>
            <option value="<=">&lt;=</option>
            <option value=">=">&gt;=</option>
          </select>
        </div>
        <div>
          <input type="text" id="available_quantity">
          <input type="hidden" id="id-value" value="available-qty">
        </div>
        <div>
          <button type="submit">Apply</button>
        </div>
      </div>
    </th>
  </thead>
  <tbody>
    <tr>
      <td>4</td>
    </tr>
    <tr>
      <td>9</td>
    </tr>
    <tr>
      <td>1</td>
    </tr>
    <tr>
      <td>0</td>
    </tr>
    <tr>
      <td>6</td>
    </tr>
    <tr>
      <td>1</td>
    </tr>
    <tr>
      <td>6</td>
    </tr>
  </tbody>
</table>
uingtea
  • 6,002
  • 2
  • 26
  • 40
  • 1
    *"Use `eval` like below"*?? - but below there's no eval :D Also - Never really ever suggest people to use eval on a string that is carelessly passed trough a user input. – Roko C. Buljan Feb 27 '21 at 18:15
  • 1
    updated, I'm not adding eval because alot people dont like that. – uingtea Feb 27 '21 at 18:19
  • `innerText` ? You should rather use `textContent` instead. I know it's name is similar to `innerHTML` but... yeah. [Why](https://stackoverflow.com/questions/35213147/difference-between-textcontent-vs-innertext) – Roko C. Buljan Feb 27 '21 at 18:41
  • People "do not like eval" because: **Warning: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). See Never use eval()!** :https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval As you see its not about liking, its a big no-no – ikiK Feb 27 '21 at 21:12
2

My solution:

you need to convert aggOperator into function and return, you can not use it as string.

So i made getCal function that has if statement inside that returns true or false if td maches condition from that function and show/hide the td itself based on it.

if (' + available_quantity + ' ' + aggOperator + ' ' + val + '){return true}else{return false};

Then apply that:

let cheak = getCal(aggOperator, available_quantity, val)
cheak === true ? $(this).parent("tr").show() : $(this).parent("tr").hide()

$('button').click(function() {
  let available_quantity = $("#available_quantity").val();
  let aggOperator = $('#aggregate_condition').find(":selected").val();


  $("table tbody tr td").each(function(e) {
    let val = $(this).text().trim()
    let cheak = getCal(aggOperator, available_quantity, val)
    cheak === true ? $(this).parent("tr").show() : $(this).parent("tr").hide()
  })

})

function getCal(aggOperator, available_quantity, val) {
  return Function('"use strict"; if (' + available_quantity + ' ' + aggOperator + ' ' + val + '){return true}else{return false};')();
}
table {
  width: 100%;
}

table thead th {
  padding: 15px;
}

table tbody tr td {
  padding: 10px;
  text-align: center;
}

.text-center {
  text-align: center;
}

.header-name {
  display: flex;
  justify-content: center;
  align-items: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<table>
  <thead>
    <th class="text-center">
      Regular Price
      <div class="header-name">
        <div>
          <select id="aggregate_condition">
            <option value="===">=</option>
            <option value="<">
              <</option>
                <option value=">">></option>
                <option value="<=">≤</option>
                <option value=">=">≥</option>
          </select>
        </div>
        <div>
          <input type="text" id="available_quantity">
          <input type="hidden" id="id-value" value="available-qty">
        </div>
        <div>
          <button type="submit">Apply</button>
        </div>
      </div>
    </th>
  </thead>
  <tbody>
    <tr>
      <td>4</td>
    </tr>
    <tr>
      <td>9</td>
    </tr>
    <tr>
      <td>1</td>
    </tr>
    <tr>
      <td>0</td>
    </tr>
    <tr>
      <td>6</td>
    </tr>
    <tr>
      <td>1</td>
    </tr>
    <tr>
      <td>6</td>
    </tr>
  </tbody>
</table>
ikiK
  • 6,328
  • 4
  • 20
  • 40