Цель: сделать форму для добавления статьи на сайт, с проверкой заполнения формы (в том числе и загрузки изображения) без перезагрузки страницы. Если все верно, то нужно загрузить изображение на сервер, а url данного изображения и значения полей формы занести в базу данных. Собственно форма: Код (Text): <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="script.js"></script> <div id="add_news_container"> <form id="add_news_form" method="post" action=""> <label for="news_img">Загрузите картинку:</label> <input type="file" name="news_img" id="news_img"/> <br/> <label for="title">Заголовок:</label> <textarea name="title" id="title" cols="80%" rows="3"></textarea> <label for="description">Краткое описание:</label> <textarea name="description" id="description" cols="80%" rows="5"></textarea> <label for="text">Текст:</label> <textarea class="HTML" name="text" id="text" cols="80%" rows="20"></textarea> <input id="main_news" name="main_news" type="checkbox" value="1"/> <label for="main_news" id="main_news_label">Главная новость</label> <br/> <input type="submit" id="submit" value="Опубликовать" /> <input type="reset" id="reset" value="Сброс"/> </form> </div> код скрипта "script.js": Код (Text): $(document).ready(function(){ /* Следующий код выполняется только после загрузки DOM */ /* Данный флаг предотвращает отправку нескольких комментариев: */ var working = false; /* Ловим событие отправки формы: */ $('#add_news_form').submit(function(e){ e.preventDefault(); if(working) return false; working = true; $('#submit').val('Публикую...'); $('span.error').remove(); /* Отправляем поля формы в submit.php: */ $.post('submit.php',$(this).serialize(),function(msg){ working = false; $('#submit').val('Опубликовать'); if(msg.status){ /* / Если вставка была успешной, добавляем комментарий / ниже последнего на странице с эффектом slideDown /*/ $(msg.html).hide().insertBefore('#add_news_container').slideDown('10000'); $('#body').val(''); } else { /* / Если есть ошибки, проходим циклом по объекту / msg.errors и выводим их на страницу /*/ $.each(msg.errors,function(k,v){ $('label[for='+k+']').append('<span class="error">'+v+'</span>'); }); } },'json'); }); }); Файл submit.php: Код (Text): <?php // Сообщение об ошибке: error_reporting(E_ALL^E_NOTICE); /* Конфигурация базы данных */ $db_host = 'localhost'; $db_user = 'root'; $db_pass = ''; $db_database = 'article'; /* Конец секции */ $link = @mysql_connect($db_host,$db_user,$db_pass) or die('Не могу установить соединение с базой данных'); mysql_query("SET NAMES 'utf8'"); mysql_select_db($db_database,$link); class news { private $data = array(); public function __construct($row) { $this->data = $row; } public function markup() { /* / Данный метод выводит разметку XHTML для комментария */ return ' <div class="news"> <p>Новость «<strong>'.$this->data['title'].'</strong>» успешно опубликована.</p> </div> '; } public static function validate(&$arr) { /* / Данный метод используется для проверки данных отправляемых через AJAX. / / Он возвращает true/false в зависимости от правильности данных, и наполняет / массив $arr, который преается как параметр либо данными либо сообщением об ошибке. */ $errors = array(); $data = array(); if(!($data['title'] = filter_input(INPUT_POST,'title',FILTER_CALLBACK,array('options'=>'news::validate_text')))) { $errors['title'] = 'Введите заголовок.'; } if(!($data['description'] = filter_input(INPUT_POST,'description',FILTER_CALLBACK,array('options'=>'news::validate_text')))) { $errors['description'] = 'Введите краткое содержание новости.'; } if(!($data['text'] = filter_input(INPUT_POST,'text',FILTER_CALLBACK,array('options'=>'news::validate_text')))) { $errors['text'] = 'Введите текст новости.'; } $data['main_news'] = filter_input(INPUT_POST,'main_news'); $data['news_img'] = filter_input(INPUT_POST,'news_img'); if(!empty($errors)){ // Если есть ошибки, копируем массив $errors в $arr: $arr = $errors; return false; } // Если данные введены правильно, подчищаем данные и копируем их в $arr: foreach($data as $k=>$v){ $arr[$k] = mysql_real_escape_string($v); } return true; } private static function validate_text($str) { /* / Данный метод используется как FILTER_CALLBACK */ if(mb_strlen($str,'utf8')<1) return false; // Удаляем все оставщиеся символы новой строки $str = str_replace(array(chr(10),chr(13)),'',$str); return $str; } } /* / Данный массив будет наполняться либо данными, / которые передаются в скрипт, / либо сообщениями об ошибке. /*/ $arr = array(); $validates = news::validate($arr); if($validates) { /* Все в порядке, вставляем данные в базу: */ $date = date('Y-m-d'); $time = date('H:i'); mysql_query(" INSERT INTO news(title,description,date,time,text,main,img_url) VALUES ( '".$arr['title']."', '".$arr['description']."', '".$date."', '".$time."', '".$arr['text']."', '".$arr['main_news']."', '".$arr['news_img']."' )"); $arr['id'] = mysql_insert_id(); /* / Данные в $arr подготовлены для запроса mysql, / но нам нужно делать вывод на экран, поэтому / готовим все элементы в массиве: /*/ $arr = array_map('stripslashes',$arr); $insertedNews = new news($arr); /* Вывод разметки только-что вставленного комментария: */ echo json_encode(array('status'=>1,'html'=>$insertedNews->markup())); } else { /* Вывод сообщений об ошибке */ echo '{"status":0,"errors":'.json_encode($arr).'}'; } ?> С проверкой форм проблем не возникает, а вот как сделать так, чтобы изображение загружаемое пользователем проверялось "на лету"? (важен размер и то, чтобы оно являлось изображением, естественно) P.S. Код чужой, переделанный, поэтому вероятность ошибок 100%-ая. Советы по их исправлению приветствуются
Затык в том, что я не знаю как на аякс проверить изображение на тип и размер. Если все нормально - загрузить на сервер, если нет - сообщить об этом без перезагрузки страницы и без отправки формы
Аякс это просто способ сходить по урлу и получить ответ. Соотв. Вам надо закинуть файлик и как-то запросить его статус. Соотв. хорошо бы закидывая файлик присвоить ему идентификатор уникальный и по нему запрашивать результат.
Вообще, про загрузку файлов на сервер без перезагрузки страницы в интернете существует уже немало статей. И я помню, что сам уже пару раз отвечал на такой вопрос на этом форуме. Обычно делается это так - на странице создаётся невидимый iframe, а форме, через которую загружают файл - присваивается атрибут target="название_невидимого_фрейма". При нажатии на submit страница не перезагружается, а данные формы, включая файл - уходят на сервер. Ответ от сервера приходит в этот невидимый iframe. Сервер должен прислать в ответ некий JavaScript-код, который, загрузившись в тот невидимый iframe, сообщит пользователю о результате загрузке файла. Я обычно присылаю в ответ просто вызов какой-нибудь JS-функции родительского окна (по отношению к фрейму) и передаю ей параметры, в которых, собственно, результат загрузки файла - либо всё ок и файл загружен (тогда можно передать также id, присвоенный сервером загруженному файлу и ссылку на превью файла, чтобы JS-функция могла сразу вывести пользователю это превью и, например, ссылку на удаление), либо всё не ок и файл не загружен (тогда можно, например, также передать текст сообщения об ошибке). Ну а дальше, имея эти данные, ты уже можешь с помощью JavaScript вывести как угодно и куда угодно результат загрузки