querySelector direct child only of referenced element - javascript

For example,
var relevantItems = ul.querySelectorAll('li.someClass[data-x=someData]')
Should only match these elements from the outer, referenced <ul>:
<ul>
<!-- This <li> matches -->
<li class="someClass" data-x="someData">
<ul>
<!-- depending on the query, there may be some extra matches within the hierarchy, but these should not be searched or included in the results -->
</ul>
</li>
<!-- need to also includes additional matches like this one: -->
<li class="someClass" data-x="someData">
</li>
</ul>
Right now I have a couple of options:
Use JavaScript to loop over childNodes/children array and compare the className and dataset.x variables traditionally.
Give each <ul> its own id and use the #id> prefix feature like so:
ul.querySelectorAll('#' + ul.id + ' > li....')
Is there a simpler syntax, or alternative function, e.g. filtering the childNodes List somehow, to achieve the same query? (without adding an external library i.e. jQuery)

Related

Is it allowed to have value for list item?

<ul id="my-list">
<li value="1001">item1 </li>
<li value="1002">item2 </li>
<li value="1003">item3 </li>
<li value="1004">item4 <li/>
</ul>
Is it allowed to have value for list item? If I can, how to access the value using javascript or jquery?
According to the W3C specification for LI element it is allowed to use value attribute for LI in some cases, but not this one. If you're using HTML5 use data-* attributes:
<ul id="my-list>
<li data-my-value="...">...</li>
<li data-my-value="123">...</li>
<li data-my-value="...">...</li>
</ul>
To get a reference to a particular element using jQuery use following selector:
$("ul#my-list li[data-my-value='123']")...
Or, if you already got reference to all LI elements use jQuery.filter():
var $items = $listItems.filter(function() {
retrun $(this).data("my-value") === "123";
});
You can add any sort of custom data attributes to your node (of course that HTML won't validate and it won't be a valid XHTML document). You can then access them using jQuery attr() function (for example).
That said it's a terrible practice and you should use a standard data- attribute, accessible for example with data() function (more details and examples in the provided link):
var theValue = $("#yourItemId").data("value");
For an attribute like:
<li id="yourItemId" data-value="1001">item1</li>
For this purposes I would recommended use jquery Data
<ul id="my-list">
<li data-value="1001">item1 </li>
<li data-value="1002">item2 </li>
<li data-value="1003">item3 </li>
<li data-value="1004">item4 <li/>
</ul>
Get second li value
$("#my-list").children().eq(2).data("value");
If you want to produce valid HTML5, you should stick to the data attributes for custom properties:
<li data-value="1001">
However, any element can have a custom attribute. In fact this has been standard in IE since version 5 (sometimes called expando properties).

javascript for creating link url from elements w/o specific IDs

In a CMS that returns a list of results from a search, I have a list of items that looks something like this:
<ul class="results_odd_row">
<li class=title> Title </li>
<li class=published> Year </li>
<li class="author"> Author </li>
<li class="avail"> Out; try Another Search</li>
</ul>
<ul class="results_even_row">... </ul>
<ul class="results_odd_row">... </ul>
...etc...
For the "try another search" link, I'd like to append onto the url some information about the record, like "http://another.search?title=[title]&author=[author]", so that information can be used to execute the other search.
How can I identify elements that have no specific ID, and where there are multiple elements of the same class on the same page? In pseudo code, what I want might be something like:
1. href = base URL (http://another.search) plus
2. the text from the first <li> element above with class="title"
3. the text from the first <li> element above with class="author"
Also, I'm limited by the CMS to whatever javascript I can use within the A tag.
If it's not already obvious, I'm a complete newbie with javascript, so please don't feel your potential response is insultingly basic.
You can build your query string in this way
var baseUrl = "http://another.search"
var author = $('.results_even_row .author, .results_odd_row .author').first().text();
var title = $('.results_even_row .title, .results_odd_row .title').first().text();
var queryString = baseUrl + "?title=[" + title + "]&author=[" + author + "]"
Try it here.
Then you just use this string for the next search.

Regex search & replacing the expression with something different for each occurrence of the expression

I am using a vendor-supplied API that uses javascript to output HTML that essentially looks like this:
<li class="parent_class"> Parent Name </li>
<div class="child_class">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</div>
<li class="parent_class"> Parent Name 2 </li>
<div class="child_class">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</div>
And so on. This is the code I'm going for:
<li class="parent_class"> Parent Name
<ul id="xc">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</ul> </li>
<li class="parent_class"> Parent Name 2 </li>
<ul id="1">
<li> Child Name 1 </li>
<li> Child Name 2 </li>
</ul></li>
(Just in case it is useful: I will be putting a <ul> tag before the API call and a </ul> tag after it to close up the whole list.)
Using more javascript, I've figured out how to replace the </div> with the </ul></li> using regular expression replace, but I'm not sure how to replace the </li><div> tags with the <ul> tags, because those need to be different every time. The first <ul> MUST be <ul id="xc"> (due to even more code I don't have control over). The other <ul>s must each have an ID, but those can be randomly generated.
I have a vague idea that I can use the exec method to create an array of all instances of </li></div>, set array[0] to <ul id="xc"> and then set array[1] to <ul id="1">, array[2] to <ul id="2"> and so on, but I'm not sure if that's a good idea (or how exactly to do it).
Thanks in advance.
Assuming you receive the HTML as a string (as opposed to a document), you can convert it using this function:
function mogrify (input) {
// 1) replace </li><div> with <ul>
var i = 0;
var out = input.replace(/<\/li>\s*<div[^>]*>/g, function () {
var listID = i == 0
? "xc"
: "xc_" + (Math.floor(Math.random() * 1e9) + 1);
++i;
return '<ul class="' + listID + '">';
});
// 2) replace </div> with </ul></li>, like you described:
return out.replace(/<\/div>/g, "</ul></li>");
}
Note that the input HTML is syntactically invalid, as is using bare numbers as ID attributes.
Use a DOM parser which is perfectly suited for mark up languages such as HTML, NOT regular expressions.
You can use .getElementsByTagName and .getAttribute to grab what divisions you need and setAttribute, createElement, appendChild to create.

jQuery: Get first element of type in top UL in a nested list

I have a nested list like this:
<ul class="list">
<li class="list_item_type_1">
<ul class="list">
<li class="list_item_type_2">Unnested item</li>
</ul>
</li>
<li class="list_item_type_2">Unnested item</li>
</ul>
With jQuery I want to add a list item before all .list_item_type_2 in the first .list.
I write it like this:
$('.list:first').find('li.list_item_type_2:first').before('<li class="list_item_type_1">Nested list (...)</li>');
This won't work as intended because the script finds the first .list_item_type_2 in the second .list and appends the new code there instead.
How can I keep the search in the first ul and prevent it from entering underlying ul elements?
Cheers!
Firstly, I'd advise constructing HTML that way. Use jQuery to assemble the HTML. It takes care of escaping and all those other useful things:
$("<li></li>").addClass("list_item_type_1")
.text("Nested list (...)")
.prependTo("ul.list:first > li.list_item_type:first");
Also, always use a tag selector ("ul.list") over a naked class selector (".list") where possible. It's much faster on most browsers.
You were so close!
Instead of find(), which searches all descendants, use children(), which only searches children.
Test: http://jquery.nodnod.net/cases/723/run
Maybe try to combine the selector in one expression ?
$('.list:first > LI.list_item_type_2:first').before('<li class="list_item_type_1">Nested list (...)</li>');
The > selector does only match the direct children, as explained in the doc.

PrototypeJS: Selecting visible elements

I am trying to formulate a selector to select a set of visible elements. Our application uses the Prototype JavaScript framework, version 1.6.0.3.
The markup I'm working with is as follows:
<ul>
<li style="display:none;">1 Hidden</li>
<li style="display:none;">2 Hidden</li>
<li style="">3 Visible</li>
<li style="display:none;">4 Hidden</li>
<li style="display:none;">5 Hidden</li>
<li style="display:none;">6 Hidden</li>
<li>7 Visible</li>
<li style="">8 Visible</li>
</ul>
As you can see, some elements may have a style attribute, but only the hidden ones contain the string "display:none;". I need to select the <li> elements that are visible, where visibility is defined as "does not contain display:none".
What I've tried to far:
var visibleItems = $$('li[style*="display:none"]'); // Yields: [ ]
var visibleItems = $$('li[style*="display"]'); // Yields: [li, li, li, li, li], but isn't specific enough
Ideas? Ideally I'd like this to be as compact as possible, but I'll take what I can get.
Yes, I know that jQuery can do this but I do not want to introduce another framework in to this application since much of it already depends on Prototype.
You can filter the items using the findAll function:
var notVisible = $$('li').findAll(function(el) { return !el.visible(); });

Categories