Динамическое представление по данным

Для объекта, имеющего несколько атрибутов, например, обувь может иметь разные color, size и т.д.

Теперь, когда мы пытались отобразить обувь и чтобы клиент мог выбирать разные атрибуты, мы используем радио (самое простое): https://jsfiddle.net/mwqy6217/

Но как сделать доступность представления в соответствии с данными?

Например, когда красные туфли продаются, радиостанция red должна быть не поддающейся проверке. Так что разные размеры.

Мы можем использовать эту структуру данных для представления обуви: {shoe:{name:'',available:['red','black','40','41']}}.

Однако разные атрибуты могут иметь отношения друг с другом, например, красные туфли с 40 размерами были распроданы, в то время как черные туфли с 40 размерами не имеют. Я думаю, что эта структура данных:

{shoe:{name:'',available:{color:{red:[40,41,42]},black:[42,43]}}}

Поскольку обувь может иметь другие атрибуты, такие как "вес", а атрибуты могут иметь 10+ опций.

Итак, как представить этот вид отношений в базе данных и сделать их читаемыми перед инженером для создания представления?

Update:

https://jsfiddle.net/xqtgqzt2/

Смотрите демо-версию, все доступные параметры предварительно определены как:

var options= [
    ["A1","B1","C1","D1"],
    ["A1","B3","D2"],
    ["A2","B1","C3","D2"]
];

Теперь, как изменить состояние переключателя в соответствии с параметрами? Например, когда A1 проверен, только B1 B3 может быть проверен (включен), когда отмечены A1 B1, можно проверить только C1 D1.

Ответ 1

Чтобы отобразить ваши переключатели относительно опции multimimensionnal array, вы можете сделать что-то вроде:

var options = [
    ["A1", "B1", "C1", "D1"],
    ["A1", "B3", "D2"],
    ["A2", "B1", "C3", "D2"]
];
var firstLevel = [];
var selectedList = [];
//Enable first options, disable the others
$("input[type=radio]").each(function (indexInput) {
    var that = this;
    that.disabled = true;
    $.each(options, function (index, value) {
        firstLevel.push(value[0]);
        if (value[0] == that.value) {
            that.disabled = false;
        }
    });
});
//on check radio, change states
$("input[type=radio]").on("click", function () {
    var thatClicked = this;
    if (firstLevel.indexOf(thatClicked.value) !== -1) {
        $('input[type=radio]').removeAttr('checked');
        $(thatClicked).prop('checked', true);
    }
    var possibleOptions = [];
    selectedList.push(thatClicked.value);
    $.each(options, function (index, value) {

        possibleOptions = possibleOptions.concat(value[0]);
        var posInArray = value.indexOf(thatClicked.value);
        if (posInArray !== -1 && typeof value[posInArray + 1] !== 'undefined') {
            //check previous options
            $.each(selectedList, function (indexSelectedList, valueSelectedList) {
                if (value.indexOf(valueSelectedList) !== -1) {
                    possibleOptions = possibleOptions.concat(value[posInArray + 1]);
                }
            });

        }
    });
    $("input[type=radio]").each(function (indexInput) {
        if (possibleOptions.indexOf(this.value) !== -1) {
            this.disabled = false;
        } else {
            this.disabled = true;
        }
    });
});
.section {
    padding: 10px;
    overflow: hidden;
}
label {
    float: left;
    width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
    <div class="section">
        <label>
            <input type="radio" value="A1" /> <span>A1</span>

        </label>
        <label>
            <input type="radio" value="A2" /> <span>A2</span>

        </label>
    </div>
    <div class="section">
        <label>
            <input type="radio" value="B1" /> <span>B1</span>

        </label>
        <label>
            <input type="radio" value="B2" /> <span>B2</span>

        </label>
        <label>
            <input type="radio" value="B3" /> <span>B3</span>

        </label>
    </div>
    <div class="section">
        <label>
            <input type="radio" value="C1" /> <span>C1</span>

        </label>
        <label>
            <input type="radio" value="C2" /> <span>C2</span>

        </label>
        <label>
            <input type="radio" value="C3" /> <span>C3</span>

        </label>
    </div>
    <div class="section">
        <label>
            <input type="radio" value="D1" /> <span>D1</span>

        </label>
        <label>
            <input type="radio" value="D2" /> <span>D2</span>

        </label>
    </div>
</div>
<div id="info">var options= [ ["A1","B1","C1","D1"], ["A1","B3","D2"], ["A2","B1","C3","D2"] ];</div>

Ответ 2

Я бы поставил свои данные так же, как и ваш второй вариант, однако, поскольку первое, о чем они будут заботиться, это размер (вы не можете изменить размер обуви), я бы показал доступные цвета для размера, а не доступные размеры для цвета. Прежде всего, вы указали всю доступность, потому что, если клиент знает, что зеленый "счастливый ботинок" размером 9, потенциально доступен, они могут вернуться позже, чтобы купить его. Затем вы можете просмотреть доступные параметры, чтобы изменить, доступен ли этот размер или цвет.

Здесь настроены данные:

var objShoes = [{
    name: 'Happy Shoe',
    sizes: [9,10,11,12,13],
    colours: ['red','blue','green'],
    available: [{
        size: 9,
        colours: ['red']
    },{
        size: 10,
        colours: ['red', 'blue']
    },{
        size: 11,
        colours: ['blue']
    },{
        size: 12,
        colours: ['red', 'blue']
    },{
        size: 13,
        colours: ['red']
    }]
}, {
    name: 'Scary Shoe',
    sizes: [8,9,10,11,12],
    colours: ['black','grey'],
    available: [{
        size: 8,
        colours: ['black']
    }]
}];

Вот пример того, как это могло бы работать, хотя я использовал поле выбора вместо переключателей. Они опрятные:).

Ответ 3

Более простой способ ИМХО состоит в том, чтобы отделить данные от определения атрибута и не иметь иерархии между атрибутами. Для этого вам нужно, чтобы каждое значение атрибута имело уникальный идентификатор.

В этом примере я использую индекс каждого атрибута в массиве как id для ссылки на него из объекта availability.

{
    attributes: [
        {value: "red",   type: "colour"}, // 0
        {value: "green", type: "colour"}, // 1
        {value: "black", type: "colour"}, // 2
        {value: "brown", type: "colour"}, // 3

        {value: 40, type: "size"}, // 4
        {value: 41, type: "size"}, // 5
        {value: 42, type: "size"}, // 6
        {value: 43, type: "size"}, // 7
        {value: 44, type: "size"}, // 8

        {value: true,  type: "with_shoelace"}, // 9
        {value: false, type: "with_shoelace"}, // 10
    ],

    products: [
        {
            name: 'some random shoe',
            availability: {
                0: [4, 7, 8, 9], // red is compatible with 40, 43 and 44, only with shoelace
                1: [4, 5, 9, 10], // green is compatible with 40, 43 and 44, with or without shoelace
                ...
                6: [2, 3, 9, 10], // 42 can be black or brown, with or without shoelace
                7: [0, 1, 10], // 43 can be red or green, without shoelace
                ...
                10: [1, 4, 6, 7, 8], // ...
            }
        },
        {
            name: 'another shoe',
            availability: {
                ...
            }
        }
    ]
}

В графическом интерфейсе вам нужно будет пересечь массивы availability из каждого проверенного атрибута, чтобы определить, какой вариант можно использовать.