So I have ul's on my webpage similar to the one below and I'm trying to loop through each of them to grab a span within the li. Below is an example of how it appears in my HTML:
<ul id="item-NineAM" class="list-group">
<li class="list-group-item w-100 border-dark past">
<span class="badge badge-dark" id="item-time">09:15 AM</span>
<p class="m-1 w-75 item-text">fsda</p>
<button class="btn btn-danger" id="trashCan"><span class="oi oi-trash"></span></button></li>
</ul>
I've set up an interval to grab the span with id #item-time and pass it into my audit function
const listGroup = $(".card .list-group li #item-time");
$.each(listGroup, function(i, itemSpan){
console.log(itemSpan)
auditItem(itemSpan)
})
I've verified in the console that the span is passed into function but I cannot seem to grab the text of it.
<span class="badge badge-dark" id="item-time">09:15 AM</span>
I need to grab the time that's inside of the span. My console tells me it's an object. Any ideas? I've tried .text() and .innerHTML but no luck.
Thanks!
The jquery selector you're assigning to listGroup should be pretty general, so you wouldn't include an id as you'd only get one match.
It looks like you're misusing id. Remember, you can only have a single instance of id and it should only be used to indicate uniqueness. Instead you want item-time to be a class since you can have several instances of classes.
I've corrected some others in your html as well.
const listGroup = $(".list-group li span.item-time");
$.each(listGroup, function(){
console.log($(this).text())
//auditItem(itemSpan)
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul class="list-group item-NineAM">
<li class="list-group-item w-100 border-dark past">
<span class="badge badge-dark item-time">09:15 AM</span>
<p class="m-1 w-75 item-text">fsda</p>
<button class="btn btn-danger trashCan">
<span class="oi oi-trash"></span>
</button>
</li>
</ul>
Related
Running this piece of Bootstrap HTML and JS code below, I am struggling to not initiate the modal when clicking on the dropdown navi-link (e.g. Mark as Read).
<ul id="notification_items" class="navi navi-hover">
<!--begin::Item-->
<li id="1f7cbbe4-2345-486a-ab66-b05601f033a9" data-notification-id="1f7cbbe4-2345-486a-ab66-b05601f033a9" data-notification-subject="Some Subject" data-notification-message="And some message" class="notification_item cursor-pointer navi-item">
<div class="pr-10 pl-2 navi-link">
<div class="navi-label mx-5"><span class="label label-dot label-lg label-primary mt-n6"></span></div>
<div class="navi-text">
<span class="font-weight-bolder font-size-lg">Some Subject</span><span class="text-muted"> - And some message</span>
<div class="text-muted font-size-sm">3 hours ago</div>
</div>
<div class="notification_actions dropdown dropdown-inline d-none">
<i class="far fa-ellipsis-h"></i>
<div class="dropdown-menu dropdown-menu-sm dropdown-menu-right" style="">
<ul class="navi flex-column navi-hover py-2">
<li class="navi-item"><span data-notification-id="1f7cbbe4-2345-486a-ab66-b05601f033a9" class="notification_mark_as_read navi-link"><span class="navi-icon"><i class="fad fa-comment-check"></i></span><span class="navi-text">Mark as Read</span></span></li>
<div class="dropdown-divider"></div>
<li class="navi-item"><span class="navi-icon"><i class="far fa-trash-alt text-danger"></i></span><span class="navi-text text-danger">Delete</span></li>
</ul>
</div>
</div>
</div>
</li>
<!--end::Item-->
</ul>
And the simple JS code piece to show the modal when clicking on the <li>:
$(document).on("click", ".notification_item", function () {
$('#notification').modal('show');
});
I tried to e.stopPropagation(); when clicking on the .notification_actions Which works initially, but then obviously every other event won't work anymore.
You have to play with the arguments from the event parameter of the click event: target and currentTarget
target will return your DOM element on which the click occurred
initially
currentTarget will always be the DOM element on which your handlers
is attached -> in your case the li.notification_item
The solution is to identify the element the click occured on - target. There are a lot of ways - in your case you can detect if your click occured in the dropdown navi-link (.dropdown-menu) by traversing the DOM up until the root menu (#notification_items):
$(document).on("click", ".notification_item", function (e) {
// you traverse up to the root ul, and looking if you are in a dropdown menu
if ($(e.target).closest('.dropdown-menu', '#notification_items').length > 0) {
// You are in a drop down menu -> do nothing
} else {
// you are somewhere else -> trigger the modal
$('#notification').modal('show');
}
});
JSFiddle
P.S. this codes checks if you are in a dropdown-menu, you can use specific selector if you want to check for a specific dropdown.
I am trying to do this:
Search for all the spans in my structure
Get the id value from each span
Update the parent with that text for test purposes
The reason for this work is that I am doing front-end customizations for an application and trying get some WAI-ARIA labelled-by values set on a parent element.
The problem is that many of the needed values come from an COTS application that I am working with/around. These needed input are not always set in a good sequence in the DOM.
I have been looking at a JS solution to get around this.
<div class="fluid-form-container">
<ul id="accordionGroup" class="Accordion" data-allow-multiple="">
<li class="fluid-form-group-container">
<h3 aria-labelledby="accordion1id">
<button aria-expanded="true" class="Accordion-trigger" aria-controls="sect1" id="accordion1id">
<span class="Accordion-title"><div class="fluid-form-title">
<div class="FormSection">
<span id="More_Info_Form_Section_Label">More Info</span>
</div>
</div>
</span>
</button>
</h3>
</li>
<li class="fluid-form-group-container">
<h3 aria-labelledby="accordion2id">
<button aria-expanded="true" class="Accordion-trigger" aria-controls="sect2" id="accordion2id">
<span class="Accordion-title"><div class="fluid-form-title">
<div class="FormSection">
<span id="Even_More_Info_Form_Section_Label">Even More Info</span>
</div>
</div>
</span>
</button>
</h3>
</li>
</div>
//My bad javaScript so far
var found_elements = [];
var outers = document.querySelectorAll('.FormSection');
for(var i=0; i<outers.length; i++) {
var elements_in_outer = outers[i].querySelectorAll("span");
var updateValue = elements_in_outer.getAttr("id");
outers[i].closest("h3").innerHTML = updateValue;
}
The expect results:
- parent tag innerHTML set to the id value of each span in the structure
Actual results:
- I'm getting errors because I am not sure what I need to use to get that id from each span found
querySelectorAll() returns a NodeList , so elements_in_outer.getAttr("id") won't work and should be replaced with querySelector()
there is no getAttr, use getAttribute
( i replaced your for with a forEach )
var found_elements = [];
var outers = document.querySelectorAll('.FormSection').forEach(div => {
var elements_in_outer = div.querySelector("span");
var updateValue = elements_in_outer.getAttribute("id");
div.closest("h3").innerHTML = updateValue;
});
<div class="fluid-form-container">
<ul id="accordionGroup" class="Accordion" data-allow-multiple="">
<li class="fluid-form-group-container">
<h3 aria-labelledby="accordion1id">
<button aria-expanded="true" class="Accordion-trigger" aria-controls="sect1" id="accordion1id">
<span class="Accordion-title"><div class="fluid-form-title">
<div class="FormSection">
<span id="More_Info_Form_Section_Label">More Info</span>
</div>
</div>
</span>
</button>
</h3>
</li>
<li class="fluid-form-group-container">
<h3 aria-labelledby="accordion2id">
<button aria-expanded="true" class="Accordion-trigger" aria-controls="sect2" id="accordion2id">
<span class="Accordion-title"><div class="fluid-form-title">
<div class="FormSection">
<span id="Even_More_Info_Form_Section_Label">Even More Info</span>
</div>
</div>
</span>
</button>
</h3>
</li>
</div>
If you know beforehand that you will only use the span elements that have an id, then use [id] in the querySelectorAll selector likewise
document.querySelectorAll('span[id]')
If you will use that as an array, then you need
[... document.querySelectorAll('span[id]')]
Assigning the new value would be something like this:
[... document.querySelectorAll('span[id]')].forEach(s => s.closest("h3").innerHTML = s.id)
i have html div where i use ng-repeat that gives me back elements from array
<div>
<div class="col-sm-3" ng-repeat="el in vm.filmovi " id="filmovi">
<img src="http://image.tmdb.org/t/p/w500/{{el.poster_path}}" style="width:100%;"><br>
<a ng-click="vm.set_favorit(el)" style="cursor:hand; color:white;" uib-tooltip="Postavi u omiljene">
<i class="glyphicon" ng-class="{'glyphicon-star-empty':el.favorit!=true, 'glyphicon-star':el.favorit==true}"
aria-hidden="true"></i></a>
<a href="http://www.imdb.com/title/{{el.imdb_id}}/" style="color:white;">
<strong>{{ el.title | limitTo: 20 }}{{el.title.length > 20 ? '...' : ''}}</strong></a>
<a class="glyphicon glyphicon-share-alt" style="margin-left:5px; color:white;" ng-click="vm.open()" uib-tooltip="share" ></a><br>
{{el.popularity}} <br>
<a style="color:white;" href="#" ng-click="vm.filter(genre)" ng-repeat="genre in el.genres"><small>{{genre.name}} </small></a>
<div ng-init="x = 0">
<span uib-rating ng-model="x" max="5"
state-on="'glyphicon-star'"
state-off="'glyphicon-star-empty'"></span></div>
</div>
</div>
now i created a button that changes value of id "filmovi"
<li><a href="#" ng-hide="vm.ulogovan" ng-click="vm.dugme();" >losta</a></li>
and created function vm.dugme() that gets element by id and sets class atribute to col-sm-4
vm.dugme=function(){
document.getElementById("filmovi").setAttribute("class","col-sm-4");
};
but when i did that only the first element changed
but i need for all of them to change to col-sm-4 , any suggestion?
Don't do DOM manipulation from angularjs controller. Instead make use of directive provided by angular.
You could use ng-class with expression so that whenever expression gets satiesfied the class will be added over that DOM. To add class put addColSm4 flag inside a controller and change that flag from dugme method of your controller. Also by looking at screenshot it seems like you need col-sm-3 class at the beginning, afterwards you need to apply col-sm-4.
HTML
<div class="row">
<div class="col-sm-3" ng-repeat="el in vm.filmovi"
ng-class="{'col-sm-4': vm.addColSm4, 'col-sm-3': !vm.addColSm4 }" >
.. Html will stay as is ..
</div>
</div>
<li>
<a href="#" ng-hide="vm.ulogovan"
ng-click="vm.dugme()">
losta
</a>
</li>
Code
vm.dugme = function (){
vm.addColSm4 = true;
};
Demo Plunker
I want to extract the text values out of this List:
<ul class="standardSuggestions">
<li class="">
<div id="idac">
<span class="email" id="idb7"><span>mail-fuer-chrisko</span>#<span>web.de</span></span>
<span class="btn-positioner"><span class="btn-wrapper btn-fix btn-service btn-xs"><input name="wishnamePanel:suggestionsContainerWrapper:freeMailSuggestionsPanel:standard-suggestion-list:suggestionRepeaterContainer:suggestion-to-repeat:1:suggestion:subForm:select-email" id="idae" value="Übernehmen" type="submit"></span></span>
</div>
</li><li class="">
<div id="idaf">
<span class="email" id="idb8"><span>post-fuer-chrisko</span>#<span>web.de</span></span>
<span class="btn-positioner"><span class="btn-wrapper btn-fix btn-service btn-xs"><input name="wishnamePanel:suggestionsContainerWrapper:freeMailSuggestionsPanel:standard-suggestion-list:suggestionRepeaterContainer:suggestion-to-repeat:2:suggestion:subForm:select-email" id="idb0" value="Übernehmen" type="submit"></span></span>
</div>
</li><li class="">
<div id="idb1">
<span class="email" id="idb9"><span>chrisko1</span>#<span>web.de</span></span>
<span class="btn-positioner"><span class="btn-wrapper btn-fix btn-service btn-xs"><input name="wishnamePanel:suggestionsContainerWrapper:freeMailSuggestionsPanel:standard-suggestion-list:suggestionRepeaterContainer:suggestion-to-repeat:3:suggestion:subForm:select-email" id="idb2" value="Übernehmen" type="submit"></span></span>
</div>
</li><li class="">
<div id="idb3">
<span class="email" id="idba"><span>chrisko.1</span>#<span>web.de</span></span>
<span class="btn-positioner"><span class="btn-wrapper btn-fix btn-service btn-xs"><input name="wishnamePanel:suggestionsContainerWrapper:freeMailSuggestionsPanel:standard-suggestion-list:suggestionRepeaterContainer:suggestion-to-repeat:4:suggestion:subForm:select-email" id="idb4" value="Übernehmen" type="submit"></span></span>
</div>
</li>
</ul>
Problem is that the div id = "" is changing on every reload. So I'm not sure how to select correct elements. I tried it with the following function:
casper.then(function(){
var listItems = this.evaluate(function () {
var nodes = document.querySelectorAll('ul > li');
return [].map.call(nodes, function(node) {
return {
text: node.querySelector("span").textContent
};
});
});
this.echo(JSON.stringify(listItems, undefined, 4));
});
echo is "null" :-(
Your iteration over the elements is correct. The only way to get a null value out of the page context is if there was an error. The only part of the code that can produce an error is node.querySelector("span").textContent, because a node doesn't necessarily have to have a <span> descendant. If it doesn't have one, then this fails with a TypeError and you get null.
The limited markup that you've shown always contains a <span> in every <li>, so there must be another <ul> on the page, that has no <span> descendants. You have to find a CSS selector with doesn't include the other <ul> element.
I propose
var nodes = document.querySelectorAll('ul.standardSuggestions > li');
I am trying to decrement a counter within a nested AnguarJs ng-repeat. I know it is a problem of scope, because the increment in the outer ng-repeat works fine, but in the inner ng-repeat is where I have to decrement and that is where I run into the problem (nothing happens). Is there any way to get an inner scope to increment/decrement/affect an outer scope? Here is the code I am working with.
<div class = "col-md-12 section-bg-conversations" ng-repeat="o in form.question | filter:searchText | orderBy:predicate" ng-show="$index<5 || form.showMoreQuestions" >
<!--section for question and option to answer-->
<span class="pull-left" style="margin-bottom:5px">
<ul style="color:#107A77; margin-left: -10px; list-style-type:none">
<li >
<!--below is only to toggle form view-->
<h7><strong><a style="color:#107A77;" ng-click="o.Answer = true" ng-show="!o.Answer">Comment</a></strong></h7>
</li>
<li>
<h7 ng-init="replyCounter=o.replyCounter">Replies ({{replyCounter}}) </h7>
</li>
<li>
<h7>
<a style="color:#107A77;text-size: 6px"
ng-init="followCounter=o.followCounter" ng-click="followConversation(o.id); o.isFollowing=true;
followCounter=followCounter+1" ng-show="!o.isFollowing">
Follow ({{followCounter}})
</a>
<span ng-show="o.isFollowing">
Following ({{followCounter}})
</span>
</h7>
</li>
</ul>
</span>
<span ng-show="o.isFollowing">
<a style='color:gold' ng-init="followCounter = o.followCounter" ng-click="unfollowConversation(o.followId); o.isFollowing = false;
followCounter = followCounter-1 " ng-hide="o.unfollowValue">Unfollow</a>
</span>
<!--form div below showing only submit and cancel-->
<div style="margin-top:5px">
<button class="btn btn-xs btn-primary" ng-init="replyCounter=o.replyCounter" style='background:#107A77'
ng-click="submitAnswer(o.id); replyCounter = replyCounter+1;">Submit</button>
<button class="btn btn-xs btn-primary" style='background:red' ng-click="o.Answer = false" ng-show="o.Answer">Cancel</button>
</div>
<div class = "col-md-offset-1" style="padding:5px"ng-repeat="a in o.replies" ng-show="$index<3 || o.showMoreReplies">
<span ng-show="a.isAuthor">
<a ng-init="replyCounter=o.replyCounter"style='color:red' ng-click="doDelete(a.id); a.deleteValue = true;
replyCounter = replyCounter-1">Delete</a>
</span>
</div>
I also included the followCounter as an exmaple of a counter that is working. Pretty much the main problem is in the last inner div that does ng-repeat="a in o.replies" and I'm not sure how to solve the problem of incrementing/decremeting the counter in the overall scope.