Плагин jFrame для библиотеки jQuery
Часто на сайтах в боковой панели можно видеть разные дополнительные сервисы: голосование, обратная связь, гостевая книга и т.п. Как правило, такие скрипты написаны с использованием AJAX или размещены в плавающем фрейме. С другой стороны, в Интернете можно найти большое число PHP-скриптов на любой вкус, но написанные в традиционном стиле — без использования объекта XMLHttpRequest. Как использовать все это богатство у себя на сайте так, чтобы они:
- во-первых, не мешали работе друг друга;
- во-вторых, не мешали работе основного скрипта.
Поясню подробнее. Допустим, у нас на сайте есть каталог продукции: это основное содержание страницы. А боковое поле (сайдбар) содержит форму обратной связи и голосование. Все три скрипта могут отправлять данные формы. И каждый из них должен принимать только свои данные, не реагируя на остальные.
Недавно наткнулся в Сети на способ решения этой задачи — плагин jFrame для библиотеки jQuery. jFrame использует AJAX функции для загрузки контента из другого документа (скрипта) с того же домена. Т.е. он полностью повторяет возможности элемента <iframe>, разница только в том, что весь подгружаемый из другого файла контент становится полноценной частью кода документа-родителя.
Пример использования:
<head>
<title>jFrame</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.form.js"></script>
<script type="text/javascript" src="jquery.jframe.js"></script>
<script type="text/javascript">
jQuery.fn.waitingJFrame = function () {
$(this).html("<strong>Загрузка...</strong>");
}
</script>
</head>
<body>
<div id="feedback" src="/catalog/feedback/"></div>
<div id="voting" src="/catalog/voting/"></div>
</body>
</html>
Анекдот по теме:
Все садятся в современный супер-самолет. Из динамиков раздается:
— Уважаемые пассажиры! Наш самолет оборудован по последнему слову техники. Во время полета вам будет предложены услуги бара, кинотеатра, бассейна, сауны. Для желающих открыты библиотека, магазины, спортивный зал и другие заведения культурного отдыха.
А теперь, приведите спинки кресел в вертикальное положение, пристегните ремни, и мы попробуем вместе со всей этой фигней взлететь!
Ладно, а теперь попробуем со все этой фигней взлететь. Скрипт каталога продукции, формирующий основное содержание страницы (DOCUMENT_ROOT/catalog/index.php):
$dblocation = "localhost"; // Имя сервера
$dbuser = "root"; // Имя пользователя
$dbpswrd = ""; // Пароль
$dbname = "catalog"; // Имя базы данных
// Соединение с сервером базы данных
$dblink = mysql_connect( $dblocation, $dbuser, $dbpswrd );
mysql_query( 'SET NAMES cp1251' );
// Выбираем базу данных
mysql_select_db( $dbname, $dblink );
?>
<html>
<html>
<title>Каталог продукции</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<style type="text/css">
a.modern {
font-weight: bold;
text-decoration: none;
}
</style>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.form.js"></script>
<script type="text/javascript" src="js/jquery.jframe.js"></script>
<script type="text/javascript">
jQuery.fn.waitingJFrame = function () {
$(this).html("<strong>Загрузка...</strong>");
}
</script>
</head>
<body>
<table border="1" cellpadding="4" cellspacing="0" width="100%" height="100%">
<tr>
<td colspan="2"><h1>ЗАО "Рога и копыта"</h1></td>
</tr>
<tr valign="top">
<td width="70%">
<h2>Каталог продукции</h2>
<?php
// Формируем запрос на извлечение товарных позиций
$query = 'SELECT code, title, description, price
FROM products
ORDER BY title';
$res = mysql_query($query);
echo '<table border="1" cellpadding="4" cellspacing="0">';
echo '<tr>';
echo '<th>Код</th>';
echo '<th>Наименование</th>';
echo '<th>Описание</th>';
echo '<th>Цена</th>';
echo '</tr>';
while( $prd = mysql_fetch_array( $res ) ) {
echo '<tr>';
echo '<td>'.$prd['code'].'</td>';
echo '<td>'.$prd['title'].'</td>';
echo '<td>'.$prd['description'].'</td>';
echo '<td align="right">'.$prd['price'].'</td>';
echo '</tr>';
}
echo '</table>';
?>
</td>
<td width="30%">
<div id="feedback" src="/catalog/feedback/"></div>
<div id="voting" src="/catalog/voting/"></div>
</td>
</tr>
<tr>
<td colspan="2" align="right">Copyright</td>
</tr>
</table>
</body>
</html>
Форма обратной связи (DOCUMENT_ROOT/catalog/feedback/index.php):
session_start();
$admin = 'admin@mail.ru';
header("Content-type: text/html; charset=windows-1251");
if ( $_SERVER['REQUEST_METHOD'] == 'POST' ) {
if ( !isset( $_POST['sendMail'] ) ) {
$_POST['name'] = iconv('UTF-8', 'CP1251', $_POST['name']);
$_POST['email'] = iconv('UTF-8', 'CP1251', $_POST['email']);
$_POST['subject'] = iconv('UTF-8', 'CP1251', $_POST['subject']);
$_POST['message'] = iconv('UTF-8', 'CP1251', $_POST['message']);
}
$name = substr( $_POST['name'], 0, 64 );
$email = substr( $_POST['email'], 0, 64 );
$subject = substr( $_POST['subject'], 0, 64 );
$message = substr( $_POST['message'], 0, 250 );
$error = '';
if ( empty( $name ) ) $error = $error.'<li>Не заполнено поле "Имя"</li>';
if ( empty( $email ) ) $error = $error.'<li>Не заполнено поле "E-mail"</li>';
if ( empty( $subject ) ) $error = $error.'<li>Не заполнено поле "Тема"</li>';
if ( empty( $message ) ) $error = $error.'<li>Не заполнено поле "Сообщение"</li>';
if ( !empty( $email ) and !preg_match( "#^[0-9a-z_\-\.]+@[0-9a-z\-\.]+\.[a-z]{2,6}$#i", $email ) )
$error = $error.'<li>поле "E-mail" должно соответствовать формату somebody@somewhere.ru</li>';
if ( !empty( $error ) ) {
$_SESSION['sendMailForm']['error'] = '<p>При заполнении формы были допущены ошибки:</p><ul>'.$error.'</ul>';
$_SESSION['sendMailForm']['name'] = $name;
$_SESSION['sendMailForm']['email'] = $email;
$_SESSION['sendMailForm']['subject'] = $subject;
$_SESSION['sendMailForm']['message'] = $message;
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
$body = "АВТОР:\r\n".$name."\r\n\r\n";
$body .= "E-MAIL:\r\n".$email."\r\n\r\n";
$body .= "ТЕМА:\r\n".$subject."\r\n\r\n";
$body .= "СООБЩЕНИЕ:\r\n".$message;
$body = quoted_printable_encode( $body );
$theme = '=?windows-1251?B?'.base64_encode('Заполнена форма на сайте').'?=';
$headers = "From: ".$_SERVER['SERVER_NAME']." <".$email.">\r\n";
$headers = $headers."Return-path: <".$email.">\r\n";
$headers = $headers."Content-type: text/plain; charset=\"windows-1251\"\r\n";
$headers = $headers."Content-Transfer-Encoding: quoted-printable\r\n\r\n";
if ( mail($admin, $theme, $body, $headers) )
$_SESSION['success'] = true;
else
$_SESSION['success'] = false;
header( 'Location: '.$_SERVER['PHP_SELF'] );
die();
}
function quoted_printable_encode ( $string ) {
// rule #2, #3 (leaves space and tab characters in tact)
$string = preg_replace_callback (
'/[^\x21-\x3C\x3E-\x7E\x09\x20]/',
'quoted_printable_encode_character',
$string
);
$newline = "=\r\n"; // '=' + CRLF (rule #4)
// make sure the splitting of lines does not interfere with escaped characters
// (chunk_split fails here)
$string = preg_replace ( '/(.{73}[^=]{0,3})/', '$1'.$newline, $string);
return $string;
}
function quoted_printable_encode_character ( $matches ) {
$character = $matches[0];
return sprintf ( '=%02x', ord ( $character ) );
}
?>
<h2>Обратная связь</h2>
<?php
if ( isset( $_SESSION['sendMailForm'] ) ) {
echo $_SESSION['sendMailForm']['error'];
$name = htmlspecialchars ( $_SESSION['sendMailForm']['name'] );
$email = htmlspecialchars ( $_SESSION['sendMailForm']['email'] );
$subject = htmlspecialchars ( $_SESSION['sendMailForm']['subject'] );
$message = htmlspecialchars ( $_SESSION['sendMailForm']['message'] );
unset( $_SESSION['sendMailForm'] );
} else {
$name = '';
$email = '';
$subject = '';
$message = '';
}
if ( isset( $_SESSION['success'] ) ) {
if ( $_SESSION['success'] )
echo '<p>Письмо успешно отправлено</p>';
else
echo '<p>Ошибка при отправке письма</p>';
unset( $_SESSION['success'] );
}
?>
<form action="<?php echo $_SERVER['PHP_SELF'] ?>" method="POST">
<table>
<tr><td>Имя:</td><td><input type="text" name="name" maxlength="64" value="<?php echo $name ?>" /></td></tr>
<tr><td>E-mail:</td><td><input type="text" name="email" maxlength="64" value="<?php echo $email ?>" /></td></tr>
<tr><td>Тема:</td><td><input type="text" name="subject" maxlength="64" value="<?php echo $subject ?>" /></td></tr>
<tr><td>Сообщение:</td><td><textarea name="message" rows="5" cols="30"><?php echo $message ?></textarea></td></tr>
<tr><td> </td><td><input type="submit" name="sendMail" value="Отправить" /></td></tr>
</table>
</form>
Скрипт голосования (DOCUMENT_ROOT/catalog/voting/index.php):
session_start();
header("Content-type: text/html; charset=windows-1251");
$actions = array( 'showForm', 'voting', 'result' );
if ( isset( $_GET['action'] ) )
$action = $_GET['action'];
else
$action = 'showForm';
if ( !in_array( $action, $actions ) ) $action = 'showForm';
switch( $action )
{
case 'showForm': // Показать форму для голосования
showForm();
break;
case 'voting': // Голосование
voting();
break;
case 'result': // Показать результаты голосования
result();
break;
}
function showForm()
{
echo '<h2>Голосование</h2>';
echo '<form action="'.$_SERVER['PHP_SELF'].'?action=voting" method="POST">'."\n";
echo '<table>'."\n";
echo '<tr><th colspan="2">Оцените сайт</th></tr>'."\n";
echo '<tr><td><input type="radio" name="mark" value="5" checked /></td><td>Отлично</td></tr>'."\n";
echo '<tr><td><input type="radio" name="mark" value="4" /></td><td>Хорошо</td></tr>'."\n";
echo '<tr><td><input type="radio" name="mark" value="3" /></td><td>Средне</td></tr>'."\n";
echo '<tr><td><input type="radio" name="mark" value="2" /></td><td>Плохо</td></tr>'."\n";
echo '<tr><td><input type="radio" name="mark" value="1" /></td><td>Очень плохо</td></tr>'."\n";
echo '<tr><td colspan="2" align="center"><input type="submit" value="Оценить" /></td></tr>'."\n";
echo '</table>'."\n";
echo '</form>'."\n";
echo '<p><a href="'.$_SERVER['PHP_SELF'].'?action=result">Результаты голосования</a></p>'."\n";
}
function voting()
{
if ( !isset( $_POST['mark'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=showForm' );
die();
}
$mark = (int)$_POST['mark'];
if ( $mark > 5 or $mark < 1 ) {
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=showForm' );
die();
}
// Если пользователь уже голосовал - не учитываем его голос
if ( isset( $_SESSION['completed'] ) ) {
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=showForm' );
die();
}
$file = file_get_contents( 'voting.txt' );
// $result[0] - общее количество проголосовавших посетителей
// $result[1] - количество посетителей, которые поставили оценку "1"
// ..........
// $result[5] - количество посетителей, которые поставили оценку "5"
// $result[6] - средняя оценка
$result = explode( '|', $file );
$result[6] = ($result[6] * $result[0] + $mark) / ($result[0] + 1);
$result[0] = $result[0] + 1;
$result[$mark] = $result[$mark] + 1;
if ( $fp = fopen('voting.txt', 'w') ) {
// Ставим на файл исключительную блокировку
if ( flock($fp, LOCK_EX) ) {
fwrite( $fp, implode( '|', $result ) );
flock( $fp, LOCK_UN );
}
fclose( $fp );
$_SESSION['completed'] = true;
}
header( 'Location: '.$_SERVER['PHP_SELF'].'?action=result' );
die();
}
function result()
{
$file = file_get_contents( 'voting.txt' );
$result = explode( '|', $file );
$width = 200;
$mark = array( 1 => 'Очень плохо', 2 => 'Плохо', 3 => 'Средне', 4 => 'Хорошо', 5 => 'Отлично' );
echo '<h2>Результаты голосования</h2>';
echo '<table>'."\n";
for ( $i = 5; $i > 0; $i-- ) {
$percent = $result[$i]/$result[0];
$w = round($width*$percent);
echo '<tr>';
echo '<td>'.$mark[$i].'</td>';
echo '<td width="'.$width.'"><img src="/catalog/voting/1.gif" width="'.$w.'" height="10" /></td>';
echo '<td>'.$result[$i].'</td>';
echo '</tr>'."\n";
}
echo '</table>'."\n";
echo '<p>Всего проголосовало: '.$result[0].
'<br/>Средняя оценка: '.number_format($result[6], 2, '.', '').'</p>'."\n";
echo '<p><a href="'.$_SERVER['PHP_SELF'].'?action=showForm">Вернуться к голосованию</a></p>'."\n";
}
?>
PAY:
Вопрос: А будет ли вновь загруженный контент индексироватьс поисковиками или нет? Т.е. например, можно ли сделать скажем таким образом пагинацию с тем условием, чтобы по всем ссылкам мог пройти поисковый робот?
22 Ноябрь 2008, 15:29admin:
PAY, вот чего не знаю, того не знаю. Думаю, что нет. Ведь для того, чтобы поисковый робот мог увидеть контент, загруженный с использованием XMLHTTPRequest, он должен выполнить некий JavaScript, а он этим не занимается. Я слышал, что SEO-оптимизаторы крайне негативно отзываются о навигации с использованием JavaScript - именно по этой причине: поисковики не видят этих ссылок. Этот плагин есть смысл использовать для второстепенных сервисов на странице - голосование, обратная связь и т.п.
22 Ноябрь 2008, 17:34Никита:
Нафиг это индексировать ? Людям нужен сервис - и толку от индексации не будет !
29 Декабрь 2008, 15:15isle:
>>Нафиг это индексировать ? Людям нужен сервис - и толку от индексации не будет !
Ну вот что это за бред? извините… У меня меню в шапочке половину страницы весит, примерно 30 ссылок в меню, индексация крайне важна.
28 Январь 2009, 6:08admin:
Никита и isle, я так думаю, что вы оба правы. Использовать этот плагин есть смысл для сервисов типа “обратная связь”, “голосование” и т.п. Нет необходимости, чтобы это индексировалось поисковиками - потому как никакого контента они не содержат. А вот использовать этот плагин для организации навигационного меню - плохоя мысль, потому как робот, чтобы увидеть эти ссылки должен выполнить некий JavaScript, а они этого не делают. Соответственно, сайт не будет проиндекирован.
28 Январь 2009, 10:31Зайва Игорь Леонидович:
Шо-то у меня как-то автоматом зарегистрировалось… этот “isle”, блин… Нельзя исправить?
Я, кстати, заметил, что один мой первый сайт со стихами на Народ.ру сделан полностью на фреймах и, судя по всему, весь в индексе… Лень проверять, извините, но аллсабмиттер показывает, что весь… сделан на ифреймах, меню тоже решил на ифреймах везде сделать.
И на главной ссылок не будет и меню проиндексируется… 
30 Январь 2009, 10:42mr.Hide:
Не удержался….
15 Февраль 2009, 2:12Поисковики индексируют и распознают javascript, не спорьте))
Статейка хорошая, хотелось бы поболее про jquery почитать. пишите, сенкс
admin:
mr.Hide, про jQuery можно почитать здесь:
16 Февраль 2009, 10:54jQuery - решения, примеры, рецепты