Меню

Първи стъпки в правене на сайтове

Влез Излез

JavaScript Хронометър – част 1

След като вече имаме основни познания за начина, по който можем да работим с JavaScript, нека разгледаме един реален пример, в който ще направим една проста 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 markup за бутона, който ще стартира и спира хронометъра. Освен него ще добавим и един <span>, в който ще изписваме изминалото време.

<body>
	<div id="stopwatch">
		<a href="#">Start</a>
		<span>00:00:00</span>
	</div>
</body>

За бутона съм използвал <a> таг, тъй като така ще мога да използвам вградените стилове мишката да сменя курсора си на ръчичка, когато се намира над връзката.

Нека добавим и малко стилове, за да изглеждат бутонът и надписът ни по-добре.

* { margin: 0; padding: 0; }
html, body { width: 100%; height: 100%; }

body { background: #EEE; color: #000; font: normal 12px/1.2 Arial, Helvetica, sans-serif; }

#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 код, когато е добавен в страница. Отговорът на този въпрос е – в момента, в който браузърът достигне до <script> тага. В нашия случай това означава, че JavaScript-ът ще се изпълни още преди нашият <body> таг и всичко в него да съществува, тъй като изпълнението ще се извърши още докато браузърът е в <head> тага. По тази причина трябва да декларираме кода си като функция, чието изпълнение да се извърши когато страницата ни е заредена.

Всъщност има и един по-добър вариант за JavaScript event, при който да извършим инициализацията на нашия скрипт. Този event се нарича DOMContentLoaded (или още DOM Ready) и се изпълнява когато браузърът е заредил всичкия markup на страницата. Каква е разликата между window.load и DOMContentLoaded? window.load изчаква не само парсирането на HTML-а, но и зареждането на картинки и всякакви други външни файлове, които сме описали в markup-а си и настъпва по-късно. Въпреки че при нас няма нито един външен файл, пак ще използваме DOM Ready, тъй като това в почти всички случаи е за предпочитане (освен разбира се, когато трябва изрично да направите нещо с JavaScript, което да изисква всички външни файлове да са заредени).

Проблемът при използването на DOMContentLoaded, обаче е, че IE7 и 8 не го поддържат. За щастие, jQuery има своите начини да определи точно кога цялостният markup е зареден и ние на готово ще използваме неговите възможности, за да се закачим за този event.

function onDomReady() {
	// това ще се изпълни след като целият markup е зареден
}

var jQueryDocument = $(document);
jQueryDocument.ready(onDomReady);

jQuery реално е един обект (и по-точно функция), която е дефинирана с името „$“ (да, макар и отначало да ви се струва странно, това е валидно име на променлива в JavaScript). В зависимост от аргументите, които са подадени към функцията тя върши най-разнообразна работа. В случая подаваме аргумент document, което в JavaScript се отнася за текущата страница. Функцията връща стойност jQuery обект, изграден „около“ страницата. Записваме този обект в променливата jQueryDocument, след което извикваме метода ready на този обект.

Самият език JavaScript ни позволява да си спестим това допълнително инициализиране на променлива и директно да извикаме метода, още при извикването на предната функция:

function onDomReady() {
	// това ще се изпълни след като целият markup е зареден
}

$(document).ready(onDomReady);

Така е доста по-кратко, нали?

Забелязвате, че на метода ready подаваме името на функцията onDomReady, която искаме да извикаме. Това много напомня addEventListener метода, именно защото работи на същия принцип – метода ready използва addEventListener при браузъри, които поддържат DOMContentLoaded.

Подобно на извикването на ready метода, при създаването на jQuery wrapper-а около document, можем директно да подадем като аргумент и самата функция, която искаме да изпълним по следния начин:

$(document).ready(function () {
	// това ще се изпълни след като целият markup е зареден
});

Забележете, че дефинираме функция там, където трябва да подадем callback аргумент. Също така забележете, че това дефиниране на функция е по-различно от останалите, тъй като тук не задаваме име на функцията, а след ключовата дума function имаме просто интервал (който дори не е задължителен – това е просто практика, която аз самият имам) и скоби, оказващи дали и какви аргументи приема функцията. Такива функции се наричат анонимни и не можем да ги извикаме директно. Удобни са именно в случаи като този, при който функцията ни трябва в един единствен случай и е безсмислено да я дефинираме като отделна функция.

Тъй като закачане на функция към DOM Ready event-а е много често срещано (кажи-речи във всеки скрипт), създателите на jQuery предлагат и един по-кратък вариант за постигане на същото. Нека за един последен път да съкратим кода си още малко (никой не обича да пише дълъг код):

$(function () {
	// това ще се изпълни след като целият markup е зареден
});

Просто подаваме callback аргумент към $() функцията, която е създадена така, че ако има един единствен аргумент и той е функция, да закачи дадената функция към DOM Ready.

Следващата промяна, която ще направим, е от съображения за правилна съвместна работа с други библиотеки, които също използват променливата $, в която записват глобални функции/обекти подобно на jQuery. По тази причина, вместо $ можем да използваме просто променливата jQuery, която по подразбиране съответства напълно на $. Тъй като обаче „jQuery“ е цели 6 символа, а „$“ си е само един, а ние не обичаме да пишем много и излишно, можем на Dom Ready callback функцията да подадем аргумент, който съдържа jQuery обекта:

jQuery(function ($) {
	// това ще се изпълни след като целият markup е зареден
});

Когато използваме $ като аргумент на функцията, ние всъщност дефинираме нова променлива, чиято стойност задаваме да е равна на jQuery и която да може да се използва само в дадената функция. В урока за JavaScript функции казахме, че всяка функция има собствен обхват на променливите (variable scope). Това означава, че една функция може да използва глобалните променливи, които са достъпни в JavaScript, но ако вътре в нея се дефинират променливи, те могат да се използват само във функцията, а не в глобалния scope. Така ние задаваме $ да има стонйст jQuery само в тази callback функция.

След като уточнихме как трябва да декларираме нашият JavaScript така, че хем да няма проблеми с други библиотеки, хем да използваме променливи с кратки имена, хем да си спестим и друго излишно в деклариране на функции и променливи, хем кодът ни да се изпълни след като HTML-а е парсиран, остава да напишем и същинския код, който да накара хронометъра ни да се задвижи. Това обаче ще оставим за втора част на урока.

Вашият коментар

Вашият имейл адрес няма да бъде публикуван. Задължителните полета са отбелязани с *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax