генерация html кода javascript
Генерация HTML: удобнее чем хелперы и чистый HTML
Писать чистый HTML часто неудобно, особенно если нужно делать динамические вставки.
Шаблонизаторы частично решают эту проблему, но их причудливый синтаксис нужно изучать, мириться с ограничениями, вкладывать одни шаблоны в другие для повторного использования, в целом попытка хороша, но что-то не то.
В некоторых фреймворках есть хелперы, в частности написать эту статью меня вынудила Aura.Html. С хелперами иная история — они изначально задуманы для реального упрощения, поскольку одной командой могут генерировать хороший кусок HTML кода, но они в большинстве заточены под определённое использование, и что-то дальше этого выглядит слишком криво.
Как более универсальное решение было бы не плохо не изобретать причудливый синтаксис, а использовать самый обычный PHP и всем знакомые примитивные CSS-селекторы.
Размышляя в таком духе некоторое время назад я принялся пилить свой велосипед. Велосипед получился, использовался в рамках другого велосипеда, потом отделился, много раз обновлялся, и сейчас я хотел бы поделиться им с сообществом.
Как оно работает?
Идея была в том, чтобы сделать как можно проще:
что на выходе даст
Это самый простой пример. Название метода — тэг, внутри передается значение. Если нужно добавить атрибутов — не проблема:
И можно было бы подумать, что проще уже никак, но тут на помощь приходят CSS-селекторы, и немного уличной магии:
На выходе будет то же самое. С первого взгляда может показаться немного странным, но на практике весьма удобно.
В сравнении с Aura.Html
В начале я упоминал Aura.Html, стоит сравнить как генерируется HTML там, и тут.
Aura.Html (пример из документации):
Любой из параметров можно было вынести в массив.
На выходе:
И ещё вариант посерьезней.
Aura.Html (пример из документации):
Тут in используется явно, его можно использовать для передачи внутренностей тэга, как Content в примере с div выше. Используются как общие правила, так и некоторые специальные, немного подробнее о которых дальше.
На выходе то же самое:
Специальная обработка
Все тэги следуют общим правилам обработки, но есть некоторые тэги, которые имеют дополнительные конструкции для удобства.
Например:
Работает похоже с select, в value значение, а checked проставится когда совпадет одноименный элемент передаваемого массива.
Ещё один пример использования in и специальной обработкой input[type=radio]:
Никаких оберток label не добавляется специально, чтобы сделать код максимально общим и предсказуемым.
Если нужно обработать массив
Это, наверное, самая часто используемая вместе с контролем вложенности возможность, так как данные и правда часто приходят откуда-то в виде массива.
Для обработки массива его можно передать прямо вместо значения:
Либо даже опустить лишние скобки в самом простом случае
Каждый элемент массива будет обработан отдельно, то есть вполне законно передавать не только строки, но и некоторые атрибуты, правда, иногда это выглядит слишком монструозно:
Если в вызове тоже были указаны атрибуты — class и style будут расширены, остальные перезаписаны, атрибуты с логическим значением false будут удалены.
С помощью волшебной палочки, которая не является привычной частью CSS-селектора (это единственное исключение, без которого можно обойтись), можно управлять тем, как будут обрабатываться уровни вложенности:
Если массив получен из базы данных, или иного хранилища — удобно использовать такой массив напрямую, и это можно сделать передав в специальный атрибут insert:
Можно и в одну строчку все атрибуты написать:
А ещё всё это можно расширять
Этот класс представляет только общие, ни к чему не привязанные правила генерации HTML, которые могут быть использованы независимо от окружения.
Но иногда хочется упростить выполнение более сложных рутинных операций.
Например, я использую многие элементы UIkit на фронтенде, и, например, для переключателя нужна особым образом подготовленный HTML.
Скопировав оригинальный код обработки input и слегка отредактировав можно получить такой результат:
Так же можно переопределить метод pre_processing, и реализовать произвольную обработку атрибутов непосредственно перед рендерингом тэга, например, при наличии атрибута data-title я навешиваю класс, и таким образом получаю всплывающую подсказку над элементом при наведении.
Преимущество использования
Генерируется HTML без шанса оставить тэг незакрытым, или что-то в этом роде.
Везде используются общие правила обработки, которые логичны, весьма быстро запоминаются, и являются намного чаще удобными, чем наоборот.
Можно использовать с абсолютно любыми тэгами, даже с веб-компонентами (пример писать не буду, и так много примеров).
Нет никаких зависимостей, есть возможность унаследовать и переопределить/расширить по желанию всё что угодно, так как это всего лишь один статический класс, и больше ничего.
На выходе обычная строка, которую можно легко использовать вместе с абсолютно любым кодом, использовать на входе следующего вызова класса.
Где взять и почитать
На этом, пожалуй, хватит примеров.
Исходный код на GitHub
Там же есть документация с подробным объяснением всех нюансов использования и всех поддерживаемых конструкций.
Поставить можно через composer, либо просто подключив файл с классом.
Пример наследования с добавлением функциональности
Использование Java-script для генерации html-странички и конфигурации девайса
Тоже скорее для заметок, но может кому понадобится…
Давным — давно, в далекой галактике… Так, о чем это я? А, вот:
Эн-ное количество времени назад я мучил посетителей данного ресурса вопросами по HTTP-протоколу и тому подобным вещам, так как понадобилось мне в разрабатываемом девайсе настройки сделать, а подключение к компу у меня идет посредством Ethernet (через W5100). Первый вариант странички я нарисовал по старинке ручками, использовав формы и методику описанную Lifelover’ом в его цикле статей. Страничка вполне себе отображалась и позволяла менять данные, я даже начал писать парсер запроса для изменения настроек в устройстве, но потом так получилось, что задвинул проект в «долгий ящик» и если и занимался им, то другими моментами, а не общением «клиент-сервер».
Не так давно я опять решил поковыряться со страницей конфигурации и наконец допилить ее до конца. Так как весь костяк у меня был написан и отдавался — я решил прикрутить к нему забор реальных конфигурационных данных устройства (до этого у меня отдавались статические данные никак с реальной конфигурацией не взаимодействующие) при генерации странички и отдаче ее браузеру. Все бы ничего, да только данные надо было вносить по тексту в разных местах по всей странице, и никак не выходило сделать это красиво без нагромождения горы кода (ну и чтоб потом, если что, можно было добавить/изменить данные не переписывая кроме страницы еще и весь здоровый блок). Это меня никак не устраивало и тогда-то я вспомнил, что есть такая вещь как Java-script…
Вспомнил, нарыл в сети учебник, и стал читать. Что-то вспомнилось, т.к. когда-то я делал пару несложных страничек, но тогда я кроме пары функций по обработке мышки ничего больше не использовал. А тут оказалось все гораздо интересней. Результат который у меня получился (пока что без обработки ответа от девайса) приложен к статье в архиве. Весь процесс и язык описывать не буду, опишу только некоторые тонкости и те плюсы, которые я получил в результате…
1. Очень сильно изменился костяк страницы. Вместо кучи таблиц типа
Перед ним идет небольшой кусок CSS, а после идет скрипт. Все остальные составляющие страницы генерятся исключительно скриптом. Минус такого подхода конечно есть: если у пользователя в браузере запрещено исполнение скриптов, то он ничего толком не увидит. С другой стороны, у меня девайс не висит в каких-то там интернетах непонятно где, а лежит передо мной на столе и даже если я страдаю паранойей, я могу отрубить инет, включить исполнение скриптов, все настроить и потом опять вырубить скрипты в исходное состояние.
2. Само наполнение страницы посредством скрипта выглядит гораздо удобоваримей и вполне читабельно и понятно:
3. Перед вышеописанным блоком функций идет блок описания переменных. Сначала я описываю переменные, которые будут браться из настроек устройства (начиная с tablerowdata и заканчивая selected_eng включительно, далее идут переменные которые используются для генерации страницы, но от настроек устройства не зависят. Тут стоит обратить внимание на то, что в приложенном файле конфигурационные параметры уже присвоены переменным. Это сделано для того, чтобы страница выглядела наглядно. В МК этот блок выглядит так:
Тоесть чтобы сгенерировать страничку с реальными данными, мне надо на лету распарсить и заполнить только 2 строки текста а не всю страницу, как при первом варианте.
4. Самые внимательные заметили некоторую разницу в вышеприведенном коде и приложенном файле.
Первое отличие — нет названия первой переменной и не хватает квадратных скобок. Тут все просто: я вынес лишние символы из данной строки оставив только необходимые для нормального парсинга.
Второе отличие — появился непонятный .split(‘ ‘). Это результат работы специальной программы-оптимизатора натравленной на скрипт (только на скрипт, всю страницу он не пережевывает и плюется). Оптимизатор удаляет лишние пробелы из текста, преобразует длинные имена переменных в короткое a,b,c и хитрым образом анализирует и оптимизирует код, компонуя его в максимально короткие структуры. В результате не надо пихать в память МК тонны ничего не значащего текста. Выгода налицо.
5. Дабы не усложнять анализ полученных от клиента данных я в некотором роде оградил себя и его от ввода неверных параметров. Это касается настроек аналогового тракта устройства. Посредством хитрого изменения комбинаций атрибутов я добился того, что запрещенные состояния в данной позиции либо не видны, либо неактивны. Например закрылкам и тормозу нельзя поставить в соответствие номер двигателя. А если управление тягой 2го двигателя стоит на 3ей оси, то нельзя поставить ее же на любую другую ось. По идее надо еще проверять корректность параметров в блоке сетевых настроек, но пока я этого делать не стал. Короткий найденный вариант на тему «вводить в поле input только цифры» меня не устроил (к тому же я до сих пор не вкурил как он работает), а длинный мне пока делать не охота. Потому я просто выдаю вместо неверных данных 0.
6. По идее самый простой способ отправки данных на сервер был описан еще Lifelover-ом: организовать кнопку submit и все. Я решил submit не делать, потому что в случае какой-либо нестыковки все параметры вылазят в командную строку браузера и он начинает ломиться неизвестно куда. Это происходит даже в случае, если обработчику submit’а запретить выдачу данных на сервер (во всяком случае в Chrom’е). Поэтому я организовал обычную кнопку, а по клику на нее сам ручками генерю строку запроса и отправляю ее на сервер посредством XMLHttpRequest. По идее данную часть кода надо еще немного модифицировать, потому как я проверял ее работу только в Хроме, а другие браузеры могут работать по другому, например кэшировать запросы и ответы и выдавать отсебятину. Из Хрома запрос уходит.
7. В предыдущем пункте я затронул вопрос о различии в обработке скрипта разными браузерами. Рассмотрим подробнее, в чем это сказывается:
Первое различие — обработка переменных: я не буду говорить за стандарт, но по идее идентификатор объявленный тегом является объектом с данным именем. Значит что к свойствам и методам этого объекта можно обращаться посредством «.». Но оказывается не всегда и не везде. Например, в приложенном файле есть следующая строка:
Первоначально она выглядела по другому:
Первоначальный вариант работал во всех браузерах за исключением IE (у меня 9). IE просто переставал обрабатывать скрипт и страница была почти пустой. После исправления IE успешно прожевал скрипт и даже не подавился, хотя я думал что придется все обращения переделывать через document.getElementById. Скорее всего так и стоит сделать дабы не вылазили непредвиденные ошибки. Похожая проблема вылезла и в Опере. Только Опера споткнулась в другом месте (IE кстати там тоже загнулся):
ch0 тоже пришлось брать посредством getElementById. После этого все заработало.
Второе различие — разница в обработке атрибута hidden (кстати это логический тип и когда он присутствует, то имеет значение true.
Мне надо было скрыть «запрещенный» элемент списка внутри тэга select, т.е. организовать строку html вида:
Первоначальая запись вида
применяемая к тэгу
срабатывала только в Хроме. Сафари, несмотря на общие корни движка, данный атрибут игнорировал. Остальные браузеры тоже.
Тогда я видоизменил запись:
После такого изменения нормально заработал FireFox, но IE, Опера и Сафари продолжали игнорировать атрибуты
В итоге пришлось делать финальный вариант:
его переваривают все браузеры (разве что с телефона не проверял, но по идее должно работать и там)…
Пооткрывайте файл разными браузерами (например Хромом и IE) и покрутите разные варианты настроек аналогового тракта, чтобы понять о чем речь.
P.S. Если в процессе экспериментов с приложенным файлом будут выявлены какие-либо траблы, прошу написать мне об этом, т.к. у меня вроде все работает.
UPD: После обработки скрипта оптимизатором и ручного убийства лишних пробелов в теле странице получилось порядка 6 с копейками Кил. текста, передаваемого непосредственно с МК, включая заголовок. По сравнению с 12К исходного материала — вполне неплохо. Предыдущий вариант у меня занимал 8 К текста (без удаления пробелов), но он не реализовывал и половины той функциональности, что есть сейчас, просто позволял ввести сетевые настройки и все.
UPD 2:
Сейчас проверил страничку с телефонов. У меня в наличии Nokia E71, браузер по иконке похож на мобильный FireFox, но его точную идентификацию я так и не нашел. И еще в наличии iPhone4 с Safary на борту.
iPhone отрабатывает все финты ушами с атрибутами как и на компе, а вот Симбиановский вариант атрибуты тэгов Options продолжает игнорить.
Но на iPhone сейчас вылезла другая фишка: я поправил в коде то место, где происходило закрытие TCP-соединения после отдачи странички. И телефонный сафари стал материться на то, что «страница не может быть отображена, т.к. соединение разорвано», хотя перед этим полностью грузит страницу и отображает. Ручная остановка загрузки страницы срабатывает и страницей можно пользоваться…
гм… эксплорер к разрыву соединения тоже относится крайне негативно. независимо от наличия Content-Length, хотя, если рвать соединение после небольшой задержки, все работает и не ругается. Однако Content-Length пришлось оставить.
UPD 3
Бился пол дня с кросс-браузерной отправкой запроса. Получилось следующее:
добавилась функция для корректного создания объекта запроса:
и соответственно изменилась сама функция выполнения запроса:
Так же, для предотвращения кэширования данных в заголовке страницы добавилась пара meta-заголовков:
С кэшированием особенно злобствовала Опера. Даже IE нормально все отсылал, а опера ни в какую. После объявления данных заголовков все заработало нормально.
Если вместо null указать » (в сети частенько попадается такая запись) — то FireFox перестает слать запросы.
UPD 4
Еще про борьбу с кэшированием… После того как проапдэйтил статью, полез ковырять прогу дальше и обнаружил, что браузеры, все как один, опять закэшировали мои запросы. После долгих плясок с бубном я это таки преодолел.
Вышеуказанные пляски с тэгом «meta» действуют только на загружаемую страницу. Кстати к «мета» я добавил еще и
Хоть и пишут, что данный параметр устаревший, но при его наличии работает лучше.
Кроме мета-тэгов желательно в заголовке страницы указать значение Cache-Control:no-cache\r\n, т.к. на мета-тэги браузеры иногда забивают.
Теперь о самом запросе:
после метода .open надо с помощью метода .setRequestHeader установить атрибуты заголовка запроса:
Причем значения атрибута Cache-Control надо ставить именно в указанном порядке, иначе возникнут проблемы с оперой и FireFox’ом.
Так же запрос не должен оканчиваться символом ‘&’ иначе Хром не будет отдавать запрос.
Задолбали меня эти браузеры… Опять закэшировали.
Добил я вроде эту тему. В приложенном файле обновленная версия страницы. Смотреть лучше на локально развернутом сервере. В данной модификации отключена проверка на корректный ответ от железки.
Решение с проблемой кэширования крылось не только в заголовках HTTP вопросов/ответов, но и в корректной имитации сервера. Тоесть на этапе написания первого варианта статьи девайс умел отвечать только на 2 запроса: «GET / » и «GET /. ». Все остальные запросы он просто игнорировал. Внимательное курение результатов сниффинга и самого стандарта HTTP 1.1 выявило обязательную обработку ошибочных состояний 404 (не найдено) и 501 (не реализовано). Связано это с тем, что после загрузки страницы с «/» браузер пытается загрузить фавиконку (а иногда и не один раз) и шлет соответственные случаю запросы. Если на них не отвечать — то браузер вполне может посчитать что сервер отпал и все остальное догрузить из кэша. А состояние 501 — добавил на всякий случай, если браузер вздумает спросить чего непотребное…
Комментарии ( 101 )
Минус такого подхода конечно есть: если у пользователя в браузере запрещено исполнение скриптов, то он ничего толком не увидит.
На самом деле, сейчас это нельзя считать минусом, потому что браузеров без поддержки javascript нет, и по умолчанию его поддержка всегда включена. А если человек отключает javascript, то он должен понимать, что это повлечет за собой неработоспособность большинства сайтов.
А может лучше было бы хранить страницы во внешней памяти? и придумывать бы ничего не пришлось, и размером не так ограничен, даже картинки можно было бы запилить.
Free Online HTML Code Generator CSS JavaScript PHP JQuery
Free Online HTML CSS JavaScript jQuery Code Generator. www.html-code-generator.com Provides Free HTML Codes. Click Generate Code That You Can Copy And Paste Into Your Website. Without Typing A Single Character Of HTML Codes With Just One Click Generate Your HTML Codes. You Can Find All Things HTML From HTML Codes, HTML Editors, HTML Generator And CSS Generator, JavaScript Code Generator, And More.
HTML Code Generator
Online HTML Editor
Here you can write and see HTML in action. HTML editor to create HTML snippets or a whole web page. you can download and save your code.
HTML CSS Rainbow Text
HTML Rainbow colors Text. add your text or paragraph and Choose a color scheme click generate button. The HTML rainbow code is useful for copy and paste into AOL Instant Messenger. By sending the HTML text.
HTML select list generator
HTML select drop down list generator. one click generate HTML drop down select list. year select list, month select list, date select list, country names select list, country phone number select list, number select list, Google Web Font Name Select List
HTML Table Tow Color Row
HTML Table Generator. This Tools Easily Create HTML Table,create Tow Color Row Background, Tow Color Background Columns, Table Row Highlight On Hover. Click The Table Cell And Enter Properties And Press The Generate Button. HTML Table Using CSS
Marquee Generator
Online HTML Marquee Generator.Use this HTML marquee generator to create scrolling text or images for your website or blog. Image Marquee Generator, Link Marquee Generator Text Marquee Generator,Generate your own HTML marquees quickly and easily. CSS transform style preview your marquee
Typewriter Text Scroll
HTML JavaScript Typewriter Text Scroll. Generate your own HTML Typewriter quickly and easily. add your scrolling typing messages and click generate button and copy code for your website or blog.
CSS Generator
CSS Textbox Styles
CSS Textbox Styles. 100 more CSS textbox style select a textbox and you can add modify CSS codes
CSS checkbox style
200 CSS Radio Button Checkbox Toggle Switch, on off Button, Android On/Off Switch Button. change radio button checkbox style
CSS Button With icon
CSS Button Generator With icon. CSS Button With Image icon Generator. CSS gradient background color button and add icons, make CSS button for your website
CSS Triangle Generator
CSS Triangle Generator. this tool create border transparent Triangle. how to create triangle first click the triangle arrow Direction and change background colors change size and click below generate button.
CSS 3D Text Generator
CSS 3D text effect generator online. create online 3D text effect, this text effect showing CSS multiple text-shadows
Применяем продвинутые техники для улучшения вашего JavaScript кода
В этой статье мы рассмотрим самые распространённые техники и шаблоны, применив которые, вы сможете сделать ваш код более изящным и компактным. Для освоения данного урока, вам необходимы базовые знания JS и опыт работы с регулярными выражениями.
Длинные условные выражения
Первый рецепт, который мы рассмотрим, поможет сократить размер условных выражений if. Идея заключается в том, чтобы заменить логические операторы на простые регулярные выражения:
Если вы данную задачу обычно решаете таким образом:
Знайте, что то же самое может быть записано вот в таком виде:
Следующий случай, с которым вам наверняка приходилось сталкиваться, это применение логического оператора:
Если у вас огромное число переменных, которые нужно проверить, вы можете создать специальный массив с именами переменных, второй массив с ожидаемыми значениями, и применить метод every. Метод every возвращает true, если проверяемые значения совпадают:
Этот же пример можно ещё больше абстрагировать:
Для точно такой же проверки с применением логического оператора OR воспользуйтесь методом some, который возвращает true, если хотя бы одно выражение совпало. Однако такие выражения используются редко. Гораздо чаще нам могут встретиться условия с чередованием обоих логических операторов:
В этом случае стандартный подход лучший.
Работа с текстом
По сравнению с другими языками, JavaScript содержит небольшое количество функций для работы со строками. Представьте ситуацию: у нас есть параграф, где все предложения разделены точками. Мы хотим каждую букву каждого первого слова предложения сделать заглавной. С помощью циклов и некоторых строковых функций данная задача решается так:
Для оптимизации данного примера воспользуемся регулярными выражениями:
Другой пример: нам необходимо извлечь из строки все телефонные номера. Предположим, что перед каждым из них есть префикс “tel:”. Это поможет нам извлечь только номера телефонов. Все остальные цифры в строках затронуты не будут. В данном примере лучшим решением может быть применение регулярных выражений, и поскольку телефонов может быть несколько, нам необходимо написать глобальное регулярное выражение. Сначала попробуем применить метод match:
Как вы уже заметили, в результате наши номера записались вместе с префиксом “:tel”. Дело в том, что match не записывает найденные значения в группы. Данный функционал доступен в методе exec.
Данный способ не является единственным возможным решением данной задачи. Также мы можем воспользоваться методом replace, который принимает функцию, в которую мы передаём саму строку. Все дальнейшие параметры указывают на различные группы захвата:
Также мы можем объявить свой собственный метод gmatch и, в дальнейшем, им пользоваться.
Теперь наш код смотрится намного лучше!
Генерация HTML кода
Если вы много работаете с JavaScript-ом, то наверняка вам довольно-таки часто приходится генерировать каике-то списки, таблицы и прочие элементы. Обычно для этого используется вот такая техника:
Данный пример решает нашу задачу, но выглядит не очень хорошо. Для более изящного решения, воспользуемся методом join:
Отлично! Но что, если нам нужен индекс? В этом случае, можем скомбинировать работу методов map и join:
Когда задачи усложняются, нам приходится писать всё больше и больше циклов для отдельных разъединённых HTML фрагментов кода. Для решения данной проблемы можем воспользоваться техникой написания шаблонов. Давайте напишем очень простого “помощника”, которого будем использовать для работы с шаблонами:
Его мы можем использовать следующим образом:
Данный способ позволяет нам генерировать HTML фрагменты кода вот таким вот изящным способом.
Используем функциональный код
JavaScript позволяет нам писать функциональный код, который мы можем использовать для написания более компактных скриптов. Примеры этому вы можете увидеть выше.
Все последние браузеры, включая IE9, поддерживают методы EcmaScript5, однако, многим из них мы можем найти альтернативу.
Одним из преимуществ обработки функции в цикле является возможность создания новой области видимости. Это может пригодиться, когда мы запускаем асинхронный код внутри цикла. Представьте ситуацию:
Теперь же результат будет такой, как мы ожидаем, однако данный код может немного запутать. Всё становится гораздо понятнее, если мы воспользуемся циклом forEach, который самостоятельно создаёт новую область видимости:
Благодаря методам, применяемым к массивам, мы можем извлечь практически любую нужную нам информацию по определённому критерию:
Данный код смотрится неплохо, однако при большом количестве операций он будет дублировать неоднократно. Это нас не устраивает, и поэтому мы объявим и реализуем специальный прототипы функций и применим уже изученные нами техники для того, чтобы иметь возможность писать вот такой изящный код:
Для понимания следующего кода, вам потребуются хорошее понимание функционального программирования в JavaScript. Надеюсь, комментарии помогут вам разобраться:
Теперь представьте, что мы можем творить благодаря системе шаблонов, которые создали ранее:
Также возможны и более сложные варианты:
Также мы можем применять к нашим объектам методы forEach, map, slice, every, some, reduce :
Итоги
Применяя функциональные техники, мы можем сделать наш код чистым и больше похожим на модульный. Такие фрэймворки, как jQuery и Zepto, применяют подобные методы программирования.
5 последних уроков рубрики «Разное»
Как выбрать хороший хостинг для своего сайта?
Выбрать хороший хостинг для своего сайта достаточно сложная задача. Особенно сейчас, когда на рынке услуг хостинга действует несколько сотен игроков с очень привлекательными предложениями. Хорошим вариантом является лидер рейтинга Хостинг Ниндзя — Макхост.
Проект готов, Все проверено на локальном сервере OpenServer и можно переносить сайт на хостинг. Вот только какую компанию выбрать? Предлагаю рассмотреть хостинг fornex.com. Отличное место для твоего проекта с перспективами бурного роста.
Разработка веб-сайтов с помощью онлайн платформы Wrike
20 ресурсов для прототипирования
Подборка из нескольких десятков ресурсов для создания мокапов и прототипов.
Топ 10 бесплатных хостингов
Небольшая подборка провайдеров бесплатного хостинга с подробным описанием.