Привет всем!
Бьюсь с проблемой уже день, силы иссякли, решил написать тут. Излагаю суть:
Пишу простенький модуль для создания галереи.
Создаю форму добавления картинки в текущую галерею, в ней же отображаю уже добавленные картинки выводя их из базы.
Здесь для каждой картинки создаётся кнопка-submit, у которой есть собственный обработчик mygallery_image_delete_submit, он удаляет. Также ниже вывода картинок есть поле типа file для выбора загружаемой картинки, и ещё одна кнопка submit для загрузки этой картинки, у неё тоже свой обработчик и валидатор.
//Выборка всех данных о изображениях галереи с айдишником $gall_id
$query = db_query("SELECT * FROM {mygallery_gallerys} AS t1
LEFT JOIN {node} AS t2 ON t1.iid = t2.nid
LEFT JOIN {node_revisions} AS t3 ON t2.nid = t3.nid
LEFT JOIN {mygallery_images} AS t4 ON t1.iid = t4.nid
LEFT JOIN {files} AS t5 ON t4.fid = t5.fid
WHERE t1.gid = %d", $gall_id);
global $base_url;
//враппер для ahah
$form['wrapper_start'] = array(
'#value' => '<div id = "wrap_here">',
);
//выводим изображения
while ($row = db_fetch_object($query)) {
$form['images'][$row->fid] = array(
'#theme' => 'gallery',
);
$form['images'][$row->fid]['remove'] = array(
'#type' => 'submit',
'#value' => '[x]',
'#name' => 'remove_'.$row->fid,
//'#src' => drupal_get_path('module', 'mygallery') . '/images/cross.png',
'#ahah' => array(
'path' => 'mygallery/image_upload/js',
'wrapper' => 'wrap_here',
'method' => 'replace',
),
'#submit' => array('mygallery_image_delete_submit')
);
//получаем путь для уменьшенной копии изображения
$small = substr($row->filepath, 0, (strlen($row->filepath) - strlen($row->filename) - 1));
//путь для оригинала
$form['images'][$row->fid]['bigimage'] = array(
'#type' => 'hidden',
'#value' => $base_url . '/' . $row->filepath,
);
//путь для уменьшенной копии
$form['images'][$row->fid]['smallimage'] = array(
'#type' => 'hidden',
'#value' => $base_url . '/'. $small . '/small/' . $row->filename,
);
$form['images'][$row->fid]['title'] = array(
'#type' => 'hidden',
'#value' => $row->title,
);
$form['images'][$row->fid]['body'] = array(
'#type' => 'hidden',
'#value' => $row->body,
);
}
//если нет картинок в галереи, выводим "нет изображений"
if(!isset($form['images']))
{
$form['images'] = array(
'#theme' => 'emptyfolder',
'#value' => 'Нет изображений',
);
}
//конец враппера для ahah
$form['wrapper_end'] = array(
'#value' => '</div>',
);
$form['upload_image'] = array(
'#type' => 'fieldset',
'#title' => t('Загрузка изображения в галерею'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['upload_image']['imagefile'] = array(
'#type' => 'file',
'#title' => t('Добавить изображение'),
'#size' => 40,
'#description' => "поддерживаемые форматы jpeg png gif",
);
$form['upload_image']['title_image'] = array(
'#type' => 'textfield',
'#title' => "Название изображения",
'#required' => FALSE,
);
$form['upload_image']['description']['body'] = array(
'#type' => 'textarea',
'#title' => 'Описание изображения',
'#required' => FALSE
);
$form['upload_image']['imagesubmit'] = array(
'#op' => 'myop',
'#type' => 'submit',
'#value' => t('Загрузить'),
'#name' => 'picsubmit',
'#ahah' => array(
'path' => 'mygallery/image_upload/js',
'wrapper' => 'wrap_here',
'method' => 'replace',
'progress' => array('type' => 'bar', 'message' => t('Пожалуйста подождите...')),
),
'#submit' => array('mygallery_image_submit'),
'#validate' => array('mygallery_image_validate'),
);
//скрытое поле содержит id текущей галереи
$form['nid'] = array(
'#type' => 'hidden',
'#value' => $gall_id,
);
$form['#attributes']['enctype'] = 'multipart/form-data';
return $form;
}
....
бла бла бла много кода валидации добавления картинки
...
}
function mygallery_image_submit($form, &$form_state) {
бла бла бла много кода сабмита картинкиЮ тут добавляем её в базу....
}
function mygallery_image_delete_submit($form, &$form_state) {
...
бла бла бла сабмитер для удаления картинки
...
}
А вот ahah обработчик для кнопок
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
$args = $form['#parameters'];
$form_id = array_shift($args);
$form['#post'] = $_POST;
$form['#redirect'] = FALSE;
$form['#programmed'] = FALSE;
$form_state['post'] = $_POST;
drupal_process_form($form_id, $form, $form_state);
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
$images = $form['images'];
// $javascript = drupal_add_js(NULL, NULL, 'header');
print drupal_to_js(array(
'status' => TRUE,
'data' => theme('status_messages') . drupal_render($images),
// 'settings' => call_user_func_array('array_merge_recursive', $javascript['setting'])
));
exit();
}
всё это дело шикарно работает при отелючении ahah, картинки добавляются, правильно отображаются, удаляются! Класс!
Но вот беда, когда подключаю ahah, в обработчике не верно идентифицируется нажатая кнопка. То есть для того чтобы
drupal_process_form($form_id, $form, $form_state); адекватно распознала нажатую кнопку и поместила её в $form_state['clicked_button'] нужно чтобы от браузера приходил $_POST содержащий '#name' нажатой кнопки, обрабатывая этот пост drupal_process_form и понимает какая кнопка была нажата.
Всё чики пуки когда я наживаю на кнопку 'загрузить' при отсутствии выбранного файла (т.е. форма выбора файла пустая), обработчик ahah в таком случае получает правильный пост, с неймом кнопки, следовательно совершенно адекватно определяет clicked_button (нажал на загрузку или на удаление). ВОТ МАГИЯ НАЧИНАЕТСЯ ОТСЮДА! Стоит мне прикрепить файл и нажать на 'загрузить' как ahah обработчик получает Post без параметра '#name', в следствии clicked_button определяется не адекватно, и в недрах drupal_process_form (а именно в form_builder -> _form_builder_ie_cleanup),clicked_button получает самую первую найденную кнопку в форме. Как так то?
Если не устали читать, то пишу что нараследовал по этой теме.
дампил в ahah обработчике $_POST , $_FILES
$_FILES при прикреплённом файле содержит информацию о нём, т.е. загружается успешно. => не в $_FILES дело
дампил и находил закономерности $_POST, закономерность одна - при прикреплённом изображении $_POST содержит name кнопки, без прикреплённого файла НЕТ. Остальные атрибуты в POST не изменяются.
Далее, пытался найти объяснение этому, полез в ahah.js. Немного помучав его firebug'om выяснил что форма отправляется таким образом
$(element_settings.element).bind(element_settings.event, function() {
console.log(options.data);
$(element_settings.element).parents('form').ajaxSubmit(options);
return false;
});
где options набор параметров
var ahah = this;
var options = {
url: ahah.url,
data: ahah.button,
beforeSubmit: function(form_values, element_settings, options) {
return ahah.beforeSubmit(form_values, element_settings, options);
},
success: function(response, status) {
// Sanity check for browser support (object expected).
// When using iFrame uploads, responses must be returned as a string.
if (typeof(response) == 'string') {
response = Drupal.parseJson(response);
}
return ahah.success(response, status);
},
complete: function(response, status) {
if (status == 'error' || status == 'parsererror') {
return ahah.error(response, ahah.url);
}
},
dataType: 'json',
type: 'POST'
};
как видим здесь у параметру data задаётся ahah.button. Ahah.button содержит связку name-value нажатой кнопки, и как показал фаер баг правильно её определяет во всех случаях! и с файлом без файла!
Проблема в том, что когда ajaxSubmit(options) отправляет форму ajax'ом в которой есть input type='file' он игнорирует параметр data, и нихрена не передаёт.(следил за отправлеными post'ами через фаербаг) Отсюда то и ясно почему name кнопки не доходит постом до моего ahah обработчика на сервере, он просто не отсылается.
Вот тут я и застрял, как быть, что делать? Извиняюсь за большое количество текста, накипело. Спасибо заранее за помощь.
Комментарии
проблему решил изначально другим путём. Но всё же проблема актуальна. Неужели это баг
...
!!!
Через ajax только в html 5 можно отправить файл все остальные способы frame-transport. Это не баг. В Drupal 6 этого 99% не реализоъвано
файл то отправляется и принимается/сохраняется без проблем, просто параметр нажатой кнопки отправки теряется
хей хей, никто не сталкивался с этой проблемой?