Пару слов о Wap и PDA сайтах

Кирилл Евсеев, May 5, 2011

Я уверен, что скоро персональные компьютеры повторят судьбу динозавров. Мейнфреймы, cloud-computing, лэптопы, мобильные устройства и нестандартные гаджеты с доступом к паутине рано или поздно окончательно победят большие и неповоротливые ящики, напичканные железяками. Обычные PC останутся только в малобюджетных гос. организациях и ВУЗах и, однажды, какой-нибудь всемирный консорциум типа ISO объявит об отмене поддержки стандартов для писюков. Рынок PC пережил свой пик в конце 90-хх – начале 2000-хх и теперь из года в год показывает стабильное снижение продаж. Вычислительные мощности топовых ноутбуков вполне сопоставимы с вычислительными мощностями топовых PC. Конечно, топовые PC продолжают выигрывать, но для абсолютного большинства бизнес-пользователей производительности мобильных платформ хватает с огромным запасом. Последний форпост PC – это геймеры. Но, рано или поздно, они окончательно пересядут на специализированные игровые консоли, а для чата и сёрфинга заменят свои писюки на ноутбуки. Последняя проблема в мобильных устройствах – ёмкость батареи. Рано или поздно эта проблема будет разрешена и PC переместятся в пыльные музеи кремниевых микросхем.

Но пока этого события не произошло, посмотрим на всю нашу деятельность критическим взглядом. Сколько сайтов сегодня имеет мобильную версию? Имеет ли сайт вашей компании мобильную версию? Имеет ли мобильную версию ваш хоумпейдж? Или блог? Насколько удобно вам работать с удалённым ресурсом с помощью телефона? Вряд ли на все эти вопросы можно ответить однозначное и твёрдое да. Конечно, огромные порталы уже давно имеют свои мобильные версии. Но бизнес рунета почему-то шевелится крайне медленно. Моя компания даже “дарит” мобильную версию сайта в случае хорошего и жирного заказа. Хотя, с точки зрения бизнеса, владельцы доменов должны давным давно обратить внимание на сайты, оптимизированные для мобильных платформ. (more…)

DIV всплывающий поверх flash-баннера

Вячеслав Гринин, May 11, 2010

В процессе создания сайтов, столкнулся однажды с проблемой выражаемой в том, что flash-баннер, размещенный на странице, закрывает собой всплывающий DIV содержащий в себе меню навигации.

Сам этот DIV имеет z-index больше нуля, и когда на странице нет никакой Flash-анимации, этот DIV плавает поверх страницы. Однако, как только появляется Flash-баннер, то баннер этот рендерится поверх любых плавающих DIV-ов.

Как и все гениальное, решение оказалось простым. Достаточно тегам OBJECT и EMBED добавить атрибут wmode со значение opaque.

Выглядеть это должно как-то так:

<OBJECT wmode="opaque" ...>
<EMBED ...>
<PARAM name="wmode" value="opaque">
</EMBED>
</OBJECT>

А связано это с тем, что по умолчанию, параметр этот принимает значение window, а это говорит браузеру, что флешку необходимо отрисовывать поверх страницы и всего, что на ней находится. Другие значения параметра wmode – opaque и transparent. Последний ко всему прочему позволяет задавать прозрачный фон для DIV’а, отображаемого поверх флешки. Учтите, что подобные игры с прозрачностью могут заметно ухудшать производительность работы браузера.

Кросдоменная передача данных между html-страницами

Вячеслав Гринин, April 29, 2010

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

Справочник по JavaScript и объектной документной модели DOM говорит нам, что для открытия нового окна нужно использовать метод window.open(), а для доступа из “дочернего” окна в “родительское” (то есть то, которое и породило новое окно) нужно использовать указатель opener. Рассмотрим этот факт на примере:

index.htm

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
 <title>Главное окно</title>
 <script>
 function openWindow() {
 window.open("http://easy4web.ru/samples/transfer/popup.htm",
    "contents", "toolbar=no", "status=no");
 }
 </script>
 </head>
 <body>
 <input type="button" onclick="openWindow()"
    value="Показать диалог"/><br />
 <input type="text" id="data" />
 </body>
</html>

popup.htm

<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <title>Диалоговое</title>
 <script>
 function transferData() {
 opener.document.getElementById("data").value =
    document.getElementById("inp").value;
 window.close();
 }
 </script>
 </head>
 <body>
 <input type="text" id="inp" name="inp"/>
 <input type="button" value="OK" onclick="transferData()"/>
 </body>
</html>

В главной странице мы видим кнопку, по нажатии на которую открывается новое окно, и TEXTBOX с айдишником data, в него-то и будет попадать текст, введенный в диалоговом окне.

А вот и диалоговое окно, в нем мы видим TEXTBOX и кнопку по нажатию на которую текст введенный в текстовое поле присваивается текстовому полю data из главного окна. А доступ к нему мы и получаем при помощи указателя opener.

Вот здесь (Передача данных между окнами в рамках одного домена) вы можете протестировать работу этого алгоритма.

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

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

Невозможность передачи данных между окнами в разных доменах

При попытке передачи данных между окнами получим ошибку Error: Access is denied.. Происходит это потому что прежде чем получить доступ к любому методу или свойству объекта opener браузер сравнит домен, в котором существует этот объект и домен, из которого происходит вызов собственно метода или свойства объекта opener. И если доменные имена не совпадают, будет возбуждено исключение “Доступ запрещен”.

Решить эту проблему можно. И мы решим ее без использования каких-либо серверных технологий, только силами JavaScript. Это становится возможным, если мы узнаем еще вот какую тонкость. При изменении свойства location.href в порожденном окне в него загрузится страница, заданная ссылкой, но значение указателя opener не изменится, он так и будет продолжать указывать на породившее его главное окно. А теперь представим себе, что мы в диалоговое окно загрузили все ту же главную страницу, или любую другую но с того же домена, где лежит главная страница, а после этого обратились к объекту opener, теперь домены диалогового окна и объекта opener снова совпадают, а значит исключение возбуждено не будет.

А теперь – время для исходников, иллюстрирующих пример:

index.htm

<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <title>Главное окно</title>
 <script>
 function openWindow() {
 var par = "?loc=" + location.href + "&id=data";
 window.open("http://easyapi.ru/easy4web/transfer/popup2.htm" + par, 
    "contents", "toolbar=no", "status=no");
 }
 function getDataFromUrl() {
 var txt_id, data;
 var url = location.href;
 var query = url.split("?")[1];
 if(query) {
 var params = query.split("&");
 for(var i = 0; i < params.length; i++) {
 var keyval = params[i].split("=");
 if(keyval[0] == "data") {
 data = keyval[1];
 }
 if(keyval[0] == "id") {
 txt_id = keyval[1];
 }
 }
 }
 if(txt_id && data) {
 opener.document.getElementById(txt_id).value = data;
 close();
 }
 }
 getDataFromUrl();
 </script>
 </head>
 <body>
 <input type="button" onclick="openWindow()" 
    value="Показать диалог"/><br/>
 <input type="text" id="data" />
 <script>
 getDataFromUrl();
 </script>
 </body>
</html>

Итак, здесь мы видим, что процедура openWindow() все также открывает диалоговое окно, однако теперь она передает ему параметры: loc – указывающий на URL самой порождающей страницы; id – айдишник текстбокса, в который будет вставлен текст из дочернего окна.
А еще мы видим, что после загрузки контента главной страницы вызывается функция getDataFromUrl(), которая проверяет, есть ли GET-параметры id и data (айдишник текстбокса и текст, который мы в него будем вставлять). Параметры эти при изначальной загрузке страницы не заданы, а сначит при первой загрузке страницы код обновляющий содержимое текстбокса не выполнится. А когда он выполнится мы узнаем после того, как рассмотрим исходники диалогового окна.

popup.htm

<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
 <title>Диалог</title>
 <script>
 function transferData() {
 var url = location.href;
 var query = url.split("?")[1];
 if(query) {
 var params = query.split("&");
 for(var i = 0; i < params.length; i++) {
 var keyval = params[i].split("=");
 if(keyval[0] == "loc") {
 var loc = keyval[1];
 }
 if(keyval[0] == "id") {
 var txt_id = keyval[1];
 }
 }
 }
 if(loc && txt_id) {
 location.href = loc + "?id=" + txt_id + 
    "&data=" + document.getElementById("inp").value;
 }
 }
 </script>
 </head>
 <body>
 <input type="text" id="inp" name="inp"/>
 <input type="button" value="OK" onclick="transferData()"/>
 </body>
</html>

Здесь при клике по кнопке выполнится функция transferData(), которая сначала извлечет из адресной строки параметры loc и id, те самые, которые мы передали окну при его порождении. И если эти параметры есть – присвоим location.href адрес страницы loc(главной страницы), а в GET-параметры ей передадим id и data(айдишник текстбокса и данные, которые мы в него запишем). При этом в текущее окно (диалоговое) загрузится содержимое главнйо страницы и выполнится та самая функция getDataFromUrl() которая на этот раз извлечет все необходимые параметры из GET-строки и выполнит метод getElementById() объекта opener.document.

Вот и весь секрет кросдоменной передачи данных между окнами.

Вот здесь (Передача данных между окнами в разных доменах) можно протестировать работу вышеприведенного алгоритма.

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

DOM: вытаскиваем текст вне тегов

Вячеслав Гринин, March 23, 2010

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

В нашем случае документ представляет собой два дива с заданными строго идентификаторами, между которыми расположен искомый текстовый элемент.  При помощи getElementById мы на ходим элемент div1, а затем при помощи nextSibling добираемся до текстового узла, ведь он стоит следующим в DOM-структуре. Получить его значение можно при помощи свойства nodeValue.

Вот и весь рецепт.

<html>
<head>
 <title>Hello!</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <script type="text/javascript">
 function getText()
 {
 var div1 = document.getElementById("div1");
 div1.nextSibling.nodeValue = "Поменял текст";
 }
 </script>
</head>
<body>
<div id="div1">Предшествующий блок</div>
Это текст я хочу получить
<div id="div2">Замыкающий блок</div>
<input type="button" value="Start!" onclick="getText()">
</body>
</html>

Хаки для браузеров

веб-дизайнер, April 15, 2009

Сегодня мне хотелось бы поговорить о так называемых «css-хаках». CSS-хаки используют тогда, когда один конкретный браузер надо заставить отображать некий блок разметки не так, как хотелось бы самому браузеру. Сразу оговорюсь, что использовать хаки нужно только тогда, когда это действительно необходимо. Скажем, всеми нами горячо любимый Internet Explorer (седьмой версии) имеет свои, сугубо специфичные представления о работе со списками. И иногда надо только ему объяснить, что он неправ:-)
Вообще задача раздельных CSS для разных браузеров имеет несколько путей решения. Один из них — встроить в <head></head> php-, или java-скрипт, определяющий тип браузера, и отсылающий конкретный браузер к предназначенной для него стилевой таблице. Второй — если проблемы возникают только с IE — так называемые «условные комментарии». В <head></head> задается конструкция вида:

<!–[if IE]><link rel=”stylesheet” href=”css/ie.css” type=”text/css” media=”screen” /><![endif]–>

или для конкретных версий Explorer’а:
<!–[if IE7]><link rel=”stylesheet” href=”css/ie7.css” type=”text/css” media=”screen” /><![endif]–>
<!–[if IE6]><link rel=”stylesheet” href=”css/ie6.css” type=”text/css” media=”screen” /><![endif]–>

И, наконец, третий путь — CSS-хаки.

Самый удобный в плане хаков браузер – Firefox (и относящиеся к его семейству), так как имеет свою группу css-классов, начинающуюся с перфикса @-moz-
Например:

@-moz-document url-prefix() {
.style {background: #F00;}
}

css-rule, x:-moz-any-link{

}

Для Opera:

@media all and (-webkit-min-device-pixel-ratio:10000),
not all and (-webkit-min-device-pixel-ratio:0) {
.style {background: #F00;} /* только для Opera */
}

html:first-child {} /* только для Opera */
html:first-child .style {
background: #F00; /* только для Opera < 9.5 */
}

Также, можно создать специальный файл стилей для Opera и подключить его следующим образом:
<head>
<link rel=”stylesheet” href=”css/opera.css” type=”opera/css” media=”screen” />
&lt/head>

Google Chrome и Safari по способу работы с блочной моделью напоминают Opera и с высокой долей вероятности можно предполагать, что если ваша верстка нормально выглядит в Опере, то и в Хроме с Сафари с нею тоже все будет нормально. Однако, на всякий случай, хаки:

body:last-child:not(:root:root) .style {
background: #F00;
}

Ну, и наконец, хак для IE. Почему только один? По опыту решения конкретных задач могу сказать, что все проблемы верстки, с которыми мне приходилось сталкиваться, были одинаковыми у наиболее распространенных версий IE (6,7). Поэтому я пользовался (если пользовался) универсальным хаком, так называемым «holy hack»:

html {
background: #f00; (это понимают все браузеры)
* background: #0f0; (а это только ослики)
}

Напоследок напомню, что практически все хаки влияют на валидность полученного кода, поэтому, если есть возможность – надо обходиться без них. А такая возможность есть почти всегда, и исключение составляет только горячо любимый всеми нами Internet Explorer:-)

Поиск по блогу:
Подписаться:
Популярные:
Облако тегов:
Разное:
Счетчик: