Odd,Even in ng-repeat Angular - css

I want to detect odd or oven in ng-repeat . now i have a fiddle that display some dots show/hide randomly , now i want to change background to not only red , for example odd = green and even = red .
function MyCtrl($scope, $timeout) {
$scope.lights = [0,1,2,3,4,5,6,8,9,10,11,12,13,14,15,16,17,18,19,20];
$scope.currentLight = 0;
function light(index){
if($scope.lights.length < index) {
light(0);
} else {
$scope.currentLight = index;
index = Math.floor((Math.random() * 20) + 1);
$timeout(function(){
light(index);
}, 1000);
}
}
light(0);
}
Any advice ?

you can use ng-class-odd and ng-class-even
from https://docs.angularjs.org/api/ng/directive/ngClassOdd
<ol ng-init="names=['John', 'Mary', 'Cate', 'Suz']">
<li ng-repeat="name in names">
<span ng-class-odd="'odd'" ng-class-even="'even'">
{{name}}
</span>
</li>
</ol>

Related

Can modern CSS display/hide N children items from X by random?

Say I have X items in a <ul> DOM:
<ul>
<li>1</li>
<li>2</li>
...
<li>X</li>
<ul>
It's easy to do this with JavaScript but is it possible to only display N items by random with pure CSS commands?
For "display", I mean the opposite of display:none. So there are X-N items be regarded as display:none
This is not possible with only CSS because it will require some programming, and CSS is not a programming language.
You can do this with Javascript and CSS as follows:
const items = document.querySelectorAll("li");
const numberToShow = Math.floor(Math.random() * items.length);
for (let i = 0; i < items.length; i++) {
if (i < numberToShow) {
items[i].style.display = "block";
} else {
items[i].style.display = "none";
}
}

changing bootstrap progress bar color based on percentage

I created a progress bar using Bootstrap and want the color to change dynamically based on percentage. So far this is what my code looks like:
<div class="progress" style="height: {{c.options.bar_height}}px;">
<div class="progress-bar progress-bar-striped active {{c.progress_bar_color}}" role="progressbar" aria-valuenow={{c.data.percent_complete}} aria-valuemin="0" aria-valuemax="100" style="width:{{c.data.percent_complete}}; font-size: {{c.options.font_size}};">
{{c.data.percent_complete}}
</div>
</div>
In my client controller, I have set the colors as such:
if(c.data.percent_complete<=50) {
c.progress_bar_color = 'progress-bar-danger';
}
if(c.data.percent_complete>50 && c.data.percent_complete<=75) {
c.progress_bar_color = 'progress-bar-warning';
}
if(c.data.percent_complete>75 && c.data.percent_complete<=99.99) {
c.progress_bar_color = 'progress-bar-primary';
}
if(c.data.percent_complete==100) {
c.progress_bar_color = 'progress-bar-success';
}
So far, the progress bar doesn't change color at all. What am I missing to get this to work?
EDIT
I got rid of my client controller and added a ng-class:
ng-class="{'progress-bar-danger': c.data.percent_complete<'33', 'progress-bar-warning': c.data.percent_complete>='33' && c.data.percent_complete<'66', 'progress-bar-success': c.data.percent_complete>='66'}"
This works for every scenario, EXCEPT when it is 100%. When the bar reaches 100%, for whatever reason, it changes to progress-bar-danger instead of progress-bar-success. Any suggestions how to fix this? Thanks!
Could try using ng-class="c.progress_bar_color" instead
Maybe this working JSFiddle helps :)
I fixed this by using uib-progressbar instead:
My client controller:
var value = c.data.percent_complete;
var type;
if (value <= c.options.danger_threshold) {
type = 'danger';
} else if (value > c.options.danger_threshold && value <= c.options.warning_threshold) {
type = 'warning';
} else if (value > c.options.warning_threshold && value <= c.options.primary_threshold) {
type = 'primary';
} else {
type = 'success';
}
c.percentage_label = value+'%';
c.type = type;
My revised HTML:
<uib-progressbar style="height: {{c.options.bar_height}}px;" class="progress-striped active" value="c.data.percent_complete" type="{{c.type}}">
<div>
<span style="font-size: {{c.options.font_size}};">{{c.percentage_label}}</span>
<i ng-if="c.data.empty.length>0" class="fa fa-info-circle info m-l-xs" popover-placement="{{c.dynamicPopover.placement}}" popover-trigger="mouseenter" uib-popover-template="c.dynamicPopover.templateUrl" popover-title="{{c.data.empty.length}} Required Fields Missing"></i>
</div>
</uib-progressbar>

Angular 2 : #ViewChildren for recursive component

I have a recursive component which displays des tag a
First , there is the parent component
- html
<div class=" suggestions" style="display : inline-block;" tabindex=-1 #autocompleteDiv>
<span style="width: auto;cursor: pointer;position: absolue">
<div *ngIf="hideInputField" style="border: 1px solid #9e9898">
{{query}}
<a style="color: #0012ff;" (click)="unselectData()">x </a>
</div>
<div *ngIf="!hideInputField">
<input type="text" [(ngModel)]="query" (keyup)="handleKeyPress($event)" (keypress)="handleEnterPress($event)"
style="padding: 4px;" (click)="displayDropdown();" #inputquery (selectValueEvent)="select($event)">
<div #suggestion *ngIf="divMustBeShow===true" tabindex="-1">
<div #recursivediv class="liclass" >
<recursive-tree-view [treeNodeDisplay]="listToBuild"
[selectedItem]="selectedItem"
(selectValueEvent)="select($event)" #recursive></recursive-tree-view>
</div>
</div>
</div>
</span>
</div>
parent code (a part) :
displayDropdown() {
if (this.divMustBeShow) {
if ((this.query && this.query.length < 1) || !this.query) {
this.divMustBeShow = false;
}
} else {
this.divMustBeShow = true;
}
}
handleEnterPress(key: KeyboardEvent) {
if (key.keyCode === 13 || key.keyCode === 20) {
//when press enter (13) or tab (20)
this.query = this.recursive.selecItemWithEnterPress();
}
}
handleKeyPress(key: KeyboardEvent) {
if (key.key === "ArrowDown") {
// if the pressed key is down arrow
this.recursive.setDownListFocus()
} else if (key.key === "ArrowUp") {
// if the pressed key is up arrow
this.recursive.setUpListFocus();
} else if (key.keyCode === 13 || key.keyCode === 20) {
//when press enter (13) or tab (20)
this.query = this.recursive.selecItemWithEnterPress();
} else if ((key.keyCode > 64 && key.keyCode < 91) // key a -> z
|| key.keyCode === 32 // space
|| key.keyCode === 8 // backspace
|| key.keyCode === 46 // delete
|| (key.keyCode > 47 && key.keyCode < 57) // 1-> 9
|| (key.keyCode > 95 && key.keyCode < 106))// 1-9 (numpad)
if (this.query && this.query.length > 1) {
this.divMustBeShow = true;
this.listToBuild = this.filterFunction(this.query, this.originalMap, this.userLanguage);
}
else {
this.divMustBeShow = true;
this.listToBuild = this.filterFunction("", this.originalMap, this.userLanguage);
}
}
html of component recursive-tree-view :
<li *ngFor="let treeNode of treeNodeDisplay.getChildren(); let x = index;" style="cursor: default;">
<div *ngIf="!treeNode.canBeClickable()">
{{treeNode.getLabel()}}
</div>
<div *ngIf="treeNode.canBeClickable()">
<a #item (click)="select(treeNode.getId())" >
{{treeNode.getLabel()}} </a>
</div>
<div *ngIf="nodeHasChildren(treeNode)">
<recursive-tree-view [treeNodeDisplay]="treeNode" (selectValueEvent)="select($event)" > </recursive-tree-view>
</div>
</li>
</ul>
in the component, i want to have of list of all (thus a list of #item)
#ViewChildren(forwardRef(() => "item"))
itemsList: QueryList<ElementRef>;
setDownListFocus() {
if (this.lineCounter < this.itemsList.toArray().length) {
if (this.lineCounter > 0) { // one item is already selected
//unselected previous element
this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter - 1].nativeElement, 'font-weight', 'normal');
}
this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter].nativeElement, 'font-weight', 'bold');
this.lineCounter++;
}
}
setUpListFocus() {
if (this.lineCounter > 0) {
this.lineCounter--;
this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter - 1].nativeElement, 'font-weight', 'bold');
this._renderer.setElementStyle(this.itemsList.toArray()[this.lineCounter].nativeElement, 'font-weight', 'normal');
}
}
lineCounter is set to 1 in ngOnInit of recursive component
the display result is :
..... (input text)
node 1
result1 => the first element must be in bold
result2
node2
result3
result4
result5
when the user press arrowDown key , the first element(thus result1) must have font normal and the second (thus result2) must be in bold
Next if the user press again arrowDown key , the second element (result2) must be normal and the hirs element (result 3) must be in bold
next if the user press upDown key , the third element (result3) must be normal and the second element must be in bold.
The element node cannot be in bold
#ViewChildren() only works for direct children.
A workaround would be a shared service where each treeNode registers itself when it is created and removes itself in ngOnDestroy.
The service can't be registered on a treeNode otherwise each treeNode would get its own instance. It has to be a parent of the root node or the root module.

Simplest way to add one class or another

With Handlebars, what's the simplest way to add one class or another to each element being rendered by an {{#each ...}} helper? I have to integrate with an existing CSS setup for a site, which requires adding one class or another to alternating elements in a list.
Example helper:
{{#each items}}
<div class="{{what here?}}">...</div>
{{/each}
...where we want even or odd as the class names. (Yes, again, I know this can be done with CSS; I'm integrating with an existing site's CSS, which uses alternating classes instead.)
As a Handlebars newbie, I'm not seeing anything built-in, but the API makes it pretty easy to add a helper that lets you select from an arbitrary-length list of items, like this:
Handlebars.registerHelper('cycle', function(index) {
index = index % (arguments.length - 2); // -2 to leave out `index` and the final argument HB adds
return arguments[index + 1];
});
Using that it would be:
{{#each items}}
<div class="{{cycle #index 'even' 'odd'}}">...</div>
{{/each}
Handlebars.registerHelper('cycle', function(index) {
index = index % (arguments.length - 2); // -2 to leave out `index` and the final argument HB adds
return arguments[index + 1];
});
var items = [
"one", "two", "three", "four", "five"
];
var template = Handlebars.compile(
document.getElementById("template").innerHTML
);
var html = template({items: items});
document.body.insertAdjacentHTML(
"beforeend",
html
);
.even {
color: blue;
}
.odd {
color: green;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.min.js"></script>
<script id="template" type="text/x-handlebars-template">
{{#each items}}
<div class="{{cycle #index 'even' 'odd'}}">{{this}}</div>
{{/each}}
</script>
Or if I wanted three classes in rotation:
{{#each items}}
<div class="{{cycle #index 'one' 'two' 'three'}}">...</div>
{{/each}
Handlebars.registerHelper('cycle', function(index) {
index = index % (arguments.length - 2); // -2 to leave out `index` and the final argument HB adds
return arguments[index + 1];
});
var items = [
"one", "two", "three", "four", "five"
];
var template = Handlebars.compile(
document.getElementById("template").innerHTML
);
var html = template({items: items});
document.body.insertAdjacentHTML(
"beforeend",
html
);
.one {
color: blue;
}
.two {
color: green;
}
.three {
color: red;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.min.js"></script>
<script id="template" type="text/x-handlebars-template">
{{#each items}}
<div class="{{cycle #index 'one' 'two' 'three'}}">{{this}}</div>
{{/each}}
</script>

Change color every other row with $.each

I am making a golf leaderboard and want to change the color on every other row to be slightly grey... How do I do that?
Here is how I get the leaderboard using ajax:
$.get("http://mypage.com/json/getleaderboard.php", function(data) {
var output = '';
output += '<li class="leaderboard-head"><span class="leaderboard-head-placement"> </span><span class="leaderboard-name tr" key="name">Name</span><span class="leaderboard-head-points">P</span></li>';
$.each(data, function (i, val) {
output += '<li><span class="leaderboard-placement">' + val.placement + '</span><span class="leaderboard-name">' + val.name + '</span><span class="leaderboard-points">' + val.points + '</span></li>';
});
$('#leaderboardList').append(output).listview('refresh');
}, "json");
hoping for help and thanks in advance :-)
You can use the nth-child selector. e.g.
<ul class="leaderboard">
<li class="leaderboard-head">1</li>
<li class="leaderboard-head">2</li>
<li class="leaderboard-head">3</li>
<li class="leaderboard-head">4</li>
<li class="leaderboard-head">5</li>
<li class="leaderboard-head">6</li>
</ul>
CSS
.leaderboard-head:nth-child(odd){ // Odd/Even according to your requirements
background-color: gray;
}
Note that this will only work in CSS3 compatible browsers. For others you can use :
$(".leaderboard").children(":nth-child(odd)").each(function(){ // Odd/Even according to your requirements
$(this).css("background", "gray");
});
FIDDLE
You can remove the css/jquery and it will still work.
Simple, you use CSS and do (assuming there is a class leaderboard-entry):
li.leaderboard-entry {
background-color: #efefef;
}
li.leaderboard-entry:nth-child(even) {
background-color: #afafaf;
}
No JavaScript required.
On a more general note, your code should read
$.get("http://mypage.com/json/getleaderboard.php")
.done(function(data) {
$('<li class="leaderboard-head">' +
'<span class="leaderboard-head-placement"> </span>' +
'<span class="leaderboard-name tr" key="name">Name</span>' +
'<span class="leaderboard-head-points">P</span>' +
'</li>'
).appendTo('#leaderboardList');
$.each(data, function (i, val) {
$('<li class="leaderboard-entry">')
.append($('<span class="leaderboard-placement">', {text: val.placement}))
.append($('<span class="leaderboard-name">', {text: val.name}))
.append($('<span class="leaderboard-points">', {text: val.points}))
.appendTo('#leaderboardList');
});
$('#leaderboardList').listview('refresh');
});
Don't create HTML by concatenating arbitrary strings. This is the single source of cross site scripting vulnerabilities (and blown markup).
Also, declaring the request type ("json") in jQuery is superfluous if the server sends JSON and sets the correct Content-Type header.
if you sway to do using jquery rather than css (good one)
$.get("http://mypage.com/json/getleaderboard.php", function(data) {
var output = '';
output += '<li class="leaderboard-head"><span class="leaderboard-head-placement"> </span><span class="leaderboard-name tr" key="name">Name</span><span class="leaderboard-head-points">P</span></li>';
$.each(data, function (i, val) {
var color_style_class = 'blue';
if (i % 2 == 0)
{
color_style_class = 'green';
}
else
{
color_style_class = 'red';
}
output += '<li><span class="leaderboard-placement ' + color_style_class + '">' + val.placement + '</span><span class="leaderboard-name">' + val.name + '</span><span class="leaderboard-points">' + val.points + '</span></li>';
});
$('#leaderboardList').append(output).listview('refresh');
}, "json");
define new style for 'blue' , 'green' and 'red' or whatever you like

Resources