LINUX.ORG.RU

Увлекательного JS'a тред

 ,


1

2

Было на странице четыре select'a и звали их «Address». Приспичило деду подгружать в них значения при загрузке страницы. Сел дед, начал писать:

selects = $('select[name="Address"]');

for(var i = 1; i < selects.length; i++) {
	var select = selects[i];
	var value  = selects[i].value;

	if (value != 0) {
		$(select).attr('disabled', false);

		$.post('/client/ajax_getCurrentLevels/', {code: value}, function(result) {
			for (var j = 0; j < result.length; j++) {
				console.log(result[j]['CODE'] + ' ' + result[j]['NAME']);
				$(select).append('<option ' + (value == result[j]['CODE'] ? "selected" : "") + ' value="' + result[j]['CODE'] + '">' + result[j]['NAME'] + '</option>');
			}
		}, 'JSON');

	}

}
Плевое дело, подумал дед. Но не тут то было! Option's добавляются всегда в последний select.

Дед в недоумении - то ли стар стал, то ли бабка виновата, то ли колобок.

Карочи, почему опции добавляются не туда, куда надо? При этом attr отрабатывает нормально для всех полей.

Deleted

Да ты тут намесил винегрет из жуйквери с ваниллой, ессно так и будет.

Ща, вникну и сварганю

deep-purple ★★★★★ ()
var f = function(select) {
	$.post('/client/ajax_getCurrentLevels/', {code: value}, function(result) {
		for (var j = 0; j < result.length; j++) {
			console.log(result[j]['CODE'] + ' ' + result[j]['NAME']);
			$(select).append('<option ' + (value == result[j]['CODE'] ? "selected" : "") + ' value="' + result[j]['CODE'] + '">' + result[j]['NAME'] + '</option>');
		}
	}, 'JSON');	
};

selects = $('select[name="Address"]');

for(var i = 1; i < selects.length; i++) {
	var select = selects[i];
	var value  = selects[i].value;

	if (value != 0) {
		$(select).attr('disabled', false);
		
		f(select);
	}

}

Но вообще жуть конечно, нужно рефакторить.

Цикл кстати вот так можно сделать: $('select[name="Address"]').each(function(select) {});

Black_Roland ★★★★ ()

Ваганыч, ты? Занимайся своим делом, а кодинг оставь кодерам.

Замыкание в JS захватывает переменные не по значению, а по ссылке. Когда замыкание исполняется, переменным уже присвоено последнее значение.

anonymous ()
$('select[name="Address"]').each(function() {
    var
        select = $(this),
        value  = parseInt(select.val(), 10);
    if (value) {
        $.post(
            '/client/ajax_getCurrentLevels/',
            {code: value},
            function(result) {
                var i, s, v;
                for (i in result) {
                    v = result[i];
                    s = (value == parseInt(v['CODE'], 10))
                        ? ' selected="selected"'
                        : '';
                    select.append('<option value="' + v['CODE'] + '"' + s +'>' + v['NAME'] + '</option>');
                }
                select.removeAttr('disabled'); // раздизаблить после вставки
            }
        );
    } else {
        select.removeAttr('disabled'); // раздизаблить сразу, т.к. не ходим
    }
});

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

deep-purple ★★★★★ ()

Вот из-за таких как ты не любят джаваскрипт.

Debasher ★★★★★ ()
Последнее исправление: Debasher (всего исправлений: 1)

Карочи, почему опции добавляются не туда, куда надо? При этом attr отрабатывает нормально для всех полей.

Потому что когда пишешь на жаваскрипте с ажаксовыми вызовами думать нужно в 4х измерениях.

Замени $.post на $.ajax({async:false}) будет тебе счастье.

ya-betmen ★★★★★ ()

Проблема здесь:

$(select).append('<option ' + (value == result[j]['CODE'] ? "selected" : "") + ' value="' + result[j]['CODE'] + '">' + result[j]['NAME'] + '</option>');

Код function(result) исполняется асинхронно, т.е. JS не ждет когда вернется резалт, от оставляет замыкание и исполняется дальше. Ты передал в функцию не текущее значение. К моменту его запуска, у тебя приложение уже давно 10 раз прокнутится и даже может вернуться с ошибкой, если ты select обNULLишь в момент между отправкой .post и возвратом result.

Чтобы этого однозначно избежать, советую дать этим селектам осмысленные id и передавать их вместе с запросом, а потом возвращать вместе с result еще и id селекта, которому он предназначается. Тогда однозначно сможешь его определить.

Что же касается совета убрать асинхронность - не советую

BaBL ★★★★★ ()
Ответ на: комментарий от no-such-file

JS не ждет когда вернется резалт, от оставляет замыкание и исполняется дальше

Если бы он оставлял замыкание, то и проблемы бы не было. Но область видимости переменных - функция, а не блок. ТС просто затирает значение переменной последним значением в цикле, довольно типичная ошибка.

no-such-file ★★★★★ ()

А нафига делать

selects = $('select[name="Address"]');
for(var i = 1; i < selects.length; i++) {

если можно просто

$('select[name="Address"]').each( function()
{
    ...
});

xorik ★★★★★ ()
Ответ на: комментарий от deep-purple

Еманая настя....

Не особо рублю в последних тэнденциях js. Но тут у тебя косяк с архитектурой. В ассинхронном коде, что-то возвращать - зло. Т.е. тебе нужны 3 маленькие функции 1-я выбирает массив элементов и для каждого вызывает 2-ю функцию. 2-я выполняет аякс для каждого элемента и скармливает и элемент и массив значений для него 3-й функции. 3-я принимает элемент и массив значений и оперирует с DOM-ом.

1-я селектор 2-я сетвой обработчик 3-я в чистом виде дом-оператор

все чистенько и никто ничего не возвращает. За подробностями гугли по «sharing by calling» - статья не по js, а просто по ассинхронке, но мозги вправляет.

ioway ()
Ответ на: комментарий от no-such-file

Нахрена? Просто function f(select)

Чтобы понятнее было.

А вообще deep-purple дал правильный вариант, в each передается callback и еще одного замыкания не надо.

Black_Roland ★★★★ ()
Ответ на: комментарий от ioway

За то мой фикс лучше других вписывается в стилистику.

ya-betmen ★★★★★ ()
Ответ на: комментарий от ya-betmen

Замени $.post на $.ajax({async:false})

Это равносильно полной генерации на бекенде, ибо браузер «подвиснет» на момент выполнения неасинка ))

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

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

Там все запутанно. Есть четыре селекта, в которые мы пихаем значение из адреса некоторого человека. А потом, в зависимости от этих значений, мы подгружаем значения «того же уровня», что и находится в селекте. Вот пример: в селекте указан Краснодарский край. Значит в этот селект нужно добавить значения остальных регионов, республик и т.д. В следующем селекте уже находятся подчиненные первому селекту значения - города и районы края и т.д.

В общем, спасибо, разобрался благодаря твоему примеру.

Deleted ()
Ответ на: комментарий от Deleted

Ну, я б не так запилил.

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

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

deep-purple ★★★★★ ()
Ответ на: комментарий от Deleted

Так я те работающий скинул - там на любую длину цепочки зависимых селектов.

deep-purple ★★★★★ ()

$(select).append('<option ' + (value == result[j]['CODE'] ? «selected» : "") + ' value=«' + result[j]['CODE'] + '»>' + result[j]['NAME'] + '</option>');

Какая мерзость.

tensai_cirno ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.