My:JS

Материал из synset
Версия от 07:59, 18 октября 2011; WikiSysop (обсуждение | вклад) (Объекты)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Введение

Подключение к html-файлу файла со скриптом обычно происходит в разделе заголовка:

 
<head>
    <script type="text/javascript" src="script.js"></script>
</head>

Там же можно размещать непосредственно скрипт:

 
<head>
   <script type="text/javascript">
      document.writeln("<H1>Моя первая страница.</H2>");
    </script>
</head>

Эта программа, используя объект document (текущий в браузере) и его метод write пишет на экране текст. Данный сценарий выполняется сразу при открытии документа. В этом же скрипте могут находится функции, которые вызываются при возникновении тех или иных событий, например, при клике на некоторой группе:

 
<div onClick="showMessage();">Текст</div>

При клике на тексте выскочит окошко, Если в script (или подключаемом файле *.js) описана функция:

 
function showMessage(){  alert ("Вы щелкнули по div-у"); }

Непосредственный запуск функции при загрузке можно объявить и в body:

 
<body onload="init();">

Переменные

 
var x = 5;                                // переменные стоит объявлять
y = 4;                                    // можно и не объявлять, тогда они становятся глобальными 
document.writeln("res=", x+y, "<br>");    // вывод в тело документа
document.writeln(typeof x, "<br>");       // вывод типа переменной в виде строки => number

x = "4";                                  // переменные имеют плавающий тип
document.writeln("res=", x+y, "<br>");    // результат равен "44" (как соединение строк)
document.writeln(typeof x, "<br>");       // вывод типа переменной => string

document.writeln(typeof Infinity, "<br>");// константа равная максимальному вещественному числу => number
document.writeln(1/0, "<br>");            // деление на ноль => Infinity
document.writeln(2*"a", "<br>");          // => NaN
document.writeln(2*"2", "<br>");          // => 4     (строка "2" преобразовалась в число)

document.writeln(typeof z, "<br>");       // => undefined (такой переменной не было)
  • Базовые примитивные типы: number, string, boolean, undefined, null
  • Infinity и NaN две зарезервированных числовых константы. Первая может быть результатом операций и дальше участвовать в вычислениях: 2*Infinity==Infinity. Вторая возникает при недопустимых операциях: Infinity-Infinity, 2*"a". Функция isFinite(x) возвращает true если число не равно Infinity.
  • Переменная будет иметь тип undefined даже если она объявлена (var z;), но ей не было присвоено значение.
  • Переменные лучше всегда объявлять (включая индексы в циклах). Иначе, став глобальными они могут непредсказуемо изменятся, особенно при вызове функции внутри цикла, которая сама используе циклы с тем же индексом.
  • Объявленные (var) переменные имеют локальную видимость только внутри функций, но не внутри остальных блоков {...}. Например, для if(true){ var x=5; } переменная x будет видна ниже.

Ветвления и циклы

Основные операторы имеют C-побный синтаксис. Например:

 
if(a==1) res=1; else res=2;

switch (a) {
  case 1:  res=1;  break;
  case 2:  res=2;  break;
  default: res=0;   break;
}

while (i < 10) {  i++;   }
do {  i++; } while (i < 10)
for (var i = 0; i < 100; i++) a[i]=i;

Дополнительно существует цикл по перечислению всех элементов массива или структуры:

 
for (var i in a) a[i]=2*i;

Математика

Действуют стандартные С-операторы:

  • Arithmetic operators: +, -, *, /, %
  • Increment operators: ++ and -- (префиксные и постфиксные)
  • Assignment operators: =, +=, -=, *=, /=,  %=
  • Logical operators: &&, ||, !, ==, ===, !=, !==, <, >, >=, <=
  • Special operators: typeof, delete.

Есть два логических сравнения: == - совпадение значения, === - совпадение и значения и типа:

 
if(1== "1") alert('1=="1"');  else alert('1!="1"');
if(1==="1") alert('1==="1"'); else alert('1!=="1"')

Математические вычисления:

 
   var s=Math.sqrt(2);  // корень квадратный
   s=s.toFixed(2);      // округление до 2-х цифр после точки

Для упрощения синтаксиса можно использовать конструкцию with для доступа ко всем полям:

   with(Math){
      var s=sqrt(2)*sin(5)+cos(PI);  
   }

Функции целого случайного числа от 0 до n-1 нет, но её можно определить:

function rand(n) { return Math.floor(Math.random()*n);  }

Массивы

Существует два типа структур: массив (пронумерованный набор значений в [...]) и хеш (набор пар “имя/значение” в {...}). Они имеют тип object. Работа с массивом:

 
var arr = new Array("aaa", "bbb", "ccc");// задание элементов
var arr = ["aaa", "bbb", "ccc"];         // тоже самое! 
var arr = new Array(4);                  // массив из 4-х элементов
arr[arr.length-1] = "CCC";               // доступ к последнему элементу

for(var i in arr) arr[i] = i;            // перебор всех элементов массива

Добавлять новые элементы можно, присваивая в не существующий индекс:

 
var a = [1, 2];
a[5]=3; 
document.writeln(a.length, "<br>");      // => 6
document.writeln(a[4], "<br>");          // =>  undefined (промежуточное значение не определено)
delete a[1];                             // теперь a[1] undefined

Массив как список или стек:

 
a.push(5, 6, 7);                         // добавляет в конец массива, возвращая новую длину
a.unshift(1,2,3);                        // тоже, что push, но в начало массива

x=a.pop();                               // Removes the last element of the array and returns it.
x=a.shift();                             // Like pop() but removes the first element, not the last.

arr=a.slice(start_index, end_index);     // получить кусок массива
arr=a.splice(start, n_del, i1, i2,...);  // удалить n_del штук, начиная с start и вставить там i1,...

Манипуляции с массивами

 
var a=[3, 5, 6], b=[1, 2, 3];
var a = a.reverse();                      // в обратном порядке       => 6, 5, 3
c=a.concat(b);                            // объединение 2-х массивов => 6,5,3,1,2,3
c=c.sort();                               // сортировка               => 1,2,3,3,5,6

arr = [1,-1, 0];
a = arr.sort()                            // => arr = [ -1, 0, 1 ]
alert(a === arr)                          // => true, это тот же, но отсортированный массив!

var st = [1,2,3].join();                  // => "1,2,3" (превращение массива в строку)
var st = [1,2,3].join("|");               // => "1|2|3" (превращение массива в строку с разделителем)

Сортировка с функцией сравнения:

 
arr.sort( [sortFunction] );
function sortFunction(a, b){
   if(a меньше, чем b по некоторому критерию) return -1 
   if(a больше, чем b по некоторому критерию) return 1  
   return 0 // в случае а = b вернуть 0
}

Ассоциативные массивы

Работа с хешами (имена ключей могут быть и строками):

 
var obj = { 
    k1: 137,
    k2: "Hi!",
    "k3": [1, 2],
};
obj.k2="By";                                    // доступ к свойствам
obj["k2"] = "By";                               // тоже самое

for(var i in obj)                               // вывод всех ключей и полей
   alert('key is: ' + i + ', value is: ' + obj[i]);
 
var obj = { };                                  // пустой объект
obj.k1 = 137;                                   // свойства можно добавлять "налету"

Объекты

Хеши могут быть объектами (их поля - другие объекты и функции). Внутри функции доступ к полям объекта осуществляется при помощи переменной this (т.е. "this object").

 
var obj = { 
    v  : 137,
    p  : {x:1, y:1},
    get: function(){ return this.v; }
};
var x = obj.p.x;
x=obj.get();

var st=obj.toString();                        // string representation of the object 

Объекты можно создавать при помощи конструктора:

 
function Ball(r)                              // конструктор 
{
   this.radius = r;
}
var b1 = new Ball(5);                         // создание при помощи new нового объекта
b1.radius=10;
var b2 = new b1.constructor(7);               // имя конструктора constructor:
if(b2 instanceof Ball){  }                    // проверка от какого конструктора создан объект

When you copy an object or pass it to a function, you only pass a reference to that object. Consequently, if you make a change to the reference, you are actually modifying the original object. The same thing applies when passing objects to functions. Тоже самое относится к массивам. Но не к строкам и числам!

Наследование:

// функция-конструктор класса
var Class = function()
{ 
   this.className = 'Class';
   alert("Class");
}
// описываем открытый метод класса
Class.prototype.method = function()
{ 
   alert('method of ' +  this.className);
}
// функция-конструктор подкласса
var SubClass = function()
{ 
   this.className = 'SubClass';
   alert("SubClass");
}
// создаем объект надкласса в .prototype подкласса  сразу под конструктором!!
SubClass.prototype = new Class(); 

// переопределяем унаследованный метод надкласса
SubClass.prototype.method = function()
{ 
   alert('method of ' +  this.className + ' but new one');
}

var subc = new SubClass(); // создаем экземпляр класса SubClass
subc.method();             // выводит 'method of SubClass'

JSON

JSON (JavaScript Object Notation) — текстовый формат обмена данными, строящийся на двух структурах: массив и хеш. Например:

{
    "name"        : "Иванов",
    "phoneNumbers": [ "2342432", "56433" ]
}

Строки

 
var s = "box";
s[0]="d"                   // => s="dox"
arr = "a,b,c".split(',')   // => массив ["a", "b", "c"]

Методы объекта строка:

  • charAt(n) - возвращает символ, позицию которого определяет параметр n.
  • substr(n1,n2) - возвращает подстроку из строки, где n1 - позиция первого символа подстроки, а n2 - количество символов в строке.

Функции:

  • parseInt("123abc"); => 123 (первое целое число)
  • parseInt('FF', 16); - по основанию 16
  • parseInt('0xFF') ; => 256
  • parseFloat('1.23abc.00'); => 1.23
  • Number(s) - преобразует строковый параметр s в число.
  • String(n) - преобразует число n в строку.
  • isNaN(s) - проверяет является ли параметр s числом (возвращая true).
  • eval('var ii = 2;') takes a string input and executes it as JavaScript code:

Функции

Functions in JavaScript are actually data. This means that the following two ways to define a function are exactly the same. Имена функций можно присваивать в переменные:

 
function f(){return 1;}
var f = function(){return 1;}                //  typeof f => "function"

Две функции с одинаковым именем не имеют смысла, т.к. вторая переопределит первую. Полиморфизм функций (разное число аргументов) делается так:

 
function args() { return arguments; }        // любая функция знает массив всех своих аргументов
a=args( 1, true, 'six')                      // =>  [1, true, 'six']

var state = 1;                            
function State(val)                          // такая функция будет:
{
   if(arguments.length==0)   return state;   // возвращать значение: s=State();
   else                      state=val;      // и задавать его: State(1);
}   

Локальные переменные являются локальными независимо от того где они внутри функции объявлены (inside the function the local scope is more important than the global scope):

 
var a = 123;
function f() { 
  alert(a);            // => undefined, а не 123!
  var a = 1;
  alert(a);            // => 1
} 
f(); 

Дата - время

Методы объекта Date

  • getDate - возвращает число в диапазоне от 1 до 31, представляющее число месяца.
  • getHours - возвращает час суток в диапазоне от 0 (полночь) до 23.
  • getMinutes - возвращает минуты в диапазоне от 0 до 59.
  • getSeconds - возвращает секунды в диапазоне от 0 до 59.
  • getDay - возвращает день недели, как целое число от 0 (воскресенье) до 6 (суббота).
  • getMonth - возвращает номер месяца в году, как целое число от 0 (январь) до 11 (декабрь).
  • getYear - возвращает год в виде двух последних цифр (getFullYear - возвращает год в виде четырех цифр).
 
   var t=new Date();
   var result=t.getHours()+":"+t.getMinutes()+":"+t.getSeconds();

Задание даты:

 
   var t=new Date("Feb,10,1975 17:45:10");

или функциями:

  • setDate - устанавливает число месяца в диапазоне от 1 до 31.
  • setHours - устанавливает час для текущего времени в диапазоне от 0 (полночь) до 23.
  • setMinutes - устанавливает минуты в диапазоне от 0 до 59.
  • setSeconds - устанавливает секунды в диапазоне от 0 до 59.
  • setYear - устанавливает значение года.
  • setMonth - устанавливает значение месяца в диапазоне от 0 (январь) до 11 (декабрь).
  • setTime - устанавливает значение объекта Date и возвращает количество миллисекунд, прошедших с 1 января 1970 года.


Графика

Фигуры

Прямоугольники:

 
fillRect  (x,y, width,height) // Рисует заполненный прямоугольник
strokeRect(x,y, width,height) // Рисует границы прямоугольника
clearRect (x,y, width,height) // Очищает заданную область и делает её полностью прозрачной

Пути:

 
beginPath();                   // начало пути
...                            // последовательность команд
closePath();                   // соединяет последнюю и первую точку (можно не делать)
stroke();                      // рисуем рамкой
fill();                        // _или_ залитую фигуру

Возможные команды линий:

 
moveTo(x, y);                  // переместиться, ничего не рисуя
lineTo(x, y);                  // провести от последней точки линию
arc(x, y, radius, startAngle, endAngle, anticlockwise); // нарисовать дугу
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); // Безье кривые
  • Для arc: x и y это координаты центра круга; startAngle и endAngle - точки начала и конца арки в радианах (углы от оси x). Параметр anticlockwise равен true, то дуга рисуется против часовой стрелки, иначе - по часовой.
  • Для bezierCurveTo: x и y - координаты конечной точки. cp1x и cp1y - координаты первой точки контроля, а cp2x и cp2y - второй точки контроля.

Картинки

Загрузка картинки:

 
var img = new Image();      // Создаём новый объект Image
img.src = 'picture.png';    // Устанавливаем путь к источнику

Если к моменту вызова drawImage загрузка ещё не закончилась, скрипт "подвисает" до её окончания. Чтобы избежать этого, используйте обработчик события onload:

 
var img = new Image();   // Создать новый объект Image
img.src = 'myImage.png'; // Установить путь к источнику
img.onload = function(){ /* выполнить drawImage здесь */   }

Собственно рисование картинки:

 
ctx.drawImage(img, dx, dy);
ctx.drawImage(img, dx, dy, dWidth, dHeight);
ctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
  • img - идентификатор изображения;
  • sx, sy - верхний левый угол вырезаемого куска из источника (source)
  • sWidth, sHeight, - высота и ширина вырезанного изображения;
  • dx, dy - положение изображения на холсте (destination);
  • dWidth, dHeight масштаб изображения.

Настройки

 
ctx.globalAlpha = 0.0                 // все сделать дальше прозрачным

ctx.fillStyle = "orange";             // разные способы задания цвета заливки
ctx.fillStyle = "#FFA500";  
ctx.fillStyle = "rgb(255,165,0)";  
ctx.fillStyle = "rgba(255,165,0,1)";  

ctx.strokeStyle = "orange";           // аналогично для цвета линий

ctx.lineWidth = 5;                    // толщина линии
сtx.lineCap   = "round";              // как оканчивать линию ['butt','round','square']

Матрицы

Вращающийся квадратик:

 
function rotate() {
  ctx.clearRect(0, 0, canvasWidth, canvasHeight);  // Clear the canvas
  ctx.translate(canvasWidth/2, canvasWidth/2);     // Move camera to the center of the canvas
  ctx.rotate(Math.PI / 180);                       // Rotate 1 degree
  ctx.translate(-canvasWidth/2, -canvasWidth/2);   // Move camera back

  ctx.fillStyle = "red";
  ctx.fillRect(canvasWidth/4, canvasWidth/4, canvasWidth/2, canvasHeight/4);
  ctx.fillStyle = "blue";
  ctx.fillRect(canvasWidth/4, canvasWidth/2, canvasWidth/2, canvasHeight/4);
}
setInterval(rotate, 100);

Локальное хранилище

Локальное хранилище сохраняет на стороне клиента (локальной машины) до 5mb данных. Это строковые данные типа пар ключ - значение.

 
localStorage.setItem('var', 'value1');      // записали var="value1"
var v = localStorage.getItem('var');        // получили значение
document.writeln("v=" + v,"<br>");

localStorage['var'] = 'value2';             // можно использовать объектную нотацию:
document.writeln("v=", localStorage['var'] ,"<br>");

// простая проверка существования счетчика:
if(localStorage.hits )  localStorage.hits = Number(localStorage.hits)+1;
else                    localStorage.hits = 1;

// защищенная работа:
if(typeof(localStorage) == 'undefined' )  alert('Ваш браузер не поддерживает localStorage()');
else try      { localStorage.setItem('name', 'Hello World!');  }
     catch (e){ if (e==QUOTA_EXCEEDED_ERR) alert('Кончилось доступное место');}

// Для сохранения объектов необходимо воспользоваться сериализацией:
var arr1 = { 1: [1, 2, 3] };
localStorage['arr'] = JSON.stringify(arr1);
var arr2 = JSON.parse(localStorage['arr']);
document.writeln("<p>", arr2[1] ,"</p>");

// вывод всех элементов:
document.writeln("<p>","localStorage.length=",localStorage.length,"</p>");
for(var v in localStorage) 
   document.writeln("<li>", v, " = ", localStorage[v] ,"</li>");

localStorage.removeItem('val');             //удалит элемент хранилища
localStorage.clear();                       //удалит все элементы
document.writeln("<p>","localStorage.length=",localStorage.length,"</p>");

События

  • onClick
  • onMouseUp
  • onMouseOver
  • onMouseOut

Работа с формами

Простой пример

Стоит обратить внимание на передачу поля формы через относительную ссылку. Так короче и надежнее (если форма спрячется внутрь другого DOM-а):

 
<HTML>
<HEAD>
<SCRIPT Language="JavaScript">
   function showAndClearField(frm){
      if (frm.firstName.value == "") alert("Hey! You didn't enter anything!");
      else                           alert("Hi: " + frm.firstName.value);
      frm.firstName.value = "";
   }
</SCRIPT>
</HEAD>
<BODY>
   <FORM NAME="test">
      <P>Enter your First Name: 
      <INPUT TYPE="TEXT" NAME="firstName">
      <INPUT TYPE="Button" Value="Show and Clear Input" onClick="showAndClearField(this.form)">
    </FORM>
</BODY>
</HTML>

Форма перемножающая два числа

 
<form name="form_add">
    <input type="text" name="t1" size="10"> * <input type="text" name="t2" size="10"> 
    <input type="button" name="button" value="=" onClick="Mult();">
    <input type="text" name="res" size="10">
</form>

Скрипт:

 
function Mult()
{
   var a= document.form_add.t1.value;
   var b= document.form_add.t2.value;
   document.form_add.res.value=a*b;
}

Передача имени формы

 
<input type="button" name="button" value="=" onClick="Mult(form_add);">

и функцию написать так:

 
function Mult(obj)
{
   obj.res.value=obj.t1.value * obj.t2.value;
}

Использование getElementById

 
<script type="text/javascript">
function notEmpty(){
	var myTextField = document.getElementById('myText');
	if(myTextField.value != "")
		alert("You entered: " + myTextField.value)
	else
		alert("Would you please enter some text?")		
}
</script>
<input type='text' id='myText' />
<input type='button' onclick='notEmpty()' value='Form Checker' />

Свертывающиеся закладки

 
/*
<body onload="slider('slider',1)">

<div id="slider">

  <div class="header"  id="one-header"> Заголовок </div>
  <div class="content" id="one-content">
      <div class="text"> текст    </div>
  </div>

</div>
*/

var array = new Array();
var speed = 5;
var timer = 10;

//-------------------------------------------------------------------------
// Loop through all the divs in the slider parent div 
// Calculate seach content divs height and set it to a variable 
function slider(target, showfirst) 
{
   var slider = document.getElementById(target);    
   var divs = slider.getElementsByTagName('div');
   var divslength = divs.length;
   for(i = 0; i < divslength; i++) {               // бежим по массиву блокв
      var div = divs[i];
      var divid = div.id;
      if(divid.indexOf("header") != -1) 
         div.onclick = new Function("processClick(this)");
      else if(divid.indexOf("content") != -1) {
         var section = divid.replace('-content','');
         array.push(section);
         div.maxh = div.offsetHeight;
         if(showfirst == 1 && i == 1) 
            div.style.display = 'block';
          else 
            div.style.display = 'none';
      } 
   }
}
//---------------------------------------------------------------------------
// Process the click - expand the selected content and collapse the others 
function processClick(div) 
{
   var catlength = array.length;
   for(i = 0; i < catlength; i++) {
      var section = array[i];
      var head = document.getElementById(section + '-header');
      var cont = section + '-content';
      var contdiv = document.getElementById(cont);
      clearInterval(contdiv.timer);
      if(head == div && contdiv.style.display == 'none') {
         contdiv.style.height = '0px';
         contdiv.style.display = 'block';
         initSlide(cont,1);
      } 
      else if(contdiv.style.display == 'block') 
         initSlide(cont,-1);
   }
}
//---------------------------------------------------------------------------
// Setup the variables and call the slide function 
function initSlide(id,dir) 
{
   var cont = document.getElementById(id);
   var maxh = cont.maxh;
   cont.direction = dir;
   cont.timer = setInterval("slide('" + id + "')", timer);
}
//---------------------------------------------------------------------------
// Collapse or expand the div by incrementally changing the divs height and opacity 
function slide(id) 
{
   var cont = document.getElementById(id);
   var maxh = cont.maxh; 
   var currheight = cont.offsetHeight;
   var dist;
   if(cont.direction == 1) 
      dist = (Math.round((maxh - currheight) / speed));
   else 
      dist = (Math.round(currheight / speed));
   if(dist <= 1) 
     dist = 1;

   cont.style.height = currheight + (dist * cont.direction) + 'px';
   cont.style.opacity = currheight / cont.maxh;
   cont.style.filter = 'alpha(opacity=' + (currheight * 100 / cont.maxh) + ')';
   if(currheight < 2 && cont.direction != 1) {
      cont.style.display = 'none';
      clearInterval(cont.timer);
   } 
   else if(currheight > (maxh - 2) && cont.direction == 1) 
      clearInterval(cont.timer);
}
//---------------------------------------------------------------------------

Ссылки

См.также