Get href list under HTML content - javascript

I have a json string which contains HTML element. What I am trying to achieve is to fetch all anchor tag value <a> in that string.
Json String
"content" : "<p>Reference information</p> <ul> <li>My Url</li> <li>Your Url</li> </ul>"
Here is HTML Format
<p>Reference information</p>
<ul>
<li>My Url</li>
<li>Your Url</li>
</ul>
I have tried like this but cannot get exact value:
<div id="TestDiv" hidden >
</div>
let anchor = document.getElementById("TestDiv").getElementsByTagName("li");
anchor[0].innerHTML
I am getting this value
My Url
But I want to get https://myurl.com
another way I tried which was closed though still has problem but don't want to use regex:
content.match(/href="([^"]*?)"/);
How can I achieve that?

// Create an element
const el = document.createElement("div");
// set the inner HTML
el.innerHTML = `
<p>Reference information</p>
<ul>
<li>My Url</li>
<li>Your Url</li>
</ul>
`;
// grab all <a> tag
const nodeList = el.querySelectorAll("a");
// convert to array
const nodeArray = [...nodeList];
// map to href
const hrefs = nodeArray.map((a) => a.href); // ["https://myurl.com/", "https://yoururl.com/"]

You can use Array.prototype.map like:
var anchorUrls = Array.prototype.map.call(
document.anchors, (i) => i.href;
);
console.log(anchorUrls);

You can access the href attribute value using .href or using the getAttribute("href") method. However you are currently getting the li elements, but you want to instead get the anchor elements.
let anchor = document.getElementById("TestDiv").getElementsByTagName("a");
anchor[0].href;
To get all of the href's you will need to loop through the array of anchors.
var i;
for (i = 0; i < anchor.length; i++) {
anchor[i].href;
}

Related

How to change the id of a unordered list of object type in jQuery object

I'm new here and I'd like to ask a question about jQuery.
I have the unordered list like:
<ul id="pages">
<li id="number1">
contains sub table a
</li>
<li id="number2">
contains sub table b
</li>
<li id="number3">
contains sub table c
</li>
<li id="number4">
contains sub table d
</li>
</ul>
And I'd like to add a different ID (new id will be same out of these id but it will be shuffle as per my requirements) to every li displayed in this <ul> (eg
<li id="number3">contains sub table d</li>
...)
Is there a way how to achieve this via jQuery?
I tried it using a for loop and this object but when i try to shuffle. Its duplicating the sub tables becouse of jQuery has child/nextsybling data inside this every object.
Basically you should get all ids, shuffle them and reassign back to DOM elements:
const $items = $('#pages li');
const ids = $items.map((i, { id }) => id);
const shuffledIds = shuffle(ids); // This is your shuffle function
$items.each((i, e) => {
e.id = shuffledIds[i];
});

List items from HTML XPath

I need to list items returned from evaluating an Xpath. I'd like to return the tweets in a list, so I can further evaluate their elements. How do I do this?
My code is:
var navigable_stream = '//*[#id="stream-items-id"]';
var FIRST_RECORD = document.evaluate(navigable_stream, document, null, XPathResult.ANY_TYPE, null).iterateNext();
console.log(FIRST_RECORD);
And the returned HTML is very long. But it has lots of tweets with different ids. Here's a picture to show what I mean:
Update
" Is there a way to match the first part of the element id i.e. 'stream-item-tweet"?"
Yes, by using referencing the partial #id as an attribute:
var tweet = document.querySelectorAll("[id^=stream-item-tweet]");
Note the ^= means that the beginning of the #id must match stream-item-tweet
Having answered the question I'd like to add that there may be a better alternative by using the class of each <li>:
var tweet = document.querySelectorAll('.js-stream-item')
Something looks invalid on the classList:
class="js-stream-item stream-item stream-item"
.stream-item is repeated twice...maybe it's best to avoid class in your circumstance.
Anyways, knowing the first way should work and maybe the second way might, tweet is now a NodeList which needs to be handled by a loop or it needs to be converted to an array so it can be processed by an array method.
Demo 2 shows how the latter is done.
Just guessing, since there's no way I can test it myself, that if that's what you can get on the console, then you could maybe use .toString() then parse and append it to the DOM.
Demo 1
Not possible to make an actual functioning Demo
var navigable_stream = '//*[#id="stream-items-id"]';
var FIRST_RECORD = document.evaluate(navigable_stream, document, null, XPathResult.ANY_TYPE, null).iterateNext();
console.log(FIRST_RECORD);
var str = FIRST_RECORD.toString();
document.getElementById('dock01').insertAdjacentHTML('beforeend', str);
<section id='dock01'></section>
Demo 2
/* Collect all elements with an #id that starts with "tweet"
|| Convert NodeList into an array
*/
var tweets = Array.from(document.querySelectorAll("[id^=tweet]"));
/* filter() the array tweets
|| if an item has data-id = "retweet"
|| add it to the new array retweets
*/
var retweets = tweets.filter(function(t) {
return t.dataset.id === "retweet";
});
console.log(retweets);
/* The lazy way to add text */
li::after {
content: attr(id);
}
/* This is just so the console results don't obscure the Demo*/
.as-console-wrapper {
width: 70%;
margin-left: 30%;
}
.as-console-row:after {
display: none !important;
}
<ol>
<li id='tweet-51515151' data-id='retweet'></li>
<li id='tweet-57885157' data-id='tweet'></li>
<li id='tweet-51677459' data-id='tweet'></li>
<li id='tweet-51890331' data-id='retweet'></li>
<li id='tweet-51515337' data-id='retweet'></li>
<li id='tweet-51593051' data-id='retweet'></li>
<li id='tweet-51333333' data-id='tweet'></li>
<li id='tweet-51534152' data-id='tweet'></li>
<li id='tweet-51599951' data-id='tweet'></li>
<li id='tweet-54785151' data-id='retweet'></li>
<li id='tweet-56785199' data-id='retweet'></li>
<li id='tweet-51557844' data-id='tweet'></li>
<li id='tweet-51510000' data-id='retweet'></li>
</ol>

Unable to access span inside an li element?

I am making a simple web app. In one part of it, I have:
<ul class="sortable list-group">
<li id="firstTag" class="tags list-group-item">
<span id="present-count" class="badge"></span>
</li>
I have to access both the li element with id="firstTag" and the span element with id="present-count".
Anyhow, I am able to access only one, if I remove the id="firstTag", I am easily able to acess the span, anyhow, in presence of it, js gives the error: "cannot set property "innerHTML" of null" for the statement:
document.getElementById("present-count").innerHTML = something;
EDIT:
Both are being called in window.onload function with "firstTag" called before "present-count". See this fiddle: http://jsfiddle.net/poddarrishabh/2xzX6/3/
This is what I want the output to look like:
where both the "Present" text and the number can be changed.(I am using bootstrap).
$("#firstTag #present-count").html();
add jquery file to your page and try this
Sounds like you want to create a text node:
var textNode = document.createTextNode("first");
document.getElementById("firstTag").appendChild(textNode);
document.getElementById("present-count").innerHTML = "something";
Or to put the text before the span:
var textNode = document.createTextNode("first");
var present = document.getElementById("present-count");
present.innerHTML = "something";
document.getElementById("firstTag").insertBefore(textNode, present);
Here is an updated Fiddle.
If you are just trying to put some text before the present-count span, then just add another span and target that instead of the wrapping li:
<ul class="sortable list-group">
<li id="firstTag" class="tags list-group-item">
<span id="another-tag"></span>
<span id="present-count" class="badge"></span>
</li>
document.getElementById("another-tag").innerHTML = "some text";
document.getElementById("present-count").innerHTML = "some more text";
Try this code snippet
document.getElementById("firstTag").innerHTML = document
.getElementById("firstTag")
.innerHTML
+ "first";
document.getElementById("present-count").innerHTML ="something";
Hope it helps.
Try adding this
document.getElementById("firstTag").innerHTML ='<span id="present-count" class="badge">'
+ '</span>'
+ ' first';
document.getElementById("present-count").innerHTML = 'something';
DEMO
You were getting this error because with the first
document.getElementById("firstTag").innerHTML = "first"
you were replacing the <span>, and your DOM looked like
<ul class="sortable list-group">
<li id="firstTag" class="tags list-group-item">
first
</li>
</ul>
Then you couldnt find the element with id present-count because it wasnt there.

jQuery cloned list items all get the same text values while using each() function

I am trying to clone a list item in the DOM and append it multiple times depending on the number of text values in the variable data using the each function. The problem is that all the new list items get the same text values (all list items are set equal to the last appended list item).
I suppose it has something to do with enclosures, but I cannot figure it out.
Can anyone explain what the problem is?
Thanks!
data:
var data = {"text1": ["text1_row1", "text1_row2"], "text2": ["text2_row1", "text2_row2"], "text3": ["text3_row1", "text3_row2"] }
HTML:
<ul>
<li id="entryTemplate" style="display:none">
<span class="text1"></span>
<span class="text2"></span>
<span class="text3"></span>
</li>
</ul>
Javascript:
function listData(data){
$.each(data.text1, function(i) {
var newDataRow = $('#entryTemplate').clone();
newDataRow.removeAttr('id')
.removeAttr('style')
.removeAttr('class')
.addClass('copy')
.appendTo('ul')
.find('.text1').text(data.text1[i])
.find('.text2').text(data.text2[i])
.find('.text3').text(data.text3[i]);
});
}
$.fn.clone = function(){
var ret = $();
this.each(function(){
ret.push(this.cloneNode(true))
});
return ret;
};
Desired HTML:
<ul>
<li id="entryTemplate" style="display:none">
<span class="text1"></span>
<span class="text2"></span>
<span class="text3"></span>
</li>
<li class="copy">
<span class="text1">text1_row1</span>
<span class="text2">text2_row1</span>
<span class="text3">text3_row1</span>
</li>
<li class="copy">
<span class="text1">text1_row2</span>
<span class="text2">text2_row2</span>
<span class="text3">text3_row2</span>
</li>
</ul>
Result I get (all li items get the text for row2):
<ul>
<li id="entryTemplate" style="display:none">
<span class="text1"></span>
<span class="text2"></span>
<span class="text3"></span>
</li>
<li class="copy">
<span class="text1">text1_row2</span>
<span class="text2">text2_row2</span>
<span class="text3">text3_row2</span>
</li>
<li class="copy">
<span class="text1">text1_row2</span>
<span class="text2">text2_row2</span>
<span class="text3">text3_row2</span>
</li>
</ul>
Your question is a bit foggy and it's not really clear what's the result you're looking for. Appart from that I saw something in your code that's probably causing it. Give it a try and let me know what happened.
When you do
$.each(data.text1, function(i) {
change it to
$.each(data.text1, function(pos, element) {
and replace your [ i ] for [element].
According to JQuery API, when doing an EACH loop, the 1st return is the position in the array and the second is the value itself.
UPDATED ANSWER:
Your data object variable is formatted wrong... It looks like you want each value of the data object to be an array (using curly brackets implies you are defining an object with keys), so you should be using square brackets []. See array vs array-like object
var data = {
"text1": ["text1_row1", "text1_row2"],
"text2": ["text2_row1", "text2_row2"],
"text3": ["text3_row1", "text3_row2"]
}
jQuery already has a clone method so you shouldn't need to override with your own.
Based on the data you provided, you want to be iterating over the data variable itself, not data.text1. Then you can get the text values by value of the current index (this is the second parameter passed to .each()) and referencing [0] and [1] to get the actual text
$.each(data,function(i,value){
console.log(value);
var newDataRow = $("#entryTemplate").clone();
newDataRow
.removeAttr('id')
.removeAttr('style')
.removeAttr('class')
.addClass('copy')
.appendTo('ul');
newDataRow.children('.text1').text(value[0]); // value[0] == data[i][0]
newDataRow.children('.text2').text(value[1]);
});

Best way to iterate through a 'sortable' list and then change the values accordingly

I have a list of items in a list:
<ul id="myList">
<li>10 Apple</li>
<li>20 Banana</li>
<li>30 Orange</li>
</ul>
The list can be sorted thanks to jQuery. However once Ive arranged the items i need to recalculate their positions i.e Orange moved to top would equal 10, apple would then equal 20 and Banana 30.
I then need to pass this data in the url in order for my server side script to process.
What is the best way to be able to pass the altered list values into the URL when i submit?
My first thought was to have a form with hidden values, so when i process the list it adds the values into the form as hidden inputs in order for me to pass the data into the URL.
Is the number before each item strictly based on position?
If so, once the sort is complete you could just replace the content based on each li element.
Does it matter how the URL contains the list text?
In the below I operated with the assumption that it can all be appended with a querystring value of list.
There are shorter ways to do this, but hopefully the verbosity will aid in understanding what happens.
<script>
var listChanger = function() {
//updates the digits prepended to each item in list
//updates URL with text of list in querystring
//accumulates the text of each list item
var valueAccumulator = [];
//Operate of each item in myList
$('#myList li').each(function(index) {
//regular expression to strip initial digits
var reInitialDigits = /^\d+/;
//remove initial digits
var textWithoutDigits = $(this).text().replace(reInitialDigits,"");
//prepend new digits (index starts at 0, so add 1 then multiply by 10 to get desired number)
$(this).text(((index + 1) * 10) + textWithoutDigits);
//append text to accumulator
valueAccumulator.push($(this).text());
});
//querystring to strip everything after the querystring
var reQueryString = /\?list\=.*$/;
//placeholder
var linkWithoutQueryString = '';
//remove querystring
linkWithoutQueryString = $('#myLink').attr('href').replace(reQueryString,'');
//change link to include URL encoded list of values
$('#myLink').attr('href',linkWithoutQueryString + "?list=" + encodeURI(valueAccumulator.join("|")));
}
$(document).ready(function() {
//make the list sortable and each time the sorting stops, run the listChanger function
$("#myList").sortable({stop:listChanger});
});
</script>
<ul id="myList">
<li>10 Apple
</li>
<li>20 Banana
</li>
<li>30 Orange
</li>
</ul>
<br />
<a id="myLink" href="mylink.html">mylink.html</a>

Categories