faq of Ru.html.Chainik


правила · список вопросов · преамбула · обратная связь

4. Вопросы от незнания JavaScript

4.1. Как сделать кнопку «Back»?
<a href="prevpage.html" onclick="history.back();return false;">Назад</a>
4.2. Как определить, что юзер открыл страницу не в кадре, и перевести его в кадр?

Можно использовать скрипт, просто перенаправляющий на фреймсет (из предыдущей версии FAQ), но гораздо грамотнее сделать так, чтобы пользователю не пришлось потом долго лазить по меню в поисках нужной странички.

Пусть http://www.myserver.com/dir/frameset.html - это фреймсет, в котором есть два фрейма: menu.html - меню, main - рабочее окно для main.html, 1.html, 2.html и т.д.

В случае, если фреймсет и вызванная страничка лежат на одном сервере, то в <head> нужно вставить такой скрипт:

<script language="JavaScript" type="text/javascript"><!-- if (parent==self || parent.location.pathname!='/dir/frameset.html') {    var framesetURL='/dir/frameset.html?main='+      escape(self.location.href)    if (typeof(location.replace)!='undefined') {      self.location.replace(framesetURL) //этот метод из JS1.1 грамотнее, чем простой редирект, потому что //не засоряет history.    } else self.location=framesetURL; } //--></script>

В случае, если вызванная страничка и фреймсет расположены на разных серверах, то скрипт будет такой:

<script language="JavaScript" type="text/javascript"><!-- var parentURL=''; with (parent.location) parentURL=protocol+'//'+hostname+pathname; if (parent==self ||    parentURL!='http://www.myserver.com/dir/frameset.html') {    var framesetURL='http://www.myserver.com/dir/frameset.html?main='+      escape(self.location.href)    if (typeof(location.replace)!='undefined') {      self.location.replace(framesetURL)    } else self.location=framesetURL; } //--></script>

Если у вас на сервере работает CGI, PHP, или ASP, то фреймсет должен взять пришедший параметр $main и указать его в качестве src для фрейма main.

Если это невозможно (страничка лежит на халявном серваке), то во frameset.html в <head> нужно поставить:

<script language="JavaScript" type="text/javascript"><!-- function loadMain() { var mainPos=location.search.indexOf('main=')+5; if (mainPos>4) {    var mainURL=location.search.substring(mainPos,location.search.length);    if (mainURL.indexOf('&')>-1) {      mainURL=mainURL.substring(0,mainURL.indexOf('&'))    }    mainURL=unescape(mainURL);    if (typeof(location.replace)!='undefined') {      self.frames.main.location.replace(mainURL)    } else self.frames.main.location.href=mainURL } } //--></script>

А в тег <frameset> нужно прописать параметр:

onload="loadMain();"

Тогда при внешней ссылке на 1.html или наборе в строке браузера http://www.myserver.com/dir/1.html откроется фреймсет, и в нужный фрейм автоматически загрузится 1.html.

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

Вставьте в <head> такой скрипт:

<script language="JavaScript" type="text/javascript"><!-- if (top!=self) {    if (typeof(location.replace)!='undefined') {      top.location.replace(self.location.href)    } else top.location.href=self.location.href; } //--></script>
4.4. Как на JS при событии в одном из кадров поменять заголовок всего фреймсета? Хотелось бы, чтобы при смене страниц в заголовке окна броузера кроме названия сайта отображалось еще и наименование текущего раздела.

В <body> документа во фрейме поставьте строку

onload="top.title=self.title;"

К сожалению, это работает только в IE.

4.5. Как вставить музыку (MIDI, WAV, MP3) в HTML файл?

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

Hачнем с MP3. Файл с таким расширением (*.mp3) и в таком формате современные браузеры не способны воспроизводить как фоновый звук. Решение проблемы несложно: нужно преобразовать обычный MP3 в закодированный MPEG 1 Layer 3 файл WAV с RIFF-заголовком. Такой файл абсолютно совпадает с исходным MP3, за исключением нескольких начальных десятков байт, и занимает практически столько же места - но, при наличии в системе кодека MP3, спокойно воспроизводится браузером, который считает его обычным WAV. Добавить RIFF-заголовок позволяет большинство программ для генерации MP3.

Поэтому будем считать, что файл с нашей музыкой имеет расширение wav или mid.

Вставляем в <head> такой скрипт:

<script language="JavaScript" type="text/javascript"><!-- var musicURL='mymusic.mid';// путь к файлу с музыкой function doMusic() {    musicTag=(navigator.appName=='Microsoft Internet Explorer')?      '<bgsound src="'+musicURL+'" />':      '<embed src="'+musicURL+'" hidden="true" autostart="true" loop="true" />';    if (confirm('Хотите ли Вы услышать музыку?')) document.write(musicTag); } //--></script>

А где-нибудь в конце документа вставьте скрипт:

<script language="JavaScript" type="text/javascript"><!-- doMusic(); //--></script>
4.6. Как определить разрешение экрана, количество цветов и внутренний размер окна браузера у посетителя?

Разрешение экрана можно узнать так:

var swidth=0; var sheight=0; if (self.screen) { // for NN4 and IE4   swidth = screen.width;   sheight = screen.height } else if (self.java) { // for NN3 with enabled Java   var jkit = java.awt.Toolkit.getDefaultToolkit();   var scrsize = jkit.getScreenSize();   swidth = scrsize.width;   sheight = scrsize.height; }

Также могут быть важны переменные screen.availWidth и screen.availHeight, дающие размер свободной области экрана (без панели задач и других панелей, постоянно занимающих место на экране, например, панели MS Office или ICQ).

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

Внутренний размер окна браузера можно узнать так:

var wwidth=(window.innerWidth)?window.innerWidth:   ((document.all)?document.body.offsetWidth:null); var wheight=(window.innerHeight)?window.innerHeight:   ((document.all)?document.body.offsetHeight:null);

Правда, к сожалению, в IE этот код работает только после того, как браузер дойдет до тега <body>. Поэтому данный код можно применять только в скриптах, выполняемых ниже <body> или в скриптах, выполняемых при возникновении тех или иных событий (наведение мышкой или нажатие на ссылку, отправка формы и т.п.).

Переменная

var colors=(screen.colorDepth)?screen.colorDepth:screen.pixelDepth;

даст вам режим отображения цветов:

4 - 16-цветный режим VGA/SVGA
8 - 256-цветный режим Indexed Color
15/16 - режим High Color (32 или 64 градации красного, зеленого и синего).
24/32 - режим True Color (256 градаций каждого основного цвета)

4.7. Как вставить дату последнего обновления?

Самый простой метод:

document.write(document.lastModified);

Есил вы хотите что-нибудь посложнее, например, вывод даты и дня недели по-русски, то скрипт напишете сами, помня, что document.lastModified является JS-объектом типа Date.

4.8. Как сделать, чтобы при наведении мышки на картинку-ссылку картинка изменилась?
<head> <script language="JavaScript" type="text/javascript"><!-- function ChangeImg() {   if(document.images) {    eval("document."+ChangeImg.arguments[0]+    ".src=('"+ChangeImg.arguments[1]+"')");   } } function preload() {   if (document.images) {     var imgsrc = preload.arguments;     arr=new Array(imgsrc.length);     for (var j=0; j<imgsrc.length; j++) {       arr[j] = new Image;       arr[j].src = imgsrc[j];     }   } } //--></script> </head> <body onload="preload('over1.gif', 'over2.gif', 'overN.gif')">

где overN.gif - картинка, которая должна показываться при наведении мышки. onload нужен для того, чтобы картинки подгружались сразу, а не в то время, когда навели мышку, так как на слабом канале эффекта сразу можно не заметить.

<a href="1.htm"     onmouseover="ChangeImg('image1','over1.gif')"     onmouseout="ChangeImg('image1','out1.gif')"><img src="out1.gif" name="image1" alt="image1" /></a> <a href="2.htm"     onmouseover="ChangeImg('image2','over2.gif')"     onmouseout="ChangeImg('image2','out2.gif')"><img src="out2.gif" name="image2" alt="image2" /></a> ... <a href="N.htm"     onmouseover="ChangeImg('imageN','overN.gif')"     onmouseout="ChangeImg('imageN','outN.gif')"><img src="outN.gif" name="imageN" alt="imageN" /></a>

в <img> "name" нужно для того, чтобы JS знал, какой картинке соответствует каждая ссылка.

Если вы хотите, чтобы картинка менялась, но не была при этом ссылкой, смотрите пункт 5.1.

4.9. Как открыть по ссылке маленькое окошко нужного размера без панели инструментов, строки состояния и т.д.?

Категорически не рекомендуется конструкция вида

<a href="javascript:window.open()">

Правильный код:

<a href="page.html" target="_blank" onclick="window.open(this.href,this.target,'width=XXX,height=YYY,location=no,toolbar=no,menubar=no,status=no');return false;">

(все, что написано в onclick, должно идти в одну строчку )

Этот код обеспечит корректное открытие нового окна с нужным URL даже при отключенных скриптах.

Можно вынести функцию открытия окна в отдельный скрипт:

<script language="JavaScript" type="text/javascript"><!-- function popup(linkObj,w_w,w_h) {   window.open(linkObj.href,linkObj.target,'width='+w_w+',height='+w_h+     'location=0,toolbar=0,menubar=0,status=0');   return false } //--></script> ... <a href="page.html" target="_blank" onclick="return popup(this,XXX,YYY);">
4.10. Как сделать фотогалерею: чтобы в документе были маленькие картинки, а при нажатии на них открывались окошки с увеличенными картинками?
<script language="JavaScript" type="text/javascript"><!-- var resId=0; var imgWndw; function imgOpen(imgLink,Title) {   if (typeof(window.resizeBy)=='undefined') return true;   imgWndw=window.open('',imgLink.target,'width=100,height=100'+     ',toolbar=no,menubar=no,location=no,status=no,'+     'resizable=yes,scrollbars=no,left='+(screen.width>>>2)+     ',top='+(screen.height>>>4));   self.focus();   var imgTitle=(Title)?Title:imgLink.href;   with (imgWndw.document){     open();     write('<ht'+'ml><he'+'ad><ti'+'tle>'+imgTitle+'</ti'+'tle>'+     '</he'+'ad><bo'+'dy leftmargin="0" topmargin="0" '+     'rightmargin="0" bottommargin="0" marginwidth="0" '+     'style="margin:0;padding:0;position:fixed;overflow:none;" '+     'marginheight="0"><img src="'+imgLink.href+'" border="0" '+     ' alt="'+imgTitle+'" title="'+imgTitle+'" class="r" /></bo'+     'dy></ht'+'ml>');     close();   }   resId=setInterval('imgResize()',100);   return false } function imgResize() {   var w=imgWndw.document.images[0].width;   if (w>screen.availWidth) w=screen.availWidth;   var h=imgWndw.document.images[0].height;   if (h>screen.availHeight) h=screen.availHeight;   if (w>50 && h>50) {     var ww=(imgWndw.innerWidth)?imgWndw.innerWidth:((document.body)?       imgWndw.document.body.clientWidth:null);     var wh=(imgWndw.innerHeight)?imgWndw.innerHeight:((document.body)?       imgWndw.document.body.clientHeight:null);     if (ww && wh) {       imgWndw.resizeBy(w-ww,h-wh);     }     imgWndw.focus();     clearInterval(resId)   } } //--></script> ... <a href="disco.jpg" target="_blank" onclick="return imgOpen(this,'Я на дискотеке');"><img src="disco_small.gif" width="80" height="60" alt="Я на дискотеке - 200 Кбайт" title="Я на дискотеке - 200 Кбайт" border="0" /></a> ... <a href="banja.jpg" target="_blank" onClick="return imgOpen(this,'Я в бане');"><img src="banja_small.gif" width="40" height="60" alt="Я в бане - 100 Кбайт" title="Я в бане - 100 Кбайт" border="0" /></a>

Если заменить target в ссылках с "_blank" на какое-нибудь определенное имя (например, "photo"), то все картинки будут открываться в одном и том же окне, которое будет автоматически подстраиваться под размер каждой новой загружаемой картинки.

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

4.11. Есть ли в JS функция, которая бы брала сценарий из внешнего файла? Как грамотно пользоваться внешними скриптами? Почему нельзя использовать внешние скрипты вместо SSI для вывода текста?

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

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

Поэтому грамотный метод использования внешних скриптов такой. В <head> документа, выше всех остальных внешних и внутренних скриптов пишется:

<script language="JavaScript" type="text/javascript"><!-- var jsLoaded=false; //--></script>

Внешний скрипт вставляется так:

<script language="JavaScript1.2" src="myscript.js" type="text/javascript"></script>

Обратите внимание на параметр language - там стоит JavaScript1.2 вместо простого JavaScript для того, чтобы старые бродилки не пытались загрузить то, что они все равно не поймут.

В файле myscript.js последней строчкой должно стоять:

jsLoaded=true;

Затем при необходимости использования функций из внешнего скрипта мы поступаем так:

а) В блоке JavaScript:

<script language="JavaScript" type="text/javascript"><!-- ... // тили-тили // трали-вали if (jsLoaded) {     // это дело мне по силе     // откажусь теперь едва ли } else {     // это мы не проходили     // это нам не задавали } ... //--></script>

б) При вызове функции по событию в теге HTML:

<a href="page.html" onClick="return (jsLoaded)?externalFunction(...):true;">
4.12. Почему NN некорректно ведет себя с русской буквой «я» в сценариях?

Теория: в яваскрипте не должно быть свободного знака 0xFF. Поэтому мы берем знаки, которые могут перекодироваться в 0xFF, и предваряем их обратным слешем. Если вы программировали на Си, такая запись вам знакома.

Практика:

кодировкаOxFFво всех кодировках пишем
1251 "я""\я"
КОИ-8 "Ъ""\Ъ"
4.13. Чтобы при наведении мышки на ссылку выдавался мой текст, а не «http://www.name.ru/...»?
<a href="http://rhc.msk.ru" onmouseover="window.status='мышка на ссылке';return true;" onmouseout="window.status=window.defaultStatus;return true;">ссылка</a>.
4.14. Как убрать рамки, возникающие при нажатии вокруг ссылок?

Hа это явление жалуются только пользователи MSIE. Оно и понятно. Вставьте в тег ссылки слова onfocus="this.blur();". Все те, кто привык, что курсор не пропадает с глаз долой, скажут вам много теплых и ласковых слов.

4.15. Как сделать выпадающее меню ссылок?
<body> <form action="/cgi-bin/redir.cgi" method="post"> <select name="redirURL" onchange="location.href=this.options[this.selectedIndex].value;"> <option value="">-- Выбрать --</option> <option value="http://www.aaa.com/">AAA</option> <option value="http://www.bbb.com/">BBB</option> <option value="http://www.ccc.com/">CCC</option> </select> <noscript><input type="submit" value="Перейти!" /></noscript> </form> </body>

Для тех, у кого отключены скрипты, создайте CGI для редиректа (/cgi-bin/redir.cgi), перенаправляющий клиента на нужную страницу.

Вот этот скрипт на Perl:

#!/path/to/perl use strict; use CGI; use CGI qw/:standard/; my $query = new CGI; print redirect(-url=>$query->param('redirURL'));

Hа PHP:

<? Header("Location: $redirURL"); ?>

Hа ASP:

<% Response.Redirect Request("redirURL") %>

правила · список вопросов · преамбула · обратная связь · наверх


По материалам эхоконференции RU.HTML.CHAINIK (news://fido7.ru.html.chainik)