I'm having a problem with JavaScript/jQuery at the moment where I'm trying to access the element inside the h4 element in my code. I'm doing this because I would like to dynamically display to the user how many guides are available in each "h4" section. For the PC section, it should display "4 reviews available" and for the Xbox One section, it should display "3 reviews available". However, both say " reviews available", and I'm assuming it's because I'm not using the jQuery functions properly. Here's the HTML code:
<h4><li class="console">PC (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
<li class="game">Guide #4</li>
</ul>
</div>
<h4><li class="console">Xbox One (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
</ul>
</div>
And here's the jQuery/JavaScript code:
$("h4").each(function() {
var node = $(this).children().children(); // gets node that has "number" class
var count = $(this).next().children().children().length; // gets number of li tags
node.innerHTML = count;
});
I tested whether or not it's properly getting the correct node and count by using the alert function for JavaScript, but for some reason, node.innerHTML = count won't display the contents of "content" properly in the element. Rather, it just displays a blank. Does anyone know why?
Its a jquery object not a DOM one..use this...
node.html(count);
node is a jQuery object here. It does not have "innerHTML". Instead you can use one of these:
node.html(count);
node.get(0).innerHTML = count;
node.get(0) will give you first DOM object from jQuery one.
A good practice is to prefix or suffix all jQuery objects with $ (e.g. $node), so that you will always know if a variable is meant to be a jQuery object.
use find() lot more cleaner and readable
$("h4").each(function() {
var $this=$(this);
var node = $this.find('.number');
var count = $this.next().find('li').length; // gets number of li tags
node.text(count); //or html()
});
and you have come invalid HTML li in h4 make sure you change that
working fiddle here
Do not use .children().children().
Only one .children() would do.
$(this).children('.game');
Also innerHTML is plain javascript. use .html(value) as node is JQuery Object.
$("h4").each(function() {
var node = $(this).children('.number');
var count = $(this).next().children('li').length;
node.html(count);
});
Reference to JQuery APIs:
.html()
.children()
$("h4").each(function() {
var $spanNumber = $('.console .number', this),
gameListCount = $(this).next().find('ul li').size();
$spanNumber.text(gameListCount)
});
You may use this also,
$("h4").each(function() {
var node = $(this).find('.number');
var count = $(this).next().find('.game').length;
node.html(count);
});
Related
I am generating rows dynamically with PHP from DB, once it compiles the initial page code looks something like this:
Snippet
<div class="options" id="options">
<div class="left_wrap">
<ul>
<li class="col_id b-bottom"></li>
<li class="hazard_header"><h3>Hazard</h3></li>
<li class="hazard_input b-bottom"></li>
<li class="con_header b-bottom"><h3>Controls</h3></li>
<li class="cat_header"><h3>Consequence Category</h3></li>
<li class="cat_options"></li>
</ul>
</div>
<div class="right_wrap">
<h2>Inherent Risk (Assessed risk without controls)</h2>
<ul class="fields">
<li class="bg b-top b-right"><h3>Consequence Level</h3><br/><span class="con_level_val"></span></li>
<li class="b-top b-right"><h3>Probability</h3><br/>Possible</li>
<li class="bg b-top b-right"><h3>Exposure (frequency)</h3><br/></li>
After page load I grab contents of the wrap options.
jQuery Snippet:
content = $("div.options").html();
Which in turns stores the above code in the variable content. Now, my question is how can I edit contents of variable content. For example I need to add value to li with class Col_ID like 1,2,3,4 and same when I am deleting I need to modify the contents again.
How can I do something along the lines content.getElement?
If you really need to work with the HTML string, here's something you can do:
content = $("div.options").html();
var $content = $(content);
// now $content is a jQuery object with a bunch of (detached) elements
// you can use the common functions on it without problems, such as
$content.find("li.col_id").text("Some text");
// now you need to do something with $content, or everything you did will...
// ...be lost. You cold, for instance, update the other variable back:
content = $content.html();
// content now has the updated HTML
Now, if you don't need the HTML string at all, then you can work directly like:
content = $("div.options");
content.find("li.col_id").text("Some text");
// now the DOM was already updated as you are dealing with attached elements
I am trying to crawl some webpages with javascript to gather information about content's hierarchy. I'm using casperjs to do the crawling, that is working ok so far.
The information that I want to parse is structured like this:
<ul>
<a></a>
<li>
<h3>
<a>
Category
<span>Description for Category</span>
</a>
</h3>
<div>
<ul>
<li>
<a>SubCategory</a>
</li>
</ul>
</div>
</li>
</ul>
But what I want to end up with is this.
<ul>
<li>Category
<ul>
<li>SubCategory</li>
</ul>
</li>
</ul>
I want to use the above html in a different webpage, so basically I'll be writing it to a file from casperjs so that I can then copy paste it into another document. I'm crawling because it's a tedious thing to do manually (90 some pages and lots of data per page).
What's the best way to deconstruct/parse a hierarchy, and then recreate it? Stay within the DOM and restructure using JQuery? Pull it out into a tree structure and rebuild it later?
Please note that this is a particular solution and will only work for the specific layout of code that you provided:
I created a parser in jQuery that receives HTML markup in a textarea and converts it into the format that you are using:
$(function(){
$("button").click(function(){
//Read in HTML
$("#parser").html($("textarea").val());
//Parse
var categories = $("#parser > ul").find("li h3 a");
$(categories).find("span").remove();
//Output result
var output = "<ul>\n";
for(var i = 0; i < categories.length; i++)
{
//Get subcategories for this category
var subCategories = $($(categories[i])).closest("h3").siblings("div").find("ul li a");
//Add markup to output
output += "\t<li>" + minimize($($(categories[i])).html()) + "\n\t\t<ul>\n";
for(var j = 0; j < subCategories.length; j++)
{
output += "\t\t\t<li>"+$($(subCategories[j])).html() + "</li>\n"
}
output += "\t\t</ul>\n\t</li>\n</ul>\n"
}
$("#result").html(output);
});
});
//Removes all white-space characters from the string.
function minimize(str)
{
return str.replace(/\s{2,}/g, '');
}
JSFiddle
It was a lot of work and is very customized. As I said earlier, if you look at the different selectors that are used here, this code is very tailored to this specific code layout.
Example:
var categories = $("#parser > ul").find("li h3 a");
This looks for a ul element just below parser that contains <a>s inside of <h3>s inside of <li>s to find the categories and then later uses
$($(categories[i])).closest("h3").siblings("div").find("ul li a");
which looks for an <h3> above the category <a> that has a sibling <div> with children <ul><li><a></a></li></ul>
So if the format is not this:
<ul>
<li>
<h3>
<a>Category</a>
</h3>
<div>
<ul>
<li>
<a>Subcategory</a>
</li>
</ul>
</div>
</li>
</ul>
It will not work.
I ended up going with this approach:
Scrape the tags from the existing website and assemble them into an array nested javascript object.
Writing them out with JSON.stringify to a file
Loading them into a new page as Javascript objects, and build the ul/li structure with a recursive function that traversed the javascript object.
I found it too hard to get my head around modifying the DOM as with the other answer(s). It was easier to break it down into multiple steps, with a well structured javascript object in the middle.
First time i've used jquery and I'm in trouble .
I used the following code in html :
<ul>
<li>hello </li>
<li>hello 2</li>
<li>hello 3</li>
</ul>
<script type="text/javascript" src="jquery-2.0.3.js"></script>
<script type="text/javascript">
var lis = jQuery('ul li')
console.log(lis)
</script>
When I checked my version , It was 2.0.3 .
But I opened firefox and used Inspect element to check the console ,
it returns
[17:57:32.367] [object Object]
instead of [<li>hello</li>]
Actually I'm learning via Tuts free courses (Hello Jquery by jeffery way) at this link; and he gets different output
Because jQuery('ul li') returns a DOM object. If you want to get internal html of li or ul then you can try it
jQuery('ul').html() // for ul internal html
jQuery('ul li').html() // for li html
or you can also use that object like jQuery(lis).html()
It returns that because it's just jquery object(element). You are just selecting that list item, not the content in it. Add .text() function to your variable for getting contents of selector:
var lis = jQuery('ul li').text();
console.log(lis);
I have certainly extremely simple problem and I'm a little ashamed of not being able to solve it by myself.
HTML:
<div>
<ul class="test">
<li>1</li>
</ul>
<ul class="test">
<li>2</li>
</ul>
</div>
JavaScript:
var tests = document.getElementsByClassName('test')[0].innerHTML;
alert(tests);
jsFiddle:
Try it
Currently, the result shows me <li>1</li>.
This is not what I want. I want the result to be <ul class="test"><li>1</li></ul>.
I tried using .parent() (I can use jQuery) but it gives me all <ul> tag while I just want the first. I also know that I could use some .split() but it is surely not the adviced way.
I thought the problem might be coming from the .innerHTML, there is a function that would allow me to recover also the target element, and not just his children?
Just use outerHTML instead of innerHTML
var tests = document.getElementsByClassName('test')[0].outerHTML
Check Fiddle
You can do the same with jQuery. $.each to iterate over the elements and then use this so that it only points to that elements instead of all the elements with that class
jQuery
var $tests = $('.test');
$tests.each(function() {
console.log(this.outerHTML)
});
jQuery Fiddle
I'm trying the new data-function in jQuery but can't make it work.
Here is a little bit of code I use for testing:
HTML
<ul>
<li data-test="list">List item</li>
<li data-test="list">List item</li>
</ul>
<ul>
<li data-name="sida">oko</li>
</ul>
JS
var test = $('li').data('name');
alert(test);
The same thing on jsFiddle:
http://jsfiddle.net/w95mY/1/
I expect to get "sida" from the alert. I found out that it works if I delete the first list. Why is that? How do I solve it?
Consider telling jQuery how to find exactly one element. For example, tell it to look for any li element with a data-name attribute:
var test = $('li[data-name]').data('name');
alert(test);
Or you can tell it to look for the last li:
var test = $('li').last().data('name');
alert(test);
Both show an alert with text "sida".