Reputation: 1738
I want to filter list of items by clicking on one column/string in list item. When I click on Sales, only items in list from Sales category will be displayed. When I click again on Sales all items in list will be displayed.
It works like I want on jsfiddle
But why it is not working in Visual Studio on ASP .net ? It throws exception in
...
var a = p.getElementsByTagName("a")[0];
...
This is my HTML code:
<div data-role="page" id="page1">
<div data-role="content">
<ul data-role="listview" data-inset="false" data-filter="true" id="testList">
<li data-icon="false">
<p class="ui-li-heading">
<strong> 1</strong>
</p>
<p class="ui-li-aside">
<span>
<a href="javascript:void(0)" class="areaItem" id="areaItem">Sales</a>
</span>
<span class="ui-icon ui-icon-gear" style="display: inline-block;"></span>
<span class="ui-icon ui-icon-check" style="display: inline-block;"></span>
</p>
</li>
</div>
</div>
This is my Javascript:
var filtered = 0;
$(".areaItem").click(function () {
var SearchTerm = $(this).text();
var ul = document.getElementById("testList");
var liArray = ul.getElementsByTagName("li");
for(var i=0; i<liArray.length; i++) {
var p = liArray[i].getElementsByTagName("p")[0];
var a = p.getElementsByTagName("a")[0];
if(filtered == 1) {
$(liArray[i]).show();
} else {
if(a.text.localeCompare(SearchTerm) != 0) {
$(liArray[i]).hide();
}
}
}
if (filtered == 0) {
filtered = 1;
} else {
filtered = 0;
}
});
Upvotes: 1
Views: 513
Reputation: 19772
I'm going to start by refactoring your javascript:
$(document).ready(function () { //Make sure doc is loaded
var list = $("#testList");
var listItems = $(list).find("li"); //could also do $("#listtest li);
$(".areaItem").click(function () {
var parentLi = $(this).closest("li"); //Get li that encloses clicked item
$(listItems).not(parentLi).toggle(); //Toggle display of other li
});
});
It is a lot simpler and more inline with how jQuery is meant to be used.
See: http://jsfiddle.net/5pMsR/3/
That in itself my not be enough to fix your problem. Double check what is rendered to the page. Particularly check id
's as ASP.net is notorious for mangling IDs. Google ASP.net name mangling and asp.net ID mangling for more info. If your IDs are mangled use the following in your script
var list = $('#<%= YourListElement.ClientID%>');
or use a class.
UPDATE
Upon re-reading your question I've realized that my solution may not meet your needs. If you want both "Sales" items visible if either of them are clicked you could use the following:
var list = $("#testList");
var listItems = $(list).find("li"); //could also do $("#listtest li);
$(".areaItem").click(function () {
var parentLi = $(this).closest("li"); //Get Parent li of clicked element
var filter = $(parentLi).find(".areaItem").text(); //Set Filter based on text of clicked item
$(listItems).filter(function(){ //Use jQuery filter to find based on text
//in the filter context 'this' is a li being filtered not the item clicked
//$(this).find(".areaItem").text() is used to compare against all list items text
return $(this).find(".areaItem").text() != filter;
}).toggle();
});
See: http://jsfiddle.net/5pMsR/8/
Update 2
I've updated the code and fiddle above to make the solution more robust based on comments. It would appear that the a
tag is not present in the final render. The code changes will now search based on CSS class as opposed to tag.
Upvotes: 2
Reputation: 1738
I came with solution which is little bit miracle to me, since I am new to javascript. All is working fine in IE but in Chrome all li disappear after click.
var filtered = 0;
$(".areaItem").click(function () {
var SearchTerm = $(this).text();
$('#testList > li').each(function () {
var a = $(this).find("a").attr("id","areaItem");
//alert(a[0].innerHTML);
if (filtered == 1) {
$(this).show();
} else {
//alert(a.text());
if (a[0].innerHTML.localeCompare(SearchTerm) != 0) {
$(this).hide();
}
}
});
if (filtered == 0) {
filtered = 1;
} else {
filtered = 0;
}
});
Upvotes: 0
Reputation: 1571
I've had a similar problem like this in the past: the issue was with the ASP.NET page life cycle and the javascript being parsed before the element(s) was created in the DOM. Since you are attempting to bind a click handler to the .areaItem
class, the elements that are members of that class must all be available in the DOM when the function gets parsed.
From memory I think I ended up delegating the click to the document thusly:
$(document).on(click, ".areaItem", function() { <function content> });
I believe this makes the parsing occur after the load
event, at which time all elements have been created.
The reason I am not sure is because I deleted all of this code out and did it a different way: by putting the script block directly in my content page after the ASP controls and HTML. Not ideal if you were wanting to have the JS in the header or a separate file, but embedding it after the content does appear to work:
<div data-role="page" id="page1">
<div data-role="content">
<ul data-role="listview" data-inset="false" data-filter="true" id="testList">
<li data-icon="false">
<p class="ui-li-heading">
<strong> 1</strong>
</p>
<p class="ui-li-aside">
<span>
<a href="javascript:void(0)" class="areaItem" id="areaItem">Sales</a>
</span>
<span class="ui-icon ui-icon-gear" style="display: inline-block;"></span>
<span class="ui-icon ui-icon-check" style="display: inline-block;"></span>
</p>
</li>
</div>
</div>
<script>
var filtered = 0;
$(".areaItem").click(function () {
var SearchTerm = $(this).text();
var ul = document.getElementById("testList");
var liArray = ul.getElementsByTagName("li");
for(var i=0; i<liArray.length; i++) {
var p = liArray[i].getElementsByTagName("p")[0];
var a = p.getElementsByTagName("a")[0];
if(filtered == 1) {
$(liArray[i]).show();
} else {
if(a.text.localeCompare(SearchTerm) != 0) {
$(liArray[i]).hide();
}
}
}
if (filtered == 0) {
filtered = 1;
} else {
filtered = 0;
}
});
</script>
Upvotes: 1