Поиск по json
Добрый день. У меня есть json массив:
<script type='text/javascript'> /* <![CDATA[ */ var DATA = {"variable":[{"item_id":19,"item_image":"","item_variation":{"steklo":"\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435","material":"\u043c\u0435\u0442\u0430\u043b\u043b"},"item_price":"110"},{"item_id":20,"item_image":"","item_variation":{"steklo":"\u043e\u0431\u044b\u0447\u043d\u043e\u0435","material":"\u043c\u0435\u0442\u0430\u043b\u043b"},"item_price":"130"},{"item_id":21,"item_image":"","item_variation":{"steklo":"\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435","material":"\u043f\u043b\u0430\u0441\u0442\u0438\u043a"},"item_price":"150"},{"item_id":22,"item_image":"","item_variation":{"steklo":"\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435","material":"\u0434\u0435\u0440\u0435\u0432\u043e"},"item_price":"160"},{"item_id":23,"item_image":"","item_variation":{"steklo":"\u043e\u0431\u044b\u0447\u043d\u043e\u0435","material":"\u043f\u043b\u0430\u0441\u0442\u0438\u043a"},"item_price":"175"},{"item_id":24,"item_image":"","item_variation":{"steklo":"\u043e\u0431\u044b\u0447\u043d\u043e\u0435","material":"\u0434\u0435\u0440\u0435\u0432\u043e"},"item_price":"199"}]}; /* ]]> */ </script> И есть форма: <form id="buy" action="" method="post"> <div class="variations"> <input type="radio" id="material-1" value="металл" name="material"> <label class="variations__item" for="material-1">металл</label> <input type="radio" id="material-2" value="пластик" name="material"> <label class="variations__item" for="material-2">пластик</label> <input type="radio" id="material-3" value="дерево" name="material"> <label class="variations__item" for="material-3">дерево</label> <div class="error">Пожалуйста, выберите "Материал"</div> </div> <div class="variations"> <input type="radio" id="steklo-1" value="ударопрочное" name="steklo"> <label class="variations__item" for="steklo-1">ударопрочное</label> <input type="radio" id="steklo-2" value="обычное" name="steklo"> <label class="variations__item" for="steklo-2">обычное</label> </div> <div class="buy__btn"> <input type="hidden" value="100" name="price"> <input type="hidden" value="12" name="product-id"> <input class="buy__btn_submit" type="submit" value="В корзину" data-click="Оформить"> </div> </form> Подскажите как реализовать. Пользователь кликает по inputы, в зависимости от комбинации инпутов получить item_id, item_image, item_price. Буду благодарен за любую помощь. Важный момент: заранее неизвестно количество блоков радиокнопок. |
Я написал пока следующее:
jQuery('#buy input[type="radio"]').click(function() { var data = {}; $('#buy').find ('input, select').each(function() { data[this.name] = $(this).val(); }); // здесь бы надо проверку $.each(DATA.variable,function(i,variation) { console.log(variation.item_variation); }); }); console.log(data) выводит: {material: "дерево", steklo: "обычное"} |
$(function() { var btn = $('#buy :radio').change(function() { var a = this, b = btn.not(this).filter(':checked')[0], f = {} if(b) { $.each(DATA.variable, function() { if(this.item_variation[a.name]==a.value && this.item_variation[b.name]==b.value) f.id = this.item_id; f.img = this.item_image; f.price = this.item_price; }); console.log(f); } }); }); |
Здорово. Вы меня уже не первый раз выручаете. А возможно ли одновременно событие на выбор select?
|
Не совсем понимаю код. Сработает ли он, если в наборе будет 1 блок радиокнопок или скажем 3 или 4?
|
Цитата:
Цитата:
|
Цитата:
|
Цитата:
Что касается select. Вопрос в том, будет ли скрипт работать, если нужно проверить 1-2 блока радиокнопок, а 3-ий блок опция - select? |
Цитата:
var btn = $('#buy :radio').change(function() { //коллекция всех кнопок и обработчик их изменения var a = this, //текущая кнопка b = btn.not(this).filter(':checked')[0], //вторая кнопка из набора или если их больше, //то будет коллекция в этом случае нужно обходить эту коллекцию в цикле, сравнивая имя и значения каждой соответственно с объектом f = {} if(b) { //есть ли выбор кроме одной кнопки? тогда ... То есть, если будет и уйма наборов кнопок, то не беда, весь этот набор (параметры его элементов имя/значения) в цикле сравнивать с набором в объекте. Но у вас то в объекте их два, значит и объект будут содержать более? |
В перспективе будет от 0 до 10-15 наборов радиокнопок и селектов вперемешку.
|
Цитата:
|
Цитата:
|
Янковиц,
... вариант <!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script> var DATA = { "variable": [{ "item_id": 19, "item_image": "", "item_variation": { "steklo": "\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435", "material": "\u043c\u0435\u0442\u0430\u043b\u043b" }, "item_price": "110" }, { "item_id": 20, "item_image": "", "item_variation": { "steklo": "\u043e\u0431\u044b\u0447\u043d\u043e\u0435", "material": "\u043c\u0435\u0442\u0430\u043b\u043b" }, "item_price": "130" }, { "item_id": 21, "item_image": "", "item_variation": { "steklo": "\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435", "material": "\u043f\u043b\u0430\u0441\u0442\u0438\u043a" }, "item_price": "150" }, { "item_id": 22, "item_image": "", "item_variation": { "steklo": "\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435", "material": "\u0434\u0435\u0440\u0435\u0432\u043e" }, "item_price": "160" }, { "item_id": 23, "item_image": "", "item_variation": { "steklo": "\u043e\u0431\u044b\u0447\u043d\u043e\u0435", "material": "\u043f\u043b\u0430\u0441\u0442\u0438\u043a" }, "item_price": "175" }, { "item_id": 24, "item_image": "", "item_variation": { "steklo": "\u043e\u0431\u044b\u0447\u043d\u043e\u0435", "material": "\u0434\u0435\u0440\u0435\u0432\u043e" }, "item_price": "199" }] }; $(function() { var sel = ['steklo','material']; $('#buy').on('change', function() { var form = this; var data = sel.reduce(function(obj, variation) { obj[variation] = form[variation].value return obj },{}) var findElem = DATA.variable.filter(function(elem) { return JSON.stringify(elem.item_variation) == JSON.stringify(data)// лучше цикл по sel }) var id = '', price = ''; if(findElem.length) { id = findElem[0].item_id; price = findElem[0].item_price } $('[name="price"]').val(price); $('[name="product-id"]').val(id); }) }); </script> </head> <body> <form id="buy" action="" method="post" > <div class="variations"> <input type="radio" id="material-1" value="металл" name="material"> <label class="variations__item" for="material-1">металл</label> <input type="radio" id="material-2" value="пластик" name="material"> <label class="variations__item" for="material-2">пластик</label> <input type="radio" id="material-3" value="дерево" name="material"> <label class="variations__item" for="material-3">дерево</label> <div class="error">Пожалуйста, выберите "Материал"</div> </div> <div class="variations"> <input type="radio" id="steklo-1" value="ударопрочное" name="steklo"> <label class="variations__item" for="steklo-1">ударопрочное</label> <input type="radio" id="steklo-2" value="обычное" name="steklo"> <label class="variations__item" for="steklo-2">обычное</label> </div> <div class="buy__btn"> <input value="100" name="price"> <input value="12" name="product-id"> <input class="buy__btn_submit" type="submit" value="В корзину" data-click="Оформить"> </div> </form> </body> </html> |
Ох, не дорос я ещё до этого.
|
Обратите внимание еще раз на то, о чем вы спрашивали - "если более ...". Я и написал код под ваш конкретно набор, которой собственно описать можно проще - есть некие наборы в объекте и элементы управления, при этом их количество равно. Код проверяет - если выбрано два элемента, то производится поиск. Вы пишите, что их возможно будет более, значит встает вопрос - поиск возможен если выбрано меньше элементов чем элементов набора (выбрать все подходящие) или только если выбраны все элементы (искать одно уникальное значение)?
|
Если выбраны все элементы сразу. Если 3 набора, значит должны быть обязательно выбраны все три. И так далее.
|
Поиск одного уникального значения
|
Предложение от рони не подходит?
Цитата:
К примеру, в базе будет храниться набор с типом SET: "один", "два", "три". Битовые значения их будут равны один - 001 два - 010 три - 100 то есть десятичные значения наборов по порядку будут равны: 1, 2, 4, 8, ... Если эти значения будут к примеру у списка со множественным выбором, то сложив значения всех выбранных опций (операция битовое ИЛИ) получим выбор пользователя. К примеру, если будет выбрана первая и последняя опция, значит это будет 101 = 5 десятичному. А при записи/выборке в базе можно оперировать как битовым так и текстовым набором. |
Прошу прощения, что поднимаю вопрос снова. Вариант Рони хорош, но там есть зависимость от последовательности.
То есть, если var sel = ['material','steklo']; Скрипт отказывается работать. Что касается битового набора, я попытался поискать, но ничего не понял. |
Что касается варианта:
$(function() { var btn = $('#buy :radio').change(function() { var a = this, b = btn.not(this).filter(':checked')[0], f = {} if(b) { $.each(DATA.variable, function() { if(this.item_variation[a.name]==a.value && this.item_variation[b.name]==b.value) f.id = this.item_id; f.img = this.item_image; f.price = this.item_price; }); console.log(f); } }); }); Не могу понять, почему id меняется, а price и img остаётся прежними. |
Цитата:
Цитата:
|
Не понял это куда?
|
Янковиц, вместо строки 71
<!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script> var DATA = { "variable": [{ "item_id": 19, "item_image": "", "item_variation": { "steklo": "\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435", "material": "\u043c\u0435\u0442\u0430\u043b\u043b" }, "item_price": "110" }, { "item_id": 20, "item_image": "", "item_variation": { "steklo": "\u043e\u0431\u044b\u0447\u043d\u043e\u0435", "material": "\u043c\u0435\u0442\u0430\u043b\u043b" }, "item_price": "130" }, { "item_id": 21, "item_image": "", "item_variation": { "steklo": "\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435", "material": "\u043f\u043b\u0430\u0441\u0442\u0438\u043a" }, "item_price": "150" }, { "item_id": 22, "item_image": "", "item_variation": { "steklo": "\u0443\u0434\u0430\u0440\u043e\u043f\u0440\u043e\u0447\u043d\u043e\u0435", "material": "\u0434\u0435\u0440\u0435\u0432\u043e" }, "item_price": "160" }, { "item_id": 23, "item_image": "", "item_variation": { "steklo": "\u043e\u0431\u044b\u0447\u043d\u043e\u0435", "material": "\u043f\u043b\u0430\u0441\u0442\u0438\u043a" }, "item_price": "175" }, { "item_id": 24, "item_image": "", "item_variation": { "steklo": "\u043e\u0431\u044b\u0447\u043d\u043e\u0435", "material": "\u0434\u0435\u0440\u0435\u0432\u043e" }, "item_price": "199" }] }; $(function() { var sel = ['material','steklo']; $('#buy').on('change', function() { var form = this; var data = sel.reduce(function(obj, variation) { obj[variation] = form[variation].value return obj },{}) var findElem = DATA.variable.filter(function(elem) { //return JSON.stringify(elem.item_variation) == JSON.stringify(data)// лучше цикл по sel return sel.every(function(key) { return elem.item_variation[key] == data[key] }) }) var id = '', price = ''; if(findElem.length) { id = findElem[0].item_id; price = findElem[0].item_price } $('[name="price"]').val(price); $('[name="product-id"]').val(id); }) }); </script> </head> <body> <form id="buy" action="" method="post" > <div class="variations"> <input type="radio" id="material-1" value="металл" name="material"> <label class="variations__item" for="material-1">металл</label> <input type="radio" id="material-2" value="пластик" name="material"> <label class="variations__item" for="material-2">пластик</label> <input type="radio" id="material-3" value="дерево" name="material"> <label class="variations__item" for="material-3">дерево</label> <div class="error">Пожалуйста, выберите "Материал"</div> </div> <div class="variations"> <input type="radio" id="steklo-1" value="ударопрочное" name="steklo"> <label class="variations__item" for="steklo-1">ударопрочное</label> <input type="radio" id="steklo-2" value="обычное" name="steklo"> <label class="variations__item" for="steklo-2">обычное</label> </div> <div class="buy__btn"> <input value="100" name="price"> <input value="12" name="product-id"> <input class="buy__btn_submit" type="submit" value="В корзину" data-click="Оформить"> </div> </form> </body> </html> |
Спасибо большое
|
Цитата:
То есть, битовое значение каждого множества, это 1 в соответствующем разряде. Цитата:
a = 000001 = 1 b = 000010 = 2 c = 000100 = 4 d = 001000 = 8 e = 010000 = 16 f = 100000 = 32 Легко заметить, что десятичные значения равны 2 в степени n, где n число от 0 до предела зависящего от разрядности системы, то есть 32 или 64. Поэтому в распоряжении могут быть 32 или 64 бита, значений которые может содержать множество SET. В основе все этого, как в общем и вашего мощного компьютера, лежит базовый набор логики: И, ИЛИ, НЕ (отрицание). На базе которых строятся более сложные логические элементы. Битовая операция ИЛИ, это логическое сложение (дизъюнкция), которое соответствует логике: на выходе (out) будет логическая 1 если на любом из ее входов (a, b) будет логическая 1, иначе на выходе будет логический 0. Количество входов может быть каким угодно. a b out 0 0 0 1 0 1 0 1 1 1 1 1 Если, к примеру, в наборе a, b, c, d, e, f будут выбраны значения a, c, e и f, то значение набора будет равно: двоичное - 110101, десятичное - 53, согласно логическому сложению: 000001 000100 010000 100000 -------- 110101 Логическое И, это логическое умножение (конъюнкция), и в отличии от ИЛИ на ее выходе будет логическая 1 только в том случае, если на всех ее входах будет логическая 1. Логическое И удобно в операциях маскирования, например для выделения определенной части входов устройства, просто числа. Вкупе этим базовым операциям стоит упомянуть и операцию ИСКЛЮЧАЮЩЕЕ ИЛИ, которая удобна для управления отдельными битами - установить/сбросить бит. В общем это и вся "арифметика" для понимания. Тем более, что вам не придется все это "считать в уме", вы либо оперируете текстовым значением множества, либо числовым, а представление числового значения как десятичное, это автоматически сделает SQL. Что касается применения SET. Разберем это на примере, он есть в архиве с дампом sql таблиц. Создайте тестовую базу на локальном сервере, импортируйте таблицы, и запустите индексный файл. В нем все, и серверная часть, и клиентская. Работа с базой написана под PDO, в котором по умолчанию выборка из базы, это строка в виде объекта. Можете исправить на свое подключение и работать как с ассоциативным массивом, это не суть важно, главное сами запросы. Ваши данные неудобны потому, что в них не прослеживается связей, это просто набор, над которым надо карпеть, чтобы что-то найти в нем. А ведь все составляющие товара, это по сути иерархия, в которой часть будет принадлежать верхнему уровню, как основные, определяющие данные, а другие части ниже лежащим уровням. Причем эти уровни могут представлять и дерево, то есть, определенный уровень определяется уровнем выше. В примере один товар помещен в таблицу товаров, и только товары имеют уникальный идентификатор. Кроме него таблица содержит название и производителя товара, и его описание. Характеристики товара содержатся в связанной таблице характеристик. В примере все упрощено - две характеристики товара, материал и качество, содержатся в одном наборе SET. Первые четыре значение, это материал, последние три, это качество. Упрощение не просто ради простоты, а и для того чтобы показать как можно оперировать битовым набором. Каждому из наборов двух характеристик материал/качество соответствуют две характеристики - цена и вес. При выборке товара из базы, наборы характеристик (ключ options), это массивы (цена, вес), первичными ключами которых является числовые значение их набора материал/качество. Запросом клиенту отдаются и подготовленные данные для двух отдельных списков. Сразу замечу, что можно было бы не получать числовые значения для списка Качество так как в коде, можно было не сдвигать бинарные данные значений этой характеристики, можно было очистить по маске четыре младших разряда, то есть вес значений остался бы тем что что и в SET. Сделано так, чтобы показать вариации, далее об этом будет сказано. Для формирования данных списка, для списка материалов берутся 4 младших разряда по битовой маске 1111 (fabric & 15), а для списка качества значение сдвигается вправо на 4 разряда (fabric >> 4). Соответственно тексты для каждого из значений получаются либо справа, либо слева от запятой (SUBSTRING_INDEX) текстового набора каждого из наборов материал/качество. В конечный массив списков помещаются только те характеристики, которые есть у данного товара. В каждый список характеристик передается и величина сдвига значения. Для первого асинхронного запроса, при открытии страницы, не указан тип данных, и в консоли можно наблюдать их структуру в json. При выборе характеристик в списках, происходит обратная операция - выбранное значение каждого списка сдвигается влево на указанное число разрядов , после чего они складываются. По этому значению как по свойству объекта data извлекается цена и вес этого набора. При добавлении в корзину такой же обратной операцией получается битовый набор характеристик материал/качество, который пишется в корзину. При извлечении из корзины, по этому значению из таблицы характеристик извлекается их текстовые значения. Почему сдвиги (вариации, о чем было выше) и что из того, что каждое значение SET подчинено 2 в степени n? Можно ведь и не обязательно SET использовать, но можно использовать принцип такого набора множества. Если держать характеристики как обычные записи в таблице - идентификатор, текст, и формировать их идентификаторы не средствами SQL полем с автоинкрементом, а управлять этим процессом, имея идентфикаторы с шагом 2 в степени n, то таким набором данных можно можно оперировать как и SET. В этом случае нужно только определить место каждой такой описанной характеристики в общем наборе, а сдвиг значений каждого набора будет определяться суммой количества значений всех предыдущих характеристик. |
Часовой пояс GMT +3, время: 18:11. |