Search code examples
javascriptjqueryhtmlcssjquery-knob

Weird behaviour on mousedrag, javascript


So I am using knob.js to create two dials, one inside another. The Outer dial represents the cumulative rating of a book, i.e. the average of all the ratings. This outer dial has data-readOnly="true" and it's value is visible at the common center of these dials. The inner dial is for me(a user) to submit his rating for that book. Thus, the inner dial value can be changed by me(a user).

<div class="demo_sub_outer">
    <input class="knob" data-thickness=".1" data-width="150" data-height="150" data-angleOffset=0 data-displayInput="true" data-angleArc=360 data-fgColor="#209652" data-bgColor="#eee" data-inputColor="" data-readOnly="true" value="{{ u_list.cum_attr_ratings.sexy }}">
</div>

<div class="demo_sub" id="demo_sub_1">
    <input class="knob" id="sexy" data-thickness="0.5" data-width="130" data-height="130" data-angleOffset=0 data-displayInput="false" data-angleArc=360 data-fgColor="#b8dcc7" data-bgColor="#e5e5e5" value="{{  u_list.attr_ratings.sexy }}" Title="Cumulative wealthiness" >
</div>

The way I want it to work is, when i change the inner dial value (i.e. when i rate a book, or change my rating for a book) the outer dial value (cumulative rating) should be updated accordingly.

Here's how I tried to do this... jsFiddle

Now this works fine if i change the inner dial value by clicking somewhere on the dial, but if i change this value by dragging mouse... results are unexpected. What could possibly be the reason for this weird behaviour.

EDIT: In the demo at jsFiddle , I have assumed that 3 other users have rated this book 80/100 ...


Solution

  • From what I understand, your issue is linked to the fact that you use the same change callback for both knobs.

    $(function($) {
        var prev_ratings = [80, 80, 80]
    
        $('.outer-knob').knob();
        $(".inner-knob").knob({
                var new_ratings = prev_ratings;
                new_ratings.push(+$('.inner-knob').val());
    
                var sum = new_ratings.reduce(function(acc, v) { return acc + v }, 0)
                $('.outer-knob').val(sum / new_ratings.length);
    
               // code with some output is available on jsfiddle below
            },
        });
    });
    

    I updated your fiddle with the following points :

    • different initialization for the knobs
    • the previous ratings are now in an array for easing testing
    • simplify the computation of the new ratings

    http://jsfiddle.net/uHkN5/16/

    I used the reduce method on array to do the actual rating computation, you can find some documentation on mdn if you are not familiar with it : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

    You will still have to figure out how to send the new rating to your backend however.