JavaScript Хронометър – част 1
Нека разгледаме един реален пример. В него ще направим една проста HTML страница и с помощта на JavaScript ще засичаме време.
В този урок ще представим основна работа с jQuery, някои основни event-и, както и какво е setInterval
.
Нека започнем с основния markup на една празна страница:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>JavaScript Хронометър</title>
<style type="text/css">
* { margin: 0; padding: 0; }
html, body { width: 100%; height: 100%; }
body { background: #EEE; color: #000; font: normal 12px/1.2 Arial, Helvetica, sans-serif; }
</style>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
</body>
</html>
Започваме с HTML5 Doctype декларация, и HTML5 character set meta таг. Освен това, в <head>
тага на страницата сме добавили и декларация за стил. По принцип би била в отделен файл, но в случая ще събера всичко на едно място, за да можем да го разглеждаме заедно.
След стиловата декларация съм заредил jQuery. След това съм добавил и таг за JavaScript-а, където ще поместим кода за нашия хронометър.
HTML
Нека добавим и HTML markup за бутона, който ще стартира и спира хронометъра. Освен него ще добавим и един <span>
, в който ще изписваме изминалото време.
<body>
<div id="stopwatch">
<a href="#">Start</a> <span>00:00:00</span>
</div>
</body>
За бутона съм използвал <a>
таг. Стандартно за него е да се клика отгоре му.
CSS
Нека добавим и малко стилове, за да изглеждат бутонът и надписът ни по-добре.
#stopwatch { margin: 50px 0; font-size: 24px; text-align: center; }
#stopwatch a,
#stopwatch span { display: inline-block; padding: 0 15px; line-height: 1.6; }
#stopwatch a { background: #404040; color: #FFF; text-decoration: none; }
#stopwatch a:hover,
#stopwatch a:focus { background: #666; }
#stopwatch span { background: #000; color: #FFF; }
JavaScript
Тук вече идва ред на JavaScript-а. Първо трябва да уточним обаче кога се изпълнява нашият JavaScript код.
Отговорът на този въпрос е: в момента, в който браузърът достигне до <script>
тага.
В нашия случай това означава, че JavaScript-ът ще се изпълни още преди нашия <body>
таг. Това означава, че браузърът няма да знае какво има в <body>
-то по-надолу. Даже само ще предполага, че надолу вероятно има <body>
.
По тази причина трябва да декларираме кода си като функция, чието изпълнение да се извърши когато страницата ни е заредена.
Всъщност има и един по-добър вариант за JavaScript event. Няма да търсим кога страницата е напълно заредена. Вместо това ще се закачим за събитие, обозначаващо, че HTML-ът е прочетен от браузъра. Този event се нарича DOMContentLoaded
(или още DOM Ready).
Каква е разликата между window.load и DOMContentLoaded?
window.load
изчаква зареждане на всичко на страницата. Това може да включва картинки, външни CSS файлове, JS файлове и не само.
При нас единственият външен файл е jQuery. Все пак ще използваме DOM Ready, тъй като това в почти всички случаи е за предпочитане. Изключение правят случаи, когато наистина ви е нужно всичко да е заредено.
jQuery има своите начини да определи точно кога цялостният markup е зареден.
function onDomReady() {
// това ще се изпълни след като целият markup е зареден
}
var jQueryDocument = $(document);
jQueryDocument.ready(onDomReady);
jQuery
jQuery реално е един обект (и по-точно функция), която е дефинирана с името $
. Макар и отначало да ви се струва странно, това е валидно име на променлива в JavaScript.
В зависимост от аргументите, които са подадени към функцията тя върши най-разнообразна работа.
ready
В случая подаваме аргумент document
, което в JavaScript се отнася за текущата страница. Функцията връща стойност jQuery обект, изграден „около“ страницата. Записваме този обект в променливата jQueryDocument
, след което извикваме метода ready
на този обект.
Самият език JavaScript ни позволява да си спестим това допълнително инициализиране на променлива и директно да извикаме метода, още при извикването на предната функция:
function onDomReady() {
// това ще се изпълни след като целият markup е зареден
}
$(document).ready(onDomReady);
Така е по-кратко, нали?
Забелязвате, че на метода ready
подаваме името на функцията onDomReady
, която искаме да извикаме? Това много напомня addEventListener
метода. Така е защото работи на същия принцип. Методът ready
използва addEventListener
при браузъри, които поддържат DOMContentLoaded
.
Можем директно да подадем като аргумент и самата функция, която искаме да изпълним по следния начин:
$(document).ready(function () {
// това ще се изпълни след като целият markup е зареден
});
Забележете, че дефинираме функция там, където трябва да подадем callback аргумент.
Също така забележете, че това дефиниране на функция е по-различно от останалите. Тук не задаваме име на функцията, а след ключовата дума function
имаме просто скоби. Те оказват дали и какви аргументи приема функцията. Такива функции се наричат анонимни и не можем да ги извикаме директно. Удобни са в случаи като този, при който функцията ни трябва в един единствен случай. Тогава нямаме нужда от име и възможност да я викаме на друго място.
$(function () {})
Тъй като закачане на функция към DOM Ready event-а е много често срещано, създателите на jQuery предлагат и един още по-кратък вариант.
Нека за един последен път да съкратим кода си още малко (никой не обича да пише дълъг код):
$(function () {
// това ще се изпълни след като целият markup е зареден
});
Просто подаваме callback аргумент към $()
функцията. Тя е създадена така, че ако има един единствен аргумент и той е функция, да я закачи към DOM Ready.
$
срещу jQuery
Следващата промяна, която ще направим, е от съображения за правилна съвместна работа с други библиотеки. Някои също използват променливата $
, в която записват глобални функции/обекти подобно на jQuery.
По тази причина, вместо $
можем да използваме просто променливата jQuery
. Тя по подразбиране съответства напълно на $
. Обаче „jQuery“ е цели 6 символа, а „$“ си е само един. А ние не обичаме да пишем много и излишно. Можем на Dom Ready callback функцията да подадем аргумент, който съдържа jQuery обекта:
jQuery(function ($) {
// това ще се изпълни след като целият markup е зареден
});
Когато използваме $
като аргумент на функцията, ние всъщност дефинираме нова променлива. Нейната стойност задаваме да е равна на jQuery
и може да се използва само в дадената функция.
В урока за JavaScript функции казахме, че всяка функция има собствен обхват на променливите (variable scope). Това означава, че ако в една функция се дефинират променливи, те могат да се използват само в нея. Така ние задаваме $
да има стойност jQuery
само в тази callback функция.
След като уточнихме как трябва да декларираме нашият JavaScript така, че:
- да няма проблеми с други библиотеки
- да използваме променливи с кратки имена
- да си спестим и друго излишно в деклариране на функции и променливи
- кодът ни да се изпълни след като HTML-а е парсиран
Остава да напишем и същинския код, който да накара хронометъра ни да се задвижи. Това обаче ще оставим за втора част на урока.