Calling initialization function inside ng-repeat - javascript

I am trying to call ng-init function inside ng-repeat and it only works only on the first element:
<li ng-repeat="comment in ad.comments|limitTo:quantity | orderBy : sortComment : true">
<div id="starsDiv" ng-init="orderComment(comment.stars)"></div>
Comment: {{comment.text}}
<cite class="clearfix"> on {{comment.posted | date}}</cite>
</li>
The orderComment inside ng-repeat function needs to init the starDiv:
$scope.orderComment= function(numOfStars){
var html = '<i class="fa fa-star-o" style="color:gold;"></i>';
for(var i =0 ; i<numOfStars-1;i++)
{
html += '<i class="fa fa-star-o" style="color:gold;"></i>';
}
document.getElementById("starsDiv").innerHTML = html;
};
Injecting HTML to the starsDiv by the value of comment.stars.
For instance if comment equals 4 there will be 4 HTML elements of :
'<i class="fa fa-star-o" style="color:gold;"></i>'
inside it.

In general, Angular discourages making changes in the DOM on your own, and in this case it's not necessary.
A simple solution might be to put in the maximum amount of possible stars and using ng-show to show only the amount we need. Assuming there are 5 stars:
<i class="fa fa-star-o" style="color:gold;" ng-show="comment.stars > 0"></i>
<i class="fa fa-star-o" style="color:gold;" ng-show="comment.stars > 1"></i>
<i class="fa fa-star-o" style="color:gold;" ng-show="comment.stars > 2"></i>
<i class="fa fa-star-o" style="color:gold;" ng-show="comment.stars > 3"></i>
<i class="fa fa-star-o" style="color:gold;" ng-show="comment.stars > 4"></i>
If you need a general solution, you can always use ng-repeat. You simply need a function that will take a number and return an array of that size. You can use the array like this.
<i class="fa fa-star-o" style="color:gold;" ng-repeat="x in array(comment.stars)"></i>
An even more general solution would be to create a custom directive that renders these stars. I recommend reading about custom directives: https://docs.angularjs.org/guide/directive

Related

How to find the count of a particular class with a particular style is repeated in a HTML Page

I have a html page, where I have two div classes :
<i class="fas fa-info-circle float-left resultsInfo" style="color: red; padding-top: 4px;" ></i>
<i class="fas fa-info-circle float-left resultsInfo" ></i>
On Page load, I need to get the count of how many times these each Div has been repeated. The only differentiating factor between these two div is the style. So I wanted to know how many times the first div oocured and how many times the second one. Please help me to find this out. I am new to HTML and js
I think the easiest way is this:
<html>
<body>
<p id="demo"></p>
<ul>
<i class="count fas fa-info-circle float-left resultsInfo" style="color: red; padding-top: 4px;" ></i>
<i class="count fas fa-info-circle float-left resultsInfo" ></i>
</ul>
</body>
</html>
and js is lookin like
document.getElementById("demo").innerHTML = "count: " + document.querySelectorAll('.count').length;
here is the example: https://jsfiddle.net/f7tsLcrd/
This snippet returns the number of elements that have a "count" class and red color
$(".count").filter(function() {
return ($(this).prop('style').color == 'red');
}).length

Change all font awesome 5 icons with a specific class to another FA icon - JS/SVG

Lets say i have 3 FA icons:
<i class="fas fa-circle"></i>
<i class="fas fa-circle"></i>
<i class="fas fa-circle"></i>
I want to change all of those to:
<i class="far fa-circle"></i>
<i class="far fa-circle"></i>
<i class="far fa-circle"></i>
This means i am modifying all of the prefix of those icons so that they change from solid to regular.
Before in FA 4.X i could just get all icons by their class name and switch their classes like so:
var icons = $(".icon");
icons.removeClass("fa-circle");
icons.addClass("fa-circle-o");
But now that they are SVG's i don't know how i can get them all and change their prefix.
I know i can change the prefix like so:
if (prefix === 'fas') {
icon.attr('data-prefix', 'far');
icon.css({ color: "#d6d6d6" });
} else {
icon.attr('data-prefix', 'fas');
icon.css({ color: "#3fcf8e" });
}
I just need to know how to get all of the icons so i can just loop through them and change their prefix.
As far as I understand…
You can always do it using your code, you just need to replace fas to far:
var icons = $(".icon");
icons.removeClass("fas");
icons.addClass("far");
// Note that this could be simplified to:
// icons.toggleClass('far fas');
<script defer src="https://use.fontawesome.com/releases/v5.2.0/js/all.js" integrity="sha384-4oV5EgaV02iISL2ban6c/RmotsABqE4yZxZLcYMAdG7FAPsyHYAPpywE9PJo+Khy" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
fas: <i class="fas fa-circle"></i>  
far: <i class="far fa-circle"></i>
<br><br>
<i class="icon fas fa-circle"></i>
<i class="icon fas fa-circle"></i>
<i class="icon fas fa-circle"></i>
Hope it helps.
I just realized that i can change the data-prefix attribute on everything with a specific class.
$(".icon").attr('data-prefix', 'far');

iterating through an array containing two elements results in three objects

I'm trying to iterate through an array and clone and append an element to a div element for each item in the array.
Everything is working except when it's more than one element I get some unexpected results.
The array contains two element's and I've checked that the each loop only runs two times, but for some reason I get a third element in the result.
Am I using clone() and appendTo() correctly?
each loop:
let items = $(contentWrap).find(".lc-rating-modal-review-items-wrap");
$(items).empty();
$.each(data.items, function (index, review) {
let item = GenerateReviewItem(review);
$(item).appendTo(items);
});
GenerateReviewItem:
function GenerateReviewItem(review) {
let result = $(wrap).find(".lc-rating-review-item-template").clone();
$(result).find(".lc-rating-review-item-template-date").html(review.dateFormated);
$(result).find(".lc-rating-review-item-body-wrap").html(review.review);
$(result).find(".lc-rating-review-item-template-stars-rating-label").html("(" + review.rating + ")");
$(result).find(".lc-rating-review-item-template-star").each(function (index, star) {
if (review.rating >= (index + 1)) {
$(star).removeClass("fa-star-o").addClass("fa-star");
}
});
return result;
}
Html to clone:
<div style="display:none;">
<div class="lc-rating-review-item-template">
<div class="lc-rating-review-item-header-wrap">
<div class="lc-rating-review-item-template-stars-wrap">
<div>
<i class="fa fa-star-o lc-rating-review-item-template-star" aria-hidden="true"></i>
</div>
<div>
<i class="fa fa-star-o lc-rating-review-item-template-star" aria-hidden="true"></i>
</div>
<div>
<i class="fa fa-star-o lc-rating-review-item-template-star" aria-hidden="true"></i>
</div>
<div>
<i class="fa fa-star-o lc-rating-review-item-template-star" aria-hidden="true"></i>
</div>
<div>
<i class="fa fa-star-o lc-rating-review-item-template-star" aria-hidden="true"></i>
</div>
<div>
<span class="lc-rating-review-item-template-stars-rating-label"></span>
</div>
</div>
<div style="text-align:right;">
<span class="lc-rating-review-item-template-date"></span>
</div>
</div>
<div class="lc-rating-review-item-body-wrap"></div>
</div>
</div>
I'd recommend storing the reference to your template node outside of your loop, and then doing the cloning inside of the loop.
Define this outside the loop:
let template = $(wrap).find(".lc-rating-review-item-template")
And then change this:
let result = $(wrap).find(".lc-rating-review-item-template").clone();
To this:
let result = template.clone();
As it is currently, when your loop executes a second time, $(wrap).find(".lc-rating-review-item-template") is likely finding two items instead of one.
It also appears that wrap, unless it is a global, is undefined within the context of the GenerateReviewItem(review) function.

How to pass a django variable from html page to javascript

My website has a sidebar that is the same on all pages. In order to avoid copying and pasting the html for the sidebar for every page I wrote some javascript as this answer suggested: How can I make my navi-bar the same across my html?
I am happy with these results except for one thing, my sidebar displays things like the users name, which I access with {{ request.user.get_full_name }}, but this does not work when I put that in my sidebar.js. So I thought a good work around would be to set a var user={{request.user.get_full_name}} in the <script> tags in my html file and then use <h3>user</h3> in my js, but I am not sure how to do that.
This is my sidebar.js
document.getElementById("navMenu").innerHTML =
'<div id="circle"><span class="glyphicon glyphicon-user"></span></div><h3>Your Name</h3>'+
'<ul class="nav nav-pills nav-stacked" style="text-align: left;">'+
'<li><i class="fa fa-home fa-fw" aria-hidden="true"></i> Home</li>'+
'<li><i class="fa fa-user fa-fw" aria-hidden="true"></i> Profile</li>'+
'<li><i class="fa fa-envelope fa-fw" aria-hidden="true"></i> Messages</li>'+
'<li><i class="fa fa-users fa-fw" aria-hidden="true"></i> Boards</li>'+
'<li><i class="fa fa-newspaper-o fa-fw" aria-hidden="true"></i> Feed</li>'+
'<li><i class="fa fa-globe fa-fw" aria-hidden="true"></i> Notifications</li>'+
'<li><label for="logout" style="font-size: 15px; font-weight: inherit;"><i class="fa fa-lock fa-fw" aria-hidden="true"></i> Logout</label></li>'+
'</ul>';
So in the second line where it has <h3>Your Name</h3> I want that to be the user variable. And this is how I am trying to pass the variable in my HTML page:
<div id="sidebar">
<nav id="navMenu"></nav>
<script src="{% static 'app/js/sidebar.js' %}">var user={{request.user.get_full_name}}</script>
<!-- logout button/form -->
<form action="/" method="post">
{% csrf_token %}
<input class="hidden" id="logout" type="submit" value="Logout"/>
</form>
</div>
I would like to avoid using PHP. The bottom line is can I use django like that inside the <script> tags and if so, how do I then use that variable in my javascript?
I can't find the reference, but I'm skeptical <script src="something.js"> can also have source within it. I've not seen it done that I can recall.
This should work, which is similar to what you are doing:
<script>
var user = '{{request.user.get_full_name}}'; // created by your django html
</script>
<script src="{% static 'app/js/sidebar.js' %}"></script>
And then in your sidebar.js you just need to do:
"....<h3>" + user + "<h3>..."
However, a cleaner way to do this would be to encapsulate your js into a function that takes the username as a parameter:
<script src="{% static 'app/js/sidebar.js' %}"></script>
Where your js is something like,
function sidebar(user) {
document.getElementById("navMenu").innerHTML = "....<h3>" + user + ";<h3>..."
}
Followed by:
<script>
sidebar('{{request.user.get_full_name}}'); // where this is created via your template.
</script>

Angular, how to set class to the clicked list item and remove from others li items?

I have this list where I'm trying to set class to the clicked list item (but class should be set only for clicked item).
I tried to do by this way but without luck:
<a href=""
ng-ctrl="ThemesCtrl"
ng-click="checkThemeContent(theme);"
ng-repeat="theme in themes"
ng-hide="theme[filterProp] !== filterValue"
class="list-group-item">
<b>{{theme.name}}</b>
<span class="themesListIcons">
<i class="fa fa-check-square-o"></i> {{theme.avg_score}}
<i class="fa fa-comment-o"></i> {{theme.count_of_cards}}
</span>
</a>
How can i do it please in the right way?
Thanks for any help.
Great.
Sorry because I have not plunker account, so I must explain you on theoretical way.
George, you have to create function in controller that selects your item, for an example, in your case:
$scope.checkThemeContent = function (name) {
$scope.selectedName = name;
}
After this step, you must only call this function in your HTML like this:
<a href=""
ng-class="{selected:theme.name==selectedName}"
ng-click="checkThemeContent(theme.name)"
ng-repeat="theme in themes"
class="list-group-item">
<b>{{theme.name}}</b>
<span class="themesListIcons">
<i class="fa fa-check-square-o"></i> {{theme.avg_score}}
<i class="fa fa-comment-o"></i> {{theme.count_of_cards}}
</span>
</a>
Please take look on ng-click part. You have to pass some property ('theme.name') of item (in your case 'theme') from list ('themes'), because you can't compare objects.
In ng-class you must also pass the same property as in ng-click.
Hope it helps.
you need change the syntax ng-class directive
<a href=""
ng-class="{'selected':$index==selectedIndex}"
ng-ctrl="ThemesCtrl"
ng-click="checkThemeContent(theme);currentTheme=theme"
ng-repeat="theme in themes"
ng-hide="theme[filterProp] !== filterValue"
class="list-group-item">
<b>{{theme.name}}</b>
<span class="themesListIcons">
<i class="fa fa-check-square-o"></i> {{theme.avg_score}}
<i class="fa fa-comment-o"></i> {{theme.count_of_cards}}
</span>
</a>
If the 'selectedIndex' is your scope variable that represents your selected item in the controller and the 'selected' is your CSS class, try to change the ng-class part like this:
ng-class="{selected: $index==selectedIndex}"

Categories