Записи в рубрике 'Дизайн'

Чем различается табличная верстка и верстка через CSS

Русский интернет (уже наконец) вовсю осваивает “дизайн через CSS”, но многие все равно не понимают, почему именно надо дизайнить так, а не по-старому, через таблицы. Руководствуются, как часто бывает, тем, что это модно. А многие, в общем-то, и не спешат уходить от таблиц, не считая, что в них есть что-то плохое. Я собираюсь написать длинный цикл статей о веб-разработке новыми методами. Главная моя цель - структурировать на русском языке те знания, которых полно в разрозненном виде по всей сети.

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

Для начала я хочу определиться с понятием “табличная верстка”. Если вы начинали заниматься веб-разработкой в 90-е годы, то знаете, что верстать страницу можно было двумя способами: потоком или таблицами. Первый способ - это попросту отсутствие всякой верстки, когда один за другим сверху вниз идут заголовки и абзацы. А таблицы - это когда вся страница представляется в виде сетки, в которую в нужные места уже вставляются текст, картинки и другие таблицы. Причем, сама по себе структура этих <table>, <tr>, <td> позволяет создать сетку любой сложности.

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

это единственный способ центрирования содержимого по вертикали

с помощью таблицы 3?3 ячейки делались рамки с оформлением углов

добавьте свое, наверняка у вас полно любимых приемов

Вот это:

<table width=”100%” background=”/i/bg_top.jpg” style=”background-repeat: no-repeat;” border=”0″ cellspacing=”0″ cellpadding=”0″>
<tr>
<td width=”75%” valign=”bottom”>
<img src=”/i/_.gif” mce_src=”/i/_.gif” width=”1″ height=”40″ border=”0″ alt=”"><br>
<table border=”0″ cellspacing=”0″ cellpadding=”0″><tr valign=”top”>

<td><img src=”/i/_.gif” mce_src=”/i/_.gif” width=”25″ height=”1″ border=”0″ alt=”"><br></td>
<td><a href=”/” mce_href=”/”><img src=”/i/logo.gif” mce_src=”/i/logo.gif” width=”213″ height=”90″ border=”0″ alt=”"></a><br></td>
<td><img src=”/i/slogan.gif” mce_src=”/i/slogan.gif” width=”124″ height=”90″ border=”0″ alt=”"><br></td>

</tr></table>
</td>
<td bgcolor=”#ffffff” background=” “><img src=”/i/_.gif” mce_src=”/i/_.gif” width=”1″ height=”1″ border=”0″ alt=”"><br></td>
<td width=”25%” bgcolor=”#0C2E82″ background=” “>
<table width=”100%” border=”0″ cellspacing=”2″ cellpadding=”2″><tr valign=”top”>

<td align=”center”>
<table width=”90%” cellpadding=”0″ cellspacing=”1″ border=”0″>
<tr valign=”top”>
<td colspan=”3″><span class=”white small”><b>Персональный кабинет</b></span></td>

</tr>

<tr valign=”top”>
<td><span class=”white small”>логин</span></td>
<td><span class=”white small”>пароль</span></td>

<td> </td>
</tr>

… я и называю табличной версткой.
Проблема

Есть куча исторических причин, почему HTML в конце 90-х годов прошлого века стал выглядеть именно так, но это тема отдельной статьи. Однако, примерно в то время все больше стало появляться людей, которые, смотря на то, куда это все развивается, стали громко говорить, что это плохо. Я постараюсь здесь свести воедино то, что эти и другие “евангелисты” неустанно говорят и пишут в книжках по поводу недостатков табличной верстки.
Много кода

Табличная верстка занимает неприлично много места. Страница более-менее хорошо упакованного сайта легко может занимать и 80КБ, и 120КБ… Это без картинок. Все это выливается не только в медленную загрузку и отрисовку, но и в немаленькие деньги за трафик как для сайтов, так и для клиентов. Ведь если картинки хотя бы кешируются браузером, то всю верстку для каждой новой страницы он неминуемо грузит заново, как бы похожа на предыдущую та ни была (кто тут сказал слово “фрейм”? не надо…).
Трудная правка

Табличную верстку трудно править вручную. Несмотря на большое развитие визуальных редакторов кода, от этой проблемы они не спасают. Если ваш сайт - динамический, значит он собирается из кусков шаблонов. И значит шаблоны будут состоять из фрагментов таблиц. Если вам приходилось когда-нибудь смотреть в такой фрагмент и думать, относится ли вот эта </td> к вашей части или закрывает ячейку из верхней части шаблона, вы понимаете, о чем я говорю… Заодно прошу прощения, если причинил кому-то боль этими темными воспоминаниями.
Негибкий дизайн в разработке

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

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

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

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

Многие мне возражают, что, мол, кому вообще нужны эти 0,000…% пользователей, пользующиеся этой экзотикой? Я думаю, это во многом путание причины и следствия: потому и 0,000…%, что нет сайтов, которыми можно нормально пользоваться ненастольными средствами. Думаю, если эта ситуация будет меняться так, как сейчас меняется, мы уже скоро застанем время, когда веб на PDA будет казаться обычным делом.

Ну вот. Кажется, достаточно .
Что взамен

Взамен W3C - организация, занимающаяся стандартами для веба - предлагает нам две спецификации: HTML 4 и CSS 2. Я ни в коем случае не предлагаю вам их читать сейчас. Не вздумайте. Это точные детализированные справочники, и чтение их в качестве художественного произведения ничего, кроме головной боли и разочарования в жизненных идеалах, не принесет. Тем более, самой сути, зачем они обе существуют, там, в общем-то, и не объяснено.

Я и ссылки-то поставил всего-навсего потому, что должны же быть ссылки на спецификации в статье про HTML и CSS!

А суть состоит в том, что нам предлагается разделить “компот” и “мух” - содержимое и оформление страниц, и пользоваться для того и другого разными средствами. HTML - для описания содержимого, его структуры, а CSS - для оформления и верстки.

Здесь важно остановиться и вчитаться в последнее предложение предыдущего абзаца еще раз. В нем неприметно поселилась ключевая мысль всей этой статьи. То есть, буквально, из HTML выкидывается все, что связано с тем, как он выглядит, а в CSS к бордюрчикам и цветам (с которых он начинался) добавляются средства для размещения элементов на странице, сдвигания, отступания и пр.
HTML 4 не является языком оформления веб-страниц.

Он является языком логической разметки страниц. Раньше, создавая HTML-документ, вы думали о том, что этот заголовок будет сделан жирной верданой золотистого цвета и отцентрован посредине большой темно-зеленой ячейки. Теперь все это предлагается выкинуть, и написать просто:
Заголовок страницы
. Выкидывается все, связанное с форматированием: шрифты, бордюры таблиц, цвет ссылок, отступы у , фоны ячеек таблиц, центрирование…

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

<div id=header>
<h1>Компания</h1>
<small>Кульный девиз</small>
</div>

<div id=main>
<p>Компания была основана…
</div>

<div id=sidebar>
<ul>
<li><a href=”" mce_href=”">Продукты</a></li>

<li><a href=”" mce_href=”">Клиенты</a></li>
<li><a href=”" mce_href=”">Контакты</a></li>
</ul>

</div>

Фактически, то, что вы делаете теперь в HTML - это некая карта страницы, не более того. Структура. Даже вот тот <small> в заголовке означает не “<font size=1>“, а “второстепенная по значению фраза внутри шапки, подзаголовок”.

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

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

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

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

Общий стиль для всего сайта

CSS спроектирован так, чтобы дизайн и стиль всего сайта хранился в одном месте (можно даже буквально в одном файле, хотя для больших проектов это не очень удобно). А это означает, что во время разработки этого самого сайта, и во время различных “редизайнов” и “рестайлингов” вам вообще не нужно, как раньше, менять все HTML’ные файлы или шаблоны, достаточно сделать изменения только в CSS.
Маленький размер страниц

Несмотря на то, что все равно в файлах суммарно остается и содержимое, и оформление, сам синтаксис CSS ведет к меньшему размеру файлов. Например, если вы (или ваш Dreamweaver) для каждой ссылки в коде раньше писали:

<font face=”Verdana, Arial, Sans-Serif” color=”#880000″ size=”2″>
<b><a href=”" mce_href=”"></a></b></font>

то теперь вы напишите в HTML:

<a href=”" mce_href=”"></a>

и в CSS:

a {Font:Bold 10pt Verdana, Arial; Color:#880000;}

и будете экономить байты на каждой ссылке. Потому что правило в CSS достаточно написать только один раз.

Даг Бауман как-то провел эксперимент, перевел заглавную страницу сайта Microsoft на CSS, получил уменьшение объема с 40КБ до 15КБ.
Кеширование оформления

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

К этому стоит добавить, что многие картинки, которые раньше делались тегами при дизайне с использованием стилей переходят тоже в правила CSS’ного файла. И большинство браузеров кеширует эти картинки агрессивней, чем те, которые сидят в HTML: он за ними даже не ходит на сервер проверять, изменились ли они, если не изменился стилевой файл.
Свободное расположение содержимого в файле

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

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

HTML c чистыми данными гораздо проще скриптовать: не надо вычленять данные из оформительского мусора и менять скрипт каждый раз, когда вам захочется поменять жирность шрифта у какой-то ключевой ячейки с данными.
Легче думать

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

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

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

Добро пожаловать в реальность

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

Первое, что сильно портит малину - это реализация всех этих стандартов в выпускающихся браузерах. Подумайте, спецификация CSS 2 была написана в 1998 году, а реальные крупные сайты, построенные с его использованием, стали появлятся что-то где-то в 2002-2003 годах. Это от того, что примерно только в это время браузеры с новыми движками, вокруг которых крутились прогрессивно мыслящие разработчики, начали переходить из стадии “оно компилируется!” в стадию “можно показывать людям”. Однако и сейчас, что в Gecko-браузерах (Firefox и другие), что в Opera, что в Safari и Konqueror, полно ошибок в реализации CSS. Не говоря уж об IE, ошибки которого никто не правил уже 4 года. А это значит, что вам, как веб-разработчику, который желает всем этим заниматься, придется привыкать не только к новой парадигме (!), что само по себе трудно, но и учить новые отвратительные хаки, как заставить тот или иной (точнее, по большей части - только тот) браузер работать вменяемо.

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

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

Источник http://webstudent.ru

Tags: CSS, html, верстка

Добавить комментарий Апрель 3, 2008

Импортирование информации с чужого сайта на свой сайт в свой дизайн

Импортирование информации с чужого сайта на свой сайт в свой дизайн. (На примере импортирования прогнозов погоды с Yahoo.)

Добре, господа!

Пример предназначен для тех, кто начинает работать с php, и не только для них.

Результатом работы программы(скрипта) является прогноз погоды на 5 дней для любого, интересующего Вас города, выводимый в виде, который нравится именно Вам, а не дизайнерам сайта-донора.

Информация в таких случаях берется с известных серверов прогноза погоды (где не пишут фразу “запрещено использование информации” и т.п.). В данном случае используется сервер http://weather.yahoo.com/ , на котором есть страницы с погодой для довольно большого количества городов, и практически всегда можно найти если не интересующий Вас город, то ближайший ему и идентичный по погодным условиям.

Это законченный проект, работающий на сайте http://sim-sim.ru в разделе туризма “погода в мире”.

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

Посему, скрипт состоит из 2-х частей:
1. Файл с администрированием (вводится в первую строку название города, на следующей строке - ссылка). Разбирать работу данной части, думаю, не стоит, комментариев более чем достаточно.
2. Файл с самой программой. Работа программы будет подробно описана ниже.
1. Администрирование.

Выводим на экран форму с паролем pass.

В окне вводятся:
номера
названия
ссылки

Затем, после нажатия на кнопку и проверки пароля, записываем новый список в файл.
<html>
<head>
<title>admin weather</title>
</head>

<body>

<?php

// адрес файла, в котором и будут записываться названия городов со ссылками
$adr=$DOCUMENT_ROOT.”/weather/weather.ini”;
$password=’pass’; // простенькая система авторизации
$eror=’Password eror!’;
$old=file($adr); // читаем то, что сейчас есть в файле

if ($submit) { // проверяем на нажатость кнопки
if ($pass==$password) {
$fp=fopen($adr,”w”);
fwrite ($fp, $ini); // записываем в файл измененные данные
fclose($fp);
$old=file($adr);
}
else {
echo $eror;
}
}
?>

<form method=post action=”<?php echo $PHP_SELF?>”>
// информация, введенная в форму, обрабатывается этим же файлом
password:<input type=text name=pass><br>
inicialisation:<textarea name=”ini” rows=15 cols=60>
<?
for ($i=0; $i<sizeof($old); $i++) {
echo $old[$i], “”; // выводим на экран текущий вариант файла
}
?>
</textarea>
<br>
<input type=submit name=”submit” value=”Enter”>
</form>

</body>
</html>

После ввода информации в файл в виде, получаем:
50
Ларнака
http://weather.yahoo.com/forecast/Larnaca_CY_f.html
51
Пафос
http://weather.yahoo.com/forecast/Paphos_CY_f.html
“44″ - номер города.
“Ларнака” - название города.
“http://weather.yahoo.com/forecast/Larnaca_CY_f.html” - ссылка на погоду в городе Ларнака на Яхе.

Ссылки на города организовываются по принципу:
<a href=http://www.sim-sim.ru/catalogue/weather.php?weather=50>Ларнака</a>

А можно так:
<a href=http://www.sim-sim.ru/catalogue/weather.php?city=Ларнака>Ларнака</a>

Но если город из друх слов, то в пробелах пишем “%20″

В таком случае, номера городов в списке не нужны:
Ларнака http://weather.yahoo.com/forecast/Larnaca_CY_f.html
Пафос http://weather.yahoo.com/forecast/Paphos_CY_f.html

Если у нас не текстовый файл, а mysql, то все проще.

Если кому понадобится вариант с mysql, пишите мне totoeval@mtu-net.ru
2. Программа (собственно, адаптер чужого кода к Вашему сайту).
<table width=100% border=0 cellspacing=0 cellpadding=2 bgcolor=<? echo $brdcolor; ?>>
<tr>
<td>

<br>
<!———————– FORECAST ————————->

<?php

$ini=$DOCUMENT_ROOT.’/weather/weather.ini’;
$region=file($ini); // читаем файл со списком городов-ссылок а массив $region

// определение координат искомого города
for ($i=0; $i<sizeof($region); $i++) {
if (trim($region[$i])==$weather) { // ищем номер города в списке
$city=trim($region[$i+1]); // название города
$adr=trim($region[$i+2]); // адрес страницы
}
else {
}
}

// если у нас передается информация не номером города, а названием, то:
for ($i=0; $i<sizeof($region); $i++) {
$city=str_replace($city,”%20″,” “); // заменяем “%20″ на ” ”
if (trim($region[$i])==$city) { // ищем название города в списке
$adr=trim($region[$i+1]); // адрес страницы
}
else {
}
}

// Входная информация для дальнейшего кода - $adr (адрес страницы
// прогноза погоды для города на сайте http://weather.yahoo.com)
// и $city - название города на родном языке.
// фразы для поиска полезной информации. Оригинал фраз можно обнаружить
// на странице, например, этой,
// проанализировав код. здесь заводим в переменные фразы, по которым будем
// искать нужную информацию (градусы, описания погоды, картинки). Используем
// фразы до и после необходимой информации. Этот блок в будущем придется
// изменять, когда на оригинале (weather.yahoo.com) изменится код страниц.
// На 14 авг. 2001 он работает.

$begin_screen=’FORECAST —-’; // начальная фраза таблицы с прогнозом погоды
$end_screen=’</b></td></tr></table></td></tr></table>’; // последняя фраза таблицы
$post_gradus=’</font></b><’; // после градусов
$before_gradus=’<font size=”3″ face=”arial”>’; // перед градусами
$before_image=’http://us.i1.yimg.com/us.yimg.com/i/we/fc/’; // перед картинкой
$post_image=’.gif’; // после картинки
$before_forecast=’top><font face=”arial” size=”2″>’; // перед фразой погоды
$post_forecast=’</font></td><td>’; // после фразы погоды

// массивы для переводов даты и описаний погоды с английского языка
// на родной (в данном случае использован вариант перевода с
// буржуйского на язык, которым разговаривал Ленин.
$endat=array(” “,”Mon”,”Tue”,”Wed”,”Thu”,”Fri”,”Sat”,”Sun”,
“May”,”Jul”,”Jun”,”Aug”,”Sep”,”Oct”,
“Nov”,”Dec”,”Jan”,”Feb”,”Mar”,”Apr”); // английские даты
$rudat=array(” “,”понедельник”,”вторник”,”среда”,”четверг”,
“пятница”,”суббота”,”воскресенье”,
“мая”,”июля”,”июня”,”августа”,”сентября”,”октября”,”ноября”,
“декабря”,”января”,”февраля”,”марта”,”апреля”); // родные даты
$eng=array(” “,”Thunderstorms”,”Sunny”,”Partly Cloudy”,
“Showers”,”Rain”,”Mostly Cloudy”,”Tstorms”,”Drizzle”,”Cloudy”,
“Flurries”,”Fog”,”High”,”Low”,”Clear”,”Sleet”,”Rain/snow”,
“Snow Showers”,”Mixed Snow”, “Rain”, “Snow”,
“Mixed”); // английские описания погоды
$rus=array(” “,”гроза”,”ясно”,”переменная облачность”,
“ливень”,”дожди”,”облачно”,”гроза”,”изморось”,”пасмурно”,
“снегопад”,”туман”,”день”,”ночь”,”ясно”,”дождь со снегом”,
“дождь со снегом”,”мокрый снег”,”снег с дождем”,”снег”,
“переменно”); // российские аналоги погоды

$brdcolor=’#ffffff’; // цвет рамки таблицы прогноза (белый)
$bgcolor=’#eeeeee’; //цвет фона ячеек таблицы (лучше - цвет фона страницы)

// А Здесь начинается код программы, который изменять не придется.

// занимаемся созданием даты, выводимой на экран.

Функция time() даст нам текущее время. Функцией date(d.” “.M,$t[$i]) получаем дату текущего и последующих 4 дней, а date(D,$t[$i]) дает нам дни недели всех 5 дней. А затем переводим даты с английского языка на родной.
$t=array(4);
$d=array(4);
$dn=array(4);
for ($i=0; $i<=4; $i++) {
$t[$i]=time()+$i*86400;
$d[$i]=date(d.” “.M,$t[$i]);
$dn[$i]=date(D,$t[$i]);
// переводим слова в дате и получаем даты на родном языке
for ($j=0; $j<sizeof($endat); $j++) {
$d[$i]=str_replace($endat[$j],$rudat[$j],$d[$i]);
$dn[$i]=str_replace($endat[$j],$rudat[$j],$dn[$i]);
} // и получаем даты на языке, которым разговаривает наш нонешний Вова
}

// начинаем обрабатывать страницу.
// Выясняем строки начала и конца таблицы с прогнозом погоды.
// Затем, будем работать именно с этим блоком.

$screen=file($adr); // читаем страницу с прогнозом погоды в переменную $screen

for ($i=1; $i<sizeof($screen); $i++) { // обрабатываем строки с первой по последнюю
if (strpos($screen[$i],$begin_screen)==false) { //находим начало таблицы с прогнозом
if (strpos($screen[$i],$end_screen)==false) { //находим ее конец
}
else {$m=$i; // $m - номер последней строки таблицы
}
}
else {$k=$i; // $k - номер первой строки таблицы
}
} // Получаем с $screen[$k] по $screen[$m] - нашу таблицу с погодой.
// Потом будемработать именно с ней, чтобы не было лишних совпадений, и
// быстро работала программа.
// Можно ее выводить в “родном дизайне, но нам это не нравится
// Начинаем искать полезную информацию.

$grad=array(9); // массив из 10 чисел градусов температуры окружающей среды

$zed=0; // счетчик градусов
for ($i=$k; $i<=$m; $i++) { //работаем с градусами
//если нет градусов в строке (если нет фразы, стоящей перед градусами.
if (strpos($screen[$i],$before_gradus,0)==false) {
}
else {// если есть градусы в строке
$string_grad=$screen[$i]; // сохраняем строку с градусами в переменную
// разбиваем строку на массив строк по разделителю, которым
// является фраза перед градусами, таким образом, мы получаем в
// 1 элементе массива строку, которая начинается собственно с
// самого градуса погоды.
$string_grad=explode($before_gradus,$string_grad);
// определяем позицию начала фразы, идущей после градуса.
$end_grad=strpos($string_grad[1],$post_gradus,0);
// первый градус получаем, как подстрока, с 0-го символа до начала фразы после градуса.
$grad[$zed]=substr($string_grad[1],0,$end_grad);
$zed++; // инкремент счетчика градусов
$end_grad=strpos($string_grad[2],$post_gradus,0);
$grad[$zed]=substr($string_grad[2],0,$end_grad); // второй градус
$zed++; // инкремент счетчика градусов
}
} // в результате чего, мы получили все градусы на нашей странице

// переводим фаренгейты в цельсии
for ($i=0; $i<=9; $i++) {$grad[$i]=round(5/9*($grad[$i]-32));
}
// в варианте с забиранием информации со страницы с цельсиями
// эту строку стоит просто закомментировать. Я оставил так, просто каприз.
// переводим фаренгейты в цельсии

// находим слова погоды абсолютно аналогично поиску градусов
$zed=0; // счетчик описаний погоды
for ($i=$k; $i<=$m; $i++) { //работаем с описаниями
//если нет описания погоды в строке
if (strpos($screen[$i],$before_forecast,0)==false) {
}
else {// если есть описания в строке
$string_grad=$screen[$i]; // сохраняем строку с описаниями в переменную
$string_grad=explode($before_forecast,$string_grad);
$end_grad=strpos($string_grad[1],$post_forecast,0);
$forec[$zed]=substr($string_grad[1],0,$end_grad);
// перебираем все варианты слов в описаниях
for ($j=0; $j<sizeof($eng); $j++) {
// переводим слова
$forec[$zed]=str_replace($eng[$j],$rus[$j],$forec[$zed]);
}
$zed++; // инкремент счетчика описаний
}
} // в результате чего, мы получили все описания погоды на нашей странице

$zed=0; // счетчик слов картинок аналогично
for ($i=$k; $i<$m; $i++) { //работаем с картинками
//если нет описания погоды в строке
if (strpos($screen[$i],$before_image,0)==false) {
}
else {// если есть картинки в строке
$string_grad=$screen[$i]; // сохраняем строку с картинками в переменную
$string_grad=explode($before_image,$string_grad);
$end_grad=strpos($string_grad[1],$post_image,0);
$for_img[$zed]=substr($string_grad[1],0,$end_grad);
$zed++; // инкремент счетчика картинок
}
} // в результате чего, мы получили все картинки на нашей странице

?>
// публикуем результаты:
<table width=100% cellpadding=0 cellspacing=0 border=0>
<tr><td width=20% align=center><font size=3><b
// выводим название города, для которого отображается прогноз погоды
><? echo $city;
?></b><br></font></td></tr></table
><table width=100% cellpadding=0 cellspacing=0 border=0>
<tr><?
// выводим на экран ячейки с датами и днями
for ($i=0; $i<=4; $i++) {
echo “<td width=20% align=center><font
size=2><b>$d[$i]<
br>$dn[$i]</b></font></td>”;
}
?></tr
></table
><table width=100% cellpadding=0 cellspacing=0 border=0
bgcolor=<? echo $brdcolor; ?>
><tr><td
><table width=100% cellpadding=2 cellspacing=1 border=0
><tr><?
$zed=0; // счетчик выводимых градусов
// выводим ячейки с прогнозами - картинки, градусы, описания
for ($i=0; $i<=4; $i++) {
$zed1=$zed+1;
echo “<td width=20% align=center bgcolor=$bgcolor
valign=middle><img src=../pic/”.$for_img[$i].”.gif border=0
alt=”.$forec[$i].”><br><br><font
size=2>”.$forec[$i].”</font><br><br><font
size=3><b>”.$grad[$zed].”°C<br>”.$grad[$zed1].”°C</b>
</font></td>”;
$zed=$zed+2;
}
?>
</tr></table>
</td>
</tr>
</table>

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

Теперь программа работает, и ее можно вставлять в свой дизайн.

Вот вариант: вышеупомянутая Ларнака

Если кого заинтересуют “вариации на тему” или возникнут вопросы, прошу писать мне totoeval[@]mtu-net.ru.

А также, пишите все, кто сможет посоветовать другие варианты. Всегда рад критике и возможности повысить свой уровень.

Tags: import, parce, php

Добавить комментарий Март 11, 2008

Автоматическое построение форм различной сложности и отправка их письмом с аттачами произвольного количества

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

В формах может присутствовать:
заголовок раздела формы
текстовое поле (text)
текстовый блок (textarea)
поле пароля (password)
поле выбора из списка (select)
поле checkbox
поле радио буттона (radio)
невидимое поле (hidden)
поле загрузки файла (file)

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

Решено сделать 3 файла:
файл с формой
файл отправки формы
файл инициализации формы

Забегая вперед, могу предположить, что кто-то захочет положить файлы программы (первые два) в отдельный каталог, например forms, и будет просто инклюдить файл с формой на нужных страницах сайта, передавая ему параметром путь к файлу инициализации данной формы. Так как формы могут все-таки отличаться друг от друга в оформлении, я не стану городить огромный файл с бесконечным количеством вариантов и приведу полностью рабочий пример, работающий на сайте «Седьмого континента» в разделе «поставщики», а также на сайте gipragor.ru в разделе «задать вопрос».

Добавлю, что в наших случаях в формах были вариации вида полей text, textarea (в форме «Седьмого континента» 3 вида поля text). В вашем случае, возможно, понядобится еще несколько вариантов для полей. Все делается аналогично тому, что будет рассмотрено ниже.

Начнем с описания файла инициализации формы.

Ниже приведен текст файла ini.php

Выбор адресата^head^0
Выберите из списка^select^1^mail консультант|info@gipragor.ru|selected админ|totoeval@mtu-net.ru
Ваши координаты^head^0
Имя^text^1
Телефон^text^0
Факс^text^0
<nobr>Е-mail</nobr>^text^0
Я хочу получить ответ по телефону^checkbox^0^checked
Вопрос^head^0
Тема^textarea^1
Вопрос^textarea^1^long
Присоединить файл^file^0^attach
Присоединить файл 2^file^0^attach2
Предыдущая страница^hidden^0^refer

Как видим, каждое поле формы описывается отдельной строкой.
Как я ни старался сделать универсальным оформление всех полей форм, — не получилось.
Вследствие этого, предлагаю такое оформление:
Первым везде идет название поля, которое выводится на экран.
Вторым — тип поля формы:
text
password
textarea
checkbox
radio
hidden
file

Третий — указатель обязательного заполнения поля. Если стоит 1 — поле обязательно. Если параметр пустой или любой отличающийся от 1, то поле не обязательное.
Четвертым указываем дополнительный параметр, если он необходим. У каждого вида поля свои дополнительные параметры:
text — long указывает на то, что поле-строка будет длинной и размещена под названием; обычное поле, без параметра, размещается справа от названия
textarea — то же самое, что и у text
checkbox — checked указывает на то, что чекбокс будет выбран по-умолчанию
radio — четвертым параметром указывается имя группы радио-буттонов, а пятым — checked, как и у checkbox
file — указываем имя указателя массива загружаемых файлов
hidden — указываем параметр, в соответствии с которым в значение этого поля будет подставлено определенное значение, либо параметр будет передан как есть

Ну вот покончили с инициализацией формы.

Теперь попробуем написать программу, выводящую форму пользователю.

Создаем файл index.php с нижеприведенным содержимым.
<!– начало –>

<h1>Задать вопрос</h1>

<?

if ($is_send == “send_query”)
{
echo “<p>Вопрос был отправлен.</p>”;
}
?>

<!–
Выводим форму типа multipart/form-data
для отправки через нее текстовых полей и файлов
–>
<form method=”post” action=”send.php” ENCTYPE=”multipart/form-data”
onsubmit=”return Validate(this);”>
<table border=”0″ cellspacing=”0″ cellpadding=”5″ width=”100%”>
<tr><td class=”text” colspan=”2″ align=”center”><b></b></td></tr>
<?
// читаем файл инициализации в массив $texts
$texts=file(”ini.php”);

// перебираем все строки в файле и определяем пустые
for ($j=0; $j<(sizeof($texts)); $j++)
{
// оператором trim удаляем у строки слева и справа пробелы и переносы
$texts[$j]=trim($texts[$j]);
// если есть пустые строки, то в новый массив $proposal_text они не записываются
if ($texts[$j] != “”) {$proposal_text[]=$texts[$j];}
}

// обнуляем переменную, в которую будут занесены все обязательные для заполнения поля
$fields=”"; // имена полей формы
$fieldnames=”"; // названия полей формы

// перебираем все строки инициализации в массиве $proposal_text
// имена полей будут называться form[0], form[1], form[2]…
// Таким образом, мы передадим всю форму в одном массиве.
// Индекс элемента массива будет указателем строки описания поля в файле инициализации
// для дальнейшей обработки полученной формы.
for ($i=0; $i<(sizeof($proposal_text)); $i++)
{
// разобьем строки специальным разделительным символом ^
// тогда $proposal[0] - текстовое название поля
// тогда $proposal[1] - указатель типа поля формы:
// text - текстовое поле-строка
// textarea - текстовое поле-блок
// hidden - невидимое поле
// password - поле ввода пароля
// file - форма для загрузки файла
// checkbox - чекбокс
// radio - радио буттон
// head - заголовки разделов форм, не имеют никаких полей,
// лишь текст выводится полужирным шрифтом, либо выделяется иным способом
// тогда $proposal[2] - указатель обязательного заполнения поля посетителем.
//Если он равен 1, то поле обязательно, если любое другое значение - нет
// тогда $proposal[3] - дополнительный параметр.
// например, у нас это:
// long в поле text и поле textarea означает, что поле бОльшей ширины
// и расположено под названием поля
// refer в поле hidden говорит о том, что передается в невидимом поле
// адрес предыдущей страницы, посещенной пользователем
// attach в поле file - имя поля загружаемого пользователем файла

// все поля оформляются соответственно указанному типу ниже в блоке switch
$proposal=explode(’^',$proposal_text[$i]);
// переменной type присвоем тип поля
$type=trim($proposal[1]);

// определяем, обязательно ли к заполнению текущее поле
if (isset($proposal[2]))
{
if (trim($proposal[2]) == ‘1′)
// если в поле указателя содержится 1, то добавляем имя поля к
{
// если в переменную fields уже были записаны данные,
// то ставим запятую
if ($fields != “”) {$fields.=’, ‘;}
$fields.=”‘form[$i]’”;
if ($fieldnames != “”) {$fieldnames.=’, ‘;}
$fieldnames.=”‘”.$proposal[0].”‘”;
$imperative=” *”;
}
else {$imperative=”";}
}
// если в строке есть дополнительный параметр, то записываем его в пtременную param
if (isset($proposal[3])) {$param=trim($proposal[3]);}

// стравниваем тип поля с возможными вариантами и соответственно оформляем его
switch ($type) {
case “head”: // поле заголовка
echo “<tr>\n\t”.
“<td class=\”text\” colspan=\”2\”><br>”.
“<p><b>$proposal[0]</b></p>”.
“</td>\n</tr>\n”;
break;
case “text”: // текстовое поле
if (isset($proposal[3])) {
if ($param == “long”) {
// если поле длинное, то располагаем его под названием
// и увеличиваем длину
echo “<tr>\n\t”.
“<td colspan=\”2\” class=\”text\”>”.
$proposal[0].”$imperative<div align=\”right\”>\n\t”.
“<input type=\”text\” name=\”form[$i]\” size=\”102\”>”.
“</div></td>\n</tr>\n”;
}
}
else {
// иначе выводим стандартное поле-строку справа от названия поля
echo “<tr>\n\t”.
“<td class=\”text\”>”.$proposal[0].”$imperative</td>\n\t”.
“<td align=\”right\” valign=\”top\”>”.
“<input type=\”text\” name=\”form[$i]\” size=\”50\”>”.
“</td>\n</tr>\n”;
}
break;
case “password”: // поле пароля
echo “<tr>\n\t”.
“<td class=\”text\”>”.$proposal[0].”$imperative</td>\n\t”.
“<td align=\”right\” valign=\”top\”>”.
“<input type=\”password\” name=\”form[$i]\” size=\”50\”>”.
“</td>\n</tr>\n”;
break;
case “textarea”: // поле текстового блока оформляем аналогично текстовому полю
if (isset($proposal[3])) {
if ($param == “long”) {
echo “<tr>\n\t”.
“<td colspan=\”2\” class=\”text\”>”.
$proposal[0].”$imperative”.
“<div align=\”right\”>\n\t”.
“<textarea name=\”form[$i]\” rows=\”6\” cols=\”102\”>”.
“</textarea></div></td>\n</tr>\n”;
}
}
else {
echo “<tr>\n\t”.
“<td class=\”text\” valign=\”top\”>”.
$proposal[0].”$imperative</td>\n\t”.
“<td align=\”right\” valign=\”top\”>”.
“<textarea name=\”form[$i]\” rows=\”4\” cols=\”50\”>”.
“</textarea></td>\n</tr>\n”;
}
break;
case “radio”: // радио буттон.
//Его дополнительный параметр - имя переменной-группы радио-буттонов.
if (!isset($proposal[3])) {$param = “form[$i]”;}
if (!isset($proposal[4])) {$checked = “”;}
// если не задан параметр выбора буттона по-умолчанию
else {$checked = ” checked”;}
// если выбран по-умолчанию
echo “<tr>\n\t”.
“<td colspan=\”2\” class=\”text\”>”.
“<input type=\”radio\” name=\”$param\” id=\”id$i\”$checked>”.
“<label for=\”id$i\”> $proposal[0]</label></td>\n</tr>\n”;
break;
case “checkbox”: // чекбокс
if (!isset($proposal[3])) {$checked = “”;}
// если не задан параметр выбора чекбокса по-умолчанию
else {$checked = ” checked”;}
// если выбран по-умолчанию
echo “<tr>\n\t”.
“<td colspan=\”2\” class=\”text\”>”.
“<input type=\”checkbox\” name=\”form[$i]\” id=\”id$i\”$checked>”.
“<label for=\”id$i\”> $proposal[0]</label></td>\n</tr>\n”;
break;
case “hidden”: // невидимое поле.
// От его параметра зависит, что в нем будет передаваться.
// Если параметр не описан, то он будет передан по-умолчанию как есть
if (!isset($proposal[3])) {$param = “form[$i]”;}
echo “<input type=\”hidden\” name=\”form[$i]\”";
if ($param==”refer”) {echo ” value=\”".urlencode($HTTP_REFERER).”\”>”;}
else {echo ” value=\”$param\”>\n”;}
break;
case “file”: // поле загружаемого пользователем файла
if (!isset($proposal[3])) {$param = “form[$i]”;}
echo “<tr>\n\t”.
“<td align=\”right\” valign=\”bottom\”>”.
“<p align=\”left\”>$proposal[0]$imperative<br>”.
“<input type=\”file\” name=\”file_att[$param]\” size=\”35\”></p>”.
“</td></tr>\n”;
break;
case “select”: // поле выбора селект
if (isset($proposal[3])) { // если заданы параметры селекта
$options = explode(”\t”, $proposal[3]);
// разделяем параметры каждой строки селекта
$option_text=explode(”|”,$option[0]);
// разбиваем первый подпараметр селекта
// на имя селекта и вид (multiselect и обычный)
// получаем в $option_text[1] - вид селекта
if ($option_text[1]==”multiselect”)
{
if (isset($option_text[2]))
{
$multiselect=”size=$option_text[2]”;
}
$multiselect.=” multiselect”;
}
else {$multiselect=” size=\”1\”";}
echo “<tr>\n\t”.
“<td class=\”text\”>$proposal[0]$imperative</td>\n\t”.
“<td align=\”right\” valign=\”top\”>”.
“<select name=\”form[$i]\” style=\”width: 317\”$multiselect>\n”;
// выводим тег селекта
for ($z=1; $z<sizeof($options); $z++)
// в 0 строке селекта у нас параметр, указывающий отправщику,
// как обрабатывать текущий селект
{
// выводим строки селекта
$option_text=explode(”|”, $options[$z]);
// в первой части - текст строки,
// во второй - передаваемое значение
if (!isset($option_text[2])) {$option_text[2]=”";}
// если параметр “выбранная строка” не установлен
echo “\t<option value=\”$option_text[1]\” $option_text[2]>”.
“$option_text[0]</option>\n”;
// вывели строку селекта
}
echo “</select></td>\n</tr>\n”;
}
break;
default:
// если тип не определен, то ничего не выводится.
// И, следовательно, стоит подумать, что еще не учтено.
}
}
?>
</table>
<!–
Выведена таблица с формой.
Осталось вывести на экран кнопки “отправить” и “очистить”,
как это делают умные дядьки на других сайтах.
–>
<table border=”0″ cellspacing=”5″ cellpadding=”0″ width=”100%”>
<tr>
<td align=”right” valign=”bottom”><input type=”submit” value=”Отправить”>
<img src=”/images/1×1.gif” width=”10″ height=”50″>
<input type=”reset” value=”Очистить”>
</td>
</tr>
</table>
<!–
Конечно, здесь могло не быть этого кода,
а кнопки отправки формы и очищения можно задать в файле инициализации,
добавив и их обработку в программе.
–>
</form>
<p>Вы можете задать вопрос.
С вопросом можно отправить файлы.<br>
Ответ вы получите на адрес электронной почты,
указанный в координатах,
либо по телефону, если поставите галочку у соответствующего пункта.</p>
<!–
Яваскрипт, которому мы передали список полей формы, обязательных к заполнению
Он определит после попытки отправки формы, заполненны ли эти поля.
Если не заполнены, то скрипт ругнется и укажет какое поле не заполненно,
установив в него курсор.
–>
<script language=”JavaScript”>
fields = new Array(<? echo $fields; ?>);
fieldnames = new Array(<? echo $fieldnames; ?>);
function Validate(forma)
{
for(i=0;i<fields.length;i++)
{
field = fields[i];
if (forma.elements[field].value == “”)
{
alert(”Вы должны заполнить поле \”"+fieldnames[i]+”\”");
forma.elements[field].focus();
return false;
}
}
return true;
}
</script>

</td>
</tr>
</table>
<!– конец –>

Ну вот, наша форма выводится на экран пользователя, и он старательно, прикусив язык, заполняет все её поля.

Но мы-то знаем, что вывести форму и заполнить её — половина дела. Важно получить форму, обработать её и отправить по выбранному или указанному по-умолчанию адресу.

Ниже приведен текст файла отправки письма с аттачами send.php, который мы кладем в папку с index.php.

<?
// определяем, с какой страницы пришел посетитель на страницу отправки
if (strpos($HTTP_REFERER, “gipragor.ru/feedback”) === false) {
// если не со страницы отправки формы, то кидаем его в форму
header(”location: .”);
}

// если посетитель прошел проверку, читаем файл инициализации
$texts=file(”ini.php”);

// перебираем все строки в файле и сохраняем в новый массив только не пустые
for ($j=0; $j<(sizeof($texts)); $j++)
{
$texts[$j]=trim($texts[$j]);
if ($texts[$j] != “”) {$proposal_text[]=$texts[$j];}
}

// Объявляем пустую строковую переменную, в которой будет храниться сообщение
$mailtext=”";

// Перебираем все строки массива формы
for ($i=0; $i<(sizeof($proposal_text)); $i++)
{
// Разбиваем строки по разделительному символу ^
// получаем подстроки, в которых хранится:
// 0 - текст названия поля формы
// 1 - тип поля формы
// 2 - указатель обязательности заполнения поля формы
// 3 - дополнительные параметры поля формы
$proposal=explode(’^',$proposal_text[$i]);
$type=trim($proposal[1]);
if (isset($proposal[3])) {$proposal[3]=trim($proposal[3]);}
if (!isset($form[$i])) {$form[$i]=”нет данных”;}
// перебираем варианты типов полей формы
switch ($type)
{
case “head”: // если заголовок раздела формы
if ($mailtext != “”)
{
// если это не первый заголовок в форме,
// то ставим перед ним 2 пустые строки
$mailtext.=”\n\n”;
}
$mailtext.=”\t$proposal[0]\n”;
break;
case “text”: // если поле текствое - строка
if (isset($proposal[3]))
{
if ($proposal[3] == “long”)
{ // если строка длинная, то выводим ее под названием поля
$mailtext.=”$proposal[0]:\n$form[$i]\n\n”;
}
}
else
{ // если строка не длинная, то выводим ее справа от названия поля
$mailtext.=”$proposal[0]: $form[$i]\n”;
}
break;
case “textarea”: // поле текстового блока
$mailtext.=”$proposal[0]:\n$form[$i]\n\n”;
break;
case “radio”: // радио буттон
$group == “$proposal[2]”;
$mailtext.=”$proposal[0]: $group\n”;
break;
case “checkbox”: // чекбокс
if (trim($form[$i]) == “on”)
{ // если чекбокс выделили, то его значение - on
$mailtext.=”$proposal[0]\n”;
}
break;
case “hidden”: // скрытое поле. Обрабатываем его взависимости от параметра
if (!isset($proposal[3])) {$param = “form[$i]”;}
if ($param=”refer”) {$form[$i]=urldecode($form[$i]);}
$mailtext.=”$proposal[0]: $form[$i]\n”;
break;
case “file”: // поле файла отправляемого пользователем в виде аттача к письму
if (!isset($proposal[3])) {$param = “form[$i]”;}
else {$param=$proposal[3];}
// создаем массив из файлов-аттачей
$att_arr[]=$file_att[$param];
$att_arr_type[]=$file_att_type[$param];
$att_arr_name[]=$file_att_name[$param];
break;
case “select”: // поле селекта
if (isset($proposal[3])) { // если есть параметры селекта
$options = explode(”\t”, $proposal[3]);
// разбиваем параметры и перебираем каждую строку
$option_text=explode(”|”,$options[0]);
// разбиваем первый подпараметр селекта
//на имя селекта и вид (multiselect и обычный)
if ($option_text[0] == “mail”) {$mailto=$form[$i];}
// если 0 параметр равен mail -
// значит это варианты e-mail адресата (в нашем случае)
$mailtext.=”$proposal[0]: $form[$i]\n”;
}
break;
default:
}
}

// удалим из текста формы теги html
$mailtext=strip_tags($mailtext);

// удалим специальные символы из текста формы
// используя стандартный способ из руководства php
$search = array (”‘&(amp|#38);’i”,
“‘&(lt|#60);’i”,
“‘&(gt|#62);’i”,
“‘&(nbsp|#160);’i”,
“‘&(iexcl|#161);’i”,
“‘&(cent|#162);’i”,
“‘&(pound|#163);’i”,
“‘&(copy|#169);’i”,
“‘�(\d+);’e”,
“‘—’i”,
“‘–’i”);
$replace = array (”&”,
“<”,
“>”,
” “,
chr(161),
chr(162),
chr(163),
chr(169),
“chr(\\1)”,
” - “,
“-”);
$mailtext = preg_replace ($search, $replace, $mailtext);

// Параметры отправляемого сообщения
if ($mailto == “”)
{ // если адресат не был выбран в форме, то указываем его по-умолчанию
$to = “totoeval@mtu-net.ru”;
}
else
{ // если адресат был выбран посетителем в форме
$to = $mailto;
}
$from = “webmaster@$SERVER_NAME”;
$subject = “New Providers”;
$message = $mailtext;

// объявление в заголовке письма параметр From - от кого.
$headers = “From: $from”;

// Оформляем boundary string - строку-разделитель
$semi_rand = md5(time());
$mime_boundary = “==Multipart_Boundary_x{$semi_rand}x”;

// определяем, был ли отправлен файл с письмом
if (sizeof($att_arr)>0)
{ // если файл отправлен
// Добавляем к заголовку письма тип передаваемых данных
$headers .= “\nMIME-Version: 1.0\n” .
“Content-Type: multipart/mixed;\n” .
” boundary=\”{$mime_boundary}\”";
// Добавляем к сообщению multipart boundary и тип передаваемых данных,
// а затем присоединяем текст письма
$message = “This is a multi-part message in MIME format.\n\n” .
“–{$mime_boundary}\n” .
“Content-Type: text/plain; charset=\”windows-1251\”\n” .
“Content-Transfer-Encoding: 7bit\n\n” .
$message . “\n\n”;
}
else
{ // если письмо без приаттаченных файлов
// Добавляем к заголовку письма тип передаваемых данных
$headers .= “\nMIME-Version: 1.0\n” .
“Content-Type: text/plain; charset=\”windows-1251\”\n” .
” boundary=\”{$mime_boundary}\”";
// Добавляем к сообщению boundary и тип передаваемых данных (текст),
// а затем присоединяем текст письма
$message = “Content-Type: text/plain; charset=\”windows-1251\”\n” .
“Content-Transfer-Encoding: 7bit\n\n” .
$message . “\n\n”;
}

// перебираем имеющиеся приаттаченные файлы
// если их нет, то аттач производиться не будет
for ($files=0; $files<sizeof($att_arr); $files++)
{

$fileatt=$att_arr[$files];
$fileatt_type=$att_arr_type[$files];
$fileatt_name=$att_arr_name[$files];

if (is_uploaded_file($fileatt))
{ // проверяем, верно ли заапплоаден файл
// Читаем файл аттача (’rb’ = читаем в двоичном виде)
$file = fopen($fileatt,’rb’); // открываем поток
$data = fread($file,filesize($fileatt));

fclose($file); // закрываем поток

// Кодируем Base64 содержимое файла
$data = chunk_split(base64_encode($data));

// Добавляем содержимое файла к сообщению
// с соответствующими заголовком и описанием типа данных
$message .= “–{$mime_boundary}\n”.
“Content-Type: {$fileatt_type};\n”.
” name=\”{$fileatt_name}\”\n”.
“Content-Transfer-Encoding: base64\n\n”.
$data.”\n\n”;
}// так перебираем все отправляемые файлы

}
$message .= “–{$mime_boundary}–\n”;
// в конец сообщения добавляем разделительную строку с окончанием сообщения

// Отправляем сообщение
@mail($to, $subject, $message, $headers);

// сообщаем в куки, что письмо отправлено
setcookie (”is_send”, “send_query”, time()+120);
// переводим пользователя к странице формы
// где ему сообщат, что письмо его отправлено
header(”location: .”);

?>

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

Все вышенаписанное предназначено для начинающих программировать на php, и для полета мысли уже опытных.

Повторять программу можно в варианте моем, своем, друга.

По вопросам всвязи с возникающими проблемами обращаться ко мне по адресу totoeval[@]mtu-net.ru
Автор: Тотоев Александр

www.nova-wings.ru
gipragor.ru
www.v6.ru
«Седьмой континент»

Tags: , ?>, mail, форма

Добавить комментарий Март 10, 2008

Использование шаблонов в PHP

Многие программеры сталкивались с проблемой, когда дизайнеру “нужна свобода” в написании html, а программеру “чистота” кода :) У меня такое приключилось при написании виртуального веб-магазина. В общем, недолго думая я стал искать различные PHP-классы для создания “динамических сайтов” с использованием так называемых шаблонов. И нашел один, который отвечал всем моим требованиям, но слишком уж он оказался “большим и тяжелым”. Называется этот класс FastTemplate (уж не помню, где я его скачал). Недолго думая, я решил написать свой класс, взяв за основу функциональность FastTemplate. Мои результаты в написании своего класса получились практически такими как у FastTemplate, но, как мне кажется, ни чуть не хуже (прим.: код я не копировал, а создавал сам с нуля).

Итак, для начала работы Вам необходимо скачать мой класс template.

Скачали? Теперь можно пробовать на простом примере. Сделаем пример листинга файлов текущего каталога с подсчетом кол-ва байт каждого файла, при этом динамически создав таблицу. Итак, создайте следующие файлы: main.htm
<html>
<head>
<title><!– ABOUT –></title>
<link rel=”stylesheet” type=”text/css” href=”/styles.css”>
</head>
<body>

<p align=”center” class=”b”><!–

ABOUT

–><br>
Localtime is <!– LOCALTIME –>
</p><br>

<div align=”center”><table
STYLE=”border-collapse:collapse” class=”th”>
<tr>
<td colspan=”2″ class=”th”
align=”center”
style=”background-color:#000000; color:white”>
File listing</td>
</tr>
<!–
TABLE_CONTENT
–>
<tr>
<td class=”th” align=”right”
style=”background-color:#000000; color:white”>&nbsp;</td>
<td class=”th”
style=”background-color:#000000; color:white”>&nbsp;
<!– TOTAL –>&nbsp;</td>
</tr>
</table></div>

</body>
</html>

rows.htm

<tr>
<td align=”right” class=”th”
style=”background-color:<!– COLOR –>;color:black”>&nbsp;
<!– PWD –>&nbsp;</td>
<td class=”th” style=”background-color:<!– COLOR –>; color:black”>&nbsp;
<!– FILESIZE –>&nbsp;</td>
</tr>

index.php

<?php

require (’templates.php’); // Включаем класс для работы с шаблонами

// Определяем теги
$meta = array( “ABOUT” => “:: template class example ::”,
“LOCALTIME” => date(”M-d-Y H:i:s”));

$t = new template;

// Инициализируем файлы и дескрипторы
$t->init(array( index => “main.htm”, rows => “rows.htm”));

// Устанавливаем ограничители (delimiter-ы)
$t->delimiters(”<!–”, “–>”);

// Определяем теги
$t->assign($meta);

$d = dir(”.”);

$colors = array(”#d4d4d4″, “#a0a0a0″); $i = 0;
$totalbytes = 0;
while ($entry = $d->read()) {
if (preg_match(”/^(.|..)$/”, $entry)) continue;
$color = $colors[$i];
$t->assign(”FILENAME”, $entry); // Определяем под тегом FILNAME имя файла
$t->assign(”COLOR”, $color); // под COLOR текущий цвет
$t->assign(”PWD”, realpath ($entry)); // Полный путь
if (($size = filesize($entry)) > 1024) {
$totalbytes += $size;
$size = sprintf(”%0.2f Kbytes”, ($size / 1024));
} else {
$totalbytes += $size;
$size .= ” bytes”;
}
$t->assign(”FILESIZE”, $size); // связываем с тегом FILESIZE длинну файла

// Обрабатываем файл с дескриптором rows, при этом полученные результаты
// закрепляем под тегом TABLE_CONTENT (путем добавления)
$t->parseit(rows, “TABLE_CONTENT”);
$i = (++$i >= count($colors)) ? 0 : $i;

// Под этим тегом у нас будет общее кол-во байт найденых файлов
$t->assign(”TOTAL”, ( ($totalbytes > 1024) ?
sprintf(”%0.2f Kbytes”, ($totalbytes / 1024)) : $totalbytes.” bytes”));
}

$d->close();

// Обрабатываем страницу с дескриптором index. Т.е. при обработке
// все попадающиеся теги будут заменены на определенное значение.
$t->parseit(index);

// Выводим все
$t->printit();
$t->freshall();

?>

Результаты выполнения можно увидеть здесь http://null.magelan.ru/php/templates Данный класс работает очень шустро, обработчик построен на основе регулярных выражений.
Детальное описание

В классе определенны массивы:
$filelist - ассоциативный массив дексрипторов и файлов
$assign - ассоциативный массив определенных тегов
$root - корневой каталог
$arr - массив с результатом
$delmiters - ограничители
// init - Инициализация шаблонов
// arr - ассоциативный массив (см.пример) с дескрипторами и файлами
// root - корневой каталог, где лежат файлы (по-умолчанию текущий)
// delimit - тут можно указать ограничитель из двух символов, например “{}”
function init($arr = “”, $root = “”, $delimit = “”)

// Установка корневого каталога шаблонов
function setroot($root = “”)

// Добавление дескрипторов и файлов для работы с шаблонами
// list - ассоциативный массив
function listit($list = “”)

// Обработка шаблона
// $d - дескриптор файла ИЛИ МАССИВ!
// $temp - обработка в тег $temp (если не указать, данная ф-ия обработает
// декср.файла и добавит его к массиву с результатами)
function parseit($d = “”, $temp = “”)

// Получить обработанный массив, возвращает string
// $array - массив
function getparsed($array)

// Указать ограничители
// $d1 - левый, $d2 - правый
// Например $t->delimiters(”<!–”, “–>”);
function delimiters($d1 = “”, $d2 = “”)

// Как listit, только добавить можно не ассоциативный массив, а
// простую строку
// $d - дескриптор файла
// $name - имя файла
function addtolist ($d = “”, $name = “”)

// Используется для очистки всех массивов в классе
function freshall()

// Используется для очистки результатов обработки
// Очищается $arr
function fresh()

// Вывести на экран.
// В v1.02 - если указан $tag, выводит тег $this->assign[”$tag”]
function printit([$tag])

Если возникнут какие-либо комментарии, пишите на null[@]magelan.ru. Также выслушаю замечания и поправки.

Огромное спасибо Fil (fil[@]apb.farlep.net) за некоторые дополнения и замечания :) И всем тем, кто откликнулся!

Источник http://www.codenet.ru/

Tags: template, шаблоны

Добавить комментарий Март 8, 2008

Что такое CSS

Страшно подумать, но в июле этого года исполнилось всего 10 лет стандарту HTML 1.0 (который, кстати, так никогда и не был “официально” принят и остался в виде черновика для “внутреннего употребления”). За эти 10 лет HTML прошел очень большой путь, завоевал практически все компьютеры в мире и стал одним из самых известных “компьютерных языков” (все-таки отнести его к языкам программирования рука не поднимается)… И одним из весьма заметных этапов развития HTML стало появление CSS - Cascading Style Sheets или, говоря по-русски, каскадных таблиц стилей.

Идея CSS очень проста. Если в HTML вы прямо в документе ставили указание на то, как должен выглядеть тот или иной элемент, то при использовании CSS такие указания выносятся в отдельный блок (который может либо включаться в документ, либо читаться из внешнего файла).

Такой простой ход стразу дает массу преимуществ вебмастеру. Прежде всего, значительно облегчается изменение внешнего вида сайта или отдельных его элементов - достаточно изменить определение соответствующего стиля в единственном CSS-файле, и эти изменения распространятся на весь сайт. Второе преимущество - сокращение размеров документов, которое особенно заметно на “красивых” страницах.

Первая версия CSS - CSS level 1 - принятая в 1996 и пересмотренная в 1999 году, позволяла оперировать только цветами, шрифтами, отступами и им подобными относительно простыми и частоиспользуемыми элементами. Принятая в 1998 году, спецификация CSS level 2 добавила возможность абсолютного позиционирования элементов, создания стилей для разных типов устройств, использования собственных курсоров, расширила возможности по выбору элементов, к которым должен применяться тот или иной стиль и многое другое. Естественно, что CSS level 2 поддерживает и таблицы стилей, созданные в CSS level 1. В настоящее время консорциум W3C активно ведет разработку стандарта CSS level 3 и CSS level 2 revision 1, которые должны учесть все возрастающие потребности вебмастеров и вебдизайнеров, по созданию современных и удобных сайтов.

Следует учитывать, что каскадные таблицы стилей не полностью абстрагируют визуальное представление документа от его содержания - они только позволяет более компактно описать правила визуального представления. И если вы захотите изменить дизайн сайта, то вам все-равно придется переписывать HTML код (правда, сделать это будет проще чем при отсутствии CSS). Значительно больший уровень абстракции можно получить, используя связку языков XML + XSL (из которых, в частности, можно генерировать HTML + CSS), но это намного сложнее, и несколько выпадает из темы данной статьи.

Но хватит теории! Давайте попробуем практикой заняться…

Есть три способа описать стиль элемента в HTML документе. Самый простой и, практически, не использующий преимуществ CSS способ - это указать стиль внутри тега HTML. Например, написать
<H2 STYLE=”COLOR: #AADDAA; FONT-WEIGHT: BOLD; FONT-SIZE:11pt;”>заголовок второго уровня</H2>
Единственное преимущество, которое можно получить таким образом - это задание некоторых атрибутов текста, которые не поддерживаются тегами HTML. Зато сохраняются все недостатки HTML - указанный стиль относится только к одному тегу и для изменения внешнего вида документа вам придется изменить описание стиля в каждом теге.

Второй способ несколько лучше: надо описания стилей заключить внутри тегов <STYLE TYPE=”text/css”> и </STYLE>. Например, если вы напишете
<STYLE TYPE=”text/css”>
H2 {COLOR: #AADDAA; FONT-WEIGHT: BOLD; FONT-SIZE:11pt;}
</STYLE>
а в тексте документа укажете <H2>заголовок второго уровня</H2>, то получите тот же эффект. Однако, в отличие от предыдущего способа, свойства отображения применятся ко всем тегам H2 в документе. И если, скажем, вам потребуется изменить размер шрифта или цвет всех заголовков второго уровня, то изменить потребуется всего одну строчку. Согласитесь, что это намного удобнее!

Однако, у предыдущего способа тоже есть свой недостаток: блок STYLE вам придется скопировать в каждую страницу своего сайта. А если страниц там несколько сотен? И вам понадобится что-то поменять? Неудобно… Но можно победить и эту проблему - с помощью тега LINK. Описав требуемые стили в отдельном текстовом файле (теги STYLE указывать не требуется), вы затем можете написать в секции HEAD документа
<LINK REL=”stylesheet” TYPE=”text/css” HREF=”style.css”>
Эта команда укажет, что таблица стилей находится во внешнем файле. Таким образом, даже для очень большого сайта может использоваться всего один файл со стилями, что очень сильно облегчает редактирование. Есть еще один “хитрый” необязательный параметр тега LINK: MEDIA. Он может указывать для какого типа устройств таблица стилей предназначена и иметь значения, например, “all” (используется по умолчанию), “handheld”, “print” и некоторые другие. Следует только учесть, что (пока еще?) не все браузеры понимают таблицы стилей, подключаемые с использованием этого параметра.

В некоторых случаях бывает полезно объединить два предыдущих метода - например, если разные секции должны иметь частично разные стили (скажем, отличаться цветом фона). Внутри тега STYLE можно указать
@import url(style.css)
и тогда к стилям, описанным внутри STYLE присоединятся стили из внешнего файла.

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

Практика показывает, что таблицы стилей редко бывают больше 2-3 Кб, даже для очень “раскрашенных” страниц. И если ваш веб-сервер умеет “на лету” сжимать страницы (в Apache, например, этим занимается mod_gzip), то такой объем будет для пользователя практически незаметен. Ну а дальше - дело техники: пишется какая-нибудь команда, которая на сервере читает таблицу стилей из внешнего файла (все-таки один файл намного легче редактировать!) и встраивает ее содержимое в страницу, отдаваемую посетителю. В простейшем случае это может быть инструкция SSI, вроде
<!–#include file=”style.css” –>
а если ваш сайт написан на php, то можно написать, например,
<?php readfile(”style.css”); ?>

Источник: http://www.listsoft.ru/

Tags: CSS, html, style

Добавить комментарий Февраль 28, 2008


Календарь

Февраль 2012
Пн Вт Ср Чт Пт Сб Вс
« Апр    
 12345
6789101112
13141516171819
20212223242526
272829  

Записи по месяцам

Записи по рубрикам

Бегун