0

Trying to replace the stroke colour of a percentage circle for each item rendered in django project. So far, I have only managed to change the colour to red. I suspect this is because it is changing them all based on the first/last record(percentage) retrieved.

Is there a way to iterate through each item in jQuery so that the stroke colour will change per item?

jQuery:

$(function() {
        var score = parseInt($("#percentage").text());
        if (score <=40) {
            $("path").css("color", "red")
        } else if (score >=40) {
            $("path").css("color", "green")
        }
    });

HTML:

{% extends "base.html" %}
{% load bootstrap_tags %}
{% load staticfiles %}

{% block head_js %}
    <script src="{% static "js/percentage.js" %}"></script>
{% endblock %}

{% block content %}
            {% for statistic in statistics %}
            <div class="stat_img">
                <img width="100%" src="/media/{{statistic.image}}">
            </div>
                <span id="percentage">{{statistic.percentage}}</span>
            <div class="stat_ranking">
                <span class="stat_title">{{statistic.title}}&nbsp;({{statistic.year}})</span>
                <br>
                <svg viewbox="0 0 36 36" class="circular-chart">
                    <path class="circle" stroke-dasharray="{{statistic.percentage}}, 100"
                          d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831
                          a 15.9155 15.9155 0 0 1 0 -31.831"/>
                        <text x="50%" y="40%" text-anchor="middle" dy=".3em">{{statistic.percentage}}%</text>
                        <text class="blue" x="50%" y="55%" text-anchor="middle" dy=".3em">{{statistic.rating}}</text>
                </svg>
            </div>

            <div class="statistics">
                    Genre: {{statistic.genre}} <br>
                    Box Office: ${{statistic.box_office}} <br>
                    Budget: ${{statistic.budget}}
            </div>
            <hr>
            {% endfor %}

{% endblock %}

2 Answers2

0

It is probably because you're using text instead of val.

Try:

$('#button1').click(function() {
        var score = $("#percentage").val();
        //score = parseInt(score);
        if (score <=40) {
            $("#path").css("color", "red")
        } else if (score >=40) {
            $("#path").css("color", "green")
        }
    });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" id="percentage">
<button type="button" id="button1">Click Me!</button>
<div id="path">
 test
</div>

Here's an awesome thread on the difference between text() and val().

almost a beginner
  • 1,622
  • 2
  • 20
  • 41
0

you are using the # to refer to elements by their id attribute, which has to be unique in the DOM. If you have multiple elements with the same id, jQuery will use the last one. Also you refer to all path elements when you assign the color.

If you have multiple percentage fields and path elements, you should number them when you create your DOM (you can use forloop.counter or forloop.counter0 in Django templates). Wrap each statistic in a row element to which you assign a unique id and change the id "percentage" in the loop to a class:

{% for statistic in statistics %}
    <div id="statistic{{ forloop.counter0 }}" class="statistic_row">
        <span class="percentage">{{statistic.percentage}}</span>
        <!-- some code -->
        <svg>
            <path class="circle"><!-- some code --></path>
        <svg>
    </div>
{% endfor %}

Then you can also do a loop in your JS (I assigned a class "percentage" so we have a number of elements to refer to)

$(function() {
    for (var i=0; i<$(".statistic_row").length(); i++) {
        var $statistic_row = $("#statistic" + i);
        var score = parseInt($statistic_row.find('.percentage').text());
        if (score <= 40) {
            $statistic_row.find('path').css("color", "red")
        } else if (score >= 40) {
            $statistic_row.find('path').css("color", "green")
        }
    }
});

EDIT: Actually, you can even do it without a counter because you have the percentage value within the svg path:

$(function() {
    // loops through all <path> elements with the class 'circle'
    $('path.circle').each(function() {
        // $(this) refers to the current <path> element
        // gets the text value of the first <text> child element
        var score = parseInt($(this).siblings('text').first().text());
        var color = 'red';
        if (score >= 40) {
            color = 'green';
        }
        // set the color of the current element
        $(this).css('stroke', color);
    }
});

Here's a fiddle: https://jsfiddle.net/hmgodtpa/4/

EDIT: You could also do it without JS:

<path class="circle {% if statistic.percentage >= 40 %}good{% else %}bad{% endif %}" stroke-dasharray="{{statistic.percentage}}, 100"
                      d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831
                      a 15.9155 15.9155 0 0 1 0 -31.831"/>

and style CSS classes for .good and .bad

masterfloda
  • 2,908
  • 1
  • 16
  • 27
  • Hey, this is what I am looking for :) and it should work, the only thing I had to change was `$(this).css('stroke', colour);` but for whatever reason it is still only applying the initial color variable to all instances and seems to be ignoring the if statement... – Andrew Fillary Aug 04 '17 at 17:19
  • Ah, sorry. I haven't testet the code :-) `text` is not a child of `path`, so of course `find()` wouldn't get it. Instead you need to use `siblings`... Updated my answer. – masterfloda Aug 04 '17 at 17:53
  • Just out of curiosity: Is there a reason why you want to do the coloring with JS? It's simpler to just add a class in the Django template and then style it with CSS. – masterfloda Aug 04 '17 at 18:05
  • It's alive! Thanks a lot :) I wanted to do it this way for a couple of reasons. To keep the CSS & HTML a little bit tidier and more importantly it's a requirement for the project that I use some JS. Good to know you can do if statements within an attribute though, you learn something new everyday! – Andrew Fillary Aug 04 '17 at 19:00