Märklin Decoder Dipswitch Settings

CSS jQuery Märklin
Input a decoder address and see the dipswitch positions for the Märklin Delta, Digital and Switch decoders.
Or change the dipswitch positions to see which decoder address it represents.

The HTML source code

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="https://www.vanderwaal.eu/favicon.ico" />

    <title>VDWWD - Märklin Decoder Dipswitch Settings</title>

    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">

</head>
<body style="background-color: #4b4d66" class="pt-4">

    <!-- van der Waal Webdesign -->
    <!-- https://www.vanderwaal.eu -->

    <div class="container bg-white" id="marklin_dipswitch_settings">

        <!-- demo content -->

        <div class="row">
            <div class="col-12 col-md-6 mx-auto text-center pt-4">

                <input autocomplete="off" class="form-control form-control-lg w-25 mx-auto decoder-address" id="decoder_address" maxlength="3" min="0" max="256" type="number">

            </div>
        </div>
        <div class="row">
            <div class="col-12 col-md-6 mx-auto text-center pt-4">

                <div class="dipswitch-container">

                    <div class="dipswitch dipswitch-delta" id="dipswitch_delta">
                        <div class="dipswitch-switches">
                        </div>
                        <div class="dipswitch-numbers">
                        </div>
                    </div>

                </div>

            </div>
        </div>
        <div class="row">
            <div class="col-12 col-md-6 mx-auto text-center pt-4">

                <div class="dipswitch-container">

                    <div class="dipswitch dipswitch-digital" id="dipswitch_digital">
                        <div class="dipswitch-switches">
                        </div>
                        <div class="dipswitch-numbers">
                        </div>
                    </div>

                </div>

            </div>
        </div>
        <div class="row">
            <div class="col-12 col-md-6 mx-auto text-center pt-4">

                <div class="dipswitch-container">

                    <div class="dipswitch dipswitch-switch" id="dipswitch_switch">
                        <div class="dipswitch-switches">
                        </div>
                        <div class="dipswitch-numbers">
                        </div>
                    </div>

                </div>

            </div>
        </div>

        <!-- footer -->

        <div class="row footer-row">
            <div class="col text-center pt-5 pb-3">

                <a target="_blank" href="https://www.vanderwaal.eu">
                    <img src="https://www.vanderwaal.eu/images/vdwwd.png" alt="van der Waal Webdesign" title="van der Waal Webdesign" width="300" height="95" />
                </a>

            </div>
        </div>

    </div>

    <!-- scripts -->

    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>

    <!-- vdwwd scripts and stylesheets -->

    <script src="marklin-decoder-dipswitch-settings.js"></script>
    <link href="marklin-decoder-dipswitch-settings.css" rel="stylesheet">

</body>
</html>

The CSS source code

#marklin_dipswitch_settings .dipswitch-container {
    display: inline-block;
    min-width: 445px
}

#marklin_dipswitch_settings .dipswitch {
    background-color: #000;
    padding: 10px !important;
    border: 3px solid silver;
    box-shadow: 3px 3px 3px rgba(0,0,0,.7);
    clear: both;
    line-height: 100%;
    display: inline-block;
    border-radius: 3px
}

#marklin_dipswitch_settings .dipswitch-switches div {
    margin: 5px;
    height: 66px;
    float: left;
    background-color: silver;
    border-bottom: 2px solid #e4e4e4;
    border-right: 2px solid #e4e4e4;
    border-top: 3px solid #404040;
    border-left: 3px solid #404040;
    padding: 2px
}

    #marklin_dipswitch_settings .dipswitch-switches div a {
        height: 22px !important;
        width: 22px !important;
        border: 1px solid #000;
        box-shadow: 2px 2px 2px #666 !important;
        cursor: pointer;
        display: block;
        text-decoration: none
    }

    #marklin_dipswitch_settings .dipswitch-switches div.off a {
        background-color: #bf1616;
        margin-top: 36px
    }

    #marklin_dipswitch_settings .dipswitch-switches div.on a {
        background-color: #308c07
    }

#marklin_dipswitch_settings .dipswitch-numbers div {
    margin: 8px 0 2px 0;
    width: 41px;
    float: left;
    color: #fff;
    font-weight: bold;
    text-align: center;
    font-family: Arial;
    font-size: 20px
}

#marklin_dipswitch_settings .address-not-available {
    opacity: .5
}

@media(max-width:575.98px) {
    #marklin_dipswitch_settings .dipswitch-container {
        min-width: 330px
    }

    #marklin_dipswitch_settings .dipswitch {
        padding: 3px !important;
        border: 2px solid silver;
        box-shadow: 3px 3px 3px #666
    }

    #marklin_dipswitch_settings .dipswitch-switches div {
        border-bottom: 1px solid #e4e4e4;
        border-right: 1px solid #e4e4e4;
        border-left: 2px solid #404040;
        border-top: 2px solid #404040;
        padding: 1px;
        height: 41px
    }

        #marklin_dipswitch_settings .dipswitch-switches div a {
            height: 16px !important;
            width: 16px !important;
            box-shadow: 1px 1px 1px #666 !important
        }

        #marklin_dipswitch_settings .dipswitch-switches div.off a {
            margin-top: 20px
        }

    #marklin_dipswitch_settings .dipswitch-numbers div {
        width: 31px;
        font-size: 16px;
        margin: 4px 0 2px 0
    }
}

The jQuery source code

var addresses_delta_adresses = [
    2, 6, 8, 18, 20, 24, 26, 54, 56, 60, 62, 72, 74, 78, 80
];

var addresses_delta_decoder = [
    '0111', '1011', '0011', '1101', '0101', '1001', '0001', '1110', '0110', '1010', '0010', '1100', '0100', '1000', '1111'
];

var addresses_digital_decoder = [
    '01101010', '00101010', '10011010', '01011010', '00011010', '10001010', '01001010', '00001010', '10100110', '01100110', '00100110', '10010110', '01010110', '00010110', '10000110', '01000110', '00000110', '10100010', '01100010', '00100010', '10010010', '01010010', '00010010', '10000010', '01000010', '00000010', '10101001', '01101001', '00101001', '10011001', '01011001', '00011001', '10001001', '01001001', '00001001', '10100101', '01100101', '00100101', '10010101', '01010101', '00010101', '10000101', '01000101', '00000101', '10100001', '01100001', '00100001', '10010001', '01010001', '00010001', '10000001', '01000001', '00000001', '10101000', '01101000', '00101000', '10011000', '01011000', '00011000', '10001000', '01001000', '00001000', '10100100', '01100100', '00100100', '10010100', '01010100', '00010100', '10000100', '01000100', '00000100', '10100000', '01100000', '00100000', '10010000', '01010000', '00010000', '10000000', '01000000', '10101010'
];

var addresses_switch_decoder = [
    "0110101011", "0110101001", "0110101010", "0110101000", "0010101011", "0010101001", "0010101010", "0010101000", "1001101011", "1001101001", "1001101010", "1001101000", "0101101011", "0101101001", "0101101010", "0101101000", "0001101011", "0001101001", "0001101010", "0001101000", "1000101011", "1000101001", "1000101010", "1000101000", "0100101011", "0100101001", "0100101010", "0100101000", "0000101011", "0000101001", "0000101010", "0000101000", "1010011011", "1010011001", "1010011010", "1010011000", "0110011011", "0110011001", "0110011010", "0110011000", "0010011011", "0010011001", "0010011010", "0010011000", "1001011011", "1001011001", "1001011010", "1001011000", "0101011011", "0101011001", "0101011010", "0101011000", "0001011011", "0001011001", "0001011010", "0001011000", "1000011011", "1000011001", "1000011010", "1000011000", "0100011011", "0100011001", "0100011010", "0100011000", "0000011011", "0000011001", "0000011010", "0000011000", "1010001011", "1010001001", "1010001010", "1010001000", "0110001011", "0110001001", "0110001010", "0110001000", "0010001011", "0010001001", "0010001010", "0010001000", "1001001011", "1001001001", "1001001010", "1001001000", "0101001011", "0101001001", "0101001010", "0101001000", "0001001011", "0001001001", "0001001010", "0001001000", "1000001011", "1000001001", "1000001010", "1000001000", "0100001011", "0100001001", "0100001010", "0100001000", "0000001011", "0000001001", "0000001010", "0000001000", "1010100111", "1010100101", "1010100110", "1010100100", "0110100111", "0110100101", "0110100110", "0110100100", "0010100111", "0010100101", "0010100110", "0010100100", "1001100111", "1001100101", "1001100110", "1001100100", "0101100111", "0101100101", "0101100110", "0101100100", "0001100111", "0001100101", "0001100110", "0001100100", "1000100111", "1000100101", "1000100110", "1000100100", "0100100111", "0100100101", "0100100110", "0100100100", "0000100111", "0000100101", "0000100110", "0000100100", "1010010111", "1010010101", "1010010110", "1010010100", "0110010111", "0110010101", "0110010110", "0110010100", "0010010111", "0010010101", "0010010110", "0010010100", "1001010111", "1001010101", "1001010110", "1001010100", "0101010111", "0101010101", "0101010110", "0101010100", "0001010111", "0001010101", "0001010110", "0001010100", "1000010111", "1000010101", "1000010110", "1000010100", "0100010111", "0100010101", "0100010110", "0100010100", "0000010111", "0000010101", "0000010110", "0000010100", "1010000111", "1010000101", "1010000110", "1010000100", "0110000111", "0110000101", "0110000110", "0110000100", "0010000111", "0010000101", "0010000110", "0010000100", "1001000111", "1001000101", "1001000110", "1001000100", "0101000111", "0101000101", "0101000110", "0101000100", "0001000111", "0001000101", "0001000110", "0001000100", "1000000111", "1000000101", "1000000110", "1000000100", "0100000111", "0100000101", "0100000110", "0100000100", "0000000111", "0000000101", "0000000110", "0000000100", "1010100011", "1010100001", "1010100010", "1010100000", "0110100011", "0110100001", "0110100010", "0110100000", "0010100011", "0010100001", "0010100010", "0010100000", "1001100011", "1001100001", "1001100010", "1001100000", "0101100011", "0101100001", "0101100010", "0101100000", "0001100011", "0001100001", "0001100010", "0001100000", "1000100011", "1000100001", "1000100010", "1000100000", "0100100011", "0100100001", "0100100010", "0100100000", "0000100011", "0000100001", "0000100010", "0000100000", "1010010011", "1010010001", "1010010010", "1010010000", "0110010011", "0110010001", "0110010010", "0110010000"
];

var $decoder_address;
var $dipswitch_delta;
var $dipswitch_digital;
var $dipswitch_switch;
var default_delta;
var default_digital;
var default_switch;
var class_notavailable;
var class_on;
var class_off;
var attr_onoff;

setTimeout(function () {

    //check if there are dipswitches
    if ($('#marklin_dipswitch_settings').length) {
        initDipSwitches();
    }
}, 50);


//start the dipswitches
function initDipSwitches() {
    $dipswitch_delta = $('#dipswitch_delta');
    $dipswitch_digital = $('#dipswitch_digital');
    $dipswitch_switch = $('#dipswitch_switch');
    $decoder_address = $('#decoder_address');
    default_delta = '0000';
    default_digital = '00000000';
    default_switch = '0000000000';
    class_notavailable = 'address-not-available';
    class_on = 'on';
    class_off = 'off';
    attr_onoff = 'onoff';

    //add switches to the container
    addDipSwitches($dipswitch_delta, default_delta.length);
    addDipSwitches($dipswitch_digital, default_digital.length);
    addDipSwitches($dipswitch_switch, default_switch.length);

    //on manual decoder address input text
    $decoder_address.on('keyup', function () {
        calculateDipSwitchFromAddress();
    });

    //on manual decoder address input arrows
    $decoder_address.on('change', function () {
        calculateDipSwitchFromAddress();
    });

    //delta dipswitch click
    $dipswitch_delta.find('a').on('click', function () {
        var $this = $(this);

        setDipSwitch($this, $this.parent().hasClass(class_off));
        calculateAddressFromDipSwitch($this);

        //set other switched to off
        processDipSwitchAddress(default_digital, $dipswitch_digital);
        processDipSwitchAddress(default_switch, $dipswitch_switch);

        return false;
    });

    //digital dipswitch click
    $dipswitch_digital.find('a').on('click', function () {
        var $this = $(this);

        setDipSwitch($this, $this.parent().hasClass(class_off));
        calculateAddressFromDipSwitch($this);

        //set other switched to off
        processDipSwitchAddress(default_switch, $dipswitch_switch);
        processDipSwitchAddress(default_delta, $dipswitch_delta);

        return false;
    });

    //switch dipswitch click
    $dipswitch_switch.find('a').on('click', function () {
        var $this = $(this);

        setDipSwitch($this, $this.parent().hasClass(class_off));
        calculateAddressFromDipSwitch($this);

        //set other switched to off
        processDipSwitchAddress(default_digital, $dipswitch_digital);
        processDipSwitchAddress(default_delta, $dipswitch_delta);

        return false;
    });
}


//calculate the address from the switch settings
function calculateAddressFromDipSwitch($this) {
    var switch_setting = '';
    var digital_address = 'N/A';
    var adresses = addresses_delta_decoder;
    var $dipswitch = $dipswitch_delta;
    var parentid = $this.closest('.dipswitch').attr('id');

    //set correctly per type of decoder
    if (parentid === 'dipswitch_digital') {
        adresses = addresses_digital_decoder;
        $dipswitch = $dipswitch_digital;
    } else if (parentid === 'dipswitch_switch') {
        adresses = addresses_switch_decoder;
        $dipswitch = $dipswitch_switch;
    }

    $dipswitch.find('a').each(function () {
        switch_setting += $(this).data(attr_onoff);
    });

    //find the digital address from the right array
    for (var i = 0; i < adresses.length; i++) {

        if (switch_setting === adresses[i]) {

            if (parentid === 'dipswitch_delta') {
                digital_address = addresses_delta_adresses[i];
            } else {
                digital_address = i + 1;
            }

            break;
        }
    }

    //check whether there are switches enabled, if not or not showing a 'n/a'
    if (parseInt(switch_setting) === 0) {
        $decoder_address.val('');
    } else {
        $decoder_address.val(digital_address);
    }
}


//calculate the switch settings from a manual address input
function calculateDipSwitchFromAddress() {
    var settings_delta = default_delta;
    var settings_digital = default_digital;
    var settings_switch = default_switch;
    var decoder_address = parseInt($decoder_address.val());

    //check whether the input is a correct number and if so set the switches
    if (!isNaN($decoder_address.val())) {

        //delta
        for (var i = 0; i < addresses_delta_decoder.length; i++) {

            if (decoder_address === addresses_delta_adresses[i]) {
                settings_delta = addresses_delta_decoder[i];

                break;
            }
        }

        //digital
        for (var ii = 0; ii < addresses_digital_decoder.length; ii++) {

            if (decoder_address === ii + 1) {
                settings_digital = addresses_digital_decoder[ii];

                break;
            }
        }

        //switch
        for (var iii = 0; iii < addresses_switch_decoder.length; iii++) {

            if (decoder_address === iii + 1) {
                settings_switch = addresses_switch_decoder[iii];

                break;
            }
        }
    }

    //process the switch address
    processDipSwitchAddress(settings_delta, $dipswitch_delta);
    processDipSwitchAddress(settings_digital, $dipswitch_digital);
    processDipSwitchAddress(settings_switch, $dipswitch_switch);

    //if there is am address, check if the dipstich supports it
    if ($decoder_address.val() !== '') {

        if (settings_delta === default_delta) {
            $dipswitch_delta.addClass(class_notavailable);
        }

        if (settings_digital === default_digital) {
            $dipswitch_digital.addClass(class_notavailable);
        }

        if (settings_switch === default_switch) {
            $dipswitch_switch.addClass(class_notavailable);
        }
    }
}


//process a digital address
function processDipSwitchAddress(address, $dipswitch) {
    var numbers = address.split('');

    $dipswitch.find('a').each(function (i) {
        setDipSwitch($(this), parseInt(numbers[i]) !== 0);
    });
}


//set a single dipswitch
function setDipSwitch($this, is_off) {
    var $parent = $this.parent();
    $dipswitch_delta.removeClass(class_notavailable);
    $dipswitch_switch.removeClass(class_notavailable);
    $dipswitch_digital.removeClass(class_notavailable);

    //switch on or off
    if (is_off) {
        $parent.removeClass(class_off);
        $parent.addClass(class_on);
    } else {
        $parent.removeClass(class_on);
        $parent.addClass(class_off);
    }

    //set the new status in the attribute
    $this.data(attr_onoff, is_off ? '1' : '0');
}


//add the dipswitches to the container
function addDipSwitches($dipswitch, cnt) {
    var $switches = $dipswitch.find('.dipswitch-switches');
    var $numbers = $dipswitch.find('.dipswitch-numbers');

    for (var i = 0; i < cnt; i++) {
        $switches.append('<div class="off"><a href="#" data-onoff="0"></a></div>');
        $numbers.append(`<div>${i + 1}</div>`)
    }
}