I have a very large HTML that contains lots of divs with the same name, I want a way to only filter or extract that value from that div.
Here is an example:
<td class="last">
<div class="container-relative">
<div class="name" title=""User" <John Appleseed>"></div>
<div class="date">9/17/2019</div>
<div class="tool"></div>
</div>
</td>
I need to extract only what's between <John Appleseed>, in this case is 'John Appleseed'.
You could use querySelectorAll to take all the elements with class name, then get the title attribute with getAttribute, and finally use a regular expression to match text between <>.
document.querySelectorAll('.name').forEach(item => {
let title = item.getAttribute('title');
console.log(title.match(/\<.*\>/));
});
<td class="last">
<div class="container-relative">
<div class="name" title=""User" <John Appleseed>"></div>
<div class="date">9/17/2019</div>
<div class="tool"></div>
</div>
</td>
var divs=[];
for(i=0,j=0,obj=document.getElementsByClassName("name");i<obj.length;i++)
if(obj[i].title.includes("John Appleseed") &&
/* obj[i].title.split("\"")[2].trim()=="<John Appleseed>" && */
obj[i].tagName.toLowerCase()=="div"){
divs[j++]=obj[i];
}
console.log(divs);
separate your div using div ID. Then get your respective div using that value of ID. Then in javascript you can use getElementByID.
You can use Xpath,
.//div[contains(#class, 'Test')]
Then extract you required text from it.
Related
I have a tool that is used for cleaning up crappy HTML in order to make sense of the underlying structure. Having stripped class, style attributes and various Angular attributes, often the resulting markup is a series of nested <div> or <span> elements that have no attributes. What I would like to do is provide option to do a second pass where a <div> or <span> with no attributes can be removed, to flatten the structure more.
Is there a way in JavaScript to confirm that an HTML element has no attributes of any kind?
And if that is possible, how might I approach this stripping of an element?
For example, assuming I have this:
<div>
<div>
<div id="blah">
<div>
<div>
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
</div>
</div>
</div>
</div>
That should end up as:
<div id="blah">
<span dir="auto">
Joe Bloggs
</span>
</div>
Which I would then format to:
<div id="blah">
<span dir="auto">
Joe Bloggs
</span>
</div>
So I'd need a function that can walk the DOM and remove a div (or span) that has no attributes while leaving the inner contents intact (unless of course any of those inner elements can also be stripped for same reason).
Any pointers before I go ahead and construct a shoddy (but working) script would be appreciated!
The attributes property will tell you how many attributes an element has.
const countAttributes = element => console.log({
count: element.attributes.length,
list: [...element.attributes].map(attribute => attribute.name)
});
const divs = document.querySelectorAll('div');
divs.forEach(countAttributes);
<div></div>
<div class="one attribute"></div>
<div class="two attributes" id="second attribute"></div>
Do note that an element without attributes might still be used for something (e.g. a stylesheet might reference it in relation to other elements).
Here's how I did it.
I created a demo element, to get the elements, then I checked the number of elements, I checked if the element should be stripped.
I replaced the element with its children, and if it didn't have any, I used its text
function strip(startElement, toStrip) {
const test = document.createElement('div');
test.innerHTML = startElement.outerHTML;
[...test.querySelectorAll('*')].forEach(elem => {
if (!elem.attributes.length && toStrip.includes(elem.tagName.toLowerCase())) {
if (elem.children.length) elem.replaceWith(...elem.children);
else elem.replaceWith(elem.innerText);
} ;
});
return test.innerHTML;
}
console.log(strip(document.querySelector('div'), ['span', 'div']));
<div>
<div>
<div id="blah">
<div>
<div>
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
</div>
</div>
</div>
</div>
Updated Code
Here you go.
document.querySelectorAll("div").forEach((ele) => {
if (ele.attributes.length === 0) {
var fragment = document.createDocumentFragment();
while (ele.firstChild) {
fragment.appendChild(ele.firstChild);
}
ele.parentNode.replaceChild(fragment, ele);
}
});
<div>
<div>
<div id="blah">
<div>
<div>
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
</div>
</div>
</div>
</div>
So final output would be
<div id="blah">
<span dir="auto">
<span>Joe Bloggs</span>
</span>
</div>
So I have this structure and elements that I would like to change values or add a list to input.
<div id="TtkGjK6BoO" class="sc-fzoant fuKkxE">
<div class="sc-AxjAm fxBnch">
<div id="kit-container" class="sc-AxirZ ihpBRB">
<h1>Title?</h1>
<form><input class="sc-fznWOq iEYfe" value=""></form>
</div>
</div>
</div>
I know this id for sure and class for sure, but class is not unique and I don't have input id, only class. How do I access the input, since, something like this does not work:
$('#TtkGjK6BoO.sc-fznWO.iEYfe').val('Hi'));
You can search by hierarchy!
$('div > h1 + form > input').val('Hello');
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="TtkGjK6BoO" class="sc-fzoant fuKkxE">
<div class="sc-AxjAm fxBnch">
<div id="kit-container" class="sc-AxirZ ihpBRB">
<h1>Title?</h1>
<form><input class="sc-fznWOq iEYfe" value=""></form>
</div>
</div>
</div>
You need a space before sub element selectors
Assuming iEYfe is unique inside the container with ID TtkGjK6BoO then this will work
$('#TtkGjK6BoO .iEYfe').val('Hi');
Is it possible with jQuery or Javascript to copy the first character of a string that's user generated to another div?
As an example, the contact list on iPhone. The first letter of the contact name is used in the circle adjacent to the name.
With the correct snippet the output would be as follows, where 'First name, Last name' will be different.
<div class="initial">F</div>
<div class="name">First name, Last name</div>
<div class="initial">J</div>
<div class="name">John Smith</div>
I tried to get some ideas from these other posts:
How do I make the first letter of a string uppercase in JavaScript?
How can I get the first three letters of a string in JQuery?
Detect character in div and remove it Javascript or jQuery
However, I'm not sure where to start and how to output the result to the 'initial' div.
The simple way to do this is to provide a function to text() of the .initial elements which reads the first character from the sibling .name and returns it, like this:
$('.initial').text(function() {
return $(this).next('.name').text().slice(0, 1).toUpperCase();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="initial"></div>
<div class="name">Foo Bar</div>
<div class="initial"></div>
<div class="name">John Smith</div>
a vanilla JS solution i came up with:
https://jsfiddle.net/y0c9be6g/
<div class="initial"></div>
<div class="name">Bob Smith</div>
<div class="initial"></div>
<div class="name">Jim Halpert </div>
<div class="initial"></div>
<div class="name">Billy Baldwin</div>
<script>
var names = document.querySelectorAll(".name");
var initials = document.querySelectorAll(".initial");
function addInitial(item){
item.previousSibling.previousSibling.innerHTML = item.textContent.charAt(0);
}
names.forEach(addInitial);
</script>
In my use case, I am trying to get value from dynamically generated hidden field in JQuery. When I click the button for that iteration I should get the value for the hidden field belongs to that iteration. But I am not able to get it. It is giving the value as 'undefined'
HTML:
<div class="comment-list-new" style= "max-height: 660px !important;overflow-y: scroll;">
<h5>Discussion Board</h5>
<ol>
{{ if .ViewData.Questions }}
{{ range .ViewData.Questions }}
<li>
<p id="question_id" class="question_id_val" hidden>{{.QuestionId}}</p>
<div class="q-comment">
<div class="qanda questiondiv" id="questionarea" name="questionarea">
<div>
<div id="topic" class="upvote pull-left">
<a class="upvote"></a>
<span class="count">3</span>
<a class="downvote"></a>
</div>
<div >
<div class="qanda-info">
<h6><p id="quest_title">{{.QuestionTitle}}</p></h6>
</div>
<p id="quest_text">{{.QuestionText}}</p>
</div>
</div >
<div class="qanda-info">
<div class="user-info">
<img src="/resources/img/team-small-2.png" />
</div>
<h6>{{.UserId}}</h6>
<span class="date alt-font sub">{{.DateCreated}}</span>
<a id="answertext" name ="answertext" type="submit" class="link-text answerbutton">Answer</a>
</div>
</div>
</div>
</li><!--end of individual question-->
{{ end }}
{{ end }}
</ol>
</div><!--end of comments list-->
JS:
$('.questiondiv').on('click', '.submitanswerbutton', function() {
console.log("In submit button");
var question_id = $(this).closest('.question_id_val').val();
var answer_text = $('.answertext_val').val();
console.log(question_id);
console.log(answer_text);
$.getJSON("/submitanswer?question_id="+question_id+"&answer="+answer_text, function(data) {
console.log("answer Response"+data);
newQuestion = "<li><div class='q-comment'><div class='qanda' id='questionarea' name='questionarea'><div><div id='topic' class='upvote pull-left'><a class='upvote'></a><span class='count'>0</span><a class='downvote'></a></div><div ><div class='qanda-info'><h6><p id='quest_title'>"+title+"</p></h6></div><p id='quest_text'>"+desc+"</p></div></div ><div class='qanda-info'><div class='user-info'><img src='/resources/img/team-small-2.png' /></div><h6>Chip Mayer</h6><span class='date alt-font sub'>September 17 2014</span><a id='answertext' name ='answertext' type='submit' class='link-text'>Answer</a></div></div></div></li>";
$('ol').append(newQuestion);
});
});
In the above code I am trying to get the value for the hidden field question_id_val.
Could anyone help me with this?
Use closest() to get a reference to the outer container (li) and then use find() method to get the hidden field.
var question_id = $(this).closest('li').find('.question_id_val').val();
val() method works for usually input form fields(textbox,hidden fields etc..) .So you need to make sure your element is a valid form field in your page.
<input type="hidden" id="question_id" class="question_id_val" />
Or if you want to keep your p tag as it is, Use the html() or text() method to get the content of the p tag.
var question_id = $(this).closest('li').find('.question_id_val').text();
Remember, these method returns the text/html of all child content as well. So make sure to use it wisely.
val() should be used primarily in select, textarea and input elements.
For getting the inner text use html() or text()
var question_id = $(this).closest('.question_id_val').html();
or
var question_id = $(this).closest('.question_id_val').text();
If you know a css selector id or class I don't see problem why you can't do something like this:
var question_id = $('#question_id').text();
Or
var question_id = $('.question_id_val').text();
I wanna be able to select a specific set of child in which an attribute is defined.
But how to select childs which are first child of the root selector that having the attribute data-role
first-of-type selector doesn't work due to the type of the element.
Here we have a sample of the DOM.
<body>
<div data-role="ca:panel" title="foo">
<div data-role="ca:vbox" width="100%">
<div data-role="ca:form">
<div data-role="ca:formitem">
<div data-role="ca:hbox">
<input data-role="ca:textinput">
<div data-role="ca:menu"></div>
</div>
</div>
<div data-role="ca:formitem">
<input data-role="ca:passwordinput">
</div>
<div data-role="ca:formitem">
<select data-role="ca:combobox">
<option>[...]</option>
</select>
</div>
</div>
<table>
<tbody>
<tr>
<td>
<span data-role="ca:label"></span>
</td>
<td>
<button data-role="ca:button"></button>
</td>
<td>
<button data-role="ca:button"></button>
</td>
</tr>
</tbody>
</table>
</div>
</body>
My filter should select only
<div data-role="ca:form">
<span data-role="ca:label"></span>
<button data-role="ca:button"></button>
<button data-role="ca:button"></button>
It should work in any case, meanings, it shouldn't be linked to a specific structure of the dom and must use data-role as 'selector'.
I'm not a relevant jQuery developer. I tried some selector such as $('[data-role]:first-of-type'); but it doesn't work.
Do you have an idea to select the right set of child.
Note: Finding the first parent is not a concern.
It is possible to do this generically using a filter, so long as you have a start node:
JSFilter: http://jsfiddle.net/TrueBlueAussie/2uppww9s/5/
var root = $('[data-role="ca:vbox"]');
var matches = root.find('[data-role]').filter(function(){
return $(this).parentsUntil(root, '[data-role]').length == 0;
});
alert(matches.length);
You can use the :first pseudonym to select the first occurance of a element like for example:
var elm = $('*[data-role="ca:form"]:first');
this will select * any type of DOM-element, with the data-role that matches "ca:form"
Since you want to return two buttons with the same data-role, we cant use ":first" for that. You would have to get the first child of a that matches in that case
var elm = $('td').children('button[data-role="ca:button"]:first');
This will look through the child elements of all TD-tags and find the first button with data-role matching "ca:button"
If you want first of all overall specifications, then you can simply use selector on all three tag types and filter them as so:
$('div, span, button').filter(function(i){
if (this.tagName == 'DIV' && $(this).data('role') == 'ca:form') return true;
if (this.tagName == 'SPAN' && $(this).data('role') == 'ca:label') return true;
if (this.tagName == 'BUTTON' && $(this).data('role') == 'ca:button') return true;
}).first();
Using .first grabs the first of them.
Also, filter can be used in a million ways to get what you want and sounds like it may get you to what you need. Just set what you're filtering for in an if/for/switch statement and return true on items that match.
jsFiddle
However, if you wanted first of each you could do something like:
$('div[data-role="ca:form"]:first, span[data-role="ca:label"]:first, button[data-role="ca:button"]:first')
If variable driven in someway, just use string concatenation.
jsFiddle