Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   тег option <<многоуровневый>> (https://javascript.ru/forum/dom-window/1263-teg-option-mnogourovnevyjj.html)

DieseL 28.05.2008 20:08

тег option <<многоуровневый>>
 
Добрый день!

Возможно кто то подскажет....

Задача:

Нужно реализовать такое... при загрузке страницы высвечивается два поля <option></option>, поумолчанию второе неактивно к примеру в первом поле название страны во стором название городов, нужно при выборе страны в первом списке чтобы второй становился активным и в нем вываливались города из этой страны.

Проблемы:
все данные динамичны находятся в базе mysql код страницы генерируется в php соответственно данные из базы выводятся в цикле, примеров в сети оч много но с ними проблема именно из за цикла php

подскажите пожалуйста вариант решения вопроса, сам неосилю :(((

Gvozd 28.05.2008 20:35

Цитата:

Сообщение от DieseL
примеров в сети оч много но с ними проблема именно из за цикла php

в чем проблема-то? если все правильно сделано, то должно работать.
Или я неправилно понял.
Другое дело, что это не самое оптимальное решение.
ИМХО, наилучший вариант(в случае большого количества стран и городов), это на событие изменения первого optiona повесить Ajax-функцию, которая подгружает список городов во второй option, и делает его доступным.
также, для ускорения стоит настроить кэширование этих запросов, с помощью ХТТП-заголовков. Если список городов постоянно изменяется, тогда делаем кеширование как описано в статье Умное Кеширование и Версионность в Javascript/CSS

Андрей Параничев 28.05.2008 21:51

Традиционно ваша задача решается так.
Есть два списка select:
<!-- Вызываем при изменении нашу функцию -->
<select name="contry" onChange="loadList(this)">
   <option value="" selected="selected"></option>
   <option value="rus">Россия</option>
   <option value="usa">США</option>
</select>

<select disabled="disabled" name="city" id="cityList">
<option></option>
</select>


Пишется код, работающий по концепции AJAX:
// Создаём объект асинхронной загрузки с сервера.
var HTTPReq = XMLHttpRequest ? 
          new XMLHttpRequest() : 
          new ActiveXObject("Microsoft.XMLHTTP");

// Устанавливаем обработчик ответа от сервера:
HTTPReq.onreadystatechange = function()
{
  // Если загружено полностью:
  if(HTTPReq.readyState == 4) 
  {
    // Обрабатываем ответ:
    var Cities =  eval("("+HTTPReq.responseText+")");
    // Заполняем список:
    fillCityList(Cities);
  }
}

// Запоминаем выбранную страну, чтоб не 
// дублировать запросы в будущем.
var selectedContry = null;


// Функция, вызываемая при изменении списка
// (при выборе страны)
function loadList(contryList)
{
    // Если выбран "пустой" вариант - очищаем список:
    if(contryList.value === "")
    {
       clearCityList();
       return;
    }
    
    // Проверяем выбрана ли уже какая-то страна:
    if(selectedContry !== null)
    {
       // Если выбрана, проверяем не текущая ли выбрана:
       if(selectedContry == contryList.value)
       {
          // Если текущая уже выбрана - делать нечего.
          return;
       }
    }
    // Если никакая не выбрана, или выбрана не текущая, ставим текущую.
    selectedContry = contryList.value;
    
    // Далее запрашиваем сервер на предмет списка городов выбранной страны.
    // Тут должна быть ваша страница php, её работа будет описана далее:
    HTTPReq.open("GET", "page.php?country="+contryList.value);
    HTTPReq.send(null);
    
    // После этого будет вызван обработчик (который мы писали ранее, так что выходим)
    return true;
}

// Фукнция, которая добавляет элементы в список городов:
function fillCityList(elements)
{
   // elements передан в формате JSON, так что щас он - объект
   // для начала очистим текущий список городов
   clearCityList();
   
   // Уберём статус неактивен с элемента:
   var cityList = document.getElementById("cityList");
   cityList.disabled = false;
   
   // Скидываем счётчик option'ов (1 - потому что первый элемент пуст)
   var i = 1;
   
   // Рассмотрим elements, в котором ключи это values, а значения - имена.
   for(var key in elements)
   {
       // Создаём и добавляем элемент в список:
       var City = new Option(elements[key], key, false, false);

       cityList.options[i++] = City;
   }
   
   // Всё.
   return true;
}

// Функция, которая очищает все элементы из второго списка:
function clearCityList()
{
   var cityList = document.getElementById("cityList");
   
   // Такое очищение, походу, работает во всех браузерах нормально.
   while (cityList.length > 0) cityList.options[0] = null;
   
   cityList.options[0] = new Option('', 0, false, false);
   
   // Установим его в неактивный
   cityList.disabled = "disabled";
}


PHP скрипт должен найти в базе данных городов, города из данной страны, и возвратить их назад в воспринимаемом для JavaScript виде. Лучше всего, если это будет JSON.
Т.е ответ должен выглядить так:
{"new_york": "New York", "dallas": "Dallas", "city": "city"}


Допустим база данных у вас такая:
| identy | name | contry |
-------------
| spb | Санкт-Петербург | rus |
| spb | Санкт-Петербург | rus |
| ny  | Нью-Йорк        | usa |


Тогда PHP скрипт должен быть примерно такой:
<?php
// Если не получен параметр - выходим
if(!array_key_exists('contry', $_GET)) die();

// Подключаемся к БД
mysql_connect('localhost', 'login', 'passwd');
mysql_select_db('database');

// Составляем безопасный запрос:
$query = sprintf("SELECT identy, name FROM cities_list WHERE country='%s'",
         mysql_real_escape_string($_GET['country']));

// Выполняем запрос:
$result = mysql_query($query);

$output = array();

// Проходим циклом по результату
while($row = mysql_fetch_assoc($result))
{
   $output[] = '"'.addslashes($row['identy'].'": "'.
               '"'.addslashes($row['title']).'"';
}

// Выводим, если есть что выводить:
if(sizeof($output) > 0)
{
   echo '{'. implode(',', $output) .'}';
}

DieseL 29.05.2008 20:41

Спасибо огромное за детальный ответ, в самом скрипте пару мелких ошибочек исправил, но к сожалению он не работает :(((

хотя если обращаюсь напрямую к старнице по типу:

HTTPReq.open("GET", "page.php?country="+contryList.value);

тоесть обращаюсь:

page.php?country=1

то просто в тексте страницы просто высвечивается информация в таком виде:

{"new_york": "New York", "dallas": "Dallas", "city": "city"}

а список второй селект как был неактивным так и остался :(((

Андрей Параничев 30.05.2008 15:32

DieseL,
Что-то я не понял. По адресу "page.php?country=1" и должен высвечиваться JSON ответ - это данные для JavaScript скрипта. Селект должен изменятся только на html странице, без перезагрузки страницы. А код должен быть рабочим, я вроде тестил.

В общем, щас гляну еще раз, из-за чего может не работать.

DieseL 01.06.2008 21:42

Цитата:

Сообщение от Андрей Параничев (Сообщение 2724)
DieseL,
Что-то я не понял. По адресу "page.php?country=1" и должен высвечиваться JSON ответ - это данные для JavaScript скрипта. Селект должен изменятся только на html странице, без перезагрузки страницы. А код должен быть рабочим, я вроде тестил.

В общем, щас гляну еще раз, из-за чего может не работать.

Спасибо большое!Подкрутил чуть чуть и Все работает! :)))

DieseL 02.06.2008 11:41

Ужасная новость :(((( Скрипт корректно работает только в Opera. В IE6, IE7, Mozilla скрипт неработает:(((

Что нетак?

Андрей Параничев 02.06.2008 19:44

DieseL,
Попробуйте заменить:
// Создаём объект асинхронной загрузки с сервера.
var HTTPReq = XMLHttpRequest ? 
          new XMLHttpRequest() : 
          new ActiveXObject("Microsoft.XMLHTTP");

На это:
try {
	var HTTPReq = new XMLHttpRequest();
} catch(e) {
	var HTTPReq = new ActiveXObject("Microsoft.XMLHTTP");
}

DieseL 03.06.2008 10:27

Цитата:

Сообщение от Андрей Параничев (Сообщение 2772)
DieseL,
Попробуйте заменить:
// Создаём объект асинхронной загрузки с сервера.
var HTTPReq = XMLHttpRequest ? 
          new XMLHttpRequest() : 
          new ActiveXObject("Microsoft.XMLHTTP");

На это:
try {
	var HTTPReq = new XMLHttpRequest();
} catch(e) {
	var HTTPReq = new ActiveXObject("Microsoft.XMLHTTP");
}

Неработает:((( уже и в тело документа поставил тег:

<meta http-equiv="cache-control" content="no-cache">
а может заголовок документа влиять на корректность работы скрипта в ИЕ???

заголовок у меня такой:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

Андрей Параничев 03.06.2008 16:30

DieseL,
Только что проверил код в Opera, Firefox, Ie 5, Ie5.5, Ie6. Везде работало (после замены из предыдущего сообщения). Какие именно вы изменения сделали в скрипте, и выводится ли ошибка в Ie (слева снизу восклицательный знак). Не работает частично или полностью?

DieseL 03.06.2008 18:00

Цитата:

Сообщение от Андрей Параничев (Сообщение 2808)
DieseL,
Только что проверил код в Opera, Firefox, Ie 5, Ie5.5, Ie6. Везде работало (после замены из предыдущего сообщения). Какие именно вы изменения сделали в скрипте, и выводится ли ошибка в Ie (слева снизу восклицательный знак). Не работает частично или полностью?

Сам скрипт я выпер в отдельный файл с названием city.js
подключаю его так:

<script type="text/javascript" src="city.js"></script>


скрипт начинался:
var HTTPReq = XMLHttpRequest ? 
          new XMLHttpRequest() : 
          new ActiveXObject("Microsoft.XMLHTTP");

изменил на:
try {
    var HTTPReq = new XMLHttpRequest();
} catch(e) {
    var HTTPReq = new ActiveXObject("Microsoft.XMLHTTP");
}

После изменений ,Опера 9.27 как работала корректно так и работает, а вот ИЕ7 при загрузке страницы - все ок, выбираю страну, он активирует селект с городами, но если я меняю страну список уже не обновляется, при этом ИЕ7 ошибок не выдает никаких, как будто все в порядке, просто данные не меняются :(((

Возможно нужно какие то дополнительные заголовки добавлять? по типу нокеш или что то ещё?

Андрей Параничев 03.06.2008 19:06

DieseL,
Попробуйте заменить строчку
HTTPReq.open("GET", "page.php?country="+contryList.value);

На
HTTPReq.open("GET", "page.php?country="+contryList.value+"&rand="+Math.random());

DieseL 03.06.2008 23:08

Андрей Параничев,
Спасибо огромное! Решил вопрос сам :) но не без Вас!

З.ы. Если кому будет нужно/полезно/интересно говорите, пример скрипта выложу :)

DieseL 04.06.2008 20:25

Андрей Параничев,
Скажите, а возможно ли как то модифицировать код чтобы при выборе во втором селекте пункт "Другой город", вместо селекта появлялась форма <input type=text> и внесенные в нее данные отправлялись на сервер в таком же виде как запрос на выборку?

P/s/ ну а там уже скрипт пхп который добавляет в базу новый город...

DieseL 11.06.2008 00:45

Уважаемый, Андрей Параничев!

Подскажите пожалуйса почему невыходит две подобные формы на одной страницы установить? Они конфликтуют друг с другом, естевственно имена функций/елементов изменены на другие во второй форме :((

Гость 15.06.2008 01:22

Цитата:

Сообщение от DieseL (Сообщение 2818)
Андрей Параничев,
Спасибо огромное! Решил вопрос сам :) но не без Вас!

З.ы. Если кому будет нужно/полезно/интересно говорите, пример скрипта выложу :)

Если можно покажите пример работающего скрипта..

DieseL 15.06.2008 18:32

ВотЪ (:

Файл index.php

<script type="text/javascript" src="district.js"></script>

Область:
<select name="Area" style="width:130px" onchange="AreaList(this)">
<option value="0" selected="selected">Выбор</option>
<option value="1">Крым</option>
<option value="2">Киевская</option>
<option value="3">Волынская</option>
<option value="4">Одесская</option>
</select>

Районный центр:
<select disabled="disabled" name="District_List" style="width:130px" id="District_List">
<option>Выбор</option>
</select>


Файл district.js

function District_makeRequest(url) {

http_request = false;

if (window.XMLHttpRequest)
{ // Mozilla, Safari,...
	http_request = new XMLHttpRequest();
if (http_request.overrideMimeType)
{
	http_request.overrideMimeType('text/xml');
}
}
else if (window.ActiveXObject)
{ // IE
try
{
	http_request = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
	http_request = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{}
}
}

if (!http_request)
{
		alert('Не получается отправить XMLHTTP запрос');
			return false;
}
	http_request.onreadystatechange = alertContents;
	http_request.open('GET', url, true);
	http_request.send(null);
}

function alertContents()
{
	if (http_request.readyState == 4)
{

var Districties = eval("("+http_request.responseText+")");
    // Заполняем список:
fillDistrict_List(Districties);

}
}

// Запоминаем выбранную страну, чтоб не
// дублировать запросы в будущем.
var selectedArea = null;


// Функция, вызываемая при изменении списка
// (при выборе страны)
function AreaList(AreaList)
{
    // Если выбран "пустой" вариант - очищаем список:
    if(AreaList.value === "")
    {
       clearDistrict_List();
       return;
    }

    // Проверяем выбрана ли уже какая-то страна:
    if(selectedArea !== null)
    {
       // Если выбрана, проверяем не текущая ли выбрана:
       if(selectedArea == AreaList.value)
       {
          // Если текущая уже выбрана - делать нечего.
          return;
       }
    }
    // Если никакая не выбрана, или выбрана не текущая, ставим текущую.
    selectedArea = AreaList.value;

    // Далее запрашиваем сервер на предмет списка городов выбранной страны.
    // Тут должна быть ваша страница php, её работа будет описана далее:

	District_makeRequest("district_select.php?district="+AreaList.value+"&rand="+Math.random());

    // После этого будет вызван обработчик (который мы писали ранее, так что выходим)
    return true;
}

// Фукнция, которая добавляет элементы в список городов:
function fillDistrict_List(elements)
{
   // elements передан в формате JSON, так что щас он - объект
   // для начала очистим текущий список городов
   clearDistrict_List();

   // Уберём статус неактивен с элемента:
   var District_List = document.getElementById("District_List");
   District_List.disabled = false;

   // Скидываем счётчик option'ов (1 - потому что первый элемент пуст)
   var i = 1;

   // Рассмотрим elements, в котором ключи это values, а значения - имена.
   for(var key in elements)
   {
       // Создаём и добавляем элемент в список:
       var District = new Option(elements[key], key, false, false);
		   District_List.options[i++] = District;
   }
   return true;
}

// Функция, которая очищает все элементы из второго списка:
function clearDistrict_List()
{
   var District_List = document.getElementById("District_List");

   // Такое очищение, походу, работает во всех браузерах нормально.
   while (District_List.length > 0) District_List.options[0] = null;

   District_List.options[0] = new Option('', 0, false, false);

   // Установим его в неактивный
   District_List.disabled = "disabled";
}


Файл district_select.php

if(!array_key_exists('district', $_GET)) die();

// Подключаемся к БД
mysql_connect("$user_host", "$user_name", "$user_pass");
mysql_select_db ("$user_base");

// Составляем безопасный запрос:
$query = sprintf("SELECT * FROM district WHERE area='%s'",
         mysql_real_escape_string($_GET['district']));

// Выполняем запрос:
$result = mysql_query($query);

$output = array();

// Проходим циклом по результату
while($row = mysql_fetch_assoc($result))
{
   $output[] = '"'.addslashes($row['id']).'": '.
               '"'.addslashes($row['name']).'"';
}

// Выводим, если есть что выводить:
if(sizeof($output) > 0)
{
   echo '{'. implode(',', $output) .'}';
}

gagagogo 06.10.2008 12:08

Можно ли как то запихнуть в select option не используя при этом цикл на JavaScript. Например при клике на элемент select c сервера должны загрузиться значения options. Их много. Перебор в цикле ( new Options) займёт много времени. А innerHTML и outerHTML с select не работают корректно. И ещё вопрос такой: почему в ваших примерах используете HttpRequest ? У меня чешутся руки написать загрузку option-сов через динамически созданный тэг script. Будет ли это иметь какие нибудь негативные последствия ?

magistr_bender 06.10.2008 12:41

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

QwQwPP 08.11.2008 02:01

Проблема
 
Попробовал реализовать предложенный код - в результате во втором окне select появляется только одно значение, хотя в базе их много.
Подскажите, в чем может быть загвоздка

Андрей Параничев 08.11.2008 02:09

Без кода проблемного места подсказать не получится.

sergey_sergey 18.10.2009 20:51

Закинул все три файла: index.php, district.js, district_select.php на сервер, в файле district_select.php изменил подключение к БД под свои данные, при запросе к базе district сменил на своё поле. Пока не работает... Что-то ещё нужно откорректировать? Спасибо.

danik.js 25.09.2010 05:03

А никто не подскажет - есть ли какойнибудь сервис, который по запросу страны выдает в xml или json области этой страны и города? Тот же могучий Google?

danik.js 25.09.2010 06:17

пока нарыл это - http://ws.geonames.org/search?countr...ureCode=A DMD
выдает регионы России. Но нифига не на русском ((
И непонятно как запросить города отдельного региона. И желательно указать какую инфу хочу получить.

Gvozd 25.09.2010 12:13

danik.js,
вы ошиблись адресом
это форум по JS, а не поисковая система
введите пожалуйста в адресной строке http://google.ru/, и ищите там.
до свидания

magistr_bender 27.09.2010 11:46

нет ну почему же.. это всётаки по теме...
у гугла есть такой инструмент
есть даже реализация твоей задачи на jQuery плагин называется geo-autocomplete
http://code.google.com/p/geo-autocomplete/

griga 18.08.2017 10:39

Проблема с имплементацией
 
Пытаюсь адаптировать ваш код под себя, но столкнулся с проблемой:
Браузер показывает следующую ошибку:
"VM3395:1 Uncaught SyntaxError: Unexpected token <
at XMLHttpRequest.HTTPReq.onreadystatechange"

Ошибка возникает на этой строке скрипта:
var Subcategories = eval("("+HTTPReq.responseText+")");

Мой файл с формой:
<?php include('head.php'); 

// Список категорий
$sql_cat = "SELECT DISTINCT category FROM expenses_cat";
$result_cat = $conn->query($sql_cat);
while($row_cat = $result_cat->fetch_assoc()) { 
	$category[] = $row_cat['category'];
} ?>

<form action="/scripts/add_expenses.php" method="post" name="add_expenses">
	<fieldset>
		<div class="row">
			<label for="category">Категория*:</label>
			<select name="category" required onchange="loadList(this)"> 
				
				<option value="" selected="selected"></option>
				<?php foreach ($category as $KEY => $category) { echo '<option value="' . $category . '">' . $category . '</option>' . "\n"; }   ?>
			</select>
		</div>

		<div class="row">
			<label for="subcategory">Подкатегория*:</label>
			<select name="subcategory" id="subcatList" disabled="disabled" required> 
			</select>
		</div>
	</fieldset>

	<div class="button"><input id="button" type="submit" value="Добавить запись" /></div>
	
</form>

<script>
// Создаём объект асинхронной загрузки с сервера.
var HTTPReq = XMLHttpRequest ? 
          new XMLHttpRequest() : 
          new ActiveXObject("Microsoft.XMLHTTP");

// Устанавливаем обработчик ответа от сервера:
HTTPReq.onreadystatechange = function()
{
  // Если загружено полностью:
  if(HTTPReq.readyState == 4) 
  {
    // Обрабатываем ответ:
    var Subcategories =  eval("("+HTTPReq.responseText+")");
    // Заполняем список:
    fillSubcatList(Subcategories);
  }
}

// Запоминаем выбранную страну, чтоб не 
// дублировать запросы в будущем.
var selectedCategory = null;


// Функция, вызываемая при изменении списка
// (при выборе страны)
function loadList(categoryList)
{
    // Если выбран "пустой" вариант - очищаем список:
    if(categoryList.value === "")
    {
       clearSubcatList();
       return;
    }
    
    // Проверяем выбрана ли уже какая-то страна:
    if(selectedCategory !== null)
    {
       // Если выбрана, проверяем не текущая ли выбрана:
       if(selectedCategory == categoryList.value)
       {
          // Если текущая уже выбрана - делать нечего.
          return;
       }
    }
    // Если никакая не выбрана, или выбрана не текущая, ставим текущую.
    selectedCategory = categoryList.value;
    
    // Далее запрашиваем сервер на предмет списка городов выбранной страны.
    // Тут должна быть ваша страница php, её работа будет описана далее:
    HTTPReq.open("GET", "page.php?category="+categoryList.value);
    HTTPReq.send(null);
    
    // После этого будет вызван обработчик (который мы писали ранее, так что выходим)
    return true;
}

// Фукнция, которая добавляет элементы в список подкатегорий:
function fillSubcatList(elements)
{
   // elements передан в формате JSON, так что щас он - объект
   // для начала очистим текущий список подкатегорий
   clearSubcatList();
   
   // Уберём статус неактивен с элемента:
   var subcatList = document.getElementById("subcatList");
   subcatList.disabled = false;
   
   // Скидываем счётчик option'ов (1 - потому что первый элемент пуст)
   var i = 1;
   
   // Рассмотрим elements, в котором ключи это values, а значения - имена.
   for(var key in elements)
   {
       // Создаём и добавляем элемент в список:
       var Subcategory = new Option(elements[key], key, false, false);

       subcatList.options[i++] = Subcategory;
   }
   
   // Всё.
   return true;
}

// Функция, которая очищает все элементы из второго списка:
function clearSubcatList()
{
   var subcatList = document.getElementById("subcatList");
   
   // Такое очищение, походу, работает во всех браузерах нормально.
   while (subcatList.length > 0) subcatList.options[0] = null;
   
   subcatList.options[0] = new Option('', 0, false, false);
   
   // Установим его в неактивный
   subcatList.disabled = "disabled";
}

</script>


Файл-обработчик page.php в той же папке:
<?php
if(!array_key_exists('category', $_GET)) die();

include('/scripts/connect.php');

$query = "SELECT id, subcategory FROM expenses_cat WHERE category='" . $_GET['category'] . "' AND inmenu = 1";
$result = $conn->query($query);
$output = array();

while($row = $result->fetch_assoc()) 
{
   $output[] = '"'.addslashes($row['id']).'": "'.
               '"'.addslashes($row['subcategory']).'"';
}

if(sizeof($output) > 0)
{
   echo '{'. implode(',', $output) .'}';
}
?>


Файл connect.php (с ним проблем нет)
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "u177653819_reg";

$conn = new mysqli($servername, $username, $password, $dbname);

if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 
?>


Буду благодарен за помощь, в javascript я полный новичек...

Nexus 18.08.2017 11:29

griga, перед строкой
var Subcategories = eval("("+HTTPReq.responseText+")");

Добавь это:
console.log(HTTPReq.responseText);

После открой консоль и посмотри, что возвращает сервер.
Там наверняка HTML-код найдется.

griga 18.08.2017 11:44

была проблема с подключением конфига connect.php
Убрал "/" и эта ошибка исчезла

Но в целом проблему это не решило((
Ругается на ту же строку:
var Subcategories =  eval("("+HTTPReq.responseText+")");

Но теперь ошибка следующая:
Uncaught SyntaxError: Unexpected token )
    at XMLHttpRequest.HTTPReq.onreadystatechange


Все скобки в файле page.php вроде сходятся...

UPD. В целях проверки заменил переменную $_GET['category'] на одно из значений category и запустил как отдельный файл.

Команда
echo '{'. implode(',', $output) .'}';
дает результат в таком формате:
{"9": ""Значение1","14": ""Значение2","16": ""ЗначениеN"}

Nexus 18.08.2017 12:09

griga, у тебя json не валидный получается.
в файле page.php смени содержимое на это:
<?php
if(!array_key_exists('category', $_GET)) die();

include('/scripts/connect.php');

$category=$conn->real_escape_string($_GET['category']);
$query = "SELECT id, subcategory FROM expenses_cat WHERE category='".$category."' AND inmenu = 1";
$result = $conn->query($query);
$output = array();

while($row=$result->fetch_assoc()){
	$output[]=array(
		$row['id']=>addslashes($row['subcategory'])
	);
};

echo json_encode($output);
exit;

А строку с чтением категорий из ответа замени этим:
var Subcategories=JSON.parse(HTTPReq.responseText);


PS. Рекомендую почитать статьи про SQL-инъекции, как минимум.
Статей по этой теме полно, вот первая попавшаяся: https://habrahabr.ru/post/148151/

griga 18.08.2017 12:15

мы на верном пути!
Теперь в теге
<select>
выдается валидное количество опций подкатегорий, но все они называются
Код:

[object Object]

Nexus 18.08.2017 12:25

griga, посмотри, что передается функции «fillSubcatList», в начало этой функции засунь это:
console.log(elements);

griga 18.08.2017 12:48

Nexus,
Вот сейчас вообще не понял(((
Снова выдает ошибку на строке
var Subcategories=JSON.parse(HTTPReq.responseText);

Ошибка:
Uncaught SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.HTTPReq.onreadystatechange

Команда
echo json_encode($output);

в файле page.php возвращает следующий результат:
[{"9":"\u0420\u0430\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u043a\u043e\u0441\u043c\u0435\u0442\u0438\u043a\u0430"},{"14":"\u041e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438"},{"16":"\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442"}]

Nexus 18.08.2017 12:59

griga,
в page.php while замените на это и все будет работать:
while($row=$result->fetch_assoc()){
    $output[$row['id']]=addslashes($row['subcategory']);
};

laimas 18.08.2017 13:08

Цитата:

Сообщение от Nexus
addslashes($row['subcategory']);

Зачем?

Nexus 18.08.2017 13:16

Цитата:

Сообщение от laimas (Сообщение 461973)
Зачем?

согласен, нужно убрать «addslashes».

griga 18.08.2017 13:28

Итак,
Теперь код page.php выглядит так:
if(!array_key_exists('category', $_GET)) die();

include('scripts/connect.php');

$query = "SELECT id, subcategory FROM expenses_cat WHERE category='" . $_GET['category'] . "' AND inmenu = 1";
$result = $conn->query($query);
$output = array();

while($row=$result->fetch_assoc()){
    $output[$row['id']]=$row['subcategory'];
};

echo json_encode($output);
exit;

Если заменить $_GET['category'] на одно из реальных значений категории, на выходе получаем данные типа
{"9":"\u0420\u0430\u0441\u0445\u043e\u0434\u043d\u0430\u044f \u043a\u043e\u0441\u043c\u0435\u0442\u0438\u043a\u0430","14":"\u041e\u0434\u043d\u043e\u0440\u0430\u0437\u043e\u0432\u044b\u0435 \u0440\u0430\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438","16":"\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442"}

В самой же форме при выборе категории консоль отображает ошибку на строке
var Subcategories=JSON.parse(HTTPReq.responseText);

VM3836:1 Uncaught SyntaxError: Unexpected token < in JSON at position 0
    at JSON.parse (<anonymous>)
    at XMLHttpRequest.HTTPReq.onreadystatechange

Может проблема кроется в передаче данных на обработку посредством $_GET?

laimas 18.08.2017 13:29

Nexus,
сервер отдает валидный json, а убрать кодирование многобайтных строк можно начиная с версии 5.4 опцией JSON_UNESCAPED_UNICODE.

Ошибка на клиенте потому, что до передачи json есть еще вывод в браузер.

Nexus 18.08.2017 13:47

Цитата:

Сообщение от laimas
сервер отдает валидный json, а убрать кодирование многобайтных строк можно начиная с версии 5.4 опцией JSON_UNESCAPED_UNICODE.

Сейчас - да, валидный, ранее - инвалидный, в посте №29 это видно.
Можно воспользоваться опцией, а можно убрать экранирование.
(Версия PHP вопрощающего неизвестна, а проверять её в коде - глупость.)

griga,
Цитата:

Сообщение от laimas
Ошибка на клиенте потому, что до передачи json есть еще вывод в браузер.

+ смотри пост №30:
$category=$conn->real_escape_string($_GET['category']);
$query = "SELECT id, subcategory FROM expenses_cat WHERE category='".$category."' AND inmenu = 1";

Цитата:

Сообщение от Nexus
PS. Рекомендую почитать статьи про SQL-инъекции, как минимум.
Статей по этой теме полно, вот первая попавшаяся: https://habrahabr.ru/post/148151/


griga 18.08.2017 14:08

Цитата:

Сообщение от Nexus (Сообщение 461984)
$category=$conn->real_escape_string($_GET['category']);
$query = "SELECT id, subcategory FROM expenses_cat WHERE category='".$category."' AND inmenu = 1";

поправил, но на ошибку никак не влияет.
Что касается среды: локальный сайт на OpenServer:
Apache-PHP-7
PHP 7.0
MySQL 5.6

P.S. Про инъекции почитаю обязательно. Спасибо


Часовой пояс GMT +3, время: 01:13.