Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

HTML+CSS+JavaScript

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: JSON
 
 автор: moonfox   (22.05.2014 в 17:58)   письмо автору
 
 

почему запрос
$.post('test.php' , $('#f1').serializeArray(), function(d) { alert(d); });

возвращает

print_r($_POST);

Array
(
    [fio] => 
    [milo] => 
    [pass] => 
    [tel] => 
    [skype] => 
)


а где же json?

  Ответить  
 
 автор: confirm   (22.05.2014 в 18:41)   письмо автору
 
   для: moonfox   (22.05.2014 в 17:58)
 

А с чего это вдруг массив должен стать JSON? $_GET, $_POST были и будут суперглобальными массивами. Руководство читать надо.

  Ответить  
 
 автор: moonfox   (22.05.2014 в 21:48)   письмо автору
 
   для: confirm   (22.05.2014 в 18:41)
 

это понятно
объясните тогда что происходит после выполнения serializearray который якообы выдает данные в формате json?
то есть меня смущает первая и вторая часть post и serializearray

у вас например в примере так же строчка
$.post('dialog.php', $(this).serializeArray(), function(d) {}, 'json');
????

  Ответить  
 
 автор: Deed   (22.05.2014 в 22:14)   письмо автору
 
   для: moonfox   (22.05.2014 в 21:48)
 

Я бы вообще не стал заморачиваться с вечно проблемным json'ом.
Ну, ладно, были когда-то скорости дайалаповские не более 56 Кб/сек...
Тем более, что http://habrahabr.ru/post/198312/

Собственно про сына JS в связке с php хорошо написано здесь: http://php.ru/manual/function.json-decode.html
Но, опять-таки, зачем усложнять сущее без необходимости??

А, понял. Вы хотите принимать данные в json'e?
Ну, тогда в функции, обрабатывающей ответ сервера:
$.post('dialog.php', $(this).serializeArray(), function(d) {}, 'json');
Нужно обработать ответ сервера (d) в json-формате:

var myArray = jQuery.parseJSON(d);
// теперь переменная myArray содержит массив.
// Например
console.log(myArray);

  Ответить  
 
 автор: moonfox   (22.05.2014 в 22:26)   письмо автору
 
   для: Deed   (22.05.2014 в 22:14)
 

спс.
вобщем то мне json не нужен ни в php ни в js
просто не понимаю как увязывается отправка постом с якобы полученными json данными
может я просто чего-то не догоняю....

  Ответить  
 
 автор: Deed   (22.05.2014 в 22:34)   письмо автору
 
   для: moonfox   (22.05.2014 в 22:26)
 

$.post('dialog.php', $(this).serializeArray(), function(d) {}, 'json'); - выделенная функция - третий параметр в $.post(), обрабатывает ОТВЕТ сервера на ЭТОТ пост-запрос.
Четвертый же параметр ('json') "предупреждает" наш скрипт, в каком виде получен этот ОТВЕТ.

  Ответить  
 
 автор: Deed   (22.05.2014 в 22:29)   письмо автору
 
   для: Deed   (22.05.2014 в 22:14)
 

json_encode - выполняется на сервере и формирует ОТВЕТ в json-формате: http://www.php.net/manual/ru/function.json-encode.php

  Ответить  
 
 автор: moonfox   (22.05.2014 в 22:31)   письмо автору
 
   для: Deed   (22.05.2014 в 22:29)
 

может подскажите в каком объекте находится переданные json данные?
в $_post массив

  Ответить  
 
 автор: moonfox   (22.05.2014 в 22:36)   письмо автору
 
   для: moonfox   (22.05.2014 в 22:31)
 

да плохо читал про callback совсем ничерта не внимательный.
теперь ясно что назад приходит..

хорошо, и наверно я должен был задать другой вопрос))))

как из js на автомате получить в php данные в формате json на примере jquery?

  Ответить  
 
 автор: Deed   (22.05.2014 в 22:49)   письмо автору
 
   для: moonfox   (22.05.2014 в 22:31)
 


$.post('dialog.php', $(this).serializeArray(), function(d) {}, 'json')

С большой долей вероятности в $_POST[0] - но для этого нужно быть оптимистом... И вообще, так писать некрасиво.
Я бы сделал так:

...
var mumu= $(this).serializeArray();
function success(d){
   var myArray = jQuery.parseJSON(d); 
   //console.log(myArray);
}
var datas={gaga:mumu};
de]
$.post('dialog.php', datas, success, 'json');
...

Ну, и файл dialog.php будет видеть переданные ему данные в переменной $_POST['gaga'] - здесь будет то, что мы запихнули в переменную mumu - (var mumu= $(this).serializeArray();)

  Ответить  
 
 автор: moonfox   (23.05.2014 в 01:14)   письмо автору
 
   для: Deed   (22.05.2014 в 22:49)
 

спс за пример

  Ответить  
 
 автор: confirm   (23.05.2014 в 10:22)   письмо автору
 
   для: Deed   (22.05.2014 в 22:49)
 

Хренью не майтесь товарищ Deed.

  Ответить  
 
 автор: moonfox   (23.05.2014 в 12:05)   письмо автору
 
   для: confirm   (23.05.2014 в 10:22)
 

покажите пример как правильно передать в php json

  Ответить  
 
 автор: confirm   (23.05.2014 в 15:47)   письмо автору
 
   для: moonfox   (23.05.2014 в 12:05)
 

Вы о чем? JSON - это строка описывающая по определенному соглашению различные типы данных. На клиенте такового формата "в свободном" виде нет, и передавая на сервер форму, браузер передает массив - ключ->значение.

Действительно JSON передать на сервер, это надо сперва сформировать такую строку:

var s = JSON.stringify(object);

а затем передать ее под каким либо именем (ключом) на сервер, только зачем эта бодяга?

  Ответить  
 
 автор: moonfox   (23.05.2014 в 15:54)   письмо автору
 
   для: confirm   (23.05.2014 в 15:47)
 

это я и хотел услышать
спасибо
просто в учебных целях.

  Ответить  
 
 автор: moonfox   (25.05.2014 в 20:54)   письмо автору
 
   для: confirm   (23.05.2014 в 15:47)
 

можно еше вопрос?

  Ответить  
 
 автор: confirm   (25.05.2014 в 22:09)   письмо автору
 
   для: moonfox   (25.05.2014 в 20:54)
 

А я разве запрещаю вам задавать здесь вопросы?

  Ответить  
 
 автор: moonfox   (25.05.2014 в 23:00)   письмо автору
 
   для: confirm   (25.05.2014 в 22:09)
 

это был запрос на внимание, ибо возможно, вы бы не обратиди внимания на старую тему.

смотрите
ваш код:

<?
if($_POST['dialog'] {
    
//принимаем запросы клиента
    
$form = &$_SESSION['form_dialog'];
    switch(
$name $_POST['dialog']) {
        case 
'mail' :   //обработка формы диалога почты
                        
$form == $name {
                            
//запрос от формы
                        
} else sendForm('mail'); //иначе отправляем код формы
                        
break;
        case 
'main' :  //обработка формы диалога личного кабинета
                        
$form == $name {
                            
//запрос от формы
                        
} else sendForm('main'); //иначе отправляем код формы
                        
break;
        case 
'basket' //обработка формы диалога корзины
                        
$form == $name {
                            
//запрос от формы
                        
} else sendForm('basket'); //иначе отправляем код формы
    
}
    exit;


$(
'[id|=dialog]').on('click', function() {
    var 
btn = $(this).prop('disable'1);
    $.
post('dialog.php'this.id.replace('-','='), function(d) {
        
//кеширование объекта для которого необходимо выполнять операции
        //и выполнение операций
        
var dialog = $(d).appendTo('body').find('form').on('submit', function() {
            $.
post('dialog.php', $(this).serializeArray(), function(d) {
                
//диалог клиент-сервер, работа над ошибками и т.д..
            
}, 'json').end().find('#close').click(function() {
                
dalog.remove();
                
btn.prop('disable'0);
                
//выполнение операций для кешированного объекта
            
}).end();
        });    
    }, 
'html');
});



при нажатии на кнопку с вызовом диалога, мы отправляем его id
$.post('dialog.php', this.id.replace('-','='), function(d) {
)};

if($_POST['dialog']
switch($name = $_POST['dialog']) {
case 'mail' :
...

то есть насколько я понимаю, id, php получает 1 раз при нажатии на кнопку и выдает соответствующий код формы
далее, вы используете 1 php и для вывода формы и для обработки ajax данных
$.post('dialog.php', this.id.replace('-','='), function(d) {
var dialog = $(d).appendTo('body').find('form').on('submit', function() {
$.post('dialog.php', $(this).serializeArray(), function(d) {
...
if($_POST['dialog'] {
$form == $name {
//запрос от формы
}
каким образом при повторном выполнении dialog.php который срабатывает при сабмите, вы получаете $_POST['dialog'] если же собственно пост с индексом dialog мы получаем только при нажатии на кнопку "показать форму"?

  Ответить  
 
 автор: confirm   (26.05.2014 в 04:45)   письмо автору
 
   для: moonfox   (25.05.2014 в 23:00)
 

Видимо трудно для понимания потому, что вы упираетесь в конкретику, а посему даже мои ошибки "перепечатываете" - $form == $name { //запрос от формы } :)

А если думать отвлеченно от форм, а например, вы гостиничный консьерж? К вам обращаются десятки постояльцев с различными вопросами, один из которых: - "Не было ли для меня почты?". Что вы будете делать? Загляните в ячейку номера комнаты постояльца - есть письмо, пусть пляшет, а нет, пусть чешет.

Что это на самом деле, если "транслировать" ваши действия в виртуальность? Да все просто - есть ячейки памяти по адресу "post", в которых (по смещениям - номера комнат) содержится статус.

Ничего непонятного нет? Думаю да. Ну это гостиница, там много постояльцев-адресатов, а у нас форма, и в единицу времени она может быть только в единственном числе. Хватит ли для этого одной ячейки памяти, которая будет помнить идентификатор формы (ее имя), и можно ли использовать это имя как статус двух состояний? Вполне.

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

Отправляем форму. Теперь ячейка инициализирована, а значит делаем вывод, что пришли данные формы и нужно обрабатывать данные. Обработали, вернули результат, и если ОК, то сбросили статус 1 - стерли в ячейке имя формы, иначе, в случае наличия ошибок, возвращаем ошибки, продолжая диалог клиент-сервер. Для идентификации формы можно отправлять ее имя скрытым полем, хотя вариаций "на эту тему" может быть тоже много.

Теперь как это решать. По большому счету, иметь массу асинхронных запрос на страницах, и каждому такому запросу вменять свой php-обработчик, это и расточительство, и распыление внимания. Почему бы не обрабатывать эти запросы одним обработчиком? Вполне можно, хотя это и не правило, и каждый волен поступать так как он волен, да бывает и необходимость в индивидуальности.

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

Неприятный момент - заказчик просит написать серверную часть сайта, плюс клиентские сценарии, и выдает верстку-дизайн готовую. А у дяди верстальщика-дизайнера свои тараканы в голове. Поэтому, когда начинаешь связывать его тараканов со сценариями, то оказывается, что и верстка не учитывает "хотений" заказчика, и именование элементов совсем никуда, ибо то что есть, потребует излишних затрат ресурсов. А править, это зачастую и перелопачивать CSS.

Именно поэтому ключ dialog, который получает сервер, это не просто первое, что в голову взбрело, а и связанные с этим ключом элементы на странице - именуются по этому ключу. Это не означает, что надо обязательно задействовать атрибут id, так как запуски диалога могут происходить и по другим условиям, отличным от описанных здесь, но связь должна быть. И если нет желания париться в будущем при потребности добавить еще диалог на странице, описывая для него все по новой, то связь "ключ-элементы запуска", это первый шаг от такой головной боли.

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

Мало того, если формы и один обработчик, есть ли смысл помнить имя полей каждой формы, писать индивидуально для каждого поля свой вывод об ошибках ввода и т.п.? Чтобы сделать код компактным, не тратя много ресурсов клиента, достаточно подчинить ситуации "ошибка-вывод" универсальному правилу - номер ошибки, это индекс поля формы, в котором есть ошибка. Это позволит легко обратиться к элементу формы, выделить его, изменить его данные на корректные, если требуется, и т.п.. Именно поэтому, в примере ниже, имена полей, это один ключ массива полей..

Сервер может возвращать форму при ее запросе разными способами - классы, описанный html-код формы в файлах и подключаемых, как элементы массива и др. В случае использования последнего, стоит помнить, что массив, это не означает строка или число как значение, это может быть что угодно. Например, если форма выдается не просто как "чистый" html-код ее, но есть необходимость вставить в нее значения где-то ранее запомненные, и по условиям, то:

<?
$array 
= ['<input name="name" value="'.($chk expression/function : null).'" />'];


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

Вот пример, он рабочий, все в одном файле, не важно как вы его назовете, будет работать, ибо ссылка на файл обработчик, это текущий файл - свойство location документа.

<?
session_start
();

//вывод формы диалога
function sendForm($name) {
    
$added = [
        
'mail'   => 'Оставьте сообщение',
        
'main'   => 'Ваш личный кабинет',
        
'basket' => 'Ваша корзина'
    
];
    
$form = [
        
'mail'   => ['Ваше имя: <input name="field[]" />','Ваше сообщение:<br><textarea name="field[]"></textarea>'],
        
'main'   => ['Ваше имя: <input name="field[]" />','Ваш город: <input name="field[]" />','Ваш возраст: <input name="field[]" />'],
        
'basket' => ['Всего товаров: <input name="field[]" value=5 />','На сумму: <input name="field[]" value=500 />']
    ];
    
    if(
array_key_exists($name$form)) {
        
$_SESSION['form_dialog'] = $name;
        exit(
'<div class="box-dialog"><h3>'.$added[$name].':</h3><form><div>'.implode('</div><div>'$form[$name]).'</div>
              <input type="hidden" name="dialog" value="'
.$name.'" />
              <button>Отправить</button></form><a class="close">&#10060;</a></div>'
);
    } else exit;
}

//обработка полученных данных, сообщение об ошибках если есть, и т.п..
function checkForm($name) {
    
$fields = [
        
'mail'   => ['name','message'], 
        
'main'   => ['name','city','age'],
        
'basket' => ['count','total']
    ];
    if(
array_key_exists($name$fields)) {
        
//запись/обновление базы по полям $fields, или выдача ошибок по индексу поля формы
        
unset($_SESSION['form_dialog']);
        exit(
json_encode(['msg'=>'Все Ok '.implode(', '$fields[$name])], JSON_UNESCAPED_UNICODE));  
    }    
}


if(
$_POST['dialog']) { 
    
//принимаем запросы клиента 
    
$form = &$_SESSION['form_dialog'];
    switch(
$name $_POST['dialog']) { 
        case 
'mail' :   //обработка формы диалога почты 
                        
if($form == $name) { 
                            
//ссылка на форму есть, значит обрабатываем форму
                            
checkForm($name); 
                        } else 
sendForm('mail'); //ссылки на форму нет, отправляем код формы 
                        
break; 
        case 
'main' :  //обработка формы диалога личного кабинета 
                        
if($form == $name) { 
                            
//ссылка на форму есть, значит обрабатываем форму
                            
checkForm($name);
                        } else 
sendForm('main'); //ссылки на форму нет, отправляем код формы 
                        
break; 
        case 
'basket' //обработка формы диалога корзины 
                        
if($form == $name) { 
                            
//ссылка на форму есть, значит обрабатываем форму
                            
checkForm($name); 
                        } else 
sendForm('basket'); //ссылки на форму нет, отправляем код формы 
    

    exit; 
}
?>

<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title></title>
<style>
.box-dialog {
    display: none;
    position: fixed;
    top: 0;
    width: 300px;
    padding: 20px;
    background: #fff;
    border: 1px solid #444;
    border-top: 0;
    border-radius: 0 0 5px 5px;
    z-index: 600;
}

.close {
    float: right;
    color: #777;
    cursor: pointer;
}

#overlap {
    width: 100%;
    height: 100%;
    background: #000;
    position: fixed;
    left: 0; top: 0;
    opacity: 0.2;
    z-index: 500;
}
</style>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script>
$(function() {
    $('body').on('click', '[id|=dialog]', function() { //запросы диалогов
        $.post(location, this.id.replace('-','='), function(d) { //запрашиваем форму диалога
            var dialog = $(d).appendTo('body') //добавляем окно/форму диалога в тело документа, 
                                               //при этом кешируем этот объект для дальнейшего обращения к нему
                             .css({left:($(document).width()-$(d).outerWidth())/2}) //центрируем диалог
                             .slideDown(500) //открываем диалог
                             .find('form') //ищем форму диалога
                             .on('submit', function() { //и ставим обработчик на ее отправку 
                                 //отправка формы
                                 $.post(location, $(this).serializeArray(), function(d) { 
                                     //непосредственно диалог клиент-сервер
                                     if(!!d.msg) dialog.find('h3').text(d.msg); //сообщение об удачном завершении
                                 }, 'json'); //диалог клиент-сервер происходит в JSON-формате (ответы сервера)
                                 return false; //отменяем непосредственную отправку формы  
                             })
                             .end() //возвращаемся к окну диалога, так как в текущий момент мы находимся в объекте form
                             .find('.close') //ищем в нем кнопку его закрытия
                             .one('click', function() { //и устанавливаем ей обработчик 
                                 //закрываем диалог
                                 dialog.slideUp(500, function() {
                                     dialog.remove(); //удаляем окно диалога
                                     $('#overlap').remove(); //удаляем перекрытие клиентской области
                                 });
                             })
                             .end(); //возвращаемся к окну диалога, иначе dialog будет равен объекту close
                $('body').append('<div id="overlap"/>'); //перекрываем клиентскую область       
        }, 'html'); //получаем форму как html
    });    
}); 
</script>
</head>

<body>
<button id="dialog-mail">Отправить сообщение</button>
<button id="dialog-main">Личный кабинет</button>
<button id="dialog-basket">Корзина</button>    
</body>
</html>

  Ответить  
 
 автор: moonfox   (26.05.2014 в 15:26)   письмо автору
 
   для: confirm   (26.05.2014 в 04:45)
 

ошибки те сути не меняют
мне принцип нужно окончательно понять.
с полем hidden ясно

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

спасибо.

и еще момент
скажите стоит ли использовать json для полученных из php данных
ну к примеру пхп возвращает статусы типа 0, 1, 2 + сообщение
как насчет в этом случае как в старые времена print '1'.'^^^'.$data[0]
и split в js
?

  Ответить  
 
 автор: Deed   (26.05.2014 в 17:27)   письмо автору
 
   для: moonfox   (26.05.2014 в 15:26)
 

А почему бы не пересылать из php просто такую строку "0, 1, 2,сообщение" и нормально "бить" ее split'oм в js??
Ну и сепаратор можно выбрать любой, не обязательно запятую.

  Ответить  
 
 автор: moonfox   (26.05.2014 в 17:29)   письмо автору
 
   для: Deed   (26.05.2014 в 17:27)
 

0 1 2 это на выбор
приходит 1^^^успешно

  Ответить  
 
 автор: Deed   (26.05.2014 в 17:35)   письмо автору
 
   для: moonfox   (26.05.2014 в 17:29)
 

Ну? Так зачем же вся эта морока с Json??
В пыхе формируем любую строку, разбитую на подстроки произвольным сепаратором, а на приеме - сплитом ее, родимую!
Все просто и удобно.

  Ответить  
 
 автор: moonfox   (26.05.2014 в 17:48)   письмо автору
 
   для: Deed   (26.05.2014 в 17:35)
 

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

может сейчас модно все ы json))
тем более что это jquery и надо юзать его функционал по полной)))

  Ответить  
 
 автор: confirm   (26.05.2014 в 17:49)   письмо автору
 
   для: Deed   (26.05.2014 в 17:35)
 

Опять дурь порите?

  Ответить  
 
 автор: moonfox   (26.05.2014 в 17:52)   письмо автору
 
   для: confirm   (26.05.2014 в 17:49)
 

кофёрм просвети пожалуйста
как рациональнее?
у меня возвращается 1 или 2 значения назад в js
стоит ли юзать json или строку через разделите слать?

  Ответить  
 
 автор: Deed   (26.05.2014 в 18:01)   письмо автору
 
   для: moonfox   (26.05.2014 в 17:52)
 

Лунный Лис, локальный сервак имеется?
Я ща сделаю два файла (не, три, третий будет htaccess для utf-8). Для проверки отпоротой дури.

  Ответить  
 
 автор: moonfox   (26.05.2014 в 18:04)   письмо автору
 
   для: Deed   (26.05.2014 в 18:01)
 

конечно имется)
не в нет же туда сюда заливать пока маюсь

  Ответить  
 
 автор: Deed   (26.05.2014 в 18:06)   письмо автору
 
   для: moonfox   (26.05.2014 в 18:04)
 

О.
Ща внук на футбол уйдет - сделаю.

  Ответить  
 
 автор: confirm   (26.05.2014 в 18:33)   письмо автору
 
   для: Deed   (26.05.2014 в 17:27)
 

И смысл этого?

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

Вообще-то их будет минимум 3: серверный сценарий, клиентский сценарий (подключение), стили (подключение).

Я ведь не просто так упомянул о необязательности именования полей типа name=name_1, name=name_2 и т.д., а вместо этого использовать индексацию. Попробуйте тем, что вы хотите использовать вести диалог: передавать ошибки, иную сопутствующую информацию. Могу гарантировать, что где-то обязательно при этом будет допущен косяк, и ...

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

Вы не думаете, а ведь форма это же не только input type=text и textarea, есть еще и радиокнопки, и чекбоксы, последние могут быть переданы, могут и нет.

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

Клиентский сценарий имеет метод запроса этих форм, их передачу на сервер, получение ответа сервера и выдачу этого ответа.

Все это для того, чтобы два этих "собеседника" не зависели ни от количества форм, ни от их содержания. Добавили на сервере описание новой формы, выдали клиенту кнопку-ссылку на эту форму и все, дальнейшее будут происходить по описанному соглашению. Но надо учитывать, что если определяем обработчика асинхронных запросов, то не потом когда нибудь, а сразу нужно учесть, что это могут быть запросы на саму различную информацию - диалоги-формы, запросы на подтверждения, простые сообщения, новости, например, блоки на страницах. И проще потом добавить в структуру серверного сценария под определенным ключом (если использовать массив) новое, чем переделывать все заново.

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

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

И еще попробуйте "прочесть в коде" что сие означает, для чего и как работает (я специально опускаю комментарии).

style.css:
.box-dialog {
    display: none;
    position: fixed;
    top: 0;
    left: 50%;
    width: 300px;
    padding: 20px;
    background: #fff;
    border: 1px solid #444;
    border-top: 0;
    border-radius: 0 0 5px 5px;
    z-index: 600;
}

#overlap {
    width: 100%;
    height: 100%;
    background: #000;
    position: fixed;
    left: 0; top: 0;
    opacity: 0.2;
    z-index: 500;
}

.close {
    float: right;
    color: #777;
    cursor: pointer;
}


script.js:
//доступность локального хранилища
var story = (function() {
   try {
     return 'localStorage' in window && window['localStorage'] !== null ? localStorage : false;
   } catch(e) {
     return false;
   } 
}());

$(function() {
    $('[id|='+butt_dialog+']').on('click', function() { 
        $.post('name.php', this.id.replace('-','='), function(d) { //запрашиваем форму диалога
            var dialog = $(d).appendTo('body') //добавляем окно/форму диалога в тело документа, 
                                               //при этом кешируем этот объект для дальнейшего обращения к нему
                             .css({left:($(document).width()-$(d).outerWidth())/2}) //центрируем диалог
                             .slideDown(500) //открываем диалог
                             .find('form') //ищем форму диалога
                             .on('submit', function() { //и ставим обработчик на ее отправку 
                                 //отправка формы
                                 $.post(('name.php', $(this).serializeArray(), function(d) { 
                                     //непосредственно диалог клиент-сервер
                                     if(!!d) {
                                         if(window[d.err]) {
                                             //вывод ошибок  
                                         } else {
                                             dialog.find('h3').text(d.msg); //сообщение об удачном завершении   
                                         } 
                                     }
                                 }, 'json'); //диалог клиент-сервер происходит в JSON-формате
                                 return false; //отменяем непосредственную отправку формы  
                             })
                             .end() //возвращаемся к окну диалога, так как в текущий момент мы находимся в объекте form
                             .find('.close') //ищем в нем кнопку его закрытия
                             .one('click', function() { //и устанавливаем ей обработчик 
                                 //закрываем диалог
                                 dialog.slideUp(500, function() {
                                     dialog.remove(); //удаляем окно диалога
                                     $('#overlap').remove(); //удаляем перекрытие клиентской области
                                 });
                             })
                             .end(); //возвращаемся к окну диалога, иначе dialog будет равен объекту #close
                $('body').append('<div id="overlap"/>'); //перекрываем клиентскую область       
        }, 'html'); //получаем форму как html
    });    
});


name.php:
<?
session_start
();

function 
setDialog($type) { 
    
$_SESSION['dialog'] = [];
    
$s 'abcdefghqwvijkmnoprstxz'
    foreach(
current($type) as $name$_SESSION['dialog'][key($type)][str_shuffle($s)[0].md5(uniqid(rand(),1))] = $name;
}


function 
sendForm($key$name) {
    
$fld = &$_SESSION['dialog'];
    if(!
array_key_exists($name$fld[$key])) exit;
    
$fld['send'] = $name;
    
$field $key.'['.$name.']';
    
    
$added = [
        
'form' => [
            
'mail'   => 'Оставьте сообщение',
            
'main'   => 'Ваш личный кабинет',
            
'basket' => 'Ваша корзина'
        
]
    ];
    
    
$window = [
        
'form' => [
            
'mail'   => ['Ваше имя: <input name="'.$field.'[]" />','Ваше сообщение:<br><textarea name="'.$field.'[]"></textarea>'],
            
'main'   => ['Ваше имя: <input name="'.$field.'[]" />','Ваш город: <input name="'.$field.'[]" />','Ваш возраст: <input name="'.$field.'[]" />'],
            
'basket' => ['Всего товаров: <input name="'.$field.'[]" value=5 />','На сумму: <input name="'.$field.'[]" value=500 />','Очистить: <input  type="checkbox" name="'.$field.'[]" />']
        ]
    ];
    
    exit(
'<div class="box-dialog"><h3>'.$added[$key][$fld[$key][$name]].':</h3><form><div>'.implode('</div><div>'$window[$key][$fld[$key][$name]]).'</div>
          <button>Отправить</button></form><a class="close">&#10060;</a></div>'
);
}


function 
checkForm($key$name) {
    
$fields = [
        
'mail'   => ['name','message'], 
        
'main'   => ['name','city','age'],
        
'basket' => ['count','total']
    ];
    
    
$name $_SESSION['dialog'][$key][$name];
    
    if(
array_key_exists($name$fields)) {
        exit(
json_encode(['msg'=>'Все Ok '.implode(', '$fields[$name])], JSON_UNESCAPED_UNICODE));  
    }    
}

$fld = &$_SESSION['dialog'];


if(
$fld && array_key_exists(key($_POST), $fld)) { 
    
$key key($_POST);
    if(
is_string($_POST[$key])) sendForm($key$_POST[$key]);
    else 
checkForm($keykey($_POST[$key]));
}


Страница:
<?
session_start
();

$fld = &$_SESSION['dialog']; 

if(
$fld && array_key_exists(key($_POST), $fld)) {  
    
$key key($_POST); 
    if(
is_string($_POST[$key])) sendForm($key$_POST[$key]); 
    else 
checkForm($keykey($_POST[$key])); 


$button = ['form'=>['mail''main''basket']]; 
setDialog($button); 
$key key($fld); 
$name array_keys($fld[$key]);
?>
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>
<script>
var butt_dialog = "<?=$key?>"; 
</script>
</head>

<body>
<button id="<?=$key?>-<?=$name[0]?>">Отправить сообщение</button>
<button id="<?=$key?>-<?=$name[1]?>">Личный кабинет</button>
<button id="<?=$key?>-<?=$name[2]?>">Корзина</button>
</body>
</html>

  Ответить  
 
 автор: moonfox   (26.05.2014 в 19:02)   письмо автору
 
   для: confirm   (26.05.2014 в 18:33)
 

js


var splash; 
$(document).ajaxStart(  function(){ splash = $('<img src="img/loader-3.png" class="load"  alt="" />').appendTo('body'); });
$(document).ajaxComplete(  function(){  splash.remove(); }); 
$(document).ajaxError(  function(){  splash.remove(); alert('Ajax Error...'); }); 

$(function() {
 $('[id|=dialog]').on('click', function() { 
    $.post('dialog.php?lang=' + $('#lang').val(), this.id.replace('-', '='), function(d) {
                        
            var dialog = $(d).appendTo('body').find('#send').on('click', function(){
            $.post('dialog-actions.php?lang=' + $('#lang').val(), $('#f1').serializeArray(), function(d) {
            
            var income = d.split('^^^');
            
            if(income[0] == 1)
            {
                if(income[1])
                $('#client').html('<div><a href="?221"><img src="img/user-ico.png" alt="" />' + income[1] + '</a></div>');
                
                $('#dlg').remove().end().find('#success').css('display', 'block');
                setTimeout(function(){ 
                  dialog.fadeOut('fast', function(){ this.remove(); });
                 }, 2000);
            }            
            else $('#dlg p').html(income[0]); 
            
            });             
        }).end().find('#close').click(function() { dialog.remove(); }).end();
    }, 'html');
 });     
});



dialog.php

<?php
session_start
();
$lang $_GET['lang'];
require_once 
'lang.php';

 if(isset(
$_POST['dialog']))
 {
   
$_SESSION['form'] = $_POST['dialog'];
   switch(
$name $_POST['dialog']) {
     
     case 
1:
     
       echo 
'<div class="zabor"></div>
             <div class="reg-shield" id="dlg">
              <div class="close" id="close">'
$list['close'][$lang], '</div>
              <br class="clr" />
              <div class="title-1"><span><strong>'
$list['reg_but'][$lang], '</strong></span></div>
              <p>'
$list['star'][$lang], '</p>
              <form name="form1" id="f1" method="post" action="">
                <table class="reg">
                <tr>
                  <td style="width:180px;">'
$list['name'][$lang], '</td>
                  <td><input type="text" name="fio" value="" /></td>
                </tr>
                <tr>
                  <td>'
$list['login'][$lang], '</td>
                  <td><input type="text" name="milo" value="" /></td>
                </tr>
                <tr>
                  <td>'
$list['pass'][$lang], '</td>
                  <td><input type="text" name="pass" value="" /></td>
                </tr>
                <tr>
                  <td>'
$list['tel'][$lang], '</td>
                  <td><input type="text" name="tel" value="" /></td>
                </tr>
                <tr>
                  <td>Skype:</td>
                  <td><input type="text" name="skype" value="" /></td>
                </tr>
                </table>
              </form>    
              <div class="send" id="send">'
$list['send'][$lang], '</div>
             </div>
             <div class="success" id="success">'
$list['complete'][$lang], '</div>'
             
;
     break;
     
     case 
2:
     
       echo 
'<div class="zabor"></div>
             <div class="auth-shield" id="dlg">
              <div class="close" id="close">'
$list['close'][$lang], '</div>
              <br class="clr" />
              <div class="title-1"><span><strong>'
$list['enter'][$lang], '</strong></span></div>
              <p>'
$list['star'][$lang], '</p>
              <form name="form1" id="f1'" method="
post" action="">
                <table class="
reg">
                <tr>
                  <td style="
width:180px;">', $list['login'][$lang], '</td>
                  <td><input type="
text" name="milo" value="" /></td>
                </tr>
                <tr>
                  <td>', 
$list['pass'][$lang], '</td>
                  <td><input type="
text" name="pass" value="" /></td>
                </tr>
              </table>
              </form>    
              <div class="
send" id="send">', $list['send'][$lang], '</div>
             </div>
             <div class="
success" id="success">', $list['auth'][$lang], '</div>'
             ;
     break;     
   
   } exit;
 }
?>

dialog-actions.php

<?php
session_start();
$lang = $_GET['lang'];
require_once 'errors.php';

require_once 'mysql.php';
$db = new db();

switch(
$_SESSION['form'])
{
   case 1;

      if(!empty(
$_POST['fio']) && !empty($_POST['milo']) && !empty($_POST['pass']) && !empty($_POST['tel']))
      {
        
$db->query('SELECT `id` FROM `clients` WHERE `login` = "'.$db->real_escape($_POST['milo']).'" LIMIT 1');
        
$pre = $db->fetch_row();
    
       if(!isset(
$pre))
       {
          
$db->query('INSERT INTO `clients` (`fio`, `login`, `skype`, `pass`, `registration`) 
          VALUES("'.$db->real_escape($_POST['
fio']).'", "'.$db->real_escape($_POST['milo']).'", 
          "'.$db->real_escape($_POST['
skype']).'", "'.md5(md5($_POST['milo']).md5($_POST['pass'])).'", '.time().')');
          print 1;
       }
       else exit(
$list['error1'][$lang]);
     }
     else exit(
$list['error2'][$lang]);
  
   break;
   
   case 2;

     if(!empty(
$_POST['milo']) && !empty($_POST['pass']))
     {
        
$db->query('SELECT `id`, `fio`, `login`, `pass` FROM `clients` WHERE `login` = "'.$db->real_escape($_POST['milo']).'" LIMIT 1');
        
$pre = $db->fetch_row();

       if(!isset(
$pre))  print $list['error4'][$lang];  
       else
       { 
         if(
$pre['login'] == $_POST['milo'] && $pre['pass'] == md5(md5($_POST['milo']).md5($_POST['pass'])))
         {
           
$_SESSION['client'] = $pre['id'];
           
$_SESSION['env'] = md5($_SERVER['HTTP_USER_AGENT']);
           print '1'.'^^^'.
$pre['fio'];
         }
         else exit(
$list['error3'][$lang]); 
       }
     }     
     else exit(
$list['error2'][$lang]);
  
   break;   
  
} exit;

?>


у вас способ формирования выдачи формы в целом практичнее,
надо подумать над этим

  Ответить  
 
 автор: confirm   (26.05.2014 в 19:30)   письмо автору
 
   для: moonfox   (26.05.2014 в 19:02)
 

var income = d.split('^^^');

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

Во-вторых, уж слишком вы утрируете понятие "форма". Форма это нечто больше чем html - форма это диалог, а диалог может подразумевать выполнение неких действий прежде чем будет отправлена форма. Кроме того, что ответ сервера может вернуть данные для формы, вполне могут быть возвращены и данные для иных объектов на странице, например, представьте, что на странице есть навигатор станичный, и пользователь ведет диалог с сервером, который включает и возможность изменить число выводимых на страницу сообщений, или же после отправки формы это число автоматически будет изменено. В этом случае нужно вернуть сообщение о результатах отправки формы, изменить состояние навигатора, и возможно еще и выполнить некую функцию. Вы думаете, что d.split('^^^') это самое что ни наесть подходящее для этого?

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

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

Ну а про реализацию JS вашего, я вообще промолчу, это так, вилами по... )

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

  Ответить  
 
 автор: moonfox   (26.05.2014 в 19:57)   письмо автору
 
   для: confirm   (26.05.2014 в 19:30)
 

 var income = d.split('^^^');
 JSON, это тоже строка, но фактически ставшая стандартом. Кроме этого браузеры умеют работать с этим типом данных

собственно нечто подобное я и хотел услышать

 годное если только у вас одна единственная форма,

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

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

я вас услышал

 вот и будете вы карячится для каждой формы отдельно

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

Ну а про реализацию JS вашего, я вообще промолчу, это так, вилами по... )

хм... 90% вашего подхода
кроме обработки возвратов сервера...

спасибо за дискуссию

  Ответить  
 
 автор: confirm   (26.05.2014 в 20:14)   письмо автору
 
   для: moonfox   (26.05.2014 в 19:57)
 

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

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

Нет, то что вы написали в своем JS, это и близко совсем не то, что у меня написано, даже и 5% нет. Не пишите сходу, лучше хорошо ознакомтесь с методами jQuery, и уверен, что поймете после этого, что таймер в вашем коде, это нечто из рук вон...

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

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

А вы все клеите кусочками, вот что плохо.

  Ответить  
 
 автор: confirm   (27.05.2014 в 06:13)   письмо автору
 
   для: moonfox   (26.05.2014 в 19:57)
 

Старайтесь мыслить образно, не заглубляясь сразу в конкретику только потому, что у вас есть две формы, и одной из них есть поле с именем skype, а у другой с именем pass, а значит надо так и писать "<form name="form1" id="f1" method="post" action="">..." и далее нудно перечислять поля.

Зачем отсылать лишнее, как то указывать тегу form атрибуты имени, идентификатора, метода..., ведь вы же пишите ajax-диалоги, и метод отправки определяет ajax, а сама форма будет доступна из кешированного объекта диалога.

И так...

Что первично - курица или яйцо?

Сказать трудно, но то что у вас первичное, это ваши данные в базе, а ваши сценарии, это танцы вокруг них, где форма как бубен, это не подлежит сомнению. Вот и начнем плясать от базы, которая будет служить источником свойств для образа "форма", который в общем представляет собой, ну скажем так - абстрактную модель (собственно вся структура, которую попытаемся описать, это абстрактная модель, а форма, это так, "моделька" :), но мы будем упрощать все, иначе...). Добавили/заменили свойства этой модели - образ остался тем же, а содержание уже изменилось.

Начиная новый проект, начинаем его с данных, которые этот проект будет отображать. По мере осмысления и конкретизации проекта, эти данные будут принимать конкретные очертания, то есть мы определим их структуру, свойства, условия... И вот на конечном этапе описываем это все таблицами, а конкретно их полями. Поле таблицы при этом имеет тип данных (если есть, то и макс. их длину), условие (NULL, NOT NULL), а также комментарий. То есть для конструктора, который будет определять в нашей модели образ формы, таблица содержит все:

а) комментарий поля определяет текст у поля формы: "Ваше имя", "Ваш адрес"..., плюс это свойство может определять и максимальную длину данных. Например, для полнотекстового поиска используем тип TINYTEXT, и при этом по тем или иным причинам есть необходимость разрешить в это поле ввод не максимально разрешенное этим типом, а меньшее. Но указать этого, как например для VARCHAR нельзя, но зато можно через разделитель, например "|", указать эту величину в комментарии.
б) NULL и NOT NULL могут определять обязательно или нет поле для заполнения
в) типы полей определяют тип поля формы:
1) VARCHAR - text
2) TINYTEXT, TEXT - textarea
3) INT, MEDIUMINT... - number
4) TINYINT (значения 0/1) - checkbox
5) ENUM - radio (значения этого типа определяет и текст в группе радиокнопок)

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

Получить все эти свойства не сложно (далее везде где будут примеры, все относительно PDO), примерно такая функция может быть:

<?
function infoColumn($db$tbl$fld) {
    
//$db - PDO
    //$tbl - имя таблицы
    //$fld - массив имен полей значений
        
    
$q $db->query('SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, DATA_TYPE, COLUMN_TYPE, COLUMN_DEFAULT, IS_NULLABLE, COLUMN_COMMENT 
                     FROM INFORMATION_SCHEMA.COLUMNS 
                     WHERE TABLE_SCHEMA = "'
.DB_BASE.'" AND TABLE_NAME = "'.$tbl.'"');
    while(
$r $q->fetch()) {
        if(
in_array($r->column_name$fld)) {
            if(
$r->data_type=='enum') {
                
$v explode("','"str_replace(["enum('","')"], ''$r->column_type));
                
$v array_combine(range(1count($v)), $v);
                
$a[$r->column_name] = ['field'=>'enum''label'=>$r->column_comment'set'=>$v'default'=>array_search($r->column_default$v)];
            } else 
$a[$r->column_name] = ['field'=>($s trim(explode('('$r->column_type)[0]))!='tinyint' str_replace(['big','medium','small','tiny'], ''$s) : $s
                                          
'label'=>explode('|'$r->column_comment)[0], 'required'=>$r->is_nullable=='NO' 0,
                                          
'max'=>$r->numeric_precision $r->numeric_precision 
                                                                       
: (($n explode('|'$r->column_comment)[1]) ? (int)$n $r->character_maximum_length)];
        }
    }
    return 
$a;
}


Наборы

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

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

В итоге получается, что конструктор форм будет иметь следующее:

а) массив описывающий соответствия типа данных в базе, типу элемента формы:
<?
$types 
= [
    
'int'     => 'number',
    
'varchar' => 'text',
    
'text'    => 'textarea',
    
'enum'    => 'radio',
    
'tinyint' => 'checkbox'
];


б) массив наборов полей имен таблиц под ключами имен таблиц (fields), который определяет структуру формы каждого диалога. Этот же массив содержит паттерны, ссылки на фильтры и пользовательские правила (terms), как описано тут. При этом все это ориентировано на применение индексации, как адреса доступа к ним:
<?
$fields 
= [
    
$prefix.'mail'   => ['fields'=>['name',5=>'message'], 'terms'=>[]], 
    
$prefix.'main'   => ['fields'=>['name','city','age',5=>'short'], 'terms'=>[]],
    
$prefix.'basket' => ['fields'=>['count','total'], 'terms'=>[]]
];


Получить код формы, это обойти массив $property, получив html-код формы и добавив его кодом окна диалога, что-то типа такого:
<?
//получить свойства формы диалога:
$property infoColumn($db$prefix.$name$fields[$prefix.$name]['fields']);
//получить код окна диалога и передать его клиенту
exit('<div class="box-dialog"><h3>'.$added[$key][$fld[$key][$name]].':</h3><form><div>'.implode('</div><div>'
      
array_map(function($v) use($types$fldname) {
          return 
$v['field']=='text' '<label>'.$v['label'].':</label><textarea name="'.$fldname.'['.$v['index'].']" 
                                        maxlength='
.$v['max'].' '.($v['required'] ? 'required' null).'></textarea>' 
                                     
: ($v['field']!='enum' '<label>'.$v['label'].': <input type="'.$types[$v['field']].'"  name="'.$fldname.'['.$v['index'].']" 
                                                               maxlength='
.$v['max'].' '.($v['required'] ? 'required' null).' /></label>' 
                                                            
'<label>'.$v['label'].':</label>'.implode(array_map(function($v$k$p) use($fldname) {
                                                                   return 
'<label><input type="radio" name="'.$fldname.'['.$p['index'].']" 
                                                                   value='
.$k.' '.($p['default']==$k 'checked' null).' /> '.$v.'</label>';}, 
                                                                   
$v['set'], array_keys($v['set']), $prop)));
      }, 
$property)).'</div><button>Отправить</button></form><a class="close">&#10060;</a></div>'); 


Я не стал останавливаться на том, что прежде чем массив $property будет обойден, в него каждому ключу (имя поля таблицы) будут добавлены соответствующие значения $fields['terms'], учитывая индексы будущих полей ($v['index']). Для полей типа enum, этот индекс и значение по умолчанию формируется и добавляется отдельно - массив $prop. Не стал останавливаться потому, что сделать это очень просто используя функции работы с массивами.

Почему все же индексы, а не ассоциативный ключ?

Мы пляшем от базы, свойства полей получаем от нее, и данные полей формы будем помещать в таблицу полям ее. При этом в двух таблицах могут быть два поля под разными именами, но условия на помещаемые в них данные могут быть или полностью одинаковы, или различаться незначительно. То есть тип фильтра или паттерн, пользовательские условия, идентичны, разница небольшая, например, максимальный размер, а значит этим полям в наборах массива $fields мы указываем один и тот же индекс (в примере это поля message и short), а маленькие нюансы будут описаны в пользовательских условиях в их ключах terms.

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

Случайное именование полей, а если их менять с каждым запросом формы через куки (в отличие от сервера, клиенту они доступны сразу после установки), то охотников выстреливать на сервер "подделками" резко убавляется.

Работа над ошибками

Вы повторили:

var dialog = $(d).appendTo('body')...

с небольшим изменением, и тем не менее я сказал, что это далеко от того, что писал я. То что вы повторили, это не мое изобретение, это удобная возможность записать последовательность операций, которую предоставляет jQuery. Собственно это и не их изобретение, так описывается в JS и доступ к свойствам объекта, просто jQuery расширил это.

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

Но я дважды пояснял почему выбрана индексация, и как при этом автоматизировать выдачу ошибок, где код совсем не будет зависеть от количества полей формы, а тем более от имен каких либо, и не требуется куча if() для каждого. Условие будет только одно:

if(window[d.err]) - если объект имеет свойство err, значит есть ошибки. А вывод, это получить коллекцию элементов формы, и у элементов с индексами равными номеру ошибок, вывести сообщения. Просто:
if(window[d.err]) {
    var f = dialog.find('form').get(0).elements;
    $.each(d.err, function(i, e) {
        $(f).eq(i).parent()
                   .append('<div class=ferr>'+e+'</div>')
                   .mouseenter(function() {
                       $(this),find('.ferr').remove();
                   });
    });
}


Обрамление элементов формы в DIV ведь тоже не абы для чего, а для того, чтобы прописав им относительно позиционирование (помимо свойств определяющих вид формы), помещать в них сообщения об ошибках с абсолютным позиционированием:
.box-dialog form div {
    position: relative;
}

.ferr {
    position: absolute;
    top: 20px;
    left: 20px;
    width: 400px;
    border-radius: 3px;
    background: #C30101;
    font: 12px Arial;
    padding: 5px;
    color: #fff;
    cursor: default;    
}

.ferr:after {
    content: '';
    position: absolute;
    left: 5px;
    top: -5px;
    border-left: 5px solid transparent;
    border-right: 5px solid transparent;
    border-bottom: 5px solid #C30101;
}


И идут они к лешему все if(name) to... Вот мои 90%, которые вы мимо ушей ;)

Не без ложки дегтя

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

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

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

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

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

Это кажется, что через чур, на самом деле написать такое, это очень просто.

Прием данных форм

Используя индексы, указывая их в массиве, набор полей при этом нужно прописывать не согласно порядку этих индексов, а в порядке именования полей, по принципу - сначала обязательные поля, затем необязательные. При этом чем более "необязательное" поле, тем больший индекс и следует ему давать. И вот почему. Если у вас хватило терпения и вы прочли все, что касаемо этой "абстракции", то понятно, что принудительная индексация полей формы позволяет размещать их как угодно, а не обязательно по порядку от 0 до N. Но мы принимаем внешние данные и будем проверять все, включая целостность структуры формы. У простого массива полей формы (без вложений) это сделать просто, так как написано по ссылке.

Хотя по ссылке, там только "идея" и она будет работать не всегда корректно, ну просто не было времени все подробно описывать. Как должно быть - если в форме поля "разбросаны" как удобнее, то принимая форму, мы сортируем массив ее полей от 0 до N. Все необязательные поля формы будут в хвосте, а набор полей таблицы должен соответствовать индексам отсортированных полей формы. При этом, например, набор имеет 5 полей, а полей формы 7. Поле с индексом 5, к примеру будет чекбокс "переместить", а с индексом 6 - "удалить"

Наличие таких полей, это проверка их, и если есть, то соответствующее действие. А если поле тоже чекбокс и он присутствует, но не является обязательным, это просто некий сервис, который в базу не пишется, то пересечения массива набора полей таблицы и набора полей пришедшей формы по их индексам, вернет нам нужные поля для заполнения, и это будут ключи, в которых этого необязательного чекбокса не будет, а соответствия им из формы их значения для комбинированного массива (эта операция производится после проверки данных, и если нет ошибок, непосредственно перед записью/обновлением в базе)

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

Не будет работать корректно по ссылке потому, что сравнение строк "0123" и "123" вернет истинный результат, то есть не то, что ожидается. Для корректного сравнения нужно сравнивать "3210" и "321", в этом случае нарушение целостности будет обнаружено.

Описывать такие комбинации задом на перед неудобно, да и не требуется, все возлагается на машину:
<?
$fields 
= [
    
$prefix.'mail'   => ['map'=>array_map(function($v) {return (string)implode(array_reverse($v));}, [
                             [
0,1,4], [0,1,2,4], [0,1,3,4], [0,1,2,3,4]
                         ]
                      )];
.

Все описанные части модели общие в плане принципа работы всего "автомата сервер-клиент", изменяется только входной набор на сервере (или определяются свойства объекта, если работаем с объектом). Индивидуальны только некие операции для тех или иных форм, которые определяются конкретными данными таблиц.

При надобности добавить в этот автомат новый тип данных, например бинарные (загрузка изображений) труда не составит, если выделить среди условий загрузки этих данных общее и описать в этой модели (новая версия объекта реализующего асинхронные запросы, поддерживает ajax загрузку бинарных данных). Сделать подобное в вашей модели будет сложнее, ибо у вас все от начала до конца индивидуально.

Дополнения

Если после окончания диалога необходимо выполнить функцию или изменить содержимое объекта на странице, то:
var exe = { //объект функций
    f1:function(d) {
        //
    },
    f2:function(d) {
        //
    }    
};
//и их запрос сервером
<?
exit(json_encode(['exe'=>['f1'=>[$var], 'f2'=>[$var]]]);
?>
//исполнение
if(window[d.exe]) for(k in d.exe) exe[k](d.exe[k]);


Изменить содержание объектов:
<?
//сервер выдал
exit(json_encode(['dst'=>['#obj1'=>$var1'#obj2'=>$var2]]);
?>
//клиент изменил
if(window[d.dst]) for(k in d.dst) $(k).html(d.dst[k]);

  Ответить  
 
 автор: Deed   (26.05.2014 в 20:57)   письмо автору
2.1 Кб
 
   для: moonfox   (22.05.2014 в 17:58)
 

Закиньте сайт в директорию "home" denver'a (или что там еще), после чего сделайте рестарт локалки, чтобы он поместил этот адрес в hosts.
JS прокомментирован подробно.
Успехов!

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования