JavaScript - FAQteam

Ну куда-ж нам без JavaScript? Сейчас даже самый захудалый баннер и то без этого не обходится.

  1. Как подавить сообщения об ошибках.
  2. Как правильно вывести текст в строке статуса .
  3. Что возвращать при событиях.
  4. Как сделать переносы в alert().
  5. Простые способы отладки скриптов.
  6. Какие можно использовать отладчики скриптов.
  7. Ограничения в JavaScript, связанные с безопасностью.

Вопрос:  Можно ли подавить вывод сообщения об ошибке, если, например, броузер какой-то версии не поддерживает объекты и/или свойства, используемые в скрипте?

Ответ: Эту проблему можно легко разрешить, перехватывая событие window.onerror. Достаточно назначить в качестве обработчика этого события функцию, возвращающую true... и все!

Пример кода подавления ошибок:

<html>
<head><title>Title</title>
<script type="text/javascript"><!--
function stopError() {
  return true;
}
window.onerror = stopError;
//--></script>
</head>
<body>
...
</body>
</html>

 Примечания: Оператор window.onerror = stopError; не даст ошибки, даже если в броузере нет такого свойства, т.к. в любом броузере вполне легальна операция - добавить к объекту window новое свойство (в нашем случае onerror).

Если у вас нет 100%-й уверенности, что ваши скрипты будут выполняться в любом броузере на любой платформе (а такой уверенности не может быть ни у кого и никогда ;), постарайтесь воспользоваться этим методом, чтобы подавить все JavaScript-ошибки. И не забывайте, что этот способ применяется не во время отладки кода, а после нее! :)

 Внимание: Назначение window.onerror обязательно нужно делать по ссылке (как указано, а не как вызов функции onerror()).

Все, что расположено в скрипте после ошибочной строки, выполняться не будет!

 Проверено на : IE4, NN4+ под Windows.


Вопрос:  Я хотел бы, чтобы в строке статуса выводилось пояснение к моей ссылке, а не адрес перехода. Но когда я пишу <a href="bla-bla.htm" onMouseOver= "window.status= 'klevaya linka'">Go!!!</a>, то все работает не так как надо...

Ответ: Все работает плохо, так как вы забыли отключить стандартную обработку события mouseover, предусмотренную в броузере -- вывод адреса перехода в строке статуса. Таким образом, стандартная обработка произошла после вашей, и "затерла" ее.

Чтобы отключить стандартную обработку, свою надо завершить возвратом логического значения true (истина). Тем самым вы как бы сигнализируете броузеру, что все уже сделано, и он может спать спокойно:

<a href="bla-bla.htm"
  onMouseOver="top.status='klevaya linka'; return true">Go!!!</a>

Заметим, что мы использовали top.status вместо window.status не для того, чтобы было покороче (если бы у нас была такая цель, можно было написать просто status='...'). А такой вариант работает и в случае, если ваш документ является одним из фреймов.

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

<a href="bla-bla.htm"
  onMouseOver="top.status='klevaya linka'; return true"
  onMouseOut="top.status=''">Go!!!</a>

то есть, вы, не мудрствуя лукаво, стираете ваше сообщение.

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

<script type="text/javascript">
<!--
oldStatus='';
function setStatus(text) {
  oldStatus=top.status;
  top.status=text;
  return true;
}
function restoreStatus() {
  top.status=oldStatus;
}
-->
</script>

а при обработке событий вызываете эти функции:

<a href="bla-bla.htm"
  onMouseOver="return setStatus('klevaya linka')"
  onMouseOut="restoreStatus()">Go!!!</a>

 Примечания: Если таким способом вы просто хотите пояснить назначение ссылки, то лучше использовать атрибут TITLE, который поддерживается многими современными броузерами (например, <a href="bla-bla.htm" title="klevaya linka">). Ну а если вы хотите скрыть истинный адрес, скрывающийся за ссылкой, то какие бы хитроумные способы вы не применили, посмотреть на исходный текст страницы можно в любом случае.

 Внимание: Хотелось бы отметить, что подобные трюки со строкой состояния броузера не очень-то понравятся многим из посетителей вашей странички. Те из них, кто захочет узнать, что же скрывается за ссылкой, будут вынуждены обращаться к пункту меню Свойства (Properties), что, естественно, не вызовет у них ликования.

 Проверено на : IE4+, NN4+ под Windows.

 Что еще почитать: А.Лебедев. О статусной строке


Вопрос:  Почему не работает моя конструкция <a href="#" onclick= "location.href = 'coolpage.htm'"> Go!!! </a>?

Ответ: Потому, что вы забыли отключить стандартную обработку указанного события, предусмотренную в браузере - переход по указанному в ссылке адресу. Таким образом, стандартная обработка произошла после вашей, и "затерла" ее.

Чтобы отключить стандартную обработку, свою надо завершить возвратом логического значения, чаще всего FALSE (return false), но иногда - наоборот - TRUE (return true). К первому случаю относятся события onClick, onMouseDown/Up, onSubmit, onReset,... Из вторых мне известны onMouseOver/Out, onError.

Точная закономерность возврата true/false покрыта мраком. Однако, наличие такой закономерности позволяет предполагать то, что во всех известных случаях оба самых распространенных браузера (NN и IE) любых версий работают в этом плане одинаково правильно (что довольно-таки удивительно).

Таким образом, вышеприведенную конструкции правильно будет записать так:

<a href="#"  onclick="location.href='coolpage.htm'; return false">Go!!!</a>

Иногда в приведенном примере вместо onClick предпочитают использовать событие onmousedown - в этом случае для корректной работы не требуется ничего возвращать. Однако, в этом случае действие выполнится также и при нажатии правой кнопки мыши на ссылке, что вряд ли интересно как дизайнерам, так и пользователям. Избежать этого можно, во всяком случае под NN (перехват событий, модель событий JS1.2), но сравнительно сложно (во всяком случае, намного сложнее, чем вернуть false). Поэтому использование onClick выглядит гораздо предпочтительнее.

Возможно, более удобным будет использовать такой вариант: <a href="javascript: location.href='coolpage.htm'">Go!!!</a> - получается короче и как-то логичнее.

 Внимание: Сама по себе приведенная конструкция с onClick довольно бессмысленна. Подобное бывает нужно для более сложных действий, и в целом предполагает, что ссылка работает как кнопка. Из этого вытекает проблема: ее можно открыть в новом окне правой кнопкой, но это не даст нужного эффекта. То же самое, кстати, относится и к варианту с href="javascript:...", а если вы используете в скрипте свои функции или переменные, это также приведет к ругани браузера (если она не отключена) на ошибки в скрипте. Бороться с этим можно следующими способами:

1) Использовать вместо ссылки настоящую кнопку, и даже прекрасиво вписать ее в страницу при помощи стилей - для счастливых пользователей IE (и, может быть, уродливо, для пользователей NN). Пожалуй, самый простой и самый верный способ. Используйте всегда, когда возможно это сделать без уродования страницы.

2) Работает только под NN, c 4-й версии (как под IE ни бился, ничего не достиг :( ). Опять-таки отключать нажатие правой кнопки на ссылке. Для этого придется перехватить событие onMouseDown, проанализировать объект event (событие) на предмет номера нажатой кнопки (для NN это свойство event.which), и в случае правой кнопки отключить стандартную обработку (return false).

Пример:

<script><!--
var NN4=(navigator.appName=="Netscape")&&(parseFloat(navigator.appVersion)>=4)
function MyMainFunction() {
  alert("Вот для чего все это надо !!")
}
//--></script>
<a href="javascript:MyMainFunction()"
  onmousedown="if(NN4)return(event.which==1)">Go!!!</a>

 Проверено на : NN4, IE4.

 Что еще почитать: О статусной строке


Вопрос:  Подскажите пожалуйста, как в alert('Очень-очень-очень длинная фраза.') сделать переносы?

Ответ: Используйте символ переноса строки \n. Например, вот так:

<html>
<head>
  <title>Smile</title>
</head>
<body onload="alert('На этой странице ничего нет.\n Только моя улыбка.\n\n:)')">
:)
</body>
</html>

 Примечания: Строка "На этой странице..." не должна иметь переносов в html-файле, иначе это сообщение не будет выводится ни в ИЕ, ни в НН. Опера его покажет, добавив дополнительные переносы.

 Проверено на : ИЕ 4, ИЕ 5, НН 4.51, Опера 3.62


Вопрос:  Мне почему-то кажется, что мой скрипт не работает. Как его отлаживать?

Ответ: Как известно из законов Мерфи - программа, работающая сразу после написания, работает неправильно. А посему отладка - самое распостраненное занятие, за которым можно застать простого труженика Интернета. Но кто сказал, что мы любим мучиться? Вот несколько советов, которые могут облегчить вашу жизнь.

Во-первых, проверьте синтаксис, скобки и кавычки. Для этого лучше всего пользоваться программой, которая раскрашивает текст в зависимости от языка - если вам неоткуда такую программу взять, сходите на http://www.chami.com/colorizer/ - "Раскрашиватель on-line". Как показывает горький опыт, большинство ошибок происходит именно из-за этого.

Простота - залог здоровья. Поэтому если вы можете обойтись простым выводом на экран - не пожалеете. Делается это так:

<script type="text/javascript">
  //предположим, вашу переменную зовут Vasya.
  alert("Вот и Вася - " + Vasya);
</script>

или же

<script type="text/javascript">
  //предположим, вашу переменную опять же зовут Vasya.
  document.write("Вот и Вася - " + Vasya + "<br>");
</script>

В первом случае вы увидите выскочившее окошко с кнопкой "ОК" и с текстом "Вот и Вася - 4" (если Vasya равен 4), а во втором вы увидите строчку "Вот и Вася - 4" прямо внутри вашей странички - на том месте, где вы поставили document.write. (<br> я добавляю, чтоб разделять отладку и собственно документ).

 Примечания: Обратите внимание, что и alert, и document.write в качестве аргумента предполагают получить строку. Более серьезные штуки, массивы, например, можно вначале скомпоновать в строку и разбавить комментариями по вкусу:

<script type="text/javascript">
  function alertArray(arr){
    var i;
    var str = "";
    for (i=0;i<arr.length;i++)
      str +="На месте "+ i+" мы видим " +arr[i]+"\n";
    alert(str);
  }
</script>
Mouse

Вопрос:  Как-то все простые способы отладки моему скрипту не помогают. Что дальше?

Ответ: Скрипты действительно бывают разные, и иногда приходится пускать в ход тяжелую артиллерию. Это так называемые debuggers - отладчики.

Отладчики под Internet Explorer:

  • Халява прежде всего - Microsoft Script Debugger берется здесь. Там же можно почитать про него и про JScript, VBScript и Windows Scripting Host (по-английски). Отладчик обещает работать с Windows 95, 98, NT4 и 2000 и помочь вам справиться со скриптами на VBScript и JScript, а так же с Java под Microsoft Java Virtual Machine. Еще этот самый отладчик готов помогать вам в отладке как на стороне сервера, так и клиента. Особенно он бывает полезен в вылавливании ошибок, которые выскакивают нежданно-негаданно посреди страницы - в этом случае вас спросят, хотите ли вы отлаживать этот негодный скрипт, допустивший ошибку. Отладчик покажет вам точное место, где произошла ошибка, и позволит вам полюбоваться на значения разных переменных, которые вас заинтересуют - для этого вам следует набрать в окошке "Command" имя переменной (для JScript) или вопросительный знак, пробел и имя переменной для VBScript. Короче говоря, гораздо лучше, чем ничего.
  • Если вам так повезло, что у вас уже есть Visual InterDev, и вы все еще не собрались ее стереть - лучше используйте ее в качестве гораздо более усовершенствованного отладчика. Для того, чтобы использовать ее в качестве такого большого отладчика Javascript запустите Explorer и Visual InterDev и в самый подходящий по вашему мнению момент выберите в меню Debug->Processes, в открывшемся окошке выберите то, что хотите отлаживать, нажмите Attach и по желанию Break - это прервет исполнение скриптов и запустит отладчик немедленно. В качестве полезных штучек следует отметить окошки Watch (которое не только сообщает значение, но и прозволяет полюбоваться "внутренностями" массивов или объектов на странице) и Call Stack (помогает определить, как вы "дошли до такой жизни", то есть порядок вызова функций) В-общем, большой и несколько неуклюжий, но очень полезный, особенно для отладки DHTML.

Отладчики под Netscape:

  • Во-первых, его собственная консоль, вызываемая магическим "javascript:" в адресной строке. Там вы увидите поподробнее, что, на какой строке в каком файле и как не сработало. Кроме того, его можно использовать в качестве калькулятора :-)
  • Кроме того, есть еще Netscape JavaScript Debugger 1.1, обитающий по этому адресу. Он работает только с Netscape 4 (что значит - не с 6). Довольно удобная вещь в хозяйстве, хотя иногда виснет.
  • Для Netscape 6 отладчика пока нет, и кроме того "мантра" "javascript:", упомянутая мною выше, не работает. :-( Для вызова консоли нужно просто пойти в меню Tasks -> Tools -> JavaScript Console. Она потеряла способности калькулятора - нет больше text box, но стала выглядеть посимпатичнее.

 Что еще почитать: Статья на Webreview "Debugging JavaScript"

Mouse

Вопрос:  Почему иногда мои скрипты не могут получить доступ к некоторым объектам на других страницах?

Ответ: Это происходит из-за встроенных ограничений в JavaScript, в основном, при работе с окнами и фреймами. А именно: "JavaScript automatically prevents scripts on one server from accessing properties of documents on a different server." (так дословно сказано в документации Netscape по Javascript). То есть скрипты не имеют полного доступа к документам на "чужих" серверах. Логику этого ограничения понять нетрудно.

Как определяется "чужой сервер"? Должны совпадать следующие части URL: protocol://host:port. Вот пример для страницы http://company.com/dir/page.html:

URL Результат Причина
http://company.com/dir2/other.html Все ОК -
http://company.com/dir/inner/another.html Все ОК -
http://www.company.com/dir/other.html Провал Разные домены (www.company.com - не совпадает с company.com)
file://D:/myPage.htm Провал Разные протоколы (file - не совпадает с http)
http://company.com:80/dir/etc.html Провал Разные порты

Что именно нельзя "трогать руками" скриптом, не прошедшим проверку?

Объект Свойства, при доступе к которым проверяется "дружественность" скрипта
document NN Для чтения и изменения: anchors, applets, cookie, domain, embeds, forms, lastmodified, length, links, referrer, title, url, formname (для каждой формы с именем=named form), reflectedjavaclass (для каждого джава-класса, доступного скриптам через liveconnect в НН) Только для изменения (т.е. читать можно): все остальное
IE Для чтения и изменения: anchors, applets, cookie, domain, embeds, forms, lastmodified, length, links, referrer, title, url, formname (для каждой формы с именем=named form), all Только для изменения (т.е. читать можно): все остальное
form elements
image lowsrc, src
NN: layer src
location все кроме x и y
window find

Что же из этого следует и как с этим бороться, если у меня два сайта?

Если ваши страницы расположены на двух разных сайтах с одним окончанием (sub-domain), например, на mouse.company.com и cat.company.com, то следущая строка в обоих страницах вас спасет:

document.domain = 'company.com'

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

Этот прием работает только если вы меняете domain на его же окончание - в нашем примере нельзя будет выставить его равным "mouse.com" или "company.ru". Кроме того, новый domain должен быть по крайней мере второго уровня - "company.com", а не "com".

Кроме того, в Нетскейпе signed scripts, а в IE ActiveX имеют особые привилегии... но это уже совсем другая история.

Mouse

Valid HTML 4.0! Made with CSS
Все вопросы и пожелания сюда или сюда