Javascript issue with keyup function - trying to use same form field on page multiple times but only 1st form field works

血红的双手。 提交于 2019-12-24 13:10:51

问题


  1. I have multiple vocabulary tables on the same html page.
  2. Above each vocabulary table, I would like to enable users to enter a word or phrase in a field to view only the table rows that contain the entered word or phrase. For example, if you enter "orde", the table rows that do not contain the string "orde" will disappear. This is already working if you visit http://www.amanado.com/idioma-colombiano/, click on "Vocabulario (oficial y de jerga) - palabras y frases comunes" to expand the accordion section, and then enter "orde" in the field below the words "Ingresa palabra o frase en el siguiente campo para filtrar la información de la tabla". After entering "orde", all but 2 rows in the vocabulary table should disappear (2 rows remain).
  3. I am having 2 issues. The 1st issue I am having is that I am unable to repeat the form field above each vocabulary table on the page because only the 1st appearance of the form field is functional when I do this. The 2nd issue I am having is that I would like the form field to apply only to all rows of the table directly below it. Currently the form field applies to all rows of all tables on the page that have a class of "myTable". Perhaps I could somehow specify a table id for each table and then have the form field above the table only apply to the table id of the table directly below the form field. And, it would be great to achieve this without having to add too much more javascript or additional css classes (preferably, I would like to avoid adding more css classes). I am guessing that both of these issues can be resolved with a couple additional lines of javascript and possibly the addition of a table id for each table in a consistent format (e.g., filter1, filter2, filter3).
  4. Below are (a) the form field as it appears in my html; (b) an example of an open table tag as it appears in my html; and (c) the javascript I am using.
  5. I am not a software engineer, but I do know how to implement a change if someone tells me what to do specifically (e.g., make this exact change, then make this exact change, then make this exact change). I appreciate any assistance anyone can provide and literal instructions would be especially appreciated.

(a) form field start here

<form class="live-search" action="" method="post">
<p>Ingresa palabra o frase en el siguiente campo para filtrar la información de la tabla</p>
<input id="filter" class="text-input" type="text" value="Mostrar sólo filas que contengan..." onFocus="clearText(this)" onBlur="clearText(this)" />
</form>

(a) form field ends here

(b) open table tag starts here

<table class="myTable" summary="Palabras y frases (oficiales y de jerga)">

(b) open table tag ends here

(c) javascript starts here (source: http://www.designchemical.com/blog/index.php/jquery/live-text-search-function-using-jquery/; I made 1 modification to this javascript to make it only apply to rows of tables w/ class="myTable")

$(document).ready(function(){
$("#filter").keyup(function(){

// Retrieve the input field text and reset the count to zero
var filter = $(this).val(), count = 0;

// Loop through the comment list
$('table[class="myTable"] tr').each(function(){

// If the list item does not contain the text phrase fade it out
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();

// Show the list item if the phrase matches and increase the count by 1
} else {
$(this).show();
count++;
}
});

// Update the count
var numberItems = count;
$("#filter-count").text(" Total = "+count);
});
});

(c) javascript ends here

ANALYSIS OF BEETROOT SUGGESTED CHANGES STARTS HERE

Beetroot, thank you. I implemented your suggested changes. As a result, I found 4 small bugs, which I believe are all a lot easier to solve than what you already solved. #1 and #2 are showstoppers and #3 and #4 I manageable. If you or someone else can instruct me how to eliminate the bugs for #1 and #2 below, that would be excellent. I very much appreciate the gracious help you've already provided.

1) When 1 or matches is found, the filter-count is correct. However, after clearing the input field, the total number of table rows is displayed and this number is incorrect. The number displayed is "1" to high. For example, go to the same Amanado.com link provided in #2 at the top of this question (Stackoverflow doesn't allow me to add another link to this question b/c I'm a new user), expand the "Vocabulario (oficial y de jerga) - abreviaturas comunes" accordion, enter "ap" in the input field below the words "Ingresa palabra o frase en el siguiente campo para filtrar la información de la tabla" and the result is "2" rows, which is correct. Then clear the input field by deleting the "ap" and the result is "19" rows, which is incorrect (the correct # of rows is "18" for this table. Perhaps the header row is being counted as a row, which it should not be. I am guessing the header row being counted may be the issue because the count is correct when the header row disappears, although the header row should never disappear (per issue/bug #2 below). Note that I made 1 change to Beetroot's suggested changes, which was that I changed $count.text(" Total = " + count) to ("(" + count + ")") for appearance/aesthetic reasons. I hope this has no relationship to this incorrect filter-count issue.

2) When a value is entered in an input field, the table header row is lost. However, the table header row should always be visible. Note per #1 above that when the table header row disappears, the row count is correct, and when the table header row is present, the row count is incorrect ("1" too many).

3) When the tag is removed, the css is lost/incorrect for the input field. Below is the css I am using. I tried replacing "input-text" with "live-search" in the javascript and changing class="input-text" to "live-search" in the input field, but this did not restore the css, so I eliminated these changes and returned to the javascript and input field as you provided. So, for now, I continue to have the extraneous tag because I haven't been successful getting the css to work when the tag is removed.

4) When "0" is present in the following tag, the "0" appears on the page for at least the 1st appearance of the input field. However, "0" should not be present when nothing has been entered. If "0" is present when nothing has been entered, "0" is incorrect/misleading because all table rows are visible and the correct filter-count should be the total of the visible table rows minus "1" for the table header row. To address this issue, I removed the "0" from the , this eliminated the appearance of the "0" when table rows are visible, and this does not seem to have caused any new issue.

Changed from:   <span class="filter-count">0</span>
Changed to:     <span class="filter-count"></span>

5) Below is the current (a) input field, (b) table open tag, (c) css, and (d) javascript that I am using after making the changes that Beetroot suggested.

(a) input field starts here

<form class="live-search" action="" method="post">
<p>Ingresa palabra o frase en el siguiente campo para    filtrar la información de la tabla</p>
<input class="input-text" type="text" value="Mostrar sólo    filas que contengan..." />
<span class="filter-count"></span>
</form>

(a) input field ends here

(b) table open tag starts here

<table class="myTable" summary="Palabras y frases (oficiales y de jerga)">

(b) table open tag ends here

(c) css starts here

.live-search {
overflow: hidden; 
width: 100%; 
padding: 8px 0; 
border: 0px solid #e3e3e3; 
margin-bottom: 10px;
font-size: 12px;
color: rgb(61, 61, 61) !important;
}

.live-search input {
border:1px solid #ddd;
padding:5px 8px;
width:300px; 
font-size: 12px;
color: rgb(61, 61, 61) !important;
-moz-border-radius:4px;
-webkit-border-radius:4px;
}

.live-search input:focus {
border-color: #c3c3c3;
-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
box-shadow: 0 0 3px rgba(0,0,0,.2);     
}

(c) css ends here

(d) javascript starts here

$(function() {
$(".input-text").keyup(function() {
var $this = $(this),
count = 0,
pattern = new RegExp($this.val(), "i"),
$group = $this.closest(".group"),
$count = $group.find(".filter-count");
$group.find(".myTable tr").each(function() {
$tr = $(this);
if ($tr.text().search(pattern) < 0) {
$tr.fadeOut();
} else {
$tr.show();
count++;
}
$count.text("(" + count + ")")
});
}).on('focus blur', function() {
if (this.defaultValue == this.value) this.value = '';
else if (this.value == '') this.value = this.defaultValue;
});
});

(d) javascript ends here


回答1:


The trick here is to work relative to the input element which is currently receiving text.

Instructions:

  • Modify the text input field to read <input class="text-input" type="text" value="Mostrar sólo filas que contengan..." /> and add to all other relevant groups. These fields do not need to be wrapped in <form></form> tags unless the form is used for something else.
  • Add <span class="filter-count">0</span> (or similar) to all relevant groups. This element will receive the count statistic.
  • Delete the function clearText.
  • Modify the javascript to read as follows :

:

$(function() {
    $(".text-input").keyup(function() {
        var $this = $(this),
            count = 0,
            pattern = new RegExp($this.val(), "i"),
            $group = $this.closest(".group"),
            $count = $group.find(".filter-count");
        $group.find(".myTable tr").each(function() {
            $tr = $(this);
            if ($tr.text().search(pattern) < 0) {
                $tr.fadeOut();
            } else {
                $tr.show();
                count++;
            }
        });
        $count.text(" Total = " + count);
    }).on('focus blur', function() {
        if (this.defaultValue == this.value) this.value = '';
        else if (this.value == '') this.value = this.defaultValue;
    });
});

Untested, so may need debugging. When it's working it should be a lot faster than the current code.

EDIT

Here's a new version which fixes previous bugs and further enhances performance.

$(function() {
    $(".text-input").on('keyup', function(e) {
        var disallow = [37, 38, 39, 40];//ignore arrow keys
        if($.inArray(e.which, disallow) > -1) {
            return true;
        }
        var inputField = this,
            val = this.value,
            pattern = new RegExp(val, "i"),
            $group = $(this).closest(".group"),
            $trs = $group.find(".myTable tbody tr"),
            $s;
        if(val === '') {
            $s = $trs;
        }
        else {
            $s = $();
            $trs.stop(true,true).each(function(i, tr) {
                if(val !== inputField.value) {//if user has made another keystroke
                    return false;//break out of .each() and hence out of the event handler
                }
                $tr = $(tr);
                if ($tr.text().match(pattern)) {
                    $s = $s.add(tr);
                }
            });
            //$trs.not($s).fadeOut();
            $trs.not($s).hide();
        }
        $group.find(".filter-count").text("(" + $s.show().length + ")");
    }).on('focus blur', function() {
        if (this.defaultValue == this.value) this.value = '';
        else if (this.value == '') this.value = this.defaultValue;
    });

    $(".group").each(function() {
        $this = $(this);
        $this.find(".filter-count").text("(" + $this.find("tbody tr").length + ")");
    });
});

You can try .fadeOut() but I personally prefer it with .hide().



来源:https://stackoverflow.com/questions/11278111/javascript-issue-with-keyup-function-trying-to-use-same-form-field-on-page-mul

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!