VP3 Slider - Prototype #1

Client-side

by davidhong

HTML

<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.css">
<script src="http://code.jquery.com/mobile/1.0/jquery.mobile-1.0.min.js"></script>
<script src="http://jquery-json.googlecode.com/files/jquery.json-2.2.min.js"></script>
<script src="https://raw.github.com/cowboy/jquery-throttle-debounce/v1.1/jquery.ba-throttle-debounce.min.js"></script>
<meta name="viewport" content="width=device-width,initial-scale=1">

<div id="home" data-role="page">
    <header data-role="header"><h1>My Shopping Bag</h1></header>
    
    <div data-role="content">
        <div class="product">
            <h1>Apple iPhone 4S 32gb</h1>
            <img src="http://images.freshnessmag.com/wp-content/uploads//2011/10/summary.png">
            <div>Discover the features and specifications that set the Apple iPhone 4S 64GB White apart from other mobile phones. It's your ticket to a world of information and entertainment via the Telstra network.</div>
            
            <form action="/echo/json" method="post">
                <div class="ui-grid-a">
                    <div class="ui-block-a">
                        <input type="text" name="pay" id="pay" value="0" />
                    </div>
                    <div class="ui-block-b">
                        <input type="text" name="points" id="points" value="22000" step="10" />
                    </div>
                </div>
                <div data-role="field-contain">
                    <input type="range" 
                           name="vp3" id="vp3" value="22000" 
                           min="13100" max="22000" 
                           data-min-cpp="0.0043" data-max-cpp="0.0063" />                  
                </div>
                
                <input type="hidden" name="awardid" value="202081">                
                <button type="button" data-role="button">Buy</button>
            </form>
        </div>
    </div>
</div>

CSS

.product img { width: 100%; }
.product div { margin: 1em 0; }
.product .ui-grid-a input { width: 80%; }
.product .ui-block-a input { float: left; }
.product .ui-block-b input { float: right; }
input.ui-slider-input { display:none !important; }

JavaScript

var VP3 = (function() {
    var getPayFromPoints = function(minCpp, maxCpp, points, max) {
        var cpp = 0,
            cost = max * maxCpp,
            delta, G;

        if (maxCpp === minCpp) {
            cpp = maxCpp;
        } else {
            delta = max / (maxCpp - minCpp);
            G = (delta * minCpp);
            cpp = (points + G) / delta;
        }

        return cost - (points * cpp);
    };

    var getPointsFromPay = function(minCpp, maxCpp, pay, max) {
        var cpp = 0,
            cost = max * maxCpp,
            delta, G;

        // CPP is the same, so points calculation requires little maths
        if (maxCpp === minCpp) {
            cpp = maxCpp;
            return (cost - pay) / cpp;
        }

        // Calculate the delta
        delta = max / (maxCpp - minCpp);
        G = (delta * minCpp);

        return ((-1 * G) + Math.sqrt(Math.pow(G, 2) - 4 * 1 * delta * (pay - cost))) / 2;
    };

    // Variables w/o suffix represent points
    return function(min, max, minCpp, maxCpp, points) {
        if (points === 0 || points < min) {
            points = min;
        }

        if (points > max) {
            points = max;
        }

        var delta = (points - min) * 100 / (max - min),
            exactPay = getPayFromPoints(minCpp, maxCpp, points, max),
            roundedPay = Math.ceil(exactPay),
            exact = getPointsFromPay(minCpp, maxCpp, roundedPay, max);

        if (points === min || exact < min) {
            roundedPay = Math.ceil(exactPay);
            exact = min;
        }

        return {
            percent: delta,
            pay: roundedPay,
            points: Math.round(exact)
        };
    };
}());

//
// VP3 update function
var update = function(event) {    
    var $input = $(this),
        $product = $input.parents('.product'),
        data = $input.data(),
        points = ~~$input.val(),
        min = ~~$input.attr('min'),
        max = ~~$input.attr('max'),
        vp3 = VP3(min, max,...