javascript how to change glyphicon according to value change - javascript

I am trying to do an optimum level feature which, when a value is higher in an optimum range, a arrow-up glyphicon will be displayed and when the value is lower, it changes to arrow-down glyphicon.
<div class="card-body" ng-repeat="item in resTemperature" ng-if="$last">
<p>
Temperature  <span class="text" style="font-weight: bold; font-size:150%" ng-repeat="i in item">{{i}} °C </span>
<span class="glyphicon" style="font-size: 200%; float: right;"></span>
</p>
</div>
Sample result with hardcoded value:

I would approach it the following way.
Add an additional class to your div indicating if your value is higher/lower/optimal.
Then get rid of your glyphicon span, replacing it with a css pseudo-element.
i.e.,
<style>
.card-body .text::after {
font-size: 200%;
float: right;
}
.card-body.optimal .text::after {
content: "O"; /* replacing these with the glyphs you want */
}
.card-body.lower .text::after {
content: "L";
}
.card-body.higher .text::after {
content: "H";
}
</style>
<div class="card-body optimal" ng-repeat="item in resTemperature" ng-if="$last">
<p>Temperature  
<span class="text" style="font-weight: bold; font-size:150%" ng-repeat="i in item">{{i}} °C </span>
</p>
</div>

Related

Why don't my class styles apply to dynamically created elements? Angularjs

My question is simple; why don't my class styles apply to dynamically created elements?
I am creating a search bar here where I generate an li per matching result, and append it to my ul. When I inspect the page, I see the classes are applied to the li's correctly, but the styles from the class itself aren't present. I hard coded a test li and it had the expected styles. What am I missing here in order to have my styles applied to these dynamically generated elements? Surely I don't have to assign every style for the li's in my typescript? Any explanation would be lovely, thank you all! (:
My HTML:
<div class="section">
<h2>Step 1: Choose an Identity Provider (IDP)</h2>
<div class="search">
<input
class="focusable"
(focusout)="handleFocusOut()"
(input)="debounce(search, 300, $event)"
placeholder="Select Identity Provider"
autocomplete="off"
/>
<i class="icon fas fa-search"></i>
<ul id="search-options">
<li class="focusable testing">IMG Salesforce</li>
</ul>
</div>
<!-- <i class="fa fa-plus"></i>-->
</div>
My scss:
.section {
...
.search {
position: relative;
width: 300px;
.icon {
position: absolute;
right: 5px;
top: 3px;
}
input {
width: 300px;
}
ul {
color: red;
li {
cursor: pointer;
&:hover {
background-color: grey;
color: red;
}
.testing {
cursor: pointer;
&:hover {
background-color: grey;
color: red;
}
}
}
}
}
}
My TS:
let ul = document.getElementById('search-options');
this.displayServices.forEach((service) => {
let li = document.createElement('li');
li.classList.add('focusable', 'testing');
li.addEventListener('focusout', this.handleFocusOut);
const img = document.createElement('img');
img.src = this.getImgUrl(service);
img.width = 20;
img.height = 20;
img.style.margin = '0 10px';
li.innerHTML = `${service.name}`;
li.style.display = 'flex';
li.style.alignItems = 'center';
li.style.border = '.5px solid black';
li.style.padding = '8px 0';
li.prepend(img);
ul.appendChild(li);
});
It's hard to be precise without seeing the whole tamale, but generally you should be getting your data in the .TS file and sending that data directly to the view. Your view should be creating those elements on the fly. Not shown in the answer here is the inline styles you were adding to the image and the LI tag - just do those in CSS.
Something like this:
TS:
this.someService.getData.subscribe(displayServices => {
this.displayServices = displayServices;
})
HTML:
<div class="section">
<h2>Step 1: Choose an Identity Provider (IDP)</h2>
<div class="search">
<input
class="focusable"
(focusout)="handleFocusOut($event)"
(input)="debounce(search, 300, $event)"
placeholder="Select Identity Provider"
autocomplete="off" />
<i class="icon fas fa-search"></i>
<ul id="search-options">
<li *ngFor="service in displayServices"
class="focusable testing"
(focusout)="handleFocusOut($event)">
<img [src]="getImgUrl(service)" />
{{service.name}}</li>
</ul>
</div>
<!-- <i class="fa fa-plus"></i>-->
</div>
the classes are applied to the li's correctly, but the styles from the class itself aren't present
If you mean the focusable and testing classes, I don't see them in your SCSS.

Adding class to group of span tags one by one

I got html structure like this:
<body>
<div class="container">
<span class="block done" id="1"></span>
<span class="block" id="2"></span>
<span class="block" id="3"></span>
<span class="block" id="4"></span>
<span class="block" id="5"></span>
</div>
<script src="loaders.js"></script>
</body>
My current goal is to add every 1s class "done" (its some kind of simple loading bar) to spans one by one and when last span got "done" class everything restart and loop over and over. Can someone help me how to write this in vanilla JavaScript?
You could do it like this:
var blocks = document.getElementsByClassName('block');
(function animateProgress(n) {
for (var i = 0; i < blocks.length; i++) {
blocks[i].classList[i < n ? 'add' : 'remove']('done');
}
setTimeout(function() {
animateProgress((n + 1) % (blocks.length + 1));
}, 400);
})(0);
.block {
float: left;
background: #eceded;
padding: 1em;
margin: 1px;
}
.block.done {
background: #7be47b;
}
<div class="container">
<span class="block"></span>
<span class="block"></span>
<span class="block"></span>
<span class="block"></span>
<span class="block"></span>
</div>

Javascript - getting the value of child element after clicking on another child element

This must be very simple, but I still cannot figure it out... Below is an example and what I tried - all I want is to get the value of <a id="{value}".. after clicking on the <div class="text" DIV.
.h {
background: lightblue;
}
.pb {
display: inline-block
}
.cb {
clear: both
}
.text {
background: #ffc;
border: 1px solid #000
}
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m75813" href="#m75183">#</a></div>
</div>
<div class="text" onclick="alert(parentNode.parentElement.firstChild.childNodes[1].a.id);">
After clicking on the yellow background, the value from [a id="m75813"] (ie. 'm75813') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>
As the element has an ID, you can just look it up by that ID. IDs have to be unique (but keep reading, I suspect you don't want to do that):
alert(document.getElementById('m75813').id);
.h {
background: lightblue;
}
.pb {
display: inline-block
}
.cb {
clear: both
}
.text {
background: #ffc;
border: 1px solid #000
}
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m75813" href="#m75183">#</a></div>
</div>
<div class="text" onclick="alert(document.getElementById('m75813').id);">
After clicking on the yellow background, the value from [a id="m75813"] (ie. 'm75813') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>
but if you have lots of these with various IDs and it's the ID you're trying to find, you can do it by going up to the parent node and using querySelector to find the a element:
alert(this.parentNode.querySelector('a').id);
.h {
background: lightblue;
}
.pb {
display: inline-block
}
.cb {
clear: both
}
.text {
background: #ffc;
border: 1px solid #000
}
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m75813" href="#m75183">#</a></div>
</div>
<div class="text" onclick="alert(this.parentNode.querySelector('a').id);">
After clicking on the yellow background, the value from [a id="m75813"] (ie. 'm75813') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m54684" href="#m54684">#</a></div>
</div>
<div class="text" onclick="alert(this.parentNode.querySelector('a').id);">
After clicking on the yellow background, the value from [a id="m54684"] (ie. 'm54684') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>
In both cases, I would suggest modern event handling rather than using onxyz-attribute-style handlers. For example: Let's assume all those article elements are in some kind of container. We can hook click on the container and then find which div the click passed through, and find the a related to that div:
document.getElementById("container").addEventListener("click", function(e) {
var element = e.target;
while (element != this) {
if (element.matches("div.text")) {
alert(element.parentNode.querySelector("a").id);
break;
}
element = element.parentNode;
}
});
document.getElementById("container").addEventListener("click", function(e) {
var element = e.target;
while (element != this) {
if (element.matches("div.text")) {
alert(element.parentNode.querySelector("a").id);
break;
}
element = element.parentNode;
}
});
.h {
background: lightblue;
}
.pb {
display: inline-block
}
.cb {
clear: both
}
.text {
background: #ffc;
border: 1px solid #000
}
<div id="container">
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m75813" href="#m75183">#</a></div>
</div>
<div class="text">
After clicking on the yellow background, the value from [a id="m75813"] (ie. 'm75813') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m54684" href="#m54684">#</a></div>
</div>
<div class="text">
After clicking on the yellow background, the value from [a id="54684"] (ie. '54684') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>
</div>
You can do this:
<div class="text" onclick="alert(document.getElementById('m75813').id);">
After clicking on the yellow background, the value from [a id="m75813"] (ie. 'm75813') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
What's happening is that your queries are returning text nodes (which includes whitespace like newlines) as well as HTML nodes, so your elements aren't at the index you expect. querySelector('a') is the simpler approach, but if you did want to select your target via it's place in the DOM structure, you could use firstChildElement and children instead of firstChild and childNodes, respectively, because they exclude text nodes:
this.parentElement.firstElementChild.children[1].firstElementChild.id
.h {
background: lightblue;
}
.pb {
display: inline-block
}
.cb {
clear: both
}
.text {
background: #ffc;
border: 1px solid #000
}
<article>
<div class="h">
<div class="pb">user</div>
<div class="pb">date <a id="m75813" href="#m75183">#</a></div>
</div>
<div class="text" onclick="alert(this.parentElement.firstElementChild.children[1].firstElementChild.id);">
After clicking on the yellow background, the value from [a id="m75813"] (ie. 'm75813') should apppear. Sentence text.<br> Other sample.<br> Hello world.
</div>
</article>

Bootstrap bug - input has-error has-feedback glyphicon not vertically centred?

Why glyphicon-warning-sign form-control-feedback is not vertically centred in the code below - after adding font-size: 20px; to the label?
<div class="container">
<div class="content align-left contact">
<p>Hello World!</p>
<form action="#" method="post" id="contact-form">
<div class="form-group has-error has-feedback">
<label for="inputName">Your Name (required)</label>
<input type="text" name="name" class="form-control" id="input-name" placeholder="Name">
<span class="glyphicon glyphicon-warning-sign form-control-feedback" aria-hidden="true"></span>
<span id="inputWarning2Status">(warning)</span>
</div>
</form>
</div>
</div>
CSS:
.has-feedback .form-control-feedback {
border: 1px solid black;
}
.content {
padding: 100px;
}
.content p {
font-size: 18px;
letter-spacing: 1px;
line-height: 30px;
padding-bottom: 20px;
}
.content.contact label {
font-weight: 700;
}
.content.contact label {
font-size: 20px; // this is where the error cause - but why!???
}
Result:
The warning text is not red too.
Any ideas?
at jsfiddle but I can't find bootstrap as the load option!
EDIT:
You can see the bug at bootply
Brad's answer is good, but it is partial. When you change size of the label, or you put some more content before input, then it will be destroyed again. Since element .form-control-feedback has absolute position, then you should warp it in the common parent with input, so you will always get the right result. Add this CSS:
.warning {
color:#a94442;
}
.my-group {
position: relative;
}
And update you HTML:
<div class="form-group has-error has-feedback">
<label for="inputName">Your Name (required)</label>
<div class="my-group">
<input type="text" name="name" class="form-control" id="input-name" placeholder="Name">
<span class="glyphicon glyphicon-warning-sign form-control-feedback" aria-hidden="true"></span>
</div>
<span id="inputWarning2Status">(warning)</span>
</div>
Working demo: http://www.bootply.com/jGxRAFMKkg
1) you can add external resources to jsfiddle on the left side of the screen, use the bootstrap CDN.
2) the font-size for the label is causing the problem. The icon is fixed and doesnt play nice with the label size changing (don't ask me why - log with bootstrap).
3) THE FIX: add the following to css:
.has-feedback label~.form-control-feedback {
top:33px;
}
.warning {
color:#a94442; /*add this class to your warnings span*/
}
DEMO https://jsfiddle.net/10yLhpu3/
Add this to you stylesheet:
.glyphicon-warning-sign{
margin-top:8px;
}
#inputWarning2Status{
color:red;
}
http://www.bootply.com/gy41ldchWf
And it will work fine.
Remove this from the style
.content.contact label {
font-size: 20px;
}
In this line of code add warning in the class
<span class="glyphicon glyphicon-warning-sign form-control-feedback warning" aria-hidden="true"></span>
add any class name then replace the style that you've remove with this
.warning {
font-size: 20px;
}

Enable and Disable a Span Class based on DOM Changes in jQuery

I have a chat fontawesome icon currently coded as:
<li class="hidden-xs"><a href="#" class="right-bar-toggle waves-effect">
<i class="fa fa-comments "></i>
</a></li>
I want a red badge with counter to display when new chat message arrives as follows:
<li class="hidden-xs"><a href="#" class="right-bar-toggle waves-effect"><i class="fa fa-comments "></i>
<span class="badge badge-xs badge-danger">3</span>
</a></li>
3 is an example of unread chat message counter.
Selected portions of my javascript code are as follows:
var msgHistory = document.querySelector('#history');
var msg = document.createElement('p');
msg.innerHTML = name + ': ' + event.data;
msg.className = event.from.connectionId === session.connection.connectionId ? 'mine' : 'theirs';
The chat is displayed in:
<p id="history"></p>
and css are as follows:
#history {
width: 100%;
height: calc(100% - 40px);
overflow: auto;
}
#history .mine {
color: #07715b;
text-align: left;
margin-left: 10px;
}
#history .theirs {
color: #4398db;
text-align: left;
margin-left: 10px;
}
The chat html will display as:
<p id="history">
<p class="mine">Me: Hi</p>
<p class="theirs">User-1: Hello</p>
<p class="mine">Me: I am testing</p>
<p class="theirs">User-1: Okay</p>
</p>
I want to enable the span class= badge and count of <p class="theirs"> being displayed on badge, when another user enters a message.
The span class= badge needs to be disabled and counter reset when <p class="mine"> is set. That is once i enter a message.
The span class= badge and counter needs to display again when new message arrives on <p class="theirs">
How is it possible with jQuery? Thanks in advance.

Categories