JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

Clothing preview test. 
<button id='randomise'>Randomise!</button>
<br><br>

<div id='options'>Dropdowns here...</div>

<div id='preview'>Layers here...</div>

<span id='info'>Description here...</span>

CSS

#preview {margin: 20px auto;position:relative;width:400px;height:300px;border:1px solid green;}
#preview img {position:absolute;top:0px;left:0px;}

.pink {filter: invert(39%) sepia(83%) saturate(666%) hue-rotate(284deg) brightness(94%) contrast(91%);}
.slate {filter: invert(60%) sepia(34%) saturate(240%) hue-rotate(184deg) brightness(92%) contrast(94%);}
.red {filter: invert(29%) sepia(89%) saturate(3528%) hue-rotate(345deg) brightness(107%) contrast(80%);}
.brown {filter: invert(54%) sepia(22%) saturate(1039%) hue-rotate(333deg) brightness(93%) contrast(90%);}
.orange {filter: invert(53%) sepia(34%) saturate(3679%) hue-rotate(1deg) brightness(96%) contrast(104%);}
.peach {filter: invert(68%) sepia(49%) saturate(449%) hue-rotate(326deg) brightness(103%) contrast(98%);}
.olive {filter: invert(71%) sepia(80%) saturate(425%) hue-rotate(21deg) brightness(90%) contrast(101%);}
.gold {filter: invert(80%) sepia(77%) saturate(5230%) hue-rotate(1deg) brightness(105%) contrast(102%);}
.green {filter: invert(58%) sepia(83%) saturate(544%) hue-rotate(65deg) brightness(94%) contrast(94%);}
.blue {filter: invert(84%) sepia(29%) saturate(5255%) hue-rotate(136deg) brightness(96%) contrast(95%);}
.teal {filter: invert(65%) sepia(79%) saturate(281%) hue-rotate(118deg) brightness(87%) contrast(86%);}
.indigo {filter: invert(35%) sepia(88%) saturate(3359%) hue-rotate(214deg) brightness(99%) contrast(95%);}
.silver {filter: invert(60%);}
.black {filter: invert(15%);}
.white {filter: invert(95%);}

JavaScript

let path = "http://griffusion.elementfx.com/demo/attire/";

let terms = {
    colours: ["blue","green","red","gold","orange","peach","brown","silver","black","white","olive","pink","indigo","slate","teal"],
    
    baseTypes: ["cloak","boots","scarf"],
    
    patternTypes: ["stripes","spots","stars"],
    
    decorTypes: ["trim","ribbon","tassels"],
    
    // Handy template to clone.
    blank: {bC: 1, bT: 1, pC: 1, pT: 0, dC: 1, dT: 0},
    
    // Deep-clone that blank wearable object.
    getBlank: function(){
        return Object.assign({}, terms.blank);
    },
    
    getColourName: function(n){
        if(n < 1 || n > terms.colours.length){
            throw "terms.getColourName(): invalid number, " + n;
        }
        return terms.colours[n - 1];
    },
    getBaseType: function(n){
        if(n < 1 || n > terms.baseTypes.length){
            throw "terms.getBaseType(): invalid number, " + n;
        }
        return terms.baseTypes[n - 1];
    },
    getPatternType: function(n){
        if(n < 1 || n > terms.patternTypes.length){
            throw "terms.getPatternType(): invalid number, " + n;
        }
        return terms.patternTypes[n - 1];
    },
    getDecorType: function(n){
        if(n < 1 || n > terms.decorTypes.length){
            throw "terms.getDecorType(): invalid number, " + n;
        }
        return terms.decorTypes[n - 1];
    },
    
    
};

let wearables = [];


renderDropdowns();

let demo = {
    bC: 1,
    bT: 1,
    pC: 3,
    pT: 1,
    dC: 4,
    dT: 1
};

renderWearable(demo);
getDescription(demo);
updateDropdowns(demo);

function renderWearable(w){
    let html = "<img src='" + path + "base.png'>";
    
    if(w.bT == 0){
        $("#preview").html(html);
        return;
    }
    
    let bCol = terms.getColourName(w.bC);
    let bType = terms.getBaseType(w.bT);
    
    html += "<img src='" + path + bType + ".png' class='" + bCol + "'>";
    
    if(w.pT > 0){
        let pCol = terms.getColourName(w.pC);
     ...