мета-данные страницы
  •  
Загрузка не удалась. Возможно, проблемы с правами доступа?

Это старая версия документа!


Упражнения и задания к урокам

Урок 1: введение

Язык JavaScript изначально был предназначен для написания простых сценариев, исполняемых в среде www-браузера…

На странице портала javascript.ru и в разделе Встраивание в веб-страницы на wikipedia подробное обсуждается вопрос внедрения скриптов в тело html-страниц с примерами и историей вопроса. Если коротко, то самый компактный и современный (по стандарту html5) вариант выглядит так:

<script>
   alert('Hello, World!');
</script>

более общий и более совместимый со стандартом html4 – так:

<script type="text/javascript">
   alert('Hello, World!');
</script>

ещё более древний, не стандартный, но до сих пор самый ходовой:

<script language="javascript">
   alert('Hello, World!');
</script>

(возможно их совмещение, указание дополнительных атрибутов, напр., кодировки скрипта – примеры см. на указанных выше сайтах)

Наиболее важным для нас атрибутом является src, который позволяет подгружать внешний отдельный файл со скриптом.

Урок 2: ввод-вывод информации из скрипта

Простейший вывод из скрипта на JavaScript осуществляется с помощью вызова функции alert("string").

<html>
<head><title>Hello, world!</title></head>
<body>
<p><a href="javascript:alert('Hello, world!')">Click me!</a></p>
</body>
</html>

Реализацию можно посмотреть тут: Hello, world!

Простейший ввод можно сделать с помощью функции prompt().

<html>
<head><title>Alert-Prompt</title></head>
<body>
<p><a href="javascript:n=prompt('Put something, please:','');alert(n)">Click me!</a></p>
</body>
</html>

Реализацию можно посмотреть тут: Alert-Prompt (в Internet Explorer'е может быть заблокировано окошко ввода, и надо будет дать специальное разрешение на временное исполнение скрипта)

NB!! Вот здесь надо прочитать Почему <a href="javascript:..."> - плохо

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

<HTML>
  <HEAD>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
    <TITLE>n!-calculating</TITLE>
    <SCRIPT LANGUAGE="JavaScript">
      function checkinput(n)
      {
        var n1;
        n = n + "";  n1 = parseInt(n) + "";
        if ((n == n1) && (n1>0)) {return 1} else {return 0};
      }  // checkinput
      function fact(n)
      {
        if ( n==0 ) { return 1; };
        return n*fact(n-1);
      };  // fact
      function You_Go()
      {
      n = prompt('put in the field a natural number: ',1);      
      while ( checkinput(n) )
      {
        f = fact(n);
        n = prompt('n!='+f+'\nput in the field a natural number: ',1);
      }
      };
    </SCRIPT>
  </HEAD>
  <BODY BGCOLOR="White" TEXT="Black" LINK="Blue" VLINK="Purple" ALINK="Red">
    <H1>Расчет факториала</H1>
    <P>На данной странице предложен пример расчета факториала...
    <BR>
    Для завершения работы введите любое ненатуральное число и/или буквы.
    <hr>
    <a href="javascript:You_Go()">Перезапуск</a></P>
    <SCRIPT LANGUAGE="JavaScript">You_Go()</SCRIPT>
  </BODY>
</HTML>

Реализацию можно посмотреть тут: факториал (в Internet Explorer'е может быть заблокировано окошко ввода, и надо будет дать специальное разрешение на временное исполнение скрипта)

Таким образом, в этом уроке, кроме собственно ввода и вывода данных, мы видим активацию функций JavaScript по событиям, задаваемым пользователем, таким как клик мышкой по ссылке, изменение данных в форме ввода и т.п. Связь эта изначально описывалась атрибутами onclick, onchange, onload и другим, добавленными к некоторым тегам в html-3, либо обработчиками в форме по атрибуту action или по псведопротоколу в ссылках (см. выше). В настоящее время, отчетливо сформировалась другая тенденция, так называемый ненавязчивый JavaScript, суть которого еще больше разделить контент с размеченным html-текстом и скрипты поддержки на javascript. Но об этом в другой раз.

Урок 2.1: ввод-вывод из полей формы

На практике функцию prompt() используют чаще всего в целях отладки. Для ввода удобней поля специально предназначенных для этого форм. Рассмотрим пример:

<HTML>
<HEAD>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
<TITLE>working with form</TITLE>
</HEAD>
<BODY BGCOLOR="White" TEXT="Black" LINK="Blue" VLINK="Purple" ALINK="Red">
<H1>Форма ввода</H1>
 
<P>Обрабатываем форму ввода...</P>
<P><form name="fm1" action="javascript:void(Yeah())">
<INPUT TYPE="text" name="tx1" value="это текст!! :)" size="60">&nbsp;
<INPUT TYPE="button" VALUE="Сменить!" onClick="Yeah()">&nbsp;
<INPUT TYPE="reset" VALUE="Сброс">
</form></P>
 
<SCRIPT LANGUAGE="JavaScript">
function Yeah()
{
  var s1 = document.fm1.tx1.value;
  var s2 = prompt('Введите что-нибудь еще!\nВаш ввод был:', s1);
  document.fm1.tx1.value = s2; 
}
</SCRIPT>
</BODY></HTML>

Обращение к полям в функции Yeah() происходит как квалифицированной глобальной переменой, точнее, как к свойству объекта, внешнего по отношению к телу функции. Запись

document.fm1.tx1.value

как раз и показывает пример такого обращения. Здесь document – это объект самого высокого уровня (выше – ссылка на окно, по умолчанию – текущее), fm1 – имя формы (подчиненного объекта), заданной в атрибуте name формы, tx1 – имя имя текстового поля ввода (подчиненного к форме), value – изменяемое свойство объекта document.fm1.tx1.

Пример доступен здесь: Доступ к полям формы через объекты

Добавим еще код. Теперь обратимся к элементам формы не через глобальный объект, а через передачу ссылки на объект при вызове функции, сократив таким образом количество вводимого текста и сделав функцию вызова более универсальной (единообразно пригодной для обработки других форм на странице).

<P>Определим Ваш любимый цвет:</P>
<P><form name="fm2">
<select name="sl">
<option>красный</option>
<option>зеленый</option>
<option>синий</option>
<option>желтый</option>
<INPUT TYPE="button" VALUE="Посмотрим выбор!" onClick="GoNow(this.form.sl)">&nbsp;
<INPUT TYPE="reset" VALUE="Сброс">
</form</P>
<SCRIPT LANGUAGE="JavaScript">
function GoNow(s)
{
  var i = s.selectedIndex;
  var s = s.options[i].text;
  alert ("" + s);
};
</SCRIPT>

Урок 3: управляющие операторы, создание функций

Пока сообщим, что язык Си-подобный, основные управляющие операторы if, for, while и др. наследуются из Си. Особенности опишем позже :)

В качестве примера рассмотрим «решатель квадратных уравнений»:

function roots(a,b,c)
{
  var sd,x1,x2;
  if (a==0 && b==0) return;
  if (a==0 && b!=0) { x1=-c/b; return [x1,x1] };
  var d  = b*b - 4*a*c;
  if (d>=0)  
    { 
      sd = Math.sqrt(d);
      x1 = (-b-sd)/(2*a);
      x2 = (-b+sd)/(2*a); 
      return [x1,x2];
    }
  else return;
}

запуск будем осуществлять через такую страничку:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Решатель квадратных уравнений</title>
</head>
<script src="roots.js"></script>
<body>
<H1>Решатель квадратных уравнений</H1>
<form name="myform">
a: <input type="text" name="a">
b: <input type="text" name="b">
c: <input type="text" name="c">
<input type="button" name="runtest" value="Решить" onclick="alert(roots(this.form.a.value,this.form.b.value,this.form.c.value))">
<input type="reset">
</form>
</body>
</html>

Урок 4: динамическое изменение документов (простой вариант)

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

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

  top.doc.document.open();
  top.doc.document.write("<P>Hello!</P>");
  top.doc.document.close();

Здесь top – ссылка на окно самого верхнего уровня (в нашем случае будем фреймсодержащее окно), top.doc – ссылка на окно (фрейм), предназначенное для перезаписи.

Если речь идет о текущем окне, то пишем document.open() и т.п.

Иллюстрация описанных идей: Пример динамического изменения документа

Урок 5: динамическое изменение документов (более сложный вариант)

Рассмотрим элементы наиболее современной технологии динамического изменения элементов HTML документа: так называемую технологию DOM.

Прежде всего мы должны уметь получить ссылку на желаемый html-элемент по его «ID»:

<div id="label23">...</div>
...
 
var zdes = document.getElementById("label123")

Далее, мы должны сформировать html-контейнер, который будет содержать требуемый html-код, и текст:

  var node1 = document.createElement('p');
  var node2 = document.createTextNode("В лесу родилась елочка");

Теперь, добавим текстовое содержимое (т.е. node2) в заданный контейнер (т.е. node1):

  node1.appendChild(node2);

Затем, мы должны добавить полученный контейнер в дерево документа:

 zdes.appendChild(node1);

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

zdes.removeChild(zdes.lastChild)

а чтобы удалить их всех, так:

function MyClear()
{
  while (zdes.lastChild) { zdes.removeChild(zdes.lastChild) };
};

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

Эта тема рассмотрена на сайте javascript.ru: Изменение страницы посредством DOM.

Другие возможности. Можно упростить вставку, не формируя поддерево DOM, а вставляя лишь требуемый html-код. Об этом можно почитать, напр., тут: JavaScript метод insertAdjacentHTML и beforeend или тут: Свойство innerHTML.

Использование css. Для создания спойлеров, описанный выше метод может оказаться громоздким. Более простым решением будет манипуляция свойством стиля, например: display:none или display:block (см. описание display или похожую технику visibility)

И реализовать тогда его можно следующим образом. Получаем как прежде ссылку на требуемый объект (html-ноду):

<div id="label23">...</div>
...
 
var zdes = document.getElementById("label123")

Затем устанавливаем

zdes.style.display = 'none';

и наш

..

вместе с содержимым визуально исчезнет. Выставим теперь:

zdes.style.display = 'block';

и он появится! 8-)

Урок 5.1: Создаем свой спойлер

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

Иными словами, выглядеть это должно примерно так:

<div class="spoilertitle" text="THIS IS SPOILER!!!"></div>
<div class="spoiler">
...здесь скрываемый текст...
</div>

Для начала определим пару полезных нам функций:

function getTagged(name, elem) {
  return (elem || document).getElementsByTagName(name);
}
 
function getNext(elem) {
  do {
    elem = elem.nextSibling;
  } while ( elem && elem.nodeType != 1 );
  return elem;
}

Здесь первая функция getTagged собирает множество элементов с тэгом name, при этом, если задан второй аргумент elem, то в его «потомках», если не задан, то – по всему документу.

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

elem.nodeType != 1

важна, если есть такой риск.

Теперь, собственно, основной код:

var alldiv = getTagged("div");
 
for (var j=0; j<alldiv.length; j++) {
  if(alldiv[j].className == "spoilertitle") 
    {
      alldiv[j].insertAdjacentHTML('afterbegin', alldiv[j].getAttribute("text"));
      alldiv[j].onclick = spoiling;
      alldiv[j].onmouseover = function(){this.style.textDecoration="underline"};
      alldiv[j].onmouseout =  function(){this.style.textDecoration="none"};
 
      var nxt = getNext(alldiv[j]);
      while ( nxt.className != "spoiler" ) {nxt = getNext(nxt)};
      nxt.style.border = "dotted black";
      nxt.style.backgroundColor = "aqua";
      nxt.style.display = "none";
    };
}
 
function spoiling() {
  var nxt = getNext(this);
  while ( nxt.className != "spoiler" ) {nxt = getNext(nxt)};
  console.log(nxt.id, "check: ",  nxt.style.display);
  if (nxt.style.display == "none")  {nxt.style.display = "block"; console.log("set=",nxt.style.display); return};
  if (nxt.style.display == "block" || !nxt.style.display) {nxt.style.display = "none";  console.log("set=",nxt.style.display)};
}

Прокомментируем программу. Условие

  if(alldiv[j].className == "spoilertitle") 

делает отбор только тэгов, помеченных классом spoilertitle. Для этого контейнера, мы, во-первых вставляем следом (но перед спойлером!) html-текст из «нестандартного» атрибута text:

 alldiv[j].insertAdjacentHTML('afterbegin', alldiv[j].getAttribute("text"));

Строка

alldiv[j].onclick = spoiling;

создает обработчик события клика мышкой по содержимому контейнера. Заметим, что spoiling – всего лишь ссылка на функцию, а не ее вызов типа spoiling(..)!

Строки

  alldiv[j].onmouseover = function(){this.style.textDecoration="underline"};
  alldiv[j].onmouseout =  function(){this.style.textDecoration="none"};

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

Далее, в блоке

      var nxt = getNext(alldiv[j]);
      while ( nxt.className != "spoiler" ) {nxt = getNext(nxt)};
      nxt.style.border = "dotted black";
      nxt.style.backgroundColor = "aqua";
      nxt.style.display = "none";

во-первых, с помощью nxt = getNext(alldiv[j]) получаем ссылку на следующий контейнер (сестринский элемент), перебираем их все, проверяя, чтобы был в наличии класс spoiler:

while ( nxt.className != "spoiler" ) {nxt = getNext(nxt)};

Для найденного элемента nxt устанавливаем требуемое стилевое оформление:

      nxt.style.border = "dotted black";
      nxt.style.backgroundColor = "aqua";
      nxt.style.display = "none";

где самое главное для нас – скрытое по умолчанию состояние спойлера: nxt.style.border = "dotted black"

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

  var nxt = getNext(this);
  while ( nxt.className != "spoiler" ) {nxt = getNext(nxt)};

мы уже обсуждали.

Команда

  console.log("check: ",  nxt.style.display);

позволяет нам осуществить запись в лог значения nxt.style.display. Наконец, проверяем

  if (nxt.style.display == "none")  {nxt.style.display = "block"; console.log("set=",nxt.style.display); return};
  if (nxt.style.display == "block" || !nxt.style.display) {nxt.style.display = "none";  console.log("set=",nxt.style.display)};

состояние значения nxt.style.display и соответственно переобпредляем это значение на противополжное (отдельная забота о случае, если pyfxtybt nxt.style.display не определено).

Код базируется на примерах, взятых из книги Резинга, создателя пакета jquery; разность стилей в выполнении однотипных задач определяется ленью и забывчивостью…

Урок 6: динамическое изменение картинок и события задержки

В браузерах рисунки рассматриваются как объекты с набором некоторых свойств. Таким образом, новый рисунок может быть создан в скрипте таким образом:

  img1 = new Image(40,120);

(однако, это не значит, что он будет отображен, тем не менее, он будет добавлен в кэш и в случае необходимости мгновенно отображен)

Наиболее важным для нас атрибутом будет src, значение которого мы будем динамически менять. Сами рисунки в документе организованы в массив, к которому удобно обращаться, если нам ненужно или неудобно обращать к рисунку по имени-ссылке.

Имя рисунка, заданного тегом <img name="myimg" src="pict.gif"> будет совпадать со значением атрибута name.

Вот как это реализовано в примере: Дин. картинки

Урок 7: тайм-аут ;-)

Пример работы с таймером и с датой демонстрирует «старый стиль» работы с таймером: вместо установки setInterval используем рекурсивный вызов таймера, и вместо передачи ссылки на функцию передаем строку с выражением для выполнения.

<HTML>

</HTML>

sic (на будущее) работа с календарем

<HTML>

<script> var alldiv = getTagged(«div»);

for (var j=0; j<alldiv.length; j++) {

if(alldiv[j].className == "spoilertitle") 
  {
    alldiv[j].insertAdjacentHTML('afterbegin', alldiv[j].getAttribute("text"));
    alldiv[j].onclick = spoiling;
    alldiv[j].onmouseover = function(){this.style.textDecoration="underline"};
    alldiv[j].onmouseout =  function(){this.style.textDecoration="none"};
    var nxt = getNext(alldiv[j]);
    while ( nxt.className != "spoiler" ) {nxt = getNext(nxt)};
    nxt.style.border = "dotted black";
    nxt.style.backgroundColor = "aqua";
    nxt.style.display = "none";
  };

}

function spoiling() {

var nxt = getNext(this);
while ( nxt.className != "spoiler" ) {nxt = getNext(this)};
console.log(nxt.id, "check: ",  nxt.style.display);
if (nxt.style.display == "none")  {nxt.style.display = "block"; console.log("set=",nxt.style.display); return};
if (nxt.style.display == "block" || !nxt.style.display) {nxt.style.display = "none";  console.log("set=",nxt.style.display)};

}

function getTagged(name, elem) {

return (elem || document).getElementsByTagName(name);

}

function getNext(elem) {

do {
  elem = elem.nextSibling;
} while ( elem && elem.nodeType != 1 );
return elem;

} </script> </HTML>