JSFiddle - React, Tailwind, and code Playground

by _nderscore

HTML

<script type="text/javascript">
mixconfig = {
    max_parts: 6,
    flavors: [ 
        /* Add a * to the beginning of a flavor name to mark it as out of stock */
        'Unflavored',
        'Apple',
        'Banana',
        'Corn',
        'Donut',
        'Egg',
        '*Fart',
        'Gopher',
        'Ham'
    ]
};
</script>
<style type="text/css">
  @import url(/themix/themix.css);
</style>
<div id="themix">
    <div>
        <b>Add a flavor: </b> 
        <select id="flavors"></select> 
        <a class="button" id="mixadd">Add</a>
    </div>
    <div class="mixlabel"><b>Current mix:</b></div>
    <ul id="mix">
    </ul>
    <div>
        <b>Current parts:</b> 
        <span id="parts">0/0</span>
    </div>
</div>
<script type="text/javascript" src="/themix/themix.js"></script>
<p>
    Product Description Here
</p>

CSS

/* 
   The Mix
   Copyright 2013 Jim Herrero
   This copy is licensed for use only on dbliquids.com
*/
#mix { 
    padding: 0;
    margin: 0;
    list-style: none; }
#mix li {
    font-size: 14px;
    padding: 5px 0; }
.mixbtn {
    border: 1px solid #e0e0e0;
    background: #999999;
    border-radius: 14px;
    padding: 5px 10px;
    text-decoration: none;
    color: #fff;
    font-weight: bold; }
.addbtn {  }
.subbtn {  }

JavaScript

/* 
   The Mix
   Copyright 2013 Jim Herrero
   This copy is licensed for use only on dbliquids.com
*/
(function(){

    var hiddenoption = $('[id*="option-"]:contains("Mix:")').css('display','none'),
        flavorlist = $('#flavors'),
        partcounter = $('#parts'),
        size = 0,
    	buckets = {
            toString:function(){
      			var output = '';
				for(var i in this) 
                    if(i != 'toString' && this[i] > 0) 
                        output += this[i] +'x '+ i +';\r\n';
          		return output;
    		}
        },
        updateCounter = function(){
            partcounter.text(size +'/'+ mixconfig.max_parts);
        };

    updateCounter();
    $('#themix').insertBefore(hiddenoption);
    
    for(var i = 0, l = mixconfig.flavors.length; i < l; i++){
        var flav = mixconfig.flavors[i];
        buckets[flav] = 0;
        flavorlist.append(
            flav.substr(0,1)=='*'?
            '<option disabled>'+flav.replace(/^\*/,'')+' (Out of Stock)</option>':
            '<option>'+flav+'</option>'
        );
    }

    $('#mixadd').bind('click',function(){
        var selection = flavorlist.find('option:selected'); 
        if(selection.length){
            if(size == mixconfig.max_parts) return alert('Too many parts!');
            var val = selection.text();
            if(!buckets[val])
                $('#mix').append(
                    '<li><a href="javascript:;" class="button subbtn">-</a> '+
                    val+' (<span class="mixamt">1</span>) <a href="javascript:;" '+
                    'class="button addbtn">+</a></li>'
                );
            buckets[val]++;
            $('#mix li:contains('+val+') .mixamt').text(buckets[val]);
            size++;
            updateCounter();
          if(size == mixconfig.max_parts)
			hiddenoption.find('textarea').val(buckets.toString());
        }
    });
       
    $('.subbtn').live('click',function(){
        $this = $(this);
        var val =...