Jump to content
  • 0

Формирование JS объекта Array() или Object()


Bolmazov
 Share

Question

Т.к. я больше программирую в PHP буду объяснять терминами этого языка.

JS (jquery) должен сформировать по сути двухмерный ассоциированный массив, но ключи массива д.б. числовыми.

Пример: array(3=>array(2), 4=>array(2,3)));

Пример формирования подобного массива:

var param = new Array();
$(".construct_field").each(function () {
var value = new Array();
$(this).children(":selected").each(function () {
value.push($(this).val());
});
param[$(this).attr('id')] = value;
});

Сформировав подобный массив, его нужно передать в качестве параметра AJAX-запросу в PHP:

Пример: $.post("script.php", {'data[]': param}, function(data){ node.after(data); }, "html");

В тестовых целях script.php возвращает var_dump($_POST['data']);

И тут я вижу следующее: array(5) { [0]=> string(15) "[object Window]" [1]=> string(15) "[object Window]" [2]=> string(15) "[object Window]" [3]=> string(1) "2" [4]=> string(3) "2,3" }

Объяснил подробно. Теперь вопрос:

1. Если внимательно посмотреть, то вложенные массивы передаются строкой (пример: [4]=> string(3) "2,3" ). Можно ли еще в JS так сформировать данные, что бы получить, то что изначально требовалось: "4=>array(2,3)"?

2. Но важнее ответ на следующий вопрос. Как видно из примера в PHP попадает не чистый массив с т.з. самого PHP. Его придется фильтровать, что бы избавится от подобных значений: "object Window". а это не cool способ. Хочется, что бы в PHP попадал уже "чистый" массив (типа array(3=>array(2), 4=>array(2,3))));

P.S. мои знания в JS не Ах!, поэтому допускаю, что формировать данные нужно как-то подругому. Прошу помочь.

Link to comment
Share on other sites

15 answers to this question

Recommended Posts

  • 0
Пан не ищет легких путей.

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

Постановка задачи:

Нужно реализовать некую форму (назовем её "конструктор").

Изначально форма состоит из одного селекта.

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

Селекты (кроме первого) могут иметь множественный выбор (multiple).

Поля каждого последующего селекта зависят от выбранных полей всех предыдущих селектов.

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

Описание моего подхода к задаче (код предыдущего поста уже немного изменен, но до сих пор отражает суть изначального вопроса):

Т.к. для формирования нового селекта и его полей мне нужно знать предыдущие селекты и их выбранные поля, то каждому селекту приписываем уникальный (среди селектов) id и каждому полю в селекте присваиваем уникальное value (по сути id поля данного селекта).

Как только пользователь выберет новое значение одного из отображаемых селектов, скрипт должен составить двухмерный массив состоящий из id селекта и набора выбранных полей (учитывается возможность multiple) и отправить этот массив на сервер для формирования нового селекта.

Link to comment
Share on other sites

  • 0

Понятно. Смотри что не так.

1. param[$(this).attr('id')] = value

value является массивом. Лучше всего привести его к строковому значению value.join(",")

2. Поясни еще раз подробно, что ты хочешь видеть на стороне сервера

Link to comment
Share on other sites

  • 0
1. param[$(this).attr('id')] = value

value является массивом. Лучше всего привести его к строковому значению value.join(",")

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

Но это на принципиально и может быть даже приемлемым способом.

Еще раз повторю, главный вопрос второй.

2. Поясни еще раз подробно, что ты хочешь видеть на стороне сервера

Главное, что я не могу сделать, это сформировать ЧИСТЫЙ массив (или объект).

Т.е. сейчас в $_POST['data'] лежит: array(5) { [0]=> string(15) "[object Window]" [1]=> string(15) "[object Window]" [2]=> string(15) "[object Window]" [3]=> string(1) "2" [4]=> string(3) "2,3" }

, а нужно array(3=>array(2), 4=>array(2,3)))).

Что бы на сервере не удалять элементы типа [0]=> string(15) "[object Window]"

Link to comment
Share on other sites

  • 0
Так это первый вопрос начального поста. Так и получается , что этот массив преобразуется в строку. А я бы хотел, что бы этот вложенный массив и оставался массивом.

Но это на принципиально и может быть даже приемлемым способом.

Еще раз повторю, главный вопрос второй.

Главное, что я не могу сделать, это сформировать ЧИСТЫЙ массив (или объект).

Т.е. сейчас в $_POST['data'] лежит: array(5) { [0]=> string(15) "[object Window]" [1]=> string(15) "[object Window]" [2]=> string(15) "[object Window]" [3]=> string(1) "2" [4]=> string(3) "2,3" }

, а нужно array(3=>array(2), 4=>array(2,3)))).

Что бы на сервере не удалять элементы типа [0]=> string(15) "[object Window]"

Про json и explode не слышал?

Link to comment
Share on other sites

  • 0
Слышал. Но как его в JavaScript'e применить в данном случае пока не догадался. Да и не было такой идеи.

Попробую.

Спасибо за идею и терпение.

Не надо это использовать в JS, это можно использовать в php.

На сервер постится data, которая представляет собой json-строку. Эту json-строку можно распарсить стандартными средствами php, и получить объекную структуру данных.

Link to comment
Share on other sites

  • 0

...Вот еще проблема.

Ожидается, что когда ajax вернет новый селект с классом construct_field, то и на него будет распространятся скрипт:

			$('.construct_field').change(function () {
var param = new Array();
var current_field = $(this);
current_field.prevAll().each(function () {
param[$(this).attr('id')] = add_param($(this));
});
param[current_field.attr('id')] = add_param(current_field);
$.post("/modules/tconstructor.php", {'constructor[]': param}, function(data){ building(current_field, data); }, "html");
});

Но вопреки моим ожиданием такого не происходит.

Тем не менее если каждому селекту добавить onChange='change($(this))'

и переписать скрипт:

		function change(_this){
var param = new Array();
var current_field = _this;
current_field.prevAll().each(function () {
param[$(this).attr('id')] = add_param($(this));
});
param[current_field.attr('id')] = add_param(current_field);
$.post("/modules/tconstructor.php", {'constructor[]': param}, function(data){ building(current_field, data); }, "html");
}

, то реакция нового селекта появится.

Почему так?

Link to comment
Share on other sites

  • 0
...Вот еще проблема.

Ожидается, что когда ajax вернет новый селект с классом construct_field, то и на него будет распространятся скрипт:

Но вопреки моим ожиданием такого не происходит.

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

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

Link to comment
Share on other sites

  • 0

Ясно.

Просто для меня (я не часто пишу клиентские скрипты) это не логично. По мне, так раз произошло событие, то почему бы не посмотреть по всему обновленному html, какой элемент подходит под данное действие.

Ты говоришь, что нужно повесить функцию-обработчик на post.

Я не представляю как это можно сделать...

Но в данной ситуации я нашел выход (как и писал ранее): каждому селекту добавить onChange='change($(this))'. Надеюс, это близко к тому что Ты имел в виду.

(Только почему ЭТО работает пока не очень уяснил.)

Есть более изящный способ (что бы не множить в каждом селекте onChange='change($(this))' )?

Link to comment
Share on other sites

  • 0
Ясно.

Просто для меня (я не часто пишу клиентские скрипты) это не логично. По мне, так раз произошло событие, то почему бы не посмотреть по всему обновленному html, какой элемент подходит под данное действие.

Ты говоришь, что нужно повесить функцию-обработчик на post.

Я не представляю как это можно сделать...

Для этого достаточно внимательно изучить документацию http://api.jquery.com/jQuery.post/

Там есть замечательный пример

$.post("test.php", { name: "John", time: "2pm" },
function(data){
alert("Data Loaded: " + data);
});

Потом подумать головой, и найти "изящный" способ.

Link to comment
Share on other sites

  • 0

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

Кратко опишу те проблемы с которыми я столкнулся по ходу написания ajax-запроса с помощью jqery. Мои частные, подозреваю не самые продуктивные, решения опишу позже, когда найду ответы на все интересующие меня вопросы.

И так:

1. нужно было собрать из формы данные с помощью jqery в удобном для разбора на стороне сервера формате.

2. ajax-запрос должен добавить (изменить) html-форму и новые элементы формы должны были реагировать на события определенные в js-скрипте для всех полей данной html-формы.

И вот я всё, казалось, сделал. Какой ни какой, а результат. И тут я решил всё проверить ... в IE. Конечно же не работает!

Копирую на localhost и начинаю разбираться в чем дело.

Первый вывод: запрос $.post("/modules/tconstructor.php", {'constructor': param}, function(data){ alert(data) }, "html"); не работает.

Точнее alert(data) выводит: array(0){}.

Что же... Немного изменил код на $.post("/modules/tconstructor.php", {'constructor[]': param}, function(data){ alert(data) }, "html");

И все заработало почти как нужно. Осталось на сервере при разборе POST переменной добавить что то типа $data = $_POST['constructor'][0];

Вот понимаю, что это костыли, но уже не до этого. Сделать бы, что-бы работало, а дальше поправим...

В итоге код заработал и под IE на localhost.

Заливаю на хостинг и ... ОПА! Тот же IE не работает!

Т.е. на хостинге даже function(data){ alert(data) }, "html" не выполняется, если сервер возвращает любую не пустую строчку data.

Это для меня вообще чудо! Но т.к. я в чудеса не верю, а верю в недостаток моих знаний в этом вопросе и кривость IE, то прошу вас помочь с решением данной проблемы.

Link to comment
Share on other sites

  • 0

Ага, понятно, в чем твоя ошибка. Ты думаешь, что при посте массива данных они каким-то магическим образом будут преобразованы в объекты PHP? Нет, этого не будет.

На твой основной вопрос никто не ответит, так как скилл телепатии ее слабо прокачан.

Link to comment
Share on other sites

  • 0

Нет. Не в этом моя ошибка и я так не думаю.

Вероятно, Ты так подумал, потому, что я слишком много понаписал тут. Это специально для того что бы не пришлось ждать чара с прокачанным скилом телепатии.

На помощь я конечно рассчитывал, но естественно не в той мере, что бы сидеть и ждать пока мне прокачают экспириэнс.

С другой стороны, я писал, для того что бы рано или поздно кто-то (я) нашел ответ на эти вопросы и форум стал еще немного полезней этой информацией.

Так вот на большую часть вопросов я нашел ответ, сейчас изложу:

Уважаемый %username%, если тебе требуется вставить html , который ты должен получить через ajax и в этом html есть элементы, на которых, по идеи, должен распространятся некоторый javascript-сценарий, то могут пригодится советы, изложенные ниже.

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

Для эффективного (менее геморного) написания javascript-сценария я конечно использовал jquery.

И так...

1. Как удобнее подготовить данные для их отправки через ajax?

Перепробовав несколько вариантов я сделал следующее: собрал в данные, в удобную для последующей работы с ними на сервере, структуру и воспользовался плагином jquery.json, что бы спокойно отправить данную структуру на сервер через ajax. На сервере нужно воспользоваться функцией json_decode (для PHP), что бы преобразовать строку из json-формата в структуру, которую ты так кропотливо формировал в javascript.

2. Когда отправишь данные, может оказаться, что сработал включенный get_magic_quotes_gpc. Так отключи его! Воспользуйся функцией stripslashes, что бы убрать экранирование.

3. Обрати внимание на кодировку, в которой php отдает обратно код. Пропиши charset в ответе сервера, если кодировка страницы не совпадает с кодировкой ответа. Еще мне помогла эта заметка про IE.

4. Когда мы вернули и вставили наш новый html в таблицу, то хотим, что бы на них тоже распространялся некоторый javascript-сценарий.

В моем случае я хочу, что бы вызывалась ф-я _change на событие change для всех элементов с классом construct_field.

В таком случае обратите внимание на строчку $('.construct_field').change(function () { _change($(this)) } ); в функции building код, который я разместил ниже.

5. И последнее. Когда я всё сделал, то обнаружил, что IE упрямо не отправляет данные ajax'ом если писать примерно так: $.post("script.php", {'param': $.toJSON(param)});

Всё заработало даже в IE, когда я переписал это примерно так: $.post("script.php", {'param[]': $.toJSON(param)});

А теперь мой javascript-код иллюстрирующий всё это:

	<script src="/tools/jquery.json-2.2.min.js" type="text/javascript"></script>
<script>
// вешаем _change функцию на событие change
// но она почему-то не будет выполнятся для вставленного html из ajax-запроса
$('.construct_field').change(function () { _change($(this)) } );

function _change(_this){

var param = new Array();
// начинаю формировать удобную для меня структуру данных для отправки в ajax-запросе
// структура param будет такой array(object('key': ..., 'value': array(...) ), object('key': ..., 'value': array(...), ...)
$('#constructor .construct_field ').each(function () {
param.push({ 'key': $(this).attr('id'), 'value': add_param($(this)) });
});
// Отправляем ajax-запрос.

$.post("/modules/tconstructor.php", {'constructor[]': $.toJSON(param)}, function(data){ building(_this, data); }, "html");
}


function add_param(field){
var value = new Array();

field.children(":selected").each(function () {
value.push($(this).val());
});

field.children(":checked").each(function () {
value.push($(this).val());
});
return value;
}

function building(field, data){
field.parents('#constructor tr').after(data);

var summ = 0;
$('.constructor_price').each(function () {
summ += parseInt($(this).text());
});
$('#constructor_summ').html('Итоговыя сумма:<b style="font-size: 16px;"> '+summ+' </b>руб.');

// а вот эта строчка заставляет выполнить функцию _change для всех элементы с классом construct_field () при выполнении события change
$('.construct_field').change(function () { _change($(this)) } );

}

</script>

Конечно, это наверняка сыровато, но, надеюсь, зерна разумного в этом есть.

Буду признателен если вы как-то конструктивно прокомментируете это, а может быть даже объясните, почему везде подобный код: $.post("script.php", {'param': $.toJSON(param)});, работает, а что бы он работал и в IE, нужно писать так: $.post("script.php", {'param[]': $.toJSON(param)}); ?

Edited by Bolmazov
Link to comment
Share on other sites

  • 0
Буду признателен если вы как-то конструктивно прокомментируете это, а может быть даже объясните, почему везде подобный код: $.post("script.php", {'param': $.toJSON(param)});, работает, а что бы он работал и в IE, нужно писать так: $.post("script.php", {'param[]': $.toJSON(param)}); ?

Скорее всего это связано с особенностями реализации HTTP в IE.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy